xref: /aoo41x/main/sw/source/core/layout/calcmove.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 #include "rootfrm.hxx"
31 #include "pagefrm.hxx"
32 #include "cntfrm.hxx"
33 #include "viewsh.hxx"
34 #include "doc.hxx"
35 #include "viewimp.hxx"
36 #include "viewopt.hxx"
37 #include "swtypes.hxx"
38 #include "dflyobj.hxx"
39 #include "dcontact.hxx"
40 #include "flyfrm.hxx"
41 #include "frmtool.hxx"
42 #include "txtftn.hxx"
43 #include "fmtftn.hxx"
44 #include <editeng/ulspitem.hxx>
45 #include <editeng/keepitem.hxx>
46 
47 #include <vcl/outdev.hxx>
48 #include <fmtfsize.hxx>
49 #include <fmtanchr.hxx>
50 #include <fmtclbl.hxx>
51 
52 #include "tabfrm.hxx"
53 #include "ftnfrm.hxx"
54 #include "txtfrm.hxx"
55 #include "pagedesc.hxx"
56 #include "ftninfo.hxx"
57 #include "sectfrm.hxx"
58 #include "dbg_lay.hxx"
59 
60 // --> OD 2004-06-23 #i28701#
61 #include <sortedobjs.hxx>
62 #include <layouter.hxx>
63 // --> OD 2004-11-01 #i36347#
64 #include <flyfrms.hxx>
65 // <--
66 
67 //------------------------------------------------------------------------
68 //				Move-Methoden
69 //------------------------------------------------------------------------
70 
71 /*************************************************************************
72 |*
73 |*	SwCntntFrm::ShouldBwdMoved()
74 |*
75 |* 	Beschreibung		Returnwert sagt, ob der Frm verschoben werden sollte.
76 |*	Ersterstellung		MA 05. Dec. 96
77 |*	Letzte Aenderung	MA 05. Dec. 96
78 |*
79 |*************************************************************************/
80 
81 
82 sal_Bool SwCntntFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool, sal_Bool & )
83 {
84 	if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()))
85 	{
86 		//Das zurueckfliessen von Frm's ist leider etwas Zeitintensiv.
87 		//Der haufigste Fall ist der, dass dort wo der Frm hinfliessen
88 		//moechte die FixSize die gleiche ist, die der Frm selbst hat.
89 		//In diesem Fall kann einfach geprueft werden, ob der Frm genug
90 		//Platz fuer seine VarSize findet, ist dies nicht der Fall kann
91 		//gleich auf das Verschieben verzichtet werden.
92 		//Die Pruefung, ob der Frm genug Platz findet fuehrt er selbst
93 		//durch, dabei wird beruecksichtigt, dass er sich moeglicherweise
94 		//aufspalten kann.
95 		//Wenn jedoch die FixSize eine andere ist oder Flys im Spiel sind
96 		//(an der alten oder neuen Position) hat alle Prueferei keinen Sinn
97 		//der Frm muss dann halt Probehalber verschoben werden (Wenn ueberhaupt
98 		//etwas Platz zur Verfuegung steht).
99 
100 		//Die FixSize der Umgebungen in denen Cntnts herumlungern ist immer
101 		//Die Breite.
102 
103 		//Wenn mehr als ein Blatt zurueckgegangen wurde (z.B. ueberspringen
104 		//von Leerseiten), so muss in jedemfall gemoved werden - sonst wuerde,
105 		//falls der Frm nicht in das Blatt passt, nicht mehr auf die
106 		//dazwischenliegenden Blaetter geachtet werden.
107 		sal_uInt8 nMoveAnyway = 0;
108 		SwPageFrm * const pNewPage = pNewUpper->FindPageFrm();
109 		SwPageFrm *pOldPage = FindPageFrm();
110 
111 		if ( SwFlowFrm::IsMoveBwdJump() )
112 			return sal_True;
113 
114 		if( IsInFtn() && IsInSct() )
115 		{
116 			SwFtnFrm* pFtn = FindFtnFrm();
117 			SwSectionFrm* pMySect = pFtn->FindSctFrm();
118 			if( pMySect && pMySect->IsFtnLock() )
119 			{
120 				SwSectionFrm *pSect = pNewUpper->FindSctFrm();
121 				while( pSect && pSect->IsInFtn() )
122 					pSect = pSect->GetUpper()->FindSctFrm();
123 				ASSERT( pSect, "Escaping footnote" );
124 				if( pSect != pMySect )
125 					return sal_False;
126 			}
127 		}
128         SWRECTFN( this )
129         SWRECTFNX( pNewUpper )
130         if( Abs( (pNewUpper->Prt().*fnRectX->fnGetWidth)() -
131                  (GetUpper()->Prt().*fnRect->fnGetWidth)() ) > 1 )
132 			nMoveAnyway = 2; // Damit kommt nur noch ein _WouldFit mit Umhaengen in Frage
133 
134         // OD 2004-05-26 #i25904# - do *not* move backward,
135         // if <nMoveAnyway> equals 3 and no space is left in new upper.
136         nMoveAnyway |= BwdMoveNecessary( pOldPage, Frm() );
137 		{
138             const IDocumentSettingAccess* pIDSA = pNewPage->GetFmt()->getIDocumentSettingAccess();
139 			SwTwips nSpace = 0;
140 			SwRect aRect( pNewUpper->Prt() );
141 			aRect.Pos() += pNewUpper->Frm().Pos();
142 			const SwFrm *pPrevFrm = pNewUpper->Lower();
143 			while ( pPrevFrm )
144 			{
145                 SwTwips nNewTop = (pPrevFrm->Frm().*fnRectX->fnGetBottom)();
146                 // OD 2004-03-01 #106629#:
147                 // consider lower spacing of last frame in a table cell
148                 {
149                     // check, if last frame is inside table and if it includes
150                     // its lower spacing.
151                     if ( !pPrevFrm->GetNext() && pPrevFrm->IsInTab() &&
152                          pIDSA->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
153                     {
154                         const SwFrm* pLastFrm = pPrevFrm;
155                         // if last frame is a section, take its last content
156                         if ( pPrevFrm->IsSctFrm() )
157                         {
158                             pLastFrm = static_cast<const SwSectionFrm*>(pPrevFrm)->FindLastCntnt();
159                             if ( pLastFrm &&
160                                  pLastFrm->FindTabFrm() != pPrevFrm->FindTabFrm() )
161                             {
162                                 pLastFrm = pLastFrm->FindTabFrm();
163                             }
164                         }
165 
166                         if ( pLastFrm )
167                         {
168                             SwBorderAttrAccess aAccess( SwFrm::GetCache(), pLastFrm );
169                             const SwBorderAttrs& rAttrs = *aAccess.Get();
170                             nNewTop -= rAttrs.GetULSpace().GetLower();
171                         }
172                     }
173                 }
174                 (aRect.*fnRectX->fnSetTop)( nNewTop );
175 
176                 pPrevFrm = pPrevFrm->GetNext();
177             }
178 
179 			nMoveAnyway |= BwdMoveNecessary( pNewPage, aRect);
180 
181             //determine space left in new upper frame
182             nSpace = (aRect.*fnRectX->fnGetHeight)();
183             const ViewShell *pSh = pNewUpper->getRootFrm()->GetCurrShell();
184             if ( IsInFtn() ||
185                  (pSh && pSh->GetViewOptions()->getBrowseMode()) ||
186                  pNewUpper->IsCellFrm() ||
187                  ( pNewUpper->IsInSct() && ( pNewUpper->IsSctFrm() ||
188                    ( pNewUpper->IsColBodyFrm() &&
189                      !pNewUpper->GetUpper()->GetPrev() &&
190                      !pNewUpper->GetUpper()->GetNext() ) ) ) )
191                 nSpace += pNewUpper->Grow( LONG_MAX, sal_True );
192 
193 			if ( nMoveAnyway < 3 )
194 			{
195                 if ( nSpace )
196 				{
197 					//Keine Beruecksichtigung der Fussnoten die an dem Absatz
198 					//kleben, denn dies wuerde extrem unuebersichtlichen Code
199 					//beduerfen (wg. Beruecksichtung der Breiten und vor allem
200 					//der Flys, die ja wieder Einfluss auf die Fussnoten nehmen...).
201 
202 					// _WouldFit kann bei gleicher Breite und _nur_ selbst verankerten Flys
203 					// befragt werden.
204 					// _WouldFit kann auch gefragt werden, wenn _nur_ fremdverankerte Flys vorliegen,
205 					// dabei ist sogar die Breite egal, da ein TestFormat in der neuen Umgebung
206 					// vorgenommen wird.
207                     // --> OD 2007-11-26 #b6614158#
208                     const sal_uInt8 nBwdMoveNecessaryResult =
209                                             BwdMoveNecessary( pNewPage, aRect);
210                     const bool bObjsInNewUpper( nBwdMoveNecessaryResult == 2 ||
211                                                 nBwdMoveNecessaryResult == 3 );
212 
213                     return _WouldFit( nSpace, pNewUpper, nMoveAnyway == 2,
214                                       bObjsInNewUpper );
215                     // <--
216 				}
217 				//Bei einem spaltigen Bereichsfrischling kann _WouldFit kein
218 				//brauchbares Ergebnis liefern, also muessen wir wirklich
219 				//zurueckfliessen
220 				else if( pNewUpper->IsInSct() && pNewUpper->IsColBodyFrm() &&
221                     !(pNewUpper->Prt().*fnRectX->fnGetWidth)() &&
222 					( pNewUpper->GetUpper()->GetPrev() ||
223 					  pNewUpper->GetUpper()->GetNext() ) )
224 					return sal_True;
225 				else
226 					return sal_False; // Kein Platz, dann ist es sinnlos, zurueckzufliessen
227 			}
228             else
229             {
230                 // OD 2004-05-26 #i25904# - check for space left in new upper
231                 if ( nSpace )
232                     return sal_True;
233                 else
234                     return sal_False;
235             }
236 		}
237 	}
238 	return  sal_False;
239 }
240 
241 //------------------------------------------------------------------------
242 //				Calc-Methoden
243 //------------------------------------------------------------------------
244 
245 /*************************************************************************
246 |*
247 |*	SwFrm::Prepare()
248 |*
249 |*	Beschreibung		Bereitet den Frm auf die 'Formatierung' (MakeAll())
250 |*		vor. Diese Methode dient dazu auf dem Stack Platz einzusparen,
251 |*		denn zur Positionsberechnung des Frm muss sichergestellt sein, dass
252 |*		die Position von Upper und Prev gueltig sind, mithin also ein
253 |*		rekursiver Aufruf (Schleife waere relativ teuer, da selten notwendig).
254 |*		Jeder Aufruf von MakeAll verbraucht aber ca. 500Byte Stack -
255 |*		das Ende ist leicht abzusehen. _Prepare benoetigt nur wenig Stack,
256 |*		deshalb solle der Rekursive Aufruf hier kein Problem sein.
257 |*		Ein weiterer Vorteil ist, das eines schoenen Tages das _Prepare und
258 |*		damit die Formatierung von Vorgaengern umgangen werden kann.
259 |*		So kann evtl. mal 'schnell' an's Dokumentende gesprungen werden.
260 |*	Ersterstellung		MA ??
261 |*	Letzte Aenderung	MA 13. Dec. 93
262 |*
263 |*************************************************************************/
264 //Zwei kleine Freundschaften werden hier zu einem Geheimbund.
265 inline void PrepareLock( SwFlowFrm *pTab )
266 {
267 	pTab->LockJoin();
268 }
269 inline void PrepareUnlock( SwFlowFrm *pTab )
270 {
271 	pTab->UnlockJoin();
272 
273 }
274 
275 // hopefully, one day this function simply will return 'false'
276 bool lcl_IsCalcUpperAllowed( const SwFrm& rFrm )
277 {
278     return !rFrm.GetUpper()->IsSctFrm() &&
279            !rFrm.GetUpper()->IsFooterFrm() &&
280            // --> OD 2004-11-02 #i23129#, #i36347# - no format of upper Writer fly frame
281            !rFrm.GetUpper()->IsFlyFrm() &&
282            // <--
283            !( rFrm.GetUpper()->IsTabFrm() && rFrm.GetUpper()->GetUpper()->IsInTab() ) &&
284            !( rFrm.IsTabFrm() && rFrm.GetUpper()->IsInTab() );
285 }
286 
287 void SwFrm::PrepareMake()
288 {
289     StackHack aHack;
290 	if ( GetUpper() )
291 	{
292         if ( lcl_IsCalcUpperAllowed( *this ) )
293             GetUpper()->Calc();
294 		ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
295 		if ( !GetUpper() )
296 			return;
297 
298 		const sal_Bool bCnt = IsCntntFrm();
299 		const sal_Bool bTab = IsTabFrm();
300 		sal_Bool bNoSect = IsInSct();
301 		sal_Bool bOldTabLock = sal_False, bFoll = sal_False;
302 		SwFlowFrm* pThis = bCnt ? (SwCntntFrm*)this : NULL;
303 
304 		if ( bTab )
305 		{
306 			pThis = (SwTabFrm*)this;
307 			bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked();
308 			::PrepareLock( (SwTabFrm*)this );
309 			bFoll = pThis->IsFollow();
310 		}
311 		else if( IsSctFrm() )
312 		{
313 			pThis = (SwSectionFrm*)this;
314 			bFoll = pThis->IsFollow();
315 			bNoSect = sal_False;
316 		}
317 		else if ( bCnt && sal_True == (bFoll = pThis->IsFollow()) &&
318 			 GetPrev() )
319 		{
320 			//Wenn der Master gereade ein CalcFollow ruft braucht die Kette
321 			//nicht durchlaufen werden. Das spart Zeit und vermeidet Probleme.
322 			if ( ((SwTxtFrm*)((SwTxtFrm*)this)->FindMaster())->IsLocked() )
323 			{
324 				MakeAll();
325 				return;
326 			}
327 		}
328 
329         // --> OD 2005-03-04 #i44049# - no format of previous frame, if current
330         // frame is a table frame and its previous frame wants to keep with it.
331         const bool bFormatPrev = !bTab ||
332                                  !GetPrev() ||
333                                  !GetPrev()->GetAttrSet()->GetKeep().GetValue();
334         if ( bFormatPrev )
335         {
336             SwFrm *pFrm = GetUpper()->Lower();
337             while ( pFrm != this )
338             {
339                 ASSERT( pFrm, ":-( Layoutgeruest wackelig (this not found)." );
340                 if ( !pFrm )
341                     return; //Oioioioi ...
342 
343                 if ( !pFrm->IsValid() )
344                 {
345                     //Ein kleiner Eingriff der hoffentlich etwas zur Verbesserung
346                     //der Stabilitaet beitraegt:
347                     //Wenn ich Follow _und_ Nachbar eines Frms vor mir bin,
348                     //so wuerde dieser mich beim Formatieren deleten; wie jeder
349                     //leicht sehen kann waere dies eine etwas unuebersichtliche
350                     //Situation die es zu vermeiden gilt.
351                     if ( bFoll && pFrm->IsFlowFrm() &&
352                          (SwFlowFrm::CastFlowFrm(pFrm))->IsAnFollow( pThis ) )
353                         break;
354 
355     //MA: 24. Mar. 94, Calc wuerde doch nur wieder in ein _Prepare laufen und so
356     //die ganze Kette nocheinmal abhuenern.
357     //              pFrm->Calc();
358                     pFrm->MakeAll();
359                     if( IsSctFrm() && !((SwSectionFrm*)this)->GetSection() )
360                         break;
361                 }
362                 //Die Kette kann bei CntntFrms waehrend des durchlaufens
363                 //aufgebrochen werden, deshalb muss der Nachfolger etwas
364                 //umstaendlich ermittelt werden. However, irgendwann _muss_
365                 //ich wieder bei mir selbst ankommen.
366                 pFrm = pFrm->FindNext();
367 
368                 //Wenn wir in einem SectionFrm gestartet sind, koennen wir durch die
369                 //MakeAll-Aufrufe in einen Section-Follow gewandert sein.
370                 //FindNext liefert allerdings den SectionFrm, nicht seinen Inhalt.
371                 // => wir finden uns selbst nicht mehr!
372                 if( bNoSect && pFrm && pFrm->IsSctFrm() )
373                 {
374                     SwFrm* pCnt = ((SwSectionFrm*)pFrm)->ContainsAny();
375                     if( pCnt )
376                         pFrm = pCnt;
377                 }
378             }
379             ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." );
380             if ( !GetUpper() )
381                 return;
382 
383             if ( lcl_IsCalcUpperAllowed( *this ) )
384                 GetUpper()->Calc();
385 
386             ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." );
387         }
388 
389 		if ( bTab && !bOldTabLock )
390 			::PrepareUnlock( (SwTabFrm*)this );
391 	}
392 	MakeAll();
393 }
394 
395 void SwFrm::OptPrepareMake()
396 {
397     // --> OD 2004-11-02 #i23129#, #i36347# - no format of upper Writer fly frame
398     if ( GetUpper() && !GetUpper()->IsFooterFrm() &&
399          !GetUpper()->IsFlyFrm() )
400     // <--
401 	{
402 		GetUpper()->Calc();
403 		ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
404 		if ( !GetUpper() )
405 			return;
406 	}
407 	if ( GetPrev() && !GetPrev()->IsValid() )
408 		PrepareMake();
409 	else
410 	{
411 		StackHack aHack;
412 		MakeAll();
413 	}
414 }
415 
416 
417 
418 void SwFrm::PrepareCrsr()
419 {
420 	StackHack aHack;
421 	if( GetUpper() && !GetUpper()->IsSctFrm() )
422 	{
423 		GetUpper()->PrepareCrsr();
424 		GetUpper()->Calc();
425 
426 		ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
427 		if ( !GetUpper() )
428 			return;
429 
430 		const sal_Bool bCnt = IsCntntFrm();
431 		const sal_Bool bTab = IsTabFrm();
432 		sal_Bool bNoSect = IsInSct();
433 
434 		sal_Bool bOldTabLock = sal_False, bFoll;
435 		SwFlowFrm* pThis = bCnt ? (SwCntntFrm*)this : NULL;
436 
437 		if ( bTab )
438 		{
439 			bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked();
440 			::PrepareLock( (SwTabFrm*)this );
441 			pThis = (SwTabFrm*)this;
442 		}
443 		else if( IsSctFrm() )
444 		{
445 			pThis = (SwSectionFrm*)this;
446 			bNoSect = sal_False;
447 		}
448 		bFoll = pThis && pThis->IsFollow();
449 
450 		SwFrm *pFrm = GetUpper()->Lower();
451 		while ( pFrm != this )
452 		{
453 			ASSERT( pFrm, ":-( Layoutgeruest wackelig (this not found)." );
454 			if ( !pFrm )
455 				return;	//Oioioioi ...
456 
457 			if ( !pFrm->IsValid() )
458 			{
459 				//Ein kleiner Eingriff der hoffentlich etwas zur Verbesserung
460 				//der Stabilitaet beitraegt:
461 				//Wenn ich Follow _und_ Nachbar eines Frms vor mir bin,
462 				//so wuerde dieser mich beim Formatieren deleten; wie jeder
463 				//leicht sehen kann waere dies eine etwas unuebersichtliche
464 				//Situation die es zu vermeiden gilt.
465 				if ( bFoll && pFrm->IsFlowFrm() &&
466 					 (SwFlowFrm::CastFlowFrm(pFrm))->IsAnFollow( pThis ) )
467 					break;
468 
469 				pFrm->MakeAll();
470 			}
471 			//Die Kette kann bei CntntFrms waehrend des durchlaufens
472 			//aufgebrochen werden, deshalb muss der Nachfolger etwas
473 			//umstaendlich ermittelt werden. However, irgendwann _muss_
474 			//ich wieder bei mir selbst ankommen.
475 			pFrm = pFrm->FindNext();
476 			if( bNoSect && pFrm && pFrm->IsSctFrm() )
477 			{
478 				SwFrm* pCnt = ((SwSectionFrm*)pFrm)->ContainsAny();
479 				if( pCnt )
480 					pFrm = pCnt;
481 			}
482 		}
483 		ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." );
484 		if ( !GetUpper() )
485 			return;
486 
487 		GetUpper()->Calc();
488 
489 		ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." );
490 
491 		if ( bTab && !bOldTabLock )
492 			::PrepareUnlock( (SwTabFrm*)this );
493 	}
494 	Calc();
495 }
496 
497 /*************************************************************************
498 |*
499 |*	SwFrm::MakePos()
500 |*
501 |*	Ersterstellung		MA ??
502 |*	Letzte Aenderung	MA 24. May. 93
503 |*
504 |*************************************************************************/
505 
506 // Hier wird GetPrev() zurueckgegeben, allerdings werden
507 // dabei leere SectionFrms ueberlesen
508 SwFrm* lcl_Prev( SwFrm* pFrm, sal_Bool bSectPrv = sal_True )
509 {
510 	SwFrm* pRet = pFrm->GetPrev();
511 	if( !pRet && pFrm->GetUpper() && pFrm->GetUpper()->IsSctFrm() &&
512 		bSectPrv && !pFrm->IsColumnFrm() )
513 		pRet = pFrm->GetUpper()->GetPrev();
514 	while( pRet && pRet->IsSctFrm() &&
515 		   !((SwSectionFrm*)pRet)->GetSection() )
516 		pRet = pRet->GetPrev();
517 	return pRet;
518 }
519 
520 SwFrm* lcl_NotHiddenPrev( SwFrm* pFrm )
521 {
522 	SwFrm *pRet = pFrm;
523 	do
524 	{
525 		pRet = lcl_Prev( pRet );
526 	} while ( pRet && pRet->IsTxtFrm() && ((SwTxtFrm*)pRet)->IsHiddenNow() );
527 	return pRet;
528 }
529 
530 void SwFrm::MakePos()
531 {
532 	if ( !bValidPos )
533 	{
534 		bValidPos = sal_True;
535 		sal_Bool bUseUpper = sal_False;
536 		SwFrm* pPrv = lcl_Prev( this );
537         if ( pPrv &&
538              ( !pPrv->IsCntntFrm() ||
539                ( ((SwCntntFrm*)pPrv)->GetFollow() != this ) )
540            )
541 		{
542             if ( !StackHack::IsLocked() &&
543                  ( !IsInSct() || IsSctFrm() ) &&
544                  !pPrv->IsSctFrm() &&
545                  !pPrv->GetAttrSet()->GetKeep().GetValue()
546                )
547             {
548 				pPrv->Calc();	//hierbei kann der Prev verschwinden!
549             }
550 			else if ( pPrv->Frm().Top() == 0 )
551             {
552 				bUseUpper = sal_True;
553             }
554 		}
555 
556 		pPrv = lcl_Prev( this, sal_False );
557         sal_uInt16 nMyType = GetType();
558         SWRECTFN( ( IsCellFrm() && GetUpper() ? GetUpper() : this  ) )
559         if ( !bUseUpper && pPrv )
560         {
561             aFrm.Pos( pPrv->Frm().Pos() );
562             if( FRM_NEIGHBOUR & nMyType )
563             {
564                 sal_Bool bR2L = IsRightToLeft();
565                 if( bR2L )
566                     (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() -
567                                                (aFrm.*fnRect->fnGetWidth)() );
568                 else
569                     (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() +
570                                           (pPrv->Frm().*fnRect->fnGetWidth)() );
571 
572                 // cells may now leave their uppers
573                 if( bVert && FRM_CELL & nMyType && !bReverse )
574                     aFrm.Pos().X() -= aFrm.Width() -pPrv->Frm().Width();
575             }
576             else if( bVert && FRM_NOTE_VERT & nMyType )
577             {
578                 if( bReverse )
579                     aFrm.Pos().X() += pPrv->Frm().Width();
580                 else
581                     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
582                 {
583 					if ( bVertL2R )
584                    		aFrm.Pos().X() += pPrv->Frm().Width();
585                 	else
586                    		aFrm.Pos().X() -= aFrm.Width();
587               	}
588             }
589             else
590                 aFrm.Pos().Y() += pPrv->Frm().Height();
591         }
592 		else if ( GetUpper() )
593 		{
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() )
609                )
610             {
611                 GetUpper()->Calc();
612             }
613             // <--
614 			pPrv = lcl_Prev( this, sal_False );
615 			if ( !bUseUpper && pPrv )
616             {
617                 aFrm.Pos( pPrv->Frm().Pos() );
618                 if( FRM_NEIGHBOUR & nMyType )
619                 {
620                     sal_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)() );
627 
628                     // cells may now leave their uppers
629                     if( bVert && FRM_CELL & nMyType && !bReverse )
630                         aFrm.Pos().X() -= aFrm.Width() -pPrv->Frm().Width();
631                 }
632                 else if( bVert && FRM_NOTE_VERT & nMyType )
633                 {
634                     if( bReverse )
635                         aFrm.Pos().X() += pPrv->Frm().Width();
636                     else
637                         aFrm.Pos().X() -= aFrm.Width();
638                 }
639                 else
640                     aFrm.Pos().Y() += pPrv->Frm().Height();
641 			}
642 			else
643 			{
644 				aFrm.Pos( GetUpper()->Frm().Pos() );
645 				aFrm.Pos() += GetUpper()->Prt().Pos();
646                 if( FRM_NEIGHBOUR & nMyType && IsRightToLeft() )
647                 {
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();
654                 }
655                 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
656                 else if( bVert && !bVertL2R && FRM_NOTE_VERT & nMyType && !bReverse )
657                     aFrm.Pos().X() -= aFrm.Width() - GetUpper()->Prt().Width();
658 			}
659 		}
660 		else
661 			aFrm.Pos().X() = aFrm.Pos().Y() = 0;
662         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
663         if( IsBodyFrm() && bVert && !bVertL2R && !bReverse && GetUpper() )
664             aFrm.Pos().X() += GetUpper()->Prt().Width() - aFrm.Width();
665 		bValidPos = sal_True;
666 	}
667 }
668 
669 /*************************************************************************
670 |*
671 |*	SwPageFrm::MakeAll()
672 |*
673 |*	Ersterstellung		MA 23. Feb. 93
674 |*	Letzte Aenderung	MA 20. Jul. 98
675 |*
676 |*************************************************************************/
677 // --> OD 2004-07-01 #i28701# - new type <SwSortedObjs>
678 void lcl_CheckObjects( SwSortedObjs* pSortedObjs, SwFrm* pFrm, long& rBot )
679 {
680 	//Und dann kann es natuerlich noch Absatzgebundene
681 	//Rahmen geben, die unterhalb ihres Absatzes stehen.
682 	long nMax = 0;
683 	for ( sal_uInt16 i = 0; i < pSortedObjs->Count(); ++i )
684 	{
685         // --> OD 2004-07-01 #i28701# - consider changed type of <SwSortedObjs>
686         // entries.
687         SwAnchoredObject* pObj = (*pSortedObjs)[i];
688 		long nTmp = 0;
689         if ( pObj->ISA(SwFlyFrm) )
690 		{
691             SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
692 			if( pFly->Frm().Top() != WEIT_WECH &&
693 				( pFrm->IsPageFrm() ? pFly->IsFlyLayFrm() :
694 				  ( pFly->IsFlyAtCntFrm() &&
695                     ( pFrm->IsBodyFrm() ? pFly->GetAnchorFrm()->IsInDocBody() :
696                                           pFly->GetAnchorFrm()->IsInFtn() ) ) ) )
697 			{
698 				nTmp = pFly->Frm().Bottom();
699 			}
700 		}
701 		else
702             nTmp = pObj->GetObjRect().Bottom();
703 		nMax = Max( nTmp, nMax );
704         // <--
705 	}
706 	++nMax; //Unterkante vs. Hoehe!
707 	rBot = Max( rBot, nMax );
708 }
709 
710 void SwPageFrm::MakeAll()
711 {
712 	PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
713 
714 	const SwRect aOldRect( Frm() );		//Anpassung der Root-Groesse
715 	const SwLayNotify aNotify( this );	//uebernimmt im DTor die Benachrichtigung
716 	SwBorderAttrAccess *pAccess = 0;
717 	const SwBorderAttrs*pAttrs = 0;
718 
719     while ( !bValidPos || !bValidSize || !bValidPrtArea )
720 	{
721 		if ( !bValidPos )
722 		{
723             // PAGES01
724             bValidPos = sal_True; // positioning of the pages is taken care of by the root frame
725         }
726 
727 		if ( !bValidSize || !bValidPrtArea )
728 		{
729 			if ( IsEmptyPage() )
730 			{
731 				Frm().Width( 0 );  Prt().Width( 0 );
732 				Frm().Height( 0 ); Prt().Height( 0 );
733 				Prt().Left( 0 );   Prt().Top( 0 );
734 				bValidSize = bValidPrtArea = sal_True;
735 			}
736 			else
737 			{
738 				if ( !pAccess )
739 				{
740 					pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
741 					pAttrs = pAccess->Get();
742 				}
743 				//Bei der BrowseView gelten feste Einstellungen.
744 				ViewShell *pSh = getRootFrm()->GetCurrShell();
745                 if ( pSh && pSh->GetViewOptions()->getBrowseMode() )
746 				{
747 					const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
748 					const long nTop    = pAttrs->CalcTopLine()   + aBorder.Height();
749 					const long nBottom = pAttrs->CalcBottomLine()+ aBorder.Height();
750 
751 					long nWidth = GetUpper() ? ((SwRootFrm*)GetUpper())->GetBrowseWidth() : 0;
752 					if ( nWidth < pSh->GetBrowseWidth() )
753 						nWidth = pSh->GetBrowseWidth();
754 					nWidth += + 2 * aBorder.Width();
755 /*
756 					long nWidth = GetUpper() ? ((SwRootFrm*)GetUpper())->GetBrowseWidth() + 2 * aBorder.Width() : 0;
757 					if ( nWidth < pSh->VisArea().Width() )
758 						nWidth = pSh->VisArea().Width(); */
759 
760 					nWidth = Max( nWidth, 2L * aBorder.Width() + 4L*MM50 );
761 					Frm().Width( nWidth );
762 
763 					SwLayoutFrm *pBody = FindBodyCont();
764 					if ( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
765 					{
766 						//Fuer Spalten gilt eine feste Hoehe
767 						Frm().Height( pAttrs->GetSize().Height() );
768 					}
769 					else
770 					{
771 						//Fuer Seiten ohne Spalten bestimmt der Inhalt die
772 						//Groesse.
773 						long nBot = Frm().Top() + nTop;
774 						SwFrm *pFrm = Lower();
775 						while ( pFrm )
776 						{
777 							long nTmp = 0;
778 							SwFrm *pCnt = ((SwLayoutFrm*)pFrm)->ContainsAny();
779 							while ( pCnt && (pCnt->GetUpper() == pFrm ||
780 											 ((SwLayoutFrm*)pFrm)->IsAnLower( pCnt )))
781 							{
782 								nTmp += pCnt->Frm().Height();
783 								if( pCnt->IsTxtFrm() &&
784 									((SwTxtFrm*)pCnt)->IsUndersized() )
785 									nTmp += ((SwTxtFrm*)pCnt)->GetParHeight()
786 											- pCnt->Prt().Height();
787 								else if( pCnt->IsSctFrm() &&
788 										 ((SwSectionFrm*)pCnt)->IsUndersized() )
789 									nTmp += ((SwSectionFrm*)pCnt)->Undersize();
790 								pCnt = pCnt->FindNext();
791 							}
792                             // OD 29.10.2002 #97265# - consider invalid body frame properties
793                             if ( pFrm->IsBodyFrm() &&
794                                  ( !pFrm->GetValidSizeFlag() ||
795                                    !pFrm->GetValidPrtAreaFlag() ) &&
796                                  ( pFrm->Frm().Height() < pFrm->Prt().Height() )
797                                )
798                             {
799                                 nTmp = Min( nTmp, pFrm->Frm().Height() );
800                             }
801                             else
802                             {
803                                 // OD 30.10.2002 #97265# - assert invalid lower property
804                                 ASSERT( !(pFrm->Frm().Height() < pFrm->Prt().Height()),
805                                         "SwPageFrm::MakeAll(): Lower with frame height < printing height" );
806                                 nTmp += pFrm->Frm().Height() - pFrm->Prt().Height();
807                             }
808 							if ( !pFrm->IsBodyFrm() )
809 								nTmp = Min( nTmp, pFrm->Frm().Height() );
810 							nBot += nTmp;
811 							// Hier werden die absatzgebundenen Objekte ueberprueft,
812 							// ob sie ueber den Body/FtnCont hinausragen.
813 							if( pSortedObjs && !pFrm->IsHeaderFrm() &&
814 								!pFrm->IsFooterFrm() )
815 								lcl_CheckObjects( pSortedObjs, pFrm, nBot );
816 							pFrm = pFrm->GetNext();
817 						}
818 						nBot += nBottom;
819 						//Und die Seitengebundenen
820 						if ( pSortedObjs )
821 							lcl_CheckObjects( pSortedObjs, this, nBot );
822 						nBot -= Frm().Top();
823                         // --> OD 2004-11-10 #i35143# - If second page frame
824                         // exists, the first page doesn't have to fulfill the
825                         // visible area.
826                         if ( !GetPrev() && !GetNext() )
827                         // <--
828                         {
829                             nBot = Max( nBot, pSh->VisArea().Height() );
830                         }
831                         // --> OD 2004-11-10 #i35143# - Assure, that the page
832                         // doesn't exceed the defined browse height.
833                         Frm().Height( Min( nBot, BROWSE_HEIGHT ) );
834                         // <--
835 					}
836 					Prt().Left ( pAttrs->CalcLeftLine() + aBorder.Width() );
837 					Prt().Top  ( nTop );
838 					Prt().Width( Frm().Width() - ( Prt().Left()
839 						+ pAttrs->CalcRightLine() + aBorder.Width() ) );
840 					Prt().Height( Frm().Height() - (nTop + nBottom) );
841 					bValidSize = bValidPrtArea = sal_True;
842 				}
843 				else
844 				{	//FixSize einstellen, bei Seiten nicht vom Upper sondern vom
845 					//Attribut vorgegeben.
846 					Frm().SSize( pAttrs->GetSize() );
847 					Format( pAttrs );
848 				}
849 			}
850 		}
851 	} //while ( !bValidPos || !bValidSize || !bValidPrtArea )
852 	delete pAccess;
853 
854     // PAGES01
855     if ( Frm() != aOldRect && GetUpper() )
856         static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 );
857 
858 #ifdef DBG_UTIL
859 	//Der Upper (Root) muss mindestens so breit
860 	//sein, dass er die breiteste Seite aufnehmen kann.
861 	if ( GetUpper() )
862     {
863         ASSERT( GetUpper()->Prt().Width() >= aFrm.Width(), "Rootsize" );
864 	}
865 #endif
866 }
867 
868 /*************************************************************************
869 |*
870 |*	SwLayoutFrm::MakeAll()
871 |*
872 |*	Ersterstellung		MA ??
873 |*	Letzte Aenderung	MA 28. Nov. 95
874 |*
875 |*************************************************************************/
876 
877 
878 void SwLayoutFrm::MakeAll()
879 {
880 	PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
881 
882 		//uebernimmt im DTor die Benachrichtigung
883 	const SwLayNotify aNotify( this );
884     sal_Bool bVert = IsVertical();
885     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
886     SwRectFn fnRect = ( IsNeighbourFrm() == bVert )? fnRectHori : ( IsVertLR() ? fnRectVertL2R : fnRectVert );
887 
888 	SwBorderAttrAccess *pAccess = 0;
889 	const SwBorderAttrs*pAttrs = 0;
890 
891 	while ( !bValidPos || !bValidSize || !bValidPrtArea )
892 	{
893 		if ( !bValidPos )
894 			MakePos();
895 
896 		if ( GetUpper() )
897 		{
898             // NEW TABLES
899             if ( IsLeaveUpperAllowed() )
900             {
901                 if ( !bValidSize )
902                     bValidPrtArea = sal_False;
903             }
904             else
905             {
906                 if ( !bValidSize )
907                 {
908                     //FixSize einstellen, die VarSize wird von Format() nach
909                     //Berechnung der PrtArea eingestellt.
910                     bValidPrtArea = sal_False;
911 
912                     SwTwips nPrtWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
913                     if( bVert && ( IsBodyFrm() || IsFtnContFrm() ) )
914                     {
915                         SwFrm* pNxt = GetPrev();
916                         while( pNxt && !pNxt->IsHeaderFrm() )
917                             pNxt = pNxt->GetPrev();
918                         if( pNxt )
919                             nPrtWidth -= pNxt->Frm().Height();
920                         pNxt = GetNext();
921                         while( pNxt && !pNxt->IsFooterFrm() )
922                             pNxt = pNxt->GetNext();
923                         if( pNxt )
924                             nPrtWidth -= pNxt->Frm().Height();
925                     }
926 
927                     const long nDiff = nPrtWidth - (Frm().*fnRect->fnGetWidth)();
928 
929                     if( IsNeighbourFrm() && IsRightToLeft() )
930                         (Frm().*fnRect->fnSubLeft)( nDiff );
931                     else
932                         (Frm().*fnRect->fnAddRight)( nDiff );
933                 }
934                 else
935                 {
936                     // Don't leave your upper
937                     const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
938                     if( (Frm().*fnRect->fnOverStep)( nDeadLine ) )
939                         bValidSize = sal_False;
940                 }
941             }
942 		}
943 		if ( !bValidSize || !bValidPrtArea )
944 		{
945 			if ( !pAccess )
946 			{
947 				pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
948 				pAttrs  = pAccess->Get();
949 			}
950 			Format( pAttrs );
951 		}
952 	} //while ( !bValidPos || !bValidSize || !bValidPrtArea )
953 	if ( pAccess )
954 		delete pAccess;
955 }
956 
957 /*************************************************************************
958 |*
959 |*	SwCntntFrm::MakePrtArea()
960 |*
961 |*	Ersterstellung		MA 17. Nov. 92
962 |*	Letzte Aenderung	MA 03. Mar. 96
963 |*
964 |*************************************************************************/
965 
966 sal_Bool SwCntntFrm::MakePrtArea( const SwBorderAttrs &rAttrs )
967 {
968 	sal_Bool bSizeChgd = sal_False;
969 
970 	if ( !bValidPrtArea )
971 	{
972 		bValidPrtArea = sal_True;
973 
974         SWRECTFN( this )
975 		const sal_Bool bTxtFrm = IsTxtFrm();
976 		SwTwips nUpper = 0;
977 		if ( bTxtFrm && ((SwTxtFrm*)this)->IsHiddenNow() )
978 		{
979 			if ( ((SwTxtFrm*)this)->HasFollow() )
980 				((SwTxtFrm*)this)->JoinFrm();
981 
982             if( (Prt().*fnRect->fnGetHeight)() )
983 				((SwTxtFrm*)this)->HideHidden();
984             Prt().Pos().X() = Prt().Pos().Y() = 0;
985             (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() );
986             (Prt().*fnRect->fnSetHeight)( 0 );
987             nUpper = -( (Frm().*fnRect->fnGetHeight)() );
988 		}
989 		else
990 		{
991 			//Vereinfachung: CntntFrms sind immer in der Hoehe Variabel!
992 
993 			//An der FixSize gibt der umgebende Frame die Groesse vor, die
994 			//Raender werden einfach abgezogen.
995             const long nLeft = rAttrs.CalcLeft( this );
996             const long nRight = ((SwBorderAttrs&)rAttrs).CalcRight( this );
997             (this->*fnRect->fnSetXMargins)( nLeft, nRight );
998 
999 			ViewShell *pSh = getRootFrm()->GetCurrShell();
1000             SwTwips nWidthArea;
1001             if( pSh && 0!=(nWidthArea=(pSh->VisArea().*fnRect->fnGetWidth)()) &&
1002                 GetUpper()->IsPageBodyFrm() &&  // nicht dagegen bei BodyFrms in Columns
1003                 pSh->GetViewOptions()->getBrowseMode() )
1004 			{
1005 				//Nicht ueber die Kante des sichbaren Bereiches hinausragen.
1006 				//Die Seite kann breiter sein, weil es Objekte mit "ueberbreite"
1007 				//geben kann (RootFrm::ImplCalcBrowseWidth())
1008 				long nMinWidth = 0;
1009 
1010 				for (sal_uInt16 i = 0; GetDrawObjs() && i < GetDrawObjs()->Count();++i)
1011 				{
1012                     // --> OD 2004-07-01 #i28701# - consider changed type of
1013                     // <SwSortedObjs> entries
1014                     SwAnchoredObject* pObj = (*GetDrawObjs())[i];
1015                     const SwFrmFmt& rFmt = pObj->GetFrmFmt();
1016                     const sal_Bool bFly = pObj->ISA(SwFlyFrm);
1017                     if ((bFly && (WEIT_WECH == pObj->GetObjRect().Width()))
1018                         || rFmt.GetFrmSize().GetWidthPercent())
1019                     {
1020 						continue;
1021                     }
1022 
1023                     if ( FLY_AS_CHAR == rFmt.GetAnchor().GetAnchorId() )
1024                     {
1025 						nMinWidth = Max( nMinWidth,
1026                                          bFly ? rFmt.GetFrmSize().GetWidth()
1027                                               : pObj->GetObjRect().Width() );
1028                     }
1029                     // <--
1030 				}
1031 
1032 				const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
1033                 long nWidth = nWidthArea - 2 * ( IsVertical() ? aBorder.Height() : aBorder.Width() );
1034                 nWidth -= (Prt().*fnRect->fnGetLeft)();
1035 				nWidth -= rAttrs.CalcRightLine();
1036 				nWidth = Max( nMinWidth, nWidth );
1037                 (Prt().*fnRect->fnSetWidth)( Min( nWidth,
1038                                             (Prt().*fnRect->fnGetWidth)() ) );
1039 			}
1040 
1041             if ( (Prt().*fnRect->fnGetWidth)() <= MINLAY )
1042 			{
1043 				//Die PrtArea sollte schon wenigstens MINLAY breit sein, passend
1044 				//zu den Minimalwerten des UI
1045                 (Prt().*fnRect->fnSetWidth)( Min( long(MINLAY),
1046                                              (Frm().*fnRect->fnGetWidth)() ) );
1047                 SwTwips nTmp = (Frm().*fnRect->fnGetWidth)() -
1048                                (Prt().*fnRect->fnGetWidth)();
1049                 if( (Prt().*fnRect->fnGetLeft)() > nTmp )
1050                     (Prt().*fnRect->fnSetLeft)( nTmp );
1051 			}
1052 
1053 			//Fuer die VarSize gelten folgende Regeln:
1054 			//1. Der erste einer Kette hat keinen Rand nach oben
1055 			//2. Nach unten gibt es nie einen Rand
1056 			//3. Der Rand nach oben ist das Maximum aus dem Abstand des
1057 			//	 Prev nach unten und dem eigenen Abstand nach oben.
1058 			//Die drei Regeln werden auf die Berechnung der Freiraeume, die von
1059 			//UL- bzw. LRSpace vorgegeben werden, angewand. Es gibt in alle
1060 			//Richtungen jedoch ggf. trotzdem einen Abstand; dieser wird durch
1061 			//Umrandung und/oder Schatten vorgegeben.
1062 			//4. Der Abstand fuer TextFrms entspricht mindestens dem Durchschuss
1063 
1064 			nUpper = CalcUpperSpace( &rAttrs, NULL );
1065 
1066             // OD 2004-03-02 #106629# - use new method <CalcLowerSpace(..)>
1067             SwTwips nLower = CalcLowerSpace( &rAttrs );
1068 //            // in balanced columned section frames we do not want the
1069 //            // common border
1070 //            sal_Bool bCommonBorder = sal_True;
1071 //            if ( IsInSct() && GetUpper()->IsColBodyFrm() )
1072 //            {
1073 //                const SwSectionFrm* pSct = FindSctFrm();
1074 //                bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue();
1075 //            }
1076 //            SwTwips nLower = bCommonBorder ?
1077 //                             rAttrs.GetBottomLine( this ) :
1078 //                             rAttrs.CalcBottomLine();
1079 
1080             (Prt().*fnRect->fnSetPosY)( (!bVert || bReverse) ? nUpper : nLower);
1081             nUpper += nLower;
1082             nUpper -= (Frm().*fnRect->fnGetHeight)() -
1083                       (Prt().*fnRect->fnGetHeight)();
1084 		}
1085 		//Wenn Unterschiede zwischen Alter und neuer Groesse,
1086 		//Grow() oder Shrink() rufen
1087 		if ( nUpper )
1088 		{
1089 			if ( nUpper > 0 )
1090                 GrowFrm( nUpper );
1091 			else
1092                 ShrinkFrm( -nUpper );
1093 			bSizeChgd = sal_True;
1094 		}
1095 	}
1096 	return bSizeChgd;
1097 }
1098 
1099 /*************************************************************************
1100 |*
1101 |*	SwCntntFrm::MakeAll()
1102 |*
1103 |*	Ersterstellung		MA ??
1104 |*	Letzte Aenderung	MA 16. Dec. 96
1105 |*
1106 |*************************************************************************/
1107 
1108 #define STOP_FLY_FORMAT 10
1109 // --> OD 2006-09-25 #b6448963# - loop prevention
1110 const int cnStopFormat = 15;
1111 // <--
1112 
1113 inline void ValidateSz( SwFrm *pFrm )
1114 {
1115 	if ( pFrm )
1116 	{
1117 		pFrm->bValidSize = sal_True;
1118 		pFrm->bValidPrtArea = sal_True;
1119 	}
1120 }
1121 
1122 void SwCntntFrm::MakeAll()
1123 {
1124 	ASSERT( GetUpper(), "keinen Upper?" );
1125 	ASSERT( IsTxtFrm(), "MakeAll(), NoTxt" );
1126 
1127 	if ( !IsFollow() && StackHack::IsLocked() )
1128 		return;
1129 
1130 	if ( IsJoinLocked() )
1131 		return;
1132 
1133     ASSERT( !((SwTxtFrm*)this)->IsSwapped(), "Calculation of a swapped frame" );
1134 
1135     StackHack aHack;
1136 
1137 	if ( ((SwTxtFrm*)this)->IsLocked() )
1138 	{
1139 		ASSERT( sal_False, "Format fuer gelockten TxtFrm." );
1140 		return;
1141 	}
1142 
1143 	LockJoin();
1144     long nFormatCount = 0;
1145     // --> OD 2006-09-25 #b6448963# - loop prevention
1146     int nConsequetiveFormatsWithoutChange = 0;
1147     // <--
1148 	PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
1149 
1150 #ifdef DBG_UTIL
1151     const SwDoc *pDoc = GetAttrSet()->GetDoc();
1152 	if( pDoc )
1153 	{
1154 		static sal_Bool bWarn = sal_False;
1155 		if( pDoc->InXMLExport() )
1156 		{
1157 			ASSERT( bWarn, "Formatting during XML-export!" );
1158 			bWarn = sal_True;
1159 		}
1160 		else
1161 			bWarn = sal_False;
1162 	}
1163 #endif
1164 
1165 	//uebernimmt im DTor die Benachrichtigung
1166 	SwCntntNotify *pNotify = new SwCntntNotify( this );
1167 
1168 	sal_Bool	bMakePage	= sal_True;		//solange sal_True kann eine neue Seite
1169 									//angelegt werden (genau einmal)
1170 	sal_Bool 	bMovedBwd	= sal_False;	//Wird sal_True wenn der Frame zurueckfliesst
1171 	sal_Bool	bMovedFwd	= sal_False;	//solange sal_False kann der Frm zurueck-
1172 									//fliessen (solange, bis er einmal
1173 									//vorwaerts ge'moved wurde).
1174 	sal_Bool	bFormatted	= sal_False;	//Fuer die Witwen und Waisen Regelung
1175 									//wird der letzte CntntFrm einer Kette
1176 									//u.U. zum Formatieren angeregt, dies
1177 									//braucht nur einmal zu passieren.
1178 									//Immer wenn der Frm gemoved wird muss
1179 									//das Flag zurueckgesetzt werden.
1180 	sal_Bool	bMustFit	= sal_False;	//Wenn einmal die Notbremse gezogen wurde,
1181 									//werden keine anderen Prepares mehr
1182 									//abgesetzt.
1183 	sal_Bool	bFitPromise = sal_False;	//Wenn ein Absatz nicht passte, mit WouldFit
1184 									//aber verspricht, dass er sich passend
1185 									//einstellt wird dieses Flag gesetzt.
1186 									//Wenn er dann sein Versprechen nicht haelt,
1187 									//kann kontrolliert verfahren werden.
1188 	sal_Bool bMoveable;
1189 	const sal_Bool bFly	= IsInFly();
1190 	const sal_Bool bTab = IsInTab();
1191 	const sal_Bool bFtn = IsInFtn();
1192 	const sal_Bool bSct = IsInSct();
1193 	Point aOldFrmPos;				//Damit bei Turnarounds jew. mit der
1194 	Point aOldPrtPos;				//letzten Pos verglichen und geprueft
1195 									//werden kann, ob ein Prepare sinnvoll ist.
1196 
1197 	SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
1198 	const SwBorderAttrs &rAttrs = *aAccess.Get();
1199 
1200     // OD 2004-02-26 #i25029#
1201     if ( !IsFollow() && rAttrs.JoinedWithPrev( *(this) ) )
1202     {
1203         pNotify->SetBordersJoinedWithPrev();
1204     }
1205 
1206     const sal_Bool bKeep = IsKeep( rAttrs.GetAttrSet() );
1207 
1208 	SwSaveFtnHeight *pSaveFtn = 0;
1209 	if ( bFtn )
1210 	{
1211 		SwFtnFrm *pFtn = FindFtnFrm();
1212 		SwSectionFrm* pSct = pFtn->FindSctFrm();
1213 		if ( !((SwTxtFrm*)pFtn->GetRef())->IsLocked() )
1214 		{
1215 			SwFtnBossFrm* pBoss = pFtn->GetRef()->FindFtnBossFrm(
1216 									pFtn->GetAttr()->GetFtn().IsEndNote() );
1217 			if( !pSct || pSct->IsColLocked() || !pSct->Growable() )
1218 				pSaveFtn = new SwSaveFtnHeight( pBoss,
1219                     ((SwTxtFrm*)pFtn->GetRef())->GetFtnLine( pFtn->GetAttr() ) );
1220 		}
1221 	}
1222 
1223     // --> OD 2008-08-12 #b6732519#
1224     if ( GetUpper()->IsSctFrm() &&
1225          HasFollow() &&
1226          GetFollow()->GetFrm() == GetNext() )
1227     {
1228         dynamic_cast<SwTxtFrm*>(this)->JoinFrm();
1229     }
1230     // <--
1231 
1232     // --> OD 2004-06-23 #i28701# - move master forward, if it has to move,
1233     // because of its object positioning.
1234     if ( !static_cast<SwTxtFrm*>(this)->IsFollow() )
1235     {
1236         sal_uInt32 nToPageNum = 0L;
1237         const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos(
1238                                                     *(GetAttrSet()->GetDoc()),
1239                                                     *(static_cast<SwTxtFrm*>(this)),
1240                                                     nToPageNum );
1241         // --> OD 2006-01-27 #i58182#
1242         // Also move a paragraph forward, which is the first one inside a table cell.
1243         if ( bMoveFwdByObjPos &&
1244              FindPageFrm()->GetPhyPageNum() < nToPageNum &&
1245              ( lcl_Prev( this ) ||
1246                GetUpper()->IsCellFrm() ||
1247                ( GetUpper()->IsSctFrm() &&
1248                  GetUpper()->GetUpper()->IsCellFrm() ) ) &&
1249              IsMoveable() )
1250         {
1251             bMovedFwd = sal_True;
1252             MoveFwd( bMakePage, sal_False );
1253         }
1254         // <--
1255     }
1256     // <--
1257 
1258     //Wenn ein Follow neben seinem Master steht und nicht passt, kann er
1259 	//gleich verschoben werden.
1260     if ( lcl_Prev( this ) && ((SwTxtFrm*)this)->IsFollow() && IsMoveable() )
1261 	{
1262 		bMovedFwd = sal_True;
1263         // OD 2004-03-02 #106629# - If follow frame is in table, it's master
1264         // will be the last in the current table cell. Thus, invalidate the
1265         // printing area of the master,
1266         if ( IsInTab() )
1267         {
1268             lcl_Prev( this )->InvalidatePrt();
1269         }
1270         MoveFwd( bMakePage, sal_False );
1271     }
1272 
1273     // OD 08.11.2002 #104840# - check footnote content for forward move.
1274     // If a content of a footnote is on a prior page/column as its invalid
1275     // reference, it can be moved forward.
1276     if ( bFtn && !bValidPos )
1277     {
1278         SwFtnFrm* pFtn = FindFtnFrm();
1279         SwCntntFrm* pRefCnt = pFtn ? pFtn->GetRef() : 0;
1280         if ( pRefCnt && !pRefCnt->IsValid() )
1281         {
1282             SwFtnBossFrm* pFtnBossOfFtn = pFtn->FindFtnBossFrm();
1283             SwFtnBossFrm* pFtnBossOfRef = pRefCnt->FindFtnBossFrm();
1284             //<loop of movefwd until condition held or no move>
1285             if ( pFtnBossOfFtn && pFtnBossOfRef &&
1286                  pFtnBossOfFtn != pFtnBossOfRef &&
1287                  pFtnBossOfFtn->IsBefore( pFtnBossOfRef ) )
1288             {
1289                 bMovedFwd = sal_True;
1290                 MoveFwd( bMakePage, sal_False );
1291             }
1292         }
1293     }
1294 
1295     SWRECTFN( this )
1296 
1297 	while ( !bValidPos || !bValidSize || !bValidPrtArea )
1298 	{
1299         // --> OD 2006-09-25 #b6448963# - loop prevention
1300         SwRect aOldFrm_StopFormat( Frm() );
1301         SwRect aOldPrt_StopFormat( Prt() );
1302         // <--
1303 		if ( sal_True == (bMoveable = IsMoveable()) )
1304 		{
1305 			SwFrm *pPre = GetIndPrev();
1306 			if ( CheckMoveFwd( bMakePage, bKeep, bMovedBwd ) )
1307 			{
1308                 SWREFRESHFN( this )
1309 				bMovedFwd = sal_True;
1310 				if ( bMovedBwd )
1311 				{
1312 					//Beim zurueckfliessen wurde der Upper angeregt sich
1313 					//vollstaendig zu Painten, dass koennen wir uns jetzt
1314 					//nach dem hin und her fliessen sparen.
1315 					GetUpper()->ResetCompletePaint();
1316 					//Der Vorgaenger wurde Invalidiert, das ist jetzt auch obsolete.
1317 					ASSERT( pPre, "missing old Prev" );
1318 					if( !pPre->IsSctFrm() )
1319 						::ValidateSz( pPre );
1320 				}
1321 				bMoveable = IsMoveable();
1322 			}
1323 		}
1324 
1325         aOldFrmPos = (Frm().*fnRect->fnGetPos)();
1326         aOldPrtPos = (Prt().*fnRect->fnGetPos)();
1327 
1328 		if ( !bValidPos )
1329 			MakePos();
1330 
1331 		//FixSize einstellen, die VarSize wird von Format() justiert.
1332 		if ( !bValidSize )
1333         {
1334             // --> OD 2006-01-03 #125452#
1335             // invalidate printing area flag, if the following conditions are hold:
1336             // - current frame width is 0.
1337             // - current printing area width is 0.
1338             // - frame width is adjusted to a value greater than 0.
1339             // - printing area flag is sal_True.
1340             // Thus, it's assured that the printing area is adjusted, if the
1341             // frame area width changes its width from 0 to something greater
1342             // than 0.
1343             // Note: A text frame can be in such a situation, if the format is
1344             //       triggered by method call <SwCrsrShell::SetCrsr()> after
1345             //       loading the document.
1346             const SwTwips nNewFrmWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
1347             if ( bValidPrtArea && nNewFrmWidth > 0 &&
1348                  (Frm().*fnRect->fnGetWidth)() == 0 &&
1349                  (Prt().*fnRect->fnGetWidth)() == 0 )
1350             {
1351                 bValidPrtArea = sal_False;
1352             }
1353 
1354             (Frm().*fnRect->fnSetWidth)( nNewFrmWidth );
1355             // <--
1356         }
1357 		if ( !bValidPrtArea )
1358 		{
1359             const long nOldW = (Prt().*fnRect->fnGetWidth)();
1360             // --> OD 2004-09-28 #i34730# - keep current frame height
1361             const SwTwips nOldH = (Frm().*fnRect->fnGetHeight)();
1362             // <--
1363 			MakePrtArea( rAttrs );
1364             if ( nOldW != (Prt().*fnRect->fnGetWidth)() )
1365 				Prepare( PREP_FIXSIZE_CHG );
1366             // --> OD 2004-09-28 #i34730# - check, if frame height has changed.
1367             // If yes, send a PREP_ADJUST_FRM and invalidate the size flag to
1368             // force a format. The format will check in its method
1369             // <SwTxtFrm::CalcPreps()>, if the already formatted lines still
1370             // fit and if not, performs necessary actions.
1371             // --> OD 2005-01-10 #i40150# - no check, if frame is undersized.
1372             if ( bValidSize && !IsUndersized() &&
1373                  nOldH != (Frm().*fnRect->fnGetHeight)() )
1374             {
1375                 // --> OD 2004-11-25 #115759# - no PREP_ADJUST_FRM and size
1376                 // invalidation, if height decreases only by the additional
1377                 // lower space as last content of a table cell and an existing
1378                 // follow containing one line exists.
1379                 const SwTwips nHDiff = nOldH - (Frm().*fnRect->fnGetHeight)();
1380                 const bool bNoPrepAdjustFrm =
1381                     nHDiff > 0 && IsInTab() && GetFollow() &&
1382                     ( 1 == static_cast<SwTxtFrm*>(GetFollow())->GetLineCount( STRING_LEN ) || (static_cast<SwTxtFrm*>(GetFollow())->Frm().*fnRect->fnGetWidth)() < 0 ) &&
1383                     GetFollow()->CalcAddLowerSpaceAsLastInTableCell() == nHDiff;
1384                 if ( !bNoPrepAdjustFrm )
1385                 {
1386                     Prepare( PREP_ADJUST_FRM );
1387                     bValidSize = sal_False;
1388                 }
1389                 // <--
1390             }
1391             // <--
1392 		}
1393 
1394 		//Damit die Witwen- und Waisen-Regelung eine Change bekommt muss der
1395 		//CntntFrm benachrichtigt werden.
1396 		//Kriterium:
1397 		//- Er muss Moveable sein (sonst mach das Spalten keinen Sinn.)
1398 		//- Er muss mit der Unterkante der PrtArea des Upper ueberlappen.
1399 		if ( !bMustFit )
1400 		{
1401 			sal_Bool bWidow = sal_True;
1402             const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1403             if ( bMoveable && !bFormatted && ( GetFollow() ||
1404                  ( (Frm().*fnRect->fnOverStep)( nDeadLine ) ) ) )
1405             {
1406 				Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
1407 				bValidSize = bWidow = sal_False;
1408 			}
1409             if( (Frm().*fnRect->fnGetPos)() != aOldFrmPos ||
1410                 (Prt().*fnRect->fnGetPos)() != aOldPrtPos )
1411 			{
1412 				// In diesem Prepare erfolgt ggf. ein _InvalidateSize().
1413 				// bValidSize wird sal_False und das Format() wird gerufen.
1414 				Prepare( PREP_POS_CHGD, (const void*)&bFormatted, sal_False );
1415 				if ( bWidow && GetFollow() )
1416 				{	Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
1417 					bValidSize = sal_False;
1418 				}
1419 			}
1420 		}
1421 		if ( !bValidSize )
1422         {
1423             bValidSize = bFormatted = sal_True;
1424             ++nFormatCount;
1425             if( nFormatCount > STOP_FLY_FORMAT )
1426                 SetFlyLock( sal_True );
1427             // --> OD 2006-09-25 #b6448963# - loop prevention
1428             // No format any longer, if <cnStopFormat> consequetive formats
1429             // without change occur.
1430             if ( nConsequetiveFormatsWithoutChange <= cnStopFormat )
1431             {
1432                 Format();
1433             }
1434 #if OSL_DEBUG_LEVEL > 1
1435             else
1436             {
1437                 ASSERT( false, "debug assertion: <SwCntntFrm::MakeAll()> - format of text frame suppressed by fix b6448963" );
1438             }
1439 #endif
1440             // <--
1441 		}
1442 
1443         // FME 16.07.2003 #i16930# - removed this code because it did not work
1444 
1445         // OD 04.04.2003 #108446# - react on the situation detected in the text
1446         // formatting - see <SwTxtFrm::FormatAdjust(..)>:
1447         // text frame has to move forward, because its text formatting stopped,
1448         // created a follow and detected, that it contains no content.
1449 /*        if ( IsTxtFrm() && bValidPos && bValidSize && bValidPrtArea &&
1450              (Frm().*fnRect->fnGetHeight)() == 0 &&
1451              HasFollow()
1452            )
1453         {
1454             SwFrm* pOldUpper = GetUpper();
1455             MoveFwd( sal_True, sal_False );
1456             if ( GetUpper() != pOldUpper )
1457             {
1458                 bMovedFwd = sal_True;
1459                 SWREFRESHFN( this )
1460                 continue;
1461             }
1462         } */
1463 
1464         //Wenn ich der erste einer Kette bin koennte ich mal sehen ob
1465 		//ich zurueckfliessen kann (wenn ich mich ueberhaupt bewegen soll).
1466 		//Damit es keine Oszillation gibt, darf ich nicht gerade vorwaerts
1467 		//geflossen sein.
1468 		sal_Bool bDummy;
1469         if ( !lcl_Prev( this ) &&
1470              !bMovedFwd &&
1471              ( bMoveable || ( bFly && !bTab ) ) &&
1472 			 ( !bFtn || !GetUpper()->FindFtnFrm()->GetPrev() )
1473              && MoveBwd( bDummy ) )
1474         {
1475             SWREFRESHFN( this )
1476 			bMovedBwd = sal_True;
1477 			bFormatted = sal_False;
1478             if ( bKeep && bMoveable )
1479 			{
1480 				if( CheckMoveFwd( bMakePage, sal_False, bMovedBwd ) )
1481 				{
1482 					bMovedFwd = sal_True;
1483 					bMoveable = IsMoveable();
1484                     SWREFRESHFN( this )
1485 				}
1486                 Point aOldPos = (Frm().*fnRect->fnGetPos)();
1487                 MakePos();
1488                 if( aOldPos != (Frm().*fnRect->fnGetPos)() )
1489 				{
1490 					Prepare( PREP_POS_CHGD, (const void*)&bFormatted, sal_False );
1491 					if ( !bValidSize )
1492 					{
1493                         (Frm().*fnRect->fnSetWidth)( (GetUpper()->
1494                                                 Prt().*fnRect->fnGetWidth)() );
1495 						if ( !bValidPrtArea )
1496 						{
1497                             const long nOldW = (Prt().*fnRect->fnGetWidth)();
1498                             MakePrtArea( rAttrs );
1499                             if( nOldW != (Prt().*fnRect->fnGetWidth)() )
1500 								Prepare( PREP_FIXSIZE_CHG, 0, sal_False );
1501 						}
1502 						if( GetFollow() )
1503 							Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
1504 						bValidSize = bFormatted = sal_True;
1505 						Format();
1506 					}
1507 				}
1508                 SwFrm *pNxt = HasFollow() ? NULL : FindNext();
1509 				while( pNxt && pNxt->IsSctFrm() )
1510 				{   // Leere Bereiche auslassen, in die anderen hinein
1511 					if( ((SwSectionFrm*)pNxt)->GetSection() )
1512 					{
1513 						SwFrm* pTmp = ((SwSectionFrm*)pNxt)->ContainsAny();
1514 						if( pTmp )
1515 						{
1516 							pNxt = pTmp;
1517 							break;
1518 						}
1519 					}
1520 					pNxt = pNxt->FindNext();
1521 				}
1522                 if ( pNxt )
1523 				{
1524                     pNxt->Calc();
1525                     if( bValidPos && !GetIndNext() )
1526                     {
1527                         SwSectionFrm *pSct = FindSctFrm();
1528                         if( pSct && !pSct->GetValidSizeFlag() )
1529                         {
1530                             SwSectionFrm* pNxtSct = pNxt->FindSctFrm();
1531                             if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
1532                                 bValidPos = sal_False;
1533                         }
1534                         else
1535                             bValidPos = sal_False;
1536                     }
1537 				}
1538 			}
1539 		}
1540 
1541 		//Der TxtFrm Validiert sich bei Fussnoten ggf. selbst, dass kann leicht
1542 		//dazu fuehren, dass seine Position obwohl unrichtig valide ist.
1543 		if ( bValidPos )
1544 		{
1545             // --> OD 2006-01-23 #i59341#
1546             // Workaround for inadequate layout algorithm:
1547             // suppress invalidation and calculation of position, if paragraph
1548             // has formatted itself at least STOP_FLY_FORMAT times and
1549             // has anchored objects.
1550             // Thus, the anchored objects get the possibility to format itself
1551             // and this probably solve the layout loop.
1552             if ( bFtn &&
1553                  nFormatCount <= STOP_FLY_FORMAT &&
1554                  !GetDrawObjs() )
1555             // <--
1556             {
1557                 bValidPos = sal_False;
1558                 MakePos();
1559                 aOldFrmPos = (Frm().*fnRect->fnGetPos)();
1560                 aOldPrtPos = (Prt().*fnRect->fnGetPos)();
1561             }
1562 		}
1563 
1564         // --> OD 2006-09-25 #b6448963# - loop prevention
1565         {
1566             if ( aOldFrm_StopFormat == Frm() &&
1567                  aOldPrt_StopFormat == Prt() )
1568             {
1569                 ++nConsequetiveFormatsWithoutChange;
1570             }
1571             else
1572             {
1573                 nConsequetiveFormatsWithoutChange = 0;
1574             }
1575         }
1576         // <--
1577 
1578 		//Wieder ein Wert ungueltig? - dann nochmal das ganze...
1579 		if ( !bValidPos || !bValidSize || !bValidPrtArea )
1580 			continue;
1581 
1582 		//Fertig?
1583 		// Achtung, wg. Hoehe==0, ist es besser statt Bottom() Top()+Height() zu nehmen
1584         // (kommt bei Undersized TxtFrms an der Unterkante eines spaltigen Bereichs vor)
1585         const long nPrtBottom = (GetUpper()->*fnRect->fnGetPrtBottom)();
1586         const long nBottomDist =  (Frm().*fnRect->fnBottomDist)( nPrtBottom );
1587         if( nBottomDist >= 0 )
1588 		{
1589             if ( bKeep && bMoveable )
1590 			{
1591 				//Wir sorgen dafuer, dass der Nachfolger gleich mit formatiert
1592 				//wird. Dadurch halten wir das Heft in der Hand, bis wirklich
1593 				//(fast) alles stabil ist. So vermeiden wir Endlosschleifen,
1594 				//die durch staendig wiederholte Versuche entstehen.
1595 				//Das bMoveFwdInvalid ist fuer #38407# notwendig. War urspruenglich
1596 				//in flowfrm.cxx rev 1.38 behoben, das unterbrach aber obiges
1597 				//Schema und spielte lieber Tuerme von Hanoi (#43669#).
1598                 SwFrm *pNxt = HasFollow() ? NULL : FindNext();
1599 				// Bei Bereichen nehmen wir lieber den Inhalt, denn nur
1600 				// dieser kann ggf. die Seite wechseln
1601 				while( pNxt && pNxt->IsSctFrm() )
1602 				{
1603 					if( ((SwSectionFrm*)pNxt)->GetSection() )
1604 					{
1605 						pNxt = ((SwSectionFrm*)pNxt)->ContainsAny();
1606 						break;
1607 					}
1608 					pNxt = pNxt->FindNext();
1609 				}
1610 				if ( pNxt )
1611 				{
1612                     const sal_Bool bMoveFwdInvalid = 0 != GetIndNext();
1613                     const sal_Bool bNxtNew =
1614                         ( 0 == (pNxt->Prt().*fnRect->fnGetHeight)() ) &&
1615                         (!pNxt->IsTxtFrm() ||!((SwTxtFrm*)pNxt)->IsHiddenNow());
1616 
1617                     pNxt->Calc();
1618 
1619                     if ( !bMovedBwd &&
1620                          ((bMoveFwdInvalid && !GetIndNext()) ||
1621                           bNxtNew) )
1622                     {
1623                         if( bMovedFwd )
1624                             pNotify->SetInvaKeep();
1625                         bMovedFwd = sal_False;
1626                     }
1627 				}
1628 			}
1629 			continue;
1630 		}
1631 
1632 		//Ich passe nicht mehr in meinen Uebergeordneten, also ist es jetzt
1633 		//an der Zeit moeglichst konstruktive Veranderungen vorzunehmen
1634 
1635 		//Wenn ich den uebergeordneten Frm nicht verlassen darf, habe
1636 		//ich ein Problem; Frei nach Artur Dent tun wir das einzige das man
1637 		//mit einen nicht loesbaren Problem tun kann: wir ignorieren es - und
1638 		//zwar mit aller Kraft.
1639 		if ( !bMoveable || IsUndersized() )
1640 		{
1641 			if( !bMoveable && IsInTab() )
1642 			{
1643                 long nDiff = -(Frm().*fnRect->fnBottomDist)(
1644                                         (GetUpper()->*fnRect->fnGetPrtBottom)() );
1645                 long nReal = GetUpper()->Grow( nDiff );
1646 				if( nReal )
1647 					continue;
1648 			}
1649 			break;
1650 		}
1651 
1652 		//Wenn ich nun ueberhaupt ganz und garnicht in meinen Upper passe
1653 		//so kann die Situation vielleicht doch noch durch Aufbrechen
1654 		//aufgeklart werden. Diese Situation tritt bei einem frisch
1655 		//erzeugten Follow auf, der zwar auf die Folgeseite geschoben wurde
1656 		//aber selbst noch zu gross fuer diese ist; also wiederum
1657 		//aufgespalten werden muss.
1658 		//Wenn ich nicht passe und nicht Spaltbar (WouldFit()) bin, so schicke
1659 		//ich meinem TxtFrmanteil die Nachricht, dass eben falls moeglich
1660 		//trotz des Attributes 'nicht aufspalten' aufgespalten werden muss.
1661 		sal_Bool bMoveOrFit = sal_False;
1662 		sal_Bool bDontMoveMe = !GetIndPrev();
1663 		if( bDontMoveMe && IsInSct() )
1664 		{
1665 			SwFtnBossFrm* pBoss = FindFtnBossFrm();
1666 			bDontMoveMe = !pBoss->IsInSct() ||
1667 						  ( !pBoss->Lower()->GetNext() && !pBoss->GetPrev() );
1668 		}
1669 
1670         // Finally, we are able to split table rows. Therefore, bDontMoveMe
1671         // can be set to sal_False:
1672         if( bDontMoveMe && IsInTab() &&
1673             0 != const_cast<SwCntntFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) )
1674             bDontMoveMe = sal_False;
1675 
1676         if ( bDontMoveMe && (Frm().*fnRect->fnGetHeight)() >
1677                             (GetUpper()->Prt().*fnRect->fnGetHeight)() )
1678 		{
1679             if ( !bFitPromise )
1680 			{
1681                 SwTwips nTmp = (GetUpper()->Prt().*fnRect->fnGetHeight)() -
1682                                (Prt().*fnRect->fnGetTop)();
1683                 sal_Bool bSplit = !IsFwdMoveAllowed();
1684                 if ( nTmp > 0 && WouldFit( nTmp, bSplit, sal_False ) )
1685 				{
1686 					Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
1687 					bValidSize = sal_False;
1688 					bFitPromise = sal_True;
1689 					continue;
1690 				}
1691 				/* -----------------19.02.99 12:58-------------------
1692 				 * Frueher wurde in Rahmen und Bereichen niemals versucht,
1693 				 * durch bMoveOrFit den TxtFrm unter Verzicht auf seine
1694 				 * Attribute (Widows,Keep) doch noch passend zu bekommen.
1695 				 * Dies haette zumindest bei spaltigen Rahmen versucht
1696 				 * werden muessen, spaetestens bei verketteten Rahmen und
1697 				 * in Bereichen muss es versucht werden.
1698 				 * Ausnahme: Wenn wir im FormatWidthCols stehen, duerfen die
1699 				 * Attribute nicht ausser Acht gelassen werden.
1700 				 * --------------------------------------------------*/
1701 				else if ( !bFtn && bMoveable &&
1702 					  ( !bFly || !FindFlyFrm()->IsColLocked() ) &&
1703 					  ( !bSct || !FindSctFrm()->IsColLocked() ) )
1704 					bMoveOrFit = sal_True;
1705             }
1706 #ifdef DBG_UTIL
1707 			else
1708 			{
1709 				ASSERT( sal_False, "+TxtFrm hat WouldFit-Versprechen nicht eingehalten." );
1710 			}
1711 #endif
1712 		}
1713 
1714 		//Mal sehen ob ich irgenwo Platz finde...
1715 		//Benachbarte Fussnoten werden in _MoveFtnCntFwd 'vorgeschoben'
1716 		SwFrm *pPre = GetIndPrev();
1717 		SwFrm *pOldUp = GetUpper();
1718 
1719 /* MA 13. Oct. 98: Was soll das denn sein!?
1720  * AMA 14. Dec 98: Wenn ein spaltiger Bereich keinen Platz mehr fuer seinen ersten ContentFrm
1721  * 		bietet, so soll dieser nicht nur in die naechste Spalte, sondern ggf. bis zur naechsten
1722  * 		Seite wandern und dort einen Section-Follow erzeugen.
1723  */
1724 		if( IsInSct() && bMovedFwd && bMakePage && pOldUp->IsColBodyFrm() &&
1725 			pOldUp->GetUpper()->GetUpper()->IsSctFrm() &&
1726 			( pPre || pOldUp->GetUpper()->GetPrev() ) &&
1727 			((SwSectionFrm*)pOldUp->GetUpper()->GetUpper())->MoveAllowed(this) )
1728 			bMovedFwd = sal_False;
1729 
1730         const sal_Bool bCheckForGrownBody = pOldUp->IsBodyFrm();
1731         const long nOldBodyHeight = (pOldUp->Frm().*fnRect->fnGetHeight)();
1732 
1733 		if ( !bMovedFwd && !MoveFwd( bMakePage, sal_False ) )
1734 			bMakePage = sal_False;
1735         SWREFRESHFN( this )
1736 
1737         // If MoveFwd moves the paragraph to the next page, a following
1738         // paragraph, which contains footnotes can can cause the old upper
1739         // frame to grow. In this case we explicitely allow a new check
1740         // for MoveBwd. Robust: We also check the bMovedBwd flag again.
1741         // If pOldUp was a footnote frame, it has been deleted inside MoveFwd.
1742         // Therefore we only check for growing body frames.
1743         if ( bCheckForGrownBody && ! bMovedBwd && pOldUp != GetUpper() &&
1744              (pOldUp->Frm().*fnRect->fnGetHeight)() > nOldBodyHeight )
1745             bMovedFwd = sal_False;
1746         else
1747             bMovedFwd = sal_True;
1748 
1749         bFormatted = sal_False;
1750 		if ( bMoveOrFit && GetUpper() == pOldUp )
1751 		{
1752             // FME 2007-08-30 #i81146# new loop control
1753             if ( nConsequetiveFormatsWithoutChange <= cnStopFormat )
1754             {
1755     			Prepare( PREP_MUST_FIT, 0, sal_False );
1756 	    		bValidSize = sal_False;
1757 		    	bMustFit = sal_True;
1758 			    continue;
1759             }
1760 
1761 #if OSL_DEBUG_LEVEL > 1
1762             ASSERT( false, "LoopControl in SwCntntFrm::MakeAll" )
1763 #endif
1764 		}
1765 		if ( bMovedBwd && GetUpper() )
1766 		{	//Unuetz gewordene Invalidierungen zuruecknehmen.
1767 			GetUpper()->ResetCompletePaint();
1768 			if( pPre && !pPre->IsSctFrm() )
1769 				::ValidateSz( pPre );
1770 		}
1771 
1772 	} //while ( !bValidPos || !bValidSize || !bValidPrtArea )
1773 
1774 
1775     // NEW: Looping Louie (Light). Should not be applied in balanced sections.
1776     // Should only be applied if there is no better solution!
1777     LOOPING_LOUIE_LIGHT( bMovedFwd && bMovedBwd && !IsInBalancedSection() &&
1778                             (
1779 
1780                                 // --> FME 2005-01-26 #118572#
1781                                 ( bFtn && !FindFtnFrm()->GetRef()->IsInSct() ) ||
1782                                 // <--
1783 
1784                                 // --> FME 2005-01-27 #i33887#
1785                                 ( IsInSct() && bKeep )
1786                                 // <--
1787 
1788                                 // ... add your conditions here ...
1789 
1790                             ),
1791                          static_cast<SwTxtFrm&>(*this) );
1792 
1793 
1794     if ( pSaveFtn )
1795 		delete pSaveFtn;
1796 
1797 	UnlockJoin();
1798 	if ( bMovedFwd || bMovedBwd )
1799 		pNotify->SetInvaKeep();
1800     // OD 2004-02-26 #i25029#
1801     if ( bMovedFwd )
1802     {
1803         pNotify->SetInvalidatePrevPrtArea();
1804     }
1805 	delete pNotify;
1806     SetFlyLock( sal_False );
1807 }
1808 
1809 /*************************************************************************
1810 |*
1811 |*	SwCntntFrm::_WouldFit()
1812 |*
1813 |*	Ersterstellung		MA 28. Feb. 95
1814 |*	Letzte Aenderung	AMA 15. Feb. 99
1815 |*
1816 |*************************************************************************/
1817 
1818 
1819 
1820 
1821 void MakeNxt( SwFrm *pFrm, SwFrm *pNxt )
1822 {
1823 	//fix(25455): Validieren, sonst kommt es zu einer Rekursion.
1824 	//Der erste Versuch, der Abbruch mit pFrm = 0 wenn !Valid,
1825 	//fuehrt leider zu dem Problem, dass das Keep dann u.U. nicht mehr
1826 	//korrekt beachtet wird (27417)
1827 	const sal_Bool bOldPos = pFrm->GetValidPosFlag();
1828 	const sal_Bool bOldSz  = pFrm->GetValidSizeFlag();
1829 	const sal_Bool bOldPrt = pFrm->GetValidPrtAreaFlag();
1830 	pFrm->bValidPos = pFrm->bValidPrtArea = pFrm->bValidSize = sal_True;
1831 
1832 	//fix(29272): Nicht MakeAll rufen, dort wird evtl. pFrm wieder invalidert
1833 	//und kommt rekursiv wieder herein.
1834 	if ( pNxt->IsCntntFrm() )
1835 	{
1836 		SwCntntNotify aNotify( (SwCntntFrm*)pNxt );
1837 		SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNxt );
1838 		const SwBorderAttrs &rAttrs = *aAccess.Get();
1839 		if ( !pNxt->GetValidSizeFlag() )
1840         {
1841             if( pNxt->IsVertical() )
1842                 pNxt->Frm().Height( pNxt->GetUpper()->Prt().Height() );
1843             else
1844                 pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() );
1845         }
1846 		((SwCntntFrm*)pNxt)->MakePrtArea( rAttrs );
1847 		pNxt->Format( &rAttrs );
1848 	}
1849 	else
1850 	{
1851 		SwLayNotify aNotify( (SwLayoutFrm*)pNxt );
1852 		SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNxt );
1853 		const SwBorderAttrs &rAttrs = *aAccess.Get();
1854 		if ( !pNxt->GetValidSizeFlag() )
1855         {
1856             if( pNxt->IsVertical() )
1857                 pNxt->Frm().Height( pNxt->GetUpper()->Prt().Height() );
1858             else
1859                 pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() );
1860         }
1861 		pNxt->Format( &rAttrs );
1862 	}
1863 
1864 	pFrm->bValidPos  	 = bOldPos;
1865 	pFrm->bValidSize 	 = bOldSz;
1866 	pFrm->bValidPrtArea  = bOldPrt;
1867 }
1868 
1869 // Diese Routine ueberprueft, ob zwischen dem FtnBoss von pFrm und dem
1870 // von pNxt keine anderen FtnBosse liegen
1871 
1872 sal_Bool lcl_IsNextFtnBoss( const SwFrm *pFrm, const SwFrm* pNxt )
1873 {
1874 	ASSERT( pFrm && pNxt, "lcl_IsNextFtnBoss: No Frames?" );
1875 	pFrm = pFrm->FindFtnBossFrm();
1876 	pNxt = pNxt->FindFtnBossFrm();
1877 	// Falls pFrm eine letzte Spalte ist, wird stattdessen die Seite genommen
1878 	while( pFrm && pFrm->IsColumnFrm() && !pFrm->GetNext() )
1879 		pFrm = pFrm->GetUpper()->FindFtnBossFrm();
1880 	// Falls pNxt eine erste Spalte ist, wird stattdessen die Seite genommen
1881 	while( pNxt && pNxt->IsColumnFrm() && !pNxt->GetPrev() )
1882 		pNxt = pNxt->GetUpper()->FindFtnBossFrm();
1883 	// So, jetzt muessen pFrm und pNxt entweder zwei benachbarte Seiten oder Spalten sein.
1884 	return ( pFrm && pNxt && pFrm->GetNext() == pNxt );
1885 }
1886 
1887 // --> OD 2007-11-26 #b6614158#
1888 sal_Bool SwCntntFrm::_WouldFit( SwTwips nSpace,
1889                             SwLayoutFrm *pNewUpper,
1890                             sal_Bool bTstMove,
1891                             const bool bObjsInNewUpper )
1892 // <--
1893 {
1894 	//Damit die Fussnote sich ihren Platz sorgsam waehlt, muss
1895 	//sie in jedem Fall gemoved werden, wenn zwischen dem
1896 	//neuen Upper und ihrer aktuellen Seite/Spalte mindestens eine
1897 	//Seite/Spalte liegt.
1898 	SwFtnFrm* pFtnFrm = 0;
1899 	if ( IsInFtn() )
1900 	{
1901 		if( !lcl_IsNextFtnBoss( pNewUpper, this ) )
1902 			return sal_True;
1903 		pFtnFrm = FindFtnFrm();
1904 	}
1905 
1906 	sal_Bool bRet;
1907 	sal_Bool bSplit = !pNewUpper->Lower();
1908 	SwCntntFrm *pFrm = this;
1909     const SwFrm *pTmpPrev = pNewUpper->Lower();
1910     if( pTmpPrev && pTmpPrev->IsFtnFrm() )
1911         pTmpPrev = ((SwFtnFrm*)pTmpPrev)->Lower();
1912     while ( pTmpPrev && pTmpPrev->GetNext() )
1913         pTmpPrev = pTmpPrev->GetNext();
1914 	do
1915 	{
1916         // --> FME 2005-03-31 #b6236853# #i46181#
1917         SwTwips nSecondCheck = 0;
1918         SwTwips nOldSpace = nSpace;
1919         sal_Bool bOldSplit = bSplit;
1920         // <--
1921 
1922 		if ( bTstMove || IsInFly() || ( IsInSct() &&
1923 			 ( pFrm->GetUpper()->IsColBodyFrm() || ( pFtnFrm &&
1924 			   pFtnFrm->GetUpper()->GetUpper()->IsColumnFrm() ) ) ) )
1925 		{
1926 			//Jetzt wirds ein bischen hinterlistig; empfindliche Gemueter sollten
1927 			//lieber wegsehen. Wenn ein Flys Spalten enthaelt so sind die Cntnts
1928 			//moveable, mit Ausnahme der in der letzten Spalte (siehe
1929 			//SwFrm::IsMoveable()). Zurueckfliessen duerfen sie aber natuerlich.
1930 			//Das WouldFit() liefert leider nur dann einen vernueftigen Wert, wenn
1931 			//der Frm moveable ist. Um dem WouldFit() einen Moveable Frm
1932 			//vorzugaukeln haenge ich ihn einfach solange um.
1933 			// Auch bei spaltigen Bereichen muss umgehaengt werden, damit
1934 			// SwSectionFrm::Growable() den richtigen Wert liefert.
1935 			// Innerhalb von Fussnoten muss ggf. sogar der SwFtnFrm umgehaengt werden,
1936 			// falls es dort keinen SwFtnFrm gibt.
1937 			SwFrm* pTmpFrm = pFrm->IsInFtn() && !pNewUpper->FindFtnFrm() ?
1938 							 (SwFrm*)pFrm->FindFtnFrm() : pFrm;
1939 			SwLayoutFrm *pUp = pTmpFrm->GetUpper();
1940 			SwFrm *pOldNext = pTmpFrm->GetNext();
1941 			pTmpFrm->Remove();
1942 			pTmpFrm->InsertBefore( pNewUpper, 0 );
1943             if ( pFrm->IsTxtFrm() &&
1944                  ( bTstMove ||
1945                    ((SwTxtFrm*)pFrm)->HasFollow() ||
1946                    ( !((SwTxtFrm*)pFrm)->HasPara() &&
1947                      !((SwTxtFrm*)pFrm)->IsEmpty()
1948                    )
1949                  )
1950                )
1951 			{
1952 				bTstMove = sal_True;
1953                 bRet = ((SwTxtFrm*)pFrm)->TestFormat( pTmpPrev, nSpace, bSplit );
1954 			}
1955 			else
1956                 bRet = pFrm->WouldFit( nSpace, bSplit, sal_False );
1957 
1958             pTmpFrm->Remove();
1959 			pTmpFrm->InsertBefore( pUp, pOldNext );
1960 		}
1961 		else
1962         {
1963             bRet = pFrm->WouldFit( nSpace, bSplit, sal_False );
1964             nSecondCheck = !bSplit ? 1 : 0;
1965         }
1966 
1967         SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
1968         const SwBorderAttrs &rAttrs = *aAccess.Get();
1969 
1970 		//Bitter aber wahr: Der Abstand muss auch noch mit einkalkuliert werden.
1971 		//Bei TestFormatierung ist dies bereits geschehen.
1972 		if ( bRet && !bTstMove )
1973 		{
1974 			SwTwips nUpper;
1975 
1976             if ( pTmpPrev )
1977 			{
1978                 nUpper = CalcUpperSpace( NULL, pTmpPrev );
1979 
1980                 // in balanced columned section frames we do not want the
1981                 // common border
1982                 sal_Bool bCommonBorder = sal_True;
1983                 if ( pFrm->IsInSct() && pFrm->GetUpper()->IsColBodyFrm() )
1984                 {
1985                     const SwSectionFrm* pSct = pFrm->FindSctFrm();
1986                     bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue();
1987                 }
1988 
1989                 // --> FME 2005-03-31 #b6236853# #i46181#
1990                 nSecondCheck = ( 1 == nSecondCheck &&
1991                                  pFrm == this &&
1992                                  IsTxtFrm() &&
1993                                  bCommonBorder &&
1994                                  !static_cast<const SwTxtFrm*>(this)->IsEmpty() ) ?
1995                                  nUpper :
1996                                  0;
1997                 // <--
1998 
1999                 nUpper += bCommonBorder ?
2000                           rAttrs.GetBottomLine( *(pFrm) ) :
2001                           rAttrs.CalcBottomLine();
2002 
2003             }
2004 			else
2005             {
2006                 // --> FME 2005-03-31 #b6236853# #i46181#
2007                 nSecondCheck = 0;
2008                 // <--
2009 
2010                 if( pFrm->IsVertical() )
2011                     nUpper = pFrm->Frm().Width() - pFrm->Prt().Width();
2012                 else
2013                     nUpper = pFrm->Frm().Height() - pFrm->Prt().Height();
2014             }
2015 
2016 			nSpace -= nUpper;
2017 
2018 			if ( nSpace < 0 )
2019             {
2020 				bRet = sal_False;
2021 
2022                 // --> FME 2005-03-31 #b6236853# #i46181#
2023                 if ( nSecondCheck > 0 )
2024                 {
2025                     // The following code is indented to solve a (rare) problem
2026                     // causing some frames not to move backward:
2027                     // SwTxtFrm::WouldFit() claims that the whole paragraph
2028                     // fits into the given space and subtracts the height of
2029                     // all lines from nSpace. nSpace - nUpper is not a valid
2030                     // indicator if the frame should be allowed to move backward.
2031                     // We do a second check with the original remaining space
2032                     // reduced by the required upper space:
2033                     nOldSpace -= nSecondCheck;
2034                     const bool bSecondRet = nOldSpace >= 0 && pFrm->WouldFit( nOldSpace, bOldSplit, sal_False );
2035                     if ( bSecondRet && bOldSplit && nOldSpace >= 0 )
2036                     {
2037                         bRet = sal_True;
2038                         bSplit = sal_True;
2039                     }
2040                 }
2041                 // <--
2042             }
2043 		}
2044 
2045         // OD 2004-03-01 #106629# - also consider lower spacing in table cells
2046         if ( bRet && IsInTab() &&
2047              pNewUpper->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
2048         {
2049             nSpace -= rAttrs.GetULSpace().GetLower();
2050             if ( nSpace < 0 )
2051             {
2052                 bRet = sal_False;
2053             }
2054         }
2055 
2056         if ( bRet && !bSplit && pFrm->IsKeep( rAttrs.GetAttrSet() ) )
2057 		{
2058 			if( bTstMove )
2059             {
2060 				while( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->HasFollow() )
2061                 {
2062 					pFrm = ((SwTxtFrm*)pFrm)->GetFollow();
2063                 }
2064                 // OD 11.04.2003 #108824# - If last follow frame of <this> text
2065                 // frame isn't valid, a formatting of the next content frame
2066                 // doesn't makes sense. Thus, return sal_True.
2067                 if ( IsAnFollow( pFrm ) && !pFrm->IsValid() )
2068                 {
2069                     ASSERT( false, "Only a warning for task 108824:/n<SwCntntFrm::_WouldFit(..) - follow not valid!" );
2070                     return sal_True;
2071                 }
2072             }
2073 			SwFrm *pNxt;
2074 			if( 0 != (pNxt = pFrm->FindNext()) && pNxt->IsCntntFrm() &&
2075 				( !pFtnFrm || ( pNxt->IsInFtn() &&
2076 				  pNxt->FindFtnFrm()->GetAttr() == pFtnFrm->GetAttr() ) ) )
2077 			{
2078 				// ProbeFormatierung vertraegt keine absatz- oder gar zeichengebundene Objekte
2079                 // --> OD 2007-11-26 #b6614158#
2080                 // current solution for the test formatting doesn't work, if
2081                 // objects are present in the remaining area of the new upper
2082                 if ( bTstMove &&
2083                      ( pNxt->GetDrawObjs() || bObjsInNewUpper ) )
2084                 {
2085                     return sal_True;
2086                 }
2087                 // <--
2088 
2089 				if ( !pNxt->IsValid() )
2090 					MakeNxt( pFrm, pNxt );
2091 
2092 				//Kleiner Trick: Wenn der naechste einen Vorgaenger hat, so hat
2093 				//er den Absatzabstand bereits berechnet. Er braucht dann nicht
2094 				//teuer kalkuliert werden.
2095 				if( lcl_NotHiddenPrev( pNxt ) )
2096                     pTmpPrev = 0;
2097 				else
2098 				{
2099 					if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow() )
2100                         pTmpPrev = lcl_NotHiddenPrev( pFrm );
2101 					else
2102                         pTmpPrev = pFrm;
2103 				}
2104 				pFrm = (SwCntntFrm*)pNxt;
2105 			}
2106 			else
2107 				pFrm = 0;
2108 		}
2109 		else
2110 			pFrm = 0;
2111 
2112 	} while ( bRet && pFrm );
2113 
2114 	return bRet;
2115 }
2116