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 <colfrm.hxx>
22 #include <rootfrm.hxx>
23 #include <cellfrm.hxx>
24 #include <rowfrm.hxx>
25 #include <swtable.hxx>
26 #include <notxtfrm.hxx>
27 #include <tabfrm.hxx>
28 #include <sectfrm.hxx>
29 #include <frmatr.hxx>
30 #include <flyfrm.hxx>
31 #include <ftnfrm.hxx>
32 #include <txtftn.hxx>
33 #include <fmtftn.hxx>
34 #include <fmtpdsc.hxx>
35 #include <fmtclbl.hxx>
36 #include <txtfrm.hxx>
37 #include <bodyfrm.hxx>
38 #include <calbck.hxx>
39 #include <viewopt.hxx>
40 #include <ndtxt.hxx>
41 #include <osl/diagnose.h>
42 #include <sal/log.hxx>
43 #include <IDocumentSettingAccess.hxx>
44 #include <formatflysplit.hxx>
45 #include <flyfrms.hxx>
46
47
48 /// Searches the first ContentFrame in BodyText below the page.
FindBodyCont()49 SwLayoutFrame *SwFootnoteBossFrame::FindBodyCont()
50 {
51 SwFrame *pLay = Lower();
52 while ( pLay && !pLay->IsBodyFrame() )
53 pLay = pLay->GetNext();
54 return static_cast<SwLayoutFrame*>(pLay);
55 }
56
57 /// Searches the last ContentFrame in BodyText below the page.
FindLastBodyContent()58 SwContentFrame *SwPageFrame::FindLastBodyContent()
59 {
60 SwContentFrame *pRet = FindFirstBodyContent();
61 SwContentFrame *pNxt = pRet;
62 while ( pNxt && pNxt->IsInDocBody() && IsAnLower( pNxt ) )
63 { pRet = pNxt;
64 pNxt = pNxt->FindNextCnt();
65 }
66 return pRet;
67 }
68
GetEndNoteSection()69 SwSectionFrame* SwPageFrame::GetEndNoteSection()
70 {
71 SwLayoutFrame* pBody = FindBodyCont();
72 if (!pBody)
73 {
74 return nullptr;
75 }
76
77 SwFrame* pLast = pBody->GetLastLower();
78 if (!pLast || !pLast->IsSctFrame())
79 {
80 return nullptr;
81 }
82
83 auto pLastSection = static_cast<SwSectionFrame*>(pLast);
84 if (!pLastSection->IsEndNoteSection())
85 {
86 return nullptr;
87 }
88
89 return pLastSection;
90 }
91
92 /**
93 * Checks if the frame contains one or more ContentFrame's anywhere in his
94 * subsidiary structure; if so the first found ContentFrame is returned.
95 */
ContainsContent() const96 const SwContentFrame *SwLayoutFrame::ContainsContent() const
97 {
98 //Search downwards the layout leaf and if there is no content, jump to the
99 //next leaf until content is found or we leave "this".
100 //Sections: Content next to sections would not be found this way (empty
101 //sections directly next to ContentFrame) therefore we need to recursively
102 //search for them even if it's more complex.
103
104 const SwLayoutFrame *pLayLeaf = this;
105 do
106 {
107 while ( (!pLayLeaf->IsSctFrame() || pLayLeaf == this ) &&
108 pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrame() )
109 pLayLeaf = static_cast<const SwLayoutFrame*>(pLayLeaf->Lower());
110
111 if( pLayLeaf->IsSctFrame() && pLayLeaf != this )
112 {
113 const SwContentFrame *pCnt = pLayLeaf->ContainsContent();
114 if( pCnt )
115 return pCnt;
116 if( pLayLeaf->GetNext() )
117 {
118 if( pLayLeaf->GetNext()->IsLayoutFrame() )
119 {
120 pLayLeaf = static_cast<const SwLayoutFrame*>(pLayLeaf->GetNext());
121 continue;
122 }
123 else
124 return static_cast<const SwContentFrame*>(pLayLeaf->GetNext());
125 }
126 }
127 else if ( pLayLeaf->Lower() )
128 return static_cast<const SwContentFrame*>(pLayLeaf->Lower());
129
130 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
131 if( !IsAnLower( pLayLeaf) )
132 return nullptr;
133 } while( pLayLeaf );
134 return nullptr;
135 }
136
137 /**
138 * Calls ContainsAny first to reach the innermost cell. From there we walk back
139 * up to the first SwCellFrame. Since we use SectionFrames, ContainsContent()->GetUpper()
140 * is not enough anymore.
141 */
FirstCell() const142 const SwCellFrame *SwLayoutFrame::FirstCell() const
143 {
144 const SwFrame* pCnt = ContainsAny();
145 while( pCnt && !pCnt->IsCellFrame() )
146 pCnt = pCnt->GetUpper();
147 return static_cast<const SwCellFrame*>(pCnt);
148 }
149
150 /** return ContentFrames, sections, and tables.
151 *
152 * @param _bInvestigateFootnoteForSections controls investigation of content of footnotes for sections.
153 * @see ContainsContent
154 */
ContainsAny(const bool _bInvestigateFootnoteForSections) const155 const SwFrame *SwLayoutFrame::ContainsAny( const bool _bInvestigateFootnoteForSections ) const
156 {
157 //Search downwards the layout leaf and if there is no content, jump to the
158 //next leaf until content is found, we leave "this" or until we found
159 //a SectionFrame or a TabFrame.
160
161 const SwLayoutFrame *pLayLeaf = this;
162 const bool bNoFootnote = IsSctFrame() && !_bInvestigateFootnoteForSections;
163 do
164 {
165 while ( ( (!pLayLeaf->IsSctFrame() && !pLayLeaf->IsTabFrame())
166 || pLayLeaf == this ) &&
167 pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrame() )
168 pLayLeaf = static_cast<const SwLayoutFrame*>(pLayLeaf->Lower());
169
170 if( ( pLayLeaf->IsTabFrame() || pLayLeaf->IsSctFrame() )
171 && pLayLeaf != this )
172 {
173 // Now we also return "deleted" SectionFrames so they can be
174 // maintained on SaveContent and RestoreContent
175 return pLayLeaf;
176 }
177 else if ( pLayLeaf->Lower() )
178 return static_cast<const SwContentFrame*>(pLayLeaf->Lower());
179
180 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
181 if( bNoFootnote && pLayLeaf && pLayLeaf->IsInFootnote() )
182 {
183 do
184 {
185 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
186 } while( pLayLeaf && pLayLeaf->IsInFootnote() );
187 }
188 if( !IsAnLower( pLayLeaf) )
189 return nullptr;
190 } while( pLayLeaf );
191 return nullptr;
192 }
193
ContainsDeleteForbiddenLayFrame() const194 bool SwLayoutFrame::ContainsDeleteForbiddenLayFrame() const
195 {
196 if (IsDeleteForbidden())
197 {
198 return true;
199 }
200 for (SwFrame const* pFrame = Lower(); pFrame; pFrame = pFrame->GetNext())
201 {
202 if (!pFrame->IsLayoutFrame())
203 {
204 continue;
205 }
206 SwLayoutFrame const*const pLay(static_cast<SwLayoutFrame const*>(pFrame));
207 if (pLay->ContainsDeleteForbiddenLayFrame() || pLay->IsColLocked())
208 {
209 return true;
210 }
211 }
212 return false;
213 }
214
GetLower() const215 const SwFrame* SwFrame::GetLower() const
216 {
217 return IsLayoutFrame() ? static_cast<const SwLayoutFrame*>(this)->Lower() : nullptr;
218 }
219
GetLower()220 SwFrame* SwFrame::GetLower()
221 {
222 return IsLayoutFrame() ? static_cast<SwLayoutFrame*>(this)->Lower() : nullptr;
223 }
224
FindPrevCnt()225 SwContentFrame* SwFrame::FindPrevCnt( )
226 {
227 if ( GetPrev() && GetPrev()->IsContentFrame() )
228 return static_cast<SwContentFrame*>(GetPrev());
229 else
230 return FindPrevCnt_();
231 }
232
FindPrevCnt() const233 const SwContentFrame* SwFrame::FindPrevCnt() const
234 {
235 if ( GetPrev() && GetPrev()->IsContentFrame() )
236 return static_cast<const SwContentFrame*>(GetPrev());
237 else
238 return const_cast<SwFrame*>(this)->FindPrevCnt_();
239 }
240
FindNextCnt(const bool _bInSameFootnote)241 SwContentFrame *SwFrame::FindNextCnt( const bool _bInSameFootnote )
242 {
243 if ( mpNext && mpNext->IsContentFrame() )
244 return static_cast<SwContentFrame*>(mpNext);
245 else
246 return FindNextCnt_( _bInSameFootnote );
247 }
248
FindNextCnt(const bool _bInSameFootnote) const249 const SwContentFrame *SwFrame::FindNextCnt( const bool _bInSameFootnote ) const
250 {
251 if ( mpNext && mpNext->IsContentFrame() )
252 return static_cast<SwContentFrame*>(mpNext);
253 else
254 return const_cast<SwFrame*>(this)->FindNextCnt_( _bInSameFootnote );
255 }
256
IsAnLower(const SwFrame * pAssumed) const257 bool SwLayoutFrame::IsAnLower( const SwFrame *pAssumed ) const
258 {
259 const SwFrame *pUp = pAssumed;
260 while ( pUp )
261 {
262 if (!pUp->IsInDtor())
263 {
264 if (pUp == this)
265 return true;
266 if (pUp->IsFlyFrame())
267 pUp = static_cast<const SwFlyFrame*>(pUp)->GetAnchorFrame();
268 else
269 pUp = pUp->GetUpper();
270 }
271 else
272 break;
273 }
274 return false;
275 }
276
277 /** method to check relative position of layout frame to
278 a given layout frame.
279
280 OD 08.11.2002 - refactoring of pseudo-local method <lcl_Apres(..)> in
281 <txtftn.cxx> for #104840#.
282
283 @param _aCheckRefLayFrame
284 constant reference of an instance of class <SwLayoutFrame> which
285 is used as the reference for the relative position check.
286
287 @return true, if <this> is positioned before the layout frame <p>
288 */
IsBefore(const SwLayoutFrame * _pCheckRefLayFrame) const289 bool SwLayoutFrame::IsBefore( const SwLayoutFrame* _pCheckRefLayFrame ) const
290 {
291 OSL_ENSURE( !IsRootFrame() , "<IsBefore> called at a <SwRootFrame>.");
292 OSL_ENSURE( !_pCheckRefLayFrame->IsRootFrame() , "<IsBefore> called with a <SwRootFrame>.");
293
294 bool bReturn;
295
296 // check, if on different pages
297 const SwPageFrame *pMyPage = FindPageFrame();
298 const SwPageFrame *pCheckRefPage = _pCheckRefLayFrame->FindPageFrame();
299 if( pMyPage != pCheckRefPage )
300 {
301 // being on different page as check reference
302 bReturn = pMyPage->GetPhyPageNum() < pCheckRefPage->GetPhyPageNum();
303 }
304 else
305 {
306 // being on same page as check reference
307 // --> search my supreme parent <pUp>, which doesn't contain check reference.
308 const SwLayoutFrame* pUp = this;
309 while ( pUp->GetUpper() &&
310 !pUp->GetUpper()->IsAnLower( _pCheckRefLayFrame )
311 )
312 pUp = pUp->GetUpper();
313 if( !pUp->GetUpper() )
314 {
315 // can occur, if <this> is a fly frm
316 bReturn = false;
317 }
318 else
319 {
320 // travel through the next's of <pUp> and check if one of these
321 // contain the check reference.
322 const SwLayoutFrame* pUpNext = static_cast<const SwLayoutFrame*>(pUp->GetNext());
323 while ( pUpNext &&
324 !pUpNext->IsAnLower( _pCheckRefLayFrame ) )
325 {
326 pUpNext = static_cast<const SwLayoutFrame*>(pUpNext->GetNext());
327 }
328 bReturn = pUpNext != nullptr;
329 }
330 }
331
332 return bReturn;
333 }
334
335 // Local helper functions for GetNextLayoutLeaf
336
lcl_FindLayoutFrame(const SwFrame * pFrame,bool bNext)337 static const SwFrame* lcl_FindLayoutFrame( const SwFrame* pFrame, bool bNext )
338 {
339 const SwFrame* pRet = nullptr;
340 if ( pFrame->IsFlyFrame() )
341 {
342 auto pFlyFrame = static_cast<const SwFlyFrame*>(pFrame);
343 if (pFlyFrame->IsFlySplitAllowed())
344 {
345 // This is a flow frame, look up the follow/precede.
346 auto pFlyAtContent = static_cast<const SwFlyAtContentFrame*>(pFlyFrame);
347 pRet = bNext ? pFlyAtContent->GetFollow() : pFlyAtContent->GetPrecede();
348 }
349 else
350 {
351 pRet = bNext ? pFlyFrame->GetNextLink() : pFlyFrame->GetPrevLink();
352 }
353 }
354 else
355 pRet = bNext ? pFrame->GetNext() : pFrame->GetPrev();
356
357 return pRet;
358 }
359
lcl_GetLower(const SwFrame * pFrame,bool bFwd)360 static const SwFrame* lcl_GetLower( const SwFrame* pFrame, bool bFwd )
361 {
362 if ( !pFrame->IsLayoutFrame() )
363 return nullptr;
364
365 return bFwd ?
366 static_cast<const SwLayoutFrame*>(pFrame)->Lower() :
367 static_cast<const SwLayoutFrame*>(pFrame)->GetLastLower();
368 }
369
370 /**
371 * Finds the next layout leaf. This is a layout frame, which does not
372 * have a lower which is a LayoutFrame. That means, pLower can be 0 or a
373 * content frame.
374 *
375 * However, pLower may be a TabFrame
376 */
ImplGetNextLayoutLeaf(bool bFwd) const377 const SwLayoutFrame *SwFrame::ImplGetNextLayoutLeaf( bool bFwd ) const
378 {
379 const SwFrame *pFrame = this;
380 const SwLayoutFrame *pLayoutFrame = nullptr;
381 const SwFrame *p = nullptr;
382 bool bGoingUp = !bFwd; // false for forward, true for backward
383 // The anchor is this frame, unless we traverse the anchor of a split fly.
384 const SwFrame* pAnchor = this;
385 do {
386
387 bool bGoingFwdOrBwd = false;
388
389 bool bGoingDown = !bGoingUp;
390 if (bGoingDown)
391 {
392 p = lcl_GetLower( pFrame, bFwd );
393 bGoingDown = nullptr != p;
394 }
395 if ( !bGoingDown )
396 {
397 // I cannot go down, because either I'm currently going up or
398 // because the is no lower.
399 // I'll try to go forward:
400 p = lcl_FindLayoutFrame( pFrame, bFwd );
401 bGoingFwdOrBwd = nullptr != p;
402 if ( !bGoingFwdOrBwd )
403 {
404 // I cannot go forward, because there is no next frame.
405 // I'll try to go up:
406 p = pFrame->GetUpper();
407
408 if (!p && pFrame->IsFlyFrame())
409 {
410 const SwFlyFrame* pFlyFrame = pFrame->FindFlyFrame();
411 if (pFlyFrame->IsFlySplitAllowed())
412 {
413 p = const_cast<SwFlyFrame*>(pFlyFrame)->FindAnchorCharFrame();
414 // Remember the anchor frame, so if we look for the leaf of a frame in a
415 // split fly (anchored in the master of a text frame, but rendered on the
416 // next page), we won't return a frame on the next page, rather return
417 // nullptr.
418 pAnchor = p;
419 }
420 }
421
422 bGoingUp = nullptr != p;
423 if ( !bGoingUp )
424 {
425 // I cannot go up, because there is no upper frame.
426 return nullptr;
427 }
428 }
429 }
430
431 // If I could not go down or forward, I'll have to go up
432 bGoingUp = !bGoingFwdOrBwd && !bGoingDown;
433
434 pFrame = p;
435 p = lcl_GetLower( pFrame, true );
436
437 } while( ( p && !p->IsFlowFrame() ) ||
438 pFrame == this ||
439 nullptr == ( pLayoutFrame = pFrame->IsLayoutFrame() ? static_cast<const SwLayoutFrame*>(pFrame) : nullptr ) ||
440 pLayoutFrame->IsAnLower( pAnchor ) );
441
442 return pLayoutFrame;
443 }
444
445 /**
446 * Walk back inside the tree: grab the subordinate Frame if one exists and the
447 * last step was not moving up a level (this would lead to an infinite up/down
448 * loop!). With this we ensure that during walking back we search through all
449 * sub trees. If we walked downwards we have to go to the end of the chain first
450 * because we go backwards from the last Frame inside another Frame. Walking
451 * forward works the same.
452 *
453 * @warning fixes here may also need to be applied to the @{lcl_NextFrame} method above
454 */
ImplGetNextContentFrame(bool bFwd) const455 const SwContentFrame* SwContentFrame::ImplGetNextContentFrame( bool bFwd ) const
456 {
457 const SwFrame *pFrame = this;
458 const SwContentFrame *pContentFrame = nullptr;
459 bool bGoingUp = false;
460 do {
461 const SwFrame *p = nullptr;
462 bool bGoingFwdOrBwd = false;
463
464 bool bGoingDown = !bGoingUp;
465 if (bGoingDown)
466 {
467 p = lcl_GetLower( pFrame, true ) ;
468 bGoingDown = nullptr != p;
469 }
470 if ( !bGoingDown )
471 {
472 p = lcl_FindLayoutFrame( pFrame, bFwd );
473 bGoingFwdOrBwd = nullptr != p;
474 if ( !bGoingFwdOrBwd )
475 {
476 p = pFrame->GetUpper();
477 bGoingUp = nullptr != p;
478 if ( !bGoingUp )
479 {
480 return nullptr;
481 }
482 }
483 }
484
485 bGoingUp = !(bGoingFwdOrBwd || bGoingDown);
486 assert(p);
487 if (!bFwd && bGoingDown)
488 {
489 while ( p->GetNext() )
490 p = p->GetNext();
491 }
492
493 pFrame = p;
494 } while ( nullptr == (pContentFrame = (pFrame->IsContentFrame() ? static_cast<const SwContentFrame*>(pFrame) : nullptr) ));
495
496 return pContentFrame;
497 }
498
ImplFindPageFrame()499 SwPageFrame* SwFrame::ImplFindPageFrame()
500 {
501 SwFrame *pRet = this;
502 while ( pRet )
503 {
504 if (pRet->IsInDtor())
505 return nullptr;
506
507 if (pRet->IsPageFrame())
508 break;
509
510 if ( pRet->GetUpper() )
511 pRet = pRet->GetUpper();
512 else if ( pRet->IsFlyFrame() )
513 {
514 // #i28701# - use new method <GetPageFrame()>
515 const auto pFly(static_cast<SwFlyFrame*>(pRet));
516 pRet = pFly->GetPageFrame();
517 if (pRet == nullptr)
518 pRet = pFly->AnchorFrame();
519 }
520 else
521 return nullptr;
522 }
523 return static_cast<SwPageFrame*>(pRet);
524 }
525
FindFootnoteBossFrame(bool bFootnotes)526 SwFootnoteBossFrame* SwFrame::FindFootnoteBossFrame( bool bFootnotes )
527 {
528 SwFrame *pRet = this;
529 // Footnote bosses can't exist inside a table; also sections with columns
530 // don't contain footnote texts there
531 if (SwFrame *pTabFrame = pRet->IsInTab() ? pRet->FindTabFrame() : nullptr)
532 pRet = pTabFrame;
533
534 // tdf139336: put the footnotes into the page frame (instead of a column frame)
535 // to avoid maximizing the section to the full page.... if:
536 // - it is in a section
537 // - collect footnotes at section end (FootnoteAtEnd) is not set
538 // - columns are evenly distributed (=balanced) is not set
539 // Note 1: at page end, the footnotes have no multi-column-capability,
540 // so this fix is used only where there is better chance to help
541 // Note 2: If balanced is not set, there is a higher chance that the 1. column will reach
542 // the end of the page... if that happens the section will be maximized anyway.
543 // Note 3: The user will be able to easily choose the old layout (with multi-column footnotes)
544 // with this setting.
545 // similar case can be reached with a page break + FootnoteAtEnd setting
546 SwSectionFrame* pSectframe = pRet->FindSctFrame();
547 bool bMoveToPageFrame = false;
548 // tdf146704: only if it is really a footnote, not an endnote.
549 // tdf54465: compatibility flag to make old odt files keep these full page sections.
550 if (bFootnotes && pSectframe
551 && pSectframe->GetFormat()->getIDocumentSettingAccess().get(
552 DocumentSettingId::FOOTNOTE_IN_COLUMN_TO_PAGEEND))
553 {
554 SwSection* pSect = pSectframe->GetSection();
555 if (pSect) {
556 bool bNoBalance = pSect->GetFormat()->GetBalancedColumns().GetValue();
557 bool bFAtEnd = pSectframe->IsFootnoteAtEnd();
558 bMoveToPageFrame = !bFAtEnd && !bNoBalance;
559 }
560 }
561 while (pRet && !pRet->IsInDtor()
562 && ((!bMoveToPageFrame && !pRet->IsFootnoteBossFrame())
563 || (bMoveToPageFrame && !pRet->IsPageFrame())))
564 {
565 if ( pRet->GetUpper() )
566 pRet = pRet->GetUpper();
567 else if ( pRet->IsFlyFrame() )
568 {
569 // #i28701# - use new method <GetPageFrame()>
570 if ( static_cast<SwFlyFrame*>(pRet)->GetPageFrame() )
571 pRet = static_cast<SwFlyFrame*>(pRet)->GetPageFrame();
572 else
573 pRet = static_cast<SwFlyFrame*>(pRet)->AnchorFrame();
574 }
575 else
576 return nullptr;
577 }
578 if( bFootnotes && pRet && pRet->IsColumnFrame() &&
579 !pRet->GetNext() && !pRet->GetPrev() )
580 {
581 SwSectionFrame* pSct = pRet->FindSctFrame();
582 assert(pSct && "FindFootnoteBossFrame: Single column outside section?");
583 if( !pSct->IsFootnoteAtEnd() )
584 return pSct->FindFootnoteBossFrame( true );
585 }
586 return static_cast<SwFootnoteBossFrame*>(pRet);
587 }
588
ImplFindTabFrame()589 SwTabFrame* SwFrame::ImplFindTabFrame()
590 {
591 SwFrame *pRet = this;
592 if (pRet->IsInDtor())
593 return nullptr;
594 while ( !pRet->IsTabFrame() )
595 {
596 pRet = pRet->GetUpper();
597 if ( !pRet )
598 return nullptr;
599 if (pRet->IsInDtor())
600 return nullptr;
601 }
602 return static_cast<SwTabFrame*>(pRet);
603 }
604
ImplFindSctFrame()605 SwSectionFrame* SwFrame::ImplFindSctFrame()
606 {
607 SwFrame *pRet = this;
608 if (pRet->IsInDtor())
609 return nullptr;
610 while ( !pRet->IsSctFrame() )
611 {
612 pRet = pRet->GetUpper();
613 if ( !pRet )
614 return nullptr;
615 if (pRet->IsInDtor())
616 return nullptr;
617 }
618 return static_cast<SwSectionFrame*>(pRet);
619 }
620
ImplFindBodyFrame() const621 const SwBodyFrame* SwFrame::ImplFindBodyFrame() const
622 {
623 const SwFrame *pRet = this;
624 while ( !pRet->IsBodyFrame() )
625 {
626 pRet = pRet->GetUpper();
627 if ( !pRet )
628 return nullptr;
629 }
630 return static_cast<const SwBodyFrame*>(pRet);
631 }
632
ImplFindFootnoteFrame()633 SwFootnoteFrame *SwFrame::ImplFindFootnoteFrame()
634 {
635 SwFrame *pRet = this;
636 while ( !pRet->IsFootnoteFrame() )
637 {
638 pRet = pRet->GetUpper();
639 if ( !pRet )
640 return nullptr;
641 }
642 return static_cast<SwFootnoteFrame*>(pRet);
643 }
644
ImplFindFlyFrame()645 SwFlyFrame *SwFrame::ImplFindFlyFrame()
646 {
647 SwFrame *pRet = this;
648 do
649 {
650 if ( pRet->IsFlyFrame() )
651 return static_cast<SwFlyFrame*>(pRet);
652 else
653 pRet = pRet->GetUpper();
654 } while ( pRet );
655 return nullptr;
656 }
657
FindColFrame()658 SwFrame *SwFrame::FindColFrame()
659 {
660 SwFrame *pFrame = this;
661 do
662 { pFrame = pFrame->GetUpper();
663 } while ( pFrame && !pFrame->IsColumnFrame() );
664 return pFrame;
665 }
666
FindRowFrame()667 SwRowFrame *SwFrame::FindRowFrame()
668 {
669 SwFrame *pFrame = this;
670 do
671 { pFrame = pFrame->GetUpper();
672 } while ( pFrame && !pFrame->IsRowFrame() );
673 return dynamic_cast< SwRowFrame* >( pFrame );
674 }
675
FindFooterOrHeader()676 SwFrame* SwFrame::FindFooterOrHeader()
677 {
678 SwFrame* pRet = this;
679 do
680 {
681 if (pRet->GetType() & FRM_HEADFOOT) //header and footer
682 return pRet;
683 else if ( pRet->GetUpper() )
684 pRet = pRet->GetUpper();
685 else if ( pRet->IsFlyFrame() )
686 pRet = static_cast<SwFlyFrame*>(pRet)->AnchorFrame();
687 else
688 return nullptr;
689 } while ( pRet );
690 return pRet;
691 }
692
FindFootNote() const693 const SwFootnoteFrame* SwFootnoteContFrame::FindFootNote() const
694 {
695 const SwFootnoteFrame* pRet = static_cast<const SwFootnoteFrame*>(Lower());
696 if( pRet && !pRet->GetAttr()->GetFootnote().IsEndNote() )
697 return pRet;
698 return nullptr;
699 }
700
FindEndNote() const701 const SwFootnoteFrame* SwFootnoteContFrame::FindEndNote() const
702 {
703 auto pRet = static_cast<const SwFootnoteFrame*>(Lower());
704 if (pRet && pRet->GetAttr()->GetFootnote().IsEndNote())
705 {
706 return pRet;
707 }
708
709 return nullptr;
710 }
711
GetPageAtPos(const Point & rPt,const Size * pSize,bool bExtend) const712 const SwPageFrame* SwRootFrame::GetPageAtPos( const Point& rPt, const Size* pSize, bool bExtend ) const
713 {
714 const SwPageFrame* pRet = nullptr;
715
716 SwRect aRect;
717 if ( pSize )
718 {
719 aRect.Pos() = rPt;
720 aRect.SSize( *pSize );
721 }
722
723 const SwFrame* pPage = Lower();
724
725 if ( !bExtend )
726 {
727 if( !getFrameArea().Contains( rPt ) )
728 return nullptr;
729
730 // skip pages above point:
731 while( pPage && rPt.Y() > pPage->getFrameArea().Bottom() )
732 pPage = pPage->GetNext();
733 }
734
735 OSL_ENSURE( GetPageNum() <= maPageRects.size(), "number of pages differs from page rect array size" );
736 size_t nPageIdx = 0;
737
738 while ( pPage && !pRet )
739 {
740 const SwRect& rBoundRect = bExtend ? maPageRects[ nPageIdx++ ] : pPage->getFrameArea();
741
742 if ( (!pSize && rBoundRect.Contains(rPt)) ||
743 (pSize && rBoundRect.Overlaps(aRect)) )
744 {
745 pRet = static_cast<const SwPageFrame*>(pPage);
746 }
747
748 pPage = pPage->GetNext();
749 }
750
751 return pRet;
752 }
753
IsBetweenPages(const Point & rPt) const754 bool SwRootFrame::IsBetweenPages(const Point& rPt) const
755 {
756 if (!getFrameArea().Contains(rPt))
757 return false;
758
759 // top visible page
760 const SwFrame* pPage = Lower();
761 if (pPage == nullptr)
762 return false;
763
764 // skip pages above point:
765 while (pPage && rPt.Y() > pPage->getFrameArea().Bottom())
766 pPage = pPage->GetNext();
767
768 if (pPage &&
769 rPt.X() >= pPage->getFrameArea().Left() &&
770 rPt.X() <= pPage->getFrameArea().Right())
771 {
772 // Trivial case when we're right in between.
773 if (!pPage->getFrameArea().Contains(rPt))
774 return true;
775
776 // In normal mode the gap is large enough and
777 // header/footer mouse interaction competes with
778 // handling hide-whitespace within them.
779 // In hide-whitespace, however, the gap is too small
780 // for convenience and there are no headers/footers.
781 const SwViewShell *pSh = GetCurrShell();
782 if (pSh && pSh->GetViewOptions()->IsWhitespaceHidden())
783 {
784 constexpr SwTwips constMargin = o3tl::convert(tools::Long(2), o3tl::Length::mm, o3tl::Length::twip);
785
786 // If we are really close to the bottom or top of a page.
787 const auto toEdge = std::min(std::abs(pPage->getFrameArea().Top() - rPt.Y()),
788 std::abs(pPage->getFrameArea().Bottom() - rPt.Y()));
789 return toEdge <= constMargin;
790 }
791 }
792
793 return false;
794 }
795
GetBreakItem() const796 const SvxFormatBreakItem& SwFrame::GetBreakItem() const
797 {
798 return GetAttrSet()->GetBreak();
799 }
800
GetPageDescItem() const801 const SwFormatPageDesc& SwFrame::GetPageDescItem() const
802 {
803 return GetAttrSet()->GetPageDesc();
804 }
805
GetBreakItem() const806 const SvxFormatBreakItem& SwTextFrame::GetBreakItem() const
807 {
808 return GetTextNodeFirst()->GetSwAttrSet().GetBreak();
809 }
810
GetPageDescItem() const811 const SwFormatPageDesc& SwTextFrame::GetPageDescItem() const
812 {
813 return GetTextNodeFirst()->GetSwAttrSet().GetPageDesc();
814 }
815
GetAttrSet() const816 const SwAttrSet* SwFrame::GetAttrSet() const
817 {
818 if (IsTextFrame())
819 {
820 return &static_cast<const SwTextFrame*>(this)->GetTextNodeForParaProps()->GetSwAttrSet();
821 }
822 else if (IsNoTextFrame())
823 {
824 return &static_cast<const SwNoTextFrame*>(this)->GetNode()->GetSwAttrSet();
825 }
826 else
827 {
828 assert(IsLayoutFrame());
829 return &static_cast<const SwLayoutFrame*>(this)->GetFormat()->GetAttrSet();
830 }
831 }
832
getSdrAllFillAttributesHelper() const833 drawinglayer::attribute::SdrAllFillAttributesHelperPtr SwFrame::getSdrAllFillAttributesHelper() const
834 {
835 if (IsTextFrame())
836 {
837 return static_cast<const SwTextFrame*>(this)->GetTextNodeForParaProps()->getSdrAllFillAttributesHelper();
838 }
839 else if (IsNoTextFrame())
840 {
841 return static_cast<const SwNoTextFrame*>(this)->GetNode()->getSdrAllFillAttributesHelper();
842 }
843 else
844 {
845 return static_cast< const SwLayoutFrame* >(this)->GetFormat()->getSdrAllFillAttributesHelper();
846 }
847 }
848
supportsFullDrawingLayerFillAttributeSet() const849 bool SwFrame::supportsFullDrawingLayerFillAttributeSet() const
850 {
851 if (IsContentFrame())
852 {
853 return true;
854 }
855 else
856 {
857 return static_cast< const SwLayoutFrame* >(this)->GetFormat()->supportsFullDrawingLayerFillAttributeSet();
858 }
859 }
860
861 /*
862 * SwFrame::FindNext_(), FindPrev_(), InvalidateNextPos()
863 * FindNextCnt_() visits tables and sections and only returns SwContentFrames.
864 *
865 * Description Invalidates the position of the next frame.
866 * This is the direct successor or in case of ContentFrames the next
867 * ContentFrame which sits in the same flow as I do:
868 * - body,
869 * - footnote,
870 * - in headers/footers the notification only needs to be forwarded
871 * inside the section
872 * - same for Flys
873 * - Contents in tabs remain only inside their cell
874 * - in principle tables behave exactly like the Contents
875 * - sections also
876 */
877 // This helper function is an equivalent to the ImplGetNextContentFrame() method,
878 // besides ContentFrames this function also returns TabFrames and SectionFrames.
lcl_NextFrame(SwFrame * pFrame)879 static SwFrame* lcl_NextFrame( SwFrame* pFrame )
880 {
881 SwFrame *pRet = nullptr;
882 bool bGoingUp = false;
883 do {
884 SwFrame *p = nullptr;
885
886 bool bGoingFwd = false;
887 bool bGoingDown = !bGoingUp && pFrame->IsLayoutFrame();
888 if (bGoingDown)
889 {
890 p = static_cast<SwLayoutFrame*>(pFrame)->Lower();
891 bGoingDown = nullptr != p;
892 }
893 if( !bGoingDown )
894 {
895 p = pFrame->IsFlyFrame() ? static_cast<SwFlyFrame*>(pFrame)->GetNextLink() : pFrame->GetNext();
896 bGoingFwd = nullptr != p;
897 if ( !bGoingFwd )
898 {
899 p = pFrame->GetUpper();
900 bGoingUp = nullptr != p;
901 if ( !bGoingUp )
902 {
903 return nullptr;
904 }
905 }
906 }
907 bGoingUp = !(bGoingFwd || bGoingDown);
908 pFrame = p;
909 } while ( nullptr == (pRet = ( ( pFrame->IsContentFrame() || ( !bGoingUp &&
910 ( pFrame->IsTabFrame() || pFrame->IsSctFrame() ) ) )? pFrame : nullptr ) ) );
911 return pRet;
912 }
913
FindNext_()914 SwFrame *SwFrame::FindNext_()
915 {
916 bool bIgnoreTab = false;
917 SwFrame *pThis = this;
918
919 if ( IsTabFrame() )
920 {
921 //The last Content of the table gets picked up and his follower is
922 //returned. To be able to deactivate the special case for tables
923 //(see below) bIgnoreTab will be set.
924 if ( static_cast<SwTabFrame*>(this)->GetFollow() )
925 return static_cast<SwTabFrame*>(this)->GetFollow();
926
927 pThis = static_cast<SwTabFrame*>(this)->FindLastContentOrTable();
928 if ( !pThis )
929 pThis = this;
930 bIgnoreTab = true;
931 }
932 else if ( IsSctFrame() )
933 {
934 //The last Content of the section gets picked and his follower is returned.
935 if ( static_cast<SwSectionFrame*>(this)->GetFollow() )
936 return static_cast<SwSectionFrame*>(this)->GetFollow();
937
938 pThis = static_cast<SwSectionFrame*>(this)->FindLastContent();
939 if ( !pThis )
940 pThis = this;
941 }
942 else if ( IsContentFrame() )
943 {
944 if( static_cast<SwContentFrame*>(this)->GetFollow() )
945 return static_cast<SwContentFrame*>(this)->GetFollow();
946 }
947 else if ( IsRowFrame() )
948 {
949 SwFrame* pMyUpper = GetUpper();
950 if ( pMyUpper->IsTabFrame() && static_cast<SwTabFrame*>(pMyUpper)->GetFollow() )
951 return static_cast<SwTabFrame*>(pMyUpper)->GetFollow()->GetLower();
952 else return nullptr;
953 }
954 else
955 return nullptr;
956
957 SwFrame* pRet = nullptr;
958 const bool bFootnote = pThis->IsInFootnote();
959 if ( !bIgnoreTab && pThis->IsInTab() )
960 {
961 SwLayoutFrame *pUp = pThis->GetUpper();
962 while (pUp && !pUp->IsCellFrame())
963 pUp = pUp->GetUpper();
964 assert(pUp && "Content flag says it's in table but it's not in cell.");
965 SwFrame* pNxt = pUp ? static_cast<SwCellFrame*>(pUp)->GetFollowCell() : nullptr;
966 if ( pNxt )
967 pNxt = static_cast<SwCellFrame*>(pNxt)->ContainsContent();
968 if ( !pNxt )
969 {
970 pNxt = lcl_NextFrame( pThis );
971 if (pUp && pUp->IsAnLower(pNxt))
972 pRet = pNxt;
973 }
974 else
975 pRet = pNxt;
976 }
977 else
978 {
979 const bool bBody = pThis->IsInDocBody();
980 SwFrame *pNxtCnt = lcl_NextFrame( pThis );
981 if ( pNxtCnt )
982 {
983 if ( bBody || bFootnote )
984 {
985 while ( pNxtCnt )
986 {
987 // OD 02.04.2003 #108446# - check for endnote, only if found
988 // next content isn't contained in a section, that collect its
989 // endnotes at its end.
990 bool bEndn = IsInSct() && !IsSctFrame() &&
991 ( !pNxtCnt->IsInSct() ||
992 !pNxtCnt->FindSctFrame()->IsEndnAtEnd()
993 );
994 if ( ( bBody && pNxtCnt->IsInDocBody() ) ||
995 ( pNxtCnt->IsInFootnote() &&
996 ( bFootnote ||
997 ( bEndn && pNxtCnt->FindFootnoteFrame()->GetAttr()->GetFootnote().IsEndNote() )
998 )
999 )
1000 )
1001 {
1002 if (pNxtCnt->IsInTab())
1003 {
1004 if (!IsTabFrame() || !static_cast<SwLayoutFrame*>(this)->IsAnLower(pNxtCnt))
1005 {
1006 pRet = pNxtCnt->FindTabFrame();
1007 break;
1008 }
1009 }
1010 else
1011 {
1012 pRet = pNxtCnt;
1013 break;
1014 }
1015 }
1016 pNxtCnt = lcl_NextFrame( pNxtCnt );
1017 }
1018 }
1019 else if ( pThis->IsInFly() )
1020 {
1021 pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrame()
1022 : pNxtCnt;
1023 }
1024 else //footer-/or header section
1025 {
1026 const SwFrame *pUp = pThis->GetUpper();
1027 const SwFrame *pCntUp = pNxtCnt->GetUpper();
1028 while ( pUp && pUp->GetUpper() &&
1029 !pUp->IsHeaderFrame() && !pUp->IsFooterFrame() )
1030 pUp = pUp->GetUpper();
1031 while ( pCntUp && pCntUp->GetUpper() &&
1032 !pCntUp->IsHeaderFrame() && !pCntUp->IsFooterFrame() )
1033 pCntUp = pCntUp->GetUpper();
1034 if ( pCntUp == pUp )
1035 {
1036 pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrame()
1037 : pNxtCnt;
1038 }
1039 }
1040 }
1041 }
1042 if( pRet && pRet->IsInSct() )
1043 {
1044 SwSectionFrame* pSct = pRet->FindSctFrame();
1045 //Footnotes in frames with columns must not return the section which
1046 //contains the footnote
1047 if( !pSct->IsAnLower( this ) &&
1048 (!bFootnote || pSct->IsInFootnote() ) )
1049 return pSct;
1050 }
1051 return pRet == this ? nullptr : pRet;
1052 }
1053
1054 // #i27138# - add parameter <_bInSameFootnote>
FindNextCnt_(const bool _bInSameFootnote)1055 SwContentFrame *SwFrame::FindNextCnt_( const bool _bInSameFootnote )
1056 {
1057 SwFrame *pThis = this;
1058
1059 if ( IsTabFrame() )
1060 {
1061 if ( static_cast<SwTabFrame*>(this)->GetFollow() )
1062 {
1063 pThis = static_cast<SwTabFrame*>(this)->GetFollow()->ContainsContent();
1064 if( pThis )
1065 return static_cast<SwContentFrame*>(pThis);
1066 }
1067 pThis = static_cast<SwTabFrame*>(this)->FindLastContentOrTable();
1068 if ( !pThis )
1069 return nullptr;
1070 }
1071 else if ( IsSctFrame() )
1072 {
1073 if ( static_cast<SwSectionFrame*>(this)->GetFollow() )
1074 {
1075 pThis = static_cast<SwSectionFrame*>(this)->GetFollow()->ContainsContent();
1076 if( pThis )
1077 return static_cast<SwContentFrame*>(pThis);
1078 }
1079 pThis = static_cast<SwSectionFrame*>(this)->FindLastContent();
1080 if ( !pThis )
1081 return nullptr;
1082 }
1083 else if ( IsContentFrame() && static_cast<SwContentFrame*>(this)->GetFollow() )
1084 return static_cast<SwContentFrame*>(this)->GetFollow();
1085
1086 if ( pThis->IsContentFrame() )
1087 {
1088 const bool bBody = pThis->IsInDocBody();
1089 const bool bFootnote = pThis->IsInFootnote();
1090 SwContentFrame *pNxtCnt = static_cast<SwContentFrame*>(pThis)->GetNextContentFrame();
1091 if ( pNxtCnt )
1092 {
1093 // #i27138#
1094 if ( bBody || ( bFootnote && !_bInSameFootnote ) )
1095 {
1096 // handling for environments 'footnotes' and 'document body frames':
1097 while ( pNxtCnt )
1098 {
1099 if ( (bBody && pNxtCnt->IsInDocBody()) ||
1100 (bFootnote && pNxtCnt->IsInFootnote()) )
1101 return pNxtCnt;
1102 pNxtCnt = pNxtCnt->GetNextContentFrame();
1103 }
1104 }
1105 // #i27138#
1106 else if ( bFootnote && _bInSameFootnote )
1107 {
1108 // handling for environments 'each footnote':
1109 // Assure that found next content frame belongs to the same footnotes
1110 const SwFootnoteFrame* pFootnoteFrameOfNext( pNxtCnt->FindFootnoteFrame() );
1111 SwFootnoteFrame* pFootnoteFrameOfCurr(pThis->FindFootnoteFrame());
1112 OSL_ENSURE( pFootnoteFrameOfCurr,
1113 "<SwFrame::FindNextCnt_() - unknown layout situation: current frame has to have an upper footnote frame." );
1114 if ( pFootnoteFrameOfNext == pFootnoteFrameOfCurr )
1115 {
1116 return pNxtCnt;
1117 }
1118 else if ( pFootnoteFrameOfCurr->GetFollow() )
1119 {
1120 // next content frame has to be the first content frame
1121 // in the follow footnote, which contains a content frame.
1122 SwFootnoteFrame* pFollowFootnoteFrameOfCurr(pFootnoteFrameOfCurr);
1123 pNxtCnt = nullptr;
1124 do {
1125 pFollowFootnoteFrameOfCurr = pFollowFootnoteFrameOfCurr->GetFollow();
1126 pNxtCnt = pFollowFootnoteFrameOfCurr->ContainsContent();
1127 } while ( !pNxtCnt && pFollowFootnoteFrameOfCurr->GetFollow() );
1128 return pNxtCnt;
1129 }
1130 else
1131 {
1132 // current content frame is the last content frame in the
1133 // footnote - no next content frame exists.
1134 return nullptr;
1135 }
1136 }
1137 else if ( pThis->IsInFly() )
1138 // handling for environments 'unlinked fly frame' and
1139 // 'group of linked fly frames':
1140 return pNxtCnt;
1141 else
1142 {
1143 // handling for environments 'page header' and 'page footer':
1144 const SwFrame *pUp = pThis->GetUpper();
1145 const SwFrame *pCntUp = pNxtCnt->GetUpper();
1146 while ( pUp && pUp->GetUpper() &&
1147 !pUp->IsHeaderFrame() && !pUp->IsFooterFrame() )
1148 pUp = pUp->GetUpper();
1149 while ( pCntUp && pCntUp->GetUpper() &&
1150 !pCntUp->IsHeaderFrame() && !pCntUp->IsFooterFrame() )
1151 pCntUp = pCntUp->GetUpper();
1152 if ( pCntUp == pUp )
1153 return pNxtCnt;
1154 }
1155 }
1156 }
1157 return nullptr;
1158 }
1159
1160 /** method to determine previous content frame in the same environment
1161 for a flow frame (content frame, table frame, section frame)
1162
1163 OD 2005-11-30 #i27138#
1164 */
FindPrevCnt_()1165 SwContentFrame* SwFrame::FindPrevCnt_()
1166 {
1167 if ( !IsFlowFrame() )
1168 {
1169 // nothing to do, if current frame isn't a flow frame.
1170 return nullptr;
1171 }
1172
1173 SwContentFrame* pPrevContentFrame( nullptr );
1174
1175 // Because method <SwContentFrame::GetPrevContentFrame()> is used to travel
1176 // through the layout, a content frame, at which the travel starts, is needed.
1177 SwContentFrame* pCurrContentFrame = dynamic_cast<SwContentFrame*>(this);
1178
1179 // perform shortcut, if current frame is a follow, and
1180 // determine <pCurrContentFrame>, if current frame is a table or section frame
1181 if ( pCurrContentFrame && pCurrContentFrame->IsFollow() )
1182 {
1183 // previous content frame is its master content frame
1184 pPrevContentFrame = pCurrContentFrame->FindMaster();
1185 }
1186 else if ( IsTabFrame() )
1187 {
1188 SwTabFrame* pTabFrame( static_cast<SwTabFrame*>(this) );
1189 if ( pTabFrame->IsFollow() )
1190 {
1191 // previous content frame is the last content of its master table frame
1192 pPrevContentFrame = pTabFrame->FindMaster()->FindLastContent();
1193 }
1194 else
1195 {
1196 // start content frame for the search is the first content frame of
1197 // the table frame.
1198 pCurrContentFrame = pTabFrame->ContainsContent();
1199 }
1200 }
1201 else if ( IsSctFrame() )
1202 {
1203 SwSectionFrame* pSectFrame( static_cast<SwSectionFrame*>(this) );
1204 if ( pSectFrame->IsFollow() )
1205 {
1206 // previous content frame is the last content of its master section frame
1207 pPrevContentFrame = pSectFrame->FindMaster()->FindLastContent();
1208 }
1209 else
1210 {
1211 // start content frame for the search is the first content frame of
1212 // the section frame.
1213 pCurrContentFrame = pSectFrame->ContainsContent();
1214 }
1215 }
1216
1217 // search for next content frame, depending on the environment, in which
1218 // the current frame is in.
1219 if ( !pPrevContentFrame && pCurrContentFrame )
1220 {
1221 pPrevContentFrame = pCurrContentFrame->GetPrevContentFrame();
1222 if ( pPrevContentFrame )
1223 {
1224 if ( pCurrContentFrame->IsInFly() )
1225 {
1226 // handling for environments 'unlinked fly frame' and
1227 // 'group of linked fly frames':
1228 // Nothing to do, <pPrevContentFrame> is the one
1229 }
1230 else
1231 {
1232 const bool bInDocBody = pCurrContentFrame->IsInDocBody();
1233 const bool bInFootnote = pCurrContentFrame->IsInFootnote();
1234 if ( bInDocBody )
1235 {
1236 // handling for environments 'footnotes' and 'document body frames':
1237 // Assure that found previous frame is also in one of these
1238 // environments. Otherwise, travel further
1239 while ( pPrevContentFrame )
1240 {
1241 if ( ( bInDocBody && pPrevContentFrame->IsInDocBody() ) ||
1242 ( bInFootnote && pPrevContentFrame->IsInFootnote() ) )
1243 {
1244 break;
1245 }
1246 pPrevContentFrame = pPrevContentFrame->GetPrevContentFrame();
1247 }
1248 }
1249 else if ( bInFootnote )
1250 {
1251 // handling for environments 'each footnote':
1252 // Assure that found next content frame belongs to the same footnotes
1253 const SwFootnoteFrame* pFootnoteFrameOfPrev( pPrevContentFrame->FindFootnoteFrame() );
1254 SwFootnoteFrame* pFootnoteFrameOfCurr(pCurrContentFrame->FindFootnoteFrame());
1255 if ( pFootnoteFrameOfPrev != pFootnoteFrameOfCurr )
1256 {
1257 if ( pFootnoteFrameOfCurr->GetMaster() )
1258 {
1259 SwFootnoteFrame* pMasterFootnoteFrameOfCurr(pFootnoteFrameOfCurr);
1260 pPrevContentFrame = nullptr;
1261 // correct wrong loop-condition
1262 do {
1263 pMasterFootnoteFrameOfCurr = pMasterFootnoteFrameOfCurr->GetMaster();
1264 pPrevContentFrame = pMasterFootnoteFrameOfCurr->FindLastContent();
1265 } while ( !pPrevContentFrame &&
1266 pMasterFootnoteFrameOfCurr->GetMaster() );
1267 }
1268 else
1269 {
1270 // current content frame is the first content in the
1271 // footnote - no previous content exists.
1272 pPrevContentFrame = nullptr;
1273 }
1274 }
1275 }
1276 else
1277 {
1278 // handling for environments 'page header' and 'page footer':
1279 // Assure that found previous frame is also in the same
1280 // page header respectively page footer as <pCurrContentFrame>
1281 // Note: At this point it's clear that <pCurrContentFrame> has
1282 // to be inside a page header or page footer and that
1283 // neither <pCurrContentFrame> nor <pPrevContentFrame> are
1284 // inside a fly frame.
1285 // Thus, method <FindFooterOrHeader()> can be used.
1286 OSL_ENSURE( pCurrContentFrame->FindFooterOrHeader(),
1287 "<SwFrame::FindPrevCnt_()> - unknown layout situation: current frame should be in page header or page footer" );
1288 OSL_ENSURE( !pPrevContentFrame->IsInFly(),
1289 "<SwFrame::FindPrevCnt_()> - unknown layout situation: found previous frame should *not* be inside a fly frame." );
1290 if ( pPrevContentFrame->FindFooterOrHeader() !=
1291 pCurrContentFrame->FindFooterOrHeader() )
1292 {
1293 pPrevContentFrame = nullptr;
1294 }
1295 }
1296 }
1297 }
1298 }
1299
1300 return pPrevContentFrame;
1301 }
1302
FindPrev_()1303 SwFrame *SwFrame::FindPrev_()
1304 {
1305 bool bIgnoreTab = false;
1306 SwFrame *pThis = this;
1307
1308 if ( IsTabFrame() )
1309 {
1310 //The first Content of the table gets picked up and his predecessor is
1311 //returned. To be able to deactivate the special case for tables
1312 //(see below) bIgnoreTab will be set.
1313 if ( static_cast<SwTabFrame*>(this)->IsFollow() )
1314 return static_cast<SwTabFrame*>(this)->FindMaster();
1315 else
1316 pThis = static_cast<SwTabFrame*>(this)->ContainsContent();
1317 bIgnoreTab = true;
1318 }
1319
1320 if ( pThis && pThis->IsContentFrame() )
1321 {
1322 SwContentFrame *pPrvCnt = static_cast<SwContentFrame*>(pThis)->GetPrevContentFrame();
1323 if( !pPrvCnt )
1324 return nullptr;
1325 if ( !bIgnoreTab && pThis->IsInTab() )
1326 {
1327 SwLayoutFrame *pUp = pThis->GetUpper();
1328 while (pUp && !pUp->IsCellFrame())
1329 pUp = pUp->GetUpper();
1330 assert(pUp && "Content flag says it's in table but it's not in cell.");
1331 if (pUp && pUp->IsAnLower(pPrvCnt))
1332 return pPrvCnt;
1333 }
1334 else
1335 {
1336 SwFrame* pRet;
1337 const bool bBody = pThis->IsInDocBody();
1338 const bool bFootnote = !bBody && pThis->IsInFootnote();
1339 if ( bBody || bFootnote )
1340 {
1341 while ( pPrvCnt )
1342 {
1343 if ( (bBody && pPrvCnt->IsInDocBody()) ||
1344 (bFootnote && pPrvCnt->IsInFootnote()) )
1345 {
1346 pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrame()
1347 : static_cast<SwFrame*>(pPrvCnt);
1348 return pRet;
1349 }
1350 pPrvCnt = pPrvCnt->GetPrevContentFrame();
1351 }
1352 }
1353 else if ( pThis->IsInFly() )
1354 {
1355 pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrame()
1356 : static_cast<SwFrame*>(pPrvCnt);
1357 return pRet;
1358 }
1359 else // footer or header or Fly
1360 {
1361 const SwFrame *pUp = pThis->GetUpper();
1362 const SwFrame *pCntUp = pPrvCnt->GetUpper();
1363 while ( pUp && pUp->GetUpper() &&
1364 !pUp->IsHeaderFrame() && !pUp->IsFooterFrame() )
1365 pUp = pUp->GetUpper();
1366 while ( pCntUp && pCntUp->GetUpper() )
1367 pCntUp = pCntUp->GetUpper();
1368 if ( pCntUp == pUp )
1369 {
1370 pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrame()
1371 : static_cast<SwFrame*>(pPrvCnt);
1372 return pRet;
1373 }
1374 }
1375 }
1376 }
1377 return nullptr;
1378 }
1379
ImplInvalidateNextPos(bool bNoFootnote)1380 void SwFrame::ImplInvalidateNextPos( bool bNoFootnote )
1381 {
1382 SwFrame *pFrame = FindNext_();
1383 if ( nullptr == pFrame )
1384 return;
1385
1386 if( pFrame->IsSctFrame() )
1387 {
1388 while( pFrame && pFrame->IsSctFrame() )
1389 {
1390 if( static_cast<SwSectionFrame*>(pFrame)->GetSection() )
1391 {
1392 SwFrame* pTmp = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
1393 if( pTmp )
1394 pTmp->InvalidatePos();
1395 else if( !bNoFootnote )
1396 static_cast<SwSectionFrame*>(pFrame)->InvalidateFootnotePos();
1397 if( !IsInSct() || FindSctFrame()->GetFollow() != pFrame )
1398 pFrame->InvalidatePos();
1399 return;
1400 }
1401 pFrame = pFrame->FindNext();
1402 }
1403 if( pFrame )
1404 {
1405 if ( pFrame->IsSctFrame())
1406 {
1407 // We need to invalidate the section's content so it gets
1408 // the chance to flow to a different page.
1409 SwFrame* pTmp = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
1410 if( pTmp )
1411 pTmp->InvalidatePos();
1412 if( !IsInSct() || FindSctFrame()->GetFollow() != pFrame )
1413 pFrame->InvalidatePos();
1414 }
1415 else
1416 pFrame->InvalidatePos();
1417 }
1418 }
1419 else
1420 pFrame->InvalidatePos();
1421 }
1422
1423 /** method to invalidate printing area of next frame
1424
1425 OD 09.01.2004 #i11859#
1426
1427 FME 2004-04-19 #i27145# Moved function from SwTextFrame to SwFrame
1428 */
InvalidateNextPrtArea()1429 void SwFrame::InvalidateNextPrtArea()
1430 {
1431 // determine next frame
1432 SwFrame* pNextFrame = FindNext();
1433 // skip empty section frames and hidden text frames
1434 {
1435 while (pNextFrame && pNextFrame->IsHiddenNow())
1436 {
1437 pNextFrame = pNextFrame->FindNext();
1438 }
1439 }
1440
1441 // Invalidate printing area of found next frame
1442 if ( !pNextFrame )
1443 return;
1444
1445 if ( pNextFrame->IsSctFrame() )
1446 {
1447 // Invalidate printing area of found section frame, if
1448 // (1) this text frame isn't in a section OR
1449 // (2) found section frame isn't a follow of the section frame this
1450 // text frame is in.
1451 if ( !IsInSct() || FindSctFrame()->GetFollow() != pNextFrame )
1452 {
1453 pNextFrame->InvalidatePrt();
1454 }
1455
1456 // Invalidate printing area of first content in found section.
1457 SwFrame* pFstContentOfSctFrame =
1458 static_cast<SwSectionFrame*>(pNextFrame)->ContainsAny();
1459 if ( pFstContentOfSctFrame )
1460 {
1461 pFstContentOfSctFrame->InvalidatePrt();
1462 }
1463 }
1464 else
1465 {
1466 pNextFrame->InvalidatePrt();
1467 }
1468 }
1469
1470 /// @returns true if the frame _directly_ sits in a section
1471 /// but not if it sits in a table which itself sits in a section.
lcl_IsInSectionDirectly(const SwFrame * pUp)1472 static bool lcl_IsInSectionDirectly( const SwFrame *pUp )
1473 {
1474 bool bSeenColumn = false;
1475
1476 while( pUp )
1477 {
1478 if( pUp->IsColumnFrame() )
1479 bSeenColumn = true;
1480 else if( pUp->IsSctFrame() )
1481 {
1482 auto pSection = static_cast<const SwSectionFrame*>(pUp);
1483 const SwFrame* pHeaderFooter = pSection->FindFooterOrHeader();
1484 // When the section frame is not in header/footer:
1485 // Allow move of frame in case our only column is not growable.
1486 // Also allow if there is a previous section frame (to move back).
1487 bool bAllowOutsideHeaderFooter = !pSection->Growable() || pSection->GetPrecede();
1488 return bSeenColumn || (!pHeaderFooter && bAllowOutsideHeaderFooter);
1489 }
1490 else if( pUp->IsTabFrame() )
1491 return false;
1492 pUp = pUp->GetUpper();
1493 }
1494 return false;
1495 }
1496
1497 /** determine, if frame is moveable in given environment
1498
1499 OD 08.08.2003 #110978#
1500 method replaced 'old' method <sal_Bool IsMoveable() const>.
1501 Determines, if frame is moveable in given environment. if no environment
1502 is given (parameter _pLayoutFrame == 0), the movability in the actual
1503 environment (<GetUpper()) is checked.
1504 */
IsMoveable(const SwLayoutFrame * _pLayoutFrame) const1505 bool SwFrame::IsMoveable( const SwLayoutFrame* _pLayoutFrame ) const
1506 {
1507 bool bRetVal = false;
1508
1509 if ( !_pLayoutFrame )
1510 {
1511 _pLayoutFrame = GetUpper();
1512 }
1513
1514 if ( _pLayoutFrame && IsFlowFrame() )
1515 {
1516 if ( _pLayoutFrame->IsInSct() && lcl_IsInSectionDirectly( _pLayoutFrame ) )
1517 {
1518 bRetVal = true;
1519 }
1520 else if ( _pLayoutFrame->IsInFly() ||
1521 _pLayoutFrame->IsInDocBody() ||
1522 _pLayoutFrame->IsInFootnote() )
1523 {
1524 // If IsMovable() is called before a MoveFwd() the method
1525 // may return false if there is no NextCellLeaf. If
1526 // IsMovable() is called before a MoveBwd() the method may
1527 // return false if there is no PrevCellLeaf.
1528 if ( _pLayoutFrame->IsInTab() && !IsTabFrame() &&
1529 ( !IsContentFrame() || (!const_cast<SwFrame*>(this)->GetNextCellLeaf()
1530 && !const_cast<SwFrame*>(this)->GetPrevCellLeaf()) )
1531 )
1532 {
1533 bRetVal = false;
1534 }
1535 else
1536 {
1537 if ( _pLayoutFrame->IsInFly() )
1538 {
1539 // if fly frame has a follow (next linked fly frame) or can split,
1540 // frame is moveable.
1541 const SwFlyFrame* pFlyFrame = _pLayoutFrame->FindFlyFrame();
1542 if ( pFlyFrame->GetNextLink() || pFlyFrame->IsFlySplitAllowed() )
1543 {
1544 bRetVal = true;
1545 }
1546 else
1547 {
1548 // if environment is columned, frame is moveable, if
1549 // it isn't in last column.
1550 // search for column frame
1551 const SwFrame* pCol = _pLayoutFrame;
1552 while ( pCol && !pCol->IsColumnFrame() )
1553 {
1554 pCol = pCol->GetUpper();
1555 }
1556 // frame is moveable, if found column frame isn't last one.
1557 if ( pCol && pCol->GetNext() )
1558 {
1559 bRetVal = true;
1560 }
1561 }
1562 }
1563 else if (!(_pLayoutFrame->IsInFootnote() && (IsTabFrame() || IsInTab())))
1564 {
1565 bRetVal = true;
1566 }
1567 }
1568 }
1569 }
1570
1571 return bRetVal;
1572 }
1573
SetInfFlags()1574 void SwFrame::SetInfFlags()
1575 {
1576 if ( !IsFlyFrame() && !GetUpper() ) //not yet pasted, no information available
1577 return;
1578
1579 mbInfInvalid = mbInfBody = mbInfTab = mbInfFly = mbInfFootnote = mbInfSct = false;
1580
1581 SwFrame *pFrame = this;
1582 if( IsFootnoteContFrame() )
1583 mbInfFootnote = true;
1584 do
1585 {
1586 // mbInfBody is only set in the page body, but not in the column body
1587 if ( pFrame->IsBodyFrame() && !mbInfFootnote && pFrame->GetUpper()
1588 && pFrame->GetUpper()->IsPageFrame() )
1589 mbInfBody = true;
1590 else if ( pFrame->IsTabFrame() || pFrame->IsCellFrame() )
1591 {
1592 mbInfTab = true;
1593 }
1594 else if ( pFrame->IsFlyFrame() )
1595 mbInfFly = true;
1596 else if ( pFrame->IsSctFrame() )
1597 mbInfSct = true;
1598 else if ( pFrame->IsFootnoteFrame() )
1599 mbInfFootnote = true;
1600
1601 pFrame = pFrame->GetUpper();
1602
1603 } while ( pFrame && !pFrame->IsPageFrame() ); //there is nothing above the page
1604 }
1605
1606 /** Updates the vertical or the righttoleft-flags.
1607 *
1608 * If the property is derived, it's from the upper or (for fly frames) from
1609 * the anchor. Otherwise we've to call a virtual method to check the property.
1610 */
SetDirFlags(bool bVert)1611 void SwFrame::SetDirFlags( bool bVert )
1612 {
1613 if( bVert )
1614 {
1615 // OD 2004-01-21 #114969# - if derived, valid vertical flag only if
1616 // vertical flag of upper/anchor is valid.
1617 if( mbDerivedVert )
1618 {
1619 const SwFrame* pAsk = IsFlyFrame() ?
1620 static_cast<SwFlyFrame*>(this)->GetAnchorFrame() : GetUpper();
1621
1622 OSL_ENSURE( pAsk != this, "Autsch! Stack overflow is about to happen" );
1623
1624 if( pAsk )
1625 {
1626 mbVertical = pAsk->IsVertical();
1627 mbVertLR = pAsk->IsVertLR();
1628 mbVertLRBT = pAsk->IsVertLRBT();
1629
1630 if ( !pAsk->mbInvalidVert )
1631 mbInvalidVert = false;
1632
1633 if ( IsCellFrame() )
1634 {
1635 SwCellFrame* pPrv = static_cast<SwCellFrame*>(this)->GetPreviousCell();
1636 if ( pPrv && !mbVertical && pPrv->IsVertical() )
1637 {
1638 mbVertical = pPrv->IsVertical();
1639 mbVertLR = pPrv->IsVertLR();
1640 mbVertLRBT = pPrv->IsVertLRBT();
1641 }
1642 }
1643 }
1644 }
1645 else
1646 CheckDirection( bVert );
1647 }
1648 else
1649 {
1650 bool bInv = false;
1651 if( !mbDerivedR2L ) // CheckDirection is able to set bDerivedR2L!
1652 CheckDirection( bVert );
1653 if( mbDerivedR2L )
1654 {
1655 const SwFrame* pAsk = IsFlyFrame() ?
1656 static_cast<SwFlyFrame*>(this)->GetAnchorFrame() : GetUpper();
1657
1658 OSL_ENSURE( pAsk != this, "Oops! Stack overflow is about to happen" );
1659
1660 if( pAsk )
1661 mbRightToLeft = pAsk->IsRightToLeft();
1662 if( !pAsk || pAsk->mbInvalidR2L )
1663 bInv = mbInvalidR2L;
1664 }
1665 mbInvalidR2L = bInv;
1666 }
1667 }
1668
GetNextCellLeaf()1669 SwLayoutFrame* SwFrame::GetNextCellLeaf()
1670 {
1671 SwFrame* pTmpFrame = this;
1672 while (pTmpFrame && !pTmpFrame->IsCellFrame())
1673 pTmpFrame = pTmpFrame->GetUpper();
1674
1675 SAL_WARN_IF(!pTmpFrame, "sw.core", "SwFrame::GetNextCellLeaf() without cell");
1676 return pTmpFrame ? static_cast<SwCellFrame*>(pTmpFrame)->GetFollowCell() : nullptr;
1677 }
1678
GetPrevCellLeaf()1679 SwLayoutFrame* SwFrame::GetPrevCellLeaf()
1680 {
1681 SwFrame* pTmpFrame = this;
1682 while (pTmpFrame && !pTmpFrame->IsCellFrame())
1683 pTmpFrame = pTmpFrame->GetUpper();
1684
1685 SAL_WARN_IF(!pTmpFrame, "sw.core", "SwFrame::GetNextPreviousLeaf() without cell");
1686 return pTmpFrame ? static_cast<SwCellFrame*>(pTmpFrame)->GetPreviousCell() : nullptr;
1687 }
1688
lcl_FindCorrespondingCellFrame(const SwRowFrame & rOrigRow,const SwCellFrame & rOrigCell,const SwRowFrame & rCorrRow,bool bInFollow)1689 static SwCellFrame* lcl_FindCorrespondingCellFrame( const SwRowFrame& rOrigRow,
1690 const SwCellFrame& rOrigCell,
1691 const SwRowFrame& rCorrRow,
1692 bool bInFollow )
1693 {
1694 SwCellFrame* pRet = nullptr;
1695 const SwCellFrame* pCell = static_cast<const SwCellFrame*>(rOrigRow.Lower());
1696 SwCellFrame* pCorrCell = const_cast<SwCellFrame*>(static_cast<const SwCellFrame*>(rCorrRow.Lower()));
1697
1698 while ( pCell != &rOrigCell && !pCell->IsAnLower( &rOrigCell ) )
1699 {
1700 pCell = static_cast<const SwCellFrame*>(pCell->GetNext());
1701 pCorrCell = static_cast<SwCellFrame*>(pCorrCell->GetNext());
1702 }
1703
1704 assert(pCell && pCorrCell && "lcl_FindCorrespondingCellFrame does not work");
1705
1706 if ( pCell != &rOrigCell )
1707 {
1708 // rOrigCell must be a lower of pCell. We need to recurse into the rows:
1709 assert(pCell->Lower() && pCell->Lower()->IsRowFrame() &&
1710 "lcl_FindCorrespondingCellFrame does not work");
1711
1712 const SwRowFrame* pRow = static_cast<const SwRowFrame*>(pCell->Lower());
1713 while ( !pRow->IsAnLower( &rOrigCell ) )
1714 pRow = static_cast<const SwRowFrame*>(pRow->GetNext());
1715
1716 SwRowFrame* pCorrRow = nullptr;
1717 if ( bInFollow )
1718 pCorrRow = pRow->GetFollowRow();
1719 else
1720 {
1721 SwRowFrame* pTmpRow = static_cast<SwRowFrame*>(pCorrCell->GetLastLower());
1722
1723 if ( pTmpRow && pTmpRow->GetFollowRow() == pRow )
1724 pCorrRow = pTmpRow;
1725 }
1726
1727 if ( pCorrRow )
1728 pRet = lcl_FindCorrespondingCellFrame( *pRow, rOrigCell, *pCorrRow, bInFollow );
1729 }
1730 else
1731 pRet = pCorrCell;
1732
1733 return pRet;
1734 }
1735
1736 // VERSION OF GetFollowCell() that assumes that we always have a follow flow line:
GetFollowCell() const1737 SwCellFrame* SwCellFrame::GetFollowCell() const
1738 {
1739 SwCellFrame* pRet = nullptr;
1740
1741 // NEW TABLES
1742 // Covered cells do not have follow cells!
1743 const tools::Long nRowSpan = GetLayoutRowSpan();
1744 if ( nRowSpan < 1 )
1745 return nullptr;
1746
1747 // find most upper row frame
1748 const SwFrame* pRow = GetUpper();
1749
1750 while (pRow && (!pRow->IsRowFrame() || !pRow->GetUpper()->IsTabFrame()))
1751 pRow = pRow->GetUpper();
1752
1753 if (!pRow)
1754 return nullptr;
1755
1756 const SwTabFrame* pTabFrame = static_cast<const SwTabFrame*>(pRow->GetUpper());
1757 if (!pTabFrame || !pTabFrame->GetFollow() || !pTabFrame->HasFollowFlowLine())
1758 return nullptr;
1759
1760 const SwCellFrame* pThisCell = this;
1761
1762 // Get last cell of the current table frame that belongs to the rowspan:
1763 if ( nRowSpan > 1 )
1764 {
1765 // optimization: Will end of row span be in last row or exceed row?
1766 tools::Long nMax = 0;
1767 while ( pRow->GetNext() && ++nMax < nRowSpan )
1768 pRow = pRow->GetNext();
1769
1770 if ( !pRow->GetNext() )
1771 {
1772 pThisCell = &pThisCell->FindStartEndOfRowSpanCell( false );
1773 pRow = pThisCell->GetUpper();
1774 }
1775 }
1776
1777 const SwRowFrame* pFollowRow = nullptr;
1778 if ( !pRow->GetNext() &&
1779 nullptr != ( pFollowRow = pRow->IsInSplitTableRow() ) &&
1780 ( !pFollowRow->IsRowSpanLine() || nRowSpan > 1 ) )
1781 pRet = lcl_FindCorrespondingCellFrame( *static_cast<const SwRowFrame*>(pRow), *pThisCell, *pFollowRow, true );
1782
1783 return pRet;
1784 }
1785
1786 // VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL
GetPreviousCell() const1787 SwCellFrame* SwCellFrame::GetPreviousCell() const
1788 {
1789 SwCellFrame* pRet = nullptr;
1790
1791 // NEW TABLES
1792 // Covered cells do not have previous cells!
1793 if ( GetLayoutRowSpan() < 1 )
1794 return nullptr;
1795
1796 // find most upper row frame
1797 const SwFrame* pRow = GetUpper();
1798 while( !pRow->IsRowFrame() || (pRow->GetUpper() && !pRow->GetUpper()->IsTabFrame()) )
1799 pRow = pRow->GetUpper();
1800
1801 OSL_ENSURE( pRow->GetUpper() && pRow->GetUpper()->IsTabFrame(), "GetPreviousCell without Table" );
1802
1803 const SwTabFrame* pTab = static_cast<const SwTabFrame*>(pRow->GetUpper());
1804
1805 if ( pTab && pTab->IsFollow() )
1806 {
1807 const SwFrame* pTmp = pTab->GetFirstNonHeadlineRow();
1808 const bool bIsInFirstLine = ( pTmp == pRow );
1809
1810 if ( bIsInFirstLine )
1811 {
1812 SwTabFrame *pMaster = pTab->FindMaster();
1813 if ( pMaster && pMaster->HasFollowFlowLine() )
1814 {
1815 SwRowFrame* pMasterRow = static_cast<SwRowFrame*>(pMaster->GetLastLower());
1816 if ( pMasterRow )
1817 pRet = lcl_FindCorrespondingCellFrame( *static_cast<const SwRowFrame*>(pRow), *this, *pMasterRow, false );
1818 if ( pRet && pRet->GetTabBox()->getRowSpan() < 1 )
1819 pRet = &const_cast<SwCellFrame&>(pRet->FindStartEndOfRowSpanCell( true ));
1820 }
1821 }
1822 }
1823
1824 return pRet;
1825 }
1826
1827 // --> NEW TABLES
FindStartEndOfRowSpanCell(bool bStart) const1828 const SwCellFrame& SwCellFrame::FindStartEndOfRowSpanCell( bool bStart ) const
1829 {
1830 const SwTabFrame* pTableFrame = dynamic_cast<const SwTabFrame*>(GetUpper()->GetUpper());
1831
1832 if ( !bStart && pTableFrame && pTableFrame->IsFollow() && pTableFrame->IsInHeadline( *this ) )
1833 return *this;
1834
1835 OSL_ENSURE( pTableFrame &&
1836 ( (bStart && GetTabBox()->getRowSpan() < 1) ||
1837 (!bStart && GetLayoutRowSpan() > 1) ),
1838 "SwCellFrame::FindStartRowSpanCell: No rowspan, no table, no cookies" );
1839
1840 if ( pTableFrame )
1841 {
1842 const SwTable* pTable = pTableFrame->GetTable();
1843
1844 sal_uInt16 nMax = USHRT_MAX;
1845 const SwFrame* pCurrentRow = GetUpper();
1846 const bool bDoNotEnterHeadline = bStart && pTableFrame->IsFollow() &&
1847 !pTableFrame->IsInHeadline( *pCurrentRow );
1848
1849 // check how many rows we are allowed to go up or down until we reach the end of
1850 // the current table frame:
1851 nMax = 0;
1852 while ( bStart ? pCurrentRow->GetPrev() : pCurrentRow->GetNext() )
1853 {
1854 if ( bStart )
1855 {
1856 // do not enter a repeated headline:
1857 if ( bDoNotEnterHeadline && pTableFrame->IsFollow() &&
1858 pTableFrame->IsInHeadline( *pCurrentRow->GetPrev() ) )
1859 break;
1860
1861 pCurrentRow = pCurrentRow->GetPrev();
1862 }
1863 else
1864 pCurrentRow = pCurrentRow->GetNext();
1865
1866 ++nMax;
1867 }
1868
1869 // By passing the nMax value for Find*OfRowSpan (in case of bCurrentTableOnly
1870 // is set) we assure that we find a rMasterBox that has a SwCellFrame in
1871 // the current table frame:
1872 const SwTableBox& rMasterBox = bStart ?
1873 GetTabBox()->FindStartOfRowSpan( *pTable, nMax ) :
1874 GetTabBox()->FindEndOfRowSpan( *pTable, nMax );
1875
1876 SwIterator<SwCellFrame,SwFormat> aIter( *rMasterBox.GetFrameFormat() );
1877
1878 for ( SwCellFrame* pMasterCell = aIter.First(); pMasterCell; pMasterCell = aIter.Next() )
1879 {
1880 if ( pMasterCell->GetTabBox() == &rMasterBox )
1881 {
1882 const SwTabFrame* pMasterTable = static_cast<const SwTabFrame*>(pMasterCell->GetUpper()->GetUpper());
1883
1884 if ( pMasterTable == pTableFrame )
1885 {
1886 return *pMasterCell;
1887 }
1888 }
1889 }
1890 }
1891
1892 SAL_WARN("sw.core", "SwCellFrame::FindStartRowSpanCell: No result");
1893
1894 return *this;
1895 }
1896
1897 // <-- NEW TABLES
1898
IsInSplitTableRow() const1899 const SwRowFrame* SwFrame::IsInSplitTableRow() const
1900 {
1901 OSL_ENSURE( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" );
1902
1903 const SwFrame* pRow = this;
1904
1905 // find most upper row frame
1906 while( pRow && ( !pRow->IsRowFrame() || !pRow->GetUpper()->IsTabFrame() ) )
1907 pRow = pRow->GetUpper();
1908
1909 if ( !pRow ) return nullptr;
1910
1911 OSL_ENSURE( pRow->GetUpper()->IsTabFrame(), "Confusion in table layout" );
1912
1913 const SwTabFrame* pTab = static_cast<const SwTabFrame*>(pRow->GetUpper());
1914
1915 // If most upper row frame is a headline row, the current frame
1916 // can't be in a split table row. Thus, add corresponding condition.
1917 if ( pRow->GetNext() ||
1918 pTab->GetTable()->IsHeadline(
1919 *(static_cast<const SwRowFrame*>(pRow)->GetTabLine()) ) ||
1920 !pTab->HasFollowFlowLine() ||
1921 !pTab->GetFollow() )
1922 return nullptr;
1923
1924 // skip headline
1925 const SwRowFrame* pFollowRow = pTab->GetFollow()->GetFirstNonHeadlineRow();
1926
1927 OSL_ENSURE( pFollowRow, "SwFrame::IsInSplitTableRow() does not work" );
1928
1929 return pFollowRow;
1930 }
1931
IsInFollowFlowRow() const1932 const SwRowFrame* SwFrame::IsInFollowFlowRow() const
1933 {
1934 OSL_ENSURE( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" );
1935
1936 // find most upper row frame
1937 const SwFrame* pRow = this;
1938 while( pRow && ( !pRow->IsRowFrame() || !pRow->GetUpper()->IsTabFrame() ) )
1939 pRow = pRow->GetUpper();
1940
1941 if ( !pRow ) return nullptr;
1942
1943 OSL_ENSURE( pRow->GetUpper()->IsTabFrame(), "Confusion in table layout" );
1944
1945 const SwTabFrame* pTab = static_cast<const SwTabFrame*>(pRow->GetUpper());
1946
1947 const SwTabFrame* pMaster = pTab->IsFollow() ? pTab->FindMaster() : nullptr;
1948
1949 if ( !pMaster || !pMaster->HasFollowFlowLine() )
1950 return nullptr;
1951
1952 const SwFrame* pTmp = pTab->GetFirstNonHeadlineRow();
1953 const bool bIsInFirstLine = ( pTmp == pRow );
1954
1955 if ( !bIsInFirstLine )
1956 return nullptr;
1957
1958 const SwRowFrame* pMasterRow = static_cast<const SwRowFrame*>(pMaster->GetLastLower());
1959 return pMasterRow;
1960 }
1961
IsInBalancedSection() const1962 bool SwFrame::IsInBalancedSection() const
1963 {
1964 bool bRet = false;
1965
1966 if ( IsInSct() )
1967 {
1968 const SwSectionFrame* pSectionFrame = FindSctFrame();
1969 if ( pSectionFrame )
1970 bRet = pSectionFrame->IsBalancedSection();
1971 }
1972 return bRet;
1973 }
1974
GetLastLower() const1975 const SwFrame* SwLayoutFrame::GetLastLower() const
1976 {
1977 const SwFrame* pRet = Lower();
1978 if ( !pRet )
1979 return nullptr;
1980 while ( pRet->GetNext() )
1981 pRet = pRet->GetNext();
1982 return pRet;
1983 }
1984
DynCastTextFrame()1985 SwTextFrame* SwFrame::DynCastTextFrame()
1986 {
1987 return IsTextFrame() ? static_cast<SwTextFrame*>(this) : nullptr;
1988 }
1989
DynCastTextFrame() const1990 const SwTextFrame* SwFrame::DynCastTextFrame() const
1991 {
1992 return IsTextFrame() ? static_cast<const SwTextFrame*>(this) : nullptr;
1993 }
1994
DynCastPageFrame()1995 SwPageFrame* SwFrame::DynCastPageFrame()
1996 {
1997 return IsPageFrame() ? static_cast<SwPageFrame*>(this) : nullptr;
1998 }
1999
DynCastPageFrame() const2000 const SwPageFrame* SwFrame::DynCastPageFrame() const
2001 {
2002 return IsPageFrame() ? static_cast<const SwPageFrame*>(this) : nullptr;
2003 }
2004
DynCastColumnFrame()2005 SwColumnFrame* SwFrame::DynCastColumnFrame()
2006 {
2007 return IsColumnFrame() ? static_cast<SwColumnFrame*>(this) : nullptr;
2008 }
2009
DynCastColumnFrame() const2010 const SwColumnFrame* SwFrame::DynCastColumnFrame() const
2011 {
2012 return IsColumnFrame() ? static_cast<const SwColumnFrame*>(this) : nullptr;
2013 }
2014
2015 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2016