merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / layout / calcmove.cxx
blob4c5df3777b318e0b5788fb911082667c4b2b61f2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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"
35 #include "cntfrm.hxx"
36 #include "viewsh.hxx"
37 #include "doc.hxx"
38 #include "viewimp.hxx"
39 #include "swtypes.hxx"
40 #include "dflyobj.hxx"
41 #include "dcontact.hxx"
42 #include "flyfrm.hxx"
43 #include "frmtool.hxx"
44 #include "txtftn.hxx"
45 #include "fmtftn.hxx"
46 #include <svx/ulspitem.hxx>
47 #include <svx/keepitem.hxx>
49 #ifndef _OUTDEV_HXX //autogen
50 #include <vcl/outdev.hxx>
51 #endif
52 #include <fmtfsize.hxx>
53 #include <fmtanchr.hxx>
54 #include <fmtclbl.hxx>
56 #include "tabfrm.hxx"
57 #include "ftnfrm.hxx"
58 #include "txtfrm.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>
69 // <--
71 #include <ndtxt.hxx>
73 //------------------------------------------------------------------------
74 // Move-Methoden
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
100 //aufspalten kann.
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
107 //Die Breite.
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() )
118 return TRUE;
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 )
131 return FALSE;
134 SWRECTFN( this )
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();
145 SwTwips nSpace = 0;
146 SwRect aRect( pNewUpper->Prt() );
147 aRect.Pos() += pNewUpper->Frm().Pos();
148 const SwFrm *pPrevFrm = pNewUpper->Lower();
149 while ( pPrevFrm )
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();
165 if ( pLastFrm &&
166 pLastFrm->FindTabFrm() != pPrevFrm->FindTabFrm() )
168 pLastFrm = pLastFrm->FindTabFrm();
172 if ( pLastFrm )
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)();
190 if ( IsInFtn() ||
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 )
201 if ( nSpace )
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
209 // befragt werden.
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
212 // vorgenommen wird.
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,
220 bObjsInNewUpper );
221 // <--
223 //Bei einem spaltigen Bereichsfrischling kann _WouldFit kein
224 //brauchbares Ergebnis liefern, also muessen wir wirklich
225 //zurueckfliessen
226 else if( pNewUpper->IsInSct() && pNewUpper->IsColBodyFrm() &&
227 !(pNewUpper->Prt().*fnRectX->fnGetWidth)() &&
228 ( pNewUpper->GetUpper()->GetPrev() ||
229 pNewUpper->GetUpper()->GetNext() ) )
230 return TRUE;
231 else
232 return FALSE; // Kein Platz, dann ist es sinnlos, zurueckzufliessen
234 else
236 // OD 2004-05-26 #i25904# - check for space left in new upper
237 if ( nSpace )
238 return TRUE;
239 else
240 return FALSE;
244 return FALSE;
247 //------------------------------------------------------------------------
248 // Calc-Methoden
249 //------------------------------------------------------------------------
251 /*************************************************************************
253 |* SwFrm::Prepare()
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 )
273 pTab->LockJoin();
275 inline void PrepareUnlock( SwFlowFrm *pTab )
277 pTab->UnlockJoin();
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() &&
288 // <--
289 !( rFrm.GetUpper()->IsTabFrm() && rFrm.GetUpper()->GetUpper()->IsInTab() ) &&
290 !( rFrm.IsTabFrm() && rFrm.GetUpper()->IsInTab() );
293 void SwFrm::PrepareMake()
295 StackHack aHack;
296 if ( GetUpper() )
298 if ( lcl_IsCalcUpperAllowed( *this ) )
299 GetUpper()->Calc();
300 ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
301 if ( !GetUpper() )
302 return;
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;
310 if ( bTab )
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();
321 bNoSect = FALSE;
323 else if ( bCnt && TRUE == (bFoll = pThis->IsFollow()) &&
324 GetPrev() )
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() )
330 MakeAll();
331 return;
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 ||
338 !GetPrev() ||
339 !GetPrev()->GetAttrSet()->GetKeep().GetValue();
340 if ( bFormatPrev )
342 SwFrm *pFrm = GetUpper()->Lower();
343 while ( pFrm != this )
345 ASSERT( pFrm, ":-( Layoutgeruest wackelig (this not found)." );
346 if ( !pFrm )
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 ) )
359 break;
361 //MA: 24. Mar. 94, Calc wuerde doch nur wieder in ein _Prepare laufen und so
362 //die ganze Kette nocheinmal abhuenern.
363 // pFrm->Calc();
364 pFrm->MakeAll();
365 if( IsSctFrm() && !((SwSectionFrm*)this)->GetSection() )
366 break;
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();
381 if( pCnt )
382 pFrm = pCnt;
385 ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." );
386 if ( !GetUpper() )
387 return;
389 if ( lcl_IsCalcUpperAllowed( *this ) )
390 GetUpper()->Calc();
392 ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." );
395 if ( bTab && !bOldTabLock )
396 ::PrepareUnlock( (SwTabFrm*)this );
398 MakeAll();
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() )
406 // <--
408 GetUpper()->Calc();
409 ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
410 if ( !GetUpper() )
411 return;
413 if ( GetPrev() && !GetPrev()->IsValid() )
414 PrepareMake();
415 else
417 StackHack aHack;
418 MakeAll();
424 void SwFrm::PrepareCrsr()
426 StackHack aHack;
427 if( GetUpper() && !GetUpper()->IsSctFrm() )
429 GetUpper()->PrepareCrsr();
430 GetUpper()->Calc();
432 ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
433 if ( !GetUpper() )
434 return;
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;
443 if ( bTab )
445 bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked();
446 ::PrepareLock( (SwTabFrm*)this );
447 pThis = (SwTabFrm*)this;
449 else if( IsSctFrm() )
451 pThis = (SwSectionFrm*)this;
452 bNoSect = FALSE;
454 bFoll = pThis && pThis->IsFollow();
456 SwFrm *pFrm = GetUpper()->Lower();
457 while ( pFrm != this )
459 ASSERT( pFrm, ":-( Layoutgeruest wackelig (this not found)." );
460 if ( !pFrm )
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 ) )
473 break;
475 pFrm->MakeAll();
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();
485 if( pCnt )
486 pFrm = pCnt;
489 ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." );
490 if ( !GetUpper() )
491 return;
493 GetUpper()->Calc();
495 ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." );
497 if ( bTab && !bOldTabLock )
498 ::PrepareUnlock( (SwTabFrm*)this );
500 Calc();
503 /*************************************************************************
505 |* SwFrm::MakePos()
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();
523 return pRet;
526 SwFrm* lcl_NotHiddenPrev( SwFrm* pFrm )
528 SwFrm *pRet = pFrm;
531 pRet = lcl_Prev( pRet );
532 } while ( pRet && pRet->IsTxtFrm() && ((SwTxtFrm*)pRet)->IsHiddenNow() );
533 return pRet;
536 void SwFrm::MakePos()
538 if ( !bValidPos )
540 bValidPos = TRUE;
541 BOOL bUseUpper = FALSE;
542 SwFrm* pPrv = lcl_Prev( this );
543 if ( pPrv &&
544 ( !pPrv->IsCntntFrm() ||
545 ( ((SwCntntFrm*)pPrv)->GetFollow() != this ) )
548 if ( !StackHack::IsLocked() &&
549 ( !IsInSct() || IsSctFrm() ) &&
550 !pPrv->IsSctFrm() &&
551 !pPrv->GetAttrSet()->GetKeep().GetValue()
554 pPrv->Calc(); //hierbei kann der Prev verschwinden!
556 else if ( pPrv->Frm().Top() == 0 )
558 bUseUpper = TRUE;
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();
571 if( bR2L )
572 (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() -
573 (aFrm.*fnRect->fnGetWidth)() );
574 else
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 )
584 if( bReverse )
585 aFrm.Pos().X() += pPrv->Frm().Width();
586 else
587 aFrm.Pos().X() -= aFrm.Width();
589 else
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() )
611 GetUpper()->Calc();
613 // <--
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();
621 if( bR2L )
622 (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() -
623 (aFrm.*fnRect->fnGetWidth)() );
624 else
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 )
634 if( bReverse )
635 aFrm.Pos().X() += pPrv->Frm().Width();
636 else
637 aFrm.Pos().X() -= aFrm.Width();
639 else
640 aFrm.Pos().Y() += pPrv->Frm().Height();
642 else
644 aFrm.Pos( GetUpper()->Frm().Pos() );
645 aFrm.Pos() += GetUpper()->Prt().Pos();
646 if( FRM_NEIGHBOUR & nMyType && IsRightToLeft() )
648 if( bVert )
649 aFrm.Pos().Y() += GetUpper()->Prt().Height()
650 - aFrm.Height();
651 else
652 aFrm.Pos().X() += GetUpper()->Prt().Width()
653 - aFrm.Width();
655 else if( bVert && FRM_NOTE_VERT & nMyType && !bReverse )
656 aFrm.Pos().X() -= aFrm.Width() - GetUpper()->Prt().Width();
659 else
660 aFrm.Pos().X() = aFrm.Pos().Y() = 0;
661 if( IsBodyFrm() && bVert && !bReverse && GetUpper() )
662 aFrm.Pos().X() += GetUpper()->Prt().Width() - aFrm.Width();
663 bValidPos = TRUE;
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.
680 long nMax = 0;
681 for ( USHORT i = 0; i < pSortedObjs->Count(); ++i )
683 // --> OD 2004-07-01 #i28701# - consider changed type of <SwSortedObjs>
684 // entries.
685 SwAnchoredObject* pObj = (*pSortedObjs)[i];
686 long nTmp = 0;
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();
699 else
700 nTmp = pObj->GetObjRect().Bottom();
701 nMax = Max( nTmp, nMax );
702 // <--
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 )
719 if ( !bValidPos )
721 // PAGES01
722 bValidPos = TRUE; // positioning of the pages is taken care of by the root frame
725 if ( !bValidSize || !bValidPrtArea )
727 if ( IsEmptyPage() )
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;
734 else
736 if ( !pAccess )
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() );
767 else
769 //Fuer Seiten ohne Spalten bestimmt der Inhalt die
770 //Groesse.
771 long nBot = Frm().Top() + nTop;
772 SwFrm *pFrm = Lower();
773 while ( pFrm )
775 long nTmp = 0;
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() );
799 else
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() );
808 nBot += nTmp;
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();
816 nBot += nBottom;
817 //Und die Seitengebundenen
818 if ( pSortedObjs )
819 lcl_CheckObjects( pSortedObjs, this, nBot );
820 nBot -= Frm().Top();
821 // --> OD 2004-11-10 #i35143# - If second page frame
822 // exists, the first page doesn't have to fulfill the
823 // visible area.
824 if ( !GetPrev() && !GetNext() )
825 // <--
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 ) );
832 // <--
834 Prt().Left ( pAttrs->CalcLeftLine() + aBorder.Width() );
835 Prt().Top ( nTop );
836 Prt().Width( Frm().Width() - ( Prt().Left()
837 + pAttrs->CalcRightLine() + aBorder.Width() ) );
838 Prt().Height( Frm().Height() - (nTop + nBottom) );
839 bValidSize = bValidPrtArea = TRUE;
841 else
842 { //FixSize einstellen, bei Seiten nicht vom Upper sondern vom
843 //Attribut vorgegeben.
844 Frm().SSize( pAttrs->GetSize() );
845 Format( pAttrs );
849 } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
850 delete pAccess;
852 // PAGES01
853 if ( Frm() != aOldRect && GetUpper() )
854 static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 );
856 #ifndef PRODUCT
857 //Der Upper (Root) muss mindestens so breit
858 //sein, dass er die breiteste Seite aufnehmen kann.
859 if ( GetUpper() )
861 ASSERT( GetUpper()->Prt().Width() >= aFrm.Width(), "Rootsize" );
863 #endif
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 )
890 if ( !bValidPos )
891 MakePos();
893 if ( GetUpper() )
895 // NEW TABLES
896 if ( IsLeaveUpperAllowed() )
898 if ( !bValidSize )
899 bValidPrtArea = FALSE;
901 else
903 if ( !bValidSize )
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();
915 if( pNxt )
916 nPrtWidth -= pNxt->Frm().Height();
917 pNxt = GetNext();
918 while( pNxt && !pNxt->IsFooterFrm() )
919 pNxt = pNxt->GetNext();
920 if( pNxt )
921 nPrtWidth -= pNxt->Frm().Height();
924 const long nDiff = nPrtWidth - (Frm().*fnRect->fnGetWidth)();
926 if( IsNeighbourFrm() && IsRightToLeft() )
927 (Frm().*fnRect->fnSubLeft)( nDiff );
928 else
929 (Frm().*fnRect->fnAddRight)( nDiff );
931 else
933 // Don't leave your upper
934 const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
935 if( (Frm().*fnRect->fnOverStep)( nDeadLine ) )
936 bValidSize = FALSE;
940 if ( !bValidSize || !bValidPrtArea )
942 if ( !pAccess )
944 pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
945 pAttrs = pAccess->Get();
947 Format( pAttrs );
949 } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
950 if ( pAccess )
951 delete pAccess;
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 ) {
976 return true;
977 } else {
978 return false;
980 } else
981 return false;
984 bool SwFrm::IsCollapse() const
986 if (IsTxtFrm()) {
987 const SwTxtFrm *pTxtFrm=(SwTxtFrm*)this;
988 const SwTxtNode *pTxtNode=pTxtFrm->GetTxtNode();
989 if (pTxtNode && pTxtNode->IsCollapse()) {
990 return true;
991 } else {
992 return false;
994 } else {
995 return false;
999 BOOL SwCntntFrm::MakePrtArea( const SwBorderAttrs &rAttrs )
1001 BOOL bSizeChgd = FALSE;
1003 if ( !bValidPrtArea )
1005 bValidPrtArea = TRUE;
1007 SWRECTFN( this )
1008 const BOOL bTxtFrm = IsTxtFrm();
1009 SwTwips nUpper = 0;
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)() );
1022 else
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();
1033 SwTwips nWidthArea;
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())
1041 long nMinWidth = 0;
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);
1050 if ( bFly &&
1051 WEIT_WECH == pObj->GetObjRect().Width()||
1052 rFmt.GetFrmSize().GetWidthPercent() )
1053 continue;
1055 if ( FLY_IN_CNTNT == rFmt.GetAnchor().GetAnchorId() )
1056 nMinWidth = Max( nMinWidth,
1057 bFly ? rFmt.GetFrmSize().GetWidth()
1058 : pObj->GetObjRect().Width() );
1059 // <--
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 );
1098 if (IsCollapse()) {
1099 ViewShell *pSh = GetShell();
1100 nUpper=0;
1101 nLower=0;
1103 // // in balanced columned section frames we do not want the
1104 // // common border
1105 // sal_Bool bCommonBorder = sal_True;
1106 // if ( IsInSct() && GetUpper()->IsColBodyFrm() )
1107 // {
1108 // const SwSectionFrm* pSct = FindSctFrm();
1109 // bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue();
1110 // }
1111 // SwTwips nLower = bCommonBorder ?
1112 // rAttrs.GetBottomLine( this ) :
1113 // rAttrs.CalcBottomLine();
1115 (Prt().*fnRect->fnSetPosY)( (!bVert || bReverse) ? nUpper : nLower);
1116 nUpper += nLower;
1117 nUpper -= (Frm().*fnRect->fnGetHeight)() -
1118 (Prt().*fnRect->fnGetHeight)();
1120 //Wenn Unterschiede zwischen Alter und neuer Groesse,
1121 //Grow() oder Shrink() rufen
1122 if ( nUpper )
1124 if ( nUpper > 0 )
1125 GrowFrm( nUpper );
1126 else
1127 ShrinkFrm( -nUpper );
1128 bSizeChgd = TRUE;
1131 return bSizeChgd;
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;
1146 // <--
1148 inline void ValidateSz( SwFrm *pFrm )
1150 if ( 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() )
1163 return;
1165 if ( IsJoinLocked() )
1166 return;
1168 ASSERT( !((SwTxtFrm*)this)->IsSwapped(), "Calculation of a swapped frame" );
1170 StackHack aHack;
1172 if ( ((SwTxtFrm*)this)->IsLocked() )
1174 ASSERT( FALSE, "Format fuer gelockten TxtFrm." );
1175 return;
1178 LockJoin();
1179 long nFormatCount = 0;
1180 // --> OD 2006-09-25 #b6448963# - loop prevention
1181 int nConsequetiveFormatsWithoutChange = 0;
1182 // <--
1183 PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
1185 #ifndef PRODUCT
1186 const SwDoc *pDoc = GetAttrSet()->GetDoc();
1187 if( pDoc )
1189 static sal_Bool bWarn = sal_False;
1190 if( pDoc->InXMLExport() )
1192 ASSERT( bWarn, "Formatting during XML-export!" );
1193 bWarn = sal_True;
1195 else
1196 bWarn = sal_False;
1198 #endif
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
1217 //abgesetzt.
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.
1223 BOOL bMoveable;
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;
1244 if ( bFtn )
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() &&
1260 HasFollow() &&
1261 GetFollow()->GetFrm() == GetNext() )
1263 dynamic_cast<SwTxtFrm*>(this)->JoinFrm();
1265 // <--
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)),
1275 nToPageNum );
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() ) ) &&
1284 IsMoveable() )
1286 bMovedFwd = TRUE;
1287 MoveFwd( bMakePage, FALSE );
1289 // <--
1291 // <--
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() )
1297 bMovedFwd = TRUE;
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,
1301 if ( IsInTab() )
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 ) )
1324 bMovedFwd = TRUE;
1325 MoveFwd( bMakePage, FALSE );
1330 SWRECTFN( this )
1332 while ( !bValidPos || !bValidSize || !bValidPrtArea )
1334 // --> OD 2006-09-25 #b6448963# - loop prevention
1335 SwRect aOldFrm_StopFormat( Frm() );
1336 SwRect aOldPrt_StopFormat( Prt() );
1337 // <--
1338 if ( TRUE == (bMoveable = IsMoveable()) )
1340 SwFrm *pPre = GetIndPrev();
1341 if ( CheckMoveFwd( bMakePage, bKeep, bMovedBwd ) )
1343 SWREFRESHFN( this )
1344 bMovedFwd = TRUE;
1345 if ( 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)();
1363 if ( !bValidPos )
1364 MakePos();
1366 //FixSize einstellen, die VarSize wird von Format() justiert.
1367 if ( !bValidSize )
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
1377 // than 0.
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 );
1390 // <--
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)();
1397 // <--
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 );
1422 bValidSize = FALSE;
1424 // <--
1426 // <--
1429 //Damit die Witwen- und Waisen-Regelung eine Change bekommt muss der
1430 //CntntFrm benachrichtigt werden.
1431 //Kriterium:
1432 //- Er muss Moveable sein (sonst mach das Spalten keinen Sinn.)
1433 //- Er muss mit der Unterkante der PrtArea des Upper ueberlappen.
1434 if ( !bMustFit )
1436 BOOL bWidow = TRUE;
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 );
1452 bValidSize = FALSE;
1456 if ( !bValidSize )
1458 bValidSize = bFormatted = TRUE;
1459 ++nFormatCount;
1460 if( nFormatCount > STOP_FLY_FORMAT )
1461 SetFlyLock( TRUE );
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 )
1467 Format();
1469 #if OSL_DEBUG_LEVEL > 1
1470 else
1472 ASSERT( false, "debug assertion: <SwCntntFrm::MakeAll()> - format of text frame suppressed by fix b6448963" );
1474 #endif
1475 // <--
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 &&
1486 HasFollow()
1489 SwFrm* pOldUpper = GetUpper();
1490 MoveFwd( TRUE, FALSE );
1491 if ( GetUpper() != pOldUpper )
1493 bMovedFwd = TRUE;
1494 SWREFRESHFN( this )
1495 continue;
1497 } */
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
1502 //geflossen sein.
1503 BOOL bDummy;
1504 if ( !lcl_Prev( this ) &&
1505 !bMovedFwd &&
1506 ( bMoveable || ( bFly && !bTab ) ) &&
1507 ( !bFtn || !GetUpper()->FindFtnFrm()->GetPrev() )
1508 && MoveBwd( bDummy ) )
1510 SWREFRESHFN( this )
1511 bMovedBwd = TRUE;
1512 bFormatted = FALSE;
1513 if ( bKeep && bMoveable )
1515 if( CheckMoveFwd( bMakePage, FALSE, bMovedBwd ) )
1517 bMovedFwd = TRUE;
1518 bMoveable = IsMoveable();
1519 SWREFRESHFN( this )
1521 Point aOldPos = (Frm().*fnRect->fnGetPos)();
1522 MakePos();
1523 if( aOldPos != (Frm().*fnRect->fnGetPos)() )
1525 Prepare( PREP_POS_CHGD, (const void*)&bFormatted, FALSE );
1526 if ( !bValidSize )
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 );
1537 if( GetFollow() )
1538 Prepare( PREP_WIDOWS_ORPHANS, 0, FALSE );
1539 bValidSize = bFormatted = TRUE;
1540 Format();
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();
1549 if( pTmp )
1551 pNxt = pTmp;
1552 break;
1555 pNxt = pNxt->FindNext();
1557 if ( pNxt )
1559 pNxt->Calc();
1560 if( bValidPos && !GetIndNext() )
1562 SwSectionFrm *pSct = FindSctFrm();
1563 if( pSct && !pSct->GetValidSizeFlag() )
1565 SwSectionFrm* pNxtSct = pNxt->FindSctFrm();
1566 if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
1567 bValidPos = FALSE;
1569 else
1570 bValidPos = FALSE;
1576 //Der TxtFrm Validiert sich bei Fussnoten ggf. selbst, dass kann leicht
1577 //dazu fuehren, dass seine Position obwohl unrichtig valide ist.
1578 if ( bValidPos )
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.
1587 if ( bFtn &&
1588 nFormatCount <= STOP_FLY_FORMAT &&
1589 !GetDrawObjs() )
1590 // <--
1592 bValidPos = FALSE;
1593 MakePos();
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;
1606 else
1608 nConsequetiveFormatsWithoutChange = 0;
1611 // <--
1613 //Wieder ein Wert ungueltig? - dann nochmal das ganze...
1614 if ( !bValidPos || !bValidSize || !bValidPrtArea )
1615 continue;
1617 //Fertig?
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();
1641 break;
1643 pNxt = pNxt->FindNext();
1645 if ( pNxt )
1647 const BOOL bMoveFwdInvalid = 0 != GetIndNext();
1648 const BOOL bNxtNew =
1649 ( 0 == (pNxt->Prt().*fnRect->fnGetHeight)() ) &&
1650 (!pNxt->IsTxtFrm() ||!((SwTxtFrm*)pNxt)->IsHiddenNow());
1652 pNxt->Calc();
1654 if ( !bMovedBwd &&
1655 ((bMoveFwdInvalid && !GetIndNext()) ||
1656 bNxtNew) )
1658 if( bMovedFwd )
1659 pNotify->SetInvaKeep();
1660 bMovedFwd = FALSE;
1664 continue;
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 );
1681 if( nReal )
1682 continue;
1684 break;
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)() )
1714 if ( !bFitPromise )
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 );
1722 bValidSize = FALSE;
1723 bFitPromise = TRUE;
1724 continue;
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() ) )
1739 bMoveOrFit = TRUE;
1741 #ifndef PRODUCT
1742 else
1744 ASSERT( FALSE, "+TxtFrm hat WouldFit-Versprechen nicht eingehalten." );
1746 #endif
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) )
1763 bMovedFwd = FALSE;
1765 const sal_Bool bCheckForGrownBody = pOldUp->IsBodyFrm();
1766 const long nOldBodyHeight = (pOldUp->Frm().*fnRect->fnGetHeight)();
1768 if ( !bMovedFwd && !MoveFwd( bMakePage, FALSE ) )
1769 bMakePage = FALSE;
1770 SWREFRESHFN( this )
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 )
1780 bMovedFwd = FALSE;
1781 else
1782 bMovedFwd = TRUE;
1784 bFormatted = FALSE;
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 );
1791 bValidSize = FALSE;
1792 bMustFit = TRUE;
1793 continue;
1796 #if OSL_DEBUG_LEVEL > 1
1797 ASSERT( false, "LoopControl in SwCntntFrm::MakeAll" )
1798 #endif
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() ) ||
1817 // <--
1819 // --> FME 2005-01-27 #i33887#
1820 ( IsInSct() && bKeep )
1821 // <--
1823 // ... add your conditions here ...
1826 static_cast<SwTxtFrm&>(*this) );
1829 if ( pSaveFtn )
1830 delete pSaveFtn;
1832 UnlockJoin();
1833 if ( bMovedFwd || bMovedBwd )
1834 pNotify->SetInvaKeep();
1835 // OD 2004-02-26 #i25029#
1836 if ( bMovedFwd )
1838 pNotify->SetInvalidatePrevPrtArea();
1840 delete pNotify;
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() );
1878 else
1879 pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() );
1881 ((SwCntntFrm*)pNxt)->MakePrtArea( rAttrs );
1882 pNxt->Format( &rAttrs );
1884 else
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() );
1893 else
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,
1925 BOOL bTstMove,
1926 const bool bObjsInNewUpper )
1927 // <--
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;
1934 if ( IsInFtn() )
1936 if( !lcl_IsNextFtnBoss( pNewUpper, this ) )
1937 return TRUE;
1938 pFtnFrm = FindFtnFrm();
1941 BOOL bRet;
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;
1955 // <--
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();
1976 pTmpFrm->Remove();
1977 pTmpFrm->InsertBefore( pNewUpper, 0 );
1978 if ( pFrm->IsTxtFrm() &&
1979 ( bTstMove ||
1980 ((SwTxtFrm*)pFrm)->HasFollow() ||
1981 ( !((SwTxtFrm*)pFrm)->HasPara() &&
1982 !((SwTxtFrm*)pFrm)->IsEmpty()
1987 bTstMove = TRUE;
1988 bRet = ((SwTxtFrm*)pFrm)->TestFormat( pTmpPrev, nSpace, bSplit );
1990 else
1991 bRet = pFrm->WouldFit( nSpace, bSplit, sal_False );
1993 pTmpFrm->Remove();
1994 pTmpFrm->InsertBefore( pUp, pOldNext );
1996 else
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 )
2009 SwTwips nUpper;
2011 if ( pTmpPrev )
2013 nUpper = CalcUpperSpace( NULL, pTmpPrev );
2015 // in balanced columned section frames we do not want the
2016 // common border
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 &&
2026 pFrm == this &&
2027 IsTxtFrm() &&
2028 bCommonBorder &&
2029 !static_cast<const SwTxtFrm*>(this)->IsEmpty() ) ?
2030 nUpper :
2032 // <--
2034 nUpper += bCommonBorder ?
2035 rAttrs.GetBottomLine( *(pFrm) ) :
2036 rAttrs.CalcBottomLine();
2039 else
2041 // --> FME 2005-03-31 #b6236853# #i46181#
2042 nSecondCheck = 0;
2043 // <--
2045 if( pFrm->IsVertical() )
2046 nUpper = pFrm->Frm().Width() - pFrm->Prt().Width();
2047 else
2048 nUpper = pFrm->Frm().Height() - pFrm->Prt().Height();
2051 nSpace -= nUpper;
2053 if ( nSpace < 0 )
2055 bRet = FALSE;
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 )
2072 bRet = TRUE;
2073 bSplit = TRUE;
2076 // <--
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();
2085 if ( nSpace < 0 )
2087 bRet = FALSE;
2091 if ( bRet && !bSplit && pFrm->IsKeep( rAttrs.GetAttrSet() ) )
2093 if( bTstMove )
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!" );
2105 return TRUE;
2108 SwFrm *pNxt;
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
2117 if ( bTstMove &&
2118 ( pNxt->GetDrawObjs() || bObjsInNewUpper ) )
2120 return TRUE;
2122 // <--
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 ) )
2131 pTmpPrev = 0;
2132 else
2134 if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow() )
2135 pTmpPrev = lcl_NotHiddenPrev( pFrm );
2136 else
2137 pTmpPrev = pFrm;
2139 pFrm = (SwCntntFrm*)pNxt;
2141 else
2142 pFrm = 0;
2144 else
2145 pFrm = 0;
2147 } while ( bRet && pFrm );
2149 return bRet;