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