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: findfrm.cxx,v $
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"
35 #include "pagefrm.hxx"
36 #include "rootfrm.hxx"
40 #include "frmtool.hxx"
43 #include <cellfrm.hxx>
45 #include <swtable.hxx>
48 #include "sectfrm.hxx"
49 #include "flyfrms.hxx"
53 // OD 09.01.2004 #i11859#
54 #include <txtfrm.hxx> // SwTxtFrm
56 /*************************************************************************
58 |* FindBodyCont, FindLastBodyCntnt()
60 |* Beschreibung Sucht den ersten/letzten CntntFrm im BodyText unterhalb
62 |* Ersterstellung MA 15. Feb. 93
63 |* Letzte Aenderung MA 18. Apr. 94
65 |*************************************************************************/
66 SwLayoutFrm
*SwFtnBossFrm::FindBodyCont()
68 SwFrm
*pLay
= Lower();
69 while ( pLay
&& !pLay
->IsBodyFrm() )
70 pLay
= pLay
->GetNext();
71 return (SwLayoutFrm
*)pLay
;
74 SwCntntFrm
*SwPageFrm::FindLastBodyCntnt()
76 SwCntntFrm
*pRet
= FindFirstBodyCntnt();
77 SwCntntFrm
*pNxt
= pRet
;
78 while ( pNxt
&& pNxt
->IsInDocBody() && IsAnLower( pNxt
) )
80 pNxt
= pNxt
->FindNextCnt();
85 /*************************************************************************
87 |* SwLayoutFrm::ContainsCntnt
89 |* Beschreibung Prueft, ob der Frame irgendwo in seiner
90 |* untergeordneten Struktur einen oder mehrere CntntFrm's enthaelt;
91 |* Falls ja wird der erste gefundene CntntFrm zurueckgegeben.
93 |* Ersterstellung MA 13. May. 92
94 |* Letzte Aenderung MA 20. Apr. 94
96 |*************************************************************************/
98 const SwCntntFrm
*SwLayoutFrm::ContainsCntnt() const
100 //LayoutBlatt nach unten hin suchen und wenn dieses keinen Inhalt hat
101 //solange die weiteren Blatter abklappern bis Inhalt gefunden oder der
102 //this verlassen wird.
103 //Sections: Cntnt neben Sections wuerde so nicht gefunden (leere Section
104 //direct neben CntntFrm), deshalb muss fuer diese Aufwendiger rekursiv gesucht
107 const SwLayoutFrm
*pLayLeaf
= this;
110 while ( (!pLayLeaf
->IsSctFrm() || pLayLeaf
== this ) &&
111 pLayLeaf
->Lower() && pLayLeaf
->Lower()->IsLayoutFrm() )
112 pLayLeaf
= (SwLayoutFrm
*)pLayLeaf
->Lower();
114 if( pLayLeaf
->IsSctFrm() && pLayLeaf
!= this )
116 const SwCntntFrm
*pCnt
= pLayLeaf
->ContainsCntnt();
119 if( pLayLeaf
->GetNext() )
121 if( pLayLeaf
->GetNext()->IsLayoutFrm() )
123 pLayLeaf
= (SwLayoutFrm
*)pLayLeaf
->GetNext();
127 return (SwCntntFrm
*)pLayLeaf
->GetNext();
130 else if ( pLayLeaf
->Lower() )
131 return (SwCntntFrm
*)pLayLeaf
->Lower();
133 pLayLeaf
= pLayLeaf
->GetNextLayoutLeaf();
134 if( !IsAnLower( pLayLeaf
) )
140 /*************************************************************************
142 |* SwLayoutFrm::FirstCell
144 |* Beschreibung ruft zunaechst ContainsAny auf, um in die innerste Zelle
145 |* hineinzukommen. Dort hangelt es sich wieder hoch zum
146 |* ersten SwCellFrm, seit es SectionFrms gibt, reicht kein
147 |* ContainsCntnt()->GetUpper() mehr...
148 |* Ersterstellung AMA 17. Mar. 99
149 |* Letzte Aenderung AMA 17. Mar. 99
151 |*************************************************************************/
153 const SwCellFrm
*SwLayoutFrm::FirstCell() const
155 const SwFrm
* pCnt
= ContainsAny();
156 while( pCnt
&& !pCnt
->IsCellFrm() )
157 pCnt
= pCnt
->GetUpper();
158 return (const SwCellFrm
*)pCnt
;
161 /*************************************************************************
163 |* SwLayoutFrm::ContainsAny
165 |* Beschreibung wie ContainsCntnt, nur dass nicht nur CntntFrms, sondern auch
166 |* Bereiche und Tabellen zurueckgegeben werden.
167 |* Ersterstellung AMA 10. Mar. 99
168 |* Letzte Aenderung AMA 10. Mar. 99
170 |*************************************************************************/
172 // --> OD 2006-02-01 #130797#
173 // New parameter <_bInvestigateFtnForSections> controls investigation of
174 // content of footnotes for sections.
175 const SwFrm
*SwLayoutFrm::ContainsAny( const bool _bInvestigateFtnForSections
) const
177 //LayoutBlatt nach unten hin suchen und wenn dieses keinen Inhalt hat
178 //solange die weiteren Blatter abklappern bis Inhalt gefunden oder der
179 //this verlassen wird.
180 // Oder bis wir einen SectionFrm oder TabFrm gefunden haben
182 const SwLayoutFrm
*pLayLeaf
= this;
183 // --> OD 2006-02-01 #130797#
184 const bool bNoFtn
= IsSctFrm() && !_bInvestigateFtnForSections
;
188 while ( ( (!pLayLeaf
->IsSctFrm() && !pLayLeaf
->IsTabFrm())
189 || pLayLeaf
== this ) &&
190 pLayLeaf
->Lower() && pLayLeaf
->Lower()->IsLayoutFrm() )
191 pLayLeaf
= (SwLayoutFrm
*)pLayLeaf
->Lower();
193 if( ( pLayLeaf
->IsTabFrm() || pLayLeaf
->IsSctFrm() )
194 && pLayLeaf
!= this )
196 // Wir liefern jetzt auch "geloeschte" SectionFrms zurueck,
197 // damit diese beim SaveCntnt und RestoreCntnt mitgepflegt werden.
200 else if ( pLayLeaf
->Lower() )
201 return (SwCntntFrm
*)pLayLeaf
->Lower();
203 pLayLeaf
= pLayLeaf
->GetNextLayoutLeaf();
204 if( bNoFtn
&& pLayLeaf
&& pLayLeaf
->IsInFtn() )
208 pLayLeaf
= pLayLeaf
->GetNextLayoutLeaf();
209 } while( pLayLeaf
&& pLayLeaf
->IsInFtn() );
211 if( !IsAnLower( pLayLeaf
) )
218 /*************************************************************************
222 |* Ersterstellung MA 27. Jul. 92
223 |* Letzte Aenderung MA 09. Oct. 97
225 |*************************************************************************/
226 const SwFrm
* SwFrm::GetLower() const
228 return IsLayoutFrm() ? ((SwLayoutFrm
*)this)->Lower() : 0;
231 SwFrm
* SwFrm::GetLower()
233 return IsLayoutFrm() ? ((SwLayoutFrm
*)this)->Lower() : 0;
236 /*************************************************************************
238 |* SwLayoutFrm::IsAnLower()
240 |* Ersterstellung MA 18. Mar. 93
241 |* Letzte Aenderung MA 18. Mar. 93
243 |*************************************************************************/
244 BOOL
SwLayoutFrm::IsAnLower( const SwFrm
*pAssumed
) const
246 const SwFrm
*pUp
= pAssumed
;
251 if ( pUp
->IsFlyFrm() )
252 pUp
= ((SwFlyFrm
*)pUp
)->GetAnchorFrm();
254 pUp
= pUp
->GetUpper();
259 /** method to check relative position of layout frame to
260 a given layout frame.
262 OD 08.11.2002 - refactoring of pseudo-local method <lcl_Apres(..)> in
263 <txtftn.cxx> for #104840#.
265 @param _aCheckRefLayFrm
266 constant reference of an instance of class <SwLayoutFrm> which
267 is used as the reference for the relative position check.
271 @return true, if <this> is positioned before the layout frame <p>
273 bool SwLayoutFrm::IsBefore( const SwLayoutFrm
* _pCheckRefLayFrm
) const
275 ASSERT( !IsRootFrm() , "<IsBefore> called at a <SwRootFrm>.");
276 ASSERT( !_pCheckRefLayFrm
->IsRootFrm() , "<IsBefore> called with a <SwRootFrm>.");
280 // check, if on different pages
281 const SwPageFrm
*pMyPage
= FindPageFrm();
282 const SwPageFrm
*pCheckRefPage
= _pCheckRefLayFrm
->FindPageFrm();
283 if( pMyPage
!= pCheckRefPage
)
285 // being on different page as check reference
286 bReturn
= pMyPage
->GetPhyPageNum() < pCheckRefPage
->GetPhyPageNum();
290 // being on same page as check reference
291 // --> search my supreme parent <pUp>, which doesn't contain check reference.
292 const SwLayoutFrm
* pUp
= this;
293 while ( pUp
->GetUpper() &&
294 !pUp
->GetUpper()->IsAnLower( _pCheckRefLayFrm
)
296 pUp
= pUp
->GetUpper();
297 if( !pUp
->GetUpper() )
299 // can occur, if <this> is a fly frm
304 // travel through the next's of <pUp> and check if one of these
305 // contain the check reference.
306 SwLayoutFrm
* pUpNext
= (SwLayoutFrm
*)pUp
->GetNext();
308 !pUpNext
->IsAnLower( _pCheckRefLayFrm
) )
310 pUpNext
= (SwLayoutFrm
*)pUpNext
->GetNext();
312 bReturn
= pUpNext
!= 0;
320 // Local helper functions for GetNextLayoutLeaf
323 const SwFrm
* lcl_FindLayoutFrame( const SwFrm
* pFrm
, bool bNext
)
325 const SwFrm
* pRet
= 0;
326 if ( pFrm
->IsFlyFrm() )
327 pRet
= bNext
? ((SwFlyFrm
*)pFrm
)->GetNextLink() : ((SwFlyFrm
*)pFrm
)->GetPrevLink();
329 pRet
= bNext
? pFrm
->GetNext() : pFrm
->GetPrev();
334 const SwFrm
* lcl_GetLower( const SwFrm
* pFrm
, bool bFwd
)
336 if ( !pFrm
->IsLayoutFrm() )
340 static_cast<const SwLayoutFrm
*>(pFrm
)->Lower() :
341 static_cast<const SwLayoutFrm
*>(pFrm
)->GetLastLower();
344 /*************************************************************************
346 |* SwFrm::ImplGetNextLayoutLeaf
348 |* Finds the next layout leaf. This is a layout frame, which does not
349 * have a lower which is a LayoutFrame. That means, pLower can be 0 or a
352 * However, pLower may be a TabFrm
354 |*************************************************************************/
356 const SwLayoutFrm
*SwFrm::ImplGetNextLayoutLeaf( bool bFwd
) const
358 const SwFrm
*pFrm
= this;
359 const SwLayoutFrm
*pLayoutFrm
= 0;
361 bool bGoingUp
= !bFwd
; // false for forward, true for backward
364 bool bGoingFwdOrBwd
= false, bGoingDown
= false;
366 bGoingDown
= ( !bGoingUp
&& ( 0 != (p
= lcl_GetLower( pFrm
, bFwd
) ) ) );
369 // I cannot go down, because either I'm currently going up or
370 // because the is no lower.
371 // I'll try to go forward:
372 bGoingFwdOrBwd
= (0 != (p
= lcl_FindLayoutFrame( pFrm
, bFwd
) ) );
373 if ( !bGoingFwdOrBwd
)
375 // I cannot go forward, because there is no next frame.
376 // I'll try to go up:
377 bGoingUp
= (0 != (p
= pFrm
->GetUpper() ) );
380 // I cannot go up, because there is no upper frame.
386 // If I could not go down or forward, I'll have to go up
387 bGoingUp
= !bGoingFwdOrBwd
&& !bGoingDown
;
390 p
= lcl_GetLower( pFrm
, true );
392 } while( ( p
&& !p
->IsFlowFrm() ) ||
394 0 == ( pLayoutFrm
= pFrm
->IsLayoutFrm() ? (SwLayoutFrm
*)pFrm
: 0 ) ||
395 pLayoutFrm
->IsAnLower( this ) );
402 /*************************************************************************
404 |* SwFrm::ImplGetNextCntntFrm( bool )
406 |* Rueckwaertswandern im Baum: Den untergeordneten Frm greifen,
407 |* wenn es einen gibt und nicht gerade zuvor um eine Ebene
408 |* aufgestiegen wurde (das wuerde zu einem endlosen Auf und Ab
409 |* fuehren!). Damit wird sichergestellt, dass beim
410 |* Rueckwaertswandern alle Unterbaeume durchsucht werden. Wenn
411 |* abgestiegen wurde, wird zuerst an das Ende der Kette gegangen,
412 |* weil im weiteren ja vom letzten Frm innerhalb eines anderen
413 |* Frms rueckwaerts gegangen wird.
414 |* Vorwaetzwander funktioniert analog.
417 |* Letzte Aenderung MA 30. Oct. 97
419 |*************************************************************************/
421 // Achtung: Fixes in ImplGetNextCntntFrm() muessen moeglicherweise auch in
422 // die weiter oben stehende Methode lcl_NextFrm(..) eingepflegt werden
423 const SwCntntFrm
* SwCntntFrm::ImplGetNextCntntFrm( bool bFwd
) const
425 const SwFrm
*pFrm
= this;
427 SwCntntFrm
*pCntntFrm
= 0;
428 BOOL bGoingUp
= FALSE
;
431 BOOL bGoingFwdOrBwd
= FALSE
, bGoingDown
= FALSE
;
433 bGoingDown
= ( !bGoingUp
&& ( 0 != ( p
= lcl_GetLower( pFrm
, true ) ) ) );
436 bGoingFwdOrBwd
= ( 0 != ( p
= lcl_FindLayoutFrame( pFrm
, bFwd
) ) );
437 if ( !bGoingFwdOrBwd
)
439 bGoingUp
= ( 0 != ( p
= pFrm
->GetUpper() ) );
447 bGoingUp
= !(bGoingFwdOrBwd
|| bGoingDown
);
451 if( bGoingDown
&& p
)
452 while ( p
->GetNext() )
457 } while ( 0 == (pCntntFrm
= (pFrm
->IsCntntFrm() ? (SwCntntFrm
*)pFrm
:0) ));
465 /*************************************************************************
467 |* SwFrm::FindRootFrm(), FindTabFrm(), FindFtnFrm(), FindFlyFrm(),
468 |* FindPageFrm(), FindColFrm()
471 |* Letzte Aenderung MA 05. Sep. 93
473 |*************************************************************************/
474 SwRootFrm
* SwFrm::FindRootFrm()
476 // MIB: A layout frame is always registerd at a SwFrmFmt and a content
477 // frame alyways at a SwCntntNode. For any other case we won't find
479 // Casting the GetDep() result instead of the frame itself (that has
480 // been done before) makes it save to use that method in constructors
482 ASSERT( GetDep(), "frame is not registered any longer" );
483 ASSERT( IsLayoutFrm() || IsCntntFrm(), "invalid frame type" );
484 SwDoc
*pDoc
= IsLayoutFrm()
485 ? static_cast < SwFrmFmt
* >( GetDep() )->GetDoc()
486 : static_cast < SwCntntNode
* >( GetDep() )->GetDoc();
487 return pDoc
->GetRootFrm();
490 SwPageFrm
* SwFrm::FindPageFrm()
493 while ( pRet
&& !pRet
->IsPageFrm() )
495 if ( pRet
->GetUpper() )
496 pRet
= pRet
->GetUpper();
497 else if ( pRet
->IsFlyFrm() )
499 // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
500 if ( static_cast<SwFlyFrm
*>(pRet
)->GetPageFrm() )
501 pRet
= static_cast<SwFlyFrm
*>(pRet
)->GetPageFrm();
503 pRet
= static_cast<SwFlyFrm
*>(pRet
)->AnchorFrm();
508 return (SwPageFrm
*)pRet
;
511 SwFtnBossFrm
* SwFrm::FindFtnBossFrm( BOOL bFootnotes
)
514 // Innerhalb einer Tabelle gibt es keine Fussnotenbosse, auch spaltige
515 // Bereiche enthalten dort keine Fussnotentexte
516 if( pRet
->IsInTab() )
517 pRet
= pRet
->FindTabFrm();
518 while ( pRet
&& !pRet
->IsFtnBossFrm() )
520 if ( pRet
->GetUpper() )
521 pRet
= pRet
->GetUpper();
522 else if ( pRet
->IsFlyFrm() )
524 // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
525 if ( static_cast<SwFlyFrm
*>(pRet
)->GetPageFrm() )
526 pRet
= static_cast<SwFlyFrm
*>(pRet
)->GetPageFrm();
528 pRet
= static_cast<SwFlyFrm
*>(pRet
)->AnchorFrm();
533 if( bFootnotes
&& pRet
&& pRet
->IsColumnFrm() &&
534 !pRet
->GetNext() && !pRet
->GetPrev() )
536 SwSectionFrm
* pSct
= pRet
->FindSctFrm();
537 ASSERT( pSct
, "FindFtnBossFrm: Single column outside section?" );
538 if( !pSct
->IsFtnAtEnd() )
539 return pSct
->FindFtnBossFrm( TRUE
);
541 return (SwFtnBossFrm
*)pRet
;
544 SwTabFrm
* SwFrm::ImplFindTabFrm()
547 while ( !pRet
->IsTabFrm() )
549 pRet
= pRet
->GetUpper();
553 return (SwTabFrm
*)pRet
;
556 SwSectionFrm
* SwFrm::ImplFindSctFrm()
559 while ( !pRet
->IsSctFrm() )
561 pRet
= pRet
->GetUpper();
565 return (SwSectionFrm
*)pRet
;
568 SwFtnFrm
*SwFrm::ImplFindFtnFrm()
571 while ( !pRet
->IsFtnFrm() )
573 pRet
= pRet
->GetUpper();
577 return (SwFtnFrm
*)pRet
;
580 SwFlyFrm
*SwFrm::ImplFindFlyFrm()
582 const SwFrm
*pRet
= this;
585 if ( pRet
->IsFlyFrm() )
586 return (SwFlyFrm
*)pRet
;
588 pRet
= pRet
->GetUpper();
593 SwFrm
*SwFrm::FindColFrm()
597 { pFrm
= pFrm
->GetUpper();
598 } while ( pFrm
&& !pFrm
->IsColumnFrm() );
602 SwRowFrm
*SwFrm::FindRowFrm()
606 { pFrm
= pFrm
->GetUpper();
607 } while ( pFrm
&& !pFrm
->IsRowFrm() );
608 return dynamic_cast< SwRowFrm
* >( pFrm
);
611 SwFrm
* SwFrm::FindFooterOrHeader()
615 { if ( pRet
->GetType() & 0x0018 ) //Header und Footer
617 else if ( pRet
->GetUpper() )
618 pRet
= pRet
->GetUpper();
619 else if ( pRet
->IsFlyFrm() )
620 pRet
= ((SwFlyFrm
*)pRet
)->AnchorFrm();
627 const SwFtnFrm
* SwFtnContFrm::FindFootNote() const
629 const SwFtnFrm
* pRet
= (SwFtnFrm
*)Lower();
630 if( pRet
&& !pRet
->GetAttr()->GetFtn().IsEndNote() )
635 const SwPageFrm
* SwRootFrm::GetPageAtPos( const Point
& rPt
, const Size
* pSize
, bool bExtend
) const
637 const SwPageFrm
* pRet
= 0;
643 aRect
.SSize() = *pSize
;
646 const SwFrm
* pPage
= Lower();
650 if( !Frm().IsInside( rPt
) )
653 // skip pages above point:
654 while( pPage
&& rPt
.Y() > pPage
->Frm().Bottom() )
655 pPage
= pPage
->GetNext();
658 ASSERT( GetPageNum() <= maPageRects
.size(), "number of pages differes from page rect array size" )
661 while ( pPage
&& !pRet
)
663 const SwRect
& rBoundRect
= bExtend
? maPageRects
[ nPageIdx
++ ] : pPage
->Frm();
665 if ( !pSize
&& rBoundRect
.IsInside( rPt
) ||
666 pSize
&& rBoundRect
.IsOver( aRect
) )
667 pRet
= static_cast<const SwPageFrm
*>(pPage
);
669 pPage
= pPage
->GetNext();
675 /*************************************************************************
677 |* SwFrmFrm::GetAttrSet()
679 |* Ersterstellung MA 02. Aug. 93
680 |* Letzte Aenderung MA 02. Aug. 93
682 |*************************************************************************/
683 const SwAttrSet
* SwFrm::GetAttrSet() const
686 return &((const SwCntntFrm
*)this)->GetNode()->GetSwAttrSet();
688 return &((const SwLayoutFrm
*)this)->GetFmt()->GetAttrSet();
691 /*************************************************************************
693 |* SwFrm::_FindNext(), _FindPrev(), InvalidateNextPos()
694 |* _FindNextCnt() geht in Tabellen und Bereiche hineinund liefert
697 |* Beschreibung Invalidiert die Position des Naechsten Frames.
698 |* Dies ist der direkte Nachfolger, oder bei CntntFrm's der naechste
699 |* CntntFrm der im gleichen Fluss liegt wie ich:
702 |* - Bei Kopf-/Fussbereichen ist die Benachrichtigung nur innerhalb des
703 |* Bereiches weiterzuleiten.
705 |* - Cntnts in Tabs halten sich ausschliesslich innerhalb ihrer Zelle
707 |* - Tabellen verhalten sich prinzipiell analog zu den Cntnts
708 |* - Bereiche ebenfalls
709 |* Ersterstellung AK 14-Feb-1991
710 |* Letzte Aenderung AMA 10. Mar. 99
712 |*************************************************************************/
714 // Diese Hilfsfunktion ist ein Aequivalent zur ImplGetNextCntntFrm()-Methode,
715 // sie liefert allerdings neben ContentFrames auch TabFrms und SectionFrms.
716 SwFrm
* lcl_NextFrm( SwFrm
* pFrm
)
719 BOOL bGoingUp
= FALSE
;
723 BOOL bGoingFwd
= FALSE
;
724 BOOL bGoingDown
= (!bGoingUp
&& ( 0 != (p
= pFrm
->IsLayoutFrm() ? ((SwLayoutFrm
*)pFrm
)->Lower() : 0)));
728 bGoingFwd
= (0 != (p
= ( pFrm
->IsFlyFrm() ? ((SwFlyFrm
*)pFrm
)->GetNextLink() : pFrm
->GetNext())));
731 bGoingUp
= (0 != (p
= pFrm
->GetUpper()));
738 bGoingUp
= !(bGoingFwd
|| bGoingDown
);
740 } while ( 0 == (pRet
= ( ( pFrm
->IsCntntFrm() || ( !bGoingUp
&&
741 ( pFrm
->IsTabFrm() || pFrm
->IsSctFrm() ) ) )? pFrm
: 0 ) ) );
745 SwFrm
*SwFrm::_FindNext()
747 BOOL bIgnoreTab
= FALSE
;
752 //Der letzte Cntnt der Tabelle wird
753 //gegriffen und dessen Nachfolger geliefert. Um die Spezialbeh.
754 //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt.
755 if ( ((SwTabFrm
*)this)->GetFollow() )
756 return ((SwTabFrm
*)this)->GetFollow();
758 pThis
= ((SwTabFrm
*)this)->FindLastCntnt();
763 else if ( IsSctFrm() )
765 //Der letzte Cntnt des Bereichs wird gegriffen und dessen Nachfolger
767 if ( ((SwSectionFrm
*)this)->GetFollow() )
768 return ((SwSectionFrm
*)this)->GetFollow();
770 pThis
= ((SwSectionFrm
*)this)->FindLastCntnt();
774 else if ( IsCntntFrm() )
776 if( ((SwCntntFrm
*)this)->GetFollow() )
777 return ((SwCntntFrm
*)this)->GetFollow();
779 else if ( IsRowFrm() )
781 SwFrm
* pMyUpper
= GetUpper();
782 if ( pMyUpper
->IsTabFrm() && ((SwTabFrm
*)pMyUpper
)->GetFollow() )
783 return ((SwTabFrm
*)pMyUpper
)->GetFollow()->GetLower();
790 const BOOL bFtn
= pThis
->IsInFtn();
791 if ( !bIgnoreTab
&& pThis
->IsInTab() )
793 SwLayoutFrm
*pUp
= pThis
->GetUpper();
794 while ( !pUp
->IsCellFrm() )
795 pUp
= pUp
->GetUpper();
796 ASSERT( pUp
, "Cntnt in Tabelle aber nicht in Zelle." );
797 SwFrm
* pNxt
= ((SwCellFrm
*)pUp
)->GetFollowCell();
799 pNxt
= ((SwCellFrm
*)pNxt
)->ContainsCntnt();
802 pNxt
= lcl_NextFrm( pThis
);
803 if ( pUp
->IsAnLower( pNxt
) )
811 const BOOL bBody
= pThis
->IsInDocBody();
812 SwFrm
*pNxtCnt
= lcl_NextFrm( pThis
);
819 // OD 02.04.2003 #108446# - check for endnote, only if found
820 // next content isn't contained in a section, that collect its
821 // endnotes at its end.
822 bool bEndn
= IsInSct() && !IsSctFrm() &&
823 ( !pNxtCnt
->IsInSct() ||
824 !pNxtCnt
->FindSctFrm()->IsEndnAtEnd()
826 if ( ( bBody
&& pNxtCnt
->IsInDocBody() ) ||
827 ( pNxtCnt
->IsInFtn() &&
829 ( bEndn
&& pNxtCnt
->FindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
834 pRet
= pNxtCnt
->IsInTab() ? pNxtCnt
->FindTabFrm()
838 pNxtCnt
= lcl_NextFrm( pNxtCnt
);
841 else if ( pThis
->IsInFly() )
843 pRet
= pNxtCnt
->IsInTab() ? pNxtCnt
->FindTabFrm()
846 else //Fuss-/oder Kopfbereich
848 const SwFrm
*pUp
= pThis
->GetUpper();
849 const SwFrm
*pCntUp
= pNxtCnt
->GetUpper();
850 while ( pUp
&& pUp
->GetUpper() &&
851 !pUp
->IsHeaderFrm() && !pUp
->IsFooterFrm() )
852 pUp
= pUp
->GetUpper();
853 while ( pCntUp
&& pCntUp
->GetUpper() &&
854 !pCntUp
->IsHeaderFrm() && !pCntUp
->IsFooterFrm() )
855 pCntUp
= pCntUp
->GetUpper();
858 pRet
= pNxtCnt
->IsInTab() ? pNxtCnt
->FindTabFrm()
864 if( pRet
&& pRet
->IsInSct() )
866 SwSectionFrm
* pSct
= pRet
->FindSctFrm();
867 //Fussnoten in spaltigen Rahmen duerfen nicht den Bereich
868 //liefern, der die Fussnoten umfasst
869 if( !pSct
->IsAnLower( this ) &&
870 (!bFtn
|| pSct
->IsInFtn() ) )
876 // --> OD 2005-12-01 #i27138# - add parameter <_bInSameFtn>
877 SwCntntFrm
*SwFrm::_FindNextCnt( const bool _bInSameFtn
)
883 if ( ((SwTabFrm
*)this)->GetFollow() )
885 pThis
= ((SwTabFrm
*)this)->GetFollow()->ContainsCntnt();
887 return (SwCntntFrm
*)pThis
;
889 pThis
= ((SwTabFrm
*)this)->FindLastCntnt();
893 else if ( IsSctFrm() )
895 if ( ((SwSectionFrm
*)this)->GetFollow() )
897 pThis
= ((SwSectionFrm
*)this)->GetFollow()->ContainsCntnt();
899 return (SwCntntFrm
*)pThis
;
901 pThis
= ((SwSectionFrm
*)this)->FindLastCntnt();
905 else if ( IsCntntFrm() && ((SwCntntFrm
*)this)->GetFollow() )
906 return ((SwCntntFrm
*)this)->GetFollow();
908 if ( pThis
->IsCntntFrm() )
910 const BOOL bBody
= pThis
->IsInDocBody();
911 const BOOL bFtn
= pThis
->IsInFtn();
912 SwCntntFrm
*pNxtCnt
= ((SwCntntFrm
*)pThis
)->GetNextCntntFrm();
915 // --> OD 2005-12-01 #i27138#
916 if ( bBody
|| ( bFtn
&& !_bInSameFtn
) )
919 // handling for environments 'footnotes' and 'document body frames':
922 if ( (bBody
&& pNxtCnt
->IsInDocBody()) ||
923 (bFtn
&& pNxtCnt
->IsInFtn()) )
925 pNxtCnt
= pNxtCnt
->GetNextCntntFrm();
928 // --> OD 2005-12-01 #i27138#
929 else if ( bFtn
&& _bInSameFtn
)
931 // handling for environments 'each footnote':
932 // Assure that found next content frame belongs to the same footnotes
933 const SwFtnFrm
* pFtnFrmOfNext( pNxtCnt
->FindFtnFrm() );
934 const SwFtnFrm
* pFtnFrmOfCurr( pThis
->FindFtnFrm() );
935 ASSERT( pFtnFrmOfCurr
,
936 "<SwFrm::_FindNextCnt() - unknown layout situation: current frame has to have an upper footnote frame." );
937 if ( pFtnFrmOfNext
== pFtnFrmOfCurr
)
941 else if ( pFtnFrmOfCurr
->GetFollow() )
943 // next content frame has to be the first content frame
944 // in the follow footnote, which contains a content frame.
945 SwFtnFrm
* pFollowFtnFrmOfCurr(
946 const_cast<SwFtnFrm
*>(pFtnFrmOfCurr
) );
949 pFollowFtnFrmOfCurr
= pFollowFtnFrmOfCurr
->GetFollow();
950 pNxtCnt
= pFollowFtnFrmOfCurr
->ContainsCntnt();
951 } while ( !pNxtCnt
&& pFollowFtnFrmOfCurr
->GetFollow() );
956 // current content frame is the last content frame in the
957 // footnote - no next content frame exists.
962 else if ( pThis
->IsInFly() )
963 // handling for environments 'unlinked fly frame' and
964 // 'group of linked fly frames':
968 // handling for environments 'page header' and 'page footer':
969 const SwFrm
*pUp
= pThis
->GetUpper();
970 const SwFrm
*pCntUp
= pNxtCnt
->GetUpper();
971 while ( pUp
&& pUp
->GetUpper() &&
972 !pUp
->IsHeaderFrm() && !pUp
->IsFooterFrm() )
973 pUp
= pUp
->GetUpper();
974 while ( pCntUp
&& pCntUp
->GetUpper() &&
975 !pCntUp
->IsHeaderFrm() && !pCntUp
->IsFooterFrm() )
976 pCntUp
= pCntUp
->GetUpper();
985 /** method to determine previous content frame in the same environment
986 for a flow frame (content frame, table frame, section frame)
988 OD 2005-11-30 #i27138#
992 SwCntntFrm
* SwFrm::_FindPrevCnt( const bool _bInSameFtn
)
996 // nothing to do, if current frame isn't a flow frame.
1000 SwCntntFrm
* pPrevCntntFrm( 0L );
1002 // Because method <SwCntntFrm::GetPrevCntntFrm()> is used to travel
1003 // through the layout, a content frame, at which the travel starts, is needed.
1004 SwCntntFrm
* pCurrCntntFrm
= dynamic_cast<SwCntntFrm
*>(this);
1006 // perform shortcut, if current frame is a follow, and
1007 // determine <pCurrCntntFrm>, if current frame is a table or section frame
1008 if ( pCurrCntntFrm
&& pCurrCntntFrm
->IsFollow() )
1010 // previous content frame is its master content frame
1011 pPrevCntntFrm
= pCurrCntntFrm
->FindMaster();
1013 else if ( IsTabFrm() )
1015 SwTabFrm
* pTabFrm( static_cast<SwTabFrm
*>(this) );
1016 if ( pTabFrm
->IsFollow() )
1018 // previous content frame is the last content of its master table frame
1019 pPrevCntntFrm
= pTabFrm
->FindMaster()->FindLastCntnt();
1023 // start content frame for the search is the first content frame of
1025 pCurrCntntFrm
= pTabFrm
->ContainsCntnt();
1028 else if ( IsSctFrm() )
1030 SwSectionFrm
* pSectFrm( static_cast<SwSectionFrm
*>(this) );
1031 if ( pSectFrm
->IsFollow() )
1033 // previous content frame is the last content of its master section frame
1034 pPrevCntntFrm
= pSectFrm
->FindMaster()->FindLastCntnt();
1038 // start content frame for the search is the first content frame of
1039 // the section frame.
1040 pCurrCntntFrm
= pSectFrm
->ContainsCntnt();
1044 // search for next content frame, depending on the environment, in which
1045 // the current frame is in.
1046 if ( !pPrevCntntFrm
&& pCurrCntntFrm
)
1048 pPrevCntntFrm
= pCurrCntntFrm
->GetPrevCntntFrm();
1049 if ( pPrevCntntFrm
)
1051 if ( pCurrCntntFrm
->IsInFly() )
1053 // handling for environments 'unlinked fly frame' and
1054 // 'group of linked fly frames':
1055 // Nothing to do, <pPrevCntntFrm> is the one
1059 const bool bInDocBody
= pCurrCntntFrm
->IsInDocBody();
1060 const bool bInFtn
= pCurrCntntFrm
->IsInFtn();
1061 if ( bInDocBody
|| ( bInFtn
&& !_bInSameFtn
) )
1063 // handling for environments 'footnotes' and 'document body frames':
1064 // Assure that found previous frame is also in one of these
1065 // environments. Otherwise, travel further
1066 while ( pPrevCntntFrm
)
1068 if ( ( bInDocBody
&& pPrevCntntFrm
->IsInDocBody() ) ||
1069 ( bInFtn
&& pPrevCntntFrm
->IsInFtn() ) )
1073 pPrevCntntFrm
= pPrevCntntFrm
->GetPrevCntntFrm();
1076 else if ( bInFtn
&& _bInSameFtn
)
1078 // handling for environments 'each footnote':
1079 // Assure that found next content frame belongs to the same footnotes
1080 const SwFtnFrm
* pFtnFrmOfPrev( pPrevCntntFrm
->FindFtnFrm() );
1081 const SwFtnFrm
* pFtnFrmOfCurr( pCurrCntntFrm
->FindFtnFrm() );
1082 if ( pFtnFrmOfPrev
!= pFtnFrmOfCurr
)
1084 if ( pFtnFrmOfCurr
->GetMaster() )
1086 SwFtnFrm
* pMasterFtnFrmOfCurr(
1087 const_cast<SwFtnFrm
*>(pFtnFrmOfCurr
) );
1089 // --> OD 2007-07-05 #146872#
1090 // correct wrong loop-condition
1092 pMasterFtnFrmOfCurr
= pMasterFtnFrmOfCurr
->GetMaster();
1093 pPrevCntntFrm
= pMasterFtnFrmOfCurr
->FindLastCntnt();
1094 } while ( !pPrevCntntFrm
&&
1095 pMasterFtnFrmOfCurr
->GetMaster() );
1100 // current content frame is the first content in the
1101 // footnote - no previous content exists.
1102 pPrevCntntFrm
= 0L;;
1108 // handling for environments 'page header' and 'page footer':
1109 // Assure that found previous frame is also in the same
1110 // page header respectively page footer as <pCurrCntntFrm>
1111 // Note: At this point its clear, that <pCurrCntntFrm> has
1112 // to be inside a page header or page footer and that
1113 // neither <pCurrCntntFrm> nor <pPrevCntntFrm> are
1114 // inside a fly frame.
1115 // Thus, method <FindFooterOrHeader()> can be used.
1116 ASSERT( pCurrCntntFrm
->FindFooterOrHeader(),
1117 "<SwFrm::_FindPrevCnt()> - unknown layout situation: current frame should be in page header or page footer" );
1118 ASSERT( !pPrevCntntFrm
->IsInFly(),
1119 "<SwFrm::_FindPrevCnt()> - unknown layout situation: found previous frame should *not* be inside a fly frame." );
1120 if ( pPrevCntntFrm
->FindFooterOrHeader() !=
1121 pCurrCntntFrm
->FindFooterOrHeader() )
1130 return pPrevCntntFrm
;
1133 SwFrm
*SwFrm::_FindPrev()
1135 BOOL bIgnoreTab
= FALSE
;
1136 SwFrm
*pThis
= this;
1140 //Der erste Cntnt der Tabelle wird
1141 //gegriffen und dessen Vorgaenger geliefert. Um die Spezialbeh.
1142 //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt.
1143 if ( ((SwTabFrm
*)this)->IsFollow() )
1144 return ((SwTabFrm
*)this)->FindMaster();
1146 pThis
= ((SwTabFrm
*)this)->ContainsCntnt();
1150 if ( pThis
&& pThis
->IsCntntFrm() )
1152 SwCntntFrm
*pPrvCnt
= ((SwCntntFrm
*)pThis
)->GetPrevCntntFrm();
1155 if ( !bIgnoreTab
&& pThis
->IsInTab() )
1157 SwLayoutFrm
*pUp
= pThis
->GetUpper();
1158 while ( !pUp
->IsCellFrm() )
1159 pUp
= pUp
->GetUpper();
1160 ASSERT( pUp
, "Cntnt in Tabelle aber nicht in Zelle." );
1161 if ( pUp
->IsAnLower( pPrvCnt
) )
1167 const BOOL bBody
= pThis
->IsInDocBody();
1168 const BOOL bFtn
= bBody
? FALSE
: pThis
->IsInFtn();
1169 if ( bBody
|| bFtn
)
1173 if ( (bBody
&& pPrvCnt
->IsInDocBody()) ||
1174 (bFtn
&& pPrvCnt
->IsInFtn()) )
1176 pRet
= pPrvCnt
->IsInTab() ? pPrvCnt
->FindTabFrm()
1180 pPrvCnt
= pPrvCnt
->GetPrevCntntFrm();
1183 else if ( pThis
->IsInFly() )
1185 pRet
= pPrvCnt
->IsInTab() ? pPrvCnt
->FindTabFrm()
1189 else //Fuss-/oder Kopfbereich oder Fly
1191 const SwFrm
*pUp
= pThis
->GetUpper();
1192 const SwFrm
*pCntUp
= pPrvCnt
->GetUpper();
1193 while ( pUp
&& pUp
->GetUpper() &&
1194 !pUp
->IsHeaderFrm() && !pUp
->IsFooterFrm() )
1195 pUp
= pUp
->GetUpper();
1196 while ( pCntUp
&& pCntUp
->GetUpper() )
1197 pCntUp
= pCntUp
->GetUpper();
1198 if ( pCntUp
== pUp
)
1200 pRet
= pPrvCnt
->IsInTab() ? pPrvCnt
->FindTabFrm()
1210 void SwFrm::ImplInvalidateNextPos( BOOL bNoFtn
)
1213 if ( 0 != (pFrm
= _FindNext()) )
1215 if( pFrm
->IsSctFrm() )
1217 while( pFrm
&& pFrm
->IsSctFrm() )
1219 if( ((SwSectionFrm
*)pFrm
)->GetSection() )
1221 SwFrm
* pTmp
= ((SwSectionFrm
*)pFrm
)->ContainsAny();
1223 pTmp
->InvalidatePos();
1225 ((SwSectionFrm
*)pFrm
)->InvalidateFtnPos();
1226 if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm
)
1227 pFrm
->InvalidatePos();
1230 pFrm
= pFrm
->FindNext();
1234 if ( pFrm
->IsSctFrm())
1235 { // Damit der Inhalt eines Bereichs die Chance erhaelt,
1236 // die Seite zu wechseln, muss er ebenfalls invalidiert werden.
1237 SwFrm
* pTmp
= ((SwSectionFrm
*)pFrm
)->ContainsAny();
1239 pTmp
->InvalidatePos();
1240 if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm
)
1241 pFrm
->InvalidatePos();
1244 pFrm
->InvalidatePos();
1248 pFrm
->InvalidatePos();
1252 /** method to invalidate printing area of next frame
1254 OD 09.01.2004 #i11859#
1258 FME 2004-04-19 #i27145# Moved function from SwTxtFrm to SwFrm
1260 void SwFrm::InvalidateNextPrtArea()
1262 // determine next frame
1263 SwFrm
* pNextFrm
= FindNext();
1264 // skip empty section frames and hidden text frames
1267 ( ( pNextFrm
->IsSctFrm() &&
1268 !static_cast<SwSectionFrm
*>(pNextFrm
)->GetSection() ) ||
1269 ( pNextFrm
->IsTxtFrm() &&
1270 static_cast<SwTxtFrm
*>(pNextFrm
)->IsHiddenNow() ) ) )
1272 pNextFrm
= pNextFrm
->FindNext();
1276 // Invalidate printing area of found next frame
1279 if ( pNextFrm
->IsSctFrm() )
1281 // Invalidate printing area of found section frame, if
1282 // (1) this text frame isn't in a section OR
1283 // (2) found section frame isn't a follow of the section frame this
1284 // text frame is in.
1285 if ( !IsInSct() || FindSctFrm()->GetFollow() != pNextFrm
)
1287 pNextFrm
->InvalidatePrt();
1290 // Invalidate printing area of first content in found section.
1291 SwFrm
* pFstCntntOfSctFrm
=
1292 static_cast<SwSectionFrm
*>(pNextFrm
)->ContainsAny();
1293 if ( pFstCntntOfSctFrm
)
1295 pFstCntntOfSctFrm
->InvalidatePrt();
1300 pNextFrm
->InvalidatePrt();
1305 /*************************************************************************
1307 |* lcl_IsInColSect()
1308 |* liefert nur TRUE, wenn der Frame _direkt_ in einem spaltigen Bereich steht,
1309 |* nicht etwa, wenn er in einer Tabelle steht, die in einem spaltigen Bereich ist.
1311 |*************************************************************************/
1313 BOOL
lcl_IsInColSct( const SwFrm
*pUp
)
1318 if( pUp
->IsColumnFrm() )
1320 else if( pUp
->IsSctFrm() )
1322 else if( pUp
->IsTabFrm() )
1324 pUp
= pUp
->GetUpper();
1329 /*************************************************************************
1331 |* SwFrm::IsMoveable();
1333 |* Ersterstellung MA 09. Mar. 93
1334 |* Letzte Aenderung MA 05. May. 95
1336 |*************************************************************************/
1337 /** determine, if frame is moveable in given environment
1339 OD 08.08.2003 #110978#
1340 method replaced 'old' method <BOOL IsMoveable() const>.
1341 Determines, if frame is moveable in given environment. if no environment
1342 is given (parameter _pLayoutFrm == 0L), the movability in the actual
1343 environment (<this->GetUpper()) is checked.
1348 bool SwFrm::IsMoveable( const SwLayoutFrm
* _pLayoutFrm
) const
1350 bool bRetVal
= false;
1354 _pLayoutFrm
= GetUpper();
1357 if ( _pLayoutFrm
&& IsFlowFrm() )
1359 if ( _pLayoutFrm
->IsInSct() && lcl_IsInColSct( _pLayoutFrm
) )
1363 else if ( _pLayoutFrm
->IsInFly() ||
1364 _pLayoutFrm
->IsInDocBody() ||
1365 _pLayoutFrm
->IsInFtn() )
1367 if ( _pLayoutFrm
->IsInTab() && !IsTabFrm() &&
1368 ( !IsCntntFrm() || !const_cast<SwFrm
*>(this)->GetNextCellLeaf( MAKEPAGE_NONE
) ) )
1374 if ( _pLayoutFrm
->IsInFly() )
1376 // if fly frame has a follow (next linked fly frame),
1377 // frame is moveable.
1378 if ( const_cast<SwLayoutFrm
*>(_pLayoutFrm
)->FindFlyFrm()->GetNextLink() )
1384 // if environment is columned, frame is moveable, if
1385 // it isn't in last column.
1386 // search for column frame
1387 const SwFrm
* pCol
= _pLayoutFrm
;
1388 while ( pCol
&& !pCol
->IsColumnFrm() )
1390 pCol
= pCol
->GetUpper();
1392 // frame is moveable, if found column frame isn't last one.
1393 if ( pCol
&& pCol
->GetNext() )
1410 /*************************************************************************
1412 |* SwFrm::SetInfFlags();
1414 |* Ersterstellung MA 05. Apr. 94
1415 |* Letzte Aenderung MA 05. Apr. 94
1417 |*************************************************************************/
1418 void SwFrm::SetInfFlags()
1420 if ( !IsFlyFrm() && !GetUpper() ) //noch nicht gepastet, keine Informationen
1423 bInfInvalid
= bInfBody
= bInfTab
= bInfFly
= bInfFtn
= bInfSct
= FALSE
;
1426 if( IsFtnContFrm() )
1429 { // bInfBody wird nur am Seitenbody, nicht im ColumnBody gesetzt
1430 if ( pFrm
->IsBodyFrm() && !bInfFtn
&& pFrm
->GetUpper()
1431 && pFrm
->GetUpper()->IsPageFrm() )
1433 else if ( pFrm
->IsTabFrm() || pFrm
->IsCellFrm() )
1437 else if ( pFrm
->IsFlyFrm() )
1439 else if ( pFrm
->IsSctFrm() )
1441 else if ( pFrm
->IsFtnFrm() )
1444 pFrm
= pFrm
->GetUpper();
1446 } while ( pFrm
&& !pFrm
->IsPageFrm() ); //Oberhalb der Seite kommt nix
1449 /*-----------------22.8.2001 14:30------------------
1450 * SwFrm::SetDirFlags( BOOL )
1451 * actualizes the vertical or the righttoleft-flags.
1452 * If the property is derived, it's from the upper or (for fly frames) from
1453 * the anchor. Otherwise we've to call a virtual method to check the property.
1454 * --------------------------------------------------*/
1456 void SwFrm::SetDirFlags( BOOL bVert
)
1460 // OD 2004-01-21 #114969# - if derived, valid vertical flag only if
1461 // vertical flag of upper/anchor is valid.
1464 const SwFrm
* pAsk
= IsFlyFrm() ?
1465 ((SwFlyFrm
*)this)->GetAnchorFrm() : GetUpper();
1467 ASSERT( pAsk
!= this, "Autsch! Stack overflow is about to happen" )
1471 bVertical
= pAsk
->IsVertical() ? 1 : 0;
1472 bReverse
= pAsk
->IsReverse() ? 1 : 0;
1473 if ( !pAsk
->bInvalidVert
)
1474 bInvalidVert
= FALSE
;
1478 CheckDirection( bVert
);
1483 if( !bDerivedR2L
) // CheckDirection is able to set bDerivedR2L!
1484 CheckDirection( bVert
);
1487 const SwFrm
* pAsk
= IsFlyFrm() ?
1488 ((SwFlyFrm
*)this)->GetAnchorFrm() : GetUpper();
1490 ASSERT( pAsk
!= this, "Autsch! Stack overflow is about to happen" )
1493 bRightToLeft
= pAsk
->IsRightToLeft() ? 1 : 0;
1494 if( !pAsk
|| pAsk
->bInvalidR2L
)
1501 SwLayoutFrm
* SwFrm::GetNextCellLeaf( MakePageType
)
1503 SwFrm
* pTmpFrm
= this;
1504 while ( !pTmpFrm
->IsCellFrm() )
1505 pTmpFrm
= pTmpFrm
->GetUpper();
1507 ASSERT( pTmpFrm
, "SwFrm::GetNextCellLeaf() without cell" )
1508 return ((SwCellFrm
*)pTmpFrm
)->GetFollowCell();
1511 SwLayoutFrm
* SwFrm::GetPrevCellLeaf( MakePageType
)
1513 SwFrm
* pTmpFrm
= this;
1514 while ( !pTmpFrm
->IsCellFrm() )
1515 pTmpFrm
= pTmpFrm
->GetUpper();
1517 ASSERT( pTmpFrm
, "SwFrm::GetNextPreviousLeaf() without cell" )
1518 return ((SwCellFrm
*)pTmpFrm
)->GetPreviousCell();
1521 SwCellFrm
* lcl_FindCorrespondingCellFrm( const SwRowFrm
& rOrigRow
,
1522 const SwCellFrm
& rOrigCell
,
1523 const SwRowFrm
& rCorrRow
,
1526 SwCellFrm
* pRet
= NULL
;
1527 SwCellFrm
* pCell
= (SwCellFrm
*)rOrigRow
.Lower();
1528 SwCellFrm
* pCorrCell
= (SwCellFrm
*)rCorrRow
.Lower();
1530 while ( pCell
!= &rOrigCell
&& !pCell
->IsAnLower( &rOrigCell
) )
1532 pCell
= (SwCellFrm
*)pCell
->GetNext();
1533 pCorrCell
= (SwCellFrm
*)pCorrCell
->GetNext();
1536 ASSERT( pCell
&& pCorrCell
, "lcl_FindCorrespondingCellFrm does not work" )
1538 if ( pCell
!= &rOrigCell
)
1540 // rOrigCell must be a lower of pCell. We need to recurse into the rows:
1541 ASSERT( pCell
->Lower() && pCell
->Lower()->IsRowFrm(),
1542 "lcl_FindCorrespondingCellFrm does not work" )
1544 SwRowFrm
* pRow
= (SwRowFrm
*)pCell
->Lower();
1545 while ( !pRow
->IsAnLower( &rOrigCell
) )
1546 pRow
= (SwRowFrm
*)pRow
->GetNext();
1548 SwRowFrm
* pCorrRow
= 0;
1550 pCorrRow
= pRow
->GetFollowRow();
1553 SwRowFrm
* pTmpRow
= static_cast<SwRowFrm
*>(pCorrCell
->GetLastLower());
1555 if ( pTmpRow
&& pTmpRow
->GetFollowRow() == pRow
)
1560 pRet
= lcl_FindCorrespondingCellFrm( *pRow
, rOrigCell
, *pCorrRow
, bInFollow
);
1568 // VERSION OF GetFollowCell() that assumes that we always have a follow flow line:
1569 SwCellFrm
* SwCellFrm::GetFollowCell() const
1571 SwCellFrm
* pRet
= NULL
;
1574 // Covered cells do not have follow cells!
1575 const long nRowSpan
= GetLayoutRowSpan();
1579 // find most upper row frame
1580 const SwFrm
* pRow
= GetUpper();
1581 while( !pRow
->IsRowFrm() || !pRow
->GetUpper()->IsTabFrm() )
1582 pRow
= pRow
->GetUpper();
1587 const SwTabFrm
* pTabFrm
= static_cast<const SwTabFrm
*>( pRow
->GetUpper() );
1588 if ( !pRow
|| !pTabFrm
->GetFollow() || !pTabFrm
->HasFollowFlowLine() )
1591 const SwCellFrm
* pThisCell
= this;
1593 // Get last cell of the current table frame that belongs to the rowspan:
1596 // optimization: Will end of row span be in last row or exceed row?
1598 while ( pRow
->GetNext() && ++nMax
< nRowSpan
)
1599 pRow
= pRow
->GetNext();
1601 if ( !pRow
->GetNext() )
1603 pThisCell
= &pThisCell
->FindStartEndOfRowSpanCell( false, true );
1604 pRow
= pThisCell
->GetUpper();
1608 const SwRowFrm
* pFollowRow
= NULL
;
1609 if ( !pRow
->GetNext() &&
1610 NULL
!= ( pFollowRow
= pRow
->IsInSplitTableRow() ) &&
1611 ( !pFollowRow
->IsRowSpanLine() || nRowSpan
> 1 ) )
1612 pRet
= lcl_FindCorrespondingCellFrm( *((SwRowFrm
*)pRow
), *pThisCell
, *pFollowRow
, true );
1617 // VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL
1618 SwCellFrm
* SwCellFrm::GetPreviousCell() const
1620 SwCellFrm
* pRet
= NULL
;
1623 // Covered cells do not have previous cells!
1624 if ( GetLayoutRowSpan() < 1 )
1627 // find most upper row frame
1628 const SwFrm
* pRow
= GetUpper();
1629 while( !pRow
->IsRowFrm() || !pRow
->GetUpper()->IsTabFrm() )
1630 pRow
= pRow
->GetUpper();
1632 ASSERT( pRow
->GetUpper() && pRow
->GetUpper()->IsTabFrm(), "GetPreviousCell without Table" );
1634 SwTabFrm
* pTab
= (SwTabFrm
*)pRow
->GetUpper();
1636 if ( pTab
->IsFollow() )
1638 const SwFrm
* pTmp
= pTab
->GetFirstNonHeadlineRow();
1639 const bool bIsInFirstLine
= ( pTmp
== pRow
);
1641 if ( bIsInFirstLine
)
1643 SwTabFrm
*pMaster
= (SwTabFrm
*)pTab
->FindMaster();
1644 if ( pMaster
&& pMaster
->HasFollowFlowLine() )
1646 SwRowFrm
* pMasterRow
= static_cast<SwRowFrm
*>(pMaster
->GetLastLower());
1648 pRet
= lcl_FindCorrespondingCellFrm( *((SwRowFrm
*)pRow
), *this, *pMasterRow
, false );
1649 if ( pRet
&& pRet
->GetTabBox()->getRowSpan() < 1 )
1650 pRet
= &const_cast<SwCellFrm
&>(pRet
->FindStartEndOfRowSpanCell( true, true ));
1659 const SwCellFrm
& SwCellFrm::FindStartEndOfRowSpanCell( bool bStart
, bool bCurrentTableOnly
) const
1661 const SwCellFrm
* pRet
= 0;
1663 const SwTabFrm
* pTableFrm
= dynamic_cast<const SwTabFrm
*>(GetUpper()->GetUpper());
1665 if ( !bStart
&& pTableFrm
->IsFollow() && pTableFrm
->IsInHeadline( *this ) )
1668 ASSERT( pTableFrm
&&
1669 ( bStart
&& GetTabBox()->getRowSpan() < 1 ||
1670 !bStart
&& GetLayoutRowSpan() > 1 ),
1671 "SwCellFrm::FindStartRowSpanCell: No rowspan, no table, no cookies" )
1675 const SwTable
* pTable
= pTableFrm
->GetTable();
1677 USHORT nMax
= USHRT_MAX
;
1678 if ( bCurrentTableOnly
)
1680 const SwFrm
* pCurrentRow
= GetUpper();
1681 const bool bDoNotEnterHeadline
= bStart
&& pTableFrm
->IsFollow() &&
1682 !pTableFrm
->IsInHeadline( *pCurrentRow
);
1684 // check how many rows we are allowed to go up or down until we reach the end of
1685 // the current table frame:
1687 while ( bStart
? pCurrentRow
->GetPrev() : pCurrentRow
->GetNext() )
1691 // do not enter a repeated headline:
1692 if ( bDoNotEnterHeadline
&& pTableFrm
->IsFollow() &&
1693 pTableFrm
->IsInHeadline( *pCurrentRow
->GetPrev() ) )
1696 pCurrentRow
= pCurrentRow
->GetPrev();
1699 pCurrentRow
= pCurrentRow
->GetNext();
1705 // By passing the nMax value for Find*OfRowSpan (in case of bCurrentTableOnly
1706 // is set) we assure that we find a rMasterBox that has a SwCellFrm in
1707 // the current table frame:
1708 const SwTableBox
& rMasterBox
= bStart
?
1709 GetTabBox()->FindStartOfRowSpan( *pTable
, nMax
) :
1710 GetTabBox()->FindEndOfRowSpan( *pTable
, nMax
);
1712 SwClientIter
aIter( const_cast<SwFrmFmt
&>( *rMasterBox
.GetFrmFmt()) );
1714 for ( SwClient
* pLast
= aIter
.First( TYPE( SwFrm
) ); pLast
; pLast
= aIter
.Next() )
1716 ASSERT( ((SwFrm
*)pLast
)->IsCellFrm(), "Non-row frame registered in table line" )
1717 const SwCellFrm
* pMasterCell
= static_cast<const SwCellFrm
*>(pLast
);
1719 if ( pMasterCell
->GetTabBox() == &rMasterBox
)
1721 const SwTabFrm
* pMasterTable
= static_cast<const SwTabFrm
*>(pMasterCell
->GetUpper()->GetUpper());
1723 if ( bCurrentTableOnly
)
1725 if ( pMasterTable
== pTableFrm
)
1733 if ( pMasterTable
== pTableFrm
||
1734 ( bStart
&& pMasterTable
->IsAnFollow( pTableFrm
) ||
1735 !bStart
&& pTableFrm
->IsAnFollow( pMasterTable
) ) )
1745 ASSERT( pRet
, "SwCellFrm::FindStartRowSpanCell: No result" )
1751 const SwRowFrm
* SwFrm::IsInSplitTableRow() const
1753 ASSERT( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" )
1755 const SwFrm
* pRow
= this;
1757 // find most upper row frame
1758 while( pRow
&& ( !pRow
->IsRowFrm() || !pRow
->GetUpper()->IsTabFrm() ) )
1759 pRow
= pRow
->GetUpper();
1761 if ( !pRow
) return NULL
;
1763 ASSERT( pRow
->GetUpper()->IsTabFrm(), "Confusion in table layout" )
1765 const SwTabFrm
* pTab
= (SwTabFrm
*)pRow
->GetUpper();
1766 // --> OD 2006-06-28 #b6443897#
1767 // If most upper row frame is a headline row, the current frame
1768 // can't be in a splitted table row. Thus, add corresponding condition.
1769 if ( pRow
->GetNext() ||
1770 pTab
->GetTable()->IsHeadline(
1771 *(static_cast<const SwRowFrm
*>(pRow
)->GetTabLine()) ) ||
1772 !pTab
->HasFollowFlowLine() ||
1773 !pTab
->GetFollow() )
1778 const SwRowFrm
* pFollowRow
= pTab
->GetFollow()->GetFirstNonHeadlineRow();
1780 ASSERT( pFollowRow
, "SwFrm::IsInSplitTableRow() does not work" )
1785 const SwRowFrm
* SwFrm::IsInFollowFlowRow() const
1787 ASSERT( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" )
1789 // find most upper row frame
1790 const SwFrm
* pRow
= this;
1791 while( pRow
&& ( !pRow
->IsRowFrm() || !pRow
->GetUpper()->IsTabFrm() ) )
1792 pRow
= pRow
->GetUpper();
1794 if ( !pRow
) return NULL
;
1796 ASSERT( pRow
->GetUpper()->IsTabFrm(), "Confusion in table layout" )
1798 const SwTabFrm
* pTab
= (SwTabFrm
*)pRow
->GetUpper();
1800 const SwTabFrm
* pMaster
= pTab
->IsFollow() ? pTab
->FindMaster() : 0;
1802 if ( !pMaster
|| !pMaster
->HasFollowFlowLine() )
1805 const SwFrm
* pTmp
= pTab
->GetFirstNonHeadlineRow();
1806 const bool bIsInFirstLine
= ( pTmp
== pRow
);
1808 if ( !bIsInFirstLine
)
1811 const SwRowFrm
* pMasterRow
= static_cast<const SwRowFrm
*>(pMaster
->GetLastLower());
1815 bool SwFrm::IsInBalancedSection() const
1821 const SwSectionFrm
* pSectionFrm
= FindSctFrm();
1823 bRet
= pSectionFrm
->IsBalancedSection();
1829 * SwLayoutFrm::GetLastLower()
1831 const SwFrm
* SwLayoutFrm::GetLastLower() const
1833 const SwFrm
* pRet
= Lower();
1836 while ( pRet
->GetNext() )
1837 pRet
= pRet
->GetNext();