1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: frmform.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <svx/keepitem.hxx>
37 #include <svx/hyznitem.hxx>
38 #include <pagefrm.hxx> // ChangeFtnRef
39 #include <ndtxt.hxx> // MakeFrm()
40 #include <dcontact.hxx> // SwDrawContact
41 #include <dflyobj.hxx> // SwVirtFlyDrawObj
43 #include <ftnfrm.hxx> // SwFtnFrm
47 #include <viewopt.hxx> // SwViewOptions
48 #include <viewsh.hxx> // ViewShell
51 #include <flyfrms.hxx>
52 #include <fmtanchr.hxx>
54 #include <itrform2.hxx> // SwTxtFormatter
55 #include <widorp.hxx> // Widows and Orphans
56 #include <txtcache.hxx>
57 #include <porrst.hxx> // SwEmptyPortion
58 #include <blink.hxx> // pBlink
59 #include <porfld.hxx> // SwFldPortion
60 #include <sectfrm.hxx> // SwSectionFrm
61 #include <pormulti.hxx> // SwMultiPortion
63 #include <rootfrm.hxx>
64 #include <frmfmt.hxx> // SwFrmFmt
65 // OD 2004-05-24 #i28701#
66 #include <sortedobjs.hxx>
72 inline FormatLevel() { ++nLevel
; }
73 inline ~FormatLevel() { --nLevel
; }
74 inline MSHORT
GetLevel() const { return nLevel
; }
75 static sal_Bool
LastLevel() { return 10 < nLevel
; }
77 MSHORT
FormatLevel::nLevel
= 0;
79 /*************************************************************************
81 *************************************************************************/
83 void ValidateTxt( SwFrm
*pFrm
) // Freund vom Frame
85 if ( ( ! pFrm
->IsVertical() &&
86 pFrm
->Frm().Width() == pFrm
->GetUpper()->Prt().Width() ) ||
88 pFrm
->Frm().Height() == pFrm
->GetUpper()->Prt().Height() )
89 pFrm
->bValidSize
= sal_True
;
91 pFrm->bValidPrtArea = sal_True;
92 //Die Position validieren um nicht unnoetige (Test-)Moves zu provozieren.
93 //Dabei darf allerdings nicht eine tatsaechlich falsche Coordinate
95 if ( !pFrm->bValidPos )
97 //Leider muessen wir dazu die korrekte Position berechnen.
98 Point aOld( pFrm->Frm().Pos() );
100 if ( aOld != pFrm->Pos() )
102 pFrm->Frm().Pos( aOld );
103 pFrm->bValidPos = sal_False;
109 void SwTxtFrm::ValidateFrm()
111 // Umgebung validieren, um Oszillationen zu verhindern.
112 SWAP_IF_SWAPPED( this )
114 if ( !IsInFly() && !IsInTab() )
115 { //Innerhalb eines Flys nur this validieren, der Rest sollte eigentlich
116 //nur fuer Fussnoten notwendig sein und die gibt es innerhalb von
117 //Flys nicht. Fix fuer 5544
118 SwSectionFrm
* pSct
= FindSctFrm();
121 if( !pSct
->IsColLocked() )
127 SwFrm
*pUp
= GetUpper();
134 //MA: mindestens das MustFit-Flag muessen wir retten!
135 ASSERT( HasPara(), "ResetPreps(), missing ParaPortion." );
136 SwParaPortion
*pPara
= GetPara();
137 const sal_Bool bMustFit
= pPara
->IsPrepMustFit();
139 pPara
->SetPrepMustFit( bMustFit
);
144 /*************************************************************************
146 *************************************************************************/
148 // nach einem RemoveFtn muss der BodyFrm und alle innenliegenden kalkuliert
149 // werden, damit die DeadLine richtig sitzt.
150 // Erst wird nach aussen hin gesucht, beim Rueckweg werden alle kalkuliert.
152 void _ValidateBodyFrm( SwFrm
*pFrm
)
154 if( pFrm
&& !pFrm
->IsCellFrm() )
156 if( !pFrm
->IsBodyFrm() && pFrm
->GetUpper() )
157 _ValidateBodyFrm( pFrm
->GetUpper() );
158 if( !pFrm
->IsSctFrm() )
162 sal_Bool bOld
= ((SwSectionFrm
*)pFrm
)->IsCntntLocked();
163 ((SwSectionFrm
*)pFrm
)->SetCntntLock( sal_True
);
166 ((SwSectionFrm
*)pFrm
)->SetCntntLock( sal_False
);
171 void SwTxtFrm::ValidateBodyFrm()
173 SWAP_IF_SWAPPED( this )
175 //siehe Kommtar in ValidateFrm()
176 if ( !IsInFly() && !IsInTab() &&
177 !( IsInSct() && FindSctFrm()->Lower()->IsColumnFrm() ) )
178 _ValidateBodyFrm( GetUpper() );
183 /*************************************************************************
184 * SwTxtFrm::FindBodyFrm()
185 *************************************************************************/
187 sal_Bool
SwTxtFrm::_GetDropRect( SwRect
&rRect
) const
189 SWAP_IF_NOT_SWAPPED( this )
191 ASSERT( HasPara(), "SwTxtFrm::_GetDropRect: try again next year." );
192 SwTxtSizeInfo
aInf( (SwTxtFrm
*)this );
193 SwTxtMargin
aLine( (SwTxtFrm
*)this, &aInf
);
194 if( aLine
.GetDropLines() )
196 rRect
.Top( aLine
.Y() );
197 rRect
.Left( aLine
.GetLineStart() );
198 rRect
.Height( aLine
.GetDropHeight() );
199 rRect
.Width( aLine
.GetDropLeft() );
201 if ( IsRightToLeft() )
202 SwitchLTRtoRTL( rRect
);
205 SwitchHorizontalToVertical( rRect
);
215 /*************************************************************************
216 * SwTxtFrm::FindBodyFrm()
217 *************************************************************************/
219 const SwBodyFrm
*SwTxtFrm::FindBodyFrm() const
223 const SwFrm
*pFrm
= GetUpper();
224 while( pFrm
&& !pFrm
->IsBodyFrm() )
225 pFrm
= pFrm
->GetUpper();
226 return (const SwBodyFrm
*)pFrm
;
231 /*************************************************************************
232 * SwTxtFrm::CalcFollow()
233 *************************************************************************/
235 sal_Bool
SwTxtFrm::CalcFollow( const xub_StrLen nTxtOfst
)
237 SWAP_IF_SWAPPED( this )
239 ASSERT( HasFollow(), "CalcFollow: missing Follow." );
241 SwTxtFrm
* pMyFollow
= GetFollow();
243 SwParaPortion
*pPara
= GetPara();
244 sal_Bool bFollowFld
= pPara
? pPara
->IsFollowField() : sal_False
;
246 if( !pMyFollow
->GetOfst() || pMyFollow
->GetOfst() != nTxtOfst
||
247 bFollowFld
|| pMyFollow
->IsFieldFollow() ||
248 ( pMyFollow
->IsVertical() && !pMyFollow
->Prt().Width() ) ||
249 ( ! pMyFollow
->IsVertical() && !pMyFollow
->Prt().Height() ) )
252 const SwFrm
*pOldUp
= GetUpper();
256 SwTwips nOldBottom
= (GetUpper()->Frm().*fnRect
->fnGetBottom
)();
257 SwTwips nMyPos
= (Frm().*fnRect
->fnGetTop
)();
259 const SwPageFrm
*pPage
= 0;
260 sal_Bool bOldInvaCntnt
= sal_True
;
261 if ( !IsInFly() && GetNext() )
263 pPage
= FindPageFrm();
264 //Minimieren - sprich ggf. zuruecksetzen - der Invalidierungen s.u.
265 bOldInvaCntnt
= pPage
->IsInvalidCntnt();
268 pMyFollow
->_SetOfst( nTxtOfst
);
269 pMyFollow
->SetFieldFollow( bFollowFld
);
270 if( HasFtn() || pMyFollow
->HasFtn() )
276 *(pPara
->GetReformat()) = SwCharRange();
277 *(pPara
->GetDelta()) = 0;
281 //Der Fussnotenbereich darf sich keinesfalls vergrossern.
282 SwSaveFtnHeight
aSave( FindFtnBossFrm( sal_True
), LONG_MAX
);
284 pMyFollow
->CalcFtnFlag();
285 if ( !pMyFollow
->GetNext() && !pMyFollow
->HasFtn() )
286 nOldBottom
= bVert
? 0 : LONG_MAX
;
290 if( !FormatLevel::LastLevel() )
292 // Weenn der Follow in einem spaltigen Bereich oder einem
293 // spaltigen Rahmen steckt, muss zunaechst dieser kalkuliert
294 // werden, da das FormatWidthCols() nicht funktioniert, wenn
295 // es aus dem MakeAll des _gelockten_ Follows heraus gerufen
297 SwSectionFrm
* pSct
= pMyFollow
->FindSctFrm();
298 if( pSct
&& !pSct
->IsAnLower( this ) )
300 if( pSct
->GetFollow() )
301 pSct
->SimpleFormat();
302 else if( ( pSct
->IsVertical() && !pSct
->Frm().Width() ) ||
303 ( ! pSct
->IsVertical() && !pSct
->Frm().Height() ) )
306 // OD 14.03.2003 #i11760# - intrinsic format of follow is controlled.
307 if ( FollowFormatAllowed() )
309 // OD 14.03.2003 #i11760# - no nested format of follows, if
310 // text frame is contained in a column frame.
311 // Thus, forbid intrinsic format of follow.
313 bool bIsFollowInColumn
= false;
314 SwFrm
* pFollowUpper
= pMyFollow
->GetUpper();
315 while ( pFollowUpper
)
317 if ( pFollowUpper
->IsColumnFrm() )
319 bIsFollowInColumn
= true;
322 if ( pFollowUpper
->IsPageFrm() ||
323 pFollowUpper
->IsFlyFrm() )
327 pFollowUpper
= pFollowUpper
->GetUpper();
329 if ( bIsFollowInColumn
)
331 pMyFollow
->ForbidFollowFormat();
336 // Der Follow merkt anhand seiner Frm().Height(), dass was schief
338 ASSERT( !pMyFollow
->GetPrev(), "SwTxtFrm::CalcFollow: cheesy follow" );
339 if( pMyFollow
->GetPrev() )
341 pMyFollow
->Prepare( PREP_CLEAR
);
343 ASSERT( !pMyFollow
->GetPrev(), "SwTxtFrm::CalcFollow: very cheesy follow" );
346 // OD 14.03.2003 #i11760# - reset control flag for follow format.
347 pMyFollow
->AllowFollowFormat();
350 //Sicherstellen, dass der Follow gepaintet wird.
351 pMyFollow
->SetCompletePaint();
355 //Solange der Follow wg. Orphans Zeilen angefordert, bekommt er
356 //diese und wird erneut formatiert, falls moeglich.
357 if( pPara
&& pPara
->IsPrepWidows() )
363 if( HasFtn() || pMyFollow
->HasFtn() )
369 *(pPara
->GetReformat()) = SwCharRange();
370 *(pPara
->GetDelta()) = 0;
376 if ( !bOldInvaCntnt
)
377 pPage
->ValidateCntnt();
381 ASSERT( pOldUp
== GetUpper(), "SwTxtFrm::CalcFollow: heavy follow" );
384 const long nRemaining
=
385 - (GetUpper()->Frm().*fnRect
->fnBottomDist
)( nOldBottom
);
386 if ( nRemaining
> 0 && !GetUpper()->IsSctFrm() &&
387 nRemaining
!= ( bVert
?
388 nMyPos
- Frm().Right() :
389 Frm().Top() - nMyPos
) )
401 /*************************************************************************
402 * SwTxtFrm::AdjustFrm()
403 *************************************************************************/
405 void SwTxtFrm::AdjustFrm( const SwTwips nChgHght
, sal_Bool bHasToFit
)
409 if( GetOfst() && !IsFollow() ) // ein gescrollter Absatz (undersized)
411 SetUndersized( nChgHght
== 0 || bHasToFit
);
414 // AdjustFrm is called with a swapped frame during
415 // formatting but the frame is not swapped during FormatEmpty
416 SWAP_IF_SWAPPED( this )
419 // Die Size-Variable des Frames wird durch Grow inkrementiert
420 // oder durch Shrink dekrementiert. Wenn die Groesse
421 // unveraendert ist, soll nichts passieren!
424 SwTwips nChgHeight
= nChgHght
;
425 if( nChgHght
&& !bHasToFit
)
427 if( IsInFtn() && !IsInSct() )
429 SwTwips nReal
= Grow( nChgHght
, sal_True
);
430 if( nReal
< nChgHght
)
432 SwTwips nBot
= (*fnRect
->fnYInc
)( (Frm().*fnRect
->fnGetBottom
)(),
434 SwFrm
* pCont
= FindFtnFrm()->GetUpper();
436 if( (pCont
->Frm().*fnRect
->fnBottomDist
)( nBot
) > 0 )
438 (Frm().*fnRect
->fnAddBottom
)( nChgHght
);
440 Prt().SSize().Width() += nChgHght
;
442 Prt().SSize().Height() += nChgHght
;
453 //MA 06. May. 93: Wenn einer der Upper ein Fly ist, so ist es
454 //sehr wahrscheinlich, dass dieser Fly durch das Grow seine
455 //Position veraendert - also muss auch meine Position korrigiert
456 //werden (sonst ist die Pruefung s.u. nicht aussagekraeftig).
457 //Die Vorgaenger muessen berechnet werden, damit die Position
458 //korrekt berechnet werden kann.
461 SwFrm
*pPre
= GetUpper()->Lower();
464 pPre
= pPre
->GetNext();
465 } while ( pPre
&& pPre
!= this );
467 const Point
aOldPos( Frm().Pos() );
469 if ( aOldPos
!= Frm().Pos() )
471 // OD 2004-07-01 #i28701# - use new method <SwFrm::InvalidateObjs(..)>
472 // No format is performed for the floating screen objects.
473 InvalidateObjs( true );
478 // Ein Grow() wird von der Layout-Seite immer akzeptiert,
479 // also auch, wenn die FixSize des umgebenden Layoutframes
480 // dies nicht zulassen sollte. Wir ueberpruefen diesen
481 // Fall und korrigieren die Werte.
482 // MA 06. May. 93: Der Frm darf allerdings auch im Notfall nicht
483 // weiter geschrumpft werden als es seine Groesse zulaesst.
487 ASSERT( ! IsSwapped(),"Swapped frame while calculating nRstHeight" );
488 nRstHeight
= Frm().Left() + Frm().Width() -
489 ( GetUpper()->Frm().Left() + GetUpper()->Prt().Left() );
492 nRstHeight
= GetUpper()->Frm().Top()
493 + GetUpper()->Prt().Top()
494 + GetUpper()->Prt().Height()
497 //In Tabellenzellen kann ich mir evtl. noch ein wenig dazuholen, weil
498 //durch eine vertikale Ausrichtung auch oben noch Raum sein kann.
499 // --> OD 2004-11-25 #115759# - assure, that first lower in upper
500 // is the current one or is valid.
502 ( GetUpper()->Lower() == this ||
503 GetUpper()->Lower()->IsValid() ) )
506 long nAdd
= (*fnRect
->fnYDiff
)( (GetUpper()->Lower()->Frm().*fnRect
->fnGetTop
)(),
507 (GetUpper()->*fnRect
->fnGetPrtTop
)() );
508 ASSERT( nAdd
>= 0, "Ey" );
512 /* ------------------------------------
513 * #50964#: nRstHeight < 0 bedeutet, dass der TxtFrm komplett ausserhalb seines
514 * Upper liegt. Dies kann passieren, wenn er innerhalb eines FlyAtCntFrm liegt, der
515 * durch das Grow() die Seite gewechselt hat. In so einem Fall ist es falsch, der
516 * folgenden Grow-Versuch durchzufuehren. Im Bugfall fuehrte dies sogar zur
518 * -----------------------------------*/
519 SwTwips nFrmHeight
= (Frm().*fnRect
->fnGetHeight
)();
520 SwTwips nPrtHeight
= (Prt().*fnRect
->fnGetHeight
)();
522 if( nRstHeight
< nFrmHeight
)
524 //Kann sein, dass ich die richtige Grosse habe, der Upper aber zu
525 //klein ist und der Upper noch Platz schaffen kann.
526 if( ( nRstHeight
>= 0 || ( IsInFtn() && IsInSct() ) ) && !bHasToFit
)
527 nRstHeight
+= GetUpper()->Grow( nFrmHeight
- nRstHeight
);
528 // In spaltigen Bereichen wollen wir moeglichst nicht zu gross werden, damit
529 // nicht ueber GetNextSctLeaf weitere Bereiche angelegt werden. Stattdessen
530 // schrumpfen wir und notieren bUndersized, damit FormatWidthCols die richtige
531 // Spaltengroesse ermitteln kann.
532 if ( nRstHeight
< nFrmHeight
)
534 if( bHasToFit
|| !IsMoveable() ||
535 ( IsInSct() && !FindSctFrm()->MoveAllowed(this) ) )
537 SetUndersized( sal_True
);
538 Shrink( Min( ( nFrmHeight
- nRstHeight
), nPrtHeight
) );
541 SetUndersized( sal_False
);
544 else if( nChgHeight
)
546 if( nRstHeight
- nFrmHeight
< nChgHeight
)
547 nChgHeight
= nRstHeight
- nFrmHeight
;
558 /*************************************************************************
559 * SwTxtFrm::AdjustFollow()
560 *************************************************************************/
562 /* AdjustFollow erwartet folgende Situation:
563 * Der SwTxtIter steht am unteren Ende des Masters, der Offset wird
564 * im Follow eingestellt.
565 * nOffset haelt den Offset im Textstring, ab dem der Master abschliesst
566 * und der Follow beginnt. Wenn er 0 ist, wird der FolgeFrame geloescht.
569 void SwTxtFrm::_AdjustFollow( SwTxtFormatter
&rLine
,
570 const xub_StrLen nOffset
, const xub_StrLen nEnd
,
571 const sal_uInt8 nMode
)
573 SwFrmSwapper
aSwapper( this, sal_False
);
575 // Wir haben den Rest der Textmasse: alle Follows loeschen
576 // Sonderfall sind DummyPortions()
577 // - special cases are controlled by parameter <nMode>.
578 if( HasFollow() && !(nMode
& 1) && nOffset
== nEnd
)
582 if( ((SwTxtFrm
*)GetFollow())->IsLocked() )
584 ASSERT( sal_False
, "+SwTxtFrm::JoinFrm: Follow ist locked." );
593 // Tanz auf dem Vulkan: Wir formatieren eben schnell noch einmal
594 // die letzte Zeile fuer das QuoVadis-Geraffel. Selbstverstaendlich
595 // kann sich dadurch auch der Offset verschieben:
596 const xub_StrLen nNewOfst
= ( IsInFtn() && ( !GetIndNext() || HasFollow() ) ) ?
597 rLine
.FormatQuoVadis(nOffset
) : nOffset
;
601 // Wir klauen unseren Follows Textmasse, dabei kann es passieren,
602 // dass wir einige Follows Joinen muessen.
603 while( GetFollow() && GetFollow()->GetFollow() &&
604 nNewOfst
>= GetFollow()->GetFollow()->GetOfst() )
611 // Der Ofst hat sich verschoben.
614 #if OSL_DEBUG_LEVEL > 1
615 static sal_Bool bTest
= sal_False
;
616 if( !bTest
|| ( nMode
& 1 ) )
619 GetFollow()->ManipOfst( 0 );
621 if ( CalcFollow( nNewOfst
) ) // CalcFollow erst zum Schluss, dort erfolgt ein SetOfst
622 rLine
.SetOnceMore( sal_True
);
626 /*************************************************************************
627 * SwTxtFrm::JoinFrm()
628 *************************************************************************/
630 SwCntntFrm
*SwTxtFrm::JoinFrm()
632 ASSERT( GetFollow(), "+SwTxtFrm::JoinFrm: no follow" );
633 SwTxtFrm
*pFoll
= GetFollow();
635 SwTxtFrm
*pNxt
= pFoll
->GetFollow();
637 // Alle Fussnoten des zu zerstoerenden Follows werden auf uns
639 xub_StrLen nStart
= pFoll
->GetOfst();
640 if ( pFoll
->HasFtn() )
642 const SwpHints
*pHints
= pFoll
->GetTxtNode()->GetpSwpHints();
645 SwFtnBossFrm
*pFtnBoss
= 0;
646 SwFtnBossFrm
*pEndBoss
= 0;
647 for ( USHORT i
= 0; i
< pHints
->Count(); ++i
)
649 const SwTxtAttr
*pHt
= (*pHints
)[i
];
650 if( RES_TXTATR_FTN
==pHt
->Which() && *pHt
->GetStart()>=nStart
)
652 if( pHt
->GetFtn().IsEndNote() )
655 pEndBoss
= pFoll
->FindFtnBossFrm();
656 pEndBoss
->ChangeFtnRef( pFoll
, (SwTxtFtn
*)pHt
, this );
661 pFtnBoss
= pFoll
->FindFtnBossFrm( sal_True
);
662 pFtnBoss
->ChangeFtnRef( pFoll
, (SwTxtFtn
*)pHt
, this );
671 else if ( pFoll
->GetValidPrtAreaFlag() ||
672 pFoll
->GetValidSizeFlag() )
674 pFoll
->CalcFtnFlag();
675 ASSERT( !pFoll
->HasFtn(), "Missing FtnFlag." );
679 pFoll
->MoveFlyInCnt( this, nStart
, STRING_LEN
);
680 pFoll
->SetFtn( FALSE
);
681 // --> OD 2005-12-01 #i27138#
682 // notify accessibility paragraphs objects about changed CONTENT_FLOWS_FROM/_TO relation.
683 // Relation CONTENT_FLOWS_FROM for current next paragraph will change
684 // and relation CONTENT_FLOWS_TO for current previous paragraph, which
685 // is <this>, will change.
687 ViewShell
* pViewShell( pFoll
->GetShell() );
688 if ( pViewShell
&& pViewShell
->GetLayout() &&
689 pViewShell
->GetLayout()->IsAnyShellAccessible() )
691 pViewShell
->InvalidateAccessibleParaFlowRelation(
692 dynamic_cast<SwTxtFrm
*>(pFoll
->FindNextCnt( true )),
703 /*************************************************************************
704 * SwTxtFrm::SplitFrm()
705 *************************************************************************/
707 SwCntntFrm
*SwTxtFrm::SplitFrm( const xub_StrLen nTxtPos
)
709 SWAP_IF_SWAPPED( this )
711 // Durch das Paste wird ein Modify() an mich verschickt.
712 // Damit meine Daten nicht verschwinden, locke ich mich.
713 SwTxtFrmLocker
aLock( this );
714 SwTxtFrm
*pNew
= (SwTxtFrm
*)(GetTxtNode()->MakeFrm());
715 pNew
->bIsFollow
= sal_True
;
717 pNew
->SetFollow( GetFollow() );
720 pNew
->Paste( GetUpper(), GetNext() );
721 // --> OD 2005-12-01 #i27138#
722 // notify accessibility paragraphs objects about changed CONTENT_FLOWS_FROM/_TO relation.
723 // Relation CONTENT_FLOWS_FROM for current next paragraph will change
724 // and relation CONTENT_FLOWS_TO for current previous paragraph, which
725 // is <this>, will change.
727 ViewShell
* pViewShell( pNew
->GetShell() );
728 if ( pViewShell
&& pViewShell
->GetLayout() &&
729 pViewShell
->GetLayout()->IsAnyShellAccessible() )
731 pViewShell
->InvalidateAccessibleParaFlowRelation(
732 dynamic_cast<SwTxtFrm
*>(pNew
->FindNextCnt( true )),
738 // Wenn durch unsere Aktionen Fussnoten in pNew landen,
739 // so muessen sie umgemeldet werden.
742 const SwpHints
*pHints
= GetTxtNode()->GetpSwpHints();
745 SwFtnBossFrm
*pFtnBoss
= 0;
746 SwFtnBossFrm
*pEndBoss
= 0;
747 for ( USHORT i
= 0; i
< pHints
->Count(); ++i
)
749 const SwTxtAttr
*pHt
= (*pHints
)[i
];
750 if( RES_TXTATR_FTN
==pHt
->Which() && *pHt
->GetStart()>=nTxtPos
)
752 if( pHt
->GetFtn().IsEndNote() )
755 pEndBoss
= FindFtnBossFrm();
756 pEndBoss
->ChangeFtnRef( this, (SwTxtFtn
*)pHt
, pNew
);
761 pFtnBoss
= FindFtnBossFrm( sal_True
);
762 pFtnBoss
->ChangeFtnRef( this, (SwTxtFtn
*)pHt
, pNew
);
764 pNew
->SetFtn( sal_True
);
773 CalcFtnFlag( nTxtPos
-1 );
774 ASSERT( !HasFtn(), "Missing FtnFlag." );
778 MoveFlyInCnt( pNew
, nTxtPos
, STRING_LEN
);
780 // Kein SetOfst oder CalcFollow, weil gleich ohnehin ein AdjustFollow folgt.
782 pNew
->ManipOfst( nTxtPos
);
789 /*************************************************************************
790 * virtual SwTxtFrm::SetOfst()
791 *************************************************************************/
793 void SwTxtFrm::_SetOfst( const xub_StrLen nNewOfst
)
796 // Es gibt tatsaechlich einen Sonderfall, in dem ein SetOfst(0)
797 // zulaessig ist: bug 3496
798 ASSERT( nNewOfst
, "!SwTxtFrm::SetOfst: missing JoinFrm()." );
801 // Die Invalidierung unseres Follows ist nicht noetig.
802 // Wir sind ein Follow, werden gleich formatiert und
803 // rufen von dort aus das SetOfst() !
805 SwParaPortion
*pPara
= GetPara();
808 SwCharRange
&rReformat
= *(pPara
->GetReformat());
809 rReformat
.Start() = 0;
810 rReformat
.Len() = GetTxt().Len();
811 *(pPara
->GetDelta()) = rReformat
.Len();
816 /*************************************************************************
817 * SwTxtFrm::CalcPreps
818 *************************************************************************/
820 sal_Bool
SwTxtFrm::CalcPreps()
822 ASSERT( ! IsVertical() || ! IsSwapped(), "SwTxtFrm::CalcPreps with swapped frame" );
825 SwParaPortion
*pPara
= GetPara();
828 sal_Bool bPrep
= pPara
->IsPrep();
829 sal_Bool bPrepWidows
= pPara
->IsPrepWidows();
830 sal_Bool bPrepAdjust
= pPara
->IsPrepAdjust();
831 sal_Bool bPrepMustFit
= pPara
->IsPrepMustFit();
834 sal_Bool bRet
= sal_False
;
835 if( bPrep
&& !pPara
->GetReformat()->Len() )
837 // PREP_WIDOWS bedeutet, dass im Follow die Orphans-Regel
839 // Es kann in unguenstigen Faellen vorkommen, dass auch ein
840 // PrepAdjust vorliegt (3680)!
845 ASSERT( GetFollow(), "+SwTxtFrm::CalcPreps: no credits" );
849 // Wir muessen uns auf zwei Faelle einstellen:
850 // Wir konnten dem Follow noch ein paar Zeilen abgeben,
851 // -> dann muessen wir schrumpfen
852 // oder wir muessen auf die naechste Seite
853 // -> dann lassen wir unseren Frame zu gross werden.
855 SwTwips nChgHeight
= GetParHeight();
856 if( nChgHeight
>= (Prt().*fnRect
->fnGetHeight
)() )
860 GetFollow()->SetJustWidow( sal_True
);
861 GetFollow()->Prepare( PREP_CLEAR
);
865 Frm().Width( Frm().Width() + Frm().Left() );
866 Prt().Width( Prt().Width() + Frm().Left() );
868 SetWidow( sal_True
);
872 SwTwips nTmp
= LONG_MAX
- (Frm().Top()+10000);
873 SwTwips nDiff
= nTmp
- Frm().Height();
874 Frm().Height( nTmp
);
875 Prt().Height( Prt().Height() + nDiff
);
876 SetWidow( sal_True
);
881 ASSERT( nChgHeight
< (Prt().*fnRect
->fnGetHeight
)(),
882 "+SwTxtFrm::CalcPrep: wanna shrink" );
884 nChgHeight
= (Prt().*fnRect
->fnGetHeight
)() - nChgHeight
;
886 GetFollow()->SetJustWidow( sal_True
);
887 GetFollow()->Prepare( PREP_CLEAR
);
888 Shrink( nChgHeight
);
889 SwRect
&rRepaint
= *(pPara
->GetRepaint());
893 SwRect
aRepaint( Frm().Pos() + Prt().Pos(), Prt().SSize() );
894 SwitchVerticalToHorizontal( aRepaint
);
895 rRepaint
.Chg( aRepaint
.Pos(), aRepaint
.SSize() );
898 rRepaint
.Chg( Frm().Pos() + Prt().Pos(), Prt().SSize() );
900 // 6792: Rrand < LRand und Repaint
901 if( 0 >= rRepaint
.Width() )
907 else if ( bPrepAdjust
)
911 if( !CalcPrepFtnAdjust() )
915 SwTxtLineAccess
aAccess( this );
916 aAccess
.GetPara()->SetPrepMustFit( sal_True
);
922 SWAP_IF_NOT_SWAPPED( this )
924 SwTxtFormatInfo
aInf( this );
925 SwTxtFormatter
aLine( this, &aInf
);
927 WidowsAndOrphans
aFrmBreak( this );
928 // Egal was die Attribute meinen, bei MustFit wird
929 // der Absatz im Notfall trotzdem gesplittet...
932 aFrmBreak
.SetKeep( sal_False
);
933 aFrmBreak
.ClrOrphLines();
935 // Bevor wir FormatAdjust aufrufen muessen wir dafuer
936 // sorgen, dass die Zeilen, die unten raushaengen
937 // auch tatsaechlich abgeschnitten werden.
938 // OD 2004-02-25 #i16128# - method renamed
939 sal_Bool bBreak
= aFrmBreak
.IsBreakNowWidAndOrp( aLine
);
941 while( !bBreak
&& aLine
.Next() )
943 // OD 2004-02-25 #i16128# - method renamed
944 bBreak
= aFrmBreak
.IsBreakNowWidAndOrp( aLine
);
948 // Es gibt Komplikationen: wenn TruncLines gerufen wird,
949 // veraendern sich ploetzlich die Bedingungen in
950 // IsInside, so dass IsBreakNow andere Ergebnisse
951 // liefern kann. Aus diesem Grund wird rFrmBreak bekannt
952 // gegeben, dass da wo rLine steht, das Ende erreicht
953 // ist. Mal sehen, ob's klappt ...
955 aFrmBreak
.SetRstHeight( aLine
);
956 FormatAdjust( aLine
, aFrmBreak
, aInf
.GetTxt().Len(), aInf
.IsStop() );
962 FormatAdjust( aLine
, aFrmBreak
,
963 aInf
.GetTxt().Len(), aInf
.IsStop() );
965 else if ( !aFrmBreak
.IsKeepAlways() )
968 // Vor dem Master wird eine Zeile geloescht, der Follow
969 // koennte eine Zeile abgeben.
970 const SwCharRange
aFollowRg( GetFollow()->GetOfst(), 1 );
971 *(pPara
->GetReformat()) += aFollowRg
;
972 // Es soll weitergehen!
978 // Eine letzte Ueberpruefung, falls das FormatAdjust() nichts
979 // brachte, muessen wir amputieren.
982 const SwTwips nMust
= (GetUpper()->*fnRect
->fnGetPrtBottom
)();
983 const SwTwips nIs
= (Frm().*fnRect
->fnGetBottom
)();
985 if( bVert
&& nIs
< nMust
)
987 Shrink( nMust
- nIs
);
988 if( Prt().Width() < 0 )
990 SetUndersized( sal_True
);
992 else if ( ! bVert
&& nIs
> nMust
)
994 Shrink( nIs
- nMust
);
995 if( Prt().Height() < 0 )
997 SetUndersized( sal_True
);
1002 pPara
->SetPrepMustFit( bPrepMustFit
);
1007 /*************************************************************************
1008 * SwTxtFrm::FormatAdjust()
1009 *************************************************************************/
1011 // Hier werden die Fussnoten und "als Zeichen"-gebundenen Objekte umgehaengt
1012 #define CHG_OFFSET( pFrm, nNew )\
1014 if( pFrm->GetOfst() < nNew )\
1015 pFrm->MoveFlyInCnt( this, 0, nNew );\
1016 else if( pFrm->GetOfst() > nNew )\
1017 MoveFlyInCnt( pFrm, nNew, STRING_LEN );\
1020 void SwTxtFrm::FormatAdjust( SwTxtFormatter
&rLine
,
1021 WidowsAndOrphans
&rFrmBreak
,
1022 const xub_StrLen nStrLen
,
1023 const sal_Bool bDummy
)
1025 SWAP_IF_NOT_SWAPPED( this )
1027 SwParaPortion
*pPara
= rLine
.GetInfo().GetParaPortion();
1029 xub_StrLen nEnd
= rLine
.GetStart();
1031 sal_Bool bHasToFit
= pPara
->IsPrepMustFit();
1033 // Das StopFlag wird durch Fussnoten gesetzt,
1034 // die auf die naechste Seite wollen.
1035 // OD, FME 2004-03-03 - call base class method <SwTxtFrmBreak::IsBreakNow(..)>
1036 // instead of method <WidowsAndOrphans::IsBreakNow(..)> to get a break,
1037 // even if due to widow rule no enough lines exists.
1038 sal_uInt8 nNew
= ( !GetFollow() &&
1042 ? ( rLine
.GetLineNr() > 1 &&
1043 !rFrmBreak
.IsInside( rLine
) )
1044 : rFrmBreak
.IsBreakNow( rLine
) ) ) )
1049 const SwFrm
*pBodyFrm
= (const SwFrm
*)(FindBodyFrm());
1051 const long nBodyHeight
= pBodyFrm
? ( IsVertical() ?
1052 pBodyFrm
->Frm().Width() :
1053 pBodyFrm
->Frm().Height() ) : 0;
1055 // Wenn die aktuellen Werte berechnet wurden, anzeigen, dass
1056 // sie jetzt gueltig sind.
1057 *(pPara
->GetReformat()) = SwCharRange();
1058 sal_Bool bDelta
= *pPara
->GetDelta() != 0;
1059 *(pPara
->GetDelta()) = 0;
1061 if( rLine
.IsStop() )
1063 rLine
.TruncLines( sal_True
);
1067 // FindBreak schneidet die letzte Zeile ab.
1068 if( !rFrmBreak
.FindBreak( this, rLine
, bHasToFit
) )
1070 // Wenn wir bis zum Ende durchformatiert haben, wird nEnd auf das Ende
1071 // gesetzt. In AdjustFollow wird dadurch ggf. JoinFrm() ausgefuehrt.
1072 // Ansonsten ist nEnd das Ende der letzten Zeile im Master.
1073 xub_StrLen nOld
= nEnd
;
1074 nEnd
= rLine
.GetEnd();
1077 if( nNew
&& nOld
< nEnd
)
1078 RemoveFtn( nOld
, nEnd
- nOld
);
1079 CHG_OFFSET( GetFollow(), nEnd
)
1081 GetFollow()->ManipOfst( nEnd
);
1085 { // Wenn wir Zeilen abgeben, darf kein Join auf den Folows gerufen werden,
1086 // im Gegenteil, es muss ggf. sogar ein Follow erzeugt werden.
1087 // Dies muss auch geschehen, wenn die Textmasse komplett im Master
1088 // bleibt, denn es k???nnte ja ein harter Zeilenumbruch noch eine weitere
1089 // Zeile (ohne Textmassse) notwendig machen!
1090 nEnd
= rLine
.GetEnd();
1093 // OD 21.03.2003 #108121# - Another case for not joining the follow:
1094 // Text frame has no content, but a numbering. Then, do *not* join.
1095 // Example of this case: When an empty, but numbered paragraph
1096 // at the end of page is completely displaced by a fly frame.
1097 // Thus, the text frame introduced a follow by a
1098 // <SwTxtFrm::SplitFrm(..)> - see below. The follow then shows
1099 // the numbering and must stay.
1100 if ( GetFollow()->GetOfst() != nEnd
||
1101 GetFollow()->IsFieldFollow() ||
1102 ( nStrLen
== 0 && GetTxtNode()->GetNumRule())
1107 CHG_OFFSET( GetFollow(), nEnd
)
1108 GetFollow()->ManipOfst( nEnd
);
1112 // OD 21.03.2003 #108121# - Only split frame, if the frame contains
1113 // content or contains no content, but has a numbering.
1115 ( nStrLen
== 0 && GetTxtNode()->GetNumRule())
1122 // Wenn sich die Resthoehe geaendert hat, z.B. durch RemoveFtn()
1123 // dann muessen wir auffuellen, um Oszillationen zu vermeiden!
1124 if( bDummy
&& pBodyFrm
&&
1125 nBodyHeight
< ( IsVertical() ?
1126 pBodyFrm
->Frm().Width() :
1127 pBodyFrm
->Frm().Height() ) )
1128 rLine
.MakeDummyLine();
1131 // In AdjustFrm() stellen wir uns selbst per Grow/Shrink ein,
1132 // in AdjustFollow() stellen wir unseren FolgeFrame ein.
1134 const SwTwips nDocPrtTop
= Frm().Top() + Prt().Top();
1135 const SwTwips nOldHeight
= Prt().SSize().Height();
1136 const SwTwips nChg
= rLine
.CalcBottomLine() - nDocPrtTop
- nOldHeight
;
1138 // Vertical Formatting:
1139 // The (rotated) repaint rectangle's x coordinate referes to the frame.
1140 // If the frame grows (or shirks) the repaint rectangle cannot simply
1141 // be rotated back after formatting, because we use the upper left point
1142 // of the frame for rotation. This point changes when growing/shrinking.
1143 if ( IsVertical() && nChg
)
1145 SwRect
&rRepaint
= *(pPara
->GetRepaint());
1146 rRepaint
.Left( rRepaint
.Left() - nChg
);
1147 rRepaint
.Width( rRepaint
.Width() - nChg
);
1150 AdjustFrm( nChg
, bHasToFit
);
1153 // FME 16.07.2003 #i16930# - removed this code because it did not
1154 // work correctly. In SwCntntFrm::MakeAll, the frame did not move to the
1155 // next page, instead the print area was recalculated and
1156 // Prepare( PREP_POS_CHGD, (const void*)&bFormatted, FALSE ) invalidated
1157 // the other flags => loop
1159 // OD 04.04.2003 #108446# - handle special case:
1160 // If text frame contains no content and just has split, because of a
1161 // line stop, it has to move forward. To force this forward move without
1162 // unnecessary formatting of its footnotes and its follow, especially in
1163 // columned sections, adjust frame height to zero (0) and do not perform
1164 // the intrinsic format of the follow.
1165 // The formating method <SwCntntFrm::MakeAll()> will initiate the move forward.
1166 sal_Bool bForcedNoIntrinsicFollowCalc = sal_False;
1168 rLine.IsStop() && HasFollow() && nNew == 1
1171 AdjustFrm( -Frm().SSize().Height(), bHasToFit );
1172 Prt().Pos().Y() = 0;
1173 Prt().Height( Frm().Height() );
1174 if ( FollowFormatAllowed() )
1176 bForcedNoIntrinsicFollowCalc = sal_True;
1177 ForbidFollowFormat();
1182 AdjustFrm( nChg, bHasToFit );
1186 if( HasFollow() || IsInFtn() )
1187 _AdjustFollow( rLine
, nEnd
, nStrLen
, nNew
);
1189 // FME 16.07.2003 #i16930# - removed this code because it did not work
1191 // OD 04.04.2003 #108446# - allow intrinsic format of follow, if above
1192 // special case has forbit it.
1193 /* if ( bForcedNoIntrinsicFollowCalc )
1195 AllowFollowFormat();
1199 pPara
->SetPrepMustFit( sal_False
);
1204 /*************************************************************************
1205 * SwTxtFrm::FormatLine()
1206 *************************************************************************/
1208 // bPrev zeigt an, ob Reformat.Start() wegen Prev() vorgezogen wurde.
1209 // Man weiss sonst nicht, ob man Repaint weiter einschraenken kann oder nicht.
1212 sal_Bool
SwTxtFrm::FormatLine( SwTxtFormatter
&rLine
, const sal_Bool bPrev
)
1214 ASSERT( ! IsVertical() || IsSwapped(),
1215 "SwTxtFrm::FormatLine( rLine, bPrev) with unswapped frame" );
1216 SwParaPortion
*pPara
= rLine
.GetInfo().GetParaPortion();
1217 // Nach rLine.FormatLine() haelt nStart den neuen Wert,
1218 // waehrend in pOldStart der alte Offset gepflegt wird.
1219 // Ueber diesen Weg soll das nDelta ersetzt werden.
1220 // *pOldStart += rLine.GetCurr()->GetLen();
1221 const SwLineLayout
*pOldCur
= rLine
.GetCurr();
1222 const xub_StrLen nOldLen
= pOldCur
->GetLen();
1223 const KSHORT nOldAscent
= pOldCur
->GetAscent();
1224 const KSHORT nOldHeight
= pOldCur
->Height();
1225 const SwTwips nOldWidth
= pOldCur
->Width() + pOldCur
->GetHangingMargin();
1226 const sal_Bool bOldHyph
= pOldCur
->IsEndHyph();
1227 SwTwips nOldTop
= 0;
1228 SwTwips nOldBottom
= 0;
1229 if( rLine
.GetCurr()->IsClipping() )
1230 rLine
.CalcUnclipped( nOldTop
, nOldBottom
);
1232 const xub_StrLen nNewStart
= rLine
.FormatLine( rLine
.GetStart() );
1234 ASSERT( Frm().Pos().Y() + Prt().Pos().Y() == rLine
.GetFirstPos(),
1235 "SwTxtFrm::FormatLine: frame leaves orbit." );
1236 ASSERT( rLine
.GetCurr()->Height(),
1237 "SwTxtFrm::FormatLine: line height is zero" );
1239 // Das aktuelle Zeilenumbruchobjekt.
1240 const SwLineLayout
*pNew
= rLine
.GetCurr();
1242 sal_Bool bUnChg
= nOldLen
== pNew
->GetLen() &&
1243 bOldHyph
== pNew
->IsEndHyph();
1244 if ( bUnChg
&& !bPrev
)
1246 // 6672: Toleranz von SLOPPY_TWIPS (5 Twips); vgl. 6922
1247 const long nWidthDiff
= nOldWidth
> pNew
->Width()
1248 ? nOldWidth
- pNew
->Width()
1249 : pNew
->Width() - nOldWidth
;
1251 // we only declare a line as unchanged, if its main values have not
1252 // changed and it is not the last line (!paragraph end symbol!)
1253 bUnChg
= nOldHeight
== pNew
->Height() &&
1254 nOldAscent
== pNew
->GetAscent() &&
1255 nWidthDiff
<= SLOPPY_TWIPS
&&
1259 // rRepaint wird berechnet:
1260 const SwTwips nBottom
= rLine
.Y() + rLine
.GetLineHeight();
1261 SwRepaint
&rRepaint
= *(pPara
->GetRepaint());
1262 if( bUnChg
&& rRepaint
.Top() == rLine
.Y()
1263 && (bPrev
|| nNewStart
<= pPara
->GetReformat()->Start())
1264 && ( nNewStart
< GetTxtNode()->GetTxt().Len() ) )
1266 rRepaint
.Top( nBottom
);
1267 rRepaint
.Height( 0 );
1273 if( nOldTop
< rRepaint
.Top() )
1274 rRepaint
.Top( nOldTop
);
1275 if( !rLine
.IsUnclipped() || nOldBottom
> rRepaint
.Bottom() )
1277 rRepaint
.Bottom( nOldBottom
- 1 );
1278 rLine
.SetUnclipped( sal_True
);
1281 if( rLine
.GetCurr()->IsClipping() && rLine
.IsFlyInCntBase() )
1283 SwTwips nTmpTop
, nTmpBottom
;
1284 rLine
.CalcUnclipped( nTmpTop
, nTmpBottom
);
1285 if( nTmpTop
< rRepaint
.Top() )
1286 rRepaint
.Top( nTmpTop
);
1287 if( !rLine
.IsUnclipped() || nTmpBottom
> rRepaint
.Bottom() )
1289 rRepaint
.Bottom( nTmpBottom
- 1 );
1290 rLine
.SetUnclipped( sal_True
);
1295 if( !rLine
.IsUnclipped() || nBottom
> rRepaint
.Bottom() )
1297 rRepaint
.Bottom( nBottom
- 1 );
1298 rLine
.SetUnclipped( sal_False
);
1301 SwTwips nRght
= Max( nOldWidth
, pNew
->Width() +
1302 pNew
->GetHangingMargin() );
1303 ViewShell
*pSh
= GetShell();
1304 const SwViewOption
*pOpt
= pSh
? pSh
->GetViewOptions() : 0;
1305 if( pOpt
&& (pOpt
->IsParagraph() || pOpt
->IsLineBreak()) )
1306 nRght
+= ( Max( nOldAscent
, pNew
->GetAscent() ) );
1308 nRght
+= ( Max( nOldAscent
, pNew
->GetAscent() ) / 4);
1309 nRght
+= rLine
.GetLeftMargin();
1310 if( rRepaint
.GetOfst() || rRepaint
.GetRightOfst() < nRght
)
1311 rRepaint
.SetRightOfst( nRght
);
1313 // Finally we enlarge the repaint rectangle if we found an underscore
1314 // within our line. 40 Twips should be enough
1315 const sal_Bool bHasUnderscore
=
1316 ( rLine
.GetInfo().GetUnderScorePos() < nNewStart
);
1317 if ( bHasUnderscore
|| rLine
.GetCurr()->HasUnderscore() )
1318 rRepaint
.Bottom( rRepaint
.Bottom() + 40 );
1320 ((SwLineLayout
*)rLine
.GetCurr())->SetUnderscore( bHasUnderscore
);
1325 // Die gute, alte nDelta-Berechnung:
1326 *(pPara
->GetDelta()) -= long(pNew
->GetLen()) - long(nOldLen
);
1329 if( rLine
.IsStop() )
1332 // Unbedingt noch eine Zeile
1333 if( rLine
.IsNewLine() )
1336 // bis zum Ende des Strings ?
1337 if( nNewStart
>= GetTxtNode()->GetTxt().Len() )
1340 if( rLine
.GetInfo().IsShift() )
1343 // Ende des Reformats erreicht ?
1344 const xub_StrLen nEnd
= pPara
->GetReformat()->Start() +
1345 pPara
->GetReformat()->Len();
1347 if( nNewStart
<= nEnd
)
1350 return 0 != *(pPara
->GetDelta());
1353 /*************************************************************************
1354 * SwTxtFrm::_Format()
1355 *************************************************************************/
1357 void SwTxtFrm::_Format( SwTxtFormatter
&rLine
, SwTxtFormatInfo
&rInf
,
1358 const sal_Bool bAdjust
)
1360 ASSERT( ! IsVertical() || IsSwapped(),"SwTxtFrm::_Format with unswapped frame" );
1362 SwParaPortion
*pPara
= rLine
.GetInfo().GetParaPortion();
1363 rLine
.SetUnclipped( sal_False
);
1365 // Das war dem C30 zu kompliziert: aString( GetTxt() );
1366 const XubString
&rString
= GetTxtNode()->GetTxt();
1367 const xub_StrLen nStrLen
= rString
.Len();
1369 SwCharRange
&rReformat
= *(pPara
->GetReformat());
1370 SwRepaint
&rRepaint
= *(pPara
->GetRepaint());
1371 SwRepaint
*pFreeze
= NULL
;
1373 // Aus Performancegruenden wird in Init() rReformat auf STRING_LEN gesetzt.
1374 // Fuer diesen Fall wird rReformat angepasst.
1375 if( rReformat
.Len() > nStrLen
)
1376 rReformat
.Len() = nStrLen
;
1379 xub_StrLen nEnd
= rReformat
.Start() + rReformat
.Len();
1380 if( nEnd
> nStrLen
)
1382 rReformat
.Len() = nStrLen
- rReformat
.Start();
1387 if( GetOfst() && !IsFollow() )
1390 nOldBottom
= rLine
.Y();
1395 rLine
.CharToLine( rReformat
.Start() );
1397 // Worte koennen durch Fortfall oder Einfuegen eines Space
1398 // auf die Zeile vor der editierten hinausgezogen werden,
1399 // deshalb muss diese ebenfalls formatiert werden.
1400 // Optimierung: Wenn rReformat erst hinter dem ersten Wort der
1401 // Zeile beginnt, so kann diese Zeile die vorige nicht mehr beeinflussen.
1402 // AMA: Leider doch, Textgroessenaenderungen + FlyFrames, die Rueckwirkung
1403 // kann im Extremfall mehrere Zeilen (Frames!!!) betreffen!
1405 // --> FME 2005-04-18 #i46560#
1406 // FME: Yes, consider this case: (word ) has to go to the next line
1407 // because ) is a forbidden character at the beginning of a line although
1408 // (word would still fit on the previous line. Adding text right in front
1409 // of ) would not trigger a reformatting of the previous line. Adding 1
1410 // to the result of FindBrk() does not solve the problem in all cases,
1411 // nevertheless it should be sufficient.
1413 sal_Bool bPrev
= rLine
.GetPrev() &&
1414 ( FindBrk( rString
, rLine
.GetStart(), rReformat
.Start() + 1 )
1415 // --> FME 2005-04-18 #i46560#
1418 >= rReformat
.Start() ||
1419 rLine
.GetCurr()->IsRest() );
1422 while( rLine
.Prev() )
1423 if( rLine
.GetCurr()->GetLen() && !rLine
.GetCurr()->IsRest() )
1425 if( !rLine
.GetStart() )
1426 rLine
.Top(); // damit NumDone nicht durcheinander kommt
1429 xub_StrLen nNew
= rLine
.GetStart() + rLine
.GetLength();
1433 if( CH_BREAK
== rString
.GetChar( nNew
) )
1440 rReformat
.Len() += rReformat
.Start() - nNew
;
1441 rReformat
.Start() = nNew
;
1444 rRepaint
.SetOfst( 0 );
1445 rRepaint
.SetRightOfst( 0 );
1446 rRepaint
.Chg( Frm().Pos() + Prt().Pos(), Prt().SSize() );
1447 if( pPara
->IsMargin() )
1448 rRepaint
.Width( rRepaint
.Width() + pPara
->GetHangingMargin() );
1449 rRepaint
.Top( rLine
.Y() );
1450 // 6792: Rrand < LRand und Repaint
1451 if( 0 >= rRepaint
.Width() )
1453 WidowsAndOrphans
aFrmBreak( this, rInf
.IsTest() ? 1 : 0 );
1455 // rLine steht jetzt auf der ersten Zeile, die formatiert werden
1456 // muss. Das Flag bFirst sorgt dafuer, dass nicht Next() gerufen wird.
1457 // Das ganze sieht verdreht aus, aber es muss sichergestellt werden,
1458 // dass bei IsBreakNow rLine auf der Zeile zum stehen kommt, die
1459 // nicht mehr passt.
1460 sal_Bool bFirst
= sal_True
;
1461 sal_Bool bFormat
= sal_True
;
1463 // 5383: Das CharToLine() kann uns auch in den roten Bereich fuehren.
1464 // In diesem Fall muessen wir zurueckwandern, bis die Zeile, die
1465 // nicht mehr passt in rLine eingestellt ist. Ansonsten geht Textmasse
1466 // verloren, weil der Ofst im Follow falsch eingestellt wird.
1468 // OD 2004-02-25 #i16128# - method renamed
1469 sal_Bool bBreak
= ( !pPara
->IsPrepMustFit() || rLine
.GetLineNr() > 1 )
1470 && aFrmBreak
.IsBreakNowWidAndOrp( rLine
);
1473 sal_Bool bPrevDone
= 0 != rLine
.Prev();
1474 // OD 2004-02-25 #i16128# - method renamed
1475 while( bPrevDone
&& aFrmBreak
.IsBreakNowWidAndOrp(rLine
) )
1476 bPrevDone
= 0 != rLine
.Prev();
1479 aFrmBreak
.SetKeep( sal_False
);
1484 // auf Nummer sicher:
1485 // OD 2004-02-25 #i16128# - method renamed
1486 bBreak
= aFrmBreak
.IsBreakNowWidAndOrp(rLine
) &&
1487 ( !pPara
->IsPrepMustFit() || rLine
.GetLineNr() > 1 );
1490 /* Bedeutung der folgenden Flags:
1491 Ist das Watch(End/Mid)Hyph-Flag gesetzt, so muss formatiert werden, wenn
1492 eine Trennung am (Zeilenende/Fly) vorliegt, sofern MaxHyph erreicht ist.
1493 Das Jump(End/Mid)Flag bedeutet, dass die naechste Zeile, bei der keine
1494 Trennung (Zeilenende/Fly) vorliegt, formatiert werden muss, da jetzt
1495 umgebrochen werden koennte, was vorher moeglicherweise durch MaxHyph
1497 Watch(End/Mid)Hyph wird gesetzt, wenn die letzte formatierte Zeile eine
1498 Trennstelle erhalten hat, vorher aber keine hatte,
1499 Jump(End/Mid)Hyph, wenn eine Trennstelle verschwindet.
1501 sal_Bool bJumpEndHyph
= sal_False
,
1502 bWatchEndHyph
= sal_False
,
1503 bJumpMidHyph
= sal_False
,
1504 bWatchMidHyph
= sal_False
;
1506 const SwAttrSet
& rAttrSet
= GetTxtNode()->GetSwAttrSet();
1507 sal_Bool bMaxHyph
= ( 0 !=
1508 ( rInf
.MaxHyph() = rAttrSet
.GetHyphenZone().GetMaxHyphens() ) );
1510 rLine
.InitCntHyph();
1512 if( IsFollow() && IsFieldFollow() && rLine
.GetStart() == GetOfst() )
1514 const SwLineLayout
* pLine
;
1516 SwTxtFrm
*pMaster
= FindMaster();
1517 ASSERT( pMaster
, "SwTxtFrm::Format: homeless follow" );
1518 if( !pMaster
->HasPara() )
1519 pMaster
->GetFormatted();
1520 SwTxtSizeInfo
aInf( pMaster
);
1521 SwTxtIter
aMasterLine( pMaster
, &aInf
);
1522 aMasterLine
.Bottom();
1523 pLine
= aMasterLine
.GetCurr();
1525 SwLinePortion
* pRest
=
1526 rLine
.MakeRestPortion( pLine
, GetOfst() );
1528 rInf
.SetRest( pRest
);
1530 SetFieldFollow( sal_False
);
1533 /* Zum Abbruchkriterium:
1534 * Um zu erkennen, dass eine Zeile nicht mehr auf die Seite passt,
1535 * muss sie formatiert werden. Dieser Ueberhang wird z.B. in AdjustFollow
1537 * Eine weitere Komplikation: wenn wir der Master sind, so muessen
1538 * wir die Zeilen durchgehen, da es ja sein kann, dass eine Zeile
1539 * vom Follow in den Master rutschen kann.
1550 if ( rLine
.GetCurr()->IsEndHyph() )
1551 rLine
.CntEndHyph()++;
1553 rLine
.CntEndHyph() = 0;
1554 if ( rLine
.GetCurr()->IsMidHyph() )
1555 rLine
.CntMidHyph()++;
1557 rLine
.CntMidHyph() = 0;
1563 SwLinePortion
* pRest
=
1564 rLine
.MakeRestPortion( rLine
.GetCurr(), rLine
.GetEnd() );
1566 rInf
.SetRest( pRest
);
1568 rLine
.Insert( new SwLineLayout() );
1573 if ( !bFormat
&& bMaxHyph
&&
1574 (bWatchEndHyph
|| bJumpEndHyph
|| bWatchMidHyph
|| bJumpMidHyph
) )
1576 if ( rLine
.GetCurr()->IsEndHyph() )
1578 if ( bWatchEndHyph
)
1579 bFormat
= ( rLine
.CntEndHyph() == rInf
.MaxHyph() );
1583 bFormat
= bJumpEndHyph
;
1584 bWatchEndHyph
= sal_False
;
1585 bJumpEndHyph
= sal_False
;
1587 if ( rLine
.GetCurr()->IsMidHyph() )
1589 if ( bWatchMidHyph
&& !bFormat
)
1590 bFormat
= ( rLine
.CntEndHyph() == rInf
.MaxHyph() );
1594 bFormat
= bFormat
|| bJumpMidHyph
;
1595 bWatchMidHyph
= sal_False
;
1596 bJumpMidHyph
= sal_False
;
1601 sal_Bool bOldEndHyph
= rLine
.GetCurr()->IsEndHyph();
1602 sal_Bool bOldMidHyph
= rLine
.GetCurr()->IsMidHyph();
1603 bFormat
= FormatLine( rLine
, bPrev
);
1604 //9334: Es kann nur ein bPrev geben... (???)
1608 if ( rLine
.GetCurr()->IsEndHyph() != bOldEndHyph
)
1610 bWatchEndHyph
= !bOldEndHyph
;
1611 bJumpEndHyph
= bOldEndHyph
;
1613 if ( rLine
.GetCurr()->IsMidHyph() != bOldMidHyph
)
1615 bWatchMidHyph
= !bOldMidHyph
;
1616 bJumpMidHyph
= bOldMidHyph
;
1621 if( !rInf
.IsNewLine() )
1624 bFormat
= 0 != rInf
.GetRest();
1625 if( rInf
.IsStop() || rInf
.GetIdx() >= nStrLen
)
1627 if( !bFormat
&& ( !bMaxHyph
|| ( !bWatchEndHyph
&&
1628 !bJumpEndHyph
&& !bWatchMidHyph
&& !bJumpMidHyph
) ) )
1632 while( rLine
.Next() )
1634 pFreeze
= new SwRepaint( rRepaint
); // to minimize painting
1640 // OD 2004-02-25 #i16128# - method renamed
1641 bBreak
= aFrmBreak
.IsBreakNowWidAndOrp(rLine
);
1646 rRepaint
= *pFreeze
;
1650 if( !rLine
.IsStop() )
1652 // Wurde aller Text formatiert und gibt es noch weitere
1653 // Zeilenobjekte, dann sind diese jetzt ueberfluessig,
1654 // weil der Text kuerzer geworden ist.
1655 if( rLine
.GetStart() + rLine
.GetLength() >= nStrLen
&&
1656 rLine
.GetCurr()->GetNext() )
1659 rLine
.SetTruncLines( sal_True
);
1663 if( !rInf
.IsTest() )
1665 // Bei OnceMore lohnt sich kein FormatAdjust
1666 if( bAdjust
|| !rLine
.GetDropFmt() || !rLine
.CalcOnceMore() )
1668 FormatAdjust( rLine
, aFrmBreak
, nStrLen
, rInf
.IsStop() );
1670 if( rRepaint
.HasArea() )
1672 rLine
.SetTruncLines( sal_False
);
1673 if( nOldBottom
) // Bei "gescollten" Absaetzen wird
1674 { // noch ueberprueft, ob durch Schrumpfen
1675 rLine
.Bottom(); // das Scrolling ueberfluessig wurde.
1676 SwTwips nNewBottom
= rLine
.Y();
1677 if( nNewBottom
< nOldBottom
)
1683 /*************************************************************************
1684 * SwTxtFrm::Format()
1685 *************************************************************************/
1687 void SwTxtFrm::FormatOnceMore( SwTxtFormatter
&rLine
, SwTxtFormatInfo
&rInf
)
1689 ASSERT( ! IsVertical() || IsSwapped(),
1690 "A frame is not swapped in SwTxtFrm::FormatOnceMore" );
1692 SwParaPortion
*pPara
= rLine
.GetInfo().GetParaPortion();
1697 KSHORT nOld
= ((const SwTxtMargin
&)rLine
).GetDropHeight();
1698 sal_Bool bShrink
= sal_False
,
1700 bGoOn
= rLine
.IsOnceMore();
1705 aDbstream
<< "OnceMore!" << endl
;
1710 if( !rLine
.GetDropFmt() )
1711 rLine
.SetOnceMore( sal_False
);
1712 SwCharRange
aRange( 0, rInf
.GetTxt().Len() );
1713 *(pPara
->GetReformat()) = aRange
;
1714 _Format( rLine
, rInf
);
1716 bGoOn
= rLine
.IsOnceMore();
1719 const KSHORT nNew
= ((const SwTxtMargin
&)rLine
).GetDropHeight();
1729 if( bShrink
== bGrow
|| 5 < nGo
)
1735 // 6107: Wenn was schief ging, muss noch einmal formatiert werden.
1738 rInf
.CtorInitTxtFormatInfo( this );
1739 rLine
.CtorInitTxtFormatter( this, &rInf
);
1740 rLine
.SetDropLines( 1 );
1741 rLine
.CalcDropHeight( 1 );
1742 SwCharRange
aTmpRange( 0, rInf
.GetTxt().Len() );
1743 *(pPara
->GetReformat()) = aTmpRange
;
1744 _Format( rLine
, rInf
, sal_True
);
1745 // 8047: Wir painten alles...
1752 /*************************************************************************
1753 * SwTxtFrm::_Format()
1754 *************************************************************************/
1757 void SwTxtFrm::_Format( SwParaPortion
*pPara
)
1759 const xub_StrLen nStrLen
= GetTxt().Len();
1761 // AMA: Wozu soll das gut sein? Scheint mir zuoft zu einem kompletten
1762 // Formatieren und Repainten zu fuehren???
1763 // if ( !(*pPara->GetDelta()) )
1764 // *(pPara->GetDelta()) = nStrLen;
1768 // Leere Zeilen werden nicht lange gequaelt:
1769 // pPara wird blank geputzt
1770 // entspricht *pPara = SwParaPortion;
1771 sal_Bool bMustFit
= pPara
->IsPrepMustFit();
1773 pPara
->FormatReset();
1774 if( pBlink
&& pPara
->IsBlinking() )
1775 pBlink
->Delete( pPara
);
1777 // delete pSpaceAdd und pKanaComp
1778 pPara
->FinishSpaceAdd();
1779 pPara
->FinishKanaComp();
1780 pPara
->ResetFlags();
1781 pPara
->SetPrepMustFit( bMustFit
);
1784 ASSERT( ! IsSwapped(), "A frame is swapped before _Format" );
1787 SwapWidthAndHeight();
1789 SwTxtFormatInfo
aInf( this );
1790 SwTxtFormatter
aLine( this, &aInf
);
1792 // OD 2004-01-15 #110582#
1793 HideAndShowObjects();
1795 _Format( aLine
, aInf
);
1797 if( aLine
.IsOnceMore() )
1798 FormatOnceMore( aLine
, aInf
);
1801 SwapWidthAndHeight();
1803 ASSERT( ! IsSwapped(), "A frame is swapped after _Format" );
1805 if( 1 < aLine
.GetDropLines() )
1807 if( SVX_ADJUST_LEFT
!= aLine
.GetAdjust() &&
1808 SVX_ADJUST_BLOCK
!= aLine
.GetAdjust() )
1810 aLine
.CalcDropAdjust();
1811 aLine
.SetPaintDrop( sal_True
);
1814 if( aLine
.IsPaintDrop() )
1816 aLine
.CalcDropRepaint();
1817 aLine
.SetPaintDrop( sal_False
);
1822 /*************************************************************************
1823 * SwTxtFrm::Format()
1824 *************************************************************************/
1827 * Format berechnet die Groesse des Textframes und ruft, wenn
1828 * diese feststeht, Shrink() oder Grow(), um die Framegroesse dem
1829 * evtl. veraenderten Platzbedarf anzupassen.
1832 void SwTxtFrm::Format( const SwBorderAttrs
* )
1835 #if OSL_DEBUG_LEVEL > 1
1836 const XubString aXXX
= GetTxtNode()->GetTxt();
1837 const SwTwips nDbgY
= Frm().Top();
1839 const SwPageFrm
*pDbgPage
= FindPageFrm();
1840 const MSHORT nDbgPageNr
= pDbgPage
->GetPhyPageNum();
1842 // Um zu gucken, ob es einen Ftn-Bereich gibt.
1843 const SwFrm
*pDbgFtnCont
= (const SwFrm
*)(FindPageFrm()->FindFtnCont());
1847 // nStopAt laesst sich vom CV bearbeiten.
1848 static MSHORT nStopAt
= 0;
1849 if( nStopAt
== GetFrmId() )
1858 //Fussnote darf nicht auf einer Seite vor ihrer Referenz stehen.
1861 const SwFtnFrm
*pFtn
= (SwFtnFrm
*)GetUpper();
1862 const SwPageFrm
*pFtnPage
= pFtn
->GetRef()->FindPageFrm();
1863 const MSHORT nFtnPageNr
= pFtnPage
->GetPhyPageNum();
1866 if( nFtnPageNr
> nDbgPageNr
)
1868 SwTxtFrmLocker
aLock(this);
1869 ASSERT( nFtnPageNr
<= nDbgPageNr
, "!Ftn steht vor der Referenz." );
1878 // --> OD 2008-01-31 #newlistlevelattrs#
1879 CalcAdditionalFirstLineOffset();
1882 // Vom Berichtsautopiloten oder ueber die BASIC-Schnittstelle kommen
1883 // gelegentlich TxtFrms mit einer Breite <=0.
1884 if( (Prt().*fnRect
->fnGetWidth
)() <= 0 )
1886 // Wenn MustFit gesetzt ist, schrumpfen wir ggf. auf die Unterkante
1887 // des Uppers, ansonsten nehmen wir einfach eine Standardgroesse
1888 // von 12 Pt. ein (240 Twip).
1889 SwTxtLineAccess
aAccess( this );
1890 long nFrmHeight
= (Frm().*fnRect
->fnGetHeight
)();
1891 if( aAccess
.GetPara()->IsPrepMustFit() )
1893 const SwTwips nLimit
= (GetUpper()->*fnRect
->fnGetPrtBottom
)();
1894 const SwTwips nDiff
= - (Frm().*fnRect
->fnBottomDist
)( nLimit
);
1898 else if( 240 < nFrmHeight
)
1899 Shrink( nFrmHeight
- 240 );
1900 else if( 240 > nFrmHeight
)
1901 Grow( 240 - nFrmHeight
);
1902 nFrmHeight
= (Frm().*fnRect
->fnGetHeight
)();
1904 long nTop
= (this->*fnRect
->fnGetTopMargin
)();
1905 if( nTop
> nFrmHeight
)
1906 (this->*fnRect
->fnSetYMargins
)( nFrmHeight
, 0 );
1907 else if( (Prt().*fnRect
->fnGetHeight
)() < 0 )
1908 (Prt().*fnRect
->fnSetHeight
)( 0 );
1912 const xub_StrLen nStrLen
= GetTxtNode()->GetTxt().Len();
1913 if ( nStrLen
|| !FormatEmpty() )
1916 SetEmpty( sal_False
);
1917 // Um nicht durch verschachtelte Formats irritiert zu werden.
1919 if( 12 == aLevel
.GetLevel() )
1922 // Die Formatinformationen duerfen u.U. nicht veraendert werden.
1926 // 8708: Vorsicht, das Format() kann auch durch GetFormatted()
1927 // angestossen werden.
1930 long nPrtHeight
= (Prt().*fnRect
->fnGetHeight
)();
1934 Shrink( nPrtHeight
);
1938 // OD 2004-01-20 #110582# - assure that objects anchored
1939 // at paragraph resp. at/as character inside paragraph
1941 HideAndShowObjects();
1947 // Waehrend wir formatieren, wollen wir nicht gestoert werden.
1948 SwTxtFrmLocker
aLock(this);
1949 SwTxtLineAccess
aAccess( this );
1950 const sal_Bool bNew
= !aAccess
.SwTxtLineAccess::IsAvailable();
1951 const sal_Bool bSetOfst
= ( GetOfst() && GetOfst() > GetTxtNode()->GetTxt().Len() );
1955 // Wir returnen, wenn schon formatiert wurde, nicht aber, wenn
1956 // der TxtFrm gerade erzeugt wurde und ueberhaupt keine Format-
1957 // informationen vorliegen.
1958 else if( !bNew
&& !aAccess
.GetPara()->GetReformat()->Len() )
1960 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
1962 aAccess
.GetPara()->SetPrepAdjust( sal_True
);
1963 aAccess
.GetPara()->SetPrep( sal_True
);
1966 SetWidow( sal_False
);
1968 else if( bSetOfst
&& IsFollow() )
1970 SwTxtFrm
*pMaster
= FindMaster();
1971 ASSERT( pMaster
, "SwTxtFrm::Format: homeless follow" );
1973 pMaster
->Prepare( PREP_FOLLOW_FOLLOWS
);
1974 SwTwips nMaxY
= (GetUpper()->*fnRect
->fnGetPrtBottom
)();
1975 if( (Frm().*fnRect
->fnOverStep
)( nMaxY
) )
1976 (this->*fnRect
->fnSetLimit
)( nMaxY
);
1977 else if( (Frm().*fnRect
->fnBottomDist
)( nMaxY
) < 0 )
1978 (Frm().*fnRect
->fnAddBottom
)( -(Frm().*fnRect
->fnGetHeight
)() );
1982 // bSetOfst here means that we have the "red arrow situation"
1986 const sal_Bool bOrphan
= IsWidow();
1987 const SwFtnBossFrm
* pFtnBoss
= HasFtn() ? FindFtnBossFrm() : 0;
1988 SwTwips nFtnHeight
= 0;
1991 const SwFtnContFrm
* pCont
= pFtnBoss
->FindFtnCont();
1992 nFtnHeight
= pCont
? (pCont
->Frm().*fnRect
->fnGetHeight
)() : 0;
1996 _Format( aAccess
.GetPara() );
1997 if( pFtnBoss
&& nFtnHeight
)
1999 const SwFtnContFrm
* pCont
= pFtnBoss
->FindFtnCont();
2000 SwTwips nNewHeight
= pCont
? (pCont
->Frm().*fnRect
->fnGetHeight
)() : 0;
2001 // If we lost some footnotes, we may have more space
2002 // for our main text, so we have to format again ...
2003 if( nNewHeight
< nFtnHeight
)
2004 nFtnHeight
= nNewHeight
;
2010 } while ( pFtnBoss
);
2014 SetWidow( sal_False
);
2017 if( IsEmptyMaster() )
2019 SwFrm
* pPre
= GetPrev();
2021 // --> FME 2004-07-22 #i10826# It's the first, it cannot keep!
2022 pPre
->GetIndPrev() &&
2024 pPre
->GetAttrSet()->GetKeep().GetValue() )
2026 pPre
->InvalidatePos();
2033 // the PrepMustFit should not survive a Format operation
2034 SwParaPortion
*pPara
= GetPara();
2036 pPara
->SetPrepMustFit( sal_False
);
2038 #if OSL_DEBUG_LEVEL > 1
2039 // Hier ein Instrumentarium, um ungewoehnlichen Master/Follow-Kombinationen,
2040 // insbesondere bei Fussnoten, auf die Schliche zu kommen
2041 if( IsFollow() || GetFollow() )
2043 SwTxtFrm
*pTmpFrm
= IsFollow() ? FindMaster() : this;
2044 const SwPageFrm
*pTmpPage
= pTmpFrm
->FindPageFrm();
2045 MSHORT nPgNr
= pTmpPage
->GetPhyPageNum();
2047 MSHORT nDummy
= 0; // nur zum Breakpoint setzen
2048 while( pTmpFrm
->GetFollow() )
2050 pTmpFrm
= pTmpFrm
->GetFollow();
2052 pTmpPage
= pTmpFrm
->FindPageFrm();
2053 nPgNr
= pTmpPage
->GetPhyPageNum();
2055 ++nDummy
; // schon fast eine Assertion wert
2056 else if( nLast
== nPgNr
)
2057 ++nDummy
; // bei Spalten voellig normal, aber sonst!?
2058 else if( nLast
< nPgNr
- 1 )
2059 ++nDummy
; // kann schon mal temporaer vorkommen
2064 CalcBaseOfstForFly();
2065 // OD 2004-03-17 #i11860#
2066 _CalcHeightOfLastLine();
2069 /*************************************************************************
2070 * SwTxtFrm::FormatQuick()
2072 * bForceQuickFormat is set if GetFormatted() has been called during the
2073 * painting process. Actually I cannot imagine a situation which requires
2074 * a full formatting of the paragraph during painting, on the other hand
2075 * a full formatting can cause the invalidation of other layout frames,
2076 * e.g., if there are footnotes in this paragraph, and invalid layout
2077 * frames will not calculated during the painting. So I actually want to
2078 * avoid a formatting during painting, but since I'm a coward, I'll only
2079 * force the quick formatting in the situation of issue i29062.
2080 *************************************************************************/
2082 sal_Bool
SwTxtFrm::FormatQuick( bool bForceQuickFormat
)
2084 ASSERT( ! IsVertical() || ! IsSwapped(),
2085 "SwTxtFrm::FormatQuick with swapped frame" );
2088 #if OSL_DEBUG_LEVEL > 1
2089 const XubString aXXX
= GetTxtNode()->GetTxt();
2090 const SwTwips nDbgY
= Frm().Top();
2093 // nStopAt laesst sich vom CV bearbeiten.
2094 static MSHORT nStopAt
= 0;
2095 if( nStopAt
== GetFrmId() )
2103 if( IsEmpty() && FormatEmpty() )
2106 // Wir sind sehr waehlerisch:
2107 if( HasPara() || IsWidow() || IsLocked()
2108 || !GetValidSizeFlag() ||
2109 ( ( IsVertical() ? Prt().Width() : Prt().Height() ) && IsHiddenNow() ) )
2112 SwTxtLineAccess
aAccess( this );
2113 SwParaPortion
*pPara
= aAccess
.GetPara();
2117 SwFrmSwapper
aSwapper( this, sal_True
);
2119 SwTxtFrmLocker
aLock(this);
2120 SwTxtFormatInfo
aInf( this, sal_False
, sal_True
);
2121 if( 0 != aInf
.MaxHyph() ) // 27483: MaxHyphen beachten!
2124 SwTxtFormatter
aLine( this, &aInf
);
2126 // DropCaps sind zu kompliziert...
2127 if( aLine
.GetDropFmt() )
2130 xub_StrLen nStart
= GetOfst();
2131 const xub_StrLen nEnd
= GetFollow()
2132 ? GetFollow()->GetOfst() : aInf
.GetTxt().Len();
2135 //DBG_LOOP; shadows declaration above.
2137 #if OSL_DEBUG_LEVEL > 1
2139 DbgLoop
aDbgLoop2( (const void*) this );
2142 nStart
= aLine
.FormatLine( nStart
);
2143 if( aInf
.IsNewLine() || (!aInf
.IsStop() && nStart
< nEnd
) )
2144 aLine
.Insert( new SwLineLayout() );
2145 } while( aLine
.Next() );
2147 // Last exit: die Hoehen muessen uebereinstimmen.
2148 Point
aTopLeft( Frm().Pos() );
2149 aTopLeft
+= Prt().Pos();
2150 const SwTwips nNewHeight
= aLine
.Y() + aLine
.GetLineHeight();
2151 const SwTwips nOldHeight
= aTopLeft
.Y() + Prt().Height();
2153 if( !bForceQuickFormat
&& nNewHeight
!= nOldHeight
&& !IsUndersized() )
2155 // Achtung: Durch FormatLevel==12 kann diese Situation auftreten, don't panic!
2156 // ASSERT( nNewHeight == nOldHeight, "!FormatQuick: rosebud" );
2157 const xub_StrLen nStrt
= GetOfst();
2158 _InvalidateRange( SwCharRange( nStrt
, nEnd
- nStrt
) );
2162 if( pFollow
&& nStart
!= ((SwTxtFrm
*)pFollow
)->GetOfst() )
2163 return sal_False
; // kann z.B. durch Orphans auftreten (35083,35081)
2165 // Geschafft, wir sind durch ...
2168 pPara
->GetRepaint()->Pos( aTopLeft
);
2169 pPara
->GetRepaint()->SSize( Prt().SSize() );
2171 // Reformat loeschen
2172 *(pPara
->GetReformat()) = SwCharRange();
2173 *(pPara
->GetDelta()) = 0;