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