xref: /AOO41X/main/sw/source/core/layout/sectfrm.cxx (revision 79aad27f7f29270c03e208e3d687e8e3850af11d)
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 
27 #include <svl/smplhint.hxx>
28 #include <svl/itemiter.hxx>
29 #include <hints.hxx>
30 #include <txtftn.hxx>
31 #include <fmtftn.hxx>
32 #include <fmtclbl.hxx>
33 #include "sectfrm.hxx"
34 #include "section.hxx"      // SwSection
35 #include "frmtool.hxx"      // StackHack
36 #include "doc.hxx"          // SwDoc
37 #include "cntfrm.hxx"       // SwCntntFrm
38 #include "rootfrm.hxx"      // SwRootFrm
39 #include "pagefrm.hxx"      // SwPageFrm
40 #include "fmtpdsc.hxx"      // SwFmtPageDesc
41 #include "fmtcntnt.hxx"     // SwFmtCntnt
42 #include "ndindex.hxx"      // SwNodeIndex
43 #include "ftnidx.hxx"
44 #include "txtfrm.hxx"       // SwTxtFrm
45 #include "fmtclds.hxx"      // SwFmtCol
46 #include "colfrm.hxx"       // SwColumnFrm
47 #include "tabfrm.hxx"       // SwTabFrm
48 #include "flyfrm.hxx"       // SwFlyFrm
49 #include "ftnfrm.hxx"       // SwFtnFrm
50 #include "layouter.hxx"     // SwLayouter
51 #include "dbg_lay.hxx"
52 #include "viewsh.hxx"
53 #include "viewopt.hxx"
54 #include "viewimp.hxx"
55 #include <editeng/ulspitem.hxx>
56 #include <editeng/lrspitem.hxx>
57 #include <editeng/brshitem.hxx>
58 #include <fmtftntx.hxx>
59 // OD 2004-05-24 #i28701#
60 #include <dflyobj.hxx>
61 #include <flyfrms.hxx>
62 #include <sortedobjs.hxx>
63 
SV_IMPL_PTRARR_SORT(SwDestroyList,SwSectionFrmPtr)64 SV_IMPL_PTRARR_SORT( SwDestroyList, SwSectionFrmPtr )
65 
66 /*************************************************************************
67 |*
68 |*  SwSectionFrm::SwSectionFrm(), ~SwSectionFrm()
69 |*
70 |*  Ersterstellung      AMA 26. Nov. 97
71 |*  Letzte Aenderung    AMA 26. Nov. 97
72 |*
73 |*************************************************************************/
74 SwSectionFrm::SwSectionFrm( SwSection &rSect, SwFrm* pSib ) :
75     SwLayoutFrm( rSect.GetFmt(), pSib ),
76     SwFlowFrm( (SwFrm&)*this ),
77     pSection( &rSect )
78 {
79     nType = FRMC_SECTION;
80 
81     CalcFtnAtEndFlag();
82     CalcEndAtEndFlag();
83 }
84 
SwSectionFrm(SwSectionFrm & rSect,sal_Bool bMaster)85 SwSectionFrm::SwSectionFrm( SwSectionFrm &rSect, sal_Bool bMaster ) :
86     SwLayoutFrm( rSect.GetFmt(), rSect.getRootFrm() ),
87     SwFlowFrm( (SwFrm&)*this ),
88     pSection( rSect.GetSection() )
89 {
90     bFtnAtEnd = rSect.IsFtnAtEnd();
91     bEndnAtEnd = rSect.IsEndnAtEnd();
92     bLockJoin = sal_False;
93     nType = FRMC_SECTION;
94 
95     PROTOCOL( this, PROT_SECTION, bMaster ? ACT_CREATE_MASTER : ACT_CREATE_FOLLOW, &rSect )
96 
97     if( bMaster )
98     {
99         if( rSect.IsFollow() )
100         {
101             SwSectionFrm* pMaster = rSect.FindMaster();
102             pMaster->SetFollow( this );
103             bIsFollow = sal_True;
104         }
105         else
106             rSect.bIsFollow = sal_True;
107         SetFollow( &rSect );
108     }
109     else
110     {
111         bIsFollow = sal_True;
112         SetFollow( rSect.GetFollow() );
113         rSect.SetFollow( this );
114         if( !GetFollow() )
115             rSect.SimpleFormat();
116         if( !rSect.IsColLocked() )
117             rSect.InvalidateSize();
118     }
119 }
120 
121 // NOTE: call <SwSectionFrm::Init()> directly after creation of a new section
122 //       frame and its insert in the layout.
Init()123 void SwSectionFrm::Init()
124 {
125     ASSERT( GetUpper(), "SwSectionFrm::Init before insertion?!" );
126     SWRECTFN( this )
127     long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
128     (Frm().*fnRect->fnSetWidth)( nWidth );
129     (Frm().*fnRect->fnSetHeight)( 0 );
130 
131     // #109700# LRSpace for sections
132     const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
133     (Prt().*fnRect->fnSetLeft)( rLRSpace.GetLeft() );
134     (Prt().*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
135                                  rLRSpace.GetRight() );
136     (Prt().*fnRect->fnSetHeight)( 0 );
137 
138     const SwFmtCol &rCol = GetFmt()->GetCol();
139     if( ( rCol.GetNumCols() > 1 || IsAnyNoteAtEnd() ) && !IsInFtn() )
140     {
141         const SwFmtCol *pOld = Lower() ? &rCol : new SwFmtCol;
142         ChgColumns( *pOld, rCol, IsAnyNoteAtEnd() );
143         if( pOld != &rCol )
144             delete pOld;
145     }
146 }
147 
~SwSectionFrm()148 SwSectionFrm::~SwSectionFrm()
149 {
150     if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
151     {
152         SwRootFrm *pRootFrm = getRootFrm();
153         if( pRootFrm )
154             pRootFrm->RemoveFromList( this );   //swmod 071108//swmod 071225
155         if( IsFollow() )
156         {
157             SwSectionFrm *pMaster = FindMaster();
158             if( pMaster )
159             {
160                 PROTOCOL( this, PROT_SECTION, ACT_DEL_FOLLOW, pMaster )
161                 pMaster->SetFollow( GetFollow() );
162                 // Ein Master greift sich immer den Platz bis zur Unterkante seines
163                 // Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder
164                 // freigeben, deshalb wird die Size des Masters invalidiert.
165                 if( !GetFollow() )
166                     pMaster->InvalidateSize();
167             }
168         }
169         else if( HasFollow() )
170         {
171             PROTOCOL( this, PROT_SECTION, ACT_DEL_MASTER, GetFollow() )
172             GetFollow()->bIsFollow = sal_False;
173         }
174     }
175 }
176 
177 
178 /*************************************************************************
179 |*
180 |*  SwSectionFrm::DelEmpty()
181 |*
182 |*  Ersterstellung      AMA 17. Dec. 97
183 |*  Letzte Aenderung    AMA 17. Dec. 97
184 |*
185 |*************************************************************************/
DelEmpty(sal_Bool bRemove)186 void SwSectionFrm::DelEmpty( sal_Bool bRemove )
187 {
188     if( IsColLocked() )
189     {
190         ASSERT( !bRemove, "Don't delete locked SectionFrms" );
191         return;
192     }
193     SwFrm* pUp = GetUpper();
194     if( pUp )
195     {
196         // --> OD 2005-12-01 #i27138#
197         // notify accessibility paragraphs objects about changed
198         // CONTENT_FLOWS_FROM/_TO relation.
199         // Relation CONTENT_FLOWS_FROM for current next paragraph will change
200         // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
201         {
202             ViewShell* pViewShell( getRootFrm()->GetCurrShell() );
203             if ( pViewShell && pViewShell->GetLayout() &&
204                  pViewShell->GetLayout()->IsAnyShellAccessible() )
205             {
206                 pViewShell->InvalidateAccessibleParaFlowRelation(
207                                 dynamic_cast<SwTxtFrm*>(FindNextCnt( true )),
208                                 dynamic_cast<SwTxtFrm*>(FindPrevCnt( true )) );
209             }
210         }
211         // <--
212         _Cut( bRemove );
213     }
214     if( IsFollow() )
215     {
216         SwSectionFrm *pMaster = FindMaster();
217         pMaster->SetFollow( GetFollow() );
218         // Ein Master greift sich immer den Platz bis zur Unterkante seines
219         // Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder
220         // freigeben, deshalb wird die Size des Masters invalidiert.
221         if( !GetFollow() && !pMaster->IsColLocked() )
222             pMaster->InvalidateSize();
223         bIsFollow = sal_False;
224     }
225     else if( HasFollow() )
226         GetFollow()->bIsFollow = sal_False;
227     pFollow = NULL;
228     if( pUp )
229     {
230         Frm().Height( 0 );
231         // Wenn wir sowieso sofort zerstoert werden, brauchen/duerfen wir
232         // uns gar nicht erst in die Liste eintragen
233         if( bRemove )
234         {   // Wenn wir bereits halbtot waren vor diesem DelEmpty, so
235             // stehen wir vermutlich auch in der Liste und muessen uns
236             // dort austragen
237             if( !pSection && getRootFrm() )
238                 getRootFrm()->RemoveFromList( this );
239         }
240         else if( getRootFrm() )
241             getRootFrm()->InsertEmptySct( this );   //swmod 071108//swmod 071225
242         pSection = NULL; // damit ist allerdings eine Reanimierung quasi ausgeschlossen
243     }
244 }
245 
246 /*************************************************************************
247 |*
248 |*  SwSectionFrm::Cut()
249 |*
250 |*  Ersterstellung      AMA 02. Dec. 97
251 |*  Letzte Aenderung    AMA 02. Dec. 97
252 |*
253 |*************************************************************************/
Cut()254 void SwSectionFrm::Cut()
255 {
256     _Cut( sal_True );
257 }
258 
_Cut(sal_Bool bRemove)259 void SwSectionFrm::_Cut( sal_Bool bRemove )
260 {
261     ASSERT( GetUpper(), "Cut ohne Upper()." );
262 
263     PROTOCOL( this, PROT_CUT, 0, GetUpper() )
264 
265     SwPageFrm *pPage = FindPageFrm();
266     InvalidatePage( pPage );
267     SwFrm *pFrm = GetNext();
268     SwFrm* pPrepFrm = NULL;
269     while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
270         pFrm = pFrm->GetNext();
271     if( pFrm )
272     {   //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
273         //berechnet der ist jetzt wo er der erste wird obsolete
274         pFrm->_InvalidatePrt();
275         pFrm->_InvalidatePos();
276         if( pFrm->IsSctFrm() )
277             pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
278         if ( pFrm && pFrm->IsCntntFrm() )
279         {
280             pFrm->InvalidatePage( pPage );
281             if( IsInFtn() && !GetIndPrev() )
282                 pPrepFrm = pFrm;
283         }
284     }
285     else
286     {
287         InvalidateNextPos();
288         //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
289         if ( 0 != (pFrm = GetPrev()) )
290         {   pFrm->SetRetouche();
291             pFrm->Prepare( PREP_WIDOWS_ORPHANS );
292             if ( pFrm->IsCntntFrm() )
293                 pFrm->InvalidatePage( pPage );
294         }
295         //Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss
296         //er die Retouche uebernehmen.
297         //Ausserdem kann eine Leerseite entstanden sein.
298         else
299         {   SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
300             pRoot->SetSuperfluous();
301             GetUpper()->SetCompletePaint();
302         }
303     }
304     //Erst removen, dann Upper Shrinken.
305     SwLayoutFrm *pUp = GetUpper();
306     if( bRemove )
307     {
308         Remove();
309         if( pUp && !pUp->Lower() && pUp->IsFtnFrm() && !pUp->IsColLocked() &&
310             pUp->GetUpper() )
311         {
312             pUp->Cut();
313             delete pUp;
314             pUp = NULL;
315         }
316     }
317     if( pPrepFrm )
318         pPrepFrm->Prepare( PREP_FTN );
319     if ( pUp )
320     {
321         SWRECTFN( this );
322         SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
323         if( nFrmHeight > 0 )
324         {
325             if( !bRemove )
326             {
327                 (Frm().*fnRect->fnSetHeight)( 0 );
328                 (Prt().*fnRect->fnSetHeight)( 0 );
329             }
330             pUp->Shrink( nFrmHeight );
331         }
332     }
333 }
334 
335 /*************************************************************************
336 |*
337 |*  SwSectionFrm::Paste()
338 |*
339 |*  Ersterstellung      AMA 04. Dec. 97
340 |*  Letzte Aenderung    AMA 04. Dec. 97
341 |*
342 |*************************************************************************/
343 
Paste(SwFrm * pParent,SwFrm * pSibling)344 void SwSectionFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
345 {
346     ASSERT( pParent, "Kein Parent fuer Paste." );
347     ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
348     ASSERT( pParent != this, "Bin selbst der Parent." );
349     ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
350     ASSERT( !GetPrev() && !GetUpper(),
351             "Bin noch irgendwo angemeldet." );
352 
353     PROTOCOL( this, PROT_PASTE, 0, GetUpper() )
354 
355     //In den Baum einhaengen.
356     SwSectionFrm* pSect = pParent->FindSctFrm();
357     // --> OD 2008-06-23 #156927#
358     // Assure that parent is not inside a table frame, which is inside the found section frame.
359     if ( pSect )
360     {
361         SwTabFrm* pTableFrm = pParent->FindTabFrm();
362         if ( pTableFrm &&
363              pSect->IsAnLower( pTableFrm ) )
364         {
365             pSect = 0;
366         }
367     }
368     // <--
369 
370     SWRECTFN( pParent )
371     if( pSect && HasToBreak( pSect ) )
372     {
373         if( pParent->IsColBodyFrm() ) // handelt es sich um einen spaltigen Bereich
374         {
375             // Falls wir zufaellig am Ende einer Spalte stehen, muss pSibling
376             // auf den ersten Frame der naechsten Spalte zeigen, damit
377             // der Inhalt der naechsten Spalte von InsertGroup richtig in den
378             // neu angelegten pSect umgehaengt wird.
379             SwColumnFrm *pCol = (SwColumnFrm*)pParent->GetUpper();
380             while( !pSibling && 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
381                 pSibling = ((SwLayoutFrm*)((SwColumnFrm*)pCol)->Lower())->Lower();
382             if( pSibling )
383             {
384                 // Schlimmer noch: alle folgenden Spalteninhalte muessen
385                 // an die pSibling-Kette angehaengt werden, damit sie
386                 // mitgenommen werden.
387                 SwFrm *pTmp = pSibling;
388                 while ( 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
389                 {
390                     while ( pTmp->GetNext() )
391                         pTmp = pTmp->GetNext();
392                     SwFrm* pSave = ::SaveCntnt( pCol );
393                     ::RestoreCntnt( pSave, pSibling->GetUpper(), pTmp, true );
394                 }
395             }
396         }
397         pParent = pSect;
398         pSect = new SwSectionFrm( *((SwSectionFrm*)pParent)->GetSection(), pParent );
399         // Wenn pParent in zwei Teile zerlegt wird, so muss sein Follow am
400         // neuen, zweiten Teil angebracht werden.
401         pSect->SetFollow( ((SwSectionFrm*)pParent)->GetFollow() );
402         ((SwSectionFrm*)pParent)->SetFollow( NULL );
403         if( pSect->GetFollow() )
404             pParent->_InvalidateSize();
405 
406         InsertGroupBefore( pParent, pSibling, pSect );
407         pSect->Init();
408         (pSect->*fnRect->fnMakePos)( pSect->GetUpper(), pSect->GetPrev(), sal_True);
409         if( !((SwLayoutFrm*)pParent)->Lower() )
410         {
411             SwSectionFrm::MoveCntntAndDelete( (SwSectionFrm*)pParent, sal_False );
412             pParent = this;
413         }
414     }
415     else
416         InsertGroupBefore( pParent, pSibling, NULL );
417 
418     _InvalidateAll();
419     SwPageFrm *pPage = FindPageFrm();
420     InvalidatePage( pPage );
421 
422     if ( pSibling )
423     {
424         pSibling->_InvalidatePos();
425         pSibling->_InvalidatePrt();
426         if ( pSibling->IsCntntFrm() )
427             pSibling->InvalidatePage( pPage );
428     }
429 
430     SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
431     if( nFrmHeight )
432         pParent->Grow( nFrmHeight );
433 
434     if ( GetPrev() )
435     {
436         if ( !IsFollow() )
437         {
438             GetPrev()->InvalidateSize();
439             if ( GetPrev()->IsCntntFrm() )
440                 GetPrev()->InvalidatePage( pPage );
441         }
442     }
443 }
444 
445 
446 /*************************************************************************
447 |*
448 |*  SwSectionFrm::HasToBreak()
449 |*
450 |*  Hier wird entschieden, ob der this-SectionFrm den uebergebenen
451 |*  (Section)Frm aufbrechen soll oder nicht.
452 |*  Zunaechst werden uebergeordnete Bereiche immer aufgebrochen,
453 |*  spaeter koennte man es einstellbar machen.
454 |*
455 |*  Ersterstellung      AMA 12. Dec. 97
456 |*  Letzte Aenderung    AMA 12. Dec. 97
457 |*
458 |*************************************************************************/
459 
HasToBreak(const SwFrm * pFrm) const460 sal_Bool SwSectionFrm::HasToBreak( const SwFrm* pFrm ) const
461 {
462     if( !pFrm->IsSctFrm() )
463         return sal_False;
464 
465     SwSectionFmt *pTmp = (SwSectionFmt*)GetFmt();
466 //  if( !pTmp->GetSect().GetValue() )
467 //      return sal_False;
468 
469     const SwFrmFmt *pOtherFmt = ((SwSectionFrm*)pFrm)->GetFmt();
470     do
471     {
472         pTmp = pTmp->GetParent();
473         if( !pTmp )
474             return sal_False;
475         if( pTmp == pOtherFmt )
476             return sal_True;
477     } while( sal_True ); // ( pTmp->GetSect().GetValue() );
478 }
479 
480 /*************************************************************************
481 |*
482 |*  SwSectionFrm::MergeNext()
483 |*
484 |*  Ersterstellung      AMA 04. Dec. 97
485 |*  Letzte Aenderung    AMA 04. Dec. 97
486 |*
487 |*  Verschmilzt zwei SectionFrms, falls es sich um den
488 |*  gleichen Bereich handelt.
489 |*  Notwendig kann dies sein, wenn ein (Unter-)Bereich geloescht wird, der
490 |*  einen anderen in zwei Teile zerlegt hatte.
491 |*
492 |*************************************************************************/
493 
MergeNext(SwSectionFrm * pNxt)494 void SwSectionFrm::MergeNext( SwSectionFrm* pNxt )
495 {
496     if( !pNxt->IsJoinLocked() && GetSection() == pNxt->GetSection() )
497     {
498         PROTOCOL( this, PROT_SECTION, ACT_MERGE, pNxt )
499 
500         SwFrm* pTmp = ::SaveCntnt( pNxt );
501         if( pTmp )
502         {
503             SwFrm* pLast = Lower();
504             SwLayoutFrm* pLay = this;
505             if( pLast )
506             {
507                 while( pLast->GetNext() )
508                     pLast = pLast->GetNext();
509                 if( pLast->IsColumnFrm() )
510                 {   // Spalten jetzt mit BodyFrm
511                     pLay = (SwLayoutFrm*)((SwLayoutFrm*)pLast)->Lower();
512                     pLast = pLay->Lower();
513                     if( pLast )
514                         while( pLast->GetNext() )
515                             pLast = pLast->GetNext();
516                 }
517             }
518             ::RestoreCntnt( pTmp, pLay, pLast, true );
519         }
520         SetFollow( pNxt->GetFollow() );
521         pNxt->SetFollow( NULL );
522         pNxt->bIsFollow = sal_False;
523         pNxt->Cut();
524         delete pNxt;
525         InvalidateSize();
526     }
527 }
528 
529 /*************************************************************************
530 |*
531 |*  SwSectionFrm::SplitSect()
532 |*
533 |*  Ersterstellung      AMA 29. Apr. 99
534 |*  Letzte Aenderung    AMA 29. Apr. 99
535 |*
536 |*  Zerteilt einen SectionFrm in zwei Teile, der zweite Teil beginnt mit dem
537 |*  uebergebenen Frame.
538 |*  Benoetigt wird dies beim Einfuegen eines inneren Bereichs, weil innerhalb
539 |*  von Rahmen oder Tabellenzellen das MoveFwd nicht den erwuenschten Effekt
540 |*  haben kann.
541 |*
542 |*************************************************************************/
543 
SplitSect(SwFrm * pFrm,sal_Bool bApres)544 sal_Bool SwSectionFrm::SplitSect( SwFrm* pFrm, sal_Bool bApres )
545 {
546     ASSERT( pFrm, "SplitSect: Why?" );
547     SwFrm* pOther = bApres ? pFrm->FindNext() : pFrm->FindPrev();
548     if( !pOther )
549         return sal_False;
550     SwSectionFrm* pSect = pOther->FindSctFrm();
551     if( pSect != this )
552         return sal_False;
553     // Den Inhalt zur Seite stellen
554     SwFrm* pSav = ::SaveCntnt( this, bApres ? pOther : pFrm );
555     ASSERT( pSav, "SplitSect: What's on?" );
556     if( pSav ) // Robust
557     {   // Einen neuen SctFrm anlegen, nicht als Follow/Master
558         SwSectionFrm* pNew = new SwSectionFrm( *pSect->GetSection(), pSect );
559         pNew->InsertBehind( pSect->GetUpper(), pSect );
560         pNew->Init();
561         SWRECTFN( this )
562         (pNew->*fnRect->fnMakePos)( NULL, pSect, sal_True );
563         // OD 25.03.2003 #108339# - restore content:
564         // determine layout frame for restoring content after the initialization
565         // of the section frame. In the section initialization the columns are
566         // created.
567         {
568             SwLayoutFrm* pLay = pNew;
569             // Search for last layout frame, e.g. for columned sections.
570             while( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
571                 pLay = (SwLayoutFrm*)pLay->Lower();
572             ::RestoreCntnt( pSav, pLay, NULL, true );
573         }
574         _InvalidateSize();
575         if( HasFollow() )
576         {
577             pNew->SetFollow( GetFollow() );
578             SetFollow( NULL );
579         }
580         return sal_True;
581     }
582     return sal_False;
583 }
584 
585 /*************************************************************************
586 |*
587 |*  SwSectionFrm::MoveCntntAndDelete()
588 |*
589 |*  Ersterstellung      AMA 29. Jan 99
590 |*  Letzte Aenderung    AMA 29. Jan 99
591 |*
592 |*  MoveCntnt wird zur Zerstoerung eines SectionFrms wg. Aufhebung oder
593 |*  Verstecken des Bereichs gerufen, um den Inhalt umzuhaengen.
594 |*  Wenn der SectionFrm keinen anderen aufbrach, so wird der Inhalt in
595 |*  den Upper bewegt. Anderfalls wird der Inhalt in den anderen SectionFrm
596 |*  umgehaengt, dieser muss ggf. gemergt werden.
597 |*
598 |*************************************************************************/
599 // Wenn ein mehrspaltiger Bereich aufgehoben wird, muessen die ContentFrms
600 // invalidiert werden
601 
lcl_InvalidateInfFlags(SwFrm * pFrm,sal_Bool bInva)602 void lcl_InvalidateInfFlags( SwFrm* pFrm, sal_Bool bInva )
603 {
604     while ( pFrm )
605     {
606         pFrm->InvalidateInfFlags();
607         if( bInva )
608         {
609             pFrm->_InvalidatePos();
610             pFrm->_InvalidateSize();
611             pFrm->_InvalidatePrt();
612         }
613         if( pFrm->IsLayoutFrm() )
614             lcl_InvalidateInfFlags( ((SwLayoutFrm*)pFrm)->GetLower(), sal_False );
615         pFrm = pFrm->GetNext();
616     }
617 }
618 
619 
620 //
621 // Works like SwCntntFrm::ImplGetNextCntntFrm, but starts with a LayoutFrm
622 //
lcl_GetNextCntntFrm(const SwLayoutFrm * pLay,bool bFwd)623 SwCntntFrm* lcl_GetNextCntntFrm( const SwLayoutFrm* pLay, bool bFwd )
624 {
625     if ( bFwd )
626     {
627         if ( pLay->GetNext() && pLay->GetNext()->IsCntntFrm() )
628             return (SwCntntFrm*)pLay->GetNext();
629     }
630     else
631     {
632         if ( pLay->GetPrev() && pLay->GetPrev()->IsCntntFrm() )
633             return (SwCntntFrm*)pLay->GetPrev();
634     }
635 
636     // #100926#
637     const SwFrm* pFrm = pLay;
638     SwCntntFrm *pCntntFrm = 0;
639     sal_Bool bGoingUp = sal_True;
640     do {
641         const SwFrm *p = 0;
642         sal_Bool bGoingFwdOrBwd = sal_False, bGoingDown = sal_False;
643 
644         bGoingDown = !bGoingUp && ( 0 !=  ( p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0 ) );
645         if ( !bGoingDown )
646         {
647             bGoingFwdOrBwd = ( 0 != ( p = pFrm->IsFlyFrm() ?
648                                           ( bFwd ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink() ) :
649                                           ( bFwd ? pFrm->GetNext() :pFrm->GetPrev() ) ) );
650             if ( !bGoingFwdOrBwd )
651             {
652                 bGoingUp = (0 != (p = pFrm->GetUpper() ) );
653                 if ( !bGoingUp )
654                     return 0;
655             }
656         }
657 
658         bGoingUp = !( bGoingFwdOrBwd || bGoingDown );
659 
660         if( !bFwd && bGoingDown && p )
661             while ( p->GetNext() )
662                 p = p->GetNext();
663 
664         pFrm = p;
665     } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
666 
667     return pCntntFrm;
668 }
669 
670 #define FIRSTLEAF( pLayFrm ) ( ( pLayFrm->Lower() && pLayFrm->Lower()->IsColumnFrm() )\
671                     ? pLayFrm->GetNextLayoutLeaf() \
672                     : pLayFrm )
673 
MoveCntntAndDelete(SwSectionFrm * pDel,sal_Bool bSave)674 void SwSectionFrm::MoveCntntAndDelete( SwSectionFrm* pDel, sal_Bool bSave )
675 {
676     sal_Bool bSize = pDel->Lower() && pDel->Lower()->IsColumnFrm();
677     SwFrm* pPrv = pDel->GetPrev();
678     SwLayoutFrm* pUp = pDel->GetUpper();
679     // OD 27.03.2003 #i12711# - initialize local pointer variables.
680     SwSectionFrm* pPrvSct = NULL;
681     SwSectionFrm* pNxtSct = NULL;
682     SwSectionFmt* pParent = static_cast<SwSectionFmt*>(pDel->GetFmt())->GetParent();
683     if( pDel->IsInTab() && pParent )
684     {
685         SwTabFrm *pTab = pDel->FindTabFrm();
686         // Wenn wir innerhalb einer Tabelle liegen, koennen wir nur Bereiche
687         // aufgebrochen haben, die ebenfalls innerhalb liegen, nicht etwa
688         // einen Bereich, der die gesamte Tabelle umfasst.
689         if( pTab->IsInSct() && pParent == pTab->FindSctFrm()->GetFmt() )
690             pParent = NULL;
691     }
692     // Wenn unser Format einen Parent besitzt, so haben wir vermutlich
693     // einen anderen SectionFrm aufgebrochen, dies muss geprueft werden,
694     // dazu besorgen wir uns zunaechst den vorhergehende und den nach-
695     // folgenden CntntFrm, mal sehen, ob diese in SectionFrms liegen.
696     // OD 27.03.2003 #i12711# - check, if previous and next section belonging
697     // together and can be joined, *not* only if deleted section contains content.
698     if ( pParent )
699     {
700         SwFrm* pPrvCntnt = lcl_GetNextCntntFrm( pDel, false );
701         pPrvSct = pPrvCntnt ? pPrvCntnt->FindSctFrm() : NULL;
702         SwFrm* pNxtCntnt = lcl_GetNextCntntFrm( pDel, true );
703         pNxtSct = pNxtCntnt ? pNxtCntnt->FindSctFrm() : NULL;
704     }
705     else
706     {
707         pParent = NULL;
708         pPrvSct = pNxtSct = NULL;
709     }
710 
711     // Jetzt wird der Inhalt beseite gestellt und der Frame zerstoert
712     SwFrm *pSave = bSave ? ::SaveCntnt( pDel ) : NULL;
713     sal_Bool bOldFtn = sal_True;
714     if( pSave && pUp->IsFtnFrm() )
715     {
716         bOldFtn = ((SwFtnFrm*)pUp)->IsColLocked();
717         ((SwFtnFrm*)pUp)->ColLock();
718     }
719     pDel->DelEmpty( sal_True );
720     delete pDel;
721     if( pParent )
722     {   // Hier wird die geeignete Einfuegeposition gesucht
723         if( pNxtSct && pNxtSct->GetFmt() == pParent )
724         {   // Hier koennen wir uns am Anfang einfuegen
725             pUp = FIRSTLEAF( pNxtSct );
726             pPrv = NULL;
727             if( pPrvSct && !( pPrvSct->GetFmt() == pParent ) )
728                 pPrvSct = NULL; // damit nicht gemergt wird
729         }
730         else if( pPrvSct && pPrvSct->GetFmt() == pParent )
731         {   // Wunderbar, hier koennen wir uns am Ende einfuegen
732             pUp = pPrvSct;
733             if( pUp->Lower() && pUp->Lower()->IsColumnFrm() )
734             {
735                 pUp = static_cast<SwLayoutFrm*>(pUp->GetLastLower());
736                 // Der Body der letzten Spalte
737                 pUp = static_cast<SwLayoutFrm*>(pUp->Lower());
738             }
739             // damit hinter dem letzten eingefuegt wird
740             pPrv = pUp->GetLastLower();
741             pPrvSct = NULL; // damit nicht gemergt wird
742         }
743         else
744         {
745             if( pSave )
746             {   // Folgende Situationen: Vor und hinter dem zu loeschenden Bereich
747                 // ist entweder die Bereichsgrenze des umfassenden Bereichs oder
748                 // es schliesst ein anderer (Geschwister-)Bereich direkt an, der
749                 // vom gleichen Parent abgeleitet ist.
750                 // Dann gibt es (noch) keinen Teil unseres Parents, der den Inhalt
751                 // aufnehmen kann,also bauen wir ihn uns.
752                 pPrvSct = new SwSectionFrm( *pParent->GetSection(), pUp );
753                 pPrvSct->InsertBehind( pUp, pPrv );
754                 pPrvSct->Init();
755                 SWRECTFN( pUp )
756                 (pPrvSct->*fnRect->fnMakePos)( pUp, pPrv, sal_True );
757                 pUp = FIRSTLEAF( pPrvSct );
758                 pPrv = NULL;
759             }
760             pPrvSct = NULL; // damit nicht gemergt wird
761         }
762     }
763     // Der Inhalt wird eingefuegt..
764     if( pSave )
765     {
766         lcl_InvalidateInfFlags( pSave, bSize );
767         ::RestoreCntnt( pSave, pUp, pPrv, true );
768         pUp->FindPageFrm()->InvalidateCntnt();
769         if( !bOldFtn )
770             ((SwFtnFrm*)pUp)->ColUnlock();
771     }
772     // jetzt koennen eventuell zwei Teile des uebergeordneten Bereich verschmelzen
773     if( pPrvSct && !pPrvSct->IsJoinLocked() )
774     {
775         ASSERT( pNxtSct, "MoveCntnt: No Merge" );
776         pPrvSct->MergeNext( pNxtSct );
777     }
778 }
779 
MakeAll()780 void SwSectionFrm::MakeAll()
781 {
782     if ( IsJoinLocked() || IsColLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
783         return;
784     if( !pSection ) // Durch DelEmpty
785     {
786         ASSERT( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
787         if( !bValidPos )
788         {
789             if( GetUpper() )
790             {
791                 SWRECTFN( GetUpper() )
792                 (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
793             }
794         }
795         bValidSize = bValidPos = bValidPrtArea = sal_True;
796         return;
797     }
798     LockJoin(); //Ich lass mich nicht unterwegs vernichten.
799 
800     while( GetNext() && GetNext() == GetFollow() )
801     {
802         const SwFrm* pFoll = GetFollow();
803         MergeNext( (SwSectionFrm*)GetNext() );
804         if( pFoll == GetFollow() )
805             break;
806     }
807 
808     // OD 2004-03-15 #116561# - In online layout join the follows, if section
809     // can grow.
810     const ViewShell *pSh = getRootFrm()->GetCurrShell();
811     if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
812          ( Grow( LONG_MAX, true ) > 0 ) )
813     {
814         while( GetFollow() )
815         {
816             const SwFrm* pFoll = GetFollow();
817             MergeNext( GetFollow() );
818             if( pFoll == GetFollow() )
819                 break;
820         }
821     }
822 
823     // Ein Bereich mit Follow nimmt allen Platz bis zur Unterkante des Uppers
824     // in Anspruch. Bewegt er sich, so kann seine Groesse zu- oder abnehmen...
825     if( !bValidPos && ToMaximize( sal_False ) )
826         bValidSize = sal_False;
827 
828 #if OSL_DEBUG_LEVEL > 1
829     const SwFmtCol &rCol = GetFmt()->GetCol();
830     (void)rCol;
831 #endif
832     SwLayoutFrm::MakeAll();
833     UnlockJoin();
834     if( pSection && IsSuperfluous() )
835         DelEmpty( sal_False );
836 }
837 
ShouldBwdMoved(SwLayoutFrm *,sal_Bool,sal_Bool &)838 sal_Bool SwSectionFrm::ShouldBwdMoved( SwLayoutFrm *, sal_Bool , sal_Bool & )
839 {
840     ASSERT( sal_False, "Hups, wo ist meine Tarnkappe?" );
841     return sal_False;
842 }
843 
_GetEndSectFmt() const844 const SwSectionFmt* SwSectionFrm::_GetEndSectFmt() const
845 {
846     const SwSectionFmt *pFmt = pSection->GetFmt();
847     while( !pFmt->GetEndAtTxtEnd().IsAtEnd() )
848     {
849         if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
850             pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
851         else
852             return NULL;
853     }
854     return pFmt;
855 }
856 
lcl_FindCntntFrm(SwCntntFrm * & rpCntntFrm,SwFtnFrm * & rpFtnFrm,SwFrm * pFrm,sal_Bool & rbChkFtn)857 void lcl_FindCntntFrm( SwCntntFrm* &rpCntntFrm, SwFtnFrm* &rpFtnFrm,
858     SwFrm* pFrm, sal_Bool &rbChkFtn )
859 {
860     if( pFrm )
861     {
862         while( pFrm->GetNext() )
863             pFrm = pFrm->GetNext();
864         while( !rpCntntFrm && pFrm )
865         {
866             if( pFrm->IsCntntFrm() )
867                 rpCntntFrm = (SwCntntFrm*)pFrm;
868             else if( pFrm->IsLayoutFrm() )
869             {
870                 if( pFrm->IsFtnFrm() )
871                 {
872                     if( rbChkFtn )
873                     {
874                         rpFtnFrm = (SwFtnFrm*)pFrm;
875                         rbChkFtn = rpFtnFrm->GetAttr()->GetFtn().IsEndNote();
876                     }
877                 }
878                 else
879                     lcl_FindCntntFrm( rpCntntFrm, rpFtnFrm,
880                         ((SwLayoutFrm*)pFrm)->Lower(), rbChkFtn );
881             }
882             pFrm = pFrm->GetPrev();
883         }
884     }
885 }
886 
FindLastCntnt(sal_uInt8 nMode)887 SwCntntFrm *SwSectionFrm::FindLastCntnt( sal_uInt8 nMode )
888 {
889     SwCntntFrm *pRet = NULL;
890     SwFtnFrm *pFtnFrm = NULL;
891     SwSectionFrm *pSect = this;
892     if( nMode )
893     {
894         const SwSectionFmt *pFmt = IsEndnAtEnd() ? GetEndSectFmt() :
895                                    pSection->GetFmt();
896         do {
897             while( pSect->HasFollow() )
898                 pSect = pSect->GetFollow();
899             SwFrm* pTmp = pSect->FindNext();
900             while( pTmp && pTmp->IsSctFrm() &&
901                    !((SwSectionFrm*)pTmp)->GetSection() )
902                 pTmp = pTmp->FindNext();
903             if( pTmp && pTmp->IsSctFrm() &&
904                 ((SwSectionFrm*)pTmp)->IsDescendantFrom( pFmt ) )
905                 pSect = (SwSectionFrm*)pTmp;
906             else
907                 break;
908         } while( sal_True );
909     }
910     sal_Bool bFtnFound = nMode == FINDMODE_ENDNOTE;
911     do
912     {
913         lcl_FindCntntFrm( pRet, pFtnFrm, pSect->Lower(), bFtnFound );
914         if( pRet || !pSect->IsFollow() || !nMode ||
915             ( FINDMODE_MYLAST == nMode && this == pSect ) )
916             break;
917         pSect = pSect->FindMaster();
918     } while( pSect );
919     if( ( nMode == FINDMODE_ENDNOTE ) && pFtnFrm )
920         pRet = pFtnFrm->ContainsCntnt();
921     return pRet;
922 }
923 
CalcMinDiff(SwTwips & rMinDiff) const924 sal_Bool SwSectionFrm::CalcMinDiff( SwTwips& rMinDiff ) const
925 {
926     if( ToMaximize( sal_True ) )
927     {
928         SWRECTFN( this )
929         rMinDiff = (GetUpper()->*fnRect->fnGetPrtBottom)();
930         rMinDiff = (Frm().*fnRect->fnBottomDist)( rMinDiff );
931         return sal_True;
932     }
933     return sal_False;
934 }
935 
936 /*************************************************************************
937  *
938  *  SwSectionFrm::CollectEndnotes(  )
939  *
940  *  Ersterstellung      AMA 03. Nov 99
941  *  Letzte Aenderung    AMA 03. Nov 99
942  *
943  *  CollectEndnotes looks for endnotes in the sectionfrm and his follows,
944  *  the endnotes will cut off the layout and put into the array.
945  *  If the first endnote is not a master-SwFtnFrm, the whole sectionfrm
946  *  contains only endnotes and it is not necessary to collect them.
947  *
948  *************************************************************************/
949 
lcl_FindEndnote(SwSectionFrm * & rpSect,sal_Bool & rbEmpty,SwLayouter * pLayouter)950 SwFtnFrm* lcl_FindEndnote( SwSectionFrm* &rpSect, sal_Bool &rbEmpty,
951     SwLayouter *pLayouter )
952 {
953     // if rEmpty is set, the rpSect is already searched
954     SwSectionFrm* pSect = rbEmpty ? rpSect->GetFollow() : rpSect;
955     while( pSect )
956     {
957        ASSERT( (pSect->Lower() && pSect->Lower()->IsColumnFrm()) || pSect->GetUpper()->IsFtnFrm(),
958                 "InsertEndnotes: Where's my column?" );
959 
960         // i73332: Columned section in endnote
961         SwColumnFrm* pCol = 0;
962         if(pSect->Lower() && pSect->Lower()->IsColumnFrm())
963             pCol = (SwColumnFrm*)pSect->Lower();
964 
965         while( pCol ) // check all columns
966         {
967             SwFtnContFrm* pFtnCont = pCol->FindFtnCont();
968             if( pFtnCont )
969             {
970                 SwFtnFrm* pRet = (SwFtnFrm*)pFtnCont->Lower();
971                 while( pRet ) // look for endnotes
972                 {
973                     if( pRet->GetAttr()->GetFtn().IsEndNote() )
974                     {
975                         if( pRet->GetMaster() )
976                         {
977                             if( pLayouter )
978                                 pLayouter->CollectEndnote( pRet );
979                             else
980                                 return 0;
981                         }
982                         else
983                             return pRet; // Found
984                     }
985                     pRet = (SwFtnFrm*)pRet->GetNext();
986                 }
987             }
988             pCol = (SwColumnFrm*)pCol->GetNext();
989         }
990         rpSect = pSect;
991         pSect = pLayouter ? pSect->GetFollow() : NULL;
992         rbEmpty = sal_True;
993     }
994     return NULL;
995 }
996 
lcl_ColumnRefresh(SwSectionFrm * pSect,sal_Bool bFollow)997 void lcl_ColumnRefresh( SwSectionFrm* pSect, sal_Bool bFollow )
998 {
999     while( pSect )
1000     {
1001         sal_Bool bOldLock = pSect->IsColLocked();
1002         pSect->ColLock();
1003         if( pSect->Lower() && pSect->Lower()->IsColumnFrm() )
1004         {
1005             SwColumnFrm *pCol = (SwColumnFrm*)pSect->Lower();
1006             do
1007             {   pCol->_InvalidateSize();
1008                 pCol->_InvalidatePos();
1009                 ((SwLayoutFrm*)pCol)->Lower()->_InvalidateSize();
1010                 pCol->Calc();   // calculation of column and
1011                 ((SwLayoutFrm*)pCol)->Lower()->Calc();  // body
1012                 pCol = (SwColumnFrm*)pCol->GetNext();
1013             } while ( pCol );
1014         }
1015         if( !bOldLock )
1016             pSect->ColUnlock();
1017         if( bFollow )
1018             pSect = pSect->GetFollow();
1019         else
1020             pSect = NULL;
1021     }
1022 }
1023 
CollectEndnotes(SwLayouter * pLayouter)1024 void SwSectionFrm::CollectEndnotes( SwLayouter* pLayouter )
1025 {
1026     ASSERT( IsColLocked(), "CollectEndnotes: You love the risk?" );
1027     // i73332: Section in footnode does not have columns!
1028     ASSERT( (Lower() && Lower()->IsColumnFrm()) || GetUpper()->IsFtnFrm(), "Where's my column?" );
1029 
1030     SwSectionFrm* pSect = this;
1031     SwFtnFrm* pFtn;
1032     sal_Bool bEmpty = sal_False;
1033     // pSect is the last sectionfrm without endnotes or the this-pointer
1034     // the first sectionfrm with endnotes may be destroyed, when the endnotes
1035     // is cutted
1036     while( 0 != (pFtn = lcl_FindEndnote( pSect, bEmpty, pLayouter )) )
1037         pLayouter->CollectEndnote( pFtn );
1038     if( pLayouter->HasEndnotes() )
1039         lcl_ColumnRefresh( this, sal_True );
1040 }
1041 
1042 /*************************************************************************
1043 |*
1044 |*  SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
1045 |*
1046 |*  Beschreibung:       Passt die Groesse an die Umgebung an.
1047 |*      Wer einen Follow oder Fussnoten besitzt, soll bis zur Unterkante
1048 |*      des Uppers gehen (bMaximize).
1049 |*      Niemand darf ueber den Upper hinausgehen, ggf. darf man versuchen (bGrow)
1050 |*      seinen Upper zu growen.
1051 |*      Wenn die Groesse veraendert werden musste, wird der Inhalt kalkuliert.
1052 |*
1053 |*************************************************************************/
1054 
1055 /// OD 18.09.2002 #100522#
1056 /// perform calculation of content, only if height has changed.
_CheckClipping(sal_Bool bGrow,sal_Bool bMaximize)1057 void SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
1058 {
1059     SWRECTFN( this )
1060     long nDiff;
1061     SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1062     if( bGrow && ( !IsInFly() || !GetUpper()->IsColBodyFrm() ||
1063                    !FindFlyFrm()->IsLocked() ) )
1064     {
1065         nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
1066         if( !bMaximize )
1067             nDiff += Undersize();
1068         if( nDiff > 0 )
1069         {
1070             long nAdd = GetUpper()->Grow( nDiff );
1071             if( bVert && !bRev )
1072                 nDeadLine -= nAdd;
1073             else
1074                 nDeadLine += nAdd;
1075         }
1076     }
1077     nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
1078     SetUndersized( !bMaximize && nDiff >= 0 );
1079     const bool bCalc = ( IsUndersized() || bMaximize ) &&
1080                        ( nDiff ||
1081                          (Prt().*fnRect->fnGetTop)() > (Frm().*fnRect->fnGetHeight)() );
1082     // OD 03.11.2003 #i19737# - introduce local variable <bExtraCalc> to indicate
1083     // that a calculation has to be done beside the value of <bCalc>.
1084     bool bExtraCalc = false;
1085     if( !bCalc && !bGrow && IsAnyNoteAtEnd() && !IsInFtn() )
1086     {
1087         SwSectionFrm *pSect = this;
1088         sal_Bool bEmpty = sal_False;
1089         SwLayoutFrm* pFtn = IsEndnAtEnd() ?
1090             lcl_FindEndnote( pSect, bEmpty, NULL ) : NULL;
1091         if( pFtn )
1092         {
1093             pFtn = pFtn->FindFtnBossFrm();
1094             SwFrm* pTmp = FindLastCntnt( FINDMODE_LASTCNT );
1095             // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
1096             if ( pTmp && pFtn->IsBefore( pTmp->FindFtnBossFrm() ) )
1097                 bExtraCalc = true;
1098         }
1099         else if( GetFollow() && !GetFollow()->ContainsAny() )
1100             bExtraCalc = true;
1101     }
1102     if ( bCalc || bExtraCalc )
1103     {
1104         nDiff = (*fnRect->fnYDiff)( nDeadLine, (Frm().*fnRect->fnGetTop)() );
1105         if( nDiff < 0 )
1106         {
1107             nDiff = 0;
1108             nDeadLine = (Frm().*fnRect->fnGetTop)();
1109         }
1110         const Size aOldSz( Prt().SSize() );
1111         long nTop = (this->*fnRect->fnGetTopMargin)();
1112         (Frm().*fnRect->fnSetBottom)( nDeadLine );
1113         nDiff = (Frm().*fnRect->fnGetHeight)();
1114         if( nTop > nDiff )
1115             nTop = nDiff;
1116         (this->*fnRect->fnSetYMargins)( nTop, 0 );
1117 
1118         // OD 18.09.2002 #100522#
1119         // Determine, if height has changed.
1120         // Note: In vertical layout the height equals the width value.
1121         bool bHeightChanged = bVert ?
1122                             (aOldSz.Width() != Prt().Width()) :
1123                             (aOldSz.Height() != Prt().Height());
1124         // Wir haben zu guter Letzt noch einmal die Hoehe geaendert,
1125         // dann wird das innere Layout (Columns) kalkuliert und
1126         // der Inhalt ebenfalls.
1127         // OD 18.09.2002 #100522#
1128         // calculate content, only if height has changed.
1129         // OD 03.11.2003 #i19737# - restriction of content calculation too strong.
1130         // If an endnote has an incorrect position or a follow section contains
1131         // no content except footnotes/endnotes, the content has also been calculated.
1132         if ( ( bHeightChanged || bExtraCalc ) && Lower() )
1133         {
1134             if( Lower()->IsColumnFrm() )
1135             {
1136                 lcl_ColumnRefresh( this, sal_False );
1137                 ::CalcCntnt( this );
1138             }
1139             else
1140             {
1141                 ChgLowersProp( aOldSz );
1142                 if( !bMaximize && !IsCntntLocked() )
1143                     ::CalcCntnt( this );
1144             }
1145         }
1146     }
1147 }
1148 
SimpleFormat()1149 void SwSectionFrm::SimpleFormat()
1150 {
1151     if ( IsJoinLocked() || IsColLocked() )
1152         return;
1153     // ASSERT( pFollow, "SimpleFormat: Follow required" );
1154     LockJoin();
1155     SWRECTFN( this )
1156     if( GetPrev() || GetUpper() )
1157     {
1158         // --> OD 2009-09-28 #b6882166#
1159         // assure notifications on position changes.
1160         const SwLayNotify aNotify( this );
1161         // <--
1162         (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
1163         bValidPos = sal_True;
1164     }
1165     SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1166     // OD 22.10.2002 #97265# - call always method <lcl_ColumnRefresh(..)>, in
1167     // order to get calculated lowers, not only if there space left in its upper.
1168     if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) >= 0 )
1169     {
1170         (Frm().*fnRect->fnSetBottom)( nDeadLine );
1171         long nHeight = (Frm().*fnRect->fnGetHeight)();
1172         long nTop = CalcUpperSpace();
1173         if( nTop > nHeight )
1174             nTop = nHeight;
1175         (this->*fnRect->fnSetYMargins)( nTop, 0 );
1176     }
1177     lcl_ColumnRefresh( this, sal_False );
1178     UnlockJoin();
1179 }
1180 
1181 // --> OD 2005-01-11 #i40147# - helper class to perform extra section format
1182 // to position anchored objects and to keep the position of whose objects locked.
1183 class ExtraFormatToPositionObjs
1184 {
1185     private:
1186         SwSectionFrm* mpSectFrm;
1187         bool mbExtraFormatPerformed;
1188 
1189     public:
ExtraFormatToPositionObjs(SwSectionFrm & _rSectFrm)1190         ExtraFormatToPositionObjs( SwSectionFrm& _rSectFrm)
1191             : mpSectFrm( &_rSectFrm ),
1192               mbExtraFormatPerformed( false )
1193         {}
1194 
~ExtraFormatToPositionObjs()1195         ~ExtraFormatToPositionObjs()
1196         {
1197             if ( mbExtraFormatPerformed )
1198             {
1199                 // release keep locked position of lower floating screen objects
1200                 SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
1201                 SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
1202                 if ( pObjs )
1203                 {
1204                     sal_uInt32 i = 0;
1205                     for ( i = 0; i < pObjs->Count(); ++i )
1206                     {
1207                         SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1208 
1209                         if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
1210                         {
1211                             pAnchoredObj->SetKeepPosLocked( false );
1212                         }
1213                     }
1214                 }
1215             }
1216         }
1217 
1218         // --> OD 2008-06-20 #i81555#
InitObjs(SwFrm & rFrm)1219         void InitObjs( SwFrm& rFrm )
1220         {
1221             SwSortedObjs* pObjs = rFrm.GetDrawObjs();
1222             if ( pObjs )
1223             {
1224                 sal_uInt32 i = 0;
1225                 for ( i = 0; i < pObjs->Count(); ++i )
1226                 {
1227                     SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1228 
1229                     pAnchoredObj->UnlockPosition();
1230                     pAnchoredObj->SetClearedEnvironment( false );
1231                 }
1232             }
1233             SwLayoutFrm* pLayoutFrm = dynamic_cast<SwLayoutFrm*>(&rFrm);
1234             if ( pLayoutFrm != 0 )
1235             {
1236                 SwFrm* pLowerFrm = pLayoutFrm->GetLower();
1237                 while ( pLowerFrm != 0 )
1238                 {
1239                     InitObjs( *pLowerFrm );
1240 
1241                     pLowerFrm = pLowerFrm->GetNext();
1242                 }
1243             }
1244         }
1245         // <--
1246 
FormatSectionToPositionObjs()1247         void FormatSectionToPositionObjs()
1248         {
1249             // perform extra format for multi-columned section.
1250             if ( mpSectFrm->Lower() && mpSectFrm->Lower()->IsColumnFrm() &&
1251                  mpSectFrm->Lower()->GetNext() )
1252             {
1253                 // grow section till bottom of printing area of upper frame
1254                 SWRECTFN( mpSectFrm );
1255                 SwTwips nTopMargin = (mpSectFrm->*fnRect->fnGetTopMargin)();
1256                 Size aOldSectPrtSize( mpSectFrm->Prt().SSize() );
1257                 SwTwips nDiff = (mpSectFrm->Frm().*fnRect->fnBottomDist)(
1258                                         (mpSectFrm->GetUpper()->*fnRect->fnGetPrtBottom)() );
1259                 (mpSectFrm->Frm().*fnRect->fnAddBottom)( nDiff );
1260                 (mpSectFrm->*fnRect->fnSetYMargins)( nTopMargin, 0 );
1261                 // --> OD 2006-05-08 #i59789#
1262                 // suppress formatting, if printing area of section is too narrow
1263                 if ( (mpSectFrm->Prt().*fnRect->fnGetHeight)() <= 0 )
1264                 {
1265                     return;
1266                 }
1267                 // <--
1268                 mpSectFrm->ChgLowersProp( aOldSectPrtSize );
1269 
1270                 // format column frames and its body and footnote container
1271                 SwColumnFrm* pColFrm = static_cast<SwColumnFrm*>(mpSectFrm->Lower());
1272                 while ( pColFrm )
1273                 {
1274                     pColFrm->Calc();
1275                     pColFrm->Lower()->Calc();
1276                     if ( pColFrm->Lower()->GetNext() )
1277                     {
1278                         pColFrm->Lower()->GetNext()->Calc();
1279                     }
1280 
1281                     pColFrm = static_cast<SwColumnFrm*>(pColFrm->GetNext());
1282                 }
1283 
1284                 // unlock position of lower floating screen objects for the extra format
1285                 // --> OD 2008-06-20 #i81555#
1286                 // Section frame can already have changed the page and its content
1287                 // can still be on the former page.
1288                 // Thus, initialize objects via lower-relationship
1289                 InitObjs( *mpSectFrm );
1290                 // <--
1291 
1292                 // format content - first with collecting its foot-/endnotes before content
1293                 // format, second without collecting its foot-/endnotes.
1294                 ::CalcCntnt( mpSectFrm );
1295                 ::CalcCntnt( mpSectFrm, true );
1296 
1297                 // keep locked position of lower floating screen objects
1298                 SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
1299                 SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
1300                 if ( pObjs )
1301                 {
1302                     sal_uInt32 i = 0;
1303                     for ( i = 0; i < pObjs->Count(); ++i )
1304                     {
1305                         SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1306 
1307                         if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
1308                         {
1309                             pAnchoredObj->SetKeepPosLocked( true );
1310                         }
1311                     }
1312                 }
1313 
1314                 mbExtraFormatPerformed = true;
1315             }
1316         }
1317 };
1318 
1319 /*************************************************************************
1320 |*
1321 |*  SwSectionFrm::Format()
1322 |*
1323 |*  Beschreibung:       "Formatiert" den Frame; Frm und PrtArea.
1324 |*  Ersterstellung      AMA 03. Dec. 97
1325 |*  Letzte Aenderung    MA 09. Oct. 98
1326 |*
1327 |*************************************************************************/
1328 
Format(const SwBorderAttrs * pAttr)1329 void SwSectionFrm::Format( const SwBorderAttrs *pAttr )
1330 {
1331     if( !pSection ) // Durch DelEmpty
1332     {
1333         ASSERT( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
1334         bValidSize = bValidPos = bValidPrtArea = sal_True;
1335         return;
1336     }
1337     SWRECTFN( this )
1338     if ( !bValidPrtArea )
1339     {
1340         PROTOCOL( this, PROT_PRTAREA, 0, 0 )
1341         bValidPrtArea = sal_True;
1342         SwTwips nUpper = CalcUpperSpace();
1343 
1344         // #109700# LRSpace for sections
1345         const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
1346         (this->*fnRect->fnSetXMargins)( rLRSpace.GetLeft(), rLRSpace.GetRight() );
1347 
1348         if( nUpper != (this->*fnRect->fnGetTopMargin)() )
1349         {
1350             bValidSize = sal_False;
1351             SwFrm* pOwn = ContainsAny();
1352             if( pOwn )
1353                 pOwn->_InvalidatePos();
1354         }
1355         (this->*fnRect->fnSetYMargins)( nUpper, 0 );
1356     }
1357 
1358     if ( !bValidSize )
1359     {
1360         PROTOCOL_ENTER( this, PROT_SIZE, 0, 0 )
1361         const long nOldHeight = (Frm().*fnRect->fnGetHeight)();
1362         sal_Bool bOldLock = IsColLocked();
1363         ColLock();
1364 
1365         bValidSize = sal_True;
1366 
1367         //die Groesse wird nur dann vom Inhalt bestimmt, wenn der SectFrm
1368         //keinen Follow hat. Anderfalls fuellt er immer den Upper bis
1369         //zur Unterkante aus. Fuer den Textfluss ist nicht er, sondern sein
1370         //Inhalt selbst verantwortlich.
1371         sal_Bool bMaximize = ToMaximize( sal_False );
1372 
1373         // OD 2004-05-17 #i28701# - If the wrapping style has to be considered
1374         // on object positioning, an extra formatting has to be performed
1375         // to determine the correct positions the floating screen objects.
1376         // --> OD 2005-01-11 #i40147#
1377         // use new helper class <ExtraFormatToPositionObjs>.
1378         // This class additionally keep the locked position of the objects
1379         // and releases this position lock keeping on destruction.
1380         ExtraFormatToPositionObjs aExtraFormatToPosObjs( *this );
1381         if ( !bMaximize &&
1382              GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
1383              !GetFmt()->GetBalancedColumns().GetValue() )
1384         {
1385             aExtraFormatToPosObjs.FormatSectionToPositionObjs();
1386         }
1387         // <--
1388 
1389         // Column widths have to be adjusted before calling _CheckClipping.
1390         // _CheckClipping can cause the formatting of the lower frames
1391         // which still have a width of 0.
1392         const sal_Bool bHasColumns = Lower() && Lower()->IsColumnFrm();
1393         if ( bHasColumns && Lower()->GetNext() )
1394             AdjustColumns( 0, sal_False );
1395 
1396         if( GetUpper() )
1397         {
1398             long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
1399             (aFrm.*fnRect->fnSetWidth)( nWidth );
1400 
1401             // #109700# LRSpace for sections
1402             const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
1403             (aPrt.*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
1404                                         rLRSpace.GetRight() );
1405 
1406             // OD 15.10.2002 #103517# - allow grow in online layout
1407             // Thus, set <..IsBrowseMode()> as parameter <bGrow> on calling
1408             // method <_CheckClipping(..)>.
1409             const ViewShell *pSh = getRootFrm()->GetCurrShell();
1410             _CheckClipping( pSh && pSh->GetViewOptions()->getBrowseMode(), bMaximize );
1411             bMaximize = ToMaximize( sal_False );
1412             bValidSize = sal_True;
1413         }
1414 
1415         //Breite der Spalten pruefen und ggf. einstellen.
1416         if ( bHasColumns && ! Lower()->GetNext() && bMaximize )
1417             ((SwColumnFrm*)Lower())->Lower()->Calc();
1418 
1419         if ( !bMaximize )
1420         {
1421             SwTwips nRemaining = (this->*fnRect->fnGetTopMargin)();
1422             SwFrm *pFrm = pLower;
1423             if( pFrm )
1424             {
1425                 if( pFrm->IsColumnFrm() && pFrm->GetNext() )
1426                 {
1427                     // --> OD 2006-05-08 #i61435#
1428                     // suppress formatting, if upper frame has height <= 0
1429                     if ( (GetUpper()->Frm().*fnRect->fnGetHeight)() > 0 )
1430                     {
1431                         FormatWidthCols( *pAttr, nRemaining, MINLAY );
1432                     }
1433                     // <--
1434                     // --> OD 2006-01-04 #126020# - adjust check for empty section
1435                     // --> OD 2006-02-01 #130797# - correct fix #126020#
1436                     while( HasFollow() && !GetFollow()->ContainsCntnt() &&
1437                            !GetFollow()->ContainsAny( true ) )
1438                     // <--
1439                     {
1440                         SwFrm* pOld = GetFollow();
1441                         GetFollow()->DelEmpty( sal_False );
1442                         if( pOld == GetFollow() )
1443                             break;
1444                     }
1445                     bMaximize = ToMaximize( sal_False );
1446                     nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
1447                 }
1448                 else
1449                 {
1450                     if( pFrm->IsColumnFrm() )
1451                     {
1452                         pFrm->Calc();
1453                         pFrm = ((SwColumnFrm*)pFrm)->Lower();
1454                         pFrm->Calc();
1455                         pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1456                         CalcFtnCntnt();
1457                     }
1458                     // Wenn wir in einem spaltigen Rahmen stehen und dieser
1459                     // gerade im FormatWidthCols ein CalcCntnt ruft, muss
1460                     // unser Inhalt ggf. kalkuliert werden.
1461                     if( pFrm && !pFrm->IsValid() && IsInFly() &&
1462                         FindFlyFrm()->IsColLocked() )
1463                         ::CalcCntnt( this );
1464                     nRemaining += InnerHeight();
1465                     bMaximize = HasFollow();
1466                 }
1467             }
1468 
1469             SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
1470             if( nDiff < 0)
1471             {
1472                 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1473                 {
1474                     long nBottom = (Frm().*fnRect->fnGetBottom)();
1475                     nBottom = (*fnRect->fnYInc)( nBottom, -nDiff );
1476                     long nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
1477                     if( nTmpDiff > 0 )
1478                     {
1479                         nTmpDiff = GetUpper()->Grow( nTmpDiff, sal_True );
1480                         nDeadLine = (*fnRect->fnYInc)( nDeadLine, nTmpDiff );
1481                         nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
1482                         if( nTmpDiff > 0 )
1483                             nDiff += nTmpDiff;
1484                         if( nDiff > 0 )
1485                             nDiff = 0;
1486                     }
1487                 }
1488             }
1489             if( nDiff )
1490             {
1491                 long nTmp = nRemaining - (Frm().*fnRect->fnGetHeight)();
1492                 long nTop = (this->*fnRect->fnGetTopMargin)();
1493                 (Frm().*fnRect->fnAddBottom)( nTmp );
1494                 (this->*fnRect->fnSetYMargins)( nTop, 0 );
1495                 InvalidateNextPos();
1496                 if( pLower && ( !pLower->IsColumnFrm() || !pLower->GetNext() ) )
1497                 {
1498                     // Wenn ein einspaltiger Bereich gerade den Platz geschaffen
1499                     // hat, den sich die "undersized" Absaetze gewuenscht haben,
1500                     // muessen diese invalidiert und kalkuliert werden, damit
1501                     // sie diesen ausfuellen.
1502                     pFrm = pLower;
1503                     if( pFrm->IsColumnFrm() )
1504                     {
1505                         pFrm->_InvalidateSize();
1506                         pFrm->_InvalidatePos();
1507                         pFrm->Calc();
1508                         pFrm = ((SwColumnFrm*)pFrm)->Lower();
1509                         pFrm->Calc();
1510                         pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1511                         CalcFtnCntnt();
1512                     }
1513                     sal_Bool bUnderSz = sal_False;
1514                     while( pFrm )
1515                     {
1516                         if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
1517                         {
1518                             pFrm->Prepare( PREP_ADJUST_FRM );
1519                             bUnderSz = sal_True;
1520                         }
1521                         pFrm = pFrm->GetNext();
1522                     }
1523                     if( bUnderSz && !IsCntntLocked() )
1524                         ::CalcCntnt( this );
1525                 }
1526             }
1527         }
1528 
1529         //Unterkante des Uppers nicht ueberschreiten. Fuer Sections mit
1530         //Follows die Unterkante auch nicht unterschreiten.
1531         if ( GetUpper() )
1532             _CheckClipping( sal_True, bMaximize );
1533         if( !bOldLock )
1534             ColUnlock();
1535         long nDiff = nOldHeight - (Frm().*fnRect->fnGetHeight)();
1536         if( nDiff > 0 )
1537         {
1538             if( !GetNext() )
1539                 SetRetouche(); // Dann muessen wir die Retusche selbst uebernehmen
1540             if( GetUpper() && !GetUpper()->IsFooterFrm() )
1541                 GetUpper()->Shrink( nDiff );
1542         }
1543         if( IsUndersized() )
1544             bValidPrtArea = sal_True;
1545     }
1546 }
1547 
1548 /*************************************************************************
1549 |*
1550 |*  SwFrm::GetNextSctLeaf()
1551 |*
1552 |*  Beschreibung        Liefert das naechste Layoutblatt in das der Frame
1553 |*      gemoved werden kann.
1554 |*      Neue Seiten werden nur dann erzeugt, wenn der Parameter sal_True ist.
1555 |*  Ersterstellung      AMA 07. Jan. 98
1556 |*  Letzte Aenderung    AMA 07. Jan. 98
1557 |*
1558 |*************************************************************************/
1559 
1560 
GetNextSctLeaf(MakePageType eMakePage)1561 SwLayoutFrm *SwFrm::GetNextSctLeaf( MakePageType eMakePage )
1562 {
1563     //Achtung: Geschachtelte Bereiche werden zur Zeit nicht unterstuetzt.
1564 
1565     PROTOCOL_ENTER( this, PROT_LEAF, ACT_NEXT_SECT, GetUpper()->FindSctFrm() )
1566 
1567     // Abkuerzungen fuer spaltige Bereiche, wenn wir noch nicht in der letzten Spalte sind.
1568     // Koennen wir in die naechste Spalte des Bereichs rutschen?
1569     if( IsColBodyFrm() && GetUpper()->GetNext() )
1570         return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetNext())->Lower();
1571     if( GetUpper()->IsColBodyFrm() && GetUpper()->GetUpper()->GetNext() )
1572         return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetUpper()->GetNext())->Lower();
1573     // Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann
1574     // nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette zuschlagen muessen
1575     if( GetUpper()->IsInTab() || FindFooterOrHeader() )
1576         return 0;
1577 
1578 //MA 03. Feb. 99: Warum GetUpper()? Das knallt mit Buch.sgl weil im
1579 //FlyAtCnt::MakeFlyPos ein Orient der SectionFrm ist und auf diesen ein
1580 //GetLeaf gerufen wird.
1581 //  SwSectionFrm *pSect = GetUpper()->FindSctFrm();
1582     SwSectionFrm *pSect = FindSctFrm();
1583     sal_Bool bWrongPage = sal_False;
1584     ASSERT( pSect, "GetNextSctLeaf: Missing SectionFrm" );
1585 
1586     // Hier eine Abkuerzung fuer Bereiche mit Follows,
1587     // dieser kann akzeptiert werden, wenn keine Spalten oder Seiten (ausser Dummyseiten)
1588     // dazwischen liegen.
1589     // Bei verketteten Rahmen und ind Fussnoten wuerde die Abkuerzung noch aufwendiger
1590     if( pSect->HasFollow() && pSect->IsInDocBody() )
1591     {
1592         if( pSect->GetFollow() == pSect->GetNext() )
1593         {
1594             SwPageFrm *pPg = pSect->GetFollow()->FindPageFrm();
1595             if( WrongPageDesc( pPg ) )
1596                 bWrongPage = sal_True;
1597             else
1598                 return FIRSTLEAF( pSect->GetFollow() );
1599         }
1600         else
1601         {
1602             SwFrm* pTmp;
1603             if( !pSect->GetUpper()->IsColBodyFrm() ||
1604                 0 == ( pTmp = pSect->GetUpper()->GetUpper()->GetNext() ) )
1605                 pTmp = pSect->FindPageFrm()->GetNext();
1606             if( pTmp ) // ist jetzt die naechste Spalte oder Seite
1607             {
1608                 SwFrm* pTmpX = pTmp;
1609                 if( pTmp->IsPageFrm() && ((SwPageFrm*)pTmp)->IsEmptyPage() )
1610                     pTmp = pTmp->GetNext(); // Dummyseiten ueberspringen
1611                 SwFrm *pUp = pSect->GetFollow()->GetUpper();
1612                 // pUp wird die Spalte, wenn der Follow in einer "nicht ersten" Spalte
1613                 // liegt, ansonsten die Seite:
1614                 if( !pUp->IsColBodyFrm() ||
1615                     !( pUp = pUp->GetUpper() )->GetPrev() )
1616                     pUp = pUp->FindPageFrm();
1617                 // Jetzt muessen pUp und pTmp die gleiche Seite/Spalte sein,
1618                 // sonst liegen Seiten oder Spalten zwischen Master und Follow.
1619                 if( pUp == pTmp || pUp->GetNext() == pTmpX )
1620                 {
1621                     SwPageFrm* pNxtPg = pUp->IsPageFrm() ?
1622                                         (SwPageFrm*)pUp : pUp->FindPageFrm();
1623                     if( WrongPageDesc( pNxtPg ) )
1624                         bWrongPage = sal_True;
1625                     else
1626                         return FIRSTLEAF( pSect->GetFollow() );
1627                 }
1628             }
1629         }
1630     }
1631 
1632     // Immer im gleichen Bereich landen: Body wieder in Body etc.
1633     const sal_Bool bBody = IsInDocBody();
1634     const sal_Bool bFtnPage = FindPageFrm()->IsFtnPage();
1635 
1636     SwLayoutFrm *pLayLeaf;
1637     // Eine Abkuerzung fuer TabFrms, damit nicht alle Zellen abgehuehnert werden
1638     if( bWrongPage )
1639         pLayLeaf = 0;
1640     else if( IsTabFrm() )
1641     {
1642         SwCntntFrm* pTmpCnt = ((SwTabFrm*)this)->FindLastCntnt();
1643         pLayLeaf = pTmpCnt ? pTmpCnt->GetUpper() : 0;
1644     }
1645     else
1646     {
1647         pLayLeaf = GetNextLayoutLeaf();
1648         if( IsColumnFrm() )
1649         {
1650             while( pLayLeaf && ((SwColumnFrm*)this)->IsAnLower( pLayLeaf ) )
1651                 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1652         }
1653     }
1654 
1655     SwLayoutFrm *pOldLayLeaf = 0;           //Damit bei neu erzeugten Seiten
1656                                             //nicht wieder vom Anfang gesucht
1657                                             //wird.
1658 
1659     while( sal_True )
1660     {
1661         if( pLayLeaf )
1662         {
1663             // Ein Layoutblatt wurde gefunden, mal sehen, ob er mich aufnehmen kann,
1664             // ob hier ein weiterer SectionFrm eingefuegt werden kann
1665             // oder ob wir weitersuchen muessen.
1666             SwPageFrm* pNxtPg = pLayLeaf->FindPageFrm();
1667             if ( !bFtnPage && pNxtPg->IsFtnPage() )
1668             {   //Wenn ich bei den Endnotenseiten angelangt bin hat sichs.
1669                 pLayLeaf = 0;
1670                 continue;
1671             }
1672             // Einmal InBody, immer InBody, nicht in Tabellen hinein
1673             // und nicht in fremde Bereiche hinein
1674             if ( (bBody && !pLayLeaf->IsInDocBody()) ||
1675                  (IsInFtn() != pLayLeaf->IsInFtn() ) ||
1676                  pLayLeaf->IsInTab() ||
1677                  ( pLayLeaf->IsInSct() && ( !pSect->HasFollow()
1678                    || pSect->GetFollow() != pLayLeaf->FindSctFrm() ) ) )
1679             {
1680                 //Er will mich nicht; neuer Versuch, neues Glueck
1681                 pOldLayLeaf = pLayLeaf;
1682                 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1683                 continue;
1684             }
1685             if( WrongPageDesc( pNxtPg ) )
1686             {
1687                 if( bWrongPage )
1688                     break; // there's a column between me and my right page
1689                 pLayLeaf = 0;
1690                 bWrongPage = sal_True;
1691                 pOldLayLeaf = 0;
1692                 continue;
1693             }
1694         }
1695         //Es gibt keinen passenden weiteren LayoutFrm, also muss eine
1696         //neue Seite her, allerdings nuetzen uns innerhalb eines Rahmens
1697         //neue Seiten nichts.
1698         else if( !pSect->IsInFly() &&
1699             ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
1700         {
1701             InsertPage(pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
1702                        sal_False );
1703             //und nochmal das ganze
1704             pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
1705             continue;
1706         }
1707         break;
1708     }
1709 
1710     if( pLayLeaf )
1711     {
1712         // Das passende Layoutblatt haben wir gefunden, wenn es dort bereits einen
1713         // Follow unseres Bereichs gibt, nehmen wir dessen erstes Layoutblatt,
1714         // andernfalls wird es Zeit, einen Bereichsfollow zu erzeugen
1715         SwSectionFrm* pNew;
1716 
1717         //Dies kann entfallen, wenn bei existierenden Follows bereits abgekuerzt wurde
1718         SwFrm* pFirst = pLayLeaf->Lower();
1719         // Auch hier muessen zum Loeschen angemeldete SectionFrms ignoriert werden
1720         while( pFirst && pFirst->IsSctFrm() && !((SwSectionFrm*)pFirst)->GetSection() )
1721             pFirst = pFirst->GetNext();
1722         if( pFirst && pFirst->IsSctFrm() && pSect->GetFollow() == pFirst )
1723             pNew = pSect->GetFollow();
1724         else if( MAKEPAGE_NOSECTION == eMakePage )
1725             return pLayLeaf;
1726         else
1727         {
1728             pNew = new SwSectionFrm( *pSect, sal_False );
1729             pNew->InsertBefore( pLayLeaf, pLayLeaf->Lower() );
1730             pNew->Init();
1731             SWRECTFN( pNew )
1732             (pNew->*fnRect->fnMakePos)( pLayLeaf, NULL, sal_True );
1733 
1734             // Wenn unser Bereichsframe einen Nachfolger hat, so muss dieser
1735             // umgehaengt werden hinter den neuen Follow der Bereichsframes.
1736             SwFrm* pTmp = pSect->GetNext();
1737             if( pTmp && pTmp != pSect->GetFollow() )
1738             {
1739                 SwFlowFrm* pNxt;
1740                 SwCntntFrm* pNxtCntnt = NULL;
1741                 if( pTmp->IsCntntFrm() )
1742                 {
1743                     pNxt = (SwCntntFrm*)pTmp;
1744                     pNxtCntnt = (SwCntntFrm*)pTmp;
1745                 }
1746                 else
1747                 {
1748                     pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
1749                     if( pTmp->IsSctFrm() )
1750                         pNxt = (SwSectionFrm*)pTmp;
1751                     else
1752                     {
1753                         ASSERT( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
1754                         pNxt = (SwTabFrm*)pTmp;
1755                     }
1756                     while( !pNxtCntnt && 0 != ( pTmp = pTmp->GetNext() ) )
1757                     {
1758                         if( pTmp->IsCntntFrm() )
1759                             pNxtCntnt = (SwCntntFrm*)pTmp;
1760                         else
1761                             pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
1762                     }
1763                 }
1764                 if( pNxtCntnt )
1765                 {
1766                     SwFtnBossFrm* pOldBoss = pSect->FindFtnBossFrm( sal_True );
1767                     if( pOldBoss == pNxtCntnt->FindFtnBossFrm( sal_True ) )
1768                     {
1769                         SwSaveFtnHeight aHeight( pOldBoss,
1770                             pOldBoss->Frm().Top() + pOldBoss->Frm().Height() );
1771                         pSect->GetUpper()->MoveLowerFtns( pNxtCntnt, pOldBoss,
1772                                     pLayLeaf->FindFtnBossFrm( sal_True ), sal_False );
1773                     }
1774                 }
1775                 ((SwFlowFrm*)pNxt)->MoveSubTree( pLayLeaf, pNew->GetNext() );
1776             }
1777             if( pNew->GetFollow() )
1778                 pNew->SimpleFormat();
1779         }
1780         // Das gesuchte Layoutblatt ist jetzt das erste des ermittelten SctFrms:
1781         pLayLeaf = FIRSTLEAF( pNew );
1782     }
1783     return pLayLeaf;
1784 }
1785 
1786 /*************************************************************************
1787 |*
1788 |*  SwFrm::GetPrevSctLeaf()
1789 |*
1790 |*  Beschreibung        Liefert das vorhergehende LayoutBlatt in das der
1791 |*      Frame gemoved werden kann.
1792 |*  Ersterstellung      AMA 07. Jan. 98
1793 |*  Letzte Aenderung    AMA 07. Jan. 98
1794 |*
1795 |*************************************************************************/
1796 
1797 
GetPrevSctLeaf(MakePageType)1798 SwLayoutFrm *SwFrm::GetPrevSctLeaf( MakePageType )
1799 {
1800     PROTOCOL_ENTER( this, PROT_LEAF, ACT_PREV_SECT, GetUpper()->FindSctFrm() )
1801 
1802     SwLayoutFrm* pCol;
1803     // ColumnFrm beinhalten jetzt stets einen BodyFrm
1804     if( IsColBodyFrm() )
1805         pCol = GetUpper();
1806     else if( GetUpper()->IsColBodyFrm() )
1807         pCol = GetUpper()->GetUpper();
1808     else
1809         pCol = NULL;
1810     sal_Bool bJump = sal_False;
1811     if( pCol )
1812     {
1813         if( pCol->GetPrev() )
1814         {
1815             do
1816             {
1817                 pCol = (SwLayoutFrm*)pCol->GetPrev();
1818                 // Gibt es dort Inhalt?
1819                 if( ((SwLayoutFrm*)pCol->Lower())->Lower() )
1820                 {
1821                     if( bJump )     // Haben wir eine leere Spalte uebersprungen?
1822                         SwFlowFrm::SetMoveBwdJump( sal_True );
1823                     return (SwLayoutFrm*)pCol->Lower();  // Der Spaltenbody
1824                 }
1825                 bJump = sal_True;
1826             } while( pCol->GetPrev() );
1827 
1828             // Hier landen wir, wenn alle Spalten leer sind,
1829             // pCol ist jetzt die erste Spalte, wir brauchen aber den Body:
1830             pCol = (SwLayoutFrm*)pCol->Lower();
1831         }
1832         else
1833             pCol = NULL;
1834     }
1835 
1836     if( bJump )     // Haben wir eine leere Spalte uebersprungen?
1837         SwFlowFrm::SetMoveBwdJump( sal_True );
1838 
1839     // Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann
1840     // nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette
1841     // zuschlagen muessen, ebenso wenn der Bereich einen pPrev hat.
1842     // Jetzt ziehen wir sogar eine leere Spalte in Betracht...
1843     ASSERT( FindSctFrm(), "GetNextSctLeaf: Missing SectionFrm" );
1844     if( ( IsInTab() && !IsTabFrm() ) || FindFooterOrHeader() )
1845         return pCol;
1846 
1847     // === IMPORTANT ===
1848     // Precondition, which needs to be hold, is that the <this> frame can be
1849     // inside a table, but then the found section frame <pSect> is also inside
1850     // this table.
1851     SwSectionFrm *pSect = FindSctFrm();
1852 
1853     // --> OD 2009-01-16 #i95698#
1854     // A table cell containing directly a section does not break - see lcl_FindSectionsInRow(..)
1855     // Thus, a table inside a section, which is inside another table can only
1856     // flow backward in the columns of its section.
1857     // Note: The table cell, which contains the section, can not have a master table cell.
1858     if ( IsTabFrm() && pSect->IsInTab() )
1859     {
1860         return pCol;
1861     }
1862     // <--
1863 
1864     {
1865         SwFrm *pPrv;
1866         if( 0 != ( pPrv = pSect->GetIndPrev() ) )
1867         {
1868             // Herumlungernde, halbtote SectionFrms sollen uns nicht beirren
1869             while( pPrv && pPrv->IsSctFrm() && !((SwSectionFrm*)pPrv)->GetSection() )
1870                 pPrv = pPrv->GetPrev();
1871             if( pPrv )
1872                 return pCol;
1873         }
1874     }
1875 
1876     const sal_Bool bBody = IsInDocBody();
1877     const sal_Bool bFly  = IsInFly();
1878 
1879     SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
1880     SwLayoutFrm *pPrevLeaf = 0;
1881 
1882     while ( pLayLeaf )
1883     {
1884         //In Tabellen oder Bereiche geht's niemals hinein.
1885         if ( pLayLeaf->IsInTab() || pLayLeaf->IsInSct() )
1886         {
1887             pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1888         }
1889         else if ( bBody && pLayLeaf->IsInDocBody() )
1890         {
1891             // If there is a pLayLeaf has a lower pLayLeaf is the frame we are looking for.
1892             // Exception: pLayLeaf->Lower() is a zombie section frame
1893             const SwFrm* pTmp = pLayLeaf->Lower();
1894             // OD 11.04.2003 #108824# - consider, that the zombie section frame
1895             // can have frame below it in the found layout leaf.
1896             // Thus, skipping zombie section frame, if possible.
1897             while ( pTmp && pTmp->IsSctFrm() &&
1898                     !( static_cast<const SwSectionFrm*>(pTmp)->GetSection() ) &&
1899                     pTmp->GetNext()
1900                   )
1901             {
1902                 pTmp = pTmp->GetNext();
1903             }
1904             if ( pTmp &&
1905                  ( !pTmp->IsSctFrm() ||
1906                    ( static_cast<const SwSectionFrm*>(pTmp)->GetSection() )
1907                  )
1908                )
1909             {
1910                 break;
1911             }
1912             pPrevLeaf = pLayLeaf;
1913             pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1914             if ( pLayLeaf )
1915                 SwFlowFrm::SetMoveBwdJump( sal_True );
1916         }
1917         else if ( bFly )
1918             break;  //Cntnts in Flys sollte jedes Layout-Blatt recht sein. Warum?
1919         else
1920             pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1921     }
1922     if( !pLayLeaf )
1923     {
1924         if( !pPrevLeaf )
1925             return pCol;
1926         pLayLeaf = pPrevLeaf;
1927     }
1928 
1929     SwSectionFrm* pNew = NULL;
1930     // Zunaechst einmal an das Ende des Layoutblatts gehen
1931     SwFrm *pTmp = pLayLeaf->Lower();
1932     if( pTmp )
1933     {
1934         while( pTmp->GetNext() )
1935             pTmp = pTmp->GetNext();
1936         if( pTmp->IsSctFrm() )
1937         {
1938             // Halbtote stoeren hier nur...
1939             while( !((SwSectionFrm*)pTmp)->GetSection() && pTmp->GetPrev() &&
1940                     pTmp->GetPrev()->IsSctFrm() )
1941                 pTmp = pTmp->GetPrev();
1942             if( ((SwSectionFrm*)pTmp)->GetFollow() == pSect )
1943                 pNew = (SwSectionFrm*)pTmp;
1944         }
1945     }
1946     if( !pNew )
1947     {
1948         pNew = new SwSectionFrm( *pSect, sal_True );
1949         pNew->InsertBefore( pLayLeaf, NULL );
1950         pNew->Init();
1951         SWRECTFN( pNew )
1952         (pNew->*fnRect->fnMakePos)( pLayLeaf, pNew->GetPrev(), sal_True );
1953 
1954         pLayLeaf = FIRSTLEAF( pNew );
1955         if( !pNew->Lower() )    // einspaltige Bereiche formatieren
1956         {
1957             pNew->MakePos();
1958             pLayLeaf->Format(); // damit die PrtArea fuers MoveBwd stimmt
1959         }
1960         else
1961             pNew->SimpleFormat();
1962     }
1963     else
1964     {
1965         pLayLeaf = FIRSTLEAF( pNew );
1966         if( pLayLeaf->IsColBodyFrm() )
1967         {
1968             // In existent section columns we're looking for the last not empty
1969             // column.
1970             SwLayoutFrm *pTmpLay = pLayLeaf;
1971             while( pLayLeaf->GetUpper()->GetNext() )
1972             {
1973                 pLayLeaf = (SwLayoutFrm*)((SwLayoutFrm*)pLayLeaf->GetUpper()->GetNext())->Lower();
1974                 if( pLayLeaf->Lower() )
1975                     pTmpLay = pLayLeaf;
1976             }
1977             // If we skipped an empty column, we've to set the jump-flag
1978             if( pLayLeaf != pTmpLay )
1979             {
1980                 pLayLeaf = pTmpLay;
1981                 SwFlowFrm::SetMoveBwdJump( sal_True );
1982             }
1983         }
1984     }
1985     return pLayLeaf;
1986 }
1987 
lcl_DeadLine(const SwFrm * pFrm)1988 SwTwips lcl_DeadLine( const SwFrm* pFrm )
1989 {
1990     const SwLayoutFrm* pUp = pFrm->GetUpper();
1991     while( pUp && pUp->IsInSct() )
1992     {
1993         if( pUp->IsSctFrm() )
1994             pUp = pUp->GetUpper();
1995         // Spalten jetzt mit BodyFrm
1996         else if( pUp->IsColBodyFrm() && pUp->GetUpper()->GetUpper()->IsSctFrm() )
1997             pUp = pUp->GetUpper()->GetUpper();
1998         else
1999             break;
2000     }
2001     SWRECTFN( pFrm )
2002     return pUp ? (pUp->*fnRect->fnGetPrtBottom)() :
2003                  (pFrm->Frm().*fnRect->fnGetBottom)();
2004 }
2005 
2006 // SwSectionFrm::Growable(..) prueft, ob der SectionFrm noch wachsen kann,
2007 // ggf. muss die Umgebung gefragt werden
2008 
Growable() const2009 sal_Bool SwSectionFrm::Growable() const
2010 {
2011     SWRECTFN( this )
2012     if( (*fnRect->fnYDiff)( lcl_DeadLine( this ),
2013         (Frm().*fnRect->fnGetBottom)() ) > 0 )
2014         return sal_True;
2015 
2016     return ( GetUpper() && ((SwFrm*)GetUpper())->Grow( LONG_MAX, sal_True ) );
2017 }
2018 
2019 /*************************************************************************
2020 |*
2021 |*  SwSectionFrm::_Grow(), _Shrink()
2022 |*
2023 |*  Ersterstellung      AMA 14. Jan. 98
2024 |*  Letzte Aenderung    AMA 14. Jan. 98
2025 |*
2026 |*************************************************************************/
2027 
_Grow(SwTwips nDist,sal_Bool bTst)2028 SwTwips SwSectionFrm::_Grow( SwTwips nDist, sal_Bool bTst )
2029 {
2030     if ( !IsColLocked() && !HasFixSize() )
2031     {
2032         SWRECTFN( this )
2033         long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2034         if( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
2035             nDist = LONG_MAX - nFrmHeight;
2036 
2037         if ( nDist <= 0L )
2038             return 0L;
2039 
2040         sal_Bool bInCalcCntnt = GetUpper() && IsInFly() && FindFlyFrm()->IsLocked();
2041         // OD 2004-03-15 #116561# - allow grow in online layout
2042         sal_Bool bGrow = !Lower() || !Lower()->IsColumnFrm() || !Lower()->GetNext() ||
2043              GetSection()->GetFmt()->GetBalancedColumns().GetValue();
2044         if( !bGrow )
2045         {
2046              const ViewShell *pSh = getRootFrm()->GetCurrShell();
2047              bGrow = pSh && pSh->GetViewOptions()->getBrowseMode();
2048         }
2049         if( bGrow )
2050         {
2051             SwTwips nGrow;
2052             if( IsInFtn() )
2053                 nGrow = 0;
2054             else
2055             {
2056                 nGrow = lcl_DeadLine( this );
2057                 nGrow = (*fnRect->fnYDiff)( nGrow,
2058                                            (Frm().*fnRect->fnGetBottom)() );
2059             }
2060             SwTwips nSpace = nGrow;
2061             if( !bInCalcCntnt && nGrow < nDist && GetUpper() )
2062                 nGrow += GetUpper()->Grow( LONG_MAX, sal_True );
2063 
2064             if( nGrow > nDist )
2065                 nGrow = nDist;
2066             if( nGrow <= 0 )
2067             {
2068                 nGrow = 0;
2069                 if( nDist && !bTst )
2070                 {
2071                     if( bInCalcCntnt )
2072                         _InvalidateSize();
2073                     else
2074                         InvalidateSize();
2075                 }
2076             }
2077             else if( !bTst )
2078             {
2079                 if( bInCalcCntnt )
2080                     _InvalidateSize();
2081                 else if( nSpace < nGrow &&  nDist != nSpace + GetUpper()->
2082                          Grow( nGrow - nSpace, sal_False ) )
2083                     InvalidateSize();
2084                 else
2085                 {
2086                     const SvxGraphicPosition ePos =
2087                         GetAttrSet()->GetBackground().GetGraphicPos();
2088                     if ( GPOS_RT < ePos && GPOS_TILED != ePos )
2089                     {
2090                         SetCompletePaint();
2091                         InvalidatePage();
2092                     }
2093                     if( GetUpper() && GetUpper()->IsHeaderFrm() )
2094                         GetUpper()->InvalidateSize();
2095                 }
2096                 (Frm().*fnRect->fnAddBottom)( nGrow );
2097                 long nPrtHeight = (Prt().*fnRect->fnGetHeight)() + nGrow;
2098                 (Prt().*fnRect->fnSetHeight)( nPrtHeight );
2099 
2100                 if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2101                 {
2102                     SwFrm* pTmp = Lower();
2103                     do
2104                     {
2105                         pTmp->_InvalidateSize();
2106                         pTmp = pTmp->GetNext();
2107                     } while ( pTmp );
2108                     _InvalidateSize();
2109                 }
2110                 if( GetNext() )
2111                 {
2112                     SwFrm *pFrm = GetNext();
2113                     while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
2114                         pFrm = pFrm->GetNext();
2115                     if( pFrm )
2116                     {
2117                         if( bInCalcCntnt )
2118                             pFrm->_InvalidatePos();
2119                         else
2120                             pFrm->InvalidatePos();
2121                     }
2122                 }
2123                 // --> OD 2004-07-05 #i28701# - Due to the new object positioning
2124                 // the frame on the next page/column can flow backward (e.g. it
2125                 // was moved forward due to the positioning of its objects ).
2126                 // Thus, invalivate this next frame, if document compatibility
2127                 // option 'Consider wrapping style influence on object positioning' is ON.
2128                 else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
2129                 {
2130                     InvalidateNextPos();
2131                 }
2132                 // <--
2133             }
2134             return nGrow;
2135         }
2136         if ( !bTst )
2137         {
2138             if( bInCalcCntnt )
2139                 _InvalidateSize();
2140             else
2141                 InvalidateSize();
2142         }
2143     }
2144     return 0L;
2145 }
2146 
_Shrink(SwTwips nDist,sal_Bool bTst)2147 SwTwips SwSectionFrm::_Shrink( SwTwips nDist, sal_Bool bTst )
2148 {
2149     if ( Lower() && !IsColLocked() && !HasFixSize() )
2150     {
2151         if( ToMaximize( sal_False ) )
2152         {
2153             if( !bTst )
2154                 InvalidateSize();
2155         }
2156         else
2157         {
2158             SWRECTFN( this )
2159             long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2160             if ( nDist > nFrmHeight )
2161                 nDist = nFrmHeight;
2162 
2163             if ( Lower()->IsColumnFrm() && Lower()->GetNext() && // FtnAtEnd
2164                  !GetSection()->GetFmt()->GetBalancedColumns().GetValue() )
2165             {   //Bei Spaltigkeit ubernimmt das Format die Kontrolle ueber
2166                 //das Wachstum (wg. des Ausgleichs).
2167                 if ( !bTst )
2168                     InvalidateSize();
2169                 return nDist;
2170             }
2171             else if( !bTst )
2172             {
2173                 const SvxGraphicPosition ePos =
2174                     GetAttrSet()->GetBackground().GetGraphicPos();
2175                 if ( GPOS_RT < ePos && GPOS_TILED != ePos )
2176                 {
2177                     SetCompletePaint();
2178                     InvalidatePage();
2179                 }
2180                 (Frm().*fnRect->fnAddBottom)( -nDist );
2181                 long nPrtHeight = (Prt().*fnRect->fnGetHeight)() - nDist;
2182                 (Prt().*fnRect->fnSetHeight)( nPrtHeight );
2183 
2184                 SwTwips nReal = 0;
2185                 // We do not allow a section frame to shrink the its upper
2186                 // footer frame. This is because in the calculation of a
2187                 // footer frame, the content of the section frame is _not_
2188                 // calculated. If there is a fly frame overlapping with the
2189                 // footer frame, the section frame is not affected by this
2190                 // during the calculation of the footer frame size.
2191                 // The footer frame does not grow in its FormatSize function
2192                 // but during the calculation of the content of the section
2193                 // frame. The section frame grows until some of its text is
2194                 // located on top of the fly frame. The next call of CalcCntnt
2195                 // tries to shrink the section and here it would also shrink
2196                 // the footer. This may not happen, because shrinking the footer
2197                 // would cause the top of the section frame to overlap with the
2198                 // fly frame again, this would result in a perfect loop.
2199                 if( GetUpper() && !GetUpper()->IsFooterFrm() )
2200                     nReal = GetUpper()->Shrink( nDist, bTst );
2201 
2202                 if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2203                 {
2204                     SwFrm* pTmp = Lower();
2205                     do
2206                     {
2207                         pTmp->_InvalidateSize();
2208                         pTmp = pTmp->GetNext();
2209                     } while ( pTmp );
2210                 }
2211                 if( GetNext() )
2212                 {
2213                     SwFrm* pFrm = GetNext();
2214                     while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
2215                         pFrm = pFrm->GetNext();
2216                     if( pFrm )
2217                         pFrm->InvalidatePos();
2218                     else
2219                         SetRetouche();
2220                 }
2221                 else
2222                     SetRetouche();
2223                 return nDist;
2224             }
2225         }
2226     }
2227     return 0L;
2228 }
2229 
2230 /*************************************************************************
2231 |*
2232 |*  SwSectionFrm::MoveAllowed()
2233 |*
2234 |*  Ersterstellung      MA 08. Oct. 98
2235 |*  Letzte Aenderung    MA 08. Oct. 98
2236 |*
2237 |*  Wann sind Frms innerhalb eines SectionFrms moveable?
2238 |*  Wenn sie noch nicht in der letzten Spalte des SectionFrms sind,
2239 |*  wenn es einen Follow gibt,
2240 |*  wenn der SectionFrm nicht mehr wachsen kann, wird es komplizierter,
2241 |*  dann kommt es darauf an, ob der SectionFrm ein naechstes Layoutblatt
2242 |*  finden kann. In (spaltigen/verketteten) Flys wird dies via GetNextLayout
2243 |*  geprueft, in Tabellen und in Kopf/Fusszeilen gibt es keins, im DocBody
2244 |*  und auch im Fussnoten dagegen immer.
2245 |*
2246 |*  Benutzt wird diese Routine im TxtFormatter, um zu entscheiden, ob ein
2247 |*  (Absatz-)Follow erzeugt werden darf oder ob der Absatz zusammenhalten muss.
2248 |*
2249 |*************************************************************************/
2250 
MoveAllowed(const SwFrm * pFrm) const2251 sal_Bool SwSectionFrm::MoveAllowed( const SwFrm* pFrm) const
2252 {
2253     // Gibt es einen Follow oder ist der Frame nicht in der letzten Spalte?
2254     if( HasFollow() || ( pFrm->GetUpper()->IsColBodyFrm() &&
2255         pFrm->GetUpper()->GetUpper()->GetNext() ) )
2256         return sal_True;
2257     if( pFrm->IsInFtn() )
2258     {
2259         if( IsInFtn() )
2260         {
2261             if( GetUpper()->IsInSct() )
2262             {
2263                 if( Growable() )
2264                     return sal_False;
2265                 return GetUpper()->FindSctFrm()->MoveAllowed( this );
2266             }
2267             else
2268                 return sal_True;
2269         }
2270         // The content of footnote inside a columned sectionfrm is moveable
2271         // except in the last column
2272         const SwLayoutFrm *pLay = pFrm->FindFtnFrm()->GetUpper()->GetUpper();
2273         if( pLay->IsColumnFrm() && pLay->GetNext() )
2274         {
2275             // The first paragraph in the first footnote in the first column
2276             // in the sectionfrm at the top of the page is not moveable,
2277             // if the columnbody is empty.
2278             sal_Bool bRet = sal_False;
2279             if( pLay->GetIndPrev() || pFrm->GetIndPrev() ||
2280                 pFrm->FindFtnFrm()->GetPrev() )
2281                 bRet = sal_True;
2282             else
2283             {
2284                 SwLayoutFrm* pBody = ((SwColumnFrm*)pLay)->FindBodyCont();
2285                 if( pBody && pBody->Lower() )
2286                     bRet = sal_True;
2287             }
2288             if( bRet && ( IsFtnAtEnd() || !Growable() ) )
2289                 return sal_True;
2290         }
2291     }
2292     // Oder kann der Bereich noch wachsen?
2293     if( !IsColLocked() && Growable() )
2294         return sal_False;
2295     // Jetzt muss untersucht werden, ob es ein Layoutblatt gibt, in dem
2296     // ein Bereichsfollow erzeugt werden kann.
2297     if( IsInTab() || ( !IsInDocBody() && FindFooterOrHeader() ) )
2298         return sal_False; // In Tabellen/Kopf/Fusszeilen geht es nicht
2299     if( IsInFly() ) // Bei spaltigen oder verketteten Rahmen
2300         return 0 != ((SwFrm*)GetUpper())->GetNextLeaf( MAKEPAGE_NONE );
2301     return sal_True;
2302 }
2303 
2304 /** Called for a frame inside a section with no direct previous frame (or only
2305     previous empty section frames) the previous frame of the outer section is
2306     returned, if the frame is the first flowing content of this section.
2307 
2308     Note: For a frame inside a table frame, which is inside a section frame,
2309           NULL is returned.
2310 */
_GetIndPrev() const2311 SwFrm* SwFrm::_GetIndPrev() const
2312 {
2313     SwFrm *pRet = NULL;
2314     // --> OD 2007-09-04 #i79774#, #b659654#
2315     // Do not assert, if the frame has a direct previous frame, because it
2316     // could be an empty section frame. The caller has to assure, that the
2317     // frame has no direct previous frame or only empty section frames as
2318     // previous frames.
2319     ASSERT( /*!pPrev &&*/ IsInSct(), "Why?" );
2320     // <--
2321     const SwFrm* pSct = GetUpper();
2322     if( !pSct )
2323         return NULL;
2324     if( pSct->IsSctFrm() )
2325         pRet = pSct->GetIndPrev();
2326     else if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
2327     {
2328         // Do not return the previous frame of the outer section, if in one
2329         // of the previous columns is content.
2330         const SwFrm* pCol = GetUpper()->GetUpper()->GetPrev();
2331         while( pCol )
2332         {
2333             ASSERT( pCol->IsColumnFrm(), "GetIndPrev(): ColumnFrm expected" );
2334             ASSERT( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
2335                     "GetIndPrev(): Where's the body?");
2336             if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
2337                 return NULL;
2338             pCol = pCol->GetPrev();
2339         }
2340         pRet = pSct->GetIndPrev();
2341     }
2342 
2343     // skip empty section frames
2344     while( pRet && pRet->IsSctFrm() && !((SwSectionFrm*)pRet)->GetSection() )
2345         pRet = pRet->GetIndPrev();
2346     return pRet;
2347 }
2348 
_GetIndNext()2349 SwFrm* SwFrm::_GetIndNext()
2350 {
2351     ASSERT( !pNext && IsInSct(), "Why?" );
2352     SwFrm* pSct = GetUpper();
2353     if( !pSct )
2354         return NULL;
2355     if( pSct->IsSctFrm() )
2356         return pSct->GetIndNext();
2357     if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
2358     {   // Wir duerfen nur den Nachfolger des SectionFrms zurueckliefern,
2359         // wenn in keiner folgenden Spalte mehr Inhalt ist
2360         SwFrm* pCol = GetUpper()->GetUpper()->GetNext();
2361         while( pCol )
2362         {
2363             ASSERT( pCol->IsColumnFrm(), "GetIndNext(): ColumnFrm expected" );
2364             ASSERT( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
2365                     "GetIndNext(): Where's the body?");
2366             if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
2367                 return NULL;
2368             pCol = pCol->GetNext();
2369         }
2370         return pSct->GetIndNext();
2371     }
2372     return NULL;
2373 }
2374 
IsDescendantFrom(const SwSectionFmt * pFmt) const2375 sal_Bool SwSectionFrm::IsDescendantFrom( const SwSectionFmt* pFmt ) const
2376 {
2377     if( !pSection || !pFmt )
2378         return sal_False;
2379     const SwSectionFmt *pMyFmt = pSection->GetFmt();
2380     while( pFmt != pMyFmt )
2381     {
2382         if( pMyFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2383             pMyFmt = (SwSectionFmt*)pMyFmt->GetRegisteredIn();
2384         else
2385             return sal_False;
2386     }
2387     return sal_True;
2388 }
2389 
CalcFtnAtEndFlag()2390 void SwSectionFrm::CalcFtnAtEndFlag()
2391 {
2392     SwSectionFmt *pFmt = GetSection()->GetFmt();
2393     sal_uInt16 nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
2394     bFtnAtEnd = FTNEND_ATPGORDOCEND != nVal;
2395     bOwnFtnNum = FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
2396                  FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
2397     while( !bFtnAtEnd && !bOwnFtnNum )
2398     {
2399         if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2400             pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
2401         else
2402             break;
2403         nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
2404         if( FTNEND_ATPGORDOCEND != nVal )
2405         {
2406             bFtnAtEnd = sal_True;
2407             bOwnFtnNum = bOwnFtnNum ||FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
2408                          FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
2409         }
2410     }
2411 }
2412 
IsEndnoteAtMyEnd() const2413 sal_Bool SwSectionFrm::IsEndnoteAtMyEnd() const
2414 {
2415     return pSection->GetFmt()->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2416 }
2417 
CalcEndAtEndFlag()2418 void SwSectionFrm::CalcEndAtEndFlag()
2419 {
2420     SwSectionFmt *pFmt = GetSection()->GetFmt();
2421     bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2422     while( !bEndnAtEnd )
2423     {
2424         if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2425             pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
2426         else
2427             break;
2428         bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2429     }
2430 }
2431 
2432 /*************************************************************************
2433 |*
2434 |*  SwSectionFrm::Modify()
2435 |*
2436 |*  Ersterstellung      MA 08. Oct. 98
2437 |*  Letzte Aenderung    MA 08. Oct. 98
2438 |*
2439 |*************************************************************************/
2440 
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)2441 void SwSectionFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
2442 {
2443     sal_uInt8 nInvFlags = 0;
2444 
2445     if( pNew && RES_ATTRSET_CHG == pNew->Which() )
2446     {
2447         SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
2448         SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
2449         SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
2450         SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
2451         while( sal_True )
2452         {
2453             _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
2454                          (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
2455                          &aOldSet, &aNewSet );
2456             if( aNIter.IsAtEnd() )
2457                 break;
2458             aNIter.NextItem();
2459             aOIter.NextItem();
2460         }
2461         if ( aOldSet.Count() || aNewSet.Count() )
2462             SwLayoutFrm::Modify( &aOldSet, &aNewSet );
2463     }
2464     else
2465         _UpdateAttr( pOld, pNew, nInvFlags );
2466 
2467     if ( nInvFlags != 0 )
2468     {
2469         if ( nInvFlags & 0x01 )
2470             InvalidateSize();
2471         if ( nInvFlags & 0x10 )
2472             SetCompletePaint();
2473     }
2474 }
2475 
SwClientNotify(const SwModify & rMod,const SfxHint & rHint)2476 void SwSectionFrm::SwClientNotify( const SwModify& rMod, const SfxHint& rHint )
2477 {
2478     // --> OD #i117863#
2479     const SwSectionFrmMoveAndDeleteHint* pHint =
2480                     dynamic_cast<const SwSectionFrmMoveAndDeleteHint*>(&rHint);
2481     if ( pHint && pHint->GetId() == SFX_HINT_DYING && &rMod == GetRegisteredIn() )
2482     {
2483         SwSectionFrm::MoveCntntAndDelete( this, pHint->IsSaveCntnt() );
2484     }
2485     // <--
2486 }
2487 
_UpdateAttr(const SfxPoolItem * pOld,const SfxPoolItem * pNew,sal_uInt8 & rInvFlags,SwAttrSetChg * pOldSet,SwAttrSetChg * pNewSet)2488 void SwSectionFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
2489                             sal_uInt8 &rInvFlags,
2490                             SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
2491 {
2492     sal_Bool bClear = sal_True;
2493     const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
2494     switch( nWhich )
2495     {   // Mehrspaltigkeit in Fussnoten unterdruecken...
2496         case RES_FMT_CHG:
2497         {
2498             const SwFmtCol& rNewCol = GetFmt()->GetCol();
2499             if( !IsInFtn() )
2500             {
2501                 //Dummer Fall. Bei der Zuweisung einer Vorlage k?nnen wir uns
2502                 //nicht auf das alte Spaltenattribut verlassen. Da diese
2503                 //wenigstens anzahlgemass fuer ChgColumns vorliegen muessen,
2504                 //bleibt uns nur einen temporaeres Attribut zu basteln.
2505                 SwFmtCol aCol;
2506                 if ( Lower() && Lower()->IsColumnFrm() )
2507                 {
2508                     sal_uInt16 nCol = 0;
2509                     SwFrm *pTmp = Lower();
2510                     do
2511                     {   ++nCol;
2512                         pTmp = pTmp->GetNext();
2513                     } while ( pTmp );
2514                     aCol.Init( nCol, 0, 1000 );
2515                 }
2516                 sal_Bool bChgFtn = IsFtnAtEnd();
2517                 sal_Bool bChgEndn = IsEndnAtEnd();
2518                 sal_Bool bChgMyEndn = IsEndnoteAtMyEnd();
2519                 CalcFtnAtEndFlag();
2520                 CalcEndAtEndFlag();
2521                 bChgFtn = ( bChgFtn != IsFtnAtEnd() ) ||
2522                           ( bChgEndn != IsEndnAtEnd() ) ||
2523                           ( bChgMyEndn != IsEndnoteAtMyEnd() );
2524                 ChgColumns( aCol, rNewCol, bChgFtn );
2525                 rInvFlags |= 0x10;
2526             }
2527             rInvFlags |= 0x01;
2528             bClear = sal_False;
2529         }
2530             break;
2531 
2532         case RES_COL:
2533             if( !IsInFtn() )
2534             {
2535                 ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
2536                 rInvFlags |= 0x11;
2537             }
2538             break;
2539 
2540         case RES_FTN_AT_TXTEND:
2541             if( !IsInFtn() )
2542             {
2543                 sal_Bool bOld = IsFtnAtEnd();
2544                 CalcFtnAtEndFlag();
2545                 if( bOld != IsFtnAtEnd() )
2546                 {
2547                     const SwFmtCol& rNewCol = GetFmt()->GetCol();
2548                     ChgColumns( rNewCol, rNewCol, sal_True );
2549                     rInvFlags |= 0x01;
2550                 }
2551             }
2552             break;
2553 
2554         case RES_END_AT_TXTEND:
2555             if( !IsInFtn() )
2556             {
2557                 sal_Bool bOld = IsEndnAtEnd();
2558                 sal_Bool bMyOld = IsEndnoteAtMyEnd();
2559                 CalcEndAtEndFlag();
2560                 if( bOld != IsEndnAtEnd() || bMyOld != IsEndnoteAtMyEnd())
2561                 {
2562                     const SwFmtCol& rNewCol = GetFmt()->GetCol();
2563                     ChgColumns( rNewCol, rNewCol, sal_True );
2564                     rInvFlags |= 0x01;
2565                 }
2566             }
2567             break;
2568         case RES_COLUMNBALANCE:
2569             rInvFlags |= 0x01;
2570             break;
2571 
2572         case RES_FRAMEDIR :
2573             SetDerivedR2L( sal_False );
2574             CheckDirChange();
2575             break;
2576 
2577         case RES_PROTECT:
2578             {
2579                 ViewShell *pSh = getRootFrm()->GetCurrShell();
2580                 if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
2581                     pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
2582             }
2583             break;
2584 
2585         default:
2586             bClear = sal_False;
2587     }
2588     if ( bClear )
2589     {
2590         if ( pOldSet || pNewSet )
2591         {
2592             if ( pOldSet )
2593                 pOldSet->ClearItem( nWhich );
2594             if ( pNewSet )
2595                 pNewSet->ClearItem( nWhich );
2596         }
2597         else
2598             SwLayoutFrm::Modify( pOld, pNew );
2599     }
2600 }
2601 
2602 /*-----------------09.06.99 14:58-------------------
2603  * SwSectionFrm::ToMaximize(..): A follow or a ftncontainer at the end of the
2604  * page causes a maximal Size of the sectionframe.
2605  * --------------------------------------------------*/
2606 
ToMaximize(sal_Bool bCheckFollow) const2607 sal_Bool SwSectionFrm::ToMaximize( sal_Bool bCheckFollow ) const
2608 {
2609     if( HasFollow() )
2610     {
2611         if( !bCheckFollow ) // Don't check superfluous follows
2612             return sal_True;
2613         const SwSectionFrm* pFoll = GetFollow();
2614         while( pFoll && pFoll->IsSuperfluous() )
2615             pFoll = pFoll->GetFollow();
2616         if( pFoll )
2617             return sal_True;
2618     }
2619     if( IsFtnAtEnd() )
2620         return sal_False;
2621     const SwFtnContFrm* pCont = ContainsFtnCont();
2622     if( !IsEndnAtEnd() )
2623         return 0 != pCont;
2624     sal_Bool bRet = sal_False;
2625     while( pCont && !bRet )
2626     {
2627         if( pCont->FindFootNote() )
2628             bRet = sal_True;
2629         else
2630             pCont = ContainsFtnCont( pCont );
2631     }
2632     return bRet;
2633 }
2634 
2635 /*-----------------09.06.99 15:07-------------------
2636  * sal_Bool SwSectionFrm::ContainsFtnCont()
2637  * checks every Column for FtnContFrms.
2638  * --------------------------------------------------*/
2639 
ContainsFtnCont(const SwFtnContFrm * pCont) const2640 SwFtnContFrm* SwSectionFrm::ContainsFtnCont( const SwFtnContFrm* pCont ) const
2641 {
2642     SwFtnContFrm* pRet = NULL;
2643     const SwLayoutFrm* pLay;
2644     if( pCont )
2645     {
2646         pLay = pCont->FindFtnBossFrm( 0 );
2647         ASSERT( IsAnLower( pLay ), "ConatainsFtnCont: Wrong FtnContainer" );
2648         pLay = (SwLayoutFrm*)pLay->GetNext();
2649     }
2650     else if( Lower() && Lower()->IsColumnFrm() )
2651         pLay = (SwLayoutFrm*)Lower();
2652     else
2653         pLay = NULL;
2654     while ( !pRet && pLay )
2655     {
2656         if( pLay->Lower() && pLay->Lower()->GetNext() )
2657         {
2658             ASSERT( pLay->Lower()->GetNext()->IsFtnContFrm(),
2659                     "ToMaximize: Unexspected Frame" );
2660             pRet = (SwFtnContFrm*)pLay->Lower()->GetNext();
2661         }
2662         ASSERT( !pLay->GetNext() || pLay->GetNext()->IsLayoutFrm(),
2663                 "ToMaximize: ColFrm exspected" );
2664         pLay = (SwLayoutFrm*)pLay->GetNext();
2665     }
2666     return pRet;
2667 }
2668 
InvalidateFtnPos()2669 void SwSectionFrm::InvalidateFtnPos()
2670 {
2671     SwFtnContFrm* pCont = ContainsFtnCont( NULL );
2672     if( pCont )
2673     {
2674         SwFrm *pTmp = pCont->ContainsCntnt();
2675         if( pTmp )
2676             pTmp->_InvalidatePos();
2677     }
2678 }
2679 
2680 /*-----------------18.03.99 10:37-------------------
2681  * SwSectionFrm::Undersize() liefert den Betrag, um den der Bereich gern
2682  * groesser waere, wenn in ihm Undersized TxtFrms liegen, ansonsten Null.
2683  * Das Undersized-Flag wird ggf. korrigiert.
2684  * --------------------------------------------------*/
2685 
Undersize(sal_Bool bOverSize)2686 long SwSectionFrm::Undersize( sal_Bool bOverSize )
2687 {
2688     bUndersized = sal_False;
2689     SWRECTFN( this )
2690     long nRet = InnerHeight() - (Prt().*fnRect->fnGetHeight)();
2691     if( nRet > 0 )
2692         bUndersized = sal_True;
2693     else if( !bOverSize )
2694         nRet = 0;
2695     return nRet;
2696 }
2697 
2698 /// OD 01.04.2003 #108446# - determine next frame for footnote/endnote formatting
2699 /// before format of current one, because current one can move backward.
2700 /// After moving backward to a previous page method <FindNext()> will return
2701 /// the text frame presenting the first page footnote, if it exists. Thus, the
2702 /// rest of the footnote/endnote container would not be formatted.
CalcFtnCntnt()2703 void SwSectionFrm::CalcFtnCntnt()
2704 {
2705     SwFtnContFrm* pCont = ContainsFtnCont();
2706     if( pCont )
2707     {
2708         SwFrm* pFrm = pCont->ContainsAny();
2709         if( pFrm )
2710             pCont->Calc();
2711         while( pFrm && IsAnLower( pFrm ) )
2712         {
2713             SwFtnFrm* pFtn = pFrm->FindFtnFrm();
2714             if( pFtn )
2715                 pFtn->Calc();
2716             // OD 01.04.2003 #108446# - determine next frame before format current frame.
2717             SwFrm* pNextFrm = 0;
2718             {
2719                 if( pFrm->IsSctFrm() )
2720                 {
2721                     pNextFrm = static_cast<SwSectionFrm*>(pFrm)->ContainsAny();
2722                 }
2723                 if( !pNextFrm )
2724                 {
2725                     pNextFrm = pFrm->FindNext();
2726                 }
2727             }
2728             pFrm->Calc();
2729             pFrm = pNextFrm;
2730         }
2731     }
2732 }
2733 
2734 /* -----------------09.02.99 14:26-------------------
2735  * Wenn ein SectionFrm leerlaeuft, z.B. weil sein Inhalt die Seite/Spalte wechselt,
2736  * so wird er nicht sofort zerstoert (es koennte noch jemand auf dem Stack einen Pointer
2737  * auf ihn halten), sondern er traegt sich in eine Liste am RootFrm ein, die spaeter
2738  * abgearbeitet wird (in LayAction::Action u.a.). Seine Groesse wird auf Null gesetzt und
2739  * sein Zeiger auf seine Section ebenfalls. Solche zum Loeschen vorgesehene SectionFrms
2740  * muessen vom Layout/beim Formatieren ignoriert werden.
2741  *
2742  * Mit InsertEmptySct nimmt der RootFrm einen SectionFrm in die Liste auf,
2743  * mit RemoveFromList kann ein SectionFrm wieder aus der Liste entfernt werden (Dtor),
2744  * mit DeleteEmptySct wird die Liste abgearbeitet und die SectionFrms zerstoert
2745  * --------------------------------------------------*/
2746 
InsertEmptySct(SwSectionFrm * pDel)2747 void SwRootFrm::InsertEmptySct( SwSectionFrm* pDel )
2748 {
2749     if( !pDestroy )
2750         pDestroy = new SwDestroyList;
2751     sal_uInt16 nPos;
2752     if( !pDestroy->Seek_Entry( pDel, &nPos ) )
2753         pDestroy->Insert( pDel );
2754 }
2755 
_DeleteEmptySct()2756 void SwRootFrm::_DeleteEmptySct()
2757 {
2758     ASSERT( pDestroy, "Keine Liste, keine Kekse" );
2759     while( pDestroy->Count() )
2760     {
2761         SwSectionFrm* pSect = (*pDestroy)[0];
2762         pDestroy->Remove( sal_uInt16(0) );
2763         ASSERT( !pSect->IsColLocked() && !pSect->IsJoinLocked(),
2764                 "DeleteEmptySct: Locked SectionFrm" );
2765         if( !pSect->Frm().HasArea() && !pSect->ContainsCntnt() )
2766         {
2767             SwLayoutFrm* pUp = pSect->GetUpper();
2768             pSect->Remove();
2769             delete pSect;
2770             if( pUp && !pUp->Lower() )
2771             {
2772                 if( pUp->IsPageBodyFrm() )
2773                     pUp->getRootFrm()->SetSuperfluous();
2774                 else if( pUp->IsFtnFrm() && !pUp->IsColLocked() &&
2775                     pUp->GetUpper() )
2776                 {
2777                     pUp->Cut();
2778                     delete pUp;
2779                 }
2780             }
2781         }
2782         else {
2783             ASSERT( pSect->GetSection(), "DeleteEmptySct: Halbtoter SectionFrm?!" );
2784         }
2785     }
2786 }
2787 
_RemoveFromList(SwSectionFrm * pSct)2788 void SwRootFrm::_RemoveFromList( SwSectionFrm* pSct )
2789 {
2790     ASSERT( pDestroy, "Where's my list?" );
2791     sal_uInt16 nPos;
2792     if( pDestroy->Seek_Entry( pSct, &nPos ) )
2793         pDestroy->Remove( nPos );
2794 }
2795 
2796 #ifdef DBG_UTIL
2797 
IsInDelList(SwSectionFrm * pSct) const2798 sal_Bool SwRootFrm::IsInDelList( SwSectionFrm* pSct ) const
2799 {
2800     sal_uInt16 nPos;
2801     return ( pDestroy && pDestroy->Seek_Entry( pSct, &nPos ) );
2802 }
2803 
2804 #endif
2805 
IsBalancedSection() const2806 bool SwSectionFrm::IsBalancedSection() const
2807 {
2808     bool bRet = false;
2809     if ( GetSection() && Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2810     {
2811         bRet = !GetSection()->GetFmt()->GetBalancedColumns().GetValue();
2812     }
2813     return bRet;
2814 }
2815 
2816