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