summaryrefslogtreecommitdiff
path: root/sw/source/core/text/itratr.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/text/itratr.cxx')
-rw-r--r--sw/source/core/text/itratr.cxx1078
1 files changed, 1078 insertions, 0 deletions
diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx
new file mode 100644
index 000000000000..60b476839705
--- /dev/null
+++ b/sw/source/core/text/itratr.cxx
@@ -0,0 +1,1078 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <txtatr.hxx>
+#include <sfx2/printer.hxx>
+#include <editeng/lrspitem.hxx>
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <fmtanchr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtftn.hxx>
+#include <frmatr.hxx>
+#include <frmfmt.hxx>
+#include <fmtfld.hxx>
+#include <doc.hxx>
+#include <viewsh.hxx> // ViewShell
+#include <rootfrm.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx>
+#include <dcontact.hxx>
+#include <fldbas.hxx> // SwField
+#include <pam.hxx> // SwPosition (lcl_MinMaxNode)
+#include <itratr.hxx>
+#include <htmltbl.hxx>
+#include <swtable.hxx>
+#include <redlnitr.hxx>
+#include <fmtsrnd.hxx>
+#include <itrtxt.hxx>
+#include <breakit.hxx>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <com/sun/star/i18n/ScriptType.hdl>
+
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star;
+
+/*************************************************************************
+ * SwAttrIter::Chg()
+ *************************************************************************/
+
+void SwAttrIter::Chg( SwTxtAttr *pHt )
+{
+ ASSERT( pHt && pFnt, "No attribute of font available for change");
+ if( pRedln && pRedln->IsOn() )
+ pRedln->ChangeTxtAttr( pFnt, *pHt, sal_True );
+ else
+ aAttrHandler.PushAndChg( *pHt, *pFnt );
+ nChgCnt++;
+}
+
+/*************************************************************************
+ * SwAttrIter::Rst()
+ *************************************************************************/
+
+void SwAttrIter::Rst( SwTxtAttr *pHt )
+{
+ ASSERT( pHt && pFnt, "No attribute of font available for reset");
+ // get top from stack after removing pHt
+ if( pRedln && pRedln->IsOn() )
+ pRedln->ChangeTxtAttr( pFnt, *pHt, sal_False );
+ else
+ aAttrHandler.PopAndChg( *pHt, *pFnt );
+ nChgCnt--;
+}
+
+/*************************************************************************
+ * virtual SwAttrIter::~SwAttrIter()
+ *************************************************************************/
+
+SwAttrIter::~SwAttrIter()
+{
+ delete pRedln;
+ delete pFnt;
+}
+
+/*************************************************************************
+ * SwAttrIter::GetAttr()
+ *
+ * Liefert fuer eine Position das Attribut, wenn das Attribut genau auf
+ * der Position nPos liegt und kein EndIndex besitzt.
+ * GetAttr() wird fuer Attribute benoetigt, die die Formatierung beeinflussen
+ * sollen, ohne dabei den Inhalt des Strings zu veraendern. Solche "entarteten"
+ * Attribute sind z.B. Felder (die expandierten Text bereit halten) und
+ * zeilengebundene Frames. Um Mehrdeutigkeiten zwischen verschiedenen
+ * solcher Attribute zu vermeiden, werden beim Anlegen eines Attributs
+ * an der Startposition ein Sonderzeichen in den String einfuegt.
+ * Der Formatierer stoesst auf das Sonderzeichen und holt sich per
+ * GetAttr() das entartete Attribut.
+ *************************************************************************/
+
+SwTxtAttr *SwAttrIter::GetAttr( const xub_StrLen nPosition ) const
+{
+ return (m_pTxtNode) ? m_pTxtNode->GetTxtAttrForCharAt(nPosition) : 0;
+}
+
+/*************************************************************************
+ * SwAttrIter::SeekAndChg()
+ *************************************************************************/
+
+sal_Bool SwAttrIter::SeekAndChgAttrIter( const xub_StrLen nNewPos, OutputDevice* pOut )
+{
+ sal_Bool bChg = nStartIndex && nNewPos == nPos ? pFnt->IsFntChg() : Seek( nNewPos );
+ if ( pLastOut != pOut )
+ {
+ pLastOut = pOut;
+ pFnt->SetFntChg( sal_True );
+ bChg = sal_True;
+ }
+ if( bChg )
+ {
+ // wenn der Aenderungszaehler auf Null ist, kennen wir die MagicNo
+ // des gewuenschten Fonts ...
+ if ( !nChgCnt && !nPropFont )
+ pFnt->SetMagic( aMagicNo[ pFnt->GetActual() ],
+ aFntIdx[ pFnt->GetActual() ], pFnt->GetActual() );
+ pFnt->ChgPhysFnt( pShell, *pOut );
+ }
+ return bChg;
+}
+
+sal_Bool SwAttrIter::IsSymbol( const xub_StrLen nNewPos )
+{
+ Seek( nNewPos );
+ if ( !nChgCnt && !nPropFont )
+ pFnt->SetMagic( aMagicNo[ pFnt->GetActual() ],
+ aFntIdx[ pFnt->GetActual() ], pFnt->GetActual() );
+ return pFnt->IsSymbol( pShell );
+}
+
+/*************************************************************************
+ * SwAttrIter::SeekStartAndChg()
+ *************************************************************************/
+
+sal_Bool SwAttrIter::SeekStartAndChgAttrIter( OutputDevice* pOut, const sal_Bool bParaFont )
+{
+ if ( pRedln && pRedln->ExtOn() )
+ pRedln->LeaveExtend( *pFnt, 0 );
+
+ // reset font to its original state
+ aAttrHandler.Reset();
+ aAttrHandler.ResetFont( *pFnt );
+
+ nStartIndex = nEndIndex = nPos = nChgCnt = 0;
+ if( nPropFont )
+ pFnt->SetProportion( nPropFont );
+ if( pRedln )
+ {
+ pRedln->Clear( pFnt );
+ if( !bParaFont )
+ nChgCnt = nChgCnt + pRedln->Seek( *pFnt, 0, STRING_LEN );
+ else
+ pRedln->Reset();
+ }
+
+ if ( pHints && !bParaFont )
+ {
+ SwTxtAttr *pTxtAttr;
+ // Solange wir noch nicht am Ende des StartArrays angekommen sind &&
+ // das TextAttribut an Position 0 beginnt ...
+ while ( ( nStartIndex < pHints->GetStartCount() ) &&
+ !(*(pTxtAttr=pHints->GetStart(nStartIndex))->GetStart()) )
+ {
+ // oeffne die TextAttribute
+ Chg( pTxtAttr );
+ nStartIndex++;
+ }
+ }
+
+ sal_Bool bChg = pFnt->IsFntChg();
+ if ( pLastOut != pOut )
+ {
+ pLastOut = pOut;
+ pFnt->SetFntChg( sal_True );
+ bChg = sal_True;
+ }
+ if( bChg )
+ {
+ // wenn der Aenderungszaehler auf Null ist, kennen wir die MagicNo
+ // des gewuenschten Fonts ...
+ if ( !nChgCnt && !nPropFont )
+ pFnt->SetMagic( aMagicNo[ pFnt->GetActual() ],
+ aFntIdx[ pFnt->GetActual() ], pFnt->GetActual() );
+ pFnt->ChgPhysFnt( pShell, *pOut );
+ }
+ return bChg;
+}
+
+/*************************************************************************
+ * SwAttrIter::SeekFwd()
+ *************************************************************************/
+
+// AMA: Neuer AttrIter Nov 94
+
+void SwAttrIter::SeekFwd( const xub_StrLen nNewPos )
+{
+ SwTxtAttr *pTxtAttr;
+
+ if ( nStartIndex ) // wenn ueberhaupt schon Attribute geoeffnet wurden...
+ {
+ // Schliesse Attr, die z. Z. geoeffnet sind, vor nNewPos+1 aber enden.
+
+ // Solange wir noch nicht am Ende des EndArrays angekommen sind &&
+ // das TextAttribut vor oder an der neuen Position endet ...
+ while ( ( nEndIndex < pHints->GetEndCount() ) &&
+ (*(pTxtAttr=pHints->GetEnd(nEndIndex))->GetAnyEnd()<=nNewPos))
+ {
+ // schliesse die TextAttribute, deren StartPos vor
+ // oder an der alten nPos lag, die z.Z. geoeffnet sind.
+ if (*pTxtAttr->GetStart() <= nPos) Rst( pTxtAttr );
+ nEndIndex++;
+ }
+ }
+ else // ueberlies die nicht geoeffneten Enden
+ {
+ while ( ( nEndIndex < pHints->GetEndCount() ) &&
+ (*(pTxtAttr=pHints->GetEnd(nEndIndex))->GetAnyEnd()<=nNewPos))
+ {
+ nEndIndex++;
+ }
+ }
+ // Solange wir noch nicht am Ende des StartArrays angekommen sind &&
+ // das TextAttribut vor oder an der neuen Position beginnt ...
+ while ( ( nStartIndex < pHints->GetStartCount() ) &&
+ (*(pTxtAttr=pHints->GetStart(nStartIndex))->GetStart()<=nNewPos))
+ {
+ // oeffne die TextAttribute, deren Ende hinter der neuen Position liegt
+ if ( *pTxtAttr->GetAnyEnd() > nNewPos ) Chg( pTxtAttr );
+ nStartIndex++;
+ }
+
+}
+
+/*************************************************************************
+ * SwAttrIter::Seek()
+ *************************************************************************/
+
+sal_Bool SwAttrIter::Seek( const xub_StrLen nNewPos )
+{
+ if ( pRedln && pRedln->ExtOn() )
+ pRedln->LeaveExtend( *pFnt, nNewPos );
+
+ if( pHints )
+ {
+ if( !nNewPos || nNewPos < nPos )
+ {
+ if( pRedln )
+ pRedln->Clear( NULL );
+
+ // reset font to its original state
+ aAttrHandler.Reset();
+ aAttrHandler.ResetFont( *pFnt );
+
+ if( nPropFont )
+ pFnt->SetProportion( nPropFont );
+ nStartIndex = nEndIndex = nPos = 0;
+ nChgCnt = 0;
+
+ // Achtung!
+ // resetting the font here makes it necessary to apply any
+ // changes for extended input directly to the font
+ if ( pRedln && pRedln->ExtOn() )
+ {
+ pRedln->UpdateExtFont( *pFnt );
+ ++nChgCnt;
+ }
+ }
+ SeekFwd( nNewPos );
+ }
+
+ pFnt->SetActual( SwScriptInfo::WhichFont( nNewPos, 0, pScriptInfo ) );
+
+ if( pRedln )
+ nChgCnt = nChgCnt + pRedln->Seek( *pFnt, nNewPos, nPos );
+ nPos = nNewPos;
+
+ if( nPropFont )
+ pFnt->SetProportion( nPropFont );
+
+ return pFnt->IsFntChg();
+}
+
+/*************************************************************************
+ * SwAttrIter::GetNextAttr()
+ *************************************************************************/
+
+xub_StrLen SwAttrIter::GetNextAttr( ) const
+{
+ xub_StrLen nNext = STRING_LEN;
+ if( pHints )
+ {
+ if (pHints->GetStartCount() > nStartIndex) // Gibt es noch Starts?
+ nNext = (*pHints->GetStart(nStartIndex)->GetStart());
+ if (pHints->GetEndCount() > nEndIndex) // Gibt es noch Enden?
+ {
+ xub_StrLen nNextEnd = (*pHints->GetEnd(nEndIndex)->GetAnyEnd());
+ if ( nNextEnd<nNext ) nNext = nNextEnd; // Wer ist naeher?
+ }
+ }
+ if (m_pTxtNode!=NULL) {
+ //TODO maybe use hints like FieldHints for this instead of looking at the text...
+ int l=(nNext<m_pTxtNode->Len()?nNext:m_pTxtNode->Len());
+ USHORT p=nPos;
+ const sal_Unicode *txt=m_pTxtNode->GetTxt().GetBuffer();
+ while(p<l && txt[p]!=CH_TXT_ATR_FIELDSTART && txt[p]!=CH_TXT_ATR_FIELDEND && txt[p]!=CH_TXT_ATR_FORMELEMENT) p++;
+ if ((p<l && p>nPos) || nNext<=p)
+ nNext=p;
+ else
+ nNext=p+1;
+ }
+ if( pRedln )
+ return pRedln->GetNextRedln( nNext );
+ return nNext;
+}
+
+#if OSL_DEBUG_LEVEL > 1
+/*************************************************************************
+ * SwAttrIter::Dump()
+ *************************************************************************/
+
+void SwAttrIter::Dump( SvStream &/*rOS*/ ) const
+{
+// Noch nicht an den neuen Attributiterator angepasst ...
+}
+
+#endif
+
+class SwMinMaxArgs
+{
+public:
+ OutputDevice* pOut;
+ ViewShell* pSh;
+ ULONG &rMin;
+ ULONG &rMax;
+ ULONG &rAbsMin;
+ long nRowWidth;
+ long nWordWidth;
+ long nWordAdd;
+ xub_StrLen nNoLineBreak;
+ SwMinMaxArgs( OutputDevice* pOutI, ViewShell* pShI, ULONG& rMinI, ULONG &rMaxI, ULONG &rAbsI )
+ : pOut( pOutI ), pSh( pShI ), rMin( rMinI ), rMax( rMaxI ), rAbsMin( rAbsI )
+ { nRowWidth = nWordWidth = nWordAdd = 0; nNoLineBreak = STRING_LEN; }
+ void Minimum( long nNew ) { if( (long)rMin < nNew ) rMin = nNew; }
+ void NewWord() { nWordAdd = nWordWidth = 0; }
+};
+
+sal_Bool lcl_MinMaxString( SwMinMaxArgs& rArg, SwFont* pFnt, const XubString &rTxt,
+ xub_StrLen nIdx, xub_StrLen nEnd )
+{
+ sal_Bool bRet = sal_False;
+ while( nIdx < nEnd )
+ {
+ xub_StrLen nStop = nIdx;
+ sal_Bool bClear;
+ LanguageType eLang = pFnt->GetLanguage();
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ bClear = CH_BLANK == rTxt.GetChar( nStop );
+ Boundary aBndry( pBreakIt->GetBreakIter()->getWordBoundary( rTxt, nIdx,
+ pBreakIt->GetLocale( eLang ),
+ WordType::DICTIONARY_WORD, TRUE ) );
+ nStop = (xub_StrLen)aBndry.endPos;
+ if( nIdx <= aBndry.startPos && nIdx && nIdx-1 != rArg.nNoLineBreak )
+ rArg.NewWord();
+ if( nStop == nIdx )
+ ++nStop;
+ if( nStop > nEnd )
+ nStop = nEnd;
+ }
+ else
+ {
+ while( nStop < nEnd && CH_BLANK != rTxt.GetChar( nStop ) )
+ ++nStop;
+ bClear = nStop == nIdx;
+ if ( bClear )
+ {
+ rArg.NewWord();
+ while( nStop < nEnd && CH_BLANK == rTxt.GetChar( nStop ) )
+ ++nStop;
+ }
+ }
+
+ SwDrawTextInfo aDrawInf( rArg.pSh, *rArg.pOut, 0, rTxt, nIdx, nStop - nIdx );
+ long nAktWidth = pFnt->_GetTxtSize( aDrawInf ).Width();
+ rArg.nRowWidth += nAktWidth;
+ if( bClear )
+ rArg.NewWord();
+ else
+ {
+ rArg.nWordWidth += nAktWidth;
+ if( (long)rArg.rAbsMin < rArg.nWordWidth )
+ rArg.rAbsMin = rArg.nWordWidth;
+ rArg.Minimum( rArg.nWordWidth + rArg.nWordAdd );
+ bRet = sal_True;
+ }
+ nIdx = nStop;
+ }
+ return bRet;
+}
+
+sal_Bool SwTxtNode::IsSymbol( const xub_StrLen nBegin ) const
+{
+ SwScriptInfo aScriptInfo;
+ SwAttrIter aIter( *(SwTxtNode*)this, aScriptInfo );
+ aIter.Seek( nBegin );
+ const SwRootFrm* pTmpRootFrm = getIDocumentLayoutAccess()->GetRootFrm();
+ return aIter.GetFnt()->IsSymbol( pTmpRootFrm ?
+ pTmpRootFrm->GetCurrShell() :
+ 0 );
+}
+
+class SwMinMaxNodeArgs
+{
+public:
+ ULONG nMaxWidth; // Summe aller Rahmenbreite
+ long nMinWidth; // Breitester Rahmen
+ long nLeftRest; // noch nicht von Rahmen ueberdeckter Platz im l. Rand
+ long nRightRest; // noch nicht von Rahmen ueberdeckter Platz im r. Rand
+ long nLeftDiff; // Min/Max-Differenz des Rahmens im linken Rand
+ long nRightDiff; // Min/Max-Differenz des Rahmens im rechten Rand
+ ULONG nIndx; // Indexnummer des Nodes
+ void Minimum( long nNew ) { if( nNew > nMinWidth ) nMinWidth = nNew; }
+};
+
+sal_Bool lcl_MinMaxNode( const SwFrmFmtPtr& rpNd, void* pArgs )
+{
+ const SwFmtAnchor& rFmtA = ((SwFrmFmt*)rpNd)->GetAnchor();
+
+ bool bCalculate = false;
+ if ((FLY_AT_PARA == rFmtA.GetAnchorId()) ||
+ (FLY_AT_CHAR == rFmtA.GetAnchorId()))
+ {
+ bCalculate = true;
+ }
+
+ if (bCalculate)
+ {
+ const SwMinMaxNodeArgs *pIn = (const SwMinMaxNodeArgs*)pArgs;
+ const SwPosition *pPos = rFmtA.GetCntntAnchor();
+ ASSERT(pPos && pIn, "Unexpected NULL arguments");
+ if (!pPos || !pIn || pIn->nIndx != pPos->nNode.GetIndex())
+ bCalculate = false;
+ }
+
+ if (bCalculate)
+ {
+ long nMin, nMax;
+ SwHTMLTableLayout *pLayout = 0;
+ MSHORT nWhich = ((SwFrmFmt*)rpNd)->Which();
+ if( RES_DRAWFRMFMT != nWhich )
+ {
+ // Enthaelt der Rahmen zu Beginn oder am Ende eine Tabelle?
+ const SwNodes& rNodes = static_cast<SwFrmFmt*>(rpNd)->GetDoc()->GetNodes();
+ const SwFmtCntnt& rFlyCntnt = ((SwFrmFmt*)rpNd)->GetCntnt();
+ ULONG nStt = rFlyCntnt.GetCntntIdx()->GetIndex();
+ SwTableNode* pTblNd = rNodes[nStt+1]->GetTableNode();
+ if( !pTblNd )
+ {
+ SwNode *pNd = rNodes[nStt];
+ pNd = rNodes[pNd->EndOfSectionIndex()-1];
+ if( pNd->IsEndNode() )
+ pTblNd = pNd->StartOfSectionNode()->GetTableNode();
+ }
+
+ if( pTblNd )
+ pLayout = pTblNd->GetTable().GetHTMLTableLayout();
+ }
+
+ const SwFmtHoriOrient& rOrient = ((SwFrmFmt*)rpNd)->GetHoriOrient();
+ sal_Int16 eHoriOri = rOrient.GetHoriOrient();
+
+ long nDiff;
+ if( pLayout )
+ {
+ nMin = pLayout->GetMin();
+ nMax = pLayout->GetMax();
+ nDiff = nMax - nMin;
+ }
+ else
+ {
+ if( RES_DRAWFRMFMT == nWhich )
+ {
+ const SdrObject* pSObj = rpNd->FindSdrObject();
+ if( pSObj )
+ nMin = pSObj->GetCurrentBoundRect().GetWidth();
+ else
+ nMin = 0;
+
+ }
+ else
+ {
+ const SwFmtFrmSize &rSz = ( (SwFrmFmt*)rpNd )->GetFrmSize();
+ nMin = rSz.GetWidth();
+ }
+ nMax = nMin;
+ nDiff = 0;
+ }
+
+ const SvxLRSpaceItem &rLR = ( (SwFrmFmt*)rpNd )->GetLRSpace();
+ nMin += rLR.GetLeft();
+ nMin += rLR.GetRight();
+ nMax += rLR.GetLeft();
+ nMax += rLR.GetRight();
+
+ if( SURROUND_THROUGHT == ((SwFrmFmt*)rpNd)->GetSurround().GetSurround() )
+ {
+ ( (SwMinMaxNodeArgs*)pArgs )->Minimum( nMin );
+ return sal_True;
+ }
+
+ // Rahmen, die recht bzw. links ausgerichtet sind, gehen nur
+ // teilweise in die Max-Berechnung ein, da der Rand schon berueck-
+ // sichtigt wird. Nur wenn die Rahmen in den Textkoerper ragen,
+ // wird dieser Teil hinzuaddiert.
+ switch( eHoriOri )
+ {
+ case text::HoriOrientation::RIGHT:
+ {
+ if( nDiff )
+ {
+ ((SwMinMaxNodeArgs*)pArgs)->nRightRest -=
+ ((SwMinMaxNodeArgs*)pArgs)->nRightDiff;
+ ((SwMinMaxNodeArgs*)pArgs)->nRightDiff = nDiff;
+ }
+ if( text::RelOrientation::FRAME != rOrient.GetRelationOrient() )
+ {
+ if( ((SwMinMaxNodeArgs*)pArgs)->nRightRest > 0 )
+ ((SwMinMaxNodeArgs*)pArgs)->nRightRest = 0;
+ }
+ ((SwMinMaxNodeArgs*)pArgs)->nRightRest -= nMin;
+ break;
+ }
+ case text::HoriOrientation::LEFT:
+ {
+ if( nDiff )
+ {
+ ((SwMinMaxNodeArgs*)pArgs)->nLeftRest -=
+ ((SwMinMaxNodeArgs*)pArgs)->nLeftDiff;
+ ((SwMinMaxNodeArgs*)pArgs)->nLeftDiff = nDiff;
+ }
+ if( text::RelOrientation::FRAME != rOrient.GetRelationOrient() &&
+ ((SwMinMaxNodeArgs*)pArgs)->nLeftRest < 0 )
+ ((SwMinMaxNodeArgs*)pArgs)->nLeftRest = 0;
+ ((SwMinMaxNodeArgs*)pArgs)->nLeftRest -= nMin;
+ break;
+ }
+ default:
+ {
+ ( (SwMinMaxNodeArgs*)pArgs )->nMaxWidth += nMax;
+ ( (SwMinMaxNodeArgs*)pArgs )->Minimum( nMin );
+ }
+ }
+ }
+ return sal_True;
+}
+
+#define FLYINCNT_MIN_WIDTH 284
+
+// changing this method very likely requires changing of
+// "GetScalingOfSelectedText"
+void SwTxtNode::GetMinMaxSize( ULONG nIndex, ULONG& rMin, ULONG &rMax,
+ ULONG& rAbsMin, OutputDevice* pOut ) const
+{
+ ViewShell* pSh = 0;
+ GetDoc()->GetEditShell( &pSh );
+ if( !pOut )
+ {
+ if( pSh )
+ pOut = pSh->GetWin();
+ if( !pOut )
+ pOut = GetpApp()->GetDefaultDevice();
+ }
+
+ MapMode aOldMap( pOut->GetMapMode() );
+ pOut->SetMapMode( MapMode( MAP_TWIP ) );
+
+ rMin = 0;
+ rMax = 0;
+ rAbsMin = 0;
+
+ const SvxLRSpaceItem &rSpace = GetSwAttrSet().GetLRSpace();
+ long nLROffset = rSpace.GetTxtLeft() + GetLeftMarginWithNum( sal_True );
+ short nFLOffs;
+ // Bei Numerierung ist ein neg. Erstzeileneinzug vermutlich
+ // bereits gefuellt...
+ if( !GetFirstLineOfsWithNum( nFLOffs ) || nFLOffs > nLROffset )
+ nLROffset = nFLOffs;
+
+ SwMinMaxNodeArgs aNodeArgs;
+ aNodeArgs.nMinWidth = 0;
+ aNodeArgs.nMaxWidth = 0;
+ aNodeArgs.nLeftRest = nLROffset;
+ aNodeArgs.nRightRest = rSpace.GetRight();
+ aNodeArgs.nLeftDiff = 0;
+ aNodeArgs.nRightDiff = 0;
+ if( nIndex )
+ {
+ SwSpzFrmFmts* pTmp = (SwSpzFrmFmts*)GetDoc()->GetSpzFrmFmts();
+ if( pTmp )
+ {
+ aNodeArgs.nIndx = nIndex;
+ pTmp->ForEach( &lcl_MinMaxNode, &aNodeArgs );
+ }
+ }
+ if( aNodeArgs.nLeftRest < 0 )
+ aNodeArgs.Minimum( nLROffset - aNodeArgs.nLeftRest );
+ aNodeArgs.nLeftRest -= aNodeArgs.nLeftDiff;
+ if( aNodeArgs.nLeftRest < 0 )
+ aNodeArgs.nMaxWidth -= aNodeArgs.nLeftRest;
+
+ if( aNodeArgs.nRightRest < 0 )
+ aNodeArgs.Minimum( rSpace.GetRight() - aNodeArgs.nRightRest );
+ aNodeArgs.nRightRest -= aNodeArgs.nRightDiff;
+ if( aNodeArgs.nRightRest < 0 )
+ aNodeArgs.nMaxWidth -= aNodeArgs.nRightRest;
+
+ SwScriptInfo aScriptInfo;
+ SwAttrIter aIter( *(SwTxtNode*)this, aScriptInfo );
+ xub_StrLen nIdx = 0;
+ aIter.SeekAndChgAttrIter( nIdx, pOut );
+ xub_StrLen nLen = m_Text.Len();
+ long nAktWidth = 0;
+ MSHORT nAdd = 0;
+ SwMinMaxArgs aArg( pOut, pSh, rMin, rMax, rAbsMin );
+ while( nIdx < nLen )
+ {
+ xub_StrLen nNextChg = aIter.GetNextAttr();
+ xub_StrLen nStop = aScriptInfo.NextScriptChg( nIdx );
+ if( nNextChg > nStop )
+ nNextChg = nStop;
+ SwTxtAttr *pHint = NULL;
+ xub_Unicode cChar = CH_BLANK;
+ nStop = nIdx;
+ while( nStop < nLen && nStop < nNextChg &&
+ CH_TAB != ( cChar = m_Text.GetChar( nStop ) ) &&
+ CH_BREAK != cChar && CHAR_HARDBLANK != cChar &&
+ CHAR_HARDHYPHEN != cChar && CHAR_SOFTHYPHEN != cChar &&
+ !pHint )
+ {
+ if( ( CH_TXTATR_BREAKWORD != cChar && CH_TXTATR_INWORD != cChar )
+ || ( 0 == ( pHint = aIter.GetAttr( nStop ) ) ) )
+ ++nStop;
+ }
+ if ( lcl_MinMaxString( aArg, aIter.GetFnt(), m_Text, nIdx, nStop ) )
+ {
+ nAdd = 20;
+ }
+ nIdx = nStop;
+ aIter.SeekAndChgAttrIter( nIdx, pOut );
+ switch( cChar )
+ {
+ case CH_BREAK :
+ {
+ if( (long)rMax < aArg.nRowWidth )
+ rMax = aArg.nRowWidth;
+ aArg.nRowWidth = 0;
+ aArg.NewWord();
+ aIter.SeekAndChgAttrIter( ++nIdx, pOut );
+ }
+ break;
+ case CH_TAB :
+ {
+ aArg.NewWord();
+ aIter.SeekAndChgAttrIter( ++nIdx, pOut );
+ }
+ break;
+ case CHAR_SOFTHYPHEN:
+ ++nIdx;
+ break;
+ case CHAR_HARDBLANK:
+ case CHAR_HARDHYPHEN:
+ {
+ XubString sTmp( cChar );
+ const SwRootFrm* pTmpRootFrm = getIDocumentLayoutAccess()->GetRootFrm();
+ SwDrawTextInfo aDrawInf( pTmpRootFrm ?
+ pTmpRootFrm->GetCurrShell() :
+ 0, *pOut, 0, sTmp, 0, 1, 0, sal_False );
+ nAktWidth = aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
+ aArg.nWordWidth += nAktWidth;
+ aArg.nRowWidth += nAktWidth;
+ if( (long)rAbsMin < aArg.nWordWidth )
+ rAbsMin = aArg.nWordWidth;
+ aArg.Minimum( aArg.nWordWidth + aArg.nWordAdd );
+ aArg.nNoLineBreak = nIdx++;
+ }
+ break;
+ case CH_TXTATR_BREAKWORD:
+ case CH_TXTATR_INWORD:
+ {
+ if( !pHint )
+ break;
+ long nOldWidth = aArg.nWordWidth;
+ long nOldAdd = aArg.nWordAdd;
+ aArg.NewWord();
+
+ switch( pHint->Which() )
+ {
+ case RES_TXTATR_FLYCNT :
+ {
+ SwFrmFmt *pFrmFmt = pHint->GetFlyCnt().GetFrmFmt();
+ const SvxLRSpaceItem &rLR = pFrmFmt->GetLRSpace();
+ if( RES_DRAWFRMFMT == pFrmFmt->Which() )
+ {
+ const SdrObject* pSObj = pFrmFmt->FindSdrObject();
+ if( pSObj )
+ nAktWidth = pSObj->GetCurrentBoundRect().GetWidth();
+ else
+ nAktWidth = 0;
+ }
+ else
+ {
+ const SwFmtFrmSize& rTmpSize = pFrmFmt->GetFrmSize();
+ if( RES_FLYFRMFMT == pFrmFmt->Which()
+ && rTmpSize.GetWidthPercent() )
+ {
+/*-----------------24.01.97 14:09----------------------------------------------
+ * Hier ein HACK fuer folgende Situation: In dem Absatz befindet sich
+ * ein Textrahmen mit relativer Groesse. Dann nehmen wir mal als minimale
+ * Breite 0,5 cm und als maximale KSHRT_MAX.
+ * Sauberer und vielleicht spaeter notwendig waere es, ueber den Inhalt
+ * des Textrahmens zu iterieren und GetMinMaxSize rekursiv zu rufen.
+ * --------------------------------------------------------------------------*/
+ nAktWidth = FLYINCNT_MIN_WIDTH; // 0,5 cm
+ if( (long)rMax < KSHRT_MAX )
+ rMax = KSHRT_MAX;
+ }
+ else
+ nAktWidth = pFrmFmt->GetFrmSize().GetWidth();
+ }
+ nAktWidth += rLR.GetLeft();
+ nAktWidth += rLR.GetRight();
+ aArg.nWordAdd = nOldWidth + nOldAdd;
+ aArg.nWordWidth = nAktWidth;
+ aArg.nRowWidth += nAktWidth;
+ if( (long)rAbsMin < aArg.nWordWidth )
+ rAbsMin = aArg.nWordWidth;
+ aArg.Minimum( aArg.nWordWidth + aArg.nWordAdd );
+ break;
+ }
+ case RES_TXTATR_FTN :
+ {
+ const XubString aTxt = pHint->GetFtn().GetNumStr();
+ if( lcl_MinMaxString( aArg, aIter.GetFnt(), aTxt, 0,
+ aTxt.Len() ) )
+ nAdd = 20;
+ break;
+ }
+ case RES_TXTATR_FIELD :
+ {
+ SwField *pFld = (SwField*)pHint->GetFld().GetFld();
+ const String aTxt = pFld->GetCntnt( FALSE );
+ if( lcl_MinMaxString( aArg, aIter.GetFnt(), aTxt, 0,
+ aTxt.Len() ) )
+ nAdd = 20;
+ break;
+ }
+ default: aArg.nWordWidth = nOldWidth;
+ aArg.nWordAdd = nOldAdd;
+
+ }
+ aIter.SeekAndChgAttrIter( ++nIdx, pOut );
+ }
+ break;
+ }
+ }
+ if( (long)rMax < aArg.nRowWidth )
+ rMax = aArg.nRowWidth;
+
+ nLROffset += rSpace.GetRight();
+
+ rAbsMin += nLROffset;
+ rAbsMin += nAdd;
+ rMin += nLROffset;
+ rMin += nAdd;
+ if( (long)rMin < aNodeArgs.nMinWidth )
+ rMin = aNodeArgs.nMinWidth;
+ if( (long)rAbsMin < aNodeArgs.nMinWidth )
+ rAbsMin = aNodeArgs.nMinWidth;
+ rMax += aNodeArgs.nMaxWidth;
+ rMax += nLROffset;
+ rMax += nAdd;
+ if( rMax < rMin ) // z.B. Rahmen mit Durchlauf gehen zunaechst nur
+ rMax = rMin; // in das Minimum ein
+ pOut->SetMapMode( aOldMap );
+}
+
+/*************************************************************************
+ * SwTxtNode::GetScalingOfSelectedText()
+ *
+ * Calculates the width of the text part specified by nStt and nEnd,
+ * the height of the line containing nStt is devided by this width,
+ * indicating the scaling factor, if the text part is rotated.
+ * Having CH_BREAKs in the text part, this method returns the scaling
+ * factor for the longest of the text parts separated by the CH_BREAKs.
+ *
+ * changing this method very likely requires changing of "GetMinMaxSize"
+ *************************************************************************/
+
+USHORT SwTxtNode::GetScalingOfSelectedText( xub_StrLen nStt, xub_StrLen nEnd )
+ const
+{
+ ViewShell* pSh = NULL;
+ OutputDevice* pOut = NULL;
+ GetDoc()->GetEditShell( &pSh );
+
+ if ( pSh )
+ pOut = &pSh->GetRefDev();
+ else
+ {
+ //Zugriff ueber StarONE, es muss keine Shell existieren oder aktiv sein.
+ if ( getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) )
+ pOut = GetpApp()->GetDefaultDevice();
+ else
+ pOut = getIDocumentDeviceAccess()->getReferenceDevice( true );
+ }
+
+ ASSERT( pOut, "GetScalingOfSelectedText without outdev" )
+
+ MapMode aOldMap( pOut->GetMapMode() );
+ pOut->SetMapMode( MapMode( MAP_TWIP ) );
+
+ if ( nStt == nEnd )
+ {
+ if ( !pBreakIt->GetBreakIter().is() )
+ return 100;
+
+ SwScriptInfo aScriptInfo;
+ SwAttrIter aIter( *(SwTxtNode*)this, aScriptInfo );
+ aIter.SeekAndChgAttrIter( nStt, pOut );
+
+ Boundary aBound =
+ pBreakIt->GetBreakIter()->getWordBoundary( GetTxt(), nStt,
+ pBreakIt->GetLocale( aIter.GetFnt()->GetLanguage() ),
+ WordType::DICTIONARY_WORD, sal_True );
+
+ if ( nStt == aBound.startPos )
+ {
+ // cursor is at left or right border of word
+ pOut->SetMapMode( aOldMap );
+ return 100;
+ }
+
+ nStt = (xub_StrLen)aBound.startPos;
+ nEnd = (xub_StrLen)aBound.endPos;
+
+ if ( nStt == nEnd )
+ {
+ pOut->SetMapMode( aOldMap );
+ return 100;
+ }
+ }
+
+ SwScriptInfo aScriptInfo;
+ SwAttrIter aIter( *(SwTxtNode*)this, aScriptInfo );
+
+ // We do not want scaling attributes to be considered during this
+ // calculation. For this, we push a temporary scaling attribute with
+ // scaling value 100 and priority flag on top of the scaling stack
+ SwAttrHandler& rAH = aIter.GetAttrHandler();
+ SvxCharScaleWidthItem aItem(100, RES_CHRATR_SCALEW);
+ SwTxtAttrEnd aAttr( aItem, nStt, nEnd );
+ aAttr.SetPriorityAttr( sal_True );
+ rAH.PushAndChg( aAttr, *(aIter.GetFnt()) );
+
+ xub_StrLen nIdx = nStt;
+
+ ULONG nWidth = 0;
+ ULONG nProWidth = 0;
+
+ while( nIdx < nEnd )
+ {
+ aIter.SeekAndChgAttrIter( nIdx, pOut );
+
+ // scan for end of portion
+ xub_StrLen nNextChg = aIter.GetNextAttr();
+ xub_StrLen nStop = aScriptInfo.NextScriptChg( nIdx );
+ if( nNextChg > nStop )
+ nNextChg = nStop;
+
+ nStop = nIdx;
+ xub_Unicode cChar = CH_BLANK;
+ SwTxtAttr* pHint = NULL;
+
+ // stop at special characters in [ nIdx, nNextChg ]
+ while( nStop < nEnd && nStop < nNextChg )
+ {
+ cChar = m_Text.GetChar( nStop );
+ if( CH_TAB == cChar || CH_BREAK == cChar ||
+ CHAR_HARDBLANK == cChar || CHAR_HARDHYPHEN == cChar ||
+ CHAR_SOFTHYPHEN == cChar ||
+ ( CH_TXTATR_BREAKWORD == cChar || CH_TXTATR_INWORD == cChar ) &&
+ ( 0 == ( pHint = aIter.GetAttr( nStop ) ) ) )
+ break;
+ else
+ ++nStop;
+ }
+
+ // calculate text widths up to cChar
+ if ( nStop > nIdx )
+ {
+ SwDrawTextInfo aDrawInf( pSh, *pOut, 0, GetTxt(), nIdx, nStop - nIdx );
+ nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
+ }
+
+ nIdx = nStop;
+ aIter.SeekAndChgAttrIter( nIdx, pOut );
+
+ if ( cChar == CH_BREAK )
+ {
+ nWidth = Max( nWidth, nProWidth );
+ nProWidth = 0;
+ nIdx++;
+ }
+ else if ( cChar == CH_TAB )
+ {
+ // tab receives width of one space
+ XubString sTmp( CH_BLANK );
+ SwDrawTextInfo aDrawInf( pSh, *pOut, 0, sTmp, 0, 1 );
+ nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
+ nIdx++;
+ }
+ else if ( cChar == CHAR_SOFTHYPHEN )
+ ++nIdx;
+ else if ( cChar == CHAR_HARDBLANK || cChar == CHAR_HARDHYPHEN )
+ {
+ XubString sTmp( cChar );
+ SwDrawTextInfo aDrawInf( pSh, *pOut, 0, sTmp, 0, 1 );
+ nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
+ nIdx++;
+ }
+ else if ( pHint && ( cChar == CH_TXTATR_BREAKWORD || CH_TXTATR_INWORD ) )
+ {
+ switch( pHint->Which() )
+ {
+ case RES_TXTATR_FTN :
+ {
+ const XubString aTxt = pHint->GetFtn().GetNumStr();
+ SwDrawTextInfo aDrawInf( pSh, *pOut, 0, aTxt, 0, aTxt.Len() );
+
+ nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
+ break;
+ }
+ case RES_TXTATR_FIELD :
+ {
+ SwField *pFld = (SwField*)pHint->GetFld().GetFld();
+ const String aTxt = pFld->GetCntnt( FALSE );
+ SwDrawTextInfo aDrawInf( pSh, *pOut, 0, aTxt, 0, aTxt.Len() );
+
+ nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
+ break;
+ }
+ default:
+ {
+ // any suggestions for a default action?
+ }
+ } // end of switch
+ nIdx++;
+ } // end of while
+ }
+
+ nWidth = Max( nWidth, nProWidth );
+
+ // search for a text frame this node belongs to
+ SwClientIter aClientIter( *(SwTxtNode*)this );
+ SwClient* pLastFrm = aClientIter.GoStart();
+ SwTxtFrm* pFrm = 0;
+
+ while( pLastFrm )
+ {
+ if ( pLastFrm->ISA( SwTxtFrm ) )
+ {
+ SwTxtFrm* pTmpFrm = ( SwTxtFrm* )pLastFrm;
+ if ( pTmpFrm->GetOfst() <= nStt &&
+ ( !pTmpFrm->GetFollow() ||
+ pTmpFrm->GetFollow()->GetOfst() > nStt ) )
+ {
+ pFrm = pTmpFrm;
+ break;
+ }
+ }
+ pLastFrm = ++aClientIter;
+ }
+
+ // search for the line containing nStt
+ if ( pFrm && pFrm->HasPara() )
+ {
+ SwTxtInfo aInf( pFrm );
+ SwTxtIter aLine( pFrm, &aInf );
+ aLine.CharToLine( nStt );
+ pOut->SetMapMode( aOldMap );
+ return (USHORT)( nWidth ?
+ ( ( 100 * aLine.GetCurr()->Height() ) / nWidth ) : 0 );
+ }
+ // no frame or no paragraph, we take the height of the character
+ // at nStt as line height
+
+ aIter.SeekAndChgAttrIter( nStt, pOut );
+ pOut->SetMapMode( aOldMap );
+
+ SwDrawTextInfo aDrawInf( pSh, *pOut, 0, GetTxt(), nStt, 1 );
+ return (USHORT)
+ ( nWidth ? ((100 * aIter.GetFnt()->_GetTxtSize( aDrawInf ).Height()) / nWidth ) : 0 );
+}
+
+USHORT SwTxtNode::GetWidthOfLeadingTabs() const
+{
+ USHORT nRet = 0;
+
+ xub_StrLen nIdx = 0;
+ sal_Unicode cCh;
+
+ while ( nIdx < GetTxt().Len() &&
+ ( '\t' == ( cCh = GetTxt().GetChar( nIdx ) ) ||
+ ' ' == cCh ) )
+ ++nIdx;
+
+ if ( nIdx > 0 )
+ {
+ SwPosition aPos( *this );
+ aPos.nContent += nIdx;
+
+ // Find the non-follow text frame:
+ SwClientIter aClientIter( (SwTxtNode&)*this );
+ SwClient* pLastFrm = aClientIter.GoStart();
+
+ while( pLastFrm )
+ {
+ // Only consider master frames:
+ if ( pLastFrm->ISA(SwTxtFrm) &&
+ !static_cast<SwTxtFrm*>(pLastFrm)->IsFollow() )
+ {
+ const SwTxtFrm* pFrm = static_cast<SwTxtFrm*>(pLastFrm);
+ SWRECTFN( pFrm )
+ SwRect aRect;
+ pFrm->GetCharRect( aRect, aPos );
+ nRet = (USHORT)
+ ( pFrm->IsRightToLeft() ?
+ (pFrm->*fnRect->fnGetPrtRight)() - (aRect.*fnRect->fnGetRight)() :
+ (aRect.*fnRect->fnGetLeft)() - (pFrm->*fnRect->fnGetPrtLeft)() );
+ break;
+ }
+ pLastFrm = ++aClientIter;
+ }
+ }
+
+ return nRet;
+}