xref: /aoo42x/main/sw/source/core/layout/flowfrm.cxx (revision efeef26f)
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 "pam.hxx"
27 #include "swtable.hxx"
28 #include "frame.hxx"
29 #include "rootfrm.hxx"
30 #include "pagefrm.hxx"
31 #include "flyfrm.hxx"
32 #include "viewsh.hxx"
33 #include "doc.hxx"
34 #include "viewimp.hxx"
35 #include "viewopt.hxx"
36 #include "dflyobj.hxx"
37 #include "frmtool.hxx"
38 #include "dcontact.hxx"
39 #include <editeng/brkitem.hxx>
40 #include <editeng/keepitem.hxx>
41 #include <fmtsrnd.hxx>
42 #include <fmtanchr.hxx>
43 #include <fmtpdsc.hxx>
44 #include <editeng/ulspitem.hxx>
45 #include <tgrditem.hxx>
46 #include <txtftn.hxx>
47 #include <fmtftn.hxx>
48 #include <editeng/pgrditem.hxx>
49 #include <paratr.hxx>
50 #include "ftnfrm.hxx"
51 #include "txtfrm.hxx"
52 #include "tabfrm.hxx"
53 #include "pagedesc.hxx"
54 #include "layact.hxx"
55 #include "fmtornt.hxx"
56 #include "flyfrms.hxx"
57 #include "sectfrm.hxx"
58 #include "section.hxx"
59 #include "dbg_lay.hxx"
60 #include "lineinfo.hxx"
61 #include <fmtclbl.hxx>
62 #include <sortedobjs.hxx>
63 #include <layouter.hxx>
64 #include <fmtfollowtextflow.hxx>
65 #include <switerator.hxx>
66 
67 sal_Bool SwFlowFrm::bMoveBwdJump = sal_False;
68 
69 
70 /*************************************************************************
71 |*
72 |*	SwFlowFrm::SwFlowFrm()
73 |*
74 |*	Ersterstellung		MA 26. Apr. 95
75 |*	Letzte Aenderung	MA 26. Apr. 95
76 |*
77 |*************************************************************************/
78 
79 
80 SwFlowFrm::SwFlowFrm( SwFrm &rFrm ) :
81 	rThis( rFrm ),
82 	pFollow( 0 )
83 {
84     bLockJoin = bIsFollow = bCntntLock = bOwnFtnNum =
85         bFtnLock = bFlyLock = sal_False;
86 }
87 
88 
89 /*************************************************************************
90 |*
91 |*  SwFlowFrm::IsFollowLocked()
92 |*     return sal_True if any follow has the JoinLocked flag
93 |*
94 |*************************************************************************/
95 
96 sal_Bool SwFlowFrm::HasLockedFollow() const
97 {
98     const SwFlowFrm* pFrm = GetFollow();
99     while( pFrm )
100     {
101         if( pFrm->IsJoinLocked() )
102             return sal_True;
103         pFrm = pFrm->GetFollow();
104     }
105     return sal_False;
106 }
107 
108 /*************************************************************************
109 |*
110 |*	SwFlowFrm::IsKeepFwdMoveAllowed()
111 |*
112 |*	Ersterstellung		MA 20. Jul. 94
113 |*	Letzte Aenderung	MA 16. May. 95
114 |*
115 |*************************************************************************/
116 
117 
118 sal_Bool SwFlowFrm::IsKeepFwdMoveAllowed()
119 {
120 	//Wenn der Vorgaenger das KeepAttribut traegt und auch dessen
121 	//Vorgaenger usw. bis zum ersten der Kette und fuer diesen das
122 	//IsFwdMoveAllowed ein sal_False liefert, so ist das Moven eben nicht erlaubt.
123 	SwFrm *pFrm = &rThis;
124 	if ( !pFrm->IsInFtn() )
125 		do
126 		{	if ( pFrm->GetAttrSet()->GetKeep().GetValue() )
127 				pFrm = pFrm->GetIndPrev();
128 			else
129 				return sal_True;
130 		} while ( pFrm );
131 
132 				  //Siehe IsFwdMoveAllowed()
133     sal_Bool bRet = sal_False;
134     if ( pFrm && pFrm->GetIndPrev() )
135         bRet = sal_True;
136 	return bRet;
137 }
138 
139 /*************************************************************************
140 |*
141 |*	  SwFlowFrm::CheckKeep()
142 |*
143 |*	  Beschreibung
144 |*	  Ersterstellung	MA 20. Jun. 95
145 |*	  Letzte Aenderung	MA 09. Apr. 97
146 |*
147 |*************************************************************************/
148 
149 
150 void SwFlowFrm::CheckKeep()
151 {
152 	//Den 'letzten' Vorgaenger mit KeepAttribut anstossen, denn
153 	//die ganze Truppe koennte zuruckrutschen.
154 	SwFrm *pPre = rThis.GetIndPrev();
155 	if( pPre->IsSctFrm() )
156 	{
157 		SwFrm *pLast = ((SwSectionFrm*)pPre)->FindLastCntnt();
158 		if( pLast && pLast->FindSctFrm() == pPre )
159 			pPre = pLast;
160 		else
161 			return;
162 	}
163 	SwFrm* pTmp;
164 	sal_Bool bKeep;
165 	while ( sal_True == (bKeep = pPre->GetAttrSet()->GetKeep().GetValue()) &&
166 			0 != ( pTmp = pPre->GetIndPrev() ) )
167 	{
168 		if( pTmp->IsSctFrm() )
169 		{
170 			SwFrm *pLast = ((SwSectionFrm*)pTmp)->FindLastCntnt();
171 			if( pLast && pLast->FindSctFrm() == pTmp )
172 				pTmp = pLast;
173 			else
174 				break;
175 		}
176 		pPre = pTmp;
177 	}
178 	if ( bKeep )
179 		pPre->InvalidatePos();
180 }
181 
182 /*************************************************************************
183 |*
184 |*	SwFlowFrm::IsKeep()
185 |*
186 |*	Ersterstellung		MA 09. Apr. 97
187 |*	Letzte Aenderung	MA 09. Apr. 97
188 |*
189 |*************************************************************************/
190 
191 sal_Bool SwFlowFrm::IsKeep( const SwAttrSet& rAttrs, bool bCheckIfLastRowShouldKeep ) const
192 {
193     // 1. The keep attribute is ignored inside footnotes
194     // 2. For compatibility reasons, the keep attribute is
195     //    ignored for frames inside table cells
196     // 3. If bBreakCheck is set to true, this function only checks
197     //    if there are any break after attributes set at rAttrs
198     //    or break before attributes set for the next content (or next table)
199     sal_Bool bKeep = bCheckIfLastRowShouldKeep ||
200                  (  !rThis.IsInFtn() &&
201                     ( !rThis.IsInTab() || rThis.IsTabFrm() ) &&
202                     rAttrs.GetKeep().GetValue() );
203 
204     ASSERT( !bCheckIfLastRowShouldKeep || rThis.IsTabFrm(),
205             "IsKeep with bCheckIfLastRowShouldKeep should only be used for tabfrms" )
206 
207     // Ignore keep attribute if there are break situations:
208 	if ( bKeep )
209 	{
210         switch ( rAttrs.GetBreak().GetBreak() )
211 		{
212 			case SVX_BREAK_COLUMN_AFTER:
213 			case SVX_BREAK_COLUMN_BOTH:
214 			case SVX_BREAK_PAGE_AFTER:
215 			case SVX_BREAK_PAGE_BOTH:
216             {
217 				bKeep = sal_False;
218             }
219             default: break;
220 		}
221 		if ( bKeep )
222 		{
223 			SwFrm *pNxt;
224 			if( 0 != (pNxt = rThis.FindNextCnt()) &&
225 				(!pFollow || pNxt != pFollow->GetFrm()))
226 			{
227                 // --> FME 2006-05-15 #135914#
228                 // The last row of a table only keeps with the next content
229                 // it they are in the same section:
230                 if ( bCheckIfLastRowShouldKeep )
231                 {
232                     const SwSection* pThisSection = 0;
233                     const SwSection* pNextSection = 0;
234                     const SwSectionFrm* pThisSectionFrm = rThis.FindSctFrm();
235                     const SwSectionFrm* pNextSectionFrm = pNxt->FindSctFrm();
236 
237                     if ( pThisSectionFrm )
238                         pThisSection = pThisSectionFrm->GetSection();
239 
240                     if ( pNextSectionFrm )
241                         pNextSection = pNextSectionFrm->GetSection();
242 
243                     if ( pThisSection != pNextSection )
244                         bKeep = sal_False;
245                 }
246                 // <--
247 
248                 if ( bKeep )
249                 {
250                     const SwAttrSet* pSet = NULL;
251 
252                     if ( pNxt->IsInTab() )
253                     {
254                         SwTabFrm* pTab = pNxt->FindTabFrm();
255                         if ( ! rThis.IsInTab() || rThis.FindTabFrm() != pTab )
256                             pSet = &pTab->GetFmt()->GetAttrSet();
257                     }
258 
259                     if ( ! pSet )
260                         pSet = pNxt->GetAttrSet();
261 
262                     ASSERT( pSet, "No AttrSet to check keep attribute" )
263 
264                     if ( pSet->GetPageDesc().GetPageDesc() )
265                         bKeep = sal_False;
266                     else switch ( pSet->GetBreak().GetBreak() )
267                     {
268                         case SVX_BREAK_COLUMN_BEFORE:
269                         case SVX_BREAK_COLUMN_BOTH:
270                         case SVX_BREAK_PAGE_BEFORE:
271                         case SVX_BREAK_PAGE_BOTH:
272                             bKeep = sal_False;
273                         default: break;
274                     }
275                 }
276 			}
277 		}
278 	}
279 	return bKeep;
280 }
281 
282 /*************************************************************************
283 |*
284 |*	SwFlowFrm::BwdMoveNecessary()
285 |*
286 |*	Ersterstellung		MA 20. Jul. 94
287 |*	Letzte Aenderung	MA 02. May. 96
288 |*
289 |*************************************************************************/
290 
291 
292 sal_uInt8 SwFlowFrm::BwdMoveNecessary( const SwPageFrm *pPage, const SwRect &rRect )
293 {
294 	// Der return-Wert entscheidet mit,
295 	// ob auf Zurueckgeflossen werden muss, (3)
296 	// ob das gute alte WouldFit gerufen werden kann (0, 1)
297 	// oder ob ein Umhaengen und eine Probeformatierung sinnvoll ist (2)
298 	// dabei bedeutet Bit 1, dass Objekte an mir selbst verankert sind
299 	// und Bit 2, dass ich anderen Objekten ausweichen muss.
300 
301 	//Wenn ein SurroundObj, dass einen Umfluss wuenscht mit dem Rect ueberlappt
302 	//ist der Fluss notwendig (weil die Verhaeltnisse nicht geschaetzt werden
303 	//koennen), es kann allerdings ggf. eine TestFormatierung stattfinden.
304 	//Wenn das SurroundObj ein Fly ist und ich selbst ein Lower bin oder der Fly
305 	//Lower von mir ist, so spielt er keine Rolle.
306 	//Wenn das SurroundObj in einem zeichengebunden Fly verankert ist, und ich
307 	//selbst nicht Lower dieses Zeichengebundenen Flys bin, so spielt der Fly
308 	//keine Rolle.
309 	//#32639# Wenn das Objekt bei mir verankert ist kann ich es
310 	//vernachlaessigen, weil es hoechstwahrscheinlich (!?) mitfliesst,
311 	//eine TestFormatierung ist dann allerdings nicht erlaubt!
312 	sal_uInt8 nRet = 0;
313 	SwFlowFrm *pTmp = this;
314 	do
315 	{   // Wenn an uns oder einem Follow Objekte haengen, so
316 		// kann keine ProbeFormatierung stattfinden, da absatzgebundene
317 		// nicht richtig beruecksichtigt wuerden und zeichengebundene sollten
318 		// gar nicht zur Probe formatiert werden.
319 		if( pTmp->GetFrm()->GetDrawObjs() )
320 			nRet = 1;
321 		pTmp = pTmp->GetFollow();
322 	} while ( !nRet && pTmp );
323 	if ( pPage->GetSortedObjs() )
324 	{
325         // --> OD 2004-07-01 #i28701# - new type <SwSortedObjs>
326         const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
327 		sal_uLong nIndex = ULONG_MAX;
328 		for ( sal_uInt16 i = 0; nRet < 3 && i < rObjs.Count(); ++i )
329 		{
330             // --> OD 2004-07-01 #i28701# - consider changed type of
331             // <SwSortedObjs> entries.
332             SwAnchoredObject* pObj = rObjs[i];
333             const SwFrmFmt& rFmt = pObj->GetFrmFmt();
334             const SwRect aRect( pObj->GetObjRect() );
335 			if ( aRect.IsOver( rRect ) &&
336                  rFmt.GetSurround().GetSurround() != SURROUND_THROUGHT )
337 			{
338 				if( rThis.IsLayoutFrm() && //Fly Lower von This?
339                     Is_Lower_Of( &rThis, pObj->GetDrawObj() ) )
340 					continue;
341                 if( pObj->ISA(SwFlyFrm) )
342 				{
343                     const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
344 					if ( pFly->IsAnLower( &rThis ) )//This Lower vom Fly?
345 						continue;
346 				}
347 
348                 const SwFrm* pAnchor = pObj->GetAnchorFrm();
349 				if ( pAnchor == &rThis )
350 				{
351 					nRet |= 1;
352 					continue;
353 				}
354 
355 				//Nicht wenn das Objekt im Textfluss hinter mir verankert ist,
356 				//denn dann weiche ich ihm nicht aus.
357 				if ( ::IsFrmInSameKontext( pAnchor, &rThis ) )
358 				{
359                     if ( rFmt.GetAnchor().GetAnchorId() == FLY_AT_PARA )
360 					{
361 						// Den Index des anderen erhalten wir immer ueber das Ankerattr.
362                         sal_uLong nTmpIndex = rFmt.GetAnchor().GetCntntAnchor()->nNode.GetIndex();
363 						// Jetzt wird noch ueberprueft, ob der aktuelle Absatz vor dem
364 						// Anker des verdraengenden Objekts im Text steht, dann wird
365 						// nicht ausgewichen.
366 						// Der Index wird moeglichst ueber einen SwFmtAnchor ermittelt,
367 						// da sonst recht teuer.
368 						if( ULONG_MAX == nIndex )
369 						{
370 							const SwNode *pNode;
371 							if ( rThis.IsCntntFrm() )
372 								pNode = ((SwCntntFrm&)rThis).GetNode();
373 							else if( rThis.IsSctFrm() )
374 								pNode = ((SwSectionFmt*)((SwSectionFrm&)rThis).
375 										GetFmt())->GetSectionNode();
376 							else
377 							{
378 								ASSERT( rThis.IsTabFrm(), "new FowFrm?" );
379 								pNode = ((SwTabFrm&)rThis).GetTable()->
380 									GetTabSortBoxes()[0]->GetSttNd()->FindTableNode();
381 							}
382 							nIndex = pNode->GetIndex();
383 						}
384 						if( nIndex < nTmpIndex )
385 							continue;
386 					}
387 				}
388 				else
389 					continue;
390 
391 				nRet |= 2;
392 			}
393 		}
394 	}
395 	return nRet;
396 }
397 
398 /*************************************************************************
399 |*
400 |*	SwFlowFrm::CutTree(), PasteTree(), MoveSubTree()
401 |*
402 |*	Beschreibung		Eine Spezialisierte Form des Cut() und Paste(), die
403 |*		eine ganze Kette umhaengt (naehmlich this und folgende). Dabei werden
404 |* 		nur minimale Operationen und Benachrichtigungen ausgefuehrt.
405 |*	Ersterstellung		MA 18. Mar. 93
406 |*	Letzte Aenderung	MA 18. May. 95
407 |*
408 |*************************************************************************/
409 
410 
411 SwLayoutFrm *SwFlowFrm::CutTree( SwFrm *pStart )
412 {
413 	//Der Start und alle Nachbarn werden ausgeschnitten, sie werden aneinander-
414 	//gereiht und ein Henkel auf den ersten wird zurueckgeliefert.
415 	//Zurueckbleibende werden geeignet invalidiert.
416 
417 	SwLayoutFrm *pLay = pStart->GetUpper();
418 	if ( pLay->IsInFtn() )
419 		pLay = pLay->FindFtnFrm();
420 
421     // --> OD 2006-05-08 #i58846#
422     // <pPrepare( PREP_QUOVADIS )> only for frames in footnotes
423     if( pStart->IsInFtn() )
424 	{
425 		SwFrm* pTmp = pStart->GetIndPrev();
426 		if( pTmp )
427 			pTmp->Prepare( PREP_QUOVADIS );
428 	}
429     // <--
430 
431 	//Nur fix auschneiden und zwar so, dass klare Verhaeltnisse bei den
432 	//Verlassenen herrschen. Die Pointer der ausgeschnittenen Kette zeigen
433 	//noch wer weiss wo hin.
434 	if ( pStart == pStart->GetUpper()->Lower() )
435 		pStart->GetUpper()->pLower = 0;
436 	if ( pStart->GetPrev() )
437 	{
438 		pStart->GetPrev()->pNext = 0;
439 		pStart->pPrev = 0;
440 	}
441 
442 	if ( pLay->IsFtnFrm() )
443     {
444         if ( !pLay->Lower() && !pLay->IsColLocked() &&
445              !((SwFtnFrm*)pLay)->IsBackMoveLocked() )
446         {
447             pLay->Cut();
448 			delete pLay;
449 		}
450         else
451         {
452             sal_Bool bUnlock = !((SwFtnFrm*)pLay)->IsBackMoveLocked();
453             ((SwFtnFrm*)pLay)->LockBackMove();
454             pLay->InvalidateSize();
455             pLay->Calc();
456             SwCntntFrm *pCnt = pLay->ContainsCntnt();
457             while ( pCnt && pLay->IsAnLower( pCnt ) )
458             {
459                 //Kann sein, dass der CntFrm gelockt ist, wir wollen hier nicht
460                 //in eine endlose Seitenwanderung hineinlaufen und rufen das
461                 //Calc garnicht erst!
462                 ASSERT( pCnt->IsTxtFrm(), "Die Graphic ist gelandet." );
463                 if ( ((SwTxtFrm*)pCnt)->IsLocked() ||
464                      ((SwTxtFrm*)pCnt)->GetFollow() == pStart )
465                     break;
466                 pCnt->Calc();
467                 pCnt = pCnt->GetNextCntntFrm();
468             }
469             if( bUnlock )
470                 ((SwFtnFrm*)pLay)->UnlockBackMove();
471         }
472 		pLay = 0;
473 	}
474 	return pLay;
475 }
476 
477 
478 
479 sal_Bool SwFlowFrm::PasteTree( SwFrm *pStart, SwLayoutFrm *pParent, SwFrm *pSibling,
480 						   SwFrm *pOldParent )
481 {
482 	//returnt sal_True wenn in der Kette ein LayoutFrm steht.
483 	sal_Bool bRet = sal_False;
484 
485 	//Die mit pStart beginnende Kette wird vor den Sibling unter den Parent
486 	//gehaengt. Fuer geeignete Invalidierung wird ebenfalls gesorgt.
487 
488 	//Ich bekomme eine fertige Kette. Der Anfang der Kette muss verpointert
489 	//werden, dann alle Upper fuer die Kette und schliesslich dass Ende.
490 	//Unterwegs werden alle geeignet invalidiert.
491 	if ( pSibling )
492 	{
493 		if ( 0 != (pStart->pPrev = pSibling->GetPrev()) )
494 			pStart->GetPrev()->pNext = pStart;
495 		else
496 			pParent->pLower = pStart;
497 		pSibling->_InvalidatePos();
498 		pSibling->_InvalidatePrt();
499 	}
500 	else
501 	{
502         if ( 0 == (pStart->pPrev = pParent->Lower()) )
503             pParent->pLower = pStart;
504         else
505         //Modified for #i100782#,04/03/2009
506         //If the pParent has more than 1 child nodes, former design will
507         //ignore them directly without any collection work. It will make some
508         //dangling pointers. This lead the crash...
509         //The new design will find the last child of pParent in loop way, and
510         //add the pStart after the last child.
511         //  pParent->Lower()->pNext = pStart;
512         {
513             SwFrm* pTemp = pParent->pLower;
514             while (pTemp)
515             {
516                 if (pTemp->pNext)
517                     pTemp = pTemp->pNext;
518                 else
519                 {
520                     pStart->pPrev = pTemp;
521                     pTemp->pNext = pStart;
522                     break;
523                 }
524             }
525         }
526         //End modification for #i100782#,04/03/2009
527 
528         // #i27145#
529         if ( pParent->IsSctFrm() )
530         {
531             // We have no sibling because pParent is a section frame and
532             // has just been created to contain some content. The printing
533             // area of the frame behind pParent has to be invalidated, so
534             // that the correct distance between pParent and the next frame
535             // can be calculated.
536             pParent->InvalidateNextPrtArea();
537         }
538 	}
539 	SwFrm *pFloat = pStart;
540 	SwFrm *pLst = 0;
541     SWRECTFN( pParent )
542 	SwTwips nGrowVal = 0;
543 	do
544 	{	pFloat->pUpper = pParent;
545 		pFloat->_InvalidateAll();
546         pFloat->CheckDirChange();
547 
548 		//Ich bin Freund des TxtFrm und darf deshalb so einiges. Das mit
549 		//dem CacheIdx scheint etwas riskant!
550 		if ( pFloat->IsTxtFrm() )
551 		{
552 			if ( ((SwTxtFrm*)pFloat)->GetCacheIdx() != USHRT_MAX )
553 				((SwTxtFrm*)pFloat)->Init();	//Ich bin sein Freund.
554 		}
555 		else
556 			bRet = sal_True;
557 
558         nGrowVal += (pFloat->Frm().*fnRect->fnGetHeight)();
559 		if ( pFloat->GetNext() )
560 			pFloat = pFloat->GetNext();
561 		else
562 		{
563             pLst = pFloat;
564 			pFloat = 0;
565 		}
566 	} while ( pFloat );
567 
568 	if ( pSibling )
569 	{
570 		pLst->pNext = pSibling;
571 		pSibling->pPrev = pLst;
572 		if( pSibling->IsInFtn() )
573 		{
574 			if( pSibling->IsSctFrm() )
575 				pSibling = ((SwSectionFrm*)pSibling)->ContainsAny();
576 			if( pSibling )
577 				pSibling->Prepare( PREP_ERGOSUM );
578 		}
579 	}
580 	if ( nGrowVal )
581 	{
582 		if ( pOldParent && pOldParent->IsBodyFrm() ) //Fuer variable Seitenhoehe beim Browsen
583             pOldParent->Shrink( nGrowVal );
584         pParent->Grow( nGrowVal );
585 	}
586 
587 	if ( pParent->IsFtnFrm() )
588 		((SwFtnFrm*)pParent)->InvalidateNxtFtnCnts( pParent->FindPageFrm() );
589 	return bRet;
590 }
591 
592 
593 
594 void SwFlowFrm::MoveSubTree( SwLayoutFrm* pParent, SwFrm* pSibling )
595 {
596 	ASSERT( pParent, "Kein Parent uebergeben." );
597 	ASSERT( rThis.GetUpper(), "Wo kommen wir denn her?" );
598 
599 	//Sparsamer benachrichtigen wenn eine Action laeuft.
600 	ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
601 	const SwViewImp *pImp = pSh ? pSh->Imp() : 0;
602 	const sal_Bool bComplete = pImp && pImp->IsAction() && pImp->GetLayAction().IsComplete();
603 
604 	if ( !bComplete )
605 	{
606 		SwFrm *pPre = rThis.GetIndPrev();
607 		if ( pPre )
608 		{
609 			pPre->SetRetouche();
610             // --> OD 2004-11-23 #115759# - follow-up of #i26250#
611             // invalidate printing area of previous frame, if it's in a table
612             if ( pPre->GetUpper()->IsInTab() )
613             {
614                 pPre->_InvalidatePrt();
615             }
616             // <--
617 			pPre->InvalidatePage();
618 		}
619 		else
620 		{	rThis.GetUpper()->SetCompletePaint();
621 			rThis.GetUpper()->InvalidatePage();
622 		}
623 	}
624 
625 	SwPageFrm *pOldPage = rThis.FindPageFrm();
626 
627 	SwLayoutFrm *pOldParent = CutTree( &rThis );
628 	const sal_Bool bInvaLay = PasteTree( &rThis, pParent, pSibling, pOldParent );
629 
630 	// Wenn durch das Cut&Paste ein leerer SectionFrm entstanden ist, sollte
631 	// dieser automatisch verschwinden.
632 	SwSectionFrm *pSct;
633     // --> OD 2006-01-04 #126020# - adjust check for empty section
634     // --> OD 2006-02-01 #130797# - correct fix #126020#
635 	if ( pOldParent && !pOldParent->Lower() &&
636          ( pOldParent->IsInSct() &&
637            !(pSct = pOldParent->FindSctFrm())->ContainsCntnt() &&
638            !pSct->ContainsAny( true ) ) )
639     // <--
640     {
641 			pSct->DelEmpty( sal_False );
642     }
643 
644     // In einem spaltigen Bereich rufen wir lieber kein Calc "von unten"
645     if( !rThis.IsInSct() &&
646         ( !rThis.IsInTab() || ( rThis.IsTabFrm() && !rThis.GetUpper()->IsInTab() ) ) )
647 		rThis.GetUpper()->Calc();
648     else if( rThis.GetUpper()->IsSctFrm() )
649 	{
650         SwSectionFrm* pTmpSct = (SwSectionFrm*)rThis.GetUpper();
651         sal_Bool bOld = pTmpSct->IsCntntLocked();
652         pTmpSct->SetCntntLock( sal_True );
653         pTmpSct->Calc();
654 		if( !bOld )
655             pTmpSct->SetCntntLock( sal_False );
656 	}
657 	SwPageFrm *pPage = rThis.FindPageFrm();
658 
659 	if ( pOldPage != pPage )
660 	{
661 		rThis.InvalidatePage( pPage );
662 		if ( rThis.IsLayoutFrm() )
663 		{
664 			SwCntntFrm *pCnt = ((SwLayoutFrm*)&rThis)->ContainsCntnt();
665 			if ( pCnt )
666 				pCnt->InvalidatePage( pPage );
667 		}
668 		else if ( pSh && pSh->GetDoc()->GetLineNumberInfo().IsRestartEachPage()
669 				  && pPage->FindFirstBodyCntnt() == &rThis )
670 		{
671 			rThis._InvalidateLineNum();
672 		}
673 	}
674 	if ( bInvaLay || (pSibling && pSibling->IsLayoutFrm()) )
675 		rThis.GetUpper()->InvalidatePage( pPage );
676 }
677 
678 /*************************************************************************
679 |*
680 |*	SwFlowFrm::IsAnFollow()
681 |*
682 |*	Ersterstellung		MA 26. Apr. 95
683 |*	Letzte Aenderung	MA 26. Apr. 95
684 |*
685 |*************************************************************************/
686 
687 
688 sal_Bool SwFlowFrm::IsAnFollow( const SwFlowFrm *pAssumed ) const
689 {
690 	const SwFlowFrm *pFoll = this;
691 	do
692 	{	if ( pAssumed == pFoll )
693 			return sal_True;
694 		pFoll = pFoll->GetFollow();
695 	} while ( pFoll );
696 	return sal_False;
697 }
698 
699 
700 /*************************************************************************
701 |*
702 |*	SwFlowFrm::FindMaster()
703 |*
704 |*	Ersterstellung		MA 26. Apr. 95
705 |*	Letzte Aenderung	MA 26. Apr. 95
706 |*
707 |*************************************************************************/
708 
709 SwTxtFrm* SwCntntFrm::FindMaster() const
710 {
711     ASSERT( IsFollow(), "SwCntntFrm::FindMaster(): !IsFollow" );
712 
713     const SwCntntFrm* pCnt = GetPrevCntntFrm();
714 
715     while ( pCnt )
716     {
717         if ( pCnt->HasFollow() && pCnt->GetFollow() == this )
718         {
719             ASSERT( pCnt->IsTxtFrm(), "NoTxtFrm with follow found" )
720             return (SwTxtFrm*)pCnt;
721         }
722         pCnt = pCnt->GetPrevCntntFrm();
723     }
724 
725     ASSERT( sal_False, "Follow ist lost in Space." );
726     return 0;
727 }
728 
729 SwSectionFrm* SwSectionFrm::FindMaster() const
730 {
731     ASSERT( IsFollow(), "SwSectionFrm::FindMaster(): !IsFollow" );
732 
733     SwIterator<SwSectionFrm,SwFmt> aIter( *pSection->GetFmt() );
734     SwSectionFrm* pSect = aIter.First();
735     while ( pSect )
736     {
737             if( pSect->GetFollow() == this )
738                 return pSect;
739         pSect = aIter.Next();
740     }
741 
742     ASSERT( sal_False, "Follow ist lost in Space." );
743     return 0;
744 }
745 
746 SwTabFrm* SwTabFrm::FindMaster( bool bFirstMaster ) const
747 {
748     ASSERT( IsFollow(), "SwTabFrm::FindMaster(): !IsFollow" );
749 
750     SwIterator<SwTabFrm,SwFmt> aIter( *GetTable()->GetFrmFmt() );
751     SwTabFrm* pTab = aIter.First();
752     while ( pTab )
753     {
754             if ( bFirstMaster )
755             {
756                 //
757                 // Optimization. This makes code like this obsolete:
758                 // while ( pTab->IsFollow() )
759                 //     pTab = pTab->FindMaster();
760                 //
761                 if ( !pTab->IsFollow() )
762                 {
763                     SwTabFrm* pNxt = pTab;
764                     while ( pNxt )
765                     {
766                         if ( pNxt->GetFollow() == this )
767                             return pTab;
768                         pNxt = pNxt->GetFollow();
769                     }
770                 }
771             }
772             else
773             {
774                 if ( pTab->GetFollow() == this )
775                     return pTab;
776             }
777 
778         pTab = aIter.Next();
779     }
780 
781     ASSERT( sal_False, "Follow ist lost in Space." );
782     return 0;
783 }
784 
785 /*************************************************************************
786 |*
787 |*	SwFrm::GetLeaf()
788 |*
789 |*	Beschreibung		Liefert das naechste/vorhergehende LayoutBlatt,
790 |* 		das _nicht_ unterhalb von this liegt (oder gar this selbst ist).
791 |* 		Ausserdem muss dieses LayoutBlatt im gleichen Textfluss wie
792 |* 		pAnch Ausgangsfrm liegen (Body, Ftn)
793 |*	Ersterstellung		MA 25. Nov. 92
794 |*	Letzte Aenderung	MA 25. Apr. 95
795 |*
796 |*************************************************************************/
797 
798 
799 const SwLayoutFrm *SwFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd,
800 								   const SwFrm *pAnch ) const
801 {
802 	//Ohne Fluss kein genuss...
803     if ( !(IsInDocBody() || IsInFtn() || IsInFly()) )
804         return 0;
805 
806 	const SwFrm *pLeaf = this;
807 	sal_Bool bFound = sal_False;
808 
809 	do
810 	{	pLeaf = ((SwFrm*)pLeaf)->GetLeaf( eMakePage, bFwd );
811 
812 		if ( pLeaf &&
813 			(!IsLayoutFrm() || !((SwLayoutFrm*)this)->IsAnLower( pLeaf )))
814 		{
815 			if ( pAnch->IsInDocBody() == pLeaf->IsInDocBody() &&
816 				 pAnch->IsInFtn()	  == pLeaf->IsInFtn() )
817 			{
818 				bFound = sal_True;
819 			}
820 		}
821 	} while ( !bFound && pLeaf );
822 
823 	return (const SwLayoutFrm*)pLeaf;
824 }
825 
826 /*************************************************************************
827 |*
828 |*	SwFrm::GetLeaf()
829 |*
830 |*	Beschreibung		Ruft Get[Next|Prev]Leaf
831 |*
832 |*	Ersterstellung		MA 20. Mar. 93
833 |*	Letzte Aenderung	MA 25. Apr. 95
834 |*
835 |*************************************************************************/
836 
837 
838 SwLayoutFrm *SwFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd )
839 {
840 	if ( IsInFtn() )
841 		return bFwd ? GetNextFtnLeaf( eMakePage ) : GetPrevFtnLeaf( eMakePage );
842 
843     // --> OD 2005-08-16 #i53323#
844     // A frame could be inside a table AND inside a section.
845     // Thus, it has to be determined, which is the first parent.
846     bool bInTab( IsInTab() );
847     bool bInSct( IsInSct() );
848     if ( bInTab && bInSct )
849     {
850         const SwFrm* pUpperFrm( GetUpper() );
851         while ( pUpperFrm )
852         {
853             if ( pUpperFrm->IsTabFrm() )
854             {
855                 // the table is the first.
856                 bInSct = false;
857                 break;
858             }
859             else if ( pUpperFrm->IsSctFrm() )
860             {
861                 // the section is the first.
862                 bInTab = false;
863                 break;
864             }
865 
866             pUpperFrm = pUpperFrm->GetUpper();
867         }
868     }
869 
870     if ( bInTab && ( !IsTabFrm() || GetUpper()->IsCellFrm() ) ) // TABLE IN TABLE
871         return bFwd ? GetNextCellLeaf( eMakePage ) : GetPrevCellLeaf( eMakePage );
872 
873     if ( bInSct )
874 		return bFwd ? GetNextSctLeaf( eMakePage ) : GetPrevSctLeaf( eMakePage );
875     // <--
876 
877 	return bFwd ? GetNextLeaf( eMakePage ) : GetPrevLeaf( eMakePage );
878 }
879 
880 
881 
882 sal_Bool SwFrm::WrongPageDesc( SwPageFrm* pNew )
883 {
884 	//Jetzt wirds leider etwas kompliziert:
885 	//Ich bringe ich evtl. selbst
886 	//einen Pagedesc mit; der der Folgeseite muss dann damit
887 	//uebereinstimmen.
888 	//Anderfalls muss ich mir etwas genauer ansehen wo der
889 	//Folgepagedesc herkam.
890 	//Wenn die Folgeseite selbst schon sagt, dass ihr
891 	//Pagedesc nicht stimmt so kann ich das Teil bedenkenlos
892 	//auswechseln.
893 	//Wenn die Seite meint, dass ihr Pagedesc stimmt, so heisst
894 	//das leider noch immer nicht, dass ich damit etwas anfangen
895 	//kann: Wenn der erste BodyCntnt einen PageDesc oder einen
896 	//PageBreak wuenscht, so muss ich ebenfalls eine neue
897 	//Seite einfuegen; es sein denn die gewuenschte Seite ist
898 	//die richtige.
899 	//Wenn ich einen neue Seite eingefuegt habe, so fangen die
900 	//Probleme leider erst an, denn wahrscheinlich wird die dann
901 	//folgende Seite verkehrt gewesen und ausgewechselt worden
902 	//sein. Das hat zur Folge, dass ich zwar eine neue (und
903 	//jetzt richtige) Seite habe, die Bedingungen zum auswechseln
904 	//aber leider noch immer stimmen.
905 	//Ausweg: Vorlaeufiger Versuch, nur einmal eine neue Seite
906 	//einsetzen (Leerseiten werden noetigenfalls bereits von
907 	//InsertPage() eingefuegt.
908 	const SwFmtPageDesc &rFmtDesc = GetAttrSet()->GetPageDesc();
909 
910 	//Mein Pagedesc zaehlt nicht, wenn ich ein Follow bin!
911 	SwPageDesc *pDesc = 0;
912 	sal_uInt16 nTmp = 0;
913 	SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( this );
914 	if ( !pFlow || !pFlow->IsFollow() )
915 	{
916 		pDesc = (SwPageDesc*)rFmtDesc.GetPageDesc();
917 		if( pDesc )
918 		{
919 			if( !pDesc->GetRightFmt() )
920 				nTmp = 2;
921 			else if( !pDesc->GetLeftFmt() )
922 				nTmp = 1;
923 			else if( rFmtDesc.GetNumOffset() )
924 				nTmp = rFmtDesc.GetNumOffset();
925 		}
926 	}
927 
928 	//Bringt der Cntnt einen Pagedesc mit oder muss zaehlt die
929 	//virtuelle Seitennummer des neuen Layoutleafs?
930 	// Bei Follows zaehlt der PageDesc nicht
931 	const sal_Bool bOdd = nTmp ? ( nTmp % 2 ? sal_True : sal_False )
932 						   : pNew->OnRightPage();
933 	if ( !pDesc )
934 		pDesc = pNew->FindPageDesc();
935 	const SwFlowFrm *pNewFlow = pNew->FindFirstBodyCntnt();
936 	// Haben wir uns selbst gefunden?
937 	if( pNewFlow == pFlow )
938 		pNewFlow = NULL;
939 	if ( pNewFlow && pNewFlow->GetFrm()->IsInTab() )
940 		pNewFlow = pNewFlow->GetFrm()->FindTabFrm();
941 	const SwPageDesc *pNewDesc= ( pNewFlow && !pNewFlow->IsFollow() )
942 			? pNewFlow->GetFrm()->GetAttrSet()->GetPageDesc().GetPageDesc():0;
943 
944 	return ( pNew->GetPageDesc() != pDesc ||   //  own desc ?
945 		pNew->GetFmt() != (bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) ||
946 		( pNewDesc && pNewDesc == pDesc ) );
947 }
948 
949 
950 /*************************************************************************
951 |*
952 |*	SwFrm::GetNextLeaf()
953 |*
954 |*	Beschreibung		Liefert das naechste LayoutBlatt in den das
955 |* 		Frame gemoved werden kann.
956 |*
957 |*	Ersterstellung		MA 16. Nov. 92
958 |*	Letzte Aenderung	MA 05. Dec. 96
959 |*
960 |*************************************************************************/
961 
962 SwLayoutFrm *SwFrm::GetNextLeaf( MakePageType eMakePage )
963 {
964 	ASSERT( !IsInFtn(), "GetNextLeaf(), don't call me for Ftn." );
965 	ASSERT( !IsInSct(), "GetNextLeaf(), don't call me for Sections." );
966 
967 	const sal_Bool bBody = IsInDocBody();		//Wenn ich aus dem DocBody komme
968 											//Will ich auch im Body landen.
969 
970 	// Bei Flys macht es keinen Sinn, Seiten einzufuegen, wir wollen lediglich
971 	 // die Verkettung absuchen.
972 	if( IsInFly() )
973 		eMakePage = MAKEPAGE_NONE;
974 
975     //Bei Tabellen gleich den grossen Sprung wagen, ein einfaches GetNext...
976 	//wuerde die erste Zellen und in der Folge alle weiteren Zellen nacheinander
977 	//abklappern....
978     SwLayoutFrm *pLayLeaf = 0;
979     if ( IsTabFrm() )
980     {
981         SwCntntFrm* pTmp = ((SwTabFrm*)this)->FindLastCntnt();
982         if ( pTmp )
983             pLayLeaf = pTmp->GetUpper();
984     }
985     if ( !pLayLeaf )
986         pLayLeaf = GetNextLayoutLeaf();
987 
988 	SwLayoutFrm *pOldLayLeaf = 0;			//Damit bei neu erzeugten Seiten
989 											//nicht wieder vom Anfang gesucht
990 											//wird.
991 	sal_Bool bNewPg = sal_False;	//nur einmal eine neue Seite einfuegen.
992 
993 	while ( sal_True )
994 	{
995 		if ( pLayLeaf )
996 		{
997 			//Es gibt noch einen weiteren LayoutFrm, mal sehen,
998 			//ob er bereit ist mich aufzunehmen.
999 			//Dazu braucht er nur von der gleichen Art wie mein Ausgangspunkt
1000 			//sein (DocBody bzw. Footnote.)
1001 			if ( pLayLeaf->FindPageFrm()->IsFtnPage() )
1002 			{	//Wenn ich bei den Endnotenseiten angelangt bin hat sichs.
1003 				pLayLeaf = 0;
1004 				continue;
1005 			}
1006 			if ( (bBody && !pLayLeaf->IsInDocBody()) || pLayLeaf->IsInTab()
1007 				 || pLayLeaf->IsInSct() )
1008 			{
1009 				//Er will mich nicht; neuer Versuch, neues Glueck
1010 				pOldLayLeaf = pLayLeaf;
1011 				pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1012 				continue;
1013 			}
1014 			//Er will mich, also ist er der gesuchte und ich bin fertig.
1015 			//Bei einem Seitenwechsel kann es allerdings noch sein, dass
1016 			//Der Seitentyp nicht der gewuenschte ist, in diesem Fall muessen
1017 			//wir eine Seite des richtigen Typs einfuegen.
1018 
1019 			if( !IsFlowFrm() && ( eMakePage == MAKEPAGE_NONE ||
1020 				eMakePage==MAKEPAGE_APPEND || eMakePage==MAKEPAGE_NOSECTION ) )
1021 				return pLayLeaf;
1022 
1023 			SwPageFrm *pNew = pLayLeaf->FindPageFrm();
1024             const ViewShell *pSh = getRootFrm()->GetCurrShell();
1025             // #111704# The pagedesc check does not make sense for frames in fly frames
1026 			if ( pNew != FindPageFrm() && !bNewPg && !IsInFly() &&
1027                  // --> FME 2005-05-10 #i46683#
1028                  // Do not consider page descriptions in browse mode (since
1029                  // MoveBwd ignored them)
1030                  !(pSh && pSh->GetViewOptions()->getBrowseMode() ) )
1031                  // <--
1032 			{
1033 				if( WrongPageDesc( pNew ) )
1034 				{
1035 					SwFtnContFrm *pCont = pNew->FindFtnCont();
1036 					if( pCont )
1037 					{
1038 						// Falls die Referenz der ersten Fussnote dieser Seite
1039 						// vor der Seite liegt, fuegen wir lieber keine neue Seite
1040 						// ein (Bug #55620#)
1041 						SwFtnFrm *pFtn = (SwFtnFrm*)pCont->Lower();
1042 						if( pFtn && pFtn->GetRef() )
1043 						{
1044 							const sal_uInt16 nRefNum = pNew->GetPhyPageNum();
1045 							if( pFtn->GetRef()->GetPhyPageNum() < nRefNum )
1046 								break;
1047 						}
1048 					}
1049 					//Erwischt, die folgende Seite ist verkehrt, also
1050 					//muss eine neue eingefuegt werden.
1051 					if ( eMakePage == MAKEPAGE_INSERT )
1052 					{
1053 						bNewPg = sal_True;
1054 
1055 						SwPageFrm *pPg = pOldLayLeaf ?
1056 									pOldLayLeaf->FindPageFrm() : 0;
1057 						if ( pPg && pPg->IsEmptyPage() )
1058 							//Nicht hinter, sondern vor der EmptyPage einfuegen.
1059 							pPg = (SwPageFrm*)pPg->GetPrev();
1060 
1061 						if ( !pPg || pPg == pNew )
1062 							pPg = FindPageFrm();
1063 
1064 						InsertPage( pPg, sal_False );
1065 						pLayLeaf = GetNextLayoutLeaf();
1066 						pOldLayLeaf = 0;
1067 						continue;
1068 					}
1069 					else
1070 						pLayLeaf = 0;
1071 				}
1072 			}
1073 			break;
1074 		}
1075 		else
1076 		{
1077 			//Es gibt keinen passenden weiteren LayoutFrm, also muss eine
1078 			//neue Seite her.
1079 			if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT )
1080 			{
1081 				InsertPage(
1082 					pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
1083 					sal_False );
1084 
1085 				//und nochmal das ganze
1086 				pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
1087 			}
1088 			else
1089 				break;
1090 		}
1091 	}
1092 	return pLayLeaf;
1093 }
1094 
1095 /*************************************************************************
1096 |*
1097 |*	SwFrm::GetPrevLeaf()
1098 |*
1099 |*	Beschreibung		Liefert das vorhergehende LayoutBlatt in das der
1100 |* 		Frame gemoved werden kann.
1101 |*	Ersterstellung		MA 16. Nov. 92
1102 |*	Letzte Aenderung	MA 25. Apr. 95
1103 |*
1104 |*************************************************************************/
1105 
1106 
1107 SwLayoutFrm *SwFrm::GetPrevLeaf( MakePageType )
1108 {
1109 	ASSERT( !IsInFtn(), "GetPrevLeaf(), don't call me for Ftn." );
1110 
1111 	const sal_Bool bBody = IsInDocBody();		//Wenn ich aus dem DocBody komme
1112 											//will ich auch im Body landen.
1113 	const sal_Bool bFly  = IsInFly();
1114 
1115 	SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
1116 	SwLayoutFrm *pPrevLeaf = 0;
1117 
1118 	while ( pLayLeaf )
1119 	{
1120 		if ( pLayLeaf->IsInTab() || 	//In Tabellen geht's niemals hinein.
1121 			 pLayLeaf->IsInSct() )		//In Bereiche natuerlich auch nicht!
1122 			pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1123 		else if ( bBody && pLayLeaf->IsInDocBody() )
1124 		{
1125 			if ( pLayLeaf->Lower() )
1126 				break;
1127 			pPrevLeaf = pLayLeaf;
1128 			pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1129 			if ( pLayLeaf )
1130 				SwFlowFrm::SetMoveBwdJump( sal_True );
1131 		}
1132 		else if ( bFly )
1133 			break;	//Cntnts in Flys sollte jedes Layout-Blatt recht sein.
1134 		else
1135 			pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1136 	}
1137 	return pLayLeaf ? pLayLeaf : pPrevLeaf;
1138 }
1139 
1140 /*************************************************************************
1141 |*
1142 |*	SwFlowFrm::IsPrevObjMove()
1143 |*
1144 |*	Ersterstellung		MA 20. Feb. 96
1145 |*	Letzte Aenderung	MA 22. Feb. 96
1146 |*
1147 |*************************************************************************/
1148 
1149 
1150 sal_Bool SwFlowFrm::IsPrevObjMove() const
1151 {
1152 	//sal_True der FlowFrm soll auf einen Rahmen des Vorgaengers Ruecksicht nehmen
1153 	//     und fuer diesen ggf. Umbrechen.
1154 
1155 	//!!!!!!!!!!!Hack!!!!!!!!!!!
1156     const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
1157     if( pSh && pSh->GetViewOptions()->getBrowseMode() )
1158 		return sal_False;
1159 
1160 	SwFrm *pPre = rThis.FindPrev();
1161 
1162 	if ( pPre && pPre->GetDrawObjs() )
1163 	{
1164 		ASSERT( SwFlowFrm::CastFlowFrm( pPre ),	"new flowfrm?" );
1165 		if(	SwFlowFrm::CastFlowFrm( pPre )->IsAnFollow( this ) )
1166 			return sal_False;
1167         SwLayoutFrm* pPreUp = pPre->GetUpper();
1168 		// Wenn der Upper ein SectionFrm oder die Spalte eines SectionFrms ist,
1169 		// duerfen wir aus diesem durchaus heraushaengen,
1170 		// es muss stattdessen der Upper des SectionFrms beruecksichtigt werden.
1171 		if( pPreUp->IsInSct() )
1172 		{
1173 			if( pPreUp->IsSctFrm() )
1174 				pPreUp = pPreUp->GetUpper();
1175 			else if( pPreUp->IsColBodyFrm() &&
1176 					 pPreUp->GetUpper()->GetUpper()->IsSctFrm() )
1177                 pPreUp = pPreUp->GetUpper()->GetUpper()->GetUpper();
1178 		}
1179         // --> OD 2004-10-15 #i26945# - re-factoring:
1180         // use <GetVertPosOrientFrm()> to determine, if object has followed the
1181         // text flow to the next layout frame
1182 		for ( sal_uInt16 i = 0; i < pPre->GetDrawObjs()->Count(); ++i )
1183 		{
1184             // --> OD 2004-07-01 #i28701# - consider changed type of
1185             // <SwSortedObjs> entries.
1186             const SwAnchoredObject* pObj = (*pPre->GetDrawObjs())[i];
1187             // OD 2004-01-20 #110582# - do not consider hidden objects
1188             // --> OD 2004-10-15 #i26945# - do not consider object, which
1189             // doesn't follow the text flow.
1190             if ( pObj->GetFrmFmt().GetDoc()->IsVisibleLayerId(
1191                                             pObj->GetDrawObj()->GetLayer() ) &&
1192                  pObj->GetFrmFmt().GetFollowTextFlow().GetValue() )
1193             // <--
1194 			{
1195                 const SwLayoutFrm* pVertPosOrientFrm = pObj->GetVertPosOrientFrm();
1196                 if ( pVertPosOrientFrm &&
1197                      pPreUp != pVertPosOrientFrm &&
1198                      !pPreUp->IsAnLower( pVertPosOrientFrm ) )
1199                 {
1200                     return sal_True;
1201                 }
1202 			}
1203 		}
1204         // <--
1205 	}
1206 	return sal_False;
1207 }
1208 
1209 /*************************************************************************
1210 |*
1211 |*	sal_Bool SwFlowFrm::IsPageBreak()
1212 |*
1213 |*	Beschreibung		Wenn vor dem Frm ein harter Seitenumbruch steht UND
1214 |*		es einen Vorgaenger auf der gleichen Seite gibt, wird sal_True
1215 |*		zurueckgeliefert (es muss ein PageBreak erzeugt werden) sal_False sonst.
1216 |*		Wenn in bAct sal_True uebergeben wird, gibt die Funktion dann sal_True
1217 |*		zurueck, wenn ein PageBreak besteht.
1218 |* 		Fuer Follows wird der harte Seitenumbruch natuerlich nicht
1219 |* 		ausgewertet.
1220 |*		Der Seitenumbruch steht im eigenen FrmFmt (BEFORE) oder im FrmFmt
1221 |*		des Vorgaengers (AFTER). Wenn es keinen Vorgaenger auf der Seite
1222 |*		gibt ist jede weitere Ueberlegung ueberfluessig.
1223 |* 		Ein Seitenumbruch (oder der Bedarf) liegt auch dann vor, wenn
1224 |* 		im FrmFmt ein PageDesc angegeben wird.
1225 |*		Die Implementierung arbeitet zuaechst nur auf CntntFrms!
1226 |*		-->Fuer LayoutFrms ist die Definition des Vorgaengers unklar.
1227 |*	Ersterstellung		MA ??
1228 |*	Letzte Aenderung	MA 21. Mar. 95
1229 |*
1230 |*************************************************************************/
1231 
1232 
1233 sal_Bool SwFlowFrm::IsPageBreak( sal_Bool bAct ) const
1234 {
1235     if ( !IsFollow() && rThis.IsInDocBody() &&
1236          ( !rThis.IsInTab() || ( rThis.IsTabFrm() && !rThis.GetUpper()->IsInTab() ) ) ) // i66968
1237 	{
1238         const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
1239         if( pSh && pSh->GetViewOptions()->getBrowseMode() )
1240             return sal_False;
1241         const SwAttrSet *pSet = rThis.GetAttrSet();
1242 
1243         //Vorgaenger ermitteln
1244 		const SwFrm *pPrev = rThis.FindPrev();
1245 		while ( pPrev && ( !pPrev->IsInDocBody() ||
1246 				( pPrev->IsTxtFrm() && ((SwTxtFrm*)pPrev)->IsHiddenNow() ) ) )
1247 			pPrev = pPrev->FindPrev();
1248 
1249 		if ( pPrev )
1250 		{
1251 			ASSERT( pPrev->IsInDocBody(), "IsPageBreak: Not in DocBody?" );
1252 			if ( bAct )
1253 			{	if ( rThis.FindPageFrm() == pPrev->FindPageFrm() )
1254 					return sal_False;
1255 			}
1256 			else
1257 			{	if ( rThis.FindPageFrm() != pPrev->FindPageFrm() )
1258 					return sal_False;
1259 			}
1260 
1261             const SvxBreak eBreak = pSet->GetBreak().GetBreak();
1262             if ( eBreak == SVX_BREAK_PAGE_BEFORE || eBreak == SVX_BREAK_PAGE_BOTH )
1263                 return sal_True;
1264             else
1265             {
1266                 const SvxBreak &ePrB = pPrev->GetAttrSet()->GetBreak().GetBreak();
1267                 if ( ePrB == SVX_BREAK_PAGE_AFTER ||
1268                      ePrB == SVX_BREAK_PAGE_BOTH  ||
1269                      pSet->GetPageDesc().GetPageDesc() )
1270                     return sal_True;
1271             }
1272         }
1273     }
1274     return sal_False;
1275 }
1276 
1277 /*************************************************************************
1278 |*
1279 |*	sal_Bool SwFlowFrm::IsColBreak()
1280 |*
1281 |*	Beschreibung		Wenn vor dem Frm ein harter Spaltenumbruch steht UND
1282 |*		es einen Vorgaenger in der gleichen Spalte gibt, wird sal_True
1283 |*		zurueckgeliefert (es muss ein PageBreak erzeugt werden) sal_False sonst.
1284 |*		Wenn in bAct sal_True uebergeben wird, gibt die Funktion dann sal_True
1285 |*		zurueck, wenn ein ColBreak besteht.
1286 |* 		Fuer Follows wird der harte Spaltenumbruch natuerlich nicht
1287 |* 		ausgewertet.
1288 |*		Der Spaltenumbruch steht im eigenen FrmFmt (BEFORE) oder im FrmFmt
1289 |*		des Vorgaengers (AFTER). Wenn es keinen Vorgaenger in der Spalte
1290 |*		gibt ist jede weitere Ueberlegung ueberfluessig.
1291 |*		Die Implementierung arbeitet zuaechst nur auf CntntFrms!
1292 |*		-->Fuer LayoutFrms ist die Definition des Vorgaengers unklar.
1293 |*	Ersterstellung		MA 11. Jun. 93
1294 |*	Letzte Aenderung	MA 21. Mar. 95
1295 |*
1296 |*************************************************************************/
1297 
1298 sal_Bool SwFlowFrm::IsColBreak( sal_Bool bAct ) const
1299 {
1300 	if ( !IsFollow() && (rThis.IsMoveable() || bAct) )
1301 	{
1302 		const SwFrm *pCol = rThis.FindColFrm();
1303 		if ( pCol )
1304 		{
1305 			//Vorgaenger ermitteln
1306 			const SwFrm *pPrev = rThis.FindPrev();
1307 			while( pPrev && ( ( !pPrev->IsInDocBody() && !rThis.IsInFly() ) ||
1308 				   ( pPrev->IsTxtFrm() && ((SwTxtFrm*)pPrev)->IsHiddenNow() ) ) )
1309 					pPrev = pPrev->FindPrev();
1310 
1311 			if ( pPrev )
1312 			{
1313 				if ( bAct )
1314 				{	if ( pCol == pPrev->FindColFrm() )
1315 						return sal_False;
1316 				}
1317 				else
1318 				{	if ( pCol != pPrev->FindColFrm() )
1319 						return sal_False;
1320 				}
1321 
1322                 const SvxBreak eBreak = rThis.GetAttrSet()->GetBreak().GetBreak();
1323                 if ( eBreak == SVX_BREAK_COLUMN_BEFORE ||
1324                      eBreak == SVX_BREAK_COLUMN_BOTH )
1325                     return sal_True;
1326                 else
1327                 {
1328                     const SvxBreak &ePrB = pPrev->GetAttrSet()->GetBreak().GetBreak();
1329                     if ( ePrB == SVX_BREAK_COLUMN_AFTER ||
1330                          ePrB == SVX_BREAK_COLUMN_BOTH )
1331                         return sal_True;
1332                 }
1333             }
1334 		}
1335 	}
1336 	return sal_False;
1337 }
1338 
1339 sal_Bool SwFlowFrm::HasParaSpaceAtPages( sal_Bool bSct ) const
1340 {
1341 	if( rThis.IsInSct() )
1342 	{
1343 		const SwFrm* pTmp = rThis.GetUpper();
1344 		while( pTmp )
1345 		{
1346 			if( pTmp->IsCellFrm() || pTmp->IsFlyFrm() ||
1347 				pTmp->IsFooterFrm() || pTmp->IsHeaderFrm() ||
1348 				( pTmp->IsFtnFrm() && !((SwFtnFrm*)pTmp)->GetMaster() ) )
1349 				return sal_True;
1350 			if( pTmp->IsPageFrm() )
1351 				return ( pTmp->GetPrev() && !IsPageBreak(sal_True) ) ? sal_False : sal_True;
1352 			if( pTmp->IsColumnFrm() && pTmp->GetPrev() )
1353 				return IsColBreak( sal_True );
1354 			if( pTmp->IsSctFrm() && ( !bSct || pTmp->GetPrev() ) )
1355 				return sal_False;
1356 			pTmp = pTmp->GetUpper();
1357 		}
1358 		ASSERT( sal_False, "HasParaSpaceAtPages: Where's my page?" );
1359 		return sal_False;
1360 	}
1361 	if( !rThis.IsInDocBody() || ( rThis.IsInTab() && !rThis.IsTabFrm()) ||
1362 		IsPageBreak( sal_True ) || ( rThis.FindColFrm() && IsColBreak( sal_True ) ) )
1363 		return sal_True;
1364 	const SwFrm* pTmp = rThis.FindColFrm();
1365 	if( pTmp )
1366 	{
1367 		if( pTmp->GetPrev() )
1368 			return sal_False;
1369 	}
1370 	else
1371 		pTmp = &rThis;
1372 	pTmp = pTmp->FindPageFrm();
1373 	return pTmp && !pTmp->GetPrev();
1374 }
1375 
1376 /** helper method to determine previous frame for calculation of the
1377     upper space
1378 
1379     OD 2004-03-10 #i11860#
1380 
1381     @author OD
1382 */
1383 const SwFrm* SwFlowFrm::_GetPrevFrmForUpperSpaceCalc( const SwFrm* _pProposedPrevFrm ) const
1384 {
1385     const SwFrm* pPrevFrm = _pProposedPrevFrm
1386                             ? _pProposedPrevFrm
1387                             : rThis.GetPrev();
1388 
1389     // Skip hidden paragraphs and empty sections
1390     while ( pPrevFrm &&
1391             ( ( pPrevFrm->IsTxtFrm() &&
1392                 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ||
1393               ( pPrevFrm->IsSctFrm() &&
1394                 !static_cast<const SwSectionFrm*>(pPrevFrm)->GetSection() ) ) )
1395     {
1396         pPrevFrm = pPrevFrm->GetPrev();
1397     }
1398 
1399     // Special case: no direct previous frame is found but frame is in footnote
1400     // Search for a previous frame in previous footnote,
1401     // if frame isn't in a section, which is also in the footnote
1402     if ( !pPrevFrm && rThis.IsInFtn() &&
1403          ( rThis.IsSctFrm() ||
1404            !rThis.IsInSct() || !rThis.FindSctFrm()->IsInFtn() ) )
1405     {
1406         const SwFtnFrm* pPrevFtnFrm =
1407                 static_cast<const SwFtnFrm*>(rThis.FindFtnFrm()->GetPrev());
1408         if ( pPrevFtnFrm )
1409         {
1410             pPrevFrm = pPrevFtnFrm->GetLastLower();
1411 
1412             // Skip hidden paragraphs and empty sections
1413             while ( pPrevFrm &&
1414                     ( ( pPrevFrm->IsTxtFrm() &&
1415                         static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ||
1416                       ( pPrevFrm->IsSctFrm() &&
1417                         !static_cast<const SwSectionFrm*>(pPrevFrm)->GetSection() ) ) )
1418             {
1419                 pPrevFrm = pPrevFrm->GetPrev();
1420             }
1421         }
1422     }
1423     // Special case: found previous frame is a section
1424     // Search for the last content in the section
1425     if( pPrevFrm && pPrevFrm->IsSctFrm() )
1426     {
1427         const SwSectionFrm* pPrevSectFrm =
1428                                     static_cast<const SwSectionFrm*>(pPrevFrm);
1429         pPrevFrm = pPrevSectFrm->FindLastCntnt();
1430         // If the last content is in a table _inside_ the section,
1431         // take the table herself.
1432         // OD 2004-02-18 #106629# - correction:
1433         // Check directly, if table is inside table, instead of indirectly
1434         // by checking, if section isn't inside a table
1435         if ( pPrevFrm && pPrevFrm->IsInTab() )
1436         {
1437             const SwTabFrm* pTableFrm = pPrevFrm->FindTabFrm();
1438             if ( pPrevSectFrm->IsAnLower( pTableFrm ) )
1439             {
1440                 pPrevFrm = pTableFrm;
1441             }
1442         }
1443         // OD 2004-02-18 #106629# correction: skip hidden text frames
1444         while ( pPrevFrm &&
1445                 pPrevFrm->IsTxtFrm() &&
1446                 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() )
1447         {
1448             pPrevFrm = pPrevFrm->GetPrev();
1449         }
1450     }
1451 
1452     return pPrevFrm;
1453 }
1454 
1455 // OD 2004-03-12 #i11860# - add 3rd parameter <_bConsiderGrid>
1456 SwTwips SwFlowFrm::CalcUpperSpace( const SwBorderAttrs *pAttrs,
1457                                    const SwFrm* pPr,
1458                                    const bool _bConsiderGrid ) const
1459 {
1460     // OD 2004-03-10 #i11860# - use new method <GetPrevFrmForUpperSpaceCalc(..)>
1461     const SwFrm* pPrevFrm = _GetPrevFrmForUpperSpaceCalc( pPr );
1462 
1463     SwBorderAttrAccess *pAccess;
1464 	SwFrm* pOwn;
1465 	if( !pAttrs )
1466 	{
1467 		if( rThis.IsSctFrm() )
1468 		{
1469 			SwSectionFrm* pFoll = &((SwSectionFrm&)rThis);
1470 			do
1471 				pOwn = pFoll->ContainsAny();
1472 			while( !pOwn && 0 != ( pFoll = pFoll->GetFollow() ) );
1473 			if( !pOwn )
1474 				return 0;
1475 		}
1476 		else
1477 			pOwn = &rThis;
1478 		pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), pOwn );
1479 		pAttrs = pAccess->Get();
1480 	}
1481 	else
1482 	{
1483 		pAccess = NULL;
1484 		pOwn = &rThis;
1485 	}
1486 	SwTwips nUpper = 0;
1487     // OD 06.01.2004 #i11859#
1488     {
1489         const IDocumentSettingAccess* pIDSA = rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess();
1490         const bool bUseFormerLineSpacing = pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING);
1491         if( pPrevFrm )
1492         {
1493             // OD 2004-03-10 #i11860# - use new method to determine needed spacing
1494             // values of found previous frame and use these values.
1495             SwTwips nPrevLowerSpace = 0;
1496             SwTwips nPrevLineSpacing = 0;
1497             // --> OD 2009-08-28 #i102458#
1498             bool bPrevLineSpacingPorportional = false;
1499             GetSpacingValuesOfFrm( (*pPrevFrm),
1500                                    nPrevLowerSpace, nPrevLineSpacing,
1501                                    bPrevLineSpacingPorportional );
1502             // <--
1503             if( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) )
1504             {
1505                 nUpper = nPrevLowerSpace + pAttrs->GetULSpace().GetUpper();
1506                 SwTwips nAdd = nPrevLineSpacing;
1507                 // OD 07.01.2004 #i11859# - consideration of the line spacing
1508                 //      for the upper spacing of a text frame
1509                 if ( bUseFormerLineSpacing )
1510                 {
1511                     // former consideration
1512                     if ( pOwn->IsTxtFrm() )
1513                     {
1514                         nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace() );
1515                     }
1516                     nUpper += nAdd;
1517                 }
1518                 else
1519                 {
1520                     // new consideration:
1521                     //      Only the proportional line spacing of the previous
1522                     //      text frame is considered for the upper spacing and
1523                     //      the line spacing values are add up instead of
1524                     //      building its maximum.
1525                     if ( pOwn->IsTxtFrm() )
1526                     {
1527                         // --> OD 2009-08-28 #i102458#
1528                         // Correction:
1529                         // A proportional line spacing of the previous text frame
1530                         // is added up to a own leading line spacing.
1531                         // Otherwise, the maximum of the leading line spacing
1532                         // of the previous text frame and the own leading line
1533                         // spacing is built.
1534                         if ( bPrevLineSpacingPorportional )
1535                         {
1536                             nAdd += static_cast<SwTxtFrm&>(rThis).GetLineSpace( true );
1537                         }
1538                         else
1539                         {
1540                             nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ) );
1541                         }
1542                         // <--
1543                     }
1544                     nUpper += nAdd;
1545                 }
1546             }
1547             else
1548             {
1549                 nUpper = Max( static_cast<long>(nPrevLowerSpace),
1550                               static_cast<long>(pAttrs->GetULSpace().GetUpper()) );
1551                 // OD 07.01.2004 #i11859# - consideration of the line spacing
1552                 //      for the upper spacing of a text frame
1553                 if ( bUseFormerLineSpacing )
1554                 {
1555                     // former consideration
1556                     if ( pOwn->IsTxtFrm() )
1557                         nUpper = Max( nUpper, ((SwTxtFrm*)pOwn)->GetLineSpace() );
1558                     if ( nPrevLineSpacing != 0 )
1559                     {
1560                         nUpper = Max( nUpper, nPrevLineSpacing );
1561                     }
1562                 }
1563                 else
1564                 {
1565                     // new consideration:
1566                     //      Only the proportional line spacing of the previous
1567                     //      text frame is considered for the upper spacing and
1568                     //      the line spacing values are add up and added to
1569                     //      the paragraph spacing instead of building the
1570                     //      maximum of the line spacings and the paragraph spacing.
1571                     SwTwips nAdd = nPrevLineSpacing;
1572                     if ( pOwn->IsTxtFrm() )
1573                     {
1574                         // --> OD 2009-08-28 #i102458#
1575                         // Correction:
1576                         // A proportional line spacing of the previous text frame
1577                         // is added up to a own leading line spacing.
1578                         // Otherwise, the maximum of the leading line spacing
1579                         // of the previous text frame and the own leading line
1580                         // spacing is built.
1581                         if ( bPrevLineSpacingPorportional )
1582                         {
1583                             nAdd += static_cast<SwTxtFrm&>(rThis).GetLineSpace( true );
1584                         }
1585                         else
1586                         {
1587                             nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ) );
1588                         }
1589                         // <--
1590                     }
1591                     nUpper += nAdd;
1592                 }
1593             }
1594         }
1595         else if ( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES) &&
1596                   CastFlowFrm( pOwn )->HasParaSpaceAtPages( rThis.IsSctFrm() ) )
1597         {
1598             nUpper = pAttrs->GetULSpace().GetUpper();
1599         }
1600     }
1601 
1602     // OD 2004-02-26 #i25029# - pass previous frame <pPrevFrm>
1603     // to method <GetTopLine(..)>, if parameter <pPr> is set.
1604     // Note: parameter <pPr> is set, if method is called from <SwTxtFrm::WouldFit(..)>
1605     nUpper += pAttrs->GetTopLine( rThis, (pPr ? pPrevFrm : 0L) );
1606 
1607     // OD 2004-03-12 #i11860# - consider value of new parameter <_bConsiderGrid>
1608     // and use new method <GetUpperSpaceAmountConsideredForPageGrid(..)>
1609 
1610 	//consider grid in square page mode
1611     if ( _bConsiderGrid && rThis.GetUpper()->GetFmt()->GetDoc()->IsSquaredPageMode() )
1612     {
1613         nUpper += _GetUpperSpaceAmountConsideredForPageGrid( nUpper );
1614     }
1615 
1616 	delete pAccess;
1617 	return nUpper;
1618 }
1619 
1620 /** method to detemine the upper space amount, which is considered for
1621     the page grid
1622 
1623     OD 2004-03-12 #i11860#
1624     Precondition: Position of frame is valid.
1625 
1626     @author OD
1627 */
1628 SwTwips SwFlowFrm::_GetUpperSpaceAmountConsideredForPageGrid(
1629                             const SwTwips _nUpperSpaceWithoutGrid ) const
1630 {
1631     SwTwips nUpperSpaceAmountConsideredForPageGrid = 0;
1632 
1633     if ( rThis.IsInDocBody() && rThis.GetAttrSet()->GetParaGrid().GetValue() )
1634     {
1635         const SwPageFrm* pPageFrm = rThis.FindPageFrm();
1636         GETGRID( pPageFrm )
1637         if( pGrid )
1638         {
1639             const SwFrm* pBodyFrm = pPageFrm->FindBodyCont();
1640             if ( pBodyFrm )
1641             {
1642                 const long nGridLineHeight =
1643                         pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
1644 
1645                 SWRECTFN( (&rThis) )
1646                 const SwTwips nBodyPrtTop = (pBodyFrm->*fnRect->fnGetPrtTop)();
1647                 const SwTwips nProposedPrtTop =
1648                         (*fnRect->fnYInc)( (rThis.Frm().*fnRect->fnGetTop)(),
1649                                            _nUpperSpaceWithoutGrid );
1650 
1651                 const SwTwips nSpaceAbovePrtTop =
1652                         (*fnRect->fnYDiff)( nProposedPrtTop, nBodyPrtTop );
1653                 const SwTwips nSpaceOfCompleteLinesAbove =
1654                         nGridLineHeight * ( nSpaceAbovePrtTop / nGridLineHeight );
1655                 SwTwips nNewPrtTop =
1656                         (*fnRect->fnYInc)( nBodyPrtTop, nSpaceOfCompleteLinesAbove );
1657                 if ( (*fnRect->fnYDiff)( nProposedPrtTop, nNewPrtTop ) > 0 )
1658                 {
1659                     nNewPrtTop = (*fnRect->fnYInc)( nNewPrtTop, nGridLineHeight );
1660                 }
1661 
1662                 const SwTwips nNewUpperSpace =
1663                         (*fnRect->fnYDiff)( nNewPrtTop,
1664                                             (rThis.Frm().*fnRect->fnGetTop)() );
1665 
1666                 nUpperSpaceAmountConsideredForPageGrid =
1667                         nNewUpperSpace - _nUpperSpaceWithoutGrid;
1668 
1669                 ASSERT( nUpperSpaceAmountConsideredForPageGrid >= 0,
1670                         "<SwFlowFrm::GetUpperSpaceAmountConsideredForPageGrid(..)> - negative space considered for page grid!" );
1671             }
1672         }
1673     }
1674     return nUpperSpaceAmountConsideredForPageGrid;
1675 }
1676 
1677 /** method to determent the upper space amount, which is considered for
1678     the previous frame
1679 
1680     OD 2004-03-11 #i11860#
1681 
1682     @author OD
1683 */
1684 SwTwips SwFlowFrm::_GetUpperSpaceAmountConsideredForPrevFrm() const
1685 {
1686     SwTwips nUpperSpaceAmountOfPrevFrm = 0;
1687 
1688     const SwFrm* pPrevFrm = _GetPrevFrmForUpperSpaceCalc();
1689     if ( pPrevFrm )
1690     {
1691         SwTwips nPrevLowerSpace = 0;
1692         SwTwips nPrevLineSpacing = 0;
1693         // --> OD 2009-08-28 #i102458#
1694         bool bDummy = false;
1695         GetSpacingValuesOfFrm( (*pPrevFrm), nPrevLowerSpace, nPrevLineSpacing, bDummy );
1696         // <--
1697         if ( nPrevLowerSpace > 0 || nPrevLineSpacing > 0 )
1698         {
1699             const IDocumentSettingAccess* pIDSA = rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess();
1700             if (  pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) ||
1701                  !pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING) )
1702             {
1703                 nUpperSpaceAmountOfPrevFrm = nPrevLowerSpace + nPrevLineSpacing;
1704             }
1705             else
1706             {
1707                 nUpperSpaceAmountOfPrevFrm = Max( nPrevLowerSpace, nPrevLineSpacing );
1708             }
1709         }
1710     }
1711 
1712     return nUpperSpaceAmountOfPrevFrm;
1713 }
1714 
1715 /** method to determine the upper space amount, which is considered for
1716     the previous frame and the page grid, if option 'Use former object
1717     positioning' is OFF
1718 
1719     OD 2004-03-18 #i11860#
1720 
1721     @author OD
1722 */
1723 SwTwips SwFlowFrm::GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() const
1724 {
1725     SwTwips nUpperSpaceAmountConsideredForPrevFrmAndPageGrid = 0;
1726 
1727     if ( !rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) )
1728     {
1729         nUpperSpaceAmountConsideredForPrevFrmAndPageGrid =
1730             _GetUpperSpaceAmountConsideredForPrevFrm() +
1731             _GetUpperSpaceAmountConsideredForPageGrid( CalcUpperSpace( 0L, 0L, false ) );
1732     }
1733 
1734     return nUpperSpaceAmountConsideredForPrevFrmAndPageGrid;
1735 }
1736 
1737 /** calculation of lower space
1738 
1739     OD 2004-03-02 #106629#
1740 
1741     @author OD
1742 */
1743 SwTwips SwFlowFrm::CalcLowerSpace( const SwBorderAttrs* _pAttrs ) const
1744 {
1745     SwTwips nLowerSpace = 0;
1746 
1747     SwBorderAttrAccess* pAttrAccess = 0L;
1748     if ( !_pAttrs )
1749     {
1750         pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), &rThis );
1751         _pAttrs = pAttrAccess->Get();
1752     }
1753 
1754     sal_Bool bCommonBorder = sal_True;
1755     if ( rThis.IsInSct() && rThis.GetUpper()->IsColBodyFrm() )
1756     {
1757         const SwSectionFrm* pSectFrm = rThis.FindSctFrm();
1758         bCommonBorder = pSectFrm->GetFmt()->GetBalancedColumns().GetValue();
1759     }
1760     nLowerSpace = bCommonBorder ?
1761                   _pAttrs->GetBottomLine( rThis ) :
1762                   _pAttrs->CalcBottomLine();
1763 
1764     // --> OD 2004-07-16 #i26250#
1765     // - correct consideration of table frames
1766     // - use new method <CalcAddLowerSpaceAsLastInTableCell(..)>
1767     if ( ( ( rThis.IsTabFrm() && rThis.GetUpper()->IsInTab() ) ||
1768            // --> OD 2004-11-16 #115759# - no lower spacing, if frame has a follow
1769            ( rThis.IsInTab() && !GetFollow() ) ) &&
1770            // <--
1771          !rThis.GetIndNext() )
1772     {
1773         nLowerSpace += CalcAddLowerSpaceAsLastInTableCell( _pAttrs );
1774     }
1775     // <--
1776 
1777     delete pAttrAccess;
1778 
1779     return nLowerSpace;
1780 }
1781 
1782 /** calculation of the additional space to be considered, if flow frame
1783     is the last inside a table cell
1784 
1785     OD 2004-07-16 #i26250#
1786 
1787     @author OD
1788 */
1789 SwTwips SwFlowFrm::CalcAddLowerSpaceAsLastInTableCell(
1790                                             const SwBorderAttrs* _pAttrs ) const
1791 {
1792     SwTwips nAdditionalLowerSpace = 0;
1793 
1794     if ( rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
1795     {
1796         const SwFrm* pFrm = &rThis;
1797         if ( pFrm->IsSctFrm() )
1798         {
1799             const SwSectionFrm* pSectFrm = static_cast<const SwSectionFrm*>(pFrm);
1800             pFrm = pSectFrm->FindLastCntnt();
1801             if ( pFrm && pFrm->IsInTab() )
1802             {
1803                 const SwTabFrm* pTableFrm = pFrm->FindTabFrm();
1804                 if ( pSectFrm->IsAnLower( pTableFrm ) )
1805                 {
1806                     pFrm = pTableFrm;
1807                 }
1808             }
1809         }
1810 
1811         SwBorderAttrAccess* pAttrAccess = 0L;
1812         if ( !_pAttrs || pFrm != &rThis )
1813         {
1814             pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), pFrm );
1815             _pAttrs = pAttrAccess->Get();
1816         }
1817 
1818         nAdditionalLowerSpace += _pAttrs->GetULSpace().GetLower();
1819 
1820         delete pAttrAccess;
1821     }
1822 
1823     return nAdditionalLowerSpace;
1824 }
1825 
1826 /*************************************************************************
1827 |*
1828 |*	sal_Bool SwFlowFrm::CheckMoveFwd()
1829 |*
1830 |*	Beschreibung		Moved den Frm vorwaerts wenn es durch die aktuellen
1831 |* 		Bedingungen und Attribute notwendig erscheint.
1832 |*	Ersterstellung		MA 05. Dec. 96
1833 |*	Letzte Aenderung	MA 09. Mar. 98
1834 |*
1835 |*************************************************************************/
1836 
1837 
1838 sal_Bool SwFlowFrm::CheckMoveFwd( sal_Bool &rbMakePage, sal_Bool bKeep, sal_Bool )
1839 {
1840 	const SwFrm* pNxt = rThis.GetIndNext();
1841 
1842 	if ( bKeep && //!bMovedBwd &&
1843 		 ( !pNxt || ( pNxt->IsTxtFrm() && ((SwTxtFrm*)pNxt)->IsEmptyMaster() ) ) &&
1844 		 ( 0 != (pNxt = rThis.FindNext()) ) && IsKeepFwdMoveAllowed() )
1845 	{
1846 		if( pNxt->IsSctFrm() )
1847 		{   // Nicht auf leere SectionFrms hereinfallen
1848 			const SwFrm* pTmp = NULL;
1849 			while( pNxt && pNxt->IsSctFrm() &&
1850 				   ( !((SwSectionFrm*)pNxt)->GetSection() ||
1851 					 0 == ( pTmp = ((SwSectionFrm*)pNxt)->ContainsAny() ) ) )
1852 			{
1853 				pNxt = pNxt->FindNext();
1854 				pTmp = NULL;
1855 			}
1856 			if( pTmp )
1857 				pNxt = pTmp; // the content of the next notempty sectionfrm
1858 		}
1859 		if( pNxt && pNxt->GetValidPosFlag() )
1860 		{
1861 			sal_Bool bMove = sal_False;
1862 			const SwSectionFrm *pSct = rThis.FindSctFrm();
1863 			if( pSct && !pSct->GetValidSizeFlag() )
1864 			{
1865 				const SwSectionFrm* pNxtSct = pNxt->FindSctFrm();
1866 				if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
1867 					bMove = sal_True;
1868 			}
1869 			else
1870 				bMove = sal_True;
1871 			if( bMove )
1872 			{
1873 				//Keep together with the following frame
1874 				MoveFwd( rbMakePage, sal_False );
1875 				return sal_True;
1876 			}
1877 		}
1878 	}
1879 
1880 	sal_Bool bMovedFwd = sal_False;
1881 
1882 	if ( rThis.GetIndPrev() )
1883 	{
1884 		if ( IsPrevObjMove() ) //Auf Objekte des Prev Ruecksicht nehmen?
1885 		{
1886 			bMovedFwd = sal_True;
1887 			if ( !MoveFwd( rbMakePage, sal_False ) )
1888 				rbMakePage = sal_False;
1889 		}
1890 		else
1891 		{
1892 			if ( IsPageBreak( sal_False ) )
1893 			{
1894 				while ( MoveFwd( rbMakePage, sal_True ) )
1895 						/* do nothing */;
1896 				rbMakePage = sal_False;
1897 				bMovedFwd = sal_True;
1898 			}
1899 			else if ( IsColBreak ( sal_False ) )
1900 			{
1901 				const SwPageFrm *pPage = rThis.FindPageFrm();
1902 				SwFrm *pCol = rThis.FindColFrm();
1903 				do
1904 				{	MoveFwd( rbMakePage, sal_False );
1905 					SwFrm *pTmp = rThis.FindColFrm();
1906 					if( pTmp != pCol )
1907 					{
1908 						bMovedFwd = sal_True;
1909 						pCol = pTmp;
1910 					}
1911 					else
1912 						break;
1913 				} while ( IsColBreak( sal_False ) );
1914 				if ( pPage != rThis.FindPageFrm() )
1915 					rbMakePage = sal_False;
1916 			}
1917 		}
1918 	}
1919 	return bMovedFwd;
1920 }
1921 
1922 /*************************************************************************
1923 |*
1924 |*	sal_Bool SwFlowFrm::MoveFwd()
1925 |*
1926 |*	Beschreibung		Returnwert sagt, ob der Frm die Seite gewechselt hat.
1927 |*	Ersterstellung		MA 05. Dec. 96
1928 |*	Letzte Aenderung	MA 05. Dec. 96
1929 |*
1930 |*************************************************************************/
1931 
1932 
1933 sal_Bool SwFlowFrm::MoveFwd( sal_Bool bMakePage, sal_Bool bPageBreak, sal_Bool bMoveAlways )
1934 {
1935 //!!!!MoveFtnCntFwd muss ggf. mitgepflegt werden.
1936 	SwFtnBossFrm *pOldBoss = rThis.FindFtnBossFrm();
1937 	if ( rThis.IsInFtn() )
1938 		return ((SwCntntFrm&)rThis).MoveFtnCntFwd( bMakePage, pOldBoss );
1939 
1940 	if( !IsFwdMoveAllowed() && !bMoveAlways )
1941 	{
1942 		sal_Bool bNoFwd = sal_True;
1943 		if( rThis.IsInSct() )
1944 		{
1945 			SwFtnBossFrm* pBoss = rThis.FindFtnBossFrm();
1946 			bNoFwd = !pBoss->IsInSct() || ( !pBoss->Lower()->GetNext() &&
1947 					 !pBoss->GetPrev() );
1948 		}
1949 
1950         // Allow the MoveFwd even if we do not have an IndPrev in these cases:
1951         if ( rThis.IsInTab() &&
1952             ( !rThis.IsTabFrm() ||
1953                 ( rThis.GetUpper()->IsInTab() &&
1954                   rThis.GetUpper()->FindTabFrm()->IsFwdMoveAllowed() ) ) &&
1955              0 != const_cast<SwFrm&>(rThis).GetNextCellLeaf( MAKEPAGE_NONE ) )
1956 /*
1957               &&
1958             // NEW TABLES
1959             // Have a look at our main competitor: We don't move inside row span cells:
1960             ( !rThis.GetUpper()->IsCellFrm() || !rThis.GetUpper()->IsLeaveUpperAllowed() ) )*/
1961         {
1962             bNoFwd = sal_False;
1963         }
1964 
1965         if( bNoFwd )
1966 		{
1967 			//Fuer PageBreak ist das Moven erlaubt, wenn der Frm nicht
1968 			//bereits der erste der Seite ist.
1969 			if ( !bPageBreak )
1970 				return sal_False;
1971 
1972 			const SwFrm *pCol = rThis.FindColFrm();
1973 			if ( !pCol || !pCol->GetPrev() )
1974 				return sal_False;
1975 		}
1976 	}
1977 
1978 	sal_Bool bSamePage = sal_True;
1979 	SwLayoutFrm *pNewUpper =
1980 			rThis.GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, sal_True );
1981 
1982 	if ( pNewUpper )
1983 	{
1984 		PROTOCOL_ENTER( &rThis, PROT_MOVE_FWD, 0, 0 );
1985 		SwPageFrm *pOldPage = pOldBoss->FindPageFrm();
1986 		//Wir moven uns und alle direkten Nachfolger vor den ersten
1987 		//CntntFrm unterhalb des neuen Uppers.
1988 
1989 		// Wenn unser NewUpper in einem SectionFrm liegt, muessen wir
1990 		// verhindern, dass sich dieser im Calc selbst zerstoert
1991 		SwSectionFrm* pSect = pNewUpper->FindSctFrm();
1992 		sal_Bool bUnlock = sal_False;
1993 		if( pSect )
1994 		{
1995 			// Wenn wir nur innerhalb unseres SectionFrms die Spalte wechseln,
1996 			// rufen wir lieber kein Calc, sonst wird noch der SectionFrm
1997 			// formatiert, der wiederum uns ruft etc.
1998 			if( pSect != rThis.FindSctFrm() )
1999 			{
2000 				bUnlock = !pSect->IsColLocked();
2001 				pSect->ColLock();
2002 				pNewUpper->Calc();
2003 				if( bUnlock )
2004 					pSect->ColUnlock();
2005 			}
2006 		}
2007         // Do not calculate split cell frames.
2008 		else if ( !pNewUpper->IsCellFrm() || ((SwLayoutFrm*)pNewUpper)->Lower() )
2009 			pNewUpper->Calc();
2010 
2011 		SwFtnBossFrm *pNewBoss = pNewUpper->FindFtnBossFrm();
2012 		sal_Bool bBossChg = pNewBoss != pOldBoss;
2013 		pNewBoss = pNewBoss->FindFtnBossFrm( sal_True );
2014 		pOldBoss = pOldBoss->FindFtnBossFrm( sal_True );
2015 		SwPageFrm* pNewPage = pOldPage;
2016 
2017 		// First, we move the footnotes.
2018 		sal_Bool bFtnMoved = sal_False;
2019 
2020         // --> FME 2004-07-15 #i26831#
2021         // If pSect has just been created, the printing area of pSect has
2022         // been calculated based on the first content of its follow.
2023         // In this case we prefer to call a SimpleFormat for this new
2024         // section after we inserted the contents. Otherwise the section
2025         // frame will invalidate its lowers, if its printing area changes
2026         // in SwSectionFrm::Format, which can cause loops.
2027         const bool bForceSimpleFormat = pSect && pSect->HasFollow() &&
2028                                        !pSect->ContainsAny();
2029         // <--
2030 
2031         if ( pNewBoss != pOldBoss )
2032 		{
2033 			pNewPage = pNewBoss->FindPageFrm();
2034 			bSamePage = pNewPage == pOldPage;
2035 			//Damit die Fussnoten nicht auf dumme Gedanken kommen
2036 			//setzen wir hier die Deadline.
2037             SWRECTFN( pOldBoss )
2038 			SwSaveFtnHeight aHeight( pOldBoss,
2039                 (pOldBoss->Frm().*fnRect->fnGetBottom)() );
2040 			SwCntntFrm* pStart = rThis.IsCntntFrm() ?
2041 				(SwCntntFrm*)&rThis : ((SwLayoutFrm&)rThis).ContainsCntnt();
2042 			ASSERT( pStart || ( rThis.IsTabFrm() && !((SwTabFrm&)rThis).Lower() ),
2043                     "MoveFwd: Missing Content" );
2044 			SwLayoutFrm* pBody = pStart ? ( pStart->IsTxtFrm() ?
2045 				(SwLayoutFrm*)((SwTxtFrm*)pStart)->FindBodyFrm() : 0 ) : 0;
2046 			if( pBody )
2047 				bFtnMoved = pBody->MoveLowerFtns( pStart, pOldBoss, pNewBoss,
2048 												  sal_False);
2049 		}
2050 		// Bei SectionFrms ist es moeglich, dass wir selbst durch pNewUpper->Calc()
2051 		// bewegt wurden, z. B. in den pNewUpper.
2052 		// MoveSubTree bzw. PasteTree ist auf so etwas nicht vorbereitet.
2053 		if( pNewUpper != rThis.GetUpper() )
2054 		{
2055             // --> FME 2004-04-19 #i27145#
2056             SwSectionFrm* pOldSct = 0;
2057             if ( rThis.GetUpper()->IsSctFrm() )
2058             {
2059                 pOldSct = static_cast<SwSectionFrm*>(rThis.GetUpper());
2060             }
2061             // <--
2062 
2063             MoveSubTree( pNewUpper, pNewUpper->Lower() );
2064 
2065             // --> FME 2004-04-19 #i27145#
2066             if ( pOldSct && pOldSct->GetSection() )
2067             {
2068                 // Prevent loops by setting the new height at
2069                 // the section frame if footnotes have been moved.
2070                 // Otherwise the call of SwLayNotify::~SwLayNotify() for
2071                 // the (invalid) section frame will invalidate the first
2072                 // lower of its follow, because it grows due to the removed
2073                 // footnotes.
2074                 // Note: If pOldSct has become empty during MoveSubTree, it
2075                 // has already been scheduled for removal. No SimpleFormat
2076                 // for these.
2077                 pOldSct->SimpleFormat();
2078             }
2079             // <--
2080 
2081             // --> FME 2004-07-15 #i26831#
2082             if ( bForceSimpleFormat )
2083             {
2084                 pSect->SimpleFormat();
2085             }
2086             // <--
2087 
2088             if ( bFtnMoved && !bSamePage )
2089 			{
2090 				pOldPage->UpdateFtnNum();
2091 				pNewPage->UpdateFtnNum();
2092 			}
2093 
2094 			if( bBossChg )
2095 			{
2096 				rThis.Prepare( PREP_BOSS_CHGD, 0, sal_False );
2097 				if( !bSamePage )
2098 				{
2099 					ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
2100 					if ( pSh && !pSh->Imp()->IsUpdateExpFlds() )
2101                         pSh->GetDoc()->SetNewFldLst(true);  //Wird von CalcLayout() hinterher erledigt!
2102 
2103                     pNewPage->InvalidateSpelling();
2104                     pNewPage->InvalidateSmartTags();    // SMARTTAGS
2105                     pNewPage->InvalidateAutoCompleteWords();
2106                     pNewPage->InvalidateWordCount();
2107 				}
2108 			}
2109 		}
2110         // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout
2111         const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
2112 
2113         if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) )
2114         {
2115             // --> OD 2009-12-31 #i106452#
2116             // check page description not only in situation with sections.
2117             if ( !bSamePage &&
2118                  ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() ||
2119                    pOldPage->GetPageDesc()->GetFollow() != pNewPage->GetPageDesc() ) )
2120             {
2121                 SwFrm::CheckPageDescs( pNewPage, sal_False );
2122             }
2123             // <--
2124         }
2125 	}
2126 	return bSamePage;
2127 }
2128 
2129 
2130 /*************************************************************************
2131 |*
2132 |*	sal_Bool SwFlowFrm::MoveBwd()
2133 |*
2134 |*	Beschreibung		Returnwert sagt, ob der Frm die Seite wechseln soll.
2135 |*						Sollte von abgeleiteten Klassen gerufen werden.
2136 |* 						Das moven selbst muessen die abgeleiteten uebernehmen.
2137 |*	Ersterstellung		MA 05. Dec. 96
2138 |*	Letzte Aenderung	MA 05. Dec. 96
2139 |*
2140 |*************************************************************************/
2141 
2142 sal_Bool SwFlowFrm::MoveBwd( sal_Bool &rbReformat )
2143 {
2144 	SwFlowFrm::SetMoveBwdJump( sal_False );
2145 
2146 	SwFtnFrm* pFtn = rThis.FindFtnFrm();
2147 	if ( pFtn && pFtn->IsBackMoveLocked() )
2148 		return sal_False;
2149 
2150     // --> OD 2004-11-29 #115759# - text frames, which are directly inside
2151     // tables aren't allowed to move backward.
2152     if ( rThis.IsTxtFrm() && rThis.IsInTab() )
2153     {
2154         const SwLayoutFrm* pUpperFrm = rThis.GetUpper();
2155         while ( pUpperFrm )
2156         {
2157             if ( pUpperFrm->IsTabFrm() )
2158             {
2159                 return sal_False;
2160             }
2161             else if ( pUpperFrm->IsColumnFrm() && pUpperFrm->IsInSct() )
2162             {
2163                 break;
2164             }
2165             pUpperFrm = pUpperFrm->GetUpper();
2166         }
2167     }
2168     // <--
2169 
2170 	SwFtnBossFrm * pOldBoss = rThis.FindFtnBossFrm();
2171 	SwPageFrm * const pOldPage = pOldBoss->FindPageFrm();
2172 	SwLayoutFrm *pNewUpper = 0;
2173 	sal_Bool bCheckPageDescs = sal_False;
2174     bool bCheckPageDescOfNextPage = false;
2175 
2176 	if ( pFtn )
2177 	{
2178         //Wenn die Fussnote bereits auf der gleichen Seite/Spalte wie die Referenz
2179         //steht, ist nix mit zurueckfliessen. Die breaks brauche fuer die
2180         //Fussnoten nicht geprueft zu werden.
2181 
2182         // --> FME 2004-11-15 #i37084# FindLastCntnt does not necessarily
2183         // have to have a result != 0
2184         SwFrm* pRef = 0;
2185         const bool bEndnote = pFtn->GetAttr()->GetFtn().IsEndNote();
2186         if( bEndnote && pFtn->IsInSct() )
2187         {
2188             SwSectionFrm* pSect = pFtn->FindSctFrm();
2189             if( pSect->IsEndnAtEnd() )
2190                 pRef = pSect->FindLastCntnt( FINDMODE_LASTCNT );
2191         }
2192         if( !pRef )
2193             pRef = pFtn->GetRef();
2194         // <--
2195 
2196         ASSERT( pRef, "MoveBwd: Endnote for an empty section?" );
2197 
2198         if( !bEndnote )
2199 			pOldBoss = pOldBoss->FindFtnBossFrm( sal_True );
2200 		SwFtnBossFrm *pRefBoss = pRef->FindFtnBossFrm( !bEndnote );
2201         if ( pOldBoss != pRefBoss &&
2202              // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
2203              ( !bEndnote ||
2204                pRefBoss->IsBefore( pOldBoss ) )
2205            )
2206 			pNewUpper = rThis.GetLeaf( MAKEPAGE_FTN, sal_False );
2207 	}
2208 	else if ( IsPageBreak( sal_True ) )	//PageBreak zu beachten?
2209 	{
2210 		//Wenn auf der vorhergehenden Seite kein Frm im Body steht,
2211 		//so ist das Zurueckfliessen trotz Pagebreak sinnvoll
2212 		//(sonst: leere Seite).
2213 		//Natuerlich muessen Leereseiten geflissentlich uebersehen werden!
2214 		const SwFrm *pFlow = &rThis;
2215 		do
2216         {
2217             pFlow = pFlow->FindPrev();
2218         } while ( pFlow &&
2219                   ( pFlow->FindPageFrm() == pOldPage ||
2220                     !pFlow->IsInDocBody() ) );
2221 		if ( pFlow )
2222 		{
2223 			long nDiff = pOldPage->GetPhyPageNum() - pFlow->GetPhyPageNum();
2224 			if ( nDiff > 1 )
2225 			{
2226 				if ( ((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage() )
2227 					nDiff -= 1;
2228 				if ( nDiff > 1 )
2229 				{
2230 					pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2231                     // --> OD 2006-05-08 #i53139#
2232                     // Now <pNewUpper> is a previous layout frame, which contains
2233                     // content. But the new upper layout frame has to be the next one.
2234                     // Thus, hack for issue i14206 no longer needed, but fix for issue 114442
2235                     // --> OD 2006-05-17 #136024# - correct fix for i53139:
2236                     // Check for wrong page description before using next new upper.
2237                     // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
2238                     // Check for correct type of new next upper layout frame
2239                     // --> OD 2006-06-08 #136538# - another correction of fix for i53139
2240                     // Assumption, that in all cases <pNewUpper> is a previous
2241                     // layout frame, which contains content, is wrong.
2242                     // --> OD 2006-07-05 #136538# - another correction of fix for i53139
2243                     // Beside type check, check also, if proposed new next upper
2244                     // frame is inside the same frame types.
2245                     // --> OD 2007-01-10 #i73194# - and yet another correction
2246                     // of fix for i53139:
2247                     // Assure that the new next upper layout frame doesn't
2248                     // equal the current one.
2249                     // E.g.: content is on page 3, on page 2 is only a 'ghost'
2250                     // section and on page 1 is normal content. Method <FindPrev(..)>
2251                     // will find the last content of page 1, but <GetLeaf(..)>
2252                     // returns new upper on page 2.
2253                     if ( pNewUpper->Lower() )
2254                     {
2255                         SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, sal_True );
2256                         if ( pNewNextUpper &&
2257                              pNewNextUpper != rThis.GetUpper() &&
2258                              pNewNextUpper->GetType() == pNewUpper->GetType() &&
2259                              pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2260                              pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2261                              pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2262                              pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2263                              !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2264                         {
2265                             pNewUpper = pNewNextUpper;
2266                             bCheckPageDescOfNextPage = true;
2267                         }
2268                     }
2269                     // <--
2270 
2271                     bCheckPageDescs = sal_True;
2272 				}
2273 			}
2274 		}
2275 	}
2276 	else if ( IsColBreak( sal_True ) )
2277 	{
2278 		//Wenn in der vorhergehenden Spalte kein CntntFrm steht, so ist
2279 		//das Zurueckfliessen trotz ColumnBreak sinnvoll
2280 		//(sonst: leere Spalte).
2281 		if( rThis.IsInSct() )
2282 		{
2283 			pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2284 			if( pNewUpper && !SwFlowFrm::IsMoveBwdJump() &&
2285 				( pNewUpper->ContainsCntnt() ||
2286 				  ( ( !pNewUpper->IsColBodyFrm() ||
2287 					  !pNewUpper->GetUpper()->GetPrev() ) &&
2288 					!pNewUpper->FindSctFrm()->GetPrev() ) ) )
2289             {
2290 				pNewUpper = 0;
2291             }
2292             // --> OD 2006-05-08 #i53139#
2293             // --> OD 2006-09-11 #i69409# - check <pNewUpper>
2294             // --> OD 2006-11-02 #i71065# - check <SwFlowFrm::IsMoveBwdJump()>
2295             else if ( pNewUpper && !SwFlowFrm::IsMoveBwdJump() )
2296             // <--
2297             {
2298                 // Now <pNewUpper> is a previous layout frame, which
2299                 // contains content. But the new upper layout frame
2300                 // has to be the next one.
2301                 // --> OD 2006-05-17 #136024# - correct fix for i53139
2302                 // Check for wrong page description before using next new upper.
2303                 // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
2304                 // Check for correct type of new next upper layout frame
2305                 // --> OD 2006-07-05 #136538# - another correction of fix for i53139
2306                 // Beside type check, check also, if proposed new next upper
2307                 // frame is inside the same frame types.
2308                 SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NOSECTION, sal_True );
2309                 if ( pNewNextUpper &&
2310                      pNewNextUpper->GetType() == pNewUpper->GetType() &&
2311                      pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2312                      pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2313                      pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2314                      pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2315                      !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2316                 {
2317                     pNewUpper = pNewNextUpper;
2318                 }
2319             }
2320             // <--
2321 		}
2322 		else
2323 		{
2324 			const SwFrm *pCol = rThis.FindColFrm();
2325 			sal_Bool bGoOn = sal_True;
2326 			sal_Bool bJump = sal_False;
2327 			do
2328 			{
2329 				if ( pCol->GetPrev() )
2330 					pCol = pCol->GetPrev();
2331 				else
2332 				{
2333 					bGoOn = sal_False;
2334 					pCol = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2335 				}
2336 				if ( pCol )
2337 				{
2338 					// ColumnFrms jetzt mit BodyFrm
2339 					SwLayoutFrm* pColBody = pCol->IsColumnFrm() ?
2340 						(SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower() :
2341 						(SwLayoutFrm*)pCol;
2342 					if ( pColBody->ContainsCntnt() )
2343 					{
2344 						bGoOn = sal_False; // Hier gibt's Inhalt, wir akzeptieren diese
2345 						// nur, wenn GetLeaf() das MoveBwdJump-Flag gesetzt hat.
2346 						if( SwFlowFrm::IsMoveBwdJump() )
2347                         {
2348 							pNewUpper = pColBody;
2349                             // --> OD 2006-05-08 #i53139#
2350                             // Now <pNewUpper> is a previous layout frame, which
2351                             // contains content. But the new upper layout frame
2352                             // has to be the next one.
2353                             // --> OD 2006-05-17 #136024# - correct fix for i53139
2354                             // Check for wrong page description before using next new upper.
2355                             // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
2356                             // Check for correct type of new next upper layout frame
2357                             // --> OD 2006-07-05 #136538# - another correction of fix for i53139
2358                             // Beside type check, check also, if proposed new next upper
2359                             // frame is inside the same frame types.
2360                             // --> OD 2006-11-02 #i71065#
2361                             // Check that the proposed new next upper layout
2362                             // frame isn't the current one.
2363                             SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, sal_True );
2364                             if ( pNewNextUpper &&
2365                                  pNewNextUpper != rThis.GetUpper() &&
2366                                  pNewNextUpper->GetType() == pNewUpper->GetType() &&
2367                                  pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2368                                  pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2369                                  pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2370                                  pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2371                                  !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2372                             {
2373                                 pNewUpper = pNewNextUpper;
2374                             }
2375                             // <--
2376                         }
2377 					}
2378 					else
2379 					{
2380 						if( pNewUpper ) // Wir hatten schon eine leere Spalte, haben
2381 							bJump = sal_True;   // also eine uebersprungen
2382 						pNewUpper = pColBody;  // Diese leere Spalte kommt in Frage,
2383 										   	// trotzdem weitersuchen
2384 					}
2385 				}
2386 			} while( bGoOn );
2387 			if( bJump )
2388 				SwFlowFrm::SetMoveBwdJump( sal_True );
2389 		}
2390 	}
2391 	else //Keine Breaks also kann ich zurueckfliessen
2392 		pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2393 
2394     // --> OD 2004-06-23 #i27801# - no move backward of 'master' text frame,
2395     // if - due to its object positioning - it isn't allowed to be on the new page frame
2396     // --> OD 2005-03-07 #i44049# - add another condition for not moving backward:
2397     // If one of its objects has restarted the layout process, moving backward
2398     // isn't sensible either.
2399     // --> OD 2005-04-19 #i47697# - refine condition made for issue i44049:
2400     // - allow move backward as long as the anchored object is only temporarily
2401     //   positions considering its wrapping style.
2402     if ( pNewUpper &&
2403          rThis.IsTxtFrm() && !IsFollow() )
2404     {
2405         sal_uInt32 nToPageNum( 0L );
2406         const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos(
2407                                                 *(pOldPage->GetFmt()->GetDoc()),
2408                                                 static_cast<SwTxtFrm&>(rThis),
2409                                                 nToPageNum );
2410         if ( bMoveFwdByObjPos &&
2411              pNewUpper->FindPageFrm()->GetPhyPageNum() < nToPageNum )
2412         {
2413             pNewUpper = 0;
2414         }
2415         // --> OD 2005-03-07 #i44049# - check, if one of its anchored objects
2416         // has restarted the layout process.
2417         else if ( rThis.GetDrawObjs() )
2418         {
2419             sal_uInt32 i = 0;
2420             for ( ; i < rThis.GetDrawObjs()->Count(); ++i )
2421             {
2422                 SwAnchoredObject* pAnchoredObj = (*rThis.GetDrawObjs())[i];
2423                 // --> OD 2005-04-19 #i47697# - refine condition - see above
2424                 if ( pAnchoredObj->RestartLayoutProcess() &&
2425                      !pAnchoredObj->IsTmpConsiderWrapInfluence() )
2426                 // <--
2427                 {
2428                     pNewUpper = 0;
2429                     break;
2430                 }
2431             }
2432         }
2433         // <--
2434     }
2435     // <--
2436 
2437     //Fuer Follows ist das zurueckfliessen nur dann erlaubt wenn in der
2438 	//neuen Umgebung kein Nachbar existiert (denn dieses waere der Master).
2439 	//(6677)Wenn allerdings leere Blaetter uebersprungen wurden wird doch gemoved.
2440 	if ( pNewUpper && IsFollow() && pNewUpper->Lower() )
2441 	{
2442         // --> OD 2007-09-05 #i79774#, #b6596954#
2443         // neglect empty sections in proposed new upper frame
2444         bool bProposedNewUpperContainsOnlyEmptySections( true );
2445         {
2446             const SwFrm* pLower( pNewUpper->Lower() );
2447             while ( pLower )
2448             {
2449                 if ( pLower->IsSctFrm() &&
2450                      !dynamic_cast<const SwSectionFrm*>(pLower)->GetSection() )
2451                 {
2452                     pLower = pLower->GetNext();
2453                     continue;
2454                 }
2455                 else
2456                 {
2457                     bProposedNewUpperContainsOnlyEmptySections = false;
2458                     break;
2459                 }
2460             }
2461         }
2462         if ( !bProposedNewUpperContainsOnlyEmptySections )
2463         {
2464             if ( SwFlowFrm::IsMoveBwdJump() )
2465             {
2466                 //Nicht hinter den Master sondern in das naechstfolgende leere
2467                 //Blatt moven.
2468                 SwFrm *pFrm = pNewUpper->Lower();
2469                 while ( pFrm->GetNext() )
2470                     pFrm = pFrm->GetNext();
2471                 pNewUpper = pFrm->GetLeaf( MAKEPAGE_INSERT, sal_True );
2472                 if( pNewUpper == rThis.GetUpper() ) //Landen wir wieder an der gleichen Stelle?
2473                     pNewUpper = NULL;           //dann eruebrigt sich das Moven
2474             }
2475             else
2476                 pNewUpper = 0;
2477         }
2478         // <--
2479 	}
2480 	if ( pNewUpper && !ShouldBwdMoved( pNewUpper, sal_True, rbReformat ) )
2481 	{
2482 		if( !pNewUpper->Lower() )
2483 		{
2484 			if( pNewUpper->IsFtnContFrm() )
2485 			{
2486 				pNewUpper->Cut();
2487 				delete pNewUpper;
2488 			}
2489 			else
2490 			{
2491 				SwSectionFrm* pSectFrm = pNewUpper->FindSctFrm();
2492                 // --> OD 2006-01-04 #126020# - adjust check for empty section
2493                 // --> OD 2006-02-01 #130797# - correct fix #126020#
2494                 if ( pSectFrm && !pSectFrm->IsColLocked() &&
2495                      !pSectFrm->ContainsCntnt() && !pSectFrm->ContainsAny( true ) )
2496                 // <--
2497 				{
2498 					pSectFrm->DelEmpty( sal_True );
2499 					delete pSectFrm;
2500 					rThis.bValidPos = sal_True;
2501 				}
2502 			}
2503 		}
2504 		pNewUpper = 0;
2505 	}
2506 
2507     // OD 2004-05-26 #i21478# - don't move backward, if flow frame wants to
2508     // keep with next frame and next frame is locked.
2509     // --> OD 2004-12-08 #i38232# - If next frame is a table, do *not* check,
2510     // if it's locked.
2511     if ( pNewUpper && !IsFollow() &&
2512          rThis.GetAttrSet()->GetKeep().GetValue() && rThis.GetIndNext() )
2513     {
2514         SwFrm* pIndNext = rThis.GetIndNext();
2515         // --> OD 2004-12-08 #i38232#
2516         if ( !pIndNext->IsTabFrm() )
2517         {
2518             // get first content of section, while empty sections are skipped
2519             while ( pIndNext && pIndNext->IsSctFrm() )
2520             {
2521                 if( static_cast<SwSectionFrm*>(pIndNext)->GetSection() )
2522                 {
2523                     SwFrm* pTmp = static_cast<SwSectionFrm*>(pIndNext)->ContainsAny();
2524                     if ( pTmp )
2525                     {
2526                         pIndNext = pTmp;
2527                         break;
2528                     }
2529                 }
2530                 pIndNext = pIndNext->GetIndNext();
2531             }
2532             ASSERT( !pIndNext || pIndNext->ISA(SwTxtFrm),
2533                     "<SwFlowFrm::MovedBwd(..)> - incorrect next found." );
2534             if ( pIndNext && pIndNext->IsFlowFrm() &&
2535                  SwFlowFrm::CastFlowFrm(pIndNext)->IsJoinLocked() )
2536             {
2537                 pNewUpper = 0L;
2538             }
2539         }
2540         // <--
2541     }
2542 
2543     // --> OD 2006-05-10 #i65250#
2544     // layout loop control for flowing content again and again moving
2545     // backward under the same layout condition.
2546     if ( pNewUpper && !IsFollow() &&
2547          pNewUpper != rThis.GetUpper() &&
2548          SwLayouter::MoveBwdSuppressed( *(pOldPage->GetFmt()->GetDoc()),
2549                                         *this, *pNewUpper ) )
2550     {
2551         SwLayoutFrm* pNextNewUpper = pNewUpper->GetLeaf(
2552                                     ( !rThis.IsSctFrm() && rThis.IsInSct() )
2553                                     ? MAKEPAGE_NOSECTION
2554                                     : MAKEPAGE_NONE,
2555                                     sal_True );
2556         // --> OD 2007-01-10 #i73194# - make code robust
2557         ASSERT( pNextNewUpper, "<SwFlowFrm::MoveBwd(..)> - missing next new upper" );
2558         if ( pNextNewUpper &&
2559              ( pNextNewUpper == rThis.GetUpper() ||
2560                pNextNewUpper->GetType() != rThis.GetUpper()->GetType() ) )
2561         // <--
2562         {
2563             pNewUpper = 0L;
2564 #if OSL_DEBUG_LEVEL > 1
2565             ASSERT( false,
2566                     "<SwFlowFrm::MoveBwd(..)> - layout loop control for layout action <Move Backward> applied!" );
2567 #endif
2568         }
2569     }
2570     // <--
2571 
2572     ASSERT( pNewUpper != rThis.GetUpper(),
2573             "<SwFlowFrm::MoveBwd(..)> - moving backward to the current upper frame!? -> Please inform OD." );
2574 	if ( pNewUpper )
2575 	{
2576 		PROTOCOL_ENTER( &rThis, PROT_MOVE_BWD, 0, 0 );
2577 		if ( pNewUpper->IsFtnContFrm() )
2578 		{
2579 			//Kann sein, dass ich einen Container bekam.
2580 			SwFtnFrm *pOld = rThis.FindFtnFrm();
2581 			SwFtnFrm *pNew = new SwFtnFrm( pOld->GetFmt(), pOld,
2582 										   pOld->GetRef(), pOld->GetAttr() );
2583 			if ( pOld->GetMaster() )
2584 			{
2585 				pNew->SetMaster( pOld->GetMaster() );
2586 				pOld->GetMaster()->SetFollow( pNew );
2587 			}
2588 			pNew->SetFollow( pOld );
2589 			pOld->SetMaster( pNew );
2590 			pNew->Paste( pNewUpper );
2591 			pNewUpper = pNew;
2592 		}
2593 		if( pNewUpper->IsFtnFrm() && rThis.IsInSct() )
2594 		{
2595 			SwSectionFrm* pSct = rThis.FindSctFrm();
2596 			//Wenn wir in einem Bereich in einer Fussnote stecken, muss im
2597 			//neuen Upper ggf. ein SwSectionFrm angelegt werden
2598 			if( pSct->IsInFtn() )
2599 			{
2600 				SwFrm* pTmp = pNewUpper->Lower();
2601 				if( pTmp )
2602 				{
2603 					while( pTmp->GetNext() )
2604 						pTmp = pTmp->GetNext();
2605 					if( !pTmp->IsSctFrm() ||
2606 						((SwSectionFrm*)pTmp)->GetFollow() != pSct )
2607 						pTmp = NULL;
2608 				}
2609 				if( pTmp )
2610 					pNewUpper = (SwSectionFrm*)pTmp;
2611 				else
2612 				{
2613                     pSct = new SwSectionFrm( *pSct, sal_True );
2614 					pSct->Paste( pNewUpper );
2615                     pSct->Init();
2616 					pNewUpper = pSct;
2617 					pSct->SimpleFormat();
2618 				}
2619 			}
2620 		}
2621 		sal_Bool bUnlock = sal_False;
2622         sal_Bool bFollow = sal_False;
2623 		//Section locken, sonst kann sie bei Fluss des einzigen Cntnt etwa
2624 		//von zweiter in die erste Spalte zerstoert werden.
2625 		SwSectionFrm* pSect = pNewUpper->FindSctFrm();
2626 		if( pSect )
2627 		{
2628 			bUnlock = !pSect->IsColLocked();
2629 			pSect->ColLock();
2630 			bFollow = pSect->HasFollow();
2631 		}
2632 		pNewUpper->Calc();
2633 		rThis.Cut();
2634         // --> OD 2005-02-23 #b6229852#
2635         // optimization: format section, if its size is invalidated and if it's
2636         // the new parent of moved backward frame.
2637         bool bFormatSect( false );
2638         // <--
2639         if( bUnlock )
2640 		{
2641             pSect->ColUnlock();
2642             if( pSect->HasFollow() != bFollow )
2643             {
2644 				pSect->InvalidateSize();
2645                 // --> OD 2005-02-23 #b6229852# - optimization
2646                 if ( pSect == pNewUpper )
2647                     bFormatSect = true;
2648                 // <--
2649             }
2650 		}
2651 
2652 		rThis.Paste( pNewUpper );
2653         // --> OD 2005-02-23 #b6229852# - optimization
2654         if ( bFormatSect )
2655             pSect->Calc();
2656         // <--
2657 
2658         SwPageFrm *pNewPage = rThis.FindPageFrm();
2659 		if( pNewPage != pOldPage )
2660 		{
2661 			rThis.Prepare( PREP_BOSS_CHGD, (const void*)pOldPage, sal_False );
2662 			ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
2663 			if ( pSh && !pSh->Imp()->IsUpdateExpFlds() )
2664                 pSh->GetDoc()->SetNewFldLst(true);  //Wird von CalcLayout() hinterher eledigt!
2665 
2666             pNewPage->InvalidateSpelling();
2667             pNewPage->InvalidateSmartTags();    // SMARTTAGS
2668 			pNewPage->InvalidateAutoCompleteWords();
2669             pNewPage->InvalidateWordCount();
2670 
2671             // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout
2672             if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) )
2673             {
2674                 if ( bCheckPageDescs && pNewPage->GetNext() )
2675                 {
2676                     SwPageFrm* pStartPage = bCheckPageDescOfNextPage ?
2677                                             pNewPage :
2678                                             (SwPageFrm*)pNewPage->GetNext();
2679                     SwFrm::CheckPageDescs( pStartPage, sal_False);
2680                 }
2681                 else if ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() )
2682                 {
2683                     //Erste Seite wird etwa durch Ausblenden eines Bereiches leer
2684                     SwFrm::CheckPageDescs( (SwPageFrm*)pNewPage, sal_False);
2685                 }
2686             }
2687 		}
2688 	}
2689 	return pNewUpper != 0;
2690 }
2691 
2692 /*************************************************************************
2693 |*
2694 |*	SwFlowFrm::CastFlowFrm
2695 |*
2696 |*	Ersterstellung		MA 03. May. 95
2697 |*	Letzte Aenderung	AMA 02. Dec. 97
2698 |*
2699 |*************************************************************************/
2700 
2701 SwFlowFrm *SwFlowFrm::CastFlowFrm( SwFrm *pFrm )
2702 {
2703 	if ( pFrm->IsCntntFrm() )
2704 		return (SwCntntFrm*)pFrm;
2705 	if ( pFrm->IsTabFrm() )
2706 		return (SwTabFrm*)pFrm;
2707 	if ( pFrm->IsSctFrm() )
2708 		return (SwSectionFrm*)pFrm;
2709 	return 0;
2710 }
2711 
2712 const SwFlowFrm *SwFlowFrm::CastFlowFrm( const SwFrm *pFrm )
2713 {
2714 	if ( pFrm->IsCntntFrm() )
2715 		return (SwCntntFrm*)pFrm;
2716 	if ( pFrm->IsTabFrm() )
2717 		return (SwTabFrm*)pFrm;
2718 	if ( pFrm->IsSctFrm() )
2719 		return (SwSectionFrm*)pFrm;
2720 	return 0;
2721 }
2722