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