xref: /AOO41X/main/sw/source/core/layout/findfrm.cxx (revision efeef26f81c84063fb0a91bde3856d4a51172d90)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 #include "pagefrm.hxx"
29 #include "rootfrm.hxx"
30 #include "cntfrm.hxx"
31 #include "node.hxx"
32 #include "doc.hxx"
33 #include "frmtool.hxx"
34 #include "flyfrm.hxx"
35 #include <frmfmt.hxx>
36 #include <cellfrm.hxx>
37 #include <rowfrm.hxx>
38 #include <swtable.hxx>
39 
40 #include "tabfrm.hxx"
41 #include "sectfrm.hxx"
42 #include "flyfrms.hxx"
43 #include "ftnfrm.hxx"
44 #include "txtftn.hxx"
45 #include "fmtftn.hxx"
46 #include <txtfrm.hxx>   // SwTxtFrm
47 #include <switerator.hxx>
48 
49 /*************************************************************************
50 |*
51 |*  FindBodyCont, FindLastBodyCntnt()
52 |*
53 |*  Beschreibung        Sucht den ersten/letzten CntntFrm im BodyText unterhalb
54 |*      der Seite.
55 |*  Ersterstellung      MA 15. Feb. 93
56 |*  Letzte Aenderung    MA 18. Apr. 94
57 |*
58 |*************************************************************************/
FindBodyCont()59 SwLayoutFrm *SwFtnBossFrm::FindBodyCont()
60 {
61     SwFrm *pLay = Lower();
62     while ( pLay && !pLay->IsBodyFrm() )
63         pLay = pLay->GetNext();
64     return (SwLayoutFrm*)pLay;
65 }
66 
FindLastBodyCntnt()67 SwCntntFrm *SwPageFrm::FindLastBodyCntnt()
68 {
69     SwCntntFrm *pRet = FindFirstBodyCntnt();
70     SwCntntFrm *pNxt = pRet;
71     while ( pNxt && pNxt->IsInDocBody() && IsAnLower( pNxt ) )
72     {   pRet = pNxt;
73         pNxt = pNxt->FindNextCnt();
74     }
75     return pRet;
76 }
77 
78 /*************************************************************************
79 |*
80 |*  SwLayoutFrm::ContainsCntnt
81 |*
82 |*  Beschreibung            Prueft, ob der Frame irgendwo in seiner
83 |*          untergeordneten Struktur einen oder mehrere CntntFrm's enthaelt;
84 |*          Falls ja wird der erste gefundene CntntFrm zurueckgegeben.
85 |*
86 |*  Ersterstellung      MA 13. May. 92
87 |*  Letzte Aenderung    MA 20. Apr. 94
88 |*
89 |*************************************************************************/
90 
ContainsCntnt() const91 const SwCntntFrm *SwLayoutFrm::ContainsCntnt() const
92 {
93     //LayoutBlatt nach unten hin suchen und wenn dieses keinen Inhalt hat
94     //solange die weiteren Blatter abklappern bis Inhalt gefunden oder der
95     //this verlassen wird.
96     //Sections: Cntnt neben Sections wuerde so nicht gefunden (leere Section
97     //direct neben CntntFrm), deshalb muss fuer diese Aufwendiger rekursiv gesucht
98     //werden.
99 
100     const SwLayoutFrm *pLayLeaf = this;
101     do
102     {
103         while ( (!pLayLeaf->IsSctFrm() || pLayLeaf == this ) &&
104                 pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrm() )
105             pLayLeaf = (SwLayoutFrm*)pLayLeaf->Lower();
106 
107         if( pLayLeaf->IsSctFrm() && pLayLeaf != this )
108         {
109             const SwCntntFrm *pCnt = pLayLeaf->ContainsCntnt();
110             if( pCnt )
111                 return pCnt;
112             if( pLayLeaf->GetNext() )
113             {
114                 if( pLayLeaf->GetNext()->IsLayoutFrm() )
115                 {
116                     pLayLeaf = (SwLayoutFrm*)pLayLeaf->GetNext();
117                     continue;
118                 }
119                 else
120                     return (SwCntntFrm*)pLayLeaf->GetNext();
121             }
122         }
123         else if ( pLayLeaf->Lower() )
124             return (SwCntntFrm*)pLayLeaf->Lower();
125 
126         pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
127         if( !IsAnLower( pLayLeaf) )
128             return 0;
129     } while( pLayLeaf );
130     return 0;
131 }
132 
133 /*************************************************************************
134 |*
135 |*  SwLayoutFrm::FirstCell
136 |*
137 |*  Beschreibung    ruft zunaechst ContainsAny auf, um in die innerste Zelle
138 |*                  hineinzukommen. Dort hangelt es sich wieder hoch zum
139 |*                  ersten SwCellFrm, seit es SectionFrms gibt, reicht kein
140 |*                  ContainsCntnt()->GetUpper() mehr...
141 |*  Ersterstellung      AMA 17. Mar. 99
142 |*  Letzte Aenderung    AMA 17. Mar. 99
143 |*
144 |*************************************************************************/
145 
FirstCell() const146 const SwCellFrm *SwLayoutFrm::FirstCell() const
147 {
148     const SwFrm* pCnt = ContainsAny();
149     while( pCnt && !pCnt->IsCellFrm() )
150         pCnt = pCnt->GetUpper();
151     return (const SwCellFrm*)pCnt;
152 }
153 
154 /*************************************************************************
155 |*
156 |*  SwLayoutFrm::ContainsAny
157 |*
158 |*  Beschreibung wie ContainsCntnt, nur dass nicht nur CntntFrms, sondern auch
159 |*          Bereiche und Tabellen zurueckgegeben werden.
160 |*  Ersterstellung      AMA 10. Mar. 99
161 |*  Letzte Aenderung    AMA 10. Mar. 99
162 |*
163 |*************************************************************************/
164 
165 // --> OD 2006-02-01 #130797#
166 // New parameter <_bInvestigateFtnForSections> controls investigation of
167 // content of footnotes for sections.
ContainsAny(const bool _bInvestigateFtnForSections) const168 const SwFrm *SwLayoutFrm::ContainsAny( const bool _bInvestigateFtnForSections ) const
169 {
170     //LayoutBlatt nach unten hin suchen und wenn dieses keinen Inhalt hat
171     //solange die weiteren Blatter abklappern bis Inhalt gefunden oder der
172     //this verlassen wird.
173     // Oder bis wir einen SectionFrm oder TabFrm gefunden haben
174 
175     const SwLayoutFrm *pLayLeaf = this;
176     // --> OD 2006-02-01 #130797#
177     const bool bNoFtn = IsSctFrm() && !_bInvestigateFtnForSections;
178     // <--
179     do
180     {
181         while ( ( (!pLayLeaf->IsSctFrm() && !pLayLeaf->IsTabFrm())
182                  || pLayLeaf == this ) &&
183                 pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrm() )
184             pLayLeaf = (SwLayoutFrm*)pLayLeaf->Lower();
185 
186         if( ( pLayLeaf->IsTabFrm() || pLayLeaf->IsSctFrm() )
187             && pLayLeaf != this )
188         {
189             // Wir liefern jetzt auch "geloeschte" SectionFrms zurueck,
190             // damit diese beim SaveCntnt und RestoreCntnt mitgepflegt werden.
191             return pLayLeaf;
192         }
193         else if ( pLayLeaf->Lower() )
194             return (SwCntntFrm*)pLayLeaf->Lower();
195 
196         pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
197         if( bNoFtn && pLayLeaf && pLayLeaf->IsInFtn() )
198         {
199             do
200             {
201                 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
202             } while( pLayLeaf && pLayLeaf->IsInFtn() );
203         }
204         if( !IsAnLower( pLayLeaf) )
205             return 0;
206     } while( pLayLeaf );
207     return 0;
208 }
209 
210 
211 /*************************************************************************
212 |*
213 |*  SwFrm::GetLower()
214 |*
215 |*  Ersterstellung      MA 27. Jul. 92
216 |*  Letzte Aenderung    MA 09. Oct. 97
217 |*
218 |*************************************************************************/
GetLower() const219 const SwFrm* SwFrm::GetLower() const
220 {
221     return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0;
222 }
223 
GetLower()224 SwFrm* SwFrm::GetLower()
225 {
226     return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0;
227 }
228 
229 /*************************************************************************
230 |*
231 |*  SwLayoutFrm::IsAnLower()
232 |*
233 |*  Ersterstellung      MA 18. Mar. 93
234 |*  Letzte Aenderung    MA 18. Mar. 93
235 |*
236 |*************************************************************************/
IsAnLower(const SwFrm * pAssumed) const237 sal_Bool SwLayoutFrm::IsAnLower( const SwFrm *pAssumed ) const
238 {
239     const SwFrm *pUp = pAssumed;
240     while ( pUp )
241     {
242         if ( pUp == this )
243             return sal_True;
244         if ( pUp->IsFlyFrm() )
245             pUp = ((SwFlyFrm*)pUp)->GetAnchorFrm();
246         else
247             pUp = pUp->GetUpper();
248     }
249     return sal_False;
250 }
251 
252 /** method to check relative position of layout frame to
253     a given layout frame.
254 
255     OD 08.11.2002 - refactoring of pseudo-local method <lcl_Apres(..)> in
256     <txtftn.cxx> for #104840#.
257 
258     @param _aCheckRefLayFrm
259     constant reference of an instance of class <SwLayoutFrm> which
260     is used as the reference for the relative position check.
261 
262     @author OD
263 
264     @return true, if <this> is positioned before the layout frame <p>
265 */
IsBefore(const SwLayoutFrm * _pCheckRefLayFrm) const266 bool SwLayoutFrm::IsBefore( const SwLayoutFrm* _pCheckRefLayFrm ) const
267 {
268     ASSERT( !IsRootFrm() , "<IsBefore> called at a <SwRootFrm>.");
269     ASSERT( !_pCheckRefLayFrm->IsRootFrm() , "<IsBefore> called with a <SwRootFrm>.");
270 
271     bool bReturn;
272 
273     // check, if on different pages
274     const SwPageFrm *pMyPage = FindPageFrm();
275     const SwPageFrm *pCheckRefPage = _pCheckRefLayFrm->FindPageFrm();
276     if( pMyPage != pCheckRefPage )
277     {
278         // being on different page as check reference
279         bReturn = pMyPage->GetPhyPageNum() < pCheckRefPage->GetPhyPageNum();
280     }
281     else
282     {
283         // being on same page as check reference
284         // --> search my supreme parent <pUp>, which doesn't contain check reference.
285         const SwLayoutFrm* pUp = this;
286         while ( pUp->GetUpper() &&
287                 !pUp->GetUpper()->IsAnLower( _pCheckRefLayFrm )
288               )
289             pUp = pUp->GetUpper();
290         if( !pUp->GetUpper() )
291         {
292             // can occur, if <this> is a fly frm
293             bReturn = false;
294         }
295         else
296         {
297             // travel through the next's of <pUp> and check if one of these
298             // contain the check reference.
299             SwLayoutFrm* pUpNext = (SwLayoutFrm*)pUp->GetNext();
300             while ( pUpNext &&
301                     !pUpNext->IsAnLower( _pCheckRefLayFrm ) )
302             {
303                 pUpNext = (SwLayoutFrm*)pUpNext->GetNext();
304             }
305             bReturn = pUpNext != 0;
306         }
307     }
308 
309     return bReturn;
310 }
311 
312 //
313 // Local helper functions for GetNextLayoutLeaf
314 //
315 
lcl_FindLayoutFrame(const SwFrm * pFrm,bool bNext)316 const SwFrm* lcl_FindLayoutFrame( const SwFrm* pFrm, bool bNext )
317 {
318     const SwFrm* pRet = 0;
319     if ( pFrm->IsFlyFrm() )
320         pRet = bNext ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink();
321     else
322         pRet = bNext ? pFrm->GetNext() : pFrm->GetPrev();
323 
324     return pRet;
325 }
326 
lcl_GetLower(const SwFrm * pFrm,bool bFwd)327 const SwFrm* lcl_GetLower( const SwFrm* pFrm, bool bFwd )
328 {
329     if ( !pFrm->IsLayoutFrm() )
330         return 0;
331 
332     return bFwd ?
333            static_cast<const SwLayoutFrm*>(pFrm)->Lower() :
334            static_cast<const SwLayoutFrm*>(pFrm)->GetLastLower();
335 }
336 
337 /*************************************************************************
338 |*
339 |*  SwFrm::ImplGetNextLayoutLeaf
340 |*
341 |* Finds the next layout leaf. This is a layout frame, which does not
342  * have a lower which is a LayoutFrame. That means, pLower can be 0 or a
343  * content frame.
344  *
345  * However, pLower may be a TabFrm
346  *
347 |*************************************************************************/
348 
ImplGetNextLayoutLeaf(bool bFwd) const349 const SwLayoutFrm *SwFrm::ImplGetNextLayoutLeaf( bool bFwd ) const
350 {
351     const SwFrm       *pFrm = this;
352     const SwLayoutFrm *pLayoutFrm = 0;
353     const SwFrm       *p = 0;
354     bool bGoingUp = !bFwd;          // false for forward, true for backward
355     do {
356 
357          bool bGoingFwdOrBwd = false, bGoingDown = false;
358 
359          bGoingDown = ( !bGoingUp && ( 0 != (p = lcl_GetLower( pFrm, bFwd ) ) ) );
360          if ( !bGoingDown )
361          {
362              // I cannot go down, because either I'm currently going up or
363              // because the is no lower.
364              // I'll try to go forward:
365              bGoingFwdOrBwd = (0 != (p = lcl_FindLayoutFrame( pFrm, bFwd ) ) );
366              if ( !bGoingFwdOrBwd )
367              {
368                  // I cannot go forward, because there is no next frame.
369                  // I'll try to go up:
370                  bGoingUp = (0 != (p = pFrm->GetUpper() ) );
371                  if ( !bGoingUp )
372                  {
373                     // I cannot go up, because there is no upper frame.
374                     return 0;
375                  }
376              }
377          }
378 
379         // If I could not go down or forward, I'll have to go up
380         bGoingUp = !bGoingFwdOrBwd && !bGoingDown;
381 
382         pFrm = p;
383         p = lcl_GetLower( pFrm, true );
384 
385     } while( ( p && !p->IsFlowFrm() ) ||
386              pFrm == this ||
387              0 == ( pLayoutFrm = pFrm->IsLayoutFrm() ? (SwLayoutFrm*)pFrm : 0 ) ||
388              pLayoutFrm->IsAnLower( this ) );
389 
390     return pLayoutFrm;
391 }
392 
393 
394 
395 /*************************************************************************
396 |*
397 |*    SwFrm::ImplGetNextCntntFrm( bool )
398 |*
399 |*      Rueckwaertswandern im Baum: Den untergeordneten Frm greifen,
400 |*      wenn es einen gibt und nicht gerade zuvor um eine Ebene
401 |*      aufgestiegen wurde (das wuerde zu einem endlosen Auf und Ab
402 |*      fuehren!). Damit wird sichergestellt, dass beim
403 |*      Rueckwaertswandern alle Unterbaeume durchsucht werden. Wenn
404 |*      abgestiegen wurde, wird zuerst an das Ende der Kette gegangen,
405 |*      weil im weiteren ja vom letzten Frm innerhalb eines anderen
406 |*      Frms rueckwaerts gegangen wird.
407 |*      Vorwaetzwander funktioniert analog.
408 |*
409 |*    Ersterstellung    ??
410 |*    Letzte Aenderung  MA 30. Oct. 97
411 |*
412 |*************************************************************************/
413 
414 // Achtung: Fixes in ImplGetNextCntntFrm() muessen moeglicherweise auch in
415 // die weiter oben stehende Methode lcl_NextFrm(..) eingepflegt werden
ImplGetNextCntntFrm(bool bFwd) const416 const SwCntntFrm* SwCntntFrm::ImplGetNextCntntFrm( bool bFwd ) const
417 {
418     const SwFrm *pFrm = this;
419     // #100926#
420     SwCntntFrm *pCntntFrm = 0;
421     sal_Bool bGoingUp = sal_False;
422     do {
423         const SwFrm *p = 0;
424         sal_Bool bGoingFwdOrBwd = sal_False, bGoingDown = sal_False;
425 
426         bGoingDown = ( !bGoingUp && ( 0 != ( p = lcl_GetLower( pFrm, true ) ) ) );
427         if ( !bGoingDown )
428         {
429             bGoingFwdOrBwd = ( 0 != ( p = lcl_FindLayoutFrame( pFrm, bFwd ) ) );
430             if ( !bGoingFwdOrBwd )
431             {
432                 bGoingUp = ( 0 != ( p = pFrm->GetUpper() ) );
433                 if ( !bGoingUp )
434                 {
435                     return 0;
436                 }
437             }
438         }
439 
440         bGoingUp = !(bGoingFwdOrBwd || bGoingDown);
441 
442         if ( !bFwd )
443         {
444             if( bGoingDown && p )
445                 while ( p->GetNext() )
446                     p = p->GetNext();
447         }
448 
449         pFrm = p;
450     } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
451 
452     return pCntntFrm;
453 }
454 
455 
456 
457 
458 /*************************************************************************
459 |*
460 |*  SwFrm::FindRootFrm(), FindTabFrm(), FindFtnFrm(), FindFlyFrm(),
461 |*         FindPageFrm(), FindColFrm()
462 |*
463 |*  Ersterstellung      ??
464 |*  Letzte Aenderung    MA 05. Sep. 93
465 |*
466 |*************************************************************************/
FindPageFrm()467 SwPageFrm* SwFrm::FindPageFrm()
468 {
469     SwFrm *pRet = this;
470     while ( pRet && !pRet->IsPageFrm() )
471     {
472         if ( pRet->GetUpper() )
473             pRet = pRet->GetUpper();
474         else if ( pRet->IsFlyFrm() )
475         {
476             // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
477             if ( static_cast<SwFlyFrm*>(pRet)->GetPageFrm() )
478                 pRet = static_cast<SwFlyFrm*>(pRet)->GetPageFrm();
479             else
480                 pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm();
481         }
482         else
483             return 0;
484     }
485     return (SwPageFrm*)pRet;
486 }
487 
FindFtnBossFrm(sal_Bool bFootnotes)488 SwFtnBossFrm* SwFrm::FindFtnBossFrm( sal_Bool bFootnotes )
489 {
490     SwFrm *pRet = this;
491     // Innerhalb einer Tabelle gibt es keine Fussnotenbosse, auch spaltige
492     // Bereiche enthalten dort keine Fussnotentexte
493     if( pRet->IsInTab() )
494         pRet = pRet->FindTabFrm();
495     while ( pRet && !pRet->IsFtnBossFrm() )
496     {
497         if ( pRet->GetUpper() )
498             pRet = pRet->GetUpper();
499         else if ( pRet->IsFlyFrm() )
500         {
501             // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
502             if ( static_cast<SwFlyFrm*>(pRet)->GetPageFrm() )
503                 pRet = static_cast<SwFlyFrm*>(pRet)->GetPageFrm();
504             else
505                 pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm();
506         }
507         else
508             return 0;
509     }
510     if( bFootnotes && pRet && pRet->IsColumnFrm() &&
511         !pRet->GetNext() && !pRet->GetPrev() )
512     {
513         SwSectionFrm* pSct = pRet->FindSctFrm();
514         ASSERT( pSct, "FindFtnBossFrm: Single column outside section?" );
515         if( !pSct->IsFtnAtEnd() )
516             return pSct->FindFtnBossFrm( sal_True );
517     }
518     return (SwFtnBossFrm*)pRet;
519 }
520 
ImplFindTabFrm()521 SwTabFrm* SwFrm::ImplFindTabFrm()
522 {
523     SwFrm *pRet = this;
524     while ( !pRet->IsTabFrm() )
525     {
526         pRet = pRet->GetUpper();
527         if ( !pRet )
528             return 0;
529     }
530     return (SwTabFrm*)pRet;
531 }
532 
ImplFindSctFrm()533 SwSectionFrm* SwFrm::ImplFindSctFrm()
534 {
535     SwFrm *pRet = this;
536     while ( !pRet->IsSctFrm() )
537     {
538         pRet = pRet->GetUpper();
539         if ( !pRet )
540             return 0;
541     }
542     return (SwSectionFrm*)pRet;
543 }
544 
ImplFindFtnFrm()545 SwFtnFrm *SwFrm::ImplFindFtnFrm()
546 {
547     SwFrm *pRet = this;
548     while ( !pRet->IsFtnFrm() )
549     {
550         pRet = pRet->GetUpper();
551         if ( !pRet )
552             return 0;
553     }
554     return (SwFtnFrm*)pRet;
555 }
556 
ImplFindFlyFrm()557 SwFlyFrm *SwFrm::ImplFindFlyFrm()
558 {
559     const SwFrm *pRet = this;
560     do
561     {
562         if ( pRet->IsFlyFrm() )
563             return (SwFlyFrm*)pRet;
564         else
565             pRet = pRet->GetUpper();
566     } while ( pRet );
567     return 0;
568 }
569 
FindColFrm()570 SwFrm *SwFrm::FindColFrm()
571 {
572     SwFrm *pFrm = this;
573     do
574     {   pFrm = pFrm->GetUpper();
575     } while ( pFrm && !pFrm->IsColumnFrm() );
576     return pFrm;
577 }
578 
FindFooterOrHeader()579 SwFrm* SwFrm::FindFooterOrHeader()
580 {
581     SwFrm* pRet = this;
582     do
583     {   if ( pRet->GetType() & 0x0018 ) //Header und Footer
584             return pRet;
585         else if ( pRet->GetUpper() )
586             pRet = pRet->GetUpper();
587         else if ( pRet->IsFlyFrm() )
588             pRet = ((SwFlyFrm*)pRet)->AnchorFrm();
589         else
590             return 0;
591     } while ( pRet );
592     return pRet;
593 }
594 
FindFootNote() const595 const SwFtnFrm* SwFtnContFrm::FindFootNote() const
596 {
597     const SwFtnFrm* pRet = (SwFtnFrm*)Lower();
598     if( pRet && !pRet->GetAttr()->GetFtn().IsEndNote() )
599         return pRet;
600     return NULL;
601 }
602 
GetPageAtPos(const Point & rPt,const Size * pSize,bool bExtend) const603 const SwPageFrm* SwRootFrm::GetPageAtPos( const Point& rPt, const Size* pSize, bool bExtend ) const
604 {
605     const SwPageFrm* pRet = 0;
606 
607     SwRect aRect;
608     if ( pSize )
609     {
610         aRect.Pos()  = rPt;
611         aRect.SSize() = *pSize;
612     }
613 
614     const SwFrm* pPage = Lower();
615 
616     if ( !bExtend )
617     {
618         if( !Frm().IsInside( rPt ) )
619             return 0;
620 
621         // skip pages above point:
622         while( pPage && rPt.Y() > pPage->Frm().Bottom() )
623             pPage = pPage->GetNext();
624     }
625 
626     ASSERT( GetPageNum() <= maPageRects.size(), "number of pages differes from page rect array size" )
627     sal_uInt16 nPageIdx = 0;
628 
629     while ( pPage && !pRet )
630     {
631         const SwRect& rBoundRect = bExtend ? maPageRects[ nPageIdx++ ] : pPage->Frm();
632 
633         if ( (!pSize && rBoundRect.IsInside(rPt)) ||
634               (pSize && rBoundRect.IsOver(aRect)) )
635         {
636             pRet = static_cast<const SwPageFrm*>(pPage);
637         }
638 
639         pPage = pPage->GetNext();
640     }
641 
642     return pRet;
643 }
644 
645 /*************************************************************************
646 |*
647 |*  SwFrmFrm::GetAttrSet()
648 |*
649 |*  Ersterstellung      MA 02. Aug. 93
650 |*  Letzte Aenderung    MA 02. Aug. 93
651 |*
652 |*************************************************************************/
GetAttrSet() const653 const SwAttrSet* SwFrm::GetAttrSet() const
654 {
655     if ( IsCntntFrm() )
656         return &((const SwCntntFrm*)this)->GetNode()->GetSwAttrSet();
657     else
658         return &((const SwLayoutFrm*)this)->GetFmt()->GetAttrSet();
659 }
660 
661 /*************************************************************************
662 |*
663 |*  SwFrm::_FindNext(), _FindPrev(), InvalidateNextPos()
664 |*         _FindNextCnt() geht in Tabellen und Bereiche hineinund liefert
665 |*         nur SwCntntFrms.
666 |*
667 |*  Beschreibung        Invalidiert die Position des Naechsten Frames.
668 |*      Dies ist der direkte Nachfolger, oder bei CntntFrm's der naechste
669 |*      CntntFrm der im gleichen Fluss liegt wie ich:
670 |*      - Body,
671 |*      - Fussnoten,
672 |*      - Bei Kopf-/Fussbereichen ist die Benachrichtigung nur innerhalb des
673 |*        Bereiches weiterzuleiten.
674 |*      - dito fuer Flys.
675 |*      - Cntnts in Tabs halten sich ausschliesslich innerhalb ihrer Zelle
676 |*        auf.
677 |*      - Tabellen verhalten sich prinzipiell analog zu den Cntnts
678 |*      - Bereiche ebenfalls
679 |*  Ersterstellung      AK 14-Feb-1991
680 |*  Letzte Aenderung    AMA 10. Mar. 99
681 |*
682 |*************************************************************************/
683 
684 // Diese Hilfsfunktion ist ein Aequivalent zur ImplGetNextCntntFrm()-Methode,
685 // sie liefert allerdings neben ContentFrames auch TabFrms und SectionFrms.
lcl_NextFrm(SwFrm * pFrm)686 SwFrm* lcl_NextFrm( SwFrm* pFrm )
687 {
688     SwFrm *pRet = 0;
689     sal_Bool bGoingUp = sal_False;
690     do {
691         SwFrm *p = 0;
692 
693         sal_Bool bGoingFwd = sal_False;
694         sal_Bool bGoingDown = (!bGoingUp && ( 0 != (p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0)));
695 
696         if( !bGoingDown )
697         {
698             bGoingFwd = (0 != (p = ( pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->GetNextLink() : pFrm->GetNext())));
699             if ( !bGoingFwd )
700             {
701                 bGoingUp = (0 != (p = pFrm->GetUpper()));
702                 if ( !bGoingUp )
703                 {
704                     return 0;
705                 }
706             }
707         }
708         bGoingUp = !(bGoingFwd || bGoingDown);
709         pFrm = p;
710     } while ( 0 == (pRet = ( ( pFrm->IsCntntFrm() || ( !bGoingUp &&
711             ( pFrm->IsTabFrm() || pFrm->IsSctFrm() ) ) )? pFrm : 0 ) ) );
712     return pRet;
713 }
714 
_FindNext()715 SwFrm *SwFrm::_FindNext()
716 {
717     sal_Bool bIgnoreTab = sal_False;
718     SwFrm *pThis = this;
719 
720     if ( IsTabFrm() )
721     {
722         //Der letzte Cntnt der Tabelle wird
723         //gegriffen und dessen Nachfolger geliefert. Um die Spezialbeh.
724         //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt.
725         if ( ((SwTabFrm*)this)->GetFollow() )
726             return ((SwTabFrm*)this)->GetFollow();
727 
728         pThis = ((SwTabFrm*)this)->FindLastCntnt();
729         if ( !pThis )
730             pThis = this;
731         bIgnoreTab = sal_True;
732     }
733     else if ( IsSctFrm() )
734     {
735         //Der letzte Cntnt des Bereichs wird gegriffen und dessen Nachfolger
736         // geliefert.
737         if ( ((SwSectionFrm*)this)->GetFollow() )
738             return ((SwSectionFrm*)this)->GetFollow();
739 
740         pThis = ((SwSectionFrm*)this)->FindLastCntnt();
741         if ( !pThis )
742             pThis = this;
743     }
744     else if ( IsCntntFrm() )
745     {
746         if( ((SwCntntFrm*)this)->GetFollow() )
747             return ((SwCntntFrm*)this)->GetFollow();
748     }
749     else if ( IsRowFrm() )
750     {
751         SwFrm* pMyUpper = GetUpper();
752         if ( pMyUpper->IsTabFrm() && ((SwTabFrm*)pMyUpper)->GetFollow() )
753             return ((SwTabFrm*)pMyUpper)->GetFollow()->GetLower();
754         else return NULL;
755     }
756     else
757         return NULL;
758 
759     SwFrm* pRet = NULL;
760     const sal_Bool bFtn  = pThis->IsInFtn();
761     if ( !bIgnoreTab && pThis->IsInTab() )
762     {
763         SwLayoutFrm *pUp = pThis->GetUpper();
764         while ( !pUp->IsCellFrm() )
765             pUp = pUp->GetUpper();
766         ASSERT( pUp, "Cntnt in Tabelle aber nicht in Zelle." );
767         SwFrm* pNxt = ((SwCellFrm*)pUp)->GetFollowCell();
768         if ( pNxt )
769             pNxt = ((SwCellFrm*)pNxt)->ContainsCntnt();
770         if ( !pNxt )
771         {
772             pNxt = lcl_NextFrm( pThis );
773             if ( pUp->IsAnLower( pNxt ) )
774                 pRet = pNxt;
775         }
776         else
777             pRet = pNxt;
778     }
779     else
780     {
781         const sal_Bool bBody = pThis->IsInDocBody();
782         SwFrm *pNxtCnt = lcl_NextFrm( pThis );
783         if ( pNxtCnt )
784         {
785             if ( bBody || bFtn )
786             {
787                 while ( pNxtCnt )
788                 {
789                     // OD 02.04.2003 #108446# - check for endnote, only if found
790                     // next content isn't contained in a section, that collect its
791                     // endnotes at its end.
792                     bool bEndn = IsInSct() && !IsSctFrm() &&
793                                  ( !pNxtCnt->IsInSct() ||
794                                    !pNxtCnt->FindSctFrm()->IsEndnAtEnd()
795                                  );
796                     if ( ( bBody && pNxtCnt->IsInDocBody() ) ||
797                          ( pNxtCnt->IsInFtn() &&
798                            ( bFtn ||
799                              ( bEndn && pNxtCnt->FindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
800                            )
801                          )
802                        )
803                     {
804                         pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
805                                                     : (SwFrm*)pNxtCnt;
806                         break;
807                     }
808                     pNxtCnt = lcl_NextFrm( pNxtCnt );
809                 }
810             }
811             else if ( pThis->IsInFly() )
812             {
813                 pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
814                                             : (SwFrm*)pNxtCnt;
815             }
816             else    //Fuss-/oder Kopfbereich
817             {
818                 const SwFrm *pUp = pThis->GetUpper();
819                 const SwFrm *pCntUp = pNxtCnt->GetUpper();
820                 while ( pUp && pUp->GetUpper() &&
821                         !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
822                     pUp = pUp->GetUpper();
823                 while ( pCntUp && pCntUp->GetUpper() &&
824                         !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() )
825                     pCntUp = pCntUp->GetUpper();
826                 if ( pCntUp == pUp )
827                 {
828                     pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
829                                                 : (SwFrm*)pNxtCnt;
830                 }
831             }
832         }
833     }
834     if( pRet && pRet->IsInSct() )
835     {
836         SwSectionFrm* pSct = pRet->FindSctFrm();
837         //Fussnoten in spaltigen Rahmen duerfen nicht den Bereich
838         //liefern, der die Fussnoten umfasst
839         if( !pSct->IsAnLower( this ) &&
840             (!bFtn || pSct->IsInFtn() ) )
841             return pSct;
842     }
843     return pRet;
844 }
845 
846 // --> OD 2005-12-01 #i27138# - add parameter <_bInSameFtn>
_FindNextCnt(const bool _bInSameFtn)847 SwCntntFrm *SwFrm::_FindNextCnt( const bool _bInSameFtn )
848 {
849     SwFrm *pThis = this;
850 
851     if ( IsTabFrm() )
852     {
853         if ( ((SwTabFrm*)this)->GetFollow() )
854         {
855             pThis = ((SwTabFrm*)this)->GetFollow()->ContainsCntnt();
856             if( pThis )
857                 return (SwCntntFrm*)pThis;
858         }
859         pThis = ((SwTabFrm*)this)->FindLastCntnt();
860         if ( !pThis )
861             return 0;
862     }
863     else if ( IsSctFrm() )
864     {
865         if ( ((SwSectionFrm*)this)->GetFollow() )
866         {
867             pThis = ((SwSectionFrm*)this)->GetFollow()->ContainsCntnt();
868             if( pThis )
869                 return (SwCntntFrm*)pThis;
870         }
871         pThis = ((SwSectionFrm*)this)->FindLastCntnt();
872         if ( !pThis )
873             return 0;
874     }
875     else if ( IsCntntFrm() && ((SwCntntFrm*)this)->GetFollow() )
876         return ((SwCntntFrm*)this)->GetFollow();
877 
878     if ( pThis->IsCntntFrm() )
879     {
880         const sal_Bool bBody = pThis->IsInDocBody();
881         const sal_Bool bFtn  = pThis->IsInFtn();
882         SwCntntFrm *pNxtCnt = ((SwCntntFrm*)pThis)->GetNextCntntFrm();
883         if ( pNxtCnt )
884         {
885             // --> OD 2005-12-01 #i27138#
886             if ( bBody || ( bFtn && !_bInSameFtn ) )
887             // <--
888             {
889                 // handling for environments 'footnotes' and 'document body frames':
890                 while ( pNxtCnt )
891                 {
892                     if ( (bBody && pNxtCnt->IsInDocBody()) ||
893                          (bFtn  && pNxtCnt->IsInFtn()) )
894                         return pNxtCnt;
895                     pNxtCnt = pNxtCnt->GetNextCntntFrm();
896                 }
897             }
898             // --> OD 2005-12-01 #i27138#
899             else if ( bFtn && _bInSameFtn )
900             {
901                 // handling for environments 'each footnote':
902                 // Assure that found next content frame belongs to the same footnotes
903                 const SwFtnFrm* pFtnFrmOfNext( pNxtCnt->FindFtnFrm() );
904                 const SwFtnFrm* pFtnFrmOfCurr( pThis->FindFtnFrm() );
905                 ASSERT( pFtnFrmOfCurr,
906                         "<SwFrm::_FindNextCnt() - unknown layout situation: current frame has to have an upper footnote frame." );
907                 if ( pFtnFrmOfNext == pFtnFrmOfCurr )
908                 {
909                     return pNxtCnt;
910                 }
911                 else if ( pFtnFrmOfCurr->GetFollow() )
912                 {
913                     // next content frame has to be the first content frame
914                     // in the follow footnote, which contains a content frame.
915                     SwFtnFrm* pFollowFtnFrmOfCurr(
916                                         const_cast<SwFtnFrm*>(pFtnFrmOfCurr) );
917                     pNxtCnt = 0L;
918                     do {
919                         pFollowFtnFrmOfCurr = pFollowFtnFrmOfCurr->GetFollow();
920                         pNxtCnt = pFollowFtnFrmOfCurr->ContainsCntnt();
921                     } while ( !pNxtCnt && pFollowFtnFrmOfCurr->GetFollow() );
922                     return pNxtCnt;
923                 }
924                 else
925                 {
926                     // current content frame is the last content frame in the
927                     // footnote - no next content frame exists.
928                     return 0L;
929                 }
930             }
931             // <--
932             else if ( pThis->IsInFly() )
933                 // handling for environments 'unlinked fly frame' and
934                 // 'group of linked fly frames':
935                 return pNxtCnt;
936             else
937             {
938                 // handling for environments 'page header' and 'page footer':
939                 const SwFrm *pUp = pThis->GetUpper();
940                 const SwFrm *pCntUp = pNxtCnt->GetUpper();
941                 while ( pUp && pUp->GetUpper() &&
942                         !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
943                     pUp = pUp->GetUpper();
944                 while ( pCntUp && pCntUp->GetUpper() &&
945                         !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() )
946                     pCntUp = pCntUp->GetUpper();
947                 if ( pCntUp == pUp )
948                     return pNxtCnt;
949             }
950         }
951     }
952     return 0;
953 }
954 
955 /** method to determine previous content frame in the same environment
956     for a flow frame (content frame, table frame, section frame)
957 
958     OD 2005-11-30 #i27138#
959 
960     @author OD
961 */
_FindPrevCnt(const bool _bInSameFtn)962 SwCntntFrm* SwFrm::_FindPrevCnt( const bool _bInSameFtn )
963 {
964     if ( !IsFlowFrm() )
965     {
966         // nothing to do, if current frame isn't a flow frame.
967         return 0L;
968     }
969 
970     SwCntntFrm* pPrevCntntFrm( 0L );
971 
972     // Because method <SwCntntFrm::GetPrevCntntFrm()> is used to travel
973     // through the layout, a content frame, at which the travel starts, is needed.
974     SwCntntFrm* pCurrCntntFrm = dynamic_cast<SwCntntFrm*>(this);
975 
976     // perform shortcut, if current frame is a follow, and
977     // determine <pCurrCntntFrm>, if current frame is a table or section frame
978     if ( pCurrCntntFrm && pCurrCntntFrm->IsFollow() )
979     {
980         // previous content frame is its master content frame
981         pPrevCntntFrm = pCurrCntntFrm->FindMaster();
982     }
983     else if ( IsTabFrm() )
984     {
985         SwTabFrm* pTabFrm( static_cast<SwTabFrm*>(this) );
986         if ( pTabFrm->IsFollow() )
987         {
988             // previous content frame is the last content of its master table frame
989             pPrevCntntFrm = pTabFrm->FindMaster()->FindLastCntnt();
990         }
991         else
992         {
993             // start content frame for the search is the first content frame of
994             // the table frame.
995             pCurrCntntFrm = pTabFrm->ContainsCntnt();
996         }
997     }
998     else if ( IsSctFrm() )
999     {
1000         SwSectionFrm* pSectFrm( static_cast<SwSectionFrm*>(this) );
1001         if ( pSectFrm->IsFollow() )
1002         {
1003             // previous content frame is the last content of its master section frame
1004             pPrevCntntFrm = pSectFrm->FindMaster()->FindLastCntnt();
1005         }
1006         else
1007         {
1008             // start content frame for the search is the first content frame of
1009             // the section frame.
1010             pCurrCntntFrm = pSectFrm->ContainsCntnt();
1011         }
1012     }
1013 
1014     // search for next content frame, depending on the environment, in which
1015     // the current frame is in.
1016     if ( !pPrevCntntFrm && pCurrCntntFrm )
1017     {
1018         pPrevCntntFrm = pCurrCntntFrm->GetPrevCntntFrm();
1019         if ( pPrevCntntFrm )
1020         {
1021             if ( pCurrCntntFrm->IsInFly() )
1022             {
1023                 // handling for environments 'unlinked fly frame' and
1024                 // 'group of linked fly frames':
1025                 // Nothing to do, <pPrevCntntFrm> is the one
1026             }
1027             else
1028             {
1029                 const bool bInDocBody = pCurrCntntFrm->IsInDocBody();
1030                 const bool bInFtn  = pCurrCntntFrm->IsInFtn();
1031                 if ( bInDocBody || ( bInFtn && !_bInSameFtn ) )
1032                 {
1033                     // handling for environments 'footnotes' and 'document body frames':
1034                     // Assure that found previous frame is also in one of these
1035                     // environments. Otherwise, travel further
1036                     while ( pPrevCntntFrm )
1037                     {
1038                         if ( ( bInDocBody && pPrevCntntFrm->IsInDocBody() ) ||
1039                              ( bInFtn && pPrevCntntFrm->IsInFtn() ) )
1040                         {
1041                             break;
1042                         }
1043                         pPrevCntntFrm = pPrevCntntFrm->GetPrevCntntFrm();
1044                     }
1045                 }
1046                 else if ( bInFtn && _bInSameFtn )
1047                 {
1048                     // handling for environments 'each footnote':
1049                     // Assure that found next content frame belongs to the same footnotes
1050                     const SwFtnFrm* pFtnFrmOfPrev( pPrevCntntFrm->FindFtnFrm() );
1051                     const SwFtnFrm* pFtnFrmOfCurr( pCurrCntntFrm->FindFtnFrm() );
1052                     if ( pFtnFrmOfPrev != pFtnFrmOfCurr )
1053                     {
1054                         if ( pFtnFrmOfCurr->GetMaster() )
1055                         {
1056                             SwFtnFrm* pMasterFtnFrmOfCurr(
1057                                         const_cast<SwFtnFrm*>(pFtnFrmOfCurr) );
1058                             pPrevCntntFrm = 0L;
1059                             // --> OD 2007-07-05 #146872#
1060                             // correct wrong loop-condition
1061                             do {
1062                                 pMasterFtnFrmOfCurr = pMasterFtnFrmOfCurr->GetMaster();
1063                                 pPrevCntntFrm = pMasterFtnFrmOfCurr->FindLastCntnt();
1064                             } while ( !pPrevCntntFrm &&
1065                                       pMasterFtnFrmOfCurr->GetMaster() );
1066                             // <--
1067                         }
1068                         else
1069                         {
1070                             // current content frame is the first content in the
1071                             // footnote - no previous content exists.
1072                             pPrevCntntFrm = 0L;;
1073                         }
1074                     }
1075                 }
1076                 else
1077                 {
1078                     // handling for environments 'page header' and 'page footer':
1079                     // Assure that found previous frame is also in the same
1080                     // page header respectively page footer as <pCurrCntntFrm>
1081                     // Note: At this point its clear, that <pCurrCntntFrm> has
1082                     //       to be inside a page header or page footer and that
1083                     //       neither <pCurrCntntFrm> nor <pPrevCntntFrm> are
1084                     //       inside a fly frame.
1085                     //       Thus, method <FindFooterOrHeader()> can be used.
1086                     ASSERT( pCurrCntntFrm->FindFooterOrHeader(),
1087                             "<SwFrm::_FindPrevCnt()> - unknown layout situation: current frame should be in page header or page footer" );
1088                     ASSERT( !pPrevCntntFrm->IsInFly(),
1089                             "<SwFrm::_FindPrevCnt()> - unknown layout situation: found previous frame should *not* be inside a fly frame." );
1090                     if ( pPrevCntntFrm->FindFooterOrHeader() !=
1091                                             pCurrCntntFrm->FindFooterOrHeader() )
1092                     {
1093                         pPrevCntntFrm = 0L;
1094                     }
1095                 }
1096             }
1097         }
1098     }
1099 
1100     return pPrevCntntFrm;
1101 }
1102 
_FindPrev()1103 SwFrm *SwFrm::_FindPrev()
1104 {
1105     sal_Bool bIgnoreTab = sal_False;
1106     SwFrm *pThis = this;
1107 
1108     if ( IsTabFrm() )
1109     {
1110         //Der erste Cntnt der Tabelle wird
1111         //gegriffen und dessen Vorgaenger geliefert. Um die Spezialbeh.
1112         //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt.
1113         if ( ((SwTabFrm*)this)->IsFollow() )
1114             return ((SwTabFrm*)this)->FindMaster();
1115         else
1116             pThis = ((SwTabFrm*)this)->ContainsCntnt();
1117         bIgnoreTab = sal_True;
1118     }
1119 
1120     if ( pThis && pThis->IsCntntFrm() )
1121     {
1122         SwCntntFrm *pPrvCnt = ((SwCntntFrm*)pThis)->GetPrevCntntFrm();
1123         if( !pPrvCnt )
1124             return 0;
1125         if ( !bIgnoreTab && pThis->IsInTab() )
1126         {
1127             SwLayoutFrm *pUp = pThis->GetUpper();
1128             while ( !pUp->IsCellFrm() )
1129                 pUp = pUp->GetUpper();
1130             ASSERT( pUp, "Cntnt in Tabelle aber nicht in Zelle." );
1131             if ( pUp->IsAnLower( pPrvCnt ) )
1132                 return pPrvCnt;
1133         }
1134         else
1135         {
1136             SwFrm* pRet;
1137             const sal_Bool bBody = pThis->IsInDocBody();
1138             const sal_Bool bFtn  = bBody ? sal_False : pThis->IsInFtn();
1139             if ( bBody || bFtn )
1140             {
1141                 while ( pPrvCnt )
1142                 {
1143                     if ( (bBody && pPrvCnt->IsInDocBody()) ||
1144                             (bFtn   && pPrvCnt->IsInFtn()) )
1145                     {
1146                         pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
1147                                                   : (SwFrm*)pPrvCnt;
1148                         return pRet;
1149                     }
1150                     pPrvCnt = pPrvCnt->GetPrevCntntFrm();
1151                 }
1152             }
1153             else if ( pThis->IsInFly() )
1154             {
1155                 pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
1156                                             : (SwFrm*)pPrvCnt;
1157                 return pRet;
1158             }
1159             else    //Fuss-/oder Kopfbereich oder Fly
1160             {
1161                 const SwFrm *pUp = pThis->GetUpper();
1162                 const SwFrm *pCntUp = pPrvCnt->GetUpper();
1163                 while ( pUp && pUp->GetUpper() &&
1164                         !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
1165                     pUp = pUp->GetUpper();
1166                 while ( pCntUp && pCntUp->GetUpper() )
1167                     pCntUp = pCntUp->GetUpper();
1168                 if ( pCntUp == pUp )
1169                 {
1170                     pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
1171                                                 : (SwFrm*)pPrvCnt;
1172                     return pRet;
1173                 }
1174             }
1175         }
1176     }
1177     return 0;
1178 }
1179 
ImplInvalidateNextPos(sal_Bool bNoFtn)1180 void SwFrm::ImplInvalidateNextPos( sal_Bool bNoFtn )
1181 {
1182     SwFrm *pFrm;
1183     if ( 0 != (pFrm = _FindNext()) )
1184     {
1185         if( pFrm->IsSctFrm() )
1186         {
1187             while( pFrm && pFrm->IsSctFrm() )
1188             {
1189                 if( ((SwSectionFrm*)pFrm)->GetSection() )
1190                 {
1191                     SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny();
1192                     if( pTmp )
1193                         pTmp->InvalidatePos();
1194                     else if( !bNoFtn )
1195                         ((SwSectionFrm*)pFrm)->InvalidateFtnPos();
1196                     if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm )
1197                         pFrm->InvalidatePos();
1198                     return;
1199                 }
1200                 pFrm = pFrm->FindNext();
1201             }
1202             if( pFrm )
1203             {
1204                 if ( pFrm->IsSctFrm())
1205                 { // Damit der Inhalt eines Bereichs die Chance erhaelt,
1206                   // die Seite zu wechseln, muss er ebenfalls invalidiert werden.
1207                     SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny();
1208                     if( pTmp )
1209                         pTmp->InvalidatePos();
1210                     if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm )
1211                         pFrm->InvalidatePos();
1212                 }
1213                 else
1214                     pFrm->InvalidatePos();
1215             }
1216         }
1217         else
1218             pFrm->InvalidatePos();
1219     }
1220 }
1221 
1222 /** method to invalidate printing area of next frame
1223 
1224     OD 09.01.2004 #i11859#
1225 
1226     @author OD
1227 
1228     FME 2004-04-19 #i27145# Moved function from SwTxtFrm to SwFrm
1229 */
InvalidateNextPrtArea()1230 void SwFrm::InvalidateNextPrtArea()
1231 {
1232     // determine next frame
1233     SwFrm* pNextFrm = FindNext();
1234     // skip empty section frames and hidden text frames
1235     {
1236         while ( pNextFrm &&
1237                 ( ( pNextFrm->IsSctFrm() &&
1238                     !static_cast<SwSectionFrm*>(pNextFrm)->GetSection() ) ||
1239                   ( pNextFrm->IsTxtFrm() &&
1240                     static_cast<SwTxtFrm*>(pNextFrm)->IsHiddenNow() ) ) )
1241         {
1242             pNextFrm = pNextFrm->FindNext();
1243         }
1244     }
1245 
1246     // Invalidate printing area of found next frame
1247     if ( pNextFrm )
1248     {
1249         if ( pNextFrm->IsSctFrm() )
1250         {
1251             // Invalidate printing area of found section frame, if
1252             // (1) this text frame isn't in a section OR
1253             // (2) found section frame isn't a follow of the section frame this
1254             //     text frame is in.
1255             if ( !IsInSct() || FindSctFrm()->GetFollow() != pNextFrm )
1256             {
1257                 pNextFrm->InvalidatePrt();
1258             }
1259 
1260             // Invalidate printing area of first content in found section.
1261             SwFrm* pFstCntntOfSctFrm =
1262                     static_cast<SwSectionFrm*>(pNextFrm)->ContainsAny();
1263             if ( pFstCntntOfSctFrm )
1264             {
1265                 pFstCntntOfSctFrm->InvalidatePrt();
1266             }
1267         }
1268         else
1269         {
1270             pNextFrm->InvalidatePrt();
1271         }
1272     }
1273 }
1274 
1275 /*************************************************************************
1276 |*
1277 |*    lcl_IsInColSect()
1278 |*      liefert nur sal_True, wenn der Frame _direkt_ in einem spaltigen Bereich steht,
1279 |*      nicht etwa, wenn er in einer Tabelle steht, die in einem spaltigen Bereich ist.
1280 |*
1281 |*************************************************************************/
1282 
lcl_IsInColSct(const SwFrm * pUp)1283 sal_Bool lcl_IsInColSct( const SwFrm *pUp )
1284 {
1285     sal_Bool bRet = sal_False;
1286     while( pUp )
1287     {
1288         if( pUp->IsColumnFrm() )
1289             bRet = sal_True;
1290         else if( pUp->IsSctFrm() )
1291             return bRet;
1292         else if( pUp->IsTabFrm() )
1293             return sal_False;
1294         pUp = pUp->GetUpper();
1295     }
1296     return sal_False;
1297 }
1298 
1299 /*************************************************************************
1300 |*
1301 |*    SwFrm::IsMoveable();
1302 |*
1303 |*    Ersterstellung    MA 09. Mar. 93
1304 |*    Letzte Aenderung  MA 05. May. 95
1305 |*
1306 |*************************************************************************/
1307 /** determine, if frame is moveable in given environment
1308 
1309     OD 08.08.2003 #110978#
1310     method replaced 'old' method <sal_Bool IsMoveable() const>.
1311     Determines, if frame is moveable in given environment. if no environment
1312     is given (parameter _pLayoutFrm == 0L), the movability in the actual
1313     environment (<this->GetUpper()) is checked.
1314 
1315     @author OD
1316 */
1317 
IsMoveable(const SwLayoutFrm * _pLayoutFrm) const1318 bool SwFrm::IsMoveable( const SwLayoutFrm* _pLayoutFrm ) const
1319 {
1320     bool bRetVal = false;
1321 
1322     if ( !_pLayoutFrm )
1323     {
1324         _pLayoutFrm = GetUpper();
1325     }
1326 
1327     if ( _pLayoutFrm && IsFlowFrm() )
1328     {
1329         if ( _pLayoutFrm->IsInSct() && lcl_IsInColSct( _pLayoutFrm ) )
1330         {
1331             bRetVal = true;
1332         }
1333         else if ( _pLayoutFrm->IsInFly() ||
1334                   _pLayoutFrm->IsInDocBody() ||
1335                   _pLayoutFrm->IsInFtn() )
1336         {
1337             if ( _pLayoutFrm->IsInTab() && !IsTabFrm() &&
1338                  ( !IsCntntFrm() || !const_cast<SwFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) ) )
1339             {
1340                 bRetVal = false;
1341             }
1342             else
1343             {
1344                 if ( _pLayoutFrm->IsInFly() )
1345                 {
1346                     // if fly frame has a follow (next linked fly frame),
1347                     // frame is moveable.
1348                     if ( const_cast<SwLayoutFrm*>(_pLayoutFrm)->FindFlyFrm()->GetNextLink() )
1349                     {
1350                         bRetVal = true;
1351                     }
1352                     else
1353                     {
1354                         // if environment is columned, frame is moveable, if
1355                         // it isn't in last column.
1356                         // search for column frame
1357                         const SwFrm* pCol = _pLayoutFrm;
1358                         while ( pCol && !pCol->IsColumnFrm() )
1359                         {
1360                             pCol = pCol->GetUpper();
1361                         }
1362                         // frame is moveable, if found column frame isn't last one.
1363                         if ( pCol && pCol->GetNext() )
1364                         {
1365                             bRetVal = true;
1366                         }
1367                     }
1368                 }
1369                 else
1370                 {
1371                     bRetVal = true;
1372                 }
1373             }
1374         }
1375     }
1376 
1377     return bRetVal;
1378 }
1379 
1380 /*************************************************************************
1381 |*
1382 |*    SwFrm::SetInfFlags();
1383 |*
1384 |*    Ersterstellung    MA 05. Apr. 94
1385 |*    Letzte Aenderung  MA 05. Apr. 94
1386 |*
1387 |*************************************************************************/
SetInfFlags()1388 void SwFrm::SetInfFlags()
1389 {
1390     if ( !IsFlyFrm() && !GetUpper() ) //noch nicht gepastet, keine Informationen
1391         return;                       //lieferbar
1392 
1393     bInfInvalid = bInfBody = bInfTab = bInfFly = bInfFtn = bInfSct = sal_False;
1394 
1395     SwFrm *pFrm = this;
1396     if( IsFtnContFrm() )
1397         bInfFtn = sal_True;
1398     do
1399     {   // bInfBody wird nur am Seitenbody, nicht im ColumnBody gesetzt
1400         if ( pFrm->IsBodyFrm() && !bInfFtn && pFrm->GetUpper()
1401              && pFrm->GetUpper()->IsPageFrm() )
1402             bInfBody = sal_True;
1403         else if ( pFrm->IsTabFrm() || pFrm->IsCellFrm() )
1404         {
1405             bInfTab = sal_True;
1406         }
1407         else if ( pFrm->IsFlyFrm() )
1408             bInfFly = sal_True;
1409         else if ( pFrm->IsSctFrm() )
1410             bInfSct = sal_True;
1411         else if ( pFrm->IsFtnFrm() )
1412             bInfFtn = sal_True;
1413 
1414         pFrm = pFrm->GetUpper();
1415 
1416     } while ( pFrm && !pFrm->IsPageFrm() ); //Oberhalb der Seite kommt nix
1417 }
1418 
1419 /*-----------------22.8.2001 14:30------------------
1420  * SwFrm::SetDirFlags( sal_Bool )
1421  * actualizes the vertical or the righttoleft-flags.
1422  * If the property is derived, it's from the upper or (for fly frames) from
1423  * the anchor. Otherwise we've to call a virtual method to check the property.
1424  * --------------------------------------------------*/
1425 
SetDirFlags(sal_Bool bVert)1426 void SwFrm::SetDirFlags( sal_Bool bVert )
1427 {
1428     if( bVert )
1429     {
1430         // OD 2004-01-21 #114969# - if derived, valid vertical flag only if
1431         // vertical flag of upper/anchor is valid.
1432         if( bDerivedVert )
1433         {
1434             const SwFrm* pAsk = IsFlyFrm() ?
1435                           ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper();
1436 
1437             ASSERT( pAsk != this, "Autsch! Stack overflow is about to happen" )
1438 
1439             if( pAsk )
1440             {
1441                 bVertical = pAsk->IsVertical() ? 1 : 0;
1442                 bReverse  = pAsk->IsReverse()  ? 1 : 0;
1443 
1444                 bVertLR  = pAsk->IsVertLR() ? 1 : 0;
1445                 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
1446                 if ( !pAsk->bInvalidVert )
1447                     bInvalidVert = sal_False;
1448             }
1449         }
1450         else
1451             CheckDirection( bVert );
1452     }
1453     else
1454     {
1455         sal_Bool bInv = 0;
1456         if( !bDerivedR2L ) // CheckDirection is able to set bDerivedR2L!
1457             CheckDirection( bVert );
1458         if( bDerivedR2L )
1459         {
1460             const SwFrm* pAsk = IsFlyFrm() ?
1461                           ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper();
1462 
1463             ASSERT( pAsk != this, "Autsch! Stack overflow is about to happen" )
1464 
1465             if( pAsk )
1466                 bRightToLeft = pAsk->IsRightToLeft() ? 1 : 0;
1467             if( !pAsk || pAsk->bInvalidR2L )
1468                 bInv = bInvalidR2L;
1469         }
1470         bInvalidR2L = bInv;
1471     }
1472 }
1473 
GetNextCellLeaf(MakePageType)1474 SwLayoutFrm* SwFrm::GetNextCellLeaf( MakePageType )
1475 {
1476     SwFrm* pTmpFrm = this;
1477     while ( !pTmpFrm->IsCellFrm() )
1478         pTmpFrm = pTmpFrm->GetUpper();
1479 
1480     ASSERT( pTmpFrm, "SwFrm::GetNextCellLeaf() without cell" )
1481     return ((SwCellFrm*)pTmpFrm)->GetFollowCell();
1482 }
1483 
GetPrevCellLeaf(MakePageType)1484 SwLayoutFrm* SwFrm::GetPrevCellLeaf( MakePageType )
1485 {
1486     SwFrm* pTmpFrm = this;
1487     while ( !pTmpFrm->IsCellFrm() )
1488         pTmpFrm = pTmpFrm->GetUpper();
1489 
1490     ASSERT( pTmpFrm, "SwFrm::GetNextPreviousLeaf() without cell" )
1491     return ((SwCellFrm*)pTmpFrm)->GetPreviousCell();
1492 }
1493 
lcl_FindCorrespondingCellFrm(const SwRowFrm & rOrigRow,const SwCellFrm & rOrigCell,const SwRowFrm & rCorrRow,bool bInFollow)1494 SwCellFrm* lcl_FindCorrespondingCellFrm( const SwRowFrm& rOrigRow,
1495                                          const SwCellFrm& rOrigCell,
1496                                          const SwRowFrm& rCorrRow,
1497                                          bool bInFollow )
1498 {
1499     SwCellFrm* pRet = NULL;
1500     SwCellFrm* pCell = (SwCellFrm*)rOrigRow.Lower();
1501     SwCellFrm* pCorrCell = (SwCellFrm*)rCorrRow.Lower();
1502 
1503     while ( pCell != &rOrigCell && !pCell->IsAnLower( &rOrigCell ) )
1504     {
1505         pCell = (SwCellFrm*)pCell->GetNext();
1506         pCorrCell = (SwCellFrm*)pCorrCell->GetNext();
1507     }
1508 
1509     ASSERT( pCell && pCorrCell, "lcl_FindCorrespondingCellFrm does not work" )
1510 
1511     if ( pCell != &rOrigCell )
1512     {
1513         // rOrigCell must be a lower of pCell. We need to recurse into the rows:
1514         ASSERT( pCell->Lower() && pCell->Lower()->IsRowFrm(),
1515                 "lcl_FindCorrespondingCellFrm does not work" )
1516 
1517         SwRowFrm* pRow = (SwRowFrm*)pCell->Lower();
1518         while ( !pRow->IsAnLower( &rOrigCell ) )
1519             pRow = (SwRowFrm*)pRow->GetNext();
1520 
1521         SwRowFrm* pCorrRow = 0;
1522         if ( bInFollow )
1523             pCorrRow = pRow->GetFollowRow();
1524         else
1525         {
1526             SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pCorrCell->GetLastLower());
1527 
1528             if ( pTmpRow && pTmpRow->GetFollowRow() == pRow )
1529                 pCorrRow = pTmpRow;
1530         }
1531 
1532         if ( pCorrRow )
1533             pRet = lcl_FindCorrespondingCellFrm( *pRow, rOrigCell, *pCorrRow, bInFollow );
1534     }
1535     else
1536         pRet = pCorrCell;
1537 
1538     return pRet;
1539 }
1540 
1541 // VERSION OF GetFollowCell() that assumes that we always have a follow flow line:
GetFollowCell() const1542 SwCellFrm* SwCellFrm::GetFollowCell() const
1543 {
1544     SwCellFrm* pRet = NULL;
1545 
1546     // NEW TABLES
1547     // Covered cells do not have follow cells!
1548     const long nRowSpan = GetLayoutRowSpan();
1549     if ( nRowSpan < 1 )
1550         return NULL;
1551 
1552     // find most upper row frame
1553     const SwFrm* pRow = GetUpper();
1554     while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
1555         pRow = pRow->GetUpper();
1556 
1557     if ( !pRow )
1558         return NULL;
1559 
1560     const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( pRow->GetUpper() );
1561     if ( !pRow || !pTabFrm->GetFollow() || !pTabFrm->HasFollowFlowLine() )
1562         return NULL;
1563 
1564     const SwCellFrm* pThisCell = this;
1565 
1566     // Get last cell of the current table frame that belongs to the rowspan:
1567     if ( nRowSpan > 1 )
1568     {
1569         // optimization: Will end of row span be in last row or exceed row?
1570         long nMax = 0;
1571         while ( pRow->GetNext() && ++nMax < nRowSpan )
1572             pRow = pRow->GetNext();
1573 
1574         if ( !pRow->GetNext() )
1575         {
1576             pThisCell = &pThisCell->FindStartEndOfRowSpanCell( false, true );
1577             pRow = pThisCell->GetUpper();
1578         }
1579     }
1580 
1581     const SwRowFrm* pFollowRow = NULL;
1582     if ( !pRow->GetNext() &&
1583          NULL != ( pFollowRow = pRow->IsInSplitTableRow() ) &&
1584          ( !pFollowRow->IsRowSpanLine() || nRowSpan > 1 ) )
1585          pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *pThisCell, *pFollowRow, true );
1586 
1587     return pRet;
1588 }
1589 
1590 // VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL
GetPreviousCell() const1591 SwCellFrm* SwCellFrm::GetPreviousCell() const
1592 {
1593     SwCellFrm* pRet = NULL;
1594 
1595     // NEW TABLES
1596     // Covered cells do not have previous cells!
1597     if ( GetLayoutRowSpan() < 1 )
1598         return NULL;
1599 
1600     // find most upper row frame
1601     const SwFrm* pRow = GetUpper();
1602     while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
1603         pRow = pRow->GetUpper();
1604 
1605     ASSERT( pRow->GetUpper() && pRow->GetUpper()->IsTabFrm(), "GetPreviousCell without Table" );
1606 
1607     SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
1608 
1609     if ( pTab->IsFollow() )
1610     {
1611         const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow();
1612         const bool bIsInFirstLine = ( pTmp == pRow );
1613 
1614         if ( bIsInFirstLine )
1615         {
1616             SwTabFrm *pMaster = (SwTabFrm*)pTab->FindMaster();
1617             if ( pMaster && pMaster->HasFollowFlowLine() )
1618             {
1619                 SwRowFrm* pMasterRow = static_cast<SwRowFrm*>(pMaster->GetLastLower());
1620                 if ( pMasterRow )
1621                     pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *this, *pMasterRow, false );
1622                 if ( pRet && pRet->GetTabBox()->getRowSpan() < 1 )
1623                     pRet = &const_cast<SwCellFrm&>(pRet->FindStartEndOfRowSpanCell( true, true ));
1624             }
1625         }
1626     }
1627 
1628     return pRet;
1629 }
1630 
1631 // --> NEW TABLES
FindStartEndOfRowSpanCell(bool bStart,bool bCurrentTableOnly) const1632 const SwCellFrm& SwCellFrm::FindStartEndOfRowSpanCell( bool bStart, bool bCurrentTableOnly ) const
1633 {
1634     const SwCellFrm* pRet = 0;
1635 
1636     const SwTabFrm* pTableFrm = dynamic_cast<const SwTabFrm*>(GetUpper()->GetUpper());
1637 
1638     if ( !bStart && pTableFrm->IsFollow() && pTableFrm->IsInHeadline( *this ) )
1639         return *this;
1640 
1641     ASSERT( pTableFrm &&
1642             (  bStart && GetTabBox()->getRowSpan() < 1 ||
1643               !bStart && GetLayoutRowSpan() > 1 ),
1644             "SwCellFrm::FindStartRowSpanCell: No rowspan, no table, no cookies" )
1645 
1646     if ( pTableFrm )
1647     {
1648         const SwTable* pTable = pTableFrm->GetTable();
1649 
1650         sal_uInt16 nMax = USHRT_MAX;
1651         if ( bCurrentTableOnly )
1652         {
1653             const SwFrm* pCurrentRow = GetUpper();
1654             const bool bDoNotEnterHeadline = bStart && pTableFrm->IsFollow() &&
1655                                         !pTableFrm->IsInHeadline( *pCurrentRow );
1656 
1657             // check how many rows we are allowed to go up or down until we reach the end of
1658             // the current table frame:
1659             nMax = 0;
1660             while ( bStart ? pCurrentRow->GetPrev() : pCurrentRow->GetNext() )
1661             {
1662                 if ( bStart )
1663                 {
1664                     // do not enter a repeated headline:
1665                     if ( bDoNotEnterHeadline && pTableFrm->IsFollow() &&
1666                          pTableFrm->IsInHeadline( *pCurrentRow->GetPrev() ) )
1667                         break;
1668 
1669                     pCurrentRow = pCurrentRow->GetPrev();
1670                 }
1671                 else
1672                     pCurrentRow = pCurrentRow->GetNext();
1673 
1674                 ++nMax;
1675             }
1676         }
1677 
1678         // By passing the nMax value for Find*OfRowSpan (in case of bCurrentTableOnly
1679         // is set) we assure that we find a rMasterBox that has a SwCellFrm in
1680         // the current table frame:
1681         const SwTableBox& rMasterBox = bStart ?
1682                                        GetTabBox()->FindStartOfRowSpan( *pTable, nMax ) :
1683                                        GetTabBox()->FindEndOfRowSpan( *pTable, nMax );
1684 
1685         SwIterator<SwCellFrm,SwFmt> aIter( *rMasterBox.GetFrmFmt() );
1686 
1687         for ( SwCellFrm* pMasterCell = aIter.First(); pMasterCell; pMasterCell = aIter.Next() )
1688         {
1689             if ( pMasterCell->GetTabBox() == &rMasterBox )
1690             {
1691                 const SwTabFrm* pMasterTable = static_cast<const SwTabFrm*>(pMasterCell->GetUpper()->GetUpper());
1692 
1693                 if ( bCurrentTableOnly )
1694                 {
1695                     if ( pMasterTable == pTableFrm )
1696                     {
1697                         pRet = pMasterCell;
1698                         break;
1699                     }
1700                 }
1701                 else
1702                 {
1703                     if ( pMasterTable == pTableFrm ||
1704                          (  (bStart && pMasterTable->IsAnFollow(pTableFrm)) ||
1705                            (!bStart && pTableFrm->IsAnFollow(pMasterTable)) ) )
1706                     {
1707                         pRet = pMasterCell;
1708                         break;
1709                     }
1710                 }
1711             }
1712         }
1713     }
1714 
1715     ASSERT( pRet, "SwCellFrm::FindStartRowSpanCell: No result" )
1716 
1717     return *pRet;
1718 }
1719 // <-- NEW TABLES
1720 
IsInSplitTableRow() const1721 const SwRowFrm* SwFrm::IsInSplitTableRow() const
1722 {
1723     ASSERT( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" )
1724 
1725     const SwFrm* pRow = this;
1726 
1727     // find most upper row frame
1728     while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) )
1729         pRow = pRow->GetUpper();
1730 
1731     if ( !pRow ) return NULL;
1732 
1733     ASSERT( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" )
1734 
1735     const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
1736     // --> OD 2006-06-28 #b6443897#
1737     // If most upper row frame is a headline row, the current frame
1738     // can't be in a splitted table row. Thus, add corresponding condition.
1739     if ( pRow->GetNext() ||
1740          pTab->GetTable()->IsHeadline(
1741                     *(static_cast<const SwRowFrm*>(pRow)->GetTabLine()) ) ||
1742          !pTab->HasFollowFlowLine() ||
1743          !pTab->GetFollow() )
1744         return NULL;
1745     // <--
1746 
1747     // skip headline
1748     const SwRowFrm* pFollowRow = pTab->GetFollow()->GetFirstNonHeadlineRow();
1749 
1750     ASSERT( pFollowRow, "SwFrm::IsInSplitTableRow() does not work" )
1751 
1752     return pFollowRow;
1753 }
1754 
IsInFollowFlowRow() const1755 const SwRowFrm* SwFrm::IsInFollowFlowRow() const
1756 {
1757     ASSERT( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" )
1758 
1759     // find most upper row frame
1760     const SwFrm* pRow = this;
1761     while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) )
1762         pRow = pRow->GetUpper();
1763 
1764     if ( !pRow ) return NULL;
1765 
1766     ASSERT( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" )
1767 
1768     const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
1769 
1770     const SwTabFrm* pMaster = pTab->IsFollow() ? pTab->FindMaster() : 0;
1771 
1772     if ( !pMaster || !pMaster->HasFollowFlowLine() )
1773         return NULL;
1774 
1775     const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow();
1776     const bool bIsInFirstLine = ( pTmp == pRow );
1777 
1778     if ( !bIsInFirstLine )
1779         return NULL;
1780 
1781     const SwRowFrm* pMasterRow = static_cast<const SwRowFrm*>(pMaster->GetLastLower());
1782     return pMasterRow;
1783 }
1784 
IsInBalancedSection() const1785 bool SwFrm::IsInBalancedSection() const
1786 {
1787     bool bRet = false;
1788 
1789     if ( IsInSct() )
1790     {
1791         const SwSectionFrm* pSectionFrm = FindSctFrm();
1792         if ( pSectionFrm )
1793             bRet = pSectionFrm->IsBalancedSection();
1794     }
1795     return bRet;
1796 }
1797 
1798 /*
1799  * SwLayoutFrm::GetLastLower()
1800  */
GetLastLower() const1801 const SwFrm* SwLayoutFrm::GetLastLower() const
1802 {
1803     const SwFrm* pRet = Lower();
1804     if ( !pRet )
1805         return 0;
1806     while ( pRet->GetNext() )
1807         pRet = pRet->GetNext();
1808     return pRet;
1809 }
1810