xref: /trunk/main/sw/source/core/layout/findfrm.cxx (revision 56b35d86)
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 //UUUU
getSdrAllFillAttributesHelper() const662 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.
lcl_NextFrm(SwFrm * pFrm)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 
_FindNext()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>
_FindNextCnt(const bool _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 */
_FindPrevCnt(const bool _bInSameFtn)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 
_FindPrev()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 
ImplInvalidateNextPos(sal_Bool bNoFtn)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 */
InvalidateNextPrtArea()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 
lcl_IsInColSct(const SwFrm * pUp)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 
IsMoveable(const SwLayoutFrm * _pLayoutFrm) const1331 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 |*************************************************************************/
SetInfFlags()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 
SetDirFlags(sal_Bool bVert)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 
GetNextCellLeaf(MakePageType)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 
GetPrevCellLeaf(MakePageType)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 
lcl_FindCorrespondingCellFrm(const SwRowFrm & rOrigRow,const SwCellFrm & rOrigCell,const SwRowFrm & rCorrRow,bool bInFollow)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:
GetFollowCell() const1555 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
GetPreviousCell() const1604 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
FindStartEndOfRowSpanCell(bool bStart,bool bCurrentTableOnly) const1645 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 
IsInSplitTableRow() const1734 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 
IsInFollowFlowRow() const1768 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 
IsInBalancedSection() const1798 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  */
GetLastLower() const1814 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