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