1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
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"
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) )
73 mnType
= FRMC_SECTION
;
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() ),
89 mnType
= FRMC_SECTION
;
91 PROTOCOL( this, PROT_SECTION
, bMaster
? ACT_CREATE_MASTER
: ACT_CREATE_FOLLOW
, &rSect
)
95 if( rSect
.IsFollow() )
97 SwSectionFrm
* pMaster
= rSect
.FindMaster();
98 pMaster
->SetFollow( this );
104 SetFollow( rSect
.GetFollow() );
105 rSect
.SetFollow( this );
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?!" );
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() );
140 SwSectionFrm::~SwSectionFrm()
142 if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
144 SwRootFrm
*pRootFrm
= getRootFrm();
146 pRootFrm
->RemoveFromList( this ); //swmod 071108//swmod 071225
149 SwSectionFrm
*pMaster
= FindMaster();
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
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
)
179 OSL_ENSURE( !bRemove
, "Don't delete locked SectionFrms" );
182 SwFrm
* pUp
= GetUpper();
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 )) );
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
210 if( !GetFollow() && !pMaster
->IsColLocked() )
211 pMaster
->InvalidateSize();
217 // If we are destroyed immediately anyway, we don't need
218 // to put us into the list
220 { // If we already were half dead before this DelEmpty,
221 // we are likely in the list and have to remove us from
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()
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();
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() )
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
280 // Furthermore a blank page could have emerged
282 { SwRootFrm
*pRoot
= (SwRootFrm
*)pPage
->GetUpper();
283 pRoot
->SetSuperfluous();
284 GetUpper()->SetCompletePaint();
287 // First remove, then shrink Upper
288 SwLayoutFrm
*pUp
= GetUpper();
292 if( pUp
&& !pUp
->Lower() && pUp
->IsFtnFrm() && !pUp
->IsColLocked() &&
301 pPrepFrm
->Prepare( PREP_FTN
);
305 SwTwips nFrmHeight
= (Frm().*fnRect
->fnGetHeight
)();
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() )
336 SwSectionFrm
* pSect
= pParent
->FindSctFrm();
338 // Assure that parent is not inside a table frame, which is inside the found section frame.
341 SwTabFrm
* pTableFrm
= pParent
->FindTabFrm();
343 pSect
->IsAnLower( pTableFrm
) )
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();
363 // Even worse: every following column content has to
364 // be attached to the pSibling-chain in order to be
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 );
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
);
387 (pSect
->*fnRect
->fnMakePos
)( pSect
->GetUpper(), pSect
->GetPrev(), sal_True
);
388 if( !((SwLayoutFrm
*)pParent
)->Lower() )
390 SwSectionFrm::MoveCntntAndDelete( (SwSectionFrm
*)pParent
, sal_False
);
395 InsertGroupBefore( pParent
, pSibling
, NULL
);
398 SwPageFrm
*pPage
= FindPageFrm();
399 InvalidatePage( pPage
);
403 pSibling
->_InvalidatePos();
404 pSibling
->_InvalidatePrt();
405 if ( pSibling
->IsCntntFrm() )
406 pSibling
->InvalidatePage( pPage
);
409 SwTwips nFrmHeight
= (Frm().*fnRect
->fnGetHeight
)();
411 pParent
->Grow( nFrmHeight
);
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() )
441 SwSectionFmt
*pTmp
= (SwSectionFmt
*)GetFmt();
442 // if( !pTmp->GetSect().GetValue() )
445 const SwFrmFmt
*pOtherFmt
= ((SwSectionFrm
*)pFrm
)->GetFmt();
448 pTmp
= pTmp
->GetParent();
451 if( pTmp
== pOtherFmt
)
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
);
475 SwFrm
* pLast
= Lower();
476 SwLayoutFrm
* pLay
= this;
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();
486 while( pLast
->GetNext() )
487 pLast
= pLast
->GetNext();
490 ::RestoreCntnt( pTmp
, pLay
, pLast
, true );
492 SetFollow( pNxt
->GetFollow() );
493 pNxt
->SetFollow( NULL
);
500 /*************************************************************************
502 |* SwSectionFrm::SplitSect()
504 |* Divides a SectionFrm into two parts. The second one starts with the
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();
517 SwSectionFrm
* pSect
= pOther
->FindSctFrm();
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
);
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
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 );
544 pNew
->SetFollow( GetFollow() );
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
566 static void lcl_InvalidateInfFlags( SwFrm
* pFrm
, bool bInva
)
570 pFrm
->InvalidateInfFlags();
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
)
591 if ( pLay
->GetNext() && pLay
->GetNext()->IsCntntFrm() )
592 return (SwCntntFrm
*)pLay
->GetNext();
596 if ( pLay
->GetPrev() && pLay
->GetPrev()->IsCntntFrm() )
597 return (SwCntntFrm
*)pLay
->GetPrev();
601 const SwFrm
* pFrm
= pLay
;
602 SwCntntFrm
*pCntntFrm
= 0;
603 bool bGoingUp
= true;
606 bool bGoingFwdOrBwd
= false;
608 bool bGoingDown
= !bGoingUp
&& ( 0 != ( p
= pFrm
->IsLayoutFrm() ? ((SwLayoutFrm
*)pFrm
)->Lower() : 0 ) );
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() ) );
622 bGoingUp
= !( bGoingFwdOrBwd
|| bGoingDown
);
624 if( !bFwd
&& bGoingDown
&& p
)
625 while ( p
->GetNext() )
629 } while ( 0 == (pCntntFrm
= (pFrm
->IsCntntFrm() ? (SwCntntFrm
*)pFrm
:0) ));
634 #define FIRSTLEAF( pLayFrm ) ( ( pLayFrm->Lower() && pLayFrm->Lower()->IsColumnFrm() )\
635 ? pLayFrm->GetNextLayoutLeaf() \
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() )
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.
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
;
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
);
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
);
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
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
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
);
719 (pPrvSct
->*fnRect
->fnMakePos
)( pUp
, pPrv
, sal_True
);
720 pUp
= FIRSTLEAF( pPrvSct
);
723 pPrvSct
= NULL
; // Such that nothing will be merged
726 // The content is going to be inserted..
729 lcl_InvalidateInfFlags( pSave
, bSize
);
730 ::RestoreCntnt( pSave
, pUp
, pPrv
, true );
731 pUp
->FindPageFrm()->InvalidateCntnt();
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 )
747 if( !pSection
) // Via DelEmpty
750 OSL_ENSURE( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
756 SWRECTFN( GetUpper() )
757 (this->*fnRect
->fnMakePos
)( GetUpper(), GetPrev(), sal_False
);
760 mbValidSize
= mbValidPos
= mbValidPrtArea
= sal_True
;
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() )
773 // OD 2004-03-15 #116561# - In online layout join the follows, if section
775 const ViewShell
*pSh
= getRootFrm()->GetCurrShell();
776 if( pSh
&& pSh
->GetViewOptions()->getBrowseMode() &&
777 ( Grow( LONG_MAX
, true ) > 0 ) )
781 const SwFrm
* pFoll
= GetFollow();
782 MergeNext( GetFollow() );
783 if( pFoll
== GetFollow() )
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();
797 SwLayoutFrm::MakeAll();
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?" );
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();
822 static void lcl_FindCntntFrm( SwCntntFrm
* &rpCntntFrm
, SwFtnFrm
* &rpFtnFrm
,
823 SwFrm
* pFrm
, sal_Bool
&rbChkFtn
)
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() )
839 rpFtnFrm
= (SwFtnFrm
*)pFrm
;
840 rbChkFtn
= rpFtnFrm
->GetAttr()->GetFtn().IsEndNote();
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;
859 const SwSectionFmt
*pFmt
= IsEndnAtEnd() ? GetEndSectFmt() :
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
;
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
) )
882 pSect
= pSect
->FindMaster();
884 if( ( nMode
== FINDMODE_ENDNOTE
) && pFtnFrm
)
885 pRet
= pFtnFrm
->ContainsCntnt();
889 sal_Bool
SwSectionFrm::CalcMinDiff( SwTwips
& rMinDiff
) const
891 if( ToMaximize( sal_True
) )
894 rMinDiff
= (GetUpper()->*fnRect
->fnGetPrtBottom
)();
895 rMinDiff
= (Frm().*fnRect
->fnBottomDist
)( rMinDiff
);
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
;
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();
932 SwFtnFrm
* pRet
= (SwFtnFrm
*)pFtnCont
->Lower();
933 while( pRet
) // look for endnotes
935 /* CollectEndNode can destroy pRet so we need to get the
938 SwFtnFrm
* pRetNext
= (SwFtnFrm
*)pRet
->GetNext();
939 if( pRet
->GetAttr()->GetFtn().IsEndNote() )
941 if( pRet
->GetMaster() )
944 pLayouter
->CollectEndnote( pRet
);
949 return pRet
; // Found
954 pCol
= (SwColumnFrm
*)pCol
->GetNext();
957 pSect
= pLayouter
? pSect
->GetFollow() : NULL
;
963 static void lcl_ColumnRefresh( SwSectionFrm
* pSect
, bool bFollow
)
967 sal_Bool bOldLock
= pSect
->IsColLocked();
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();
984 pSect
= pSect
->GetFollow();
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;
999 // pSect is the last sectionfrm without endnotes or the this-pointer
1000 // the first sectionfrm with endnotes may be destroyed, when the endnotes
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
)
1027 SwTwips nDeadLine
= (GetUpper()->*fnRect
->fnGetPrtBottom
)();
1028 if( bGrow
&& ( !IsInFly() || !GetUpper()->IsColBodyFrm() ||
1029 !FindFlyFrm()->IsLocked() ) )
1031 nDiff
= -(Frm().*fnRect
->fnBottomDist
)( nDeadLine
);
1033 nDiff
+= Undersize();
1036 long nAdd
= GetUpper()->Grow( nDiff
);
1037 if( bVert
&& !bRev
)
1043 nDiff
= -(Frm().*fnRect
->fnBottomDist
)( nDeadLine
);
1044 SetUndersized( !bMaximize
&& nDiff
>= 0 );
1045 const bool bCalc
= ( IsUndersized() || bMaximize
) &&
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
;
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() ) )
1065 else if( GetFollow() && !GetFollow()->ContainsAny() )
1068 if ( bCalc
|| bExtraCalc
)
1070 nDiff
= (*fnRect
->fnYDiff
)( nDeadLine
, (Frm().*fnRect
->fnGetTop
)() );
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
)();
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 );
1106 ChgLowersProp( aOldSz
);
1107 if( !bMaximize
&& !IsCntntLocked() )
1108 ::CalcCntnt( this );
1114 void SwSectionFrm::SimpleFormat()
1116 if ( IsJoinLocked() || IsColLocked() )
1118 // OSL_ENSURE( pFollow, "SimpleFormat: Follow required" );
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
)
1139 (this->*fnRect
->fnSetYMargins
)( nTop
, 0 );
1141 lcl_ColumnRefresh( this, false );
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
1150 SwSectionFrm
* mpSectFrm
;
1151 bool mbExtraFormatPerformed
;
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;
1169 for ( i
= 0; i
< pObjs
->Count(); ++i
)
1171 SwAnchoredObject
* pAnchoredObj
= (*pObjs
)[i
];
1173 if ( mpSectFrm
->IsAnLower( pAnchoredObj
->GetAnchorFrm() ) )
1175 pAnchoredObj
->SetKeepPosLocked( false );
1183 void InitObjs( SwFrm
& rFrm
)
1185 SwSortedObjs
* pObjs
= rFrm
.GetDrawObjs();
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 );
1225 // suppress formatting, if printing area of section is too narrow
1226 if ( (mpSectFrm
->Prt().*fnRect
->fnGetHeight
)() <= 0 )
1230 mpSectFrm
->ChgLowersProp( aOldSectPrtSize
);
1232 // format column frames and its body and footnote container
1233 SwColumnFrm
* pColFrm
= static_cast<SwColumnFrm
*>(mpSectFrm
->Lower());
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
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;
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
1293 OSL_ENSURE( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
1295 mbValidSize
= mbValidPos
= mbValidPrtArea
= sal_True
;
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();
1314 pOwn
->_InvalidatePos();
1316 (this->*fnRect
->fnSetYMargins
)( nUpper
, 0 );
1321 PROTOCOL_ENTER( this, PROT_SIZE
, 0, 0 )
1322 const long nOldHeight
= (Frm().*fnRect
->fnGetHeight
)();
1323 sal_Bool bOldLock
= IsColLocked();
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.
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 );
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
);
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();
1380 SwTwips nRemaining
= (this->*fnRect
->fnGetTopMargin
)();
1381 SwFrm
*pFrm
= pLower
;
1384 if( pFrm
->IsColumnFrm() && pFrm
->GetNext() )
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() )
1402 bMaximize
= ToMaximize( sal_False
);
1403 nRemaining
+= (pFrm
->Frm().*fnRect
->fnGetHeight
)();
1407 if( pFrm
->IsColumnFrm() )
1410 pFrm
= ((SwColumnFrm
*)pFrm
)->Lower();
1412 pFrm
= ((SwLayoutFrm
*)pFrm
)->Lower();
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
;
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
);
1435 nTmpDiff
= GetUpper()->Grow( nTmpDiff
, sal_True
);
1436 nDeadLine
= (*fnRect
->fnYInc
)( nDeadLine
, nTmpDiff
);
1437 nTmpDiff
= (*fnRect
->fnYDiff
)( nBottom
, nDeadLine
);
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
1458 if( pFrm
->IsColumnFrm() )
1460 pFrm
->_InvalidateSize();
1461 pFrm
->_InvalidatePos();
1463 pFrm
= ((SwColumnFrm
*)pFrm
)->Lower();
1465 pFrm
= ((SwLayoutFrm
*)pFrm
)->Lower();
1468 bool bUnderSz
= false;
1471 if( pFrm
->IsTxtFrm() && ((SwTxtFrm
*)pFrm
)->IsUndersized() )
1473 pFrm
->Prepare( PREP_ADJUST_FRM
);
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
1487 _CheckClipping( sal_True
, bMaximize
);
1490 long nDiff
= nOldHeight
- (Frm().*fnRect
->fnGetHeight
)();
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
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() )
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
1543 if( pSect
->HasFollow() && pSect
->IsInDocBody() )
1545 if( pSect
->GetFollow() == pSect
->GetNext() )
1547 SwPageFrm
*pPg
= pSect
->GetFollow()->FindPageFrm();
1548 if( WrongPageDesc( pPg
) )
1551 return FIRSTLEAF( pSect
->GetFollow() );
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
) )
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
1593 else if( IsTabFrm() )
1595 SwCntntFrm
* pTmpCnt
= ((SwTabFrm
*)this)->FindLastCntnt();
1596 pLayLeaf
= pTmpCnt
? pTmpCnt
->GetUpper() : 0;
1600 pLayLeaf
= GetNextLayoutLeaf();
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
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
1619 SwPageFrm
* pNxtPg
= pLayLeaf
->FindPageFrm();
1620 if ( !bFtnPage
&& pNxtPg
->IsFtnPage() )
1621 { // If I reached the end note pages it's over
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();
1637 if( WrongPageDesc( pNxtPg
) )
1640 break; // there's a column between me and my right page
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(),
1654 // and again the whole thing
1655 pLayLeaf
= pOldLayLeaf
? pOldLayLeaf
: GetNextLayoutLeaf();
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
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
)
1679 pNew
= new SwSectionFrm( *pSect
, sal_False
);
1680 pNew
->InsertBefore( pLayLeaf
, pLayLeaf
->Lower() );
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() )
1691 SwCntntFrm
* pNxtCntnt
= NULL
;
1692 if( pTmp
->IsCntntFrm() )
1694 pNxt
= (SwCntntFrm
*)pTmp
;
1695 pNxtCntnt
= (SwCntntFrm
*)pTmp
;
1699 pNxtCntnt
= ((SwLayoutFrm
*)pTmp
)->ContainsCntnt();
1700 if( pTmp
->IsSctFrm() )
1701 pNxt
= (SwSectionFrm
*)pTmp
;
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
;
1712 pNxtCntnt
= ((SwLayoutFrm
*)pTmp
)->ContainsCntnt();
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
);
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() )
1752 // ColumnFrm always contain a BodyFrm now
1753 if( IsColBodyFrm() )
1755 else if( GetUpper()->IsColBodyFrm() )
1756 pCol
= GetUpper()->GetUpper();
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
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();
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() )
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
1801 SwSectionFrm
*pSect
= FindSctFrm();
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() )
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();
1825 const sal_Bool bBody
= IsInDocBody();
1826 const sal_Bool bFly
= IsInFly();
1828 SwLayoutFrm
*pLayLeaf
= GetPrevLayoutLeaf();
1829 SwLayoutFrm
*pPrevLeaf
= 0;
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() ) &&
1851 pTmp
= pTmp
->GetNext();
1854 ( !pTmp
->IsSctFrm() ||
1855 ( static_cast<const SwSectionFrm
*>(pTmp
)->GetSection() )
1861 pPrevLeaf
= pLayLeaf
;
1862 pLayLeaf
= pLayLeaf
->GetPrevLayoutLeaf();
1864 SwFlowFrm::SetMoveBwdJump( sal_True
);
1867 break; // Cntnts in Flys every layout sheet should be right. Why?
1869 pLayLeaf
= pLayLeaf
->GetPrevLayoutLeaf();
1875 pLayLeaf
= pPrevLeaf
;
1878 SwSectionFrm
* pNew
= NULL
;
1879 // At first go to the end of the layout sheet
1880 SwFrm
*pTmp
= pLayLeaf
->Lower();
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
;
1897 pNew
= new SwSectionFrm( *pSect
, sal_True
);
1898 pNew
->InsertBefore( pLayLeaf
, NULL
);
1901 (pNew
->*fnRect
->fnMakePos
)( pLayLeaf
, pNew
->GetPrev(), sal_True
);
1903 pLayLeaf
= FIRSTLEAF( pNew
);
1904 if( !pNew
->Lower() ) // Format single column sections
1907 pLayLeaf
->Format(); // In order that the PrtArea is correct for the MoveBwd
1910 pNew
->SimpleFormat();
1914 pLayLeaf
= FIRSTLEAF( pNew
);
1915 if( pLayLeaf
->IsColBodyFrm() )
1917 // In existent section columns we're looking for the last not empty
1919 SwLayoutFrm
*pTmpLay
= pLayLeaf
;
1920 while( pLayLeaf
->GetUpper()->GetNext() )
1922 pLayLeaf
= (SwLayoutFrm
*)((SwLayoutFrm
*)pLayLeaf
->GetUpper()->GetNext())->Lower();
1923 if( pLayLeaf
->Lower() )
1926 // If we skipped an empty column, we've to set the jump-flag
1927 if( pLayLeaf
!= pTmpLay
)
1930 SwFlowFrm::SetMoveBwdJump( sal_True
);
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();
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
1960 if( (*fnRect
->fnYDiff
)( lcl_DeadLine( this ),
1961 (Frm().*fnRect
->fnGetBottom
)() ) > 0 )
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() )
1978 long nFrmHeight
= (Frm().*fnRect
->fnGetHeight
)();
1979 if( nFrmHeight
> 0 && nDist
> (LONG_MAX
- nFrmHeight
) )
1980 nDist
= LONG_MAX
- nFrmHeight
;
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();
1991 const ViewShell
*pSh
= getRootFrm()->GetCurrShell();
1992 bGrow
= pSh
&& pSh
->GetViewOptions()->getBrowseMode();
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
);
2014 if( nDist
&& !bTst
)
2026 else if( nSpace
< nGrow
&& nDist
!= nSpace
+ GetUpper()->
2027 Grow( nGrow
- nSpace
, sal_False
) )
2031 const SvxGraphicPosition ePos
=
2032 GetAttrSet()->GetBackground().GetGraphicPos();
2033 if ( GPOS_RT
< ePos
&& GPOS_TILED
!= ePos
)
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();
2057 SwFrm
*pFrm
= GetNext();
2058 while( pFrm
&& pFrm
->IsSctFrm() && !((SwSectionFrm
*)pFrm
)->GetSection() )
2059 pFrm
= pFrm
->GetNext();
2063 pFrm
->_InvalidatePos();
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();
2091 SwTwips
SwSectionFrm::_Shrink( SwTwips nDist
, sal_Bool bTst
)
2093 if ( Lower() && !IsColLocked() && !HasFixSize() )
2095 if( ToMaximize( sal_False
) )
2103 long nFrmHeight
= (Frm().*fnRect
->fnGetHeight
)();
2104 if ( 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)
2117 const SvxGraphicPosition ePos
=
2118 GetAttrSet()->GetBackground().GetGraphicPos();
2119 if ( GPOS_RT
< ePos
&& GPOS_TILED
!= ePos
)
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();
2156 SwFrm
* pFrm
= GetNext();
2157 while( pFrm
&& pFrm
->IsSctFrm() && !((SwSectionFrm
*)pFrm
)->GetSection() )
2158 pFrm
= pFrm
->GetNext();
2160 pFrm
->InvalidatePos();
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() ) )
2196 if( pFrm
->IsInFtn() )
2200 if( GetUpper()->IsInSct() )
2204 return GetUpper()->FindSctFrm()->MoveAllowed( this );
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.
2218 if( pLay
->GetIndPrev() || pFrm
->GetIndPrev() ||
2219 pFrm
->FindFtnFrm()->GetPrev() )
2223 SwLayoutFrm
* pBody
= ((SwColumnFrm
*)pLay
)->FindBodyCont();
2224 if( pBody
&& pBody
->Lower() )
2227 if( bRet
&& ( IsFtnAtEnd() || !Growable() ) )
2231 // Or can the section still grow?
2232 if( !IsColLocked() && Growable() )
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
);
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,
2250 SwFrm
* SwFrm::_GetIndPrev() const
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
2258 OSL_ENSURE( /*!pPrev &&*/ IsInSct(), "Why?" );
2259 const SwFrm
* pSct
= GetUpper();
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();
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() )
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();
2287 SwFrm
* SwFrm::_GetIndNext()
2289 OSL_ENSURE( !mpNext
&& IsInSct(), "Why?" );
2290 SwFrm
* pSct
= GetUpper();
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();
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() )
2306 pCol
= pCol
->GetNext();
2308 return pSct
->GetIndNext();
2313 sal_Bool
SwSectionFrm::IsDescendantFrom( const SwSectionFmt
* pFmt
) const
2315 if( !pSection
|| !pFmt
)
2317 const SwSectionFmt
*pMyFmt
= pSection
->GetFmt();
2318 while( pFmt
!= pMyFmt
)
2320 if( pMyFmt
->GetRegisteredIn()->ISA( SwSectionFmt
) )
2321 pMyFmt
= (SwSectionFmt
*)pMyFmt
->GetRegisteredIn();
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();
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();
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
);
2388 _UpdateAttr( (SfxPoolItem
*)aOIter
.GetCurItem(),
2389 (SfxPoolItem
*)aNIter
.GetCurItem(), nInvFlags
,
2390 &aOldSet
, &aNewSet
);
2391 if( aNIter
.IsAtEnd() )
2396 if ( aOldSet
.Count() || aNewSet
.Count() )
2397 SwLayoutFrm::Modify( &aOldSet
, &aNewSet
);
2400 _UpdateAttr( pOld
, pNew
, nInvFlags
);
2402 if ( nInvFlags
!= 0 )
2404 if ( nInvFlags
& 0x01 )
2406 if ( nInvFlags
& 0x10 )
2411 void SwSectionFrm::SwClientNotify( const SwModify
& rMod
, const SfxHint
& rHint
)
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
)
2427 const sal_uInt16 nWhich
= pOld
? pOld
->Which() : pNew
? pNew
->Which() : 0;
2429 { // Suppress multi columns in foot notes
2432 const SwFmtCol
& rNewCol
= GetFmt()->GetCol();
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.
2439 if ( Lower() && Lower()->IsColumnFrm() )
2441 sal_uInt16 nCol
= 0;
2442 SwFrm
*pTmp
= Lower();
2445 pTmp
= pTmp
->GetNext();
2447 aCol
.Init( nCol
, 0, 1000 );
2449 bool bChgFtn
= IsFtnAtEnd();
2450 bool const bChgEndn
= IsEndnAtEnd();
2451 bool const bChgMyEndn
= IsEndnoteAtMyEnd();
2454 bChgFtn
= ( bChgFtn
!= IsFtnAtEnd() ) ||
2455 ( bChgEndn
!= IsEndnAtEnd() ) ||
2456 ( bChgMyEndn
!= IsEndnoteAtMyEnd() );
2457 ChgColumns( aCol
, rNewCol
, bChgFtn
);
2468 ChgColumns( *(const SwFmtCol
*)pOld
, *(const SwFmtCol
*)pNew
);
2473 case RES_FTN_AT_TXTEND
:
2476 bool const bOld
= IsFtnAtEnd();
2478 if (bOld
!= IsFtnAtEnd())
2480 const SwFmtCol
& rNewCol
= GetFmt()->GetCol();
2481 ChgColumns( rNewCol
, rNewCol
, sal_True
);
2487 case RES_END_AT_TXTEND
:
2490 bool const bOld
= IsEndnAtEnd();
2491 bool const bMyOld
= IsEndnoteAtMyEnd();
2493 if (bOld
!= IsEndnAtEnd() || bMyOld
!= IsEndnoteAtMyEnd())
2495 const SwFmtCol
& rNewCol
= GetFmt()->GetCol();
2496 ChgColumns( rNewCol
, rNewCol
, sal_True
);
2501 case RES_COLUMNBALANCE
:
2506 SetDerivedR2L( sal_False
);
2512 ViewShell
*pSh
= getRootFrm()->GetCurrShell();
2513 if( pSh
&& pSh
->GetLayout()->IsAnyShellAccessible() )
2514 pSh
->Imp()->InvalidateAccessibleEditableState( sal_True
, this );
2523 if ( pOldSet
|| pNewSet
)
2526 pOldSet
->ClearItem( nWhich
);
2528 pNewSet
->ClearItem( nWhich
);
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
2544 if( !bCheckFollow
) // Don't check superfluous follows
2546 const SwSectionFrm
* pFoll
= GetFollow();
2547 while( pFoll
&& pFoll
->IsSuperfluous() )
2548 pFoll
= pFoll
->GetFollow();
2554 const SwFtnContFrm
* pCont
= ContainsFtnCont();
2555 if( !IsEndnAtEnd() )
2557 sal_Bool bRet
= sal_False
;
2558 while( pCont
&& !bRet
)
2560 if( pCont
->FindFootNote() )
2563 pCont
= ContainsFtnCont( pCont
);
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
;
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();
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();
2602 void SwSectionFrm::InvalidateFtnPos()
2604 SwFtnContFrm
* pCont
= ContainsFtnCont( NULL
);
2607 SwFrm
*pTmp
= pCont
->ContainsCntnt();
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,
2617 * If necessary the undersized-flag is corrected.
2618 * --------------------------------------------------*/
2620 long SwSectionFrm::Undersize( sal_Bool bOverSize
)
2622 bUndersized
= sal_False
;
2624 long nRet
= InnerHeight() - (Prt().*fnRect
->fnGetHeight
)();
2626 bUndersized
= sal_True
;
2627 else if( !bOverSize
)
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();
2642 SwFrm
* pFrm
= pCont
->ContainsAny();
2645 while( pFrm
&& IsAnLower( pFrm
) )
2647 SwFtnFrm
* pFtn
= pFrm
->FindFtnFrm();
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();
2659 pNextFrm
= pFrm
->FindNext();
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
)
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();
2701 if( pUp
&& !pUp
->Lower() )
2703 if( pUp
->IsPageBodyFrm() )
2704 pUp
->getRootFrm()->SetSuperfluous();
2705 else if( pUp
->IsFtnFrm() && !pUp
->IsColLocked() &&
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
);
2726 bool SwRootFrm::IsInDelList( SwSectionFrm
* pSct
) const
2728 return pDestroy
&& pDestroy
->find( pSct
) != pDestroy
->end();
2732 bool SwSectionFrm::IsBalancedSection() const
2735 if ( GetSection() && Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2737 bRet
= !GetSection()->GetFmt()->GetBalancedColumns().GetValue();
2742 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */