update credits
[LibreOffice.git] / sw / source / core / layout / sectfrm.cxx
blob9722b23c2057a5cbd8064f10eacdb927e68028f1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <svl/smplhint.hxx>
22 #include <svl/itemiter.hxx>
23 #include <hints.hxx>
24 #include <txtftn.hxx>
25 #include <fmtftn.hxx>
26 #include <fmtclbl.hxx>
27 #include "sectfrm.hxx"
28 #include "section.hxx" // SwSection
29 #include "frmtool.hxx" // StackHack
30 #include "doc.hxx" // SwDoc
31 #include "cntfrm.hxx" // SwCntntFrm
32 #include "rootfrm.hxx" // SwRootFrm
33 #include "pagefrm.hxx" // SwPageFrm
34 #include "fmtpdsc.hxx" // SwFmtPageDesc
35 #include "fmtcntnt.hxx" // SwFmtCntnt
36 #include "ndindex.hxx" // SwNodeIndex
37 #include "ftnidx.hxx"
38 #include "txtfrm.hxx" // SwTxtFrm
39 #include "fmtclds.hxx" // SwFmtCol
40 #include "colfrm.hxx" // SwColumnFrm
41 #include "tabfrm.hxx" // SwTabFrm
42 #include "flyfrm.hxx" // SwFlyFrm
43 #include "ftnfrm.hxx" // SwFtnFrm
44 #include "layouter.hxx" // SwLayouter
45 #include "dbg_lay.hxx"
46 #include "viewsh.hxx"
47 #include "viewopt.hxx"
48 #include "viewimp.hxx"
49 #include <editeng/ulspitem.hxx>
50 #include <editeng/lrspitem.hxx>
51 #include <editeng/brushitem.hxx>
52 #include <fmtftntx.hxx>
53 // OD 2004-05-24 #i28701#
54 #include <dflyobj.hxx>
55 #include <flyfrms.hxx>
56 #include <sortedobjs.hxx>
58 /*************************************************************************
60 |* SwSectionFrm::SwSectionFrm(), ~SwSectionFrm()
62 |*************************************************************************/
63 SwSectionFrm::SwSectionFrm( SwSection &rSect, SwFrm* pSib )
64 : SwLayoutFrm( rSect.GetFmt(), pSib )
65 , SwFlowFrm( static_cast<SwFrm&>(*this) )
66 , pSection( &rSect )
67 , bFtnAtEnd(false)
68 , bEndnAtEnd(false)
69 , bCntntLock(false)
70 , bOwnFtnNum(false)
71 , bFtnLock(false)
73 mnType = FRMC_SECTION;
75 CalcFtnAtEndFlag();
76 CalcEndAtEndFlag();
79 SwSectionFrm::SwSectionFrm( SwSectionFrm &rSect, sal_Bool bMaster ) :
80 SwLayoutFrm( rSect.GetFmt(), rSect.getRootFrm() ),
81 SwFlowFrm( (SwFrm&)*this ),
82 pSection( rSect.GetSection() ),
83 bFtnAtEnd( rSect.IsFtnAtEnd() ),
84 bEndnAtEnd( rSect.IsEndnAtEnd() ),
85 bCntntLock( false ),
86 bOwnFtnNum( false ),
87 bFtnLock( false )
89 mnType = FRMC_SECTION;
91 PROTOCOL( this, PROT_SECTION, bMaster ? ACT_CREATE_MASTER : ACT_CREATE_FOLLOW, &rSect )
93 if( bMaster )
95 if( rSect.IsFollow() )
97 SwSectionFrm* pMaster = rSect.FindMaster();
98 pMaster->SetFollow( this );
100 SetFollow( &rSect );
102 else
104 SetFollow( rSect.GetFollow() );
105 rSect.SetFollow( this );
106 if( !GetFollow() )
107 rSect.SimpleFormat();
108 if( !rSect.IsColLocked() )
109 rSect.InvalidateSize();
113 // NOTE: call <SwSectionFrm::Init()> directly after creation of a new section
114 // frame and its insert in the layout.
115 void SwSectionFrm::Init()
117 OSL_ENSURE( GetUpper(), "SwSectionFrm::Init before insertion?!" );
118 SWRECTFN( this )
119 long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
120 (Frm().*fnRect->fnSetWidth)( nWidth );
121 (Frm().*fnRect->fnSetHeight)( 0 );
123 // #109700# LRSpace for sections
124 const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
125 (Prt().*fnRect->fnSetLeft)( rLRSpace.GetLeft() );
126 (Prt().*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
127 rLRSpace.GetRight() );
128 (Prt().*fnRect->fnSetHeight)( 0 );
130 const SwFmtCol &rCol = GetFmt()->GetCol();
131 if( ( rCol.GetNumCols() > 1 || IsAnyNoteAtEnd() ) && !IsInFtn() )
133 const SwFmtCol *pOld = Lower() ? &rCol : new SwFmtCol;
134 ChgColumns( *pOld, rCol, IsAnyNoteAtEnd() );
135 if( pOld != &rCol )
136 delete pOld;
140 SwSectionFrm::~SwSectionFrm()
142 if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
144 SwRootFrm *pRootFrm = getRootFrm();
145 if( pRootFrm )
146 pRootFrm->RemoveFromList( this ); //swmod 071108//swmod 071225
147 if( IsFollow() )
149 SwSectionFrm *pMaster = FindMaster();
150 if( pMaster )
152 PROTOCOL( this, PROT_SECTION, ACT_DEL_FOLLOW, pMaster )
153 pMaster->SetFollow( GetFollow() );
154 // A Master always grabs the space until the lower edge of his
155 // Upper. If he doesn't have a Follow anymore, he can
156 // release it, which is why the Size of the Master is
157 // invalidated.
158 if( !GetFollow() )
159 pMaster->InvalidateSize();
162 else if( HasFollow() )
164 PROTOCOL( this, PROT_SECTION, ACT_DEL_MASTER, GetFollow() )
170 /*************************************************************************
172 |* SwSectionFrm::DelEmpty()
174 |*************************************************************************/
175 void SwSectionFrm::DelEmpty( sal_Bool bRemove )
177 if( IsColLocked() )
179 OSL_ENSURE( !bRemove, "Don't delete locked SectionFrms" );
180 return;
182 SwFrm* pUp = GetUpper();
183 if( pUp )
185 // #i27138#
186 // notify accessibility paragraphs objects about changed
187 // CONTENT_FLOWS_FROM/_TO relation.
188 // Relation CONTENT_FLOWS_FROM for current next paragraph will change
189 // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
191 ViewShell* pViewShell( getRootFrm()->GetCurrShell() );
192 if ( pViewShell && pViewShell->GetLayout() &&
193 pViewShell->GetLayout()->IsAnyShellAccessible() )
195 pViewShell->InvalidateAccessibleParaFlowRelation(
196 dynamic_cast<SwTxtFrm*>(FindNextCnt( true )),
197 dynamic_cast<SwTxtFrm*>(FindPrevCnt( true )) );
200 _Cut( bRemove );
202 if( IsFollow() )
204 SwSectionFrm *pMaster = FindMaster();
205 pMaster->SetFollow( GetFollow() );
206 // A Master always grabs the space until the lower edge of his
207 // Upper. If he doesn't have a Follow anymore, he can
208 // release it, which is why the Size of the Master is
209 // invalidated.
210 if( !GetFollow() && !pMaster->IsColLocked() )
211 pMaster->InvalidateSize();
213 SetFollow(0);
214 if( pUp )
216 Frm().Height( 0 );
217 // If we are destroyed immediately anyway, we don't need
218 // to put us into the list
219 if( bRemove )
220 { // If we already were half dead before this DelEmpty,
221 // we are likely in the list and have to remove us from
222 // it
223 if( !pSection && getRootFrm() )
224 getRootFrm()->RemoveFromList( this );
226 else if( getRootFrm() )
227 getRootFrm()->InsertEmptySct( this ); //swmod 071108//swmod 071225
228 pSection = NULL; // like this a reanimation is virtually impossible though
232 /*************************************************************************
234 |* SwSectionFrm::Cut()
236 |*************************************************************************/
237 void SwSectionFrm::Cut()
239 _Cut( sal_True );
242 void SwSectionFrm::_Cut( sal_Bool bRemove )
244 OSL_ENSURE( GetUpper(), "Cut ohne Upper()." );
246 PROTOCOL( this, PROT_CUT, 0, GetUpper() )
248 SwPageFrm *pPage = FindPageFrm();
249 InvalidatePage( pPage );
250 SwFrm *pFrm = GetNext();
251 SwFrm* pPrepFrm = NULL;
252 while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
253 pFrm = pFrm->GetNext();
254 if( pFrm )
255 { // The former successor might have calculated a gap to the predecessor
256 // which is now obsolete since he becomes the first
257 pFrm->_InvalidatePrt();
258 pFrm->_InvalidatePos();
259 if( pFrm->IsSctFrm() )
260 pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
261 if ( pFrm && pFrm->IsCntntFrm() )
263 pFrm->InvalidatePage( pPage );
264 if( IsInFtn() && !GetIndPrev() )
265 pPrepFrm = pFrm;
268 else
270 InvalidateNextPos();
271 // Someone has to take over the retouching: predecessor or Upper
272 if ( 0 != (pFrm = GetPrev()) )
273 { pFrm->SetRetouche();
274 pFrm->Prepare( PREP_WIDOWS_ORPHANS );
275 if ( pFrm->IsCntntFrm() )
276 pFrm->InvalidatePage( pPage );
278 // If I am (was) the only FlowFrm in my Upper, then he has to take over
279 // the retouching.
280 // Furthermore a blank page could have emerged
281 else
282 { SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
283 pRoot->SetSuperfluous();
284 GetUpper()->SetCompletePaint();
287 // First remove, then shrink Upper
288 SwLayoutFrm *pUp = GetUpper();
289 if( bRemove )
291 Remove();
292 if( pUp && !pUp->Lower() && pUp->IsFtnFrm() && !pUp->IsColLocked() &&
293 pUp->GetUpper() )
295 pUp->Cut();
296 delete pUp;
297 pUp = NULL;
300 if( pPrepFrm )
301 pPrepFrm->Prepare( PREP_FTN );
302 if ( pUp )
304 SWRECTFN( this );
305 SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
306 if( nFrmHeight > 0 )
308 if( !bRemove )
310 (Frm().*fnRect->fnSetHeight)( 0 );
311 (Prt().*fnRect->fnSetHeight)( 0 );
313 pUp->Shrink( nFrmHeight );
318 /*************************************************************************
320 |* SwSectionFrm::Paste()
322 |*************************************************************************/
324 void SwSectionFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
326 OSL_ENSURE( pParent, "Kein Parent fuer Paste." );
327 OSL_ENSURE( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
328 OSL_ENSURE( pParent != this, "Bin selbst der Parent." );
329 OSL_ENSURE( pSibling != this, "Bin mein eigener Nachbar." );
330 OSL_ENSURE( !GetPrev() && !GetUpper(),
331 "Bin noch irgendwo angemeldet." );
333 PROTOCOL( this, PROT_PASTE, 0, GetUpper() )
335 // Add to the tree
336 SwSectionFrm* pSect = pParent->FindSctFrm();
337 // #156927#
338 // Assure that parent is not inside a table frame, which is inside the found section frame.
339 if ( pSect )
341 SwTabFrm* pTableFrm = pParent->FindTabFrm();
342 if ( pTableFrm &&
343 pSect->IsAnLower( pTableFrm ) )
345 pSect = 0;
349 SWRECTFN( pParent )
350 if( pSect && HasToBreak( pSect ) )
352 if( pParent->IsColBodyFrm() ) // dealing with a single-column area
354 // If we are coincidentally at the end of a column, pSibling
355 // has to point to the first frame of the next column in order
356 // for the content of the next column to be moved correctly to the
357 // newly created pSect by the InsertGroup
358 SwColumnFrm *pCol = (SwColumnFrm*)pParent->GetUpper();
359 while( !pSibling && 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
360 pSibling = ((SwLayoutFrm*)((SwColumnFrm*)pCol)->Lower())->Lower();
361 if( pSibling )
363 // Even worse: every following column content has to
364 // be attached to the pSibling-chain in order to be
365 // taken along
366 SwFrm *pTmp = pSibling;
367 while ( 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
369 while ( pTmp->GetNext() )
370 pTmp = pTmp->GetNext();
371 SwFrm* pSave = ::SaveCntnt( pCol );
372 ::RestoreCntnt( pSave, pSibling->GetUpper(), pTmp, true );
376 pParent = pSect;
377 pSect = new SwSectionFrm( *((SwSectionFrm*)pParent)->GetSection(), pParent );
378 // if pParent is decomposed into two parts, its Follow has to be attached
379 // to the new second part
380 pSect->SetFollow( ((SwSectionFrm*)pParent)->GetFollow() );
381 ((SwSectionFrm*)pParent)->SetFollow( NULL );
382 if( pSect->GetFollow() )
383 pParent->_InvalidateSize();
385 InsertGroupBefore( pParent, pSibling, pSect );
386 pSect->Init();
387 (pSect->*fnRect->fnMakePos)( pSect->GetUpper(), pSect->GetPrev(), sal_True);
388 if( !((SwLayoutFrm*)pParent)->Lower() )
390 SwSectionFrm::MoveCntntAndDelete( (SwSectionFrm*)pParent, sal_False );
391 pParent = this;
394 else
395 InsertGroupBefore( pParent, pSibling, NULL );
397 _InvalidateAll();
398 SwPageFrm *pPage = FindPageFrm();
399 InvalidatePage( pPage );
401 if ( pSibling )
403 pSibling->_InvalidatePos();
404 pSibling->_InvalidatePrt();
405 if ( pSibling->IsCntntFrm() )
406 pSibling->InvalidatePage( pPage );
409 SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
410 if( nFrmHeight )
411 pParent->Grow( nFrmHeight );
413 if ( GetPrev() )
415 if ( !IsFollow() )
417 GetPrev()->InvalidateSize();
418 if ( GetPrev()->IsCntntFrm() )
419 GetPrev()->InvalidatePage( pPage );
425 /*************************************************************************
427 |* SwSectionFrm::HasToBreak()
429 |* Here it's decided whether the this-SectionFrm should break up
430 |* the passed (Section)frm (or not).
431 |* Initiall, all superior sections are broken up. Later on that could
432 |* be made configurable.
434 |*************************************************************************/
436 sal_Bool SwSectionFrm::HasToBreak( const SwFrm* pFrm ) const
438 if( !pFrm->IsSctFrm() )
439 return sal_False;
441 SwSectionFmt *pTmp = (SwSectionFmt*)GetFmt();
442 // if( !pTmp->GetSect().GetValue() )
443 // return sal_False;
445 const SwFrmFmt *pOtherFmt = ((SwSectionFrm*)pFrm)->GetFmt();
448 pTmp = pTmp->GetParent();
449 if( !pTmp )
450 return sal_False;
451 if( pTmp == pOtherFmt )
452 return sal_True;
453 } while( true ); // ( pTmp->GetSect().GetValue() );
456 /*************************************************************************
458 |* SwSectionFrm::MergeNext()
460 |* Merges two SectionFrms, in case it's about the same section.
461 |* This can be necessary when a (sub)section is deleted that had
462 |* divided another part into two.
464 |*************************************************************************/
466 void SwSectionFrm::MergeNext( SwSectionFrm* pNxt )
468 if( !pNxt->IsJoinLocked() && GetSection() == pNxt->GetSection() )
470 PROTOCOL( this, PROT_SECTION, ACT_MERGE, pNxt )
472 SwFrm* pTmp = ::SaveCntnt( pNxt );
473 if( pTmp )
475 SwFrm* pLast = Lower();
476 SwLayoutFrm* pLay = this;
477 if( pLast )
479 while( pLast->GetNext() )
480 pLast = pLast->GetNext();
481 if( pLast->IsColumnFrm() )
482 { // Columns now with BodyFrm
483 pLay = (SwLayoutFrm*)((SwLayoutFrm*)pLast)->Lower();
484 pLast = pLay->Lower();
485 if( pLast )
486 while( pLast->GetNext() )
487 pLast = pLast->GetNext();
490 ::RestoreCntnt( pTmp, pLay, pLast, true );
492 SetFollow( pNxt->GetFollow() );
493 pNxt->SetFollow( NULL );
494 pNxt->Cut();
495 delete pNxt;
496 InvalidateSize();
500 /*************************************************************************
502 |* SwSectionFrm::SplitSect()
504 |* Divides a SectionFrm into two parts. The second one starts with the
505 |* passed frame.
506 |* This is required when inserting an inner section, because the MoveFwd
507 |* cannot have the desired effect within a frame or a table cell.
509 |*************************************************************************/
511 sal_Bool SwSectionFrm::SplitSect( SwFrm* pFrm, sal_Bool bApres )
513 OSL_ENSURE( pFrm, "SplitSect: Why?" );
514 SwFrm* pOther = bApres ? pFrm->FindNext() : pFrm->FindPrev();
515 if( !pOther )
516 return sal_False;
517 SwSectionFrm* pSect = pOther->FindSctFrm();
518 if( pSect != this )
519 return sal_False;
520 // Put the content aside
521 SwFrm* pSav = ::SaveCntnt( this, bApres ? pOther : pFrm );
522 OSL_ENSURE( pSav, "SplitSect: What's on?" );
523 if( pSav ) // be robust
524 { // Create a new SctFrm, not as a Follower/master
525 SwSectionFrm* pNew = new SwSectionFrm( *pSect->GetSection(), pSect );
526 pNew->InsertBehind( pSect->GetUpper(), pSect );
527 pNew->Init();
528 SWRECTFN( this )
529 (pNew->*fnRect->fnMakePos)( NULL, pSect, sal_True );
530 // OD 25.03.2003 #108339# - restore content:
531 // determine layout frame for restoring content after the initialization
532 // of the section frame. In the section initialization the columns are
533 // created.
535 SwLayoutFrm* pLay = pNew;
536 // Search for last layout frame, e.g. for columned sections.
537 while( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
538 pLay = (SwLayoutFrm*)pLay->Lower();
539 ::RestoreCntnt( pSav, pLay, NULL, true );
541 _InvalidateSize();
542 if( HasFollow() )
544 pNew->SetFollow( GetFollow() );
545 SetFollow( NULL );
547 return sal_True;
549 return sal_False;
552 /*************************************************************************
554 |* SwSectionFrm::MoveCntntAndDelete()
556 |* MoveCntnt is called for destroying a SectionFrms, due to
557 |* the cancellation or hiding of a section, to handle the content.
558 |* If the SectionFrm hasn't broken up another one, then the content
559 |* is moved to the Upper. Otherwise the content is moved to another
560 |* SectionFrm, which has to be potentially merged.
562 |*************************************************************************/
563 // If a multi-column section is cancelled, the ContentFrms have to be
564 // invalidated
566 static void lcl_InvalidateInfFlags( SwFrm* pFrm, bool bInva )
568 while ( pFrm )
570 pFrm->InvalidateInfFlags();
571 if( bInva )
573 pFrm->_InvalidatePos();
574 pFrm->_InvalidateSize();
575 pFrm->_InvalidatePrt();
577 if( pFrm->IsLayoutFrm() )
578 lcl_InvalidateInfFlags( ((SwLayoutFrm*)pFrm)->GetLower(), sal_False );
579 pFrm = pFrm->GetNext();
585 // Works like SwCntntFrm::ImplGetNextCntntFrm, but starts with a LayoutFrm
587 static SwCntntFrm* lcl_GetNextCntntFrm( const SwLayoutFrm* pLay, bool bFwd )
589 if ( bFwd )
591 if ( pLay->GetNext() && pLay->GetNext()->IsCntntFrm() )
592 return (SwCntntFrm*)pLay->GetNext();
594 else
596 if ( pLay->GetPrev() && pLay->GetPrev()->IsCntntFrm() )
597 return (SwCntntFrm*)pLay->GetPrev();
600 // #100926#
601 const SwFrm* pFrm = pLay;
602 SwCntntFrm *pCntntFrm = 0;
603 bool bGoingUp = true;
604 do {
605 const SwFrm *p = 0;
606 bool bGoingFwdOrBwd = false;
608 bool bGoingDown = !bGoingUp && ( 0 != ( p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0 ) );
609 if ( !bGoingDown )
611 bGoingFwdOrBwd = ( 0 != ( p = pFrm->IsFlyFrm() ?
612 ( bFwd ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink() ) :
613 ( bFwd ? pFrm->GetNext() :pFrm->GetPrev() ) ) );
614 if ( !bGoingFwdOrBwd )
616 bGoingUp = (0 != (p = pFrm->GetUpper() ) );
617 if ( !bGoingUp )
618 return 0;
622 bGoingUp = !( bGoingFwdOrBwd || bGoingDown );
624 if( !bFwd && bGoingDown && p )
625 while ( p->GetNext() )
626 p = p->GetNext();
628 pFrm = p;
629 } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
631 return pCntntFrm;
634 #define FIRSTLEAF( pLayFrm ) ( ( pLayFrm->Lower() && pLayFrm->Lower()->IsColumnFrm() )\
635 ? pLayFrm->GetNextLayoutLeaf() \
636 : pLayFrm )
638 void SwSectionFrm::MoveCntntAndDelete( SwSectionFrm* pDel, sal_Bool bSave )
640 bool bSize = pDel->Lower() && pDel->Lower()->IsColumnFrm();
641 SwFrm* pPrv = pDel->GetPrev();
642 SwLayoutFrm* pUp = pDel->GetUpper();
643 // OD 27.03.2003 #i12711# - initialize local pointer variables.
644 SwSectionFrm* pPrvSct = NULL;
645 SwSectionFrm* pNxtSct = NULL;
646 SwSectionFmt* pParent = static_cast<SwSectionFmt*>(pDel->GetFmt())->GetParent();
647 if( pDel->IsInTab() && pParent )
649 SwTabFrm *pTab = pDel->FindTabFrm();
650 // If we are within a table, we can only have broken up sections that
651 // are inside as well, but not a section that contains the whole table.
652 if( pTab->IsInSct() && pParent == pTab->FindSctFrm()->GetFmt() )
653 pParent = NULL;
655 // If our Format has a parent, we have probably broken up another
656 // SectionFrm, which has to be checked. To do so we first acquire the
657 // succeeding and the preceding CntntFrm, let's see if they
658 // lay in the SectionFrms.
659 // OD 27.03.2003 #i12711# - check, if previous and next section belonging
660 // together and can be joined, *not* only if deleted section contains content.
661 if ( pParent )
663 SwFrm* pPrvCntnt = lcl_GetNextCntntFrm( pDel, false );
664 pPrvSct = pPrvCntnt ? pPrvCntnt->FindSctFrm() : NULL;
665 SwFrm* pNxtCntnt = lcl_GetNextCntntFrm( pDel, true );
666 pNxtSct = pNxtCntnt ? pNxtCntnt->FindSctFrm() : NULL;
668 else
670 pParent = NULL;
671 pPrvSct = pNxtSct = NULL;
674 // Now the content is put aside and the frame is destroyed
675 SwFrm *pSave = bSave ? ::SaveCntnt( pDel ) : NULL;
676 sal_Bool bOldFtn = sal_True;
677 if( pSave && pUp->IsFtnFrm() )
679 bOldFtn = ((SwFtnFrm*)pUp)->IsColLocked();
680 ((SwFtnFrm*)pUp)->ColLock();
682 pDel->DelEmpty( sal_True );
683 delete pDel;
684 if( pParent )
685 { // Search for the appropriate insert position
686 if( pNxtSct && pNxtSct->GetFmt() == pParent )
687 { // Here we can insert outselves at the beginning
688 pUp = FIRSTLEAF( pNxtSct );
689 pPrv = NULL;
690 if( pPrvSct && !( pPrvSct->GetFmt() == pParent ) )
691 pPrvSct = NULL; // In order that nothing is merged
693 else if( pPrvSct && pPrvSct->GetFmt() == pParent )
694 { // Wonderful, here we can insert ourselves at the end
695 pUp = pPrvSct;
696 if( pUp->Lower() && pUp->Lower()->IsColumnFrm() )
698 pUp = static_cast<SwLayoutFrm*>(pUp->GetLastLower());
699 // The body of the last column
700 pUp = static_cast<SwLayoutFrm*>(pUp->Lower());
702 // In order to perform the insertion after the last one
703 pPrv = pUp->GetLastLower();
704 pPrvSct = NULL; // Such that nothing is merged
706 else
708 if( pSave )
709 { // Following situations: before and after the section-to-be
710 // deleted there is the section boundary of the enclosing
711 // section, or another (sibling) section connects subsequently,
712 // that derives from the same Parent.
713 // In that case, there's not (yet) a part of our parent available
714 // that can store the content, so we create it here.
715 pPrvSct = new SwSectionFrm( *pParent->GetSection(), pUp );
716 pPrvSct->InsertBehind( pUp, pPrv );
717 pPrvSct->Init();
718 SWRECTFN( pUp )
719 (pPrvSct->*fnRect->fnMakePos)( pUp, pPrv, sal_True );
720 pUp = FIRSTLEAF( pPrvSct );
721 pPrv = NULL;
723 pPrvSct = NULL; // Such that nothing will be merged
726 // The content is going to be inserted..
727 if( pSave )
729 lcl_InvalidateInfFlags( pSave, bSize );
730 ::RestoreCntnt( pSave, pUp, pPrv, true );
731 pUp->FindPageFrm()->InvalidateCntnt();
732 if( !bOldFtn )
733 ((SwFtnFrm*)pUp)->ColUnlock();
735 // Now two parts of the superior section could possibly be merged
736 if( pPrvSct && !pPrvSct->IsJoinLocked() )
738 OSL_ENSURE( pNxtSct, "MoveCntnt: No Merge" );
739 pPrvSct->MergeNext( pNxtSct );
743 void SwSectionFrm::MakeAll()
745 if ( IsJoinLocked() || IsColLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
746 return;
747 if( !pSection ) // Via DelEmpty
749 #ifdef DBG_UTIL
750 OSL_ENSURE( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
751 #endif
752 if( !mbValidPos )
754 if( GetUpper() )
756 SWRECTFN( GetUpper() )
757 (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
760 mbValidSize = mbValidPos = mbValidPrtArea = sal_True;
761 return;
763 LockJoin(); // I don't let myself to be destroyed on the way
765 while( GetNext() && GetNext() == GetFollow() )
767 const SwFrm* pFoll = GetFollow();
768 MergeNext( (SwSectionFrm*)GetNext() );
769 if( pFoll == GetFollow() )
770 break;
773 // OD 2004-03-15 #116561# - In online layout join the follows, if section
774 // can grow.
775 const ViewShell *pSh = getRootFrm()->GetCurrShell();
776 if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
777 ( Grow( LONG_MAX, true ) > 0 ) )
779 while( GetFollow() )
781 const SwFrm* pFoll = GetFollow();
782 MergeNext( GetFollow() );
783 if( pFoll == GetFollow() )
784 break;
788 // A section with Follow uses all the space until the lower edge of the
789 // Upper. If it moves, its size can grow or decrease...
790 if( !mbValidPos && ToMaximize( sal_False ) )
791 mbValidSize = sal_False;
793 #if OSL_DEBUG_LEVEL > 1
794 const SwFmtCol &rCol = GetFmt()->GetCol();
795 (void)rCol;
796 #endif
797 SwLayoutFrm::MakeAll();
798 UnlockJoin();
799 if( pSection && IsSuperfluous() )
800 DelEmpty( sal_False );
803 sal_Bool SwSectionFrm::ShouldBwdMoved( SwLayoutFrm *, sal_Bool , sal_Bool & )
805 OSL_FAIL( "Hups, wo ist meine Tarnkappe?" );
806 return sal_False;
809 const SwSectionFmt* SwSectionFrm::_GetEndSectFmt() const
811 const SwSectionFmt *pFmt = pSection->GetFmt();
812 while( !pFmt->GetEndAtTxtEnd().IsAtEnd() )
814 if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
815 pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
816 else
817 return NULL;
819 return pFmt;
822 static void lcl_FindCntntFrm( SwCntntFrm* &rpCntntFrm, SwFtnFrm* &rpFtnFrm,
823 SwFrm* pFrm, sal_Bool &rbChkFtn )
825 if( pFrm )
827 while( pFrm->GetNext() )
828 pFrm = pFrm->GetNext();
829 while( !rpCntntFrm && pFrm )
831 if( pFrm->IsCntntFrm() )
832 rpCntntFrm = (SwCntntFrm*)pFrm;
833 else if( pFrm->IsLayoutFrm() )
835 if( pFrm->IsFtnFrm() )
837 if( rbChkFtn )
839 rpFtnFrm = (SwFtnFrm*)pFrm;
840 rbChkFtn = rpFtnFrm->GetAttr()->GetFtn().IsEndNote();
843 else
844 lcl_FindCntntFrm( rpCntntFrm, rpFtnFrm,
845 ((SwLayoutFrm*)pFrm)->Lower(), rbChkFtn );
847 pFrm = pFrm->GetPrev();
852 SwCntntFrm *SwSectionFrm::FindLastCntnt( sal_uInt8 nMode )
854 SwCntntFrm *pRet = NULL;
855 SwFtnFrm *pFtnFrm = NULL;
856 SwSectionFrm *pSect = this;
857 if( nMode )
859 const SwSectionFmt *pFmt = IsEndnAtEnd() ? GetEndSectFmt() :
860 pSection->GetFmt();
861 do {
862 while( pSect->HasFollow() )
863 pSect = pSect->GetFollow();
864 SwFrm* pTmp = pSect->FindNext();
865 while( pTmp && pTmp->IsSctFrm() &&
866 !((SwSectionFrm*)pTmp)->GetSection() )
867 pTmp = pTmp->FindNext();
868 if( pTmp && pTmp->IsSctFrm() &&
869 ((SwSectionFrm*)pTmp)->IsDescendantFrom( pFmt ) )
870 pSect = (SwSectionFrm*)pTmp;
871 else
872 break;
873 } while( true );
875 sal_Bool bFtnFound = nMode == FINDMODE_ENDNOTE;
878 lcl_FindCntntFrm( pRet, pFtnFrm, pSect->Lower(), bFtnFound );
879 if( pRet || !pSect->IsFollow() || !nMode ||
880 ( FINDMODE_MYLAST == nMode && this == pSect ) )
881 break;
882 pSect = pSect->FindMaster();
883 } while( pSect );
884 if( ( nMode == FINDMODE_ENDNOTE ) && pFtnFrm )
885 pRet = pFtnFrm->ContainsCntnt();
886 return pRet;
889 sal_Bool SwSectionFrm::CalcMinDiff( SwTwips& rMinDiff ) const
891 if( ToMaximize( sal_True ) )
893 SWRECTFN( this )
894 rMinDiff = (GetUpper()->*fnRect->fnGetPrtBottom)();
895 rMinDiff = (Frm().*fnRect->fnBottomDist)( rMinDiff );
896 return sal_True;
898 return sal_False;
901 /*************************************************************************
903 * SwSectionFrm::CollectEndnotes( )
905 * CollectEndnotes looks for endnotes in the sectionfrm and his follows,
906 * the endnotes will cut off the layout and put into the array.
907 * If the first endnote is not a master-SwFtnFrm, the whole sectionfrm
908 * contains only endnotes and it is not necessary to collect them.
910 *************************************************************************/
912 static SwFtnFrm* lcl_FindEndnote( SwSectionFrm* &rpSect, bool &rbEmpty,
913 SwLayouter *pLayouter )
915 // if rEmpty is set, the rpSect is already searched
916 SwSectionFrm* pSect = rbEmpty ? rpSect->GetFollow() : rpSect;
917 while( pSect )
919 OSL_ENSURE( (pSect->Lower() && pSect->Lower()->IsColumnFrm()) || pSect->GetUpper()->IsFtnFrm(),
920 "InsertEndnotes: Where's my column?" );
922 // i73332: Columned section in endnote
923 SwColumnFrm* pCol = 0;
924 if(pSect->Lower() && pSect->Lower()->IsColumnFrm())
925 pCol = (SwColumnFrm*)pSect->Lower();
927 while( pCol ) // check all columns
929 SwFtnContFrm* pFtnCont = pCol->FindFtnCont();
930 if( pFtnCont )
932 SwFtnFrm* pRet = (SwFtnFrm*)pFtnCont->Lower();
933 while( pRet ) // look for endnotes
935 /* CollectEndNode can destroy pRet so we need to get the
936 next early
938 SwFtnFrm* pRetNext = (SwFtnFrm*)pRet->GetNext();
939 if( pRet->GetAttr()->GetFtn().IsEndNote() )
941 if( pRet->GetMaster() )
943 if( pLayouter )
944 pLayouter->CollectEndnote( pRet );
945 else
946 return 0;
948 else
949 return pRet; // Found
951 pRet = pRetNext;
954 pCol = (SwColumnFrm*)pCol->GetNext();
956 rpSect = pSect;
957 pSect = pLayouter ? pSect->GetFollow() : NULL;
958 rbEmpty = true;
960 return NULL;
963 static void lcl_ColumnRefresh( SwSectionFrm* pSect, bool bFollow )
965 while( pSect )
967 sal_Bool bOldLock = pSect->IsColLocked();
968 pSect->ColLock();
969 if( pSect->Lower() && pSect->Lower()->IsColumnFrm() )
971 SwColumnFrm *pCol = (SwColumnFrm*)pSect->Lower();
973 { pCol->_InvalidateSize();
974 pCol->_InvalidatePos();
975 ((SwLayoutFrm*)pCol)->Lower()->_InvalidateSize();
976 pCol->Calc(); // calculation of column and
977 ((SwLayoutFrm*)pCol)->Lower()->Calc(); // body
978 pCol = (SwColumnFrm*)pCol->GetNext();
979 } while ( pCol );
981 if( !bOldLock )
982 pSect->ColUnlock();
983 if( bFollow )
984 pSect = pSect->GetFollow();
985 else
986 pSect = NULL;
990 void SwSectionFrm::CollectEndnotes( SwLayouter* pLayouter )
992 OSL_ENSURE( IsColLocked(), "CollectEndnotes: You love the risk?" );
993 // i73332: Section in footnode does not have columns!
994 OSL_ENSURE( (Lower() && Lower()->IsColumnFrm()) || GetUpper()->IsFtnFrm(), "Where's my column?" );
996 SwSectionFrm* pSect = this;
997 SwFtnFrm* pFtn;
998 bool bEmpty = false;
999 // pSect is the last sectionfrm without endnotes or the this-pointer
1000 // the first sectionfrm with endnotes may be destroyed, when the endnotes
1001 // is cutted
1002 while( 0 != (pFtn = lcl_FindEndnote( pSect, bEmpty, pLayouter )) )
1003 pLayouter->CollectEndnote( pFtn );
1004 if( pLayouter->HasEndnotes() )
1005 lcl_ColumnRefresh( this, true );
1008 /*************************************************************************
1010 |* SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
1012 |* Description: Fits the size to the surroundings.
1013 |* Those that have a Follow or foot notes, have to extend until
1014 |* the lower edge of a upper (bMaximize)
1015 |* They must not extend above the Upper, as the case may be one can
1016 |* try to grow its upper (bGrow)
1017 |* If the size had to be changed, the content is calculated.
1019 |*************************************************************************/
1021 /// OD 18.09.2002 #100522#
1022 /// perform calculation of content, only if height has changed.
1023 void SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
1025 SWRECTFN( this )
1026 long nDiff;
1027 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1028 if( bGrow && ( !IsInFly() || !GetUpper()->IsColBodyFrm() ||
1029 !FindFlyFrm()->IsLocked() ) )
1031 nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
1032 if( !bMaximize )
1033 nDiff += Undersize();
1034 if( nDiff > 0 )
1036 long nAdd = GetUpper()->Grow( nDiff );
1037 if( bVert && !bRev )
1038 nDeadLine -= nAdd;
1039 else
1040 nDeadLine += nAdd;
1043 nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
1044 SetUndersized( !bMaximize && nDiff >= 0 );
1045 const bool bCalc = ( IsUndersized() || bMaximize ) &&
1046 ( nDiff ||
1047 (Prt().*fnRect->fnGetTop)() > (Frm().*fnRect->fnGetHeight)() );
1048 // OD 03.11.2003 #i19737# - introduce local variable <bExtraCalc> to indicate
1049 // that a calculation has to be done beside the value of <bCalc>.
1050 bool bExtraCalc = false;
1051 if( !bCalc && !bGrow && IsAnyNoteAtEnd() && !IsInFtn() )
1053 SwSectionFrm *pSect = this;
1054 bool bEmpty = false;
1055 SwLayoutFrm* pFtn = IsEndnAtEnd() ?
1056 lcl_FindEndnote( pSect, bEmpty, NULL ) : NULL;
1057 if( pFtn )
1059 pFtn = pFtn->FindFtnBossFrm();
1060 SwFrm* pTmp = FindLastCntnt( FINDMODE_LASTCNT );
1061 // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
1062 if ( pTmp && pFtn->IsBefore( pTmp->FindFtnBossFrm() ) )
1063 bExtraCalc = true;
1065 else if( GetFollow() && !GetFollow()->ContainsAny() )
1066 bExtraCalc = true;
1068 if ( bCalc || bExtraCalc )
1070 nDiff = (*fnRect->fnYDiff)( nDeadLine, (Frm().*fnRect->fnGetTop)() );
1071 if( nDiff < 0 )
1073 nDiff = 0;
1074 nDeadLine = (Frm().*fnRect->fnGetTop)();
1076 const Size aOldSz( Prt().SSize() );
1077 long nTop = (this->*fnRect->fnGetTopMargin)();
1078 (Frm().*fnRect->fnSetBottom)( nDeadLine );
1079 nDiff = (Frm().*fnRect->fnGetHeight)();
1080 if( nTop > nDiff )
1081 nTop = nDiff;
1082 (this->*fnRect->fnSetYMargins)( nTop, 0 );
1084 // OD 18.09.2002 #100522#
1085 // Determine, if height has changed.
1086 // Note: In vertical layout the height equals the width value.
1087 bool bHeightChanged = bVert ?
1088 (aOldSz.Width() != Prt().Width()) :
1089 (aOldSz.Height() != Prt().Height());
1090 // Last but not least we have changed the height again, thus the inner
1091 // layout (columns) is calculated and the content as well.
1092 // OD 18.09.2002 #100522#
1093 // calculate content, only if height has changed.
1094 // OD 03.11.2003 #i19737# - restriction of content calculation too strong.
1095 // If an endnote has an incorrect position or a follow section contains
1096 // no content except footnotes/endnotes, the content has also been calculated.
1097 if ( ( bHeightChanged || bExtraCalc ) && Lower() )
1099 if( Lower()->IsColumnFrm() )
1101 lcl_ColumnRefresh( this, false );
1102 ::CalcCntnt( this );
1104 else
1106 ChgLowersProp( aOldSz );
1107 if( !bMaximize && !IsCntntLocked() )
1108 ::CalcCntnt( this );
1114 void SwSectionFrm::SimpleFormat()
1116 if ( IsJoinLocked() || IsColLocked() )
1117 return;
1118 // OSL_ENSURE( pFollow, "SimpleFormat: Follow required" );
1119 LockJoin();
1120 SWRECTFN( this )
1121 if( GetPrev() || GetUpper() )
1124 // assure notifications on position changes.
1125 const SwLayNotify aNotify( this );
1126 (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
1127 mbValidPos = sal_True;
1129 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1130 // OD 22.10.2002 #97265# - call always method <lcl_ColumnRefresh(..)>, in
1131 // order to get calculated lowers, not only if there space left in its upper.
1132 if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) >= 0 )
1134 (Frm().*fnRect->fnSetBottom)( nDeadLine );
1135 long nHeight = (Frm().*fnRect->fnGetHeight)();
1136 long nTop = CalcUpperSpace();
1137 if( nTop > nHeight )
1138 nTop = nHeight;
1139 (this->*fnRect->fnSetYMargins)( nTop, 0 );
1141 lcl_ColumnRefresh( this, false );
1142 UnlockJoin();
1145 // #i40147# - helper class to perform extra section format
1146 // to position anchored objects and to keep the position of whose objects locked.
1147 class ExtraFormatToPositionObjs
1149 private:
1150 SwSectionFrm* mpSectFrm;
1151 bool mbExtraFormatPerformed;
1153 public:
1154 ExtraFormatToPositionObjs( SwSectionFrm& _rSectFrm)
1155 : mpSectFrm( &_rSectFrm ),
1156 mbExtraFormatPerformed( false )
1159 ~ExtraFormatToPositionObjs()
1161 if ( mbExtraFormatPerformed )
1163 // release keep locked position of lower floating screen objects
1164 SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
1165 SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
1166 if ( pObjs )
1168 sal_uInt32 i = 0;
1169 for ( i = 0; i < pObjs->Count(); ++i )
1171 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1173 if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
1175 pAnchoredObj->SetKeepPosLocked( false );
1182 // #i81555#
1183 void InitObjs( SwFrm& rFrm )
1185 SwSortedObjs* pObjs = rFrm.GetDrawObjs();
1186 if ( pObjs )
1188 sal_uInt32 i = 0;
1189 for ( i = 0; i < pObjs->Count(); ++i )
1191 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1193 pAnchoredObj->UnlockPosition();
1194 pAnchoredObj->SetClearedEnvironment( false );
1197 SwLayoutFrm* pLayoutFrm = dynamic_cast<SwLayoutFrm*>(&rFrm);
1198 if ( pLayoutFrm != 0 )
1200 SwFrm* pLowerFrm = pLayoutFrm->GetLower();
1201 while ( pLowerFrm != 0 )
1203 InitObjs( *pLowerFrm );
1205 pLowerFrm = pLowerFrm->GetNext();
1210 void FormatSectionToPositionObjs()
1212 // perform extra format for multi-columned section.
1213 if ( mpSectFrm->Lower() && mpSectFrm->Lower()->IsColumnFrm() &&
1214 mpSectFrm->Lower()->GetNext() )
1216 // grow section till bottom of printing area of upper frame
1217 SWRECTFN( mpSectFrm );
1218 SwTwips nTopMargin = (mpSectFrm->*fnRect->fnGetTopMargin)();
1219 Size aOldSectPrtSize( mpSectFrm->Prt().SSize() );
1220 SwTwips nDiff = (mpSectFrm->Frm().*fnRect->fnBottomDist)(
1221 (mpSectFrm->GetUpper()->*fnRect->fnGetPrtBottom)() );
1222 (mpSectFrm->Frm().*fnRect->fnAddBottom)( nDiff );
1223 (mpSectFrm->*fnRect->fnSetYMargins)( nTopMargin, 0 );
1224 // #i59789#
1225 // suppress formatting, if printing area of section is too narrow
1226 if ( (mpSectFrm->Prt().*fnRect->fnGetHeight)() <= 0 )
1228 return;
1230 mpSectFrm->ChgLowersProp( aOldSectPrtSize );
1232 // format column frames and its body and footnote container
1233 SwColumnFrm* pColFrm = static_cast<SwColumnFrm*>(mpSectFrm->Lower());
1234 while ( pColFrm )
1236 pColFrm->Calc();
1237 pColFrm->Lower()->Calc();
1238 if ( pColFrm->Lower()->GetNext() )
1240 pColFrm->Lower()->GetNext()->Calc();
1243 pColFrm = static_cast<SwColumnFrm*>(pColFrm->GetNext());
1246 // unlock position of lower floating screen objects for the extra format
1247 // #i81555#
1248 // Section frame can already have changed the page and its content
1249 // can still be on the former page.
1250 // Thus, initialize objects via lower-relationship
1251 InitObjs( *mpSectFrm );
1253 // format content - first with collecting its foot-/endnotes before content
1254 // format, second without collecting its foot-/endnotes.
1255 ::CalcCntnt( mpSectFrm );
1256 ::CalcCntnt( mpSectFrm, true );
1258 // keep locked position of lower floating screen objects
1259 SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
1260 SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
1261 if ( pObjs )
1263 sal_uInt32 i = 0;
1264 for ( i = 0; i < pObjs->Count(); ++i )
1266 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1268 if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
1270 pAnchoredObj->SetKeepPosLocked( true );
1275 mbExtraFormatPerformed = true;
1280 /*************************************************************************
1282 |* SwSectionFrm::Format()
1284 |* Description: "formats" the frame; Frm and PrtArea
1286 |*************************************************************************/
1288 void SwSectionFrm::Format( const SwBorderAttrs *pAttr )
1290 if( !pSection ) // via DelEmpty
1292 #ifdef DBG_UTIL
1293 OSL_ENSURE( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
1294 #endif
1295 mbValidSize = mbValidPos = mbValidPrtArea = sal_True;
1296 return;
1298 SWRECTFN( this )
1299 if ( !mbValidPrtArea )
1301 PROTOCOL( this, PROT_PRTAREA, 0, 0 )
1302 mbValidPrtArea = sal_True;
1303 SwTwips nUpper = CalcUpperSpace();
1305 // #109700# LRSpace for sections
1306 const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
1307 (this->*fnRect->fnSetXMargins)( rLRSpace.GetLeft(), rLRSpace.GetRight() );
1309 if( nUpper != (this->*fnRect->fnGetTopMargin)() )
1311 mbValidSize = sal_False;
1312 SwFrm* pOwn = ContainsAny();
1313 if( pOwn )
1314 pOwn->_InvalidatePos();
1316 (this->*fnRect->fnSetYMargins)( nUpper, 0 );
1319 if ( !mbValidSize )
1321 PROTOCOL_ENTER( this, PROT_SIZE, 0, 0 )
1322 const long nOldHeight = (Frm().*fnRect->fnGetHeight)();
1323 sal_Bool bOldLock = IsColLocked();
1324 ColLock();
1326 mbValidSize = sal_True;
1328 // The size is only determined by the content, if the SectFrm does not have a
1329 // Follow. Otherwise it fills (occupies) the Upper down to the lower edge.
1330 // It is not responsible for the text flow, but the content is.
1331 sal_Bool bMaximize = ToMaximize( sal_False );
1333 // OD 2004-05-17 #i28701# - If the wrapping style has to be considered
1334 // on object positioning, an extra formatting has to be performed
1335 // to determine the correct positions the floating screen objects.
1336 // #i40147#
1337 // use new helper class <ExtraFormatToPositionObjs>.
1338 // This class additionally keep the locked position of the objects
1339 // and releases this position lock keeping on destruction.
1340 ExtraFormatToPositionObjs aExtraFormatToPosObjs( *this );
1341 if ( !bMaximize &&
1342 GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
1343 !GetFmt()->GetBalancedColumns().GetValue() )
1345 aExtraFormatToPosObjs.FormatSectionToPositionObjs();
1348 // Column widths have to be adjusted before calling _CheckClipping.
1349 // _CheckClipping can cause the formatting of the lower frames
1350 // which still have a width of 0.
1351 const bool bHasColumns = Lower() && Lower()->IsColumnFrm();
1352 if ( bHasColumns && Lower()->GetNext() )
1353 AdjustColumns( 0, sal_False );
1355 if( GetUpper() )
1357 long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
1358 (maFrm.*fnRect->fnSetWidth)( nWidth );
1360 // #109700# LRSpace for sections
1361 const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
1362 (maPrt.*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
1363 rLRSpace.GetRight() );
1365 // OD 15.10.2002 #103517# - allow grow in online layout
1366 // Thus, set <..IsBrowseMode()> as parameter <bGrow> on calling
1367 // method <_CheckClipping(..)>.
1368 const ViewShell *pSh = getRootFrm()->GetCurrShell();
1369 _CheckClipping( pSh && pSh->GetViewOptions()->getBrowseMode(), bMaximize );
1370 bMaximize = ToMaximize( sal_False );
1371 mbValidSize = sal_True;
1374 // Check the width of the columns and adjust if necessary
1375 if ( bHasColumns && ! Lower()->GetNext() && bMaximize )
1376 ((SwColumnFrm*)Lower())->Lower()->Calc();
1378 if ( !bMaximize )
1380 SwTwips nRemaining = (this->*fnRect->fnGetTopMargin)();
1381 SwFrm *pFrm = pLower;
1382 if( pFrm )
1384 if( pFrm->IsColumnFrm() && pFrm->GetNext() )
1386 // #i61435#
1387 // suppress formatting, if upper frame has height <= 0
1388 if ( (GetUpper()->Frm().*fnRect->fnGetHeight)() > 0 )
1390 FormatWidthCols( *pAttr, nRemaining, MINLAY );
1392 // #126020# - adjust check for empty section
1393 // #130797# - correct fix #126020#
1394 while( HasFollow() && !GetFollow()->ContainsCntnt() &&
1395 !GetFollow()->ContainsAny( true ) )
1397 SwFrm* pOld = GetFollow();
1398 GetFollow()->DelEmpty( sal_False );
1399 if( pOld == GetFollow() )
1400 break;
1402 bMaximize = ToMaximize( sal_False );
1403 nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
1405 else
1407 if( pFrm->IsColumnFrm() )
1409 pFrm->Calc();
1410 pFrm = ((SwColumnFrm*)pFrm)->Lower();
1411 pFrm->Calc();
1412 pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1413 CalcFtnCntnt();
1415 // If we are in a columned frame which calls a CalcCntnt
1416 // in the FormatWidthCols, the content might need calculating
1417 if( pFrm && !pFrm->IsValid() && IsInFly() &&
1418 FindFlyFrm()->IsColLocked() )
1419 ::CalcCntnt( this );
1420 nRemaining += InnerHeight();
1421 bMaximize = HasFollow();
1425 SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
1426 if( nDiff < 0)
1428 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1430 long nBottom = (Frm().*fnRect->fnGetBottom)();
1431 nBottom = (*fnRect->fnYInc)( nBottom, -nDiff );
1432 long nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
1433 if( nTmpDiff > 0 )
1435 nTmpDiff = GetUpper()->Grow( nTmpDiff, sal_True );
1436 nDeadLine = (*fnRect->fnYInc)( nDeadLine, nTmpDiff );
1437 nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
1438 if( nTmpDiff > 0 )
1439 nDiff += nTmpDiff;
1440 if( nDiff > 0 )
1441 nDiff = 0;
1445 if( nDiff )
1447 long nTmp = nRemaining - (Frm().*fnRect->fnGetHeight)();
1448 long nTop = (this->*fnRect->fnGetTopMargin)();
1449 (Frm().*fnRect->fnAddBottom)( nTmp );
1450 (this->*fnRect->fnSetYMargins)( nTop, 0 );
1451 InvalidateNextPos();
1452 if( pLower && ( !pLower->IsColumnFrm() || !pLower->GetNext() ) )
1454 // If a single-column section just created the space that
1455 // was requested by the "undersized" paragraphs, then they
1456 // have to be invalidated and calculated, so they fully cover it
1457 pFrm = pLower;
1458 if( pFrm->IsColumnFrm() )
1460 pFrm->_InvalidateSize();
1461 pFrm->_InvalidatePos();
1462 pFrm->Calc();
1463 pFrm = ((SwColumnFrm*)pFrm)->Lower();
1464 pFrm->Calc();
1465 pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1466 CalcFtnCntnt();
1468 bool bUnderSz = false;
1469 while( pFrm )
1471 if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
1473 pFrm->Prepare( PREP_ADJUST_FRM );
1474 bUnderSz = true;
1476 pFrm = pFrm->GetNext();
1478 if( bUnderSz && !IsCntntLocked() )
1479 ::CalcCntnt( this );
1484 // Do not exceed the lower edge of the Upper.
1485 // Do not extend below the lower edge with Sections with Follows
1486 if ( GetUpper() )
1487 _CheckClipping( sal_True, bMaximize );
1488 if( !bOldLock )
1489 ColUnlock();
1490 long nDiff = nOldHeight - (Frm().*fnRect->fnGetHeight)();
1491 if( nDiff > 0 )
1493 if( !GetNext() )
1494 SetRetouche(); // Take over the retouching ourselves
1495 if( GetUpper() && !GetUpper()->IsFooterFrm() )
1496 GetUpper()->Shrink( nDiff );
1498 if( IsUndersized() )
1499 mbValidPrtArea = sal_True;
1503 /*************************************************************************
1505 |* SwFrm::GetNextSctLeaf()
1507 |* Description: Returns the next layout sheet where the frame
1508 |* can be moved in.
1509 |* New pages are created only if the parameter sal_True is set
1511 |*************************************************************************/
1514 SwLayoutFrm *SwFrm::GetNextSctLeaf( MakePageType eMakePage )
1516 // Attention: Nested sections are currently not supported
1518 PROTOCOL_ENTER( this, PROT_LEAF, ACT_NEXT_SECT, GetUpper()->FindSctFrm() )
1520 // Shortcuts for "columned" sections, if we're not in the last column
1521 // Can we slide to the next column of the section?
1522 if( IsColBodyFrm() && GetUpper()->GetNext() )
1523 return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetNext())->Lower();
1524 if( GetUpper()->IsColBodyFrm() && GetUpper()->GetUpper()->GetNext() )
1525 return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetUpper()->GetNext())->Lower();
1526 // Inside a section, in tables, or sections of headers/footers, there can be only
1527 // one column shift be made, one of the above shortcuts should have applied!
1528 if( GetUpper()->IsInTab() || FindFooterOrHeader() )
1529 return 0;
1531 // Why GetUpper()? This crashes sometimes, because in
1532 // FlyAtCnt::MakeFlyPos there is an Orient of the SectionFrm and on this a
1533 // GetLeaf is called
1534 // SwSectionFrm *pSect = GetUpper()->FindSctFrm();
1535 SwSectionFrm *pSect = FindSctFrm();
1536 bool bWrongPage = false;
1537 OSL_ENSURE( pSect, "GetNextSctLeaf: Missing SectionFrm" );
1539 // Shortcut for sections with Follows. That's ok,
1540 // if no columns or pages (except dummy pages) lie in between.
1541 // In case of linked frames and in footnotes the shortcut would get
1542 // even more costly
1543 if( pSect->HasFollow() && pSect->IsInDocBody() )
1545 if( pSect->GetFollow() == pSect->GetNext() )
1547 SwPageFrm *pPg = pSect->GetFollow()->FindPageFrm();
1548 if( WrongPageDesc( pPg ) )
1549 bWrongPage = true;
1550 else
1551 return FIRSTLEAF( pSect->GetFollow() );
1553 else
1555 SwFrm* pTmp;
1556 if( !pSect->GetUpper()->IsColBodyFrm() ||
1557 0 == ( pTmp = pSect->GetUpper()->GetUpper()->GetNext() ) )
1558 pTmp = pSect->FindPageFrm()->GetNext();
1559 if( pTmp ) // is now the next column or page
1561 SwFrm* pTmpX = pTmp;
1562 if( pTmp->IsPageFrm() && ((SwPageFrm*)pTmp)->IsEmptyPage() )
1563 pTmp = pTmp->GetNext(); // skip dummy pages
1564 SwFrm *pUp = pSect->GetFollow()->GetUpper();
1565 // pUp becomes the next column if the Follow lies in a column
1566 // that is not a "not first" one, otherwise the page
1567 if( !pUp->IsColBodyFrm() ||
1568 !( pUp = pUp->GetUpper() )->GetPrev() )
1569 pUp = pUp->FindPageFrm();
1570 // Now pUp and pTmp have to be the same page/column, otherwise
1571 // pages or columns lie between Master and Follow
1572 if( pUp == pTmp || pUp->GetNext() == pTmpX )
1574 SwPageFrm* pNxtPg = pUp->IsPageFrm() ?
1575 (SwPageFrm*)pUp : pUp->FindPageFrm();
1576 if( WrongPageDesc( pNxtPg ) )
1577 bWrongPage = true;
1578 else
1579 return FIRSTLEAF( pSect->GetFollow() );
1585 // Always end up in the same section: Body again inside Body etc.
1586 const sal_Bool bBody = IsInDocBody();
1587 const sal_Bool bFtnPage = FindPageFrm()->IsFtnPage();
1589 SwLayoutFrm *pLayLeaf;
1590 // A shortcut for TabFrms such that not all cells need to be visited
1591 if( bWrongPage )
1592 pLayLeaf = 0;
1593 else if( IsTabFrm() )
1595 SwCntntFrm* pTmpCnt = ((SwTabFrm*)this)->FindLastCntnt();
1596 pLayLeaf = pTmpCnt ? pTmpCnt->GetUpper() : 0;
1598 else
1600 pLayLeaf = GetNextLayoutLeaf();
1601 if( IsColumnFrm() )
1603 while( pLayLeaf && ((SwColumnFrm*)this)->IsAnLower( pLayLeaf ) )
1604 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1608 SwLayoutFrm *pOldLayLeaf = 0; // Such that in case of newly
1609 // created pages, the search is
1610 // not started over at the beginning
1612 while( true )
1614 if( pLayLeaf )
1616 // A layout leaf was found, let's see whether it can store me or
1617 // another SectionFrm can be inserted here, or we have to continue
1618 // searching
1619 SwPageFrm* pNxtPg = pLayLeaf->FindPageFrm();
1620 if ( !bFtnPage && pNxtPg->IsFtnPage() )
1621 { // If I reached the end note pages it's over
1622 pLayLeaf = 0;
1623 continue;
1625 // Once inBody always inBody, don't step into tables and not into other sections
1626 if ( (bBody && !pLayLeaf->IsInDocBody()) ||
1627 (IsInFtn() != pLayLeaf->IsInFtn() ) ||
1628 pLayLeaf->IsInTab() ||
1629 ( pLayLeaf->IsInSct() && ( !pSect->HasFollow()
1630 || pSect->GetFollow() != pLayLeaf->FindSctFrm() ) ) )
1632 // Rejected - try again.
1633 pOldLayLeaf = pLayLeaf;
1634 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1635 continue;
1637 if( WrongPageDesc( pNxtPg ) )
1639 if( bWrongPage )
1640 break; // there's a column between me and my right page
1641 pLayLeaf = 0;
1642 bWrongPage = true;
1643 pOldLayLeaf = 0;
1644 continue;
1647 // There is no further LayoutFrm that fits, so a new page
1648 // has to be created, although new pages are worthless within a frame
1649 else if( !pSect->IsInFly() &&
1650 ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
1652 InsertPage(pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
1653 sal_False );
1654 // and again the whole thing
1655 pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
1656 continue;
1658 break;
1661 if( pLayLeaf )
1663 // We have found the suitable layout sheet. If there (in the sheet) is
1664 // already a Follow of our section, we take its first layout sheet,
1665 // otherwise it is time to create a section follow
1666 SwSectionFrm* pNew;
1668 // This can be omitted if existing Follows were cut short
1669 SwFrm* pFirst = pLayLeaf->Lower();
1670 // Here SectionFrms that are to be deleted must be ignored
1671 while( pFirst && pFirst->IsSctFrm() && !((SwSectionFrm*)pFirst)->GetSection() )
1672 pFirst = pFirst->GetNext();
1673 if( pFirst && pFirst->IsSctFrm() && pSect->GetFollow() == pFirst )
1674 pNew = pSect->GetFollow();
1675 else if( MAKEPAGE_NOSECTION == eMakePage )
1676 return pLayLeaf;
1677 else
1679 pNew = new SwSectionFrm( *pSect, sal_False );
1680 pNew->InsertBefore( pLayLeaf, pLayLeaf->Lower() );
1681 pNew->Init();
1682 SWRECTFN( pNew )
1683 (pNew->*fnRect->fnMakePos)( pLayLeaf, NULL, sal_True );
1685 // If our section frame has a successor then that has to be
1686 // moved behind the new Follow of the section frames
1687 SwFrm* pTmp = pSect->GetNext();
1688 if( pTmp && pTmp != pSect->GetFollow() )
1690 SwFlowFrm* pNxt;
1691 SwCntntFrm* pNxtCntnt = NULL;
1692 if( pTmp->IsCntntFrm() )
1694 pNxt = (SwCntntFrm*)pTmp;
1695 pNxtCntnt = (SwCntntFrm*)pTmp;
1697 else
1699 pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
1700 if( pTmp->IsSctFrm() )
1701 pNxt = (SwSectionFrm*)pTmp;
1702 else
1704 OSL_ENSURE( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
1705 pNxt = (SwTabFrm*)pTmp;
1707 while( !pNxtCntnt && 0 != ( pTmp = pTmp->GetNext() ) )
1709 if( pTmp->IsCntntFrm() )
1710 pNxtCntnt = (SwCntntFrm*)pTmp;
1711 else
1712 pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
1715 if( pNxtCntnt )
1717 SwFtnBossFrm* pOldBoss = pSect->FindFtnBossFrm( sal_True );
1718 if( pOldBoss == pNxtCntnt->FindFtnBossFrm( sal_True ) )
1720 SwSaveFtnHeight aHeight( pOldBoss,
1721 pOldBoss->Frm().Top() + pOldBoss->Frm().Height() );
1722 pSect->GetUpper()->MoveLowerFtns( pNxtCntnt, pOldBoss,
1723 pLayLeaf->FindFtnBossFrm( sal_True ), sal_False );
1726 ((SwFlowFrm*)pNxt)->MoveSubTree( pLayLeaf, pNew->GetNext() );
1728 if( pNew->GetFollow() )
1729 pNew->SimpleFormat();
1731 // The wanted layout sheet is now the first of the determined SctFrms:
1732 pLayLeaf = FIRSTLEAF( pNew );
1734 return pLayLeaf;
1737 /*************************************************************************
1739 |* SwFrm::GetPrevSctLeaf()
1741 |* Description Returns the preceding layout sheet where the frame
1742 |* can be moved into
1744 |*************************************************************************/
1747 SwLayoutFrm *SwFrm::GetPrevSctLeaf( MakePageType )
1749 PROTOCOL_ENTER( this, PROT_LEAF, ACT_PREV_SECT, GetUpper()->FindSctFrm() )
1751 SwLayoutFrm* pCol;
1752 // ColumnFrm always contain a BodyFrm now
1753 if( IsColBodyFrm() )
1754 pCol = GetUpper();
1755 else if( GetUpper()->IsColBodyFrm() )
1756 pCol = GetUpper()->GetUpper();
1757 else
1758 pCol = NULL;
1759 bool bJump = false;
1760 if( pCol )
1762 if( pCol->GetPrev() )
1766 pCol = (SwLayoutFrm*)pCol->GetPrev();
1767 // Is there any content?
1768 // Gibt es dort Inhalt?
1769 if( ((SwLayoutFrm*)pCol->Lower())->Lower() )
1771 if( bJump ) // Did we skip a blank page?
1772 SwFlowFrm::SetMoveBwdJump( sal_True );
1773 return (SwLayoutFrm*)pCol->Lower(); // The columnm body
1775 bJump = true;
1776 } while( pCol->GetPrev() );
1778 // We get here when all columns are empty, pCol is now the
1779 // first column, we need the body though
1780 pCol = (SwLayoutFrm*)pCol->Lower();
1782 else
1783 pCol = NULL;
1786 if( bJump ) // Did we skip a blank page?
1787 SwFlowFrm::SetMoveBwdJump( sal_True );
1789 // Within sections in tables or section in headers/footers there can
1790 // be only one column change be made, one of the above shortcuts should
1791 // have applied, also when the section has a pPrev.
1792 // Now we even consider an empty column...
1793 OSL_ENSURE( FindSctFrm(), "GetNextSctLeaf: Missing SectionFrm" );
1794 if( ( IsInTab() && !IsTabFrm() ) || FindFooterOrHeader() )
1795 return pCol;
1797 // === IMPORTANT ===
1798 // Precondition, which needs to be hold, is that the <this> frame can be
1799 // inside a table, but then the found section frame <pSect> is also inside
1800 // this table.
1801 SwSectionFrm *pSect = FindSctFrm();
1803 // #i95698#
1804 // A table cell containing directly a section does not break - see lcl_FindSectionsInRow(..)
1805 // Thus, a table inside a section, which is inside another table can only
1806 // flow backward in the columns of its section.
1807 // Note: The table cell, which contains the section, can not have a master table cell.
1808 if ( IsTabFrm() && pSect->IsInTab() )
1810 return pCol;
1814 SwFrm *pPrv;
1815 if( 0 != ( pPrv = pSect->GetIndPrev() ) )
1817 // Mooching, half dead SectionFrms shouldn't confuse us
1818 while( pPrv && pPrv->IsSctFrm() && !((SwSectionFrm*)pPrv)->GetSection() )
1819 pPrv = pPrv->GetPrev();
1820 if( pPrv )
1821 return pCol;
1825 const sal_Bool bBody = IsInDocBody();
1826 const sal_Bool bFly = IsInFly();
1828 SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
1829 SwLayoutFrm *pPrevLeaf = 0;
1831 while ( pLayLeaf )
1833 // Never step into tables or sections
1834 if ( pLayLeaf->IsInTab() || pLayLeaf->IsInSct() )
1836 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1838 else if ( bBody && pLayLeaf->IsInDocBody() )
1840 // If there is a pLayLeaf has a lower pLayLeaf is the frame we are looking for.
1841 // Exception: pLayLeaf->Lower() is a zombie section frame
1842 const SwFrm* pTmp = pLayLeaf->Lower();
1843 // OD 11.04.2003 #108824# - consider, that the zombie section frame
1844 // can have frame below it in the found layout leaf.
1845 // Thus, skipping zombie section frame, if possible.
1846 while ( pTmp && pTmp->IsSctFrm() &&
1847 !( static_cast<const SwSectionFrm*>(pTmp)->GetSection() ) &&
1848 pTmp->GetNext()
1851 pTmp = pTmp->GetNext();
1853 if ( pTmp &&
1854 ( !pTmp->IsSctFrm() ||
1855 ( static_cast<const SwSectionFrm*>(pTmp)->GetSection() )
1859 break;
1861 pPrevLeaf = pLayLeaf;
1862 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1863 if ( pLayLeaf )
1864 SwFlowFrm::SetMoveBwdJump( sal_True );
1866 else if ( bFly )
1867 break; // Cntnts in Flys every layout sheet should be right. Why?
1868 else
1869 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1871 if( !pLayLeaf )
1873 if( !pPrevLeaf )
1874 return pCol;
1875 pLayLeaf = pPrevLeaf;
1878 SwSectionFrm* pNew = NULL;
1879 // At first go to the end of the layout sheet
1880 SwFrm *pTmp = pLayLeaf->Lower();
1881 if( pTmp )
1883 while( pTmp->GetNext() )
1884 pTmp = pTmp->GetNext();
1885 if( pTmp->IsSctFrm() )
1887 // Half dead ones only interfere here
1888 while( !((SwSectionFrm*)pTmp)->GetSection() && pTmp->GetPrev() &&
1889 pTmp->GetPrev()->IsSctFrm() )
1890 pTmp = pTmp->GetPrev();
1891 if( ((SwSectionFrm*)pTmp)->GetFollow() == pSect )
1892 pNew = (SwSectionFrm*)pTmp;
1895 if( !pNew )
1897 pNew = new SwSectionFrm( *pSect, sal_True );
1898 pNew->InsertBefore( pLayLeaf, NULL );
1899 pNew->Init();
1900 SWRECTFN( pNew )
1901 (pNew->*fnRect->fnMakePos)( pLayLeaf, pNew->GetPrev(), sal_True );
1903 pLayLeaf = FIRSTLEAF( pNew );
1904 if( !pNew->Lower() ) // Format single column sections
1906 pNew->MakePos();
1907 pLayLeaf->Format(); // In order that the PrtArea is correct for the MoveBwd
1909 else
1910 pNew->SimpleFormat();
1912 else
1914 pLayLeaf = FIRSTLEAF( pNew );
1915 if( pLayLeaf->IsColBodyFrm() )
1917 // In existent section columns we're looking for the last not empty
1918 // column.
1919 SwLayoutFrm *pTmpLay = pLayLeaf;
1920 while( pLayLeaf->GetUpper()->GetNext() )
1922 pLayLeaf = (SwLayoutFrm*)((SwLayoutFrm*)pLayLeaf->GetUpper()->GetNext())->Lower();
1923 if( pLayLeaf->Lower() )
1924 pTmpLay = pLayLeaf;
1926 // If we skipped an empty column, we've to set the jump-flag
1927 if( pLayLeaf != pTmpLay )
1929 pLayLeaf = pTmpLay;
1930 SwFlowFrm::SetMoveBwdJump( sal_True );
1934 return pLayLeaf;
1937 static SwTwips lcl_DeadLine( const SwFrm* pFrm )
1939 const SwLayoutFrm* pUp = pFrm->GetUpper();
1940 while( pUp && pUp->IsInSct() )
1942 if( pUp->IsSctFrm() )
1943 pUp = pUp->GetUpper();
1944 // Columns now with BodyFrm
1945 else if( pUp->IsColBodyFrm() && pUp->GetUpper()->GetUpper()->IsSctFrm() )
1946 pUp = pUp->GetUpper()->GetUpper();
1947 else
1948 break;
1950 SWRECTFN( pFrm )
1951 return pUp ? (pUp->*fnRect->fnGetPrtBottom)() :
1952 (pFrm->Frm().*fnRect->fnGetBottom)();
1954 // SwSectionFrm::Growable(..) checks whether the SectionFrm is still able to
1955 // grow, as case may be the environment has to be asked
1957 sal_Bool SwSectionFrm::Growable() const
1959 SWRECTFN( this )
1960 if( (*fnRect->fnYDiff)( lcl_DeadLine( this ),
1961 (Frm().*fnRect->fnGetBottom)() ) > 0 )
1962 return sal_True;
1964 return ( GetUpper() && ((SwFrm*)GetUpper())->Grow( LONG_MAX, sal_True ) );
1967 /*************************************************************************
1969 |* SwSectionFrm::_Grow(), _Shrink()
1971 |*************************************************************************/
1973 SwTwips SwSectionFrm::_Grow( SwTwips nDist, sal_Bool bTst )
1975 if ( !IsColLocked() && !HasFixSize() )
1977 SWRECTFN( this )
1978 long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
1979 if( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
1980 nDist = LONG_MAX - nFrmHeight;
1982 if ( nDist <= 0L )
1983 return 0L;
1985 bool bInCalcCntnt = GetUpper() && IsInFly() && FindFlyFrm()->IsLocked();
1986 // OD 2004-03-15 #116561# - allow grow in online layout
1987 bool bGrow = !Lower() || !Lower()->IsColumnFrm() || !Lower()->GetNext() ||
1988 GetSection()->GetFmt()->GetBalancedColumns().GetValue();
1989 if( !bGrow )
1991 const ViewShell *pSh = getRootFrm()->GetCurrShell();
1992 bGrow = pSh && pSh->GetViewOptions()->getBrowseMode();
1994 if( bGrow )
1996 SwTwips nGrow;
1997 if( IsInFtn() )
1998 nGrow = 0;
1999 else
2001 nGrow = lcl_DeadLine( this );
2002 nGrow = (*fnRect->fnYDiff)( nGrow,
2003 (Frm().*fnRect->fnGetBottom)() );
2005 SwTwips nSpace = nGrow;
2006 if( !bInCalcCntnt && nGrow < nDist && GetUpper() )
2007 nGrow += GetUpper()->Grow( LONG_MAX, sal_True );
2009 if( nGrow > nDist )
2010 nGrow = nDist;
2011 if( nGrow <= 0 )
2013 nGrow = 0;
2014 if( nDist && !bTst )
2016 if( bInCalcCntnt )
2017 _InvalidateSize();
2018 else
2019 InvalidateSize();
2022 else if( !bTst )
2024 if( bInCalcCntnt )
2025 _InvalidateSize();
2026 else if( nSpace < nGrow && nDist != nSpace + GetUpper()->
2027 Grow( nGrow - nSpace, sal_False ) )
2028 InvalidateSize();
2029 else
2031 const SvxGraphicPosition ePos =
2032 GetAttrSet()->GetBackground().GetGraphicPos();
2033 if ( GPOS_RT < ePos && GPOS_TILED != ePos )
2035 SetCompletePaint();
2036 InvalidatePage();
2038 if( GetUpper() && GetUpper()->IsHeaderFrm() )
2039 GetUpper()->InvalidateSize();
2041 (Frm().*fnRect->fnAddBottom)( nGrow );
2042 long nPrtHeight = (Prt().*fnRect->fnGetHeight)() + nGrow;
2043 (Prt().*fnRect->fnSetHeight)( nPrtHeight );
2045 if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2047 SwFrm* pTmp = Lower();
2050 pTmp->_InvalidateSize();
2051 pTmp = pTmp->GetNext();
2052 } while ( pTmp );
2053 _InvalidateSize();
2055 if( GetNext() )
2057 SwFrm *pFrm = GetNext();
2058 while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
2059 pFrm = pFrm->GetNext();
2060 if( pFrm )
2062 if( bInCalcCntnt )
2063 pFrm->_InvalidatePos();
2064 else
2065 pFrm->InvalidatePos();
2068 // #i28701# - Due to the new object positioning
2069 // the frame on the next page/column can flow backward (e.g. it
2070 // was moved forward due to the positioning of its objects ).
2071 // Thus, invalivate this next frame, if document compatibility
2072 // option 'Consider wrapping style influence on object positioning' is ON.
2073 else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
2075 InvalidateNextPos();
2078 return nGrow;
2080 if ( !bTst )
2082 if( bInCalcCntnt )
2083 _InvalidateSize();
2084 else
2085 InvalidateSize();
2088 return 0L;
2091 SwTwips SwSectionFrm::_Shrink( SwTwips nDist, sal_Bool bTst )
2093 if ( Lower() && !IsColLocked() && !HasFixSize() )
2095 if( ToMaximize( sal_False ) )
2097 if( !bTst )
2098 InvalidateSize();
2100 else
2102 SWRECTFN( this )
2103 long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2104 if ( nDist > nFrmHeight )
2105 nDist = nFrmHeight;
2107 if ( Lower()->IsColumnFrm() && Lower()->GetNext() && // FtnAtEnd
2108 !GetSection()->GetFmt()->GetBalancedColumns().GetValue() )
2109 { // With column bases the format takes over the control of the
2110 // growth (because of the balance)
2111 if ( !bTst )
2112 InvalidateSize();
2113 return nDist;
2115 else if( !bTst )
2117 const SvxGraphicPosition ePos =
2118 GetAttrSet()->GetBackground().GetGraphicPos();
2119 if ( GPOS_RT < ePos && GPOS_TILED != ePos )
2121 SetCompletePaint();
2122 InvalidatePage();
2124 (Frm().*fnRect->fnAddBottom)( -nDist );
2125 long nPrtHeight = (Prt().*fnRect->fnGetHeight)() - nDist;
2126 (Prt().*fnRect->fnSetHeight)( nPrtHeight );
2128 // We do not allow a section frame to shrink the its upper
2129 // footer frame. This is because in the calculation of a
2130 // footer frame, the content of the section frame is _not_
2131 // calculated. If there is a fly frame overlapping with the
2132 // footer frame, the section frame is not affected by this
2133 // during the calculation of the footer frame size.
2134 // The footer frame does not grow in its FormatSize function
2135 // but during the calculation of the content of the section
2136 // frame. The section frame grows until some of its text is
2137 // located on top of the fly frame. The next call of CalcCntnt
2138 // tries to shrink the section and here it would also shrink
2139 // the footer. This may not happen, because shrinking the footer
2140 // would cause the top of the section frame to overlap with the
2141 // fly frame again, this would result in a perfect loop.
2142 if( GetUpper() && !GetUpper()->IsFooterFrm() )
2143 GetUpper()->Shrink( nDist, bTst );
2145 if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2147 SwFrm* pTmp = Lower();
2150 pTmp->_InvalidateSize();
2151 pTmp = pTmp->GetNext();
2152 } while ( pTmp );
2154 if( GetNext() )
2156 SwFrm* pFrm = GetNext();
2157 while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
2158 pFrm = pFrm->GetNext();
2159 if( pFrm )
2160 pFrm->InvalidatePos();
2161 else
2162 SetRetouche();
2164 else
2165 SetRetouche();
2166 return nDist;
2170 return 0L;
2173 /*************************************************************************
2175 |* SwSectionFrm::MoveAllowed()
2177 |* When are Frms within a SectionFrms moveable?
2178 |* If they are not in the last column of a SectionFrms yet,
2179 |* if there is no Follow,
2180 |* if the SectionFrm cannot grow anymore, then it gets more complicated,
2181 |* in that case it depends on whether the SectionFrm can find a next
2182 |* layout sheet. In (column based/chained) Flys this is checked via
2183 |* GetNextLayout, in tables and headers/footers there is none, however in the
2184 |* DocBody and in foot notes there is always one.
2185 |* This routine is used in the TxtFormatter to decided whether it's allowed to
2186 |* create a (paragraph-)Follow or whether the paragraph has to stick together
2188 |*************************************************************************/
2190 sal_Bool SwSectionFrm::MoveAllowed( const SwFrm* pFrm) const
2192 // Is there a Follow or is the Frame not in the last column?
2193 if( HasFollow() || ( pFrm->GetUpper()->IsColBodyFrm() &&
2194 pFrm->GetUpper()->GetUpper()->GetNext() ) )
2195 return sal_True;
2196 if( pFrm->IsInFtn() )
2198 if( IsInFtn() )
2200 if( GetUpper()->IsInSct() )
2202 if( Growable() )
2203 return sal_False;
2204 return GetUpper()->FindSctFrm()->MoveAllowed( this );
2206 else
2207 return sal_True;
2209 // The content of footnote inside a columned sectionfrm is moveable
2210 // except in the last column
2211 const SwLayoutFrm *pLay = pFrm->FindFtnFrm()->GetUpper()->GetUpper();
2212 if( pLay->IsColumnFrm() && pLay->GetNext() )
2214 // The first paragraph in the first footnote in the first column
2215 // in the sectionfrm at the top of the page is not moveable,
2216 // if the columnbody is empty.
2217 bool bRet = false;
2218 if( pLay->GetIndPrev() || pFrm->GetIndPrev() ||
2219 pFrm->FindFtnFrm()->GetPrev() )
2220 bRet = true;
2221 else
2223 SwLayoutFrm* pBody = ((SwColumnFrm*)pLay)->FindBodyCont();
2224 if( pBody && pBody->Lower() )
2225 bRet = true;
2227 if( bRet && ( IsFtnAtEnd() || !Growable() ) )
2228 return sal_True;
2231 // Or can the section still grow?
2232 if( !IsColLocked() && Growable() )
2233 return sal_False;
2234 // Now it has to be examined whether there is a layout sheet wherein
2235 // a section Follow can be created
2236 if( IsInTab() || ( !IsInDocBody() && FindFooterOrHeader() ) )
2237 return sal_False; // It doesn't work in tables/headers/footers
2238 if( IsInFly() ) // In column based or chained frames
2239 return 0 != ((SwFrm*)GetUpper())->GetNextLeaf( MAKEPAGE_NONE );
2240 return sal_True;
2243 /** Called for a frame inside a section with no direct previous frame (or only
2244 previous empty section frames) the previous frame of the outer section is
2245 returned, if the frame is the first flowing content of this section.
2247 Note: For a frame inside a table frame, which is inside a section frame,
2248 NULL is returned.
2250 SwFrm* SwFrm::_GetIndPrev() const
2252 SwFrm *pRet = NULL;
2253 // #i79774#
2254 // Do not assert, if the frame has a direct previous frame, because it
2255 // could be an empty section frame. The caller has to assure, that the
2256 // frame has no direct previous frame or only empty section frames as
2257 // previous frames.
2258 OSL_ENSURE( /*!pPrev &&*/ IsInSct(), "Why?" );
2259 const SwFrm* pSct = GetUpper();
2260 if( !pSct )
2261 return NULL;
2262 if( pSct->IsSctFrm() )
2263 pRet = pSct->GetIndPrev();
2264 else if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
2266 // Do not return the previous frame of the outer section, if in one
2267 // of the previous columns is content.
2268 const SwFrm* pCol = GetUpper()->GetUpper()->GetPrev();
2269 while( pCol )
2271 OSL_ENSURE( pCol->IsColumnFrm(), "GetIndPrev(): ColumnFrm expected" );
2272 OSL_ENSURE( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
2273 "GetIndPrev(): Where's the body?");
2274 if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
2275 return NULL;
2276 pCol = pCol->GetPrev();
2278 pRet = pSct->GetIndPrev();
2281 // skip empty section frames
2282 while( pRet && pRet->IsSctFrm() && !((SwSectionFrm*)pRet)->GetSection() )
2283 pRet = pRet->GetIndPrev();
2284 return pRet;
2287 SwFrm* SwFrm::_GetIndNext()
2289 OSL_ENSURE( !mpNext && IsInSct(), "Why?" );
2290 SwFrm* pSct = GetUpper();
2291 if( !pSct )
2292 return NULL;
2293 if( pSct->IsSctFrm() )
2294 return pSct->GetIndNext();
2295 if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
2296 { // We can only return the successor of the SectionFrms if there is no
2297 // content in the successing columns
2298 SwFrm* pCol = GetUpper()->GetUpper()->GetNext();
2299 while( pCol )
2301 OSL_ENSURE( pCol->IsColumnFrm(), "GetIndNext(): ColumnFrm expected" );
2302 OSL_ENSURE( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
2303 "GetIndNext(): Where's the body?");
2304 if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
2305 return NULL;
2306 pCol = pCol->GetNext();
2308 return pSct->GetIndNext();
2310 return NULL;
2313 sal_Bool SwSectionFrm::IsDescendantFrom( const SwSectionFmt* pFmt ) const
2315 if( !pSection || !pFmt )
2316 return sal_False;
2317 const SwSectionFmt *pMyFmt = pSection->GetFmt();
2318 while( pFmt != pMyFmt )
2320 if( pMyFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2321 pMyFmt = (SwSectionFmt*)pMyFmt->GetRegisteredIn();
2322 else
2323 return sal_False;
2325 return sal_True;
2328 void SwSectionFrm::CalcFtnAtEndFlag()
2330 SwSectionFmt *pFmt = GetSection()->GetFmt();
2331 sal_uInt16 nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
2332 bFtnAtEnd = FTNEND_ATPGORDOCEND != nVal;
2333 bOwnFtnNum = FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
2334 FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
2335 while( !bFtnAtEnd && !bOwnFtnNum )
2337 if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2338 pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
2339 else
2340 break;
2341 nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
2342 if( FTNEND_ATPGORDOCEND != nVal )
2344 bFtnAtEnd = sal_True;
2345 bOwnFtnNum = bOwnFtnNum ||FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
2346 FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
2351 bool SwSectionFrm::IsEndnoteAtMyEnd() const
2353 return pSection->GetFmt()->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2356 void SwSectionFrm::CalcEndAtEndFlag()
2358 SwSectionFmt *pFmt = GetSection()->GetFmt();
2359 bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2360 while( !bEndnAtEnd )
2362 if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2363 pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
2364 else
2365 break;
2366 bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2370 /*************************************************************************
2372 |* SwSectionFrm::Modify()
2374 |*************************************************************************/
2376 void SwSectionFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
2378 sal_uInt8 nInvFlags = 0;
2380 if( pNew && RES_ATTRSET_CHG == pNew->Which() )
2382 SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
2383 SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
2384 SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
2385 SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
2386 while( true )
2388 _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
2389 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
2390 &aOldSet, &aNewSet );
2391 if( aNIter.IsAtEnd() )
2392 break;
2393 aNIter.NextItem();
2394 aOIter.NextItem();
2396 if ( aOldSet.Count() || aNewSet.Count() )
2397 SwLayoutFrm::Modify( &aOldSet, &aNewSet );
2399 else
2400 _UpdateAttr( pOld, pNew, nInvFlags );
2402 if ( nInvFlags != 0 )
2404 if ( nInvFlags & 0x01 )
2405 InvalidateSize();
2406 if ( nInvFlags & 0x10 )
2407 SetCompletePaint();
2411 void SwSectionFrm::SwClientNotify( const SwModify& rMod, const SfxHint& rHint )
2413 // #i117863#
2414 const SwSectionFrmMoveAndDeleteHint* pHint =
2415 dynamic_cast<const SwSectionFrmMoveAndDeleteHint*>(&rHint);
2416 if ( pHint && pHint->GetId() == SFX_HINT_DYING && &rMod == GetRegisteredIn() )
2418 SwSectionFrm::MoveCntntAndDelete( this, pHint->IsSaveCntnt() );
2422 void SwSectionFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
2423 sal_uInt8 &rInvFlags,
2424 SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
2426 bool bClear = true;
2427 const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
2428 switch( nWhich )
2429 { // Suppress multi columns in foot notes
2430 case RES_FMT_CHG:
2432 const SwFmtCol& rNewCol = GetFmt()->GetCol();
2433 if( !IsInFtn() )
2435 // Nasty case. When allocating a template we can not count
2436 // on the old column attribute. We're left with creating a
2437 // temporary attribute here.
2438 SwFmtCol aCol;
2439 if ( Lower() && Lower()->IsColumnFrm() )
2441 sal_uInt16 nCol = 0;
2442 SwFrm *pTmp = Lower();
2444 { ++nCol;
2445 pTmp = pTmp->GetNext();
2446 } while ( pTmp );
2447 aCol.Init( nCol, 0, 1000 );
2449 bool bChgFtn = IsFtnAtEnd();
2450 bool const bChgEndn = IsEndnAtEnd();
2451 bool const bChgMyEndn = IsEndnoteAtMyEnd();
2452 CalcFtnAtEndFlag();
2453 CalcEndAtEndFlag();
2454 bChgFtn = ( bChgFtn != IsFtnAtEnd() ) ||
2455 ( bChgEndn != IsEndnAtEnd() ) ||
2456 ( bChgMyEndn != IsEndnoteAtMyEnd() );
2457 ChgColumns( aCol, rNewCol, bChgFtn );
2458 rInvFlags |= 0x10;
2460 rInvFlags |= 0x01;
2461 bClear = false;
2463 break;
2465 case RES_COL:
2466 if( !IsInFtn() )
2468 ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
2469 rInvFlags |= 0x11;
2471 break;
2473 case RES_FTN_AT_TXTEND:
2474 if( !IsInFtn() )
2476 bool const bOld = IsFtnAtEnd();
2477 CalcFtnAtEndFlag();
2478 if (bOld != IsFtnAtEnd())
2480 const SwFmtCol& rNewCol = GetFmt()->GetCol();
2481 ChgColumns( rNewCol, rNewCol, sal_True );
2482 rInvFlags |= 0x01;
2485 break;
2487 case RES_END_AT_TXTEND:
2488 if( !IsInFtn() )
2490 bool const bOld = IsEndnAtEnd();
2491 bool const bMyOld = IsEndnoteAtMyEnd();
2492 CalcEndAtEndFlag();
2493 if (bOld != IsEndnAtEnd() || bMyOld != IsEndnoteAtMyEnd())
2495 const SwFmtCol& rNewCol = GetFmt()->GetCol();
2496 ChgColumns( rNewCol, rNewCol, sal_True );
2497 rInvFlags |= 0x01;
2500 break;
2501 case RES_COLUMNBALANCE:
2502 rInvFlags |= 0x01;
2503 break;
2505 case RES_FRAMEDIR :
2506 SetDerivedR2L( sal_False );
2507 CheckDirChange();
2508 break;
2510 case RES_PROTECT:
2512 ViewShell *pSh = getRootFrm()->GetCurrShell();
2513 if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
2514 pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
2516 break;
2518 default:
2519 bClear = false;
2521 if ( bClear )
2523 if ( pOldSet || pNewSet )
2525 if ( pOldSet )
2526 pOldSet->ClearItem( nWhich );
2527 if ( pNewSet )
2528 pNewSet->ClearItem( nWhich );
2530 else
2531 SwLayoutFrm::Modify( pOld, pNew );
2535 /*--------------------------------------------------
2536 * SwSectionFrm::ToMaximize(..): A follow or a ftncontainer at the end of the
2537 * page causes a maximal Size of the sectionframe.
2538 * --------------------------------------------------*/
2540 sal_Bool SwSectionFrm::ToMaximize( sal_Bool bCheckFollow ) const
2542 if( HasFollow() )
2544 if( !bCheckFollow ) // Don't check superfluous follows
2545 return sal_True;
2546 const SwSectionFrm* pFoll = GetFollow();
2547 while( pFoll && pFoll->IsSuperfluous() )
2548 pFoll = pFoll->GetFollow();
2549 if( pFoll )
2550 return sal_True;
2552 if( IsFtnAtEnd() )
2553 return sal_False;
2554 const SwFtnContFrm* pCont = ContainsFtnCont();
2555 if( !IsEndnAtEnd() )
2556 return 0 != pCont;
2557 sal_Bool bRet = sal_False;
2558 while( pCont && !bRet )
2560 if( pCont->FindFootNote() )
2561 bRet = sal_True;
2562 else
2563 pCont = ContainsFtnCont( pCont );
2565 return bRet;
2568 /*--------------------------------------------------
2569 * sal_Bool SwSectionFrm::ContainsFtnCont()
2570 * checks every Column for FtnContFrms.
2571 * --------------------------------------------------*/
2573 SwFtnContFrm* SwSectionFrm::ContainsFtnCont( const SwFtnContFrm* pCont ) const
2575 SwFtnContFrm* pRet = NULL;
2576 const SwLayoutFrm* pLay;
2577 if( pCont )
2579 pLay = pCont->FindFtnBossFrm( 0 );
2580 OSL_ENSURE( IsAnLower( pLay ), "ConatainsFtnCont: Wrong FtnContainer" );
2581 pLay = (SwLayoutFrm*)pLay->GetNext();
2583 else if( Lower() && Lower()->IsColumnFrm() )
2584 pLay = (SwLayoutFrm*)Lower();
2585 else
2586 pLay = NULL;
2587 while ( !pRet && pLay )
2589 if( pLay->Lower() && pLay->Lower()->GetNext() )
2591 OSL_ENSURE( pLay->Lower()->GetNext()->IsFtnContFrm(),
2592 "ToMaximize: Unexspected Frame" );
2593 pRet = (SwFtnContFrm*)pLay->Lower()->GetNext();
2595 OSL_ENSURE( !pLay->GetNext() || pLay->GetNext()->IsLayoutFrm(),
2596 "ToMaximize: ColFrm exspected" );
2597 pLay = (SwLayoutFrm*)pLay->GetNext();
2599 return pRet;
2602 void SwSectionFrm::InvalidateFtnPos()
2604 SwFtnContFrm* pCont = ContainsFtnCont( NULL );
2605 if( pCont )
2607 SwFrm *pTmp = pCont->ContainsCntnt();
2608 if( pTmp )
2609 pTmp->_InvalidatePos();
2613 /*--------------------------------------------------
2614 * SwSectionFrm::Undersize() returns the value that the section
2615 * would like to be greater if it has undersized TxtFrms in it,
2616 * otherwise Null..
2617 * If necessary the undersized-flag is corrected.
2618 * --------------------------------------------------*/
2620 long SwSectionFrm::Undersize( sal_Bool bOverSize )
2622 bUndersized = sal_False;
2623 SWRECTFN( this )
2624 long nRet = InnerHeight() - (Prt().*fnRect->fnGetHeight)();
2625 if( nRet > 0 )
2626 bUndersized = sal_True;
2627 else if( !bOverSize )
2628 nRet = 0;
2629 return nRet;
2632 /// OD 01.04.2003 #108446# - determine next frame for footnote/endnote formatting
2633 /// before format of current one, because current one can move backward.
2634 /// After moving backward to a previous page method <FindNext()> will return
2635 /// the text frame presenting the first page footnote, if it exists. Thus, the
2636 /// rest of the footnote/endnote container would not be formatted.
2637 void SwSectionFrm::CalcFtnCntnt()
2639 SwFtnContFrm* pCont = ContainsFtnCont();
2640 if( pCont )
2642 SwFrm* pFrm = pCont->ContainsAny();
2643 if( pFrm )
2644 pCont->Calc();
2645 while( pFrm && IsAnLower( pFrm ) )
2647 SwFtnFrm* pFtn = pFrm->FindFtnFrm();
2648 if( pFtn )
2649 pFtn->Calc();
2650 // OD 01.04.2003 #108446# - determine next frame before format current frame.
2651 SwFrm* pNextFrm = 0;
2653 if( pFrm->IsSctFrm() )
2655 pNextFrm = static_cast<SwSectionFrm*>(pFrm)->ContainsAny();
2657 if( !pNextFrm )
2659 pNextFrm = pFrm->FindNext();
2662 pFrm->Calc();
2663 pFrm = pNextFrm;
2667 /* --------------------------------------------------
2668 * If a SectionFrm gets empty, e.g. because its content changes the page/column,
2669 * it is not destroyed immediately (there could be a pointer left to it on the
2670 * stack), instead it puts itself in a list at the RootFrm, which is processed
2671 * later on (in Layaction::Action among others). Its size is set to Null and
2672 * the pointer to its page as well. Such SectionFrms that are to be deleted
2673 * must be ignored by the layout/during formatting.
2675 * With InsertEmptySct the RootFrm stores a SectionFrm in the list,
2676 * with RemoveFromList it can be removed from the list (Dtor),
2677 * with DeleteEmptySct the list is processed and the SectionFrms are destroyed.
2678 * --------------------------------------------------*/
2680 void SwRootFrm::InsertEmptySct( SwSectionFrm* pDel )
2682 if( !pDestroy )
2683 pDestroy = new SwDestroyList;
2684 pDestroy->insert( pDel );
2687 void SwRootFrm::_DeleteEmptySct()
2689 OSL_ENSURE( pDestroy, "Keine Liste, keine Kekse" );
2690 while( !pDestroy->empty() )
2692 SwSectionFrm* pSect = *pDestroy->begin();
2693 pDestroy->erase( pDestroy->begin() );
2694 OSL_ENSURE( !pSect->IsColLocked() && !pSect->IsJoinLocked(),
2695 "DeleteEmptySct: Locked SectionFrm" );
2696 if( !pSect->Frm().HasArea() && !pSect->ContainsCntnt() )
2698 SwLayoutFrm* pUp = pSect->GetUpper();
2699 pSect->Remove();
2700 delete pSect;
2701 if( pUp && !pUp->Lower() )
2703 if( pUp->IsPageBodyFrm() )
2704 pUp->getRootFrm()->SetSuperfluous();
2705 else if( pUp->IsFtnFrm() && !pUp->IsColLocked() &&
2706 pUp->GetUpper() )
2708 pUp->Cut();
2709 delete pUp;
2713 else {
2714 OSL_ENSURE( pSect->GetSection(), "DeleteEmptySct: Halbtoter SectionFrm?!" );
2719 void SwRootFrm::_RemoveFromList( SwSectionFrm* pSct )
2721 OSL_ENSURE( pDestroy, "Where's my list?" );
2722 pDestroy->erase( pSct );
2725 #ifdef DBG_UTIL
2726 bool SwRootFrm::IsInDelList( SwSectionFrm* pSct ) const
2728 return pDestroy && pDestroy->find( pSct ) != pDestroy->end();
2730 #endif
2732 bool SwSectionFrm::IsBalancedSection() const
2734 bool bRet = false;
2735 if ( GetSection() && Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2737 bRet = !GetSection()->GetFmt()->GetBalancedColumns().GetValue();
2739 return bRet;
2742 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */