1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27 #include <svl/smplhint.hxx>
28 #include <svl/itemiter.hxx>
29 #include <hints.hxx>
30 #include <txtftn.hxx>
31 #include <fmtftn.hxx>
32 #include <fmtclbl.hxx>
33 #include "sectfrm.hxx"
34 #include "section.hxx" // SwSection
35 #include "frmtool.hxx" // StackHack
36 #include "doc.hxx" // SwDoc
37 #include "cntfrm.hxx" // SwCntntFrm
38 #include "rootfrm.hxx" // SwRootFrm
39 #include "pagefrm.hxx" // SwPageFrm
40 #include "fmtpdsc.hxx" // SwFmtPageDesc
41 #include "fmtcntnt.hxx" // SwFmtCntnt
42 #include "ndindex.hxx" // SwNodeIndex
43 #include "ftnidx.hxx"
44 #include "txtfrm.hxx" // SwTxtFrm
45 #include "fmtclds.hxx" // SwFmtCol
46 #include "colfrm.hxx" // SwColumnFrm
47 #include "tabfrm.hxx" // SwTabFrm
48 #include "flyfrm.hxx" // SwFlyFrm
49 #include "ftnfrm.hxx" // SwFtnFrm
50 #include "layouter.hxx" // SwLayouter
51 #include "dbg_lay.hxx"
52 #include "viewsh.hxx"
53 #include "viewopt.hxx"
54 #include "viewimp.hxx"
55 #include <editeng/ulspitem.hxx>
56 #include <editeng/lrspitem.hxx>
57 #include <editeng/brshitem.hxx>
58 #include <fmtftntx.hxx>
59 // OD 2004-05-24 #i28701#
60 #include <dflyobj.hxx>
61 #include <flyfrms.hxx>
62 #include <sortedobjs.hxx>
63
SV_IMPL_PTRARR_SORT(SwDestroyList,SwSectionFrmPtr)64 SV_IMPL_PTRARR_SORT( SwDestroyList, SwSectionFrmPtr )
65
66 /*************************************************************************
67 |*
68 |* SwSectionFrm::SwSectionFrm(), ~SwSectionFrm()
69 |*
70 |* Ersterstellung AMA 26. Nov. 97
71 |* Letzte Aenderung AMA 26. Nov. 97
72 |*
73 |*************************************************************************/
74 SwSectionFrm::SwSectionFrm( SwSection &rSect, SwFrm* pSib ) :
75 SwLayoutFrm( rSect.GetFmt(), pSib ),
76 SwFlowFrm( (SwFrm&)*this ),
77 pSection( &rSect )
78 {
79 nType = FRMC_SECTION;
80
81 CalcFtnAtEndFlag();
82 CalcEndAtEndFlag();
83 }
84
SwSectionFrm(SwSectionFrm & rSect,sal_Bool bMaster)85 SwSectionFrm::SwSectionFrm( SwSectionFrm &rSect, sal_Bool bMaster ) :
86 SwLayoutFrm( rSect.GetFmt(), rSect.getRootFrm() ),
87 SwFlowFrm( (SwFrm&)*this ),
88 pSection( rSect.GetSection() )
89 {
90 bFtnAtEnd = rSect.IsFtnAtEnd();
91 bEndnAtEnd = rSect.IsEndnAtEnd();
92 bLockJoin = sal_False;
93 nType = FRMC_SECTION;
94
95 PROTOCOL( this, PROT_SECTION, bMaster ? ACT_CREATE_MASTER : ACT_CREATE_FOLLOW, &rSect )
96
97 if( bMaster )
98 {
99 if( rSect.IsFollow() )
100 {
101 SwSectionFrm* pMaster = rSect.FindMaster();
102 pMaster->SetFollow( this );
103 bIsFollow = sal_True;
104 }
105 else
106 rSect.bIsFollow = sal_True;
107 SetFollow( &rSect );
108 }
109 else
110 {
111 bIsFollow = sal_True;
112 SetFollow( rSect.GetFollow() );
113 rSect.SetFollow( this );
114 if( !GetFollow() )
115 rSect.SimpleFormat();
116 if( !rSect.IsColLocked() )
117 rSect.InvalidateSize();
118 }
119 }
120
121 // NOTE: call <SwSectionFrm::Init()> directly after creation of a new section
122 // frame and its insert in the layout.
Init()123 void SwSectionFrm::Init()
124 {
125 ASSERT( GetUpper(), "SwSectionFrm::Init before insertion?!" );
126 SWRECTFN( this )
127 long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
128 (Frm().*fnRect->fnSetWidth)( nWidth );
129 (Frm().*fnRect->fnSetHeight)( 0 );
130
131 // #109700# LRSpace for sections
132 const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
133 (Prt().*fnRect->fnSetLeft)( rLRSpace.GetLeft() );
134 (Prt().*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
135 rLRSpace.GetRight() );
136 (Prt().*fnRect->fnSetHeight)( 0 );
137
138 const SwFmtCol &rCol = GetFmt()->GetCol();
139 if( ( rCol.GetNumCols() > 1 || IsAnyNoteAtEnd() ) && !IsInFtn() )
140 {
141 const SwFmtCol *pOld = Lower() ? &rCol : new SwFmtCol;
142 ChgColumns( *pOld, rCol, IsAnyNoteAtEnd() );
143 if( pOld != &rCol )
144 delete pOld;
145 }
146 }
147
~SwSectionFrm()148 SwSectionFrm::~SwSectionFrm()
149 {
150 if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
151 {
152 SwRootFrm *pRootFrm = getRootFrm();
153 if( pRootFrm )
154 pRootFrm->RemoveFromList( this ); //swmod 071108//swmod 071225
155 if( IsFollow() )
156 {
157 SwSectionFrm *pMaster = FindMaster();
158 if( pMaster )
159 {
160 PROTOCOL( this, PROT_SECTION, ACT_DEL_FOLLOW, pMaster )
161 pMaster->SetFollow( GetFollow() );
162 // Ein Master greift sich immer den Platz bis zur Unterkante seines
163 // Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder
164 // freigeben, deshalb wird die Size des Masters invalidiert.
165 if( !GetFollow() )
166 pMaster->InvalidateSize();
167 }
168 }
169 else if( HasFollow() )
170 {
171 PROTOCOL( this, PROT_SECTION, ACT_DEL_MASTER, GetFollow() )
172 GetFollow()->bIsFollow = sal_False;
173 }
174 }
175 }
176
177
178 /*************************************************************************
179 |*
180 |* SwSectionFrm::DelEmpty()
181 |*
182 |* Ersterstellung AMA 17. Dec. 97
183 |* Letzte Aenderung AMA 17. Dec. 97
184 |*
185 |*************************************************************************/
DelEmpty(sal_Bool bRemove)186 void SwSectionFrm::DelEmpty( sal_Bool bRemove )
187 {
188 if( IsColLocked() )
189 {
190 ASSERT( !bRemove, "Don't delete locked SectionFrms" );
191 return;
192 }
193 SwFrm* pUp = GetUpper();
194 if( pUp )
195 {
196 // --> OD 2005-12-01 #i27138#
197 // notify accessibility paragraphs objects about changed
198 // CONTENT_FLOWS_FROM/_TO relation.
199 // Relation CONTENT_FLOWS_FROM for current next paragraph will change
200 // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
201 {
202 ViewShell* pViewShell( getRootFrm()->GetCurrShell() );
203 if ( pViewShell && pViewShell->GetLayout() &&
204 pViewShell->GetLayout()->IsAnyShellAccessible() )
205 {
206 pViewShell->InvalidateAccessibleParaFlowRelation(
207 dynamic_cast<SwTxtFrm*>(FindNextCnt( true )),
208 dynamic_cast<SwTxtFrm*>(FindPrevCnt( true )) );
209 }
210 }
211 // <--
212 _Cut( bRemove );
213 }
214 if( IsFollow() )
215 {
216 SwSectionFrm *pMaster = FindMaster();
217 pMaster->SetFollow( GetFollow() );
218 // Ein Master greift sich immer den Platz bis zur Unterkante seines
219 // Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder
220 // freigeben, deshalb wird die Size des Masters invalidiert.
221 if( !GetFollow() && !pMaster->IsColLocked() )
222 pMaster->InvalidateSize();
223 bIsFollow = sal_False;
224 }
225 else if( HasFollow() )
226 GetFollow()->bIsFollow = sal_False;
227 pFollow = NULL;
228 if( pUp )
229 {
230 Frm().Height( 0 );
231 // Wenn wir sowieso sofort zerstoert werden, brauchen/duerfen wir
232 // uns gar nicht erst in die Liste eintragen
233 if( bRemove )
234 { // Wenn wir bereits halbtot waren vor diesem DelEmpty, so
235 // stehen wir vermutlich auch in der Liste und muessen uns
236 // dort austragen
237 if( !pSection && getRootFrm() )
238 getRootFrm()->RemoveFromList( this );
239 }
240 else if( getRootFrm() )
241 getRootFrm()->InsertEmptySct( this ); //swmod 071108//swmod 071225
242 pSection = NULL; // damit ist allerdings eine Reanimierung quasi ausgeschlossen
243 }
244 }
245
246 /*************************************************************************
247 |*
248 |* SwSectionFrm::Cut()
249 |*
250 |* Ersterstellung AMA 02. Dec. 97
251 |* Letzte Aenderung AMA 02. Dec. 97
252 |*
253 |*************************************************************************/
Cut()254 void SwSectionFrm::Cut()
255 {
256 _Cut( sal_True );
257 }
258
_Cut(sal_Bool bRemove)259 void SwSectionFrm::_Cut( sal_Bool bRemove )
260 {
261 ASSERT( GetUpper(), "Cut ohne Upper()." );
262
263 PROTOCOL( this, PROT_CUT, 0, GetUpper() )
264
265 SwPageFrm *pPage = FindPageFrm();
266 InvalidatePage( pPage );
267 SwFrm *pFrm = GetNext();
268 SwFrm* pPrepFrm = NULL;
269 while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
270 pFrm = pFrm->GetNext();
271 if( pFrm )
272 { //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
273 //berechnet der ist jetzt wo er der erste wird obsolete
274 pFrm->_InvalidatePrt();
275 pFrm->_InvalidatePos();
276 if( pFrm->IsSctFrm() )
277 pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
278 if ( pFrm && pFrm->IsCntntFrm() )
279 {
280 pFrm->InvalidatePage( pPage );
281 if( IsInFtn() && !GetIndPrev() )
282 pPrepFrm = pFrm;
283 }
284 }
285 else
286 {
287 InvalidateNextPos();
288 //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
289 if ( 0 != (pFrm = GetPrev()) )
290 { pFrm->SetRetouche();
291 pFrm->Prepare( PREP_WIDOWS_ORPHANS );
292 if ( pFrm->IsCntntFrm() )
293 pFrm->InvalidatePage( pPage );
294 }
295 //Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss
296 //er die Retouche uebernehmen.
297 //Ausserdem kann eine Leerseite entstanden sein.
298 else
299 { SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
300 pRoot->SetSuperfluous();
301 GetUpper()->SetCompletePaint();
302 }
303 }
304 //Erst removen, dann Upper Shrinken.
305 SwLayoutFrm *pUp = GetUpper();
306 if( bRemove )
307 {
308 Remove();
309 if( pUp && !pUp->Lower() && pUp->IsFtnFrm() && !pUp->IsColLocked() &&
310 pUp->GetUpper() )
311 {
312 pUp->Cut();
313 delete pUp;
314 pUp = NULL;
315 }
316 }
317 if( pPrepFrm )
318 pPrepFrm->Prepare( PREP_FTN );
319 if ( pUp )
320 {
321 SWRECTFN( this );
322 SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
323 if( nFrmHeight > 0 )
324 {
325 if( !bRemove )
326 {
327 (Frm().*fnRect->fnSetHeight)( 0 );
328 (Prt().*fnRect->fnSetHeight)( 0 );
329 }
330 pUp->Shrink( nFrmHeight );
331 }
332 }
333 }
334
335 /*************************************************************************
336 |*
337 |* SwSectionFrm::Paste()
338 |*
339 |* Ersterstellung AMA 04. Dec. 97
340 |* Letzte Aenderung AMA 04. Dec. 97
341 |*
342 |*************************************************************************/
343
Paste(SwFrm * pParent,SwFrm * pSibling)344 void SwSectionFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
345 {
346 ASSERT( pParent, "Kein Parent fuer Paste." );
347 ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
348 ASSERT( pParent != this, "Bin selbst der Parent." );
349 ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
350 ASSERT( !GetPrev() && !GetUpper(),
351 "Bin noch irgendwo angemeldet." );
352
353 PROTOCOL( this, PROT_PASTE, 0, GetUpper() )
354
355 //In den Baum einhaengen.
356 SwSectionFrm* pSect = pParent->FindSctFrm();
357 // --> OD 2008-06-23 #156927#
358 // Assure that parent is not inside a table frame, which is inside the found section frame.
359 if ( pSect )
360 {
361 SwTabFrm* pTableFrm = pParent->FindTabFrm();
362 if ( pTableFrm &&
363 pSect->IsAnLower( pTableFrm ) )
364 {
365 pSect = 0;
366 }
367 }
368 // <--
369
370 SWRECTFN( pParent )
371 if( pSect && HasToBreak( pSect ) )
372 {
373 if( pParent->IsColBodyFrm() ) // handelt es sich um einen spaltigen Bereich
374 {
375 // Falls wir zufaellig am Ende einer Spalte stehen, muss pSibling
376 // auf den ersten Frame der naechsten Spalte zeigen, damit
377 // der Inhalt der naechsten Spalte von InsertGroup richtig in den
378 // neu angelegten pSect umgehaengt wird.
379 SwColumnFrm *pCol = (SwColumnFrm*)pParent->GetUpper();
380 while( !pSibling && 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
381 pSibling = ((SwLayoutFrm*)((SwColumnFrm*)pCol)->Lower())->Lower();
382 if( pSibling )
383 {
384 // Schlimmer noch: alle folgenden Spalteninhalte muessen
385 // an die pSibling-Kette angehaengt werden, damit sie
386 // mitgenommen werden.
387 SwFrm *pTmp = pSibling;
388 while ( 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
389 {
390 while ( pTmp->GetNext() )
391 pTmp = pTmp->GetNext();
392 SwFrm* pSave = ::SaveCntnt( pCol );
393 ::RestoreCntnt( pSave, pSibling->GetUpper(), pTmp, true );
394 }
395 }
396 }
397 pParent = pSect;
398 pSect = new SwSectionFrm( *((SwSectionFrm*)pParent)->GetSection(), pParent );
399 // Wenn pParent in zwei Teile zerlegt wird, so muss sein Follow am
400 // neuen, zweiten Teil angebracht werden.
401 pSect->SetFollow( ((SwSectionFrm*)pParent)->GetFollow() );
402 ((SwSectionFrm*)pParent)->SetFollow( NULL );
403 if( pSect->GetFollow() )
404 pParent->_InvalidateSize();
405
406 InsertGroupBefore( pParent, pSibling, pSect );
407 pSect->Init();
408 (pSect->*fnRect->fnMakePos)( pSect->GetUpper(), pSect->GetPrev(), sal_True);
409 if( !((SwLayoutFrm*)pParent)->Lower() )
410 {
411 SwSectionFrm::MoveCntntAndDelete( (SwSectionFrm*)pParent, sal_False );
412 pParent = this;
413 }
414 }
415 else
416 InsertGroupBefore( pParent, pSibling, NULL );
417
418 _InvalidateAll();
419 SwPageFrm *pPage = FindPageFrm();
420 InvalidatePage( pPage );
421
422 if ( pSibling )
423 {
424 pSibling->_InvalidatePos();
425 pSibling->_InvalidatePrt();
426 if ( pSibling->IsCntntFrm() )
427 pSibling->InvalidatePage( pPage );
428 }
429
430 SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
431 if( nFrmHeight )
432 pParent->Grow( nFrmHeight );
433
434 if ( GetPrev() )
435 {
436 if ( !IsFollow() )
437 {
438 GetPrev()->InvalidateSize();
439 if ( GetPrev()->IsCntntFrm() )
440 GetPrev()->InvalidatePage( pPage );
441 }
442 }
443 }
444
445
446 /*************************************************************************
447 |*
448 |* SwSectionFrm::HasToBreak()
449 |*
450 |* Hier wird entschieden, ob der this-SectionFrm den uebergebenen
451 |* (Section)Frm aufbrechen soll oder nicht.
452 |* Zunaechst werden uebergeordnete Bereiche immer aufgebrochen,
453 |* spaeter koennte man es einstellbar machen.
454 |*
455 |* Ersterstellung AMA 12. Dec. 97
456 |* Letzte Aenderung AMA 12. Dec. 97
457 |*
458 |*************************************************************************/
459
HasToBreak(const SwFrm * pFrm) const460 sal_Bool SwSectionFrm::HasToBreak( const SwFrm* pFrm ) const
461 {
462 if( !pFrm->IsSctFrm() )
463 return sal_False;
464
465 SwSectionFmt *pTmp = (SwSectionFmt*)GetFmt();
466 // if( !pTmp->GetSect().GetValue() )
467 // return sal_False;
468
469 const SwFrmFmt *pOtherFmt = ((SwSectionFrm*)pFrm)->GetFmt();
470 do
471 {
472 pTmp = pTmp->GetParent();
473 if( !pTmp )
474 return sal_False;
475 if( pTmp == pOtherFmt )
476 return sal_True;
477 } while( sal_True ); // ( pTmp->GetSect().GetValue() );
478 }
479
480 /*************************************************************************
481 |*
482 |* SwSectionFrm::MergeNext()
483 |*
484 |* Ersterstellung AMA 04. Dec. 97
485 |* Letzte Aenderung AMA 04. Dec. 97
486 |*
487 |* Verschmilzt zwei SectionFrms, falls es sich um den
488 |* gleichen Bereich handelt.
489 |* Notwendig kann dies sein, wenn ein (Unter-)Bereich geloescht wird, der
490 |* einen anderen in zwei Teile zerlegt hatte.
491 |*
492 |*************************************************************************/
493
MergeNext(SwSectionFrm * pNxt)494 void SwSectionFrm::MergeNext( SwSectionFrm* pNxt )
495 {
496 if( !pNxt->IsJoinLocked() && GetSection() == pNxt->GetSection() )
497 {
498 PROTOCOL( this, PROT_SECTION, ACT_MERGE, pNxt )
499
500 SwFrm* pTmp = ::SaveCntnt( pNxt );
501 if( pTmp )
502 {
503 SwFrm* pLast = Lower();
504 SwLayoutFrm* pLay = this;
505 if( pLast )
506 {
507 while( pLast->GetNext() )
508 pLast = pLast->GetNext();
509 if( pLast->IsColumnFrm() )
510 { // Spalten jetzt mit BodyFrm
511 pLay = (SwLayoutFrm*)((SwLayoutFrm*)pLast)->Lower();
512 pLast = pLay->Lower();
513 if( pLast )
514 while( pLast->GetNext() )
515 pLast = pLast->GetNext();
516 }
517 }
518 ::RestoreCntnt( pTmp, pLay, pLast, true );
519 }
520 SetFollow( pNxt->GetFollow() );
521 pNxt->SetFollow( NULL );
522 pNxt->bIsFollow = sal_False;
523 pNxt->Cut();
524 delete pNxt;
525 InvalidateSize();
526 }
527 }
528
529 /*************************************************************************
530 |*
531 |* SwSectionFrm::SplitSect()
532 |*
533 |* Ersterstellung AMA 29. Apr. 99
534 |* Letzte Aenderung AMA 29. Apr. 99
535 |*
536 |* Zerteilt einen SectionFrm in zwei Teile, der zweite Teil beginnt mit dem
537 |* uebergebenen Frame.
538 |* Benoetigt wird dies beim Einfuegen eines inneren Bereichs, weil innerhalb
539 |* von Rahmen oder Tabellenzellen das MoveFwd nicht den erwuenschten Effekt
540 |* haben kann.
541 |*
542 |*************************************************************************/
543
SplitSect(SwFrm * pFrm,sal_Bool bApres)544 sal_Bool SwSectionFrm::SplitSect( SwFrm* pFrm, sal_Bool bApres )
545 {
546 ASSERT( pFrm, "SplitSect: Why?" );
547 SwFrm* pOther = bApres ? pFrm->FindNext() : pFrm->FindPrev();
548 if( !pOther )
549 return sal_False;
550 SwSectionFrm* pSect = pOther->FindSctFrm();
551 if( pSect != this )
552 return sal_False;
553 // Den Inhalt zur Seite stellen
554 SwFrm* pSav = ::SaveCntnt( this, bApres ? pOther : pFrm );
555 ASSERT( pSav, "SplitSect: What's on?" );
556 if( pSav ) // Robust
557 { // Einen neuen SctFrm anlegen, nicht als Follow/Master
558 SwSectionFrm* pNew = new SwSectionFrm( *pSect->GetSection(), pSect );
559 pNew->InsertBehind( pSect->GetUpper(), pSect );
560 pNew->Init();
561 SWRECTFN( this )
562 (pNew->*fnRect->fnMakePos)( NULL, pSect, sal_True );
563 // OD 25.03.2003 #108339# - restore content:
564 // determine layout frame for restoring content after the initialization
565 // of the section frame. In the section initialization the columns are
566 // created.
567 {
568 SwLayoutFrm* pLay = pNew;
569 // Search for last layout frame, e.g. for columned sections.
570 while( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
571 pLay = (SwLayoutFrm*)pLay->Lower();
572 ::RestoreCntnt( pSav, pLay, NULL, true );
573 }
574 _InvalidateSize();
575 if( HasFollow() )
576 {
577 pNew->SetFollow( GetFollow() );
578 SetFollow( NULL );
579 }
580 return sal_True;
581 }
582 return sal_False;
583 }
584
585 /*************************************************************************
586 |*
587 |* SwSectionFrm::MoveCntntAndDelete()
588 |*
589 |* Ersterstellung AMA 29. Jan 99
590 |* Letzte Aenderung AMA 29. Jan 99
591 |*
592 |* MoveCntnt wird zur Zerstoerung eines SectionFrms wg. Aufhebung oder
593 |* Verstecken des Bereichs gerufen, um den Inhalt umzuhaengen.
594 |* Wenn der SectionFrm keinen anderen aufbrach, so wird der Inhalt in
595 |* den Upper bewegt. Anderfalls wird der Inhalt in den anderen SectionFrm
596 |* umgehaengt, dieser muss ggf. gemergt werden.
597 |*
598 |*************************************************************************/
599 // Wenn ein mehrspaltiger Bereich aufgehoben wird, muessen die ContentFrms
600 // invalidiert werden
601
lcl_InvalidateInfFlags(SwFrm * pFrm,sal_Bool bInva)602 void lcl_InvalidateInfFlags( SwFrm* pFrm, sal_Bool bInva )
603 {
604 while ( pFrm )
605 {
606 pFrm->InvalidateInfFlags();
607 if( bInva )
608 {
609 pFrm->_InvalidatePos();
610 pFrm->_InvalidateSize();
611 pFrm->_InvalidatePrt();
612 }
613 if( pFrm->IsLayoutFrm() )
614 lcl_InvalidateInfFlags( ((SwLayoutFrm*)pFrm)->GetLower(), sal_False );
615 pFrm = pFrm->GetNext();
616 }
617 }
618
619
620 //
621 // Works like SwCntntFrm::ImplGetNextCntntFrm, but starts with a LayoutFrm
622 //
lcl_GetNextCntntFrm(const SwLayoutFrm * pLay,bool bFwd)623 SwCntntFrm* lcl_GetNextCntntFrm( const SwLayoutFrm* pLay, bool bFwd )
624 {
625 if ( bFwd )
626 {
627 if ( pLay->GetNext() && pLay->GetNext()->IsCntntFrm() )
628 return (SwCntntFrm*)pLay->GetNext();
629 }
630 else
631 {
632 if ( pLay->GetPrev() && pLay->GetPrev()->IsCntntFrm() )
633 return (SwCntntFrm*)pLay->GetPrev();
634 }
635
636 // #100926#
637 const SwFrm* pFrm = pLay;
638 SwCntntFrm *pCntntFrm = 0;
639 sal_Bool bGoingUp = sal_True;
640 do {
641 const SwFrm *p = 0;
642 sal_Bool bGoingFwdOrBwd = sal_False, bGoingDown = sal_False;
643
644 bGoingDown = !bGoingUp && ( 0 != ( p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0 ) );
645 if ( !bGoingDown )
646 {
647 bGoingFwdOrBwd = ( 0 != ( p = pFrm->IsFlyFrm() ?
648 ( bFwd ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink() ) :
649 ( bFwd ? pFrm->GetNext() :pFrm->GetPrev() ) ) );
650 if ( !bGoingFwdOrBwd )
651 {
652 bGoingUp = (0 != (p = pFrm->GetUpper() ) );
653 if ( !bGoingUp )
654 return 0;
655 }
656 }
657
658 bGoingUp = !( bGoingFwdOrBwd || bGoingDown );
659
660 if( !bFwd && bGoingDown && p )
661 while ( p->GetNext() )
662 p = p->GetNext();
663
664 pFrm = p;
665 } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
666
667 return pCntntFrm;
668 }
669
670 #define FIRSTLEAF( pLayFrm ) ( ( pLayFrm->Lower() && pLayFrm->Lower()->IsColumnFrm() )\
671 ? pLayFrm->GetNextLayoutLeaf() \
672 : pLayFrm )
673
MoveCntntAndDelete(SwSectionFrm * pDel,sal_Bool bSave)674 void SwSectionFrm::MoveCntntAndDelete( SwSectionFrm* pDel, sal_Bool bSave )
675 {
676 sal_Bool bSize = pDel->Lower() && pDel->Lower()->IsColumnFrm();
677 SwFrm* pPrv = pDel->GetPrev();
678 SwLayoutFrm* pUp = pDel->GetUpper();
679 // OD 27.03.2003 #i12711# - initialize local pointer variables.
680 SwSectionFrm* pPrvSct = NULL;
681 SwSectionFrm* pNxtSct = NULL;
682 SwSectionFmt* pParent = static_cast<SwSectionFmt*>(pDel->GetFmt())->GetParent();
683 if( pDel->IsInTab() && pParent )
684 {
685 SwTabFrm *pTab = pDel->FindTabFrm();
686 // Wenn wir innerhalb einer Tabelle liegen, koennen wir nur Bereiche
687 // aufgebrochen haben, die ebenfalls innerhalb liegen, nicht etwa
688 // einen Bereich, der die gesamte Tabelle umfasst.
689 if( pTab->IsInSct() && pParent == pTab->FindSctFrm()->GetFmt() )
690 pParent = NULL;
691 }
692 // Wenn unser Format einen Parent besitzt, so haben wir vermutlich
693 // einen anderen SectionFrm aufgebrochen, dies muss geprueft werden,
694 // dazu besorgen wir uns zunaechst den vorhergehende und den nach-
695 // folgenden CntntFrm, mal sehen, ob diese in SectionFrms liegen.
696 // OD 27.03.2003 #i12711# - check, if previous and next section belonging
697 // together and can be joined, *not* only if deleted section contains content.
698 if ( pParent )
699 {
700 SwFrm* pPrvCntnt = lcl_GetNextCntntFrm( pDel, false );
701 pPrvSct = pPrvCntnt ? pPrvCntnt->FindSctFrm() : NULL;
702 SwFrm* pNxtCntnt = lcl_GetNextCntntFrm( pDel, true );
703 pNxtSct = pNxtCntnt ? pNxtCntnt->FindSctFrm() : NULL;
704 }
705 else
706 {
707 pParent = NULL;
708 pPrvSct = pNxtSct = NULL;
709 }
710
711 // Jetzt wird der Inhalt beseite gestellt und der Frame zerstoert
712 SwFrm *pSave = bSave ? ::SaveCntnt( pDel ) : NULL;
713 sal_Bool bOldFtn = sal_True;
714 if( pSave && pUp->IsFtnFrm() )
715 {
716 bOldFtn = ((SwFtnFrm*)pUp)->IsColLocked();
717 ((SwFtnFrm*)pUp)->ColLock();
718 }
719 pDel->DelEmpty( sal_True );
720 delete pDel;
721 if( pParent )
722 { // Hier wird die geeignete Einfuegeposition gesucht
723 if( pNxtSct && pNxtSct->GetFmt() == pParent )
724 { // Hier koennen wir uns am Anfang einfuegen
725 pUp = FIRSTLEAF( pNxtSct );
726 pPrv = NULL;
727 if( pPrvSct && !( pPrvSct->GetFmt() == pParent ) )
728 pPrvSct = NULL; // damit nicht gemergt wird
729 }
730 else if( pPrvSct && pPrvSct->GetFmt() == pParent )
731 { // Wunderbar, hier koennen wir uns am Ende einfuegen
732 pUp = pPrvSct;
733 if( pUp->Lower() && pUp->Lower()->IsColumnFrm() )
734 {
735 pUp = static_cast<SwLayoutFrm*>(pUp->GetLastLower());
736 // Der Body der letzten Spalte
737 pUp = static_cast<SwLayoutFrm*>(pUp->Lower());
738 }
739 // damit hinter dem letzten eingefuegt wird
740 pPrv = pUp->GetLastLower();
741 pPrvSct = NULL; // damit nicht gemergt wird
742 }
743 else
744 {
745 if( pSave )
746 { // Folgende Situationen: Vor und hinter dem zu loeschenden Bereich
747 // ist entweder die Bereichsgrenze des umfassenden Bereichs oder
748 // es schliesst ein anderer (Geschwister-)Bereich direkt an, der
749 // vom gleichen Parent abgeleitet ist.
750 // Dann gibt es (noch) keinen Teil unseres Parents, der den Inhalt
751 // aufnehmen kann,also bauen wir ihn uns.
752 pPrvSct = new SwSectionFrm( *pParent->GetSection(), pUp );
753 pPrvSct->InsertBehind( pUp, pPrv );
754 pPrvSct->Init();
755 SWRECTFN( pUp )
756 (pPrvSct->*fnRect->fnMakePos)( pUp, pPrv, sal_True );
757 pUp = FIRSTLEAF( pPrvSct );
758 pPrv = NULL;
759 }
760 pPrvSct = NULL; // damit nicht gemergt wird
761 }
762 }
763 // Der Inhalt wird eingefuegt..
764 if( pSave )
765 {
766 lcl_InvalidateInfFlags( pSave, bSize );
767 ::RestoreCntnt( pSave, pUp, pPrv, true );
768 pUp->FindPageFrm()->InvalidateCntnt();
769 if( !bOldFtn )
770 ((SwFtnFrm*)pUp)->ColUnlock();
771 }
772 // jetzt koennen eventuell zwei Teile des uebergeordneten Bereich verschmelzen
773 if( pPrvSct && !pPrvSct->IsJoinLocked() )
774 {
775 ASSERT( pNxtSct, "MoveCntnt: No Merge" );
776 pPrvSct->MergeNext( pNxtSct );
777 }
778 }
779
MakeAll()780 void SwSectionFrm::MakeAll()
781 {
782 if ( IsJoinLocked() || IsColLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
783 return;
784 if( !pSection ) // Durch DelEmpty
785 {
786 ASSERT( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
787 if( !bValidPos )
788 {
789 if( GetUpper() )
790 {
791 SWRECTFN( GetUpper() )
792 (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
793 }
794 }
795 bValidSize = bValidPos = bValidPrtArea = sal_True;
796 return;
797 }
798 LockJoin(); //Ich lass mich nicht unterwegs vernichten.
799
800 while( GetNext() && GetNext() == GetFollow() )
801 {
802 const SwFrm* pFoll = GetFollow();
803 MergeNext( (SwSectionFrm*)GetNext() );
804 if( pFoll == GetFollow() )
805 break;
806 }
807
808 // OD 2004-03-15 #116561# - In online layout join the follows, if section
809 // can grow.
810 const ViewShell *pSh = getRootFrm()->GetCurrShell();
811 if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
812 ( Grow( LONG_MAX, true ) > 0 ) )
813 {
814 while( GetFollow() )
815 {
816 const SwFrm* pFoll = GetFollow();
817 MergeNext( GetFollow() );
818 if( pFoll == GetFollow() )
819 break;
820 }
821 }
822
823 // Ein Bereich mit Follow nimmt allen Platz bis zur Unterkante des Uppers
824 // in Anspruch. Bewegt er sich, so kann seine Groesse zu- oder abnehmen...
825 if( !bValidPos && ToMaximize( sal_False ) )
826 bValidSize = sal_False;
827
828 #if OSL_DEBUG_LEVEL > 1
829 const SwFmtCol &rCol = GetFmt()->GetCol();
830 (void)rCol;
831 #endif
832 SwLayoutFrm::MakeAll();
833 UnlockJoin();
834 if( pSection && IsSuperfluous() )
835 DelEmpty( sal_False );
836 }
837
ShouldBwdMoved(SwLayoutFrm *,sal_Bool,sal_Bool &)838 sal_Bool SwSectionFrm::ShouldBwdMoved( SwLayoutFrm *, sal_Bool , sal_Bool & )
839 {
840 ASSERT( sal_False, "Hups, wo ist meine Tarnkappe?" );
841 return sal_False;
842 }
843
_GetEndSectFmt() const844 const SwSectionFmt* SwSectionFrm::_GetEndSectFmt() const
845 {
846 const SwSectionFmt *pFmt = pSection->GetFmt();
847 while( !pFmt->GetEndAtTxtEnd().IsAtEnd() )
848 {
849 if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
850 pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
851 else
852 return NULL;
853 }
854 return pFmt;
855 }
856
lcl_FindCntntFrm(SwCntntFrm * & rpCntntFrm,SwFtnFrm * & rpFtnFrm,SwFrm * pFrm,sal_Bool & rbChkFtn)857 void lcl_FindCntntFrm( SwCntntFrm* &rpCntntFrm, SwFtnFrm* &rpFtnFrm,
858 SwFrm* pFrm, sal_Bool &rbChkFtn )
859 {
860 if( pFrm )
861 {
862 while( pFrm->GetNext() )
863 pFrm = pFrm->GetNext();
864 while( !rpCntntFrm && pFrm )
865 {
866 if( pFrm->IsCntntFrm() )
867 rpCntntFrm = (SwCntntFrm*)pFrm;
868 else if( pFrm->IsLayoutFrm() )
869 {
870 if( pFrm->IsFtnFrm() )
871 {
872 if( rbChkFtn )
873 {
874 rpFtnFrm = (SwFtnFrm*)pFrm;
875 rbChkFtn = rpFtnFrm->GetAttr()->GetFtn().IsEndNote();
876 }
877 }
878 else
879 lcl_FindCntntFrm( rpCntntFrm, rpFtnFrm,
880 ((SwLayoutFrm*)pFrm)->Lower(), rbChkFtn );
881 }
882 pFrm = pFrm->GetPrev();
883 }
884 }
885 }
886
FindLastCntnt(sal_uInt8 nMode)887 SwCntntFrm *SwSectionFrm::FindLastCntnt( sal_uInt8 nMode )
888 {
889 SwCntntFrm *pRet = NULL;
890 SwFtnFrm *pFtnFrm = NULL;
891 SwSectionFrm *pSect = this;
892 if( nMode )
893 {
894 const SwSectionFmt *pFmt = IsEndnAtEnd() ? GetEndSectFmt() :
895 pSection->GetFmt();
896 do {
897 while( pSect->HasFollow() )
898 pSect = pSect->GetFollow();
899 SwFrm* pTmp = pSect->FindNext();
900 while( pTmp && pTmp->IsSctFrm() &&
901 !((SwSectionFrm*)pTmp)->GetSection() )
902 pTmp = pTmp->FindNext();
903 if( pTmp && pTmp->IsSctFrm() &&
904 ((SwSectionFrm*)pTmp)->IsDescendantFrom( pFmt ) )
905 pSect = (SwSectionFrm*)pTmp;
906 else
907 break;
908 } while( sal_True );
909 }
910 sal_Bool bFtnFound = nMode == FINDMODE_ENDNOTE;
911 do
912 {
913 lcl_FindCntntFrm( pRet, pFtnFrm, pSect->Lower(), bFtnFound );
914 if( pRet || !pSect->IsFollow() || !nMode ||
915 ( FINDMODE_MYLAST == nMode && this == pSect ) )
916 break;
917 pSect = pSect->FindMaster();
918 } while( pSect );
919 if( ( nMode == FINDMODE_ENDNOTE ) && pFtnFrm )
920 pRet = pFtnFrm->ContainsCntnt();
921 return pRet;
922 }
923
CalcMinDiff(SwTwips & rMinDiff) const924 sal_Bool SwSectionFrm::CalcMinDiff( SwTwips& rMinDiff ) const
925 {
926 if( ToMaximize( sal_True ) )
927 {
928 SWRECTFN( this )
929 rMinDiff = (GetUpper()->*fnRect->fnGetPrtBottom)();
930 rMinDiff = (Frm().*fnRect->fnBottomDist)( rMinDiff );
931 return sal_True;
932 }
933 return sal_False;
934 }
935
936 /*************************************************************************
937 *
938 * SwSectionFrm::CollectEndnotes( )
939 *
940 * Ersterstellung AMA 03. Nov 99
941 * Letzte Aenderung AMA 03. Nov 99
942 *
943 * CollectEndnotes looks for endnotes in the sectionfrm and his follows,
944 * the endnotes will cut off the layout and put into the array.
945 * If the first endnote is not a master-SwFtnFrm, the whole sectionfrm
946 * contains only endnotes and it is not necessary to collect them.
947 *
948 *************************************************************************/
949
lcl_FindEndnote(SwSectionFrm * & rpSect,sal_Bool & rbEmpty,SwLayouter * pLayouter)950 SwFtnFrm* lcl_FindEndnote( SwSectionFrm* &rpSect, sal_Bool &rbEmpty,
951 SwLayouter *pLayouter )
952 {
953 // if rEmpty is set, the rpSect is already searched
954 SwSectionFrm* pSect = rbEmpty ? rpSect->GetFollow() : rpSect;
955 while( pSect )
956 {
957 ASSERT( (pSect->Lower() && pSect->Lower()->IsColumnFrm()) || pSect->GetUpper()->IsFtnFrm(),
958 "InsertEndnotes: Where's my column?" );
959
960 // i73332: Columned section in endnote
961 SwColumnFrm* pCol = 0;
962 if(pSect->Lower() && pSect->Lower()->IsColumnFrm())
963 pCol = (SwColumnFrm*)pSect->Lower();
964
965 while( pCol ) // check all columns
966 {
967 SwFtnContFrm* pFtnCont = pCol->FindFtnCont();
968 if( pFtnCont )
969 {
970 SwFtnFrm* pRet = (SwFtnFrm*)pFtnCont->Lower();
971 while( pRet ) // look for endnotes
972 {
973 if( pRet->GetAttr()->GetFtn().IsEndNote() )
974 {
975 if( pRet->GetMaster() )
976 {
977 if( pLayouter )
978 pLayouter->CollectEndnote( pRet );
979 else
980 return 0;
981 }
982 else
983 return pRet; // Found
984 }
985 pRet = (SwFtnFrm*)pRet->GetNext();
986 }
987 }
988 pCol = (SwColumnFrm*)pCol->GetNext();
989 }
990 rpSect = pSect;
991 pSect = pLayouter ? pSect->GetFollow() : NULL;
992 rbEmpty = sal_True;
993 }
994 return NULL;
995 }
996
lcl_ColumnRefresh(SwSectionFrm * pSect,sal_Bool bFollow)997 void lcl_ColumnRefresh( SwSectionFrm* pSect, sal_Bool bFollow )
998 {
999 while( pSect )
1000 {
1001 sal_Bool bOldLock = pSect->IsColLocked();
1002 pSect->ColLock();
1003 if( pSect->Lower() && pSect->Lower()->IsColumnFrm() )
1004 {
1005 SwColumnFrm *pCol = (SwColumnFrm*)pSect->Lower();
1006 do
1007 { pCol->_InvalidateSize();
1008 pCol->_InvalidatePos();
1009 ((SwLayoutFrm*)pCol)->Lower()->_InvalidateSize();
1010 pCol->Calc(); // calculation of column and
1011 ((SwLayoutFrm*)pCol)->Lower()->Calc(); // body
1012 pCol = (SwColumnFrm*)pCol->GetNext();
1013 } while ( pCol );
1014 }
1015 if( !bOldLock )
1016 pSect->ColUnlock();
1017 if( bFollow )
1018 pSect = pSect->GetFollow();
1019 else
1020 pSect = NULL;
1021 }
1022 }
1023
CollectEndnotes(SwLayouter * pLayouter)1024 void SwSectionFrm::CollectEndnotes( SwLayouter* pLayouter )
1025 {
1026 ASSERT( IsColLocked(), "CollectEndnotes: You love the risk?" );
1027 // i73332: Section in footnode does not have columns!
1028 ASSERT( (Lower() && Lower()->IsColumnFrm()) || GetUpper()->IsFtnFrm(), "Where's my column?" );
1029
1030 SwSectionFrm* pSect = this;
1031 SwFtnFrm* pFtn;
1032 sal_Bool bEmpty = sal_False;
1033 // pSect is the last sectionfrm without endnotes or the this-pointer
1034 // the first sectionfrm with endnotes may be destroyed, when the endnotes
1035 // is cutted
1036 while( 0 != (pFtn = lcl_FindEndnote( pSect, bEmpty, pLayouter )) )
1037 pLayouter->CollectEndnote( pFtn );
1038 if( pLayouter->HasEndnotes() )
1039 lcl_ColumnRefresh( this, sal_True );
1040 }
1041
1042 /*************************************************************************
1043 |*
1044 |* SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
1045 |*
1046 |* Beschreibung: Passt die Groesse an die Umgebung an.
1047 |* Wer einen Follow oder Fussnoten besitzt, soll bis zur Unterkante
1048 |* des Uppers gehen (bMaximize).
1049 |* Niemand darf ueber den Upper hinausgehen, ggf. darf man versuchen (bGrow)
1050 |* seinen Upper zu growen.
1051 |* Wenn die Groesse veraendert werden musste, wird der Inhalt kalkuliert.
1052 |*
1053 |*************************************************************************/
1054
1055 /// OD 18.09.2002 #100522#
1056 /// perform calculation of content, only if height has changed.
_CheckClipping(sal_Bool bGrow,sal_Bool bMaximize)1057 void SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
1058 {
1059 SWRECTFN( this )
1060 long nDiff;
1061 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1062 if( bGrow && ( !IsInFly() || !GetUpper()->IsColBodyFrm() ||
1063 !FindFlyFrm()->IsLocked() ) )
1064 {
1065 nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
1066 if( !bMaximize )
1067 nDiff += Undersize();
1068 if( nDiff > 0 )
1069 {
1070 long nAdd = GetUpper()->Grow( nDiff );
1071 if( bVert && !bRev )
1072 nDeadLine -= nAdd;
1073 else
1074 nDeadLine += nAdd;
1075 }
1076 }
1077 nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
1078 SetUndersized( !bMaximize && nDiff >= 0 );
1079 const bool bCalc = ( IsUndersized() || bMaximize ) &&
1080 ( nDiff ||
1081 (Prt().*fnRect->fnGetTop)() > (Frm().*fnRect->fnGetHeight)() );
1082 // OD 03.11.2003 #i19737# - introduce local variable <bExtraCalc> to indicate
1083 // that a calculation has to be done beside the value of <bCalc>.
1084 bool bExtraCalc = false;
1085 if( !bCalc && !bGrow && IsAnyNoteAtEnd() && !IsInFtn() )
1086 {
1087 SwSectionFrm *pSect = this;
1088 sal_Bool bEmpty = sal_False;
1089 SwLayoutFrm* pFtn = IsEndnAtEnd() ?
1090 lcl_FindEndnote( pSect, bEmpty, NULL ) : NULL;
1091 if( pFtn )
1092 {
1093 pFtn = pFtn->FindFtnBossFrm();
1094 SwFrm* pTmp = FindLastCntnt( FINDMODE_LASTCNT );
1095 // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
1096 if ( pTmp && pFtn->IsBefore( pTmp->FindFtnBossFrm() ) )
1097 bExtraCalc = true;
1098 }
1099 else if( GetFollow() && !GetFollow()->ContainsAny() )
1100 bExtraCalc = true;
1101 }
1102 if ( bCalc || bExtraCalc )
1103 {
1104 nDiff = (*fnRect->fnYDiff)( nDeadLine, (Frm().*fnRect->fnGetTop)() );
1105 if( nDiff < 0 )
1106 {
1107 nDiff = 0;
1108 nDeadLine = (Frm().*fnRect->fnGetTop)();
1109 }
1110 const Size aOldSz( Prt().SSize() );
1111 long nTop = (this->*fnRect->fnGetTopMargin)();
1112 (Frm().*fnRect->fnSetBottom)( nDeadLine );
1113 nDiff = (Frm().*fnRect->fnGetHeight)();
1114 if( nTop > nDiff )
1115 nTop = nDiff;
1116 (this->*fnRect->fnSetYMargins)( nTop, 0 );
1117
1118 // OD 18.09.2002 #100522#
1119 // Determine, if height has changed.
1120 // Note: In vertical layout the height equals the width value.
1121 bool bHeightChanged = bVert ?
1122 (aOldSz.Width() != Prt().Width()) :
1123 (aOldSz.Height() != Prt().Height());
1124 // Wir haben zu guter Letzt noch einmal die Hoehe geaendert,
1125 // dann wird das innere Layout (Columns) kalkuliert und
1126 // der Inhalt ebenfalls.
1127 // OD 18.09.2002 #100522#
1128 // calculate content, only if height has changed.
1129 // OD 03.11.2003 #i19737# - restriction of content calculation too strong.
1130 // If an endnote has an incorrect position or a follow section contains
1131 // no content except footnotes/endnotes, the content has also been calculated.
1132 if ( ( bHeightChanged || bExtraCalc ) && Lower() )
1133 {
1134 if( Lower()->IsColumnFrm() )
1135 {
1136 lcl_ColumnRefresh( this, sal_False );
1137 ::CalcCntnt( this );
1138 }
1139 else
1140 {
1141 ChgLowersProp( aOldSz );
1142 if( !bMaximize && !IsCntntLocked() )
1143 ::CalcCntnt( this );
1144 }
1145 }
1146 }
1147 }
1148
SimpleFormat()1149 void SwSectionFrm::SimpleFormat()
1150 {
1151 if ( IsJoinLocked() || IsColLocked() )
1152 return;
1153 // ASSERT( pFollow, "SimpleFormat: Follow required" );
1154 LockJoin();
1155 SWRECTFN( this )
1156 if( GetPrev() || GetUpper() )
1157 {
1158 // --> OD 2009-09-28 #b6882166#
1159 // assure notifications on position changes.
1160 const SwLayNotify aNotify( this );
1161 // <--
1162 (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
1163 bValidPos = sal_True;
1164 }
1165 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1166 // OD 22.10.2002 #97265# - call always method <lcl_ColumnRefresh(..)>, in
1167 // order to get calculated lowers, not only if there space left in its upper.
1168 if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) >= 0 )
1169 {
1170 (Frm().*fnRect->fnSetBottom)( nDeadLine );
1171 long nHeight = (Frm().*fnRect->fnGetHeight)();
1172 long nTop = CalcUpperSpace();
1173 if( nTop > nHeight )
1174 nTop = nHeight;
1175 (this->*fnRect->fnSetYMargins)( nTop, 0 );
1176 }
1177 lcl_ColumnRefresh( this, sal_False );
1178 UnlockJoin();
1179 }
1180
1181 // --> OD 2005-01-11 #i40147# - helper class to perform extra section format
1182 // to position anchored objects and to keep the position of whose objects locked.
1183 class ExtraFormatToPositionObjs
1184 {
1185 private:
1186 SwSectionFrm* mpSectFrm;
1187 bool mbExtraFormatPerformed;
1188
1189 public:
ExtraFormatToPositionObjs(SwSectionFrm & _rSectFrm)1190 ExtraFormatToPositionObjs( SwSectionFrm& _rSectFrm)
1191 : mpSectFrm( &_rSectFrm ),
1192 mbExtraFormatPerformed( false )
1193 {}
1194
~ExtraFormatToPositionObjs()1195 ~ExtraFormatToPositionObjs()
1196 {
1197 if ( mbExtraFormatPerformed )
1198 {
1199 // release keep locked position of lower floating screen objects
1200 SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
1201 SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
1202 if ( pObjs )
1203 {
1204 sal_uInt32 i = 0;
1205 for ( i = 0; i < pObjs->Count(); ++i )
1206 {
1207 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1208
1209 if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
1210 {
1211 pAnchoredObj->SetKeepPosLocked( false );
1212 }
1213 }
1214 }
1215 }
1216 }
1217
1218 // --> OD 2008-06-20 #i81555#
InitObjs(SwFrm & rFrm)1219 void InitObjs( SwFrm& rFrm )
1220 {
1221 SwSortedObjs* pObjs = rFrm.GetDrawObjs();
1222 if ( pObjs )
1223 {
1224 sal_uInt32 i = 0;
1225 for ( i = 0; i < pObjs->Count(); ++i )
1226 {
1227 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1228
1229 pAnchoredObj->UnlockPosition();
1230 pAnchoredObj->SetClearedEnvironment( false );
1231 }
1232 }
1233 SwLayoutFrm* pLayoutFrm = dynamic_cast<SwLayoutFrm*>(&rFrm);
1234 if ( pLayoutFrm != 0 )
1235 {
1236 SwFrm* pLowerFrm = pLayoutFrm->GetLower();
1237 while ( pLowerFrm != 0 )
1238 {
1239 InitObjs( *pLowerFrm );
1240
1241 pLowerFrm = pLowerFrm->GetNext();
1242 }
1243 }
1244 }
1245 // <--
1246
FormatSectionToPositionObjs()1247 void FormatSectionToPositionObjs()
1248 {
1249 // perform extra format for multi-columned section.
1250 if ( mpSectFrm->Lower() && mpSectFrm->Lower()->IsColumnFrm() &&
1251 mpSectFrm->Lower()->GetNext() )
1252 {
1253 // grow section till bottom of printing area of upper frame
1254 SWRECTFN( mpSectFrm );
1255 SwTwips nTopMargin = (mpSectFrm->*fnRect->fnGetTopMargin)();
1256 Size aOldSectPrtSize( mpSectFrm->Prt().SSize() );
1257 SwTwips nDiff = (mpSectFrm->Frm().*fnRect->fnBottomDist)(
1258 (mpSectFrm->GetUpper()->*fnRect->fnGetPrtBottom)() );
1259 (mpSectFrm->Frm().*fnRect->fnAddBottom)( nDiff );
1260 (mpSectFrm->*fnRect->fnSetYMargins)( nTopMargin, 0 );
1261 // --> OD 2006-05-08 #i59789#
1262 // suppress formatting, if printing area of section is too narrow
1263 if ( (mpSectFrm->Prt().*fnRect->fnGetHeight)() <= 0 )
1264 {
1265 return;
1266 }
1267 // <--
1268 mpSectFrm->ChgLowersProp( aOldSectPrtSize );
1269
1270 // format column frames and its body and footnote container
1271 SwColumnFrm* pColFrm = static_cast<SwColumnFrm*>(mpSectFrm->Lower());
1272 while ( pColFrm )
1273 {
1274 pColFrm->Calc();
1275 pColFrm->Lower()->Calc();
1276 if ( pColFrm->Lower()->GetNext() )
1277 {
1278 pColFrm->Lower()->GetNext()->Calc();
1279 }
1280
1281 pColFrm = static_cast<SwColumnFrm*>(pColFrm->GetNext());
1282 }
1283
1284 // unlock position of lower floating screen objects for the extra format
1285 // --> OD 2008-06-20 #i81555#
1286 // Section frame can already have changed the page and its content
1287 // can still be on the former page.
1288 // Thus, initialize objects via lower-relationship
1289 InitObjs( *mpSectFrm );
1290 // <--
1291
1292 // format content - first with collecting its foot-/endnotes before content
1293 // format, second without collecting its foot-/endnotes.
1294 ::CalcCntnt( mpSectFrm );
1295 ::CalcCntnt( mpSectFrm, true );
1296
1297 // keep locked position of lower floating screen objects
1298 SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
1299 SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
1300 if ( pObjs )
1301 {
1302 sal_uInt32 i = 0;
1303 for ( i = 0; i < pObjs->Count(); ++i )
1304 {
1305 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1306
1307 if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
1308 {
1309 pAnchoredObj->SetKeepPosLocked( true );
1310 }
1311 }
1312 }
1313
1314 mbExtraFormatPerformed = true;
1315 }
1316 }
1317 };
1318
1319 /*************************************************************************
1320 |*
1321 |* SwSectionFrm::Format()
1322 |*
1323 |* Beschreibung: "Formatiert" den Frame; Frm und PrtArea.
1324 |* Ersterstellung AMA 03. Dec. 97
1325 |* Letzte Aenderung MA 09. Oct. 98
1326 |*
1327 |*************************************************************************/
1328
Format(const SwBorderAttrs * pAttr)1329 void SwSectionFrm::Format( const SwBorderAttrs *pAttr )
1330 {
1331 if( !pSection ) // Durch DelEmpty
1332 {
1333 ASSERT( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
1334 bValidSize = bValidPos = bValidPrtArea = sal_True;
1335 return;
1336 }
1337 SWRECTFN( this )
1338 if ( !bValidPrtArea )
1339 {
1340 PROTOCOL( this, PROT_PRTAREA, 0, 0 )
1341 bValidPrtArea = sal_True;
1342 SwTwips nUpper = CalcUpperSpace();
1343
1344 // #109700# LRSpace for sections
1345 const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
1346 (this->*fnRect->fnSetXMargins)( rLRSpace.GetLeft(), rLRSpace.GetRight() );
1347
1348 if( nUpper != (this->*fnRect->fnGetTopMargin)() )
1349 {
1350 bValidSize = sal_False;
1351 SwFrm* pOwn = ContainsAny();
1352 if( pOwn )
1353 pOwn->_InvalidatePos();
1354 }
1355 (this->*fnRect->fnSetYMargins)( nUpper, 0 );
1356 }
1357
1358 if ( !bValidSize )
1359 {
1360 PROTOCOL_ENTER( this, PROT_SIZE, 0, 0 )
1361 const long nOldHeight = (Frm().*fnRect->fnGetHeight)();
1362 sal_Bool bOldLock = IsColLocked();
1363 ColLock();
1364
1365 bValidSize = sal_True;
1366
1367 //die Groesse wird nur dann vom Inhalt bestimmt, wenn der SectFrm
1368 //keinen Follow hat. Anderfalls fuellt er immer den Upper bis
1369 //zur Unterkante aus. Fuer den Textfluss ist nicht er, sondern sein
1370 //Inhalt selbst verantwortlich.
1371 sal_Bool bMaximize = ToMaximize( sal_False );
1372
1373 // OD 2004-05-17 #i28701# - If the wrapping style has to be considered
1374 // on object positioning, an extra formatting has to be performed
1375 // to determine the correct positions the floating screen objects.
1376 // --> OD 2005-01-11 #i40147#
1377 // use new helper class <ExtraFormatToPositionObjs>.
1378 // This class additionally keep the locked position of the objects
1379 // and releases this position lock keeping on destruction.
1380 ExtraFormatToPositionObjs aExtraFormatToPosObjs( *this );
1381 if ( !bMaximize &&
1382 GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
1383 !GetFmt()->GetBalancedColumns().GetValue() )
1384 {
1385 aExtraFormatToPosObjs.FormatSectionToPositionObjs();
1386 }
1387 // <--
1388
1389 // Column widths have to be adjusted before calling _CheckClipping.
1390 // _CheckClipping can cause the formatting of the lower frames
1391 // which still have a width of 0.
1392 const sal_Bool bHasColumns = Lower() && Lower()->IsColumnFrm();
1393 if ( bHasColumns && Lower()->GetNext() )
1394 AdjustColumns( 0, sal_False );
1395
1396 if( GetUpper() )
1397 {
1398 long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
1399 (aFrm.*fnRect->fnSetWidth)( nWidth );
1400
1401 // #109700# LRSpace for sections
1402 const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
1403 (aPrt.*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
1404 rLRSpace.GetRight() );
1405
1406 // OD 15.10.2002 #103517# - allow grow in online layout
1407 // Thus, set <..IsBrowseMode()> as parameter <bGrow> on calling
1408 // method <_CheckClipping(..)>.
1409 const ViewShell *pSh = getRootFrm()->GetCurrShell();
1410 _CheckClipping( pSh && pSh->GetViewOptions()->getBrowseMode(), bMaximize );
1411 bMaximize = ToMaximize( sal_False );
1412 bValidSize = sal_True;
1413 }
1414
1415 //Breite der Spalten pruefen und ggf. einstellen.
1416 if ( bHasColumns && ! Lower()->GetNext() && bMaximize )
1417 ((SwColumnFrm*)Lower())->Lower()->Calc();
1418
1419 if ( !bMaximize )
1420 {
1421 SwTwips nRemaining = (this->*fnRect->fnGetTopMargin)();
1422 SwFrm *pFrm = pLower;
1423 if( pFrm )
1424 {
1425 if( pFrm->IsColumnFrm() && pFrm->GetNext() )
1426 {
1427 // --> OD 2006-05-08 #i61435#
1428 // suppress formatting, if upper frame has height <= 0
1429 if ( (GetUpper()->Frm().*fnRect->fnGetHeight)() > 0 )
1430 {
1431 FormatWidthCols( *pAttr, nRemaining, MINLAY );
1432 }
1433 // <--
1434 // --> OD 2006-01-04 #126020# - adjust check for empty section
1435 // --> OD 2006-02-01 #130797# - correct fix #126020#
1436 while( HasFollow() && !GetFollow()->ContainsCntnt() &&
1437 !GetFollow()->ContainsAny( true ) )
1438 // <--
1439 {
1440 SwFrm* pOld = GetFollow();
1441 GetFollow()->DelEmpty( sal_False );
1442 if( pOld == GetFollow() )
1443 break;
1444 }
1445 bMaximize = ToMaximize( sal_False );
1446 nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
1447 }
1448 else
1449 {
1450 if( pFrm->IsColumnFrm() )
1451 {
1452 pFrm->Calc();
1453 pFrm = ((SwColumnFrm*)pFrm)->Lower();
1454 pFrm->Calc();
1455 pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1456 CalcFtnCntnt();
1457 }
1458 // Wenn wir in einem spaltigen Rahmen stehen und dieser
1459 // gerade im FormatWidthCols ein CalcCntnt ruft, muss
1460 // unser Inhalt ggf. kalkuliert werden.
1461 if( pFrm && !pFrm->IsValid() && IsInFly() &&
1462 FindFlyFrm()->IsColLocked() )
1463 ::CalcCntnt( this );
1464 nRemaining += InnerHeight();
1465 bMaximize = HasFollow();
1466 }
1467 }
1468
1469 SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
1470 if( nDiff < 0)
1471 {
1472 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
1473 {
1474 long nBottom = (Frm().*fnRect->fnGetBottom)();
1475 nBottom = (*fnRect->fnYInc)( nBottom, -nDiff );
1476 long nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
1477 if( nTmpDiff > 0 )
1478 {
1479 nTmpDiff = GetUpper()->Grow( nTmpDiff, sal_True );
1480 nDeadLine = (*fnRect->fnYInc)( nDeadLine, nTmpDiff );
1481 nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
1482 if( nTmpDiff > 0 )
1483 nDiff += nTmpDiff;
1484 if( nDiff > 0 )
1485 nDiff = 0;
1486 }
1487 }
1488 }
1489 if( nDiff )
1490 {
1491 long nTmp = nRemaining - (Frm().*fnRect->fnGetHeight)();
1492 long nTop = (this->*fnRect->fnGetTopMargin)();
1493 (Frm().*fnRect->fnAddBottom)( nTmp );
1494 (this->*fnRect->fnSetYMargins)( nTop, 0 );
1495 InvalidateNextPos();
1496 if( pLower && ( !pLower->IsColumnFrm() || !pLower->GetNext() ) )
1497 {
1498 // Wenn ein einspaltiger Bereich gerade den Platz geschaffen
1499 // hat, den sich die "undersized" Absaetze gewuenscht haben,
1500 // muessen diese invalidiert und kalkuliert werden, damit
1501 // sie diesen ausfuellen.
1502 pFrm = pLower;
1503 if( pFrm->IsColumnFrm() )
1504 {
1505 pFrm->_InvalidateSize();
1506 pFrm->_InvalidatePos();
1507 pFrm->Calc();
1508 pFrm = ((SwColumnFrm*)pFrm)->Lower();
1509 pFrm->Calc();
1510 pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1511 CalcFtnCntnt();
1512 }
1513 sal_Bool bUnderSz = sal_False;
1514 while( pFrm )
1515 {
1516 if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
1517 {
1518 pFrm->Prepare( PREP_ADJUST_FRM );
1519 bUnderSz = sal_True;
1520 }
1521 pFrm = pFrm->GetNext();
1522 }
1523 if( bUnderSz && !IsCntntLocked() )
1524 ::CalcCntnt( this );
1525 }
1526 }
1527 }
1528
1529 //Unterkante des Uppers nicht ueberschreiten. Fuer Sections mit
1530 //Follows die Unterkante auch nicht unterschreiten.
1531 if ( GetUpper() )
1532 _CheckClipping( sal_True, bMaximize );
1533 if( !bOldLock )
1534 ColUnlock();
1535 long nDiff = nOldHeight - (Frm().*fnRect->fnGetHeight)();
1536 if( nDiff > 0 )
1537 {
1538 if( !GetNext() )
1539 SetRetouche(); // Dann muessen wir die Retusche selbst uebernehmen
1540 if( GetUpper() && !GetUpper()->IsFooterFrm() )
1541 GetUpper()->Shrink( nDiff );
1542 }
1543 if( IsUndersized() )
1544 bValidPrtArea = sal_True;
1545 }
1546 }
1547
1548 /*************************************************************************
1549 |*
1550 |* SwFrm::GetNextSctLeaf()
1551 |*
1552 |* Beschreibung Liefert das naechste Layoutblatt in das der Frame
1553 |* gemoved werden kann.
1554 |* Neue Seiten werden nur dann erzeugt, wenn der Parameter sal_True ist.
1555 |* Ersterstellung AMA 07. Jan. 98
1556 |* Letzte Aenderung AMA 07. Jan. 98
1557 |*
1558 |*************************************************************************/
1559
1560
GetNextSctLeaf(MakePageType eMakePage)1561 SwLayoutFrm *SwFrm::GetNextSctLeaf( MakePageType eMakePage )
1562 {
1563 //Achtung: Geschachtelte Bereiche werden zur Zeit nicht unterstuetzt.
1564
1565 PROTOCOL_ENTER( this, PROT_LEAF, ACT_NEXT_SECT, GetUpper()->FindSctFrm() )
1566
1567 // Abkuerzungen fuer spaltige Bereiche, wenn wir noch nicht in der letzten Spalte sind.
1568 // Koennen wir in die naechste Spalte des Bereichs rutschen?
1569 if( IsColBodyFrm() && GetUpper()->GetNext() )
1570 return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetNext())->Lower();
1571 if( GetUpper()->IsColBodyFrm() && GetUpper()->GetUpper()->GetNext() )
1572 return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetUpper()->GetNext())->Lower();
1573 // Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann
1574 // nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette zuschlagen muessen
1575 if( GetUpper()->IsInTab() || FindFooterOrHeader() )
1576 return 0;
1577
1578 //MA 03. Feb. 99: Warum GetUpper()? Das knallt mit Buch.sgl weil im
1579 //FlyAtCnt::MakeFlyPos ein Orient der SectionFrm ist und auf diesen ein
1580 //GetLeaf gerufen wird.
1581 // SwSectionFrm *pSect = GetUpper()->FindSctFrm();
1582 SwSectionFrm *pSect = FindSctFrm();
1583 sal_Bool bWrongPage = sal_False;
1584 ASSERT( pSect, "GetNextSctLeaf: Missing SectionFrm" );
1585
1586 // Hier eine Abkuerzung fuer Bereiche mit Follows,
1587 // dieser kann akzeptiert werden, wenn keine Spalten oder Seiten (ausser Dummyseiten)
1588 // dazwischen liegen.
1589 // Bei verketteten Rahmen und ind Fussnoten wuerde die Abkuerzung noch aufwendiger
1590 if( pSect->HasFollow() && pSect->IsInDocBody() )
1591 {
1592 if( pSect->GetFollow() == pSect->GetNext() )
1593 {
1594 SwPageFrm *pPg = pSect->GetFollow()->FindPageFrm();
1595 if( WrongPageDesc( pPg ) )
1596 bWrongPage = sal_True;
1597 else
1598 return FIRSTLEAF( pSect->GetFollow() );
1599 }
1600 else
1601 {
1602 SwFrm* pTmp;
1603 if( !pSect->GetUpper()->IsColBodyFrm() ||
1604 0 == ( pTmp = pSect->GetUpper()->GetUpper()->GetNext() ) )
1605 pTmp = pSect->FindPageFrm()->GetNext();
1606 if( pTmp ) // ist jetzt die naechste Spalte oder Seite
1607 {
1608 SwFrm* pTmpX = pTmp;
1609 if( pTmp->IsPageFrm() && ((SwPageFrm*)pTmp)->IsEmptyPage() )
1610 pTmp = pTmp->GetNext(); // Dummyseiten ueberspringen
1611 SwFrm *pUp = pSect->GetFollow()->GetUpper();
1612 // pUp wird die Spalte, wenn der Follow in einer "nicht ersten" Spalte
1613 // liegt, ansonsten die Seite:
1614 if( !pUp->IsColBodyFrm() ||
1615 !( pUp = pUp->GetUpper() )->GetPrev() )
1616 pUp = pUp->FindPageFrm();
1617 // Jetzt muessen pUp und pTmp die gleiche Seite/Spalte sein,
1618 // sonst liegen Seiten oder Spalten zwischen Master und Follow.
1619 if( pUp == pTmp || pUp->GetNext() == pTmpX )
1620 {
1621 SwPageFrm* pNxtPg = pUp->IsPageFrm() ?
1622 (SwPageFrm*)pUp : pUp->FindPageFrm();
1623 if( WrongPageDesc( pNxtPg ) )
1624 bWrongPage = sal_True;
1625 else
1626 return FIRSTLEAF( pSect->GetFollow() );
1627 }
1628 }
1629 }
1630 }
1631
1632 // Immer im gleichen Bereich landen: Body wieder in Body etc.
1633 const sal_Bool bBody = IsInDocBody();
1634 const sal_Bool bFtnPage = FindPageFrm()->IsFtnPage();
1635
1636 SwLayoutFrm *pLayLeaf;
1637 // Eine Abkuerzung fuer TabFrms, damit nicht alle Zellen abgehuehnert werden
1638 if( bWrongPage )
1639 pLayLeaf = 0;
1640 else if( IsTabFrm() )
1641 {
1642 SwCntntFrm* pTmpCnt = ((SwTabFrm*)this)->FindLastCntnt();
1643 pLayLeaf = pTmpCnt ? pTmpCnt->GetUpper() : 0;
1644 }
1645 else
1646 {
1647 pLayLeaf = GetNextLayoutLeaf();
1648 if( IsColumnFrm() )
1649 {
1650 while( pLayLeaf && ((SwColumnFrm*)this)->IsAnLower( pLayLeaf ) )
1651 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1652 }
1653 }
1654
1655 SwLayoutFrm *pOldLayLeaf = 0; //Damit bei neu erzeugten Seiten
1656 //nicht wieder vom Anfang gesucht
1657 //wird.
1658
1659 while( sal_True )
1660 {
1661 if( pLayLeaf )
1662 {
1663 // Ein Layoutblatt wurde gefunden, mal sehen, ob er mich aufnehmen kann,
1664 // ob hier ein weiterer SectionFrm eingefuegt werden kann
1665 // oder ob wir weitersuchen muessen.
1666 SwPageFrm* pNxtPg = pLayLeaf->FindPageFrm();
1667 if ( !bFtnPage && pNxtPg->IsFtnPage() )
1668 { //Wenn ich bei den Endnotenseiten angelangt bin hat sichs.
1669 pLayLeaf = 0;
1670 continue;
1671 }
1672 // Einmal InBody, immer InBody, nicht in Tabellen hinein
1673 // und nicht in fremde Bereiche hinein
1674 if ( (bBody && !pLayLeaf->IsInDocBody()) ||
1675 (IsInFtn() != pLayLeaf->IsInFtn() ) ||
1676 pLayLeaf->IsInTab() ||
1677 ( pLayLeaf->IsInSct() && ( !pSect->HasFollow()
1678 || pSect->GetFollow() != pLayLeaf->FindSctFrm() ) ) )
1679 {
1680 //Er will mich nicht; neuer Versuch, neues Glueck
1681 pOldLayLeaf = pLayLeaf;
1682 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1683 continue;
1684 }
1685 if( WrongPageDesc( pNxtPg ) )
1686 {
1687 if( bWrongPage )
1688 break; // there's a column between me and my right page
1689 pLayLeaf = 0;
1690 bWrongPage = sal_True;
1691 pOldLayLeaf = 0;
1692 continue;
1693 }
1694 }
1695 //Es gibt keinen passenden weiteren LayoutFrm, also muss eine
1696 //neue Seite her, allerdings nuetzen uns innerhalb eines Rahmens
1697 //neue Seiten nichts.
1698 else if( !pSect->IsInFly() &&
1699 ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
1700 {
1701 InsertPage(pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
1702 sal_False );
1703 //und nochmal das ganze
1704 pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
1705 continue;
1706 }
1707 break;
1708 }
1709
1710 if( pLayLeaf )
1711 {
1712 // Das passende Layoutblatt haben wir gefunden, wenn es dort bereits einen
1713 // Follow unseres Bereichs gibt, nehmen wir dessen erstes Layoutblatt,
1714 // andernfalls wird es Zeit, einen Bereichsfollow zu erzeugen
1715 SwSectionFrm* pNew;
1716
1717 //Dies kann entfallen, wenn bei existierenden Follows bereits abgekuerzt wurde
1718 SwFrm* pFirst = pLayLeaf->Lower();
1719 // Auch hier muessen zum Loeschen angemeldete SectionFrms ignoriert werden
1720 while( pFirst && pFirst->IsSctFrm() && !((SwSectionFrm*)pFirst)->GetSection() )
1721 pFirst = pFirst->GetNext();
1722 if( pFirst && pFirst->IsSctFrm() && pSect->GetFollow() == pFirst )
1723 pNew = pSect->GetFollow();
1724 else if( MAKEPAGE_NOSECTION == eMakePage )
1725 return pLayLeaf;
1726 else
1727 {
1728 pNew = new SwSectionFrm( *pSect, sal_False );
1729 pNew->InsertBefore( pLayLeaf, pLayLeaf->Lower() );
1730 pNew->Init();
1731 SWRECTFN( pNew )
1732 (pNew->*fnRect->fnMakePos)( pLayLeaf, NULL, sal_True );
1733
1734 // Wenn unser Bereichsframe einen Nachfolger hat, so muss dieser
1735 // umgehaengt werden hinter den neuen Follow der Bereichsframes.
1736 SwFrm* pTmp = pSect->GetNext();
1737 if( pTmp && pTmp != pSect->GetFollow() )
1738 {
1739 SwFlowFrm* pNxt;
1740 SwCntntFrm* pNxtCntnt = NULL;
1741 if( pTmp->IsCntntFrm() )
1742 {
1743 pNxt = (SwCntntFrm*)pTmp;
1744 pNxtCntnt = (SwCntntFrm*)pTmp;
1745 }
1746 else
1747 {
1748 pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
1749 if( pTmp->IsSctFrm() )
1750 pNxt = (SwSectionFrm*)pTmp;
1751 else
1752 {
1753 ASSERT( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
1754 pNxt = (SwTabFrm*)pTmp;
1755 }
1756 while( !pNxtCntnt && 0 != ( pTmp = pTmp->GetNext() ) )
1757 {
1758 if( pTmp->IsCntntFrm() )
1759 pNxtCntnt = (SwCntntFrm*)pTmp;
1760 else
1761 pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
1762 }
1763 }
1764 if( pNxtCntnt )
1765 {
1766 SwFtnBossFrm* pOldBoss = pSect->FindFtnBossFrm( sal_True );
1767 if( pOldBoss == pNxtCntnt->FindFtnBossFrm( sal_True ) )
1768 {
1769 SwSaveFtnHeight aHeight( pOldBoss,
1770 pOldBoss->Frm().Top() + pOldBoss->Frm().Height() );
1771 pSect->GetUpper()->MoveLowerFtns( pNxtCntnt, pOldBoss,
1772 pLayLeaf->FindFtnBossFrm( sal_True ), sal_False );
1773 }
1774 }
1775 ((SwFlowFrm*)pNxt)->MoveSubTree( pLayLeaf, pNew->GetNext() );
1776 }
1777 if( pNew->GetFollow() )
1778 pNew->SimpleFormat();
1779 }
1780 // Das gesuchte Layoutblatt ist jetzt das erste des ermittelten SctFrms:
1781 pLayLeaf = FIRSTLEAF( pNew );
1782 }
1783 return pLayLeaf;
1784 }
1785
1786 /*************************************************************************
1787 |*
1788 |* SwFrm::GetPrevSctLeaf()
1789 |*
1790 |* Beschreibung Liefert das vorhergehende LayoutBlatt in das der
1791 |* Frame gemoved werden kann.
1792 |* Ersterstellung AMA 07. Jan. 98
1793 |* Letzte Aenderung AMA 07. Jan. 98
1794 |*
1795 |*************************************************************************/
1796
1797
GetPrevSctLeaf(MakePageType)1798 SwLayoutFrm *SwFrm::GetPrevSctLeaf( MakePageType )
1799 {
1800 PROTOCOL_ENTER( this, PROT_LEAF, ACT_PREV_SECT, GetUpper()->FindSctFrm() )
1801
1802 SwLayoutFrm* pCol;
1803 // ColumnFrm beinhalten jetzt stets einen BodyFrm
1804 if( IsColBodyFrm() )
1805 pCol = GetUpper();
1806 else if( GetUpper()->IsColBodyFrm() )
1807 pCol = GetUpper()->GetUpper();
1808 else
1809 pCol = NULL;
1810 sal_Bool bJump = sal_False;
1811 if( pCol )
1812 {
1813 if( pCol->GetPrev() )
1814 {
1815 do
1816 {
1817 pCol = (SwLayoutFrm*)pCol->GetPrev();
1818 // Gibt es dort Inhalt?
1819 if( ((SwLayoutFrm*)pCol->Lower())->Lower() )
1820 {
1821 if( bJump ) // Haben wir eine leere Spalte uebersprungen?
1822 SwFlowFrm::SetMoveBwdJump( sal_True );
1823 return (SwLayoutFrm*)pCol->Lower(); // Der Spaltenbody
1824 }
1825 bJump = sal_True;
1826 } while( pCol->GetPrev() );
1827
1828 // Hier landen wir, wenn alle Spalten leer sind,
1829 // pCol ist jetzt die erste Spalte, wir brauchen aber den Body:
1830 pCol = (SwLayoutFrm*)pCol->Lower();
1831 }
1832 else
1833 pCol = NULL;
1834 }
1835
1836 if( bJump ) // Haben wir eine leere Spalte uebersprungen?
1837 SwFlowFrm::SetMoveBwdJump( sal_True );
1838
1839 // Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann
1840 // nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette
1841 // zuschlagen muessen, ebenso wenn der Bereich einen pPrev hat.
1842 // Jetzt ziehen wir sogar eine leere Spalte in Betracht...
1843 ASSERT( FindSctFrm(), "GetNextSctLeaf: Missing SectionFrm" );
1844 if( ( IsInTab() && !IsTabFrm() ) || FindFooterOrHeader() )
1845 return pCol;
1846
1847 // === IMPORTANT ===
1848 // Precondition, which needs to be hold, is that the <this> frame can be
1849 // inside a table, but then the found section frame <pSect> is also inside
1850 // this table.
1851 SwSectionFrm *pSect = FindSctFrm();
1852
1853 // --> OD 2009-01-16 #i95698#
1854 // A table cell containing directly a section does not break - see lcl_FindSectionsInRow(..)
1855 // Thus, a table inside a section, which is inside another table can only
1856 // flow backward in the columns of its section.
1857 // Note: The table cell, which contains the section, can not have a master table cell.
1858 if ( IsTabFrm() && pSect->IsInTab() )
1859 {
1860 return pCol;
1861 }
1862 // <--
1863
1864 {
1865 SwFrm *pPrv;
1866 if( 0 != ( pPrv = pSect->GetIndPrev() ) )
1867 {
1868 // Herumlungernde, halbtote SectionFrms sollen uns nicht beirren
1869 while( pPrv && pPrv->IsSctFrm() && !((SwSectionFrm*)pPrv)->GetSection() )
1870 pPrv = pPrv->GetPrev();
1871 if( pPrv )
1872 return pCol;
1873 }
1874 }
1875
1876 const sal_Bool bBody = IsInDocBody();
1877 const sal_Bool bFly = IsInFly();
1878
1879 SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
1880 SwLayoutFrm *pPrevLeaf = 0;
1881
1882 while ( pLayLeaf )
1883 {
1884 //In Tabellen oder Bereiche geht's niemals hinein.
1885 if ( pLayLeaf->IsInTab() || pLayLeaf->IsInSct() )
1886 {
1887 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1888 }
1889 else if ( bBody && pLayLeaf->IsInDocBody() )
1890 {
1891 // If there is a pLayLeaf has a lower pLayLeaf is the frame we are looking for.
1892 // Exception: pLayLeaf->Lower() is a zombie section frame
1893 const SwFrm* pTmp = pLayLeaf->Lower();
1894 // OD 11.04.2003 #108824# - consider, that the zombie section frame
1895 // can have frame below it in the found layout leaf.
1896 // Thus, skipping zombie section frame, if possible.
1897 while ( pTmp && pTmp->IsSctFrm() &&
1898 !( static_cast<const SwSectionFrm*>(pTmp)->GetSection() ) &&
1899 pTmp->GetNext()
1900 )
1901 {
1902 pTmp = pTmp->GetNext();
1903 }
1904 if ( pTmp &&
1905 ( !pTmp->IsSctFrm() ||
1906 ( static_cast<const SwSectionFrm*>(pTmp)->GetSection() )
1907 )
1908 )
1909 {
1910 break;
1911 }
1912 pPrevLeaf = pLayLeaf;
1913 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1914 if ( pLayLeaf )
1915 SwFlowFrm::SetMoveBwdJump( sal_True );
1916 }
1917 else if ( bFly )
1918 break; //Cntnts in Flys sollte jedes Layout-Blatt recht sein. Warum?
1919 else
1920 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1921 }
1922 if( !pLayLeaf )
1923 {
1924 if( !pPrevLeaf )
1925 return pCol;
1926 pLayLeaf = pPrevLeaf;
1927 }
1928
1929 SwSectionFrm* pNew = NULL;
1930 // Zunaechst einmal an das Ende des Layoutblatts gehen
1931 SwFrm *pTmp = pLayLeaf->Lower();
1932 if( pTmp )
1933 {
1934 while( pTmp->GetNext() )
1935 pTmp = pTmp->GetNext();
1936 if( pTmp->IsSctFrm() )
1937 {
1938 // Halbtote stoeren hier nur...
1939 while( !((SwSectionFrm*)pTmp)->GetSection() && pTmp->GetPrev() &&
1940 pTmp->GetPrev()->IsSctFrm() )
1941 pTmp = pTmp->GetPrev();
1942 if( ((SwSectionFrm*)pTmp)->GetFollow() == pSect )
1943 pNew = (SwSectionFrm*)pTmp;
1944 }
1945 }
1946 if( !pNew )
1947 {
1948 pNew = new SwSectionFrm( *pSect, sal_True );
1949 pNew->InsertBefore( pLayLeaf, NULL );
1950 pNew->Init();
1951 SWRECTFN( pNew )
1952 (pNew->*fnRect->fnMakePos)( pLayLeaf, pNew->GetPrev(), sal_True );
1953
1954 pLayLeaf = FIRSTLEAF( pNew );
1955 if( !pNew->Lower() ) // einspaltige Bereiche formatieren
1956 {
1957 pNew->MakePos();
1958 pLayLeaf->Format(); // damit die PrtArea fuers MoveBwd stimmt
1959 }
1960 else
1961 pNew->SimpleFormat();
1962 }
1963 else
1964 {
1965 pLayLeaf = FIRSTLEAF( pNew );
1966 if( pLayLeaf->IsColBodyFrm() )
1967 {
1968 // In existent section columns we're looking for the last not empty
1969 // column.
1970 SwLayoutFrm *pTmpLay = pLayLeaf;
1971 while( pLayLeaf->GetUpper()->GetNext() )
1972 {
1973 pLayLeaf = (SwLayoutFrm*)((SwLayoutFrm*)pLayLeaf->GetUpper()->GetNext())->Lower();
1974 if( pLayLeaf->Lower() )
1975 pTmpLay = pLayLeaf;
1976 }
1977 // If we skipped an empty column, we've to set the jump-flag
1978 if( pLayLeaf != pTmpLay )
1979 {
1980 pLayLeaf = pTmpLay;
1981 SwFlowFrm::SetMoveBwdJump( sal_True );
1982 }
1983 }
1984 }
1985 return pLayLeaf;
1986 }
1987
lcl_DeadLine(const SwFrm * pFrm)1988 SwTwips lcl_DeadLine( const SwFrm* pFrm )
1989 {
1990 const SwLayoutFrm* pUp = pFrm->GetUpper();
1991 while( pUp && pUp->IsInSct() )
1992 {
1993 if( pUp->IsSctFrm() )
1994 pUp = pUp->GetUpper();
1995 // Spalten jetzt mit BodyFrm
1996 else if( pUp->IsColBodyFrm() && pUp->GetUpper()->GetUpper()->IsSctFrm() )
1997 pUp = pUp->GetUpper()->GetUpper();
1998 else
1999 break;
2000 }
2001 SWRECTFN( pFrm )
2002 return pUp ? (pUp->*fnRect->fnGetPrtBottom)() :
2003 (pFrm->Frm().*fnRect->fnGetBottom)();
2004 }
2005
2006 // SwSectionFrm::Growable(..) prueft, ob der SectionFrm noch wachsen kann,
2007 // ggf. muss die Umgebung gefragt werden
2008
Growable() const2009 sal_Bool SwSectionFrm::Growable() const
2010 {
2011 SWRECTFN( this )
2012 if( (*fnRect->fnYDiff)( lcl_DeadLine( this ),
2013 (Frm().*fnRect->fnGetBottom)() ) > 0 )
2014 return sal_True;
2015
2016 return ( GetUpper() && ((SwFrm*)GetUpper())->Grow( LONG_MAX, sal_True ) );
2017 }
2018
2019 /*************************************************************************
2020 |*
2021 |* SwSectionFrm::_Grow(), _Shrink()
2022 |*
2023 |* Ersterstellung AMA 14. Jan. 98
2024 |* Letzte Aenderung AMA 14. Jan. 98
2025 |*
2026 |*************************************************************************/
2027
_Grow(SwTwips nDist,sal_Bool bTst)2028 SwTwips SwSectionFrm::_Grow( SwTwips nDist, sal_Bool bTst )
2029 {
2030 if ( !IsColLocked() && !HasFixSize() )
2031 {
2032 SWRECTFN( this )
2033 long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2034 if( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
2035 nDist = LONG_MAX - nFrmHeight;
2036
2037 if ( nDist <= 0L )
2038 return 0L;
2039
2040 sal_Bool bInCalcCntnt = GetUpper() && IsInFly() && FindFlyFrm()->IsLocked();
2041 // OD 2004-03-15 #116561# - allow grow in online layout
2042 sal_Bool bGrow = !Lower() || !Lower()->IsColumnFrm() || !Lower()->GetNext() ||
2043 GetSection()->GetFmt()->GetBalancedColumns().GetValue();
2044 if( !bGrow )
2045 {
2046 const ViewShell *pSh = getRootFrm()->GetCurrShell();
2047 bGrow = pSh && pSh->GetViewOptions()->getBrowseMode();
2048 }
2049 if( bGrow )
2050 {
2051 SwTwips nGrow;
2052 if( IsInFtn() )
2053 nGrow = 0;
2054 else
2055 {
2056 nGrow = lcl_DeadLine( this );
2057 nGrow = (*fnRect->fnYDiff)( nGrow,
2058 (Frm().*fnRect->fnGetBottom)() );
2059 }
2060 SwTwips nSpace = nGrow;
2061 if( !bInCalcCntnt && nGrow < nDist && GetUpper() )
2062 nGrow += GetUpper()->Grow( LONG_MAX, sal_True );
2063
2064 if( nGrow > nDist )
2065 nGrow = nDist;
2066 if( nGrow <= 0 )
2067 {
2068 nGrow = 0;
2069 if( nDist && !bTst )
2070 {
2071 if( bInCalcCntnt )
2072 _InvalidateSize();
2073 else
2074 InvalidateSize();
2075 }
2076 }
2077 else if( !bTst )
2078 {
2079 if( bInCalcCntnt )
2080 _InvalidateSize();
2081 else if( nSpace < nGrow && nDist != nSpace + GetUpper()->
2082 Grow( nGrow - nSpace, sal_False ) )
2083 InvalidateSize();
2084 else
2085 {
2086 const SvxGraphicPosition ePos =
2087 GetAttrSet()->GetBackground().GetGraphicPos();
2088 if ( GPOS_RT < ePos && GPOS_TILED != ePos )
2089 {
2090 SetCompletePaint();
2091 InvalidatePage();
2092 }
2093 if( GetUpper() && GetUpper()->IsHeaderFrm() )
2094 GetUpper()->InvalidateSize();
2095 }
2096 (Frm().*fnRect->fnAddBottom)( nGrow );
2097 long nPrtHeight = (Prt().*fnRect->fnGetHeight)() + nGrow;
2098 (Prt().*fnRect->fnSetHeight)( nPrtHeight );
2099
2100 if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2101 {
2102 SwFrm* pTmp = Lower();
2103 do
2104 {
2105 pTmp->_InvalidateSize();
2106 pTmp = pTmp->GetNext();
2107 } while ( pTmp );
2108 _InvalidateSize();
2109 }
2110 if( GetNext() )
2111 {
2112 SwFrm *pFrm = GetNext();
2113 while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
2114 pFrm = pFrm->GetNext();
2115 if( pFrm )
2116 {
2117 if( bInCalcCntnt )
2118 pFrm->_InvalidatePos();
2119 else
2120 pFrm->InvalidatePos();
2121 }
2122 }
2123 // --> OD 2004-07-05 #i28701# - Due to the new object positioning
2124 // the frame on the next page/column can flow backward (e.g. it
2125 // was moved forward due to the positioning of its objects ).
2126 // Thus, invalivate this next frame, if document compatibility
2127 // option 'Consider wrapping style influence on object positioning' is ON.
2128 else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
2129 {
2130 InvalidateNextPos();
2131 }
2132 // <--
2133 }
2134 return nGrow;
2135 }
2136 if ( !bTst )
2137 {
2138 if( bInCalcCntnt )
2139 _InvalidateSize();
2140 else
2141 InvalidateSize();
2142 }
2143 }
2144 return 0L;
2145 }
2146
_Shrink(SwTwips nDist,sal_Bool bTst)2147 SwTwips SwSectionFrm::_Shrink( SwTwips nDist, sal_Bool bTst )
2148 {
2149 if ( Lower() && !IsColLocked() && !HasFixSize() )
2150 {
2151 if( ToMaximize( sal_False ) )
2152 {
2153 if( !bTst )
2154 InvalidateSize();
2155 }
2156 else
2157 {
2158 SWRECTFN( this )
2159 long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2160 if ( nDist > nFrmHeight )
2161 nDist = nFrmHeight;
2162
2163 if ( Lower()->IsColumnFrm() && Lower()->GetNext() && // FtnAtEnd
2164 !GetSection()->GetFmt()->GetBalancedColumns().GetValue() )
2165 { //Bei Spaltigkeit ubernimmt das Format die Kontrolle ueber
2166 //das Wachstum (wg. des Ausgleichs).
2167 if ( !bTst )
2168 InvalidateSize();
2169 return nDist;
2170 }
2171 else if( !bTst )
2172 {
2173 const SvxGraphicPosition ePos =
2174 GetAttrSet()->GetBackground().GetGraphicPos();
2175 if ( GPOS_RT < ePos && GPOS_TILED != ePos )
2176 {
2177 SetCompletePaint();
2178 InvalidatePage();
2179 }
2180 (Frm().*fnRect->fnAddBottom)( -nDist );
2181 long nPrtHeight = (Prt().*fnRect->fnGetHeight)() - nDist;
2182 (Prt().*fnRect->fnSetHeight)( nPrtHeight );
2183
2184 SwTwips nReal = 0;
2185 // We do not allow a section frame to shrink the its upper
2186 // footer frame. This is because in the calculation of a
2187 // footer frame, the content of the section frame is _not_
2188 // calculated. If there is a fly frame overlapping with the
2189 // footer frame, the section frame is not affected by this
2190 // during the calculation of the footer frame size.
2191 // The footer frame does not grow in its FormatSize function
2192 // but during the calculation of the content of the section
2193 // frame. The section frame grows until some of its text is
2194 // located on top of the fly frame. The next call of CalcCntnt
2195 // tries to shrink the section and here it would also shrink
2196 // the footer. This may not happen, because shrinking the footer
2197 // would cause the top of the section frame to overlap with the
2198 // fly frame again, this would result in a perfect loop.
2199 if( GetUpper() && !GetUpper()->IsFooterFrm() )
2200 nReal = GetUpper()->Shrink( nDist, bTst );
2201
2202 if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2203 {
2204 SwFrm* pTmp = Lower();
2205 do
2206 {
2207 pTmp->_InvalidateSize();
2208 pTmp = pTmp->GetNext();
2209 } while ( pTmp );
2210 }
2211 if( GetNext() )
2212 {
2213 SwFrm* pFrm = GetNext();
2214 while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
2215 pFrm = pFrm->GetNext();
2216 if( pFrm )
2217 pFrm->InvalidatePos();
2218 else
2219 SetRetouche();
2220 }
2221 else
2222 SetRetouche();
2223 return nDist;
2224 }
2225 }
2226 }
2227 return 0L;
2228 }
2229
2230 /*************************************************************************
2231 |*
2232 |* SwSectionFrm::MoveAllowed()
2233 |*
2234 |* Ersterstellung MA 08. Oct. 98
2235 |* Letzte Aenderung MA 08. Oct. 98
2236 |*
2237 |* Wann sind Frms innerhalb eines SectionFrms moveable?
2238 |* Wenn sie noch nicht in der letzten Spalte des SectionFrms sind,
2239 |* wenn es einen Follow gibt,
2240 |* wenn der SectionFrm nicht mehr wachsen kann, wird es komplizierter,
2241 |* dann kommt es darauf an, ob der SectionFrm ein naechstes Layoutblatt
2242 |* finden kann. In (spaltigen/verketteten) Flys wird dies via GetNextLayout
2243 |* geprueft, in Tabellen und in Kopf/Fusszeilen gibt es keins, im DocBody
2244 |* und auch im Fussnoten dagegen immer.
2245 |*
2246 |* Benutzt wird diese Routine im TxtFormatter, um zu entscheiden, ob ein
2247 |* (Absatz-)Follow erzeugt werden darf oder ob der Absatz zusammenhalten muss.
2248 |*
2249 |*************************************************************************/
2250
MoveAllowed(const SwFrm * pFrm) const2251 sal_Bool SwSectionFrm::MoveAllowed( const SwFrm* pFrm) const
2252 {
2253 // Gibt es einen Follow oder ist der Frame nicht in der letzten Spalte?
2254 if( HasFollow() || ( pFrm->GetUpper()->IsColBodyFrm() &&
2255 pFrm->GetUpper()->GetUpper()->GetNext() ) )
2256 return sal_True;
2257 if( pFrm->IsInFtn() )
2258 {
2259 if( IsInFtn() )
2260 {
2261 if( GetUpper()->IsInSct() )
2262 {
2263 if( Growable() )
2264 return sal_False;
2265 return GetUpper()->FindSctFrm()->MoveAllowed( this );
2266 }
2267 else
2268 return sal_True;
2269 }
2270 // The content of footnote inside a columned sectionfrm is moveable
2271 // except in the last column
2272 const SwLayoutFrm *pLay = pFrm->FindFtnFrm()->GetUpper()->GetUpper();
2273 if( pLay->IsColumnFrm() && pLay->GetNext() )
2274 {
2275 // The first paragraph in the first footnote in the first column
2276 // in the sectionfrm at the top of the page is not moveable,
2277 // if the columnbody is empty.
2278 sal_Bool bRet = sal_False;
2279 if( pLay->GetIndPrev() || pFrm->GetIndPrev() ||
2280 pFrm->FindFtnFrm()->GetPrev() )
2281 bRet = sal_True;
2282 else
2283 {
2284 SwLayoutFrm* pBody = ((SwColumnFrm*)pLay)->FindBodyCont();
2285 if( pBody && pBody->Lower() )
2286 bRet = sal_True;
2287 }
2288 if( bRet && ( IsFtnAtEnd() || !Growable() ) )
2289 return sal_True;
2290 }
2291 }
2292 // Oder kann der Bereich noch wachsen?
2293 if( !IsColLocked() && Growable() )
2294 return sal_False;
2295 // Jetzt muss untersucht werden, ob es ein Layoutblatt gibt, in dem
2296 // ein Bereichsfollow erzeugt werden kann.
2297 if( IsInTab() || ( !IsInDocBody() && FindFooterOrHeader() ) )
2298 return sal_False; // In Tabellen/Kopf/Fusszeilen geht es nicht
2299 if( IsInFly() ) // Bei spaltigen oder verketteten Rahmen
2300 return 0 != ((SwFrm*)GetUpper())->GetNextLeaf( MAKEPAGE_NONE );
2301 return sal_True;
2302 }
2303
2304 /** Called for a frame inside a section with no direct previous frame (or only
2305 previous empty section frames) the previous frame of the outer section is
2306 returned, if the frame is the first flowing content of this section.
2307
2308 Note: For a frame inside a table frame, which is inside a section frame,
2309 NULL is returned.
2310 */
_GetIndPrev() const2311 SwFrm* SwFrm::_GetIndPrev() const
2312 {
2313 SwFrm *pRet = NULL;
2314 // --> OD 2007-09-04 #i79774#, #b659654#
2315 // Do not assert, if the frame has a direct previous frame, because it
2316 // could be an empty section frame. The caller has to assure, that the
2317 // frame has no direct previous frame or only empty section frames as
2318 // previous frames.
2319 ASSERT( /*!pPrev &&*/ IsInSct(), "Why?" );
2320 // <--
2321 const SwFrm* pSct = GetUpper();
2322 if( !pSct )
2323 return NULL;
2324 if( pSct->IsSctFrm() )
2325 pRet = pSct->GetIndPrev();
2326 else if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
2327 {
2328 // Do not return the previous frame of the outer section, if in one
2329 // of the previous columns is content.
2330 const SwFrm* pCol = GetUpper()->GetUpper()->GetPrev();
2331 while( pCol )
2332 {
2333 ASSERT( pCol->IsColumnFrm(), "GetIndPrev(): ColumnFrm expected" );
2334 ASSERT( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
2335 "GetIndPrev(): Where's the body?");
2336 if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
2337 return NULL;
2338 pCol = pCol->GetPrev();
2339 }
2340 pRet = pSct->GetIndPrev();
2341 }
2342
2343 // skip empty section frames
2344 while( pRet && pRet->IsSctFrm() && !((SwSectionFrm*)pRet)->GetSection() )
2345 pRet = pRet->GetIndPrev();
2346 return pRet;
2347 }
2348
_GetIndNext()2349 SwFrm* SwFrm::_GetIndNext()
2350 {
2351 ASSERT( !pNext && IsInSct(), "Why?" );
2352 SwFrm* pSct = GetUpper();
2353 if( !pSct )
2354 return NULL;
2355 if( pSct->IsSctFrm() )
2356 return pSct->GetIndNext();
2357 if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
2358 { // Wir duerfen nur den Nachfolger des SectionFrms zurueckliefern,
2359 // wenn in keiner folgenden Spalte mehr Inhalt ist
2360 SwFrm* pCol = GetUpper()->GetUpper()->GetNext();
2361 while( pCol )
2362 {
2363 ASSERT( pCol->IsColumnFrm(), "GetIndNext(): ColumnFrm expected" );
2364 ASSERT( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
2365 "GetIndNext(): Where's the body?");
2366 if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
2367 return NULL;
2368 pCol = pCol->GetNext();
2369 }
2370 return pSct->GetIndNext();
2371 }
2372 return NULL;
2373 }
2374
IsDescendantFrom(const SwSectionFmt * pFmt) const2375 sal_Bool SwSectionFrm::IsDescendantFrom( const SwSectionFmt* pFmt ) const
2376 {
2377 if( !pSection || !pFmt )
2378 return sal_False;
2379 const SwSectionFmt *pMyFmt = pSection->GetFmt();
2380 while( pFmt != pMyFmt )
2381 {
2382 if( pMyFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2383 pMyFmt = (SwSectionFmt*)pMyFmt->GetRegisteredIn();
2384 else
2385 return sal_False;
2386 }
2387 return sal_True;
2388 }
2389
CalcFtnAtEndFlag()2390 void SwSectionFrm::CalcFtnAtEndFlag()
2391 {
2392 SwSectionFmt *pFmt = GetSection()->GetFmt();
2393 sal_uInt16 nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
2394 bFtnAtEnd = FTNEND_ATPGORDOCEND != nVal;
2395 bOwnFtnNum = FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
2396 FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
2397 while( !bFtnAtEnd && !bOwnFtnNum )
2398 {
2399 if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2400 pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
2401 else
2402 break;
2403 nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
2404 if( FTNEND_ATPGORDOCEND != nVal )
2405 {
2406 bFtnAtEnd = sal_True;
2407 bOwnFtnNum = bOwnFtnNum ||FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
2408 FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
2409 }
2410 }
2411 }
2412
IsEndnoteAtMyEnd() const2413 sal_Bool SwSectionFrm::IsEndnoteAtMyEnd() const
2414 {
2415 return pSection->GetFmt()->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2416 }
2417
CalcEndAtEndFlag()2418 void SwSectionFrm::CalcEndAtEndFlag()
2419 {
2420 SwSectionFmt *pFmt = GetSection()->GetFmt();
2421 bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2422 while( !bEndnAtEnd )
2423 {
2424 if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
2425 pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
2426 else
2427 break;
2428 bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
2429 }
2430 }
2431
2432 /*************************************************************************
2433 |*
2434 |* SwSectionFrm::Modify()
2435 |*
2436 |* Ersterstellung MA 08. Oct. 98
2437 |* Letzte Aenderung MA 08. Oct. 98
2438 |*
2439 |*************************************************************************/
2440
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)2441 void SwSectionFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
2442 {
2443 sal_uInt8 nInvFlags = 0;
2444
2445 if( pNew && RES_ATTRSET_CHG == pNew->Which() )
2446 {
2447 SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
2448 SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
2449 SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
2450 SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
2451 while( sal_True )
2452 {
2453 _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
2454 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
2455 &aOldSet, &aNewSet );
2456 if( aNIter.IsAtEnd() )
2457 break;
2458 aNIter.NextItem();
2459 aOIter.NextItem();
2460 }
2461 if ( aOldSet.Count() || aNewSet.Count() )
2462 SwLayoutFrm::Modify( &aOldSet, &aNewSet );
2463 }
2464 else
2465 _UpdateAttr( pOld, pNew, nInvFlags );
2466
2467 if ( nInvFlags != 0 )
2468 {
2469 if ( nInvFlags & 0x01 )
2470 InvalidateSize();
2471 if ( nInvFlags & 0x10 )
2472 SetCompletePaint();
2473 }
2474 }
2475
SwClientNotify(const SwModify & rMod,const SfxHint & rHint)2476 void SwSectionFrm::SwClientNotify( const SwModify& rMod, const SfxHint& rHint )
2477 {
2478 // --> OD #i117863#
2479 const SwSectionFrmMoveAndDeleteHint* pHint =
2480 dynamic_cast<const SwSectionFrmMoveAndDeleteHint*>(&rHint);
2481 if ( pHint && pHint->GetId() == SFX_HINT_DYING && &rMod == GetRegisteredIn() )
2482 {
2483 SwSectionFrm::MoveCntntAndDelete( this, pHint->IsSaveCntnt() );
2484 }
2485 // <--
2486 }
2487
_UpdateAttr(const SfxPoolItem * pOld,const SfxPoolItem * pNew,sal_uInt8 & rInvFlags,SwAttrSetChg * pOldSet,SwAttrSetChg * pNewSet)2488 void SwSectionFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
2489 sal_uInt8 &rInvFlags,
2490 SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
2491 {
2492 sal_Bool bClear = sal_True;
2493 const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
2494 switch( nWhich )
2495 { // Mehrspaltigkeit in Fussnoten unterdruecken...
2496 case RES_FMT_CHG:
2497 {
2498 const SwFmtCol& rNewCol = GetFmt()->GetCol();
2499 if( !IsInFtn() )
2500 {
2501 //Dummer Fall. Bei der Zuweisung einer Vorlage k?nnen wir uns
2502 //nicht auf das alte Spaltenattribut verlassen. Da diese
2503 //wenigstens anzahlgemass fuer ChgColumns vorliegen muessen,
2504 //bleibt uns nur einen temporaeres Attribut zu basteln.
2505 SwFmtCol aCol;
2506 if ( Lower() && Lower()->IsColumnFrm() )
2507 {
2508 sal_uInt16 nCol = 0;
2509 SwFrm *pTmp = Lower();
2510 do
2511 { ++nCol;
2512 pTmp = pTmp->GetNext();
2513 } while ( pTmp );
2514 aCol.Init( nCol, 0, 1000 );
2515 }
2516 sal_Bool bChgFtn = IsFtnAtEnd();
2517 sal_Bool bChgEndn = IsEndnAtEnd();
2518 sal_Bool bChgMyEndn = IsEndnoteAtMyEnd();
2519 CalcFtnAtEndFlag();
2520 CalcEndAtEndFlag();
2521 bChgFtn = ( bChgFtn != IsFtnAtEnd() ) ||
2522 ( bChgEndn != IsEndnAtEnd() ) ||
2523 ( bChgMyEndn != IsEndnoteAtMyEnd() );
2524 ChgColumns( aCol, rNewCol, bChgFtn );
2525 rInvFlags |= 0x10;
2526 }
2527 rInvFlags |= 0x01;
2528 bClear = sal_False;
2529 }
2530 break;
2531
2532 case RES_COL:
2533 if( !IsInFtn() )
2534 {
2535 ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
2536 rInvFlags |= 0x11;
2537 }
2538 break;
2539
2540 case RES_FTN_AT_TXTEND:
2541 if( !IsInFtn() )
2542 {
2543 sal_Bool bOld = IsFtnAtEnd();
2544 CalcFtnAtEndFlag();
2545 if( bOld != IsFtnAtEnd() )
2546 {
2547 const SwFmtCol& rNewCol = GetFmt()->GetCol();
2548 ChgColumns( rNewCol, rNewCol, sal_True );
2549 rInvFlags |= 0x01;
2550 }
2551 }
2552 break;
2553
2554 case RES_END_AT_TXTEND:
2555 if( !IsInFtn() )
2556 {
2557 sal_Bool bOld = IsEndnAtEnd();
2558 sal_Bool bMyOld = IsEndnoteAtMyEnd();
2559 CalcEndAtEndFlag();
2560 if( bOld != IsEndnAtEnd() || bMyOld != IsEndnoteAtMyEnd())
2561 {
2562 const SwFmtCol& rNewCol = GetFmt()->GetCol();
2563 ChgColumns( rNewCol, rNewCol, sal_True );
2564 rInvFlags |= 0x01;
2565 }
2566 }
2567 break;
2568 case RES_COLUMNBALANCE:
2569 rInvFlags |= 0x01;
2570 break;
2571
2572 case RES_FRAMEDIR :
2573 SetDerivedR2L( sal_False );
2574 CheckDirChange();
2575 break;
2576
2577 case RES_PROTECT:
2578 {
2579 ViewShell *pSh = getRootFrm()->GetCurrShell();
2580 if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
2581 pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
2582 }
2583 break;
2584
2585 default:
2586 bClear = sal_False;
2587 }
2588 if ( bClear )
2589 {
2590 if ( pOldSet || pNewSet )
2591 {
2592 if ( pOldSet )
2593 pOldSet->ClearItem( nWhich );
2594 if ( pNewSet )
2595 pNewSet->ClearItem( nWhich );
2596 }
2597 else
2598 SwLayoutFrm::Modify( pOld, pNew );
2599 }
2600 }
2601
2602 /*-----------------09.06.99 14:58-------------------
2603 * SwSectionFrm::ToMaximize(..): A follow or a ftncontainer at the end of the
2604 * page causes a maximal Size of the sectionframe.
2605 * --------------------------------------------------*/
2606
ToMaximize(sal_Bool bCheckFollow) const2607 sal_Bool SwSectionFrm::ToMaximize( sal_Bool bCheckFollow ) const
2608 {
2609 if( HasFollow() )
2610 {
2611 if( !bCheckFollow ) // Don't check superfluous follows
2612 return sal_True;
2613 const SwSectionFrm* pFoll = GetFollow();
2614 while( pFoll && pFoll->IsSuperfluous() )
2615 pFoll = pFoll->GetFollow();
2616 if( pFoll )
2617 return sal_True;
2618 }
2619 if( IsFtnAtEnd() )
2620 return sal_False;
2621 const SwFtnContFrm* pCont = ContainsFtnCont();
2622 if( !IsEndnAtEnd() )
2623 return 0 != pCont;
2624 sal_Bool bRet = sal_False;
2625 while( pCont && !bRet )
2626 {
2627 if( pCont->FindFootNote() )
2628 bRet = sal_True;
2629 else
2630 pCont = ContainsFtnCont( pCont );
2631 }
2632 return bRet;
2633 }
2634
2635 /*-----------------09.06.99 15:07-------------------
2636 * sal_Bool SwSectionFrm::ContainsFtnCont()
2637 * checks every Column for FtnContFrms.
2638 * --------------------------------------------------*/
2639
ContainsFtnCont(const SwFtnContFrm * pCont) const2640 SwFtnContFrm* SwSectionFrm::ContainsFtnCont( const SwFtnContFrm* pCont ) const
2641 {
2642 SwFtnContFrm* pRet = NULL;
2643 const SwLayoutFrm* pLay;
2644 if( pCont )
2645 {
2646 pLay = pCont->FindFtnBossFrm( 0 );
2647 ASSERT( IsAnLower( pLay ), "ConatainsFtnCont: Wrong FtnContainer" );
2648 pLay = (SwLayoutFrm*)pLay->GetNext();
2649 }
2650 else if( Lower() && Lower()->IsColumnFrm() )
2651 pLay = (SwLayoutFrm*)Lower();
2652 else
2653 pLay = NULL;
2654 while ( !pRet && pLay )
2655 {
2656 if( pLay->Lower() && pLay->Lower()->GetNext() )
2657 {
2658 ASSERT( pLay->Lower()->GetNext()->IsFtnContFrm(),
2659 "ToMaximize: Unexspected Frame" );
2660 pRet = (SwFtnContFrm*)pLay->Lower()->GetNext();
2661 }
2662 ASSERT( !pLay->GetNext() || pLay->GetNext()->IsLayoutFrm(),
2663 "ToMaximize: ColFrm exspected" );
2664 pLay = (SwLayoutFrm*)pLay->GetNext();
2665 }
2666 return pRet;
2667 }
2668
InvalidateFtnPos()2669 void SwSectionFrm::InvalidateFtnPos()
2670 {
2671 SwFtnContFrm* pCont = ContainsFtnCont( NULL );
2672 if( pCont )
2673 {
2674 SwFrm *pTmp = pCont->ContainsCntnt();
2675 if( pTmp )
2676 pTmp->_InvalidatePos();
2677 }
2678 }
2679
2680 /*-----------------18.03.99 10:37-------------------
2681 * SwSectionFrm::Undersize() liefert den Betrag, um den der Bereich gern
2682 * groesser waere, wenn in ihm Undersized TxtFrms liegen, ansonsten Null.
2683 * Das Undersized-Flag wird ggf. korrigiert.
2684 * --------------------------------------------------*/
2685
Undersize(sal_Bool bOverSize)2686 long SwSectionFrm::Undersize( sal_Bool bOverSize )
2687 {
2688 bUndersized = sal_False;
2689 SWRECTFN( this )
2690 long nRet = InnerHeight() - (Prt().*fnRect->fnGetHeight)();
2691 if( nRet > 0 )
2692 bUndersized = sal_True;
2693 else if( !bOverSize )
2694 nRet = 0;
2695 return nRet;
2696 }
2697
2698 /// OD 01.04.2003 #108446# - determine next frame for footnote/endnote formatting
2699 /// before format of current one, because current one can move backward.
2700 /// After moving backward to a previous page method <FindNext()> will return
2701 /// the text frame presenting the first page footnote, if it exists. Thus, the
2702 /// rest of the footnote/endnote container would not be formatted.
CalcFtnCntnt()2703 void SwSectionFrm::CalcFtnCntnt()
2704 {
2705 SwFtnContFrm* pCont = ContainsFtnCont();
2706 if( pCont )
2707 {
2708 SwFrm* pFrm = pCont->ContainsAny();
2709 if( pFrm )
2710 pCont->Calc();
2711 while( pFrm && IsAnLower( pFrm ) )
2712 {
2713 SwFtnFrm* pFtn = pFrm->FindFtnFrm();
2714 if( pFtn )
2715 pFtn->Calc();
2716 // OD 01.04.2003 #108446# - determine next frame before format current frame.
2717 SwFrm* pNextFrm = 0;
2718 {
2719 if( pFrm->IsSctFrm() )
2720 {
2721 pNextFrm = static_cast<SwSectionFrm*>(pFrm)->ContainsAny();
2722 }
2723 if( !pNextFrm )
2724 {
2725 pNextFrm = pFrm->FindNext();
2726 }
2727 }
2728 pFrm->Calc();
2729 pFrm = pNextFrm;
2730 }
2731 }
2732 }
2733
2734 /* -----------------09.02.99 14:26-------------------
2735 * Wenn ein SectionFrm leerlaeuft, z.B. weil sein Inhalt die Seite/Spalte wechselt,
2736 * so wird er nicht sofort zerstoert (es koennte noch jemand auf dem Stack einen Pointer
2737 * auf ihn halten), sondern er traegt sich in eine Liste am RootFrm ein, die spaeter
2738 * abgearbeitet wird (in LayAction::Action u.a.). Seine Groesse wird auf Null gesetzt und
2739 * sein Zeiger auf seine Section ebenfalls. Solche zum Loeschen vorgesehene SectionFrms
2740 * muessen vom Layout/beim Formatieren ignoriert werden.
2741 *
2742 * Mit InsertEmptySct nimmt der RootFrm einen SectionFrm in die Liste auf,
2743 * mit RemoveFromList kann ein SectionFrm wieder aus der Liste entfernt werden (Dtor),
2744 * mit DeleteEmptySct wird die Liste abgearbeitet und die SectionFrms zerstoert
2745 * --------------------------------------------------*/
2746
InsertEmptySct(SwSectionFrm * pDel)2747 void SwRootFrm::InsertEmptySct( SwSectionFrm* pDel )
2748 {
2749 if( !pDestroy )
2750 pDestroy = new SwDestroyList;
2751 sal_uInt16 nPos;
2752 if( !pDestroy->Seek_Entry( pDel, &nPos ) )
2753 pDestroy->Insert( pDel );
2754 }
2755
_DeleteEmptySct()2756 void SwRootFrm::_DeleteEmptySct()
2757 {
2758 ASSERT( pDestroy, "Keine Liste, keine Kekse" );
2759 while( pDestroy->Count() )
2760 {
2761 SwSectionFrm* pSect = (*pDestroy)[0];
2762 pDestroy->Remove( sal_uInt16(0) );
2763 ASSERT( !pSect->IsColLocked() && !pSect->IsJoinLocked(),
2764 "DeleteEmptySct: Locked SectionFrm" );
2765 if( !pSect->Frm().HasArea() && !pSect->ContainsCntnt() )
2766 {
2767 SwLayoutFrm* pUp = pSect->GetUpper();
2768 pSect->Remove();
2769 delete pSect;
2770 if( pUp && !pUp->Lower() )
2771 {
2772 if( pUp->IsPageBodyFrm() )
2773 pUp->getRootFrm()->SetSuperfluous();
2774 else if( pUp->IsFtnFrm() && !pUp->IsColLocked() &&
2775 pUp->GetUpper() )
2776 {
2777 pUp->Cut();
2778 delete pUp;
2779 }
2780 }
2781 }
2782 else {
2783 ASSERT( pSect->GetSection(), "DeleteEmptySct: Halbtoter SectionFrm?!" );
2784 }
2785 }
2786 }
2787
_RemoveFromList(SwSectionFrm * pSct)2788 void SwRootFrm::_RemoveFromList( SwSectionFrm* pSct )
2789 {
2790 ASSERT( pDestroy, "Where's my list?" );
2791 sal_uInt16 nPos;
2792 if( pDestroy->Seek_Entry( pSct, &nPos ) )
2793 pDestroy->Remove( nPos );
2794 }
2795
2796 #ifdef DBG_UTIL
2797
IsInDelList(SwSectionFrm * pSct) const2798 sal_Bool SwRootFrm::IsInDelList( SwSectionFrm* pSct ) const
2799 {
2800 sal_uInt16 nPos;
2801 return ( pDestroy && pDestroy->Seek_Entry( pSct, &nPos ) );
2802 }
2803
2804 #endif
2805
IsBalancedSection() const2806 bool SwSectionFrm::IsBalancedSection() const
2807 {
2808 bool bRet = false;
2809 if ( GetSection() && Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
2810 {
2811 bRet = !GetSection()->GetFmt()->GetBalancedColumns().GetValue();
2812 }
2813 return bRet;
2814 }
2815
2816