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