xref: /trunk/main/sw/source/core/layout/flowfrm.cxx (revision 7a3ba306)
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 
SwFlowFrm(SwFrm & rFrm)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 
HasLockedFollow() const96 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 
IsKeepFwdMoveAllowed()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 
CheckKeep()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 
IsKeep(const SwAttrSet & rAttrs,bool bCheckIfLastRowShouldKeep) const191 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 
BwdMoveNecessary(const SwPageFrm * pPage,const SwRect & rRect)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 
CutTree(SwFrm * pStart)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 
PasteTree(SwFrm * pStart,SwLayoutFrm * pParent,SwFrm * pSibling,SwFrm * pOldParent)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 
MoveSubTree(SwLayoutFrm * pParent,SwFrm * pSibling)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 
IsAnFollow(const SwFlowFrm * pAssumed) const688 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 
FindMaster() const709 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 
FindMaster() const729 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 
FindMaster(bool bFirstMaster) const746 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 
GetLeaf(MakePageType eMakePage,sal_Bool bFwd,const SwFrm * pAnch) const799 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 
GetLeaf(MakePageType eMakePage,sal_Bool bFwd)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 
WrongPageDesc(SwPageFrm * pNew)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 
GetNextLeaf(MakePageType eMakePage)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 
GetPrevLeaf(MakePageType)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 
IsPrevObjMove() const1150 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 
IsPageBreak(sal_Bool bAct) const1233 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 
IsColBreak(sal_Bool bAct) const1298 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 
HasParaSpaceAtPages(sal_Bool bSct) const1339 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 */
_GetPrevFrmForUpperSpaceCalc(const SwFrm * _pProposedPrevFrm) const1383 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>
CalcUpperSpace(const SwBorderAttrs * pAttrs,const SwFrm * pPr,const bool _bConsiderGrid) const1456 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 */
_GetUpperSpaceAmountConsideredForPageGrid(const SwTwips _nUpperSpaceWithoutGrid) const1628 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 */
_GetUpperSpaceAmountConsideredForPrevFrm() const1684 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 */
GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() const1723 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             ( rThis.GetUpper()->GetFmt()->GetDoc()->IsSquaredPageMode()
1732               ? _GetUpperSpaceAmountConsideredForPageGrid( CalcUpperSpace( 0, 0, false ) )
1733               : 0 );
1734     }
1735 
1736     return nUpperSpaceAmountConsideredForPrevFrmAndPageGrid;
1737 }
1738 
1739 /** calculation of lower space
1740 
1741     OD 2004-03-02 #106629#
1742 
1743     @author OD
1744 */
CalcLowerSpace(const SwBorderAttrs * _pAttrs) const1745 SwTwips SwFlowFrm::CalcLowerSpace( const SwBorderAttrs* _pAttrs ) const
1746 {
1747     SwTwips nLowerSpace = 0;
1748 
1749     SwBorderAttrAccess* pAttrAccess = 0L;
1750     if ( !_pAttrs )
1751     {
1752         pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), &rThis );
1753         _pAttrs = pAttrAccess->Get();
1754     }
1755 
1756     sal_Bool bCommonBorder = sal_True;
1757     if ( rThis.IsInSct() && rThis.GetUpper()->IsColBodyFrm() )
1758     {
1759         const SwSectionFrm* pSectFrm = rThis.FindSctFrm();
1760         bCommonBorder = pSectFrm->GetFmt()->GetBalancedColumns().GetValue();
1761     }
1762     nLowerSpace = bCommonBorder ?
1763                   _pAttrs->GetBottomLine( rThis ) :
1764                   _pAttrs->CalcBottomLine();
1765 
1766     // --> OD 2004-07-16 #i26250#
1767     // - correct consideration of table frames
1768     // - use new method <CalcAddLowerSpaceAsLastInTableCell(..)>
1769     if ( ( ( rThis.IsTabFrm() && rThis.GetUpper()->IsInTab() ) ||
1770            // --> OD 2004-11-16 #115759# - no lower spacing, if frame has a follow
1771            ( rThis.IsInTab() && !GetFollow() ) ) &&
1772            // <--
1773          !rThis.GetIndNext() )
1774     {
1775         nLowerSpace += CalcAddLowerSpaceAsLastInTableCell( _pAttrs );
1776     }
1777     // <--
1778 
1779     delete pAttrAccess;
1780 
1781     return nLowerSpace;
1782 }
1783 
1784 /** calculation of the additional space to be considered, if flow frame
1785     is the last inside a table cell
1786 
1787     OD 2004-07-16 #i26250#
1788 
1789     @author OD
1790 */
CalcAddLowerSpaceAsLastInTableCell(const SwBorderAttrs * _pAttrs) const1791 SwTwips SwFlowFrm::CalcAddLowerSpaceAsLastInTableCell(
1792                                             const SwBorderAttrs* _pAttrs ) const
1793 {
1794     SwTwips nAdditionalLowerSpace = 0;
1795 
1796     if ( rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
1797     {
1798         const SwFrm* pFrm = &rThis;
1799         if ( pFrm->IsSctFrm() )
1800         {
1801             const SwSectionFrm* pSectFrm = static_cast<const SwSectionFrm*>(pFrm);
1802             pFrm = pSectFrm->FindLastCntnt();
1803             if ( pFrm && pFrm->IsInTab() )
1804             {
1805                 const SwTabFrm* pTableFrm = pFrm->FindTabFrm();
1806                 if ( pSectFrm->IsAnLower( pTableFrm ) )
1807                 {
1808                     pFrm = pTableFrm;
1809                 }
1810             }
1811         }
1812 
1813         SwBorderAttrAccess* pAttrAccess = 0L;
1814         if ( !_pAttrs || pFrm != &rThis )
1815         {
1816             pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), pFrm );
1817             _pAttrs = pAttrAccess->Get();
1818         }
1819 
1820         nAdditionalLowerSpace += _pAttrs->GetULSpace().GetLower();
1821 
1822         delete pAttrAccess;
1823     }
1824 
1825     return nAdditionalLowerSpace;
1826 }
1827 
1828 /*************************************************************************
1829 |*
1830 |*	sal_Bool SwFlowFrm::CheckMoveFwd()
1831 |*
1832 |*	Beschreibung		Moved den Frm vorwaerts wenn es durch die aktuellen
1833 |* 		Bedingungen und Attribute notwendig erscheint.
1834 |*	Ersterstellung		MA 05. Dec. 96
1835 |*	Letzte Aenderung	MA 09. Mar. 98
1836 |*
1837 |*************************************************************************/
1838 
1839 
CheckMoveFwd(sal_Bool & rbMakePage,sal_Bool bKeep,sal_Bool)1840 sal_Bool SwFlowFrm::CheckMoveFwd( sal_Bool &rbMakePage, sal_Bool bKeep, sal_Bool )
1841 {
1842 	const SwFrm* pNxt = rThis.GetIndNext();
1843 
1844 	if ( bKeep && //!bMovedBwd &&
1845 		 ( !pNxt || ( pNxt->IsTxtFrm() && ((SwTxtFrm*)pNxt)->IsEmptyMaster() ) ) &&
1846 		 ( 0 != (pNxt = rThis.FindNext()) ) && IsKeepFwdMoveAllowed() )
1847 	{
1848 		if( pNxt->IsSctFrm() )
1849 		{   // Nicht auf leere SectionFrms hereinfallen
1850 			const SwFrm* pTmp = NULL;
1851 			while( pNxt && pNxt->IsSctFrm() &&
1852 				   ( !((SwSectionFrm*)pNxt)->GetSection() ||
1853 					 0 == ( pTmp = ((SwSectionFrm*)pNxt)->ContainsAny() ) ) )
1854 			{
1855 				pNxt = pNxt->FindNext();
1856 				pTmp = NULL;
1857 			}
1858 			if( pTmp )
1859 				pNxt = pTmp; // the content of the next notempty sectionfrm
1860 		}
1861 		if( pNxt && pNxt->GetValidPosFlag() )
1862 		{
1863 			sal_Bool bMove = sal_False;
1864 			const SwSectionFrm *pSct = rThis.FindSctFrm();
1865 			if( pSct && !pSct->GetValidSizeFlag() )
1866 			{
1867 				const SwSectionFrm* pNxtSct = pNxt->FindSctFrm();
1868 				if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
1869 					bMove = sal_True;
1870 			}
1871 			else
1872 				bMove = sal_True;
1873 			if( bMove )
1874 			{
1875 				//Keep together with the following frame
1876 				MoveFwd( rbMakePage, sal_False );
1877 				return sal_True;
1878 			}
1879 		}
1880 	}
1881 
1882 	sal_Bool bMovedFwd = sal_False;
1883 
1884 	if ( rThis.GetIndPrev() )
1885 	{
1886 		if ( IsPrevObjMove() ) //Auf Objekte des Prev Ruecksicht nehmen?
1887 		{
1888 			bMovedFwd = sal_True;
1889 			if ( !MoveFwd( rbMakePage, sal_False ) )
1890 				rbMakePage = sal_False;
1891 		}
1892 		else
1893 		{
1894 			if ( IsPageBreak( sal_False ) )
1895 			{
1896 				while ( MoveFwd( rbMakePage, sal_True ) )
1897 						/* do nothing */;
1898 				rbMakePage = sal_False;
1899 				bMovedFwd = sal_True;
1900 			}
1901 			else if ( IsColBreak ( sal_False ) )
1902 			{
1903 				const SwPageFrm *pPage = rThis.FindPageFrm();
1904 				SwFrm *pCol = rThis.FindColFrm();
1905 				do
1906 				{	MoveFwd( rbMakePage, sal_False );
1907 					SwFrm *pTmp = rThis.FindColFrm();
1908 					if( pTmp != pCol )
1909 					{
1910 						bMovedFwd = sal_True;
1911 						pCol = pTmp;
1912 					}
1913 					else
1914 						break;
1915 				} while ( IsColBreak( sal_False ) );
1916 				if ( pPage != rThis.FindPageFrm() )
1917 					rbMakePage = sal_False;
1918 			}
1919 		}
1920 	}
1921 	return bMovedFwd;
1922 }
1923 
1924 /*************************************************************************
1925 |*
1926 |*	sal_Bool SwFlowFrm::MoveFwd()
1927 |*
1928 |*	Beschreibung		Returnwert sagt, ob der Frm die Seite gewechselt hat.
1929 |*	Ersterstellung		MA 05. Dec. 96
1930 |*	Letzte Aenderung	MA 05. Dec. 96
1931 |*
1932 |*************************************************************************/
1933 
1934 
MoveFwd(sal_Bool bMakePage,sal_Bool bPageBreak,sal_Bool bMoveAlways)1935 sal_Bool SwFlowFrm::MoveFwd( sal_Bool bMakePage, sal_Bool bPageBreak, sal_Bool bMoveAlways )
1936 {
1937 //!!!!MoveFtnCntFwd muss ggf. mitgepflegt werden.
1938 	SwFtnBossFrm *pOldBoss = rThis.FindFtnBossFrm();
1939 	if ( rThis.IsInFtn() )
1940 		return ((SwCntntFrm&)rThis).MoveFtnCntFwd( bMakePage, pOldBoss );
1941 
1942 	if( !IsFwdMoveAllowed() && !bMoveAlways )
1943 	{
1944 		sal_Bool bNoFwd = sal_True;
1945 		if( rThis.IsInSct() )
1946 		{
1947 			SwFtnBossFrm* pBoss = rThis.FindFtnBossFrm();
1948 			bNoFwd = !pBoss->IsInSct() || ( !pBoss->Lower()->GetNext() &&
1949 					 !pBoss->GetPrev() );
1950 		}
1951 
1952         // Allow the MoveFwd even if we do not have an IndPrev in these cases:
1953         if ( rThis.IsInTab() &&
1954             ( !rThis.IsTabFrm() ||
1955                 ( rThis.GetUpper()->IsInTab() &&
1956                   rThis.GetUpper()->FindTabFrm()->IsFwdMoveAllowed() ) ) &&
1957              0 != const_cast<SwFrm&>(rThis).GetNextCellLeaf( MAKEPAGE_NONE ) )
1958 /*
1959               &&
1960             // NEW TABLES
1961             // Have a look at our main competitor: We don't move inside row span cells:
1962             ( !rThis.GetUpper()->IsCellFrm() || !rThis.GetUpper()->IsLeaveUpperAllowed() ) )*/
1963         {
1964             bNoFwd = sal_False;
1965         }
1966 
1967         if( bNoFwd )
1968 		{
1969 			//Fuer PageBreak ist das Moven erlaubt, wenn der Frm nicht
1970 			//bereits der erste der Seite ist.
1971 			if ( !bPageBreak )
1972 				return sal_False;
1973 
1974 			const SwFrm *pCol = rThis.FindColFrm();
1975 			if ( !pCol || !pCol->GetPrev() )
1976 				return sal_False;
1977 		}
1978 	}
1979 
1980 	sal_Bool bSamePage = sal_True;
1981 	SwLayoutFrm *pNewUpper =
1982 			rThis.GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, sal_True );
1983 
1984 	if ( pNewUpper )
1985 	{
1986 		PROTOCOL_ENTER( &rThis, PROT_MOVE_FWD, 0, 0 );
1987 		SwPageFrm *pOldPage = pOldBoss->FindPageFrm();
1988 		//Wir moven uns und alle direkten Nachfolger vor den ersten
1989 		//CntntFrm unterhalb des neuen Uppers.
1990 
1991 		// Wenn unser NewUpper in einem SectionFrm liegt, muessen wir
1992 		// verhindern, dass sich dieser im Calc selbst zerstoert
1993 		SwSectionFrm* pSect = pNewUpper->FindSctFrm();
1994 		sal_Bool bUnlock = sal_False;
1995 		if( pSect )
1996 		{
1997 			// Wenn wir nur innerhalb unseres SectionFrms die Spalte wechseln,
1998 			// rufen wir lieber kein Calc, sonst wird noch der SectionFrm
1999 			// formatiert, der wiederum uns ruft etc.
2000 			if( pSect != rThis.FindSctFrm() )
2001 			{
2002 				bUnlock = !pSect->IsColLocked();
2003 				pSect->ColLock();
2004 				pNewUpper->Calc();
2005 				if( bUnlock )
2006 					pSect->ColUnlock();
2007 			}
2008 		}
2009         // Do not calculate split cell frames.
2010 		else if ( !pNewUpper->IsCellFrm() || ((SwLayoutFrm*)pNewUpper)->Lower() )
2011 			pNewUpper->Calc();
2012 
2013 		SwFtnBossFrm *pNewBoss = pNewUpper->FindFtnBossFrm();
2014 		sal_Bool bBossChg = pNewBoss != pOldBoss;
2015 		pNewBoss = pNewBoss->FindFtnBossFrm( sal_True );
2016 		pOldBoss = pOldBoss->FindFtnBossFrm( sal_True );
2017 		SwPageFrm* pNewPage = pOldPage;
2018 
2019 		// First, we move the footnotes.
2020 		sal_Bool bFtnMoved = sal_False;
2021 
2022         // --> FME 2004-07-15 #i26831#
2023         // If pSect has just been created, the printing area of pSect has
2024         // been calculated based on the first content of its follow.
2025         // In this case we prefer to call a SimpleFormat for this new
2026         // section after we inserted the contents. Otherwise the section
2027         // frame will invalidate its lowers, if its printing area changes
2028         // in SwSectionFrm::Format, which can cause loops.
2029         const bool bForceSimpleFormat = pSect && pSect->HasFollow() &&
2030                                        !pSect->ContainsAny();
2031         // <--
2032 
2033         if ( pNewBoss != pOldBoss )
2034 		{
2035 			pNewPage = pNewBoss->FindPageFrm();
2036 			bSamePage = pNewPage == pOldPage;
2037 			//Damit die Fussnoten nicht auf dumme Gedanken kommen
2038 			//setzen wir hier die Deadline.
2039             SWRECTFN( pOldBoss )
2040 			SwSaveFtnHeight aHeight( pOldBoss,
2041                 (pOldBoss->Frm().*fnRect->fnGetBottom)() );
2042 			SwCntntFrm* pStart = rThis.IsCntntFrm() ?
2043 				(SwCntntFrm*)&rThis : ((SwLayoutFrm&)rThis).ContainsCntnt();
2044 			ASSERT( pStart || ( rThis.IsTabFrm() && !((SwTabFrm&)rThis).Lower() ),
2045                     "MoveFwd: Missing Content" );
2046 			SwLayoutFrm* pBody = pStart ? ( pStart->IsTxtFrm() ?
2047 				(SwLayoutFrm*)((SwTxtFrm*)pStart)->FindBodyFrm() : 0 ) : 0;
2048 			if( pBody )
2049 				bFtnMoved = pBody->MoveLowerFtns( pStart, pOldBoss, pNewBoss,
2050 												  sal_False);
2051 		}
2052 		// Bei SectionFrms ist es moeglich, dass wir selbst durch pNewUpper->Calc()
2053 		// bewegt wurden, z. B. in den pNewUpper.
2054 		// MoveSubTree bzw. PasteTree ist auf so etwas nicht vorbereitet.
2055 		if( pNewUpper != rThis.GetUpper() )
2056 		{
2057             // --> FME 2004-04-19 #i27145#
2058             SwSectionFrm* pOldSct = 0;
2059             if ( rThis.GetUpper()->IsSctFrm() )
2060             {
2061                 pOldSct = static_cast<SwSectionFrm*>(rThis.GetUpper());
2062             }
2063             // <--
2064 
2065             MoveSubTree( pNewUpper, pNewUpper->Lower() );
2066 
2067             // --> FME 2004-04-19 #i27145#
2068             if ( pOldSct && pOldSct->GetSection() )
2069             {
2070                 // Prevent loops by setting the new height at
2071                 // the section frame if footnotes have been moved.
2072                 // Otherwise the call of SwLayNotify::~SwLayNotify() for
2073                 // the (invalid) section frame will invalidate the first
2074                 // lower of its follow, because it grows due to the removed
2075                 // footnotes.
2076                 // Note: If pOldSct has become empty during MoveSubTree, it
2077                 // has already been scheduled for removal. No SimpleFormat
2078                 // for these.
2079                 pOldSct->SimpleFormat();
2080             }
2081             // <--
2082 
2083             // --> FME 2004-07-15 #i26831#
2084             if ( bForceSimpleFormat )
2085             {
2086                 pSect->SimpleFormat();
2087             }
2088             // <--
2089 
2090             if ( bFtnMoved && !bSamePage )
2091 			{
2092 				pOldPage->UpdateFtnNum();
2093 				pNewPage->UpdateFtnNum();
2094 			}
2095 
2096 			if( bBossChg )
2097 			{
2098 				rThis.Prepare( PREP_BOSS_CHGD, 0, sal_False );
2099 				if( !bSamePage )
2100 				{
2101 					ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
2102 					if ( pSh && !pSh->Imp()->IsUpdateExpFlds() )
2103                         pSh->GetDoc()->SetNewFldLst(true);  //Wird von CalcLayout() hinterher erledigt!
2104 
2105                     pNewPage->InvalidateSpelling();
2106                     pNewPage->InvalidateSmartTags();    // SMARTTAGS
2107                     pNewPage->InvalidateAutoCompleteWords();
2108                     pNewPage->InvalidateWordCount();
2109 				}
2110 			}
2111 		}
2112         // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout
2113         const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
2114 
2115         if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) )
2116         {
2117             // --> OD 2009-12-31 #i106452#
2118             // check page description not only in situation with sections.
2119             if ( !bSamePage &&
2120                  ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() ||
2121                    pOldPage->GetPageDesc()->GetFollow() != pNewPage->GetPageDesc() ) )
2122             {
2123                 SwFrm::CheckPageDescs( pNewPage, sal_False );
2124             }
2125             // <--
2126         }
2127 	}
2128 	return bSamePage;
2129 }
2130 
2131 
2132 /*************************************************************************
2133 |*
2134 |*	sal_Bool SwFlowFrm::MoveBwd()
2135 |*
2136 |*	Beschreibung		Returnwert sagt, ob der Frm die Seite wechseln soll.
2137 |*						Sollte von abgeleiteten Klassen gerufen werden.
2138 |* 						Das moven selbst muessen die abgeleiteten uebernehmen.
2139 |*	Ersterstellung		MA 05. Dec. 96
2140 |*	Letzte Aenderung	MA 05. Dec. 96
2141 |*
2142 |*************************************************************************/
2143 
MoveBwd(sal_Bool & rbReformat)2144 sal_Bool SwFlowFrm::MoveBwd( sal_Bool &rbReformat )
2145 {
2146 	SwFlowFrm::SetMoveBwdJump( sal_False );
2147 
2148 	SwFtnFrm* pFtn = rThis.FindFtnFrm();
2149 	if ( pFtn && pFtn->IsBackMoveLocked() )
2150 		return sal_False;
2151 
2152     // --> OD 2004-11-29 #115759# - text frames, which are directly inside
2153     // tables aren't allowed to move backward.
2154     if ( rThis.IsTxtFrm() && rThis.IsInTab() )
2155     {
2156         const SwLayoutFrm* pUpperFrm = rThis.GetUpper();
2157         while ( pUpperFrm )
2158         {
2159             if ( pUpperFrm->IsTabFrm() )
2160             {
2161                 return sal_False;
2162             }
2163             else if ( pUpperFrm->IsColumnFrm() && pUpperFrm->IsInSct() )
2164             {
2165                 break;
2166             }
2167             pUpperFrm = pUpperFrm->GetUpper();
2168         }
2169     }
2170     // <--
2171 
2172 	SwFtnBossFrm * pOldBoss = rThis.FindFtnBossFrm();
2173 	SwPageFrm * const pOldPage = pOldBoss->FindPageFrm();
2174 	SwLayoutFrm *pNewUpper = 0;
2175 	sal_Bool bCheckPageDescs = sal_False;
2176     bool bCheckPageDescOfNextPage = false;
2177 
2178 	if ( pFtn )
2179 	{
2180         //Wenn die Fussnote bereits auf der gleichen Seite/Spalte wie die Referenz
2181         //steht, ist nix mit zurueckfliessen. Die breaks brauche fuer die
2182         //Fussnoten nicht geprueft zu werden.
2183 
2184         // --> FME 2004-11-15 #i37084# FindLastCntnt does not necessarily
2185         // have to have a result != 0
2186         SwFrm* pRef = 0;
2187         const bool bEndnote = pFtn->GetAttr()->GetFtn().IsEndNote();
2188         if( bEndnote && pFtn->IsInSct() )
2189         {
2190             SwSectionFrm* pSect = pFtn->FindSctFrm();
2191             if( pSect->IsEndnAtEnd() )
2192                 pRef = pSect->FindLastCntnt( FINDMODE_LASTCNT );
2193         }
2194         if( !pRef )
2195             pRef = pFtn->GetRef();
2196         // <--
2197 
2198         ASSERT( pRef, "MoveBwd: Endnote for an empty section?" );
2199 
2200         if( !bEndnote )
2201 			pOldBoss = pOldBoss->FindFtnBossFrm( sal_True );
2202 		SwFtnBossFrm *pRefBoss = pRef->FindFtnBossFrm( !bEndnote );
2203         if ( pOldBoss != pRefBoss &&
2204              // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
2205              ( !bEndnote ||
2206                pRefBoss->IsBefore( pOldBoss ) )
2207            )
2208 			pNewUpper = rThis.GetLeaf( MAKEPAGE_FTN, sal_False );
2209 	}
2210 	else if ( IsPageBreak( sal_True ) )	//PageBreak zu beachten?
2211 	{
2212 		//Wenn auf der vorhergehenden Seite kein Frm im Body steht,
2213 		//so ist das Zurueckfliessen trotz Pagebreak sinnvoll
2214 		//(sonst: leere Seite).
2215 		//Natuerlich muessen Leereseiten geflissentlich uebersehen werden!
2216 		const SwFrm *pFlow = &rThis;
2217 		do
2218         {
2219             pFlow = pFlow->FindPrev();
2220         } while ( pFlow &&
2221                   ( pFlow->FindPageFrm() == pOldPage ||
2222                     !pFlow->IsInDocBody() ) );
2223 		if ( pFlow )
2224 		{
2225 			long nDiff = pOldPage->GetPhyPageNum() - pFlow->GetPhyPageNum();
2226 			if ( nDiff > 1 )
2227 			{
2228 				if ( ((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage() )
2229 					nDiff -= 1;
2230 				if ( nDiff > 1 )
2231 				{
2232 					pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2233                     // --> OD 2006-05-08 #i53139#
2234                     // Now <pNewUpper> is a previous layout frame, which contains
2235                     // content. But the new upper layout frame has to be the next one.
2236                     // Thus, hack for issue i14206 no longer needed, but fix for issue 114442
2237                     // --> OD 2006-05-17 #136024# - correct fix for i53139:
2238                     // Check for wrong page description before using next new upper.
2239                     // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
2240                     // Check for correct type of new next upper layout frame
2241                     // --> OD 2006-06-08 #136538# - another correction of fix for i53139
2242                     // Assumption, that in all cases <pNewUpper> is a previous
2243                     // layout frame, which contains content, is wrong.
2244                     // --> OD 2006-07-05 #136538# - another correction of fix for i53139
2245                     // Beside type check, check also, if proposed new next upper
2246                     // frame is inside the same frame types.
2247                     // --> OD 2007-01-10 #i73194# - and yet another correction
2248                     // of fix for i53139:
2249                     // Assure that the new next upper layout frame doesn't
2250                     // equal the current one.
2251                     // E.g.: content is on page 3, on page 2 is only a 'ghost'
2252                     // section and on page 1 is normal content. Method <FindPrev(..)>
2253                     // will find the last content of page 1, but <GetLeaf(..)>
2254                     // returns new upper on page 2.
2255                     if ( pNewUpper->Lower() )
2256                     {
2257                         SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, sal_True );
2258                         if ( pNewNextUpper &&
2259                              pNewNextUpper != rThis.GetUpper() &&
2260                              pNewNextUpper->GetType() == pNewUpper->GetType() &&
2261                              pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2262                              pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2263                              pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2264                              pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2265                              !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2266                         {
2267                             pNewUpper = pNewNextUpper;
2268                             bCheckPageDescOfNextPage = true;
2269                         }
2270                     }
2271                     // <--
2272 
2273                     bCheckPageDescs = sal_True;
2274 				}
2275 			}
2276 		}
2277 	}
2278 	else if ( IsColBreak( sal_True ) )
2279 	{
2280 		//Wenn in der vorhergehenden Spalte kein CntntFrm steht, so ist
2281 		//das Zurueckfliessen trotz ColumnBreak sinnvoll
2282 		//(sonst: leere Spalte).
2283 		if( rThis.IsInSct() )
2284 		{
2285 			pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2286 			if( pNewUpper && !SwFlowFrm::IsMoveBwdJump() &&
2287 				( pNewUpper->ContainsCntnt() ||
2288 				  ( ( !pNewUpper->IsColBodyFrm() ||
2289 					  !pNewUpper->GetUpper()->GetPrev() ) &&
2290 					!pNewUpper->FindSctFrm()->GetPrev() ) ) )
2291             {
2292 				pNewUpper = 0;
2293             }
2294             // --> OD 2006-05-08 #i53139#
2295             // --> OD 2006-09-11 #i69409# - check <pNewUpper>
2296             // --> OD 2006-11-02 #i71065# - check <SwFlowFrm::IsMoveBwdJump()>
2297             else if ( pNewUpper && !SwFlowFrm::IsMoveBwdJump() )
2298             // <--
2299             {
2300                 // Now <pNewUpper> is a previous layout frame, which
2301                 // contains content. But the new upper layout frame
2302                 // has to be the next one.
2303                 // --> OD 2006-05-17 #136024# - correct fix for i53139
2304                 // Check for wrong page description before using next new upper.
2305                 // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
2306                 // Check for correct type of new next upper layout frame
2307                 // --> OD 2006-07-05 #136538# - another correction of fix for i53139
2308                 // Beside type check, check also, if proposed new next upper
2309                 // frame is inside the same frame types.
2310                 SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NOSECTION, sal_True );
2311                 if ( pNewNextUpper &&
2312                      pNewNextUpper->GetType() == pNewUpper->GetType() &&
2313                      pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2314                      pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2315                      pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2316                      pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2317                      !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2318                 {
2319                     pNewUpper = pNewNextUpper;
2320                 }
2321             }
2322             // <--
2323 		}
2324 		else
2325 		{
2326 			const SwFrm *pCol = rThis.FindColFrm();
2327 			sal_Bool bGoOn = sal_True;
2328 			sal_Bool bJump = sal_False;
2329 			do
2330 			{
2331 				if ( pCol->GetPrev() )
2332 					pCol = pCol->GetPrev();
2333 				else
2334 				{
2335 					bGoOn = sal_False;
2336 					pCol = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2337 				}
2338 				if ( pCol )
2339 				{
2340 					// ColumnFrms jetzt mit BodyFrm
2341 					SwLayoutFrm* pColBody = pCol->IsColumnFrm() ?
2342 						(SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower() :
2343 						(SwLayoutFrm*)pCol;
2344 					if ( pColBody->ContainsCntnt() )
2345 					{
2346 						bGoOn = sal_False; // Hier gibt's Inhalt, wir akzeptieren diese
2347 						// nur, wenn GetLeaf() das MoveBwdJump-Flag gesetzt hat.
2348 						if( SwFlowFrm::IsMoveBwdJump() )
2349                         {
2350 							pNewUpper = pColBody;
2351                             // --> OD 2006-05-08 #i53139#
2352                             // Now <pNewUpper> is a previous layout frame, which
2353                             // contains content. But the new upper layout frame
2354                             // has to be the next one.
2355                             // --> OD 2006-05-17 #136024# - correct fix for i53139
2356                             // Check for wrong page description before using next new upper.
2357                             // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
2358                             // Check for correct type of new next upper layout frame
2359                             // --> OD 2006-07-05 #136538# - another correction of fix for i53139
2360                             // Beside type check, check also, if proposed new next upper
2361                             // frame is inside the same frame types.
2362                             // --> OD 2006-11-02 #i71065#
2363                             // Check that the proposed new next upper layout
2364                             // frame isn't the current one.
2365                             SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, sal_True );
2366                             if ( pNewNextUpper &&
2367                                  pNewNextUpper != rThis.GetUpper() &&
2368                                  pNewNextUpper->GetType() == pNewUpper->GetType() &&
2369                                  pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2370                                  pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2371                                  pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2372                                  pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2373                                  !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2374                             {
2375                                 pNewUpper = pNewNextUpper;
2376                             }
2377                             // <--
2378                         }
2379 					}
2380 					else
2381 					{
2382 						if( pNewUpper ) // Wir hatten schon eine leere Spalte, haben
2383 							bJump = sal_True;   // also eine uebersprungen
2384 						pNewUpper = pColBody;  // Diese leere Spalte kommt in Frage,
2385 										   	// trotzdem weitersuchen
2386 					}
2387 				}
2388 			} while( bGoOn );
2389 			if( bJump )
2390 				SwFlowFrm::SetMoveBwdJump( sal_True );
2391 		}
2392 	}
2393 	else //Keine Breaks also kann ich zurueckfliessen
2394 		pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2395 
2396     // --> OD 2004-06-23 #i27801# - no move backward of 'master' text frame,
2397     // if - due to its object positioning - it isn't allowed to be on the new page frame
2398     // --> OD 2005-03-07 #i44049# - add another condition for not moving backward:
2399     // If one of its objects has restarted the layout process, moving backward
2400     // isn't sensible either.
2401     // --> OD 2005-04-19 #i47697# - refine condition made for issue i44049:
2402     // - allow move backward as long as the anchored object is only temporarily
2403     //   positions considering its wrapping style.
2404     if ( pNewUpper &&
2405          rThis.IsTxtFrm() && !IsFollow() )
2406     {
2407         sal_uInt32 nToPageNum( 0L );
2408         const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos(
2409                                                 *(pOldPage->GetFmt()->GetDoc()),
2410                                                 static_cast<SwTxtFrm&>(rThis),
2411                                                 nToPageNum );
2412         if ( bMoveFwdByObjPos &&
2413              pNewUpper->FindPageFrm()->GetPhyPageNum() < nToPageNum )
2414         {
2415             pNewUpper = 0;
2416         }
2417         // --> OD 2005-03-07 #i44049# - check, if one of its anchored objects
2418         // has restarted the layout process.
2419         else if ( rThis.GetDrawObjs() )
2420         {
2421             sal_uInt32 i = 0;
2422             for ( ; i < rThis.GetDrawObjs()->Count(); ++i )
2423             {
2424                 SwAnchoredObject* pAnchoredObj = (*rThis.GetDrawObjs())[i];
2425                 // --> OD 2005-04-19 #i47697# - refine condition - see above
2426                 if ( pAnchoredObj->RestartLayoutProcess() &&
2427                      !pAnchoredObj->IsTmpConsiderWrapInfluence() )
2428                 // <--
2429                 {
2430                     pNewUpper = 0;
2431                     break;
2432                 }
2433             }
2434         }
2435         // <--
2436     }
2437     // <--
2438 
2439     //Fuer Follows ist das zurueckfliessen nur dann erlaubt wenn in der
2440 	//neuen Umgebung kein Nachbar existiert (denn dieses waere der Master).
2441 	//(6677)Wenn allerdings leere Blaetter uebersprungen wurden wird doch gemoved.
2442 	if ( pNewUpper && IsFollow() && pNewUpper->Lower() )
2443 	{
2444         // --> OD 2007-09-05 #i79774#, #b6596954#
2445         // neglect empty sections in proposed new upper frame
2446         bool bProposedNewUpperContainsOnlyEmptySections( true );
2447         {
2448             const SwFrm* pLower( pNewUpper->Lower() );
2449             while ( pLower )
2450             {
2451                 if ( pLower->IsSctFrm() &&
2452                      !dynamic_cast<const SwSectionFrm*>(pLower)->GetSection() )
2453                 {
2454                     pLower = pLower->GetNext();
2455                     continue;
2456                 }
2457                 else
2458                 {
2459                     bProposedNewUpperContainsOnlyEmptySections = false;
2460                     break;
2461                 }
2462             }
2463         }
2464         if ( !bProposedNewUpperContainsOnlyEmptySections )
2465         {
2466             if ( SwFlowFrm::IsMoveBwdJump() )
2467             {
2468                 //Nicht hinter den Master sondern in das naechstfolgende leere
2469                 //Blatt moven.
2470                 SwFrm *pFrm = pNewUpper->Lower();
2471                 while ( pFrm->GetNext() )
2472                     pFrm = pFrm->GetNext();
2473                 pNewUpper = pFrm->GetLeaf( MAKEPAGE_INSERT, sal_True );
2474                 if( pNewUpper == rThis.GetUpper() ) //Landen wir wieder an der gleichen Stelle?
2475                     pNewUpper = NULL;           //dann eruebrigt sich das Moven
2476             }
2477             else
2478                 pNewUpper = 0;
2479         }
2480         // <--
2481 	}
2482 	if ( pNewUpper && !ShouldBwdMoved( pNewUpper, sal_True, rbReformat ) )
2483 	{
2484 		if( !pNewUpper->Lower() )
2485 		{
2486 			if( pNewUpper->IsFtnContFrm() )
2487 			{
2488 				pNewUpper->Cut();
2489 				delete pNewUpper;
2490 			}
2491 			else
2492 			{
2493 				SwSectionFrm* pSectFrm = pNewUpper->FindSctFrm();
2494                 // --> OD 2006-01-04 #126020# - adjust check for empty section
2495                 // --> OD 2006-02-01 #130797# - correct fix #126020#
2496                 if ( pSectFrm && !pSectFrm->IsColLocked() &&
2497                      !pSectFrm->ContainsCntnt() && !pSectFrm->ContainsAny( true ) )
2498                 // <--
2499 				{
2500 					pSectFrm->DelEmpty( sal_True );
2501 					delete pSectFrm;
2502 					rThis.bValidPos = sal_True;
2503 				}
2504 			}
2505 		}
2506 		pNewUpper = 0;
2507 	}
2508 
2509     // OD 2004-05-26 #i21478# - don't move backward, if flow frame wants to
2510     // keep with next frame and next frame is locked.
2511     // --> OD 2004-12-08 #i38232# - If next frame is a table, do *not* check,
2512     // if it's locked.
2513     if ( pNewUpper && !IsFollow() &&
2514          rThis.GetAttrSet()->GetKeep().GetValue() && rThis.GetIndNext() )
2515     {
2516         SwFrm* pIndNext = rThis.GetIndNext();
2517         // --> OD 2004-12-08 #i38232#
2518         if ( !pIndNext->IsTabFrm() )
2519         {
2520             // get first content of section, while empty sections are skipped
2521             while ( pIndNext && pIndNext->IsSctFrm() )
2522             {
2523                 if( static_cast<SwSectionFrm*>(pIndNext)->GetSection() )
2524                 {
2525                     SwFrm* pTmp = static_cast<SwSectionFrm*>(pIndNext)->ContainsAny();
2526                     if ( pTmp )
2527                     {
2528                         pIndNext = pTmp;
2529                         break;
2530                     }
2531                 }
2532                 pIndNext = pIndNext->GetIndNext();
2533             }
2534             ASSERT( !pIndNext || pIndNext->ISA(SwTxtFrm),
2535                     "<SwFlowFrm::MovedBwd(..)> - incorrect next found." );
2536             if ( pIndNext && pIndNext->IsFlowFrm() &&
2537                  SwFlowFrm::CastFlowFrm(pIndNext)->IsJoinLocked() )
2538             {
2539                 pNewUpper = 0L;
2540             }
2541         }
2542         // <--
2543     }
2544 
2545     // --> OD 2006-05-10 #i65250#
2546     // layout loop control for flowing content again and again moving
2547     // backward under the same layout condition.
2548     if ( pNewUpper && !IsFollow() &&
2549          pNewUpper != rThis.GetUpper() &&
2550          SwLayouter::MoveBwdSuppressed( *(pOldPage->GetFmt()->GetDoc()),
2551                                         *this, *pNewUpper ) )
2552     {
2553         SwLayoutFrm* pNextNewUpper = pNewUpper->GetLeaf(
2554                                     ( !rThis.IsSctFrm() && rThis.IsInSct() )
2555                                     ? MAKEPAGE_NOSECTION
2556                                     : MAKEPAGE_NONE,
2557                                     sal_True );
2558         // --> OD 2007-01-10 #i73194# - make code robust
2559         ASSERT( pNextNewUpper, "<SwFlowFrm::MoveBwd(..)> - missing next new upper" );
2560         if ( pNextNewUpper &&
2561              ( pNextNewUpper == rThis.GetUpper() ||
2562                pNextNewUpper->GetType() != rThis.GetUpper()->GetType() ) )
2563         // <--
2564         {
2565             pNewUpper = 0L;
2566 #if OSL_DEBUG_LEVEL > 1
2567             ASSERT( false,
2568                     "<SwFlowFrm::MoveBwd(..)> - layout loop control for layout action <Move Backward> applied!" );
2569 #endif
2570         }
2571     }
2572     // <--
2573 
2574     ASSERT( pNewUpper != rThis.GetUpper(),
2575             "<SwFlowFrm::MoveBwd(..)> - moving backward to the current upper frame!? -> Please inform OD." );
2576 	if ( pNewUpper )
2577 	{
2578 		PROTOCOL_ENTER( &rThis, PROT_MOVE_BWD, 0, 0 );
2579 		if ( pNewUpper->IsFtnContFrm() )
2580 		{
2581 			//Kann sein, dass ich einen Container bekam.
2582 			SwFtnFrm *pOld = rThis.FindFtnFrm();
2583 			SwFtnFrm *pNew = new SwFtnFrm( pOld->GetFmt(), pOld,
2584 										   pOld->GetRef(), pOld->GetAttr() );
2585 			if ( pOld->GetMaster() )
2586 			{
2587 				pNew->SetMaster( pOld->GetMaster() );
2588 				pOld->GetMaster()->SetFollow( pNew );
2589 			}
2590 			pNew->SetFollow( pOld );
2591 			pOld->SetMaster( pNew );
2592 			pNew->Paste( pNewUpper );
2593 			pNewUpper = pNew;
2594 		}
2595 		if( pNewUpper->IsFtnFrm() && rThis.IsInSct() )
2596 		{
2597 			SwSectionFrm* pSct = rThis.FindSctFrm();
2598 			//Wenn wir in einem Bereich in einer Fussnote stecken, muss im
2599 			//neuen Upper ggf. ein SwSectionFrm angelegt werden
2600 			if( pSct->IsInFtn() )
2601 			{
2602 				SwFrm* pTmp = pNewUpper->Lower();
2603 				if( pTmp )
2604 				{
2605 					while( pTmp->GetNext() )
2606 						pTmp = pTmp->GetNext();
2607 					if( !pTmp->IsSctFrm() ||
2608 						((SwSectionFrm*)pTmp)->GetFollow() != pSct )
2609 						pTmp = NULL;
2610 				}
2611 				if( pTmp )
2612 					pNewUpper = (SwSectionFrm*)pTmp;
2613 				else
2614 				{
2615                     pSct = new SwSectionFrm( *pSct, sal_True );
2616 					pSct->Paste( pNewUpper );
2617                     pSct->Init();
2618 					pNewUpper = pSct;
2619 					pSct->SimpleFormat();
2620 				}
2621 			}
2622 		}
2623 		sal_Bool bUnlock = sal_False;
2624         sal_Bool bFollow = sal_False;
2625 		//Section locken, sonst kann sie bei Fluss des einzigen Cntnt etwa
2626 		//von zweiter in die erste Spalte zerstoert werden.
2627 		SwSectionFrm* pSect = pNewUpper->FindSctFrm();
2628 		if( pSect )
2629 		{
2630 			bUnlock = !pSect->IsColLocked();
2631 			pSect->ColLock();
2632 			bFollow = pSect->HasFollow();
2633 		}
2634 		pNewUpper->Calc();
2635 		rThis.Cut();
2636         // --> OD 2005-02-23 #b6229852#
2637         // optimization: format section, if its size is invalidated and if it's
2638         // the new parent of moved backward frame.
2639         bool bFormatSect( false );
2640         // <--
2641         if( bUnlock )
2642 		{
2643             pSect->ColUnlock();
2644             if( pSect->HasFollow() != bFollow )
2645             {
2646 				pSect->InvalidateSize();
2647                 // --> OD 2005-02-23 #b6229852# - optimization
2648                 if ( pSect == pNewUpper )
2649                     bFormatSect = true;
2650                 // <--
2651             }
2652 		}
2653 
2654 		rThis.Paste( pNewUpper );
2655         // --> OD 2005-02-23 #b6229852# - optimization
2656         if ( bFormatSect )
2657             pSect->Calc();
2658         // <--
2659 
2660         SwPageFrm *pNewPage = rThis.FindPageFrm();
2661 		if( pNewPage != pOldPage )
2662 		{
2663 			rThis.Prepare( PREP_BOSS_CHGD, (const void*)pOldPage, sal_False );
2664 			ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
2665 			if ( pSh && !pSh->Imp()->IsUpdateExpFlds() )
2666                 pSh->GetDoc()->SetNewFldLst(true);  //Wird von CalcLayout() hinterher eledigt!
2667 
2668             pNewPage->InvalidateSpelling();
2669             pNewPage->InvalidateSmartTags();    // SMARTTAGS
2670 			pNewPage->InvalidateAutoCompleteWords();
2671             pNewPage->InvalidateWordCount();
2672 
2673             // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout
2674             if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) )
2675             {
2676                 if ( bCheckPageDescs && pNewPage->GetNext() )
2677                 {
2678                     SwPageFrm* pStartPage = bCheckPageDescOfNextPage ?
2679                                             pNewPage :
2680                                             (SwPageFrm*)pNewPage->GetNext();
2681                     SwFrm::CheckPageDescs( pStartPage, sal_False);
2682                 }
2683                 else if ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() )
2684                 {
2685                     //Erste Seite wird etwa durch Ausblenden eines Bereiches leer
2686                     SwFrm::CheckPageDescs( (SwPageFrm*)pNewPage, sal_False);
2687                 }
2688             }
2689 		}
2690 	}
2691 	return pNewUpper != 0;
2692 }
2693 
2694 /*************************************************************************
2695 |*
2696 |*	SwFlowFrm::CastFlowFrm
2697 |*
2698 |*	Ersterstellung		MA 03. May. 95
2699 |*	Letzte Aenderung	AMA 02. Dec. 97
2700 |*
2701 |*************************************************************************/
2702 
CastFlowFrm(SwFrm * pFrm)2703 SwFlowFrm *SwFlowFrm::CastFlowFrm( SwFrm *pFrm )
2704 {
2705 	if ( pFrm->IsCntntFrm() )
2706 		return (SwCntntFrm*)pFrm;
2707 	if ( pFrm->IsTabFrm() )
2708 		return (SwTabFrm*)pFrm;
2709 	if ( pFrm->IsSctFrm() )
2710 		return (SwSectionFrm*)pFrm;
2711 	return 0;
2712 }
2713 
CastFlowFrm(const SwFrm * pFrm)2714 const SwFlowFrm *SwFlowFrm::CastFlowFrm( const SwFrm *pFrm )
2715 {
2716 	if ( pFrm->IsCntntFrm() )
2717 		return (SwCntntFrm*)pFrm;
2718 	if ( pFrm->IsTabFrm() )
2719 		return (SwTabFrm*)pFrm;
2720 	if ( pFrm->IsSctFrm() )
2721 		return (SwSectionFrm*)pFrm;
2722 	return 0;
2723 }
2724