update dev300-m58
[ooovba.git] / sw / source / core / layout / flowfrm.cxx
blob4968601e7a397657d1968256c2749c51a5e04fbd
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: flowfrm.cxx,v $
10 * $Revision: 1.71 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include "pam.hxx"
34 #include "swtable.hxx"
35 #include "frame.hxx"
36 #include "pagefrm.hxx"
37 #include "flyfrm.hxx"
38 #include "viewsh.hxx"
39 #include "doc.hxx"
40 #include "viewimp.hxx"
41 #include "dflyobj.hxx"
42 #include "frmtool.hxx"
43 #include "dcontact.hxx"
44 #include <svx/brkitem.hxx>
45 #include <svx/keepitem.hxx>
46 #include <fmtsrnd.hxx>
47 #include <fmtanchr.hxx>
48 #include <fmtpdsc.hxx>
49 #include <svx/ulspitem.hxx>
50 #include <tgrditem.hxx>
51 #include <txtftn.hxx>
52 #include <fmtftn.hxx>
53 #include <svx/pgrditem.hxx>
54 #include <paratr.hxx>
56 #include "ftnfrm.hxx"
57 #include "txtfrm.hxx"
58 #include "tabfrm.hxx"
59 #include "pagedesc.hxx"
60 #include "layact.hxx"
61 #include "fmtornt.hxx"
62 #include "flyfrms.hxx"
63 #include "sectfrm.hxx"
64 #include "section.hxx"
65 #include "dbg_lay.hxx"
66 #include "lineinfo.hxx"
67 // OD 2004-03-02 #106629#
68 #include <fmtclbl.hxx>
69 // --> OD 2004-06-23 #i28701#
70 #include <sortedobjs.hxx>
71 #include <layouter.hxx>
72 // <--
73 // --> OD 2004-10-15 #i26945#
74 #include <fmtfollowtextflow.hxx>
75 // <--
77 BOOL SwFlowFrm::bMoveBwdJump = FALSE;
80 /*************************************************************************
82 |* SwFlowFrm::SwFlowFrm()
84 |* Ersterstellung MA 26. Apr. 95
85 |* Letzte Aenderung MA 26. Apr. 95
87 |*************************************************************************/
90 SwFlowFrm::SwFlowFrm( SwFrm &rFrm ) :
91 rThis( rFrm ),
92 pFollow( 0 )
94 bLockJoin = bIsFollow = bCntntLock = bOwnFtnNum =
95 bFtnLock = bFlyLock = FALSE;
99 /*************************************************************************
101 |* SwFlowFrm::IsFollowLocked()
102 |* return TRUE if any follow has the JoinLocked flag
104 |*************************************************************************/
106 sal_Bool SwFlowFrm::HasLockedFollow() const
108 const SwFlowFrm* pFrm = GetFollow();
109 while( pFrm )
111 if( pFrm->IsJoinLocked() )
112 return sal_True;
113 pFrm = pFrm->GetFollow();
115 return sal_False;
118 /*************************************************************************
120 |* SwFlowFrm::IsKeepFwdMoveAllowed()
122 |* Ersterstellung MA 20. Jul. 94
123 |* Letzte Aenderung MA 16. May. 95
125 |*************************************************************************/
128 BOOL SwFlowFrm::IsKeepFwdMoveAllowed()
130 //Wenn der Vorgaenger das KeepAttribut traegt und auch dessen
131 //Vorgaenger usw. bis zum ersten der Kette und fuer diesen das
132 //IsFwdMoveAllowed ein FALSE liefert, so ist das Moven eben nicht erlaubt.
133 SwFrm *pFrm = &rThis;
134 if ( !pFrm->IsInFtn() )
136 { if ( pFrm->GetAttrSet()->GetKeep().GetValue() )
137 pFrm = pFrm->GetIndPrev();
138 else
139 return TRUE;
140 } while ( pFrm );
142 //Siehe IsFwdMoveAllowed()
143 BOOL bRet = FALSE;
144 if ( pFrm && pFrm->GetIndPrev() )
145 bRet = TRUE;
146 return bRet;
149 /*************************************************************************
151 |* SwFlowFrm::CheckKeep()
153 |* Beschreibung
154 |* Ersterstellung MA 20. Jun. 95
155 |* Letzte Aenderung MA 09. Apr. 97
157 |*************************************************************************/
160 void SwFlowFrm::CheckKeep()
162 //Den 'letzten' Vorgaenger mit KeepAttribut anstossen, denn
163 //die ganze Truppe koennte zuruckrutschen.
164 SwFrm *pPre = rThis.GetIndPrev();
165 if( pPre->IsSctFrm() )
167 SwFrm *pLast = ((SwSectionFrm*)pPre)->FindLastCntnt();
168 if( pLast && pLast->FindSctFrm() == pPre )
169 pPre = pLast;
170 else
171 return;
173 SwFrm* pTmp;
174 BOOL bKeep;
175 while ( TRUE == (bKeep = pPre->GetAttrSet()->GetKeep().GetValue()) &&
176 0 != ( pTmp = pPre->GetIndPrev() ) )
178 if( pTmp->IsSctFrm() )
180 SwFrm *pLast = ((SwSectionFrm*)pTmp)->FindLastCntnt();
181 if( pLast && pLast->FindSctFrm() == pTmp )
182 pTmp = pLast;
183 else
184 break;
186 pPre = pTmp;
188 if ( bKeep )
189 pPre->InvalidatePos();
192 /*************************************************************************
194 |* SwFlowFrm::IsKeep()
196 |* Ersterstellung MA 09. Apr. 97
197 |* Letzte Aenderung MA 09. Apr. 97
199 |*************************************************************************/
201 BOOL SwFlowFrm::IsKeep( const SwAttrSet& rAttrs, bool bCheckIfLastRowShouldKeep ) const
203 // 1. The keep attribute is ignored inside footnotes
204 // 2. For compatibility reasons, the keep attribute is
205 // ignored for frames inside table cells
206 // 3. If bBreakCheck is set to true, this function only checks
207 // if there are any break after attributes set at rAttrs
208 // or break before attributes set for the next content (or next table)
209 BOOL bKeep = bCheckIfLastRowShouldKeep ||
210 ( !rThis.IsInFtn() &&
211 ( !rThis.IsInTab() || rThis.IsTabFrm() ) &&
212 rAttrs.GetKeep().GetValue() );
214 ASSERT( !bCheckIfLastRowShouldKeep || rThis.IsTabFrm(),
215 "IsKeep with bCheckIfLastRowShouldKeep should only be used for tabfrms" )
217 // Ignore keep attribute if there are break situations:
218 if ( bKeep )
220 switch ( rAttrs.GetBreak().GetBreak() )
222 case SVX_BREAK_COLUMN_AFTER:
223 case SVX_BREAK_COLUMN_BOTH:
224 case SVX_BREAK_PAGE_AFTER:
225 case SVX_BREAK_PAGE_BOTH:
227 bKeep = FALSE;
229 default: break;
231 if ( bKeep )
233 SwFrm *pNxt;
234 if( 0 != (pNxt = rThis.FindNextCnt()) &&
235 (!pFollow || pNxt != pFollow->GetFrm()))
237 // --> FME 2006-05-15 #135914#
238 // The last row of a table only keeps with the next content
239 // it they are in the same section:
240 if ( bCheckIfLastRowShouldKeep )
242 const SwSection* pThisSection = 0;
243 const SwSection* pNextSection = 0;
244 const SwSectionFrm* pThisSectionFrm = rThis.FindSctFrm();
245 const SwSectionFrm* pNextSectionFrm = pNxt->FindSctFrm();
247 if ( pThisSectionFrm )
248 pThisSection = pThisSectionFrm->GetSection();
250 if ( pNextSectionFrm )
251 pNextSection = pNextSectionFrm->GetSection();
253 if ( pThisSection != pNextSection )
254 bKeep = FALSE;
256 // <--
258 if ( bKeep )
260 const SwAttrSet* pSet = NULL;
262 if ( pNxt->IsInTab() )
264 SwTabFrm* pTab = pNxt->FindTabFrm();
265 if ( ! rThis.IsInTab() || rThis.FindTabFrm() != pTab )
266 pSet = &pTab->GetFmt()->GetAttrSet();
269 if ( ! pSet )
270 pSet = pNxt->GetAttrSet();
272 ASSERT( pSet, "No AttrSet to check keep attribute" )
274 if ( pSet->GetPageDesc().GetPageDesc() )
275 bKeep = FALSE;
276 else switch ( pSet->GetBreak().GetBreak() )
278 case SVX_BREAK_COLUMN_BEFORE:
279 case SVX_BREAK_COLUMN_BOTH:
280 case SVX_BREAK_PAGE_BEFORE:
281 case SVX_BREAK_PAGE_BOTH:
282 bKeep = FALSE;
283 default: break;
289 return bKeep;
292 /*************************************************************************
294 |* SwFlowFrm::BwdMoveNecessary()
296 |* Ersterstellung MA 20. Jul. 94
297 |* Letzte Aenderung MA 02. May. 96
299 |*************************************************************************/
302 BYTE SwFlowFrm::BwdMoveNecessary( const SwPageFrm *pPage, const SwRect &rRect )
304 // Der return-Wert entscheidet mit,
305 // ob auf Zurueckgeflossen werden muss, (3)
306 // ob das gute alte WouldFit gerufen werden kann (0, 1)
307 // oder ob ein Umhaengen und eine Probeformatierung sinnvoll ist (2)
308 // dabei bedeutet Bit 1, dass Objekte an mir selbst verankert sind
309 // und Bit 2, dass ich anderen Objekten ausweichen muss.
311 //Wenn ein SurroundObj, dass einen Umfluss wuenscht mit dem Rect ueberlappt
312 //ist der Fluss notwendig (weil die Verhaeltnisse nicht geschaetzt werden
313 //koennen), es kann allerdings ggf. eine TestFormatierung stattfinden.
314 //Wenn das SurroundObj ein Fly ist und ich selbst ein Lower bin oder der Fly
315 //Lower von mir ist, so spielt er keine Rolle.
316 //Wenn das SurroundObj in einem zeichengebunden Fly verankert ist, und ich
317 //selbst nicht Lower dieses Zeichengebundenen Flys bin, so spielt der Fly
318 //keine Rolle.
319 //#32639# Wenn das Objekt bei mir verankert ist kann ich es
320 //vernachlaessigen, weil es hoechstwahrscheinlich (!?) mitfliesst,
321 //eine TestFormatierung ist dann allerdings nicht erlaubt!
322 BYTE nRet = 0;
323 SwFlowFrm *pTmp = this;
325 { // Wenn an uns oder einem Follow Objekte haengen, so
326 // kann keine ProbeFormatierung stattfinden, da absatzgebundene
327 // nicht richtig beruecksichtigt wuerden und zeichengebundene sollten
328 // gar nicht zur Probe formatiert werden.
329 if( pTmp->GetFrm()->GetDrawObjs() )
330 nRet = 1;
331 pTmp = pTmp->GetFollow();
332 } while ( !nRet && pTmp );
333 if ( pPage->GetSortedObjs() )
335 // --> OD 2004-07-01 #i28701# - new type <SwSortedObjs>
336 const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
337 ULONG nIndex = ULONG_MAX;
338 for ( USHORT i = 0; nRet < 3 && i < rObjs.Count(); ++i )
340 // --> OD 2004-07-01 #i28701# - consider changed type of
341 // <SwSortedObjs> entries.
342 SwAnchoredObject* pObj = rObjs[i];
343 const SwFrmFmt& rFmt = pObj->GetFrmFmt();
344 const SwRect aRect( pObj->GetObjRect() );
345 if ( aRect.IsOver( rRect ) &&
346 rFmt.GetSurround().GetSurround() != SURROUND_THROUGHT )
348 if( rThis.IsLayoutFrm() && //Fly Lower von This?
349 Is_Lower_Of( &rThis, pObj->GetDrawObj() ) )
350 continue;
351 if( pObj->ISA(SwFlyFrm) )
353 const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
354 if ( pFly->IsAnLower( &rThis ) )//This Lower vom Fly?
355 continue;
358 const SwFrm* pAnchor = pObj->GetAnchorFrm();
359 if ( pAnchor == &rThis )
361 nRet |= 1;
362 continue;
365 //Nicht wenn das Objekt im Textfluss hinter mir verankert ist,
366 //denn dann weiche ich ihm nicht aus.
367 if ( ::IsFrmInSameKontext( pAnchor, &rThis ) )
369 if ( rFmt.GetAnchor().GetAnchorId() == FLY_AT_CNTNT )
371 // Den Index des anderen erhalten wir immer ueber das Ankerattr.
372 ULONG nTmpIndex = rFmt.GetAnchor().GetCntntAnchor()->nNode.GetIndex();
373 // Jetzt wird noch ueberprueft, ob der aktuelle Absatz vor dem
374 // Anker des verdraengenden Objekts im Text steht, dann wird
375 // nicht ausgewichen.
376 // Der Index wird moeglichst ueber einen SwFmtAnchor ermittelt,
377 // da sonst recht teuer.
378 if( ULONG_MAX == nIndex )
380 const SwNode *pNode;
381 if ( rThis.IsCntntFrm() )
382 pNode = ((SwCntntFrm&)rThis).GetNode();
383 else if( rThis.IsSctFrm() )
384 pNode = ((SwSectionFmt*)((SwSectionFrm&)rThis).
385 GetFmt())->GetSectionNode();
386 else
388 ASSERT( rThis.IsTabFrm(), "new FowFrm?" );
389 pNode = ((SwTabFrm&)rThis).GetTable()->
390 GetTabSortBoxes()[0]->GetSttNd()->FindTableNode();
392 nIndex = pNode->GetIndex();
394 if( nIndex < nTmpIndex )
395 continue;
398 else
399 continue;
401 nRet |= 2;
405 return nRet;
408 /*************************************************************************
410 |* SwFlowFrm::CutTree(), PasteTree(), MoveSubTree()
412 |* Beschreibung Eine Spezialisierte Form des Cut() und Paste(), die
413 |* eine ganze Kette umhaengt (naehmlich this und folgende). Dabei werden
414 |* nur minimale Operationen und Benachrichtigungen ausgefuehrt.
415 |* Ersterstellung MA 18. Mar. 93
416 |* Letzte Aenderung MA 18. May. 95
418 |*************************************************************************/
421 SwLayoutFrm *SwFlowFrm::CutTree( SwFrm *pStart )
423 //Der Start und alle Nachbarn werden ausgeschnitten, sie werden aneinander-
424 //gereiht und ein Henkel auf den ersten wird zurueckgeliefert.
425 //Zurueckbleibende werden geeignet invalidiert.
427 SwLayoutFrm *pLay = pStart->GetUpper();
428 if ( pLay->IsInFtn() )
429 pLay = pLay->FindFtnFrm();
431 // --> OD 2006-05-08 #i58846#
432 // <pPrepare( PREP_QUOVADIS )> only for frames in footnotes
433 if( pStart->IsInFtn() )
435 SwFrm* pTmp = pStart->GetIndPrev();
436 if( pTmp )
437 pTmp->Prepare( PREP_QUOVADIS );
439 // <--
441 //Nur fix auschneiden und zwar so, dass klare Verhaeltnisse bei den
442 //Verlassenen herrschen. Die Pointer der ausgeschnittenen Kette zeigen
443 //noch wer weiss wo hin.
444 if ( pStart == pStart->GetUpper()->Lower() )
445 pStart->GetUpper()->pLower = 0;
446 if ( pStart->GetPrev() )
448 pStart->GetPrev()->pNext = 0;
449 pStart->pPrev = 0;
452 if ( pLay->IsFtnFrm() )
454 if ( !pLay->Lower() && !pLay->IsColLocked() &&
455 !((SwFtnFrm*)pLay)->IsBackMoveLocked() )
457 pLay->Cut();
458 delete pLay;
460 else
462 BOOL bUnlock = !((SwFtnFrm*)pLay)->IsBackMoveLocked();
463 ((SwFtnFrm*)pLay)->LockBackMove();
464 pLay->InvalidateSize();
465 pLay->Calc();
466 SwCntntFrm *pCnt = pLay->ContainsCntnt();
467 while ( pCnt && pLay->IsAnLower( pCnt ) )
469 //Kann sein, dass der CntFrm gelockt ist, wir wollen hier nicht
470 //in eine endlose Seitenwanderung hineinlaufen und rufen das
471 //Calc garnicht erst!
472 ASSERT( pCnt->IsTxtFrm(), "Die Graphic ist gelandet." );
473 if ( ((SwTxtFrm*)pCnt)->IsLocked() ||
474 ((SwTxtFrm*)pCnt)->GetFollow() == pStart )
475 break;
476 pCnt->Calc();
477 pCnt = pCnt->GetNextCntntFrm();
479 if( bUnlock )
480 ((SwFtnFrm*)pLay)->UnlockBackMove();
482 pLay = 0;
484 return pLay;
489 BOOL SwFlowFrm::PasteTree( SwFrm *pStart, SwLayoutFrm *pParent, SwFrm *pSibling,
490 SwFrm *pOldParent )
492 //returnt TRUE wenn in der Kette ein LayoutFrm steht.
493 BOOL bRet = FALSE;
495 //Die mit pStart beginnende Kette wird vor den Sibling unter den Parent
496 //gehaengt. Fuer geeignete Invalidierung wird ebenfalls gesorgt.
498 //Ich bekomme eine fertige Kette. Der Anfang der Kette muss verpointert
499 //werden, dann alle Upper fuer die Kette und schliesslich dass Ende.
500 //Unterwegs werden alle geeignet invalidiert.
501 if ( pSibling )
503 if ( 0 != (pStart->pPrev = pSibling->GetPrev()) )
504 pStart->GetPrev()->pNext = pStart;
505 else
506 pParent->pLower = pStart;
507 pSibling->_InvalidatePos();
508 pSibling->_InvalidatePrt();
510 else
512 if ( 0 == (pStart->pPrev = pParent->Lower()) )
513 pParent->pLower = pStart;
514 else
515 //Modified for #i100782#,04/03/2009
516 //If the pParent has more than 1 child nodes, former design will
517 //ignore them directly without any collection work. It will make some
518 //dangling pointers. This lead the crash...
519 //The new design will find the last child of pParent in loop way, and
520 //add the pStart after the last child.
521 // pParent->Lower()->pNext = pStart;
523 SwFrm* pTemp = pParent->pLower;
524 while (pTemp)
526 if (pTemp->pNext)
527 pTemp = pTemp->pNext;
528 else
530 pStart->pPrev = pTemp;
531 pTemp->pNext = pStart;
532 break;
536 //End modification for #i100782#,04/03/2009
538 // #i27145#
539 if ( pParent->IsSctFrm() )
541 // We have no sibling because pParent is a section frame and
542 // has just been created to contain some content. The printing
543 // area of the frame behind pParent has to be invalidated, so
544 // that the correct distance between pParent and the next frame
545 // can be calculated.
546 pParent->InvalidateNextPrtArea();
549 SwFrm *pFloat = pStart;
550 SwFrm *pLst = 0;
551 SWRECTFN( pParent )
552 SwTwips nGrowVal = 0;
554 { pFloat->pUpper = pParent;
555 pFloat->_InvalidateAll();
556 pFloat->CheckDirChange();
558 //Ich bin Freund des TxtFrm und darf deshalb so einiges. Das mit
559 //dem CacheIdx scheint etwas riskant!
560 if ( pFloat->IsTxtFrm() )
562 if ( ((SwTxtFrm*)pFloat)->GetCacheIdx() != USHRT_MAX )
563 ((SwTxtFrm*)pFloat)->Init(); //Ich bin sein Freund.
565 else
566 bRet = TRUE;
568 nGrowVal += (pFloat->Frm().*fnRect->fnGetHeight)();
569 if ( pFloat->GetNext() )
570 pFloat = pFloat->GetNext();
571 else
573 pLst = pFloat;
574 pFloat = 0;
576 } while ( pFloat );
578 if ( pSibling )
580 pLst->pNext = pSibling;
581 pSibling->pPrev = pLst;
582 if( pSibling->IsInFtn() )
584 if( pSibling->IsSctFrm() )
585 pSibling = ((SwSectionFrm*)pSibling)->ContainsAny();
586 if( pSibling )
587 pSibling->Prepare( PREP_ERGOSUM );
590 if ( nGrowVal )
592 if ( pOldParent && pOldParent->IsBodyFrm() ) //Fuer variable Seitenhoehe beim Browsen
593 pOldParent->Shrink( nGrowVal );
594 pParent->Grow( nGrowVal );
597 if ( pParent->IsFtnFrm() )
598 ((SwFtnFrm*)pParent)->InvalidateNxtFtnCnts( pParent->FindPageFrm() );
599 return bRet;
604 void SwFlowFrm::MoveSubTree( SwLayoutFrm* pParent, SwFrm* pSibling )
606 ASSERT( pParent, "Kein Parent uebergeben." );
607 ASSERT( rThis.GetUpper(), "Wo kommen wir denn her?" );
609 //Sparsamer benachrichtigen wenn eine Action laeuft.
610 ViewShell *pSh = rThis.GetShell();
611 const SwViewImp *pImp = pSh ? pSh->Imp() : 0;
612 const BOOL bComplete = pImp && pImp->IsAction() && pImp->GetLayAction().IsComplete();
614 if ( !bComplete )
616 SwFrm *pPre = rThis.GetIndPrev();
617 if ( pPre )
619 pPre->SetRetouche();
620 // --> OD 2004-11-23 #115759# - follow-up of #i26250#
621 // invalidate printing area of previous frame, if it's in a table
622 if ( pPre->GetUpper()->IsInTab() )
624 pPre->_InvalidatePrt();
626 // <--
627 pPre->InvalidatePage();
629 else
630 { rThis.GetUpper()->SetCompletePaint();
631 rThis.GetUpper()->InvalidatePage();
635 SwPageFrm *pOldPage = rThis.FindPageFrm();
637 SwLayoutFrm *pOldParent = CutTree( &rThis );
638 const BOOL bInvaLay = PasteTree( &rThis, pParent, pSibling, pOldParent );
640 // Wenn durch das Cut&Paste ein leerer SectionFrm entstanden ist, sollte
641 // dieser automatisch verschwinden.
642 SwSectionFrm *pSct;
643 // --> OD 2006-01-04 #126020# - adjust check for empty section
644 // --> OD 2006-02-01 #130797# - correct fix #126020#
645 if ( pOldParent && !pOldParent->Lower() &&
646 ( pOldParent->IsInSct() &&
647 !(pSct = pOldParent->FindSctFrm())->ContainsCntnt() &&
648 !pSct->ContainsAny( true ) ) )
649 // <--
651 pSct->DelEmpty( FALSE );
654 // In einem spaltigen Bereich rufen wir lieber kein Calc "von unten"
655 if( !rThis.IsInSct() &&
656 ( !rThis.IsInTab() || ( rThis.IsTabFrm() && !rThis.GetUpper()->IsInTab() ) ) )
657 rThis.GetUpper()->Calc();
658 else if( rThis.GetUpper()->IsSctFrm() )
660 SwSectionFrm* pTmpSct = (SwSectionFrm*)rThis.GetUpper();
661 BOOL bOld = pTmpSct->IsCntntLocked();
662 pTmpSct->SetCntntLock( TRUE );
663 pTmpSct->Calc();
664 if( !bOld )
665 pTmpSct->SetCntntLock( FALSE );
667 SwPageFrm *pPage = rThis.FindPageFrm();
669 if ( pOldPage != pPage )
671 rThis.InvalidatePage( pPage );
672 if ( rThis.IsLayoutFrm() )
674 SwCntntFrm *pCnt = ((SwLayoutFrm*)&rThis)->ContainsCntnt();
675 if ( pCnt )
676 pCnt->InvalidatePage( pPage );
678 else if ( pSh && pSh->GetDoc()->GetLineNumberInfo().IsRestartEachPage()
679 && pPage->FindFirstBodyCntnt() == &rThis )
681 rThis._InvalidateLineNum();
684 if ( bInvaLay || (pSibling && pSibling->IsLayoutFrm()) )
685 rThis.GetUpper()->InvalidatePage( pPage );
688 /*************************************************************************
690 |* SwFlowFrm::IsAnFollow()
692 |* Ersterstellung MA 26. Apr. 95
693 |* Letzte Aenderung MA 26. Apr. 95
695 |*************************************************************************/
698 BOOL SwFlowFrm::IsAnFollow( const SwFlowFrm *pAssumed ) const
700 const SwFlowFrm *pFoll = this;
702 { if ( pAssumed == pFoll )
703 return TRUE;
704 pFoll = pFoll->GetFollow();
705 } while ( pFoll );
706 return FALSE;
710 /*************************************************************************
712 |* SwFlowFrm::FindMaster()
714 |* Ersterstellung MA 26. Apr. 95
715 |* Letzte Aenderung MA 26. Apr. 95
717 |*************************************************************************/
719 SwTxtFrm* SwCntntFrm::FindMaster() const
721 ASSERT( IsFollow(), "SwCntntFrm::FindMaster(): !IsFollow" );
723 const SwCntntFrm* pCnt = GetPrevCntntFrm();
725 while ( pCnt )
727 if ( pCnt->HasFollow() && pCnt->GetFollow() == this )
729 ASSERT( pCnt->IsTxtFrm(), "NoTxtFrm with follow found" )
730 return (SwTxtFrm*)pCnt;
732 pCnt = pCnt->GetPrevCntntFrm();
735 ASSERT( FALSE, "Follow ist lost in Space." );
736 return 0;
739 SwSectionFrm* SwSectionFrm::FindMaster() const
741 ASSERT( IsFollow(), "SwSectionFrm::FindMaster(): !IsFollow" );
743 SwClientIter aIter( *pSection->GetFmt() );
744 SwClient *pLast = aIter.GoStart();
746 while ( pLast )
748 if ( pLast->ISA( SwFrm ) )
750 ASSERT( ((SwFrm*)pLast)->IsSctFrm(),
751 "Non-section frame registered in section format" )
752 SwSectionFrm* pSect = (SwSectionFrm*)pLast;
753 if( pSect->GetFollow() == this )
754 return pSect;
756 pLast = aIter++;
759 ASSERT( FALSE, "Follow ist lost in Space." );
760 return 0;
763 SwTabFrm* SwTabFrm::FindMaster( bool bFirstMaster ) const
765 ASSERT( IsFollow(), "SwTabFrm::FindMaster(): !IsFollow" );
767 SwClientIter aIter( *GetTable()->GetFrmFmt() );
768 SwClient* pLast = aIter.GoStart();
770 while ( pLast )
772 if ( pLast->ISA( SwFrm ) )
774 ASSERT( ((SwFrm*)pLast)->IsTabFrm(),
775 "Non-table frame registered in table format" )
776 SwTabFrm* pTab = (SwTabFrm*)pLast;
778 if ( bFirstMaster )
781 // Optimization. This makes code like this obsolete:
782 // while ( pTab->IsFollow() )
783 // pTab = pTab->FindMaster();
785 if ( !pTab->IsFollow() )
787 SwTabFrm* pNxt = pTab;
788 while ( pNxt )
790 if ( pNxt->GetFollow() == this )
791 return pTab;
792 pNxt = pNxt->GetFollow();
796 else
798 if ( pTab->GetFollow() == this )
799 return pTab;
802 pLast = aIter++;
805 ASSERT( FALSE, "Follow ist lost in Space." );
806 return 0;
809 /*************************************************************************
811 |* SwFrm::GetLeaf()
813 |* Beschreibung Liefert das naechste/vorhergehende LayoutBlatt,
814 |* das _nicht_ unterhalb von this liegt (oder gar this selbst ist).
815 |* Ausserdem muss dieses LayoutBlatt im gleichen Textfluss wie
816 |* pAnch Ausgangsfrm liegen (Body, Ftn)
817 |* Ersterstellung MA 25. Nov. 92
818 |* Letzte Aenderung MA 25. Apr. 95
820 |*************************************************************************/
823 const SwLayoutFrm *SwFrm::GetLeaf( MakePageType eMakePage, BOOL bFwd,
824 const SwFrm *pAnch ) const
826 //Ohne Fluss kein genuss...
827 if ( !(IsInDocBody() || IsInFtn() || IsInFly()) )
828 return 0;
830 const SwFrm *pLeaf = this;
831 BOOL bFound = FALSE;
834 { pLeaf = ((SwFrm*)pLeaf)->GetLeaf( eMakePage, bFwd );
836 if ( pLeaf &&
837 (!IsLayoutFrm() || !((SwLayoutFrm*)this)->IsAnLower( pLeaf )))
839 if ( pAnch->IsInDocBody() == pLeaf->IsInDocBody() &&
840 pAnch->IsInFtn() == pLeaf->IsInFtn() )
842 bFound = TRUE;
845 } while ( !bFound && pLeaf );
847 return (const SwLayoutFrm*)pLeaf;
850 /*************************************************************************
852 |* SwFrm::GetLeaf()
854 |* Beschreibung Ruft Get[Next|Prev]Leaf
856 |* Ersterstellung MA 20. Mar. 93
857 |* Letzte Aenderung MA 25. Apr. 95
859 |*************************************************************************/
862 SwLayoutFrm *SwFrm::GetLeaf( MakePageType eMakePage, BOOL bFwd )
864 if ( IsInFtn() )
865 return bFwd ? GetNextFtnLeaf( eMakePage ) : GetPrevFtnLeaf( eMakePage );
867 // --> OD 2005-08-16 #i53323#
868 // A frame could be inside a table AND inside a section.
869 // Thus, it has to be determined, which is the first parent.
870 bool bInTab( IsInTab() );
871 bool bInSct( IsInSct() );
872 if ( bInTab && bInSct )
874 const SwFrm* pUpperFrm( GetUpper() );
875 while ( pUpperFrm )
877 if ( pUpperFrm->IsTabFrm() )
879 // the table is the first.
880 bInSct = false;
881 break;
883 else if ( pUpperFrm->IsSctFrm() )
885 // the section is the first.
886 bInTab = false;
887 break;
890 pUpperFrm = pUpperFrm->GetUpper();
894 if ( bInTab && ( !IsTabFrm() || GetUpper()->IsCellFrm() ) ) // TABLE IN TABLE
895 return bFwd ? GetNextCellLeaf( eMakePage ) : GetPrevCellLeaf( eMakePage );
897 if ( bInSct )
898 return bFwd ? GetNextSctLeaf( eMakePage ) : GetPrevSctLeaf( eMakePage );
899 // <--
901 return bFwd ? GetNextLeaf( eMakePage ) : GetPrevLeaf( eMakePage );
906 BOOL SwFrm::WrongPageDesc( SwPageFrm* pNew )
908 //Jetzt wirds leider etwas kompliziert:
909 //Ich bringe ich evtl. selbst
910 //einen Pagedesc mit; der der Folgeseite muss dann damit
911 //uebereinstimmen.
912 //Anderfalls muss ich mir etwas genauer ansehen wo der
913 //Folgepagedesc herkam.
914 //Wenn die Folgeseite selbst schon sagt, dass ihr
915 //Pagedesc nicht stimmt so kann ich das Teil bedenkenlos
916 //auswechseln.
917 //Wenn die Seite meint, dass ihr Pagedesc stimmt, so heisst
918 //das leider noch immer nicht, dass ich damit etwas anfangen
919 //kann: Wenn der erste BodyCntnt einen PageDesc oder einen
920 //PageBreak wuenscht, so muss ich ebenfalls eine neue
921 //Seite einfuegen; es sein denn die gewuenschte Seite ist
922 //die richtige.
923 //Wenn ich einen neue Seite eingefuegt habe, so fangen die
924 //Probleme leider erst an, denn wahrscheinlich wird die dann
925 //folgende Seite verkehrt gewesen und ausgewechselt worden
926 //sein. Das hat zur Folge, dass ich zwar eine neue (und
927 //jetzt richtige) Seite habe, die Bedingungen zum auswechseln
928 //aber leider noch immer stimmen.
929 //Ausweg: Vorlaeufiger Versuch, nur einmal eine neue Seite
930 //einsetzen (Leerseiten werden noetigenfalls bereits von
931 //InsertPage() eingefuegt.
932 const SwFmtPageDesc &rFmtDesc = GetAttrSet()->GetPageDesc();
934 //Mein Pagedesc zaehlt nicht, wenn ich ein Follow bin!
935 SwPageDesc *pDesc = 0;
936 USHORT nTmp = 0;
937 SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( this );
938 if ( !pFlow || !pFlow->IsFollow() )
940 pDesc = (SwPageDesc*)rFmtDesc.GetPageDesc();
941 if( pDesc )
943 if( !pDesc->GetRightFmt() )
944 nTmp = 2;
945 else if( !pDesc->GetLeftFmt() )
946 nTmp = 1;
947 else if( rFmtDesc.GetNumOffset() )
948 nTmp = rFmtDesc.GetNumOffset();
952 //Bringt der Cntnt einen Pagedesc mit oder muss zaehlt die
953 //virtuelle Seitennummer des neuen Layoutleafs?
954 // Bei Follows zaehlt der PageDesc nicht
955 const BOOL bOdd = nTmp ? ( nTmp % 2 ? TRUE : FALSE )
956 : pNew->OnRightPage();
957 if ( !pDesc )
958 pDesc = pNew->FindPageDesc();
959 const SwFlowFrm *pNewFlow = pNew->FindFirstBodyCntnt();
960 // Haben wir uns selbst gefunden?
961 if( pNewFlow == pFlow )
962 pNewFlow = NULL;
963 if ( pNewFlow && pNewFlow->GetFrm()->IsInTab() )
964 pNewFlow = pNewFlow->GetFrm()->FindTabFrm();
965 const SwPageDesc *pNewDesc= ( pNewFlow && !pNewFlow->IsFollow() )
966 ? pNewFlow->GetFrm()->GetAttrSet()->GetPageDesc().GetPageDesc():0;
968 return ( pNew->GetPageDesc() != pDesc || // own desc ?
969 pNew->GetFmt() != (bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) ||
970 ( pNewDesc && pNewDesc == pDesc ) );
974 /*************************************************************************
976 |* SwFrm::GetNextLeaf()
978 |* Beschreibung Liefert das naechste LayoutBlatt in den das
979 |* Frame gemoved werden kann.
981 |* Ersterstellung MA 16. Nov. 92
982 |* Letzte Aenderung MA 05. Dec. 96
984 |*************************************************************************/
986 SwLayoutFrm *SwFrm::GetNextLeaf( MakePageType eMakePage )
988 ASSERT( !IsInFtn(), "GetNextLeaf(), don't call me for Ftn." );
989 ASSERT( !IsInSct(), "GetNextLeaf(), don't call me for Sections." );
991 const BOOL bBody = IsInDocBody(); //Wenn ich aus dem DocBody komme
992 //Will ich auch im Body landen.
994 // Bei Flys macht es keinen Sinn, Seiten einzufuegen, wir wollen lediglich
995 // die Verkettung absuchen.
996 if( IsInFly() )
997 eMakePage = MAKEPAGE_NONE;
999 //Bei Tabellen gleich den grossen Sprung wagen, ein einfaches GetNext...
1000 //wuerde die erste Zellen und in der Folge alle weiteren Zellen nacheinander
1001 //abklappern....
1002 SwLayoutFrm *pLayLeaf = 0;
1003 if ( IsTabFrm() )
1005 SwCntntFrm* pTmp = ((SwTabFrm*)this)->FindLastCntnt();
1006 if ( pTmp )
1007 pLayLeaf = pTmp->GetUpper();
1009 if ( !pLayLeaf )
1010 pLayLeaf = GetNextLayoutLeaf();
1012 SwLayoutFrm *pOldLayLeaf = 0; //Damit bei neu erzeugten Seiten
1013 //nicht wieder vom Anfang gesucht
1014 //wird.
1015 BOOL bNewPg = FALSE; //nur einmal eine neue Seite einfuegen.
1017 while ( TRUE )
1019 if ( pLayLeaf )
1021 //Es gibt noch einen weiteren LayoutFrm, mal sehen,
1022 //ob er bereit ist mich aufzunehmen.
1023 //Dazu braucht er nur von der gleichen Art wie mein Ausgangspunkt
1024 //sein (DocBody bzw. Footnote.)
1025 if ( pLayLeaf->FindPageFrm()->IsFtnPage() )
1026 { //Wenn ich bei den Endnotenseiten angelangt bin hat sichs.
1027 pLayLeaf = 0;
1028 continue;
1030 if ( (bBody && !pLayLeaf->IsInDocBody()) || pLayLeaf->IsInTab()
1031 || pLayLeaf->IsInSct() )
1033 //Er will mich nicht; neuer Versuch, neues Glueck
1034 pOldLayLeaf = pLayLeaf;
1035 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1036 continue;
1038 //Er will mich, also ist er der gesuchte und ich bin fertig.
1039 //Bei einem Seitenwechsel kann es allerdings noch sein, dass
1040 //Der Seitentyp nicht der gewuenschte ist, in diesem Fall muessen
1041 //wir eine Seite des richtigen Typs einfuegen.
1043 if( !IsFlowFrm() && ( eMakePage == MAKEPAGE_NONE ||
1044 eMakePage==MAKEPAGE_APPEND || eMakePage==MAKEPAGE_NOSECTION ) )
1045 return pLayLeaf;
1047 SwPageFrm *pNew = pLayLeaf->FindPageFrm();
1048 // #111704# The pagedesc check does not make sense for frames in fly frames
1049 if ( pNew != FindPageFrm() && !bNewPg && !IsInFly() &&
1050 // --> FME 2005-05-10 #i46683#
1051 // Do not consider page descriptions in browse mode (since
1052 // MoveBwd ignored them)
1053 !pNew->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) )
1054 // <--
1056 if( WrongPageDesc( pNew ) )
1058 SwFtnContFrm *pCont = pNew->FindFtnCont();
1059 if( pCont )
1061 // Falls die Referenz der ersten Fussnote dieser Seite
1062 // vor der Seite liegt, fuegen wir lieber keine neue Seite
1063 // ein (Bug #55620#)
1064 SwFtnFrm *pFtn = (SwFtnFrm*)pCont->Lower();
1065 if( pFtn && pFtn->GetRef() )
1067 const USHORT nRefNum = pNew->GetPhyPageNum();
1068 if( pFtn->GetRef()->GetPhyPageNum() < nRefNum )
1069 break;
1072 //Erwischt, die folgende Seite ist verkehrt, also
1073 //muss eine neue eingefuegt werden.
1074 if ( eMakePage == MAKEPAGE_INSERT )
1076 bNewPg = TRUE;
1078 SwPageFrm *pPg = pOldLayLeaf ?
1079 pOldLayLeaf->FindPageFrm() : 0;
1080 if ( pPg && pPg->IsEmptyPage() )
1081 //Nicht hinter, sondern vor der EmptyPage einfuegen.
1082 pPg = (SwPageFrm*)pPg->GetPrev();
1084 if ( !pPg || pPg == pNew )
1085 pPg = FindPageFrm();
1087 InsertPage( pPg, FALSE );
1088 pLayLeaf = GetNextLayoutLeaf();
1089 pOldLayLeaf = 0;
1090 continue;
1092 else
1093 pLayLeaf = 0;
1096 break;
1098 else
1100 //Es gibt keinen passenden weiteren LayoutFrm, also muss eine
1101 //neue Seite her.
1102 if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT )
1104 InsertPage(
1105 pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
1106 FALSE );
1108 //und nochmal das ganze
1109 pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
1111 else
1112 break;
1115 return pLayLeaf;
1118 /*************************************************************************
1120 |* SwFrm::GetPrevLeaf()
1122 |* Beschreibung Liefert das vorhergehende LayoutBlatt in das der
1123 |* Frame gemoved werden kann.
1124 |* Ersterstellung MA 16. Nov. 92
1125 |* Letzte Aenderung MA 25. Apr. 95
1127 |*************************************************************************/
1130 SwLayoutFrm *SwFrm::GetPrevLeaf( MakePageType )
1132 ASSERT( !IsInFtn(), "GetPrevLeaf(), don't call me for Ftn." );
1134 const BOOL bBody = IsInDocBody(); //Wenn ich aus dem DocBody komme
1135 //will ich auch im Body landen.
1136 const BOOL bFly = IsInFly();
1138 SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
1139 SwLayoutFrm *pPrevLeaf = 0;
1141 while ( pLayLeaf )
1143 if ( pLayLeaf->IsInTab() || //In Tabellen geht's niemals hinein.
1144 pLayLeaf->IsInSct() ) //In Bereiche natuerlich auch nicht!
1145 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1146 else if ( bBody && pLayLeaf->IsInDocBody() )
1148 if ( pLayLeaf->Lower() )
1149 break;
1150 pPrevLeaf = pLayLeaf;
1151 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1152 if ( pLayLeaf )
1153 SwFlowFrm::SetMoveBwdJump( TRUE );
1155 else if ( bFly )
1156 break; //Cntnts in Flys sollte jedes Layout-Blatt recht sein.
1157 else
1158 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1160 return pLayLeaf ? pLayLeaf : pPrevLeaf;
1163 /*************************************************************************
1165 |* SwFlowFrm::IsPrevObjMove()
1167 |* Ersterstellung MA 20. Feb. 96
1168 |* Letzte Aenderung MA 22. Feb. 96
1170 |*************************************************************************/
1173 BOOL SwFlowFrm::IsPrevObjMove() const
1175 //TRUE der FlowFrm soll auf einen Rahmen des Vorgaengers Ruecksicht nehmen
1176 // und fuer diesen ggf. Umbrechen.
1178 //!!!!!!!!!!!Hack!!!!!!!!!!!
1179 if ( rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) )
1180 return FALSE;
1182 SwFrm *pPre = rThis.FindPrev();
1184 if ( pPre && pPre->GetDrawObjs() )
1186 ASSERT( SwFlowFrm::CastFlowFrm( pPre ), "new flowfrm?" );
1187 if( SwFlowFrm::CastFlowFrm( pPre )->IsAnFollow( this ) )
1188 return FALSE;
1189 SwLayoutFrm* pPreUp = pPre->GetUpper();
1190 // Wenn der Upper ein SectionFrm oder die Spalte eines SectionFrms ist,
1191 // duerfen wir aus diesem durchaus heraushaengen,
1192 // es muss stattdessen der Upper des SectionFrms beruecksichtigt werden.
1193 if( pPreUp->IsInSct() )
1195 if( pPreUp->IsSctFrm() )
1196 pPreUp = pPreUp->GetUpper();
1197 else if( pPreUp->IsColBodyFrm() &&
1198 pPreUp->GetUpper()->GetUpper()->IsSctFrm() )
1199 pPreUp = pPreUp->GetUpper()->GetUpper()->GetUpper();
1201 // --> OD 2004-10-15 #i26945# - re-factoring:
1202 // use <GetVertPosOrientFrm()> to determine, if object has followed the
1203 // text flow to the next layout frame
1204 for ( USHORT i = 0; i < pPre->GetDrawObjs()->Count(); ++i )
1206 // --> OD 2004-07-01 #i28701# - consider changed type of
1207 // <SwSortedObjs> entries.
1208 const SwAnchoredObject* pObj = (*pPre->GetDrawObjs())[i];
1209 // OD 2004-01-20 #110582# - do not consider hidden objects
1210 // --> OD 2004-10-15 #i26945# - do not consider object, which
1211 // doesn't follow the text flow.
1212 if ( pObj->GetFrmFmt().GetDoc()->IsVisibleLayerId(
1213 pObj->GetDrawObj()->GetLayer() ) &&
1214 pObj->GetFrmFmt().GetFollowTextFlow().GetValue() )
1215 // <--
1217 const SwLayoutFrm* pVertPosOrientFrm = pObj->GetVertPosOrientFrm();
1218 if ( pVertPosOrientFrm &&
1219 pPreUp != pVertPosOrientFrm &&
1220 !pPreUp->IsAnLower( pVertPosOrientFrm ) )
1222 return TRUE;
1226 // <--
1228 return FALSE;
1231 /*************************************************************************
1233 |* BOOL SwFlowFrm::IsPageBreak()
1235 |* Beschreibung Wenn vor dem Frm ein harter Seitenumbruch steht UND
1236 |* es einen Vorgaenger auf der gleichen Seite gibt, wird TRUE
1237 |* zurueckgeliefert (es muss ein PageBreak erzeugt werden) FALSE sonst.
1238 |* Wenn in bAct TRUE uebergeben wird, gibt die Funktion dann TRUE
1239 |* zurueck, wenn ein PageBreak besteht.
1240 |* Fuer Follows wird der harte Seitenumbruch natuerlich nicht
1241 |* ausgewertet.
1242 |* Der Seitenumbruch steht im eigenen FrmFmt (BEFORE) oder im FrmFmt
1243 |* des Vorgaengers (AFTER). Wenn es keinen Vorgaenger auf der Seite
1244 |* gibt ist jede weitere Ueberlegung ueberfluessig.
1245 |* Ein Seitenumbruch (oder der Bedarf) liegt auch dann vor, wenn
1246 |* im FrmFmt ein PageDesc angegeben wird.
1247 |* Die Implementierung arbeitet zuaechst nur auf CntntFrms!
1248 |* -->Fuer LayoutFrms ist die Definition des Vorgaengers unklar.
1249 |* Ersterstellung MA ??
1250 |* Letzte Aenderung MA 21. Mar. 95
1252 |*************************************************************************/
1255 BOOL SwFlowFrm::IsPageBreak( BOOL bAct ) const
1257 if ( !IsFollow() && rThis.IsInDocBody() &&
1258 ( !rThis.IsInTab() || ( rThis.IsTabFrm() && !rThis.GetUpper()->IsInTab() ) ) && // i66968
1259 !rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) )
1261 const SwAttrSet *pSet = rThis.GetAttrSet();
1263 //Vorgaenger ermitteln
1264 const SwFrm *pPrev = rThis.FindPrev();
1265 while ( pPrev && ( !pPrev->IsInDocBody() ||
1266 ( pPrev->IsTxtFrm() && ((SwTxtFrm*)pPrev)->IsHiddenNow() ) ) )
1267 pPrev = pPrev->FindPrev();
1269 if ( pPrev )
1271 ASSERT( pPrev->IsInDocBody(), "IsPageBreak: Not in DocBody?" );
1272 if ( bAct )
1273 { if ( rThis.FindPageFrm() == pPrev->FindPageFrm() )
1274 return FALSE;
1276 else
1277 { if ( rThis.FindPageFrm() != pPrev->FindPageFrm() )
1278 return FALSE;
1281 const SvxBreak eBreak = pSet->GetBreak().GetBreak();
1282 if ( eBreak == SVX_BREAK_PAGE_BEFORE || eBreak == SVX_BREAK_PAGE_BOTH )
1283 return TRUE;
1284 else
1286 const SvxBreak &ePrB = pPrev->GetAttrSet()->GetBreak().GetBreak();
1287 if ( ePrB == SVX_BREAK_PAGE_AFTER ||
1288 ePrB == SVX_BREAK_PAGE_BOTH ||
1289 pSet->GetPageDesc().GetPageDesc() )
1290 return TRUE;
1294 return FALSE;
1297 /*************************************************************************
1299 |* BOOL SwFlowFrm::IsColBreak()
1301 |* Beschreibung Wenn vor dem Frm ein harter Spaltenumbruch steht UND
1302 |* es einen Vorgaenger in der gleichen Spalte gibt, wird TRUE
1303 |* zurueckgeliefert (es muss ein PageBreak erzeugt werden) FALSE sonst.
1304 |* Wenn in bAct TRUE uebergeben wird, gibt die Funktion dann TRUE
1305 |* zurueck, wenn ein ColBreak besteht.
1306 |* Fuer Follows wird der harte Spaltenumbruch natuerlich nicht
1307 |* ausgewertet.
1308 |* Der Spaltenumbruch steht im eigenen FrmFmt (BEFORE) oder im FrmFmt
1309 |* des Vorgaengers (AFTER). Wenn es keinen Vorgaenger in der Spalte
1310 |* gibt ist jede weitere Ueberlegung ueberfluessig.
1311 |* Die Implementierung arbeitet zuaechst nur auf CntntFrms!
1312 |* -->Fuer LayoutFrms ist die Definition des Vorgaengers unklar.
1313 |* Ersterstellung MA 11. Jun. 93
1314 |* Letzte Aenderung MA 21. Mar. 95
1316 |*************************************************************************/
1318 BOOL SwFlowFrm::IsColBreak( BOOL bAct ) const
1320 if ( !IsFollow() && (rThis.IsMoveable() || bAct) )
1322 const SwFrm *pCol = rThis.FindColFrm();
1323 if ( pCol )
1325 //Vorgaenger ermitteln
1326 const SwFrm *pPrev = rThis.FindPrev();
1327 while( pPrev && ( ( !pPrev->IsInDocBody() && !rThis.IsInFly() ) ||
1328 ( pPrev->IsTxtFrm() && ((SwTxtFrm*)pPrev)->IsHiddenNow() ) ) )
1329 pPrev = pPrev->FindPrev();
1331 if ( pPrev )
1333 if ( bAct )
1334 { if ( pCol == pPrev->FindColFrm() )
1335 return FALSE;
1337 else
1338 { if ( pCol != pPrev->FindColFrm() )
1339 return FALSE;
1342 const SvxBreak eBreak = rThis.GetAttrSet()->GetBreak().GetBreak();
1343 if ( eBreak == SVX_BREAK_COLUMN_BEFORE ||
1344 eBreak == SVX_BREAK_COLUMN_BOTH )
1345 return TRUE;
1346 else
1348 const SvxBreak &ePrB = pPrev->GetAttrSet()->GetBreak().GetBreak();
1349 if ( ePrB == SVX_BREAK_COLUMN_AFTER ||
1350 ePrB == SVX_BREAK_COLUMN_BOTH )
1351 return TRUE;
1356 return FALSE;
1359 BOOL SwFlowFrm::HasParaSpaceAtPages( BOOL bSct ) const
1361 if( rThis.IsInSct() )
1363 const SwFrm* pTmp = rThis.GetUpper();
1364 while( pTmp )
1366 if( pTmp->IsCellFrm() || pTmp->IsFlyFrm() ||
1367 pTmp->IsFooterFrm() || pTmp->IsHeaderFrm() ||
1368 ( pTmp->IsFtnFrm() && !((SwFtnFrm*)pTmp)->GetMaster() ) )
1369 return TRUE;
1370 if( pTmp->IsPageFrm() )
1371 return ( pTmp->GetPrev() && !IsPageBreak(TRUE) ) ? FALSE : TRUE;
1372 if( pTmp->IsColumnFrm() && pTmp->GetPrev() )
1373 return IsColBreak( TRUE );
1374 if( pTmp->IsSctFrm() && ( !bSct || pTmp->GetPrev() ) )
1375 return FALSE;
1376 pTmp = pTmp->GetUpper();
1378 ASSERT( FALSE, "HasParaSpaceAtPages: Where's my page?" );
1379 return FALSE;
1381 if( !rThis.IsInDocBody() || ( rThis.IsInTab() && !rThis.IsTabFrm()) ||
1382 IsPageBreak( TRUE ) || ( rThis.FindColFrm() && IsColBreak( TRUE ) ) )
1383 return TRUE;
1384 const SwFrm* pTmp = rThis.FindColFrm();
1385 if( pTmp )
1387 if( pTmp->GetPrev() )
1388 return FALSE;
1390 else
1391 pTmp = &rThis;
1392 pTmp = pTmp->FindPageFrm();
1393 return pTmp && !pTmp->GetPrev();
1396 /** helper method to determine previous frame for calculation of the
1397 upper space
1399 OD 2004-03-10 #i11860#
1401 @author OD
1403 const SwFrm* SwFlowFrm::_GetPrevFrmForUpperSpaceCalc( const SwFrm* _pProposedPrevFrm ) const
1405 const SwFrm* pPrevFrm = _pProposedPrevFrm
1406 ? _pProposedPrevFrm
1407 : rThis.GetPrev();
1409 // Skip hidden paragraphs and empty sections
1410 while ( pPrevFrm &&
1411 ( ( pPrevFrm->IsTxtFrm() &&
1412 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ||
1413 ( pPrevFrm->IsSctFrm() &&
1414 !static_cast<const SwSectionFrm*>(pPrevFrm)->GetSection() ) ) )
1416 pPrevFrm = pPrevFrm->GetPrev();
1419 // Special case: no direct previous frame is found but frame is in footnote
1420 // Search for a previous frame in previous footnote,
1421 // if frame isn't in a section, which is also in the footnote
1422 if ( !pPrevFrm && rThis.IsInFtn() &&
1423 ( rThis.IsSctFrm() ||
1424 !rThis.IsInSct() || !rThis.FindSctFrm()->IsInFtn() ) )
1426 const SwFtnFrm* pPrevFtnFrm =
1427 static_cast<const SwFtnFrm*>(rThis.FindFtnFrm()->GetPrev());
1428 if ( pPrevFtnFrm )
1430 pPrevFrm = pPrevFtnFrm->GetLastLower();
1432 // Skip hidden paragraphs and empty sections
1433 while ( pPrevFrm &&
1434 ( ( pPrevFrm->IsTxtFrm() &&
1435 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ||
1436 ( pPrevFrm->IsSctFrm() &&
1437 !static_cast<const SwSectionFrm*>(pPrevFrm)->GetSection() ) ) )
1439 pPrevFrm = pPrevFrm->GetPrev();
1443 // Special case: found previous frame is a section
1444 // Search for the last content in the section
1445 if( pPrevFrm && pPrevFrm->IsSctFrm() )
1447 const SwSectionFrm* pPrevSectFrm =
1448 static_cast<const SwSectionFrm*>(pPrevFrm);
1449 pPrevFrm = pPrevSectFrm->FindLastCntnt();
1450 // If the last content is in a table _inside_ the section,
1451 // take the table herself.
1452 // OD 2004-02-18 #106629# - correction:
1453 // Check directly, if table is inside table, instead of indirectly
1454 // by checking, if section isn't inside a table
1455 if ( pPrevFrm && pPrevFrm->IsInTab() )
1457 const SwTabFrm* pTableFrm = pPrevFrm->FindTabFrm();
1458 if ( pPrevSectFrm->IsAnLower( pTableFrm ) )
1460 pPrevFrm = pTableFrm;
1463 // OD 2004-02-18 #106629# correction: skip hidden text frames
1464 while ( pPrevFrm &&
1465 pPrevFrm->IsTxtFrm() &&
1466 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() )
1468 pPrevFrm = pPrevFrm->GetPrev();
1472 return pPrevFrm;
1475 // OD 2004-03-12 #i11860# - add 3rd parameter <_bConsiderGrid>
1476 SwTwips SwFlowFrm::CalcUpperSpace( const SwBorderAttrs *pAttrs,
1477 const SwFrm* pPr,
1478 const bool _bConsiderGrid ) const
1480 // OD 2004-03-10 #i11860# - use new method <GetPrevFrmForUpperSpaceCalc(..)>
1481 const SwFrm* pPrevFrm = _GetPrevFrmForUpperSpaceCalc( pPr );
1483 SwBorderAttrAccess *pAccess;
1484 SwFrm* pOwn;
1485 if( !pAttrs )
1487 if( rThis.IsSctFrm() )
1489 SwSectionFrm* pFoll = &((SwSectionFrm&)rThis);
1491 pOwn = pFoll->ContainsAny();
1492 while( !pOwn && 0 != ( pFoll = pFoll->GetFollow() ) );
1493 if( !pOwn )
1494 return 0;
1496 else
1497 pOwn = &rThis;
1498 pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), pOwn );
1499 pAttrs = pAccess->Get();
1501 else
1503 pAccess = NULL;
1504 pOwn = &rThis;
1506 SwTwips nUpper = 0;
1507 // OD 06.01.2004 #i11859#
1509 const IDocumentSettingAccess* pIDSA = rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess();
1510 const bool bUseFormerLineSpacing = pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING);
1511 if( pPrevFrm )
1513 // OD 2004-03-10 #i11860# - use new method to determine needed spacing
1514 // values of found previous frame and use these values.
1515 SwTwips nPrevLowerSpace = 0;
1516 SwTwips nPrevLineSpacing = 0;
1517 // --> OD 2009-08-28 #i102458#
1518 bool bPrevLineSpacingPorportional = false;
1519 GetSpacingValuesOfFrm( (*pPrevFrm),
1520 nPrevLowerSpace, nPrevLineSpacing,
1521 bPrevLineSpacingPorportional );
1522 // <--
1523 if( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) )
1525 nUpper = nPrevLowerSpace + pAttrs->GetULSpace().GetUpper();
1526 SwTwips nAdd = nPrevLineSpacing;
1527 // OD 07.01.2004 #i11859# - consideration of the line spacing
1528 // for the upper spacing of a text frame
1529 if ( bUseFormerLineSpacing )
1531 // former consideration
1532 if ( pOwn->IsTxtFrm() )
1534 nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace() );
1536 nUpper += nAdd;
1538 else
1540 // new consideration:
1541 // Only the proportional line spacing of the previous
1542 // text frame is considered for the upper spacing and
1543 // the line spacing values are add up instead of
1544 // building its maximum.
1545 if ( pOwn->IsTxtFrm() )
1547 // --> OD 2009-08-28 #i102458#
1548 // Correction:
1549 // A proportional line spacing of the previous text frame
1550 // is added up to a own leading line spacing.
1551 // Otherwise, the maximum of the leading line spacing
1552 // of the previous text frame and the own leading line
1553 // spacing is built.
1554 if ( bPrevLineSpacingPorportional )
1556 nAdd += static_cast<SwTxtFrm&>(rThis).GetLineSpace( true );
1558 else
1560 nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ) );
1562 // <--
1564 nUpper += nAdd;
1567 else
1569 nUpper = Max( static_cast<long>(nPrevLowerSpace),
1570 static_cast<long>(pAttrs->GetULSpace().GetUpper()) );
1571 // OD 07.01.2004 #i11859# - consideration of the line spacing
1572 // for the upper spacing of a text frame
1573 if ( bUseFormerLineSpacing )
1575 // former consideration
1576 if ( pOwn->IsTxtFrm() )
1577 nUpper = Max( nUpper, ((SwTxtFrm*)pOwn)->GetLineSpace() );
1578 if ( nPrevLineSpacing != 0 )
1580 nUpper = Max( nUpper, nPrevLineSpacing );
1583 else
1585 // new consideration:
1586 // Only the proportional line spacing of the previous
1587 // text frame is considered for the upper spacing and
1588 // the line spacing values are add up and added to
1589 // the paragraph spacing instead of building the
1590 // maximum of the line spacings and the paragraph spacing.
1591 SwTwips nAdd = nPrevLineSpacing;
1592 if ( pOwn->IsTxtFrm() )
1594 // --> OD 2009-08-28 #i102458#
1595 // Correction:
1596 // A proportional line spacing of the previous text frame
1597 // is added up to a own leading line spacing.
1598 // Otherwise, the maximum of the leading line spacing
1599 // of the previous text frame and the own leading line
1600 // spacing is built.
1601 if ( bPrevLineSpacingPorportional )
1603 nAdd += static_cast<SwTxtFrm&>(rThis).GetLineSpace( true );
1605 else
1607 nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ) );
1609 // <--
1611 nUpper += nAdd;
1615 else if ( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES) &&
1616 CastFlowFrm( pOwn )->HasParaSpaceAtPages( rThis.IsSctFrm() ) )
1618 nUpper = pAttrs->GetULSpace().GetUpper();
1622 // OD 2004-02-26 #i25029# - pass previous frame <pPrevFrm>
1623 // to method <GetTopLine(..)>, if parameter <pPr> is set.
1624 // Note: parameter <pPr> is set, if method is called from <SwTxtFrm::WouldFit(..)>
1625 nUpper += pAttrs->GetTopLine( rThis, (pPr ? pPrevFrm : 0L) );
1627 // OD 2004-03-12 #i11860# - consider value of new parameter <_bConsiderGrid>
1628 // and use new method <GetUpperSpaceAmountConsideredForPageGrid(..)>
1630 //consider grid in square page mode
1631 if ( _bConsiderGrid && rThis.GetUpper()->GetFmt()->GetDoc()->IsSquaredPageMode() )
1633 nUpper += _GetUpperSpaceAmountConsideredForPageGrid( nUpper );
1636 delete pAccess;
1637 return nUpper;
1640 /** method to detemine the upper space amount, which is considered for
1641 the page grid
1643 OD 2004-03-12 #i11860#
1644 Precondition: Position of frame is valid.
1646 @author OD
1648 SwTwips SwFlowFrm::_GetUpperSpaceAmountConsideredForPageGrid(
1649 const SwTwips _nUpperSpaceWithoutGrid ) const
1651 SwTwips nUpperSpaceAmountConsideredForPageGrid = 0;
1653 if ( rThis.IsInDocBody() && rThis.GetAttrSet()->GetParaGrid().GetValue() )
1655 const SwPageFrm* pPageFrm = rThis.FindPageFrm();
1656 GETGRID( pPageFrm )
1657 if( pGrid )
1659 const SwFrm* pBodyFrm = pPageFrm->FindBodyCont();
1660 if ( pBodyFrm )
1662 const long nGridLineHeight =
1663 pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
1665 SWRECTFN( (&rThis) )
1666 const SwTwips nBodyPrtTop = (pBodyFrm->*fnRect->fnGetPrtTop)();
1667 const SwTwips nProposedPrtTop =
1668 (*fnRect->fnYInc)( (rThis.Frm().*fnRect->fnGetTop)(),
1669 _nUpperSpaceWithoutGrid );
1671 const SwTwips nSpaceAbovePrtTop =
1672 (*fnRect->fnYDiff)( nProposedPrtTop, nBodyPrtTop );
1673 const SwTwips nSpaceOfCompleteLinesAbove =
1674 nGridLineHeight * ( nSpaceAbovePrtTop / nGridLineHeight );
1675 SwTwips nNewPrtTop =
1676 (*fnRect->fnYInc)( nBodyPrtTop, nSpaceOfCompleteLinesAbove );
1677 if ( (*fnRect->fnYDiff)( nProposedPrtTop, nNewPrtTop ) > 0 )
1679 nNewPrtTop = (*fnRect->fnYInc)( nNewPrtTop, nGridLineHeight );
1682 const SwTwips nNewUpperSpace =
1683 (*fnRect->fnYDiff)( nNewPrtTop,
1684 (rThis.Frm().*fnRect->fnGetTop)() );
1686 nUpperSpaceAmountConsideredForPageGrid =
1687 nNewUpperSpace - _nUpperSpaceWithoutGrid;
1689 ASSERT( nUpperSpaceAmountConsideredForPageGrid >= 0,
1690 "<SwFlowFrm::GetUpperSpaceAmountConsideredForPageGrid(..)> - negative space considered for page grid!" );
1694 return nUpperSpaceAmountConsideredForPageGrid;
1697 /** method to determent the upper space amount, which is considered for
1698 the previous frame
1700 OD 2004-03-11 #i11860#
1702 @author OD
1704 SwTwips SwFlowFrm::_GetUpperSpaceAmountConsideredForPrevFrm() const
1706 SwTwips nUpperSpaceAmountOfPrevFrm = 0;
1708 const SwFrm* pPrevFrm = _GetPrevFrmForUpperSpaceCalc();
1709 if ( pPrevFrm )
1711 SwTwips nPrevLowerSpace = 0;
1712 SwTwips nPrevLineSpacing = 0;
1713 // --> OD 2009-08-28 #i102458#
1714 bool bDummy = false;
1715 GetSpacingValuesOfFrm( (*pPrevFrm), nPrevLowerSpace, nPrevLineSpacing, bDummy );
1716 // <--
1717 if ( nPrevLowerSpace > 0 || nPrevLineSpacing > 0 )
1719 const IDocumentSettingAccess* pIDSA = rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess();
1720 if ( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) ||
1721 !pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING) )
1723 nUpperSpaceAmountOfPrevFrm = nPrevLowerSpace + nPrevLineSpacing;
1725 else
1727 nUpperSpaceAmountOfPrevFrm = Max( nPrevLowerSpace, nPrevLineSpacing );
1732 return nUpperSpaceAmountOfPrevFrm;
1735 /** method to determine the upper space amount, which is considered for
1736 the previous frame and the page grid, if option 'Use former object
1737 positioning' is OFF
1739 OD 2004-03-18 #i11860#
1741 @author OD
1743 SwTwips SwFlowFrm::GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() const
1745 SwTwips nUpperSpaceAmountConsideredForPrevFrmAndPageGrid = 0;
1747 if ( !rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) )
1749 nUpperSpaceAmountConsideredForPrevFrmAndPageGrid =
1750 _GetUpperSpaceAmountConsideredForPrevFrm() +
1751 _GetUpperSpaceAmountConsideredForPageGrid( CalcUpperSpace( 0L, 0L, false ) );
1754 return nUpperSpaceAmountConsideredForPrevFrmAndPageGrid;
1757 /** calculation of lower space
1759 OD 2004-03-02 #106629#
1761 @author OD
1763 SwTwips SwFlowFrm::CalcLowerSpace( const SwBorderAttrs* _pAttrs ) const
1765 SwTwips nLowerSpace = 0;
1767 SwBorderAttrAccess* pAttrAccess = 0L;
1768 if ( !_pAttrs )
1770 pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), &rThis );
1771 _pAttrs = pAttrAccess->Get();
1774 sal_Bool bCommonBorder = sal_True;
1775 if ( rThis.IsInSct() && rThis.GetUpper()->IsColBodyFrm() )
1777 const SwSectionFrm* pSectFrm = rThis.FindSctFrm();
1778 bCommonBorder = pSectFrm->GetFmt()->GetBalancedColumns().GetValue();
1780 nLowerSpace = bCommonBorder ?
1781 _pAttrs->GetBottomLine( rThis ) :
1782 _pAttrs->CalcBottomLine();
1784 // --> OD 2004-07-16 #i26250#
1785 // - correct consideration of table frames
1786 // - use new method <CalcAddLowerSpaceAsLastInTableCell(..)>
1787 if ( ( ( rThis.IsTabFrm() && rThis.GetUpper()->IsInTab() ) ||
1788 // --> OD 2004-11-16 #115759# - no lower spacing, if frame has a follow
1789 ( rThis.IsInTab() && !GetFollow() ) ) &&
1790 // <--
1791 !rThis.GetIndNext() )
1793 nLowerSpace += CalcAddLowerSpaceAsLastInTableCell( _pAttrs );
1795 // <--
1797 delete pAttrAccess;
1799 return nLowerSpace;
1802 /** calculation of the additional space to be considered, if flow frame
1803 is the last inside a table cell
1805 OD 2004-07-16 #i26250#
1807 @author OD
1809 SwTwips SwFlowFrm::CalcAddLowerSpaceAsLastInTableCell(
1810 const SwBorderAttrs* _pAttrs ) const
1812 SwTwips nAdditionalLowerSpace = 0;
1814 if ( rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
1816 const SwFrm* pFrm = &rThis;
1817 if ( pFrm->IsSctFrm() )
1819 const SwSectionFrm* pSectFrm = static_cast<const SwSectionFrm*>(pFrm);
1820 pFrm = pSectFrm->FindLastCntnt();
1821 if ( pFrm && pFrm->IsInTab() )
1823 const SwTabFrm* pTableFrm = pFrm->FindTabFrm();
1824 if ( pSectFrm->IsAnLower( pTableFrm ) )
1826 pFrm = pTableFrm;
1831 SwBorderAttrAccess* pAttrAccess = 0L;
1832 if ( !_pAttrs || pFrm != &rThis )
1834 pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), pFrm );
1835 _pAttrs = pAttrAccess->Get();
1838 nAdditionalLowerSpace += _pAttrs->GetULSpace().GetLower();
1840 delete pAttrAccess;
1843 return nAdditionalLowerSpace;
1846 /*************************************************************************
1848 |* BOOL SwFlowFrm::CheckMoveFwd()
1850 |* Beschreibung Moved den Frm vorwaerts wenn es durch die aktuellen
1851 |* Bedingungen und Attribute notwendig erscheint.
1852 |* Ersterstellung MA 05. Dec. 96
1853 |* Letzte Aenderung MA 09. Mar. 98
1855 |*************************************************************************/
1858 BOOL SwFlowFrm::CheckMoveFwd( BOOL &rbMakePage, BOOL bKeep, BOOL )
1860 const SwFrm* pNxt = rThis.GetIndNext();
1862 if ( bKeep && //!bMovedBwd &&
1863 ( !pNxt || ( pNxt->IsTxtFrm() && ((SwTxtFrm*)pNxt)->IsEmptyMaster() ) ) &&
1864 ( 0 != (pNxt = rThis.FindNext()) ) && IsKeepFwdMoveAllowed() )
1866 if( pNxt->IsSctFrm() )
1867 { // Nicht auf leere SectionFrms hereinfallen
1868 const SwFrm* pTmp = NULL;
1869 while( pNxt && pNxt->IsSctFrm() &&
1870 ( !((SwSectionFrm*)pNxt)->GetSection() ||
1871 0 == ( pTmp = ((SwSectionFrm*)pNxt)->ContainsAny() ) ) )
1873 pNxt = pNxt->FindNext();
1874 pTmp = NULL;
1876 if( pTmp )
1877 pNxt = pTmp; // the content of the next notempty sectionfrm
1879 if( pNxt && pNxt->GetValidPosFlag() )
1881 BOOL bMove = FALSE;
1882 const SwSectionFrm *pSct = rThis.FindSctFrm();
1883 if( pSct && !pSct->GetValidSizeFlag() )
1885 const SwSectionFrm* pNxtSct = pNxt->FindSctFrm();
1886 if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
1887 bMove = TRUE;
1889 else
1890 bMove = TRUE;
1891 if( bMove )
1893 //Keep together with the following frame
1894 MoveFwd( rbMakePage, FALSE );
1895 return TRUE;
1900 BOOL bMovedFwd = FALSE;
1902 if ( rThis.GetIndPrev() )
1904 if ( IsPrevObjMove() ) //Auf Objekte des Prev Ruecksicht nehmen?
1906 bMovedFwd = TRUE;
1907 if ( !MoveFwd( rbMakePage, FALSE ) )
1908 rbMakePage = FALSE;
1910 else
1912 if ( IsPageBreak( FALSE ) )
1914 while ( MoveFwd( rbMakePage, TRUE ) )
1915 /* do nothing */;
1916 rbMakePage = FALSE;
1917 bMovedFwd = TRUE;
1919 else if ( IsColBreak ( FALSE ) )
1921 const SwPageFrm *pPage = rThis.FindPageFrm();
1922 SwFrm *pCol = rThis.FindColFrm();
1924 { MoveFwd( rbMakePage, FALSE );
1925 SwFrm *pTmp = rThis.FindColFrm();
1926 if( pTmp != pCol )
1928 bMovedFwd = TRUE;
1929 pCol = pTmp;
1931 else
1932 break;
1933 } while ( IsColBreak( FALSE ) );
1934 if ( pPage != rThis.FindPageFrm() )
1935 rbMakePage = FALSE;
1939 return bMovedFwd;
1942 /*************************************************************************
1944 |* BOOL SwFlowFrm::MoveFwd()
1946 |* Beschreibung Returnwert sagt, ob der Frm die Seite gewechselt hat.
1947 |* Ersterstellung MA 05. Dec. 96
1948 |* Letzte Aenderung MA 05. Dec. 96
1950 |*************************************************************************/
1953 BOOL SwFlowFrm::MoveFwd( BOOL bMakePage, BOOL bPageBreak, BOOL bMoveAlways )
1955 //!!!!MoveFtnCntFwd muss ggf. mitgepflegt werden.
1956 SwFtnBossFrm *pOldBoss = rThis.FindFtnBossFrm();
1957 if ( rThis.IsInFtn() )
1958 return ((SwCntntFrm&)rThis).MoveFtnCntFwd( bMakePage, pOldBoss );
1960 if( !IsFwdMoveAllowed() && !bMoveAlways )
1962 BOOL bNoFwd = TRUE;
1963 if( rThis.IsInSct() )
1965 SwFtnBossFrm* pBoss = rThis.FindFtnBossFrm();
1966 bNoFwd = !pBoss->IsInSct() || ( !pBoss->Lower()->GetNext() &&
1967 !pBoss->GetPrev() );
1970 // Allow the MoveFwd even if we do not have an IndPrev in these cases:
1971 if ( rThis.IsInTab() &&
1972 ( !rThis.IsTabFrm() ||
1973 ( rThis.GetUpper()->IsInTab() &&
1974 rThis.GetUpper()->FindTabFrm()->IsFwdMoveAllowed() ) ) &&
1975 0 != const_cast<SwFrm&>(rThis).GetNextCellLeaf( MAKEPAGE_NONE ) )
1978 // NEW TABLES
1979 // Have a look at our main competitor: We don't move inside row span cells:
1980 ( !rThis.GetUpper()->IsCellFrm() || !rThis.GetUpper()->IsLeaveUpperAllowed() ) )*/
1982 bNoFwd = FALSE;
1985 if( bNoFwd )
1987 //Fuer PageBreak ist das Moven erlaubt, wenn der Frm nicht
1988 //bereits der erste der Seite ist.
1989 if ( !bPageBreak )
1990 return FALSE;
1992 const SwFrm *pCol = rThis.FindColFrm();
1993 if ( !pCol || !pCol->GetPrev() )
1994 return FALSE;
1998 BOOL bSamePage = TRUE;
1999 SwLayoutFrm *pNewUpper =
2000 rThis.GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, TRUE );
2002 if ( pNewUpper )
2004 PROTOCOL_ENTER( &rThis, PROT_MOVE_FWD, 0, 0 );
2005 SwPageFrm *pOldPage = pOldBoss->FindPageFrm();
2006 //Wir moven uns und alle direkten Nachfolger vor den ersten
2007 //CntntFrm unterhalb des neuen Uppers.
2009 // Wenn unser NewUpper in einem SectionFrm liegt, muessen wir
2010 // verhindern, dass sich dieser im Calc selbst zerstoert
2011 SwSectionFrm* pSect = pNewUpper->FindSctFrm();
2012 BOOL bUnlock = FALSE;
2013 if( pSect )
2015 // Wenn wir nur innerhalb unseres SectionFrms die Spalte wechseln,
2016 // rufen wir lieber kein Calc, sonst wird noch der SectionFrm
2017 // formatiert, der wiederum uns ruft etc.
2018 if( pSect != rThis.FindSctFrm() )
2020 bUnlock = !pSect->IsColLocked();
2021 pSect->ColLock();
2022 pNewUpper->Calc();
2023 if( bUnlock )
2024 pSect->ColUnlock();
2027 // Do not calculate split cell frames.
2028 else if ( !pNewUpper->IsCellFrm() || ((SwLayoutFrm*)pNewUpper)->Lower() )
2029 pNewUpper->Calc();
2031 SwFtnBossFrm *pNewBoss = pNewUpper->FindFtnBossFrm();
2032 BOOL bBossChg = pNewBoss != pOldBoss;
2033 pNewBoss = pNewBoss->FindFtnBossFrm( TRUE );
2034 pOldBoss = pOldBoss->FindFtnBossFrm( TRUE );
2035 SwPageFrm* pNewPage = pOldPage;
2037 // First, we move the footnotes.
2038 BOOL bFtnMoved = FALSE;
2040 // --> FME 2004-07-15 #i26831#
2041 // If pSect has just been created, the printing area of pSect has
2042 // been calculated based on the first content of its follow.
2043 // In this case we prefer to call a SimpleFormat for this new
2044 // section after we inserted the contents. Otherwise the section
2045 // frame will invalidate its lowers, if its printing area changes
2046 // in SwSectionFrm::Format, which can cause loops.
2047 const bool bForceSimpleFormat = pSect && pSect->HasFollow() &&
2048 !pSect->ContainsAny();
2049 // <--
2051 if ( pNewBoss != pOldBoss )
2053 pNewPage = pNewBoss->FindPageFrm();
2054 bSamePage = pNewPage == pOldPage;
2055 //Damit die Fussnoten nicht auf dumme Gedanken kommen
2056 //setzen wir hier die Deadline.
2057 SWRECTFN( pOldBoss )
2058 SwSaveFtnHeight aHeight( pOldBoss,
2059 (pOldBoss->Frm().*fnRect->fnGetBottom)() );
2060 SwCntntFrm* pStart = rThis.IsCntntFrm() ?
2061 (SwCntntFrm*)&rThis : ((SwLayoutFrm&)rThis).ContainsCntnt();
2062 ASSERT( pStart || ( rThis.IsTabFrm() && !((SwTabFrm&)rThis).Lower() ),
2063 "MoveFwd: Missing Content" );
2064 SwLayoutFrm* pBody = pStart ? ( pStart->IsTxtFrm() ?
2065 (SwLayoutFrm*)((SwTxtFrm*)pStart)->FindBodyFrm() : 0 ) : 0;
2066 if( pBody )
2067 bFtnMoved = pBody->MoveLowerFtns( pStart, pOldBoss, pNewBoss,
2068 FALSE);
2070 // Bei SectionFrms ist es moeglich, dass wir selbst durch pNewUpper->Calc()
2071 // bewegt wurden, z. B. in den pNewUpper.
2072 // MoveSubTree bzw. PasteTree ist auf so etwas nicht vorbereitet.
2073 if( pNewUpper != rThis.GetUpper() )
2075 // --> FME 2004-04-19 #i27145#
2076 SwSectionFrm* pOldSct = 0;
2077 if ( rThis.GetUpper()->IsSctFrm() )
2079 pOldSct = static_cast<SwSectionFrm*>(rThis.GetUpper());
2081 // <--
2083 MoveSubTree( pNewUpper, pNewUpper->Lower() );
2085 // --> FME 2004-04-19 #i27145#
2086 if ( pOldSct && pOldSct->GetSection() )
2088 // Prevent loops by setting the new height at
2089 // the section frame if footnotes have been moved.
2090 // Otherwise the call of SwLayNotify::~SwLayNotify() for
2091 // the (invalid) section frame will invalidate the first
2092 // lower of its follow, because it grows due to the removed
2093 // footnotes.
2094 // Note: If pOldSct has become empty during MoveSubTree, it
2095 // has already been scheduled for removal. No SimpleFormat
2096 // for these.
2097 pOldSct->SimpleFormat();
2099 // <--
2101 // --> FME 2004-07-15 #i26831#
2102 if ( bForceSimpleFormat )
2104 pSect->SimpleFormat();
2106 // <--
2108 if ( bFtnMoved && !bSamePage )
2110 pOldPage->UpdateFtnNum();
2111 pNewPage->UpdateFtnNum();
2114 if( bBossChg )
2116 rThis.Prepare( PREP_BOSS_CHGD, 0, FALSE );
2117 if( !bSamePage )
2119 ViewShell *pSh = rThis.GetShell();
2120 if ( pSh && !pSh->Imp()->IsUpdateExpFlds() )
2121 pSh->GetDoc()->SetNewFldLst(true); //Wird von CalcLayout() hinterher erledigt!
2123 pNewPage->InvalidateSpelling();
2124 pNewPage->InvalidateSmartTags(); // SMARTTAGS
2125 pNewPage->InvalidateAutoCompleteWords();
2126 pNewPage->InvalidateWordCount();
2130 // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout
2131 if ( !pNewPage->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) )
2133 //Bei Sections kann es passieren, das wir gleich in den Follow geflutscht
2134 //sind. Dadurch wird nicht vom GetLeaf fuer die richtige Seite gesorgt.
2135 //Das muessen wir fuer diesen Fall pruefen.
2136 if ( !bSamePage && pNewUpper->IsInSct() &&
2137 ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() ||
2138 pOldPage->GetPageDesc()->GetFollow() != pNewPage->GetPageDesc() ) )
2139 SwFrm::CheckPageDescs( pNewPage, FALSE );
2142 return bSamePage;
2146 /*************************************************************************
2148 |* BOOL SwFlowFrm::MoveBwd()
2150 |* Beschreibung Returnwert sagt, ob der Frm die Seite wechseln soll.
2151 |* Sollte von abgeleiteten Klassen gerufen werden.
2152 |* Das moven selbst muessen die abgeleiteten uebernehmen.
2153 |* Ersterstellung MA 05. Dec. 96
2154 |* Letzte Aenderung MA 05. Dec. 96
2156 |*************************************************************************/
2158 BOOL SwFlowFrm::MoveBwd( BOOL &rbReformat )
2160 SwFlowFrm::SetMoveBwdJump( FALSE );
2162 SwFtnFrm* pFtn = rThis.FindFtnFrm();
2163 if ( pFtn && pFtn->IsBackMoveLocked() )
2164 return FALSE;
2166 // --> OD 2004-11-29 #115759# - text frames, which are directly inside
2167 // tables aren't allowed to move backward.
2168 if ( rThis.IsTxtFrm() && rThis.IsInTab() )
2170 const SwLayoutFrm* pUpperFrm = rThis.GetUpper();
2171 while ( pUpperFrm )
2173 if ( pUpperFrm->IsTabFrm() )
2175 return FALSE;
2177 else if ( pUpperFrm->IsColumnFrm() && pUpperFrm->IsInSct() )
2179 break;
2181 pUpperFrm = pUpperFrm->GetUpper();
2184 // <--
2186 SwFtnBossFrm * pOldBoss = rThis.FindFtnBossFrm();
2187 SwPageFrm * const pOldPage = pOldBoss->FindPageFrm();
2188 SwLayoutFrm *pNewUpper = 0;
2189 BOOL bCheckPageDescs = FALSE;
2190 bool bCheckPageDescOfNextPage = false;
2192 if ( pFtn )
2194 //Wenn die Fussnote bereits auf der gleichen Seite/Spalte wie die Referenz
2195 //steht, ist nix mit zurueckfliessen. Die breaks brauche fuer die
2196 //Fussnoten nicht geprueft zu werden.
2198 // --> FME 2004-11-15 #i37084# FindLastCntnt does not necessarily
2199 // have to have a result != 0
2200 SwFrm* pRef = 0;
2201 const bool bEndnote = pFtn->GetAttr()->GetFtn().IsEndNote();
2202 if( bEndnote && pFtn->IsInSct() )
2204 SwSectionFrm* pSect = pFtn->FindSctFrm();
2205 if( pSect->IsEndnAtEnd() )
2206 pRef = pSect->FindLastCntnt( FINDMODE_LASTCNT );
2208 if( !pRef )
2209 pRef = pFtn->GetRef();
2210 // <--
2212 ASSERT( pRef, "MoveBwd: Endnote for an empty section?" );
2214 if( !bEndnote )
2215 pOldBoss = pOldBoss->FindFtnBossFrm( TRUE );
2216 SwFtnBossFrm *pRefBoss = pRef->FindFtnBossFrm( !bEndnote );
2217 if ( pOldBoss != pRefBoss &&
2218 // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
2219 ( !bEndnote ||
2220 pRefBoss->IsBefore( pOldBoss ) )
2222 pNewUpper = rThis.GetLeaf( MAKEPAGE_FTN, FALSE );
2224 else if ( IsPageBreak( TRUE ) ) //PageBreak zu beachten?
2226 //Wenn auf der vorhergehenden Seite kein Frm im Body steht,
2227 //so ist das Zurueckfliessen trotz Pagebreak sinnvoll
2228 //(sonst: leere Seite).
2229 //Natuerlich muessen Leereseiten geflissentlich uebersehen werden!
2230 const SwFrm *pFlow = &rThis;
2233 pFlow = pFlow->FindPrev();
2234 } while ( pFlow &&
2235 ( pFlow->FindPageFrm() == pOldPage ||
2236 !pFlow->IsInDocBody() ) );
2237 if ( pFlow )
2239 long nDiff = pOldPage->GetPhyPageNum() - pFlow->GetPhyPageNum();
2240 if ( nDiff > 1 )
2242 if ( ((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage() )
2243 nDiff -= 1;
2244 if ( nDiff > 1 )
2246 pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, FALSE );
2247 // --> OD 2006-05-08 #i53139#
2248 // Now <pNewUpper> is a previous layout frame, which contains
2249 // content. But the new upper layout frame has to be the next one.
2250 // Thus, hack for issue i14206 no longer needed, but fix for issue 114442
2251 // --> OD 2006-05-17 #136024# - correct fix for i53139:
2252 // Check for wrong page description before using next new upper.
2253 // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
2254 // Check for correct type of new next upper layout frame
2255 // --> OD 2006-06-08 #136538# - another correction of fix for i53139
2256 // Assumption, that in all cases <pNewUpper> is a previous
2257 // layout frame, which contains content, is wrong.
2258 // --> OD 2006-07-05 #136538# - another correction of fix for i53139
2259 // Beside type check, check also, if proposed new next upper
2260 // frame is inside the same frame types.
2261 // --> OD 2007-01-10 #i73194# - and yet another correction
2262 // of fix for i53139:
2263 // Assure that the new next upper layout frame doesn't
2264 // equal the current one.
2265 // E.g.: content is on page 3, on page 2 is only a 'ghost'
2266 // section and on page 1 is normal content. Method <FindPrev(..)>
2267 // will find the last content of page 1, but <GetLeaf(..)>
2268 // returns new upper on page 2.
2269 if ( pNewUpper->Lower() )
2271 SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, TRUE );
2272 if ( pNewNextUpper &&
2273 pNewNextUpper != rThis.GetUpper() &&
2274 pNewNextUpper->GetType() == pNewUpper->GetType() &&
2275 pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2276 pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2277 pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2278 pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2279 !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2281 pNewUpper = pNewNextUpper;
2282 bCheckPageDescOfNextPage = true;
2285 // <--
2287 bCheckPageDescs = TRUE;
2292 else if ( IsColBreak( TRUE ) )
2294 //Wenn in der vorhergehenden Spalte kein CntntFrm steht, so ist
2295 //das Zurueckfliessen trotz ColumnBreak sinnvoll
2296 //(sonst: leere Spalte).
2297 if( rThis.IsInSct() )
2299 pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, FALSE );
2300 if( pNewUpper && !SwFlowFrm::IsMoveBwdJump() &&
2301 ( pNewUpper->ContainsCntnt() ||
2302 ( ( !pNewUpper->IsColBodyFrm() ||
2303 !pNewUpper->GetUpper()->GetPrev() ) &&
2304 !pNewUpper->FindSctFrm()->GetPrev() ) ) )
2306 pNewUpper = 0;
2308 // --> OD 2006-05-08 #i53139#
2309 // --> OD 2006-09-11 #i69409# - check <pNewUpper>
2310 // --> OD 2006-11-02 #i71065# - check <SwFlowFrm::IsMoveBwdJump()>
2311 else if ( pNewUpper && !SwFlowFrm::IsMoveBwdJump() )
2312 // <--
2314 // Now <pNewUpper> is a previous layout frame, which
2315 // contains content. But the new upper layout frame
2316 // has to be the next one.
2317 // --> OD 2006-05-17 #136024# - correct fix for i53139
2318 // Check for wrong page description before using next new upper.
2319 // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
2320 // Check for correct type of new next upper layout frame
2321 // --> OD 2006-07-05 #136538# - another correction of fix for i53139
2322 // Beside type check, check also, if proposed new next upper
2323 // frame is inside the same frame types.
2324 SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NOSECTION, TRUE );
2325 if ( pNewNextUpper &&
2326 pNewNextUpper->GetType() == pNewUpper->GetType() &&
2327 pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2328 pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2329 pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2330 pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2331 !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2333 pNewUpper = pNewNextUpper;
2336 // <--
2338 else
2340 const SwFrm *pCol = rThis.FindColFrm();
2341 BOOL bGoOn = TRUE;
2342 BOOL bJump = FALSE;
2345 if ( pCol->GetPrev() )
2346 pCol = pCol->GetPrev();
2347 else
2349 bGoOn = FALSE;
2350 pCol = rThis.GetLeaf( MAKEPAGE_NONE, FALSE );
2352 if ( pCol )
2354 // ColumnFrms jetzt mit BodyFrm
2355 SwLayoutFrm* pColBody = pCol->IsColumnFrm() ?
2356 (SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower() :
2357 (SwLayoutFrm*)pCol;
2358 if ( pColBody->ContainsCntnt() )
2360 bGoOn = FALSE; // Hier gibt's Inhalt, wir akzeptieren diese
2361 // nur, wenn GetLeaf() das MoveBwdJump-Flag gesetzt hat.
2362 if( SwFlowFrm::IsMoveBwdJump() )
2364 pNewUpper = pColBody;
2365 // --> OD 2006-05-08 #i53139#
2366 // Now <pNewUpper> is a previous layout frame, which
2367 // contains content. But the new upper layout frame
2368 // has to be the next one.
2369 // --> OD 2006-05-17 #136024# - correct fix for i53139
2370 // Check for wrong page description before using next new upper.
2371 // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
2372 // Check for correct type of new next upper layout frame
2373 // --> OD 2006-07-05 #136538# - another correction of fix for i53139
2374 // Beside type check, check also, if proposed new next upper
2375 // frame is inside the same frame types.
2376 // --> OD 2006-11-02 #i71065#
2377 // Check that the proposed new next upper layout
2378 // frame isn't the current one.
2379 SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, TRUE );
2380 if ( pNewNextUpper &&
2381 pNewNextUpper != rThis.GetUpper() &&
2382 pNewNextUpper->GetType() == pNewUpper->GetType() &&
2383 pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2384 pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2385 pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2386 pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2387 !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2389 pNewUpper = pNewNextUpper;
2391 // <--
2394 else
2396 if( pNewUpper ) // Wir hatten schon eine leere Spalte, haben
2397 bJump = TRUE; // also eine uebersprungen
2398 pNewUpper = pColBody; // Diese leere Spalte kommt in Frage,
2399 // trotzdem weitersuchen
2402 } while( bGoOn );
2403 if( bJump )
2404 SwFlowFrm::SetMoveBwdJump( TRUE );
2407 else //Keine Breaks also kann ich zurueckfliessen
2408 pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, FALSE );
2410 // --> OD 2004-06-23 #i27801# - no move backward of 'master' text frame,
2411 // if - due to its object positioning - it isn't allowed to be on the new page frame
2412 // --> OD 2005-03-07 #i44049# - add another condition for not moving backward:
2413 // If one of its objects has restarted the layout process, moving backward
2414 // isn't sensible either.
2415 // --> OD 2005-04-19 #i47697# - refine condition made for issue i44049:
2416 // - allow move backward as long as the anchored object is only temporarily
2417 // positions considering its wrapping style.
2418 if ( pNewUpper &&
2419 rThis.IsTxtFrm() && !IsFollow() )
2421 sal_uInt32 nToPageNum( 0L );
2422 const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos(
2423 *(pOldPage->GetFmt()->GetDoc()),
2424 static_cast<SwTxtFrm&>(rThis),
2425 nToPageNum );
2426 if ( bMoveFwdByObjPos &&
2427 pNewUpper->FindPageFrm()->GetPhyPageNum() < nToPageNum )
2429 pNewUpper = 0;
2431 // --> OD 2005-03-07 #i44049# - check, if one of its anchored objects
2432 // has restarted the layout process.
2433 else if ( rThis.GetDrawObjs() )
2435 sal_uInt32 i = 0;
2436 for ( ; i < rThis.GetDrawObjs()->Count(); ++i )
2438 SwAnchoredObject* pAnchoredObj = (*rThis.GetDrawObjs())[i];
2439 // --> OD 2005-04-19 #i47697# - refine condition - see above
2440 if ( pAnchoredObj->RestartLayoutProcess() &&
2441 !pAnchoredObj->IsTmpConsiderWrapInfluence() )
2442 // <--
2444 pNewUpper = 0;
2445 break;
2449 // <--
2451 // <--
2453 //Fuer Follows ist das zurueckfliessen nur dann erlaubt wenn in der
2454 //neuen Umgebung kein Nachbar existiert (denn dieses waere der Master).
2455 //(6677)Wenn allerdings leere Blaetter uebersprungen wurden wird doch gemoved.
2456 if ( pNewUpper && IsFollow() && pNewUpper->Lower() )
2458 // --> OD 2007-09-05 #i79774#, #b6596954#
2459 // neglect empty sections in proposed new upper frame
2460 bool bProposedNewUpperContainsOnlyEmptySections( true );
2462 const SwFrm* pLower( pNewUpper->Lower() );
2463 while ( pLower )
2465 if ( pLower->IsSctFrm() &&
2466 !dynamic_cast<const SwSectionFrm*>(pLower)->GetSection() )
2468 pLower = pLower->GetNext();
2469 continue;
2471 else
2473 bProposedNewUpperContainsOnlyEmptySections = false;
2474 break;
2478 if ( !bProposedNewUpperContainsOnlyEmptySections )
2480 if ( SwFlowFrm::IsMoveBwdJump() )
2482 //Nicht hinter den Master sondern in das naechstfolgende leere
2483 //Blatt moven.
2484 SwFrm *pFrm = pNewUpper->Lower();
2485 while ( pFrm->GetNext() )
2486 pFrm = pFrm->GetNext();
2487 pNewUpper = pFrm->GetLeaf( MAKEPAGE_INSERT, TRUE );
2488 if( pNewUpper == rThis.GetUpper() ) //Landen wir wieder an der gleichen Stelle?
2489 pNewUpper = NULL; //dann eruebrigt sich das Moven
2491 else
2492 pNewUpper = 0;
2494 // <--
2496 if ( pNewUpper && !ShouldBwdMoved( pNewUpper, TRUE, rbReformat ) )
2498 if( !pNewUpper->Lower() )
2500 if( pNewUpper->IsFtnContFrm() )
2502 pNewUpper->Cut();
2503 delete pNewUpper;
2505 else
2507 SwSectionFrm* pSectFrm = pNewUpper->FindSctFrm();
2508 // --> OD 2006-01-04 #126020# - adjust check for empty section
2509 // --> OD 2006-02-01 #130797# - correct fix #126020#
2510 if ( pSectFrm && !pSectFrm->IsColLocked() &&
2511 !pSectFrm->ContainsCntnt() && !pSectFrm->ContainsAny( true ) )
2512 // <--
2514 pSectFrm->DelEmpty( TRUE );
2515 delete pSectFrm;
2516 rThis.bValidPos = TRUE;
2520 pNewUpper = 0;
2523 // OD 2004-05-26 #i21478# - don't move backward, if flow frame wants to
2524 // keep with next frame and next frame is locked.
2525 // --> OD 2004-12-08 #i38232# - If next frame is a table, do *not* check,
2526 // if it's locked.
2527 if ( pNewUpper && !IsFollow() &&
2528 rThis.GetAttrSet()->GetKeep().GetValue() && rThis.GetIndNext() )
2530 SwFrm* pIndNext = rThis.GetIndNext();
2531 // --> OD 2004-12-08 #i38232#
2532 if ( !pIndNext->IsTabFrm() )
2534 // get first content of section, while empty sections are skipped
2535 while ( pIndNext && pIndNext->IsSctFrm() )
2537 if( static_cast<SwSectionFrm*>(pIndNext)->GetSection() )
2539 SwFrm* pTmp = static_cast<SwSectionFrm*>(pIndNext)->ContainsAny();
2540 if ( pTmp )
2542 pIndNext = pTmp;
2543 break;
2546 pIndNext = pIndNext->GetIndNext();
2548 ASSERT( !pIndNext || pIndNext->ISA(SwTxtFrm),
2549 "<SwFlowFrm::MovedBwd(..)> - incorrect next found." );
2550 if ( pIndNext && pIndNext->IsFlowFrm() &&
2551 SwFlowFrm::CastFlowFrm(pIndNext)->IsJoinLocked() )
2553 pNewUpper = 0L;
2556 // <--
2559 // --> OD 2006-05-10 #i65250#
2560 // layout loop control for flowing content again and again moving
2561 // backward under the same layout condition.
2562 if ( pNewUpper && !IsFollow() &&
2563 pNewUpper != rThis.GetUpper() &&
2564 SwLayouter::MoveBwdSuppressed( *(pOldPage->GetFmt()->GetDoc()),
2565 *this, *pNewUpper ) )
2567 SwLayoutFrm* pNextNewUpper = pNewUpper->GetLeaf(
2568 ( !rThis.IsSctFrm() && rThis.IsInSct() )
2569 ? MAKEPAGE_NOSECTION
2570 : MAKEPAGE_NONE,
2571 TRUE );
2572 // --> OD 2007-01-10 #i73194# - make code robust
2573 ASSERT( pNextNewUpper, "<SwFlowFrm::MoveBwd(..)> - missing next new upper" );
2574 if ( pNextNewUpper &&
2575 ( pNextNewUpper == rThis.GetUpper() ||
2576 pNextNewUpper->GetType() != rThis.GetUpper()->GetType() ) )
2577 // <--
2579 pNewUpper = 0L;
2580 #if OSL_DEBUG_LEVEL > 1
2581 ASSERT( false,
2582 "<SwFlowFrm::MoveBwd(..)> - layout loop control for layout action <Move Backward> applied!" );
2583 #endif
2586 // <--
2588 ASSERT( pNewUpper != rThis.GetUpper(),
2589 "<SwFlowFrm::MoveBwd(..)> - moving backward to the current upper frame!? -> Please inform OD." );
2590 if ( pNewUpper )
2592 PROTOCOL_ENTER( &rThis, PROT_MOVE_BWD, 0, 0 );
2593 if ( pNewUpper->IsFtnContFrm() )
2595 //Kann sein, dass ich einen Container bekam.
2596 SwFtnFrm *pOld = rThis.FindFtnFrm();
2597 SwFtnFrm *pNew = new SwFtnFrm( pOld->GetFmt(),
2598 pOld->GetRef(), pOld->GetAttr() );
2599 if ( pOld->GetMaster() )
2601 pNew->SetMaster( pOld->GetMaster() );
2602 pOld->GetMaster()->SetFollow( pNew );
2604 pNew->SetFollow( pOld );
2605 pOld->SetMaster( pNew );
2606 pNew->Paste( pNewUpper );
2607 pNewUpper = pNew;
2609 if( pNewUpper->IsFtnFrm() && rThis.IsInSct() )
2611 SwSectionFrm* pSct = rThis.FindSctFrm();
2612 //Wenn wir in einem Bereich in einer Fussnote stecken, muss im
2613 //neuen Upper ggf. ein SwSectionFrm angelegt werden
2614 if( pSct->IsInFtn() )
2616 SwFrm* pTmp = pNewUpper->Lower();
2617 if( pTmp )
2619 while( pTmp->GetNext() )
2620 pTmp = pTmp->GetNext();
2621 if( !pTmp->IsSctFrm() ||
2622 ((SwSectionFrm*)pTmp)->GetFollow() != pSct )
2623 pTmp = NULL;
2625 if( pTmp )
2626 pNewUpper = (SwSectionFrm*)pTmp;
2627 else
2629 pSct = new SwSectionFrm( *pSct, TRUE );
2630 pSct->Paste( pNewUpper );
2631 pSct->Init();
2632 pNewUpper = pSct;
2633 pSct->SimpleFormat();
2637 BOOL bUnlock = FALSE;
2638 BOOL bFollow = FALSE;
2639 //Section locken, sonst kann sie bei Fluss des einzigen Cntnt etwa
2640 //von zweiter in die erste Spalte zerstoert werden.
2641 SwSectionFrm* pSect = pNewUpper->FindSctFrm();
2642 if( pSect )
2644 bUnlock = !pSect->IsColLocked();
2645 pSect->ColLock();
2646 bFollow = pSect->HasFollow();
2648 pNewUpper->Calc();
2649 rThis.Cut();
2650 // --> OD 2005-02-23 #b6229852#
2651 // optimization: format section, if its size is invalidated and if it's
2652 // the new parent of moved backward frame.
2653 bool bFormatSect( false );
2654 // <--
2655 if( bUnlock )
2657 pSect->ColUnlock();
2658 if( pSect->HasFollow() != bFollow )
2660 pSect->InvalidateSize();
2661 // --> OD 2005-02-23 #b6229852# - optimization
2662 if ( pSect == pNewUpper )
2663 bFormatSect = true;
2664 // <--
2668 rThis.Paste( pNewUpper );
2669 // --> OD 2005-02-23 #b6229852# - optimization
2670 if ( bFormatSect )
2671 pSect->Calc();
2672 // <--
2674 SwPageFrm *pNewPage = rThis.FindPageFrm();
2675 if( pNewPage != pOldPage )
2677 rThis.Prepare( PREP_BOSS_CHGD, (const void*)pOldPage, FALSE );
2678 ViewShell *pSh = rThis.GetShell();
2679 if ( pSh && !pSh->Imp()->IsUpdateExpFlds() )
2680 pSh->GetDoc()->SetNewFldLst(true); //Wird von CalcLayout() hinterher eledigt!
2682 pNewPage->InvalidateSpelling();
2683 pNewPage->InvalidateSmartTags(); // SMARTTAGS
2684 pNewPage->InvalidateAutoCompleteWords();
2685 pNewPage->InvalidateWordCount();
2687 // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout
2688 if ( !pNewPage->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) )
2690 if ( bCheckPageDescs && pNewPage->GetNext() )
2692 SwPageFrm* pStartPage = bCheckPageDescOfNextPage ?
2693 pNewPage :
2694 (SwPageFrm*)pNewPage->GetNext();
2695 SwFrm::CheckPageDescs( pStartPage, FALSE);
2697 else if ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() )
2699 //Erste Seite wird etwa durch Ausblenden eines Bereiches leer
2700 SwFrm::CheckPageDescs( (SwPageFrm*)pNewPage, FALSE);
2705 return pNewUpper != 0;
2708 /*************************************************************************
2710 |* SwFlowFrm::CastFlowFrm
2712 |* Ersterstellung MA 03. May. 95
2713 |* Letzte Aenderung AMA 02. Dec. 97
2715 |*************************************************************************/
2717 SwFlowFrm *SwFlowFrm::CastFlowFrm( SwFrm *pFrm )
2719 if ( pFrm->IsCntntFrm() )
2720 return (SwCntntFrm*)pFrm;
2721 if ( pFrm->IsTabFrm() )
2722 return (SwTabFrm*)pFrm;
2723 if ( pFrm->IsSctFrm() )
2724 return (SwSectionFrm*)pFrm;
2725 return 0;
2728 const SwFlowFrm *SwFlowFrm::CastFlowFrm( const SwFrm *pFrm )
2730 if ( pFrm->IsCntntFrm() )
2731 return (SwCntntFrm*)pFrm;
2732 if ( pFrm->IsTabFrm() )
2733 return (SwTabFrm*)pFrm;
2734 if ( pFrm->IsSctFrm() )
2735 return (SwSectionFrm*)pFrm;
2736 return 0;