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 0 : SwSectionFrm::SwSectionFrm( SwSection &rSect, SwFrm* pSib )
58 0 : : 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 0 : , bFtnLock(false)
66 : {
67 0 : mnType = FRMC_SECTION;
68 :
69 0 : CalcFtnAtEndFlag();
70 0 : CalcEndAtEndFlag();
71 0 : }
72 :
73 0 : SwSectionFrm::SwSectionFrm( SwSectionFrm &rSect, sal_Bool bMaster ) :
74 0 : SwLayoutFrm( rSect.GetFmt(), rSect.getRootFrm() ),
75 : SwFlowFrm( (SwFrm&)*this ),
76 0 : pSection( rSect.GetSection() ),
77 0 : bFtnAtEnd( rSect.IsFtnAtEnd() ),
78 0 : bEndnAtEnd( rSect.IsEndnAtEnd() ),
79 : bCntntLock( false ),
80 : bOwnFtnNum( false ),
81 0 : bFtnLock( false )
82 : {
83 0 : mnType = FRMC_SECTION;
84 :
85 : PROTOCOL( this, PROT_SECTION, bMaster ? ACT_CREATE_MASTER : ACT_CREATE_FOLLOW, &rSect )
86 :
87 0 : if( bMaster )
88 : {
89 0 : if( rSect.IsFollow() )
90 : {
91 0 : SwSectionFrm* pMaster = rSect.FindMaster();
92 0 : pMaster->SetFollow( this );
93 : }
94 0 : SetFollow( &rSect );
95 : }
96 : else
97 : {
98 0 : SetFollow( rSect.GetFollow() );
99 0 : rSect.SetFollow( this );
100 0 : if( !GetFollow() )
101 0 : rSect.SimpleFormat();
102 0 : if( !rSect.IsColLocked() )
103 0 : rSect.InvalidateSize();
104 : }
105 0 : }
106 :
107 : // NOTE: call <SwSectionFrm::Init()> directly after creation of a new section
108 : // frame and its insert in the layout.
109 0 : void SwSectionFrm::Init()
110 : {
111 : OSL_ENSURE( GetUpper(), "SwSectionFrm::Init before insertion?!" );
112 0 : SWRECTFN( this )
113 0 : long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
114 0 : (Frm().*fnRect->fnSetWidth)( nWidth );
115 0 : (Frm().*fnRect->fnSetHeight)( 0 );
116 :
117 : // #109700# LRSpace for sections
118 0 : const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
119 0 : (Prt().*fnRect->fnSetLeft)( rLRSpace.GetLeft() );
120 0 : (Prt().*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
121 0 : rLRSpace.GetRight() );
122 0 : (Prt().*fnRect->fnSetHeight)( 0 );
123 :
124 0 : const SwFmtCol &rCol = GetFmt()->GetCol();
125 0 : if( ( rCol.GetNumCols() > 1 || IsAnyNoteAtEnd() ) && !IsInFtn() )
126 : {
127 0 : const SwFmtCol *pOld = Lower() ? &rCol : new SwFmtCol;
128 0 : ChgColumns( *pOld, rCol, IsAnyNoteAtEnd() );
129 0 : if( pOld != &rCol )
130 0 : delete pOld;
131 : }
132 0 : }
133 :
134 0 : SwSectionFrm::~SwSectionFrm()
135 : {
136 0 : if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
137 : {
138 0 : SwRootFrm *pRootFrm = getRootFrm();
139 0 : if( pRootFrm )
140 0 : pRootFrm->RemoveFromList( this );
141 0 : if( IsFollow() )
142 : {
143 0 : SwSectionFrm *pMaster = FindMaster();
144 0 : if( pMaster )
145 : {
146 : PROTOCOL( this, PROT_SECTION, ACT_DEL_FOLLOW, pMaster )
147 0 : 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 0 : if( !GetFollow() )
153 0 : pMaster->InvalidateSize();
154 : }
155 : }
156 0 : else if( HasFollow() )
157 : {
158 : PROTOCOL( this, PROT_SECTION, ACT_DEL_MASTER, GetFollow() )
159 : }
160 : }
161 0 : }
162 :
163 0 : void SwSectionFrm::DelEmpty( sal_Bool bRemove )
164 : {
165 0 : if( IsColLocked() )
166 : {
167 : OSL_ENSURE( !bRemove, "Don't delete locked SectionFrms" );
168 0 : return;
169 : }
170 0 : SwFrm* pUp = GetUpper();
171 0 : 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 0 : SwViewShell* pViewShell( getRootFrm()->GetCurrShell() );
180 0 : if ( pViewShell && pViewShell->GetLayout() &&
181 0 : pViewShell->GetLayout()->IsAnyShellAccessible() )
182 : {
183 : pViewShell->InvalidateAccessibleParaFlowRelation(
184 0 : dynamic_cast<SwTxtFrm*>(FindNextCnt( true )),
185 0 : dynamic_cast<SwTxtFrm*>(FindPrevCnt( true )) );
186 : }
187 : }
188 0 : _Cut( bRemove );
189 : }
190 0 : if( IsFollow() )
191 : {
192 0 : SwSectionFrm *pMaster = FindMaster();
193 0 : 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 0 : if( !GetFollow() && !pMaster->IsColLocked() )
199 0 : pMaster->InvalidateSize();
200 : }
201 0 : SetFollow(0);
202 0 : if( pUp )
203 : {
204 0 : Frm().Height( 0 );
205 : // If we are destroyed immediately anyway, we don't need
206 : // to put us into the list
207 0 : 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 0 : if( !pSection && getRootFrm() )
212 0 : getRootFrm()->RemoveFromList( this );
213 : }
214 0 : else if( getRootFrm() )
215 0 : getRootFrm()->InsertEmptySct( this );
216 0 : pSection = NULL; // like this a reanimation is virtually impossible though
217 : }
218 : }
219 :
220 0 : void SwSectionFrm::Cut()
221 : {
222 0 : _Cut( sal_True );
223 0 : }
224 :
225 0 : void SwSectionFrm::_Cut( sal_Bool bRemove )
226 : {
227 : OSL_ENSURE( GetUpper(), "Cut ohne Upper()." );
228 :
229 : PROTOCOL( this, PROT_CUT, 0, GetUpper() )
230 :
231 0 : SwPageFrm *pPage = FindPageFrm();
232 0 : InvalidatePage( pPage );
233 0 : SwFrm *pFrm = GetNext();
234 0 : SwFrm* pPrepFrm = NULL;
235 0 : while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
236 0 : pFrm = pFrm->GetNext();
237 0 : 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 0 : pFrm->_InvalidatePrt();
241 0 : pFrm->_InvalidatePos();
242 0 : if( pFrm->IsSctFrm() )
243 0 : pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
244 0 : if ( pFrm && pFrm->IsCntntFrm() )
245 : {
246 0 : pFrm->InvalidatePage( pPage );
247 0 : if( IsInFtn() && !GetIndPrev() )
248 0 : pPrepFrm = pFrm;
249 : }
250 : }
251 : else
252 : {
253 0 : InvalidateNextPos();
254 : // Someone has to take over the retouching: predecessor or Upper
255 0 : if ( 0 != (pFrm = GetPrev()) )
256 0 : { pFrm->SetRetouche();
257 0 : pFrm->Prepare( PREP_WIDOWS_ORPHANS );
258 0 : if ( pFrm->IsCntntFrm() )
259 0 : 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 0 : { SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
266 0 : pRoot->SetSuperfluous();
267 0 : GetUpper()->SetCompletePaint();
268 : }
269 : }
270 : // First remove, then shrink Upper
271 0 : SwLayoutFrm *pUp = GetUpper();
272 0 : if( bRemove )
273 : {
274 0 : Remove();
275 0 : 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 0 : if( pPrepFrm )
284 0 : pPrepFrm->Prepare( PREP_FTN );
285 0 : if ( pUp )
286 : {
287 0 : SWRECTFN( this );
288 0 : SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
289 0 : if( nFrmHeight > 0 )
290 : {
291 0 : if( !bRemove )
292 : {
293 0 : (Frm().*fnRect->fnSetHeight)( 0 );
294 0 : (Prt().*fnRect->fnSetHeight)( 0 );
295 : }
296 0 : pUp->Shrink( nFrmHeight );
297 : }
298 : }
299 0 : }
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 0 : void SwSectionFrm::MergeNext( SwSectionFrm* pNxt )
431 : {
432 0 : if( !pNxt->IsJoinLocked() && GetSection() == pNxt->GetSection() )
433 : {
434 : PROTOCOL( this, PROT_SECTION, ACT_MERGE, pNxt )
435 :
436 0 : SwFrm* pTmp = ::SaveCntnt( pNxt );
437 0 : if( pTmp )
438 : {
439 0 : SwFrm* pLast = Lower();
440 0 : SwLayoutFrm* pLay = this;
441 0 : if( pLast )
442 : {
443 0 : while( pLast->GetNext() )
444 0 : pLast = pLast->GetNext();
445 0 : 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 0 : ::RestoreCntnt( pTmp, pLay, pLast, true );
455 : }
456 0 : SetFollow( pNxt->GetFollow() );
457 0 : pNxt->SetFollow( NULL );
458 0 : pNxt->Cut();
459 0 : delete pNxt;
460 0 : InvalidateSize();
461 : }
462 0 : }
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 0 : sal_Bool SwSectionFrm::SplitSect( SwFrm* pFrm, sal_Bool bApres )
471 : {
472 : OSL_ENSURE( pFrm, "SplitSect: Why?" );
473 0 : SwFrm* pOther = bApres ? pFrm->FindNext() : pFrm->FindPrev();
474 0 : if( !pOther )
475 0 : return sal_False;
476 0 : SwSectionFrm* pSect = pOther->FindSctFrm();
477 0 : if( pSect != this )
478 0 : return sal_False;
479 : // Put the content aside
480 0 : SwFrm* pSav = ::SaveCntnt( this, bApres ? pOther : pFrm );
481 : OSL_ENSURE( pSav, "SplitSect: What's on?" );
482 0 : if( pSav ) // be robust
483 : { // Create a new SctFrm, not as a Follower/master
484 0 : SwSectionFrm* pNew = new SwSectionFrm( *pSect->GetSection(), pSect );
485 0 : pNew->InsertBehind( pSect->GetUpper(), pSect );
486 0 : pNew->Init();
487 0 : SWRECTFN( this )
488 0 : (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 0 : SwLayoutFrm* pLay = pNew;
495 : // Search for last layout frame, e.g. for columned sections.
496 0 : while( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
497 0 : pLay = (SwLayoutFrm*)pLay->Lower();
498 0 : ::RestoreCntnt( pSav, pLay, NULL, true );
499 : }
500 0 : _InvalidateSize();
501 0 : if( HasFollow() )
502 : {
503 0 : pNew->SetFollow( GetFollow() );
504 0 : SetFollow( NULL );
505 : }
506 0 : 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 0 : static void lcl_InvalidateInfFlags( SwFrm* pFrm, bool bInva )
521 : {
522 0 : while ( pFrm )
523 : {
524 0 : pFrm->InvalidateInfFlags();
525 0 : if( bInva )
526 : {
527 0 : pFrm->_InvalidatePos();
528 0 : pFrm->_InvalidateSize();
529 0 : pFrm->_InvalidatePrt();
530 : }
531 0 : if( pFrm->IsLayoutFrm() )
532 0 : lcl_InvalidateInfFlags( ((SwLayoutFrm*)pFrm)->GetLower(), false );
533 0 : pFrm = pFrm->GetNext();
534 : }
535 0 : }
536 :
537 : // Works like SwCntntFrm::ImplGetNextCntntFrm, but starts with a LayoutFrm
538 0 : static SwCntntFrm* lcl_GetNextCntntFrm( const SwLayoutFrm* pLay, bool bFwd )
539 : {
540 0 : if ( bFwd )
541 : {
542 0 : if ( pLay->GetNext() && pLay->GetNext()->IsCntntFrm() )
543 0 : return (SwCntntFrm*)pLay->GetNext();
544 : }
545 : else
546 : {
547 0 : if ( pLay->GetPrev() && pLay->GetPrev()->IsCntntFrm() )
548 0 : return (SwCntntFrm*)pLay->GetPrev();
549 : }
550 :
551 : // #100926#
552 0 : const SwFrm* pFrm = pLay;
553 0 : SwCntntFrm *pCntntFrm = 0;
554 0 : bool bGoingUp = true;
555 0 : do {
556 0 : const SwFrm *p = 0;
557 0 : bool bGoingFwdOrBwd = false;
558 :
559 0 : bool bGoingDown = !bGoingUp && ( 0 != ( p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0 ) );
560 0 : if ( !bGoingDown )
561 : {
562 0 : bGoingFwdOrBwd = ( 0 != ( p = pFrm->IsFlyFrm() ?
563 : ( bFwd ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink() ) :
564 0 : ( bFwd ? pFrm->GetNext() :pFrm->GetPrev() ) ) );
565 0 : if ( !bGoingFwdOrBwd )
566 : {
567 0 : bGoingUp = (0 != (p = pFrm->GetUpper() ) );
568 0 : if ( !bGoingUp )
569 0 : return 0;
570 : }
571 : }
572 :
573 0 : bGoingUp = !( bGoingFwdOrBwd || bGoingDown );
574 :
575 0 : if( !bFwd && bGoingDown && p )
576 0 : while ( p->GetNext() )
577 0 : p = p->GetNext();
578 :
579 0 : pFrm = p;
580 0 : } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
581 :
582 0 : return pCntntFrm;
583 : }
584 :
585 : #define FIRSTLEAF( pLayFrm ) ( ( pLayFrm->Lower() && pLayFrm->Lower()->IsColumnFrm() )\
586 : ? pLayFrm->GetNextLayoutLeaf() \
587 : : pLayFrm )
588 :
589 0 : void SwSectionFrm::MoveCntntAndDelete( SwSectionFrm* pDel, sal_Bool bSave )
590 : {
591 0 : bool bSize = pDel->Lower() && pDel->Lower()->IsColumnFrm();
592 0 : SwFrm* pPrv = pDel->GetPrev();
593 0 : SwLayoutFrm* pUp = pDel->GetUpper();
594 : // OD 27.03.2003 #i12711# - initialize local pointer variables.
595 0 : SwSectionFrm* pPrvSct = NULL;
596 0 : SwSectionFrm* pNxtSct = NULL;
597 0 : SwSectionFmt* pParent = static_cast<SwSectionFmt*>(pDel->GetFmt())->GetParent();
598 0 : 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 0 : if ( pParent )
613 : {
614 0 : SwFrm* pPrvCntnt = lcl_GetNextCntntFrm( pDel, false );
615 0 : pPrvSct = pPrvCntnt ? pPrvCntnt->FindSctFrm() : NULL;
616 0 : SwFrm* pNxtCntnt = lcl_GetNextCntntFrm( pDel, true );
617 0 : pNxtSct = pNxtCntnt ? pNxtCntnt->FindSctFrm() : NULL;
618 : }
619 : else
620 : {
621 0 : pParent = NULL;
622 0 : pPrvSct = pNxtSct = NULL;
623 : }
624 :
625 : // Now the content is put aside and the frame is destroyed
626 0 : SwFrm *pSave = bSave ? ::SaveCntnt( pDel ) : NULL;
627 0 : sal_Bool bOldFtn = sal_True;
628 0 : if( pSave && pUp->IsFtnFrm() )
629 : {
630 0 : bOldFtn = ((SwFtnFrm*)pUp)->IsColLocked();
631 0 : ((SwFtnFrm*)pUp)->ColLock();
632 : }
633 0 : pDel->DelEmpty( sal_True );
634 0 : delete pDel;
635 0 : if( pParent )
636 : { // Search for the appropriate insert position
637 0 : 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 0 : else if( pPrvSct && pPrvSct->GetFmt() == pParent )
645 : { // Wonderful, here we can insert ourselves at the end
646 0 : pUp = pPrvSct;
647 0 : if( pUp->Lower() && pUp->Lower()->IsColumnFrm() )
648 : {
649 0 : pUp = static_cast<SwLayoutFrm*>(pUp->GetLastLower());
650 : // The body of the last column
651 0 : pUp = static_cast<SwLayoutFrm*>(pUp->Lower());
652 : }
653 : // In order to perform the insertion after the last one
654 0 : pPrv = pUp->GetLastLower();
655 0 : pPrvSct = NULL; // Such that nothing is merged
656 : }
657 : else
658 : {
659 0 : 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 0 : pPrvSct = NULL; // Such that nothing will be merged
675 : }
676 : }
677 : // The content is going to be inserted..
678 0 : if( pSave )
679 : {
680 0 : lcl_InvalidateInfFlags( pSave, bSize );
681 0 : ::RestoreCntnt( pSave, pUp, pPrv, true );
682 0 : pUp->FindPageFrm()->InvalidateCntnt();
683 0 : if( !bOldFtn )
684 0 : ((SwFtnFrm*)pUp)->ColUnlock();
685 : }
686 : // Now two parts of the superior section could possibly be merged
687 0 : if( pPrvSct && !pPrvSct->IsJoinLocked() )
688 : {
689 : OSL_ENSURE( pNxtSct, "MoveCntnt: No Merge" );
690 0 : pPrvSct->MergeNext( pNxtSct );
691 : }
692 0 : }
693 :
694 0 : void SwSectionFrm::MakeAll()
695 : {
696 0 : if ( IsJoinLocked() || IsColLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
697 0 : return;
698 0 : if( !pSection ) // Via DelEmpty
699 : {
700 : #ifdef DBG_UTIL
701 : OSL_ENSURE( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
702 : #endif
703 0 : if( !mbValidPos )
704 : {
705 0 : if( GetUpper() )
706 : {
707 0 : SWRECTFN( GetUpper() )
708 0 : (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
709 : }
710 : }
711 0 : mbValidSize = mbValidPos = mbValidPrtArea = sal_True;
712 0 : return;
713 : }
714 0 : LockJoin(); // I don't let myself to be destroyed on the way
715 :
716 0 : while( GetNext() && GetNext() == GetFollow() )
717 : {
718 0 : const SwFrm* pFoll = GetFollow();
719 0 : MergeNext( (SwSectionFrm*)GetNext() );
720 0 : 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 0 : const SwViewShell *pSh = getRootFrm()->GetCurrShell();
727 0 : if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
728 0 : ( Grow( LONG_MAX, true ) > 0 ) )
729 : {
730 0 : 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 0 : if( !mbValidPos && ToMaximize( sal_False ) )
742 0 : mbValidSize = sal_False;
743 :
744 : #if OSL_DEBUG_LEVEL > 1
745 : const SwFmtCol &rCol = GetFmt()->GetCol();
746 : (void)rCol;
747 : #endif
748 0 : SwLayoutFrm::MakeAll();
749 0 : UnlockJoin();
750 0 : if( pSection && IsSuperfluous() )
751 0 : 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 0 : static void lcl_FindCntntFrm( SwCntntFrm* &rpCntntFrm, SwFtnFrm* &rpFtnFrm,
774 : SwFrm* pFrm, sal_Bool &rbChkFtn )
775 : {
776 0 : if( pFrm )
777 : {
778 0 : while( pFrm->GetNext() )
779 0 : pFrm = pFrm->GetNext();
780 0 : while( !rpCntntFrm && pFrm )
781 : {
782 0 : if( pFrm->IsCntntFrm() )
783 0 : rpCntntFrm = (SwCntntFrm*)pFrm;
784 0 : else if( pFrm->IsLayoutFrm() )
785 : {
786 0 : 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 0 : ((SwLayoutFrm*)pFrm)->Lower(), rbChkFtn );
797 : }
798 0 : pFrm = pFrm->GetPrev();
799 : }
800 : }
801 0 : }
802 :
803 0 : SwCntntFrm *SwSectionFrm::FindLastCntnt( sal_uInt8 nMode )
804 : {
805 0 : SwCntntFrm *pRet = NULL;
806 0 : SwFtnFrm *pFtnFrm = NULL;
807 0 : SwSectionFrm *pSect = this;
808 0 : 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 0 : sal_Bool bFtnFound = nMode == FINDMODE_ENDNOTE;
827 0 : do
828 : {
829 0 : lcl_FindCntntFrm( pRet, pFtnFrm, pSect->Lower(), bFtnFound );
830 0 : if( pRet || !pSect->IsFollow() || !nMode ||
831 0 : ( FINDMODE_MYLAST == nMode && this == pSect ) )
832 0 : break;
833 0 : pSect = pSect->FindMaster();
834 : } while( pSect );
835 0 : if( ( nMode == FINDMODE_ENDNOTE ) && pFtnFrm )
836 0 : pRet = pFtnFrm->ContainsCntnt();
837 0 : return pRet;
838 : }
839 :
840 0 : sal_Bool SwSectionFrm::CalcMinDiff( SwTwips& rMinDiff ) const
841 : {
842 0 : if( ToMaximize( sal_True ) )
843 : {
844 0 : SWRECTFN( this )
845 0 : rMinDiff = (GetUpper()->*fnRect->fnGetPrtBottom)();
846 0 : rMinDiff = (Frm().*fnRect->fnBottomDist)( rMinDiff );
847 0 : return sal_True;
848 : }
849 0 : 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 0 : static SwFtnFrm* lcl_FindEndnote( SwSectionFrm* &rpSect, bool &rbEmpty,
859 : SwLayouter *pLayouter )
860 : {
861 : // if rEmpty is set, the rpSect is already searched
862 0 : SwSectionFrm* pSect = rbEmpty ? rpSect->GetFollow() : rpSect;
863 0 : 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 0 : SwColumnFrm* pCol = 0;
870 0 : if(pSect->Lower() && pSect->Lower()->IsColumnFrm())
871 0 : pCol = (SwColumnFrm*)pSect->Lower();
872 :
873 0 : while( pCol ) // check all columns
874 : {
875 0 : SwFtnContFrm* pFtnCont = pCol->FindFtnCont();
876 0 : 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 0 : pCol = (SwColumnFrm*)pCol->GetNext();
901 : }
902 0 : rpSect = pSect;
903 0 : pSect = pLayouter ? pSect->GetFollow() : NULL;
904 0 : rbEmpty = true;
905 : }
906 0 : return NULL;
907 : }
908 :
909 0 : static void lcl_ColumnRefresh( SwSectionFrm* pSect, bool bFollow )
910 : {
911 0 : while( pSect )
912 : {
913 0 : sal_Bool bOldLock = pSect->IsColLocked();
914 0 : pSect->ColLock();
915 0 : if( pSect->Lower() && pSect->Lower()->IsColumnFrm() )
916 : {
917 0 : SwColumnFrm *pCol = (SwColumnFrm*)pSect->Lower();
918 0 : do
919 0 : { pCol->_InvalidateSize();
920 0 : pCol->_InvalidatePos();
921 0 : ((SwLayoutFrm*)pCol)->Lower()->_InvalidateSize();
922 0 : pCol->Calc(); // calculation of column and
923 0 : ((SwLayoutFrm*)pCol)->Lower()->Calc(); // body
924 0 : pCol = (SwColumnFrm*)pCol->GetNext();
925 : } while ( pCol );
926 : }
927 0 : if( !bOldLock )
928 0 : pSect->ColUnlock();
929 0 : if( bFollow )
930 0 : pSect = pSect->GetFollow();
931 : else
932 0 : pSect = NULL;
933 : }
934 0 : }
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 0 : void SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
965 : {
966 0 : SWRECTFN( this )
967 : long nDiff;
968 0 : SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
969 0 : if( bGrow && ( !IsInFly() || !GetUpper()->IsColBodyFrm() ||
970 0 : !FindFlyFrm()->IsLocked() ) )
971 : {
972 0 : nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
973 0 : if( !bMaximize )
974 0 : nDiff += Undersize();
975 0 : if( nDiff > 0 )
976 : {
977 0 : long nAdd = GetUpper()->Grow( nDiff );
978 0 : if( bVert && !bRev )
979 0 : nDeadLine -= nAdd;
980 : else
981 0 : nDeadLine += nAdd;
982 : }
983 : }
984 0 : nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
985 0 : SetUndersized( !bMaximize && nDiff >= 0 );
986 0 : const bool bCalc = ( IsUndersized() || bMaximize ) &&
987 0 : ( nDiff ||
988 0 : (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 0 : bool bExtraCalc = false;
992 0 : if( !bCalc && !bGrow && IsAnyNoteAtEnd() && !IsInFtn() )
993 : {
994 0 : SwSectionFrm *pSect = this;
995 0 : bool bEmpty = false;
996 0 : SwLayoutFrm* pFtn = IsEndnAtEnd() ?
997 0 : lcl_FindEndnote( pSect, bEmpty, NULL ) : NULL;
998 0 : 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 0 : else if( GetFollow() && !GetFollow()->ContainsAny() )
1007 0 : bExtraCalc = true;
1008 : }
1009 0 : if ( bCalc || bExtraCalc )
1010 : {
1011 0 : nDiff = (*fnRect->fnYDiff)( nDeadLine, (Frm().*fnRect->fnGetTop)() );
1012 0 : if( nDiff < 0 )
1013 : {
1014 0 : nDiff = 0;
1015 0 : nDeadLine = (Frm().*fnRect->fnGetTop)();
1016 : }
1017 0 : const Size aOldSz( Prt().SSize() );
1018 0 : long nTop = (this->*fnRect->fnGetTopMargin)();
1019 0 : (Frm().*fnRect->fnSetBottom)( nDeadLine );
1020 0 : nDiff = (Frm().*fnRect->fnGetHeight)();
1021 0 : if( nTop > nDiff )
1022 0 : nTop = nDiff;
1023 0 : (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 0 : (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 0 : if ( ( bHeightChanged || bExtraCalc ) && Lower() )
1039 : {
1040 0 : if( Lower()->IsColumnFrm() )
1041 : {
1042 0 : lcl_ColumnRefresh( this, false );
1043 0 : ::CalcCntnt( this );
1044 : }
1045 : else
1046 : {
1047 0 : ChgLowersProp( aOldSz );
1048 0 : if( !bMaximize && !IsCntntLocked() )
1049 0 : ::CalcCntnt( this );
1050 : }
1051 : }
1052 : }
1053 0 : }
1054 :
1055 0 : void SwSectionFrm::SimpleFormat()
1056 : {
1057 0 : if ( IsJoinLocked() || IsColLocked() )
1058 0 : return;
1059 0 : LockJoin();
1060 0 : SWRECTFN( this )
1061 0 : if( GetPrev() || GetUpper() )
1062 : {
1063 : // assure notifications on position changes.
1064 0 : const SwLayNotify aNotify( this );
1065 0 : (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
1066 0 : mbValidPos = sal_True;
1067 : }
1068 0 : 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 0 : if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) >= 0 )
1072 : {
1073 0 : (Frm().*fnRect->fnSetBottom)( nDeadLine );
1074 0 : long nHeight = (Frm().*fnRect->fnGetHeight)();
1075 0 : long nTop = CalcUpperSpace();
1076 0 : if( nTop > nHeight )
1077 0 : nTop = nHeight;
1078 0 : (this->*fnRect->fnSetYMargins)( nTop, 0 );
1079 : }
1080 0 : lcl_ColumnRefresh( this, false );
1081 0 : 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 0 : ExtraFormatToPositionObjs( SwSectionFrm& _rSectFrm)
1094 : : mpSectFrm( &_rSectFrm ),
1095 0 : mbExtraFormatPerformed( false )
1096 0 : {}
1097 :
1098 0 : ~ExtraFormatToPositionObjs()
1099 : {
1100 0 : if ( mbExtraFormatPerformed )
1101 : {
1102 : // release keep locked position of lower floating screen objects
1103 0 : SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
1104 0 : SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
1105 0 : if ( pObjs )
1106 : {
1107 0 : sal_uInt32 i = 0;
1108 0 : for ( i = 0; i < pObjs->Count(); ++i )
1109 : {
1110 0 : SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1111 :
1112 0 : if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
1113 : {
1114 0 : pAnchoredObj->SetKeepPosLocked( false );
1115 : }
1116 : }
1117 : }
1118 : }
1119 0 : }
1120 :
1121 : // #i81555#
1122 0 : void InitObjs( SwFrm& rFrm )
1123 : {
1124 0 : SwSortedObjs* pObjs = rFrm.GetDrawObjs();
1125 0 : 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 0 : SwLayoutFrm* pLayoutFrm = dynamic_cast<SwLayoutFrm*>(&rFrm);
1137 0 : if ( pLayoutFrm != 0 )
1138 : {
1139 0 : SwFrm* pLowerFrm = pLayoutFrm->GetLower();
1140 0 : while ( pLowerFrm != 0 )
1141 : {
1142 0 : InitObjs( *pLowerFrm );
1143 :
1144 0 : pLowerFrm = pLowerFrm->GetNext();
1145 : }
1146 : }
1147 0 : }
1148 :
1149 0 : void FormatSectionToPositionObjs()
1150 : {
1151 : // perform extra format for multi-columned section.
1152 0 : if ( mpSectFrm->Lower() && mpSectFrm->Lower()->IsColumnFrm() &&
1153 0 : mpSectFrm->Lower()->GetNext() )
1154 : {
1155 : // grow section till bottom of printing area of upper frame
1156 0 : SWRECTFN( mpSectFrm );
1157 0 : SwTwips nTopMargin = (mpSectFrm->*fnRect->fnGetTopMargin)();
1158 0 : Size aOldSectPrtSize( mpSectFrm->Prt().SSize() );
1159 0 : SwTwips nDiff = (mpSectFrm->Frm().*fnRect->fnBottomDist)(
1160 0 : (mpSectFrm->GetUpper()->*fnRect->fnGetPrtBottom)() );
1161 0 : (mpSectFrm->Frm().*fnRect->fnAddBottom)( nDiff );
1162 0 : (mpSectFrm->*fnRect->fnSetYMargins)( nTopMargin, 0 );
1163 : // #i59789#
1164 : // suppress formatting, if printing area of section is too narrow
1165 0 : if ( (mpSectFrm->Prt().*fnRect->fnGetHeight)() <= 0 )
1166 : {
1167 0 : return;
1168 : }
1169 0 : mpSectFrm->ChgLowersProp( aOldSectPrtSize );
1170 :
1171 : // format column frames and its body and footnote container
1172 0 : SwColumnFrm* pColFrm = static_cast<SwColumnFrm*>(mpSectFrm->Lower());
1173 0 : while ( pColFrm )
1174 : {
1175 0 : pColFrm->Calc();
1176 0 : pColFrm->Lower()->Calc();
1177 0 : if ( pColFrm->Lower()->GetNext() )
1178 : {
1179 0 : pColFrm->Lower()->GetNext()->Calc();
1180 : }
1181 :
1182 0 : 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 0 : InitObjs( *mpSectFrm );
1191 :
1192 : // format content - first with collecting its foot-/endnotes before content
1193 : // format, second without collecting its foot-/endnotes.
1194 0 : ::CalcCntnt( mpSectFrm );
1195 0 : ::CalcCntnt( mpSectFrm, true );
1196 :
1197 : // keep locked position of lower floating screen objects
1198 0 : SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
1199 0 : SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
1200 0 : if ( pObjs )
1201 : {
1202 0 : sal_uInt32 i = 0;
1203 0 : for ( i = 0; i < pObjs->Count(); ++i )
1204 : {
1205 0 : SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1206 :
1207 0 : if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
1208 : {
1209 0 : pAnchoredObj->SetKeepPosLocked( true );
1210 : }
1211 : }
1212 : }
1213 :
1214 0 : mbExtraFormatPerformed = true;
1215 : }
1216 : }
1217 : };
1218 :
1219 : /// "formats" the frame; Frm and PrtArea
1220 0 : void SwSectionFrm::Format( const SwBorderAttrs *pAttr )
1221 : {
1222 0 : 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 0 : return;
1229 : }
1230 0 : SWRECTFN( this )
1231 0 : if ( !mbValidPrtArea )
1232 : {
1233 : PROTOCOL( this, PROT_PRTAREA, 0, 0 )
1234 0 : mbValidPrtArea = sal_True;
1235 0 : SwTwips nUpper = CalcUpperSpace();
1236 :
1237 : // #109700# LRSpace for sections
1238 0 : const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
1239 0 : (this->*fnRect->fnSetXMargins)( rLRSpace.GetLeft(), rLRSpace.GetRight() );
1240 :
1241 0 : if( nUpper != (this->*fnRect->fnGetTopMargin)() )
1242 : {
1243 0 : mbValidSize = sal_False;
1244 0 : SwFrm* pOwn = ContainsAny();
1245 0 : if( pOwn )
1246 0 : pOwn->_InvalidatePos();
1247 : }
1248 0 : (this->*fnRect->fnSetYMargins)( nUpper, 0 );
1249 : }
1250 :
1251 0 : if ( !mbValidSize )
1252 : {
1253 : PROTOCOL_ENTER( this, PROT_SIZE, 0, 0 )
1254 0 : const long nOldHeight = (Frm().*fnRect->fnGetHeight)();
1255 0 : sal_Bool bOldLock = IsColLocked();
1256 0 : ColLock();
1257 :
1258 0 : 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 0 : 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 0 : ExtraFormatToPositionObjs aExtraFormatToPosObjs( *this );
1273 0 : if ( !bMaximize &&
1274 0 : GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
1275 0 : !GetFmt()->GetBalancedColumns().GetValue() )
1276 : {
1277 0 : 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 0 : const bool bHasColumns = Lower() && Lower()->IsColumnFrm();
1284 0 : if ( bHasColumns && Lower()->GetNext() )
1285 0 : AdjustColumns( 0, sal_False );
1286 :
1287 0 : if( GetUpper() )
1288 : {
1289 0 : long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
1290 0 : (maFrm.*fnRect->fnSetWidth)( nWidth );
1291 :
1292 : // #109700# LRSpace for sections
1293 0 : const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
1294 0 : (maPrt.*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
1295 0 : 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 0 : const SwViewShell *pSh = getRootFrm()->GetCurrShell();
1301 0 : _CheckClipping( pSh && pSh->GetViewOptions()->getBrowseMode(), bMaximize );
1302 0 : bMaximize = ToMaximize( sal_False );
1303 0 : mbValidSize = sal_True;
1304 : }
1305 :
1306 : // Check the width of the columns and adjust if necessary
1307 0 : if ( bHasColumns && ! Lower()->GetNext() && bMaximize )
1308 0 : ((SwColumnFrm*)Lower())->Lower()->Calc();
1309 :
1310 0 : if ( !bMaximize )
1311 : {
1312 0 : SwTwips nRemaining = (this->*fnRect->fnGetTopMargin)();
1313 0 : SwFrm *pFrm = pLower;
1314 0 : if( pFrm )
1315 : {
1316 0 : if( pFrm->IsColumnFrm() && pFrm->GetNext() )
1317 : {
1318 : // #i61435#
1319 : // suppress formatting, if upper frame has height <= 0
1320 0 : if ( (GetUpper()->Frm().*fnRect->fnGetHeight)() > 0 )
1321 : {
1322 0 : FormatWidthCols( *pAttr, nRemaining, MINLAY );
1323 : }
1324 : // #126020# - adjust check for empty section
1325 : // #130797# - correct fix #126020#
1326 0 : 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 0 : bMaximize = ToMaximize( sal_False );
1335 0 : nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
1336 : }
1337 : else
1338 : {
1339 0 : if( pFrm->IsColumnFrm() )
1340 : {
1341 0 : pFrm->Calc();
1342 0 : pFrm = ((SwColumnFrm*)pFrm)->Lower();
1343 0 : pFrm->Calc();
1344 0 : pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1345 0 : CalcFtnCntnt();
1346 : }
1347 : // If we are in a columned frame which calls a CalcCntnt
1348 : // in the FormatWidthCols, the content might need calculating
1349 0 : if( pFrm && !pFrm->IsValid() && IsInFly() &&
1350 0 : FindFlyFrm()->IsColLocked() )
1351 0 : ::CalcCntnt( this );
1352 0 : nRemaining += InnerHeight();
1353 0 : bMaximize = HasFollow();
1354 : }
1355 : }
1356 :
1357 0 : SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
1358 0 : if( nDiff < 0)
1359 : {
1360 0 : SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1361 : {
1362 0 : long nBottom = (Frm().*fnRect->fnGetBottom)();
1363 0 : nBottom = (*fnRect->fnYInc)( nBottom, -nDiff );
1364 0 : long nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
1365 0 : if( nTmpDiff > 0 )
1366 : {
1367 0 : nTmpDiff = GetUpper()->Grow( nTmpDiff, sal_True );
1368 0 : nDeadLine = (*fnRect->fnYInc)( nDeadLine, nTmpDiff );
1369 0 : nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
1370 0 : if( nTmpDiff > 0 )
1371 0 : nDiff += nTmpDiff;
1372 0 : if( nDiff > 0 )
1373 0 : nDiff = 0;
1374 : }
1375 : }
1376 : }
1377 0 : if( nDiff )
1378 : {
1379 0 : long nTmp = nRemaining - (Frm().*fnRect->fnGetHeight)();
1380 0 : long nTop = (this->*fnRect->fnGetTopMargin)();
1381 0 : (Frm().*fnRect->fnAddBottom)( nTmp );
1382 0 : (this->*fnRect->fnSetYMargins)( nTop, 0 );
1383 0 : InvalidateNextPos();
1384 0 : 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 0 : pFrm = pLower;
1390 0 : if( pFrm->IsColumnFrm() )
1391 : {
1392 0 : pFrm->_InvalidateSize();
1393 0 : pFrm->_InvalidatePos();
1394 0 : pFrm->Calc();
1395 0 : pFrm = ((SwColumnFrm*)pFrm)->Lower();
1396 0 : pFrm->Calc();
1397 0 : pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1398 0 : CalcFtnCntnt();
1399 : }
1400 0 : bool bUnderSz = false;
1401 0 : while( pFrm )
1402 : {
1403 0 : if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
1404 : {
1405 0 : pFrm->Prepare( PREP_ADJUST_FRM );
1406 0 : bUnderSz = true;
1407 : }
1408 0 : pFrm = pFrm->GetNext();
1409 : }
1410 0 : 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 0 : if ( GetUpper() )
1419 0 : _CheckClipping( sal_True, bMaximize );
1420 0 : if( !bOldLock )
1421 0 : ColUnlock();
1422 0 : long nDiff = nOldHeight - (Frm().*fnRect->fnGetHeight)();
1423 0 : if( nDiff > 0 )
1424 : {
1425 0 : if( !GetNext() )
1426 0 : SetRetouche(); // Take over the retouching ourselves
1427 0 : if( GetUpper() && !GetUpper()->IsFooterFrm() )
1428 0 : GetUpper()->Shrink( nDiff );
1429 : }
1430 0 : if( IsUndersized() )
1431 0 : 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 0 : 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 0 : if( IsColBodyFrm() && GetUpper()->GetNext() )
1446 0 : return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetNext())->Lower();
1447 0 : if( GetUpper()->IsColBodyFrm() && GetUpper()->GetUpper()->GetNext() )
1448 0 : 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 0 : if( GetUpper()->IsInTab() || FindFooterOrHeader() )
1452 0 : return 0;
1453 :
1454 0 : SwSectionFrm *pSect = FindSctFrm();
1455 0 : 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 0 : if( pSect->HasFollow() && pSect->IsInDocBody() )
1463 : {
1464 0 : 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 0 : if( !pSect->GetUpper()->IsColBodyFrm() ||
1476 0 : 0 == ( pTmp = pSect->GetUpper()->GetUpper()->GetNext() ) )
1477 0 : pTmp = pSect->FindPageFrm()->GetNext();
1478 0 : if( pTmp ) // is now the next column or page
1479 : {
1480 0 : SwFrm* pTmpX = pTmp;
1481 0 : if( pTmp->IsPageFrm() && ((SwPageFrm*)pTmp)->IsEmptyPage() )
1482 0 : pTmp = pTmp->GetNext(); // skip dummy pages
1483 0 : 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 0 : if( !pUp->IsColBodyFrm() ||
1487 0 : !( pUp = pUp->GetUpper() )->GetPrev() )
1488 0 : 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 0 : if( pUp == pTmp || pUp->GetNext() == pTmpX )
1492 : {
1493 0 : SwPageFrm* pNxtPg = pUp->IsPageFrm() ?
1494 0 : (SwPageFrm*)pUp : pUp->FindPageFrm();
1495 0 : if( WrongPageDesc( pNxtPg ) )
1496 0 : bWrongPage = true;
1497 : else
1498 0 : return FIRSTLEAF( pSect->GetFollow() );
1499 : }
1500 : }
1501 : }
1502 : }
1503 :
1504 : // Always end up in the same section: Body again inside Body etc.
1505 0 : const sal_Bool bBody = IsInDocBody();
1506 0 : 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 0 : if( bWrongPage )
1511 0 : pLayLeaf = 0;
1512 0 : else if( IsTabFrm() )
1513 : {
1514 0 : SwCntntFrm* pTmpCnt = ((SwTabFrm*)this)->FindLastCntnt();
1515 0 : pLayLeaf = pTmpCnt ? pTmpCnt->GetUpper() : 0;
1516 : }
1517 : else
1518 : {
1519 0 : pLayLeaf = GetNextLayoutLeaf();
1520 0 : if( IsColumnFrm() )
1521 : {
1522 0 : while( pLayLeaf && ((SwColumnFrm*)this)->IsAnLower( pLayLeaf ) )
1523 0 : pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1524 : }
1525 : }
1526 :
1527 0 : 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 0 : 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 0 : SwPageFrm* pNxtPg = pLayLeaf->FindPageFrm();
1539 0 : if ( !bFtnPage && pNxtPg->IsFtnPage() )
1540 : { // If I reached the end note pages it's over
1541 0 : pLayLeaf = 0;
1542 0 : continue;
1543 : }
1544 : // Once inBody always inBody, don't step into tables and not into other sections
1545 0 : if ( (bBody && !pLayLeaf->IsInDocBody()) ||
1546 0 : (IsInFtn() != pLayLeaf->IsInFtn() ) ||
1547 0 : pLayLeaf->IsInTab() ||
1548 0 : ( pLayLeaf->IsInSct() && ( !pSect->HasFollow()
1549 0 : || pSect->GetFollow() != pLayLeaf->FindSctFrm() ) ) )
1550 : {
1551 : // Rejected - try again.
1552 0 : pOldLayLeaf = pLayLeaf;
1553 0 : pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1554 0 : continue;
1555 : }
1556 0 : if( WrongPageDesc( pNxtPg ) )
1557 : {
1558 0 : if( bWrongPage )
1559 0 : break; // there's a column between me and my right page
1560 0 : pLayLeaf = 0;
1561 0 : bWrongPage = true;
1562 0 : pOldLayLeaf = 0;
1563 0 : 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 0 : else if( !pSect->IsInFly() &&
1569 0 : ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
1570 : {
1571 0 : InsertPage(pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
1572 0 : sal_False );
1573 : // and again the whole thing
1574 0 : pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
1575 0 : continue;
1576 : }
1577 0 : break;
1578 : }
1579 :
1580 0 : 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 0 : SwFrm* pFirst = pLayLeaf->Lower();
1589 : // Here SectionFrms that are to be deleted must be ignored
1590 0 : while( pFirst && pFirst->IsSctFrm() && !((SwSectionFrm*)pFirst)->GetSection() )
1591 0 : pFirst = pFirst->GetNext();
1592 0 : if( pFirst && pFirst->IsSctFrm() && pSect->GetFollow() == pFirst )
1593 0 : pNew = pSect->GetFollow();
1594 0 : else if( MAKEPAGE_NOSECTION == eMakePage )
1595 0 : return pLayLeaf;
1596 : else
1597 : {
1598 0 : pNew = new SwSectionFrm( *pSect, sal_False );
1599 0 : pNew->InsertBefore( pLayLeaf, pLayLeaf->Lower() );
1600 0 : pNew->Init();
1601 0 : SWRECTFN( pNew )
1602 0 : (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 0 : SwFrm* pTmp = pSect->GetNext();
1607 0 : if( pTmp && pTmp != pSect->GetFollow() )
1608 : {
1609 : SwFlowFrm* pNxt;
1610 0 : SwCntntFrm* pNxtCntnt = NULL;
1611 0 : if( pTmp->IsCntntFrm() )
1612 : {
1613 0 : pNxt = (SwCntntFrm*)pTmp;
1614 0 : pNxtCntnt = (SwCntntFrm*)pTmp;
1615 : }
1616 : else
1617 : {
1618 0 : pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
1619 0 : if( pTmp->IsSctFrm() )
1620 0 : pNxt = (SwSectionFrm*)pTmp;
1621 : else
1622 : {
1623 : OSL_ENSURE( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
1624 0 : pNxt = (SwTabFrm*)pTmp;
1625 : }
1626 0 : 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 0 : if( pNxtCntnt )
1635 : {
1636 0 : SwFtnBossFrm* pOldBoss = pSect->FindFtnBossFrm( sal_True );
1637 0 : if( pOldBoss == pNxtCntnt->FindFtnBossFrm( sal_True ) )
1638 : {
1639 : SwSaveFtnHeight aHeight( pOldBoss,
1640 0 : pOldBoss->Frm().Top() + pOldBoss->Frm().Height() );
1641 : pSect->GetUpper()->MoveLowerFtns( pNxtCntnt, pOldBoss,
1642 0 : pLayLeaf->FindFtnBossFrm( sal_True ), sal_False );
1643 : }
1644 : }
1645 0 : ((SwFlowFrm*)pNxt)->MoveSubTree( pLayLeaf, pNew->GetNext() );
1646 : }
1647 0 : if( pNew->GetFollow() )
1648 0 : pNew->SimpleFormat();
1649 : }
1650 : // The wanted layout sheet is now the first of the determined SctFrms:
1651 0 : pLayLeaf = FIRSTLEAF( pNew );
1652 : }
1653 0 : return pLayLeaf;
1654 : }
1655 :
1656 : /// Returns the preceding layout sheet where the frame can be moved into
1657 0 : 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 0 : if( IsColBodyFrm() )
1664 0 : pCol = GetUpper();
1665 0 : else if( GetUpper()->IsColBodyFrm() )
1666 0 : pCol = GetUpper()->GetUpper();
1667 : else
1668 0 : pCol = NULL;
1669 0 : bool bJump = false;
1670 0 : if( pCol )
1671 : {
1672 0 : if( pCol->GetPrev() )
1673 : {
1674 0 : do
1675 : {
1676 0 : pCol = (SwLayoutFrm*)pCol->GetPrev();
1677 : // Is there any content?
1678 0 : if( ((SwLayoutFrm*)pCol->Lower())->Lower() )
1679 : {
1680 0 : if( bJump ) // Did we skip a blank page?
1681 0 : SwFlowFrm::SetMoveBwdJump( sal_True );
1682 0 : return (SwLayoutFrm*)pCol->Lower(); // The columnm body
1683 : }
1684 0 : bJump = true;
1685 0 : } 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 0 : pCol = (SwLayoutFrm*)pCol->Lower();
1690 : }
1691 : else
1692 0 : pCol = NULL;
1693 : }
1694 :
1695 0 : if( bJump ) // Did we skip a blank page?
1696 0 : 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 0 : 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 0 : 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 0 : if ( IsTabFrm() && pSect->IsInTab() )
1718 : {
1719 0 : return pCol;
1720 : }
1721 :
1722 : {
1723 : SwFrm *pPrv;
1724 0 : if( 0 != ( pPrv = pSect->GetIndPrev() ) )
1725 : {
1726 : // Mooching, half dead SectionFrms shouldn't confuse us
1727 0 : while( pPrv && pPrv->IsSctFrm() && !((SwSectionFrm*)pPrv)->GetSection() )
1728 0 : pPrv = pPrv->GetPrev();
1729 0 : if( pPrv )
1730 0 : return pCol;
1731 : }
1732 : }
1733 :
1734 0 : const sal_Bool bBody = IsInDocBody();
1735 0 : const sal_Bool bFly = IsInFly();
1736 :
1737 0 : SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
1738 0 : SwLayoutFrm *pPrevLeaf = 0;
1739 :
1740 0 : while ( pLayLeaf )
1741 : {
1742 : // Never step into tables or sections
1743 0 : if ( pLayLeaf->IsInTab() || pLayLeaf->IsInSct() )
1744 : {
1745 0 : pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1746 : }
1747 0 : 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 0 : 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 0 : while ( pTmp && pTmp->IsSctFrm() &&
1756 0 : !( static_cast<const SwSectionFrm*>(pTmp)->GetSection() ) &&
1757 0 : pTmp->GetNext()
1758 : )
1759 : {
1760 0 : pTmp = pTmp->GetNext();
1761 : }
1762 0 : if ( pTmp &&
1763 0 : ( !pTmp->IsSctFrm() ||
1764 0 : ( static_cast<const SwSectionFrm*>(pTmp)->GetSection() )
1765 : )
1766 : )
1767 : {
1768 0 : break;
1769 : }
1770 0 : pPrevLeaf = pLayLeaf;
1771 0 : pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1772 0 : if ( pLayLeaf )
1773 0 : SwFlowFrm::SetMoveBwdJump( sal_True );
1774 : }
1775 0 : else if ( bFly )
1776 0 : break; // Cntnts in Flys every layout sheet should be right. Why?
1777 : else
1778 0 : pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1779 : }
1780 0 : if( !pLayLeaf )
1781 : {
1782 0 : if( !pPrevLeaf )
1783 0 : return pCol;
1784 0 : pLayLeaf = pPrevLeaf;
1785 : }
1786 :
1787 0 : SwSectionFrm* pNew = NULL;
1788 : // At first go to the end of the layout sheet
1789 0 : SwFrm *pTmp = pLayLeaf->Lower();
1790 0 : if( pTmp )
1791 : {
1792 0 : while( pTmp->GetNext() )
1793 0 : pTmp = pTmp->GetNext();
1794 0 : if( pTmp->IsSctFrm() )
1795 : {
1796 : // Half dead ones only interfere here
1797 0 : while( !((SwSectionFrm*)pTmp)->GetSection() && pTmp->GetPrev() &&
1798 0 : pTmp->GetPrev()->IsSctFrm() )
1799 0 : pTmp = pTmp->GetPrev();
1800 0 : if( ((SwSectionFrm*)pTmp)->GetFollow() == pSect )
1801 0 : pNew = (SwSectionFrm*)pTmp;
1802 : }
1803 : }
1804 0 : if( !pNew )
1805 : {
1806 0 : pNew = new SwSectionFrm( *pSect, sal_True );
1807 0 : pNew->InsertBefore( pLayLeaf, NULL );
1808 0 : pNew->Init();
1809 0 : SWRECTFN( pNew )
1810 0 : (pNew->*fnRect->fnMakePos)( pLayLeaf, pNew->GetPrev(), sal_True );
1811 :
1812 0 : pLayLeaf = FIRSTLEAF( pNew );
1813 0 : if( !pNew->Lower() ) // Format single column sections
1814 : {
1815 0 : pNew->MakePos();
1816 0 : pLayLeaf->Format(); // In order that the PrtArea is correct for the MoveBwd
1817 : }
1818 : else
1819 0 : pNew->SimpleFormat();
1820 : }
1821 : else
1822 : {
1823 0 : pLayLeaf = FIRSTLEAF( pNew );
1824 0 : if( pLayLeaf->IsColBodyFrm() )
1825 : {
1826 : // In existent section columns we're looking for the last not empty
1827 : // column.
1828 0 : SwLayoutFrm *pTmpLay = pLayLeaf;
1829 0 : while( pLayLeaf->GetUpper()->GetNext() )
1830 : {
1831 0 : pLayLeaf = (SwLayoutFrm*)((SwLayoutFrm*)pLayLeaf->GetUpper()->GetNext())->Lower();
1832 0 : if( pLayLeaf->Lower() )
1833 0 : pTmpLay = pLayLeaf;
1834 : }
1835 : // If we skipped an empty column, we've to set the jump-flag
1836 0 : if( pLayLeaf != pTmpLay )
1837 : {
1838 0 : pLayLeaf = pTmpLay;
1839 0 : SwFlowFrm::SetMoveBwdJump( sal_True );
1840 : }
1841 : }
1842 : }
1843 0 : return pLayLeaf;
1844 : }
1845 :
1846 0 : static SwTwips lcl_DeadLine( const SwFrm* pFrm )
1847 : {
1848 0 : const SwLayoutFrm* pUp = pFrm->GetUpper();
1849 0 : 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 0 : SWRECTFN( pFrm )
1860 0 : return pUp ? (pUp->*fnRect->fnGetPrtBottom)() :
1861 0 : (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 0 : sal_Bool SwSectionFrm::Growable() const
1866 : {
1867 0 : SWRECTFN( this )
1868 0 : if( (*fnRect->fnYDiff)( lcl_DeadLine( this ),
1869 0 : (Frm().*fnRect->fnGetBottom)() ) > 0 )
1870 0 : return sal_True;
1871 :
1872 0 : return ( GetUpper() && ((SwFrm*)GetUpper())->Grow( LONG_MAX, sal_True ) );
1873 : }
1874 :
1875 0 : SwTwips SwSectionFrm::_Grow( SwTwips nDist, sal_Bool bTst )
1876 : {
1877 0 : if ( !IsColLocked() && !HasFixSize() )
1878 : {
1879 0 : SWRECTFN( this )
1880 0 : long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
1881 0 : if( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
1882 0 : nDist = LONG_MAX - nFrmHeight;
1883 :
1884 0 : if ( nDist <= 0L )
1885 0 : return 0L;
1886 :
1887 0 : bool bInCalcCntnt = GetUpper() && IsInFly() && FindFlyFrm()->IsLocked();
1888 : // OD 2004-03-15 #116561# - allow grow in online layout
1889 0 : bool bGrow = !Lower() || !Lower()->IsColumnFrm() || !Lower()->GetNext() ||
1890 0 : GetSection()->GetFmt()->GetBalancedColumns().GetValue();
1891 0 : if( !bGrow )
1892 : {
1893 0 : const SwViewShell *pSh = getRootFrm()->GetCurrShell();
1894 0 : bGrow = pSh && pSh->GetViewOptions()->getBrowseMode();
1895 : }
1896 0 : if( bGrow )
1897 : {
1898 : SwTwips nGrow;
1899 0 : if( IsInFtn() )
1900 0 : nGrow = 0;
1901 : else
1902 : {
1903 0 : nGrow = lcl_DeadLine( this );
1904 : nGrow = (*fnRect->fnYDiff)( nGrow,
1905 0 : (Frm().*fnRect->fnGetBottom)() );
1906 : }
1907 0 : SwTwips nSpace = nGrow;
1908 0 : if( !bInCalcCntnt && nGrow < nDist && GetUpper() )
1909 0 : nGrow += GetUpper()->Grow( LONG_MAX, sal_True );
1910 :
1911 0 : if( nGrow > nDist )
1912 0 : nGrow = nDist;
1913 0 : if( nGrow <= 0 )
1914 : {
1915 0 : nGrow = 0;
1916 0 : if( nDist && !bTst )
1917 : {
1918 0 : if( bInCalcCntnt )
1919 0 : _InvalidateSize();
1920 : else
1921 0 : InvalidateSize();
1922 : }
1923 : }
1924 0 : else if( !bTst )
1925 : {
1926 0 : if( bInCalcCntnt )
1927 0 : _InvalidateSize();
1928 0 : else if( nSpace < nGrow && nDist != nSpace + GetUpper()->
1929 0 : Grow( nGrow - nSpace, sal_False ) )
1930 0 : InvalidateSize();
1931 : else
1932 : {
1933 : const SvxGraphicPosition ePos =
1934 0 : GetAttrSet()->GetBackground().GetGraphicPos();
1935 0 : if ( GPOS_RT < ePos && GPOS_TILED != ePos )
1936 : {
1937 0 : SetCompletePaint();
1938 0 : InvalidatePage();
1939 : }
1940 0 : if( GetUpper() && GetUpper()->IsHeaderFrm() )
1941 0 : GetUpper()->InvalidateSize();
1942 : }
1943 0 : (Frm().*fnRect->fnAddBottom)( nGrow );
1944 0 : long nPrtHeight = (Prt().*fnRect->fnGetHeight)() + nGrow;
1945 0 : (Prt().*fnRect->fnSetHeight)( nPrtHeight );
1946 :
1947 0 : if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
1948 : {
1949 0 : SwFrm* pTmp = Lower();
1950 0 : do
1951 : {
1952 0 : pTmp->_InvalidateSize();
1953 0 : pTmp = pTmp->GetNext();
1954 : } while ( pTmp );
1955 0 : _InvalidateSize();
1956 : }
1957 0 : if( GetNext() )
1958 : {
1959 0 : SwFrm *pFrm = GetNext();
1960 0 : while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
1961 0 : pFrm = pFrm->GetNext();
1962 0 : if( pFrm )
1963 : {
1964 0 : if( bInCalcCntnt )
1965 0 : pFrm->_InvalidatePos();
1966 : else
1967 0 : 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 0 : else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
1976 : {
1977 0 : InvalidateNextPos();
1978 : }
1979 : }
1980 0 : return nGrow;
1981 : }
1982 0 : if ( !bTst )
1983 : {
1984 0 : if( bInCalcCntnt )
1985 0 : _InvalidateSize();
1986 : else
1987 0 : InvalidateSize();
1988 : }
1989 : }
1990 0 : return 0L;
1991 : }
1992 :
1993 0 : SwTwips SwSectionFrm::_Shrink( SwTwips nDist, sal_Bool bTst )
1994 : {
1995 0 : if ( Lower() && !IsColLocked() && !HasFixSize() )
1996 : {
1997 0 : if( ToMaximize( sal_False ) )
1998 : {
1999 0 : if( !bTst )
2000 0 : InvalidateSize();
2001 : }
2002 : else
2003 : {
2004 0 : SWRECTFN( this )
2005 0 : long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2006 0 : if ( nDist > nFrmHeight )
2007 0 : nDist = nFrmHeight;
2008 :
2009 0 : if ( Lower()->IsColumnFrm() && Lower()->GetNext() && // FtnAtEnd
2010 0 : !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 0 : else if( !bTst )
2018 : {
2019 : const SvxGraphicPosition ePos =
2020 0 : GetAttrSet()->GetBackground().GetGraphicPos();
2021 0 : if ( GPOS_RT < ePos && GPOS_TILED != ePos )
2022 : {
2023 0 : SetCompletePaint();
2024 0 : InvalidatePage();
2025 : }
2026 0 : (Frm().*fnRect->fnAddBottom)( -nDist );
2027 0 : long nPrtHeight = (Prt().*fnRect->fnGetHeight)() - nDist;
2028 0 : (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 0 : if( GetUpper() && !GetUpper()->IsFooterFrm() )
2045 0 : GetUpper()->Shrink( nDist, bTst );
2046 :
2047 0 : if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2048 : {
2049 0 : SwFrm* pTmp = Lower();
2050 0 : do
2051 : {
2052 0 : pTmp->_InvalidateSize();
2053 0 : pTmp = pTmp->GetNext();
2054 : } while ( pTmp );
2055 : }
2056 0 : if( GetNext() )
2057 : {
2058 0 : SwFrm* pFrm = GetNext();
2059 0 : while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
2060 0 : pFrm = pFrm->GetNext();
2061 0 : if( pFrm )
2062 0 : pFrm->InvalidatePos();
2063 : else
2064 0 : SetRetouche();
2065 : }
2066 : else
2067 0 : SetRetouche();
2068 0 : return nDist;
2069 : }
2070 : }
2071 : }
2072 0 : 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 0 : sal_Bool SwSectionFrm::MoveAllowed( const SwFrm* pFrm) const
2089 : {
2090 : // Is there a Follow or is the Frame not in the last column?
2091 0 : if( HasFollow() || ( pFrm->GetUpper()->IsColBodyFrm() &&
2092 0 : pFrm->GetUpper()->GetUpper()->GetNext() ) )
2093 0 : return sal_True;
2094 0 : if( pFrm->IsInFtn() )
2095 : {
2096 0 : 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 0 : const SwLayoutFrm *pLay = pFrm->FindFtnFrm()->GetUpper()->GetUpper();
2110 0 : 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 0 : bool bRet = false;
2116 0 : if( pLay->GetIndPrev() || pFrm->GetIndPrev() ||
2117 0 : pFrm->FindFtnFrm()->GetPrev() )
2118 0 : bRet = true;
2119 : else
2120 : {
2121 0 : SwLayoutFrm* pBody = ((SwColumnFrm*)pLay)->FindBodyCont();
2122 0 : if( pBody && pBody->Lower() )
2123 0 : bRet = true;
2124 : }
2125 0 : if( bRet && ( IsFtnAtEnd() || !Growable() ) )
2126 0 : return sal_True;
2127 : }
2128 : }
2129 : // Or can the section still grow?
2130 0 : if( !IsColLocked() && Growable() )
2131 0 : 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 0 : if( IsInTab() || ( !IsInDocBody() && FindFooterOrHeader() ) )
2135 0 : return sal_False; // It doesn't work in tables/headers/footers
2136 0 : if( IsInFly() ) // In column based or chained frames
2137 0 : return 0 != ((SwFrm*)GetUpper())->GetNextLeaf( MAKEPAGE_NONE );
2138 0 : 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 0 : SwFrm* SwFrm::_GetIndPrev() const
2149 : {
2150 0 : 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 0 : const SwFrm* pSct = GetUpper();
2158 0 : if( !pSct )
2159 0 : return NULL;
2160 0 : if( pSct->IsSctFrm() )
2161 0 : pRet = pSct->GetIndPrev();
2162 0 : 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 0 : const SwFrm* pCol = GetUpper()->GetUpper()->GetPrev();
2167 0 : 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 0 : if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
2173 0 : return NULL;
2174 0 : pCol = pCol->GetPrev();
2175 : }
2176 0 : pRet = pSct->GetIndPrev();
2177 : }
2178 :
2179 : // skip empty section frames
2180 0 : while( pRet && pRet->IsSctFrm() && !((SwSectionFrm*)pRet)->GetSection() )
2181 0 : pRet = pRet->GetIndPrev();
2182 0 : return pRet;
2183 : }
2184 :
2185 0 : SwFrm* SwFrm::_GetIndNext()
2186 : {
2187 : OSL_ENSURE( !mpNext && IsInSct(), "Why?" );
2188 0 : SwFrm* pSct = GetUpper();
2189 0 : if( !pSct )
2190 0 : return NULL;
2191 0 : if( pSct->IsSctFrm() )
2192 0 : return pSct->GetIndNext();
2193 0 : 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 0 : SwFrm* pCol = GetUpper()->GetUpper()->GetNext();
2197 0 : 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 0 : if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
2203 0 : return NULL;
2204 0 : pCol = pCol->GetNext();
2205 : }
2206 0 : return pSct->GetIndNext();
2207 : }
2208 0 : 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 0 : void SwSectionFrm::CalcFtnAtEndFlag()
2227 : {
2228 0 : SwSectionFmt *pFmt = GetSection()->GetFmt();
2229 0 : sal_uInt16 nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
2230 0 : bFtnAtEnd = FTNEND_ATPGORDOCEND != nVal;
2231 0 : bOwnFtnNum = FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
2232 0 : FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
2233 0 : while( !bFtnAtEnd && !bOwnFtnNum )
2234 : {
2235 0 : if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2236 0 : pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
2237 : else
2238 0 : break;
2239 0 : nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
2240 0 : if( FTNEND_ATPGORDOCEND != nVal )
2241 : {
2242 0 : bFtnAtEnd = true;
2243 0 : bOwnFtnNum = bOwnFtnNum ||FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
2244 0 : FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
2245 : }
2246 : }
2247 0 : }
2248 :
2249 0 : bool SwSectionFrm::IsEndnoteAtMyEnd() const
2250 : {
2251 0 : return pSection->GetFmt()->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2252 : }
2253 :
2254 0 : void SwSectionFrm::CalcEndAtEndFlag()
2255 : {
2256 0 : SwSectionFmt *pFmt = GetSection()->GetFmt();
2257 0 : bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2258 0 : while( !bEndnAtEnd )
2259 : {
2260 0 : if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2261 0 : pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
2262 : else
2263 0 : break;
2264 0 : bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2265 : }
2266 0 : }
2267 :
2268 0 : void SwSectionFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
2269 : {
2270 0 : sal_uInt8 nInvFlags = 0;
2271 :
2272 0 : if( pNew && RES_ATTRSET_CHG == pNew->Which() )
2273 : {
2274 0 : SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
2275 0 : SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
2276 0 : SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
2277 0 : SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
2278 : while( true )
2279 : {
2280 : _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
2281 : (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
2282 0 : &aOldSet, &aNewSet );
2283 0 : if( aNIter.IsAtEnd() )
2284 0 : break;
2285 0 : aNIter.NextItem();
2286 0 : aOIter.NextItem();
2287 : }
2288 0 : if ( aOldSet.Count() || aNewSet.Count() )
2289 0 : SwLayoutFrm::Modify( &aOldSet, &aNewSet );
2290 : }
2291 : else
2292 0 : _UpdateAttr( pOld, pNew, nInvFlags );
2293 :
2294 0 : if ( nInvFlags != 0 )
2295 : {
2296 0 : if ( nInvFlags & 0x01 )
2297 0 : InvalidateSize();
2298 0 : if ( nInvFlags & 0x10 )
2299 0 : SetCompletePaint();
2300 : }
2301 0 : }
2302 :
2303 0 : void SwSectionFrm::SwClientNotify( const SwModify& rMod, const SfxHint& rHint )
2304 : {
2305 : // #i117863#
2306 : const SwSectionFrmMoveAndDeleteHint* pHint =
2307 0 : dynamic_cast<const SwSectionFrmMoveAndDeleteHint*>(&rHint);
2308 0 : if ( pHint && pHint->GetId() == SFX_HINT_DYING && &rMod == GetRegisteredIn() )
2309 : {
2310 0 : SwSectionFrm::MoveCntntAndDelete( this, pHint->IsSaveCntnt() );
2311 : }
2312 0 : }
2313 :
2314 0 : void SwSectionFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
2315 : sal_uInt8 &rInvFlags,
2316 : SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
2317 : {
2318 0 : bool bClear = true;
2319 0 : const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
2320 0 : switch( nWhich )
2321 : { // Suppress multi columns in foot notes
2322 : case RES_FMT_CHG:
2323 : {
2324 0 : const SwFmtCol& rNewCol = GetFmt()->GetCol();
2325 0 : 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 0 : SwFmtCol aCol;
2331 0 : 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 0 : bool bChgFtn = IsFtnAtEnd();
2342 0 : bool const bChgEndn = IsEndnAtEnd();
2343 0 : bool const bChgMyEndn = IsEndnoteAtMyEnd();
2344 0 : CalcFtnAtEndFlag();
2345 0 : CalcEndAtEndFlag();
2346 0 : bChgFtn = ( bChgFtn != IsFtnAtEnd() ) ||
2347 0 : ( bChgEndn != IsEndnAtEnd() ) ||
2348 0 : ( bChgMyEndn != IsEndnoteAtMyEnd() );
2349 0 : ChgColumns( aCol, rNewCol, bChgFtn );
2350 0 : rInvFlags |= 0x10;
2351 : }
2352 0 : rInvFlags |= 0x01;
2353 0 : bClear = false;
2354 : }
2355 0 : break;
2356 :
2357 : case RES_COL:
2358 0 : if( !IsInFtn() )
2359 : {
2360 : assert(pOld && pNew);
2361 0 : if (pOld && pNew)
2362 : {
2363 0 : ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
2364 0 : rInvFlags |= 0x11;
2365 : }
2366 : }
2367 0 : break;
2368 :
2369 : case RES_FTN_AT_TXTEND:
2370 0 : if( !IsInFtn() )
2371 : {
2372 0 : bool const bOld = IsFtnAtEnd();
2373 0 : CalcFtnAtEndFlag();
2374 0 : if (bOld != IsFtnAtEnd())
2375 : {
2376 0 : const SwFmtCol& rNewCol = GetFmt()->GetCol();
2377 0 : ChgColumns( rNewCol, rNewCol, sal_True );
2378 0 : rInvFlags |= 0x01;
2379 : }
2380 : }
2381 0 : break;
2382 :
2383 : case RES_END_AT_TXTEND:
2384 0 : if( !IsInFtn() )
2385 : {
2386 0 : bool const bOld = IsEndnAtEnd();
2387 0 : bool const bMyOld = IsEndnoteAtMyEnd();
2388 0 : CalcEndAtEndFlag();
2389 0 : if (bOld != IsEndnAtEnd() || bMyOld != IsEndnoteAtMyEnd())
2390 : {
2391 0 : const SwFmtCol& rNewCol = GetFmt()->GetCol();
2392 0 : ChgColumns( rNewCol, rNewCol, sal_True );
2393 0 : rInvFlags |= 0x01;
2394 : }
2395 : }
2396 0 : break;
2397 : case RES_COLUMNBALANCE:
2398 0 : rInvFlags |= 0x01;
2399 0 : break;
2400 :
2401 : case RES_FRAMEDIR :
2402 0 : SetDerivedR2L( sal_False );
2403 0 : CheckDirChange();
2404 0 : break;
2405 :
2406 : case RES_PROTECT:
2407 : {
2408 0 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
2409 0 : if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
2410 0 : pSh->Imp()->InvalidateAccessibleEditableState( true, this );
2411 : }
2412 0 : break;
2413 :
2414 : default:
2415 0 : bClear = false;
2416 : }
2417 0 : if ( bClear )
2418 : {
2419 0 : if ( pOldSet || pNewSet )
2420 : {
2421 0 : if ( pOldSet )
2422 0 : pOldSet->ClearItem( nWhich );
2423 0 : if ( pNewSet )
2424 0 : pNewSet->ClearItem( nWhich );
2425 : }
2426 : else
2427 0 : SwLayoutFrm::Modify( pOld, pNew );
2428 : }
2429 0 : }
2430 :
2431 : /// A follow or a ftncontainer at the end of the page causes a maximal Size of the sectionframe.
2432 0 : sal_Bool SwSectionFrm::ToMaximize( sal_Bool bCheckFollow ) const
2433 : {
2434 0 : if( HasFollow() )
2435 : {
2436 0 : if( !bCheckFollow ) // Don't check superfluous follows
2437 0 : return sal_True;
2438 0 : const SwSectionFrm* pFoll = GetFollow();
2439 0 : while( pFoll && pFoll->IsSuperfluous() )
2440 0 : pFoll = pFoll->GetFollow();
2441 0 : if( pFoll )
2442 0 : return sal_True;
2443 : }
2444 0 : if( IsFtnAtEnd() )
2445 0 : return sal_False;
2446 0 : const SwFtnContFrm* pCont = ContainsFtnCont();
2447 0 : if( !IsEndnAtEnd() )
2448 0 : return 0 != pCont;
2449 0 : sal_Bool bRet = sal_False;
2450 0 : while( pCont && !bRet )
2451 : {
2452 0 : if( pCont->FindFootNote() )
2453 0 : bRet = sal_True;
2454 : else
2455 0 : pCont = ContainsFtnCont( pCont );
2456 : }
2457 0 : return bRet;
2458 : }
2459 :
2460 : /// Check every Column for FtnContFrms.
2461 0 : SwFtnContFrm* SwSectionFrm::ContainsFtnCont( const SwFtnContFrm* pCont ) const
2462 : {
2463 0 : SwFtnContFrm* pRet = NULL;
2464 : const SwLayoutFrm* pLay;
2465 0 : 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 0 : else if( Lower() && Lower()->IsColumnFrm() )
2472 0 : pLay = (SwLayoutFrm*)Lower();
2473 : else
2474 0 : pLay = NULL;
2475 0 : while ( !pRet && pLay )
2476 : {
2477 0 : if( pLay->Lower() && pLay->Lower()->GetNext() )
2478 : {
2479 : OSL_ENSURE( pLay->Lower()->GetNext()->IsFtnContFrm(),
2480 : "ToMaximize: Unexspected Frame" );
2481 0 : pRet = (SwFtnContFrm*)pLay->Lower()->GetNext();
2482 : }
2483 : OSL_ENSURE( !pLay->GetNext() || pLay->GetNext()->IsLayoutFrm(),
2484 : "ToMaximize: ColFrm exspected" );
2485 0 : pLay = (SwLayoutFrm*)pLay->GetNext();
2486 : }
2487 0 : return pRet;
2488 : }
2489 :
2490 0 : void SwSectionFrm::InvalidateFtnPos()
2491 : {
2492 0 : SwFtnContFrm* pCont = ContainsFtnCont( NULL );
2493 0 : if( pCont )
2494 : {
2495 0 : SwFrm *pTmp = pCont->ContainsCntnt();
2496 0 : if( pTmp )
2497 0 : pTmp->_InvalidatePos();
2498 : }
2499 0 : }
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 0 : long SwSectionFrm::Undersize( sal_Bool bOverSize )
2507 : {
2508 0 : m_bUndersized = sal_False;
2509 0 : SWRECTFN( this )
2510 0 : long nRet = InnerHeight() - (Prt().*fnRect->fnGetHeight)();
2511 0 : if( nRet > 0 )
2512 0 : m_bUndersized = sal_True;
2513 0 : else if( !bOverSize )
2514 0 : nRet = 0;
2515 0 : 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 0 : void SwSectionFrm::CalcFtnCntnt()
2524 : {
2525 0 : SwFtnContFrm* pCont = ContainsFtnCont();
2526 0 : if( pCont )
2527 : {
2528 0 : SwFrm* pFrm = pCont->ContainsAny();
2529 0 : if( pFrm )
2530 0 : pCont->Calc();
2531 0 : while( pFrm && IsAnLower( pFrm ) )
2532 : {
2533 0 : SwFtnFrm* pFtn = pFrm->FindFtnFrm();
2534 0 : if( pFtn )
2535 0 : pFtn->Calc();
2536 : // OD 01.04.2003 #108446# - determine next frame before format current frame.
2537 0 : SwFrm* pNextFrm = 0;
2538 : {
2539 0 : if( pFrm->IsSctFrm() )
2540 : {
2541 0 : pNextFrm = static_cast<SwSectionFrm*>(pFrm)->ContainsAny();
2542 : }
2543 0 : if( !pNextFrm )
2544 : {
2545 0 : pNextFrm = pFrm->FindNext();
2546 : }
2547 : }
2548 0 : pFrm->Calc();
2549 0 : pFrm = pNextFrm;
2550 : }
2551 : }
2552 0 : }
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 0 : void SwRootFrm::InsertEmptySct( SwSectionFrm* pDel )
2567 : {
2568 0 : if( !pDestroy )
2569 0 : pDestroy = new SwDestroyList;
2570 0 : pDestroy->insert( pDel );
2571 0 : }
2572 :
2573 0 : void SwRootFrm::_DeleteEmptySct()
2574 : {
2575 : OSL_ENSURE( pDestroy, "Keine Liste, keine Kekse" );
2576 0 : while( !pDestroy->empty() )
2577 : {
2578 0 : SwSectionFrm* pSect = *pDestroy->begin();
2579 0 : pDestroy->erase( pDestroy->begin() );
2580 : OSL_ENSURE( !pSect->IsColLocked() && !pSect->IsJoinLocked(),
2581 : "DeleteEmptySct: Locked SectionFrm" );
2582 0 : if( !pSect->Frm().HasArea() && !pSect->ContainsCntnt() )
2583 : {
2584 0 : SwLayoutFrm* pUp = pSect->GetUpper();
2585 0 : pSect->Remove();
2586 0 : delete pSect;
2587 0 : if( pUp && !pUp->Lower() )
2588 : {
2589 0 : if( pUp->IsPageBodyFrm() )
2590 0 : pUp->getRootFrm()->SetSuperfluous();
2591 0 : 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 0 : }
2604 :
2605 0 : void SwRootFrm::_RemoveFromList( SwSectionFrm* pSct )
2606 : {
2607 : OSL_ENSURE( pDestroy, "Where's my list?" );
2608 0 : pDestroy->erase( pSct );
2609 0 : }
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 0 : bool SwSectionFrm::IsBalancedSection() const
2619 : {
2620 0 : bool bRet = false;
2621 0 : if ( GetSection() && Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2622 : {
2623 0 : bRet = !GetSection()->GetFmt()->GetBalancedColumns().GetValue();
2624 : }
2625 0 : return bRet;
2626 : }
2627 :
2628 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|