xref: /aoo4110/main/sw/source/core/layout/findfrm.cxx (revision b1cdbd2c)
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