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: calcmove.cxx,v $
10 * $Revision: 1.73.252.1 $
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"
33 #include "rootfrm.hxx"
34 #include "pagefrm.hxx"
38 #include "viewimp.hxx"
39 #include "swtypes.hxx"
40 #include "dflyobj.hxx"
41 #include "dcontact.hxx"
43 #include "frmtool.hxx"
46 #include <svx/ulspitem.hxx>
47 #include <svx/keepitem.hxx>
49 #ifndef _OUTDEV_HXX //autogen
50 #include <vcl/outdev.hxx>
52 #include <fmtfsize.hxx>
53 #include <fmtanchr.hxx>
54 #include <fmtclbl.hxx>
59 #include "pagedesc.hxx"
60 #include "ftninfo.hxx"
61 #include "sectfrm.hxx"
62 #include "dbg_lay.hxx"
64 // --> OD 2004-06-23 #i28701#
65 #include <sortedobjs.hxx>
66 #include <layouter.hxx>
67 // --> OD 2004-11-01 #i36347#
68 #include <flyfrms.hxx>
73 //------------------------------------------------------------------------
75 //------------------------------------------------------------------------
77 /*************************************************************************
79 |* SwCntntFrm::ShouldBwdMoved()
81 |* Beschreibung Returnwert sagt, ob der Frm verschoben werden sollte.
82 |* Ersterstellung MA 05. Dec. 96
83 |* Letzte Aenderung MA 05. Dec. 96
85 |*************************************************************************/
88 BOOL
SwCntntFrm::ShouldBwdMoved( SwLayoutFrm
*pNewUpper
, BOOL
, BOOL
& )
90 if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()))
92 //Das zurueckfliessen von Frm's ist leider etwas Zeitintensiv.
93 //Der haufigste Fall ist der, dass dort wo der Frm hinfliessen
94 //moechte die FixSize die gleiche ist, die der Frm selbst hat.
95 //In diesem Fall kann einfach geprueft werden, ob der Frm genug
96 //Platz fuer seine VarSize findet, ist dies nicht der Fall kann
97 //gleich auf das Verschieben verzichtet werden.
98 //Die Pruefung, ob der Frm genug Platz findet fuehrt er selbst
99 //durch, dabei wird beruecksichtigt, dass er sich moeglicherweise
101 //Wenn jedoch die FixSize eine andere ist oder Flys im Spiel sind
102 //(an der alten oder neuen Position) hat alle Prueferei keinen Sinn
103 //der Frm muss dann halt Probehalber verschoben werden (Wenn ueberhaupt
104 //etwas Platz zur Verfuegung steht).
106 //Die FixSize der Umgebungen in denen Cntnts herumlungern ist immer
109 //Wenn mehr als ein Blatt zurueckgegangen wurde (z.B. ueberspringen
110 //von Leerseiten), so muss in jedemfall gemoved werden - sonst wuerde,
111 //falls der Frm nicht in das Blatt passt, nicht mehr auf die
112 //dazwischenliegenden Blaetter geachtet werden.
113 BYTE nMoveAnyway
= 0;
114 SwPageFrm
* const pNewPage
= pNewUpper
->FindPageFrm();
115 SwPageFrm
*pOldPage
= FindPageFrm();
117 if ( SwFlowFrm::IsMoveBwdJump() )
120 if( IsInFtn() && IsInSct() )
122 SwFtnFrm
* pFtn
= FindFtnFrm();
123 SwSectionFrm
* pMySect
= pFtn
->FindSctFrm();
124 if( pMySect
&& pMySect
->IsFtnLock() )
126 SwSectionFrm
*pSect
= pNewUpper
->FindSctFrm();
127 while( pSect
&& pSect
->IsInFtn() )
128 pSect
= pSect
->GetUpper()->FindSctFrm();
129 ASSERT( pSect
, "Escaping footnote" );
130 if( pSect
!= pMySect
)
135 SWRECTFNX( pNewUpper
)
136 if( Abs( (pNewUpper
->Prt().*fnRectX
->fnGetWidth
)() -
137 (GetUpper()->Prt().*fnRect
->fnGetWidth
)() ) > 1 )
138 nMoveAnyway
= 2; // Damit kommt nur noch ein _WouldFit mit Umhaengen in Frage
140 // OD 2004-05-26 #i25904# - do *not* move backward,
141 // if <nMoveAnyway> equals 3 and no space is left in new upper.
142 nMoveAnyway
|= BwdMoveNecessary( pOldPage
, Frm() );
144 const IDocumentSettingAccess
* pIDSA
= pNewPage
->GetFmt()->getIDocumentSettingAccess();
146 SwRect
aRect( pNewUpper
->Prt() );
147 aRect
.Pos() += pNewUpper
->Frm().Pos();
148 const SwFrm
*pPrevFrm
= pNewUpper
->Lower();
151 SwTwips nNewTop
= (pPrevFrm
->Frm().*fnRectX
->fnGetBottom
)();
152 // OD 2004-03-01 #106629#:
153 // consider lower spacing of last frame in a table cell
155 // check, if last frame is inside table and if it includes
156 // its lower spacing.
157 if ( !pPrevFrm
->GetNext() && pPrevFrm
->IsInTab() &&
158 pIDSA
->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS
) )
160 const SwFrm
* pLastFrm
= pPrevFrm
;
161 // if last frame is a section, take its last content
162 if ( pPrevFrm
->IsSctFrm() )
164 pLastFrm
= static_cast<const SwSectionFrm
*>(pPrevFrm
)->FindLastCntnt();
166 pLastFrm
->FindTabFrm() != pPrevFrm
->FindTabFrm() )
168 pLastFrm
= pLastFrm
->FindTabFrm();
174 SwBorderAttrAccess
aAccess( SwFrm::GetCache(), pLastFrm
);
175 const SwBorderAttrs
& rAttrs
= *aAccess
.Get();
176 nNewTop
-= rAttrs
.GetULSpace().GetLower();
180 (aRect
.*fnRectX
->fnSetTop
)( nNewTop
);
182 pPrevFrm
= pPrevFrm
->GetNext();
185 nMoveAnyway
|= BwdMoveNecessary( pNewPage
, aRect
);
187 //determine space left in new upper frame
188 nSpace
= (aRect
.*fnRectX
->fnGetHeight
)();
191 pIDSA
->get(IDocumentSettingAccess::BROWSE_MODE
) ||
192 pNewUpper
->IsCellFrm() ||
193 ( pNewUpper
->IsInSct() && ( pNewUpper
->IsSctFrm() ||
194 ( pNewUpper
->IsColBodyFrm() &&
195 !pNewUpper
->GetUpper()->GetPrev() &&
196 !pNewUpper
->GetUpper()->GetNext() ) ) ) )
197 nSpace
+= pNewUpper
->Grow( LONG_MAX
, TRUE
);
199 if ( nMoveAnyway
< 3 )
203 //Keine Beruecksichtigung der Fussnoten die an dem Absatz
204 //kleben, denn dies wuerde extrem unuebersichtlichen Code
205 //beduerfen (wg. Beruecksichtung der Breiten und vor allem
206 //der Flys, die ja wieder Einfluss auf die Fussnoten nehmen...).
208 // _WouldFit kann bei gleicher Breite und _nur_ selbst verankerten Flys
210 // _WouldFit kann auch gefragt werden, wenn _nur_ fremdverankerte Flys vorliegen,
211 // dabei ist sogar die Breite egal, da ein TestFormat in der neuen Umgebung
213 // --> OD 2007-11-26 #b6614158#
214 const BYTE nBwdMoveNecessaryResult
=
215 BwdMoveNecessary( pNewPage
, aRect
);
216 const bool bObjsInNewUpper( nBwdMoveNecessaryResult
== 2 ||
217 nBwdMoveNecessaryResult
== 3 );
219 return _WouldFit( nSpace
, pNewUpper
, nMoveAnyway
== 2,
223 //Bei einem spaltigen Bereichsfrischling kann _WouldFit kein
224 //brauchbares Ergebnis liefern, also muessen wir wirklich
226 else if( pNewUpper
->IsInSct() && pNewUpper
->IsColBodyFrm() &&
227 !(pNewUpper
->Prt().*fnRectX
->fnGetWidth
)() &&
228 ( pNewUpper
->GetUpper()->GetPrev() ||
229 pNewUpper
->GetUpper()->GetNext() ) )
232 return FALSE
; // Kein Platz, dann ist es sinnlos, zurueckzufliessen
236 // OD 2004-05-26 #i25904# - check for space left in new upper
247 //------------------------------------------------------------------------
249 //------------------------------------------------------------------------
251 /*************************************************************************
255 |* Beschreibung Bereitet den Frm auf die 'Formatierung' (MakeAll())
256 |* vor. Diese Methode dient dazu auf dem Stack Platz einzusparen,
257 |* denn zur Positionsberechnung des Frm muss sichergestellt sein, dass
258 |* die Position von Upper und Prev gueltig sind, mithin also ein
259 |* rekursiver Aufruf (Schleife waere relativ teuer, da selten notwendig).
260 |* Jeder Aufruf von MakeAll verbraucht aber ca. 500Byte Stack -
261 |* das Ende ist leicht abzusehen. _Prepare benoetigt nur wenig Stack,
262 |* deshalb solle der Rekursive Aufruf hier kein Problem sein.
263 |* Ein weiterer Vorteil ist, das eines schoenen Tages das _Prepare und
264 |* damit die Formatierung von Vorgaengern umgangen werden kann.
265 |* So kann evtl. mal 'schnell' an's Dokumentende gesprungen werden.
266 |* Ersterstellung MA ??
267 |* Letzte Aenderung MA 13. Dec. 93
269 |*************************************************************************/
270 //Zwei kleine Freundschaften werden hier zu einem Geheimbund.
271 inline void PrepareLock( SwFlowFrm
*pTab
)
275 inline void PrepareUnlock( SwFlowFrm
*pTab
)
281 // hopefully, one day this function simply will return 'false'
282 bool lcl_IsCalcUpperAllowed( const SwFrm
& rFrm
)
284 return !rFrm
.GetUpper()->IsSctFrm() &&
285 !rFrm
.GetUpper()->IsFooterFrm() &&
286 // --> OD 2004-11-02 #i23129#, #i36347# - no format of upper Writer fly frame
287 !rFrm
.GetUpper()->IsFlyFrm() &&
289 !( rFrm
.GetUpper()->IsTabFrm() && rFrm
.GetUpper()->GetUpper()->IsInTab() ) &&
290 !( rFrm
.IsTabFrm() && rFrm
.GetUpper()->IsInTab() );
293 void SwFrm::PrepareMake()
298 if ( lcl_IsCalcUpperAllowed( *this ) )
300 ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
304 const BOOL bCnt
= IsCntntFrm();
305 const BOOL bTab
= IsTabFrm();
306 BOOL bNoSect
= IsInSct();
307 BOOL bOldTabLock
= FALSE
, bFoll
= FALSE
;
308 SwFlowFrm
* pThis
= bCnt
? (SwCntntFrm
*)this : NULL
;
312 pThis
= (SwTabFrm
*)this;
313 bOldTabLock
= ((SwTabFrm
*)this)->IsJoinLocked();
314 ::PrepareLock( (SwTabFrm
*)this );
315 bFoll
= pThis
->IsFollow();
317 else if( IsSctFrm() )
319 pThis
= (SwSectionFrm
*)this;
320 bFoll
= pThis
->IsFollow();
323 else if ( bCnt
&& TRUE
== (bFoll
= pThis
->IsFollow()) &&
326 //Wenn der Master gereade ein CalcFollow ruft braucht die Kette
327 //nicht durchlaufen werden. Das spart Zeit und vermeidet Probleme.
328 if ( ((SwTxtFrm
*)((SwTxtFrm
*)this)->FindMaster())->IsLocked() )
335 // --> OD 2005-03-04 #i44049# - no format of previous frame, if current
336 // frame is a table frame and its previous frame wants to keep with it.
337 const bool bFormatPrev
= !bTab
||
339 !GetPrev()->GetAttrSet()->GetKeep().GetValue();
342 SwFrm
*pFrm
= GetUpper()->Lower();
343 while ( pFrm
!= this )
345 ASSERT( pFrm
, ":-( Layoutgeruest wackelig (this not found)." );
347 return; //Oioioioi ...
349 if ( !pFrm
->IsValid() )
351 //Ein kleiner Eingriff der hoffentlich etwas zur Verbesserung
352 //der Stabilitaet beitraegt:
353 //Wenn ich Follow _und_ Nachbar eines Frms vor mir bin,
354 //so wuerde dieser mich beim Formatieren deleten; wie jeder
355 //leicht sehen kann waere dies eine etwas unuebersichtliche
356 //Situation die es zu vermeiden gilt.
357 if ( bFoll
&& pFrm
->IsFlowFrm() &&
358 (SwFlowFrm::CastFlowFrm(pFrm
))->IsAnFollow( pThis
) )
361 //MA: 24. Mar. 94, Calc wuerde doch nur wieder in ein _Prepare laufen und so
362 //die ganze Kette nocheinmal abhuenern.
365 if( IsSctFrm() && !((SwSectionFrm
*)this)->GetSection() )
368 //Die Kette kann bei CntntFrms waehrend des durchlaufens
369 //aufgebrochen werden, deshalb muss der Nachfolger etwas
370 //umstaendlich ermittelt werden. However, irgendwann _muss_
371 //ich wieder bei mir selbst ankommen.
372 pFrm
= pFrm
->FindNext();
374 //Wenn wir in einem SectionFrm gestartet sind, koennen wir durch die
375 //MakeAll-Aufrufe in einen Section-Follow gewandert sein.
376 //FindNext liefert allerdings den SectionFrm, nicht seinen Inhalt.
377 // => wir finden uns selbst nicht mehr!
378 if( bNoSect
&& pFrm
&& pFrm
->IsSctFrm() )
380 SwFrm
* pCnt
= ((SwSectionFrm
*)pFrm
)->ContainsAny();
385 ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." );
389 if ( lcl_IsCalcUpperAllowed( *this ) )
392 ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." );
395 if ( bTab
&& !bOldTabLock
)
396 ::PrepareUnlock( (SwTabFrm
*)this );
401 void SwFrm::OptPrepareMake()
403 // --> OD 2004-11-02 #i23129#, #i36347# - no format of upper Writer fly frame
404 if ( GetUpper() && !GetUpper()->IsFooterFrm() &&
405 !GetUpper()->IsFlyFrm() )
409 ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
413 if ( GetPrev() && !GetPrev()->IsValid() )
424 void SwFrm::PrepareCrsr()
427 if( GetUpper() && !GetUpper()->IsSctFrm() )
429 GetUpper()->PrepareCrsr();
432 ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
436 const BOOL bCnt
= IsCntntFrm();
437 const BOOL bTab
= IsTabFrm();
438 BOOL bNoSect
= IsInSct();
440 BOOL bOldTabLock
= FALSE
, bFoll
;
441 SwFlowFrm
* pThis
= bCnt
? (SwCntntFrm
*)this : NULL
;
445 bOldTabLock
= ((SwTabFrm
*)this)->IsJoinLocked();
446 ::PrepareLock( (SwTabFrm
*)this );
447 pThis
= (SwTabFrm
*)this;
449 else if( IsSctFrm() )
451 pThis
= (SwSectionFrm
*)this;
454 bFoll
= pThis
&& pThis
->IsFollow();
456 SwFrm
*pFrm
= GetUpper()->Lower();
457 while ( pFrm
!= this )
459 ASSERT( pFrm
, ":-( Layoutgeruest wackelig (this not found)." );
461 return; //Oioioioi ...
463 if ( !pFrm
->IsValid() )
465 //Ein kleiner Eingriff der hoffentlich etwas zur Verbesserung
466 //der Stabilitaet beitraegt:
467 //Wenn ich Follow _und_ Nachbar eines Frms vor mir bin,
468 //so wuerde dieser mich beim Formatieren deleten; wie jeder
469 //leicht sehen kann waere dies eine etwas unuebersichtliche
470 //Situation die es zu vermeiden gilt.
471 if ( bFoll
&& pFrm
->IsFlowFrm() &&
472 (SwFlowFrm::CastFlowFrm(pFrm
))->IsAnFollow( pThis
) )
477 //Die Kette kann bei CntntFrms waehrend des durchlaufens
478 //aufgebrochen werden, deshalb muss der Nachfolger etwas
479 //umstaendlich ermittelt werden. However, irgendwann _muss_
480 //ich wieder bei mir selbst ankommen.
481 pFrm
= pFrm
->FindNext();
482 if( bNoSect
&& pFrm
&& pFrm
->IsSctFrm() )
484 SwFrm
* pCnt
= ((SwSectionFrm
*)pFrm
)->ContainsAny();
489 ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." );
495 ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." );
497 if ( bTab
&& !bOldTabLock
)
498 ::PrepareUnlock( (SwTabFrm
*)this );
503 /*************************************************************************
507 |* Ersterstellung MA ??
508 |* Letzte Aenderung MA 24. May. 93
510 |*************************************************************************/
512 // Hier wird GetPrev() zurueckgegeben, allerdings werden
513 // dabei leere SectionFrms ueberlesen
514 SwFrm
* lcl_Prev( SwFrm
* pFrm
, BOOL bSectPrv
= TRUE
)
516 SwFrm
* pRet
= pFrm
->GetPrev();
517 if( !pRet
&& pFrm
->GetUpper() && pFrm
->GetUpper()->IsSctFrm() &&
518 bSectPrv
&& !pFrm
->IsColumnFrm() )
519 pRet
= pFrm
->GetUpper()->GetPrev();
520 while( pRet
&& pRet
->IsSctFrm() &&
521 !((SwSectionFrm
*)pRet
)->GetSection() )
522 pRet
= pRet
->GetPrev();
526 SwFrm
* lcl_NotHiddenPrev( SwFrm
* pFrm
)
531 pRet
= lcl_Prev( pRet
);
532 } while ( pRet
&& pRet
->IsTxtFrm() && ((SwTxtFrm
*)pRet
)->IsHiddenNow() );
536 void SwFrm::MakePos()
541 BOOL bUseUpper
= FALSE
;
542 SwFrm
* pPrv
= lcl_Prev( this );
544 ( !pPrv
->IsCntntFrm() ||
545 ( ((SwCntntFrm
*)pPrv
)->GetFollow() != this ) )
548 if ( !StackHack::IsLocked() &&
549 ( !IsInSct() || IsSctFrm() ) &&
551 !pPrv
->GetAttrSet()->GetKeep().GetValue()
554 pPrv
->Calc(); //hierbei kann der Prev verschwinden!
556 else if ( pPrv
->Frm().Top() == 0 )
562 pPrv
= lcl_Prev( this, FALSE
);
563 USHORT nMyType
= GetType();
564 SWRECTFN( ( IsCellFrm() && GetUpper() ? GetUpper() : this ) )
565 if ( !bUseUpper
&& pPrv
)
567 aFrm
.Pos( pPrv
->Frm().Pos() );
568 if( FRM_NEIGHBOUR
& nMyType
)
570 BOOL bR2L
= IsRightToLeft();
572 (aFrm
.*fnRect
->fnSetPosX
)( (aFrm
.*fnRect
->fnGetLeft
)() -
573 (aFrm
.*fnRect
->fnGetWidth
)() );
575 (aFrm
.*fnRect
->fnSetPosX
)( (aFrm
.*fnRect
->fnGetLeft
)() +
576 (pPrv
->Frm().*fnRect
->fnGetWidth
)() );
578 // cells may now leave their uppers
579 if( bVert
&& FRM_CELL
& nMyType
&& !bReverse
)
580 aFrm
.Pos().X() -= aFrm
.Width() -pPrv
->Frm().Width();
582 else if( bVert
&& FRM_NOTE_VERT
& nMyType
)
585 aFrm
.Pos().X() += pPrv
->Frm().Width();
587 aFrm
.Pos().X() -= aFrm
.Width();
590 aFrm
.Pos().Y() += pPrv
->Frm().Height();
592 else if ( GetUpper() )
594 // OD 15.10.2002 #103517# - add safeguard for <SwFooterFrm::Calc()>
595 // If parent frame is a footer frame and its <ColLocked()>, then
596 // do *not* calculate it.
597 // NOTE: Footer frame is <ColLocked()> during its
598 // <FormatSize(..)>, which is called from <Format(..)>, which
599 // is called from <MakeAll()>, which is called from <Calc()>.
600 // --> OD 2005-11-17 #i56850#
601 // - no format of upper Writer fly frame, which is anchored
602 // at-paragraph or at-character.
603 if ( !GetUpper()->IsTabFrm() &&
604 !( IsTabFrm() && GetUpper()->IsInTab() ) &&
605 !GetUpper()->IsSctFrm() &&
606 !dynamic_cast<SwFlyAtCntFrm
*>(GetUpper()) &&
607 !( GetUpper()->IsFooterFrm() &&
608 GetUpper()->IsColLocked() )
614 pPrv
= lcl_Prev( this, FALSE
);
615 if ( !bUseUpper
&& pPrv
)
617 aFrm
.Pos( pPrv
->Frm().Pos() );
618 if( FRM_NEIGHBOUR
& nMyType
)
620 BOOL bR2L
= IsRightToLeft();
622 (aFrm
.*fnRect
->fnSetPosX
)( (aFrm
.*fnRect
->fnGetLeft
)() -
623 (aFrm
.*fnRect
->fnGetWidth
)() );
625 (aFrm
.*fnRect
->fnSetPosX
)( (aFrm
.*fnRect
->fnGetLeft
)() +
626 (pPrv
->Frm().*fnRect
->fnGetWidth
)() );
628 // cells may now leave their uppers
629 if( bVert
&& FRM_CELL
& nMyType
&& !bReverse
)
630 aFrm
.Pos().X() -= aFrm
.Width() -pPrv
->Frm().Width();
632 else if( bVert
&& FRM_NOTE_VERT
& nMyType
)
635 aFrm
.Pos().X() += pPrv
->Frm().Width();
637 aFrm
.Pos().X() -= aFrm
.Width();
640 aFrm
.Pos().Y() += pPrv
->Frm().Height();
644 aFrm
.Pos( GetUpper()->Frm().Pos() );
645 aFrm
.Pos() += GetUpper()->Prt().Pos();
646 if( FRM_NEIGHBOUR
& nMyType
&& IsRightToLeft() )
649 aFrm
.Pos().Y() += GetUpper()->Prt().Height()
652 aFrm
.Pos().X() += GetUpper()->Prt().Width()
655 else if( bVert
&& FRM_NOTE_VERT
& nMyType
&& !bReverse
)
656 aFrm
.Pos().X() -= aFrm
.Width() - GetUpper()->Prt().Width();
660 aFrm
.Pos().X() = aFrm
.Pos().Y() = 0;
661 if( IsBodyFrm() && bVert
&& !bReverse
&& GetUpper() )
662 aFrm
.Pos().X() += GetUpper()->Prt().Width() - aFrm
.Width();
667 /*************************************************************************
669 |* SwPageFrm::MakeAll()
671 |* Ersterstellung MA 23. Feb. 93
672 |* Letzte Aenderung MA 20. Jul. 98
674 |*************************************************************************/
675 // --> OD 2004-07-01 #i28701# - new type <SwSortedObjs>
676 void lcl_CheckObjects( SwSortedObjs
* pSortedObjs
, SwFrm
* pFrm
, long& rBot
)
678 //Und dann kann es natuerlich noch Absatzgebundene
679 //Rahmen geben, die unterhalb ihres Absatzes stehen.
681 for ( USHORT i
= 0; i
< pSortedObjs
->Count(); ++i
)
683 // --> OD 2004-07-01 #i28701# - consider changed type of <SwSortedObjs>
685 SwAnchoredObject
* pObj
= (*pSortedObjs
)[i
];
687 if ( pObj
->ISA(SwFlyFrm
) )
689 SwFlyFrm
*pFly
= static_cast<SwFlyFrm
*>(pObj
);
690 if( pFly
->Frm().Top() != WEIT_WECH
&&
691 ( pFrm
->IsPageFrm() ? pFly
->IsFlyLayFrm() :
692 ( pFly
->IsFlyAtCntFrm() &&
693 ( pFrm
->IsBodyFrm() ? pFly
->GetAnchorFrm()->IsInDocBody() :
694 pFly
->GetAnchorFrm()->IsInFtn() ) ) ) )
696 nTmp
= pFly
->Frm().Bottom();
700 nTmp
= pObj
->GetObjRect().Bottom();
701 nMax
= Max( nTmp
, nMax
);
704 ++nMax
; //Unterkante vs. Hoehe!
705 rBot
= Max( rBot
, nMax
);
708 void SwPageFrm::MakeAll()
710 PROTOCOL_ENTER( this, PROT_MAKEALL
, 0, 0 )
712 const SwRect
aOldRect( Frm() ); //Anpassung der Root-Groesse
713 const SwLayNotify
aNotify( this ); //uebernimmt im DTor die Benachrichtigung
714 SwBorderAttrAccess
*pAccess
= 0;
715 const SwBorderAttrs
*pAttrs
= 0;
717 while ( !bValidPos
|| !bValidSize
|| !bValidPrtArea
)
722 bValidPos
= TRUE
; // positioning of the pages is taken care of by the root frame
725 if ( !bValidSize
|| !bValidPrtArea
)
729 Frm().Width( 0 ); Prt().Width( 0 );
730 Frm().Height( 0 ); Prt().Height( 0 );
731 Prt().Left( 0 ); Prt().Top( 0 );
732 bValidSize
= bValidPrtArea
= TRUE
;
738 pAccess
= new SwBorderAttrAccess( SwFrm::GetCache(), this );
739 pAttrs
= pAccess
->Get();
741 //Bei der BrowseView gelten feste Einstellungen.
742 ViewShell
*pSh
= GetShell();
743 if ( pSh
&& GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
) )
745 const Size aBorder
= pSh
->GetOut()->PixelToLogic( pSh
->GetBrowseBorder() );
746 const long nTop
= pAttrs
->CalcTopLine() + aBorder
.Height();
747 const long nBottom
= pAttrs
->CalcBottomLine()+ aBorder
.Height();
749 long nWidth
= GetUpper() ? ((SwRootFrm
*)GetUpper())->GetBrowseWidth() : 0;
750 if ( nWidth
< pSh
->GetBrowseWidth() )
751 nWidth
= pSh
->GetBrowseWidth();
752 nWidth
+= + 2 * aBorder
.Width();
754 long nWidth = GetUpper() ? ((SwRootFrm*)GetUpper())->GetBrowseWidth() + 2 * aBorder.Width() : 0;
755 if ( nWidth < pSh->VisArea().Width() )
756 nWidth = pSh->VisArea().Width(); */
758 nWidth
= Max( nWidth
, 2L * aBorder
.Width() + 4L*MM50
);
759 Frm().Width( nWidth
);
761 SwLayoutFrm
*pBody
= FindBodyCont();
762 if ( pBody
&& pBody
->Lower() && pBody
->Lower()->IsColumnFrm() )
764 //Fuer Spalten gilt eine feste Hoehe
765 Frm().Height( pAttrs
->GetSize().Height() );
769 //Fuer Seiten ohne Spalten bestimmt der Inhalt die
771 long nBot
= Frm().Top() + nTop
;
772 SwFrm
*pFrm
= Lower();
776 SwFrm
*pCnt
= ((SwLayoutFrm
*)pFrm
)->ContainsAny();
777 while ( pCnt
&& (pCnt
->GetUpper() == pFrm
||
778 ((SwLayoutFrm
*)pFrm
)->IsAnLower( pCnt
)))
780 nTmp
+= pCnt
->Frm().Height();
781 if( pCnt
->IsTxtFrm() &&
782 ((SwTxtFrm
*)pCnt
)->IsUndersized() )
783 nTmp
+= ((SwTxtFrm
*)pCnt
)->GetParHeight()
784 - pCnt
->Prt().Height();
785 else if( pCnt
->IsSctFrm() &&
786 ((SwSectionFrm
*)pCnt
)->IsUndersized() )
787 nTmp
+= ((SwSectionFrm
*)pCnt
)->Undersize();
788 pCnt
= pCnt
->FindNext();
790 // OD 29.10.2002 #97265# - consider invalid body frame properties
791 if ( pFrm
->IsBodyFrm() &&
792 ( !pFrm
->GetValidSizeFlag() ||
793 !pFrm
->GetValidPrtAreaFlag() ) &&
794 ( pFrm
->Frm().Height() < pFrm
->Prt().Height() )
797 nTmp
= Min( nTmp
, pFrm
->Frm().Height() );
801 // OD 30.10.2002 #97265# - assert invalid lower property
802 ASSERT( !(pFrm
->Frm().Height() < pFrm
->Prt().Height()),
803 "SwPageFrm::MakeAll(): Lower with frame height < printing height" );
804 nTmp
+= pFrm
->Frm().Height() - pFrm
->Prt().Height();
806 if ( !pFrm
->IsBodyFrm() )
807 nTmp
= Min( nTmp
, pFrm
->Frm().Height() );
809 // Hier werden die absatzgebundenen Objekte ueberprueft,
810 // ob sie ueber den Body/FtnCont hinausragen.
811 if( pSortedObjs
&& !pFrm
->IsHeaderFrm() &&
812 !pFrm
->IsFooterFrm() )
813 lcl_CheckObjects( pSortedObjs
, pFrm
, nBot
);
814 pFrm
= pFrm
->GetNext();
817 //Und die Seitengebundenen
819 lcl_CheckObjects( pSortedObjs
, this, nBot
);
821 // --> OD 2004-11-10 #i35143# - If second page frame
822 // exists, the first page doesn't have to fulfill the
824 if ( !GetPrev() && !GetNext() )
827 nBot
= Max( nBot
, pSh
->VisArea().Height() );
829 // --> OD 2004-11-10 #i35143# - Assure, that the page
830 // doesn't exceed the defined browse height.
831 Frm().Height( Min( nBot
, BROWSE_HEIGHT
) );
834 Prt().Left ( pAttrs
->CalcLeftLine() + aBorder
.Width() );
836 Prt().Width( Frm().Width() - ( Prt().Left()
837 + pAttrs
->CalcRightLine() + aBorder
.Width() ) );
838 Prt().Height( Frm().Height() - (nTop
+ nBottom
) );
839 bValidSize
= bValidPrtArea
= TRUE
;
842 { //FixSize einstellen, bei Seiten nicht vom Upper sondern vom
843 //Attribut vorgegeben.
844 Frm().SSize( pAttrs
->GetSize() );
849 } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
853 if ( Frm() != aOldRect
&& GetUpper() )
854 static_cast<SwRootFrm
*>(GetUpper())->CheckViewLayout( 0, 0 );
857 //Der Upper (Root) muss mindestens so breit
858 //sein, dass er die breiteste Seite aufnehmen kann.
861 ASSERT( GetUpper()->Prt().Width() >= aFrm
.Width(), "Rootsize" );
866 /*************************************************************************
868 |* SwLayoutFrm::MakeAll()
870 |* Ersterstellung MA ??
871 |* Letzte Aenderung MA 28. Nov. 95
873 |*************************************************************************/
876 void SwLayoutFrm::MakeAll()
878 PROTOCOL_ENTER( this, PROT_MAKEALL
, 0, 0 )
880 //uebernimmt im DTor die Benachrichtigung
881 const SwLayNotify
aNotify( this );
882 BOOL bVert
= IsVertical();
883 SwRectFn fnRect
= ( IsNeighbourFrm() == bVert
)? fnRectHori
: fnRectVert
;
885 SwBorderAttrAccess
*pAccess
= 0;
886 const SwBorderAttrs
*pAttrs
= 0;
888 while ( !bValidPos
|| !bValidSize
|| !bValidPrtArea
)
896 if ( IsLeaveUpperAllowed() )
899 bValidPrtArea
= FALSE
;
905 //FixSize einstellen, die VarSize wird von Format() nach
906 //Berechnung der PrtArea eingestellt.
907 bValidPrtArea
= FALSE
;
909 SwTwips nPrtWidth
= (GetUpper()->Prt().*fnRect
->fnGetWidth
)();
910 if( bVert
&& ( IsBodyFrm() || IsFtnContFrm() ) )
912 SwFrm
* pNxt
= GetPrev();
913 while( pNxt
&& !pNxt
->IsHeaderFrm() )
914 pNxt
= pNxt
->GetPrev();
916 nPrtWidth
-= pNxt
->Frm().Height();
918 while( pNxt
&& !pNxt
->IsFooterFrm() )
919 pNxt
= pNxt
->GetNext();
921 nPrtWidth
-= pNxt
->Frm().Height();
924 const long nDiff
= nPrtWidth
- (Frm().*fnRect
->fnGetWidth
)();
926 if( IsNeighbourFrm() && IsRightToLeft() )
927 (Frm().*fnRect
->fnSubLeft
)( nDiff
);
929 (Frm().*fnRect
->fnAddRight
)( nDiff
);
933 // Don't leave your upper
934 const SwTwips nDeadLine
= (GetUpper()->*fnRect
->fnGetPrtBottom
)();
935 if( (Frm().*fnRect
->fnOverStep
)( nDeadLine
) )
940 if ( !bValidSize
|| !bValidPrtArea
)
944 pAccess
= new SwBorderAttrAccess( SwFrm::GetCache(), this );
945 pAttrs
= pAccess
->Get();
949 } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
954 /*************************************************************************
956 |* SwCntntFrm::MakePrtArea()
958 |* Ersterstellung MA 17. Nov. 92
959 |* Letzte Aenderung MA 03. Mar. 96
961 |*************************************************************************/
962 bool SwTxtNode::IsCollapse() const
964 if ( GetDoc()->get( IDocumentSettingAccess::COLLAPSE_EMPTY_CELL_PARA
) && GetTxt().Len()==0 ) {
965 ULONG nIdx
=GetIndex();
966 const SwEndNode
*pNdBefore
=GetNodes()[nIdx
-1]->GetEndNode();
967 const SwEndNode
*pNdAfter
=GetNodes()[nIdx
+1]->GetEndNode();
969 // The paragraph is collapsed only if the NdAfter is the end of a cell
970 bool bInTable
= this->FindTableNode( ) != NULL
;
972 SwSortedObjs
* pObjs
= this->GetFrm()->GetDrawObjs( );
973 sal_uInt32 nObjs
= ( pObjs
!= NULL
) ? pObjs
->Count( ) : 0;
975 if ( pNdBefore
!=NULL
&& pNdAfter
!=NULL
&& nObjs
== 0 && bInTable
) {
984 bool SwFrm::IsCollapse() const
987 const SwTxtFrm
*pTxtFrm
=(SwTxtFrm
*)this;
988 const SwTxtNode
*pTxtNode
=pTxtFrm
->GetTxtNode();
989 if (pTxtNode
&& pTxtNode
->IsCollapse()) {
999 BOOL
SwCntntFrm::MakePrtArea( const SwBorderAttrs
&rAttrs
)
1001 BOOL bSizeChgd
= FALSE
;
1003 if ( !bValidPrtArea
)
1005 bValidPrtArea
= TRUE
;
1008 const BOOL bTxtFrm
= IsTxtFrm();
1010 if ( bTxtFrm
&& ((SwTxtFrm
*)this)->IsHiddenNow() )
1012 if ( ((SwTxtFrm
*)this)->HasFollow() )
1013 ((SwTxtFrm
*)this)->JoinFrm();
1015 if( (Prt().*fnRect
->fnGetHeight
)() )
1016 ((SwTxtFrm
*)this)->HideHidden();
1017 Prt().Pos().X() = Prt().Pos().Y() = 0;
1018 (Prt().*fnRect
->fnSetWidth
)( (Frm().*fnRect
->fnGetWidth
)() );
1019 (Prt().*fnRect
->fnSetHeight
)( 0 );
1020 nUpper
= -( (Frm().*fnRect
->fnGetHeight
)() );
1024 //Vereinfachung: CntntFrms sind immer in der Hoehe Variabel!
1026 //An der FixSize gibt der umgebende Frame die Groesse vor, die
1027 //Raender werden einfach abgezogen.
1028 const long nLeft
= rAttrs
.CalcLeft( this );
1029 const long nRight
= ((SwBorderAttrs
&)rAttrs
).CalcRight( this );
1030 (this->*fnRect
->fnSetXMargins
)( nLeft
, nRight
);
1032 ViewShell
*pSh
= GetShell();
1034 if( pSh
&& 0!=(nWidthArea
=(pSh
->VisArea().*fnRect
->fnGetWidth
)()) &&
1035 GetUpper()->IsPageBodyFrm() && // nicht dagegen bei BodyFrms in Columns
1036 pSh
->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
) )
1038 //Nicht ueber die Kante des sichbaren Bereiches hinausragen.
1039 //Die Seite kann breiter sein, weil es Objekte mit "ueberbreite"
1040 //geben kann (RootFrm::ImplCalcBrowseWidth())
1043 for (USHORT i
= 0; GetDrawObjs() && i
< GetDrawObjs()->Count();++i
)
1045 // --> OD 2004-07-01 #i28701# - consider changed type of
1046 // <SwSortedObjs> entries
1047 SwAnchoredObject
* pObj
= (*GetDrawObjs())[i
];
1048 const SwFrmFmt
& rFmt
= pObj
->GetFrmFmt();
1049 const BOOL bFly
= pObj
->ISA(SwFlyFrm
);
1051 WEIT_WECH
== pObj
->GetObjRect().Width()||
1052 rFmt
.GetFrmSize().GetWidthPercent() )
1055 if ( FLY_IN_CNTNT
== rFmt
.GetAnchor().GetAnchorId() )
1056 nMinWidth
= Max( nMinWidth
,
1057 bFly
? rFmt
.GetFrmSize().GetWidth()
1058 : pObj
->GetObjRect().Width() );
1062 const Size aBorder
= pSh
->GetOut()->PixelToLogic( pSh
->GetBrowseBorder() );
1063 long nWidth
= nWidthArea
- 2 * ( IsVertical() ? aBorder
.Height() : aBorder
.Width() );
1064 nWidth
-= (Prt().*fnRect
->fnGetLeft
)();
1065 nWidth
-= rAttrs
.CalcRightLine();
1066 nWidth
= Max( nMinWidth
, nWidth
);
1067 (Prt().*fnRect
->fnSetWidth
)( Min( nWidth
,
1068 (Prt().*fnRect
->fnGetWidth
)() ) );
1071 if ( (Prt().*fnRect
->fnGetWidth
)() <= MINLAY
)
1073 //Die PrtArea sollte schon wenigstens MINLAY breit sein, passend
1074 //zu den Minimalwerten des UI
1075 (Prt().*fnRect
->fnSetWidth
)( Min( long(MINLAY
),
1076 (Frm().*fnRect
->fnGetWidth
)() ) );
1077 SwTwips nTmp
= (Frm().*fnRect
->fnGetWidth
)() -
1078 (Prt().*fnRect
->fnGetWidth
)();
1079 if( (Prt().*fnRect
->fnGetLeft
)() > nTmp
)
1080 (Prt().*fnRect
->fnSetLeft
)( nTmp
);
1083 //Fuer die VarSize gelten folgende Regeln:
1084 //1. Der erste einer Kette hat keinen Rand nach oben
1085 //2. Nach unten gibt es nie einen Rand
1086 //3. Der Rand nach oben ist das Maximum aus dem Abstand des
1087 // Prev nach unten und dem eigenen Abstand nach oben.
1088 //Die drei Regeln werden auf die Berechnung der Freiraeume, die von
1089 //UL- bzw. LRSpace vorgegeben werden, angewand. Es gibt in alle
1090 //Richtungen jedoch ggf. trotzdem einen Abstand; dieser wird durch
1091 //Umrandung und/oder Schatten vorgegeben.
1092 //4. Der Abstand fuer TextFrms entspricht mindestens dem Durchschuss
1094 nUpper
= CalcUpperSpace( &rAttrs
, NULL
);
1096 // OD 2004-03-02 #106629# - use new method <CalcLowerSpace(..)>
1097 SwTwips nLower
= CalcLowerSpace( &rAttrs
);
1099 ViewShell
*pSh
= GetShell();
1103 // // in balanced columned section frames we do not want the
1105 // sal_Bool bCommonBorder = sal_True;
1106 // if ( IsInSct() && GetUpper()->IsColBodyFrm() )
1108 // const SwSectionFrm* pSct = FindSctFrm();
1109 // bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue();
1111 // SwTwips nLower = bCommonBorder ?
1112 // rAttrs.GetBottomLine( this ) :
1113 // rAttrs.CalcBottomLine();
1115 (Prt().*fnRect
->fnSetPosY
)( (!bVert
|| bReverse
) ? nUpper
: nLower
);
1117 nUpper
-= (Frm().*fnRect
->fnGetHeight
)() -
1118 (Prt().*fnRect
->fnGetHeight
)();
1120 //Wenn Unterschiede zwischen Alter und neuer Groesse,
1121 //Grow() oder Shrink() rufen
1127 ShrinkFrm( -nUpper
);
1134 /*************************************************************************
1136 |* SwCntntFrm::MakeAll()
1138 |* Ersterstellung MA ??
1139 |* Letzte Aenderung MA 16. Dec. 96
1141 |*************************************************************************/
1143 #define STOP_FLY_FORMAT 10
1144 // --> OD 2006-09-25 #b6448963# - loop prevention
1145 const int cnStopFormat
= 15;
1148 inline void ValidateSz( SwFrm
*pFrm
)
1152 pFrm
->bValidSize
= TRUE
;
1153 pFrm
->bValidPrtArea
= TRUE
;
1157 void SwCntntFrm::MakeAll()
1159 ASSERT( GetUpper(), "keinen Upper?" );
1160 ASSERT( IsTxtFrm(), "MakeAll(), NoTxt" );
1162 if ( !IsFollow() && StackHack::IsLocked() )
1165 if ( IsJoinLocked() )
1168 ASSERT( !((SwTxtFrm
*)this)->IsSwapped(), "Calculation of a swapped frame" );
1172 if ( ((SwTxtFrm
*)this)->IsLocked() )
1174 ASSERT( FALSE
, "Format fuer gelockten TxtFrm." );
1179 long nFormatCount
= 0;
1180 // --> OD 2006-09-25 #b6448963# - loop prevention
1181 int nConsequetiveFormatsWithoutChange
= 0;
1183 PROTOCOL_ENTER( this, PROT_MAKEALL
, 0, 0 )
1186 const SwDoc
*pDoc
= GetAttrSet()->GetDoc();
1189 static sal_Bool bWarn
= sal_False
;
1190 if( pDoc
->InXMLExport() )
1192 ASSERT( bWarn
, "Formatting during XML-export!" );
1200 //uebernimmt im DTor die Benachrichtigung
1201 SwCntntNotify
*pNotify
= new SwCntntNotify( this );
1203 BOOL bMakePage
= TRUE
; //solange TRUE kann eine neue Seite
1204 //angelegt werden (genau einmal)
1205 BOOL bMovedBwd
= FALSE
; //Wird TRUE wenn der Frame zurueckfliesst
1206 BOOL bMovedFwd
= FALSE
; //solange FALSE kann der Frm zurueck-
1207 //fliessen (solange, bis er einmal
1208 //vorwaerts ge'moved wurde).
1209 BOOL bFormatted
= FALSE
; //Fuer die Witwen und Waisen Regelung
1210 //wird der letzte CntntFrm einer Kette
1211 //u.U. zum Formatieren angeregt, dies
1212 //braucht nur einmal zu passieren.
1213 //Immer wenn der Frm gemoved wird muss
1214 //das Flag zurueckgesetzt werden.
1215 BOOL bMustFit
= FALSE
; //Wenn einmal die Notbremse gezogen wurde,
1216 //werden keine anderen Prepares mehr
1218 BOOL bFitPromise
= FALSE
; //Wenn ein Absatz nicht passte, mit WouldFit
1219 //aber verspricht, dass er sich passend
1220 //einstellt wird dieses Flag gesetzt.
1221 //Wenn er dann sein Versprechen nicht haelt,
1222 //kann kontrolliert verfahren werden.
1224 const BOOL bFly
= IsInFly();
1225 const BOOL bTab
= IsInTab();
1226 const BOOL bFtn
= IsInFtn();
1227 const BOOL bSct
= IsInSct();
1228 Point aOldFrmPos
; //Damit bei Turnarounds jew. mit der
1229 Point aOldPrtPos
; //letzten Pos verglichen und geprueft
1230 //werden kann, ob ein Prepare sinnvoll ist.
1232 SwBorderAttrAccess
aAccess( SwFrm::GetCache(), this );
1233 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
1235 // OD 2004-02-26 #i25029#
1236 if ( !IsFollow() && rAttrs
.JoinedWithPrev( *(this) ) )
1238 pNotify
->SetBordersJoinedWithPrev();
1241 const BOOL bKeep
= IsKeep( rAttrs
.GetAttrSet() );
1243 SwSaveFtnHeight
*pSaveFtn
= 0;
1246 SwFtnFrm
*pFtn
= FindFtnFrm();
1247 SwSectionFrm
* pSct
= pFtn
->FindSctFrm();
1248 if ( !((SwTxtFrm
*)pFtn
->GetRef())->IsLocked() )
1250 SwFtnBossFrm
* pBoss
= pFtn
->GetRef()->FindFtnBossFrm(
1251 pFtn
->GetAttr()->GetFtn().IsEndNote() );
1252 if( !pSct
|| pSct
->IsColLocked() || !pSct
->Growable() )
1253 pSaveFtn
= new SwSaveFtnHeight( pBoss
,
1254 ((SwTxtFrm
*)pFtn
->GetRef())->GetFtnLine( pFtn
->GetAttr() ) );
1258 // --> OD 2008-08-12 #b6732519#
1259 if ( GetUpper()->IsSctFrm() &&
1261 GetFollow()->GetFrm() == GetNext() )
1263 dynamic_cast<SwTxtFrm
*>(this)->JoinFrm();
1267 // --> OD 2004-06-23 #i28701# - move master forward, if it has to move,
1268 // because of its object positioning.
1269 if ( !static_cast<SwTxtFrm
*>(this)->IsFollow() )
1271 sal_uInt32 nToPageNum
= 0L;
1272 const bool bMoveFwdByObjPos
= SwLayouter::FrmMovedFwdByObjPos(
1273 *(GetAttrSet()->GetDoc()),
1274 *(static_cast<SwTxtFrm
*>(this)),
1276 // --> OD 2006-01-27 #i58182#
1277 // Also move a paragraph forward, which is the first one inside a table cell.
1278 if ( bMoveFwdByObjPos
&&
1279 FindPageFrm()->GetPhyPageNum() < nToPageNum
&&
1280 ( lcl_Prev( this ) ||
1281 GetUpper()->IsCellFrm() ||
1282 ( GetUpper()->IsSctFrm() &&
1283 GetUpper()->GetUpper()->IsCellFrm() ) ) &&
1287 MoveFwd( bMakePage
, FALSE
);
1293 //Wenn ein Follow neben seinem Master steht und nicht passt, kann er
1294 //gleich verschoben werden.
1295 if ( lcl_Prev( this ) && ((SwTxtFrm
*)this)->IsFollow() && IsMoveable() )
1298 // OD 2004-03-02 #106629# - If follow frame is in table, it's master
1299 // will be the last in the current table cell. Thus, invalidate the
1300 // printing area of the master,
1303 lcl_Prev( this )->InvalidatePrt();
1305 MoveFwd( bMakePage
, FALSE
);
1308 // OD 08.11.2002 #104840# - check footnote content for forward move.
1309 // If a content of a footnote is on a prior page/column as its invalid
1310 // reference, it can be moved forward.
1311 if ( bFtn
&& !bValidPos
)
1313 SwFtnFrm
* pFtn
= FindFtnFrm();
1314 SwCntntFrm
* pRefCnt
= pFtn
? pFtn
->GetRef() : 0;
1315 if ( pRefCnt
&& !pRefCnt
->IsValid() )
1317 SwFtnBossFrm
* pFtnBossOfFtn
= pFtn
->FindFtnBossFrm();
1318 SwFtnBossFrm
* pFtnBossOfRef
= pRefCnt
->FindFtnBossFrm();
1319 //<loop of movefwd until condition held or no move>
1320 if ( pFtnBossOfFtn
&& pFtnBossOfRef
&&
1321 pFtnBossOfFtn
!= pFtnBossOfRef
&&
1322 pFtnBossOfFtn
->IsBefore( pFtnBossOfRef
) )
1325 MoveFwd( bMakePage
, FALSE
);
1332 while ( !bValidPos
|| !bValidSize
|| !bValidPrtArea
)
1334 // --> OD 2006-09-25 #b6448963# - loop prevention
1335 SwRect
aOldFrm_StopFormat( Frm() );
1336 SwRect
aOldPrt_StopFormat( Prt() );
1338 if ( TRUE
== (bMoveable
= IsMoveable()) )
1340 SwFrm
*pPre
= GetIndPrev();
1341 if ( CheckMoveFwd( bMakePage
, bKeep
, bMovedBwd
) )
1347 //Beim zurueckfliessen wurde der Upper angeregt sich
1348 //vollstaendig zu Painten, dass koennen wir uns jetzt
1349 //nach dem hin und her fliessen sparen.
1350 GetUpper()->ResetCompletePaint();
1351 //Der Vorgaenger wurde Invalidiert, das ist jetzt auch obsolete.
1352 ASSERT( pPre
, "missing old Prev" );
1353 if( !pPre
->IsSctFrm() )
1354 ::ValidateSz( pPre
);
1356 bMoveable
= IsMoveable();
1360 aOldFrmPos
= (Frm().*fnRect
->fnGetPos
)();
1361 aOldPrtPos
= (Prt().*fnRect
->fnGetPos
)();
1366 //FixSize einstellen, die VarSize wird von Format() justiert.
1369 // --> OD 2006-01-03 #125452#
1370 // invalidate printing area flag, if the following conditions are hold:
1371 // - current frame width is 0.
1372 // - current printing area width is 0.
1373 // - frame width is adjusted to a value greater than 0.
1374 // - printing area flag is TRUE.
1375 // Thus, it's assured that the printing area is adjusted, if the
1376 // frame area width changes its width from 0 to something greater
1378 // Note: A text frame can be in such a situation, if the format is
1379 // triggered by method call <SwCrsrShell::SetCrsr()> after
1380 // loading the document.
1381 const SwTwips nNewFrmWidth
= (GetUpper()->Prt().*fnRect
->fnGetWidth
)();
1382 if ( bValidPrtArea
&& nNewFrmWidth
> 0 &&
1383 (Frm().*fnRect
->fnGetWidth
)() == 0 &&
1384 (Prt().*fnRect
->fnGetWidth
)() == 0 )
1386 bValidPrtArea
= FALSE
;
1389 (Frm().*fnRect
->fnSetWidth
)( nNewFrmWidth
);
1392 if ( !bValidPrtArea
)
1394 const long nOldW
= (Prt().*fnRect
->fnGetWidth
)();
1395 // --> OD 2004-09-28 #i34730# - keep current frame height
1396 const SwTwips nOldH
= (Frm().*fnRect
->fnGetHeight
)();
1398 MakePrtArea( rAttrs
);
1399 if ( nOldW
!= (Prt().*fnRect
->fnGetWidth
)() )
1400 Prepare( PREP_FIXSIZE_CHG
);
1401 // --> OD 2004-09-28 #i34730# - check, if frame height has changed.
1402 // If yes, send a PREP_ADJUST_FRM and invalidate the size flag to
1403 // force a format. The format will check in its method
1404 // <SwTxtFrm::CalcPreps()>, if the already formatted lines still
1405 // fit and if not, performs necessary actions.
1406 // --> OD 2005-01-10 #i40150# - no check, if frame is undersized.
1407 if ( bValidSize
&& !IsUndersized() &&
1408 nOldH
!= (Frm().*fnRect
->fnGetHeight
)() )
1410 // --> OD 2004-11-25 #115759# - no PREP_ADJUST_FRM and size
1411 // invalidation, if height decreases only by the additional
1412 // lower space as last content of a table cell and an existing
1413 // follow containing one line exists.
1414 const SwTwips nHDiff
= nOldH
- (Frm().*fnRect
->fnGetHeight
)();
1415 const bool bNoPrepAdjustFrm
=
1416 nHDiff
> 0 && IsInTab() && GetFollow() &&
1417 ( 1 == static_cast<SwTxtFrm
*>(GetFollow())->GetLineCount( STRING_LEN
) || (static_cast<SwTxtFrm
*>(GetFollow())->Frm().*fnRect
->fnGetWidth
)() < 0 ) &&
1418 GetFollow()->CalcAddLowerSpaceAsLastInTableCell() == nHDiff
;
1419 if ( !bNoPrepAdjustFrm
)
1421 Prepare( PREP_ADJUST_FRM
);
1429 //Damit die Witwen- und Waisen-Regelung eine Change bekommt muss der
1430 //CntntFrm benachrichtigt werden.
1432 //- Er muss Moveable sein (sonst mach das Spalten keinen Sinn.)
1433 //- Er muss mit der Unterkante der PrtArea des Upper ueberlappen.
1437 const SwTwips nDeadLine
= (GetUpper()->*fnRect
->fnGetPrtBottom
)();
1438 if ( bMoveable
&& !bFormatted
&& ( GetFollow() ||
1439 ( (Frm().*fnRect
->fnOverStep
)( nDeadLine
) ) ) )
1441 Prepare( PREP_WIDOWS_ORPHANS
, 0, FALSE
);
1442 bValidSize
= bWidow
= FALSE
;
1444 if( (Frm().*fnRect
->fnGetPos
)() != aOldFrmPos
||
1445 (Prt().*fnRect
->fnGetPos
)() != aOldPrtPos
)
1447 // In diesem Prepare erfolgt ggf. ein _InvalidateSize().
1448 // bValidSize wird FALSE und das Format() wird gerufen.
1449 Prepare( PREP_POS_CHGD
, (const void*)&bFormatted
, FALSE
);
1450 if ( bWidow
&& GetFollow() )
1451 { Prepare( PREP_WIDOWS_ORPHANS
, 0, FALSE
);
1458 bValidSize
= bFormatted
= TRUE
;
1460 if( nFormatCount
> STOP_FLY_FORMAT
)
1462 // --> OD 2006-09-25 #b6448963# - loop prevention
1463 // No format any longer, if <cnStopFormat> consequetive formats
1464 // without change occur.
1465 if ( nConsequetiveFormatsWithoutChange
<= cnStopFormat
)
1469 #if OSL_DEBUG_LEVEL > 1
1472 ASSERT( false, "debug assertion: <SwCntntFrm::MakeAll()> - format of text frame suppressed by fix b6448963" );
1478 // FME 16.07.2003 #i16930# - removed this code because it did not work
1480 // OD 04.04.2003 #108446# - react on the situation detected in the text
1481 // formatting - see <SwTxtFrm::FormatAdjust(..)>:
1482 // text frame has to move forward, because its text formatting stopped,
1483 // created a follow and detected, that it contains no content.
1484 /* if ( IsTxtFrm() && bValidPos && bValidSize && bValidPrtArea &&
1485 (Frm().*fnRect->fnGetHeight)() == 0 &&
1489 SwFrm* pOldUpper = GetUpper();
1490 MoveFwd( TRUE, FALSE );
1491 if ( GetUpper() != pOldUpper )
1499 //Wenn ich der erste einer Kette bin koennte ich mal sehen ob
1500 //ich zurueckfliessen kann (wenn ich mich ueberhaupt bewegen soll).
1501 //Damit es keine Oszillation gibt, darf ich nicht gerade vorwaerts
1504 if ( !lcl_Prev( this ) &&
1506 ( bMoveable
|| ( bFly
&& !bTab
) ) &&
1507 ( !bFtn
|| !GetUpper()->FindFtnFrm()->GetPrev() )
1508 && MoveBwd( bDummy
) )
1513 if ( bKeep
&& bMoveable
)
1515 if( CheckMoveFwd( bMakePage
, FALSE
, bMovedBwd
) )
1518 bMoveable
= IsMoveable();
1521 Point aOldPos
= (Frm().*fnRect
->fnGetPos
)();
1523 if( aOldPos
!= (Frm().*fnRect
->fnGetPos
)() )
1525 Prepare( PREP_POS_CHGD
, (const void*)&bFormatted
, FALSE
);
1528 (Frm().*fnRect
->fnSetWidth
)( (GetUpper()->
1529 Prt().*fnRect
->fnGetWidth
)() );
1530 if ( !bValidPrtArea
)
1532 const long nOldW
= (Prt().*fnRect
->fnGetWidth
)();
1533 MakePrtArea( rAttrs
);
1534 if( nOldW
!= (Prt().*fnRect
->fnGetWidth
)() )
1535 Prepare( PREP_FIXSIZE_CHG
, 0, FALSE
);
1538 Prepare( PREP_WIDOWS_ORPHANS
, 0, FALSE
);
1539 bValidSize
= bFormatted
= TRUE
;
1543 SwFrm
*pNxt
= HasFollow() ? NULL
: FindNext();
1544 while( pNxt
&& pNxt
->IsSctFrm() )
1545 { // Leere Bereiche auslassen, in die anderen hinein
1546 if( ((SwSectionFrm
*)pNxt
)->GetSection() )
1548 SwFrm
* pTmp
= ((SwSectionFrm
*)pNxt
)->ContainsAny();
1555 pNxt
= pNxt
->FindNext();
1560 if( bValidPos
&& !GetIndNext() )
1562 SwSectionFrm
*pSct
= FindSctFrm();
1563 if( pSct
&& !pSct
->GetValidSizeFlag() )
1565 SwSectionFrm
* pNxtSct
= pNxt
->FindSctFrm();
1566 if( pNxtSct
&& pSct
->IsAnFollow( pNxtSct
) )
1576 //Der TxtFrm Validiert sich bei Fussnoten ggf. selbst, dass kann leicht
1577 //dazu fuehren, dass seine Position obwohl unrichtig valide ist.
1580 // --> OD 2006-01-23 #i59341#
1581 // Workaround for inadequate layout algorithm:
1582 // suppress invalidation and calculation of position, if paragraph
1583 // has formatted itself at least STOP_FLY_FORMAT times and
1584 // has anchored objects.
1585 // Thus, the anchored objects get the possibility to format itself
1586 // and this probably solve the layout loop.
1588 nFormatCount
<= STOP_FLY_FORMAT
&&
1594 aOldFrmPos
= (Frm().*fnRect
->fnGetPos
)();
1595 aOldPrtPos
= (Prt().*fnRect
->fnGetPos
)();
1599 // --> OD 2006-09-25 #b6448963# - loop prevention
1601 if ( aOldFrm_StopFormat
== Frm() &&
1602 aOldPrt_StopFormat
== Prt() )
1604 ++nConsequetiveFormatsWithoutChange
;
1608 nConsequetiveFormatsWithoutChange
= 0;
1613 //Wieder ein Wert ungueltig? - dann nochmal das ganze...
1614 if ( !bValidPos
|| !bValidSize
|| !bValidPrtArea
)
1618 // Achtung, wg. Hoehe==0, ist es besser statt Bottom() Top()+Height() zu nehmen
1619 // (kommt bei Undersized TxtFrms an der Unterkante eines spaltigen Bereichs vor)
1620 const long nPrtBottom
= (GetUpper()->*fnRect
->fnGetPrtBottom
)();
1621 const long nBottomDist
= (Frm().*fnRect
->fnBottomDist
)( nPrtBottom
);
1622 if( nBottomDist
>= 0 )
1624 if ( bKeep
&& bMoveable
)
1626 //Wir sorgen dafuer, dass der Nachfolger gleich mit formatiert
1627 //wird. Dadurch halten wir das Heft in der Hand, bis wirklich
1628 //(fast) alles stabil ist. So vermeiden wir Endlosschleifen,
1629 //die durch staendig wiederholte Versuche entstehen.
1630 //Das bMoveFwdInvalid ist fuer #38407# notwendig. War urspruenglich
1631 //in flowfrm.cxx rev 1.38 behoben, das unterbrach aber obiges
1632 //Schema und spielte lieber Tuerme von Hanoi (#43669#).
1633 SwFrm
*pNxt
= HasFollow() ? NULL
: FindNext();
1634 // Bei Bereichen nehmen wir lieber den Inhalt, denn nur
1635 // dieser kann ggf. die Seite wechseln
1636 while( pNxt
&& pNxt
->IsSctFrm() )
1638 if( ((SwSectionFrm
*)pNxt
)->GetSection() )
1640 pNxt
= ((SwSectionFrm
*)pNxt
)->ContainsAny();
1643 pNxt
= pNxt
->FindNext();
1647 const BOOL bMoveFwdInvalid
= 0 != GetIndNext();
1648 const BOOL bNxtNew
=
1649 ( 0 == (pNxt
->Prt().*fnRect
->fnGetHeight
)() ) &&
1650 (!pNxt
->IsTxtFrm() ||!((SwTxtFrm
*)pNxt
)->IsHiddenNow());
1655 ((bMoveFwdInvalid
&& !GetIndNext()) ||
1659 pNotify
->SetInvaKeep();
1667 //Ich passe nicht mehr in meinen Uebergeordneten, also ist es jetzt
1668 //an der Zeit moeglichst konstruktive Veranderungen vorzunehmen
1670 //Wenn ich den uebergeordneten Frm nicht verlassen darf, habe
1671 //ich ein Problem; Frei nach Artur Dent tun wir das einzige das man
1672 //mit einen nicht loesbaren Problem tun kann: wir ignorieren es - und
1673 //zwar mit aller Kraft.
1674 if ( !bMoveable
|| IsUndersized() )
1676 if( !bMoveable
&& IsInTab() )
1678 long nDiff
= -(Frm().*fnRect
->fnBottomDist
)(
1679 (GetUpper()->*fnRect
->fnGetPrtBottom
)() );
1680 long nReal
= GetUpper()->Grow( nDiff
);
1687 //Wenn ich nun ueberhaupt ganz und garnicht in meinen Upper passe
1688 //so kann die Situation vielleicht doch noch durch Aufbrechen
1689 //aufgeklart werden. Diese Situation tritt bei einem frisch
1690 //erzeugten Follow auf, der zwar auf die Folgeseite geschoben wurde
1691 //aber selbst noch zu gross fuer diese ist; also wiederum
1692 //aufgespalten werden muss.
1693 //Wenn ich nicht passe und nicht Spaltbar (WouldFit()) bin, so schicke
1694 //ich meinem TxtFrmanteil die Nachricht, dass eben falls moeglich
1695 //trotz des Attributes 'nicht aufspalten' aufgespalten werden muss.
1696 BOOL bMoveOrFit
= FALSE
;
1697 BOOL bDontMoveMe
= !GetIndPrev();
1698 if( bDontMoveMe
&& IsInSct() )
1700 SwFtnBossFrm
* pBoss
= FindFtnBossFrm();
1701 bDontMoveMe
= !pBoss
->IsInSct() ||
1702 ( !pBoss
->Lower()->GetNext() && !pBoss
->GetPrev() );
1705 // Finally, we are able to split table rows. Therefore, bDontMoveMe
1706 // can be set to FALSE:
1707 if( bDontMoveMe
&& IsInTab() &&
1708 0 != const_cast<SwCntntFrm
*>(this)->GetNextCellLeaf( MAKEPAGE_NONE
) )
1709 bDontMoveMe
= FALSE
;
1711 if ( bDontMoveMe
&& (Frm().*fnRect
->fnGetHeight
)() >
1712 (GetUpper()->Prt().*fnRect
->fnGetHeight
)() )
1716 SwTwips nTmp
= (GetUpper()->Prt().*fnRect
->fnGetHeight
)() -
1717 (Prt().*fnRect
->fnGetTop
)();
1718 BOOL bSplit
= !IsFwdMoveAllowed();
1719 if ( nTmp
> 0 && WouldFit( nTmp
, bSplit
, sal_False
) )
1721 Prepare( PREP_WIDOWS_ORPHANS
, 0, FALSE
);
1726 /* -----------------19.02.99 12:58-------------------
1727 * Frueher wurde in Rahmen und Bereichen niemals versucht,
1728 * durch bMoveOrFit den TxtFrm unter Verzicht auf seine
1729 * Attribute (Widows,Keep) doch noch passend zu bekommen.
1730 * Dies haette zumindest bei spaltigen Rahmen versucht
1731 * werden muessen, spaetestens bei verketteten Rahmen und
1732 * in Bereichen muss es versucht werden.
1733 * Ausnahme: Wenn wir im FormatWidthCols stehen, duerfen die
1734 * Attribute nicht ausser Acht gelassen werden.
1735 * --------------------------------------------------*/
1736 else if ( !bFtn
&& bMoveable
&&
1737 ( !bFly
|| !FindFlyFrm()->IsColLocked() ) &&
1738 ( !bSct
|| !FindSctFrm()->IsColLocked() ) )
1744 ASSERT( FALSE
, "+TxtFrm hat WouldFit-Versprechen nicht eingehalten." );
1749 //Mal sehen ob ich irgenwo Platz finde...
1750 //Benachbarte Fussnoten werden in _MoveFtnCntFwd 'vorgeschoben'
1751 SwFrm
*pPre
= GetIndPrev();
1752 SwFrm
*pOldUp
= GetUpper();
1754 /* MA 13. Oct. 98: Was soll das denn sein!?
1755 * AMA 14. Dec 98: Wenn ein spaltiger Bereich keinen Platz mehr fuer seinen ersten ContentFrm
1756 * bietet, so soll dieser nicht nur in die naechste Spalte, sondern ggf. bis zur naechsten
1757 * Seite wandern und dort einen Section-Follow erzeugen.
1759 if( IsInSct() && bMovedFwd
&& bMakePage
&& pOldUp
->IsColBodyFrm() &&
1760 pOldUp
->GetUpper()->GetUpper()->IsSctFrm() &&
1761 ( pPre
|| pOldUp
->GetUpper()->GetPrev() ) &&
1762 ((SwSectionFrm
*)pOldUp
->GetUpper()->GetUpper())->MoveAllowed(this) )
1765 const sal_Bool bCheckForGrownBody
= pOldUp
->IsBodyFrm();
1766 const long nOldBodyHeight
= (pOldUp
->Frm().*fnRect
->fnGetHeight
)();
1768 if ( !bMovedFwd
&& !MoveFwd( bMakePage
, FALSE
) )
1772 // If MoveFwd moves the paragraph to the next page, a following
1773 // paragraph, which contains footnotes can can cause the old upper
1774 // frame to grow. In this case we explicitely allow a new check
1775 // for MoveBwd. Robust: We also check the bMovedBwd flag again.
1776 // If pOldUp was a footnote frame, it has been deleted inside MoveFwd.
1777 // Therefore we only check for growing body frames.
1778 if ( bCheckForGrownBody
&& ! bMovedBwd
&& pOldUp
!= GetUpper() &&
1779 (pOldUp
->Frm().*fnRect
->fnGetHeight
)() > nOldBodyHeight
)
1785 if ( bMoveOrFit
&& GetUpper() == pOldUp
)
1787 // FME 2007-08-30 #i81146# new loop control
1788 if ( nConsequetiveFormatsWithoutChange
<= cnStopFormat
)
1790 Prepare( PREP_MUST_FIT
, 0, FALSE
);
1796 #if OSL_DEBUG_LEVEL > 1
1797 ASSERT( false, "LoopControl in SwCntntFrm::MakeAll" )
1800 if ( bMovedBwd
&& GetUpper() )
1801 { //Unuetz gewordene Invalidierungen zuruecknehmen.
1802 GetUpper()->ResetCompletePaint();
1803 if( pPre
&& !pPre
->IsSctFrm() )
1804 ::ValidateSz( pPre
);
1807 } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
1810 // NEW: Looping Louie (Light). Should not be applied in balanced sections.
1811 // Should only be applied if there is no better solution!
1812 LOOPING_LOUIE_LIGHT( bMovedFwd
&& bMovedBwd
&& !IsInBalancedSection() &&
1815 // --> FME 2005-01-26 #118572#
1816 ( bFtn
&& !FindFtnFrm()->GetRef()->IsInSct() ) ||
1819 // --> FME 2005-01-27 #i33887#
1820 ( IsInSct() && bKeep
)
1823 // ... add your conditions here ...
1826 static_cast<SwTxtFrm
&>(*this) );
1833 if ( bMovedFwd
|| bMovedBwd
)
1834 pNotify
->SetInvaKeep();
1835 // OD 2004-02-26 #i25029#
1838 pNotify
->SetInvalidatePrevPrtArea();
1841 SetFlyLock( FALSE
);
1844 /*************************************************************************
1846 |* SwCntntFrm::_WouldFit()
1848 |* Ersterstellung MA 28. Feb. 95
1849 |* Letzte Aenderung AMA 15. Feb. 99
1851 |*************************************************************************/
1856 void MakeNxt( SwFrm
*pFrm
, SwFrm
*pNxt
)
1858 //fix(25455): Validieren, sonst kommt es zu einer Rekursion.
1859 //Der erste Versuch, der Abbruch mit pFrm = 0 wenn !Valid,
1860 //fuehrt leider zu dem Problem, dass das Keep dann u.U. nicht mehr
1861 //korrekt beachtet wird (27417)
1862 const BOOL bOldPos
= pFrm
->GetValidPosFlag();
1863 const BOOL bOldSz
= pFrm
->GetValidSizeFlag();
1864 const BOOL bOldPrt
= pFrm
->GetValidPrtAreaFlag();
1865 pFrm
->bValidPos
= pFrm
->bValidPrtArea
= pFrm
->bValidSize
= TRUE
;
1867 //fix(29272): Nicht MakeAll rufen, dort wird evtl. pFrm wieder invalidert
1868 //und kommt rekursiv wieder herein.
1869 if ( pNxt
->IsCntntFrm() )
1871 SwCntntNotify
aNotify( (SwCntntFrm
*)pNxt
);
1872 SwBorderAttrAccess
aAccess( SwFrm::GetCache(), pNxt
);
1873 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
1874 if ( !pNxt
->GetValidSizeFlag() )
1876 if( pNxt
->IsVertical() )
1877 pNxt
->Frm().Height( pNxt
->GetUpper()->Prt().Height() );
1879 pNxt
->Frm().Width( pNxt
->GetUpper()->Prt().Width() );
1881 ((SwCntntFrm
*)pNxt
)->MakePrtArea( rAttrs
);
1882 pNxt
->Format( &rAttrs
);
1886 SwLayNotify
aNotify( (SwLayoutFrm
*)pNxt
);
1887 SwBorderAttrAccess
aAccess( SwFrm::GetCache(), pNxt
);
1888 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
1889 if ( !pNxt
->GetValidSizeFlag() )
1891 if( pNxt
->IsVertical() )
1892 pNxt
->Frm().Height( pNxt
->GetUpper()->Prt().Height() );
1894 pNxt
->Frm().Width( pNxt
->GetUpper()->Prt().Width() );
1896 pNxt
->Format( &rAttrs
);
1899 pFrm
->bValidPos
= bOldPos
;
1900 pFrm
->bValidSize
= bOldSz
;
1901 pFrm
->bValidPrtArea
= bOldPrt
;
1904 // Diese Routine ueberprueft, ob zwischen dem FtnBoss von pFrm und dem
1905 // von pNxt keine anderen FtnBosse liegen
1907 BOOL
lcl_IsNextFtnBoss( const SwFrm
*pFrm
, const SwFrm
* pNxt
)
1909 ASSERT( pFrm
&& pNxt
, "lcl_IsNextFtnBoss: No Frames?" );
1910 pFrm
= pFrm
->FindFtnBossFrm();
1911 pNxt
= pNxt
->FindFtnBossFrm();
1912 // Falls pFrm eine letzte Spalte ist, wird stattdessen die Seite genommen
1913 while( pFrm
&& pFrm
->IsColumnFrm() && !pFrm
->GetNext() )
1914 pFrm
= pFrm
->GetUpper()->FindFtnBossFrm();
1915 // Falls pNxt eine erste Spalte ist, wird stattdessen die Seite genommen
1916 while( pNxt
&& pNxt
->IsColumnFrm() && !pNxt
->GetPrev() )
1917 pNxt
= pNxt
->GetUpper()->FindFtnBossFrm();
1918 // So, jetzt muessen pFrm und pNxt entweder zwei benachbarte Seiten oder Spalten sein.
1919 return ( pFrm
&& pNxt
&& pFrm
->GetNext() == pNxt
);
1922 // --> OD 2007-11-26 #b6614158#
1923 BOOL
SwCntntFrm::_WouldFit( SwTwips nSpace
,
1924 SwLayoutFrm
*pNewUpper
,
1926 const bool bObjsInNewUpper
)
1929 //Damit die Fussnote sich ihren Platz sorgsam waehlt, muss
1930 //sie in jedem Fall gemoved werden, wenn zwischen dem
1931 //neuen Upper und ihrer aktuellen Seite/Spalte mindestens eine
1932 //Seite/Spalte liegt.
1933 SwFtnFrm
* pFtnFrm
= 0;
1936 if( !lcl_IsNextFtnBoss( pNewUpper
, this ) )
1938 pFtnFrm
= FindFtnFrm();
1942 BOOL bSplit
= !pNewUpper
->Lower();
1943 SwCntntFrm
*pFrm
= this;
1944 const SwFrm
*pTmpPrev
= pNewUpper
->Lower();
1945 if( pTmpPrev
&& pTmpPrev
->IsFtnFrm() )
1946 pTmpPrev
= ((SwFtnFrm
*)pTmpPrev
)->Lower();
1947 while ( pTmpPrev
&& pTmpPrev
->GetNext() )
1948 pTmpPrev
= pTmpPrev
->GetNext();
1951 // --> FME 2005-03-31 #b6236853# #i46181#
1952 SwTwips nSecondCheck
= 0;
1953 SwTwips nOldSpace
= nSpace
;
1954 BOOL bOldSplit
= bSplit
;
1957 if ( bTstMove
|| IsInFly() || ( IsInSct() &&
1958 ( pFrm
->GetUpper()->IsColBodyFrm() || ( pFtnFrm
&&
1959 pFtnFrm
->GetUpper()->GetUpper()->IsColumnFrm() ) ) ) )
1961 //Jetzt wirds ein bischen hinterlistig; empfindliche Gemueter sollten
1962 //lieber wegsehen. Wenn ein Flys Spalten enthaelt so sind die Cntnts
1963 //moveable, mit Ausnahme der in der letzten Spalte (siehe
1964 //SwFrm::IsMoveable()). Zurueckfliessen duerfen sie aber natuerlich.
1965 //Das WouldFit() liefert leider nur dann einen vernueftigen Wert, wenn
1966 //der Frm moveable ist. Um dem WouldFit() einen Moveable Frm
1967 //vorzugaukeln haenge ich ihn einfach solange um.
1968 // Auch bei spaltigen Bereichen muss umgehaengt werden, damit
1969 // SwSectionFrm::Growable() den richtigen Wert liefert.
1970 // Innerhalb von Fussnoten muss ggf. sogar der SwFtnFrm umgehaengt werden,
1971 // falls es dort keinen SwFtnFrm gibt.
1972 SwFrm
* pTmpFrm
= pFrm
->IsInFtn() && !pNewUpper
->FindFtnFrm() ?
1973 (SwFrm
*)pFrm
->FindFtnFrm() : pFrm
;
1974 SwLayoutFrm
*pUp
= pTmpFrm
->GetUpper();
1975 SwFrm
*pOldNext
= pTmpFrm
->GetNext();
1977 pTmpFrm
->InsertBefore( pNewUpper
, 0 );
1978 if ( pFrm
->IsTxtFrm() &&
1980 ((SwTxtFrm
*)pFrm
)->HasFollow() ||
1981 ( !((SwTxtFrm
*)pFrm
)->HasPara() &&
1982 !((SwTxtFrm
*)pFrm
)->IsEmpty()
1988 bRet
= ((SwTxtFrm
*)pFrm
)->TestFormat( pTmpPrev
, nSpace
, bSplit
);
1991 bRet
= pFrm
->WouldFit( nSpace
, bSplit
, sal_False
);
1994 pTmpFrm
->InsertBefore( pUp
, pOldNext
);
1998 bRet
= pFrm
->WouldFit( nSpace
, bSplit
, sal_False
);
1999 nSecondCheck
= !bSplit
? 1 : 0;
2002 SwBorderAttrAccess
aAccess( SwFrm::GetCache(), pFrm
);
2003 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
2005 //Bitter aber wahr: Der Abstand muss auch noch mit einkalkuliert werden.
2006 //Bei TestFormatierung ist dies bereits geschehen.
2007 if ( bRet
&& !bTstMove
)
2013 nUpper
= CalcUpperSpace( NULL
, pTmpPrev
);
2015 // in balanced columned section frames we do not want the
2017 sal_Bool bCommonBorder
= sal_True
;
2018 if ( pFrm
->IsInSct() && pFrm
->GetUpper()->IsColBodyFrm() )
2020 const SwSectionFrm
* pSct
= pFrm
->FindSctFrm();
2021 bCommonBorder
= pSct
->GetFmt()->GetBalancedColumns().GetValue();
2024 // --> FME 2005-03-31 #b6236853# #i46181#
2025 nSecondCheck
= ( 1 == nSecondCheck
&&
2029 !static_cast<const SwTxtFrm
*>(this)->IsEmpty() ) ?
2034 nUpper
+= bCommonBorder
?
2035 rAttrs
.GetBottomLine( *(pFrm
) ) :
2036 rAttrs
.CalcBottomLine();
2041 // --> FME 2005-03-31 #b6236853# #i46181#
2045 if( pFrm
->IsVertical() )
2046 nUpper
= pFrm
->Frm().Width() - pFrm
->Prt().Width();
2048 nUpper
= pFrm
->Frm().Height() - pFrm
->Prt().Height();
2057 // --> FME 2005-03-31 #b6236853# #i46181#
2058 if ( nSecondCheck
> 0 )
2060 // The following code is indented to solve a (rare) problem
2061 // causing some frames not to move backward:
2062 // SwTxtFrm::WouldFit() claims that the whole paragraph
2063 // fits into the given space and subtracts the height of
2064 // all lines from nSpace. nSpace - nUpper is not a valid
2065 // indicator if the frame should be allowed to move backward.
2066 // We do a second check with the original remaining space
2067 // reduced by the required upper space:
2068 nOldSpace
-= nSecondCheck
;
2069 const bool bSecondRet
= nOldSpace
>= 0 && pFrm
->WouldFit( nOldSpace
, bOldSplit
, sal_False
);
2070 if ( bSecondRet
&& bOldSplit
&& nOldSpace
>= 0 )
2080 // OD 2004-03-01 #106629# - also consider lower spacing in table cells
2081 if ( bRet
&& IsInTab() &&
2082 pNewUpper
->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS
) )
2084 nSpace
-= rAttrs
.GetULSpace().GetLower();
2091 if ( bRet
&& !bSplit
&& pFrm
->IsKeep( rAttrs
.GetAttrSet() ) )
2095 while( pFrm
->IsTxtFrm() && ((SwTxtFrm
*)pFrm
)->HasFollow() )
2097 pFrm
= ((SwTxtFrm
*)pFrm
)->GetFollow();
2099 // OD 11.04.2003 #108824# - If last follow frame of <this> text
2100 // frame isn't valid, a formatting of the next content frame
2101 // doesn't makes sense. Thus, return TRUE.
2102 if ( IsAnFollow( pFrm
) && !pFrm
->IsValid() )
2104 ASSERT( false, "Only a warning for task 108824:/n<SwCntntFrm::_WouldFit(..) - follow not valid!" );
2109 if( 0 != (pNxt
= pFrm
->FindNext()) && pNxt
->IsCntntFrm() &&
2110 ( !pFtnFrm
|| ( pNxt
->IsInFtn() &&
2111 pNxt
->FindFtnFrm()->GetAttr() == pFtnFrm
->GetAttr() ) ) )
2113 // ProbeFormatierung vertraegt keine absatz- oder gar zeichengebundene Objekte
2114 // --> OD 2007-11-26 #b6614158#
2115 // current solution for the test formatting doesn't work, if
2116 // objects are present in the remaining area of the new upper
2118 ( pNxt
->GetDrawObjs() || bObjsInNewUpper
) )
2124 if ( !pNxt
->IsValid() )
2125 MakeNxt( pFrm
, pNxt
);
2127 //Kleiner Trick: Wenn der naechste einen Vorgaenger hat, so hat
2128 //er den Absatzabstand bereits berechnet. Er braucht dann nicht
2129 //teuer kalkuliert werden.
2130 if( lcl_NotHiddenPrev( pNxt
) )
2134 if( pFrm
->IsTxtFrm() && ((SwTxtFrm
*)pFrm
)->IsHiddenNow() )
2135 pTmpPrev
= lcl_NotHiddenPrev( pFrm
);
2139 pFrm
= (SwCntntFrm
*)pNxt
;
2147 } while ( bRet
&& pFrm
);