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