Update ooo320-m1
[ooovba.git] / sw / source / core / layout / findfrm.cxx
blobd64105670365ff6c8e8eecfb550488026bc35b86
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: findfrm.cxx,v $
10 * $Revision: 1.48 $
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"
37 #include "cntfrm.hxx"
38 #include "node.hxx"
39 #include "doc.hxx"
40 #include "frmtool.hxx"
41 #include "flyfrm.hxx"
42 #include <frmfmt.hxx>
43 #include <cellfrm.hxx>
44 #include <rowfrm.hxx>
45 #include <swtable.hxx>
47 #include "tabfrm.hxx"
48 #include "sectfrm.hxx"
49 #include "flyfrms.hxx"
50 #include "ftnfrm.hxx"
51 #include "txtftn.hxx"
52 #include "fmtftn.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
61 |* der Seite.
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 ) )
79 { pRet = pNxt;
80 pNxt = pNxt->FindNextCnt();
82 return pRet;
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
105 //werden.
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();
117 if( pCnt )
118 return pCnt;
119 if( pLayLeaf->GetNext() )
121 if( pLayLeaf->GetNext()->IsLayoutFrm() )
123 pLayLeaf = (SwLayoutFrm*)pLayLeaf->GetNext();
124 continue;
126 else
127 return (SwCntntFrm*)pLayLeaf->GetNext();
130 else if ( pLayLeaf->Lower() )
131 return (SwCntntFrm*)pLayLeaf->Lower();
133 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
134 if( !IsAnLower( pLayLeaf) )
135 return 0;
136 } while( pLayLeaf );
137 return 0;
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;
185 // <--
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.
198 return pLayLeaf;
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) )
212 return 0;
213 } while( pLayLeaf );
214 return 0;
218 /*************************************************************************
220 |* SwFrm::GetLower()
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;
247 while ( pUp )
249 if ( pUp == this )
250 return TRUE;
251 if ( pUp->IsFlyFrm() )
252 pUp = ((SwFlyFrm*)pUp)->GetAnchorFrm();
253 else
254 pUp = pUp->GetUpper();
256 return FALSE;
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.
269 @author OD
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>.");
278 bool bReturn;
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();
288 else
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
300 bReturn = false;
302 else
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();
307 while ( pUpNext &&
308 !pUpNext->IsAnLower( _pCheckRefLayFrm ) )
310 pUpNext = (SwLayoutFrm*)pUpNext->GetNext();
312 bReturn = pUpNext != 0;
316 return bReturn;
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();
328 else
329 pRet = bNext ? pFrm->GetNext() : pFrm->GetPrev();
331 return pRet;
334 const SwFrm* lcl_GetLower( const SwFrm* pFrm, bool bFwd )
336 if ( !pFrm->IsLayoutFrm() )
337 return 0;
339 return bFwd ?
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
350 * content frame.
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;
360 const SwFrm *p = 0;
361 bool bGoingUp = !bFwd; // false for forward, true for backward
362 do {
364 bool bGoingFwdOrBwd = false, bGoingDown = false;
366 bGoingDown = ( !bGoingUp && ( 0 != (p = lcl_GetLower( pFrm, bFwd ) ) ) );
367 if ( !bGoingDown )
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() ) );
378 if ( !bGoingUp )
380 // I cannot go up, because there is no upper frame.
381 return 0;
386 // If I could not go down or forward, I'll have to go up
387 bGoingUp = !bGoingFwdOrBwd && !bGoingDown;
389 pFrm = p;
390 p = lcl_GetLower( pFrm, true );
392 } while( ( p && !p->IsFlowFrm() ) ||
393 pFrm == this ||
394 0 == ( pLayoutFrm = pFrm->IsLayoutFrm() ? (SwLayoutFrm*)pFrm : 0 ) ||
395 pLayoutFrm->IsAnLower( this ) );
397 return pLayoutFrm;
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.
416 |* Ersterstellung ??
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;
426 // #100926#
427 SwCntntFrm *pCntntFrm = 0;
428 BOOL bGoingUp = FALSE;
429 do {
430 const SwFrm *p = 0;
431 BOOL bGoingFwdOrBwd = FALSE, bGoingDown = FALSE;
433 bGoingDown = ( !bGoingUp && ( 0 != ( p = lcl_GetLower( pFrm, true ) ) ) );
434 if ( !bGoingDown )
436 bGoingFwdOrBwd = ( 0 != ( p = lcl_FindLayoutFrame( pFrm, bFwd ) ) );
437 if ( !bGoingFwdOrBwd )
439 bGoingUp = ( 0 != ( p = pFrm->GetUpper() ) );
440 if ( !bGoingUp )
442 return 0;
447 bGoingUp = !(bGoingFwdOrBwd || bGoingDown);
449 if ( !bFwd )
451 if( bGoingDown && p )
452 while ( p->GetNext() )
453 p = p->GetNext();
456 pFrm = p;
457 } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
459 return pCntntFrm;
465 /*************************************************************************
467 |* SwFrm::FindRootFrm(), FindTabFrm(), FindFtnFrm(), FindFlyFrm(),
468 |* FindPageFrm(), FindColFrm()
470 |* Ersterstellung ??
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
478 // a root frame.
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
481 // and destructors.
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()
492 SwFrm *pRet = this;
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();
502 else
503 pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm();
505 else
506 return 0;
508 return (SwPageFrm*)pRet;
511 SwFtnBossFrm* SwFrm::FindFtnBossFrm( BOOL bFootnotes )
513 SwFrm *pRet = this;
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();
527 else
528 pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm();
530 else
531 return 0;
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()
546 SwFrm *pRet = this;
547 while ( !pRet->IsTabFrm() )
549 pRet = pRet->GetUpper();
550 if ( !pRet )
551 return 0;
553 return (SwTabFrm*)pRet;
556 SwSectionFrm* SwFrm::ImplFindSctFrm()
558 SwFrm *pRet = this;
559 while ( !pRet->IsSctFrm() )
561 pRet = pRet->GetUpper();
562 if ( !pRet )
563 return 0;
565 return (SwSectionFrm*)pRet;
568 SwFtnFrm *SwFrm::ImplFindFtnFrm()
570 SwFrm *pRet = this;
571 while ( !pRet->IsFtnFrm() )
573 pRet = pRet->GetUpper();
574 if ( !pRet )
575 return 0;
577 return (SwFtnFrm*)pRet;
580 SwFlyFrm *SwFrm::ImplFindFlyFrm()
582 const SwFrm *pRet = this;
585 if ( pRet->IsFlyFrm() )
586 return (SwFlyFrm*)pRet;
587 else
588 pRet = pRet->GetUpper();
589 } while ( pRet );
590 return 0;
593 SwFrm *SwFrm::FindColFrm()
595 SwFrm *pFrm = this;
597 { pFrm = pFrm->GetUpper();
598 } while ( pFrm && !pFrm->IsColumnFrm() );
599 return pFrm;
602 SwRowFrm *SwFrm::FindRowFrm()
604 SwFrm *pFrm = this;
606 { pFrm = pFrm->GetUpper();
607 } while ( pFrm && !pFrm->IsRowFrm() );
608 return dynamic_cast< SwRowFrm* >( pFrm );
611 SwFrm* SwFrm::FindFooterOrHeader()
613 SwFrm* pRet = this;
615 { if ( pRet->GetType() & 0x0018 ) //Header und Footer
616 return pRet;
617 else if ( pRet->GetUpper() )
618 pRet = pRet->GetUpper();
619 else if ( pRet->IsFlyFrm() )
620 pRet = ((SwFlyFrm*)pRet)->AnchorFrm();
621 else
622 return 0;
623 } while ( pRet );
624 return pRet;
627 const SwFtnFrm* SwFtnContFrm::FindFootNote() const
629 const SwFtnFrm* pRet = (SwFtnFrm*)Lower();
630 if( pRet && !pRet->GetAttr()->GetFtn().IsEndNote() )
631 return pRet;
632 return NULL;
635 const SwPageFrm* SwRootFrm::GetPageAtPos( const Point& rPt, const Size* pSize, bool bExtend ) const
637 const SwPageFrm* pRet = 0;
639 SwRect aRect;
640 if ( pSize )
642 aRect.Pos() = rPt;
643 aRect.SSize() = *pSize;
646 const SwFrm* pPage = Lower();
648 if ( !bExtend )
650 if( !Frm().IsInside( rPt ) )
651 return 0;
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" )
659 USHORT nPageIdx = 0;
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();
672 return pRet;
675 /*************************************************************************
677 |* SwFrmFrm::GetAttrSet()
679 |* Ersterstellung MA 02. Aug. 93
680 |* Letzte Aenderung MA 02. Aug. 93
682 |*************************************************************************/
683 const SwAttrSet* SwFrm::GetAttrSet() const
685 if ( IsCntntFrm() )
686 return &((const SwCntntFrm*)this)->GetNode()->GetSwAttrSet();
687 else
688 return &((const SwLayoutFrm*)this)->GetFmt()->GetAttrSet();
691 /*************************************************************************
693 |* SwFrm::_FindNext(), _FindPrev(), InvalidateNextPos()
694 |* _FindNextCnt() geht in Tabellen und Bereiche hineinund liefert
695 |* nur SwCntntFrms.
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:
700 |* - Body,
701 |* - Fussnoten,
702 |* - Bei Kopf-/Fussbereichen ist die Benachrichtigung nur innerhalb des
703 |* Bereiches weiterzuleiten.
704 |* - dito fuer Flys.
705 |* - Cntnts in Tabs halten sich ausschliesslich innerhalb ihrer Zelle
706 |* auf.
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 )
718 SwFrm *pRet = 0;
719 BOOL bGoingUp = FALSE;
720 do {
721 SwFrm *p = 0;
723 BOOL bGoingFwd = FALSE;
724 BOOL bGoingDown = (!bGoingUp && ( 0 != (p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0)));
726 if( !bGoingDown )
728 bGoingFwd = (0 != (p = ( pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->GetNextLink() : pFrm->GetNext())));
729 if ( !bGoingFwd )
731 bGoingUp = (0 != (p = pFrm->GetUpper()));
732 if ( !bGoingUp )
734 return 0;
738 bGoingUp = !(bGoingFwd || bGoingDown);
739 pFrm = p;
740 } while ( 0 == (pRet = ( ( pFrm->IsCntntFrm() || ( !bGoingUp &&
741 ( pFrm->IsTabFrm() || pFrm->IsSctFrm() ) ) )? pFrm : 0 ) ) );
742 return pRet;
745 SwFrm *SwFrm::_FindNext()
747 BOOL bIgnoreTab = FALSE;
748 SwFrm *pThis = this;
750 if ( IsTabFrm() )
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();
759 if ( !pThis )
760 pThis = this;
761 bIgnoreTab = TRUE;
763 else if ( IsSctFrm() )
765 //Der letzte Cntnt des Bereichs wird gegriffen und dessen Nachfolger
766 // geliefert.
767 if ( ((SwSectionFrm*)this)->GetFollow() )
768 return ((SwSectionFrm*)this)->GetFollow();
770 pThis = ((SwSectionFrm*)this)->FindLastCntnt();
771 if ( !pThis )
772 pThis = this;
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();
784 else return NULL;
786 else
787 return NULL;
789 SwFrm* pRet = NULL;
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();
798 if ( pNxt )
799 pNxt = ((SwCellFrm*)pNxt)->ContainsCntnt();
800 if ( !pNxt )
802 pNxt = lcl_NextFrm( pThis );
803 if ( pUp->IsAnLower( pNxt ) )
804 pRet = pNxt;
806 else
807 pRet = pNxt;
809 else
811 const BOOL bBody = pThis->IsInDocBody();
812 SwFrm *pNxtCnt = lcl_NextFrm( pThis );
813 if ( pNxtCnt )
815 if ( bBody || bFtn )
817 while ( pNxtCnt )
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() &&
828 ( bFtn ||
829 ( bEndn && pNxtCnt->FindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
834 pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
835 : (SwFrm*)pNxtCnt;
836 break;
838 pNxtCnt = lcl_NextFrm( pNxtCnt );
841 else if ( pThis->IsInFly() )
843 pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
844 : (SwFrm*)pNxtCnt;
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();
856 if ( pCntUp == pUp )
858 pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
859 : (SwFrm*)pNxtCnt;
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() ) )
871 return pSct;
873 return pRet;
876 // --> OD 2005-12-01 #i27138# - add parameter <_bInSameFtn>
877 SwCntntFrm *SwFrm::_FindNextCnt( const bool _bInSameFtn )
879 SwFrm *pThis = this;
881 if ( IsTabFrm() )
883 if ( ((SwTabFrm*)this)->GetFollow() )
885 pThis = ((SwTabFrm*)this)->GetFollow()->ContainsCntnt();
886 if( pThis )
887 return (SwCntntFrm*)pThis;
889 pThis = ((SwTabFrm*)this)->FindLastCntnt();
890 if ( !pThis )
891 return 0;
893 else if ( IsSctFrm() )
895 if ( ((SwSectionFrm*)this)->GetFollow() )
897 pThis = ((SwSectionFrm*)this)->GetFollow()->ContainsCntnt();
898 if( pThis )
899 return (SwCntntFrm*)pThis;
901 pThis = ((SwSectionFrm*)this)->FindLastCntnt();
902 if ( !pThis )
903 return 0;
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();
913 if ( pNxtCnt )
915 // --> OD 2005-12-01 #i27138#
916 if ( bBody || ( bFtn && !_bInSameFtn ) )
917 // <--
919 // handling for environments 'footnotes' and 'document body frames':
920 while ( pNxtCnt )
922 if ( (bBody && pNxtCnt->IsInDocBody()) ||
923 (bFtn && pNxtCnt->IsInFtn()) )
924 return pNxtCnt;
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 )
939 return pNxtCnt;
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) );
947 pNxtCnt = 0L;
948 do {
949 pFollowFtnFrmOfCurr = pFollowFtnFrmOfCurr->GetFollow();
950 pNxtCnt = pFollowFtnFrmOfCurr->ContainsCntnt();
951 } while ( !pNxtCnt && pFollowFtnFrmOfCurr->GetFollow() );
952 return pNxtCnt;
954 else
956 // current content frame is the last content frame in the
957 // footnote - no next content frame exists.
958 return 0L;
961 // <--
962 else if ( pThis->IsInFly() )
963 // handling for environments 'unlinked fly frame' and
964 // 'group of linked fly frames':
965 return pNxtCnt;
966 else
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();
977 if ( pCntUp == pUp )
978 return pNxtCnt;
982 return 0;
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#
990 @author OD
992 SwCntntFrm* SwFrm::_FindPrevCnt( const bool _bInSameFtn )
994 if ( !IsFlowFrm() )
996 // nothing to do, if current frame isn't a flow frame.
997 return 0L;
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();
1021 else
1023 // start content frame for the search is the first content frame of
1024 // the table frame.
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();
1036 else
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
1057 else
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() ) )
1071 break;
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) );
1088 pPrevCntntFrm = 0L;
1089 // --> OD 2007-07-05 #146872#
1090 // correct wrong loop-condition
1091 do {
1092 pMasterFtnFrmOfCurr = pMasterFtnFrmOfCurr->GetMaster();
1093 pPrevCntntFrm = pMasterFtnFrmOfCurr->FindLastCntnt();
1094 } while ( !pPrevCntntFrm &&
1095 pMasterFtnFrmOfCurr->GetMaster() );
1096 // <--
1098 else
1100 // current content frame is the first content in the
1101 // footnote - no previous content exists.
1102 pPrevCntntFrm = 0L;;
1106 else
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() )
1123 pPrevCntntFrm = 0L;
1130 return pPrevCntntFrm;
1133 SwFrm *SwFrm::_FindPrev()
1135 BOOL bIgnoreTab = FALSE;
1136 SwFrm *pThis = this;
1138 if ( IsTabFrm() )
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();
1145 else
1146 pThis = ((SwTabFrm*)this)->ContainsCntnt();
1147 bIgnoreTab = TRUE;
1150 if ( pThis && pThis->IsCntntFrm() )
1152 SwCntntFrm *pPrvCnt = ((SwCntntFrm*)pThis)->GetPrevCntntFrm();
1153 if( !pPrvCnt )
1154 return 0;
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 ) )
1162 return pPrvCnt;
1164 else
1166 SwFrm* pRet;
1167 const BOOL bBody = pThis->IsInDocBody();
1168 const BOOL bFtn = bBody ? FALSE : pThis->IsInFtn();
1169 if ( bBody || bFtn )
1171 while ( pPrvCnt )
1173 if ( (bBody && pPrvCnt->IsInDocBody()) ||
1174 (bFtn && pPrvCnt->IsInFtn()) )
1176 pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
1177 : (SwFrm*)pPrvCnt;
1178 return pRet;
1180 pPrvCnt = pPrvCnt->GetPrevCntntFrm();
1183 else if ( pThis->IsInFly() )
1185 pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
1186 : (SwFrm*)pPrvCnt;
1187 return pRet;
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()
1201 : (SwFrm*)pPrvCnt;
1202 return pRet;
1207 return 0;
1210 void SwFrm::ImplInvalidateNextPos( BOOL bNoFtn )
1212 SwFrm *pFrm;
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();
1222 if( pTmp )
1223 pTmp->InvalidatePos();
1224 else if( !bNoFtn )
1225 ((SwSectionFrm*)pFrm)->InvalidateFtnPos();
1226 if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm )
1227 pFrm->InvalidatePos();
1228 return;
1230 pFrm = pFrm->FindNext();
1232 if( pFrm )
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();
1238 if( pTmp )
1239 pTmp->InvalidatePos();
1240 if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm )
1241 pFrm->InvalidatePos();
1243 else
1244 pFrm->InvalidatePos();
1247 else
1248 pFrm->InvalidatePos();
1252 /** method to invalidate printing area of next frame
1254 OD 09.01.2004 #i11859#
1256 @author OD
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
1266 while ( pNextFrm &&
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
1277 if ( pNextFrm )
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();
1298 else
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 )
1315 BOOL bRet = FALSE;
1316 while( pUp )
1318 if( pUp->IsColumnFrm() )
1319 bRet = TRUE;
1320 else if( pUp->IsSctFrm() )
1321 return bRet;
1322 else if( pUp->IsTabFrm() )
1323 return FALSE;
1324 pUp = pUp->GetUpper();
1326 return FALSE;
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.
1345 @author OD
1348 bool SwFrm::IsMoveable( const SwLayoutFrm* _pLayoutFrm ) const
1350 bool bRetVal = false;
1352 if ( !_pLayoutFrm )
1354 _pLayoutFrm = GetUpper();
1357 if ( _pLayoutFrm && IsFlowFrm() )
1359 if ( _pLayoutFrm->IsInSct() && lcl_IsInColSct( _pLayoutFrm ) )
1361 bRetVal = true;
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 ) ) )
1370 bRetVal = false;
1372 else
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() )
1380 bRetVal = true;
1382 else
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() )
1395 bRetVal = true;
1399 else
1401 bRetVal = true;
1407 return bRetVal;
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
1421 return; //lieferbar
1423 bInfInvalid = bInfBody = bInfTab = bInfFly = bInfFtn = bInfSct = FALSE;
1425 SwFrm *pFrm = this;
1426 if( IsFtnContFrm() )
1427 bInfFtn = TRUE;
1429 { // bInfBody wird nur am Seitenbody, nicht im ColumnBody gesetzt
1430 if ( pFrm->IsBodyFrm() && !bInfFtn && pFrm->GetUpper()
1431 && pFrm->GetUpper()->IsPageFrm() )
1432 bInfBody = TRUE;
1433 else if ( pFrm->IsTabFrm() || pFrm->IsCellFrm() )
1435 bInfTab = TRUE;
1437 else if ( pFrm->IsFlyFrm() )
1438 bInfFly = TRUE;
1439 else if ( pFrm->IsSctFrm() )
1440 bInfSct = TRUE;
1441 else if ( pFrm->IsFtnFrm() )
1442 bInfFtn = TRUE;
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 )
1458 if( bVert )
1460 // OD 2004-01-21 #114969# - if derived, valid vertical flag only if
1461 // vertical flag of upper/anchor is valid.
1462 if( bDerivedVert )
1464 const SwFrm* pAsk = IsFlyFrm() ?
1465 ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper();
1467 ASSERT( pAsk != this, "Autsch! Stack overflow is about to happen" )
1469 if( pAsk )
1471 bVertical = pAsk->IsVertical() ? 1 : 0;
1472 bReverse = pAsk->IsReverse() ? 1 : 0;
1473 if ( !pAsk->bInvalidVert )
1474 bInvalidVert = FALSE;
1477 else
1478 CheckDirection( bVert );
1480 else
1482 BOOL bInv = 0;
1483 if( !bDerivedR2L ) // CheckDirection is able to set bDerivedR2L!
1484 CheckDirection( bVert );
1485 if( bDerivedR2L )
1487 const SwFrm* pAsk = IsFlyFrm() ?
1488 ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper();
1490 ASSERT( pAsk != this, "Autsch! Stack overflow is about to happen" )
1492 if( pAsk )
1493 bRightToLeft = pAsk->IsRightToLeft() ? 1 : 0;
1494 if( !pAsk || pAsk->bInvalidR2L )
1495 bInv = bInvalidR2L;
1497 bInvalidR2L = bInv;
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,
1524 bool bInFollow )
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;
1549 if ( bInFollow )
1550 pCorrRow = pRow->GetFollowRow();
1551 else
1553 SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pCorrCell->GetLastLower());
1555 if ( pTmpRow && pTmpRow->GetFollowRow() == pRow )
1556 pCorrRow = pTmpRow;
1559 if ( pCorrRow )
1560 pRet = lcl_FindCorrespondingCellFrm( *pRow, rOrigCell, *pCorrRow, bInFollow );
1562 else
1563 pRet = pCorrCell;
1565 return pRet;
1568 // VERSION OF GetFollowCell() that assumes that we always have a follow flow line:
1569 SwCellFrm* SwCellFrm::GetFollowCell() const
1571 SwCellFrm* pRet = NULL;
1573 // NEW TABLES
1574 // Covered cells do not have follow cells!
1575 const long nRowSpan = GetLayoutRowSpan();
1576 if ( nRowSpan < 1 )
1577 return NULL;
1579 // find most upper row frame
1580 const SwFrm* pRow = GetUpper();
1581 while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
1582 pRow = pRow->GetUpper();
1584 if ( !pRow )
1585 return NULL;
1587 const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( pRow->GetUpper() );
1588 if ( !pRow || !pTabFrm->GetFollow() || !pTabFrm->HasFollowFlowLine() )
1589 return NULL;
1591 const SwCellFrm* pThisCell = this;
1593 // Get last cell of the current table frame that belongs to the rowspan:
1594 if ( nRowSpan > 1 )
1596 // optimization: Will end of row span be in last row or exceed row?
1597 long nMax = 0;
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 );
1614 return pRet;
1617 // VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL
1618 SwCellFrm* SwCellFrm::GetPreviousCell() const
1620 SwCellFrm* pRet = NULL;
1622 // NEW TABLES
1623 // Covered cells do not have previous cells!
1624 if ( GetLayoutRowSpan() < 1 )
1625 return NULL;
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());
1647 if ( pMasterRow )
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 ));
1655 return pRet;
1658 // --> NEW TABLES
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 ) )
1666 return *this;
1668 ASSERT( pTableFrm &&
1669 ( bStart && GetTabBox()->getRowSpan() < 1 ||
1670 !bStart && GetLayoutRowSpan() > 1 ),
1671 "SwCellFrm::FindStartRowSpanCell: No rowspan, no table, no cookies" )
1673 if ( pTableFrm )
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:
1686 nMax = 0;
1687 while ( bStart ? pCurrentRow->GetPrev() : pCurrentRow->GetNext() )
1689 if ( bStart )
1691 // do not enter a repeated headline:
1692 if ( bDoNotEnterHeadline && pTableFrm->IsFollow() &&
1693 pTableFrm->IsInHeadline( *pCurrentRow->GetPrev() ) )
1694 break;
1696 pCurrentRow = pCurrentRow->GetPrev();
1698 else
1699 pCurrentRow = pCurrentRow->GetNext();
1701 ++nMax;
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 )
1727 pRet = pMasterCell;
1728 break;
1731 else
1733 if ( pMasterTable == pTableFrm ||
1734 ( bStart && pMasterTable->IsAnFollow( pTableFrm ) ||
1735 !bStart && pTableFrm->IsAnFollow( pMasterTable ) ) )
1737 pRet = pMasterCell;
1738 break;
1745 ASSERT( pRet, "SwCellFrm::FindStartRowSpanCell: No result" )
1747 return *pRet;
1749 // <-- NEW TABLES
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() )
1774 return NULL;
1775 // <--
1777 // skip headline
1778 const SwRowFrm* pFollowRow = pTab->GetFollow()->GetFirstNonHeadlineRow();
1780 ASSERT( pFollowRow, "SwFrm::IsInSplitTableRow() does not work" )
1782 return pFollowRow;
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() )
1803 return NULL;
1805 const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow();
1806 const bool bIsInFirstLine = ( pTmp == pRow );
1808 if ( !bIsInFirstLine )
1809 return NULL;
1811 const SwRowFrm* pMasterRow = static_cast<const SwRowFrm*>(pMaster->GetLastLower());
1812 return pMasterRow;
1815 bool SwFrm::IsInBalancedSection() const
1817 bool bRet = false;
1819 if ( IsInSct() )
1821 const SwSectionFrm* pSectionFrm = FindSctFrm();
1822 if ( pSectionFrm )
1823 bRet = pSectionFrm->IsBalancedSection();
1825 return bRet;
1829 * SwLayoutFrm::GetLastLower()
1831 const SwFrm* SwLayoutFrm::GetLastLower() const
1833 const SwFrm* pRet = Lower();
1834 if ( !pRet )
1835 return 0;
1836 while ( pRet->GetNext() )
1837 pRet = pRet->GetNext();
1838 return pRet;