xref: /trunk/main/sw/source/core/layout/findfrm.cxx (revision ffd38472365e95f6a578737bc9a5eb0fac624a86)
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 |*************************************************************************/
59 SwLayoutFrm *SwFtnBossFrm::FindBodyCont()
60 {
61     SwFrm *pLay = Lower();
62     while ( pLay && !pLay->IsBodyFrm() )
63         pLay = pLay->GetNext();
64     return (SwLayoutFrm*)pLay;
65 }
66 
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 
91 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 
146 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.
168 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 |*************************************************************************/
219 const SwFrm* SwFrm::GetLower() const
220 {
221     return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0;
222 }
223 
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 |*************************************************************************/
237 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 */
266 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 
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 
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 
349 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
416 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 |*************************************************************************/
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 
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 
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 
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 
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 
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 
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 
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 
595 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 
603 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 |*************************************************************************/
653 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 //UUUU
662 drawinglayer::attribute::SdrAllFillAttributesHelperPtr SwFrm::getSdrAllFillAttributesHelper() const
663 {
664     if(IsCntntFrm())
665     {
666         return static_cast< const SwCntntFrm* >(this)->GetNode()->getSdrAllFillAttributesHelper();
667     }
668     else
669     {
670         return static_cast< const SwLayoutFrm* >(this)->GetFmt()->getSdrAllFillAttributesHelper();
671     }
672 }
673 
674 /*************************************************************************
675 |*
676 |*  SwFrm::_FindNext(), _FindPrev(), InvalidateNextPos()
677 |*         _FindNextCnt() geht in Tabellen und Bereiche hineinund liefert
678 |*         nur SwCntntFrms.
679 |*
680 |*  Beschreibung        Invalidiert die Position des Naechsten Frames.
681 |*      Dies ist der direkte Nachfolger, oder bei CntntFrm's der naechste
682 |*      CntntFrm der im gleichen Fluss liegt wie ich:
683 |*      - Body,
684 |*      - Fussnoten,
685 |*      - Bei Kopf-/Fussbereichen ist die Benachrichtigung nur innerhalb des
686 |*        Bereiches weiterzuleiten.
687 |*      - dito fuer Flys.
688 |*      - Cntnts in Tabs halten sich ausschliesslich innerhalb ihrer Zelle
689 |*        auf.
690 |*      - Tabellen verhalten sich prinzipiell analog zu den Cntnts
691 |*      - Bereiche ebenfalls
692 |*  Ersterstellung      AK 14-Feb-1991
693 |*  Letzte Aenderung    AMA 10. Mar. 99
694 |*
695 |*************************************************************************/
696 
697 // Diese Hilfsfunktion ist ein Aequivalent zur ImplGetNextCntntFrm()-Methode,
698 // sie liefert allerdings neben ContentFrames auch TabFrms und SectionFrms.
699 SwFrm* lcl_NextFrm( SwFrm* pFrm )
700 {
701     SwFrm *pRet = 0;
702     sal_Bool bGoingUp = sal_False;
703     do {
704         SwFrm *p = 0;
705 
706         sal_Bool bGoingFwd = sal_False;
707         sal_Bool bGoingDown = (!bGoingUp && ( 0 != (p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0)));
708 
709         if( !bGoingDown )
710         {
711             bGoingFwd = (0 != (p = ( pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->GetNextLink() : pFrm->GetNext())));
712             if ( !bGoingFwd )
713             {
714                 bGoingUp = (0 != (p = pFrm->GetUpper()));
715                 if ( !bGoingUp )
716                 {
717                     return 0;
718                 }
719             }
720         }
721         bGoingUp = !(bGoingFwd || bGoingDown);
722         pFrm = p;
723     } while ( 0 == (pRet = ( ( pFrm->IsCntntFrm() || ( !bGoingUp &&
724             ( pFrm->IsTabFrm() || pFrm->IsSctFrm() ) ) )? pFrm : 0 ) ) );
725     return pRet;
726 }
727 
728 SwFrm *SwFrm::_FindNext()
729 {
730     sal_Bool bIgnoreTab = sal_False;
731     SwFrm *pThis = this;
732 
733     if ( IsTabFrm() )
734     {
735         //Der letzte Cntnt der Tabelle wird
736         //gegriffen und dessen Nachfolger geliefert. Um die Spezialbeh.
737         //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt.
738         if ( ((SwTabFrm*)this)->GetFollow() )
739             return ((SwTabFrm*)this)->GetFollow();
740 
741         pThis = ((SwTabFrm*)this)->FindLastCntnt();
742         if ( !pThis )
743             pThis = this;
744         bIgnoreTab = sal_True;
745     }
746     else if ( IsSctFrm() )
747     {
748         //Der letzte Cntnt des Bereichs wird gegriffen und dessen Nachfolger
749         // geliefert.
750         if ( ((SwSectionFrm*)this)->GetFollow() )
751             return ((SwSectionFrm*)this)->GetFollow();
752 
753         pThis = ((SwSectionFrm*)this)->FindLastCntnt();
754         if ( !pThis )
755             pThis = this;
756     }
757     else if ( IsCntntFrm() )
758     {
759         if( ((SwCntntFrm*)this)->GetFollow() )
760             return ((SwCntntFrm*)this)->GetFollow();
761     }
762     else if ( IsRowFrm() )
763     {
764         SwFrm* pMyUpper = GetUpper();
765         if ( pMyUpper->IsTabFrm() && ((SwTabFrm*)pMyUpper)->GetFollow() )
766             return ((SwTabFrm*)pMyUpper)->GetFollow()->GetLower();
767         else return NULL;
768     }
769     else
770         return NULL;
771 
772     SwFrm* pRet = NULL;
773     const sal_Bool bFtn  = pThis->IsInFtn();
774     if ( !bIgnoreTab && pThis->IsInTab() )
775     {
776         SwLayoutFrm *pUp = pThis->GetUpper();
777         while ( !pUp->IsCellFrm() )
778             pUp = pUp->GetUpper();
779         ASSERT( pUp, "Cntnt in Tabelle aber nicht in Zelle." );
780         SwFrm* pNxt = ((SwCellFrm*)pUp)->GetFollowCell();
781         if ( pNxt )
782             pNxt = ((SwCellFrm*)pNxt)->ContainsCntnt();
783         if ( !pNxt )
784         {
785             pNxt = lcl_NextFrm( pThis );
786             if ( pUp->IsAnLower( pNxt ) )
787                 pRet = pNxt;
788         }
789         else
790             pRet = pNxt;
791     }
792     else
793     {
794         const sal_Bool bBody = pThis->IsInDocBody();
795         SwFrm *pNxtCnt = lcl_NextFrm( pThis );
796         if ( pNxtCnt )
797         {
798             if ( bBody || bFtn )
799             {
800                 while ( pNxtCnt )
801                 {
802                     // OD 02.04.2003 #108446# - check for endnote, only if found
803                     // next content isn't contained in a section, that collect its
804                     // endnotes at its end.
805                     bool bEndn = IsInSct() && !IsSctFrm() &&
806                                  ( !pNxtCnt->IsInSct() ||
807                                    !pNxtCnt->FindSctFrm()->IsEndnAtEnd()
808                                  );
809                     if ( ( bBody && pNxtCnt->IsInDocBody() ) ||
810                          ( pNxtCnt->IsInFtn() &&
811                            ( bFtn ||
812                              ( bEndn && pNxtCnt->FindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
813                            )
814                          )
815                        )
816                     {
817                         pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
818                                                     : (SwFrm*)pNxtCnt;
819                         break;
820                     }
821                     pNxtCnt = lcl_NextFrm( pNxtCnt );
822                 }
823             }
824             else if ( pThis->IsInFly() )
825             {
826                 pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
827                                             : (SwFrm*)pNxtCnt;
828             }
829             else    //Fuss-/oder Kopfbereich
830             {
831                 const SwFrm *pUp = pThis->GetUpper();
832                 const SwFrm *pCntUp = pNxtCnt->GetUpper();
833                 while ( pUp && pUp->GetUpper() &&
834                         !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
835                     pUp = pUp->GetUpper();
836                 while ( pCntUp && pCntUp->GetUpper() &&
837                         !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() )
838                     pCntUp = pCntUp->GetUpper();
839                 if ( pCntUp == pUp )
840                 {
841                     pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
842                                                 : (SwFrm*)pNxtCnt;
843                 }
844             }
845         }
846     }
847     if( pRet && pRet->IsInSct() )
848     {
849         SwSectionFrm* pSct = pRet->FindSctFrm();
850         //Fussnoten in spaltigen Rahmen duerfen nicht den Bereich
851         //liefern, der die Fussnoten umfasst
852         if( !pSct->IsAnLower( this ) &&
853             (!bFtn || pSct->IsInFtn() ) )
854             return pSct;
855     }
856     return pRet;
857 }
858 
859 // --> OD 2005-12-01 #i27138# - add parameter <_bInSameFtn>
860 SwCntntFrm *SwFrm::_FindNextCnt( const bool _bInSameFtn )
861 {
862     SwFrm *pThis = this;
863 
864     if ( IsTabFrm() )
865     {
866         if ( ((SwTabFrm*)this)->GetFollow() )
867         {
868             pThis = ((SwTabFrm*)this)->GetFollow()->ContainsCntnt();
869             if( pThis )
870                 return (SwCntntFrm*)pThis;
871         }
872         pThis = ((SwTabFrm*)this)->FindLastCntnt();
873         if ( !pThis )
874             return 0;
875     }
876     else if ( IsSctFrm() )
877     {
878         if ( ((SwSectionFrm*)this)->GetFollow() )
879         {
880             pThis = ((SwSectionFrm*)this)->GetFollow()->ContainsCntnt();
881             if( pThis )
882                 return (SwCntntFrm*)pThis;
883         }
884         pThis = ((SwSectionFrm*)this)->FindLastCntnt();
885         if ( !pThis )
886             return 0;
887     }
888     else if ( IsCntntFrm() && ((SwCntntFrm*)this)->GetFollow() )
889         return ((SwCntntFrm*)this)->GetFollow();
890 
891     if ( pThis->IsCntntFrm() )
892     {
893         const sal_Bool bBody = pThis->IsInDocBody();
894         const sal_Bool bFtn  = pThis->IsInFtn();
895         SwCntntFrm *pNxtCnt = ((SwCntntFrm*)pThis)->GetNextCntntFrm();
896         if ( pNxtCnt )
897         {
898             // --> OD 2005-12-01 #i27138#
899             if ( bBody || ( bFtn && !_bInSameFtn ) )
900             // <--
901             {
902                 // handling for environments 'footnotes' and 'document body frames':
903                 while ( pNxtCnt )
904                 {
905                     if ( (bBody && pNxtCnt->IsInDocBody()) ||
906                          (bFtn  && pNxtCnt->IsInFtn()) )
907                         return pNxtCnt;
908                     pNxtCnt = pNxtCnt->GetNextCntntFrm();
909                 }
910             }
911             // --> OD 2005-12-01 #i27138#
912             else if ( bFtn && _bInSameFtn )
913             {
914                 // handling for environments 'each footnote':
915                 // Assure that found next content frame belongs to the same footnotes
916                 const SwFtnFrm* pFtnFrmOfNext( pNxtCnt->FindFtnFrm() );
917                 const SwFtnFrm* pFtnFrmOfCurr( pThis->FindFtnFrm() );
918                 ASSERT( pFtnFrmOfCurr,
919                         "<SwFrm::_FindNextCnt() - unknown layout situation: current frame has to have an upper footnote frame." );
920                 if ( pFtnFrmOfNext == pFtnFrmOfCurr )
921                 {
922                     return pNxtCnt;
923                 }
924                 else if ( pFtnFrmOfCurr->GetFollow() )
925                 {
926                     // next content frame has to be the first content frame
927                     // in the follow footnote, which contains a content frame.
928                     SwFtnFrm* pFollowFtnFrmOfCurr(
929                                         const_cast<SwFtnFrm*>(pFtnFrmOfCurr) );
930                     pNxtCnt = 0L;
931                     do {
932                         pFollowFtnFrmOfCurr = pFollowFtnFrmOfCurr->GetFollow();
933                         pNxtCnt = pFollowFtnFrmOfCurr->ContainsCntnt();
934                     } while ( !pNxtCnt && pFollowFtnFrmOfCurr->GetFollow() );
935                     return pNxtCnt;
936                 }
937                 else
938                 {
939                     // current content frame is the last content frame in the
940                     // footnote - no next content frame exists.
941                     return 0L;
942                 }
943             }
944             // <--
945             else if ( pThis->IsInFly() )
946                 // handling for environments 'unlinked fly frame' and
947                 // 'group of linked fly frames':
948                 return pNxtCnt;
949             else
950             {
951                 // handling for environments 'page header' and 'page footer':
952                 const SwFrm *pUp = pThis->GetUpper();
953                 const SwFrm *pCntUp = pNxtCnt->GetUpper();
954                 while ( pUp && pUp->GetUpper() &&
955                         !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
956                     pUp = pUp->GetUpper();
957                 while ( pCntUp && pCntUp->GetUpper() &&
958                         !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() )
959                     pCntUp = pCntUp->GetUpper();
960                 if ( pCntUp == pUp )
961                     return pNxtCnt;
962             }
963         }
964     }
965     return 0;
966 }
967 
968 /** method to determine previous content frame in the same environment
969     for a flow frame (content frame, table frame, section frame)
970 
971     OD 2005-11-30 #i27138#
972 
973     @author OD
974 */
975 SwCntntFrm* SwFrm::_FindPrevCnt( const bool _bInSameFtn )
976 {
977     if ( !IsFlowFrm() )
978     {
979         // nothing to do, if current frame isn't a flow frame.
980         return 0L;
981     }
982 
983     SwCntntFrm* pPrevCntntFrm( 0L );
984 
985     // Because method <SwCntntFrm::GetPrevCntntFrm()> is used to travel
986     // through the layout, a content frame, at which the travel starts, is needed.
987     SwCntntFrm* pCurrCntntFrm = dynamic_cast<SwCntntFrm*>(this);
988 
989     // perform shortcut, if current frame is a follow, and
990     // determine <pCurrCntntFrm>, if current frame is a table or section frame
991     if ( pCurrCntntFrm && pCurrCntntFrm->IsFollow() )
992     {
993         // previous content frame is its master content frame
994         pPrevCntntFrm = pCurrCntntFrm->FindMaster();
995     }
996     else if ( IsTabFrm() )
997     {
998         SwTabFrm* pTabFrm( static_cast<SwTabFrm*>(this) );
999         if ( pTabFrm->IsFollow() )
1000         {
1001             // previous content frame is the last content of its master table frame
1002             pPrevCntntFrm = pTabFrm->FindMaster()->FindLastCntnt();
1003         }
1004         else
1005         {
1006             // start content frame for the search is the first content frame of
1007             // the table frame.
1008             pCurrCntntFrm = pTabFrm->ContainsCntnt();
1009         }
1010     }
1011     else if ( IsSctFrm() )
1012     {
1013         SwSectionFrm* pSectFrm( static_cast<SwSectionFrm*>(this) );
1014         if ( pSectFrm->IsFollow() )
1015         {
1016             // previous content frame is the last content of its master section frame
1017             pPrevCntntFrm = pSectFrm->FindMaster()->FindLastCntnt();
1018         }
1019         else
1020         {
1021             // start content frame for the search is the first content frame of
1022             // the section frame.
1023             pCurrCntntFrm = pSectFrm->ContainsCntnt();
1024         }
1025     }
1026 
1027     // search for next content frame, depending on the environment, in which
1028     // the current frame is in.
1029     if ( !pPrevCntntFrm && pCurrCntntFrm )
1030     {
1031         pPrevCntntFrm = pCurrCntntFrm->GetPrevCntntFrm();
1032         if ( pPrevCntntFrm )
1033         {
1034             if ( pCurrCntntFrm->IsInFly() )
1035             {
1036                 // handling for environments 'unlinked fly frame' and
1037                 // 'group of linked fly frames':
1038                 // Nothing to do, <pPrevCntntFrm> is the one
1039             }
1040             else
1041             {
1042                 const bool bInDocBody = pCurrCntntFrm->IsInDocBody();
1043                 const bool bInFtn  = pCurrCntntFrm->IsInFtn();
1044                 if ( bInDocBody || ( bInFtn && !_bInSameFtn ) )
1045                 {
1046                     // handling for environments 'footnotes' and 'document body frames':
1047                     // Assure that found previous frame is also in one of these
1048                     // environments. Otherwise, travel further
1049                     while ( pPrevCntntFrm )
1050                     {
1051                         if ( ( bInDocBody && pPrevCntntFrm->IsInDocBody() ) ||
1052                              ( bInFtn && pPrevCntntFrm->IsInFtn() ) )
1053                         {
1054                             break;
1055                         }
1056                         pPrevCntntFrm = pPrevCntntFrm->GetPrevCntntFrm();
1057                     }
1058                 }
1059                 else if ( bInFtn && _bInSameFtn )
1060                 {
1061                     // handling for environments 'each footnote':
1062                     // Assure that found next content frame belongs to the same footnotes
1063                     const SwFtnFrm* pFtnFrmOfPrev( pPrevCntntFrm->FindFtnFrm() );
1064                     const SwFtnFrm* pFtnFrmOfCurr( pCurrCntntFrm->FindFtnFrm() );
1065                     if ( pFtnFrmOfPrev != pFtnFrmOfCurr )
1066                     {
1067                         if ( pFtnFrmOfCurr->GetMaster() )
1068                         {
1069                             SwFtnFrm* pMasterFtnFrmOfCurr(
1070                                         const_cast<SwFtnFrm*>(pFtnFrmOfCurr) );
1071                             pPrevCntntFrm = 0L;
1072                             // --> OD 2007-07-05 #146872#
1073                             // correct wrong loop-condition
1074                             do {
1075                                 pMasterFtnFrmOfCurr = pMasterFtnFrmOfCurr->GetMaster();
1076                                 pPrevCntntFrm = pMasterFtnFrmOfCurr->FindLastCntnt();
1077                             } while ( !pPrevCntntFrm &&
1078                                       pMasterFtnFrmOfCurr->GetMaster() );
1079                             // <--
1080                         }
1081                         else
1082                         {
1083                             // current content frame is the first content in the
1084                             // footnote - no previous content exists.
1085                             pPrevCntntFrm = 0L;
1086                         }
1087                     }
1088                 }
1089                 else
1090                 {
1091                     // handling for environments 'page header' and 'page footer':
1092                     // Assure that found previous frame is also in the same
1093                     // page header respectively page footer as <pCurrCntntFrm>
1094                     // Note: At this point its clear, that <pCurrCntntFrm> has
1095                     //       to be inside a page header or page footer and that
1096                     //       neither <pCurrCntntFrm> nor <pPrevCntntFrm> are
1097                     //       inside a fly frame.
1098                     //       Thus, method <FindFooterOrHeader()> can be used.
1099                     ASSERT( pCurrCntntFrm->FindFooterOrHeader(),
1100                             "<SwFrm::_FindPrevCnt()> - unknown layout situation: current frame should be in page header or page footer" );
1101                     ASSERT( !pPrevCntntFrm->IsInFly(),
1102                             "<SwFrm::_FindPrevCnt()> - unknown layout situation: found previous frame should *not* be inside a fly frame." );
1103                     if ( pPrevCntntFrm->FindFooterOrHeader() !=
1104                                             pCurrCntntFrm->FindFooterOrHeader() )
1105                     {
1106                         pPrevCntntFrm = 0L;
1107                     }
1108                 }
1109             }
1110         }
1111     }
1112 
1113     return pPrevCntntFrm;
1114 }
1115 
1116 SwFrm *SwFrm::_FindPrev()
1117 {
1118     sal_Bool bIgnoreTab = sal_False;
1119     SwFrm *pThis = this;
1120 
1121     if ( IsTabFrm() )
1122     {
1123         //Der erste Cntnt der Tabelle wird
1124         //gegriffen und dessen Vorgaenger geliefert. Um die Spezialbeh.
1125         //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt.
1126         if ( ((SwTabFrm*)this)->IsFollow() )
1127             return ((SwTabFrm*)this)->FindMaster();
1128         else
1129             pThis = ((SwTabFrm*)this)->ContainsCntnt();
1130         bIgnoreTab = sal_True;
1131     }
1132 
1133     if ( pThis && pThis->IsCntntFrm() )
1134     {
1135         SwCntntFrm *pPrvCnt = ((SwCntntFrm*)pThis)->GetPrevCntntFrm();
1136         if( !pPrvCnt )
1137             return 0;
1138         if ( !bIgnoreTab && pThis->IsInTab() )
1139         {
1140             SwLayoutFrm *pUp = pThis->GetUpper();
1141             while ( !pUp->IsCellFrm() )
1142                 pUp = pUp->GetUpper();
1143             ASSERT( pUp, "Cntnt in Tabelle aber nicht in Zelle." );
1144             if ( pUp->IsAnLower( pPrvCnt ) )
1145                 return pPrvCnt;
1146         }
1147         else
1148         {
1149             SwFrm* pRet;
1150             const sal_Bool bBody = pThis->IsInDocBody();
1151             const sal_Bool bFtn  = bBody ? sal_False : pThis->IsInFtn();
1152             if ( bBody || bFtn )
1153             {
1154                 while ( pPrvCnt )
1155                 {
1156                     if ( (bBody && pPrvCnt->IsInDocBody()) ||
1157                             (bFtn   && pPrvCnt->IsInFtn()) )
1158                     {
1159                         pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
1160                                                   : (SwFrm*)pPrvCnt;
1161                         return pRet;
1162                     }
1163                     pPrvCnt = pPrvCnt->GetPrevCntntFrm();
1164                 }
1165             }
1166             else if ( pThis->IsInFly() )
1167             {
1168                 pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
1169                                             : (SwFrm*)pPrvCnt;
1170                 return pRet;
1171             }
1172             else    //Fuss-/oder Kopfbereich oder Fly
1173             {
1174                 const SwFrm *pUp = pThis->GetUpper();
1175                 const SwFrm *pCntUp = pPrvCnt->GetUpper();
1176                 while ( pUp && pUp->GetUpper() &&
1177                         !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
1178                     pUp = pUp->GetUpper();
1179                 while ( pCntUp && pCntUp->GetUpper() )
1180                     pCntUp = pCntUp->GetUpper();
1181                 if ( pCntUp == pUp )
1182                 {
1183                     pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
1184                                                 : (SwFrm*)pPrvCnt;
1185                     return pRet;
1186                 }
1187             }
1188         }
1189     }
1190     return 0;
1191 }
1192 
1193 void SwFrm::ImplInvalidateNextPos( sal_Bool bNoFtn )
1194 {
1195     SwFrm *pFrm;
1196     if ( 0 != (pFrm = _FindNext()) )
1197     {
1198         if( pFrm->IsSctFrm() )
1199         {
1200             while( pFrm && pFrm->IsSctFrm() )
1201             {
1202                 if( ((SwSectionFrm*)pFrm)->GetSection() )
1203                 {
1204                     SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny();
1205                     if( pTmp )
1206                         pTmp->InvalidatePos();
1207                     else if( !bNoFtn )
1208                         ((SwSectionFrm*)pFrm)->InvalidateFtnPos();
1209                     if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm )
1210                         pFrm->InvalidatePos();
1211                     return;
1212                 }
1213                 pFrm = pFrm->FindNext();
1214             }
1215             if( pFrm )
1216             {
1217                 if ( pFrm->IsSctFrm())
1218                 { // Damit der Inhalt eines Bereichs die Chance erhaelt,
1219                   // die Seite zu wechseln, muss er ebenfalls invalidiert werden.
1220                     SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny();
1221                     if( pTmp )
1222                         pTmp->InvalidatePos();
1223                     if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm )
1224                         pFrm->InvalidatePos();
1225                 }
1226                 else
1227                     pFrm->InvalidatePos();
1228             }
1229         }
1230         else
1231             pFrm->InvalidatePos();
1232     }
1233 }
1234 
1235 /** method to invalidate printing area of next frame
1236 
1237     OD 09.01.2004 #i11859#
1238 
1239     @author OD
1240 
1241     FME 2004-04-19 #i27145# Moved function from SwTxtFrm to SwFrm
1242 */
1243 void SwFrm::InvalidateNextPrtArea()
1244 {
1245     // determine next frame
1246     SwFrm* pNextFrm = FindNext();
1247     // skip empty section frames and hidden text frames
1248     {
1249         while ( pNextFrm &&
1250                 ( ( pNextFrm->IsSctFrm() &&
1251                     !static_cast<SwSectionFrm*>(pNextFrm)->GetSection() ) ||
1252                   ( pNextFrm->IsTxtFrm() &&
1253                     static_cast<SwTxtFrm*>(pNextFrm)->IsHiddenNow() ) ) )
1254         {
1255             pNextFrm = pNextFrm->FindNext();
1256         }
1257     }
1258 
1259     // Invalidate printing area of found next frame
1260     if ( pNextFrm )
1261     {
1262         if ( pNextFrm->IsSctFrm() )
1263         {
1264             // Invalidate printing area of found section frame, if
1265             // (1) this text frame isn't in a section OR
1266             // (2) found section frame isn't a follow of the section frame this
1267             //     text frame is in.
1268             if ( !IsInSct() || FindSctFrm()->GetFollow() != pNextFrm )
1269             {
1270                 pNextFrm->InvalidatePrt();
1271             }
1272 
1273             // Invalidate printing area of first content in found section.
1274             SwFrm* pFstCntntOfSctFrm =
1275                     static_cast<SwSectionFrm*>(pNextFrm)->ContainsAny();
1276             if ( pFstCntntOfSctFrm )
1277             {
1278                 pFstCntntOfSctFrm->InvalidatePrt();
1279             }
1280         }
1281         else
1282         {
1283             pNextFrm->InvalidatePrt();
1284         }
1285     }
1286 }
1287 
1288 /*************************************************************************
1289 |*
1290 |*    lcl_IsInColSect()
1291 |*      liefert nur sal_True, wenn der Frame _direkt_ in einem spaltigen Bereich steht,
1292 |*      nicht etwa, wenn er in einer Tabelle steht, die in einem spaltigen Bereich ist.
1293 |*
1294 |*************************************************************************/
1295 
1296 sal_Bool lcl_IsInColSct( const SwFrm *pUp )
1297 {
1298     sal_Bool bRet = sal_False;
1299     while( pUp )
1300     {
1301         if( pUp->IsColumnFrm() )
1302             bRet = sal_True;
1303         else if( pUp->IsSctFrm() )
1304             return bRet;
1305         else if( pUp->IsTabFrm() )
1306             return sal_False;
1307         pUp = pUp->GetUpper();
1308     }
1309     return sal_False;
1310 }
1311 
1312 /*************************************************************************
1313 |*
1314 |*    SwFrm::IsMoveable();
1315 |*
1316 |*    Ersterstellung    MA 09. Mar. 93
1317 |*    Letzte Aenderung  MA 05. May. 95
1318 |*
1319 |*************************************************************************/
1320 /** determine, if frame is moveable in given environment
1321 
1322     OD 08.08.2003 #110978#
1323     method replaced 'old' method <sal_Bool IsMoveable() const>.
1324     Determines, if frame is moveable in given environment. if no environment
1325     is given (parameter _pLayoutFrm == 0L), the movability in the actual
1326     environment (<this->GetUpper()) is checked.
1327 
1328     @author OD
1329 */
1330 
1331 bool SwFrm::IsMoveable( const SwLayoutFrm* _pLayoutFrm ) const
1332 {
1333     bool bRetVal = false;
1334 
1335     if ( !_pLayoutFrm )
1336     {
1337         _pLayoutFrm = GetUpper();
1338     }
1339 
1340     if ( _pLayoutFrm && IsFlowFrm() )
1341     {
1342         if ( _pLayoutFrm->IsInSct() && lcl_IsInColSct( _pLayoutFrm ) )
1343         {
1344             bRetVal = true;
1345         }
1346         else if ( _pLayoutFrm->IsInFly() ||
1347                   _pLayoutFrm->IsInDocBody() ||
1348                   _pLayoutFrm->IsInFtn() )
1349         {
1350             if ( _pLayoutFrm->IsInTab() && !IsTabFrm() &&
1351                  ( !IsCntntFrm() || !const_cast<SwFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) ) )
1352             {
1353                 bRetVal = false;
1354             }
1355             else
1356             {
1357                 if ( _pLayoutFrm->IsInFly() )
1358                 {
1359                     // if fly frame has a follow (next linked fly frame),
1360                     // frame is moveable.
1361                     if ( const_cast<SwLayoutFrm*>(_pLayoutFrm)->FindFlyFrm()->GetNextLink() )
1362                     {
1363                         bRetVal = true;
1364                     }
1365                     else
1366                     {
1367                         // if environment is columned, frame is moveable, if
1368                         // it isn't in last column.
1369                         // search for column frame
1370                         const SwFrm* pCol = _pLayoutFrm;
1371                         while ( pCol && !pCol->IsColumnFrm() )
1372                         {
1373                             pCol = pCol->GetUpper();
1374                         }
1375                         // frame is moveable, if found column frame isn't last one.
1376                         if ( pCol && pCol->GetNext() )
1377                         {
1378                             bRetVal = true;
1379                         }
1380                     }
1381                 }
1382                 else
1383                 {
1384                     bRetVal = true;
1385                 }
1386             }
1387         }
1388     }
1389 
1390     return bRetVal;
1391 }
1392 
1393 /*************************************************************************
1394 |*
1395 |*    SwFrm::SetInfFlags();
1396 |*
1397 |*    Ersterstellung    MA 05. Apr. 94
1398 |*    Letzte Aenderung  MA 05. Apr. 94
1399 |*
1400 |*************************************************************************/
1401 void SwFrm::SetInfFlags()
1402 {
1403     if ( !IsFlyFrm() && !GetUpper() ) //noch nicht gepastet, keine Informationen
1404         return;                       //lieferbar
1405 
1406     bInfInvalid = bInfBody = bInfTab = bInfFly = bInfFtn = bInfSct = sal_False;
1407 
1408     SwFrm *pFrm = this;
1409     if( IsFtnContFrm() )
1410         bInfFtn = sal_True;
1411     do
1412     {   // bInfBody wird nur am Seitenbody, nicht im ColumnBody gesetzt
1413         if ( pFrm->IsBodyFrm() && !bInfFtn && pFrm->GetUpper()
1414              && pFrm->GetUpper()->IsPageFrm() )
1415             bInfBody = sal_True;
1416         else if ( pFrm->IsTabFrm() || pFrm->IsCellFrm() )
1417         {
1418             bInfTab = sal_True;
1419         }
1420         else if ( pFrm->IsFlyFrm() )
1421             bInfFly = sal_True;
1422         else if ( pFrm->IsSctFrm() )
1423             bInfSct = sal_True;
1424         else if ( pFrm->IsFtnFrm() )
1425             bInfFtn = sal_True;
1426 
1427         pFrm = pFrm->GetUpper();
1428 
1429     } while ( pFrm && !pFrm->IsPageFrm() ); //Oberhalb der Seite kommt nix
1430 }
1431 
1432 /*-----------------22.8.2001 14:30------------------
1433  * SwFrm::SetDirFlags( sal_Bool )
1434  * actualizes the vertical or the righttoleft-flags.
1435  * If the property is derived, it's from the upper or (for fly frames) from
1436  * the anchor. Otherwise we've to call a virtual method to check the property.
1437  * --------------------------------------------------*/
1438 
1439 void SwFrm::SetDirFlags( sal_Bool bVert )
1440 {
1441     if( bVert )
1442     {
1443         // OD 2004-01-21 #114969# - if derived, valid vertical flag only if
1444         // vertical flag of upper/anchor is valid.
1445         if( bDerivedVert )
1446         {
1447             const SwFrm* pAsk = IsFlyFrm() ?
1448                           ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper();
1449 
1450             ASSERT( pAsk != this, "Autsch! Stack overflow is about to happen" )
1451 
1452             if( pAsk )
1453             {
1454                 bVertical = pAsk->IsVertical() ? 1 : 0;
1455                 bReverse  = pAsk->IsReverse()  ? 1 : 0;
1456 
1457                 bVertLR  = pAsk->IsVertLR() ? 1 : 0;
1458                 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
1459                 if ( !pAsk->bInvalidVert )
1460                     bInvalidVert = sal_False;
1461             }
1462         }
1463         else
1464             CheckDirection( bVert );
1465     }
1466     else
1467     {
1468         sal_Bool bInv = 0;
1469         if( !bDerivedR2L ) // CheckDirection is able to set bDerivedR2L!
1470             CheckDirection( bVert );
1471         if( bDerivedR2L )
1472         {
1473             const SwFrm* pAsk = IsFlyFrm() ?
1474                           ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper();
1475 
1476             ASSERT( pAsk != this, "Autsch! Stack overflow is about to happen" )
1477 
1478             if( pAsk )
1479                 bRightToLeft = pAsk->IsRightToLeft() ? 1 : 0;
1480             if( !pAsk || pAsk->bInvalidR2L )
1481                 bInv = bInvalidR2L;
1482         }
1483         bInvalidR2L = bInv;
1484     }
1485 }
1486 
1487 SwLayoutFrm* SwFrm::GetNextCellLeaf( MakePageType )
1488 {
1489     SwFrm* pTmpFrm = this;
1490     while ( !pTmpFrm->IsCellFrm() )
1491         pTmpFrm = pTmpFrm->GetUpper();
1492 
1493     ASSERT( pTmpFrm, "SwFrm::GetNextCellLeaf() without cell" )
1494     return ((SwCellFrm*)pTmpFrm)->GetFollowCell();
1495 }
1496 
1497 SwLayoutFrm* SwFrm::GetPrevCellLeaf( MakePageType )
1498 {
1499     SwFrm* pTmpFrm = this;
1500     while ( !pTmpFrm->IsCellFrm() )
1501         pTmpFrm = pTmpFrm->GetUpper();
1502 
1503     ASSERT( pTmpFrm, "SwFrm::GetNextPreviousLeaf() without cell" )
1504     return ((SwCellFrm*)pTmpFrm)->GetPreviousCell();
1505 }
1506 
1507 SwCellFrm* lcl_FindCorrespondingCellFrm( const SwRowFrm& rOrigRow,
1508                                          const SwCellFrm& rOrigCell,
1509                                          const SwRowFrm& rCorrRow,
1510                                          bool bInFollow )
1511 {
1512     SwCellFrm* pRet = NULL;
1513     SwCellFrm* pCell = (SwCellFrm*)rOrigRow.Lower();
1514     SwCellFrm* pCorrCell = (SwCellFrm*)rCorrRow.Lower();
1515 
1516     while ( pCell != &rOrigCell && !pCell->IsAnLower( &rOrigCell ) )
1517     {
1518         pCell = (SwCellFrm*)pCell->GetNext();
1519         pCorrCell = (SwCellFrm*)pCorrCell->GetNext();
1520     }
1521 
1522     ASSERT( pCell && pCorrCell, "lcl_FindCorrespondingCellFrm does not work" )
1523 
1524     if ( pCell != &rOrigCell )
1525     {
1526         // rOrigCell must be a lower of pCell. We need to recurse into the rows:
1527         ASSERT( pCell->Lower() && pCell->Lower()->IsRowFrm(),
1528                 "lcl_FindCorrespondingCellFrm does not work" )
1529 
1530         SwRowFrm* pRow = (SwRowFrm*)pCell->Lower();
1531         while ( !pRow->IsAnLower( &rOrigCell ) )
1532             pRow = (SwRowFrm*)pRow->GetNext();
1533 
1534         SwRowFrm* pCorrRow = 0;
1535         if ( bInFollow )
1536             pCorrRow = pRow->GetFollowRow();
1537         else
1538         {
1539             SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pCorrCell->GetLastLower());
1540 
1541             if ( pTmpRow && pTmpRow->GetFollowRow() == pRow )
1542                 pCorrRow = pTmpRow;
1543         }
1544 
1545         if ( pCorrRow )
1546             pRet = lcl_FindCorrespondingCellFrm( *pRow, rOrigCell, *pCorrRow, bInFollow );
1547     }
1548     else
1549         pRet = pCorrCell;
1550 
1551     return pRet;
1552 }
1553 
1554 // VERSION OF GetFollowCell() that assumes that we always have a follow flow line:
1555 SwCellFrm* SwCellFrm::GetFollowCell() const
1556 {
1557     SwCellFrm* pRet = NULL;
1558 
1559     // NEW TABLES
1560     // Covered cells do not have follow cells!
1561     const long nRowSpan = GetLayoutRowSpan();
1562     if ( nRowSpan < 1 )
1563         return NULL;
1564 
1565     // find most upper row frame
1566     const SwFrm* pRow = GetUpper();
1567     while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
1568         pRow = pRow->GetUpper();
1569 
1570     if ( !pRow )
1571         return NULL;
1572 
1573     const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( pRow->GetUpper() );
1574     if ( !pRow || !pTabFrm->GetFollow() || !pTabFrm->HasFollowFlowLine() )
1575         return NULL;
1576 
1577     const SwCellFrm* pThisCell = this;
1578 
1579     // Get last cell of the current table frame that belongs to the rowspan:
1580     if ( nRowSpan > 1 )
1581     {
1582         // optimization: Will end of row span be in last row or exceed row?
1583         long nMax = 0;
1584         while ( pRow->GetNext() && ++nMax < nRowSpan )
1585             pRow = pRow->GetNext();
1586 
1587         if ( !pRow->GetNext() )
1588         {
1589             pThisCell = &pThisCell->FindStartEndOfRowSpanCell( false, true );
1590             pRow = pThisCell->GetUpper();
1591         }
1592     }
1593 
1594     const SwRowFrm* pFollowRow = NULL;
1595     if ( !pRow->GetNext() &&
1596          NULL != ( pFollowRow = pRow->IsInSplitTableRow() ) &&
1597          ( !pFollowRow->IsRowSpanLine() || nRowSpan > 1 ) )
1598          pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *pThisCell, *pFollowRow, true );
1599 
1600     return pRet;
1601 }
1602 
1603 // VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL
1604 SwCellFrm* SwCellFrm::GetPreviousCell() const
1605 {
1606     SwCellFrm* pRet = NULL;
1607 
1608     // NEW TABLES
1609     // Covered cells do not have previous cells!
1610     if ( GetLayoutRowSpan() < 1 )
1611         return NULL;
1612 
1613     // find most upper row frame
1614     const SwFrm* pRow = GetUpper();
1615     while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
1616         pRow = pRow->GetUpper();
1617 
1618     ASSERT( pRow->GetUpper() && pRow->GetUpper()->IsTabFrm(), "GetPreviousCell without Table" );
1619 
1620     SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
1621 
1622     if ( pTab->IsFollow() )
1623     {
1624         const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow();
1625         const bool bIsInFirstLine = ( pTmp == pRow );
1626 
1627         if ( bIsInFirstLine )
1628         {
1629             SwTabFrm *pMaster = (SwTabFrm*)pTab->FindMaster();
1630             if ( pMaster && pMaster->HasFollowFlowLine() )
1631             {
1632                 SwRowFrm* pMasterRow = static_cast<SwRowFrm*>(pMaster->GetLastLower());
1633                 if ( pMasterRow )
1634                     pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *this, *pMasterRow, false );
1635                 if ( pRet && pRet->GetTabBox()->getRowSpan() < 1 )
1636                     pRet = &const_cast<SwCellFrm&>(pRet->FindStartEndOfRowSpanCell( true, true ));
1637             }
1638         }
1639     }
1640 
1641     return pRet;
1642 }
1643 
1644 // --> NEW TABLES
1645 const SwCellFrm& SwCellFrm::FindStartEndOfRowSpanCell( bool bStart, bool bCurrentTableOnly ) const
1646 {
1647     const SwCellFrm* pRet = 0;
1648 
1649     const SwTabFrm* pTableFrm = dynamic_cast<const SwTabFrm*>(GetUpper()->GetUpper());
1650 
1651     if ( !bStart && pTableFrm->IsFollow() && pTableFrm->IsInHeadline( *this ) )
1652         return *this;
1653 
1654     ASSERT( pTableFrm &&
1655             (  bStart && GetTabBox()->getRowSpan() < 1 ||
1656               !bStart && GetLayoutRowSpan() > 1 ),
1657             "SwCellFrm::FindStartRowSpanCell: No rowspan, no table, no cookies" )
1658 
1659     if ( pTableFrm )
1660     {
1661         const SwTable* pTable = pTableFrm->GetTable();
1662 
1663         sal_uInt16 nMax = USHRT_MAX;
1664         if ( bCurrentTableOnly )
1665         {
1666             const SwFrm* pCurrentRow = GetUpper();
1667             const bool bDoNotEnterHeadline = bStart && pTableFrm->IsFollow() &&
1668                                         !pTableFrm->IsInHeadline( *pCurrentRow );
1669 
1670             // check how many rows we are allowed to go up or down until we reach the end of
1671             // the current table frame:
1672             nMax = 0;
1673             while ( bStart ? pCurrentRow->GetPrev() : pCurrentRow->GetNext() )
1674             {
1675                 if ( bStart )
1676                 {
1677                     // do not enter a repeated headline:
1678                     if ( bDoNotEnterHeadline && pTableFrm->IsFollow() &&
1679                          pTableFrm->IsInHeadline( *pCurrentRow->GetPrev() ) )
1680                         break;
1681 
1682                     pCurrentRow = pCurrentRow->GetPrev();
1683                 }
1684                 else
1685                     pCurrentRow = pCurrentRow->GetNext();
1686 
1687                 ++nMax;
1688             }
1689         }
1690 
1691         // By passing the nMax value for Find*OfRowSpan (in case of bCurrentTableOnly
1692         // is set) we assure that we find a rMasterBox that has a SwCellFrm in
1693         // the current table frame:
1694         const SwTableBox& rMasterBox = bStart ?
1695                                        GetTabBox()->FindStartOfRowSpan( *pTable, nMax ) :
1696                                        GetTabBox()->FindEndOfRowSpan( *pTable, nMax );
1697 
1698         SwIterator<SwCellFrm,SwFmt> aIter( *rMasterBox.GetFrmFmt() );
1699 
1700         for ( SwCellFrm* pMasterCell = aIter.First(); pMasterCell; pMasterCell = aIter.Next() )
1701         {
1702             if ( pMasterCell->GetTabBox() == &rMasterBox )
1703             {
1704                 const SwTabFrm* pMasterTable = static_cast<const SwTabFrm*>(pMasterCell->GetUpper()->GetUpper());
1705 
1706                 if ( bCurrentTableOnly )
1707                 {
1708                     if ( pMasterTable == pTableFrm )
1709                     {
1710                         pRet = pMasterCell;
1711                         break;
1712                     }
1713                 }
1714                 else
1715                 {
1716                     if ( pMasterTable == pTableFrm ||
1717                          (  (bStart && pMasterTable->IsAnFollow(pTableFrm)) ||
1718                            (!bStart && pTableFrm->IsAnFollow(pMasterTable)) ) )
1719                     {
1720                         pRet = pMasterCell;
1721                         break;
1722                     }
1723                 }
1724             }
1725         }
1726     }
1727 
1728     ASSERT( pRet, "SwCellFrm::FindStartRowSpanCell: No result" )
1729 
1730     return *pRet;
1731 }
1732 // <-- NEW TABLES
1733 
1734 const SwRowFrm* SwFrm::IsInSplitTableRow() const
1735 {
1736     ASSERT( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" )
1737 
1738     const SwFrm* pRow = this;
1739 
1740     // find most upper row frame
1741     while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) )
1742         pRow = pRow->GetUpper();
1743 
1744     if ( !pRow ) return NULL;
1745 
1746     ASSERT( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" )
1747 
1748     const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
1749     // --> OD 2006-06-28 #b6443897#
1750     // If most upper row frame is a headline row, the current frame
1751     // can't be in a splitted table row. Thus, add corresponding condition.
1752     if ( pRow->GetNext() ||
1753          pTab->GetTable()->IsHeadline(
1754                     *(static_cast<const SwRowFrm*>(pRow)->GetTabLine()) ) ||
1755          !pTab->HasFollowFlowLine() ||
1756          !pTab->GetFollow() )
1757         return NULL;
1758     // <--
1759 
1760     // skip headline
1761     const SwRowFrm* pFollowRow = pTab->GetFollow()->GetFirstNonHeadlineRow();
1762 
1763     ASSERT( pFollowRow, "SwFrm::IsInSplitTableRow() does not work" )
1764 
1765     return pFollowRow;
1766 }
1767 
1768 const SwRowFrm* SwFrm::IsInFollowFlowRow() const
1769 {
1770     ASSERT( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" )
1771 
1772     // find most upper row frame
1773     const SwFrm* pRow = this;
1774     while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) )
1775         pRow = pRow->GetUpper();
1776 
1777     if ( !pRow ) return NULL;
1778 
1779     ASSERT( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" )
1780 
1781     const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
1782 
1783     const SwTabFrm* pMaster = pTab->IsFollow() ? pTab->FindMaster() : 0;
1784 
1785     if ( !pMaster || !pMaster->HasFollowFlowLine() )
1786         return NULL;
1787 
1788     const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow();
1789     const bool bIsInFirstLine = ( pTmp == pRow );
1790 
1791     if ( !bIsInFirstLine )
1792         return NULL;
1793 
1794     const SwRowFrm* pMasterRow = static_cast<const SwRowFrm*>(pMaster->GetLastLower());
1795     return pMasterRow;
1796 }
1797 
1798 bool SwFrm::IsInBalancedSection() const
1799 {
1800     bool bRet = false;
1801 
1802     if ( IsInSct() )
1803     {
1804         const SwSectionFrm* pSectionFrm = FindSctFrm();
1805         if ( pSectionFrm )
1806             bRet = pSectionFrm->IsBalancedSection();
1807     }
1808     return bRet;
1809 }
1810 
1811 /*
1812  * SwLayoutFrm::GetLastLower()
1813  */
1814 const SwFrm* SwLayoutFrm::GetLastLower() const
1815 {
1816     const SwFrm* pRet = Lower();
1817     if ( !pRet )
1818         return 0;
1819     while ( pRet->GetNext() )
1820         pRet = pRet->GetNext();
1821     return pRet;
1822 }
1823