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