diff options
Diffstat (limited to 'sw/source/core/text/frmform.cxx')
-rw-r--r-- | sw/source/core/text/frmform.cxx | 2068 |
1 files changed, 2068 insertions, 0 deletions
diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx new file mode 100644 index 000000000000..e28b1694d8a6 --- /dev/null +++ b/sw/source/core/text/frmform.cxx @@ -0,0 +1,2068 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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/keepitem.hxx> +#include <editeng/hyznitem.hxx> +#include <pagefrm.hxx> // ChangeFtnRef +#include <ndtxt.hxx> // MakeFrm() +#include <dcontact.hxx> // SwDrawContact +#include <dflyobj.hxx> // SwVirtFlyDrawObj +#include <flyfrm.hxx> +#include <ftnfrm.hxx> // SwFtnFrm +#include <txtftn.hxx> +#include <fmtftn.hxx> +#include <paratr.hxx> +#include <viewopt.hxx> // SwViewOptions +#include <viewsh.hxx> // ViewShell +#include <frmatr.hxx> +#include <pam.hxx> +#include <flyfrms.hxx> +#include <fmtanchr.hxx> +#include <itrform2.hxx> // SwTxtFormatter +#include <widorp.hxx> // Widows and Orphans +#include <txtcache.hxx> +#include <porrst.hxx> // SwEmptyPortion +#include <blink.hxx> // pBlink +#include <porfld.hxx> // SwFldPortion +#include <sectfrm.hxx> // SwSectionFrm +#include <pormulti.hxx> // SwMultiPortion + +#include <rootfrm.hxx> +#include <frmfmt.hxx> // SwFrmFmt +// OD 2004-05-24 #i28701# +#include <sortedobjs.hxx> + +// Toleranzwert in der Formatierung und Textausgabe. +#define SLOPPY_TWIPS 5 + +class FormatLevel +{ + static MSHORT nLevel; +public: + inline FormatLevel() { ++nLevel; } + inline ~FormatLevel() { --nLevel; } + inline MSHORT GetLevel() const { return nLevel; } + static sal_Bool LastLevel() { return 10 < nLevel; } +}; +MSHORT FormatLevel::nLevel = 0; + +/************************************************************************* + * ValidateTxt/Frm() + *************************************************************************/ + +void ValidateTxt( SwFrm *pFrm ) // Freund vom Frame +{ + if ( ( ! pFrm->IsVertical() && + pFrm->Frm().Width() == pFrm->GetUpper()->Prt().Width() ) || + ( pFrm->IsVertical() && + pFrm->Frm().Height() == pFrm->GetUpper()->Prt().Height() ) ) + pFrm->bValidSize = sal_True; +} + +void SwTxtFrm::ValidateFrm() +{ + // Umgebung validieren, um Oszillationen zu verhindern. + SWAP_IF_SWAPPED( this ) + + if ( !IsInFly() && !IsInTab() ) + { //Innerhalb eines Flys nur this validieren, der Rest sollte eigentlich + //nur fuer Fussnoten notwendig sein und die gibt es innerhalb von + //Flys nicht. Fix fuer 5544 + SwSectionFrm* pSct = FindSctFrm(); + if( pSct ) + { + if( !pSct->IsColLocked() ) + pSct->ColLock(); + else + pSct = NULL; + } + + SwFrm *pUp = GetUpper(); + pUp->Calc(); + if( pSct ) + pSct->ColUnlock(); + } + ValidateTxt( this ); + + //MA: mindestens das MustFit-Flag muessen wir retten! + OSL_ENSURE( HasPara(), "ResetPreps(), missing ParaPortion." ); + SwParaPortion *pPara = GetPara(); + const sal_Bool bMustFit = pPara->IsPrepMustFit(); + ResetPreps(); + pPara->SetPrepMustFit( bMustFit ); + + UNDO_SWAP( this ) +} + +/************************************************************************* + * ValidateBodyFrm() + *************************************************************************/ + +// nach einem RemoveFtn muss der BodyFrm und alle innenliegenden kalkuliert +// werden, damit die DeadLine richtig sitzt. +// Erst wird nach aussen hin gesucht, beim Rueckweg werden alle kalkuliert. + +void _ValidateBodyFrm( SwFrm *pFrm ) +{ + if( pFrm && !pFrm->IsCellFrm() ) + { + if( !pFrm->IsBodyFrm() && pFrm->GetUpper() ) + _ValidateBodyFrm( pFrm->GetUpper() ); + if( !pFrm->IsSctFrm() ) + pFrm->Calc(); + else + { + sal_Bool bOld = ((SwSectionFrm*)pFrm)->IsCntntLocked(); + ((SwSectionFrm*)pFrm)->SetCntntLock( sal_True ); + pFrm->Calc(); + if( !bOld ) + ((SwSectionFrm*)pFrm)->SetCntntLock( sal_False ); + } + } +} + +void SwTxtFrm::ValidateBodyFrm() +{ + SWAP_IF_SWAPPED( this ) + + //siehe Kommtar in ValidateFrm() + if ( !IsInFly() && !IsInTab() && + !( IsInSct() && FindSctFrm()->Lower()->IsColumnFrm() ) ) + _ValidateBodyFrm( GetUpper() ); + + UNDO_SWAP( this ) +} + +/************************************************************************* + * SwTxtFrm::FindBodyFrm() + *************************************************************************/ + +sal_Bool SwTxtFrm::_GetDropRect( SwRect &rRect ) const +{ + SWAP_IF_NOT_SWAPPED( this ) + + OSL_ENSURE( HasPara(), "SwTxtFrm::_GetDropRect: try again next year." ); + SwTxtSizeInfo aInf( (SwTxtFrm*)this ); + SwTxtMargin aLine( (SwTxtFrm*)this, &aInf ); + if( aLine.GetDropLines() ) + { + rRect.Top( aLine.Y() ); + rRect.Left( aLine.GetLineStart() ); + rRect.Height( aLine.GetDropHeight() ); + rRect.Width( aLine.GetDropLeft() ); + + if ( IsRightToLeft() ) + SwitchLTRtoRTL( rRect ); + + if ( IsVertical() ) + SwitchHorizontalToVertical( rRect ); + UNDO_SWAP( this ) + return sal_True; + } + + UNDO_SWAP( this ) + + return sal_False; +} + +/************************************************************************* + * SwTxtFrm::FindBodyFrm() + *************************************************************************/ + +const SwBodyFrm *SwTxtFrm::FindBodyFrm() const +{ + if ( IsInDocBody() ) + { + const SwFrm *pFrm = GetUpper(); + while( pFrm && !pFrm->IsBodyFrm() ) + pFrm = pFrm->GetUpper(); + return (const SwBodyFrm*)pFrm; + } + return 0; +} + +/************************************************************************* + * SwTxtFrm::CalcFollow() + *************************************************************************/ + +sal_Bool SwTxtFrm::CalcFollow( const xub_StrLen nTxtOfst ) +{ + SWAP_IF_SWAPPED( this ) + + OSL_ENSURE( HasFollow(), "CalcFollow: missing Follow." ); + + SwTxtFrm* pMyFollow = GetFollow(); + + SwParaPortion *pPara = GetPara(); + sal_Bool bFollowFld = pPara ? pPara->IsFollowField() : sal_False; + + if( !pMyFollow->GetOfst() || pMyFollow->GetOfst() != nTxtOfst || + bFollowFld || pMyFollow->IsFieldFollow() || + ( pMyFollow->IsVertical() && !pMyFollow->Prt().Width() ) || + ( ! pMyFollow->IsVertical() && !pMyFollow->Prt().Height() ) ) + { +#if OSL_DEBUG_LEVEL > 1 + const SwFrm *pOldUp = GetUpper(); +#endif + + SWRECTFN ( this ) + SwTwips nOldBottom = (GetUpper()->Frm().*fnRect->fnGetBottom)(); + SwTwips nMyPos = (Frm().*fnRect->fnGetTop)(); + + const SwPageFrm *pPage = 0; + sal_Bool bOldInvaCntnt = sal_True; + if ( !IsInFly() && GetNext() ) + { + pPage = FindPageFrm(); + //Minimieren - sprich ggf. zuruecksetzen - der Invalidierungen s.u. + bOldInvaCntnt = pPage->IsInvalidCntnt(); + } + + pMyFollow->_SetOfst( nTxtOfst ); + pMyFollow->SetFieldFollow( bFollowFld ); + if( HasFtn() || pMyFollow->HasFtn() ) + { + ValidateFrm(); + ValidateBodyFrm(); + if( pPara ) + { + *(pPara->GetReformat()) = SwCharRange(); + *(pPara->GetDelta()) = 0; + } + } + + //Der Fussnotenbereich darf sich keinesfalls vergrossern. + SwSaveFtnHeight aSave( FindFtnBossFrm( sal_True ), LONG_MAX ); + + pMyFollow->CalcFtnFlag(); + if ( !pMyFollow->GetNext() && !pMyFollow->HasFtn() ) + nOldBottom = bVert ? 0 : LONG_MAX; + + while( sal_True ) + { + if( !FormatLevel::LastLevel() ) + { + // Weenn der Follow in einem spaltigen Bereich oder einem + // spaltigen Rahmen steckt, muss zunaechst dieser kalkuliert + // werden, da das FormatWidthCols() nicht funktioniert, wenn + // es aus dem MakeAll des _gelockten_ Follows heraus gerufen + // wird. + SwSectionFrm* pSct = pMyFollow->FindSctFrm(); + if( pSct && !pSct->IsAnLower( this ) ) + { + if( pSct->GetFollow() ) + pSct->SimpleFormat(); + else if( ( pSct->IsVertical() && !pSct->Frm().Width() ) || + ( ! pSct->IsVertical() && !pSct->Frm().Height() ) ) + break; + } + // OD 14.03.2003 #i11760# - intrinsic format of follow is controlled. + if ( FollowFormatAllowed() ) + { + // OD 14.03.2003 #i11760# - no nested format of follows, if + // text frame is contained in a column frame. + // Thus, forbid intrinsic format of follow. + { + bool bIsFollowInColumn = false; + SwFrm* pFollowUpper = pMyFollow->GetUpper(); + while ( pFollowUpper ) + { + if ( pFollowUpper->IsColumnFrm() ) + { + bIsFollowInColumn = true; + break; + } + if ( pFollowUpper->IsPageFrm() || + pFollowUpper->IsFlyFrm() ) + { + break; + } + pFollowUpper = pFollowUpper->GetUpper(); + } + if ( bIsFollowInColumn ) + { + pMyFollow->ForbidFollowFormat(); + } + } + + pMyFollow->Calc(); + // Der Follow merkt anhand seiner Frm().Height(), dass was schief + // gelaufen ist. + OSL_ENSURE( !pMyFollow->GetPrev(), "SwTxtFrm::CalcFollow: cheesy follow" ); + if( pMyFollow->GetPrev() ) + { + pMyFollow->Prepare( PREP_CLEAR ); + pMyFollow->Calc(); + OSL_ENSURE( !pMyFollow->GetPrev(), "SwTxtFrm::CalcFollow: very cheesy follow" ); + } + + // OD 14.03.2003 #i11760# - reset control flag for follow format. + pMyFollow->AllowFollowFormat(); + } + + //Sicherstellen, dass der Follow gepaintet wird. + pMyFollow->SetCompletePaint(); + } + + pPara = GetPara(); + //Solange der Follow wg. Orphans Zeilen angefordert, bekommt er + //diese und wird erneut formatiert, falls moeglich. + if( pPara && pPara->IsPrepWidows() ) + CalcPreps(); + else + break; + } + + if( HasFtn() || pMyFollow->HasFtn() ) + { + ValidateBodyFrm(); + ValidateFrm(); + if( pPara ) + { + *(pPara->GetReformat()) = SwCharRange(); + *(pPara->GetDelta()) = 0; + } + } + + if ( pPage ) + { + if ( !bOldInvaCntnt ) + pPage->ValidateCntnt(); + } + +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE( pOldUp == GetUpper(), "SwTxtFrm::CalcFollow: heavy follow" ); +#endif + + const long nRemaining = + - (GetUpper()->Frm().*fnRect->fnBottomDist)( nOldBottom ); + if ( nRemaining > 0 && !GetUpper()->IsSctFrm() && + nRemaining != ( bVert ? + nMyPos - Frm().Right() : + Frm().Top() - nMyPos ) ) + { + UNDO_SWAP( this ) + return sal_True; + } + } + + UNDO_SWAP( this ) + + return sal_False; +} + +/************************************************************************* + * SwTxtFrm::AdjustFrm() + *************************************************************************/ + +void SwTxtFrm::AdjustFrm( const SwTwips nChgHght, sal_Bool bHasToFit ) +{ + if( IsUndersized() ) + { + if( GetOfst() && !IsFollow() ) // ein gescrollter Absatz (undersized) + return; + SetUndersized( nChgHght == 0 || bHasToFit ); + } + + // AdjustFrm is called with a swapped frame during + // formatting but the frame is not swapped during FormatEmpty + SWAP_IF_SWAPPED( this ) + SWRECTFN ( this ) + + // Die Size-Variable des Frames wird durch Grow inkrementiert + // oder durch Shrink dekrementiert. Wenn die Groesse + // unveraendert ist, soll nichts passieren! + if( nChgHght >= 0) + { + SwTwips nChgHeight = nChgHght; + if( nChgHght && !bHasToFit ) + { + if( IsInFtn() && !IsInSct() ) + { + SwTwips nReal = Grow( nChgHght, sal_True ); + if( nReal < nChgHght ) + { + SwTwips nBot = (*fnRect->fnYInc)( (Frm().*fnRect->fnGetBottom)(), + nChgHght - nReal ); + SwFrm* pCont = FindFtnFrm()->GetUpper(); + + if( (pCont->Frm().*fnRect->fnBottomDist)( nBot ) > 0 ) + { + (Frm().*fnRect->fnAddBottom)( nChgHght ); + if( bVert ) + Prt().SSize().Width() += nChgHght; + else + Prt().SSize().Height() += nChgHght; + UNDO_SWAP( this ) + return; + } + } + } + + Grow( nChgHght ); + + if ( IsInFly() ) + { + //MA 06. May. 93: Wenn einer der Upper ein Fly ist, so ist es + //sehr wahrscheinlich, dass dieser Fly durch das Grow seine + //Position veraendert - also muss auch meine Position korrigiert + //werden (sonst ist die Pruefung s.u. nicht aussagekraeftig). + //Die Vorgaenger muessen berechnet werden, damit die Position + //korrekt berechnet werden kann. + if ( GetPrev() ) + { + SwFrm *pPre = GetUpper()->Lower(); + do + { pPre->Calc(); + pPre = pPre->GetNext(); + } while ( pPre && pPre != this ); + } + const Point aOldPos( Frm().Pos() ); + MakePos(); + if ( aOldPos != Frm().Pos() ) + { + // OD 2004-07-01 #i28701# - use new method <SwFrm::InvalidateObjs(..)> + // No format is performed for the floating screen objects. + InvalidateObjs( true ); + } + } + nChgHeight = 0; + } + // Ein Grow() wird von der Layout-Seite immer akzeptiert, + // also auch, wenn die FixSize des umgebenden Layoutframes + // dies nicht zulassen sollte. Wir ueberpruefen diesen + // Fall und korrigieren die Werte. + // MA 06. May. 93: Der Frm darf allerdings auch im Notfall nicht + // weiter geschrumpft werden als es seine Groesse zulaesst. + SwTwips nRstHeight; + if ( IsVertical() ) + { + OSL_ENSURE( ! IsSwapped(),"Swapped frame while calculating nRstHeight" ); + + //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin + if ( IsVertLR() ) + nRstHeight = GetUpper()->Frm().Left() + + GetUpper()->Prt().Left() + + GetUpper()->Prt().Width() + - Frm().Left(); + else + nRstHeight = Frm().Left() + Frm().Width() - + ( GetUpper()->Frm().Left() + GetUpper()->Prt().Left() ); + } + else + nRstHeight = GetUpper()->Frm().Top() + + GetUpper()->Prt().Top() + + GetUpper()->Prt().Height() + - Frm().Top(); + + //In Tabellenzellen kann ich mir evtl. noch ein wenig dazuholen, weil + //durch eine vertikale Ausrichtung auch oben noch Raum sein kann. + // --> OD 2004-11-25 #115759# - assure, that first lower in upper + // is the current one or is valid. + if ( IsInTab() && + ( GetUpper()->Lower() == this || + GetUpper()->Lower()->IsValid() ) ) + // <-- + { + long nAdd = (*fnRect->fnYDiff)( (GetUpper()->Lower()->Frm().*fnRect->fnGetTop)(), + (GetUpper()->*fnRect->fnGetPrtTop)() ); + OSL_ENSURE( nAdd >= 0, "Ey" ); + nRstHeight += nAdd; + } + +/* ------------------------------------ + * #50964#: nRstHeight < 0 bedeutet, dass der TxtFrm komplett ausserhalb seines + * Upper liegt. Dies kann passieren, wenn er innerhalb eines FlyAtCntFrm liegt, der + * durch das Grow() die Seite gewechselt hat. In so einem Fall ist es falsch, der + * folgenden Grow-Versuch durchzufuehren. Im Bugfall fuehrte dies sogar zur + * Endlosschleife. + * -----------------------------------*/ + SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)(); + SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)(); + + if( nRstHeight < nFrmHeight ) + { + //Kann sein, dass ich die richtige Grosse habe, der Upper aber zu + //klein ist und der Upper noch Platz schaffen kann. + if( ( nRstHeight >= 0 || ( IsInFtn() && IsInSct() ) ) && !bHasToFit ) + nRstHeight += GetUpper()->Grow( nFrmHeight - nRstHeight ); + // In spaltigen Bereichen wollen wir moeglichst nicht zu gross werden, damit + // nicht ueber GetNextSctLeaf weitere Bereiche angelegt werden. Stattdessen + // schrumpfen wir und notieren bUndersized, damit FormatWidthCols die richtige + // Spaltengroesse ermitteln kann. + if ( nRstHeight < nFrmHeight ) + { + if( bHasToFit || !IsMoveable() || + ( IsInSct() && !FindSctFrm()->MoveAllowed(this) ) ) + { + SetUndersized( sal_True ); + Shrink( Min( ( nFrmHeight - nRstHeight), nPrtHeight ) ); + } + else + SetUndersized( sal_False ); + } + } + else if( nChgHeight ) + { + if( nRstHeight - nFrmHeight < nChgHeight ) + nChgHeight = nRstHeight - nFrmHeight; + if( nChgHeight ) + Grow( nChgHeight ); + } + } + else + Shrink( -nChgHght ); + + UNDO_SWAP( this ) +} + +/************************************************************************* + * SwTxtFrm::AdjustFollow() + *************************************************************************/ + +/* AdjustFollow erwartet folgende Situation: + * Der SwTxtIter steht am unteren Ende des Masters, der Offset wird + * im Follow eingestellt. + * nOffset haelt den Offset im Textstring, ab dem der Master abschliesst + * und der Follow beginnt. Wenn er 0 ist, wird der FolgeFrame geloescht. + */ + +void SwTxtFrm::_AdjustFollow( SwTxtFormatter &rLine, + const xub_StrLen nOffset, const xub_StrLen nEnd, + const sal_uInt8 nMode ) +{ + SwFrmSwapper aSwapper( this, sal_False ); + + // Wir haben den Rest der Textmasse: alle Follows loeschen + // Sonderfall sind DummyPortions() + // - special cases are controlled by parameter <nMode>. + if( HasFollow() && !(nMode & 1) && nOffset == nEnd ) + { + while( GetFollow() ) + { + if( ((SwTxtFrm*)GetFollow())->IsLocked() ) + { + OSL_FAIL( "+SwTxtFrm::JoinFrm: Follow ist locked." ); + return; + } + JoinFrm(); + } + + return; + } + + // Tanz auf dem Vulkan: Wir formatieren eben schnell noch einmal + // die letzte Zeile fuer das QuoVadis-Geraffel. Selbstverstaendlich + // kann sich dadurch auch der Offset verschieben: + const xub_StrLen nNewOfst = ( IsInFtn() && ( !GetIndNext() || HasFollow() ) ) ? + rLine.FormatQuoVadis(nOffset) : nOffset; + + if( !(nMode & 1) ) + { + // Wir klauen unseren Follows Textmasse, dabei kann es passieren, + // dass wir einige Follows Joinen muessen. + while( GetFollow() && GetFollow()->GetFollow() && + nNewOfst >= GetFollow()->GetFollow()->GetOfst() ) + { + JoinFrm(); + } + } + + // Der Ofst hat sich verschoben. + if( GetFollow() ) + { +#if OSL_DEBUG_LEVEL > 1 + static sal_Bool bTest = sal_False; + if( !bTest || ( nMode & 1 ) ) +#endif + if ( nMode ) + GetFollow()->ManipOfst( 0 ); + + if ( CalcFollow( nNewOfst ) ) // CalcFollow erst zum Schluss, dort erfolgt ein SetOfst + rLine.SetOnceMore( sal_True ); + } +} + +/************************************************************************* + * SwTxtFrm::JoinFrm() + *************************************************************************/ + +SwCntntFrm *SwTxtFrm::JoinFrm() +{ + OSL_ENSURE( GetFollow(), "+SwTxtFrm::JoinFrm: no follow" ); + SwTxtFrm *pFoll = GetFollow(); + + SwTxtFrm *pNxt = pFoll->GetFollow(); + + // Alle Fussnoten des zu zerstoerenden Follows werden auf uns + // umgehaengt. + xub_StrLen nStart = pFoll->GetOfst(); + if ( pFoll->HasFtn() ) + { + const SwpHints *pHints = pFoll->GetTxtNode()->GetpSwpHints(); + if( pHints ) + { + SwFtnBossFrm *pFtnBoss = 0; + SwFtnBossFrm *pEndBoss = 0; + for ( sal_uInt16 i = 0; i < pHints->Count(); ++i ) + { + const SwTxtAttr *pHt = (*pHints)[i]; + if( RES_TXTATR_FTN==pHt->Which() && *pHt->GetStart()>=nStart ) + { + if( pHt->GetFtn().IsEndNote() ) + { + if( !pEndBoss ) + pEndBoss = pFoll->FindFtnBossFrm(); + pEndBoss->ChangeFtnRef( pFoll, (SwTxtFtn*)pHt, this ); + } + else + { + if( !pFtnBoss ) + pFtnBoss = pFoll->FindFtnBossFrm( sal_True ); + pFtnBoss->ChangeFtnRef( pFoll, (SwTxtFtn*)pHt, this ); + } + SetFtn( sal_True ); + } + } + } + } + +#if OSL_DEBUG_LEVEL > 1 + else if ( pFoll->GetValidPrtAreaFlag() || + pFoll->GetValidSizeFlag() ) + { + pFoll->CalcFtnFlag(); + OSL_ENSURE( !pFoll->HasFtn(), "Missing FtnFlag." ); + } +#endif + + pFoll->MoveFlyInCnt( this, nStart, STRING_LEN ); + pFoll->SetFtn( sal_False ); + // --> OD 2005-12-01 #i27138# + // notify accessibility paragraphs objects about changed CONTENT_FLOWS_FROM/_TO relation. + // Relation CONTENT_FLOWS_FROM for current next paragraph will change + // and relation CONTENT_FLOWS_TO for current previous paragraph, which + // is <this>, will change. + { + ViewShell* pViewShell( pFoll->getRootFrm()->GetCurrShell() ); + if ( pViewShell && pViewShell->GetLayout() && + pViewShell->GetLayout()->IsAnyShellAccessible() ) + { + pViewShell->InvalidateAccessibleParaFlowRelation( + dynamic_cast<SwTxtFrm*>(pFoll->FindNextCnt( true )), + this ); + } + } + // <-- + pFoll->Cut(); + delete pFoll; + pFollow = pNxt; + return pNxt; +} + +/************************************************************************* + * SwTxtFrm::SplitFrm() + *************************************************************************/ + +SwCntntFrm *SwTxtFrm::SplitFrm( const xub_StrLen nTxtPos ) +{ + SWAP_IF_SWAPPED( this ) + + // Durch das Paste wird ein Modify() an mich verschickt. + // Damit meine Daten nicht verschwinden, locke ich mich. + SwTxtFrmLocker aLock( this ); + SwTxtFrm *pNew = (SwTxtFrm *)(GetTxtNode()->MakeFrm( this )); + pNew->bIsFollow = sal_True; + + pNew->SetFollow( GetFollow() ); + SetFollow( pNew ); + + pNew->Paste( GetUpper(), GetNext() ); + // --> OD 2005-12-01 #i27138# + // notify accessibility paragraphs objects about changed CONTENT_FLOWS_FROM/_TO relation. + // Relation CONTENT_FLOWS_FROM for current next paragraph will change + // and relation CONTENT_FLOWS_TO for current previous paragraph, which + // is <this>, will change. + { + ViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() ); + if ( pViewShell && pViewShell->GetLayout() && + pViewShell->GetLayout()->IsAnyShellAccessible() ) + { + pViewShell->InvalidateAccessibleParaFlowRelation( + dynamic_cast<SwTxtFrm*>(pNew->FindNextCnt( true )), + this ); + } + } + // <-- + + // Wenn durch unsere Aktionen Fussnoten in pNew landen, + // so muessen sie umgemeldet werden. + if ( HasFtn() ) + { + const SwpHints *pHints = GetTxtNode()->GetpSwpHints(); + if( pHints ) + { + SwFtnBossFrm *pFtnBoss = 0; + SwFtnBossFrm *pEndBoss = 0; + for ( sal_uInt16 i = 0; i < pHints->Count(); ++i ) + { + const SwTxtAttr *pHt = (*pHints)[i]; + if( RES_TXTATR_FTN==pHt->Which() && *pHt->GetStart()>=nTxtPos ) + { + if( pHt->GetFtn().IsEndNote() ) + { + if( !pEndBoss ) + pEndBoss = FindFtnBossFrm(); + pEndBoss->ChangeFtnRef( this, (SwTxtFtn*)pHt, pNew ); + } + else + { + if( !pFtnBoss ) + pFtnBoss = FindFtnBossFrm( sal_True ); + pFtnBoss->ChangeFtnRef( this, (SwTxtFtn*)pHt, pNew ); + } + pNew->SetFtn( sal_True ); + } + } + } + } + +#if OSL_DEBUG_LEVEL > 1 + else + { + CalcFtnFlag( nTxtPos-1 ); + OSL_ENSURE( !HasFtn(), "Missing FtnFlag." ); + } +#endif + + MoveFlyInCnt( pNew, nTxtPos, STRING_LEN ); + + // Kein SetOfst oder CalcFollow, weil gleich ohnehin ein AdjustFollow folgt. + + pNew->ManipOfst( nTxtPos ); + + UNDO_SWAP( this ) + return pNew; +} + + +/************************************************************************* + * virtual SwTxtFrm::SetOfst() + *************************************************************************/ + +void SwTxtFrm::_SetOfst( const xub_StrLen nNewOfst ) +{ + // Die Invalidierung unseres Follows ist nicht noetig. + // Wir sind ein Follow, werden gleich formatiert und + // rufen von dort aus das SetOfst() ! + nOfst = nNewOfst; + SwParaPortion *pPara = GetPara(); + if( pPara ) + { + SwCharRange &rReformat = *(pPara->GetReformat()); + rReformat.Start() = 0; + rReformat.Len() = GetTxt().Len(); + *(pPara->GetDelta()) = rReformat.Len(); + } + InvalidateSize(); +} + +/************************************************************************* + * SwTxtFrm::CalcPreps + *************************************************************************/ + +sal_Bool SwTxtFrm::CalcPreps() +{ + OSL_ENSURE( ! IsVertical() || ! IsSwapped(), "SwTxtFrm::CalcPreps with swapped frame" ); + SWRECTFN( this ); + + SwParaPortion *pPara = GetPara(); + if ( !pPara ) + return sal_False; + sal_Bool bPrep = pPara->IsPrep(); + sal_Bool bPrepWidows = pPara->IsPrepWidows(); + sal_Bool bPrepAdjust = pPara->IsPrepAdjust(); + sal_Bool bPrepMustFit = pPara->IsPrepMustFit(); + ResetPreps(); + + sal_Bool bRet = sal_False; + if( bPrep && !pPara->GetReformat()->Len() ) + { + // PREP_WIDOWS bedeutet, dass im Follow die Orphans-Regel + // zuschlug. + // Es kann in unguenstigen Faellen vorkommen, dass auch ein + // PrepAdjust vorliegt (3680)! + if( bPrepWidows ) + { + if( !GetFollow() ) + { + OSL_ENSURE( GetFollow(), "+SwTxtFrm::CalcPreps: no credits" ); + return sal_False; + } + + // Wir muessen uns auf zwei Faelle einstellen: + // Wir konnten dem Follow noch ein paar Zeilen abgeben, + // -> dann muessen wir schrumpfen + // oder wir muessen auf die naechste Seite + // -> dann lassen wir unseren Frame zu gross werden. + + SwTwips nChgHeight = GetParHeight(); + if( nChgHeight >= (Prt().*fnRect->fnGetHeight)() ) + { + if( bPrepMustFit ) + { + GetFollow()->SetJustWidow( sal_True ); + GetFollow()->Prepare( PREP_CLEAR ); + } + else if ( bVert ) + { + Frm().Width( Frm().Width() + Frm().Left() ); + Prt().Width( Prt().Width() + Frm().Left() ); + Frm().Left( 0 ); + SetWidow( sal_True ); + } + else + { + SwTwips nTmp = LONG_MAX - (Frm().Top()+10000); + SwTwips nDiff = nTmp - Frm().Height(); + Frm().Height( nTmp ); + Prt().Height( Prt().Height() + nDiff ); + SetWidow( sal_True ); + } + } + else + { + OSL_ENSURE( nChgHeight < (Prt().*fnRect->fnGetHeight)(), + "+SwTxtFrm::CalcPrep: wanna shrink" ); + + nChgHeight = (Prt().*fnRect->fnGetHeight)() - nChgHeight; + + GetFollow()->SetJustWidow( sal_True ); + GetFollow()->Prepare( PREP_CLEAR ); + Shrink( nChgHeight ); + SwRect &rRepaint = *(pPara->GetRepaint()); + + if ( bVert ) + { + SwRect aRepaint( Frm().Pos() + Prt().Pos(), Prt().SSize() ); + SwitchVerticalToHorizontal( aRepaint ); + rRepaint.Chg( aRepaint.Pos(), aRepaint.SSize() ); + } + else + rRepaint.Chg( Frm().Pos() + Prt().Pos(), Prt().SSize() ); + + if( 0 >= rRepaint.Width() ) + rRepaint.Width(1); + } + bRet = sal_True; + } + + else if ( bPrepAdjust ) + { + if ( HasFtn() ) + { + if( !CalcPrepFtnAdjust() ) + { + if( bPrepMustFit ) + { + SwTxtLineAccess aAccess( this ); + aAccess.GetPara()->SetPrepMustFit( sal_True ); + } + return sal_False; + } + } + + SWAP_IF_NOT_SWAPPED( this ) + + SwTxtFormatInfo aInf( this ); + SwTxtFormatter aLine( this, &aInf ); + + WidowsAndOrphans aFrmBreak( this ); + // Egal was die Attribute meinen, bei MustFit wird + // der Absatz im Notfall trotzdem gesplittet... + if( bPrepMustFit ) + { + aFrmBreak.SetKeep( sal_False ); + aFrmBreak.ClrOrphLines(); + } + // Bevor wir FormatAdjust aufrufen muessen wir dafuer + // sorgen, dass die Zeilen, die unten raushaengen + // auch tatsaechlich abgeschnitten werden. + // OD 2004-02-25 #i16128# - method renamed + sal_Bool bBreak = aFrmBreak.IsBreakNowWidAndOrp( aLine ); + bRet = sal_True; + while( !bBreak && aLine.Next() ) + { + // OD 2004-02-25 #i16128# - method renamed + bBreak = aFrmBreak.IsBreakNowWidAndOrp( aLine ); + } + if( bBreak ) + { + // Es gibt Komplikationen: wenn TruncLines gerufen wird, + // veraendern sich ploetzlich die Bedingungen in + // IsInside, so dass IsBreakNow andere Ergebnisse + // liefern kann. Aus diesem Grund wird rFrmBreak bekannt + // gegeben, dass da wo rLine steht, das Ende erreicht + // ist. Mal sehen, ob's klappt ... + aLine.TruncLines(); + aFrmBreak.SetRstHeight( aLine ); + FormatAdjust( aLine, aFrmBreak, aInf.GetTxt().Len(), aInf.IsStop() ); + } + else + { + if( !GetFollow() ) + { + FormatAdjust( aLine, aFrmBreak, + aInf.GetTxt().Len(), aInf.IsStop() ); + } + else if ( !aFrmBreak.IsKeepAlways() ) + { + // Siehe Bug: 2320 + // Vor dem Master wird eine Zeile geloescht, der Follow + // koennte eine Zeile abgeben. + const SwCharRange aFollowRg( GetFollow()->GetOfst(), 1 ); + *(pPara->GetReformat()) += aFollowRg; + // Es soll weitergehen! + bRet = sal_False; + } + } + + UNDO_SWAP( this ) + // Eine letzte Ueberpruefung, falls das FormatAdjust() nichts + // brachte, muessen wir amputieren. + if( bPrepMustFit ) + { + const SwTwips nMust = (GetUpper()->*fnRect->fnGetPrtBottom)(); + const SwTwips nIs = (Frm().*fnRect->fnGetBottom)(); + + if( bVert && nIs < nMust ) + { + Shrink( nMust - nIs ); + if( Prt().Width() < 0 ) + Prt().Width( 0 ); + SetUndersized( sal_True ); + } + else if ( ! bVert && nIs > nMust ) + { + Shrink( nIs - nMust ); + if( Prt().Height() < 0 ) + Prt().Height( 0 ); + SetUndersized( sal_True ); + } + } + } + } + pPara->SetPrepMustFit( bPrepMustFit ); + return bRet; +} + + +/************************************************************************* + * SwTxtFrm::FormatAdjust() + *************************************************************************/ + +// Hier werden die Fussnoten und "als Zeichen"-gebundenen Objekte umgehaengt +#define CHG_OFFSET( pFrm, nNew )\ + {\ + if( pFrm->GetOfst() < nNew )\ + pFrm->MoveFlyInCnt( this, 0, nNew );\ + else if( pFrm->GetOfst() > nNew )\ + MoveFlyInCnt( pFrm, nNew, STRING_LEN );\ + } + +void SwTxtFrm::FormatAdjust( SwTxtFormatter &rLine, + WidowsAndOrphans &rFrmBreak, + const xub_StrLen nStrLen, + const sal_Bool bDummy ) +{ + SWAP_IF_NOT_SWAPPED( this ) + + SwParaPortion *pPara = rLine.GetInfo().GetParaPortion(); + + xub_StrLen nEnd = rLine.GetStart(); + + sal_Bool bHasToFit = pPara->IsPrepMustFit(); + + // Das StopFlag wird durch Fussnoten gesetzt, + // die auf die naechste Seite wollen. + // OD, FME 2004-03-03 - call base class method <SwTxtFrmBreak::IsBreakNow(..)> + // instead of method <WidowsAndOrphans::IsBreakNow(..)> to get a break, + // even if due to widow rule no enough lines exists. + sal_uInt8 nNew = ( !GetFollow() && + nEnd < nStrLen && + ( rLine.IsStop() || + ( bHasToFit + ? ( rLine.GetLineNr() > 1 && + !rFrmBreak.IsInside( rLine ) ) + : rFrmBreak.IsBreakNow( rLine ) ) ) ) + ? 1 : 0; + if ( nNew ) + SplitFrm( nEnd ); + + const SwFrm *pBodyFrm = (const SwFrm*)(FindBodyFrm()); + + const long nBodyHeight = pBodyFrm ? ( IsVertical() ? + pBodyFrm->Frm().Width() : + pBodyFrm->Frm().Height() ) : 0; + + // Wenn die aktuellen Werte berechnet wurden, anzeigen, dass + // sie jetzt gueltig sind. + *(pPara->GetReformat()) = SwCharRange(); + sal_Bool bDelta = *pPara->GetDelta() != 0; + *(pPara->GetDelta()) = 0; + + if( rLine.IsStop() ) + { + rLine.TruncLines( sal_True ); + nNew = 1; + } + + // FindBreak schneidet die letzte Zeile ab. + if( !rFrmBreak.FindBreak( this, rLine, bHasToFit ) ) + { + // Wenn wir bis zum Ende durchformatiert haben, wird nEnd auf das Ende + // gesetzt. In AdjustFollow wird dadurch ggf. JoinFrm() ausgefuehrt. + // Ansonsten ist nEnd das Ende der letzten Zeile im Master. + xub_StrLen nOld = nEnd; + nEnd = rLine.GetEnd(); + if( GetFollow() ) + { + if( nNew && nOld < nEnd ) + RemoveFtn( nOld, nEnd - nOld ); + CHG_OFFSET( GetFollow(), nEnd ) + if( !bDelta ) + GetFollow()->ManipOfst( nEnd ); + } + } + else + { // Wenn wir Zeilen abgeben, darf kein Join auf den Folows gerufen werden, + // im Gegenteil, es muss ggf. sogar ein Follow erzeugt werden. + // Dies muss auch geschehen, wenn die Textmasse komplett im Master + // bleibt, denn es k???nnte ja ein harter Zeilenumbruch noch eine weitere + // Zeile (ohne Textmassse) notwendig machen! + nEnd = rLine.GetEnd(); + if( GetFollow() ) + { + // OD 21.03.2003 #108121# - Another case for not joining the follow: + // Text frame has no content, but a numbering. Then, do *not* join. + // Example of this case: When an empty, but numbered paragraph + // at the end of page is completely displaced by a fly frame. + // Thus, the text frame introduced a follow by a + // <SwTxtFrm::SplitFrm(..)> - see below. The follow then shows + // the numbering and must stay. + if ( GetFollow()->GetOfst() != nEnd || + GetFollow()->IsFieldFollow() || + ( nStrLen == 0 && GetTxtNode()->GetNumRule()) + ) + { + nNew |= 3; + } + CHG_OFFSET( GetFollow(), nEnd ) + GetFollow()->ManipOfst( nEnd ); + } + else + { + // OD 21.03.2003 #108121# - Only split frame, if the frame contains + // content or contains no content, but has a numbering. + if ( nStrLen > 0 || + ( nStrLen == 0 && GetTxtNode()->GetNumRule()) + ) + { + SplitFrm( nEnd ); + nNew |= 3; + } + } + // Wenn sich die Resthoehe geaendert hat, z.B. durch RemoveFtn() + // dann muessen wir auffuellen, um Oszillationen zu vermeiden! + if( bDummy && pBodyFrm && + nBodyHeight < ( IsVertical() ? + pBodyFrm->Frm().Width() : + pBodyFrm->Frm().Height() ) ) + rLine.MakeDummyLine(); + } + + // In AdjustFrm() stellen wir uns selbst per Grow/Shrink ein, + // in AdjustFollow() stellen wir unseren FolgeFrame ein. + + const SwTwips nDocPrtTop = Frm().Top() + Prt().Top(); + const SwTwips nOldHeight = Prt().SSize().Height(); + const SwTwips nChg = rLine.CalcBottomLine() - nDocPrtTop - nOldHeight; + + // Vertical Formatting: + // The (rotated) repaint rectangle's x coordinate referes to the frame. + // If the frame grows (or shirks) the repaint rectangle cannot simply + // be rotated back after formatting, because we use the upper left point + // of the frame for rotation. This point changes when growing/shrinking. + + //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin + if ( IsVertical() && !IsVertLR() && nChg ) + { + SwRect &rRepaint = *(pPara->GetRepaint()); + rRepaint.Left( rRepaint.Left() - nChg ); + rRepaint.Width( rRepaint.Width() - nChg ); + } + + AdjustFrm( nChg, bHasToFit ); + + if( HasFollow() || IsInFtn() ) + _AdjustFollow( rLine, nEnd, nStrLen, nNew ); + + pPara->SetPrepMustFit( sal_False ); + + UNDO_SWAP( this ) +} + +/************************************************************************* + * SwTxtFrm::FormatLine() + *************************************************************************/ + +// bPrev zeigt an, ob Reformat.Start() wegen Prev() vorgezogen wurde. +// Man weiss sonst nicht, ob man Repaint weiter einschraenken kann oder nicht. + + +sal_Bool SwTxtFrm::FormatLine( SwTxtFormatter &rLine, const sal_Bool bPrev ) +{ + OSL_ENSURE( ! IsVertical() || IsSwapped(), + "SwTxtFrm::FormatLine( rLine, bPrev) with unswapped frame" ); + SwParaPortion *pPara = rLine.GetInfo().GetParaPortion(); + const SwLineLayout *pOldCur = rLine.GetCurr(); + const xub_StrLen nOldLen = pOldCur->GetLen(); + const KSHORT nOldAscent = pOldCur->GetAscent(); + const KSHORT nOldHeight = pOldCur->Height(); + const SwTwips nOldWidth = pOldCur->Width() + pOldCur->GetHangingMargin(); + const sal_Bool bOldHyph = pOldCur->IsEndHyph(); + SwTwips nOldTop = 0; + SwTwips nOldBottom = 0; + if( rLine.GetCurr()->IsClipping() ) + rLine.CalcUnclipped( nOldTop, nOldBottom ); + + const xub_StrLen nNewStart = rLine.FormatLine( rLine.GetStart() ); + + OSL_ENSURE( Frm().Pos().Y() + Prt().Pos().Y() == rLine.GetFirstPos(), + "SwTxtFrm::FormatLine: frame leaves orbit." ); + OSL_ENSURE( rLine.GetCurr()->Height(), + "SwTxtFrm::FormatLine: line height is zero" ); + + // Das aktuelle Zeilenumbruchobjekt. + const SwLineLayout *pNew = rLine.GetCurr(); + + sal_Bool bUnChg = nOldLen == pNew->GetLen() && + bOldHyph == pNew->IsEndHyph(); + if ( bUnChg && !bPrev ) + { + const long nWidthDiff = nOldWidth > pNew->Width() + ? nOldWidth - pNew->Width() + : pNew->Width() - nOldWidth; + + // we only declare a line as unchanged, if its main values have not + // changed and it is not the last line (!paragraph end symbol!) + bUnChg = nOldHeight == pNew->Height() && + nOldAscent == pNew->GetAscent() && + nWidthDiff <= SLOPPY_TWIPS && + pOldCur->GetNext(); + } + + // rRepaint wird berechnet: + const SwTwips nBottom = rLine.Y() + rLine.GetLineHeight(); + SwRepaint &rRepaint = *(pPara->GetRepaint()); + if( bUnChg && rRepaint.Top() == rLine.Y() + && (bPrev || nNewStart <= pPara->GetReformat()->Start()) + && ( nNewStart < GetTxtNode()->GetTxt().Len() ) ) + { + rRepaint.Top( nBottom ); + rRepaint.Height( 0 ); + } + else + { + if( nOldTop ) + { + if( nOldTop < rRepaint.Top() ) + rRepaint.Top( nOldTop ); + if( !rLine.IsUnclipped() || nOldBottom > rRepaint.Bottom() ) + { + rRepaint.Bottom( nOldBottom - 1 ); + rLine.SetUnclipped( sal_True ); + } + } + if( rLine.GetCurr()->IsClipping() && rLine.IsFlyInCntBase() ) + { + SwTwips nTmpTop, nTmpBottom; + rLine.CalcUnclipped( nTmpTop, nTmpBottom ); + if( nTmpTop < rRepaint.Top() ) + rRepaint.Top( nTmpTop ); + if( !rLine.IsUnclipped() || nTmpBottom > rRepaint.Bottom() ) + { + rRepaint.Bottom( nTmpBottom - 1 ); + rLine.SetUnclipped( sal_True ); + } + } + else + { + if( !rLine.IsUnclipped() || nBottom > rRepaint.Bottom() ) + { + rRepaint.Bottom( nBottom - 1 ); + rLine.SetUnclipped( sal_False ); + } + } + SwTwips nRght = Max( nOldWidth, pNew->Width() + + pNew->GetHangingMargin() ); + ViewShell *pSh = getRootFrm()->GetCurrShell(); + const SwViewOption *pOpt = pSh ? pSh->GetViewOptions() : 0; + if( pOpt && (pOpt->IsParagraph() || pOpt->IsLineBreak()) ) + nRght += ( Max( nOldAscent, pNew->GetAscent() ) ); + else + nRght += ( Max( nOldAscent, pNew->GetAscent() ) / 4); + nRght += rLine.GetLeftMargin(); + if( rRepaint.GetOfst() || rRepaint.GetRightOfst() < nRght ) + rRepaint.SetRightOfst( nRght ); + + // Finally we enlarge the repaint rectangle if we found an underscore + // within our line. 40 Twips should be enough + const sal_Bool bHasUnderscore = + ( rLine.GetInfo().GetUnderScorePos() < nNewStart ); + if ( bHasUnderscore || rLine.GetCurr()->HasUnderscore() ) + rRepaint.Bottom( rRepaint.Bottom() + 40 ); + + ((SwLineLayout*)rLine.GetCurr())->SetUnderscore( bHasUnderscore ); + } + if( !bUnChg ) + rLine.SetChanges(); + + // Die gute, alte nDelta-Berechnung: + *(pPara->GetDelta()) -= long(pNew->GetLen()) - long(nOldLen); + + // Stop! + if( rLine.IsStop() ) + return sal_False; + + // Unbedingt noch eine Zeile + if( rLine.IsNewLine() ) + return sal_True; + + // bis zum Ende des Strings ? + if( nNewStart >= GetTxtNode()->GetTxt().Len() ) + return sal_False; + + if( rLine.GetInfo().IsShift() ) + return sal_True; + + // Ende des Reformats erreicht ? + const xub_StrLen nEnd = pPara->GetReformat()->Start() + + pPara->GetReformat()->Len(); + + if( nNewStart <= nEnd ) + return sal_True; + + return 0 != *(pPara->GetDelta()); +} + +/************************************************************************* + * SwTxtFrm::_Format() + *************************************************************************/ + +void SwTxtFrm::_Format( SwTxtFormatter &rLine, SwTxtFormatInfo &rInf, + const sal_Bool bAdjust ) +{ + OSL_ENSURE( ! IsVertical() || IsSwapped(),"SwTxtFrm::_Format with unswapped frame" ); + + SwParaPortion *pPara = rLine.GetInfo().GetParaPortion(); + rLine.SetUnclipped( sal_False ); + + // Das war dem C30 zu kompliziert: aString( GetTxt() ); + const XubString &rString = GetTxtNode()->GetTxt(); + const xub_StrLen nStrLen = rString.Len(); + + SwCharRange &rReformat = *(pPara->GetReformat()); + SwRepaint &rRepaint = *(pPara->GetRepaint()); + SwRepaint *pFreeze = NULL; + + // Aus Performancegruenden wird in Init() rReformat auf STRING_LEN gesetzt. + // Fuer diesen Fall wird rReformat angepasst. + if( rReformat.Len() > nStrLen ) + rReformat.Len() = nStrLen; + + // Optimiert: + xub_StrLen nEnd = rReformat.Start() + rReformat.Len(); + if( nEnd > nStrLen ) + { + rReformat.Len() = nStrLen - rReformat.Start(); + nEnd = nStrLen; + } + + SwTwips nOldBottom; + if( GetOfst() && !IsFollow() ) + { + rLine.Bottom(); + nOldBottom = rLine.Y(); + rLine.Top(); + } + else + nOldBottom = 0; + rLine.CharToLine( rReformat.Start() ); + + // Worte koennen durch Fortfall oder Einfuegen eines Space + // auf die Zeile vor der editierten hinausgezogen werden, + // deshalb muss diese ebenfalls formatiert werden. + // Optimierung: Wenn rReformat erst hinter dem ersten Wort der + // Zeile beginnt, so kann diese Zeile die vorige nicht mehr beeinflussen. + // AMA: Leider doch, Textgroessenaenderungen + FlyFrames, die Rueckwirkung + // kann im Extremfall mehrere Zeilen (Frames!!!) betreffen! + + // --> FME 2005-04-18 #i46560# + // FME: Yes, consider this case: (word ) has to go to the next line + // because ) is a forbidden character at the beginning of a line although + // (word would still fit on the previous line. Adding text right in front + // of ) would not trigger a reformatting of the previous line. Adding 1 + // to the result of FindBrk() does not solve the problem in all cases, + // nevertheless it should be sufficient. + // <-- + sal_Bool bPrev = rLine.GetPrev() && + ( FindBrk( rString, rLine.GetStart(), rReformat.Start() + 1 ) + // --> FME 2005-04-18 #i46560# + + 1 + // <-- + >= rReformat.Start() || + rLine.GetCurr()->IsRest() ); + if( bPrev ) + { + while( rLine.Prev() ) + if( rLine.GetCurr()->GetLen() && !rLine.GetCurr()->IsRest() ) + { + if( !rLine.GetStart() ) + rLine.Top(); // damit NumDone nicht durcheinander kommt + break; + } + xub_StrLen nNew = rLine.GetStart() + rLine.GetLength(); + if( nNew ) + { + --nNew; + if( CH_BREAK == rString.GetChar( nNew ) ) + { + ++nNew; + rLine.Next(); + bPrev = sal_False; + } + } + rReformat.Len() += rReformat.Start() - nNew; + rReformat.Start() = nNew; + } + + rRepaint.SetOfst( 0 ); + rRepaint.SetRightOfst( 0 ); + rRepaint.Chg( Frm().Pos() + Prt().Pos(), Prt().SSize() ); + if( pPara->IsMargin() ) + rRepaint.Width( rRepaint.Width() + pPara->GetHangingMargin() ); + rRepaint.Top( rLine.Y() ); + if( 0 >= rRepaint.Width() ) + rRepaint.Width(1); + WidowsAndOrphans aFrmBreak( this, rInf.IsTest() ? 1 : 0 ); + + // rLine steht jetzt auf der ersten Zeile, die formatiert werden + // muss. Das Flag bFirst sorgt dafuer, dass nicht Next() gerufen wird. + // Das ganze sieht verdreht aus, aber es muss sichergestellt werden, + // dass bei IsBreakNow rLine auf der Zeile zum stehen kommt, die + // nicht mehr passt. + sal_Bool bFirst = sal_True; + sal_Bool bFormat = sal_True; + + // 5383: Das CharToLine() kann uns auch in den roten Bereich fuehren. + // In diesem Fall muessen wir zurueckwandern, bis die Zeile, die + // nicht mehr passt in rLine eingestellt ist. Ansonsten geht Textmasse + // verloren, weil der Ofst im Follow falsch eingestellt wird. + + // OD 2004-02-25 #i16128# - method renamed + sal_Bool bBreak = ( !pPara->IsPrepMustFit() || rLine.GetLineNr() > 1 ) + && aFrmBreak.IsBreakNowWidAndOrp( rLine ); + if( bBreak ) + { + sal_Bool bPrevDone = 0 != rLine.Prev(); + // OD 2004-02-25 #i16128# - method renamed + while( bPrevDone && aFrmBreak.IsBreakNowWidAndOrp(rLine) ) + bPrevDone = 0 != rLine.Prev(); + if( bPrevDone ) + { + aFrmBreak.SetKeep( sal_False ); + rLine.Next(); + } + rLine.TruncLines(); + + // auf Nummer sicher: + // OD 2004-02-25 #i16128# - method renamed + bBreak = aFrmBreak.IsBreakNowWidAndOrp(rLine) && + ( !pPara->IsPrepMustFit() || rLine.GetLineNr() > 1 ); + } + + /* Bedeutung der folgenden Flags: + Ist das Watch(End/Mid)Hyph-Flag gesetzt, so muss formatiert werden, wenn + eine Trennung am (Zeilenende/Fly) vorliegt, sofern MaxHyph erreicht ist. + Das Jump(End/Mid)Flag bedeutet, dass die naechste Zeile, bei der keine + Trennung (Zeilenende/Fly) vorliegt, formatiert werden muss, da jetzt + umgebrochen werden koennte, was vorher moeglicherweise durch MaxHyph + verboten war. + Watch(End/Mid)Hyph wird gesetzt, wenn die letzte formatierte Zeile eine + Trennstelle erhalten hat, vorher aber keine hatte, + Jump(End/Mid)Hyph, wenn eine Trennstelle verschwindet. + */ + sal_Bool bJumpEndHyph = sal_False, + bWatchEndHyph = sal_False, + bJumpMidHyph = sal_False, + bWatchMidHyph = sal_False; + + const SwAttrSet& rAttrSet = GetTxtNode()->GetSwAttrSet(); + sal_Bool bMaxHyph = ( 0 != + ( rInf.MaxHyph() = rAttrSet.GetHyphenZone().GetMaxHyphens() ) ); + if ( bMaxHyph ) + rLine.InitCntHyph(); + + if( IsFollow() && IsFieldFollow() && rLine.GetStart() == GetOfst() ) + { + const SwLineLayout* pLine; + { + SwTxtFrm *pMaster = FindMaster(); + OSL_ENSURE( pMaster, "SwTxtFrm::Format: homeless follow" ); + if( !pMaster->HasPara() ) + pMaster->GetFormatted(); + SwTxtSizeInfo aInf( pMaster ); + SwTxtIter aMasterLine( pMaster, &aInf ); + aMasterLine.Bottom(); + pLine = aMasterLine.GetCurr(); + } + SwLinePortion* pRest = + rLine.MakeRestPortion( pLine, GetOfst() ); + if( pRest ) + rInf.SetRest( pRest ); + else + SetFieldFollow( sal_False ); + } + + /* Zum Abbruchkriterium: + * Um zu erkennen, dass eine Zeile nicht mehr auf die Seite passt, + * muss sie formatiert werden. Dieser Ueberhang wird z.B. in AdjustFollow + * wieder entfernt. + * Eine weitere Komplikation: wenn wir der Master sind, so muessen + * wir die Zeilen durchgehen, da es ja sein kann, dass eine Zeile + * vom Follow in den Master rutschen kann. + */ + do + { + if( bFirst ) + bFirst = sal_False; + else + { + if ( bMaxHyph ) + { + if ( rLine.GetCurr()->IsEndHyph() ) + rLine.CntEndHyph()++; + else + rLine.CntEndHyph() = 0; + if ( rLine.GetCurr()->IsMidHyph() ) + rLine.CntMidHyph()++; + else + rLine.CntMidHyph() = 0; + } + if( !rLine.Next() ) + { + if( !bFormat ) + { + SwLinePortion* pRest = + rLine.MakeRestPortion( rLine.GetCurr(), rLine.GetEnd() ); + if( pRest ) + rInf.SetRest( pRest ); + } + rLine.Insert( new SwLineLayout() ); + rLine.Next(); + bFormat = sal_True; + } + } + if ( !bFormat && bMaxHyph && + (bWatchEndHyph || bJumpEndHyph || bWatchMidHyph || bJumpMidHyph) ) + { + if ( rLine.GetCurr()->IsEndHyph() ) + { + if ( bWatchEndHyph ) + bFormat = ( rLine.CntEndHyph() == rInf.MaxHyph() ); + } + else + { + bFormat = bJumpEndHyph; + bWatchEndHyph = sal_False; + bJumpEndHyph = sal_False; + } + if ( rLine.GetCurr()->IsMidHyph() ) + { + if ( bWatchMidHyph && !bFormat ) + bFormat = ( rLine.CntEndHyph() == rInf.MaxHyph() ); + } + else + { + bFormat = bFormat || bJumpMidHyph; + bWatchMidHyph = sal_False; + bJumpMidHyph = sal_False; + } + } + if( bFormat ) + { + sal_Bool bOldEndHyph = rLine.GetCurr()->IsEndHyph(); + sal_Bool bOldMidHyph = rLine.GetCurr()->IsMidHyph(); + bFormat = FormatLine( rLine, bPrev ); + //9334: Es kann nur ein bPrev geben... (???) + bPrev = sal_False; + if ( bMaxHyph ) + { + if ( rLine.GetCurr()->IsEndHyph() != bOldEndHyph ) + { + bWatchEndHyph = !bOldEndHyph; + bJumpEndHyph = bOldEndHyph; + } + if ( rLine.GetCurr()->IsMidHyph() != bOldMidHyph ) + { + bWatchMidHyph = !bOldMidHyph; + bJumpMidHyph = bOldMidHyph; + } + } + } + + if( !rInf.IsNewLine() ) + { + if( !bFormat ) + bFormat = 0 != rInf.GetRest(); + if( rInf.IsStop() || rInf.GetIdx() >= nStrLen ) + break; + if( !bFormat && ( !bMaxHyph || ( !bWatchEndHyph && + !bJumpEndHyph && !bWatchMidHyph && !bJumpMidHyph ) ) ) + { + if( GetFollow() ) + { + while( rLine.Next() ) + ; //Nothing + pFreeze = new SwRepaint( rRepaint ); // to minimize painting + } + else + break; + } + } + // OD 2004-02-25 #i16128# - method renamed + bBreak = aFrmBreak.IsBreakNowWidAndOrp(rLine); + }while( !bBreak ); + + if( pFreeze ) + { + rRepaint = *pFreeze; + delete pFreeze; + } + + if( !rLine.IsStop() ) + { + // Wurde aller Text formatiert und gibt es noch weitere + // Zeilenobjekte, dann sind diese jetzt ueberfluessig, + // weil der Text kuerzer geworden ist. + if( rLine.GetStart() + rLine.GetLength() >= nStrLen && + rLine.GetCurr()->GetNext() ) + { + rLine.TruncLines(); + rLine.SetTruncLines( sal_True ); + } + } + + if( !rInf.IsTest() ) + { + // Bei OnceMore lohnt sich kein FormatAdjust + if( bAdjust || !rLine.GetDropFmt() || !rLine.CalcOnceMore() ) + { + FormatAdjust( rLine, aFrmBreak, nStrLen, rInf.IsStop() ); + } + if( rRepaint.HasArea() ) + SetRepaint(); + rLine.SetTruncLines( sal_False ); + if( nOldBottom ) // Bei "gescollten" Absaetzen wird + { // noch ueberprueft, ob durch Schrumpfen + rLine.Bottom(); // das Scrolling ueberfluessig wurde. + SwTwips nNewBottom = rLine.Y(); + if( nNewBottom < nOldBottom ) + _SetOfst( 0 ); + } + } +} + +/************************************************************************* + * SwTxtFrm::Format() + *************************************************************************/ + +void SwTxtFrm::FormatOnceMore( SwTxtFormatter &rLine, SwTxtFormatInfo &rInf ) +{ + OSL_ENSURE( ! IsVertical() || IsSwapped(), + "A frame is not swapped in SwTxtFrm::FormatOnceMore" ); + + SwParaPortion *pPara = rLine.GetInfo().GetParaPortion(); + if( !pPara ) + return; + + // ggf gegen pPara + KSHORT nOld = ((const SwTxtMargin&)rLine).GetDropHeight(); + sal_Bool bShrink = sal_False, + bGrow = sal_False, + bGoOn = rLine.IsOnceMore(); + sal_uInt8 nGo = 0; + while( bGoOn ) + { + ++nGo; + rInf.Init(); + rLine.Top(); + if( !rLine.GetDropFmt() ) + rLine.SetOnceMore( sal_False ); + SwCharRange aRange( 0, rInf.GetTxt().Len() ); + *(pPara->GetReformat()) = aRange; + _Format( rLine, rInf ); + + bGoOn = rLine.IsOnceMore(); + if( bGoOn ) + { + const KSHORT nNew = ((const SwTxtMargin&)rLine).GetDropHeight(); + if( nOld == nNew ) + bGoOn = sal_False; + else + { + if( nOld > nNew ) + bShrink = sal_True; + else + bGrow = sal_True; + + if( bShrink == bGrow || 5 < nGo ) + bGoOn = sal_False; + + nOld = nNew; + } + + // 6107: Wenn was schief ging, muss noch einmal formatiert werden. + if( !bGoOn ) + { + rInf.CtorInitTxtFormatInfo( this ); + rLine.CtorInitTxtFormatter( this, &rInf ); + rLine.SetDropLines( 1 ); + rLine.CalcDropHeight( 1 ); + SwCharRange aTmpRange( 0, rInf.GetTxt().Len() ); + *(pPara->GetReformat()) = aTmpRange; + _Format( rLine, rInf, sal_True ); + // 8047: Wir painten alles... + SetCompletePaint(); + } + } + } +} + +/************************************************************************* + * SwTxtFrm::_Format() + *************************************************************************/ + + +void SwTxtFrm::_Format( SwParaPortion *pPara ) +{ + const xub_StrLen nStrLen = GetTxt().Len(); + + if ( !nStrLen ) + { + // Leere Zeilen werden nicht lange gequaelt: + // pPara wird blank geputzt + // entspricht *pPara = SwParaPortion; + sal_Bool bMustFit = pPara->IsPrepMustFit(); + pPara->Truncate(); + pPara->FormatReset(); + if( pBlink && pPara->IsBlinking() ) + pBlink->Delete( pPara ); + + // delete pSpaceAdd und pKanaComp + pPara->FinishSpaceAdd(); + pPara->FinishKanaComp(); + pPara->ResetFlags(); + pPara->SetPrepMustFit( bMustFit ); + } + + OSL_ENSURE( ! IsSwapped(), "A frame is swapped before _Format" ); + + if ( IsVertical() ) + SwapWidthAndHeight(); + + SwTxtFormatInfo aInf( this ); + SwTxtFormatter aLine( this, &aInf ); + + // OD 2004-01-15 #110582# + HideAndShowObjects(); + + _Format( aLine, aInf ); + + if( aLine.IsOnceMore() ) + FormatOnceMore( aLine, aInf ); + + if ( IsVertical() ) + SwapWidthAndHeight(); + + OSL_ENSURE( ! IsSwapped(), "A frame is swapped after _Format" ); + + if( 1 < aLine.GetDropLines() ) + { + if( SVX_ADJUST_LEFT != aLine.GetAdjust() && + SVX_ADJUST_BLOCK != aLine.GetAdjust() ) + { + aLine.CalcDropAdjust(); + aLine.SetPaintDrop( sal_True ); + } + + if( aLine.IsPaintDrop() ) + { + aLine.CalcDropRepaint(); + aLine.SetPaintDrop( sal_False ); + } + } +} + +/************************************************************************* + * SwTxtFrm::Format() + *************************************************************************/ + +/* + * Format berechnet die Groesse des Textframes und ruft, wenn + * diese feststeht, Shrink() oder Grow(), um die Framegroesse dem + * evtl. veraenderten Platzbedarf anzupassen. + */ + +void SwTxtFrm::Format( const SwBorderAttrs * ) +{ +#if OSL_DEBUG_LEVEL > 1 + const XubString aXXX = GetTxtNode()->GetTxt(); + const SwTwips nDbgY = Frm().Top(); + (void)nDbgY; + const SwPageFrm *pDbgPage = FindPageFrm(); + const MSHORT nDbgPageNr = pDbgPage->GetPhyPageNum(); + (void)nDbgPageNr; + // Um zu gucken, ob es einen Ftn-Bereich gibt. + const SwFrm *pDbgFtnCont = (const SwFrm*)(FindPageFrm()->FindFtnCont()); + (void)pDbgFtnCont; + + // nStopAt laesst sich vom CV bearbeiten. + static MSHORT nStopAt = 0; + if( nStopAt == GetFrmId() ) + { + int i = GetFrmId(); + (void)i; + } +#endif + + SWRECTFN( this ) + + CalcAdditionalFirstLineOffset(); + + // Vom Berichtsautopiloten oder ueber die BASIC-Schnittstelle kommen + // gelegentlich TxtFrms mit einer Breite <=0. + if( (Prt().*fnRect->fnGetWidth)() <= 0 ) + { + // Wenn MustFit gesetzt ist, schrumpfen wir ggf. auf die Unterkante + // des Uppers, ansonsten nehmen wir einfach eine Standardgroesse + // von 12 Pt. ein (240 Twip). + SwTxtLineAccess aAccess( this ); + long nFrmHeight = (Frm().*fnRect->fnGetHeight)(); + if( aAccess.GetPara()->IsPrepMustFit() ) + { + const SwTwips nLimit = (GetUpper()->*fnRect->fnGetPrtBottom)(); + const SwTwips nDiff = - (Frm().*fnRect->fnBottomDist)( nLimit ); + if( nDiff > 0 ) + Shrink( nDiff ); + } + else if( 240 < nFrmHeight ) + Shrink( nFrmHeight - 240 ); + else if( 240 > nFrmHeight ) + Grow( 240 - nFrmHeight ); + nFrmHeight = (Frm().*fnRect->fnGetHeight)(); + + long nTop = (this->*fnRect->fnGetTopMargin)(); + if( nTop > nFrmHeight ) + (this->*fnRect->fnSetYMargins)( nFrmHeight, 0 ); + else if( (Prt().*fnRect->fnGetHeight)() < 0 ) + (Prt().*fnRect->fnSetHeight)( 0 ); + return; + } + + const xub_StrLen nStrLen = GetTxtNode()->GetTxt().Len(); + if ( nStrLen || !FormatEmpty() ) + { + + SetEmpty( sal_False ); + // Um nicht durch verschachtelte Formats irritiert zu werden. + FormatLevel aLevel; + if( 12 == aLevel.GetLevel() ) + return; + + // Die Formatinformationen duerfen u.U. nicht veraendert werden. + if( IsLocked() ) + return; + + // 8708: Vorsicht, das Format() kann auch durch GetFormatted() + // angestossen werden. + if( IsHiddenNow() ) + { + long nPrtHeight = (Prt().*fnRect->fnGetHeight)(); + if( nPrtHeight ) + { + HideHidden(); + Shrink( nPrtHeight ); + } + else + { + // OD 2004-01-20 #110582# - assure that objects anchored + // at paragraph resp. at/as character inside paragraph + // are hidden. + HideAndShowObjects(); + } + ChgThisLines(); + return; + } + + // Waehrend wir formatieren, wollen wir nicht gestoert werden. + SwTxtFrmLocker aLock(this); + SwTxtLineAccess aAccess( this ); + const sal_Bool bNew = !aAccess.SwTxtLineAccess::IsAvailable(); + const sal_Bool bSetOfst = ( GetOfst() && GetOfst() > GetTxtNode()->GetTxt().Len() ); + + if( CalcPreps() ) + ; // nothing + // Wir returnen, wenn schon formatiert wurde, nicht aber, wenn + // der TxtFrm gerade erzeugt wurde und ueberhaupt keine Format- + // informationen vorliegen. + else if( !bNew && !aAccess.GetPara()->GetReformat()->Len() ) + { + if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() ) + { + aAccess.GetPara()->SetPrepAdjust( sal_True ); + aAccess.GetPara()->SetPrep( sal_True ); + CalcPreps(); + } + SetWidow( sal_False ); + } + else if( bSetOfst && IsFollow() ) + { + SwTxtFrm *pMaster = FindMaster(); + OSL_ENSURE( pMaster, "SwTxtFrm::Format: homeless follow" ); + if( pMaster ) + pMaster->Prepare( PREP_FOLLOW_FOLLOWS ); + SwTwips nMaxY = (GetUpper()->*fnRect->fnGetPrtBottom)(); + if( (Frm().*fnRect->fnOverStep)( nMaxY ) ) + (this->*fnRect->fnSetLimit)( nMaxY ); + else if( (Frm().*fnRect->fnBottomDist)( nMaxY ) < 0 ) + (Frm().*fnRect->fnAddBottom)( -(Frm().*fnRect->fnGetHeight)() ); + } + else + { + // bSetOfst here means that we have the "red arrow situation" + if ( bSetOfst ) + _SetOfst( 0 ); + + const sal_Bool bOrphan = IsWidow(); + const SwFtnBossFrm* pFtnBoss = HasFtn() ? FindFtnBossFrm() : 0; + SwTwips nFtnHeight = 0; + if( pFtnBoss ) + { + const SwFtnContFrm* pCont = pFtnBoss->FindFtnCont(); + nFtnHeight = pCont ? (pCont->Frm().*fnRect->fnGetHeight)() : 0; + } + do + { + _Format( aAccess.GetPara() ); + if( pFtnBoss && nFtnHeight ) + { + const SwFtnContFrm* pCont = pFtnBoss->FindFtnCont(); + SwTwips nNewHeight = pCont ? (pCont->Frm().*fnRect->fnGetHeight)() : 0; + // If we lost some footnotes, we may have more space + // for our main text, so we have to format again ... + if( nNewHeight < nFtnHeight ) + nFtnHeight = nNewHeight; + else + break; + } + else + break; + } while ( pFtnBoss ); + if( bOrphan ) + { + ValidateFrm(); + SetWidow( sal_False ); + } + } + if( IsEmptyMaster() ) + { + SwFrm* pPre = GetPrev(); + if( pPre && + // --> FME 2004-07-22 #i10826# It's the first, it cannot keep! + pPre->GetIndPrev() && + // <-- + pPre->GetAttrSet()->GetKeep().GetValue() ) + { + pPre->InvalidatePos(); + } + } + } + + ChgThisLines(); + + // the PrepMustFit should not survive a Format operation + SwParaPortion *pPara = GetPara(); + if ( pPara ) + pPara->SetPrepMustFit( sal_False ); + +#if OSL_DEBUG_LEVEL > 1 + // Hier ein Instrumentarium, um ungewoehnlichen Master/Follow-Kombinationen, + // insbesondere bei Fussnoten, auf die Schliche zu kommen + if( IsFollow() || GetFollow() ) + { + SwTxtFrm *pTmpFrm = IsFollow() ? FindMaster() : this; + const SwPageFrm *pTmpPage = pTmpFrm->FindPageFrm(); + MSHORT nPgNr = pTmpPage->GetPhyPageNum(); + MSHORT nLast; + MSHORT nDummy = 0; // nur zum Breakpoint setzen + while( pTmpFrm->GetFollow() ) + { + pTmpFrm = pTmpFrm->GetFollow(); + nLast = nPgNr; + pTmpPage = pTmpFrm->FindPageFrm(); + nPgNr = pTmpPage->GetPhyPageNum(); + if( nLast > nPgNr ) + ++nDummy; // schon fast eine Assertion wert + else if( nLast == nPgNr ) + ++nDummy; // bei Spalten voellig normal, aber sonst!? + else if( nLast < nPgNr - 1 ) + ++nDummy; // kann schon mal temporaer vorkommen + } + } +#endif + + CalcBaseOfstForFly(); + // OD 2004-03-17 #i11860# + _CalcHeightOfLastLine(); +} + +/************************************************************************* + * SwTxtFrm::FormatQuick() + * + * bForceQuickFormat is set if GetFormatted() has been called during the + * painting process. Actually I cannot imagine a situation which requires + * a full formatting of the paragraph during painting, on the other hand + * a full formatting can cause the invalidation of other layout frames, + * e.g., if there are footnotes in this paragraph, and invalid layout + * frames will not calculated during the painting. So I actually want to + * avoid a formatting during painting, but since I'm a coward, I'll only + * force the quick formatting in the situation of issue i29062. + *************************************************************************/ + +sal_Bool SwTxtFrm::FormatQuick( bool bForceQuickFormat ) +{ + OSL_ENSURE( ! IsVertical() || ! IsSwapped(), + "SwTxtFrm::FormatQuick with swapped frame" ); + +#if OSL_DEBUG_LEVEL > 1 + const XubString aXXX = GetTxtNode()->GetTxt(); + const SwTwips nDbgY = Frm().Top(); + (void)nDbgY; + // nStopAt laesst sich vom CV bearbeiten. + static MSHORT nStopAt = 0; + if( nStopAt == GetFrmId() ) + { + int i = GetFrmId(); + (void)i; + } +#endif + + if( IsEmpty() && FormatEmpty() ) + return sal_True; + + // Wir sind sehr waehlerisch: + if( HasPara() || IsWidow() || IsLocked() + || !GetValidSizeFlag() || + ( ( IsVertical() ? Prt().Width() : Prt().Height() ) && IsHiddenNow() ) ) + return sal_False; + + SwTxtLineAccess aAccess( this ); + SwParaPortion *pPara = aAccess.GetPara(); + if( !pPara ) + return sal_False; + + SwFrmSwapper aSwapper( this, sal_True ); + + SwTxtFrmLocker aLock(this); + SwTxtFormatInfo aInf( this, sal_False, sal_True ); + if( 0 != aInf.MaxHyph() ) // 27483: MaxHyphen beachten! + return sal_False; + + SwTxtFormatter aLine( this, &aInf ); + + // DropCaps sind zu kompliziert... + if( aLine.GetDropFmt() ) + return sal_False; + + xub_StrLen nStart = GetOfst(); + const xub_StrLen nEnd = GetFollow() + ? GetFollow()->GetOfst() : aInf.GetTxt().Len(); + do + { + nStart = aLine.FormatLine( nStart ); + if( aInf.IsNewLine() || (!aInf.IsStop() && nStart < nEnd) ) + aLine.Insert( new SwLineLayout() ); + } while( aLine.Next() ); + + // Last exit: die Hoehen muessen uebereinstimmen. + Point aTopLeft( Frm().Pos() ); + aTopLeft += Prt().Pos(); + const SwTwips nNewHeight = aLine.Y() + aLine.GetLineHeight(); + const SwTwips nOldHeight = aTopLeft.Y() + Prt().Height(); + + if( !bForceQuickFormat && nNewHeight != nOldHeight && !IsUndersized() ) + { + // Achtung: Durch FormatLevel==12 kann diese Situation auftreten, don't panic! + const xub_StrLen nStrt = GetOfst(); + _InvalidateRange( SwCharRange( nStrt, nEnd - nStrt) ); + return sal_False; + } + + if( pFollow && nStart != ((SwTxtFrm*)pFollow)->GetOfst() ) + return sal_False; // kann z.B. durch Orphans auftreten (35083,35081) + + // Geschafft, wir sind durch ... + + // Repaint setzen + pPara->GetRepaint()->Pos( aTopLeft ); + pPara->GetRepaint()->SSize( Prt().SSize() ); + + // Reformat loeschen + *(pPara->GetReformat()) = SwCharRange(); + *(pPara->GetDelta()) = 0; + + return sal_True; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |