Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "pagefrm.hxx"
21 : #include "rootfrm.hxx"
22 : #include <cellfrm.hxx>
23 : #include <rowfrm.hxx>
24 : #include <swtable.hxx>
25 :
26 : #include "tabfrm.hxx"
27 : #include "sectfrm.hxx"
28 : #include "flyfrms.hxx"
29 : #include "ftnfrm.hxx"
30 : #include "txtftn.hxx"
31 : #include "fmtftn.hxx"
32 : #include <txtfrm.hxx>
33 : #include <switerator.hxx>
34 :
35 : /// Searches the first CntntFrm in BodyText below the page.
36 0 : SwLayoutFrm *SwFtnBossFrm::FindBodyCont()
37 : {
38 0 : SwFrm *pLay = Lower();
39 0 : while ( pLay && !pLay->IsBodyFrm() )
40 0 : pLay = pLay->GetNext();
41 0 : return (SwLayoutFrm*)pLay;
42 : }
43 :
44 : /// Searches the last CntntFrm in BodyText below the page.
45 0 : SwCntntFrm *SwPageFrm::FindLastBodyCntnt()
46 : {
47 0 : SwCntntFrm *pRet = FindFirstBodyCntnt();
48 0 : SwCntntFrm *pNxt = pRet;
49 0 : while ( pNxt && pNxt->IsInDocBody() && IsAnLower( pNxt ) )
50 0 : { pRet = pNxt;
51 0 : pNxt = pNxt->FindNextCnt();
52 : }
53 0 : return pRet;
54 : }
55 :
56 : /**
57 : * Checks if the frame contains one or more CntntFrm's anywhere in his
58 : * subsidiary structure; if so the first found CntntFrm is returned.
59 : */
60 0 : const SwCntntFrm *SwLayoutFrm::ContainsCntnt() const
61 : {
62 : //Search downwards the layout leaf and if there is no content, jump to the
63 : //next leaf until content is found or we leave "this".
64 : //Sections: Cntnt next to sections would not be found this way (empty
65 : //sections directly next to CntntFrm) therefore we need to recursively
66 : //search for them even if it's more complex.
67 :
68 0 : const SwLayoutFrm *pLayLeaf = this;
69 0 : do
70 : {
71 0 : while ( (!pLayLeaf->IsSctFrm() || pLayLeaf == this ) &&
72 0 : pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrm() )
73 0 : pLayLeaf = (SwLayoutFrm*)pLayLeaf->Lower();
74 :
75 0 : if( pLayLeaf->IsSctFrm() && pLayLeaf != this )
76 : {
77 0 : const SwCntntFrm *pCnt = pLayLeaf->ContainsCntnt();
78 0 : if( pCnt )
79 0 : return pCnt;
80 0 : if( pLayLeaf->GetNext() )
81 : {
82 0 : if( pLayLeaf->GetNext()->IsLayoutFrm() )
83 : {
84 0 : pLayLeaf = (SwLayoutFrm*)pLayLeaf->GetNext();
85 0 : continue;
86 : }
87 : else
88 0 : return (SwCntntFrm*)pLayLeaf->GetNext();
89 : }
90 : }
91 0 : else if ( pLayLeaf->Lower() )
92 0 : return (SwCntntFrm*)pLayLeaf->Lower();
93 :
94 0 : pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
95 0 : if( !IsAnLower( pLayLeaf) )
96 0 : return 0;
97 : } while( pLayLeaf );
98 0 : return 0;
99 : }
100 :
101 : /**
102 : * Calls ContainsAny first to reach the innermost cell. From there we walk back
103 : * up to the first SwCellFrm. Since we use SectionFrms, ContainsCntnt()->GetUpper()
104 : * is not enough anymore.
105 : */
106 0 : const SwCellFrm *SwLayoutFrm::FirstCell() const
107 : {
108 0 : const SwFrm* pCnt = ContainsAny();
109 0 : while( pCnt && !pCnt->IsCellFrm() )
110 0 : pCnt = pCnt->GetUpper();
111 0 : return (const SwCellFrm*)pCnt;
112 : }
113 :
114 : /** return CntntFrms, sections, and tables.
115 : *
116 : * @param _bInvestigateFtnForSections controls investigation of content of footnotes for sections.
117 : * @see ContainsCntnt
118 : */
119 0 : const SwFrm *SwLayoutFrm::ContainsAny( const bool _bInvestigateFtnForSections ) const
120 : {
121 : //Search downwards the layout leaf and if there is no content, jump to the
122 : //next leaf until content is found, we leave "this" or until we found
123 : //a SectionFrm or a TabFrm.
124 :
125 0 : const SwLayoutFrm *pLayLeaf = this;
126 : // #130797#
127 0 : const bool bNoFtn = IsSctFrm() && !_bInvestigateFtnForSections;
128 0 : do
129 : {
130 0 : while ( ( (!pLayLeaf->IsSctFrm() && !pLayLeaf->IsTabFrm())
131 0 : || pLayLeaf == this ) &&
132 0 : pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrm() )
133 0 : pLayLeaf = (SwLayoutFrm*)pLayLeaf->Lower();
134 :
135 0 : if( ( pLayLeaf->IsTabFrm() || pLayLeaf->IsSctFrm() )
136 0 : && pLayLeaf != this )
137 : {
138 : // Now we also return "deleted" SectionFrms so they can be
139 : // maintained on SaveCntnt and RestoreCntnt
140 0 : return pLayLeaf;
141 : }
142 0 : else if ( pLayLeaf->Lower() )
143 0 : return (SwCntntFrm*)pLayLeaf->Lower();
144 :
145 0 : pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
146 0 : if( bNoFtn && pLayLeaf && pLayLeaf->IsInFtn() )
147 : {
148 0 : do
149 : {
150 0 : pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
151 0 : } while( pLayLeaf && pLayLeaf->IsInFtn() );
152 : }
153 0 : if( !IsAnLower( pLayLeaf) )
154 0 : return 0;
155 : } while( pLayLeaf );
156 0 : return 0;
157 : }
158 :
159 0 : const SwFrm* SwFrm::GetLower() const
160 : {
161 0 : return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0;
162 : }
163 :
164 0 : SwFrm* SwFrm::GetLower()
165 : {
166 0 : return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0;
167 : }
168 :
169 0 : sal_Bool SwLayoutFrm::IsAnLower( const SwFrm *pAssumed ) const
170 : {
171 0 : const SwFrm *pUp = pAssumed;
172 0 : while ( pUp )
173 : {
174 0 : if ( pUp == this )
175 0 : return sal_True;
176 0 : if ( pUp->IsFlyFrm() )
177 0 : pUp = ((SwFlyFrm*)pUp)->GetAnchorFrm();
178 : else
179 0 : pUp = pUp->GetUpper();
180 : }
181 0 : return sal_False;
182 : }
183 :
184 : /** method to check relative position of layout frame to
185 : a given layout frame.
186 :
187 : OD 08.11.2002 - refactoring of pseudo-local method <lcl_Apres(..)> in
188 : <txtftn.cxx> for #104840#.
189 :
190 : @param _aCheckRefLayFrm
191 : constant reference of an instance of class <SwLayoutFrm> which
192 : is used as the reference for the relative position check.
193 :
194 : @return true, if <this> is positioned before the layout frame <p>
195 : */
196 0 : bool SwLayoutFrm::IsBefore( const SwLayoutFrm* _pCheckRefLayFrm ) const
197 : {
198 : OSL_ENSURE( !IsRootFrm() , "<IsBefore> called at a <SwRootFrm>.");
199 : OSL_ENSURE( !_pCheckRefLayFrm->IsRootFrm() , "<IsBefore> called with a <SwRootFrm>.");
200 :
201 : bool bReturn;
202 :
203 : // check, if on different pages
204 0 : const SwPageFrm *pMyPage = FindPageFrm();
205 0 : const SwPageFrm *pCheckRefPage = _pCheckRefLayFrm->FindPageFrm();
206 0 : if( pMyPage != pCheckRefPage )
207 : {
208 : // being on different page as check reference
209 0 : bReturn = pMyPage->GetPhyPageNum() < pCheckRefPage->GetPhyPageNum();
210 : }
211 : else
212 : {
213 : // being on same page as check reference
214 : // --> search my supreme parent <pUp>, which doesn't contain check reference.
215 0 : const SwLayoutFrm* pUp = this;
216 0 : while ( pUp->GetUpper() &&
217 0 : !pUp->GetUpper()->IsAnLower( _pCheckRefLayFrm )
218 : )
219 0 : pUp = pUp->GetUpper();
220 0 : if( !pUp->GetUpper() )
221 : {
222 : // can occur, if <this> is a fly frm
223 0 : bReturn = false;
224 : }
225 : else
226 : {
227 : // travel through the next's of <pUp> and check if one of these
228 : // contain the check reference.
229 0 : SwLayoutFrm* pUpNext = (SwLayoutFrm*)pUp->GetNext();
230 0 : while ( pUpNext &&
231 0 : !pUpNext->IsAnLower( _pCheckRefLayFrm ) )
232 : {
233 0 : pUpNext = (SwLayoutFrm*)pUpNext->GetNext();
234 : }
235 0 : bReturn = pUpNext != 0;
236 : }
237 : }
238 :
239 0 : return bReturn;
240 : }
241 :
242 : // Local helper functions for GetNextLayoutLeaf
243 :
244 0 : static const SwFrm* lcl_FindLayoutFrame( const SwFrm* pFrm, bool bNext )
245 : {
246 0 : const SwFrm* pRet = 0;
247 0 : if ( pFrm->IsFlyFrm() )
248 0 : pRet = bNext ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink();
249 : else
250 0 : pRet = bNext ? pFrm->GetNext() : pFrm->GetPrev();
251 :
252 0 : return pRet;
253 : }
254 :
255 0 : static const SwFrm* lcl_GetLower( const SwFrm* pFrm, bool bFwd )
256 : {
257 0 : if ( !pFrm->IsLayoutFrm() )
258 0 : return 0;
259 :
260 : return bFwd ?
261 : static_cast<const SwLayoutFrm*>(pFrm)->Lower() :
262 0 : static_cast<const SwLayoutFrm*>(pFrm)->GetLastLower();
263 : }
264 :
265 : /**
266 : * Finds the next layout leaf. This is a layout frame, which does not
267 : * have a lower which is a LayoutFrame. That means, pLower can be 0 or a
268 : * content frame.
269 : *
270 : * However, pLower may be a TabFrm
271 : */
272 0 : const SwLayoutFrm *SwFrm::ImplGetNextLayoutLeaf( bool bFwd ) const
273 : {
274 0 : const SwFrm *pFrm = this;
275 0 : const SwLayoutFrm *pLayoutFrm = 0;
276 0 : const SwFrm *p = 0;
277 0 : bool bGoingUp = !bFwd; // false for forward, true for backward
278 0 : do {
279 :
280 0 : bool bGoingFwdOrBwd = false;
281 :
282 0 : bool bGoingDown = ( !bGoingUp && ( 0 != (p = lcl_GetLower( pFrm, bFwd ) ) ) );
283 0 : if ( !bGoingDown )
284 : {
285 : // I cannot go down, because either I'm currently going up or
286 : // because the is no lower.
287 : // I'll try to go forward:
288 0 : bGoingFwdOrBwd = (0 != (p = lcl_FindLayoutFrame( pFrm, bFwd ) ) );
289 0 : if ( !bGoingFwdOrBwd )
290 : {
291 : // I cannot go forward, because there is no next frame.
292 : // I'll try to go up:
293 0 : bGoingUp = (0 != (p = pFrm->GetUpper() ) );
294 0 : if ( !bGoingUp )
295 : {
296 : // I cannot go up, because there is no upper frame.
297 0 : return 0;
298 : }
299 : }
300 : }
301 :
302 : // If I could not go down or forward, I'll have to go up
303 0 : bGoingUp = !bGoingFwdOrBwd && !bGoingDown;
304 :
305 0 : pFrm = p;
306 0 : p = lcl_GetLower( pFrm, true );
307 :
308 0 : } while( ( p && !p->IsFlowFrm() ) ||
309 0 : pFrm == this ||
310 0 : 0 == ( pLayoutFrm = pFrm->IsLayoutFrm() ? (SwLayoutFrm*)pFrm : 0 ) ||
311 0 : pLayoutFrm->IsAnLower( this ) );
312 :
313 0 : return pLayoutFrm;
314 : }
315 :
316 : /**
317 : * Walk back inside the tree: grab the subordinate Frm if one exists and the
318 : * last step was not moving up a level (this would lead to an infinite up/down
319 : * loop!). With this we ensure that during walking back we search through all
320 : * sub trees. If we walked downwards we have to go to the end of the chain first
321 : * because we go backwards from the last Frm inside another Frm. Walking
322 : * forward works the same.
323 : *
324 : * @warning fixes here may also need to be applied to the @{lcl_NextFrm} method above
325 : */
326 0 : const SwCntntFrm* SwCntntFrm::ImplGetNextCntntFrm( bool bFwd ) const
327 : {
328 0 : const SwFrm *pFrm = this;
329 : // #100926#
330 0 : SwCntntFrm *pCntntFrm = 0;
331 0 : bool bGoingUp = false;
332 0 : do {
333 0 : const SwFrm *p = 0;
334 0 : bool bGoingFwdOrBwd = false;
335 :
336 0 : bool bGoingDown = ( !bGoingUp && ( 0 != ( p = lcl_GetLower( pFrm, true ) ) ) );
337 0 : if ( !bGoingDown )
338 : {
339 0 : bGoingFwdOrBwd = ( 0 != ( p = lcl_FindLayoutFrame( pFrm, bFwd ) ) );
340 0 : if ( !bGoingFwdOrBwd )
341 : {
342 0 : bGoingUp = ( 0 != ( p = pFrm->GetUpper() ) );
343 0 : if ( !bGoingUp )
344 : {
345 0 : return 0;
346 : }
347 : }
348 : }
349 :
350 0 : bGoingUp = !(bGoingFwdOrBwd || bGoingDown);
351 :
352 0 : if ( !bFwd )
353 : {
354 0 : if( bGoingDown && p )
355 0 : while ( p->GetNext() )
356 0 : p = p->GetNext();
357 : }
358 :
359 0 : pFrm = p;
360 0 : } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
361 :
362 0 : return pCntntFrm;
363 : }
364 :
365 0 : SwPageFrm* SwFrm::FindPageFrm()
366 : {
367 0 : SwFrm *pRet = this;
368 0 : while ( pRet && !pRet->IsPageFrm() )
369 : {
370 0 : if ( pRet->GetUpper() )
371 0 : pRet = pRet->GetUpper();
372 0 : else if ( pRet->IsFlyFrm() )
373 : {
374 : // #i28701# - use new method <GetPageFrm()>
375 0 : if ( static_cast<SwFlyFrm*>(pRet)->GetPageFrm() )
376 0 : pRet = static_cast<SwFlyFrm*>(pRet)->GetPageFrm();
377 : else
378 0 : pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm();
379 : }
380 : else
381 0 : return 0;
382 : }
383 0 : return (SwPageFrm*)pRet;
384 : }
385 :
386 0 : SwFtnBossFrm* SwFrm::FindFtnBossFrm( sal_Bool bFootnotes )
387 : {
388 0 : SwFrm *pRet = this;
389 : // Footnote bosses can't exist inside a table; also sections with columns
390 : // don't contain footnote texts there
391 0 : if( pRet->IsInTab() )
392 0 : pRet = pRet->FindTabFrm();
393 0 : while ( pRet && !pRet->IsFtnBossFrm() )
394 : {
395 0 : if ( pRet->GetUpper() )
396 0 : pRet = pRet->GetUpper();
397 0 : else if ( pRet->IsFlyFrm() )
398 : {
399 : // #i28701# - use new method <GetPageFrm()>
400 0 : if ( static_cast<SwFlyFrm*>(pRet)->GetPageFrm() )
401 0 : pRet = static_cast<SwFlyFrm*>(pRet)->GetPageFrm();
402 : else
403 0 : pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm();
404 : }
405 : else
406 0 : return 0;
407 : }
408 0 : if( bFootnotes && pRet && pRet->IsColumnFrm() &&
409 0 : !pRet->GetNext() && !pRet->GetPrev() )
410 : {
411 0 : SwSectionFrm* pSct = pRet->FindSctFrm();
412 : OSL_ENSURE( pSct, "FindFtnBossFrm: Single column outside section?" );
413 0 : if( !pSct->IsFtnAtEnd() )
414 0 : return pSct->FindFtnBossFrm( sal_True );
415 : }
416 0 : return (SwFtnBossFrm*)pRet;
417 : }
418 :
419 0 : SwTabFrm* SwFrm::ImplFindTabFrm()
420 : {
421 0 : SwFrm *pRet = this;
422 0 : while ( !pRet->IsTabFrm() )
423 : {
424 0 : pRet = pRet->GetUpper();
425 0 : if ( !pRet )
426 0 : return 0;
427 : }
428 0 : return (SwTabFrm*)pRet;
429 : }
430 :
431 0 : SwSectionFrm* SwFrm::ImplFindSctFrm()
432 : {
433 0 : SwFrm *pRet = this;
434 0 : while ( !pRet->IsSctFrm() )
435 : {
436 0 : pRet = pRet->GetUpper();
437 0 : if ( !pRet )
438 0 : return 0;
439 : }
440 0 : return (SwSectionFrm*)pRet;
441 : }
442 :
443 0 : SwFtnFrm *SwFrm::ImplFindFtnFrm()
444 : {
445 0 : SwFrm *pRet = this;
446 0 : while ( !pRet->IsFtnFrm() )
447 : {
448 0 : pRet = pRet->GetUpper();
449 0 : if ( !pRet )
450 0 : return 0;
451 : }
452 0 : return (SwFtnFrm*)pRet;
453 : }
454 :
455 0 : SwFlyFrm *SwFrm::ImplFindFlyFrm()
456 : {
457 0 : const SwFrm *pRet = this;
458 0 : do
459 : {
460 0 : if ( pRet->IsFlyFrm() )
461 0 : return (SwFlyFrm*)pRet;
462 : else
463 0 : pRet = pRet->GetUpper();
464 : } while ( pRet );
465 0 : return 0;
466 : }
467 :
468 0 : SwFrm *SwFrm::FindColFrm()
469 : {
470 0 : SwFrm *pFrm = this;
471 0 : do
472 0 : { pFrm = pFrm->GetUpper();
473 0 : } while ( pFrm && !pFrm->IsColumnFrm() );
474 0 : return pFrm;
475 : }
476 :
477 0 : SwRowFrm *SwFrm::FindRowFrm()
478 : {
479 0 : SwFrm *pFrm = this;
480 0 : do
481 0 : { pFrm = pFrm->GetUpper();
482 0 : } while ( pFrm && !pFrm->IsRowFrm() );
483 0 : return dynamic_cast< SwRowFrm* >( pFrm );
484 : }
485 :
486 0 : SwFrm* SwFrm::FindFooterOrHeader()
487 : {
488 0 : SwFrm* pRet = this;
489 0 : do
490 0 : { if ( pRet->GetType() & 0x0018 ) //header and footer
491 0 : return pRet;
492 0 : else if ( pRet->GetUpper() )
493 0 : pRet = pRet->GetUpper();
494 0 : else if ( pRet->IsFlyFrm() )
495 0 : pRet = ((SwFlyFrm*)pRet)->AnchorFrm();
496 : else
497 0 : return 0;
498 : } while ( pRet );
499 0 : return pRet;
500 : }
501 :
502 0 : const SwFtnFrm* SwFtnContFrm::FindFootNote() const
503 : {
504 0 : const SwFtnFrm* pRet = (SwFtnFrm*)Lower();
505 0 : if( pRet && !pRet->GetAttr()->GetFtn().IsEndNote() )
506 0 : return pRet;
507 0 : return NULL;
508 : }
509 :
510 0 : const SwPageFrm* SwRootFrm::GetPageAtPos( const Point& rPt, const Size* pSize, bool bExtend ) const
511 : {
512 0 : const SwPageFrm* pRet = 0;
513 :
514 0 : SwRect aRect;
515 0 : if ( pSize )
516 : {
517 0 : aRect.Pos() = rPt;
518 0 : aRect.SSize() = *pSize;
519 : }
520 :
521 0 : const SwFrm* pPage = Lower();
522 :
523 0 : if ( !bExtend )
524 : {
525 0 : if( !Frm().IsInside( rPt ) )
526 0 : return 0;
527 :
528 : // skip pages above point:
529 0 : while( pPage && rPt.Y() > pPage->Frm().Bottom() )
530 0 : pPage = pPage->GetNext();
531 : }
532 :
533 : OSL_ENSURE( GetPageNum() <= maPageRects.size(), "number of pages differes from page rect array size" );
534 0 : sal_uInt16 nPageIdx = 0;
535 :
536 0 : while ( pPage && !pRet )
537 : {
538 0 : const SwRect& rBoundRect = bExtend ? maPageRects[ nPageIdx++ ] : pPage->Frm();
539 :
540 0 : if ( (!pSize && rBoundRect.IsInside(rPt)) ||
541 0 : (pSize && rBoundRect.IsOver(aRect)) )
542 : {
543 0 : pRet = static_cast<const SwPageFrm*>(pPage);
544 : }
545 :
546 0 : pPage = pPage->GetNext();
547 : }
548 :
549 0 : return pRet;
550 : }
551 :
552 0 : const SwAttrSet* SwFrm::GetAttrSet() const
553 : {
554 0 : if ( IsCntntFrm() )
555 0 : return &((const SwCntntFrm*)this)->GetNode()->GetSwAttrSet();
556 : else
557 0 : return &((const SwLayoutFrm*)this)->GetFmt()->GetAttrSet();
558 : }
559 :
560 : /*************************************************************************
561 : |*
562 : |* SwFrm::_FindNext(), _FindPrev(), InvalidateNextPos()
563 : |* _FindNextCnt() visits tables and sections and only returns SwCntntFrms.
564 : |*
565 : |* Description Invalidates the position of the next frame.
566 : |* This is the direct successor or in case of CntntFrms the next
567 : |* CntntFrm which sits in the same flow as I do:
568 : |* - body,
569 : |* - footnote,
570 : |* - in headers/footers the notification only needs to be forwarded
571 : |* inside the section
572 : |* - same for Flys
573 : |* - Cntnts in tabs remain only inside their cell
574 : |* - in principle tables behave exactly like the Cntnts
575 : |* - sections also
576 : |*************************************************************************/
577 :
578 : // This helper function is an equivalent to the ImplGetNextCntntFrm() method,
579 : // besides ContentFrames this function also returns TabFrms and SectionFrms.
580 0 : static SwFrm* lcl_NextFrm( SwFrm* pFrm )
581 : {
582 0 : SwFrm *pRet = 0;
583 0 : bool bGoingUp = false;
584 0 : do {
585 0 : SwFrm *p = 0;
586 :
587 0 : bool bGoingFwd = false;
588 0 : bool bGoingDown = (!bGoingUp && ( 0 != (p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0)));
589 :
590 0 : if( !bGoingDown )
591 : {
592 0 : bGoingFwd = (0 != (p = ( pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->GetNextLink() : pFrm->GetNext())));
593 0 : if ( !bGoingFwd )
594 : {
595 0 : bGoingUp = (0 != (p = pFrm->GetUpper()));
596 0 : if ( !bGoingUp )
597 : {
598 0 : return 0;
599 : }
600 : }
601 : }
602 0 : bGoingUp = !(bGoingFwd || bGoingDown);
603 0 : pFrm = p;
604 0 : } while ( 0 == (pRet = ( ( pFrm->IsCntntFrm() || ( !bGoingUp &&
605 0 : ( pFrm->IsTabFrm() || pFrm->IsSctFrm() ) ) )? pFrm : 0 ) ) );
606 0 : return pRet;
607 : }
608 :
609 0 : SwFrm *SwFrm::_FindNext()
610 : {
611 0 : bool bIgnoreTab = false;
612 0 : SwFrm *pThis = this;
613 :
614 0 : if ( IsTabFrm() )
615 : {
616 : //The last Cntnt of the table gets picked up and his follower is
617 : //returned. To be able to deactivate the special case for tables
618 : //(see below) bIgnoreTab will be set.
619 0 : if ( ((SwTabFrm*)this)->GetFollow() )
620 0 : return ((SwTabFrm*)this)->GetFollow();
621 :
622 0 : pThis = ((SwTabFrm*)this)->FindLastCntnt();
623 0 : if ( !pThis )
624 0 : pThis = this;
625 0 : bIgnoreTab = true;
626 : }
627 0 : else if ( IsSctFrm() )
628 : {
629 : //The last Cntnt of the section gets picked and his follower is returned.
630 0 : if ( ((SwSectionFrm*)this)->GetFollow() )
631 0 : return ((SwSectionFrm*)this)->GetFollow();
632 :
633 0 : pThis = ((SwSectionFrm*)this)->FindLastCntnt();
634 0 : if ( !pThis )
635 0 : pThis = this;
636 : }
637 0 : else if ( IsCntntFrm() )
638 : {
639 0 : if( ((SwCntntFrm*)this)->GetFollow() )
640 0 : return ((SwCntntFrm*)this)->GetFollow();
641 : }
642 0 : else if ( IsRowFrm() )
643 : {
644 0 : SwFrm* pMyUpper = GetUpper();
645 0 : if ( pMyUpper->IsTabFrm() && ((SwTabFrm*)pMyUpper)->GetFollow() )
646 0 : return ((SwTabFrm*)pMyUpper)->GetFollow()->GetLower();
647 0 : else return NULL;
648 : }
649 : else
650 0 : return NULL;
651 :
652 0 : SwFrm* pRet = NULL;
653 0 : const sal_Bool bFtn = pThis->IsInFtn();
654 0 : if ( !bIgnoreTab && pThis->IsInTab() )
655 : {
656 0 : SwLayoutFrm *pUp = pThis->GetUpper();
657 0 : while ( !pUp->IsCellFrm() )
658 0 : pUp = pUp->GetUpper();
659 : OSL_ENSURE( pUp, "Cntnt in Tabelle aber nicht in Zelle." );
660 0 : SwFrm* pNxt = ((SwCellFrm*)pUp)->GetFollowCell();
661 0 : if ( pNxt )
662 0 : pNxt = ((SwCellFrm*)pNxt)->ContainsCntnt();
663 0 : if ( !pNxt )
664 : {
665 0 : pNxt = lcl_NextFrm( pThis );
666 0 : if ( pUp->IsAnLower( pNxt ) )
667 0 : pRet = pNxt;
668 : }
669 : else
670 0 : pRet = pNxt;
671 : }
672 : else
673 : {
674 0 : const bool bBody = pThis->IsInDocBody();
675 0 : SwFrm *pNxtCnt = lcl_NextFrm( pThis );
676 0 : if ( pNxtCnt )
677 : {
678 0 : if ( bBody || bFtn )
679 : {
680 0 : while ( pNxtCnt )
681 : {
682 : // OD 02.04.2003 #108446# - check for endnote, only if found
683 : // next content isn't contained in a section, that collect its
684 : // endnotes at its end.
685 0 : bool bEndn = IsInSct() && !IsSctFrm() &&
686 0 : ( !pNxtCnt->IsInSct() ||
687 0 : !pNxtCnt->FindSctFrm()->IsEndnAtEnd()
688 0 : );
689 0 : if ( ( bBody && pNxtCnt->IsInDocBody() ) ||
690 0 : ( pNxtCnt->IsInFtn() &&
691 0 : ( bFtn ||
692 0 : ( bEndn && pNxtCnt->FindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
693 : )
694 : )
695 : )
696 : {
697 0 : pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
698 0 : : (SwFrm*)pNxtCnt;
699 0 : break;
700 : }
701 0 : pNxtCnt = lcl_NextFrm( pNxtCnt );
702 0 : }
703 : }
704 0 : else if ( pThis->IsInFly() )
705 : {
706 0 : pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
707 0 : : (SwFrm*)pNxtCnt;
708 : }
709 : else //footer-/or header section
710 : {
711 0 : const SwFrm *pUp = pThis->GetUpper();
712 0 : const SwFrm *pCntUp = pNxtCnt->GetUpper();
713 0 : while ( pUp && pUp->GetUpper() &&
714 0 : !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
715 0 : pUp = pUp->GetUpper();
716 0 : while ( pCntUp && pCntUp->GetUpper() &&
717 0 : !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() )
718 0 : pCntUp = pCntUp->GetUpper();
719 0 : if ( pCntUp == pUp )
720 : {
721 0 : pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
722 0 : : (SwFrm*)pNxtCnt;
723 : }
724 : }
725 : }
726 : }
727 0 : if( pRet && pRet->IsInSct() )
728 : {
729 0 : SwSectionFrm* pSct = pRet->FindSctFrm();
730 : //Footnotes in frames with columns must not return the section which
731 : //contains the footnote
732 0 : if( !pSct->IsAnLower( this ) &&
733 0 : (!bFtn || pSct->IsInFtn() ) )
734 0 : return pSct;
735 : }
736 0 : return pRet;
737 : }
738 :
739 : // #i27138# - add parameter <_bInSameFtn>
740 0 : SwCntntFrm *SwFrm::_FindNextCnt( const bool _bInSameFtn )
741 : {
742 0 : SwFrm *pThis = this;
743 :
744 0 : if ( IsTabFrm() )
745 : {
746 0 : if ( ((SwTabFrm*)this)->GetFollow() )
747 : {
748 0 : pThis = ((SwTabFrm*)this)->GetFollow()->ContainsCntnt();
749 0 : if( pThis )
750 0 : return (SwCntntFrm*)pThis;
751 : }
752 0 : pThis = ((SwTabFrm*)this)->FindLastCntnt();
753 0 : if ( !pThis )
754 0 : return 0;
755 : }
756 0 : else if ( IsSctFrm() )
757 : {
758 0 : if ( ((SwSectionFrm*)this)->GetFollow() )
759 : {
760 0 : pThis = ((SwSectionFrm*)this)->GetFollow()->ContainsCntnt();
761 0 : if( pThis )
762 0 : return (SwCntntFrm*)pThis;
763 : }
764 0 : pThis = ((SwSectionFrm*)this)->FindLastCntnt();
765 0 : if ( !pThis )
766 0 : return 0;
767 : }
768 0 : else if ( IsCntntFrm() && ((SwCntntFrm*)this)->GetFollow() )
769 0 : return ((SwCntntFrm*)this)->GetFollow();
770 :
771 0 : if ( pThis->IsCntntFrm() )
772 : {
773 0 : const bool bBody = pThis->IsInDocBody();
774 0 : const sal_Bool bFtn = pThis->IsInFtn();
775 0 : SwCntntFrm *pNxtCnt = ((SwCntntFrm*)pThis)->GetNextCntntFrm();
776 0 : if ( pNxtCnt )
777 : {
778 : // #i27138#
779 0 : if ( bBody || ( bFtn && !_bInSameFtn ) )
780 : {
781 : // handling for environments 'footnotes' and 'document body frames':
782 0 : while ( pNxtCnt )
783 : {
784 0 : if ( (bBody && pNxtCnt->IsInDocBody()) ||
785 0 : (bFtn && pNxtCnt->IsInFtn()) )
786 0 : return pNxtCnt;
787 0 : pNxtCnt = pNxtCnt->GetNextCntntFrm();
788 : }
789 : }
790 : // #i27138#
791 0 : else if ( bFtn && _bInSameFtn )
792 : {
793 : // handling for environments 'each footnote':
794 : // Assure that found next content frame belongs to the same footnotes
795 0 : const SwFtnFrm* pFtnFrmOfNext( pNxtCnt->FindFtnFrm() );
796 0 : const SwFtnFrm* pFtnFrmOfCurr( pThis->FindFtnFrm() );
797 : OSL_ENSURE( pFtnFrmOfCurr,
798 : "<SwFrm::_FindNextCnt() - unknown layout situation: current frame has to have an upper footnote frame." );
799 0 : if ( pFtnFrmOfNext == pFtnFrmOfCurr )
800 : {
801 0 : return pNxtCnt;
802 : }
803 0 : else if ( pFtnFrmOfCurr->GetFollow() )
804 : {
805 : // next content frame has to be the first content frame
806 : // in the follow footnote, which contains a content frame.
807 : SwFtnFrm* pFollowFtnFrmOfCurr(
808 0 : const_cast<SwFtnFrm*>(pFtnFrmOfCurr) );
809 0 : pNxtCnt = 0L;
810 0 : do {
811 0 : pFollowFtnFrmOfCurr = pFollowFtnFrmOfCurr->GetFollow();
812 0 : pNxtCnt = pFollowFtnFrmOfCurr->ContainsCntnt();
813 0 : } while ( !pNxtCnt && pFollowFtnFrmOfCurr->GetFollow() );
814 0 : return pNxtCnt;
815 : }
816 : else
817 : {
818 : // current content frame is the last content frame in the
819 : // footnote - no next content frame exists.
820 0 : return 0L;
821 : }
822 : }
823 0 : else if ( pThis->IsInFly() )
824 : // handling for environments 'unlinked fly frame' and
825 : // 'group of linked fly frames':
826 0 : return pNxtCnt;
827 : else
828 : {
829 : // handling for environments 'page header' and 'page footer':
830 0 : const SwFrm *pUp = pThis->GetUpper();
831 0 : const SwFrm *pCntUp = pNxtCnt->GetUpper();
832 0 : while ( pUp && pUp->GetUpper() &&
833 0 : !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
834 0 : pUp = pUp->GetUpper();
835 0 : while ( pCntUp && pCntUp->GetUpper() &&
836 0 : !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() )
837 0 : pCntUp = pCntUp->GetUpper();
838 0 : if ( pCntUp == pUp )
839 0 : return pNxtCnt;
840 : }
841 : }
842 : }
843 0 : return 0;
844 : }
845 :
846 : /** method to determine previous content frame in the same environment
847 : for a flow frame (content frame, table frame, section frame)
848 :
849 : OD 2005-11-30 #i27138#
850 : */
851 0 : SwCntntFrm* SwFrm::_FindPrevCnt( const bool _bInSameFtn )
852 : {
853 0 : if ( !IsFlowFrm() )
854 : {
855 : // nothing to do, if current frame isn't a flow frame.
856 0 : return 0L;
857 : }
858 :
859 0 : SwCntntFrm* pPrevCntntFrm( 0L );
860 :
861 : // Because method <SwCntntFrm::GetPrevCntntFrm()> is used to travel
862 : // through the layout, a content frame, at which the travel starts, is needed.
863 0 : SwCntntFrm* pCurrCntntFrm = dynamic_cast<SwCntntFrm*>(this);
864 :
865 : // perform shortcut, if current frame is a follow, and
866 : // determine <pCurrCntntFrm>, if current frame is a table or section frame
867 0 : if ( pCurrCntntFrm && pCurrCntntFrm->IsFollow() )
868 : {
869 : // previous content frame is its master content frame
870 0 : pPrevCntntFrm = pCurrCntntFrm->FindMaster();
871 : }
872 0 : else if ( IsTabFrm() )
873 : {
874 0 : SwTabFrm* pTabFrm( static_cast<SwTabFrm*>(this) );
875 0 : if ( pTabFrm->IsFollow() )
876 : {
877 : // previous content frame is the last content of its master table frame
878 0 : pPrevCntntFrm = pTabFrm->FindMaster()->FindLastCntnt();
879 : }
880 : else
881 : {
882 : // start content frame for the search is the first content frame of
883 : // the table frame.
884 0 : pCurrCntntFrm = pTabFrm->ContainsCntnt();
885 : }
886 : }
887 0 : else if ( IsSctFrm() )
888 : {
889 0 : SwSectionFrm* pSectFrm( static_cast<SwSectionFrm*>(this) );
890 0 : if ( pSectFrm->IsFollow() )
891 : {
892 : // previous content frame is the last content of its master section frame
893 0 : pPrevCntntFrm = pSectFrm->FindMaster()->FindLastCntnt();
894 : }
895 : else
896 : {
897 : // start content frame for the search is the first content frame of
898 : // the section frame.
899 0 : pCurrCntntFrm = pSectFrm->ContainsCntnt();
900 : }
901 : }
902 :
903 : // search for next content frame, depending on the environment, in which
904 : // the current frame is in.
905 0 : if ( !pPrevCntntFrm && pCurrCntntFrm )
906 : {
907 0 : pPrevCntntFrm = pCurrCntntFrm->GetPrevCntntFrm();
908 0 : if ( pPrevCntntFrm )
909 : {
910 0 : if ( pCurrCntntFrm->IsInFly() )
911 : {
912 : // handling for environments 'unlinked fly frame' and
913 : // 'group of linked fly frames':
914 : // Nothing to do, <pPrevCntntFrm> is the one
915 : }
916 : else
917 : {
918 0 : const bool bInDocBody = pCurrCntntFrm->IsInDocBody();
919 0 : const bool bInFtn = pCurrCntntFrm->IsInFtn();
920 0 : if ( bInDocBody || ( bInFtn && !_bInSameFtn ) )
921 : {
922 : // handling for environments 'footnotes' and 'document body frames':
923 : // Assure that found previous frame is also in one of these
924 : // environments. Otherwise, travel further
925 0 : while ( pPrevCntntFrm )
926 : {
927 0 : if ( ( bInDocBody && pPrevCntntFrm->IsInDocBody() ) ||
928 0 : ( bInFtn && pPrevCntntFrm->IsInFtn() ) )
929 : {
930 0 : break;
931 : }
932 0 : pPrevCntntFrm = pPrevCntntFrm->GetPrevCntntFrm();
933 : }
934 : }
935 0 : else if ( bInFtn && _bInSameFtn )
936 : {
937 : // handling for environments 'each footnote':
938 : // Assure that found next content frame belongs to the same footnotes
939 0 : const SwFtnFrm* pFtnFrmOfPrev( pPrevCntntFrm->FindFtnFrm() );
940 0 : const SwFtnFrm* pFtnFrmOfCurr( pCurrCntntFrm->FindFtnFrm() );
941 0 : if ( pFtnFrmOfPrev != pFtnFrmOfCurr )
942 : {
943 0 : if ( pFtnFrmOfCurr->GetMaster() )
944 : {
945 : SwFtnFrm* pMasterFtnFrmOfCurr(
946 0 : const_cast<SwFtnFrm*>(pFtnFrmOfCurr) );
947 0 : pPrevCntntFrm = 0L;
948 : // #146872#
949 : // correct wrong loop-condition
950 0 : do {
951 0 : pMasterFtnFrmOfCurr = pMasterFtnFrmOfCurr->GetMaster();
952 0 : pPrevCntntFrm = pMasterFtnFrmOfCurr->FindLastCntnt();
953 0 : } while ( !pPrevCntntFrm &&
954 0 : pMasterFtnFrmOfCurr->GetMaster() );
955 : }
956 : else
957 : {
958 : // current content frame is the first content in the
959 : // footnote - no previous content exists.
960 0 : pPrevCntntFrm = 0L;;
961 : }
962 0 : }
963 : }
964 : else
965 : {
966 : // handling for environments 'page header' and 'page footer':
967 : // Assure that found previous frame is also in the same
968 : // page header respectively page footer as <pCurrCntntFrm>
969 : // Note: At this point its clear, that <pCurrCntntFrm> has
970 : // to be inside a page header or page footer and that
971 : // neither <pCurrCntntFrm> nor <pPrevCntntFrm> are
972 : // inside a fly frame.
973 : // Thus, method <FindFooterOrHeader()> can be used.
974 : OSL_ENSURE( pCurrCntntFrm->FindFooterOrHeader(),
975 : "<SwFrm::_FindPrevCnt()> - unknown layout situation: current frame should be in page header or page footer" );
976 : OSL_ENSURE( !pPrevCntntFrm->IsInFly(),
977 : "<SwFrm::_FindPrevCnt()> - unknown layout situation: found previous frame should *not* be inside a fly frame." );
978 0 : if ( pPrevCntntFrm->FindFooterOrHeader() !=
979 0 : pCurrCntntFrm->FindFooterOrHeader() )
980 : {
981 0 : pPrevCntntFrm = 0L;
982 : }
983 : }
984 : }
985 : }
986 : }
987 :
988 0 : return pPrevCntntFrm;
989 : }
990 :
991 0 : SwFrm *SwFrm::_FindPrev()
992 : {
993 0 : bool bIgnoreTab = false;
994 0 : SwFrm *pThis = this;
995 :
996 0 : if ( IsTabFrm() )
997 : {
998 : //The first Cntnt of the table gets picked up and his predecessor is
999 : //returnd. To be able to deactivate the special case for tables
1000 : //(see below) bIgnoreTab will be set.
1001 0 : if ( ((SwTabFrm*)this)->IsFollow() )
1002 0 : return ((SwTabFrm*)this)->FindMaster();
1003 : else
1004 0 : pThis = ((SwTabFrm*)this)->ContainsCntnt();
1005 0 : bIgnoreTab = true;
1006 : }
1007 :
1008 0 : if ( pThis && pThis->IsCntntFrm() )
1009 : {
1010 0 : SwCntntFrm *pPrvCnt = ((SwCntntFrm*)pThis)->GetPrevCntntFrm();
1011 0 : if( !pPrvCnt )
1012 0 : return 0;
1013 0 : if ( !bIgnoreTab && pThis->IsInTab() )
1014 : {
1015 0 : SwLayoutFrm *pUp = pThis->GetUpper();
1016 0 : while ( !pUp->IsCellFrm() )
1017 0 : pUp = pUp->GetUpper();
1018 : OSL_ENSURE( pUp, "Cntnt in table but not in cell." );
1019 0 : if ( pUp->IsAnLower( pPrvCnt ) )
1020 0 : return pPrvCnt;
1021 : }
1022 : else
1023 : {
1024 : SwFrm* pRet;
1025 0 : const bool bBody = pThis->IsInDocBody();
1026 0 : const sal_Bool bFtn = bBody ? sal_False : pThis->IsInFtn();
1027 0 : if ( bBody || bFtn )
1028 : {
1029 0 : while ( pPrvCnt )
1030 : {
1031 0 : if ( (bBody && pPrvCnt->IsInDocBody()) ||
1032 0 : (bFtn && pPrvCnt->IsInFtn()) )
1033 : {
1034 0 : pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
1035 0 : : (SwFrm*)pPrvCnt;
1036 0 : return pRet;
1037 : }
1038 0 : pPrvCnt = pPrvCnt->GetPrevCntntFrm();
1039 : }
1040 : }
1041 0 : else if ( pThis->IsInFly() )
1042 : {
1043 0 : pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
1044 0 : : (SwFrm*)pPrvCnt;
1045 0 : return pRet;
1046 : }
1047 : else // footer or header or Fly
1048 : {
1049 0 : const SwFrm *pUp = pThis->GetUpper();
1050 0 : const SwFrm *pCntUp = pPrvCnt->GetUpper();
1051 0 : while ( pUp && pUp->GetUpper() &&
1052 0 : !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
1053 0 : pUp = pUp->GetUpper();
1054 0 : while ( pCntUp && pCntUp->GetUpper() )
1055 0 : pCntUp = pCntUp->GetUpper();
1056 0 : if ( pCntUp == pUp )
1057 : {
1058 0 : pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
1059 0 : : (SwFrm*)pPrvCnt;
1060 0 : return pRet;
1061 : }
1062 : }
1063 : }
1064 : }
1065 0 : return 0;
1066 : }
1067 :
1068 0 : void SwFrm::ImplInvalidateNextPos( sal_Bool bNoFtn )
1069 : {
1070 : SwFrm *pFrm;
1071 0 : if ( 0 != (pFrm = _FindNext()) )
1072 : {
1073 0 : if( pFrm->IsSctFrm() )
1074 : {
1075 0 : while( pFrm && pFrm->IsSctFrm() )
1076 : {
1077 0 : if( ((SwSectionFrm*)pFrm)->GetSection() )
1078 : {
1079 0 : SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny();
1080 0 : if( pTmp )
1081 0 : pTmp->InvalidatePos();
1082 0 : else if( !bNoFtn )
1083 0 : ((SwSectionFrm*)pFrm)->InvalidateFtnPos();
1084 0 : if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm )
1085 0 : pFrm->InvalidatePos();
1086 0 : return;
1087 : }
1088 0 : pFrm = pFrm->FindNext();
1089 : }
1090 0 : if( pFrm )
1091 : {
1092 0 : if ( pFrm->IsSctFrm())
1093 : {
1094 : // We need to invalidate the section's content so it gets
1095 : // the chance to flow to a different page.
1096 0 : SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny();
1097 0 : if( pTmp )
1098 0 : pTmp->InvalidatePos();
1099 0 : if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm )
1100 0 : pFrm->InvalidatePos();
1101 : }
1102 : else
1103 0 : pFrm->InvalidatePos();
1104 : }
1105 : }
1106 : else
1107 0 : pFrm->InvalidatePos();
1108 : }
1109 : }
1110 :
1111 : /** method to invalidate printing area of next frame
1112 :
1113 : OD 09.01.2004 #i11859#
1114 :
1115 : FME 2004-04-19 #i27145# Moved function from SwTxtFrm to SwFrm
1116 : */
1117 0 : void SwFrm::InvalidateNextPrtArea()
1118 : {
1119 : // determine next frame
1120 0 : SwFrm* pNextFrm = FindNext();
1121 : // skip empty section frames and hidden text frames
1122 : {
1123 0 : while ( pNextFrm &&
1124 0 : ( ( pNextFrm->IsSctFrm() &&
1125 0 : !static_cast<SwSectionFrm*>(pNextFrm)->GetSection() ) ||
1126 0 : ( pNextFrm->IsTxtFrm() &&
1127 0 : static_cast<SwTxtFrm*>(pNextFrm)->IsHiddenNow() ) ) )
1128 : {
1129 0 : pNextFrm = pNextFrm->FindNext();
1130 : }
1131 : }
1132 :
1133 : // Invalidate printing area of found next frame
1134 0 : if ( pNextFrm )
1135 : {
1136 0 : if ( pNextFrm->IsSctFrm() )
1137 : {
1138 : // Invalidate printing area of found section frame, if
1139 : // (1) this text frame isn't in a section OR
1140 : // (2) found section frame isn't a follow of the section frame this
1141 : // text frame is in.
1142 0 : if ( !IsInSct() || FindSctFrm()->GetFollow() != pNextFrm )
1143 : {
1144 0 : pNextFrm->InvalidatePrt();
1145 : }
1146 :
1147 : // Invalidate printing area of first content in found section.
1148 : SwFrm* pFstCntntOfSctFrm =
1149 0 : static_cast<SwSectionFrm*>(pNextFrm)->ContainsAny();
1150 0 : if ( pFstCntntOfSctFrm )
1151 : {
1152 0 : pFstCntntOfSctFrm->InvalidatePrt();
1153 : }
1154 : }
1155 : else
1156 : {
1157 0 : pNextFrm->InvalidatePrt();
1158 : }
1159 : }
1160 0 : }
1161 :
1162 : /// @returns true if the frame _directly_ sits in a section with columns
1163 : /// but not if it sits in a table which itself sits in a section with columns.
1164 0 : static bool lcl_IsInColSct( const SwFrm *pUp )
1165 : {
1166 0 : bool bRet = false;
1167 0 : while( pUp )
1168 : {
1169 0 : if( pUp->IsColumnFrm() )
1170 0 : bRet = true;
1171 0 : else if( pUp->IsSctFrm() )
1172 0 : return bRet;
1173 0 : else if( pUp->IsTabFrm() )
1174 0 : return false;
1175 0 : pUp = pUp->GetUpper();
1176 : }
1177 0 : return false;
1178 : }
1179 :
1180 : /** determine, if frame is moveable in given environment
1181 :
1182 : OD 08.08.2003 #110978#
1183 : method replaced 'old' method <sal_Bool IsMoveable() const>.
1184 : Determines, if frame is moveable in given environment. if no environment
1185 : is given (parameter _pLayoutFrm == 0L), the movability in the actual
1186 : environment (<this->GetUpper()) is checked.
1187 : */
1188 0 : bool SwFrm::IsMoveable( const SwLayoutFrm* _pLayoutFrm ) const
1189 : {
1190 0 : bool bRetVal = false;
1191 :
1192 0 : if ( !_pLayoutFrm )
1193 : {
1194 0 : _pLayoutFrm = GetUpper();
1195 : }
1196 :
1197 0 : if ( _pLayoutFrm && IsFlowFrm() )
1198 : {
1199 0 : if ( _pLayoutFrm->IsInSct() && lcl_IsInColSct( _pLayoutFrm ) )
1200 : {
1201 0 : bRetVal = true;
1202 : }
1203 0 : else if ( _pLayoutFrm->IsInFly() ||
1204 0 : _pLayoutFrm->IsInDocBody() ||
1205 0 : _pLayoutFrm->IsInFtn() )
1206 : {
1207 0 : if ( _pLayoutFrm->IsInTab() && !IsTabFrm() &&
1208 0 : ( !IsCntntFrm() || !const_cast<SwFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) ) )
1209 : {
1210 0 : bRetVal = false;
1211 : }
1212 : else
1213 : {
1214 0 : if ( _pLayoutFrm->IsInFly() )
1215 : {
1216 : // if fly frame has a follow (next linked fly frame),
1217 : // frame is moveable.
1218 0 : if ( const_cast<SwLayoutFrm*>(_pLayoutFrm)->FindFlyFrm()->GetNextLink() )
1219 : {
1220 0 : bRetVal = true;
1221 : }
1222 : else
1223 : {
1224 : // if environment is columned, frame is moveable, if
1225 : // it isn't in last column.
1226 : // search for column frame
1227 0 : const SwFrm* pCol = _pLayoutFrm;
1228 0 : while ( pCol && !pCol->IsColumnFrm() )
1229 : {
1230 0 : pCol = pCol->GetUpper();
1231 : }
1232 : // frame is moveable, if found column frame isn't last one.
1233 0 : if ( pCol && pCol->GetNext() )
1234 : {
1235 0 : bRetVal = true;
1236 : }
1237 : }
1238 : }
1239 : else
1240 : {
1241 0 : bRetVal = true;
1242 : }
1243 : }
1244 : }
1245 : }
1246 :
1247 0 : return bRetVal;
1248 : }
1249 :
1250 0 : void SwFrm::SetInfFlags()
1251 : {
1252 0 : if ( !IsFlyFrm() && !GetUpper() ) //not yet pasted, no information available
1253 0 : return;
1254 :
1255 0 : mbInfInvalid = mbInfBody = mbInfTab = mbInfFly = mbInfFtn = mbInfSct = sal_False;
1256 :
1257 0 : SwFrm *pFrm = this;
1258 0 : if( IsFtnContFrm() )
1259 0 : mbInfFtn = sal_True;
1260 0 : do
1261 : {
1262 : // mbInfBody is only set in the page body, but not in the column body
1263 0 : if ( pFrm->IsBodyFrm() && !mbInfFtn && pFrm->GetUpper()
1264 0 : && pFrm->GetUpper()->IsPageFrm() )
1265 0 : mbInfBody = sal_True;
1266 0 : else if ( pFrm->IsTabFrm() || pFrm->IsCellFrm() )
1267 : {
1268 0 : mbInfTab = sal_True;
1269 : }
1270 0 : else if ( pFrm->IsFlyFrm() )
1271 0 : mbInfFly = sal_True;
1272 0 : else if ( pFrm->IsSctFrm() )
1273 0 : mbInfSct = sal_True;
1274 0 : else if ( pFrm->IsFtnFrm() )
1275 0 : mbInfFtn = sal_True;
1276 :
1277 0 : pFrm = pFrm->GetUpper();
1278 :
1279 0 : } while ( pFrm && !pFrm->IsPageFrm() ); //there is nothing above the page
1280 : }
1281 :
1282 : /** Updates the vertical or the righttoleft-flags.
1283 : *
1284 : * If the property is derived, it's from the upper or (for fly frames) from
1285 : * the anchor. Otherwise we've to call a virtual method to check the property.
1286 : */
1287 0 : void SwFrm::SetDirFlags( sal_Bool bVert )
1288 : {
1289 0 : if( bVert )
1290 : {
1291 : // OD 2004-01-21 #114969# - if derived, valid vertical flag only if
1292 : // vertical flag of upper/anchor is valid.
1293 0 : if( mbDerivedVert )
1294 : {
1295 0 : const SwFrm* pAsk = IsFlyFrm() ?
1296 0 : ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper();
1297 :
1298 : OSL_ENSURE( pAsk != this, "Autsch! Stack overflow is about to happen" );
1299 :
1300 0 : if( pAsk )
1301 : {
1302 0 : mbVertical = pAsk->IsVertical() ? 1 : 0;
1303 0 : mbReverse = pAsk->IsReverse() ? 1 : 0;
1304 :
1305 0 : mbVertLR = pAsk->IsVertLR() ? 1 : 0;
1306 : //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
1307 0 : if ( !pAsk->mbInvalidVert )
1308 0 : mbInvalidVert = sal_False;
1309 : }
1310 : }
1311 : else
1312 0 : CheckDirection( bVert );
1313 : }
1314 : else
1315 : {
1316 0 : sal_Bool bInv = 0;
1317 0 : if( !mbDerivedR2L ) // CheckDirection is able to set bDerivedR2L!
1318 0 : CheckDirection( bVert );
1319 0 : if( mbDerivedR2L )
1320 : {
1321 0 : const SwFrm* pAsk = IsFlyFrm() ?
1322 0 : ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper();
1323 :
1324 : OSL_ENSURE( pAsk != this, "Oops! Stack overflow is about to happen" );
1325 :
1326 0 : if( pAsk )
1327 0 : mbRightToLeft = pAsk->IsRightToLeft() ? 1 : 0;
1328 0 : if( !pAsk || pAsk->mbInvalidR2L )
1329 0 : bInv = mbInvalidR2L;
1330 : }
1331 0 : mbInvalidR2L = bInv;
1332 : }
1333 0 : }
1334 :
1335 0 : SwLayoutFrm* SwFrm::GetNextCellLeaf( MakePageType )
1336 : {
1337 0 : SwFrm* pTmpFrm = this;
1338 0 : while ( !pTmpFrm->IsCellFrm() )
1339 0 : pTmpFrm = pTmpFrm->GetUpper();
1340 :
1341 : OSL_ENSURE( pTmpFrm, "SwFrm::GetNextCellLeaf() without cell" );
1342 0 : return ((SwCellFrm*)pTmpFrm)->GetFollowCell();
1343 : }
1344 :
1345 0 : SwLayoutFrm* SwFrm::GetPrevCellLeaf( MakePageType )
1346 : {
1347 0 : SwFrm* pTmpFrm = this;
1348 0 : while ( !pTmpFrm->IsCellFrm() )
1349 0 : pTmpFrm = pTmpFrm->GetUpper();
1350 :
1351 : OSL_ENSURE( pTmpFrm, "SwFrm::GetNextPreviousLeaf() without cell" );
1352 0 : return ((SwCellFrm*)pTmpFrm)->GetPreviousCell();
1353 : }
1354 :
1355 0 : static SwCellFrm* lcl_FindCorrespondingCellFrm( const SwRowFrm& rOrigRow,
1356 : const SwCellFrm& rOrigCell,
1357 : const SwRowFrm& rCorrRow,
1358 : bool bInFollow )
1359 : {
1360 0 : SwCellFrm* pRet = NULL;
1361 0 : SwCellFrm* pCell = (SwCellFrm*)rOrigRow.Lower();
1362 0 : SwCellFrm* pCorrCell = (SwCellFrm*)rCorrRow.Lower();
1363 :
1364 0 : while ( pCell != &rOrigCell && !pCell->IsAnLower( &rOrigCell ) )
1365 : {
1366 0 : pCell = (SwCellFrm*)pCell->GetNext();
1367 0 : pCorrCell = (SwCellFrm*)pCorrCell->GetNext();
1368 : }
1369 :
1370 : OSL_ENSURE( pCell && pCorrCell, "lcl_FindCorrespondingCellFrm does not work" );
1371 :
1372 0 : if ( pCell != &rOrigCell )
1373 : {
1374 : // rOrigCell must be a lower of pCell. We need to recurse into the rows:
1375 : OSL_ENSURE( pCell->Lower() && pCell->Lower()->IsRowFrm(),
1376 : "lcl_FindCorrespondingCellFrm does not work" );
1377 :
1378 0 : SwRowFrm* pRow = (SwRowFrm*)pCell->Lower();
1379 0 : while ( !pRow->IsAnLower( &rOrigCell ) )
1380 0 : pRow = (SwRowFrm*)pRow->GetNext();
1381 :
1382 0 : SwRowFrm* pCorrRow = 0;
1383 0 : if ( bInFollow )
1384 0 : pCorrRow = pRow->GetFollowRow();
1385 : else
1386 : {
1387 0 : SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pCorrCell->GetLastLower());
1388 :
1389 0 : if ( pTmpRow && pTmpRow->GetFollowRow() == pRow )
1390 0 : pCorrRow = pTmpRow;
1391 : }
1392 :
1393 0 : if ( pCorrRow )
1394 0 : pRet = lcl_FindCorrespondingCellFrm( *pRow, rOrigCell, *pCorrRow, bInFollow );
1395 : }
1396 : else
1397 0 : pRet = pCorrCell;
1398 :
1399 0 : return pRet;
1400 : }
1401 :
1402 : // VERSION OF GetFollowCell() that assumes that we always have a follow flow line:
1403 0 : SwCellFrm* SwCellFrm::GetFollowCell() const
1404 : {
1405 0 : SwCellFrm* pRet = NULL;
1406 :
1407 : // NEW TABLES
1408 : // Covered cells do not have follow cells!
1409 0 : const long nRowSpan = GetLayoutRowSpan();
1410 0 : if ( nRowSpan < 1 )
1411 0 : return NULL;
1412 :
1413 : // find most upper row frame
1414 0 : const SwFrm* pRow = GetUpper();
1415 0 : while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
1416 0 : pRow = pRow->GetUpper();
1417 :
1418 0 : if ( !pRow )
1419 0 : return NULL;
1420 :
1421 0 : const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( pRow->GetUpper() );
1422 0 : if ( !pRow || !pTabFrm->GetFollow() || !pTabFrm->HasFollowFlowLine() )
1423 0 : return NULL;
1424 :
1425 0 : const SwCellFrm* pThisCell = this;
1426 :
1427 : // Get last cell of the current table frame that belongs to the rowspan:
1428 0 : if ( nRowSpan > 1 )
1429 : {
1430 : // optimization: Will end of row span be in last row or exceed row?
1431 0 : long nMax = 0;
1432 0 : while ( pRow->GetNext() && ++nMax < nRowSpan )
1433 0 : pRow = pRow->GetNext();
1434 :
1435 0 : if ( !pRow->GetNext() )
1436 : {
1437 0 : pThisCell = &pThisCell->FindStartEndOfRowSpanCell( false, true );
1438 0 : pRow = pThisCell->GetUpper();
1439 : }
1440 : }
1441 :
1442 0 : const SwRowFrm* pFollowRow = NULL;
1443 0 : if ( !pRow->GetNext() &&
1444 0 : NULL != ( pFollowRow = pRow->IsInSplitTableRow() ) &&
1445 0 : ( !pFollowRow->IsRowSpanLine() || nRowSpan > 1 ) )
1446 0 : pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *pThisCell, *pFollowRow, true );
1447 :
1448 0 : return pRet;
1449 : }
1450 :
1451 : // VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL
1452 0 : SwCellFrm* SwCellFrm::GetPreviousCell() const
1453 : {
1454 0 : SwCellFrm* pRet = NULL;
1455 :
1456 : // NEW TABLES
1457 : // Covered cells do not have previous cells!
1458 0 : if ( GetLayoutRowSpan() < 1 )
1459 0 : return NULL;
1460 :
1461 : // find most upper row frame
1462 0 : const SwFrm* pRow = GetUpper();
1463 0 : while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
1464 0 : pRow = pRow->GetUpper();
1465 :
1466 : OSL_ENSURE( pRow->GetUpper() && pRow->GetUpper()->IsTabFrm(), "GetPreviousCell without Table" );
1467 :
1468 0 : SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
1469 :
1470 0 : if ( pTab->IsFollow() )
1471 : {
1472 0 : const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow();
1473 0 : const bool bIsInFirstLine = ( pTmp == pRow );
1474 :
1475 0 : if ( bIsInFirstLine )
1476 : {
1477 0 : SwTabFrm *pMaster = (SwTabFrm*)pTab->FindMaster();
1478 0 : if ( pMaster && pMaster->HasFollowFlowLine() )
1479 : {
1480 0 : SwRowFrm* pMasterRow = static_cast<SwRowFrm*>(pMaster->GetLastLower());
1481 0 : if ( pMasterRow )
1482 0 : pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *this, *pMasterRow, false );
1483 0 : if ( pRet && pRet->GetTabBox()->getRowSpan() < 1 )
1484 0 : pRet = &const_cast<SwCellFrm&>(pRet->FindStartEndOfRowSpanCell( true, true ));
1485 : }
1486 : }
1487 : }
1488 :
1489 0 : return pRet;
1490 : }
1491 :
1492 : // --> NEW TABLES
1493 0 : const SwCellFrm& SwCellFrm::FindStartEndOfRowSpanCell( bool bStart, bool bCurrentTableOnly ) const
1494 : {
1495 0 : const SwCellFrm* pRet = 0;
1496 :
1497 0 : const SwTabFrm* pTableFrm = dynamic_cast<const SwTabFrm*>(GetUpper()->GetUpper());
1498 :
1499 0 : if ( !bStart && pTableFrm && pTableFrm->IsFollow() && pTableFrm->IsInHeadline( *this ) )
1500 0 : return *this;
1501 :
1502 : OSL_ENSURE( pTableFrm &&
1503 : ( (bStart && GetTabBox()->getRowSpan() < 1) ||
1504 : (!bStart && GetLayoutRowSpan() > 1) ),
1505 : "SwCellFrm::FindStartRowSpanCell: No rowspan, no table, no cookies" );
1506 :
1507 0 : if ( pTableFrm )
1508 : {
1509 0 : const SwTable* pTable = pTableFrm->GetTable();
1510 :
1511 0 : sal_uInt16 nMax = USHRT_MAX;
1512 0 : if ( bCurrentTableOnly )
1513 : {
1514 0 : const SwFrm* pCurrentRow = GetUpper();
1515 0 : const bool bDoNotEnterHeadline = bStart && pTableFrm->IsFollow() &&
1516 0 : !pTableFrm->IsInHeadline( *pCurrentRow );
1517 :
1518 : // check how many rows we are allowed to go up or down until we reach the end of
1519 : // the current table frame:
1520 0 : nMax = 0;
1521 0 : while ( bStart ? pCurrentRow->GetPrev() : pCurrentRow->GetNext() )
1522 : {
1523 0 : if ( bStart )
1524 : {
1525 : // do not enter a repeated headline:
1526 0 : if ( bDoNotEnterHeadline && pTableFrm->IsFollow() &&
1527 0 : pTableFrm->IsInHeadline( *pCurrentRow->GetPrev() ) )
1528 0 : break;
1529 :
1530 0 : pCurrentRow = pCurrentRow->GetPrev();
1531 : }
1532 : else
1533 0 : pCurrentRow = pCurrentRow->GetNext();
1534 :
1535 0 : ++nMax;
1536 : }
1537 : }
1538 :
1539 : // By passing the nMax value for Find*OfRowSpan (in case of bCurrentTableOnly
1540 : // is set) we assure that we find a rMasterBox that has a SwCellFrm in
1541 : // the current table frame:
1542 : const SwTableBox& rMasterBox = bStart ?
1543 0 : GetTabBox()->FindStartOfRowSpan( *pTable, nMax ) :
1544 0 : GetTabBox()->FindEndOfRowSpan( *pTable, nMax );
1545 :
1546 0 : SwIterator<SwCellFrm,SwFmt> aIter( *rMasterBox.GetFrmFmt() );
1547 :
1548 0 : for ( SwCellFrm* pMasterCell = aIter.First(); pMasterCell; pMasterCell = aIter.Next() )
1549 : {
1550 0 : if ( pMasterCell->GetTabBox() == &rMasterBox )
1551 : {
1552 0 : const SwTabFrm* pMasterTable = static_cast<const SwTabFrm*>(pMasterCell->GetUpper()->GetUpper());
1553 :
1554 0 : if ( bCurrentTableOnly )
1555 : {
1556 0 : if ( pMasterTable == pTableFrm )
1557 : {
1558 0 : pRet = pMasterCell;
1559 0 : break;
1560 : }
1561 : }
1562 : else
1563 : {
1564 0 : if ( pMasterTable == pTableFrm ||
1565 0 : ( (bStart && pMasterTable->IsAnFollow(pTableFrm)) ||
1566 0 : (!bStart && pTableFrm->IsAnFollow(pMasterTable)) ) )
1567 : {
1568 0 : pRet = pMasterCell;
1569 0 : break;
1570 : }
1571 : }
1572 : }
1573 0 : }
1574 : }
1575 :
1576 : OSL_ENSURE( pRet, "SwCellFrm::FindStartRowSpanCell: No result" );
1577 :
1578 0 : return *pRet;
1579 : }
1580 : // <-- NEW TABLES
1581 :
1582 0 : const SwRowFrm* SwFrm::IsInSplitTableRow() const
1583 : {
1584 : OSL_ENSURE( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" );
1585 :
1586 0 : const SwFrm* pRow = this;
1587 :
1588 : // find most upper row frame
1589 0 : while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) )
1590 0 : pRow = pRow->GetUpper();
1591 :
1592 0 : if ( !pRow ) return NULL;
1593 :
1594 : OSL_ENSURE( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" );
1595 :
1596 0 : const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
1597 :
1598 : // If most upper row frame is a headline row, the current frame
1599 : // can't be in a splitted table row. Thus, add corresponding condition.
1600 0 : if ( pRow->GetNext() ||
1601 : pTab->GetTable()->IsHeadline(
1602 0 : *(static_cast<const SwRowFrm*>(pRow)->GetTabLine()) ) ||
1603 0 : !pTab->HasFollowFlowLine() ||
1604 0 : !pTab->GetFollow() )
1605 0 : return NULL;
1606 :
1607 : // skip headline
1608 0 : const SwRowFrm* pFollowRow = pTab->GetFollow()->GetFirstNonHeadlineRow();
1609 :
1610 : OSL_ENSURE( pFollowRow, "SwFrm::IsInSplitTableRow() does not work" );
1611 :
1612 0 : return pFollowRow;
1613 : }
1614 :
1615 0 : const SwRowFrm* SwFrm::IsInFollowFlowRow() const
1616 : {
1617 : OSL_ENSURE( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" );
1618 :
1619 : // find most upper row frame
1620 0 : const SwFrm* pRow = this;
1621 0 : while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) )
1622 0 : pRow = pRow->GetUpper();
1623 :
1624 0 : if ( !pRow ) return NULL;
1625 :
1626 : OSL_ENSURE( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" );
1627 :
1628 0 : const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
1629 :
1630 0 : const SwTabFrm* pMaster = pTab->IsFollow() ? pTab->FindMaster() : 0;
1631 :
1632 0 : if ( !pMaster || !pMaster->HasFollowFlowLine() )
1633 0 : return NULL;
1634 :
1635 0 : const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow();
1636 0 : const bool bIsInFirstLine = ( pTmp == pRow );
1637 :
1638 0 : if ( !bIsInFirstLine )
1639 0 : return NULL;
1640 :
1641 0 : const SwRowFrm* pMasterRow = static_cast<const SwRowFrm*>(pMaster->GetLastLower());
1642 0 : return pMasterRow;
1643 : }
1644 :
1645 0 : bool SwFrm::IsInBalancedSection() const
1646 : {
1647 0 : bool bRet = false;
1648 :
1649 0 : if ( IsInSct() )
1650 : {
1651 0 : const SwSectionFrm* pSectionFrm = FindSctFrm();
1652 0 : if ( pSectionFrm )
1653 0 : bRet = pSectionFrm->IsBalancedSection();
1654 : }
1655 0 : return bRet;
1656 : }
1657 :
1658 0 : const SwFrm* SwLayoutFrm::GetLastLower() const
1659 : {
1660 0 : const SwFrm* pRet = Lower();
1661 0 : if ( !pRet )
1662 0 : return 0;
1663 0 : while ( pRet->GetNext() )
1664 0 : pRet = pRet->GetNext();
1665 0 : return pRet;
1666 : }
1667 :
1668 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|