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