Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
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/brshitem.hxx>
52 : #include <fmtftntx.hxx>
53 : // OD 2004-05-24 #i28701#
54 : #include <dflyobj.hxx>
55 : #include <flyfrms.hxx>
56 : #include <sortedobjs.hxx>
57 :
58 : /*************************************************************************
59 : |*
60 : |* SwSectionFrm::SwSectionFrm(), ~SwSectionFrm()
61 : |*
62 : |*************************************************************************/
63 76 : SwSectionFrm::SwSectionFrm( SwSection &rSect, SwFrm* pSib )
64 76 : : 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 76 : , bFtnLock(false)
72 : {
73 76 : nType = FRMC_SECTION;
74 :
75 76 : CalcFtnAtEndFlag();
76 76 : CalcEndAtEndFlag();
77 76 : }
78 :
79 4 : SwSectionFrm::SwSectionFrm( SwSectionFrm &rSect, sal_Bool bMaster ) :
80 8 : SwLayoutFrm( rSect.GetFmt(), rSect.getRootFrm() ),
81 : SwFlowFrm( (SwFrm&)*this ),
82 4 : pSection( rSect.GetSection() ),
83 4 : bFtnAtEnd( rSect.IsFtnAtEnd() ),
84 4 : bEndnAtEnd( rSect.IsEndnAtEnd() ),
85 : bCntntLock( false ),
86 : bOwnFtnNum( false ),
87 20 : bFtnLock( false )
88 : {
89 4 : nType = FRMC_SECTION;
90 :
91 : PROTOCOL( this, PROT_SECTION, bMaster ? ACT_CREATE_MASTER : ACT_CREATE_FOLLOW, &rSect )
92 :
93 4 : if( bMaster )
94 : {
95 0 : if( rSect.IsFollow() )
96 : {
97 0 : SwSectionFrm* pMaster = rSect.FindMaster();
98 0 : pMaster->SetFollow( this );
99 : }
100 0 : SetFollow( &rSect );
101 : }
102 : else
103 : {
104 4 : SetFollow( rSect.GetFollow() );
105 4 : rSect.SetFollow( this );
106 4 : if( !GetFollow() )
107 4 : rSect.SimpleFormat();
108 4 : if( !rSect.IsColLocked() )
109 4 : rSect.InvalidateSize();
110 : }
111 4 : }
112 :
113 : // NOTE: call <SwSectionFrm::Init()> directly after creation of a new section
114 : // frame and its insert in the layout.
115 80 : void SwSectionFrm::Init()
116 : {
117 : OSL_ENSURE( GetUpper(), "SwSectionFrm::Init before insertion?!" );
118 80 : SWRECTFN( this )
119 80 : long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
120 80 : (Frm().*fnRect->fnSetWidth)( nWidth );
121 80 : (Frm().*fnRect->fnSetHeight)( 0 );
122 :
123 : // #109700# LRSpace for sections
124 80 : const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
125 80 : (Prt().*fnRect->fnSetLeft)( rLRSpace.GetLeft() );
126 160 : (Prt().*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
127 160 : rLRSpace.GetRight() );
128 80 : (Prt().*fnRect->fnSetHeight)( 0 );
129 :
130 80 : const SwFmtCol &rCol = GetFmt()->GetCol();
131 80 : if( ( rCol.GetNumCols() > 1 || IsAnyNoteAtEnd() ) && !IsInFtn() )
132 : {
133 0 : const SwFmtCol *pOld = Lower() ? &rCol : new SwFmtCol;
134 0 : ChgColumns( *pOld, rCol, IsAnyNoteAtEnd() );
135 0 : if( pOld != &rCol )
136 0 : delete pOld;
137 : }
138 80 : }
139 :
140 6 : SwSectionFrm::~SwSectionFrm()
141 : {
142 2 : if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
143 : {
144 0 : SwRootFrm *pRootFrm = getRootFrm();
145 0 : if( pRootFrm )
146 0 : pRootFrm->RemoveFromList( this ); //swmod 071108//swmod 071225
147 0 : if( IsFollow() )
148 : {
149 0 : SwSectionFrm *pMaster = FindMaster();
150 0 : if( pMaster )
151 : {
152 : PROTOCOL( this, PROT_SECTION, ACT_DEL_FOLLOW, pMaster )
153 0 : 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 0 : if( !GetFollow() )
159 0 : pMaster->InvalidateSize();
160 : }
161 : }
162 0 : else if( HasFollow() )
163 : {
164 : PROTOCOL( this, PROT_SECTION, ACT_DEL_MASTER, GetFollow() )
165 : }
166 : }
167 4 : }
168 :
169 :
170 : /*************************************************************************
171 : |*
172 : |* SwSectionFrm::DelEmpty()
173 : |*
174 : |*************************************************************************/
175 0 : void SwSectionFrm::DelEmpty( sal_Bool bRemove )
176 : {
177 0 : if( IsColLocked() )
178 : {
179 : OSL_ENSURE( !bRemove, "Don't delete locked SectionFrms" );
180 0 : return;
181 : }
182 0 : SwFrm* pUp = GetUpper();
183 0 : if( pUp )
184 : {
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.
190 : {
191 0 : ViewShell* pViewShell( getRootFrm()->GetCurrShell() );
192 0 : if ( pViewShell && pViewShell->GetLayout() &&
193 0 : pViewShell->GetLayout()->IsAnyShellAccessible() )
194 : {
195 : pViewShell->InvalidateAccessibleParaFlowRelation(
196 0 : dynamic_cast<SwTxtFrm*>(FindNextCnt( true )),
197 0 : dynamic_cast<SwTxtFrm*>(FindPrevCnt( true )) );
198 : }
199 : }
200 0 : _Cut( bRemove );
201 : }
202 0 : if( IsFollow() )
203 : {
204 0 : SwSectionFrm *pMaster = FindMaster();
205 0 : 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 0 : if( !GetFollow() && !pMaster->IsColLocked() )
211 0 : pMaster->InvalidateSize();
212 : }
213 0 : SetFollow(0);
214 0 : if( pUp )
215 : {
216 0 : Frm().Height( 0 );
217 : // If we are destroyed immediately anyway, we don't need
218 : // to put us into the list
219 0 : 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 0 : if( !pSection && getRootFrm() )
224 0 : getRootFrm()->RemoveFromList( this );
225 : }
226 0 : else if( getRootFrm() )
227 0 : getRootFrm()->InsertEmptySct( this ); //swmod 071108//swmod 071225
228 0 : pSection = NULL; // like this a reanimation is virtually impossible though
229 : }
230 : }
231 :
232 : /*************************************************************************
233 : |*
234 : |* SwSectionFrm::Cut()
235 : |*
236 : |*************************************************************************/
237 0 : void SwSectionFrm::Cut()
238 : {
239 0 : _Cut( sal_True );
240 0 : }
241 :
242 0 : void SwSectionFrm::_Cut( sal_Bool bRemove )
243 : {
244 : OSL_ENSURE( GetUpper(), "Cut ohne Upper()." );
245 :
246 : PROTOCOL( this, PROT_CUT, 0, GetUpper() )
247 :
248 0 : SwPageFrm *pPage = FindPageFrm();
249 0 : InvalidatePage( pPage );
250 0 : SwFrm *pFrm = GetNext();
251 0 : SwFrm* pPrepFrm = NULL;
252 0 : while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
253 0 : pFrm = pFrm->GetNext();
254 0 : 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 0 : pFrm->_InvalidatePrt();
258 0 : pFrm->_InvalidatePos();
259 0 : if( pFrm->IsSctFrm() )
260 0 : pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
261 0 : if ( pFrm && pFrm->IsCntntFrm() )
262 : {
263 0 : pFrm->InvalidatePage( pPage );
264 0 : if( IsInFtn() && !GetIndPrev() )
265 0 : pPrepFrm = pFrm;
266 : }
267 : }
268 : else
269 : {
270 0 : InvalidateNextPos();
271 : // Someone has to take over the retouching: predecessor or Upper
272 0 : if ( 0 != (pFrm = GetPrev()) )
273 0 : { pFrm->SetRetouche();
274 0 : pFrm->Prepare( PREP_WIDOWS_ORPHANS );
275 0 : if ( pFrm->IsCntntFrm() )
276 0 : pFrm->InvalidatePage( pPage );
277 : }
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 0 : { SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
283 0 : pRoot->SetSuperfluous();
284 0 : GetUpper()->SetCompletePaint();
285 : }
286 : }
287 : // First remove, then shrink Upper
288 0 : SwLayoutFrm *pUp = GetUpper();
289 0 : if( bRemove )
290 : {
291 0 : Remove();
292 0 : if( pUp && !pUp->Lower() && pUp->IsFtnFrm() && !pUp->IsColLocked() &&
293 0 : pUp->GetUpper() )
294 : {
295 0 : pUp->Cut();
296 0 : delete pUp;
297 0 : pUp = NULL;
298 : }
299 : }
300 0 : if( pPrepFrm )
301 0 : pPrepFrm->Prepare( PREP_FTN );
302 0 : if ( pUp )
303 : {
304 0 : SWRECTFN( this );
305 0 : SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
306 0 : if( nFrmHeight > 0 )
307 : {
308 0 : if( !bRemove )
309 : {
310 0 : (Frm().*fnRect->fnSetHeight)( 0 );
311 0 : (Prt().*fnRect->fnSetHeight)( 0 );
312 : }
313 0 : pUp->Shrink( nFrmHeight );
314 : }
315 : }
316 0 : }
317 :
318 : /*************************************************************************
319 : |*
320 : |* SwSectionFrm::Paste()
321 : |*
322 : |*************************************************************************/
323 :
324 0 : void SwSectionFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
325 : {
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." );
332 :
333 : PROTOCOL( this, PROT_PASTE, 0, GetUpper() )
334 :
335 : // Add to the tree
336 0 : SwSectionFrm* pSect = pParent->FindSctFrm();
337 : // #156927#
338 : // Assure that parent is not inside a table frame, which is inside the found section frame.
339 0 : if ( pSect )
340 : {
341 0 : SwTabFrm* pTableFrm = pParent->FindTabFrm();
342 0 : if ( pTableFrm &&
343 0 : pSect->IsAnLower( pTableFrm ) )
344 : {
345 0 : pSect = 0;
346 : }
347 : }
348 :
349 0 : SWRECTFN( pParent )
350 0 : if( pSect && HasToBreak( pSect ) )
351 : {
352 0 : if( pParent->IsColBodyFrm() ) // dealing with a single-column area
353 : {
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 0 : SwColumnFrm *pCol = (SwColumnFrm*)pParent->GetUpper();
359 0 : while( !pSibling && 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
360 0 : pSibling = ((SwLayoutFrm*)((SwColumnFrm*)pCol)->Lower())->Lower();
361 0 : if( pSibling )
362 : {
363 : // Even worse: every following column content has to
364 : // be attached to the pSibling-chain in order to be
365 : // taken along
366 0 : SwFrm *pTmp = pSibling;
367 0 : while ( 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
368 : {
369 0 : while ( pTmp->GetNext() )
370 0 : pTmp = pTmp->GetNext();
371 0 : SwFrm* pSave = ::SaveCntnt( pCol );
372 0 : ::RestoreCntnt( pSave, pSibling->GetUpper(), pTmp, true );
373 : }
374 : }
375 : }
376 0 : pParent = pSect;
377 0 : 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 0 : pSect->SetFollow( ((SwSectionFrm*)pParent)->GetFollow() );
381 0 : ((SwSectionFrm*)pParent)->SetFollow( NULL );
382 0 : if( pSect->GetFollow() )
383 0 : pParent->_InvalidateSize();
384 :
385 0 : InsertGroupBefore( pParent, pSibling, pSect );
386 0 : pSect->Init();
387 0 : (pSect->*fnRect->fnMakePos)( pSect->GetUpper(), pSect->GetPrev(), sal_True);
388 0 : if( !((SwLayoutFrm*)pParent)->Lower() )
389 : {
390 0 : SwSectionFrm::MoveCntntAndDelete( (SwSectionFrm*)pParent, sal_False );
391 0 : pParent = this;
392 : }
393 : }
394 : else
395 0 : InsertGroupBefore( pParent, pSibling, NULL );
396 :
397 0 : _InvalidateAll();
398 0 : SwPageFrm *pPage = FindPageFrm();
399 0 : InvalidatePage( pPage );
400 :
401 0 : if ( pSibling )
402 : {
403 0 : pSibling->_InvalidatePos();
404 0 : pSibling->_InvalidatePrt();
405 0 : if ( pSibling->IsCntntFrm() )
406 0 : pSibling->InvalidatePage( pPage );
407 : }
408 :
409 0 : SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
410 0 : if( nFrmHeight )
411 0 : pParent->Grow( nFrmHeight );
412 :
413 0 : if ( GetPrev() )
414 : {
415 0 : if ( !IsFollow() )
416 : {
417 0 : GetPrev()->InvalidateSize();
418 0 : if ( GetPrev()->IsCntntFrm() )
419 0 : GetPrev()->InvalidatePage( pPage );
420 : }
421 : }
422 0 : }
423 :
424 :
425 : /*************************************************************************
426 : |*
427 : |* SwSectionFrm::HasToBreak()
428 : |*
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.
433 : |*
434 : |*************************************************************************/
435 :
436 0 : sal_Bool SwSectionFrm::HasToBreak( const SwFrm* pFrm ) const
437 : {
438 0 : if( !pFrm->IsSctFrm() )
439 0 : return sal_False;
440 :
441 0 : SwSectionFmt *pTmp = (SwSectionFmt*)GetFmt();
442 : // if( !pTmp->GetSect().GetValue() )
443 : // return sal_False;
444 :
445 0 : const SwFrmFmt *pOtherFmt = ((SwSectionFrm*)pFrm)->GetFmt();
446 0 : do
447 : {
448 0 : pTmp = pTmp->GetParent();
449 0 : if( !pTmp )
450 0 : return sal_False;
451 0 : if( pTmp == pOtherFmt )
452 0 : return sal_True;
453 : } while( true ); // ( pTmp->GetSect().GetValue() );
454 : }
455 :
456 : /*************************************************************************
457 : |*
458 : |* SwSectionFrm::MergeNext()
459 : |*
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.
463 : |*
464 : |*************************************************************************/
465 :
466 0 : void SwSectionFrm::MergeNext( SwSectionFrm* pNxt )
467 : {
468 0 : if( !pNxt->IsJoinLocked() && GetSection() == pNxt->GetSection() )
469 : {
470 : PROTOCOL( this, PROT_SECTION, ACT_MERGE, pNxt )
471 :
472 0 : SwFrm* pTmp = ::SaveCntnt( pNxt );
473 0 : if( pTmp )
474 : {
475 0 : SwFrm* pLast = Lower();
476 0 : SwLayoutFrm* pLay = this;
477 0 : if( pLast )
478 : {
479 0 : while( pLast->GetNext() )
480 0 : pLast = pLast->GetNext();
481 0 : if( pLast->IsColumnFrm() )
482 : { // Columns now with BodyFrm
483 0 : pLay = (SwLayoutFrm*)((SwLayoutFrm*)pLast)->Lower();
484 0 : pLast = pLay->Lower();
485 0 : if( pLast )
486 0 : while( pLast->GetNext() )
487 0 : pLast = pLast->GetNext();
488 : }
489 : }
490 0 : ::RestoreCntnt( pTmp, pLay, pLast, true );
491 : }
492 0 : SetFollow( pNxt->GetFollow() );
493 0 : pNxt->SetFollow( NULL );
494 0 : pNxt->Cut();
495 0 : delete pNxt;
496 0 : InvalidateSize();
497 : }
498 0 : }
499 :
500 : /*************************************************************************
501 : |*
502 : |* SwSectionFrm::SplitSect()
503 : |*
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.
508 : |*
509 : |*************************************************************************/
510 :
511 0 : sal_Bool SwSectionFrm::SplitSect( SwFrm* pFrm, sal_Bool bApres )
512 : {
513 : OSL_ENSURE( pFrm, "SplitSect: Why?" );
514 0 : SwFrm* pOther = bApres ? pFrm->FindNext() : pFrm->FindPrev();
515 0 : if( !pOther )
516 0 : return sal_False;
517 0 : SwSectionFrm* pSect = pOther->FindSctFrm();
518 0 : if( pSect != this )
519 0 : return sal_False;
520 : // Put the content aside
521 0 : SwFrm* pSav = ::SaveCntnt( this, bApres ? pOther : pFrm );
522 : OSL_ENSURE( pSav, "SplitSect: What's on?" );
523 0 : if( pSav ) // be robust
524 : { // Create a new SctFrm, not as a Follower/master
525 0 : SwSectionFrm* pNew = new SwSectionFrm( *pSect->GetSection(), pSect );
526 0 : pNew->InsertBehind( pSect->GetUpper(), pSect );
527 0 : pNew->Init();
528 0 : SWRECTFN( this )
529 0 : (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.
534 : {
535 0 : SwLayoutFrm* pLay = pNew;
536 : // Search for last layout frame, e.g. for columned sections.
537 0 : while( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
538 0 : pLay = (SwLayoutFrm*)pLay->Lower();
539 0 : ::RestoreCntnt( pSav, pLay, NULL, true );
540 : }
541 0 : _InvalidateSize();
542 0 : if( HasFollow() )
543 : {
544 0 : pNew->SetFollow( GetFollow() );
545 0 : SetFollow( NULL );
546 : }
547 0 : return sal_True;
548 : }
549 0 : return sal_False;
550 : }
551 :
552 : /*************************************************************************
553 : |*
554 : |* SwSectionFrm::MoveCntntAndDelete()
555 : |*
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.
561 : |*
562 : |*************************************************************************/
563 : // If a multi-column section is cancelled, the ContentFrms have to be
564 : // invalidated
565 :
566 0 : static void lcl_InvalidateInfFlags( SwFrm* pFrm, bool bInva )
567 : {
568 0 : while ( pFrm )
569 : {
570 0 : pFrm->InvalidateInfFlags();
571 0 : if( bInva )
572 : {
573 0 : pFrm->_InvalidatePos();
574 0 : pFrm->_InvalidateSize();
575 0 : pFrm->_InvalidatePrt();
576 : }
577 0 : if( pFrm->IsLayoutFrm() )
578 0 : lcl_InvalidateInfFlags( ((SwLayoutFrm*)pFrm)->GetLower(), sal_False );
579 0 : pFrm = pFrm->GetNext();
580 : }
581 0 : }
582 :
583 :
584 : //
585 : // Works like SwCntntFrm::ImplGetNextCntntFrm, but starts with a LayoutFrm
586 : //
587 0 : static SwCntntFrm* lcl_GetNextCntntFrm( const SwLayoutFrm* pLay, bool bFwd )
588 : {
589 0 : if ( bFwd )
590 : {
591 0 : if ( pLay->GetNext() && pLay->GetNext()->IsCntntFrm() )
592 0 : return (SwCntntFrm*)pLay->GetNext();
593 : }
594 : else
595 : {
596 0 : if ( pLay->GetPrev() && pLay->GetPrev()->IsCntntFrm() )
597 0 : return (SwCntntFrm*)pLay->GetPrev();
598 : }
599 :
600 : // #100926#
601 0 : const SwFrm* pFrm = pLay;
602 0 : SwCntntFrm *pCntntFrm = 0;
603 0 : bool bGoingUp = true;
604 0 : do {
605 0 : const SwFrm *p = 0;
606 0 : bool bGoingFwdOrBwd = false;
607 :
608 0 : bool bGoingDown = !bGoingUp && ( 0 != ( p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0 ) );
609 0 : if ( !bGoingDown )
610 : {
611 0 : bGoingFwdOrBwd = ( 0 != ( p = pFrm->IsFlyFrm() ?
612 : ( bFwd ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink() ) :
613 0 : ( bFwd ? pFrm->GetNext() :pFrm->GetPrev() ) ) );
614 0 : if ( !bGoingFwdOrBwd )
615 : {
616 0 : bGoingUp = (0 != (p = pFrm->GetUpper() ) );
617 0 : if ( !bGoingUp )
618 0 : return 0;
619 : }
620 : }
621 :
622 0 : bGoingUp = !( bGoingFwdOrBwd || bGoingDown );
623 :
624 0 : if( !bFwd && bGoingDown && p )
625 0 : while ( p->GetNext() )
626 0 : p = p->GetNext();
627 :
628 0 : pFrm = p;
629 0 : } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
630 :
631 0 : return pCntntFrm;
632 : }
633 :
634 : #define FIRSTLEAF( pLayFrm ) ( ( pLayFrm->Lower() && pLayFrm->Lower()->IsColumnFrm() )\
635 : ? pLayFrm->GetNextLayoutLeaf() \
636 : : pLayFrm )
637 :
638 0 : void SwSectionFrm::MoveCntntAndDelete( SwSectionFrm* pDel, sal_Bool bSave )
639 : {
640 0 : bool bSize = pDel->Lower() && pDel->Lower()->IsColumnFrm();
641 0 : SwFrm* pPrv = pDel->GetPrev();
642 0 : SwLayoutFrm* pUp = pDel->GetUpper();
643 : // OD 27.03.2003 #i12711# - initialize local pointer variables.
644 0 : SwSectionFrm* pPrvSct = NULL;
645 0 : SwSectionFrm* pNxtSct = NULL;
646 0 : SwSectionFmt* pParent = static_cast<SwSectionFmt*>(pDel->GetFmt())->GetParent();
647 0 : if( pDel->IsInTab() && pParent )
648 : {
649 0 : 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 0 : if( pTab->IsInSct() && pParent == pTab->FindSctFrm()->GetFmt() )
653 0 : pParent = NULL;
654 : }
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 0 : if ( pParent )
662 : {
663 0 : SwFrm* pPrvCntnt = lcl_GetNextCntntFrm( pDel, false );
664 0 : pPrvSct = pPrvCntnt ? pPrvCntnt->FindSctFrm() : NULL;
665 0 : SwFrm* pNxtCntnt = lcl_GetNextCntntFrm( pDel, true );
666 0 : pNxtSct = pNxtCntnt ? pNxtCntnt->FindSctFrm() : NULL;
667 : }
668 : else
669 : {
670 0 : pParent = NULL;
671 0 : pPrvSct = pNxtSct = NULL;
672 : }
673 :
674 : // Now the content is put aside and the frame is destroyed
675 0 : SwFrm *pSave = bSave ? ::SaveCntnt( pDel ) : NULL;
676 0 : sal_Bool bOldFtn = sal_True;
677 0 : if( pSave && pUp->IsFtnFrm() )
678 : {
679 0 : bOldFtn = ((SwFtnFrm*)pUp)->IsColLocked();
680 0 : ((SwFtnFrm*)pUp)->ColLock();
681 : }
682 0 : pDel->DelEmpty( sal_True );
683 0 : delete pDel;
684 0 : if( pParent )
685 : { // Search for the appropriate insert position
686 0 : if( pNxtSct && pNxtSct->GetFmt() == pParent )
687 : { // Here we can insert outselves at the beginning
688 0 : pUp = FIRSTLEAF( pNxtSct );
689 0 : pPrv = NULL;
690 0 : if( pPrvSct && !( pPrvSct->GetFmt() == pParent ) )
691 0 : pPrvSct = NULL; // In order that nothing is merged
692 : }
693 0 : else if( pPrvSct && pPrvSct->GetFmt() == pParent )
694 : { // Wonderful, here we can insert ourselves at the end
695 0 : pUp = pPrvSct;
696 0 : if( pUp->Lower() && pUp->Lower()->IsColumnFrm() )
697 : {
698 0 : pUp = static_cast<SwLayoutFrm*>(pUp->GetLastLower());
699 : // The body of the last column
700 0 : pUp = static_cast<SwLayoutFrm*>(pUp->Lower());
701 : }
702 : // In order to perform the insertion after the last one
703 0 : pPrv = pUp->GetLastLower();
704 0 : pPrvSct = NULL; // Such that nothing is merged
705 : }
706 : else
707 : {
708 0 : 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 0 : pPrvSct = new SwSectionFrm( *pParent->GetSection(), pUp );
716 0 : pPrvSct->InsertBehind( pUp, pPrv );
717 0 : pPrvSct->Init();
718 0 : SWRECTFN( pUp )
719 0 : (pPrvSct->*fnRect->fnMakePos)( pUp, pPrv, sal_True );
720 0 : pUp = FIRSTLEAF( pPrvSct );
721 0 : pPrv = NULL;
722 : }
723 0 : pPrvSct = NULL; // Such that nothing will be merged
724 : }
725 : }
726 : // The content is going to be inserted..
727 0 : if( pSave )
728 : {
729 0 : lcl_InvalidateInfFlags( pSave, bSize );
730 0 : ::RestoreCntnt( pSave, pUp, pPrv, true );
731 0 : pUp->FindPageFrm()->InvalidateCntnt();
732 0 : if( !bOldFtn )
733 0 : ((SwFtnFrm*)pUp)->ColUnlock();
734 : }
735 : // Now two parts of the superior section could possibly be merged
736 0 : if( pPrvSct && !pPrvSct->IsJoinLocked() )
737 : {
738 : OSL_ENSURE( pNxtSct, "MoveCntnt: No Merge" );
739 0 : pPrvSct->MergeNext( pNxtSct );
740 : }
741 0 : }
742 :
743 80 : void SwSectionFrm::MakeAll()
744 : {
745 80 : if ( IsJoinLocked() || IsColLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
746 2 : return;
747 78 : if( !pSection ) // Via DelEmpty
748 : {
749 : #ifdef DBG_UTIL
750 : OSL_ENSURE( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
751 : #endif
752 0 : if( !bValidPos )
753 : {
754 0 : if( GetUpper() )
755 : {
756 0 : SWRECTFN( GetUpper() )
757 0 : (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
758 : }
759 : }
760 0 : bValidSize = bValidPos = bValidPrtArea = sal_True;
761 0 : return;
762 : }
763 78 : LockJoin(); // I don't let myself to be destroyed on the way
764 :
765 78 : while( GetNext() && GetNext() == GetFollow() )
766 : {
767 0 : const SwFrm* pFoll = GetFollow();
768 0 : MergeNext( (SwSectionFrm*)GetNext() );
769 0 : if( pFoll == GetFollow() )
770 0 : break;
771 : }
772 :
773 : // OD 2004-03-15 #116561# - In online layout join the follows, if section
774 : // can grow.
775 78 : const ViewShell *pSh = getRootFrm()->GetCurrShell();
776 78 : if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
777 0 : ( Grow( LONG_MAX, true ) > 0 ) )
778 : {
779 0 : while( GetFollow() )
780 : {
781 0 : const SwFrm* pFoll = GetFollow();
782 0 : MergeNext( GetFollow() );
783 0 : if( pFoll == GetFollow() )
784 0 : break;
785 : }
786 : }
787 :
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 78 : if( !bValidPos && ToMaximize( sal_False ) )
791 0 : bValidSize = sal_False;
792 :
793 : #if OSL_DEBUG_LEVEL > 1
794 : const SwFmtCol &rCol = GetFmt()->GetCol();
795 : (void)rCol;
796 : #endif
797 78 : SwLayoutFrm::MakeAll();
798 78 : UnlockJoin();
799 78 : if( pSection && IsSuperfluous() )
800 0 : DelEmpty( sal_False );
801 : }
802 :
803 0 : sal_Bool SwSectionFrm::ShouldBwdMoved( SwLayoutFrm *, sal_Bool , sal_Bool & )
804 : {
805 : OSL_FAIL( "Hups, wo ist meine Tarnkappe?" );
806 0 : return sal_False;
807 : }
808 :
809 0 : const SwSectionFmt* SwSectionFrm::_GetEndSectFmt() const
810 : {
811 0 : const SwSectionFmt *pFmt = pSection->GetFmt();
812 0 : while( !pFmt->GetEndAtTxtEnd().IsAtEnd() )
813 : {
814 0 : if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
815 0 : pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
816 : else
817 0 : return NULL;
818 : }
819 0 : return pFmt;
820 : }
821 :
822 88 : static void lcl_FindCntntFrm( SwCntntFrm* &rpCntntFrm, SwFtnFrm* &rpFtnFrm,
823 : SwFrm* pFrm, sal_Bool &rbChkFtn )
824 : {
825 88 : if( pFrm )
826 : {
827 240 : while( pFrm->GetNext() )
828 64 : pFrm = pFrm->GetNext();
829 264 : while( !rpCntntFrm && pFrm )
830 : {
831 88 : if( pFrm->IsCntntFrm() )
832 88 : rpCntntFrm = (SwCntntFrm*)pFrm;
833 0 : else if( pFrm->IsLayoutFrm() )
834 : {
835 0 : if( pFrm->IsFtnFrm() )
836 : {
837 0 : if( rbChkFtn )
838 : {
839 0 : rpFtnFrm = (SwFtnFrm*)pFrm;
840 0 : rbChkFtn = rpFtnFrm->GetAttr()->GetFtn().IsEndNote();
841 : }
842 : }
843 : else
844 : lcl_FindCntntFrm( rpCntntFrm, rpFtnFrm,
845 0 : ((SwLayoutFrm*)pFrm)->Lower(), rbChkFtn );
846 : }
847 88 : pFrm = pFrm->GetPrev();
848 : }
849 : }
850 88 : }
851 :
852 88 : SwCntntFrm *SwSectionFrm::FindLastCntnt( sal_uInt8 nMode )
853 : {
854 88 : SwCntntFrm *pRet = NULL;
855 88 : SwFtnFrm *pFtnFrm = NULL;
856 88 : SwSectionFrm *pSect = this;
857 88 : if( nMode )
858 : {
859 0 : const SwSectionFmt *pFmt = IsEndnAtEnd() ? GetEndSectFmt() :
860 0 : pSection->GetFmt();
861 0 : do {
862 0 : while( pSect->HasFollow() )
863 0 : pSect = pSect->GetFollow();
864 0 : SwFrm* pTmp = pSect->FindNext();
865 0 : while( pTmp && pTmp->IsSctFrm() &&
866 0 : !((SwSectionFrm*)pTmp)->GetSection() )
867 0 : pTmp = pTmp->FindNext();
868 0 : if( pTmp && pTmp->IsSctFrm() &&
869 0 : ((SwSectionFrm*)pTmp)->IsDescendantFrom( pFmt ) )
870 0 : pSect = (SwSectionFrm*)pTmp;
871 : else
872 0 : break;
873 : } while( true );
874 : }
875 88 : sal_Bool bFtnFound = nMode == FINDMODE_ENDNOTE;
876 0 : do
877 : {
878 88 : lcl_FindCntntFrm( pRet, pFtnFrm, pSect->Lower(), bFtnFound );
879 88 : if( pRet || !pSect->IsFollow() || !nMode ||
880 : ( FINDMODE_MYLAST == nMode && this == pSect ) )
881 88 : break;
882 0 : pSect = pSect->FindMaster();
883 : } while( pSect );
884 88 : if( ( nMode == FINDMODE_ENDNOTE ) && pFtnFrm )
885 0 : pRet = pFtnFrm->ContainsCntnt();
886 88 : return pRet;
887 : }
888 :
889 0 : sal_Bool SwSectionFrm::CalcMinDiff( SwTwips& rMinDiff ) const
890 : {
891 0 : if( ToMaximize( sal_True ) )
892 : {
893 0 : SWRECTFN( this )
894 0 : rMinDiff = (GetUpper()->*fnRect->fnGetPrtBottom)();
895 0 : rMinDiff = (Frm().*fnRect->fnBottomDist)( rMinDiff );
896 0 : return sal_True;
897 : }
898 0 : return sal_False;
899 : }
900 :
901 : /*************************************************************************
902 : *
903 : * SwSectionFrm::CollectEndnotes( )
904 : *
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.
909 : *
910 : *************************************************************************/
911 :
912 0 : static SwFtnFrm* lcl_FindEndnote( SwSectionFrm* &rpSect, bool &rbEmpty,
913 : SwLayouter *pLayouter )
914 : {
915 : // if rEmpty is set, the rpSect is already searched
916 0 : SwSectionFrm* pSect = rbEmpty ? rpSect->GetFollow() : rpSect;
917 0 : while( pSect )
918 : {
919 : OSL_ENSURE( (pSect->Lower() && pSect->Lower()->IsColumnFrm()) || pSect->GetUpper()->IsFtnFrm(),
920 : "InsertEndnotes: Where's my column?" );
921 :
922 : // i73332: Columned section in endnote
923 0 : SwColumnFrm* pCol = 0;
924 0 : if(pSect->Lower() && pSect->Lower()->IsColumnFrm())
925 0 : pCol = (SwColumnFrm*)pSect->Lower();
926 :
927 0 : while( pCol ) // check all columns
928 : {
929 0 : SwFtnContFrm* pFtnCont = pCol->FindFtnCont();
930 0 : if( pFtnCont )
931 : {
932 0 : SwFtnFrm* pRet = (SwFtnFrm*)pFtnCont->Lower();
933 0 : while( pRet ) // look for endnotes
934 : {
935 0 : if( pRet->GetAttr()->GetFtn().IsEndNote() )
936 : {
937 0 : if( pRet->GetMaster() )
938 : {
939 0 : if( pLayouter )
940 0 : pLayouter->CollectEndnote( pRet );
941 : else
942 0 : return 0;
943 : }
944 : else
945 0 : return pRet; // Found
946 : }
947 0 : pRet = (SwFtnFrm*)pRet->GetNext();
948 : }
949 : }
950 0 : pCol = (SwColumnFrm*)pCol->GetNext();
951 : }
952 0 : rpSect = pSect;
953 0 : pSect = pLayouter ? pSect->GetFollow() : NULL;
954 0 : rbEmpty = true;
955 : }
956 0 : return NULL;
957 : }
958 :
959 8 : static void lcl_ColumnRefresh( SwSectionFrm* pSect, bool bFollow )
960 : {
961 24 : while( pSect )
962 : {
963 8 : sal_Bool bOldLock = pSect->IsColLocked();
964 8 : pSect->ColLock();
965 8 : if( pSect->Lower() && pSect->Lower()->IsColumnFrm() )
966 : {
967 0 : SwColumnFrm *pCol = (SwColumnFrm*)pSect->Lower();
968 0 : do
969 0 : { pCol->_InvalidateSize();
970 0 : pCol->_InvalidatePos();
971 0 : ((SwLayoutFrm*)pCol)->Lower()->_InvalidateSize();
972 0 : pCol->Calc(); // calculation of column and
973 0 : ((SwLayoutFrm*)pCol)->Lower()->Calc(); // body
974 0 : pCol = (SwColumnFrm*)pCol->GetNext();
975 : } while ( pCol );
976 : }
977 8 : if( !bOldLock )
978 8 : pSect->ColUnlock();
979 8 : if( bFollow )
980 0 : pSect = pSect->GetFollow();
981 : else
982 8 : pSect = NULL;
983 : }
984 8 : }
985 :
986 0 : void SwSectionFrm::CollectEndnotes( SwLayouter* pLayouter )
987 : {
988 : OSL_ENSURE( IsColLocked(), "CollectEndnotes: You love the risk?" );
989 : // i73332: Section in footnode does not have columns!
990 : OSL_ENSURE( (Lower() && Lower()->IsColumnFrm()) || GetUpper()->IsFtnFrm(), "Where's my column?" );
991 :
992 0 : SwSectionFrm* pSect = this;
993 : SwFtnFrm* pFtn;
994 0 : bool bEmpty = false;
995 : // pSect is the last sectionfrm without endnotes or the this-pointer
996 : // the first sectionfrm with endnotes may be destroyed, when the endnotes
997 : // is cutted
998 0 : while( 0 != (pFtn = lcl_FindEndnote( pSect, bEmpty, pLayouter )) )
999 0 : pLayouter->CollectEndnote( pFtn );
1000 0 : if( pLayouter->HasEndnotes() )
1001 0 : lcl_ColumnRefresh( this, true );
1002 0 : }
1003 :
1004 : /*************************************************************************
1005 : |*
1006 : |* SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
1007 : |*
1008 : |* Description: Fits the size to the surroundings.
1009 : |* Those that have a Follow or foot notes, have to extend until
1010 : |* the lower edge of a upper (bMaximize)
1011 : |* They must not extend above the Upper, as the case may be one can
1012 : |* try to grow its upper (bGrow)
1013 : |* If the size had to be changed, the content is calculated.
1014 : |*
1015 : |*************************************************************************/
1016 :
1017 : /// OD 18.09.2002 #100522#
1018 : /// perform calculation of content, only if height has changed.
1019 156 : void SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
1020 : {
1021 156 : SWRECTFN( this )
1022 : long nDiff;
1023 156 : SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1024 156 : if( bGrow && ( !IsInFly() || !GetUpper()->IsColBodyFrm() ||
1025 0 : !FindFlyFrm()->IsLocked() ) )
1026 : {
1027 78 : nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
1028 78 : if( !bMaximize )
1029 76 : nDiff += Undersize();
1030 78 : if( nDiff > 0 )
1031 : {
1032 2 : long nAdd = GetUpper()->Grow( nDiff );
1033 2 : if( bVert && !bRev )
1034 0 : nDeadLine -= nAdd;
1035 : else
1036 2 : nDeadLine += nAdd;
1037 : }
1038 : }
1039 156 : nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
1040 156 : SetUndersized( !bMaximize && nDiff >= 0 );
1041 156 : const bool bCalc = ( IsUndersized() || bMaximize ) &&
1042 : ( nDiff ||
1043 156 : (Prt().*fnRect->fnGetTop)() > (Frm().*fnRect->fnGetHeight)() );
1044 : // OD 03.11.2003 #i19737# - introduce local variable <bExtraCalc> to indicate
1045 : // that a calculation has to be done beside the value of <bCalc>.
1046 156 : bool bExtraCalc = false;
1047 156 : if( !bCalc && !bGrow && IsAnyNoteAtEnd() && !IsInFtn() )
1048 : {
1049 0 : SwSectionFrm *pSect = this;
1050 0 : bool bEmpty = false;
1051 0 : SwLayoutFrm* pFtn = IsEndnAtEnd() ?
1052 0 : lcl_FindEndnote( pSect, bEmpty, NULL ) : NULL;
1053 0 : if( pFtn )
1054 : {
1055 0 : pFtn = pFtn->FindFtnBossFrm();
1056 0 : SwFrm* pTmp = FindLastCntnt( FINDMODE_LASTCNT );
1057 : // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
1058 0 : if ( pTmp && pFtn->IsBefore( pTmp->FindFtnBossFrm() ) )
1059 0 : bExtraCalc = true;
1060 : }
1061 0 : else if( GetFollow() && !GetFollow()->ContainsAny() )
1062 0 : bExtraCalc = true;
1063 : }
1064 156 : if ( bCalc || bExtraCalc )
1065 : {
1066 2 : nDiff = (*fnRect->fnYDiff)( nDeadLine, (Frm().*fnRect->fnGetTop)() );
1067 2 : if( nDiff < 0 )
1068 : {
1069 0 : nDiff = 0;
1070 0 : nDeadLine = (Frm().*fnRect->fnGetTop)();
1071 : }
1072 2 : const Size aOldSz( Prt().SSize() );
1073 2 : long nTop = (this->*fnRect->fnGetTopMargin)();
1074 2 : (Frm().*fnRect->fnSetBottom)( nDeadLine );
1075 2 : nDiff = (Frm().*fnRect->fnGetHeight)();
1076 2 : if( nTop > nDiff )
1077 0 : nTop = nDiff;
1078 2 : (this->*fnRect->fnSetYMargins)( nTop, 0 );
1079 :
1080 : // OD 18.09.2002 #100522#
1081 : // Determine, if height has changed.
1082 : // Note: In vertical layout the height equals the width value.
1083 : bool bHeightChanged = bVert ?
1084 0 : (aOldSz.Width() != Prt().Width()) :
1085 2 : (aOldSz.Height() != Prt().Height());
1086 : // Last but not least we have changed the height again, thus the inner
1087 : // layout (columns) is calculated and the content as well.
1088 : // OD 18.09.2002 #100522#
1089 : // calculate content, only if height has changed.
1090 : // OD 03.11.2003 #i19737# - restriction of content calculation too strong.
1091 : // If an endnote has an incorrect position or a follow section contains
1092 : // no content except footnotes/endnotes, the content has also been calculated.
1093 2 : if ( ( bHeightChanged || bExtraCalc ) && Lower() )
1094 : {
1095 2 : if( Lower()->IsColumnFrm() )
1096 : {
1097 0 : lcl_ColumnRefresh( this, false );
1098 0 : ::CalcCntnt( this );
1099 : }
1100 : else
1101 : {
1102 2 : ChgLowersProp( aOldSz );
1103 2 : if( !bMaximize && !IsCntntLocked() )
1104 0 : ::CalcCntnt( this );
1105 : }
1106 : }
1107 : }
1108 156 : }
1109 :
1110 8 : void SwSectionFrm::SimpleFormat()
1111 : {
1112 8 : if ( IsJoinLocked() || IsColLocked() )
1113 8 : return;
1114 : // OSL_ENSURE( pFollow, "SimpleFormat: Follow required" );
1115 8 : LockJoin();
1116 8 : SWRECTFN( this )
1117 8 : if( GetPrev() || GetUpper() )
1118 : {
1119 : //
1120 : // assure notifications on position changes.
1121 8 : const SwLayNotify aNotify( this );
1122 8 : (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
1123 8 : bValidPos = sal_True;
1124 : }
1125 8 : SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1126 : // OD 22.10.2002 #97265# - call always method <lcl_ColumnRefresh(..)>, in
1127 : // order to get calculated lowers, not only if there space left in its upper.
1128 8 : if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) >= 0 )
1129 : {
1130 8 : (Frm().*fnRect->fnSetBottom)( nDeadLine );
1131 8 : long nHeight = (Frm().*fnRect->fnGetHeight)();
1132 8 : long nTop = CalcUpperSpace();
1133 8 : if( nTop > nHeight )
1134 0 : nTop = nHeight;
1135 8 : (this->*fnRect->fnSetYMargins)( nTop, 0 );
1136 : }
1137 8 : lcl_ColumnRefresh( this, false );
1138 8 : UnlockJoin();
1139 : }
1140 :
1141 : // #i40147# - helper class to perform extra section format
1142 : // to position anchored objects and to keep the position of whose objects locked.
1143 : class ExtraFormatToPositionObjs
1144 : {
1145 : private:
1146 : SwSectionFrm* mpSectFrm;
1147 : bool mbExtraFormatPerformed;
1148 :
1149 : public:
1150 78 : ExtraFormatToPositionObjs( SwSectionFrm& _rSectFrm)
1151 : : mpSectFrm( &_rSectFrm ),
1152 78 : mbExtraFormatPerformed( false )
1153 78 : {}
1154 :
1155 78 : ~ExtraFormatToPositionObjs()
1156 : {
1157 78 : if ( mbExtraFormatPerformed )
1158 : {
1159 : // release keep locked position of lower floating screen objects
1160 0 : SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
1161 0 : SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
1162 0 : if ( pObjs )
1163 : {
1164 0 : sal_uInt32 i = 0;
1165 0 : for ( i = 0; i < pObjs->Count(); ++i )
1166 : {
1167 0 : SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1168 :
1169 0 : if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
1170 : {
1171 0 : pAnchoredObj->SetKeepPosLocked( false );
1172 : }
1173 : }
1174 : }
1175 : }
1176 78 : }
1177 :
1178 : // #i81555#
1179 0 : void InitObjs( SwFrm& rFrm )
1180 : {
1181 0 : SwSortedObjs* pObjs = rFrm.GetDrawObjs();
1182 0 : if ( pObjs )
1183 : {
1184 0 : sal_uInt32 i = 0;
1185 0 : for ( i = 0; i < pObjs->Count(); ++i )
1186 : {
1187 0 : SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1188 :
1189 0 : pAnchoredObj->UnlockPosition();
1190 0 : pAnchoredObj->SetClearedEnvironment( false );
1191 : }
1192 : }
1193 0 : SwLayoutFrm* pLayoutFrm = dynamic_cast<SwLayoutFrm*>(&rFrm);
1194 0 : if ( pLayoutFrm != 0 )
1195 : {
1196 0 : SwFrm* pLowerFrm = pLayoutFrm->GetLower();
1197 0 : while ( pLowerFrm != 0 )
1198 : {
1199 0 : InitObjs( *pLowerFrm );
1200 :
1201 0 : pLowerFrm = pLowerFrm->GetNext();
1202 : }
1203 : }
1204 0 : }
1205 :
1206 2 : void FormatSectionToPositionObjs()
1207 : {
1208 : // perform extra format for multi-columned section.
1209 2 : if ( mpSectFrm->Lower() && mpSectFrm->Lower()->IsColumnFrm() &&
1210 0 : mpSectFrm->Lower()->GetNext() )
1211 : {
1212 : // grow section till bottom of printing area of upper frame
1213 0 : SWRECTFN( mpSectFrm );
1214 0 : SwTwips nTopMargin = (mpSectFrm->*fnRect->fnGetTopMargin)();
1215 0 : Size aOldSectPrtSize( mpSectFrm->Prt().SSize() );
1216 0 : SwTwips nDiff = (mpSectFrm->Frm().*fnRect->fnBottomDist)(
1217 0 : (mpSectFrm->GetUpper()->*fnRect->fnGetPrtBottom)() );
1218 0 : (mpSectFrm->Frm().*fnRect->fnAddBottom)( nDiff );
1219 0 : (mpSectFrm->*fnRect->fnSetYMargins)( nTopMargin, 0 );
1220 : // #i59789#
1221 : // suppress formatting, if printing area of section is too narrow
1222 0 : if ( (mpSectFrm->Prt().*fnRect->fnGetHeight)() <= 0 )
1223 : {
1224 2 : return;
1225 : }
1226 0 : mpSectFrm->ChgLowersProp( aOldSectPrtSize );
1227 :
1228 : // format column frames and its body and footnote container
1229 0 : SwColumnFrm* pColFrm = static_cast<SwColumnFrm*>(mpSectFrm->Lower());
1230 0 : while ( pColFrm )
1231 : {
1232 0 : pColFrm->Calc();
1233 0 : pColFrm->Lower()->Calc();
1234 0 : if ( pColFrm->Lower()->GetNext() )
1235 : {
1236 0 : pColFrm->Lower()->GetNext()->Calc();
1237 : }
1238 :
1239 0 : pColFrm = static_cast<SwColumnFrm*>(pColFrm->GetNext());
1240 : }
1241 :
1242 : // unlock position of lower floating screen objects for the extra format
1243 : // #i81555#
1244 : // Section frame can already have changed the page and its content
1245 : // can still be on the former page.
1246 : // Thus, initialize objects via lower-relationship
1247 0 : InitObjs( *mpSectFrm );
1248 :
1249 : // format content - first with collecting its foot-/endnotes before content
1250 : // format, second without collecting its foot-/endnotes.
1251 0 : ::CalcCntnt( mpSectFrm );
1252 0 : ::CalcCntnt( mpSectFrm, true );
1253 :
1254 : // keep locked position of lower floating screen objects
1255 0 : SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
1256 0 : SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
1257 0 : if ( pObjs )
1258 : {
1259 0 : sal_uInt32 i = 0;
1260 0 : for ( i = 0; i < pObjs->Count(); ++i )
1261 : {
1262 0 : SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1263 :
1264 0 : if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
1265 : {
1266 0 : pAnchoredObj->SetKeepPosLocked( true );
1267 : }
1268 : }
1269 : }
1270 :
1271 0 : mbExtraFormatPerformed = true;
1272 : }
1273 : }
1274 : };
1275 :
1276 : /*************************************************************************
1277 : |*
1278 : |* SwSectionFrm::Format()
1279 : |*
1280 : |* Description: "formats" the frame; Frm and PrtArea
1281 : |*
1282 : |*************************************************************************/
1283 :
1284 78 : void SwSectionFrm::Format( const SwBorderAttrs *pAttr )
1285 : {
1286 78 : if( !pSection ) // via DelEmpty
1287 : {
1288 : #ifdef DBG_UTIL
1289 : OSL_ENSURE( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
1290 : #endif
1291 0 : bValidSize = bValidPos = bValidPrtArea = sal_True;
1292 78 : return;
1293 : }
1294 78 : SWRECTFN( this )
1295 78 : if ( !bValidPrtArea )
1296 : {
1297 : PROTOCOL( this, PROT_PRTAREA, 0, 0 )
1298 78 : bValidPrtArea = sal_True;
1299 78 : SwTwips nUpper = CalcUpperSpace();
1300 :
1301 : // #109700# LRSpace for sections
1302 78 : const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
1303 78 : (this->*fnRect->fnSetXMargins)( rLRSpace.GetLeft(), rLRSpace.GetRight() );
1304 :
1305 78 : if( nUpper != (this->*fnRect->fnGetTopMargin)() )
1306 : {
1307 0 : bValidSize = sal_False;
1308 0 : SwFrm* pOwn = ContainsAny();
1309 0 : if( pOwn )
1310 0 : pOwn->_InvalidatePos();
1311 : }
1312 78 : (this->*fnRect->fnSetYMargins)( nUpper, 0 );
1313 : }
1314 :
1315 78 : if ( !bValidSize )
1316 : {
1317 : PROTOCOL_ENTER( this, PROT_SIZE, 0, 0 )
1318 78 : const long nOldHeight = (Frm().*fnRect->fnGetHeight)();
1319 78 : sal_Bool bOldLock = IsColLocked();
1320 78 : ColLock();
1321 :
1322 78 : bValidSize = sal_True;
1323 :
1324 : // The size is only determined by the content, if the SectFrm does not have a
1325 : // Follow. Otherwise it fills (occupies) the Upper down to the lower edge.
1326 : // It is not responsible for the text flow, but the content is.
1327 78 : sal_Bool bMaximize = ToMaximize( sal_False );
1328 :
1329 : // OD 2004-05-17 #i28701# - If the wrapping style has to be considered
1330 : // on object positioning, an extra formatting has to be performed
1331 : // to determine the correct positions the floating screen objects.
1332 : // #i40147#
1333 : // use new helper class <ExtraFormatToPositionObjs>.
1334 : // This class additionally keep the locked position of the objects
1335 : // and releases this position lock keeping on destruction.
1336 78 : ExtraFormatToPositionObjs aExtraFormatToPosObjs( *this );
1337 156 : if ( !bMaximize &&
1338 76 : GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
1339 2 : !GetFmt()->GetBalancedColumns().GetValue() )
1340 : {
1341 2 : aExtraFormatToPosObjs.FormatSectionToPositionObjs();
1342 : }
1343 :
1344 : // Column widths have to be adjusted before calling _CheckClipping.
1345 : // _CheckClipping can cause the formatting of the lower frames
1346 : // which still have a width of 0.
1347 78 : const bool bHasColumns = Lower() && Lower()->IsColumnFrm();
1348 78 : if ( bHasColumns && Lower()->GetNext() )
1349 0 : AdjustColumns( 0, sal_False );
1350 :
1351 78 : if( GetUpper() )
1352 : {
1353 78 : long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
1354 78 : (aFrm.*fnRect->fnSetWidth)( nWidth );
1355 :
1356 : // #109700# LRSpace for sections
1357 78 : const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
1358 78 : (aPrt.*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
1359 156 : rLRSpace.GetRight() );
1360 :
1361 : // OD 15.10.2002 #103517# - allow grow in online layout
1362 : // Thus, set <..IsBrowseMode()> as parameter <bGrow> on calling
1363 : // method <_CheckClipping(..)>.
1364 78 : const ViewShell *pSh = getRootFrm()->GetCurrShell();
1365 78 : _CheckClipping( pSh && pSh->GetViewOptions()->getBrowseMode(), bMaximize );
1366 78 : bMaximize = ToMaximize( sal_False );
1367 78 : bValidSize = sal_True;
1368 : }
1369 :
1370 : // Check the width of the columns and adjust if necessary
1371 78 : if ( bHasColumns && ! Lower()->GetNext() && bMaximize )
1372 0 : ((SwColumnFrm*)Lower())->Lower()->Calc();
1373 :
1374 78 : if ( !bMaximize )
1375 : {
1376 76 : SwTwips nRemaining = (this->*fnRect->fnGetTopMargin)();
1377 76 : SwFrm *pFrm = pLower;
1378 76 : if( pFrm )
1379 : {
1380 76 : if( pFrm->IsColumnFrm() && pFrm->GetNext() )
1381 : {
1382 : // #i61435#
1383 : // suppress formatting, if upper frame has height <= 0
1384 0 : if ( (GetUpper()->Frm().*fnRect->fnGetHeight)() > 0 )
1385 : {
1386 0 : FormatWidthCols( *pAttr, nRemaining, MINLAY );
1387 : }
1388 : // #126020# - adjust check for empty section
1389 : // #130797# - correct fix #126020#
1390 0 : while( HasFollow() && !GetFollow()->ContainsCntnt() &&
1391 0 : !GetFollow()->ContainsAny( true ) )
1392 : {
1393 0 : SwFrm* pOld = GetFollow();
1394 0 : GetFollow()->DelEmpty( sal_False );
1395 0 : if( pOld == GetFollow() )
1396 0 : break;
1397 : }
1398 0 : bMaximize = ToMaximize( sal_False );
1399 0 : nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
1400 : }
1401 : else
1402 : {
1403 76 : if( pFrm->IsColumnFrm() )
1404 : {
1405 0 : pFrm->Calc();
1406 0 : pFrm = ((SwColumnFrm*)pFrm)->Lower();
1407 0 : pFrm->Calc();
1408 0 : pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1409 0 : CalcFtnCntnt();
1410 : }
1411 : // If we are in a columned frame which calls a CalcCntnt
1412 : // in the FormatWidthCols, the content might need calculating
1413 76 : if( pFrm && !pFrm->IsValid() && IsInFly() &&
1414 0 : FindFlyFrm()->IsColLocked() )
1415 0 : ::CalcCntnt( this );
1416 76 : nRemaining += InnerHeight();
1417 76 : bMaximize = HasFollow();
1418 : }
1419 : }
1420 :
1421 76 : SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
1422 76 : if( nDiff < 0)
1423 : {
1424 2 : SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1425 : {
1426 2 : long nBottom = (Frm().*fnRect->fnGetBottom)();
1427 2 : nBottom = (*fnRect->fnYInc)( nBottom, -nDiff );
1428 2 : long nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
1429 2 : if( nTmpDiff > 0 )
1430 : {
1431 2 : nTmpDiff = GetUpper()->Grow( nTmpDiff, sal_True );
1432 2 : nDeadLine = (*fnRect->fnYInc)( nDeadLine, nTmpDiff );
1433 2 : nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
1434 2 : if( nTmpDiff > 0 )
1435 2 : nDiff += nTmpDiff;
1436 2 : if( nDiff > 0 )
1437 0 : nDiff = 0;
1438 : }
1439 : }
1440 : }
1441 76 : if( nDiff )
1442 : {
1443 2 : long nTmp = nRemaining - (Frm().*fnRect->fnGetHeight)();
1444 2 : long nTop = (this->*fnRect->fnGetTopMargin)();
1445 2 : (Frm().*fnRect->fnAddBottom)( nTmp );
1446 2 : (this->*fnRect->fnSetYMargins)( nTop, 0 );
1447 2 : InvalidateNextPos();
1448 2 : if( pLower && ( !pLower->IsColumnFrm() || !pLower->GetNext() ) )
1449 : {
1450 : // If a single-column section just created the space that
1451 : // was requested by the "undersized" paragraphs, then they
1452 : // have to be invalidated and calculated, so they fully cover it
1453 2 : pFrm = pLower;
1454 2 : if( pFrm->IsColumnFrm() )
1455 : {
1456 0 : pFrm->_InvalidateSize();
1457 0 : pFrm->_InvalidatePos();
1458 0 : pFrm->Calc();
1459 0 : pFrm = ((SwColumnFrm*)pFrm)->Lower();
1460 0 : pFrm->Calc();
1461 0 : pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1462 0 : CalcFtnCntnt();
1463 : }
1464 2 : bool bUnderSz = false;
1465 6 : while( pFrm )
1466 : {
1467 2 : if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
1468 : {
1469 0 : pFrm->Prepare( PREP_ADJUST_FRM );
1470 0 : bUnderSz = true;
1471 : }
1472 2 : pFrm = pFrm->GetNext();
1473 : }
1474 2 : if( bUnderSz && !IsCntntLocked() )
1475 0 : ::CalcCntnt( this );
1476 : }
1477 : }
1478 : }
1479 :
1480 : // Do not exceed the lower edge of the Upper.
1481 : // Do not extend below the lower edge with Sections with Follows
1482 78 : if ( GetUpper() )
1483 78 : _CheckClipping( sal_True, bMaximize );
1484 78 : if( !bOldLock )
1485 78 : ColUnlock();
1486 78 : long nDiff = nOldHeight - (Frm().*fnRect->fnGetHeight)();
1487 78 : if( nDiff > 0 )
1488 : {
1489 0 : if( !GetNext() )
1490 0 : SetRetouche(); // Take over the retouching ourselves
1491 0 : if( GetUpper() && !GetUpper()->IsFooterFrm() )
1492 0 : GetUpper()->Shrink( nDiff );
1493 : }
1494 78 : if( IsUndersized() )
1495 2 : bValidPrtArea = sal_True;
1496 : }
1497 : }
1498 :
1499 : /*************************************************************************
1500 : |*
1501 : |* SwFrm::GetNextSctLeaf()
1502 : |*
1503 : |* Description: Returns the next layout sheet where the frame
1504 : |* can be moved in.
1505 : |* New pages are created only if the parameter sal_True is set
1506 : |*
1507 : |*************************************************************************/
1508 :
1509 :
1510 2 : SwLayoutFrm *SwFrm::GetNextSctLeaf( MakePageType eMakePage )
1511 : {
1512 : // Attention: Nested sections are currently not supported
1513 :
1514 : PROTOCOL_ENTER( this, PROT_LEAF, ACT_NEXT_SECT, GetUpper()->FindSctFrm() )
1515 :
1516 : // Shortcuts for "columned" sections, if we're not in the last column
1517 : // Can we slide to the next column of the section?
1518 2 : if( IsColBodyFrm() && GetUpper()->GetNext() )
1519 0 : return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetNext())->Lower();
1520 2 : if( GetUpper()->IsColBodyFrm() && GetUpper()->GetUpper()->GetNext() )
1521 0 : return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetUpper()->GetNext())->Lower();
1522 : // Inside a section, in tables, or sections of headers/footers, there can be only
1523 : // one column shift be made, one of the above shortcuts should have applied!
1524 2 : if( GetUpper()->IsInTab() || FindFooterOrHeader() )
1525 0 : return 0;
1526 :
1527 : // Why GetUpper()? This crashes sometimes, because in
1528 : // FlyAtCnt::MakeFlyPos there is an Orient of the SectionFrm and on this a
1529 : // GetLeaf is called
1530 : // SwSectionFrm *pSect = GetUpper()->FindSctFrm();
1531 2 : SwSectionFrm *pSect = FindSctFrm();
1532 2 : bool bWrongPage = false;
1533 : OSL_ENSURE( pSect, "GetNextSctLeaf: Missing SectionFrm" );
1534 :
1535 : // Shortcut for sections with Follows. That's ok,
1536 : // if no columns or pages (except dummy pages) lie in between.
1537 : // In case of linked frames and in footnotes the shortcut would get
1538 : // even more costly
1539 2 : if( pSect->HasFollow() && pSect->IsInDocBody() )
1540 : {
1541 0 : if( pSect->GetFollow() == pSect->GetNext() )
1542 : {
1543 0 : SwPageFrm *pPg = pSect->GetFollow()->FindPageFrm();
1544 0 : if( WrongPageDesc( pPg ) )
1545 0 : bWrongPage = true;
1546 : else
1547 0 : return FIRSTLEAF( pSect->GetFollow() );
1548 : }
1549 : else
1550 : {
1551 : SwFrm* pTmp;
1552 0 : if( !pSect->GetUpper()->IsColBodyFrm() ||
1553 0 : 0 == ( pTmp = pSect->GetUpper()->GetUpper()->GetNext() ) )
1554 0 : pTmp = pSect->FindPageFrm()->GetNext();
1555 0 : if( pTmp ) // is now the next column or page
1556 : {
1557 0 : SwFrm* pTmpX = pTmp;
1558 0 : if( pTmp->IsPageFrm() && ((SwPageFrm*)pTmp)->IsEmptyPage() )
1559 0 : pTmp = pTmp->GetNext(); // skip dummy pages
1560 0 : SwFrm *pUp = pSect->GetFollow()->GetUpper();
1561 : // pUp becomes the next column if the Follow lies in a column
1562 : // that is not a "not first" one, otherwise the page
1563 0 : if( !pUp->IsColBodyFrm() ||
1564 0 : !( pUp = pUp->GetUpper() )->GetPrev() )
1565 0 : pUp = pUp->FindPageFrm();
1566 : // Now pUp and pTmp have to be the same page/column, otherwise
1567 : // pages or columns lie between Master and Follow
1568 0 : if( pUp == pTmp || pUp->GetNext() == pTmpX )
1569 : {
1570 0 : SwPageFrm* pNxtPg = pUp->IsPageFrm() ?
1571 0 : (SwPageFrm*)pUp : pUp->FindPageFrm();
1572 0 : if( WrongPageDesc( pNxtPg ) )
1573 0 : bWrongPage = true;
1574 : else
1575 0 : return FIRSTLEAF( pSect->GetFollow() );
1576 : }
1577 : }
1578 : }
1579 : }
1580 :
1581 : // Always end up in the same section: Body again inside Body etc.
1582 2 : const sal_Bool bBody = IsInDocBody();
1583 2 : const sal_Bool bFtnPage = FindPageFrm()->IsFtnPage();
1584 :
1585 : SwLayoutFrm *pLayLeaf;
1586 : // A shortcut for TabFrms such that not all cells need to be visited
1587 2 : if( bWrongPage )
1588 0 : pLayLeaf = 0;
1589 2 : else if( IsTabFrm() )
1590 : {
1591 0 : SwCntntFrm* pTmpCnt = ((SwTabFrm*)this)->FindLastCntnt();
1592 0 : pLayLeaf = pTmpCnt ? pTmpCnt->GetUpper() : 0;
1593 : }
1594 : else
1595 : {
1596 2 : pLayLeaf = GetNextLayoutLeaf();
1597 2 : if( IsColumnFrm() )
1598 : {
1599 0 : while( pLayLeaf && ((SwColumnFrm*)this)->IsAnLower( pLayLeaf ) )
1600 0 : pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1601 : }
1602 : }
1603 :
1604 2 : SwLayoutFrm *pOldLayLeaf = 0; // Such that in case of newly
1605 : // created pages, the search is
1606 : // not started over at the beginning
1607 :
1608 4 : while( true )
1609 : {
1610 6 : if( pLayLeaf )
1611 : {
1612 : // A layout leaf was found, let's see whether it can store me or
1613 : // another SectionFrm can be inserted here, or we have to continue
1614 : // searching
1615 4 : SwPageFrm* pNxtPg = pLayLeaf->FindPageFrm();
1616 4 : if ( !bFtnPage && pNxtPg->IsFtnPage() )
1617 : { // If I reached the end note pages it's over
1618 0 : pLayLeaf = 0;
1619 0 : continue;
1620 : }
1621 : // Once inBody always inBody, don't step into tables and not into other sections
1622 16 : if ( (bBody && !pLayLeaf->IsInDocBody()) ||
1623 4 : (IsInFtn() != pLayLeaf->IsInFtn() ) ||
1624 4 : pLayLeaf->IsInTab() ||
1625 4 : ( pLayLeaf->IsInSct() && ( !pSect->HasFollow()
1626 0 : || pSect->GetFollow() != pLayLeaf->FindSctFrm() ) ) )
1627 : {
1628 : // Rejected - try again.
1629 0 : pOldLayLeaf = pLayLeaf;
1630 0 : pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1631 0 : continue;
1632 : }
1633 4 : if( WrongPageDesc( pNxtPg ) )
1634 : {
1635 2 : if( bWrongPage )
1636 0 : break; // there's a column between me and my right page
1637 2 : pLayLeaf = 0;
1638 2 : bWrongPage = true;
1639 2 : pOldLayLeaf = 0;
1640 2 : continue;
1641 : }
1642 : }
1643 : // There is no further LayoutFrm that fits, so a new page
1644 : // has to be created, although new pages are worthless within a frame
1645 2 : else if( !pSect->IsInFly() &&
1646 : ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
1647 : {
1648 0 : InsertPage(pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
1649 2 : sal_False );
1650 : // and again the whole thing
1651 2 : pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
1652 2 : continue;
1653 : }
1654 2 : break;
1655 : }
1656 :
1657 2 : if( pLayLeaf )
1658 : {
1659 : // We have found the suitable layout sheet. If there (in the sheet) is
1660 : // already a Follow of our section, we take its first layout sheet,
1661 : // otherwise it is time to create a section follow
1662 : SwSectionFrm* pNew;
1663 :
1664 : // This can be omitted if existing Follows were cut short
1665 2 : SwFrm* pFirst = pLayLeaf->Lower();
1666 : // Here SectionFrms that are to be deleted must be ignored
1667 4 : while( pFirst && pFirst->IsSctFrm() && !((SwSectionFrm*)pFirst)->GetSection() )
1668 0 : pFirst = pFirst->GetNext();
1669 2 : if( pFirst && pFirst->IsSctFrm() && pSect->GetFollow() == pFirst )
1670 0 : pNew = pSect->GetFollow();
1671 2 : else if( MAKEPAGE_NOSECTION == eMakePage )
1672 0 : return pLayLeaf;
1673 : else
1674 : {
1675 2 : pNew = new SwSectionFrm( *pSect, sal_False );
1676 2 : pNew->InsertBefore( pLayLeaf, pLayLeaf->Lower() );
1677 2 : pNew->Init();
1678 2 : SWRECTFN( pNew )
1679 2 : (pNew->*fnRect->fnMakePos)( pLayLeaf, NULL, sal_True );
1680 :
1681 : // If our section frame has a successor then that has to be
1682 : // moved behind the new Follow of the section frames
1683 2 : SwFrm* pTmp = pSect->GetNext();
1684 2 : if( pTmp && pTmp != pSect->GetFollow() )
1685 : {
1686 : SwFlowFrm* pNxt;
1687 0 : SwCntntFrm* pNxtCntnt = NULL;
1688 0 : if( pTmp->IsCntntFrm() )
1689 : {
1690 0 : pNxt = (SwCntntFrm*)pTmp;
1691 0 : pNxtCntnt = (SwCntntFrm*)pTmp;
1692 : }
1693 : else
1694 : {
1695 0 : pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
1696 0 : if( pTmp->IsSctFrm() )
1697 0 : pNxt = (SwSectionFrm*)pTmp;
1698 : else
1699 : {
1700 : OSL_ENSURE( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
1701 0 : pNxt = (SwTabFrm*)pTmp;
1702 : }
1703 0 : while( !pNxtCntnt && 0 != ( pTmp = pTmp->GetNext() ) )
1704 : {
1705 0 : if( pTmp->IsCntntFrm() )
1706 0 : pNxtCntnt = (SwCntntFrm*)pTmp;
1707 : else
1708 0 : pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
1709 : }
1710 : }
1711 0 : if( pNxtCntnt )
1712 : {
1713 0 : SwFtnBossFrm* pOldBoss = pSect->FindFtnBossFrm( sal_True );
1714 0 : if( pOldBoss == pNxtCntnt->FindFtnBossFrm( sal_True ) )
1715 : {
1716 : SwSaveFtnHeight aHeight( pOldBoss,
1717 0 : pOldBoss->Frm().Top() + pOldBoss->Frm().Height() );
1718 : pSect->GetUpper()->MoveLowerFtns( pNxtCntnt, pOldBoss,
1719 0 : pLayLeaf->FindFtnBossFrm( sal_True ), sal_False );
1720 : }
1721 : }
1722 0 : ((SwFlowFrm*)pNxt)->MoveSubTree( pLayLeaf, pNew->GetNext() );
1723 : }
1724 2 : if( pNew->GetFollow() )
1725 0 : pNew->SimpleFormat();
1726 : }
1727 : // The wanted layout sheet is now the first of the determined SctFrms:
1728 2 : pLayLeaf = FIRSTLEAF( pNew );
1729 : }
1730 2 : return pLayLeaf;
1731 : }
1732 :
1733 : /*************************************************************************
1734 : |*
1735 : |* SwFrm::GetPrevSctLeaf()
1736 : |*
1737 : |* Description Returns the preceding layout sheet where the frame
1738 : |* can be moved into
1739 : |*
1740 : |*************************************************************************/
1741 :
1742 :
1743 158 : SwLayoutFrm *SwFrm::GetPrevSctLeaf( MakePageType )
1744 : {
1745 : PROTOCOL_ENTER( this, PROT_LEAF, ACT_PREV_SECT, GetUpper()->FindSctFrm() )
1746 :
1747 : SwLayoutFrm* pCol;
1748 : // ColumnFrm always contain a BodyFrm now
1749 158 : if( IsColBodyFrm() )
1750 0 : pCol = GetUpper();
1751 158 : else if( GetUpper()->IsColBodyFrm() )
1752 0 : pCol = GetUpper()->GetUpper();
1753 : else
1754 158 : pCol = NULL;
1755 158 : bool bJump = false;
1756 158 : if( pCol )
1757 : {
1758 0 : if( pCol->GetPrev() )
1759 : {
1760 0 : do
1761 : {
1762 0 : pCol = (SwLayoutFrm*)pCol->GetPrev();
1763 : // Is there any content?
1764 : // Gibt es dort Inhalt?
1765 0 : if( ((SwLayoutFrm*)pCol->Lower())->Lower() )
1766 : {
1767 0 : if( bJump ) // Did we skip a blank page?
1768 0 : SwFlowFrm::SetMoveBwdJump( sal_True );
1769 0 : return (SwLayoutFrm*)pCol->Lower(); // The columnm body
1770 : }
1771 0 : bJump = true;
1772 0 : } while( pCol->GetPrev() );
1773 :
1774 : // We get here when all columns are empty, pCol is now the
1775 : // first column, we need the body though
1776 0 : pCol = (SwLayoutFrm*)pCol->Lower();
1777 : }
1778 : else
1779 0 : pCol = NULL;
1780 : }
1781 :
1782 158 : if( bJump ) // Did we skip a blank page?
1783 0 : SwFlowFrm::SetMoveBwdJump( sal_True );
1784 :
1785 : // Within sections in tables or section in headers/footers there can
1786 : // be only one column change be made, one of the above shortcuts should
1787 : // have applied, also when the section has a pPrev.
1788 : // Now we even consider an empty column...
1789 : OSL_ENSURE( FindSctFrm(), "GetNextSctLeaf: Missing SectionFrm" );
1790 158 : if( ( IsInTab() && !IsTabFrm() ) || FindFooterOrHeader() )
1791 0 : return pCol;
1792 :
1793 : // === IMPORTANT ===
1794 : // Precondition, which needs to be hold, is that the <this> frame can be
1795 : // inside a table, but then the found section frame <pSect> is also inside
1796 : // this table.
1797 158 : SwSectionFrm *pSect = FindSctFrm();
1798 :
1799 : // #i95698#
1800 : // A table cell containing directly a section does not break - see lcl_FindSectionsInRow(..)
1801 : // Thus, a table inside a section, which is inside another table can only
1802 : // flow backward in the columns of its section.
1803 : // Note: The table cell, which contains the section, can not have a master table cell.
1804 158 : if ( IsTabFrm() && pSect->IsInTab() )
1805 : {
1806 0 : return pCol;
1807 : }
1808 :
1809 : {
1810 : SwFrm *pPrv;
1811 158 : if( 0 != ( pPrv = pSect->GetIndPrev() ) )
1812 : {
1813 : // Mooching, half dead SectionFrms shouldn't confuse us
1814 0 : while( pPrv && pPrv->IsSctFrm() && !((SwSectionFrm*)pPrv)->GetSection() )
1815 0 : pPrv = pPrv->GetPrev();
1816 0 : if( pPrv )
1817 0 : return pCol;
1818 : }
1819 : }
1820 :
1821 158 : const sal_Bool bBody = IsInDocBody();
1822 158 : const sal_Bool bFly = IsInFly();
1823 :
1824 158 : SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
1825 158 : SwLayoutFrm *pPrevLeaf = 0;
1826 :
1827 320 : while ( pLayLeaf )
1828 : {
1829 : // Never step into tables or sections
1830 4 : if ( pLayLeaf->IsInTab() || pLayLeaf->IsInSct() )
1831 : {
1832 0 : pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1833 : }
1834 4 : else if ( bBody && pLayLeaf->IsInDocBody() )
1835 : {
1836 : // If there is a pLayLeaf has a lower pLayLeaf is the frame we are looking for.
1837 : // Exception: pLayLeaf->Lower() is a zombie section frame
1838 0 : const SwFrm* pTmp = pLayLeaf->Lower();
1839 : // OD 11.04.2003 #108824# - consider, that the zombie section frame
1840 : // can have frame below it in the found layout leaf.
1841 : // Thus, skipping zombie section frame, if possible.
1842 0 : while ( pTmp && pTmp->IsSctFrm() &&
1843 0 : !( static_cast<const SwSectionFrm*>(pTmp)->GetSection() ) &&
1844 0 : pTmp->GetNext()
1845 : )
1846 : {
1847 0 : pTmp = pTmp->GetNext();
1848 : }
1849 0 : if ( pTmp &&
1850 0 : ( !pTmp->IsSctFrm() ||
1851 0 : ( static_cast<const SwSectionFrm*>(pTmp)->GetSection() )
1852 : )
1853 : )
1854 : {
1855 0 : break;
1856 : }
1857 0 : pPrevLeaf = pLayLeaf;
1858 0 : pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1859 0 : if ( pLayLeaf )
1860 0 : SwFlowFrm::SetMoveBwdJump( sal_True );
1861 : }
1862 4 : else if ( bFly )
1863 0 : break; // Cntnts in Flys every layout sheet should be right. Why?
1864 : else
1865 4 : pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1866 : }
1867 158 : if( !pLayLeaf )
1868 : {
1869 158 : if( !pPrevLeaf )
1870 158 : return pCol;
1871 0 : pLayLeaf = pPrevLeaf;
1872 : }
1873 :
1874 0 : SwSectionFrm* pNew = NULL;
1875 : // At first go to the end of the layout sheet
1876 0 : SwFrm *pTmp = pLayLeaf->Lower();
1877 0 : if( pTmp )
1878 : {
1879 0 : while( pTmp->GetNext() )
1880 0 : pTmp = pTmp->GetNext();
1881 0 : if( pTmp->IsSctFrm() )
1882 : {
1883 : // Half dead ones only interfere here
1884 0 : while( !((SwSectionFrm*)pTmp)->GetSection() && pTmp->GetPrev() &&
1885 0 : pTmp->GetPrev()->IsSctFrm() )
1886 0 : pTmp = pTmp->GetPrev();
1887 0 : if( ((SwSectionFrm*)pTmp)->GetFollow() == pSect )
1888 0 : pNew = (SwSectionFrm*)pTmp;
1889 : }
1890 : }
1891 0 : if( !pNew )
1892 : {
1893 0 : pNew = new SwSectionFrm( *pSect, sal_True );
1894 0 : pNew->InsertBefore( pLayLeaf, NULL );
1895 0 : pNew->Init();
1896 0 : SWRECTFN( pNew )
1897 0 : (pNew->*fnRect->fnMakePos)( pLayLeaf, pNew->GetPrev(), sal_True );
1898 :
1899 0 : pLayLeaf = FIRSTLEAF( pNew );
1900 0 : if( !pNew->Lower() ) // Format single column sections
1901 : {
1902 0 : pNew->MakePos();
1903 0 : pLayLeaf->Format(); // In order that the PrtArea is correct for the MoveBwd
1904 : }
1905 : else
1906 0 : pNew->SimpleFormat();
1907 : }
1908 : else
1909 : {
1910 0 : pLayLeaf = FIRSTLEAF( pNew );
1911 0 : if( pLayLeaf->IsColBodyFrm() )
1912 : {
1913 : // In existent section columns we're looking for the last not empty
1914 : // column.
1915 0 : SwLayoutFrm *pTmpLay = pLayLeaf;
1916 0 : while( pLayLeaf->GetUpper()->GetNext() )
1917 : {
1918 0 : pLayLeaf = (SwLayoutFrm*)((SwLayoutFrm*)pLayLeaf->GetUpper()->GetNext())->Lower();
1919 0 : if( pLayLeaf->Lower() )
1920 0 : pTmpLay = pLayLeaf;
1921 : }
1922 : // If we skipped an empty column, we've to set the jump-flag
1923 0 : if( pLayLeaf != pTmpLay )
1924 : {
1925 0 : pLayLeaf = pTmpLay;
1926 0 : SwFlowFrm::SetMoveBwdJump( sal_True );
1927 : }
1928 : }
1929 : }
1930 0 : return pLayLeaf;
1931 : }
1932 :
1933 414 : static SwTwips lcl_DeadLine( const SwFrm* pFrm )
1934 : {
1935 414 : const SwLayoutFrm* pUp = pFrm->GetUpper();
1936 414 : while( pUp && pUp->IsInSct() )
1937 : {
1938 0 : if( pUp->IsSctFrm() )
1939 0 : pUp = pUp->GetUpper();
1940 : // Columns now with BodyFrm
1941 0 : else if( pUp->IsColBodyFrm() && pUp->GetUpper()->GetUpper()->IsSctFrm() )
1942 0 : pUp = pUp->GetUpper()->GetUpper();
1943 : else
1944 0 : break;
1945 : }
1946 414 : SWRECTFN( pFrm )
1947 414 : return pUp ? (pUp->*fnRect->fnGetPrtBottom)() :
1948 828 : (pFrm->Frm().*fnRect->fnGetBottom)();
1949 : }
1950 : // SwSectionFrm::Growable(..) checks whether the SectionFrm is still able to
1951 : // grow, as case may be the environment has to be asked
1952 :
1953 2 : sal_Bool SwSectionFrm::Growable() const
1954 : {
1955 2 : SWRECTFN( this )
1956 2 : if( (*fnRect->fnYDiff)( lcl_DeadLine( this ),
1957 2 : (Frm().*fnRect->fnGetBottom)() ) > 0 )
1958 0 : return sal_True;
1959 :
1960 2 : return ( GetUpper() && ((SwFrm*)GetUpper())->Grow( LONG_MAX, sal_True ) );
1961 : }
1962 :
1963 : /*************************************************************************
1964 : |*
1965 : |* SwSectionFrm::_Grow(), _Shrink()
1966 : |*
1967 : |*************************************************************************/
1968 :
1969 412 : SwTwips SwSectionFrm::_Grow( SwTwips nDist, sal_Bool bTst )
1970 : {
1971 412 : if ( !IsColLocked() && !HasFixSize() )
1972 : {
1973 412 : SWRECTFN( this )
1974 412 : long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
1975 412 : if( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
1976 0 : nDist = LONG_MAX - nFrmHeight;
1977 :
1978 412 : if ( nDist <= 0L )
1979 0 : return 0L;
1980 :
1981 412 : bool bInCalcCntnt = GetUpper() && IsInFly() && FindFlyFrm()->IsLocked();
1982 : // OD 2004-03-15 #116561# - allow grow in online layout
1983 824 : bool bGrow = !Lower() || !Lower()->IsColumnFrm() || !Lower()->GetNext() ||
1984 824 : GetSection()->GetFmt()->GetBalancedColumns().GetValue();
1985 412 : if( !bGrow )
1986 : {
1987 0 : const ViewShell *pSh = getRootFrm()->GetCurrShell();
1988 0 : bGrow = pSh && pSh->GetViewOptions()->getBrowseMode();
1989 : }
1990 412 : if( bGrow )
1991 : {
1992 : SwTwips nGrow;
1993 412 : if( IsInFtn() )
1994 0 : nGrow = 0;
1995 : else
1996 : {
1997 412 : nGrow = lcl_DeadLine( this );
1998 : nGrow = (*fnRect->fnYDiff)( nGrow,
1999 412 : (Frm().*fnRect->fnGetBottom)() );
2000 : }
2001 412 : SwTwips nSpace = nGrow;
2002 412 : if( !bInCalcCntnt && nGrow < nDist && GetUpper() )
2003 270 : nGrow += GetUpper()->Grow( LONG_MAX, sal_True );
2004 :
2005 412 : if( nGrow > nDist )
2006 142 : nGrow = nDist;
2007 412 : if( nGrow <= 0 )
2008 : {
2009 6 : nGrow = 0;
2010 6 : if( nDist && !bTst )
2011 : {
2012 4 : if( bInCalcCntnt )
2013 0 : _InvalidateSize();
2014 : else
2015 4 : InvalidateSize();
2016 : }
2017 : }
2018 406 : else if( !bTst )
2019 : {
2020 146 : if( bInCalcCntnt )
2021 0 : _InvalidateSize();
2022 146 : else if( nSpace < nGrow && nDist != nSpace + GetUpper()->
2023 0 : Grow( nGrow - nSpace, sal_False ) )
2024 0 : InvalidateSize();
2025 : else
2026 : {
2027 : const SvxGraphicPosition ePos =
2028 146 : GetAttrSet()->GetBackground().GetGraphicPos();
2029 146 : if ( GPOS_RT < ePos && GPOS_TILED != ePos )
2030 : {
2031 0 : SetCompletePaint();
2032 0 : InvalidatePage();
2033 : }
2034 146 : if( GetUpper() && GetUpper()->IsHeaderFrm() )
2035 0 : GetUpper()->InvalidateSize();
2036 : }
2037 146 : (Frm().*fnRect->fnAddBottom)( nGrow );
2038 146 : long nPrtHeight = (Prt().*fnRect->fnGetHeight)() + nGrow;
2039 146 : (Prt().*fnRect->fnSetHeight)( nPrtHeight );
2040 :
2041 146 : if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2042 : {
2043 0 : SwFrm* pTmp = Lower();
2044 0 : do
2045 : {
2046 0 : pTmp->_InvalidateSize();
2047 0 : pTmp = pTmp->GetNext();
2048 : } while ( pTmp );
2049 0 : _InvalidateSize();
2050 : }
2051 146 : if( GetNext() )
2052 : {
2053 4 : SwFrm *pFrm = GetNext();
2054 8 : while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
2055 0 : pFrm = pFrm->GetNext();
2056 4 : if( pFrm )
2057 : {
2058 4 : if( bInCalcCntnt )
2059 0 : pFrm->_InvalidatePos();
2060 : else
2061 4 : pFrm->InvalidatePos();
2062 : }
2063 : }
2064 : // #i28701# - Due to the new object positioning
2065 : // the frame on the next page/column can flow backward (e.g. it
2066 : // was moved forward due to the positioning of its objects ).
2067 : // Thus, invalivate this next frame, if document compatibility
2068 : // option 'Consider wrapping style influence on object positioning' is ON.
2069 142 : else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
2070 : {
2071 4 : InvalidateNextPos();
2072 : }
2073 : }
2074 412 : return nGrow;
2075 : }
2076 0 : if ( !bTst )
2077 : {
2078 0 : if( bInCalcCntnt )
2079 0 : _InvalidateSize();
2080 : else
2081 0 : InvalidateSize();
2082 : }
2083 : }
2084 0 : return 0L;
2085 : }
2086 :
2087 2 : SwTwips SwSectionFrm::_Shrink( SwTwips nDist, sal_Bool bTst )
2088 : {
2089 2 : if ( Lower() && !IsColLocked() && !HasFixSize() )
2090 : {
2091 2 : if( ToMaximize( sal_False ) )
2092 : {
2093 0 : if( !bTst )
2094 0 : InvalidateSize();
2095 : }
2096 : else
2097 : {
2098 2 : SWRECTFN( this )
2099 2 : long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2100 2 : if ( nDist > nFrmHeight )
2101 0 : nDist = nFrmHeight;
2102 :
2103 2 : if ( Lower()->IsColumnFrm() && Lower()->GetNext() && // FtnAtEnd
2104 0 : !GetSection()->GetFmt()->GetBalancedColumns().GetValue() )
2105 : { // With column bases the format takes over the control of the
2106 : // growth (because of the balance)
2107 0 : if ( !bTst )
2108 0 : InvalidateSize();
2109 0 : return nDist;
2110 : }
2111 2 : else if( !bTst )
2112 : {
2113 : const SvxGraphicPosition ePos =
2114 2 : GetAttrSet()->GetBackground().GetGraphicPos();
2115 2 : if ( GPOS_RT < ePos && GPOS_TILED != ePos )
2116 : {
2117 0 : SetCompletePaint();
2118 0 : InvalidatePage();
2119 : }
2120 2 : (Frm().*fnRect->fnAddBottom)( -nDist );
2121 2 : long nPrtHeight = (Prt().*fnRect->fnGetHeight)() - nDist;
2122 2 : (Prt().*fnRect->fnSetHeight)( nPrtHeight );
2123 :
2124 : // We do not allow a section frame to shrink the its upper
2125 : // footer frame. This is because in the calculation of a
2126 : // footer frame, the content of the section frame is _not_
2127 : // calculated. If there is a fly frame overlapping with the
2128 : // footer frame, the section frame is not affected by this
2129 : // during the calculation of the footer frame size.
2130 : // The footer frame does not grow in its FormatSize function
2131 : // but during the calculation of the content of the section
2132 : // frame. The section frame grows until some of its text is
2133 : // located on top of the fly frame. The next call of CalcCntnt
2134 : // tries to shrink the section and here it would also shrink
2135 : // the footer. This may not happen, because shrinking the footer
2136 : // would cause the top of the section frame to overlap with the
2137 : // fly frame again, this would result in a perfect loop.
2138 2 : if( GetUpper() && !GetUpper()->IsFooterFrm() )
2139 2 : GetUpper()->Shrink( nDist, bTst );
2140 :
2141 2 : if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2142 : {
2143 0 : SwFrm* pTmp = Lower();
2144 0 : do
2145 : {
2146 0 : pTmp->_InvalidateSize();
2147 0 : pTmp = pTmp->GetNext();
2148 : } while ( pTmp );
2149 : }
2150 2 : if( GetNext() )
2151 : {
2152 0 : SwFrm* pFrm = GetNext();
2153 0 : while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
2154 0 : pFrm = pFrm->GetNext();
2155 0 : if( pFrm )
2156 0 : pFrm->InvalidatePos();
2157 : else
2158 0 : SetRetouche();
2159 : }
2160 : else
2161 2 : SetRetouche();
2162 2 : return nDist;
2163 : }
2164 : }
2165 : }
2166 0 : return 0L;
2167 : }
2168 :
2169 : /*************************************************************************
2170 : |*
2171 : |* SwSectionFrm::MoveAllowed()
2172 : |*
2173 : |* When are Frms within a SectionFrms moveable?
2174 : |* If they are not in the last column of a SectionFrms yet,
2175 : |* if there is no Follow,
2176 : |* if the SectionFrm cannot grow anymore, then it gets more complicated,
2177 : |* in that case it depends on whether the SectionFrm can find a next
2178 : |* layout sheet. In (column based/chained) Flys this is checked via
2179 : |* GetNextLayout, in tables and headers/footers there is none, however in the
2180 : |* DocBody and in foot notes there is always one.
2181 : |* This routine is used in the TxtFormatter to decided whether it's allowed to
2182 : |* create a (paragraph-)Follow or whether the paragraph has to stick together
2183 : |*
2184 : |*************************************************************************/
2185 :
2186 2 : sal_Bool SwSectionFrm::MoveAllowed( const SwFrm* pFrm) const
2187 : {
2188 : // Is there a Follow or is the Frame not in the last column?
2189 2 : if( HasFollow() || ( pFrm->GetUpper()->IsColBodyFrm() &&
2190 0 : pFrm->GetUpper()->GetUpper()->GetNext() ) )
2191 0 : return sal_True;
2192 2 : if( pFrm->IsInFtn() )
2193 : {
2194 0 : if( IsInFtn() )
2195 : {
2196 0 : if( GetUpper()->IsInSct() )
2197 : {
2198 0 : if( Growable() )
2199 0 : return sal_False;
2200 0 : return GetUpper()->FindSctFrm()->MoveAllowed( this );
2201 : }
2202 : else
2203 0 : return sal_True;
2204 : }
2205 : // The content of footnote inside a columned sectionfrm is moveable
2206 : // except in the last column
2207 0 : const SwLayoutFrm *pLay = pFrm->FindFtnFrm()->GetUpper()->GetUpper();
2208 0 : if( pLay->IsColumnFrm() && pLay->GetNext() )
2209 : {
2210 : // The first paragraph in the first footnote in the first column
2211 : // in the sectionfrm at the top of the page is not moveable,
2212 : // if the columnbody is empty.
2213 0 : bool bRet = false;
2214 0 : if( pLay->GetIndPrev() || pFrm->GetIndPrev() ||
2215 0 : pFrm->FindFtnFrm()->GetPrev() )
2216 0 : bRet = true;
2217 : else
2218 : {
2219 0 : SwLayoutFrm* pBody = ((SwColumnFrm*)pLay)->FindBodyCont();
2220 0 : if( pBody && pBody->Lower() )
2221 0 : bRet = true;
2222 : }
2223 0 : if( bRet && ( IsFtnAtEnd() || !Growable() ) )
2224 0 : return sal_True;
2225 : }
2226 : }
2227 : // Or can the section still grow?
2228 2 : if( !IsColLocked() && Growable() )
2229 0 : return sal_False;
2230 : // Now it has to be examined whether there is a layout sheet wherein
2231 : // a section Follow can be created
2232 2 : if( IsInTab() || ( !IsInDocBody() && FindFooterOrHeader() ) )
2233 0 : return sal_False; // It doesn't work in tables/headers/footers
2234 2 : if( IsInFly() ) // In column based or chained frames
2235 0 : return 0 != ((SwFrm*)GetUpper())->GetNextLeaf( MAKEPAGE_NONE );
2236 2 : return sal_True;
2237 : }
2238 :
2239 : /** Called for a frame inside a section with no direct previous frame (or only
2240 : previous empty section frames) the previous frame of the outer section is
2241 : returned, if the frame is the first flowing content of this section.
2242 :
2243 : Note: For a frame inside a table frame, which is inside a section frame,
2244 : NULL is returned.
2245 : */
2246 1224 : SwFrm* SwFrm::_GetIndPrev() const
2247 : {
2248 1224 : SwFrm *pRet = NULL;
2249 : // #i79774#
2250 : // Do not assert, if the frame has a direct previous frame, because it
2251 : // could be an empty section frame. The caller has to assure, that the
2252 : // frame has no direct previous frame or only empty section frames as
2253 : // previous frames.
2254 : OSL_ENSURE( /*!pPrev &&*/ IsInSct(), "Why?" );
2255 1224 : const SwFrm* pSct = GetUpper();
2256 1224 : if( !pSct )
2257 0 : return NULL;
2258 1224 : if( pSct->IsSctFrm() )
2259 516 : pRet = pSct->GetIndPrev();
2260 708 : else if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
2261 : {
2262 : // Do not return the previous frame of the outer section, if in one
2263 : // of the previous columns is content.
2264 0 : const SwFrm* pCol = GetUpper()->GetUpper()->GetPrev();
2265 0 : while( pCol )
2266 : {
2267 : OSL_ENSURE( pCol->IsColumnFrm(), "GetIndPrev(): ColumnFrm expected" );
2268 : OSL_ENSURE( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
2269 : "GetIndPrev(): Where's the body?");
2270 0 : if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
2271 0 : return NULL;
2272 0 : pCol = pCol->GetPrev();
2273 : }
2274 0 : pRet = pSct->GetIndPrev();
2275 : }
2276 :
2277 : // skip empty section frames
2278 2448 : while( pRet && pRet->IsSctFrm() && !((SwSectionFrm*)pRet)->GetSection() )
2279 0 : pRet = pRet->GetIndPrev();
2280 1224 : return pRet;
2281 : }
2282 :
2283 560 : SwFrm* SwFrm::_GetIndNext()
2284 : {
2285 : OSL_ENSURE( !pNext && IsInSct(), "Why?" );
2286 560 : SwFrm* pSct = GetUpper();
2287 560 : if( !pSct )
2288 0 : return NULL;
2289 560 : if( pSct->IsSctFrm() )
2290 254 : return pSct->GetIndNext();
2291 306 : if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
2292 : { // We can only return the successor of the SectionFrms if there is no
2293 : // content in the successing columns
2294 0 : SwFrm* pCol = GetUpper()->GetUpper()->GetNext();
2295 0 : while( pCol )
2296 : {
2297 : OSL_ENSURE( pCol->IsColumnFrm(), "GetIndNext(): ColumnFrm expected" );
2298 : OSL_ENSURE( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
2299 : "GetIndNext(): Where's the body?");
2300 0 : if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
2301 0 : return NULL;
2302 0 : pCol = pCol->GetNext();
2303 : }
2304 0 : return pSct->GetIndNext();
2305 : }
2306 306 : return NULL;
2307 : }
2308 :
2309 0 : sal_Bool SwSectionFrm::IsDescendantFrom( const SwSectionFmt* pFmt ) const
2310 : {
2311 0 : if( !pSection || !pFmt )
2312 0 : return sal_False;
2313 0 : const SwSectionFmt *pMyFmt = pSection->GetFmt();
2314 0 : while( pFmt != pMyFmt )
2315 : {
2316 0 : if( pMyFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2317 0 : pMyFmt = (SwSectionFmt*)pMyFmt->GetRegisteredIn();
2318 : else
2319 0 : return sal_False;
2320 : }
2321 0 : return sal_True;
2322 : }
2323 :
2324 76 : void SwSectionFrm::CalcFtnAtEndFlag()
2325 : {
2326 76 : SwSectionFmt *pFmt = GetSection()->GetFmt();
2327 76 : sal_uInt16 nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
2328 76 : bFtnAtEnd = FTNEND_ATPGORDOCEND != nVal;
2329 : bOwnFtnNum = FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
2330 76 : FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
2331 152 : while( !bFtnAtEnd && !bOwnFtnNum )
2332 : {
2333 76 : if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2334 0 : pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
2335 : else
2336 76 : break;
2337 0 : nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
2338 0 : if( FTNEND_ATPGORDOCEND != nVal )
2339 : {
2340 0 : bFtnAtEnd = sal_True;
2341 : bOwnFtnNum = bOwnFtnNum ||FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
2342 0 : FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
2343 : }
2344 : }
2345 76 : }
2346 :
2347 0 : bool SwSectionFrm::IsEndnoteAtMyEnd() const
2348 : {
2349 0 : return pSection->GetFmt()->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2350 : }
2351 :
2352 76 : void SwSectionFrm::CalcEndAtEndFlag()
2353 : {
2354 76 : SwSectionFmt *pFmt = GetSection()->GetFmt();
2355 76 : bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2356 152 : while( !bEndnAtEnd )
2357 : {
2358 76 : if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2359 0 : pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
2360 : else
2361 76 : break;
2362 0 : bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2363 : }
2364 76 : }
2365 :
2366 : /*************************************************************************
2367 : |*
2368 : |* SwSectionFrm::Modify()
2369 : |*
2370 : |*************************************************************************/
2371 :
2372 0 : void SwSectionFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
2373 : {
2374 0 : sal_uInt8 nInvFlags = 0;
2375 :
2376 0 : if( pNew && RES_ATTRSET_CHG == pNew->Which() )
2377 : {
2378 0 : SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
2379 0 : SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
2380 0 : SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
2381 0 : SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
2382 0 : while( true )
2383 : {
2384 : _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
2385 : (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
2386 0 : &aOldSet, &aNewSet );
2387 0 : if( aNIter.IsAtEnd() )
2388 0 : break;
2389 0 : aNIter.NextItem();
2390 0 : aOIter.NextItem();
2391 : }
2392 0 : if ( aOldSet.Count() || aNewSet.Count() )
2393 0 : SwLayoutFrm::Modify( &aOldSet, &aNewSet );
2394 : }
2395 : else
2396 0 : _UpdateAttr( pOld, pNew, nInvFlags );
2397 :
2398 0 : if ( nInvFlags != 0 )
2399 : {
2400 0 : if ( nInvFlags & 0x01 )
2401 0 : InvalidateSize();
2402 0 : if ( nInvFlags & 0x10 )
2403 0 : SetCompletePaint();
2404 : }
2405 0 : }
2406 :
2407 0 : void SwSectionFrm::SwClientNotify( const SwModify& rMod, const SfxHint& rHint )
2408 : {
2409 : // #i117863#
2410 : const SwSectionFrmMoveAndDeleteHint* pHint =
2411 0 : dynamic_cast<const SwSectionFrmMoveAndDeleteHint*>(&rHint);
2412 0 : if ( pHint && pHint->GetId() == SFX_HINT_DYING && &rMod == GetRegisteredIn() )
2413 : {
2414 0 : SwSectionFrm::MoveCntntAndDelete( this, pHint->IsSaveCntnt() );
2415 : }
2416 0 : }
2417 :
2418 0 : void SwSectionFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
2419 : sal_uInt8 &rInvFlags,
2420 : SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
2421 : {
2422 0 : bool bClear = true;
2423 0 : const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
2424 0 : switch( nWhich )
2425 : { // Suppress multi columns in foot notes
2426 : case RES_FMT_CHG:
2427 : {
2428 0 : const SwFmtCol& rNewCol = GetFmt()->GetCol();
2429 0 : if( !IsInFtn() )
2430 : {
2431 : // Nasty case. When allocating a template we can not count
2432 : // on the old column attribute. We're left with creating a
2433 : // temporary attribute here.
2434 0 : SwFmtCol aCol;
2435 0 : if ( Lower() && Lower()->IsColumnFrm() )
2436 : {
2437 0 : sal_uInt16 nCol = 0;
2438 0 : SwFrm *pTmp = Lower();
2439 0 : do
2440 0 : { ++nCol;
2441 0 : pTmp = pTmp->GetNext();
2442 : } while ( pTmp );
2443 0 : aCol.Init( nCol, 0, 1000 );
2444 : }
2445 0 : bool bChgFtn = IsFtnAtEnd();
2446 0 : bool const bChgEndn = IsEndnAtEnd();
2447 0 : bool const bChgMyEndn = IsEndnoteAtMyEnd();
2448 0 : CalcFtnAtEndFlag();
2449 0 : CalcEndAtEndFlag();
2450 0 : bChgFtn = ( bChgFtn != IsFtnAtEnd() ) ||
2451 0 : ( bChgEndn != IsEndnAtEnd() ) ||
2452 0 : ( bChgMyEndn != IsEndnoteAtMyEnd() );
2453 0 : ChgColumns( aCol, rNewCol, bChgFtn );
2454 0 : rInvFlags |= 0x10;
2455 : }
2456 0 : rInvFlags |= 0x01;
2457 0 : bClear = false;
2458 : }
2459 0 : break;
2460 :
2461 : case RES_COL:
2462 0 : if( !IsInFtn() )
2463 : {
2464 0 : ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
2465 0 : rInvFlags |= 0x11;
2466 : }
2467 0 : break;
2468 :
2469 : case RES_FTN_AT_TXTEND:
2470 0 : if( !IsInFtn() )
2471 : {
2472 0 : bool const bOld = IsFtnAtEnd();
2473 0 : CalcFtnAtEndFlag();
2474 0 : if (bOld != IsFtnAtEnd())
2475 : {
2476 0 : const SwFmtCol& rNewCol = GetFmt()->GetCol();
2477 0 : ChgColumns( rNewCol, rNewCol, sal_True );
2478 0 : rInvFlags |= 0x01;
2479 : }
2480 : }
2481 0 : break;
2482 :
2483 : case RES_END_AT_TXTEND:
2484 0 : if( !IsInFtn() )
2485 : {
2486 0 : bool const bOld = IsEndnAtEnd();
2487 0 : bool const bMyOld = IsEndnoteAtMyEnd();
2488 0 : CalcEndAtEndFlag();
2489 0 : if (bOld != IsEndnAtEnd() || bMyOld != IsEndnoteAtMyEnd())
2490 : {
2491 0 : const SwFmtCol& rNewCol = GetFmt()->GetCol();
2492 0 : ChgColumns( rNewCol, rNewCol, sal_True );
2493 0 : rInvFlags |= 0x01;
2494 : }
2495 : }
2496 0 : break;
2497 : case RES_COLUMNBALANCE:
2498 0 : rInvFlags |= 0x01;
2499 0 : break;
2500 :
2501 : case RES_FRAMEDIR :
2502 0 : SetDerivedR2L( sal_False );
2503 0 : CheckDirChange();
2504 0 : break;
2505 :
2506 : case RES_PROTECT:
2507 : {
2508 0 : ViewShell *pSh = getRootFrm()->GetCurrShell();
2509 0 : if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
2510 0 : pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
2511 : }
2512 0 : break;
2513 :
2514 : default:
2515 0 : bClear = false;
2516 : }
2517 0 : if ( bClear )
2518 : {
2519 0 : if ( pOldSet || pNewSet )
2520 : {
2521 0 : if ( pOldSet )
2522 0 : pOldSet->ClearItem( nWhich );
2523 0 : if ( pNewSet )
2524 0 : pNewSet->ClearItem( nWhich );
2525 : }
2526 : else
2527 0 : SwLayoutFrm::Modify( pOld, pNew );
2528 : }
2529 0 : }
2530 :
2531 : /*--------------------------------------------------
2532 : * SwSectionFrm::ToMaximize(..): A follow or a ftncontainer at the end of the
2533 : * page causes a maximal Size of the sectionframe.
2534 : * --------------------------------------------------*/
2535 :
2536 240 : sal_Bool SwSectionFrm::ToMaximize( sal_Bool bCheckFollow ) const
2537 : {
2538 240 : if( HasFollow() )
2539 : {
2540 4 : if( !bCheckFollow ) // Don't check superfluous follows
2541 4 : return sal_True;
2542 0 : const SwSectionFrm* pFoll = GetFollow();
2543 0 : while( pFoll && pFoll->IsSuperfluous() )
2544 0 : pFoll = pFoll->GetFollow();
2545 0 : if( pFoll )
2546 0 : return sal_True;
2547 : }
2548 236 : if( IsFtnAtEnd() )
2549 0 : return sal_False;
2550 236 : const SwFtnContFrm* pCont = ContainsFtnCont();
2551 236 : if( !IsEndnAtEnd() )
2552 236 : return 0 != pCont;
2553 0 : sal_Bool bRet = sal_False;
2554 0 : while( pCont && !bRet )
2555 : {
2556 0 : if( pCont->FindFootNote() )
2557 0 : bRet = sal_True;
2558 : else
2559 0 : pCont = ContainsFtnCont( pCont );
2560 : }
2561 0 : return bRet;
2562 : }
2563 :
2564 : /*--------------------------------------------------
2565 : * sal_Bool SwSectionFrm::ContainsFtnCont()
2566 : * checks every Column for FtnContFrms.
2567 : * --------------------------------------------------*/
2568 :
2569 236 : SwFtnContFrm* SwSectionFrm::ContainsFtnCont( const SwFtnContFrm* pCont ) const
2570 : {
2571 236 : SwFtnContFrm* pRet = NULL;
2572 : const SwLayoutFrm* pLay;
2573 236 : if( pCont )
2574 : {
2575 0 : pLay = pCont->FindFtnBossFrm( 0 );
2576 : OSL_ENSURE( IsAnLower( pLay ), "ConatainsFtnCont: Wrong FtnContainer" );
2577 0 : pLay = (SwLayoutFrm*)pLay->GetNext();
2578 : }
2579 236 : else if( Lower() && Lower()->IsColumnFrm() )
2580 0 : pLay = (SwLayoutFrm*)Lower();
2581 : else
2582 236 : pLay = NULL;
2583 472 : while ( !pRet && pLay )
2584 : {
2585 0 : if( pLay->Lower() && pLay->Lower()->GetNext() )
2586 : {
2587 : OSL_ENSURE( pLay->Lower()->GetNext()->IsFtnContFrm(),
2588 : "ToMaximize: Unexspected Frame" );
2589 0 : pRet = (SwFtnContFrm*)pLay->Lower()->GetNext();
2590 : }
2591 : OSL_ENSURE( !pLay->GetNext() || pLay->GetNext()->IsLayoutFrm(),
2592 : "ToMaximize: ColFrm exspected" );
2593 0 : pLay = (SwLayoutFrm*)pLay->GetNext();
2594 : }
2595 236 : return pRet;
2596 : }
2597 :
2598 0 : void SwSectionFrm::InvalidateFtnPos()
2599 : {
2600 0 : SwFtnContFrm* pCont = ContainsFtnCont( NULL );
2601 0 : if( pCont )
2602 : {
2603 0 : SwFrm *pTmp = pCont->ContainsCntnt();
2604 0 : if( pTmp )
2605 0 : pTmp->_InvalidatePos();
2606 : }
2607 0 : }
2608 :
2609 : /*--------------------------------------------------
2610 : * SwSectionFrm::Undersize() returns the value that the section
2611 : * would like to be greater if it has undersized TxtFrms in it,
2612 : * otherwise Null..
2613 : * If necessary the undersized-flag is corrected.
2614 : * --------------------------------------------------*/
2615 :
2616 76 : long SwSectionFrm::Undersize( sal_Bool bOverSize )
2617 : {
2618 76 : bUndersized = sal_False;
2619 76 : SWRECTFN( this )
2620 76 : long nRet = InnerHeight() - (Prt().*fnRect->fnGetHeight)();
2621 76 : if( nRet > 0 )
2622 0 : bUndersized = sal_True;
2623 76 : else if( !bOverSize )
2624 76 : nRet = 0;
2625 76 : return nRet;
2626 : }
2627 :
2628 : /// OD 01.04.2003 #108446# - determine next frame for footnote/endnote formatting
2629 : /// before format of current one, because current one can move backward.
2630 : /// After moving backward to a previous page method <FindNext()> will return
2631 : /// the text frame presenting the first page footnote, if it exists. Thus, the
2632 : /// rest of the footnote/endnote container would not be formatted.
2633 0 : void SwSectionFrm::CalcFtnCntnt()
2634 : {
2635 0 : SwFtnContFrm* pCont = ContainsFtnCont();
2636 0 : if( pCont )
2637 : {
2638 0 : SwFrm* pFrm = pCont->ContainsAny();
2639 0 : if( pFrm )
2640 0 : pCont->Calc();
2641 0 : while( pFrm && IsAnLower( pFrm ) )
2642 : {
2643 0 : SwFtnFrm* pFtn = pFrm->FindFtnFrm();
2644 0 : if( pFtn )
2645 0 : pFtn->Calc();
2646 : // OD 01.04.2003 #108446# - determine next frame before format current frame.
2647 0 : SwFrm* pNextFrm = 0;
2648 : {
2649 0 : if( pFrm->IsSctFrm() )
2650 : {
2651 0 : pNextFrm = static_cast<SwSectionFrm*>(pFrm)->ContainsAny();
2652 : }
2653 0 : if( !pNextFrm )
2654 : {
2655 0 : pNextFrm = pFrm->FindNext();
2656 : }
2657 : }
2658 0 : pFrm->Calc();
2659 0 : pFrm = pNextFrm;
2660 : }
2661 : }
2662 0 : }
2663 : /* --------------------------------------------------
2664 : * If a SectionFrm gets empty, e.g. because its content changes the page/column,
2665 : * it is not destroyed immediately (there could be a pointer left to it on the
2666 : * stack), instead it puts itself in a list at the RootFrm, which is processed
2667 : * later on (in Layaction::Action among others). Its size is set to Null and
2668 : * the pointer to its page as well. Such SectionFrms that are to be deleted
2669 : * must be ignored by the layout/during formatting.
2670 : *
2671 : * With InsertEmptySct the RootFrm stores a SectionFrm in the list,
2672 : * with RemoveFromList it can be removed from the list (Dtor),
2673 : * with DeleteEmptySct the list is processed and the SectionFrms are destroyed.
2674 : * --------------------------------------------------*/
2675 :
2676 0 : void SwRootFrm::InsertEmptySct( SwSectionFrm* pDel )
2677 : {
2678 0 : if( !pDestroy )
2679 0 : pDestroy = new SwDestroyList;
2680 0 : pDestroy->insert( pDel );
2681 0 : }
2682 :
2683 0 : void SwRootFrm::_DeleteEmptySct()
2684 : {
2685 : OSL_ENSURE( pDestroy, "Keine Liste, keine Kekse" );
2686 0 : while( !pDestroy->empty() )
2687 : {
2688 0 : SwSectionFrm* pSect = *pDestroy->begin();
2689 0 : pDestroy->erase( pDestroy->begin() );
2690 : OSL_ENSURE( !pSect->IsColLocked() && !pSect->IsJoinLocked(),
2691 : "DeleteEmptySct: Locked SectionFrm" );
2692 0 : if( !pSect->Frm().HasArea() && !pSect->ContainsCntnt() )
2693 : {
2694 0 : SwLayoutFrm* pUp = pSect->GetUpper();
2695 0 : pSect->Remove();
2696 0 : delete pSect;
2697 0 : if( pUp && !pUp->Lower() )
2698 : {
2699 0 : if( pUp->IsPageBodyFrm() )
2700 0 : pUp->getRootFrm()->SetSuperfluous();
2701 0 : else if( pUp->IsFtnFrm() && !pUp->IsColLocked() &&
2702 0 : pUp->GetUpper() )
2703 : {
2704 0 : pUp->Cut();
2705 0 : delete pUp;
2706 : }
2707 : }
2708 : }
2709 : else {
2710 : OSL_ENSURE( pSect->GetSection(), "DeleteEmptySct: Halbtoter SectionFrm?!" );
2711 : }
2712 : }
2713 0 : }
2714 :
2715 0 : void SwRootFrm::_RemoveFromList( SwSectionFrm* pSct )
2716 : {
2717 : OSL_ENSURE( pDestroy, "Where's my list?" );
2718 0 : pDestroy->erase( pSct );
2719 0 : }
2720 :
2721 : #ifdef DBG_UTIL
2722 : bool SwRootFrm::IsInDelList( SwSectionFrm* pSct ) const
2723 : {
2724 : return pDestroy && pDestroy->find( pSct ) != pDestroy->end();
2725 : }
2726 : #endif
2727 :
2728 0 : bool SwSectionFrm::IsBalancedSection() const
2729 : {
2730 0 : bool bRet = false;
2731 0 : if ( GetSection() && Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2732 : {
2733 0 : bRet = !GetSection()->GetFmt()->GetBalancedColumns().GetValue();
2734 : }
2735 0 : return bRet;
2736 : }
2737 :
2738 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|