summaryrefslogtreecommitdiff
path: root/sw/source/core/text/txtfrm.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/text/txtfrm.cxx')
-rw-r--r--sw/source/core/text/txtfrm.cxx2753
1 files changed, 2753 insertions, 0 deletions
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
new file mode 100644
index 000000000000..0861f98b2ddf
--- /dev/null
+++ b/sw/source/core/text/txtfrm.cxx
@@ -0,0 +1,2753 @@
+/*************************************************************************
+ *
+ * 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 <hints.hxx>
+#include <svl/ctloptions.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/sfxuno.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/pgrditem.hxx>
+#include <swmodule.hxx>
+#include <SwSmartTagMgr.hxx>
+#include <doc.hxx> // GetDoc()
+#include <pagefrm.hxx> // InvalidateSpelling
+#include <rootfrm.hxx>
+#include <viewsh.hxx> // ViewShell
+#include <pam.hxx> // SwPosition
+#include <ndtxt.hxx> // SwTxtNode
+#include <txtatr.hxx>
+#include <paratr.hxx>
+#include <viewopt.hxx>
+#include <dflyobj.hxx>
+#include <flyfrm.hxx>
+#include <tabfrm.hxx>
+#include <frmtool.hxx>
+#include <pagedesc.hxx> // SwPageDesc
+#include <tgrditem.hxx>
+#include <dbg_lay.hxx>
+#include <fmtfld.hxx>
+#include <fmtftn.hxx>
+#include <txtfld.hxx>
+#include <txtftn.hxx>
+#include <charatr.hxx>
+#include <ftninfo.hxx>
+#include <fmtline.hxx>
+#include <txtfrm.hxx> // SwTxtFrm
+#include <sectfrm.hxx> // SwSectFrm
+#include <txtcfg.hxx> // DBG_LOOP
+#include <itrform2.hxx> // Iteratoren
+#include <widorp.hxx> // SwFrmBreak
+#include <txtcache.hxx>
+#include <fntcache.hxx> // GetLineSpace benutzt pLastFont
+#include <SwGrammarMarkUp.hxx>
+#include <lineinfo.hxx>
+#include <SwPortionHandler.hxx>
+// OD 2004-01-15 #110582#
+#include <dcontact.hxx>
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+// --> OD 2005-03-30 #???#
+#include <txtflcnt.hxx> // SwTxtFlyCnt
+#include <fmtflcnt.hxx> // SwFmtFlyCnt
+#include <fmtcntnt.hxx> // SwFmtCntnt
+// <--
+// --> OD 2008-01-31 #newlistlevelattrs#
+#include <numrule.hxx>
+// <--
+#include <swtable.hxx>
+#include <fldupde.hxx>
+#include <IGrammarContact.hxx>
+
+#if OSL_DEBUG_LEVEL > 1
+#include <txtpaint.hxx> // DbgRect
+extern const sal_Char *GetPrepName( const enum PrepareHint ePrep );
+#endif
+
+
+TYPEINIT1( SwTxtFrm, SwCntntFrm );
+
+// Switches width and height of the text frame
+void SwTxtFrm::SwapWidthAndHeight()
+{
+ if ( ! bIsSwapped )
+ {
+ const long nPrtOfstX = Prt().Pos().X();
+ Prt().Pos().X() = Prt().Pos().Y();
+ Prt().Pos().Y() = Frm().Width() - ( nPrtOfstX + Prt().Width() );
+ }
+ else
+ {
+ const long nPrtOfstY = Prt().Pos().Y();
+ Prt().Pos().Y() = Prt().Pos().X();
+ Prt().Pos().X() = Frm().Height() - ( nPrtOfstY + Prt().Height() );
+ }
+
+ const long nFrmWidth = Frm().Width();
+ Frm().Width( Frm().Height() );
+ Frm().Height( nFrmWidth );
+ const long nPrtWidth = Prt().Width();
+ Prt().Width( Prt().Height() );
+ Prt().Height( nPrtWidth );
+
+ bIsSwapped = ! bIsSwapped;
+}
+
+// Calculates the coordinates of a rectangle when switching from
+// horizontal to vertical layout.
+void SwTxtFrm::SwitchHorizontalToVertical( SwRect& rRect ) const
+{
+ // calc offset inside frame
+ const long nOfstX = rRect.Left() - Frm().Left();
+ const long nOfstY = rRect.Top() + rRect.Height() - Frm().Top();
+ const long nWidth = rRect.Width();
+ const long nHeight = rRect.Height();
+
+ if ( bIsSwapped )
+ rRect.Left( Frm().Left() + Frm().Height() - nOfstY );
+ else
+ // frame is rotated
+ rRect.Left( Frm().Left() + Frm().Width() - nOfstY );
+
+ rRect.Top( Frm().Top() + nOfstX );
+ rRect.Width( nHeight );
+ rRect.Height( nWidth );
+}
+
+// Calculates the coordinates of a point when switching from
+// horizontal to vertical layout.
+void SwTxtFrm::SwitchHorizontalToVertical( Point& rPoint ) const
+{
+ // calc offset inside frame
+ const long nOfstX = rPoint.X() - Frm().Left();
+ const long nOfstY = rPoint.Y() - Frm().Top();
+
+ if ( bIsSwapped )
+ rPoint.X() = Frm().Left() + Frm().Height() - nOfstY;
+ else
+ // calc rotated coords
+ rPoint.X() = Frm().Left() + Frm().Width() - nOfstY;
+
+ rPoint.Y() = Frm().Top() + nOfstX;
+}
+
+// Calculates the a limit value when switching from
+// horizontal to vertical layout.
+long SwTxtFrm::SwitchHorizontalToVertical( long nLimit ) const
+{
+ Point aTmp( 0, nLimit );
+ SwitchHorizontalToVertical( aTmp );
+ return aTmp.X();
+}
+
+// Calculates the coordinates of a rectangle when switching from
+// vertical to horizontal layout.
+void SwTxtFrm::SwitchVerticalToHorizontal( SwRect& rRect ) const
+{
+ long nOfstX;
+
+ // calc offset inside frame
+ if ( bIsSwapped )
+ nOfstX = Frm().Left() + Frm().Height() - ( rRect.Left() + rRect.Width() );
+ else
+ nOfstX = Frm().Left() + Frm().Width() - ( rRect.Left() + rRect.Width() );
+
+ const long nOfstY = rRect.Top() - Frm().Top();
+ const long nWidth = rRect.Height();
+ const long nHeight = rRect.Width();
+
+ // calc rotated coords
+ rRect.Left( Frm().Left() + nOfstY );
+ rRect.Top( Frm().Top() + nOfstX );
+ rRect.Width( nWidth );
+ rRect.Height( nHeight );
+}
+
+// Calculates the coordinates of a point when switching from
+// vertical to horizontal layout.
+void SwTxtFrm::SwitchVerticalToHorizontal( Point& rPoint ) const
+{
+ long nOfstX;
+
+ // calc offset inside frame
+ if ( bIsSwapped )
+ nOfstX = Frm().Left() + Frm().Height() - rPoint.X();
+ else
+ nOfstX = Frm().Left() + Frm().Width() - rPoint.X();
+
+ const long nOfstY = rPoint.Y() - Frm().Top();
+
+ // calc rotated coords
+ rPoint.X() = Frm().Left() + nOfstY;
+ rPoint.Y() = Frm().Top() + nOfstX;
+}
+
+// Calculates the a limit value when switching from
+// vertical to horizontal layout.
+long SwTxtFrm::SwitchVerticalToHorizontal( long nLimit ) const
+{
+ Point aTmp( nLimit, 0 );
+ SwitchVerticalToHorizontal( aTmp );
+ return aTmp.Y();
+}
+
+SwFrmSwapper::SwFrmSwapper( const SwTxtFrm* pTxtFrm, sal_Bool bSwapIfNotSwapped )
+ : pFrm( pTxtFrm ), bUndo( sal_False )
+{
+ if ( pFrm->IsVertical() &&
+ ( ( bSwapIfNotSwapped && ! pFrm->IsSwapped() ) ||
+ ( ! bSwapIfNotSwapped && pFrm->IsSwapped() ) ) )
+ {
+ bUndo = sal_True;
+ ((SwTxtFrm*)pFrm)->SwapWidthAndHeight();
+ }
+}
+
+SwFrmSwapper::~SwFrmSwapper()
+{
+ if ( bUndo )
+ ((SwTxtFrm*)pFrm)->SwapWidthAndHeight();
+}
+
+void SwTxtFrm::SwitchLTRtoRTL( SwRect& rRect ) const
+{
+ SWAP_IF_NOT_SWAPPED( this )
+
+ long nWidth = rRect.Width();
+ rRect.Left( 2 * ( Frm().Left() + Prt().Left() ) +
+ Prt().Width() - rRect.Right() - 1 );
+
+ rRect.Width( nWidth );
+
+ UNDO_SWAP( this )
+}
+
+void SwTxtFrm::SwitchLTRtoRTL( Point& rPoint ) const
+{
+ SWAP_IF_NOT_SWAPPED( this )
+
+ rPoint.X() = 2 * ( Frm().Left() + Prt().Left() ) + Prt().Width() - rPoint.X() - 1;
+
+ UNDO_SWAP( this )
+}
+
+SwLayoutModeModifier::SwLayoutModeModifier( const OutputDevice& rOutp ) :
+ rOut( rOutp ), nOldLayoutMode( rOutp.GetLayoutMode() )
+{
+}
+
+SwLayoutModeModifier::~SwLayoutModeModifier()
+{
+ ((OutputDevice&)rOut).SetLayoutMode( nOldLayoutMode );
+}
+
+void SwLayoutModeModifier::Modify( sal_Bool bChgToRTL )
+{
+ ((OutputDevice&)rOut).SetLayoutMode( bChgToRTL ?
+ TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL :
+ TEXT_LAYOUT_BIDI_STRONG );
+}
+
+void SwLayoutModeModifier::SetAuto()
+{
+ const ULONG nNewLayoutMode = nOldLayoutMode & ~TEXT_LAYOUT_BIDI_STRONG;
+ ((OutputDevice&)rOut).SetLayoutMode( nNewLayoutMode );
+}
+
+SwDigitModeModifier::SwDigitModeModifier( const OutputDevice& rOutp, LanguageType eCurLang ) :
+ rOut( rOutp ), nOldLanguageType( rOutp.GetDigitLanguage() )
+{
+ LanguageType eLang = eCurLang;
+ const SvtCTLOptions::TextNumerals nTextNumerals = SW_MOD()->GetCTLOptions().GetCTLTextNumerals();
+
+ if ( SvtCTLOptions::NUMERALS_HINDI == nTextNumerals )
+ eLang = LANGUAGE_ARABIC_SAUDI_ARABIA;
+ else if ( SvtCTLOptions::NUMERALS_ARABIC == nTextNumerals )
+ eLang = LANGUAGE_ENGLISH;
+ else if ( SvtCTLOptions::NUMERALS_SYSTEM == nTextNumerals )
+ eLang = (LanguageType)::GetAppLanguage();
+
+ ((OutputDevice&)rOut).SetDigitLanguage( eLang );
+}
+
+SwDigitModeModifier::~SwDigitModeModifier()
+{
+ ((OutputDevice&)rOut).SetDigitLanguage( nOldLanguageType );
+}
+
+/*************************************************************************
+ * SwTxtFrm::Init()
+ *************************************************************************/
+
+void SwTxtFrm::Init()
+{
+ ASSERT( !IsLocked(), "+SwTxtFrm::Init: this ist locked." );
+ if( !IsLocked() )
+ {
+ ClearPara();
+ ResetBlinkPor();
+ //Die Flags direkt setzen um ResetPreps und damit ein unnuetzes GetPara
+ //einzusparen.
+ // Nicht bOrphan, bLocked oder bWait auf sal_False setzen !
+ // bOrphan = bFlag7 = bFlag8 = sal_False;
+ }
+}
+
+/*************************************************************************
+|* SwTxtFrm::CTORen/DTOR
+|*************************************************************************/
+
+void SwTxtFrm::InitCtor()
+{
+ nCacheIdx = MSHRT_MAX;
+ nOfst = 0;
+ nAllLines = 0;
+ nThisLines = 0;
+ mnFlyAnchorOfst = 0;
+ mnFlyAnchorOfstNoWrap = 0;
+ mnFtnLine = 0;
+ // OD 2004-03-17 #i11860#
+ mnHeightOfLastLine = 0;
+ // --> OD 2008-01-31 #newlistlevelattrs#
+ mnAdditionalFirstLineOffset = 0;
+ // <--
+
+ nType = FRMC_TXT;
+ bLocked = bFormatted = bWidow = bUndersized = bJustWidow =
+ bEmpty = bInFtnConnect = bFtn = bRepaint = bBlinkPor =
+ bFieldFollow = bHasAnimation = bIsSwapped = sal_False;
+ // OD 14.03.2003 #i11760#
+ mbFollowFormatAllowed = sal_True;
+}
+
+/*************************************************************************
+ * SwTxtFrm::SwTxtFrm()
+ *************************************************************************/
+SwTxtFrm::SwTxtFrm(SwTxtNode * const pNode)
+ : SwCntntFrm(pNode)
+{
+ InitCtor();
+}
+
+/*************************************************************************
+ * SwTxtFrm::~SwTxtFrm()
+ *************************************************************************/
+SwTxtFrm::~SwTxtFrm()
+{
+ // Remove associated SwParaPortion from pTxtCache
+ ClearPara();
+}
+
+const XubString& SwTxtFrm::GetTxt() const
+{
+ return GetTxtNode()->GetTxt();
+}
+
+void SwTxtFrm::ResetPreps()
+{
+ if ( GetCacheIdx() != MSHRT_MAX )
+ {
+ SwParaPortion *pPara;
+ if( 0 != (pPara = GetPara()) )
+ pPara->ResetPreps();
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrm::IsHiddenNow()
+ *************************************************************************/
+sal_Bool SwTxtFrm::IsHiddenNow() const
+{
+ SwFrmSwapper aSwapper( this, sal_True );
+
+ if( !Frm().Width() && IsValid() && GetUpper()->IsValid() )
+ //bei Stackueberlauf (StackHack) invalid!
+ {
+// ASSERT( false, "SwTxtFrm::IsHiddenNow: thin frame" );
+ return sal_True;
+ }
+
+ const bool bHiddenCharsHidePara = GetTxtNode()->HasHiddenCharAttribute( true );
+ const bool bHiddenParaField = GetTxtNode()->HasHiddenParaField();
+ const ViewShell* pVsh = GetShell();
+
+ if ( pVsh && ( bHiddenCharsHidePara || bHiddenParaField ) )
+ {
+ if (
+ ( bHiddenParaField &&
+ ( !pVsh->GetViewOptions()->IsShowHiddenPara() &&
+ !pVsh->GetViewOptions()->IsFldName() ) ) ||
+ ( bHiddenCharsHidePara &&
+ !pVsh->GetViewOptions()->IsShowHiddenChar() ) )
+ {
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+
+/*************************************************************************
+ * SwTxtFrm::HideHidden()
+ *************************************************************************/
+// Entfernt die Anhaengsel des Textfrms wenn dieser hidden ist
+
+void SwTxtFrm::HideHidden()
+{
+ ASSERT( !GetFollow() && IsHiddenNow(),
+ "HideHidden on visible frame of hidden frame has follow" );
+
+ const xub_StrLen nEnd = STRING_LEN;
+ HideFootnotes( GetOfst(), nEnd );
+ // OD 2004-01-15 #110582#
+ HideAndShowObjects();
+
+ //Die Formatinfos sind jetzt obsolete
+ ClearPara();
+}
+
+/*************************************************************************
+ * SwTxtFrm::HideFootnotes()
+ *************************************************************************/
+void SwTxtFrm::HideFootnotes( xub_StrLen nStart, xub_StrLen nEnd )
+{
+ const SwpHints *pHints = GetTxtNode()->GetpSwpHints();
+ if( pHints )
+ {
+ const USHORT nSize = pHints->Count();
+ SwPageFrm *pPage = 0;
+ for ( USHORT i = 0; i < nSize; ++i )
+ {
+ const SwTxtAttr *pHt = (*pHints)[i];
+ if ( pHt->Which() == RES_TXTATR_FTN )
+ {
+ const xub_StrLen nIdx = *pHt->GetStart();
+ if ( nEnd < nIdx )
+ break;
+ if( nStart <= nIdx )
+ {
+ if( !pPage )
+ pPage = FindPageFrm();
+ pPage->RemoveFtn( this, (SwTxtFtn*)pHt );
+ }
+ }
+ }
+ }
+}
+
+// --> OD 2005-03-30 #120729# - hotfix: WW8 documents contain at its end hidden,
+// as-character anchored graphics, which are used for a graphic bullet list.
+// As long as these graphic bullet list aren't imported, do not hide a
+// at-character anchored object, if
+// (a) the document is an imported WW8 document -
+// checked by checking certain compatibility options -,
+// (b) the paragraph is the last content in the document and
+// (c) the anchor character is an as-character anchored graphic.
+bool lcl_HideObj( const SwTxtFrm& _rFrm,
+ const RndStdIds _eAnchorType,
+ const xub_StrLen _nObjAnchorPos,
+ SwAnchoredObject* _pAnchoredObj )
+{
+ bool bRet( true );
+
+ if (_eAnchorType == FLY_AT_CHAR)
+ {
+ const IDocumentSettingAccess* pIDSA = _rFrm.GetTxtNode()->getIDocumentSettingAccess();
+ if ( !pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) &&
+ !pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING) &&
+ !pIDSA->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) &&
+ pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
+ _rFrm.IsInDocBody() && !_rFrm.FindNextCnt() )
+ {
+ const xub_Unicode cAnchorChar =
+ _rFrm.GetTxtNode()->GetTxt().GetChar( _nObjAnchorPos );
+ if ( cAnchorChar == CH_TXTATR_BREAKWORD )
+ {
+ const SwTxtAttr* const pHint(
+ _rFrm.GetTxtNode()->GetTxtAttrForCharAt(_nObjAnchorPos,
+ RES_TXTATR_FLYCNT) );
+ if ( pHint )
+ {
+ const SwFrmFmt* pFrmFmt =
+ static_cast<const SwTxtFlyCnt*>(pHint)->GetFlyCnt().GetFrmFmt();
+ if ( pFrmFmt->Which() == RES_FLYFRMFMT )
+ {
+ SwNodeIndex nCntntIndex = *(pFrmFmt->GetCntnt().GetCntntIdx());
+ nCntntIndex++;
+ if ( nCntntIndex.GetNode().IsNoTxtNode() )
+ {
+ bRet = false;
+ // set needed data structure values for object positioning
+ SWRECTFN( (&_rFrm) );
+ SwRect aLastCharRect( _rFrm.Frm() );
+ (aLastCharRect.*fnRect->fnSetWidth)( 1 );
+ _pAnchoredObj->maLastCharRect = aLastCharRect;
+ _pAnchoredObj->mnLastTopOfLine = (aLastCharRect.*fnRect->fnGetTop)();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return bRet;
+}
+// <--
+/*************************************************************************
+ * SwTxtFrm::HideAndShowObjects()
+ *************************************************************************/
+/** method to hide/show objects
+
+ OD 2004-01-15 #110582#
+ method hides respectively shows objects, which are anchored at paragraph,
+ at/as a character of the paragraph, corresponding to the paragraph and
+ paragraph portion visibility.
+
+ - is called from HideHidden() - should hide objects in hidden paragraphs and
+ - from _Format() - should hide/show objects in partly visible paragraphs
+
+ @author OD
+*/
+void SwTxtFrm::HideAndShowObjects()
+{
+ if ( GetDrawObjs() )
+ {
+ if ( IsHiddenNow() )
+ {
+ // complete paragraph is hidden. Thus, hide all objects
+ for ( sal_uInt32 i = 0; i < GetDrawObjs()->Count(); ++i )
+ {
+ SdrObject* pObj = (*GetDrawObjs())[i]->DrawObj();
+ SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
+ // --> OD 2005-03-30 #120729# - hotfix: do not hide object
+ // under certain conditions
+ const RndStdIds eAnchorType( pContact->GetAnchorId() );
+ const xub_StrLen nObjAnchorPos = pContact->GetCntntAnchorIndex().GetIndex();
+ if ((eAnchorType != FLY_AT_CHAR) ||
+ lcl_HideObj( *this, eAnchorType, nObjAnchorPos,
+ (*GetDrawObjs())[i] ))
+ {
+ pContact->MoveObjToInvisibleLayer( pObj );
+ }
+ // <--
+ }
+ }
+ else
+ {
+ // paragraph is visible, but can contain hidden text portion.
+ // first we check if objects are allowed to be hidden:
+ const SwTxtNode& rNode = *GetTxtNode();
+ const ViewShell* pVsh = GetShell();
+ const bool bShouldBeHidden = !pVsh || !pVsh->GetWin() ||
+ !pVsh->GetViewOptions()->IsShowHiddenChar();
+
+ // Thus, show all objects, which are anchored at paragraph and
+ // hide/show objects, which are anchored at/as character, according
+ // to the visibility of the anchor character.
+ for ( sal_uInt32 i = 0; i < GetDrawObjs()->Count(); ++i )
+ {
+ SdrObject* pObj = (*GetDrawObjs())[i]->DrawObj();
+ SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
+ // --> OD 2005-03-30 #120729# - determine anchor type only once
+ const RndStdIds eAnchorType( pContact->GetAnchorId() );
+ // <--
+
+ if (eAnchorType == FLY_AT_PARA)
+ {
+ pContact->MoveObjToVisibleLayer( pObj );
+ }
+ else if ((eAnchorType == FLY_AT_CHAR) ||
+ (eAnchorType == FLY_AS_CHAR))
+ {
+ xub_StrLen nHiddenStart;
+ xub_StrLen nHiddenEnd;
+ xub_StrLen nObjAnchorPos = pContact->GetCntntAnchorIndex().GetIndex();
+ SwScriptInfo::GetBoundsOfHiddenRange( rNode, nObjAnchorPos, nHiddenStart, nHiddenEnd, 0 );
+ // --> OD 2005-03-30 #120729# - hotfix: do not hide object
+ // under certain conditions
+ if ( nHiddenStart != STRING_LEN && bShouldBeHidden &&
+ lcl_HideObj( *this, eAnchorType, nObjAnchorPos, (*GetDrawObjs())[i] ) )
+ // <--
+ pContact->MoveObjToInvisibleLayer( pObj );
+ else
+ pContact->MoveObjToVisibleLayer( pObj );
+ }
+ else
+ {
+ ASSERT( false,
+ "<SwTxtFrm::HideAndShowObjects()> - object not anchored at/inside paragraph!?" );
+ }
+ }
+ }
+ }
+
+ if ( IsFollow() )
+ {
+ FindMaster()->HideAndShowObjects();
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrm::FindBrk()
+ *
+ * Liefert die erste Trennmoeglichkeit in der aktuellen Zeile zurueck.
+ * Die Methode wird in SwTxtFrm::Format() benutzt, um festzustellen, ob
+ * die Vorgaengerzeile mitformatiert werden muss.
+ * nFound ist <= nEndLine.
+ *************************************************************************/
+
+xub_StrLen SwTxtFrm::FindBrk( const XubString &rTxt,
+ const xub_StrLen nStart,
+ const xub_StrLen nEnd ) const
+{
+ // --> OD 2009-12-28 #i104291# - applying patch to avoid overflow.
+ unsigned long nFound = nStart;
+ const xub_StrLen nEndLine = Min( nEnd, rTxt.Len() );
+
+ // Wir ueberlesen erst alle Blanks am Anfang der Zeile (vgl. Bug 2235).
+ while( nFound <= nEndLine &&
+ ' ' == rTxt.GetChar( static_cast<xub_StrLen>(nFound) ) )
+ {
+ nFound++;
+ }
+
+ // Eine knifflige Sache mit den TxtAttr-Dummy-Zeichen (hier "$"):
+ // "Dr.$Meyer" am Anfang der zweiten Zeile. Dahinter ein Blank eingegeben
+ // und das Wort rutscht nicht in die erste Zeile, obwohl es ginge.
+ // Aus diesem Grund nehmen wir das Dummy-Zeichen noch mit.
+ while( nFound <= nEndLine &&
+ ' ' != rTxt.GetChar( static_cast<xub_StrLen>(nFound) ) )
+ {
+ nFound++;
+ }
+
+ return nFound <= STRING_LEN
+ ? static_cast<xub_StrLen>(nFound)
+ : STRING_LEN;
+ // <--
+}
+
+/*************************************************************************
+ * SwTxtFrm::IsIdxInside()
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::IsIdxInside( const xub_StrLen nPos, const xub_StrLen nLen ) const
+{
+ if( GetOfst() > nPos + nLen ) // d.h., der Bereich liegt komplett vor uns.
+ return sal_False;
+
+ if( !GetFollow() ) // der Bereich liegt nicht komplett vor uns,
+ return sal_True; // nach uns kommt niemand mehr.
+
+ const xub_StrLen nMax = GetFollow()->GetOfst();
+
+ // der Bereich liegt nicht komplett hinter uns bzw.
+ // unser Text ist geloescht worden.
+ if( nMax > nPos || nMax > GetTxt().Len() )
+ return sal_True;
+
+ // changes made in the first line of a follow can modify the master
+ const SwParaPortion* pPara = GetFollow()->GetPara();
+ return pPara && ( nPos <= nMax + pPara->GetLen() );
+}
+
+/*************************************************************************
+ * SwTxtFrm::InvalidateRange()
+ *************************************************************************/
+inline void SwTxtFrm::InvalidateRange(const SwCharRange &aRange, const long nD)
+{
+ if ( IsIdxInside( aRange.Start(), aRange.Len() ) )
+ _InvalidateRange( aRange, nD );
+}
+
+/*************************************************************************
+ * SwTxtFrm::_InvalidateRange()
+ *************************************************************************/
+
+void SwTxtFrm::_InvalidateRange( const SwCharRange &aRange, const long nD)
+{
+ if ( !HasPara() )
+ { InvalidateSize();
+ return;
+ }
+
+ SetWidow( sal_False );
+ SwParaPortion *pPara = GetPara();
+
+ sal_Bool bInv = sal_False;
+ if( 0 != nD )
+ {
+ //Auf nDelta werden die Differenzen zwischen alter und
+ //neuer Zeilenlaenge aufaddiert, deshalb ist es negativ,
+ //wenn Zeichen eingefuegt wurden, positiv, wenn Zeichen
+ //geloescht wurden.
+ *(pPara->GetDelta()) += nD;
+ bInv = sal_True;
+ }
+ SwCharRange &rReformat = *(pPara->GetReformat());
+ if(aRange != rReformat) {
+ if( STRING_LEN == rReformat.Len() )
+ rReformat = aRange;
+ else
+ rReformat += aRange;
+ bInv = sal_True;
+ }
+ if(bInv)
+ {
+// 90365: nD is passed to a follow two times
+// if( GetFollow() )
+// ((SwTxtFrm*)GetFollow())->InvalidateRange( aRange, nD );
+ InvalidateSize();
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrm::CalcLineSpace()
+ *************************************************************************/
+
+void SwTxtFrm::CalcLineSpace()
+{
+ ASSERT( ! IsVertical() || ! IsSwapped(),
+ "SwTxtFrm::CalcLineSpace with swapped frame!" )
+
+ if( IsLocked() || !HasPara() )
+ return;
+
+ SwParaPortion *pPara;
+ if( GetDrawObjs() ||
+ GetTxtNode()->GetSwAttrSet().GetLRSpace().IsAutoFirst() ||
+ ( pPara = GetPara() )->IsFixLineHeight() )
+ {
+ Init();
+ return;
+ }
+
+ Size aNewSize( Prt().SSize() );
+
+ SwTxtFormatInfo aInf( this );
+ SwTxtFormatter aLine( this, &aInf );
+ if( aLine.GetDropLines() )
+ {
+ Init();
+ return;
+ }
+
+ aLine.Top();
+ aLine.RecalcRealHeight();
+
+ aNewSize.Height() = (aLine.Y() - Frm().Top()) + aLine.GetLineHeight();
+
+ SwTwips nDelta = aNewSize.Height() - Prt().Height();
+ // 4291: Unterlauf bei Flys
+ if( aInf.GetTxtFly()->IsOn() )
+ {
+ SwRect aTmpFrm( Frm() );
+ if( nDelta < 0 )
+ aTmpFrm.Height( Prt().Height() );
+ else
+ aTmpFrm.Height( aNewSize.Height() );
+ if( aInf.GetTxtFly()->Relax( aTmpFrm ) )
+ {
+ Init();
+ return;
+ }
+ }
+
+ if( nDelta )
+ {
+ SwTxtFrmBreak aBreak( this );
+ if( GetFollow() || aBreak.IsBreakNow( aLine ) )
+ {
+ // Wenn es einen Follow() gibt, oder wenn wir an dieser
+ // Stelle aufbrechen muessen, so wird neu formatiert.
+ Init();
+ }
+ else
+ {
+ // Alles nimmt seinen gewohnten Gang ...
+ pPara->SetPrepAdjust();
+ pPara->SetPrep();
+ }
+ }
+}
+
+//
+// SET_WRONG( nPos, nCnt, bMove )
+//
+#define SET_WRONG( nPos, nCnt, bMove ) \
+{ \
+ lcl_SetWrong( *this, nPos, nCnt, bMove ); \
+}
+
+void lcl_SetWrong( SwTxtFrm& rFrm, xub_StrLen nPos, long nCnt, bool bMove )
+{
+ if ( !rFrm.IsFollow() )
+ {
+ SwTxtNode* pTxtNode = rFrm.GetTxtNode();
+ IGrammarContact* pGrammarContact = getGrammarContact( *pTxtNode );
+ SwGrammarMarkUp* pWrongGrammar = pGrammarContact ?
+ pGrammarContact->getGrammarCheck( *pTxtNode, false ) :
+ pTxtNode->GetGrammarCheck();
+ bool bGrammarProxy = pWrongGrammar != pTxtNode->GetGrammarCheck();
+ if( bMove )
+ {
+ if( pTxtNode->GetWrong() )
+ pTxtNode->GetWrong()->Move( nPos, nCnt );
+ if( pWrongGrammar )
+ pWrongGrammar->MoveGrammar( nPos, nCnt );
+ if( bGrammarProxy && pTxtNode->GetGrammarCheck() )
+ pTxtNode->GetGrammarCheck()->MoveGrammar( nPos, nCnt );
+ if( pTxtNode->GetSmartTags() )
+ pTxtNode->GetSmartTags()->Move( nPos, nCnt );
+ }
+ else
+ {
+ xub_StrLen nLen = (xub_StrLen)nCnt;
+ if( pTxtNode->GetWrong() )
+ pTxtNode->GetWrong()->Invalidate( nPos, nLen );
+ if( pWrongGrammar )
+ pWrongGrammar->Invalidate( nPos, nLen );
+ if( pTxtNode->GetSmartTags() )
+ pTxtNode->GetSmartTags()->Invalidate( nPos, nLen );
+ }
+ if ( !pTxtNode->GetWrong() && !pTxtNode->IsWrongDirty() )
+ {
+ pTxtNode->SetWrong( new SwWrongList( WRONGLIST_SPELL ) );
+ pTxtNode->GetWrong()->SetInvalid( nPos, nPos + (USHORT)( nCnt > 0 ? nCnt : 1 ) );
+ }
+ if ( !pTxtNode->GetSmartTags() && !pTxtNode->IsSmartTagDirty() )
+ {
+ // SMARTTAGS
+ pTxtNode->SetSmartTags( new SwWrongList( WRONGLIST_SMARTTAG ) );
+ pTxtNode->GetSmartTags()->SetInvalid( nPos, nPos + (USHORT)( nCnt > 0 ? nCnt : 1 ) );
+ }
+ pTxtNode->SetWrongDirty( true );
+ pTxtNode->SetGrammarCheckDirty( true );
+ pTxtNode->SetWordCountDirty( true );
+ pTxtNode->SetAutoCompleteWordDirty( true );
+ // SMARTTAGS
+ pTxtNode->SetSmartTagDirty( true );
+ }
+
+ SwRootFrm *pRootFrm = rFrm.FindRootFrm();
+ if (pRootFrm)
+ {
+ pRootFrm->SetNeedGrammarCheck( TRUE );
+ }
+
+ SwPageFrm *pPage = rFrm.FindPageFrm();
+ if( pPage )
+ {
+ pPage->InvalidateSpelling();
+ pPage->InvalidateAutoCompleteWords();
+ pPage->InvalidateWordCount();
+ pPage->InvalidateSmartTags();
+ }
+}
+
+//
+// SET_SCRIPT_INVAL( nPos )
+//
+
+#define SET_SCRIPT_INVAL( nPos )\
+ lcl_SetScriptInval( *this, nPos );
+
+void lcl_SetScriptInval( SwTxtFrm& rFrm, xub_StrLen nPos )
+{
+ if( rFrm.GetPara() )
+ rFrm.GetPara()->GetScriptInfo().SetInvalidity( nPos );
+}
+
+void lcl_ModifyOfst( SwTxtFrm* pFrm, xub_StrLen nPos, xub_StrLen nLen )
+{
+ while( pFrm && pFrm->GetOfst() <= nPos )
+ pFrm = pFrm->GetFollow();
+ while( pFrm )
+ {
+ pFrm->ManipOfst( pFrm->GetOfst() + nLen );
+ pFrm = pFrm->GetFollow();
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrm::Modify()
+ *************************************************************************/
+
+void SwTxtFrm::Modify( SfxPoolItem *pOld, SfxPoolItem *pNew )
+{
+ const MSHORT nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+
+ //Wuensche die FrmAttribute betreffen werden von der Basisklasse
+ //verarbeitet.
+ if( IsInRange( aFrmFmtSetRange, nWhich ) || RES_FMT_CHG == nWhich )
+ {
+ SwCntntFrm::Modify( pOld, pNew );
+ if( nWhich == RES_FMT_CHG && GetShell() )
+ {
+ // Collection hat sich geaendert
+ Prepare( PREP_CLEAR );
+ _InvalidatePrt();
+ SET_WRONG( 0, STRING_LEN, false );
+ SetDerivedR2L( sal_False );
+ CheckDirChange();
+ // OD 09.12.2002 #105576# - Force complete paint due to existing
+ // indents.
+ SetCompletePaint();
+ InvalidateLineNum();
+ }
+ return;
+ }
+
+ // Im gelockten Zustand werden keine Bestellungen angenommen.
+ if( IsLocked() )
+ return;
+
+ // Dies spart Stack, man muss nur aufpassen,
+ // dass sie Variablen gesetzt werden.
+ xub_StrLen nPos, nLen;
+ sal_Bool bSetFldsDirty = sal_False;
+ sal_Bool bRecalcFtnFlag = sal_False;
+
+ switch( nWhich )
+ {
+ case RES_LINENUMBER:
+ {
+ InvalidateLineNum();
+ }
+ break;
+ case RES_INS_TXT:
+ {
+ nPos = ((SwInsTxt*)pNew)->nPos;
+ nLen = ((SwInsTxt*)pNew)->nLen;
+ if( IsIdxInside( nPos, nLen ) )
+ {
+ if( !nLen )
+ {
+ // 6969: Aktualisierung der NumPortions auch bei leeren Zeilen!
+ if( nPos )
+ InvalidateSize();
+ else
+ Prepare( PREP_CLEAR );
+ }
+ else
+ _InvalidateRange( SwCharRange( nPos, nLen ), nLen );
+ }
+ SET_WRONG( nPos, nLen, true )
+ SET_SCRIPT_INVAL( nPos )
+ bSetFldsDirty = sal_True;
+ if( HasFollow() )
+ lcl_ModifyOfst( this, nPos, nLen );
+ }
+ break;
+ case RES_DEL_CHR:
+ {
+ nPos = ((SwDelChr*)pNew)->nPos;
+ InvalidateRange( SwCharRange( nPos, 1 ), -1 );
+ SET_WRONG( nPos, -1, true )
+ SET_SCRIPT_INVAL( nPos )
+ bSetFldsDirty = bRecalcFtnFlag = sal_True;
+ if( HasFollow() )
+ lcl_ModifyOfst( this, nPos, STRING_LEN );
+ }
+ break;
+ case RES_DEL_TXT:
+ {
+ nPos = ((SwDelTxt*)pNew)->nStart;
+ nLen = ((SwDelTxt*)pNew)->nLen;
+ long m = nLen;
+ m *= -1;
+ if( IsIdxInside( nPos, nLen ) )
+ {
+ if( !nLen )
+ InvalidateSize();
+ else
+ InvalidateRange( SwCharRange( nPos, 1 ), m );
+ }
+ SET_WRONG( nPos, m, true )
+ SET_SCRIPT_INVAL( nPos )
+ bSetFldsDirty = bRecalcFtnFlag = sal_True;
+ if( HasFollow() )
+ lcl_ModifyOfst( this, nPos, nLen );
+ }
+ break;
+ case RES_UPDATE_ATTR:
+ {
+ nPos = ((SwUpdateAttr*)pNew)->nStart;
+ nLen = ((SwUpdateAttr*)pNew)->nEnd - nPos;
+ if( IsIdxInside( nPos, nLen ) )
+ {
+ // Es muss in jedem Fall neu formatiert werden,
+ // auch wenn der invalidierte Bereich null ist.
+ // Beispiel: leere Zeile, 14Pt einstellen !
+ // if( !nLen ) nLen = 1;
+
+ // 6680: FtnNummern muessen formatiert werden.
+ if( !nLen )
+ nLen = 1;
+
+ _InvalidateRange( SwCharRange( nPos, nLen) );
+ MSHORT nTmp = ((SwUpdateAttr*)pNew)->nWhichAttr;
+
+ if( ! nTmp || RES_TXTATR_CHARFMT == nTmp || RES_TXTATR_AUTOFMT == nTmp ||
+ RES_FMT_CHG == nTmp || RES_ATTRSET_CHG == nTmp )
+ {
+ SET_WRONG( nPos, nPos + nLen, false )
+ SET_SCRIPT_INVAL( nPos )
+ }
+ }
+
+ // --> OD 2010-02-16 #i104008#
+ if ( GetShell() )
+ {
+ GetShell()->InvalidateAccessibleParaAttrs( *this );
+ }
+ // <--
+ }
+ break;
+ case RES_OBJECTDYING:
+ break;
+
+ case RES_PARATR_LINESPACING:
+ {
+ CalcLineSpace();
+ InvalidateSize();
+ _InvalidatePrt();
+ if( IsInSct() && !GetPrev() )
+ {
+ SwSectionFrm *pSect = FindSctFrm();
+ if( pSect->ContainsAny() == this )
+ pSect->InvalidatePrt();
+ }
+
+ // OD 09.01.2004 #i11859# - correction:
+ // (1) Also invalidate next frame on next page/column.
+ // (2) Skip empty sections and hidden paragraphs
+ // Thus, use method <InvalidateNextPrtArea()>
+ InvalidateNextPrtArea();
+
+ SetCompletePaint();
+ }
+ break;
+ case RES_TXTATR_FIELD:
+ {
+ nPos = *((SwFmtFld*)pNew)->GetTxtFld()->GetStart();
+ if( IsIdxInside( nPos, 1 ) )
+ {
+ if( pNew == pOld )
+ {
+ // Nur repainten
+ // opt: invalidate aufs Window ?
+ InvalidatePage();
+ SetCompletePaint();
+ }
+ else
+ _InvalidateRange( SwCharRange( nPos, 1 ) );
+ }
+ bSetFldsDirty = sal_True;
+ // ST2
+ if ( SwSmartTagMgr::Get().IsSmartTagsEnabled() )
+ SET_WRONG( nPos, nPos + 1, false )
+ }
+ break;
+ case RES_TXTATR_FTN :
+ {
+ nPos = *((SwFmtFtn*)pNew)->GetTxtFtn()->GetStart();
+ if( IsInFtn() || IsIdxInside( nPos, 1 ) )
+ Prepare( PREP_FTN, ((SwFmtFtn*)pNew)->GetTxtFtn() );
+ break;
+ }
+
+ case RES_ATTRSET_CHG:
+ {
+ InvalidateLineNum();
+
+ SwAttrSet& rNewSet = *((SwAttrSetChg*)pNew)->GetChgSet();
+ const SfxPoolItem* pItem;
+ int nClear = 0;
+ MSHORT nCount = rNewSet.Count();
+
+ if( SFX_ITEM_SET == rNewSet.GetItemState( RES_TXTATR_FTN,
+ sal_False, &pItem ))
+ {
+ nPos = *((SwFmtFtn*)pItem)->GetTxtFtn()->GetStart();
+ if( IsIdxInside( nPos, 1 ) )
+ Prepare( PREP_FTN, pNew );
+ nClear = 0x01;
+ --nCount;
+ }
+
+ if( SFX_ITEM_SET == rNewSet.GetItemState( RES_TXTATR_FIELD,
+ sal_False, &pItem ))
+ {
+ nPos = *((SwFmtFld*)pItem)->GetTxtFld()->GetStart();
+ if( IsIdxInside( nPos, 1 ) )
+ {
+ const SfxPoolItem& rOldItem = ((SwAttrSetChg*)pOld)->
+ GetChgSet()->Get( RES_TXTATR_FIELD );
+ if( pItem == &rOldItem )
+ {
+ // Nur repainten
+ // opt: invalidate aufs Window ?
+ InvalidatePage();
+ SetCompletePaint();
+ }
+ else
+ _InvalidateRange( SwCharRange( nPos, 1 ) );
+ }
+ nClear |= 0x02;
+ --nCount;
+ }
+ sal_Bool bLineSpace = SFX_ITEM_SET == rNewSet.GetItemState(
+ RES_PARATR_LINESPACING, sal_False ),
+ bRegister = SFX_ITEM_SET == rNewSet.GetItemState(
+ RES_PARATR_REGISTER, sal_False );
+ if ( bLineSpace || bRegister )
+ {
+ Prepare( bRegister ? PREP_REGISTER : PREP_ADJUST_FRM );
+ CalcLineSpace();
+ InvalidateSize();
+ _InvalidatePrt();
+
+ // OD 09.01.2004 #i11859# - correction:
+ // (1) Also invalidate next frame on next page/column.
+ // (2) Skip empty sections and hidden paragraphs
+ // Thus, use method <InvalidateNextPrtArea()>
+ InvalidateNextPrtArea();
+
+ SetCompletePaint();
+ nClear |= 0x04;
+ if ( bLineSpace )
+ {
+ --nCount;
+ if( IsInSct() && !GetPrev() )
+ {
+ SwSectionFrm *pSect = FindSctFrm();
+ if( pSect->ContainsAny() == this )
+ pSect->InvalidatePrt();
+ }
+ }
+ if ( bRegister )
+ --nCount;
+ }
+ if ( SFX_ITEM_SET == rNewSet.GetItemState( RES_PARATR_SPLIT,
+ sal_False ))
+ {
+ if ( GetPrev() )
+ CheckKeep();
+ Prepare( PREP_CLEAR );
+ InvalidateSize();
+ nClear |= 0x08;
+ --nCount;
+ }
+
+ if( SFX_ITEM_SET == rNewSet.GetItemState( RES_BACKGROUND, sal_False)
+ && !IsFollow() && GetDrawObjs() )
+ {
+ SwSortedObjs *pObjs = GetDrawObjs();
+ for ( int i = 0; GetDrawObjs() && i < int(pObjs->Count()); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[MSHORT(i)];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ if( !pFly->IsFlyInCntFrm() )
+ {
+ const SvxBrushItem &rBack =
+ pFly->GetAttrSet()->GetBackground();
+ // OD 20.08.2002 #99657# #GetTransChg#
+ // following condition determines, if the fly frame
+ // "inherites" the background color of text frame.
+ // This is the case, if fly frame background
+ // color is "no fill"/"auto fill" and if the fly frame
+ // has no background graphic.
+ // Thus, check complete fly frame background
+ // color and *not* only its transparency value
+ if ( (rBack.GetColor() == COL_TRANSPARENT) &&
+ //if( rBack.GetColor().GetTransparency() &&
+ rBack.GetGraphicPos() == GPOS_NONE )
+ {
+ pFly->SetCompletePaint();
+ pFly->InvalidatePage();
+ }
+ }
+ }
+ }
+ }
+
+ if ( SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_TXTATR_CHARFMT, sal_False ) )
+ {
+ SET_WRONG( 0, STRING_LEN, false )
+ SET_SCRIPT_INVAL( 0 )
+ }
+ else if ( SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_CHRATR_LANGUAGE, sal_False ) ||
+ SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_CHRATR_CJK_LANGUAGE, sal_False ) ||
+ SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_CHRATR_CTL_LANGUAGE, sal_False ) )
+ SET_WRONG( 0, STRING_LEN, false )
+ else if ( SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_CHRATR_FONT, sal_False ) ||
+ SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_CHRATR_CJK_FONT, sal_False ) ||
+ SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_CHRATR_CTL_FONT, sal_False ) )
+ SET_SCRIPT_INVAL( 0 )
+ else if ( SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_FRAMEDIR, sal_False ) )
+ {
+ SetDerivedR2L( sal_False );
+ CheckDirChange();
+ // OD 09.12.2002 #105576# - Force complete paint due to existing
+ // indents.
+ SetCompletePaint();
+ }
+
+
+ if( nCount )
+ {
+ if( GetShell() )
+ {
+ Prepare( PREP_CLEAR );
+ _InvalidatePrt();
+ }
+
+ if( nClear )
+ {
+ SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
+ SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
+
+ if( 0x01 & nClear )
+ {
+ aOldSet.ClearItem( RES_TXTATR_FTN );
+ aNewSet.ClearItem( RES_TXTATR_FTN );
+ }
+ if( 0x02 & nClear )
+ {
+ aOldSet.ClearItem( RES_TXTATR_FIELD );
+ aNewSet.ClearItem( RES_TXTATR_FIELD );
+ }
+ if ( 0x04 & nClear )
+ {
+ if ( bLineSpace )
+ {
+ aOldSet.ClearItem( RES_PARATR_LINESPACING );
+ aNewSet.ClearItem( RES_PARATR_LINESPACING );
+ }
+ if ( bRegister )
+ {
+ aOldSet.ClearItem( RES_PARATR_REGISTER );
+ aNewSet.ClearItem( RES_PARATR_REGISTER );
+ }
+ }
+ if ( 0x08 & nClear )
+ {
+ aOldSet.ClearItem( RES_PARATR_SPLIT );
+ aNewSet.ClearItem( RES_PARATR_SPLIT );
+ }
+ SwCntntFrm::Modify( &aOldSet, &aNewSet );
+ }
+ else
+ SwCntntFrm::Modify( pOld, pNew );
+ }
+
+ // --> OD 2009-01-06 #i88069#
+ if ( GetShell() )
+ {
+ GetShell()->InvalidateAccessibleParaAttrs( *this );
+ }
+ // <--
+ }
+ break;
+
+/* Seit dem neuen Blocksatz muessen wir immer neu formatieren:
+ case RES_PARATR_ADJUST:
+ {
+ if( GetShell() )
+ {
+ Prepare( PREP_CLEAR );
+ }
+ break;
+ }
+*/
+ // 6870: SwDocPosUpdate auswerten.
+ case RES_DOCPOS_UPDATE:
+ {
+ if( pOld && pNew )
+ {
+ const SwDocPosUpdate *pDocPos = (const SwDocPosUpdate*)pOld;
+ if( pDocPos->nDocPos <= aFrm.Top() )
+ {
+ const SwFmtFld *pFld = (const SwFmtFld *)pNew;
+ InvalidateRange(
+ SwCharRange( *pFld->GetTxtFld()->GetStart(), 1 ) );
+ }
+ }
+ break;
+ }
+ case RES_PARATR_SPLIT:
+ if ( GetPrev() )
+ CheckKeep();
+ Prepare( PREP_CLEAR );
+ bSetFldsDirty = sal_True;
+ break;
+ case RES_FRAMEDIR :
+ SetDerivedR2L( sal_False );
+ CheckDirChange();
+ break;
+ default:
+ {
+ Prepare( PREP_CLEAR );
+ _InvalidatePrt();
+ if ( !nWhich )
+ {
+ //Wird z.B. bei HiddenPara mit 0 gerufen.
+ SwFrm *pNxt;
+ if ( 0 != (pNxt = FindNext()) )
+ pNxt->InvalidatePrt();
+ }
+ }
+ } // switch
+
+ if( bSetFldsDirty )
+ GetNode()->getIDocumentFieldsAccess()->SetFieldsDirty( sal_True, GetNode(), 1 );
+
+ if ( bRecalcFtnFlag )
+ CalcFtnFlag();
+}
+
+sal_Bool SwTxtFrm::GetInfo( SfxPoolItem &rHnt ) const
+{
+ if ( RES_VIRTPAGENUM_INFO == rHnt.Which() && IsInDocBody() && ! IsFollow() )
+ {
+ SwVirtPageNumInfo &rInfo = (SwVirtPageNumInfo&)rHnt;
+ const SwPageFrm *pPage = FindPageFrm();
+ if ( pPage )
+ {
+ if ( pPage == rInfo.GetOrigPage() && !GetPrev() )
+ {
+ //Das sollte er sein (kann allenfalls temporaer anders sein,
+ // sollte uns das beunruhigen?)
+ rInfo.SetInfo( pPage, this );
+ return sal_False;
+ }
+ if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() &&
+ (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum()))
+ {
+ //Das koennte er sein.
+ rInfo.SetInfo( pPage, this );
+ }
+ }
+ }
+ return sal_True;
+}
+
+/*************************************************************************
+ * SwTxtFrm::PrepWidows()
+ *************************************************************************/
+
+void SwTxtFrm::PrepWidows( const MSHORT nNeed, sal_Bool bNotify )
+{
+ ASSERT(GetFollow() && nNeed, "+SwTxtFrm::Prepare: lost all friends");
+
+ SwParaPortion *pPara = GetPara();
+ if ( !pPara )
+ return;
+ pPara->SetPrepWidows( sal_True );
+
+ // These two lines of code have been deleted for #102340#.
+ // Obviously the widow control does not work if we have a
+ // pMaster->pFollow->pFollow situation:
+
+ // returnen oder nicht ist hier die Frage.
+ // Ohne IsLocked() ist 5156 gefaehrlich,
+ // ohne IsFollow() werden die Orphans unterdrueckt: 6968.
+ // Abfrage auf IsLocked erst hier, weil das Flag gesetzt werden soll.
+// if( IsLocked() && IsFollow() )
+// return;
+
+ MSHORT nHave = nNeed;
+
+ // Wir geben ein paar Zeilen ab und schrumpfen im CalcPreps()
+ SWAP_IF_NOT_SWAPPED( this )
+
+ SwTxtSizeInfo aInf( this );
+ SwTxtMargin aLine( this, &aInf );
+ aLine.Bottom();
+ xub_StrLen nTmpLen = aLine.GetCurr()->GetLen();
+ while( nHave && aLine.PrevLine() )
+ {
+ if( nTmpLen )
+ --nHave;
+ nTmpLen = aLine.GetCurr()->GetLen();
+ }
+ // In dieser Ecke tummelten sich einige Bugs: 7513, 7606.
+ // Wenn feststeht, dass Zeilen abgegeben werden koennen,
+ // muss der Master darueber hinaus die Widow-Regel ueberpruefen.
+ if( !nHave )
+ {
+ sal_Bool bSplit;
+ if( !IsFollow() ) //Nur ein Master entscheidet ueber Orphans
+ {
+ const WidowsAndOrphans aWidOrp( this );
+ bSplit = ( aLine.GetLineNr() >= aWidOrp.GetOrphansLines() &&
+ aLine.GetLineNr() >= aLine.GetDropLines() );
+ }
+ else
+ bSplit = sal_True;
+
+ if( bSplit )
+ {
+ GetFollow()->SetOfst( aLine.GetEnd() );
+ aLine.TruncLines( sal_True );
+ if( pPara->IsFollowField() )
+ GetFollow()->SetFieldFollow( sal_True );
+ }
+ }
+ if ( bNotify )
+ {
+ _InvalidateSize();
+ InvalidatePage();
+ }
+
+ UNDO_SWAP( this )
+}
+
+/*************************************************************************
+ * SwTxtFrm::Prepare
+ *************************************************************************/
+
+sal_Bool lcl_ErgoVadis( SwTxtFrm* pFrm, xub_StrLen &rPos, const PrepareHint ePrep )
+{
+ const SwFtnInfo &rFtnInfo = pFrm->GetNode()->GetDoc()->GetFtnInfo();
+ if( ePrep == PREP_ERGOSUM )
+ {
+ if( !rFtnInfo.aErgoSum.Len() )
+ return sal_False;;
+ rPos = pFrm->GetOfst();
+ }
+ else
+ {
+ if( !rFtnInfo.aQuoVadis.Len() )
+ return sal_False;
+ if( pFrm->HasFollow() )
+ rPos = pFrm->GetFollow()->GetOfst();
+ else
+ rPos = pFrm->GetTxt().Len();
+ if( rPos )
+ --rPos; // unser letztes Zeichen
+ }
+ return sal_True;
+}
+
+void SwTxtFrm::Prepare( const PrepareHint ePrep, const void* pVoid,
+ sal_Bool bNotify )
+{
+ SwFrmSwapper aSwapper( this, sal_False );
+
+#if OSL_DEBUG_LEVEL > 1
+ const SwTwips nDbgY = Frm().Top();
+ (void)nDbgY;
+#endif
+
+ if ( IsEmpty() )
+ {
+ switch ( ePrep )
+ {
+ case PREP_BOSS_CHGD:
+ SetInvalidVert( TRUE ); // Test
+ case PREP_WIDOWS_ORPHANS:
+ case PREP_WIDOWS:
+ case PREP_FTN_GONE : return;
+
+ case PREP_POS_CHGD :
+ {
+ // Auch in (spaltigen) Bereichen ist ein InvalidateSize notwendig,
+ // damit formatiert wird und ggf. das bUndersized gesetzt wird.
+ if( IsInFly() || IsInSct() )
+ {
+ SwTwips nTmpBottom = GetUpper()->Frm().Top() +
+ GetUpper()->Prt().Bottom();
+ if( nTmpBottom < Frm().Bottom() )
+ break;
+ }
+ // Gibt es ueberhaupt Flys auf der Seite ?
+ SwTxtFly aTxtFly( this );
+ if( aTxtFly.IsOn() )
+ {
+ // Ueberlappt irgendein Fly ?
+ aTxtFly.Relax();
+ if ( aTxtFly.IsOn() || IsUndersized() )
+ break;
+ }
+ if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue())
+ break;
+
+ GETGRID( FindPageFrm() )
+ if ( pGrid && GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() )
+ break;
+
+ // --> OD 2004-07-16 #i28701# - consider anchored objects
+ if ( GetDrawObjs() )
+ break;
+ // <--
+
+ return;
+ }
+ default:
+ break;
+ }
+ }
+
+ if( !HasPara() && PREP_MUST_FIT != ePrep )
+ {
+ SetInvalidVert( TRUE ); // Test
+ ASSERT( !IsLocked(), "SwTxtFrm::Prepare: three of a perfect pair" );
+ if ( bNotify )
+ InvalidateSize();
+ else
+ _InvalidateSize();
+ return;
+ }
+
+ //Objekt mit Locking aus dem Cache holen.
+ SwTxtLineAccess aAccess( this );
+ SwParaPortion *pPara = aAccess.GetPara();
+
+ switch( ePrep )
+ {
+ case PREP_MOVEFTN : Frm().Height(0);
+ Prt().Height(0);
+ _InvalidatePrt();
+ _InvalidateSize();
+ // KEIN break
+ case PREP_ADJUST_FRM : pPara->SetPrepAdjust( sal_True );
+ if( IsFtnNumFrm() != pPara->IsFtnNum() ||
+ IsUndersized() )
+ {
+ InvalidateRange( SwCharRange( 0, 1 ), 1);
+ if( GetOfst() && !IsFollow() )
+ _SetOfst( 0 );
+ }
+ break;
+ case PREP_MUST_FIT : pPara->SetPrepMustFit( sal_True );
+ /* no break here */
+ case PREP_WIDOWS_ORPHANS : pPara->SetPrepAdjust( sal_True );
+ break;
+
+ case PREP_WIDOWS :
+ // MustFit ist staerker als alles anderes
+ if( pPara->IsPrepMustFit() )
+ return;
+ // Siehe Kommentar in WidowsAndOrphans::FindOrphans und CalcPreps()
+ PrepWidows( *(const MSHORT *)pVoid, bNotify );
+ break;
+
+ case PREP_FTN :
+ {
+ SwTxtFtn *pFtn = (SwTxtFtn *)pVoid;
+ if( IsInFtn() )
+ {
+ // Bin ich der erste TxtFrm einer Fussnote ?
+ if( !GetPrev() )
+ // Wir sind also ein TxtFrm der Fussnote, die
+ // die Fussnotenzahl zur Anzeige bringen muss.
+ // Oder den ErgoSum-Text...
+ InvalidateRange( SwCharRange( 0, 1 ), 1);
+
+ if( !GetNext() )
+ {
+ // Wir sind der letzte Ftn, jetzt muessten die
+ // QuoVadis-Texte geupdated werden.
+ const SwFtnInfo &rFtnInfo = GetNode()->GetDoc()->GetFtnInfo();
+ if( !pPara->UpdateQuoVadis( rFtnInfo.aQuoVadis ) )
+ {
+ xub_StrLen nPos = pPara->GetParLen();
+ if( nPos )
+ --nPos;
+ InvalidateRange( SwCharRange( nPos, 1 ), 1);
+ }
+ }
+ }
+ else
+ {
+ // Wir sind also der TxtFrm _mit_ der Fussnote
+ const xub_StrLen nPos = *pFtn->GetStart();
+ InvalidateRange( SwCharRange( nPos, 1 ), 1);
+ }
+ break;
+ }
+ case PREP_BOSS_CHGD :
+ {
+ // Test
+ {
+ SetInvalidVert( FALSE );
+ BOOL bOld = IsVertical();
+ SetInvalidVert( TRUE );
+ if( bOld != IsVertical() )
+ InvalidateRange( SwCharRange( GetOfst(), STRING_LEN ) );
+ }
+
+ if( HasFollow() )
+ {
+ xub_StrLen nNxtOfst = GetFollow()->GetOfst();
+ if( nNxtOfst )
+ --nNxtOfst;
+ InvalidateRange( SwCharRange( nNxtOfst, 1 ), 1);
+ }
+ if( IsInFtn() )
+ {
+ xub_StrLen nPos;
+ if( lcl_ErgoVadis( this, nPos, PREP_QUOVADIS ) )
+ InvalidateRange( SwCharRange( nPos, 1 ), 0 );
+ if( lcl_ErgoVadis( this, nPos, PREP_ERGOSUM ) )
+ InvalidateRange( SwCharRange( nPos, 1 ), 0 );
+ }
+ // 4739: Wenn wir ein Seitennummernfeld besitzen, muessen wir
+ // die Stellen invalidieren.
+ SwpHints *pHints = GetTxtNode()->GetpSwpHints();
+ if( pHints )
+ {
+ const USHORT nSize = pHints->Count();
+ const xub_StrLen nEnd = GetFollow() ?
+ GetFollow()->GetOfst() : STRING_LEN;
+ for ( USHORT i = 0; i < nSize; ++i )
+ {
+ const SwTxtAttr *pHt = (*pHints)[i];
+ const xub_StrLen nStart = *pHt->GetStart();
+ if( nStart >= GetOfst() )
+ {
+ if( nStart >= nEnd )
+ i = nSize; // fuehrt das Ende herbei
+ else
+ {
+ // 4029: wenn wir zurueckfliessen und eine Ftn besitzen, so
+ // fliesst die Ftn in jedem Fall auch mit. Damit sie nicht im
+ // Weg steht, schicken wir uns ein ADJUST_FRM.
+ // pVoid != 0 bedeutet MoveBwd()
+ const MSHORT nWhich = pHt->Which();
+ if( RES_TXTATR_FIELD == nWhich ||
+ (HasFtn() && pVoid && RES_TXTATR_FTN == nWhich))
+ InvalidateRange( SwCharRange( nStart, 1 ), 1 );
+ }
+ }
+ }
+ }
+ // A new boss, a new chance for growing
+ if( IsUndersized() )
+ {
+ _InvalidateSize();
+ InvalidateRange( SwCharRange( GetOfst(), 1 ), 1);
+ }
+ break;
+ }
+
+ case PREP_POS_CHGD :
+ {
+ if ( GetValidPrtAreaFlag() )
+ {
+ GETGRID( FindPageFrm() )
+ if ( pGrid && GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() )
+ InvalidatePrt();
+ }
+
+ // Falls wir mit niemandem ueberlappen:
+ // Ueberlappte irgendein Fly _vor_ der Positionsaenderung ?
+ sal_Bool bFormat = pPara->HasFly();
+ if( !bFormat )
+ {
+ if( IsInFly() )
+ {
+ SwTwips nTmpBottom = GetUpper()->Frm().Top() +
+ GetUpper()->Prt().Bottom();
+ if( nTmpBottom < Frm().Bottom() )
+ bFormat = sal_True;
+ }
+ if( !bFormat )
+ {
+ if ( GetDrawObjs() )
+ {
+ const sal_uInt32 nCnt = GetDrawObjs()->Count();
+ for ( MSHORT i = 0; i < nCnt; ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i];
+ // --> OD 2004-07-16 #i28701# - consider all
+ // to-character anchored objects
+ if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
+ == FLY_AT_CHAR )
+ {
+ bFormat = sal_True;
+ break;
+ }
+ }
+ }
+ if( !bFormat )
+ {
+ // Gibt es ueberhaupt Flys auf der Seite ?
+ SwTxtFly aTxtFly( this );
+ if( aTxtFly.IsOn() )
+ {
+ // Ueberlappt irgendein Fly ?
+ aTxtFly.Relax();
+ bFormat = aTxtFly.IsOn() || IsUndersized();
+ }
+ }
+ }
+ }
+
+ if( bFormat )
+ {
+ if( !IsLocked() )
+ {
+ if( pPara->GetRepaint()->HasArea() )
+ SetCompletePaint();
+ Init();
+ pPara = 0;
+ _InvalidateSize();
+ }
+ }
+ else
+ {
+ if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
+ Prepare( PREP_REGISTER, 0, bNotify );
+ // Durch Positionsverschiebungen mit Ftns muessen die
+ // Frames neu adjustiert werden.
+ else if( HasFtn() )
+ {
+ Prepare( PREP_ADJUST_FRM, 0, bNotify );
+ _InvalidateSize();
+ }
+ else
+ return; // damit kein SetPrep() erfolgt.
+ }
+ break;
+ }
+ case PREP_REGISTER:
+ if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
+ {
+ pPara->SetPrepAdjust( sal_True );
+ CalcLineSpace();
+ InvalidateSize();
+ _InvalidatePrt();
+ SwFrm* pNxt;
+ if ( 0 != ( pNxt = GetIndNext() ) )
+ {
+ pNxt->_InvalidatePrt();
+ if ( pNxt->IsLayoutFrm() )
+ pNxt->InvalidatePage();
+ }
+ SetCompletePaint();
+ }
+ break;
+ case PREP_FTN_GONE :
+ {
+ // Wenn ein Follow uns ruft, weil eine Fussnote geloescht wird, muss unsere
+ // letzte Zeile formatiert werden, damit ggf. die erste Zeile des Follows
+ // hochrutschen kann, die extra auf die naechste Seite gerutscht war, um mit
+ // der Fussnote zusammen zu sein, insbesondere bei spaltigen Bereichen.
+ ASSERT( GetFollow(), "PREP_FTN_GONE darf nur vom Follow gerufen werden" );
+ xub_StrLen nPos = GetFollow()->GetOfst();
+ if( IsFollow() && GetOfst() == nPos ) // falls wir gar keine Textmasse besitzen,
+ FindMaster()->Prepare( PREP_FTN_GONE ); // rufen wir das Prepare unseres Masters
+ if( nPos )
+ --nPos; // das Zeichen vor unserem Follow
+ InvalidateRange( SwCharRange( nPos, 1 ), 0 );
+ return;
+ }
+ case PREP_ERGOSUM:
+ case PREP_QUOVADIS:
+ {
+ xub_StrLen nPos;
+ if( lcl_ErgoVadis( this, nPos, ePrep ) )
+ InvalidateRange( SwCharRange( nPos, 1 ), 0 );
+ }
+ break;
+ case PREP_FLY_ATTR_CHG:
+ {
+ if( pVoid )
+ {
+ xub_StrLen nWhere = CalcFlyPos( (SwFrmFmt*)pVoid );
+ ASSERT( STRING_LEN != nWhere, "Prepare: Why me?" );
+ InvalidateRange( SwCharRange( nWhere, 1 ) );
+ return;
+ }
+ // else ... Laufe in den Default-Switch
+ }
+ case PREP_CLEAR:
+ default:
+ {
+ if( IsLocked() )
+ {
+ if( PREP_FLY_ARRIVE == ePrep || PREP_FLY_LEAVE == ePrep )
+ {
+ xub_StrLen nLen = ( GetFollow() ? GetFollow()->GetOfst() :
+ STRING_LEN ) - GetOfst();
+ InvalidateRange( SwCharRange( GetOfst(), nLen ), 0 );
+ }
+ }
+ else
+ {
+ if( pPara->GetRepaint()->HasArea() )
+ SetCompletePaint();
+ Init();
+ pPara = 0;
+ if( GetOfst() && !IsFollow() )
+ _SetOfst( 0 );
+ if ( bNotify )
+ InvalidateSize();
+ else
+ _InvalidateSize();
+ }
+ return; // damit kein SetPrep() erfolgt.
+ }
+ }
+ if( pPara )
+ pPara->SetPrep( sal_True );
+}
+
+/* -----------------11.02.99 17:56-------------------
+ * Kleine Hilfsklasse mit folgender Funktion:
+ * Sie soll eine Probeformatierung vorbereiten.
+ * Der Frame wird in Groesse und Position angepasst, sein SwParaPortion zur Seite
+ * gestellt und eine neue erzeugt, dazu wird formatiert mit gesetztem bTestFormat.
+ * Im Dtor wird der TxtFrm wieder in seinen alten Zustand zurueckversetzt.
+ *
+ * --------------------------------------------------*/
+
+class SwTestFormat
+{
+ SwTxtFrm *pFrm;
+ SwParaPortion *pOldPara;
+ SwRect aOldFrm, aOldPrt;
+public:
+ SwTestFormat( SwTxtFrm* pTxtFrm, const SwFrm* pPrv, SwTwips nMaxHeight );
+ ~SwTestFormat();
+};
+
+SwTestFormat::SwTestFormat( SwTxtFrm* pTxtFrm, const SwFrm* pPre, SwTwips nMaxHeight )
+ : pFrm( pTxtFrm )
+{
+ aOldFrm = pFrm->Frm();
+ aOldPrt = pFrm->Prt();
+
+ SWRECTFN( pFrm )
+ SwTwips nLower = (pFrm->*fnRect->fnGetBottomMargin)();
+
+ pFrm->Frm() = pFrm->GetUpper()->Prt();
+ pFrm->Frm() += pFrm->GetUpper()->Frm().Pos();
+
+ (pFrm->Frm().*fnRect->fnSetHeight)( nMaxHeight );
+ if( pFrm->GetPrev() )
+ (pFrm->Frm().*fnRect->fnSetPosY)(
+ (pFrm->GetPrev()->Frm().*fnRect->fnGetBottom)() -
+ ( bVert ? nMaxHeight + 1 : 0 ) );
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ (pFrm->Prt().*fnRect->fnSetPosX)( rAttrs.CalcLeft( pFrm ) );
+
+ if( pPre )
+ {
+ SwTwips nUpper = pFrm->CalcUpperSpace( &rAttrs, pPre );
+ (pFrm->Prt().*fnRect->fnSetPosY)( nUpper );
+ }
+ (pFrm->Prt().*fnRect->fnSetHeight)(
+ Max( 0L , (pFrm->Frm().*fnRect->fnGetHeight)() -
+ (pFrm->Prt().*fnRect->fnGetTop)() - nLower ) );
+ (pFrm->Prt().*fnRect->fnSetWidth)(
+ (pFrm->Frm().*fnRect->fnGetWidth)() -
+ // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
+ ( rAttrs.CalcLeft( pFrm ) + rAttrs.CalcRight( pFrm ) ) );
+ pOldPara = pFrm->HasPara() ? pFrm->GetPara() : NULL;
+ pFrm->SetPara( new SwParaPortion(), sal_False );
+
+ ASSERT( ! pFrm->IsSwapped(), "A frame is swapped before _Format" );
+
+ if ( pFrm->IsVertical() )
+ pFrm->SwapWidthAndHeight();
+
+ SwTxtFormatInfo aInf( pFrm, sal_False, sal_True, sal_True );
+ SwTxtFormatter aLine( pFrm, &aInf );
+
+ pFrm->_Format( aLine, aInf );
+
+ if ( pFrm->IsVertical() )
+ pFrm->SwapWidthAndHeight();
+
+ ASSERT( ! pFrm->IsSwapped(), "A frame is swapped after _Format" );
+}
+
+SwTestFormat::~SwTestFormat()
+{
+ pFrm->Frm() = aOldFrm;
+ pFrm->Prt() = aOldPrt;
+ pFrm->SetPara( pOldPara );
+}
+
+sal_Bool SwTxtFrm::TestFormat( const SwFrm* pPrv, SwTwips &rMaxHeight, sal_Bool &bSplit )
+{
+ PROTOCOL_ENTER( this, PROT_TESTFORMAT, 0, 0 )
+
+ if( IsLocked() && GetUpper()->Prt().Width() <= 0 )
+ return sal_False;
+
+ SwTestFormat aSave( this, pPrv, rMaxHeight );
+
+ return SwTxtFrm::WouldFit( rMaxHeight, bSplit, sal_True );
+}
+
+
+/*************************************************************************
+ * SwTxtFrm::WouldFit()
+ *************************************************************************/
+
+/* SwTxtFrm::WouldFit()
+ * sal_True: wenn ich aufspalten kann.
+ * Es soll und braucht nicht neu formatiert werden.
+ * Wir gehen davon aus, dass bereits formatiert wurde und dass
+ * die Formatierungsdaten noch aktuell sind.
+ * Wir gehen davon aus, dass die Framebreiten des evtl. Masters und
+ * Follows gleich sind. Deswegen wird kein FindBreak() mit FindOrphans()
+ * gerufen.
+ * Die benoetigte Hoehe wird von nMaxHeight abgezogen!
+ */
+
+sal_Bool SwTxtFrm::WouldFit( SwTwips &rMaxHeight, sal_Bool &bSplit, sal_Bool bTst )
+{
+ ASSERT( ! IsVertical() || ! IsSwapped(),
+ "SwTxtFrm::WouldFit with swapped frame" );
+ SWRECTFN( this );
+
+ if( IsLocked() )
+ return sal_False;
+
+ //Kann gut sein, dass mir der IdleCollector mir die gecachten
+ //Informationen entzogen hat.
+ if( !IsEmpty() )
+ GetFormatted();
+
+ // OD 2004-05-24 #i27801# - correction: 'short cut' for empty paragraph
+ // can *not* be applied, if test format is in progress. The test format doesn't
+ // adjust the frame and the printing area - see method <SwTxtFrm::_Format(..)>,
+ // which is called in <SwTxtFrm::TestFormat(..)>
+ if ( IsEmpty() && !bTst )
+ {
+ bSplit = sal_False;
+ SwTwips nHeight = bVert ? Prt().SSize().Width() : Prt().SSize().Height();
+ if( rMaxHeight < nHeight )
+ return sal_False;
+ else
+ {
+ rMaxHeight -= nHeight;
+ return sal_True;
+ }
+ }
+
+ // In sehr unguenstigen Faellen kann GetPara immer noch 0 sein.
+ // Dann returnen wir sal_True, um auf der neuen Seite noch einmal
+ // anformatiert zu werden.
+ ASSERT( HasPara() || IsHiddenNow(), "WouldFit: GetFormatted() and then !HasPara()" );
+ if( !HasPara() || ( !(Frm().*fnRect->fnGetHeight)() && IsHiddenNow() ) )
+ return sal_True;
+
+ // Da das Orphan-Flag nur sehr fluechtig existiert, wird als zweite
+ // Bedingung ueberprueft, ob die Rahmengroesse durch CalcPreps
+ // auf riesengross gesetzt wird, um ein MoveFwd zu erzwingen.
+ if( IsWidow() || ( bVert ?
+ ( 0 == Frm().Left() ) :
+ ( LONG_MAX - 20000 < Frm().Bottom() ) ) )
+ {
+ SetWidow(sal_False);
+ if ( GetFollow() )
+ {
+ // Wenn wir hier durch eine Widow-Anforderung unseres Follows gelandet
+ // sind, wird ueberprueft, ob es ueberhaupt einen Follow mit einer
+ // echten Hoehe gibt, andernfalls (z.B. in neu angelegten SctFrms)
+ // ignorieren wir das IsWidow() und pruefen doch noch, ob wir
+ // genung Platz finden.
+ if( ( ( ! bVert && LONG_MAX - 20000 >= Frm().Bottom() ) ||
+ ( bVert && 0 < Frm().Left() ) ) &&
+ ( GetFollow()->IsVertical() ?
+ !GetFollow()->Frm().Width() :
+ !GetFollow()->Frm().Height() ) )
+ {
+ SwTxtFrm* pFoll = GetFollow()->GetFollow();
+ while( pFoll &&
+ ( pFoll->IsVertical() ?
+ !pFoll->Frm().Width() :
+ !pFoll->Frm().Height() ) )
+ pFoll = pFoll->GetFollow();
+ if( pFoll )
+ return sal_False;
+ }
+ else
+ return sal_False;
+ }
+ }
+
+ SWAP_IF_NOT_SWAPPED( this );
+
+ SwTxtSizeInfo aInf( this );
+ SwTxtMargin aLine( this, &aInf );
+
+ WidowsAndOrphans aFrmBreak( this, rMaxHeight, bSplit );
+
+ sal_Bool bRet = sal_True;
+
+ aLine.Bottom();
+ // Ist Aufspalten ueberhaupt notwendig?
+ if ( 0 != ( bSplit = !aFrmBreak.IsInside( aLine ) ) )
+ bRet = !aFrmBreak.IsKeepAlways() && aFrmBreak.WouldFit( aLine, rMaxHeight, bTst );
+ else
+ {
+ //Wir brauchen die Gesamthoehe inklusive der aktuellen Zeile
+ aLine.Top();
+ do
+ {
+ rMaxHeight -= aLine.GetLineHeight();
+ } while ( aLine.Next() );
+ }
+
+ UNDO_SWAP( this )
+
+ return bRet;
+}
+
+
+/*************************************************************************
+ * SwTxtFrm::GetParHeight()
+ *************************************************************************/
+
+KSHORT SwTxtFrm::GetParHeight() const
+{
+ ASSERT( ! IsVertical() || ! IsSwapped(),
+ "SwTxtFrm::GetParHeight with swapped frame" )
+
+ if( !HasPara() )
+ { // Fuer nichtleere Absaetze ist dies ein Sonderfall, da koennen wir
+ // bei UnderSized ruhig nur 1 Twip mehr anfordern.
+ KSHORT nRet = (KSHORT)Prt().SSize().Height();
+ if( IsUndersized() )
+ {
+ if( IsEmpty() )
+ nRet = (KSHORT)EmptyHeight();
+ else
+ ++nRet;
+ }
+ return nRet;
+ }
+
+ // FME, OD 08.01.2004 #i11859# - refactoring and improve code
+ const SwLineLayout* pLineLayout = GetPara();
+ KSHORT nHeight = pLineLayout->GetRealHeight();
+ if( GetOfst() && !IsFollow() ) // Ist dieser Absatz gescrollt? Dann ist unsere
+ nHeight *= 2; // bisherige Hoehe mind. eine Zeilenhoehe zu gering
+ // OD 2004-03-04 #115793#
+ while ( pLineLayout && pLineLayout->GetNext() )
+ {
+ pLineLayout = pLineLayout->GetNext();
+ nHeight = nHeight + pLineLayout->GetRealHeight();
+ }
+
+ return nHeight;
+}
+
+
+/*************************************************************************
+ * SwTxtFrm::GetFormatted()
+ *************************************************************************/
+
+// returnt this _immer_ im formatierten Zustand!
+SwTxtFrm* SwTxtFrm::GetFormatted( bool bForceQuickFormat )
+{
+ SWAP_IF_SWAPPED( this )
+
+ //Kann gut sein, dass mir der IdleCollector mir die gecachten
+ //Informationen entzogen hat. Calc() ruft unser Format.
+ //Nicht bei leeren Absaetzen!
+ if( !HasPara() && !(IsValid() && IsEmpty()) )
+ {
+ // Calc() muss gerufen werden, weil unsere Frameposition
+ // nicht stimmen muss.
+ const sal_Bool bFormat = GetValidSizeFlag();
+ Calc();
+ // Es kann durchaus sein, dass Calc() das Format()
+ // nicht anstiess (weil wir einst vom Idle-Zerstoerer
+ // aufgefordert wurden unsere Formatinformationen wegzuschmeissen).
+ // 6995: Optimierung mit FormatQuick()
+ if( bFormat && !FormatQuick( bForceQuickFormat ) )
+ Format();
+ }
+
+ UNDO_SWAP( this )
+
+ return this;
+}
+
+/*************************************************************************
+ * SwTxtFrm::CalcFitToContent()
+ *************************************************************************/
+
+SwTwips SwTxtFrm::CalcFitToContent()
+{
+ // --> FME 2004-07-16 #i31490#
+ // If we are currently locked, we better return with a
+ // fairly reasonable value:
+ if ( IsLocked() )
+ return Prt().Width();
+ // <--
+
+ SwParaPortion* pOldPara = GetPara();
+ SwParaPortion *pDummy = new SwParaPortion();
+ SetPara( pDummy, false );
+ const SwPageFrm* pPage = FindPageFrm();
+
+ const Point aOldFrmPos = Frm().Pos();
+ const SwTwips nOldFrmWidth = Frm().Width();
+ const SwTwips nOldPrtWidth = Prt().Width();
+ const SwTwips nPageWidth = GetUpper()->IsVertical() ?
+ pPage->Prt().Height() :
+ pPage->Prt().Width();
+
+ Frm().Width( nPageWidth );
+ Prt().Width( nPageWidth );
+
+ // --> FME 2004-07-19 #i25422# objects anchored as character in RTL
+ if ( IsRightToLeft() )
+ Frm().Pos().X() += nOldFrmWidth - nPageWidth;
+
+ // --> FME 2004-07-16 #i31490#
+ SwTxtFrmLocker aLock( this );
+ // <--
+
+ SwTxtFormatInfo aInf( this, sal_False, sal_True, sal_True );
+ aInf.SetIgnoreFly( sal_True );
+ SwTxtFormatter aLine( this, &aInf );
+ SwHookOut aHook( aInf );
+
+ // --> OD 2005-09-06 #i54031# - assure mininum of MINLAY twips.
+ const SwTwips nMax = Max( (SwTwips)MINLAY,
+ aLine._CalcFitToContent() + 1 );
+ // <--
+
+ Frm().Width( nOldFrmWidth );
+ Prt().Width( nOldPrtWidth );
+
+ // --> FME 2004-07-19 #i25422# objects anchored as character in RTL
+ if ( IsRightToLeft() )
+ Frm().Pos() = aOldFrmPos;
+
+
+ SetPara( pOldPara );
+
+ return nMax;
+}
+
+/** simulate format for a list item paragraph, whose list level attributes
+ are in LABEL_ALIGNMENT mode, in order to determine additional first
+ line offset for the real text formatting due to the value of label
+ adjustment attribute of the list level.
+
+ OD 2008-01-31 #newlistlevelattrs#
+
+ @author OD
+*/
+void SwTxtFrm::CalcAdditionalFirstLineOffset()
+{
+ if ( IsLocked() )
+ return;
+
+ // reset additional first line offset
+ mnAdditionalFirstLineOffset = 0;
+
+ const SwTxtNode* pTxtNode( GetTxtNode() );
+ if ( pTxtNode && pTxtNode->IsNumbered() && pTxtNode->IsCountedInList() &&
+ pTxtNode->GetNumRule() )
+ {
+ const SwNumFmt& rNumFmt =
+ pTxtNode->GetNumRule()->Get( static_cast<USHORT>(pTxtNode->GetActualListLevel()) );
+ if ( rNumFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ // keep current paragraph portion and apply dummy paragraph portion
+ SwParaPortion* pOldPara = GetPara();
+ SwParaPortion *pDummy = new SwParaPortion();
+ SetPara( pDummy, false );
+
+ // lock paragraph
+ SwTxtFrmLocker aLock( this );
+
+ // simulate text formatting
+ SwTxtFormatInfo aInf( this, sal_False, sal_True, sal_True );
+ aInf.SetIgnoreFly( sal_True );
+ SwTxtFormatter aLine( this, &aInf );
+ SwHookOut aHook( aInf );
+ aLine._CalcFitToContent();
+
+ // determine additional first line offset
+ const SwLinePortion* pFirstPortion = aLine.GetCurr()->GetFirstPortion();
+ if ( pFirstPortion->InNumberGrp() && !pFirstPortion->IsFtnNumPortion() )
+ {
+ SwTwips nNumberPortionWidth( pFirstPortion->Width() );
+
+ const SwLinePortion* pPortion = pFirstPortion->GetPortion();
+ while ( pPortion &&
+ pPortion->InNumberGrp() && !pPortion->IsFtnNumPortion())
+ {
+ nNumberPortionWidth += pPortion->Width();
+ pPortion = pPortion->GetPortion();
+ }
+
+ if ( ( IsRightToLeft() &&
+ rNumFmt.GetNumAdjust() == SVX_ADJUST_LEFT ) ||
+ ( !IsRightToLeft() &&
+ rNumFmt.GetNumAdjust() == SVX_ADJUST_RIGHT ) )
+ {
+ mnAdditionalFirstLineOffset = -nNumberPortionWidth;
+ }
+ else if ( rNumFmt.GetNumAdjust() == SVX_ADJUST_CENTER )
+ {
+ mnAdditionalFirstLineOffset = -(nNumberPortionWidth/2);
+ }
+ }
+
+ // restore paragraph portion
+ SetPara( pOldPara );
+ }
+ }
+}
+
+/** determine height of last line for the calculation of the proportional line
+ spacing
+
+ OD 08.01.2004 #i11859#
+ OD 2004-03-17 #i11860# - method <GetHeightOfLastLineForPropLineSpacing()>
+ replace by method <_CalcHeightOfLastLine()>. Height of last line will be
+ stored in new member <mnHeightOfLastLine> and can be accessed via method
+ <GetHeightOfLastLine()>
+ OD 2005-05-20 #i47162# - introduce new optional parameter <_bUseFont>
+ in order to force the usage of the former algorithm to determine the
+ height of the last line, which uses the font.
+
+ @author OD
+*/
+void SwTxtFrm::_CalcHeightOfLastLine( const bool _bUseFont )
+{
+ // --> OD 2006-11-13 #i71281#
+ // invalidate printing area, if height of last line changes
+ const SwTwips mnOldHeightOfLastLine( mnHeightOfLastLine );
+ // <--
+ // determine output device
+ ViewShell* pVsh = GetShell();
+ ASSERT( pVsh, "<SwTxtFrm::_GetHeightOfLastLineForPropLineSpacing()> - no ViewShell" );
+ // --> OD 2007-07-02 #i78921# - make code robust, according to provided patch
+ // There could be no <ViewShell> instance in the case of loading a binary
+ // StarOffice file format containing an embedded Writer document.
+ if ( !pVsh )
+ {
+ return;
+ }
+ OutputDevice* pOut = pVsh->GetOut();
+ const IDocumentSettingAccess* pIDSA = GetTxtNode()->getIDocumentSettingAccess();
+ if ( !pIDSA->get(IDocumentSettingAccess::BROWSE_MODE) ||
+ pVsh->GetViewOptions()->IsPrtFormat() )
+ {
+ pOut = GetTxtNode()->getIDocumentDeviceAccess()->getReferenceDevice( true );
+ }
+ ASSERT( pOut, "<SwTxtFrm::_GetHeightOfLastLineForPropLineSpacing()> - no OutputDevice" );
+ // --> OD 2007-07-02 #i78921# - make code robust, according to provided patch
+ if ( !pOut )
+ {
+ return;
+ }
+ // <--
+
+ // determine height of last line
+
+ if ( _bUseFont || pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING ) )
+ {
+ // former determination of last line height for proprotional line
+ // spacing - take height of font set at the paragraph
+ SwFont aFont( GetAttrSet(), pIDSA );
+
+ // Wir muessen dafuer sorgen, dass am OutputDevice der Font
+ // korrekt restauriert wird, sonst droht ein Last!=Owner.
+ if ( pLastFont )
+ {
+ SwFntObj *pOldFont = pLastFont;
+ pLastFont = NULL;
+ aFont.SetFntChg( sal_True );
+ aFont.ChgPhysFnt( pVsh, *pOut );
+ mnHeightOfLastLine = aFont.GetHeight( pVsh, *pOut );
+ pLastFont->Unlock();
+ pLastFont = pOldFont;
+ pLastFont->SetDevFont( pVsh, *pOut );
+ }
+ else
+ {
+ Font aOldFont = pOut->GetFont();
+ aFont.SetFntChg( sal_True );
+ aFont.ChgPhysFnt( pVsh, *pOut );
+ mnHeightOfLastLine = aFont.GetHeight( pVsh, *pOut );
+ pLastFont->Unlock();
+ pLastFont = NULL;
+ pOut->SetFont( aOldFont );
+ }
+ }
+ else
+ {
+ // new determination of last line height - take actually height of last line
+ // --> OD 2008-05-06 #i89000#
+ // assure same results, if paragraph is undersized
+ if ( IsUndersized() )
+ {
+ mnHeightOfLastLine = 0;
+ }
+ else
+ {
+ bool bCalcHeightOfLastLine = true;
+ if ( !HasPara() )
+ {
+ if ( IsEmpty() )
+ {
+ mnHeightOfLastLine = EmptyHeight();
+ bCalcHeightOfLastLine = false;
+ }
+ }
+
+ if ( bCalcHeightOfLastLine )
+ {
+ ASSERT( HasPara(),
+ "<SwTxtFrm::_CalcHeightOfLastLine()> - missing paragraph portions." );
+ const SwLineLayout* pLineLayout = GetPara();
+ while ( pLineLayout && pLineLayout->GetNext() )
+ {
+ // iteration to last line
+ pLineLayout = pLineLayout->GetNext();
+ }
+ if ( pLineLayout )
+ {
+ SwTwips nAscent, nDescent, nDummy1, nDummy2;
+ // --> OD 2005-05-20 #i47162# - suppress consideration of
+ // fly content portions and the line portion.
+ pLineLayout->MaxAscentDescent( nAscent, nDescent,
+ nDummy1, nDummy2,
+ 0, true );
+ // <--
+ // --> OD 2006-11-22 #i71281#
+ // Suppress wrong invalidation of printing area, if method is
+ // called recursive.
+ // Thus, member <mnHeightOfLastLine> is only set directly, if
+ // no recursive call is needed.
+ // mnHeightOfLastLine = nAscent + nDescent;
+ const SwTwips nNewHeightOfLastLine = nAscent + nDescent;
+ // --> OD 2005-05-20 #i47162# - if last line only contains
+ // fly content portions, <mnHeightOfLastLine> is zero.
+ // In this case determine height of last line by the font
+ if ( nNewHeightOfLastLine == 0 )
+ {
+ _CalcHeightOfLastLine( true );
+ }
+ else
+ {
+ mnHeightOfLastLine = nNewHeightOfLastLine;
+ }
+ // <--
+ // <--
+ }
+ }
+ }
+ // <--
+ }
+ // --> OD 2006-11-13 #i71281#
+ // invalidate printing area, if height of last line changes
+ if ( mnHeightOfLastLine != mnOldHeightOfLastLine )
+ {
+ InvalidatePrt();
+ }
+ // <--
+}
+
+/*************************************************************************
+ * SwTxtFrm::GetLineSpace()
+ *************************************************************************/
+// OD 07.01.2004 #i11859# - change return data type
+// add default parameter <_bNoPropLineSpacing> to control, if the
+// value of a proportional line spacing is returned or not
+// OD 07.01.2004 - trying to describe purpose of method:
+// Method returns the value of the inter line spacing for a text frame.
+// Such a value exists for proportional line spacings ("1,5 Lines",
+// "Double", "Proportional" and for leading line spacing ("Leading").
+// By parameter <_bNoPropLineSpace> (default value false) it can be
+// controlled, if the value of a proportional line spacing is returned.
+long SwTxtFrm::GetLineSpace( const bool _bNoPropLineSpace ) const
+{
+ long nRet = 0;
+
+ const SwAttrSet* pSet = GetAttrSet();
+ const SvxLineSpacingItem &rSpace = pSet->GetLineSpacing();
+
+ switch( rSpace.GetInterLineSpaceRule() )
+ {
+ case SVX_INTER_LINE_SPACE_PROP:
+ {
+ // OD 07.01.2004 #i11859#
+ if ( _bNoPropLineSpace )
+ {
+ break;
+ }
+
+ // OD 2004-03-17 #i11860# - use method <GetHeightOfLastLine()>
+ nRet = GetHeightOfLastLine();
+
+ long nTmp = nRet;
+ nTmp *= rSpace.GetPropLineSpace();
+ nTmp /= 100;
+ nTmp -= nRet;
+ if ( nTmp > 0 )
+ nRet = nTmp;
+ else
+ nRet = 0;
+ }
+ break;
+ case SVX_INTER_LINE_SPACE_FIX:
+ {
+ if ( rSpace.GetInterLineSpace() > 0 )
+ nRet = rSpace.GetInterLineSpace();
+ }
+ break;
+ default:
+ break;
+ }
+ return nRet;
+}
+
+/*************************************************************************
+ * SwTxtFrm::FirstLineHeight()
+ *************************************************************************/
+
+KSHORT SwTxtFrm::FirstLineHeight() const
+{
+ if ( !HasPara() )
+ {
+ if( IsEmpty() && IsValid() )
+ return IsVertical() ? (KSHORT)Prt().Width() : (KSHORT)Prt().Height();
+ return KSHRT_MAX;
+ }
+ const SwParaPortion *pPara = GetPara();
+ if ( !pPara )
+ return KSHRT_MAX;
+
+ return pPara->Height();
+}
+
+MSHORT SwTxtFrm::GetLineCount( xub_StrLen nPos )
+{
+ MSHORT nRet = 0;
+ SwTxtFrm *pFrm = this;
+ do
+ {
+ pFrm->GetFormatted();
+ if( !pFrm->HasPara() )
+ break;
+ SwTxtSizeInfo aInf( pFrm );
+ SwTxtMargin aLine( pFrm, &aInf );
+ if( STRING_LEN == nPos )
+ aLine.Bottom();
+ else
+ aLine.CharToLine( nPos );
+ nRet = nRet + aLine.GetLineNr();
+ pFrm = pFrm->GetFollow();
+ } while ( pFrm && pFrm->GetOfst() <= nPos );
+ return nRet;
+}
+
+void SwTxtFrm::ChgThisLines()
+{
+ //not necassary to format here (GerFormatted etc.), because we have to come from there!
+
+ ULONG nNew = 0;
+ const SwLineNumberInfo &rInf = GetNode()->getIDocumentLineNumberAccess()->GetLineNumberInfo();
+ if ( GetTxt().Len() && HasPara() )
+ {
+ SwTxtSizeInfo aInf( this );
+ SwTxtMargin aLine( this, &aInf );
+ if ( rInf.IsCountBlankLines() )
+ {
+ aLine.Bottom();
+ nNew = (ULONG)aLine.GetLineNr();
+ }
+ else
+ {
+ do
+ {
+ if( aLine.GetCurr()->HasCntnt() )
+ ++nNew;
+ } while ( aLine.NextLine() );
+ }
+ }
+ else if ( rInf.IsCountBlankLines() )
+ nNew = 1;
+
+ if ( nNew != nThisLines )
+ {
+ if ( !IsInTab() && GetAttrSet()->GetLineNumber().IsCount() )
+ {
+ nAllLines -= nThisLines;
+ nThisLines = nNew;
+ nAllLines += nThisLines;
+ SwFrm *pNxt = GetNextCntntFrm();
+ while( pNxt && pNxt->IsInTab() )
+ {
+ if( 0 != (pNxt = pNxt->FindTabFrm()) )
+ pNxt = pNxt->FindNextCnt();
+ }
+ if( pNxt )
+ pNxt->InvalidateLineNum();
+
+ //Extend repaint to the bottom.
+ if ( HasPara() )
+ {
+ SwRepaint *pRepaint = GetPara()->GetRepaint();
+ pRepaint->Bottom( Max( pRepaint->Bottom(),
+ Frm().Top()+Prt().Bottom()));
+ }
+ }
+ else //Paragraphs which are not counted should not manipulate the AllLines.
+ nThisLines = nNew;
+ }
+}
+
+
+void SwTxtFrm::RecalcAllLines()
+{
+ ValidateLineNum();
+
+ const SwAttrSet *pAttrSet = GetAttrSet();
+
+ if ( !IsInTab() )
+ {
+ const ULONG nOld = GetAllLines();
+ const SwFmtLineNumber &rLineNum = pAttrSet->GetLineNumber();
+ ULONG nNewNum;
+ const bool bRestart = GetTxtNode()->getIDocumentLineNumberAccess()->GetLineNumberInfo().IsRestartEachPage();
+
+ if ( !IsFollow() && rLineNum.GetStartValue() && rLineNum.IsCount() )
+ nNewNum = rLineNum.GetStartValue() - 1;
+ //If it is a follow or not has not be considered if it is a restart at each page; the
+ //restart should also take affekt at follows.
+ else if ( bRestart && FindPageFrm()->FindFirstBodyCntnt() == this )
+ {
+ nNewNum = 0;
+ }
+ else
+ {
+ SwCntntFrm *pPrv = GetPrevCntntFrm();
+ while ( pPrv &&
+ (pPrv->IsInTab() || pPrv->IsInDocBody() != IsInDocBody()) )
+ pPrv = pPrv->GetPrevCntntFrm();
+
+ // --> FME 2007-06-22 #i78254# Restart line numbering at page change:
+ // First body content may be in table!
+ if ( bRestart && pPrv && pPrv->FindPageFrm() != FindPageFrm() )
+ pPrv = 0;
+ // <--
+
+ nNewNum = pPrv ? ((SwTxtFrm*)pPrv)->GetAllLines() : 0;
+ }
+ if ( rLineNum.IsCount() )
+ nNewNum += GetThisLines();
+
+ if ( nOld != nNewNum )
+ {
+ nAllLines = nNewNum;
+ SwCntntFrm *pNxt = GetNextCntntFrm();
+ while ( pNxt &&
+ (pNxt->IsInTab() || pNxt->IsInDocBody() != IsInDocBody()) )
+ pNxt = pNxt->GetNextCntntFrm();
+ if ( pNxt )
+ {
+ if ( pNxt->GetUpper() != GetUpper() )
+ pNxt->InvalidateLineNum();
+ else
+ pNxt->_InvalidateLineNum();
+ }
+ }
+ }
+}
+
+void SwTxtFrm::VisitPortions( SwPortionHandler& rPH ) const
+{
+ const SwParaPortion* pPara = GetPara();
+
+ if( pPara )
+ {
+ if ( IsFollow() )
+ rPH.Skip( GetOfst() );
+
+ const SwLineLayout* pLine = pPara;
+ while ( pLine )
+ {
+ const SwLinePortion* pPor = pLine->GetFirstPortion();
+ while ( pPor )
+ {
+ pPor->HandlePortion( rPH );
+ pPor = pPor->GetPortion();
+ }
+
+ rPH.LineBreak();
+ pLine = pLine->GetNext();
+ }
+ }
+
+ rPH.Finish();
+}
+
+
+/*************************************************************************
+ * SwTxtFrm::GetScriptInfo()
+ *************************************************************************/
+
+const SwScriptInfo* SwTxtFrm::GetScriptInfo() const
+{
+ const SwParaPortion* pPara = GetPara();
+ return pPara ? &pPara->GetScriptInfo() : 0;
+}
+
+/*************************************************************************
+ * lcl_CalcFlyBasePos()
+ * Helper function for SwTxtFrm::CalcBasePosForFly()
+ *************************************************************************/
+
+SwTwips lcl_CalcFlyBasePos( const SwTxtFrm& rFrm, SwRect aFlyRect,
+ SwTxtFly& rTxtFly )
+{
+ SWRECTFN( (&rFrm) )
+ SwTwips nRet = rFrm.IsRightToLeft() ?
+ (rFrm.Frm().*fnRect->fnGetRight)() :
+ (rFrm.Frm().*fnRect->fnGetLeft)();
+
+ do
+ {
+ SwRect aRect = rTxtFly.GetFrm( aFlyRect );
+ if ( 0 != (aRect.*fnRect->fnGetWidth)() )
+ {
+ if ( rFrm.IsRightToLeft() )
+ {
+ if ( (aRect.*fnRect->fnGetRight)() -
+ (aFlyRect.*fnRect->fnGetRight)() >= 0 )
+ {
+ (aFlyRect.*fnRect->fnSetRight)(
+ (aRect.*fnRect->fnGetLeft)() );
+ nRet = (aRect.*fnRect->fnGetLeft)();
+ }
+ else
+ break;
+ }
+ else
+ {
+ if ( (aFlyRect.*fnRect->fnGetLeft)() -
+ (aRect.*fnRect->fnGetLeft)() >= 0 )
+ {
+ (aFlyRect.*fnRect->fnSetLeft)(
+ (aRect.*fnRect->fnGetRight)() + 1 );
+ nRet = (aRect.*fnRect->fnGetRight)();
+ }
+ else
+ break;
+ }
+ }
+ else
+ break;
+ }
+ while ( (aFlyRect.*fnRect->fnGetWidth)() > 0 );
+
+ return nRet;
+}
+
+/*************************************************************************
+ * SwTxtFrm::CalcBasePosForFly()
+ *************************************************************************/
+
+void SwTxtFrm::CalcBaseOfstForFly()
+{
+ ASSERT( !IsVertical() || !IsSwapped(),
+ "SwTxtFrm::CalcBasePosForFly with swapped frame!" )
+
+ const SwNode* pNode = GetTxtNode();
+ if ( !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_FLY_OFFSETS) )
+ return;
+
+ SWRECTFN( this )
+
+ SwRect aFlyRect( Frm().Pos() + Prt().Pos(), Prt().SSize() );
+
+ // Get first 'real' line and adjust position and height of line rectangle
+ // OD 08.09.2003 #110978#, #108749#, #110354# - correct behaviour,
+ // if no 'real' line exists (empty paragraph with and without a dummy portion)
+ {
+ SwTwips nTop = (aFlyRect.*fnRect->fnGetTop)();
+ const SwLineLayout* pLay = GetPara();
+ SwTwips nLineHeight = 200;
+ while( pLay && pLay->IsDummy() && pLay->GetNext() )
+ {
+ nTop += pLay->Height();
+ pLay = pLay->GetNext();
+ }
+ if ( pLay )
+ {
+ nLineHeight = pLay->Height();
+ }
+ (aFlyRect.*fnRect->fnSetTopAndHeight)( nTop, nLineHeight );
+ }
+
+ SwTxtFly aTxtFly( this );
+ aTxtFly.SetIgnoreCurrentFrame( sal_True );
+ aTxtFly.SetIgnoreContour( sal_True );
+ // --> OD 2004-12-17 #118809# - ignore objects in page header|footer for
+ // text frames not in page header|footer
+ aTxtFly.SetIgnoreObjsInHeaderFooter( sal_True );
+ // <--
+ SwTwips nRet1 = lcl_CalcFlyBasePos( *this, aFlyRect, aTxtFly );
+ aTxtFly.SetIgnoreCurrentFrame( sal_False );
+ SwTwips nRet2 = lcl_CalcFlyBasePos( *this, aFlyRect, aTxtFly );
+
+ // make values relative to frame start position
+ SwTwips nLeft = IsRightToLeft() ?
+ (Frm().*fnRect->fnGetRight)() :
+ (Frm().*fnRect->fnGetLeft)();
+
+ mnFlyAnchorOfst = nRet1 - nLeft;
+ mnFlyAnchorOfstNoWrap = nRet2 - nLeft;
+}