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