LibreOffice Module sw (master)  1
ftnfrm.cxx
Go to the documentation of this file.
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 <txtftn.hxx>
21 #include <fmtftn.hxx>
22 #include <ftnidx.hxx>
23 #include <pagefrm.hxx>
24 #include <colfrm.hxx>
25 #include <rootfrm.hxx>
26 #include <frmtool.hxx>
27 #include <ftnfrm.hxx>
28 #include <txtfrm.hxx>
29 #include <tabfrm.hxx>
30 #include <pagedesc.hxx>
31 #include <ftninfo.hxx>
32 #include <sectfrm.hxx>
33 #include <objectformatter.hxx>
34 #include <viewopt.hxx>
35 #include <calbck.hxx>
36 #include <ndindex.hxx>
37 #include <pam.hxx>
38 #include <ndtxt.hxx>
39 #include <sal/log.hxx>
40 
41 #define ENDNOTE 0x80000000
42 
45 static sal_uLong lcl_FindFootnotePos( const SwDoc *pDoc, const SwTextFootnote *pAttr )
46 {
47  const SwFootnoteIdxs &rFootnoteIdxs = pDoc->GetFootnoteIdxs();
48 
49  SwTextFootnote* pBla = const_cast<SwTextFootnote*>(pAttr);
50  SwFootnoteIdxs::const_iterator it = rFootnoteIdxs.find( pBla );
51  if ( it != rFootnoteIdxs.end() )
52  {
53  sal_uLong nRet = it - rFootnoteIdxs.begin();
54  if( pAttr->GetFootnote().IsEndNote() )
55  return nRet + ENDNOTE;
56  return nRet;
57  }
58  OSL_ENSURE( !pDoc, "FootnotePos not found." );
59  return 0;
60 }
61 
62 bool SwFootnoteFrame::operator<( const SwTextFootnote* pTextFootnote ) const
63 {
64  const SwDoc* pDoc = GetFormat()->GetDoc();
65  OSL_ENSURE( pDoc, "SwFootnoteFrame: Missing doc!" );
66  return lcl_FindFootnotePos( pDoc, GetAttr() ) <
67  lcl_FindFootnotePos( pDoc, pTextFootnote );
68 }
69 
70 /*
71 |*
72 |* bool lcl_NextFootnoteBoss( SwFootnoteBossFrame* pBoss, SwPageFrame* pPage)
73 |* sets pBoss on the next SwFootnoteBossFrame, which can either be a column
74 |* or a page (without columns). If the page changes meanwhile,
75 |* pPage contains the new page and this function returns true.
76 |*
77 |*/
78 
79 static bool lcl_NextFootnoteBoss( SwFootnoteBossFrame* &rpBoss, SwPageFrame* &rpPage,
80  bool bDontLeave )
81 {
82  if( rpBoss->IsColumnFrame() )
83  {
84  if( rpBoss->GetNext() )
85  {
86  rpBoss = static_cast<SwFootnoteBossFrame*>(rpBoss->GetNext()); //next column
87  return false;
88  }
89  if( rpBoss->IsInSct() )
90  {
91  SwSectionFrame* pSct = rpBoss->FindSctFrame()->GetFollow();
92  if( pSct )
93  {
94  OSL_ENSURE( pSct->Lower() && pSct->Lower()->IsColumnFrame(),
95  "Where's the column?" );
96  rpBoss = static_cast<SwColumnFrame*>(pSct->Lower());
97  SwPageFrame* pOld = rpPage;
98  rpPage = pSct->FindPageFrame();
99  return pOld != rpPage;
100  }
101  else if( bDontLeave )
102  {
103  rpPage = nullptr;
104  rpBoss = nullptr;
105  return false;
106  }
107  }
108  }
109  rpPage = static_cast<SwPageFrame*>(rpPage->GetNext()); // next page
110  rpBoss = rpPage;
111  if( rpPage )
112  {
113  SwLayoutFrame* pBody = rpPage->FindBodyCont();
114  if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrame() )
115  rpBoss = static_cast<SwFootnoteBossFrame*>(pBody->Lower()); // first column
116  }
117  return true;
118 }
119 
121 static sal_uInt16 lcl_ColumnNum( const SwFrame* pBoss )
122 {
123  sal_uInt16 nRet = 0;
124  if( !pBoss->IsColumnFrame() )
125  return 0;
126  const SwFrame* pCol;
127  if( pBoss->IsInSct() )
128  {
129  pCol = pBoss->GetUpper()->FindColFrame();
130  if( pBoss->GetNext() || pBoss->GetPrev() )
131  {
132  while( pBoss )
133  {
134  ++nRet; // Section columns
135  pBoss = pBoss->GetPrev();
136  }
137  }
138  }
139  else
140  pCol = pBoss;
141  while( pCol )
142  {
143  nRet += 256; // Page columns
144  pCol = pCol->GetPrev();
145  }
146  return nRet;
147 }
148 
150  SwLayoutFrame( pFormat, pSib )
151 {
153 }
154 
155 
156 // lcl_Undersize(..) walks over a SwFrame and its contents
157 // and returns the sum of all requested TextFrame magnifications.
158 
159 static long lcl_Undersize( const SwFrame* pFrame )
160 {
161  long nRet = 0;
162  SwRectFnSet aRectFnSet(pFrame);
163  if( pFrame->IsTextFrame() )
164  {
165  if( static_cast<const SwTextFrame*>(pFrame)->IsUndersized() )
166  {
167  // Does this TextFrame would like to be a little bit bigger?
168  nRet = static_cast<const SwTextFrame*>(pFrame)->GetParHeight() -
169  aRectFnSet.GetHeight(pFrame->getFramePrintArea());
170  if( nRet < 0 )
171  nRet = 0;
172  }
173  }
174  else if( pFrame->IsLayoutFrame() )
175  {
176  const SwFrame* pNxt = static_cast<const SwLayoutFrame*>(pFrame)->Lower();
177  while( pNxt )
178  {
179  nRet += lcl_Undersize( pNxt );
180  pNxt = pNxt->GetNext();
181  }
182  }
183  return nRet;
184 }
185 
188 {
189  // calculate total border, only one distance to the top
190  const SwPageFrame* pPage = FindPageFrame();
191  const SwPageFootnoteInfo &rInf = pPage->GetPageDesc()->GetFootnoteInfo();
192  const SwTwips nBorder = rInf.GetTopDist() + rInf.GetBottomDist() +
193  rInf.GetLineWidth();
194  SwRectFnSet aRectFnSet(this);
195 
196  if ( !isFramePrintAreaValid() )
197  {
200 
201  aRectFnSet.SetTop( aPrt, nBorder );
202  aRectFnSet.SetWidth( aPrt, aRectFnSet.GetWidth(getFrameArea()) );
203  aRectFnSet.SetHeight(aPrt, aRectFnSet.GetHeight(getFrameArea()) - nBorder );
204 
205  if( aRectFnSet.GetHeight(aPrt) < 0 && !pPage->IsFootnotePage() )
206  {
207  setFrameAreaSizeValid(false);
208  }
209  }
210 
211  if ( !isFrameAreaSizeValid() )
212  {
213  bool bGrow = pPage->IsFootnotePage();
214  if( bGrow )
215  {
216  const SwViewShell *pSh = getRootFrame() ? getRootFrame()->GetCurrShell() : nullptr;
217  if( pSh && pSh->GetViewOptions()->getBrowseMode() )
218  bGrow = false;
219  }
220  if( bGrow )
221  Grow( LONG_MAX );
222  else
223  {
224  // VarSize is determined based on the content plus the borders
225  SwTwips nRemaining = 0;
226  SwFrame *pFrame = m_pLower;
227  while ( pFrame )
228  { // lcl_Undersize(..) respects (recursively) TextFrames, which
229  // would like to be bigger. They are created especially in
230  // columnized borders, if these do not have their maximum
231  // size yet.
232  nRemaining += aRectFnSet.GetHeight(pFrame->getFrameArea()) + lcl_Undersize( pFrame );
233  pFrame = pFrame->GetNext();
234  }
235  // add the own border
236  nRemaining += nBorder;
237 
238  SwTwips nDiff;
239  if( IsInSct() )
240  {
241  nDiff = -aRectFnSet.BottomDist( getFrameArea(), aRectFnSet.GetPrtBottom(*GetUpper()) );
242  if( nDiff > 0 )
243  {
244  if( nDiff > aRectFnSet.GetHeight(getFrameArea()) )
245  {
246  nDiff = aRectFnSet.GetHeight(getFrameArea());
247  }
248 
250  aRectFnSet.AddBottom( aFrm, -nDiff );
251  aRectFnSet.AddHeight( aFrm, -nDiff );
252  }
253  }
254  nDiff = aRectFnSet.GetHeight(getFrameArea()) - nRemaining;
255  if ( nDiff > 0 )
256  Shrink( nDiff );
257  else if ( nDiff < 0 )
258  {
259  Grow( -nDiff );
260  // It may happen that there is less space available,
261  // than what the border needs - the size of the PrtArea
262  // will then be negative.
263  SwTwips nPrtHeight = aRectFnSet.GetHeight(getFramePrintArea());
264  if( nPrtHeight < 0 )
265  {
266  const SwTwips nTmpDiff = std::max( aRectFnSet.GetTop(getFramePrintArea()), -nPrtHeight );
268  aRectFnSet.SubTop( aPrt, nTmpDiff );
269  }
270  }
271  }
272 
273  setFrameAreaSizeValid(true);
274  }
275 }
276 
278 {
279  // No check if FixSize since FootnoteContainer are variable up to their max. height.
280  // If the max. height is LONG_MAX, take as much space as needed.
281  // If the page is a special footnote page, take also as much as possible.
282  assert(GetUpper() && GetUpper()->IsFootnoteBossFrame());
283 
284  SwRectFnSet aRectFnSet(this);
285  if( aRectFnSet.GetHeight(getFrameArea()) > 0 &&
286  nDist > ( LONG_MAX - aRectFnSet.GetHeight(getFrameArea()) ) )
287  nDist = LONG_MAX - aRectFnSet.GetHeight(getFrameArea());
288 
289  SwFootnoteBossFrame *pBoss = static_cast<SwFootnoteBossFrame*>(GetUpper());
290  if( IsInSct() )
291  {
292  SwSectionFrame* pSect = FindSctFrame();
293  OSL_ENSURE( pSect, "GrowFrame: Missing SectFrame" );
294  // In a section, which has to maximize, a footnotecontainer is allowed
295  // to grow, when the section can't grow anymore.
296  if( !bTst && !pSect->IsColLocked() &&
297  pSect->ToMaximize( false ) && pSect->Growable() )
298  {
299  pSect->InvalidateSize();
300  return 0;
301  }
302  }
303  const SwViewShell *pSh = getRootFrame() ? getRootFrame()->GetCurrShell() : nullptr;
304  const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
305  SwPageFrame *pPage = pBoss->FindPageFrame();
306  if ( bBrowseMode || !pPage->IsFootnotePage() )
307  {
308  if ( pBoss->GetMaxFootnoteHeight() != LONG_MAX )
309  {
310  nDist = std::min( nDist, pBoss->GetMaxFootnoteHeight()
311  - aRectFnSet.GetHeight(getFrameArea()) );
312  if ( nDist <= 0 )
313  return 0;
314  }
315  // FootnoteBoss also influences the max value
316  if( !IsInSct() )
317  {
318  const SwTwips nMax = pBoss->GetVarSpace();
319  if ( nDist > nMax )
320  nDist = nMax;
321  if ( nDist <= 0 )
322  return 0;
323  }
324  }
325  else if( nDist > aRectFnSet.GetHeight(GetPrev()->getFrameArea()) )
326  // do not use more space than the body has
327  nDist = aRectFnSet.GetHeight(GetPrev()->getFrameArea());
328 
329  long nAvail = 0;
330  if ( bBrowseMode )
331  {
332  nAvail = GetUpper()->getFramePrintArea().Height();
333  const SwFrame *pAvail = GetUpper()->Lower();
334  do
335  { nAvail -= pAvail->getFrameArea().Height();
336  pAvail = pAvail->GetNext();
337  } while ( pAvail );
338  if ( nAvail > nDist )
339  nAvail = nDist;
340  }
341 
342  if ( !bTst )
343  {
345  aRectFnSet.SetHeight( aFrm, aRectFnSet.GetHeight(aFrm) + nDist );
346 
347  if( IsVertical() && !IsVertLR() )
348  {
349  aFrm.Pos().AdjustX( -nDist );
350  }
351  }
352  long nGrow = nDist - nAvail,
353  nReal = 0;
354  if ( nGrow > 0 )
355  {
356  SwNeighbourAdjust nAdjust = pBoss->NeighbourhoodAdjustment();
357  if( SwNeighbourAdjust::OnlyAdjust == nAdjust )
358  nReal = AdjustNeighbourhood( nGrow, bTst );
359  else
360  {
361  if( SwNeighbourAdjust::GrowAdjust == nAdjust )
362  {
363  SwFrame* pFootnote = Lower();
364  if( pFootnote )
365  {
366  while( pFootnote->GetNext() )
367  pFootnote = pFootnote->GetNext();
368  if( static_cast<SwFootnoteFrame*>(pFootnote)->GetAttr()->GetFootnote().IsEndNote() )
369  {
370  nReal = AdjustNeighbourhood( nGrow, bTst );
371  nAdjust = SwNeighbourAdjust::GrowShrink; // no more AdjustNeighbourhood
372  }
373  }
374  }
375  nReal += pBoss->Grow( nGrow - nReal, bTst );
376  if( ( SwNeighbourAdjust::GrowAdjust == nAdjust || SwNeighbourAdjust::AdjustGrow == nAdjust )
377  && nReal < nGrow )
378  nReal += AdjustNeighbourhood( nGrow - nReal, bTst );
379  }
380  }
381 
382  nReal += nAvail;
383 
384  if ( !bTst )
385  {
386  if ( nReal != nDist )
387  {
388  nDist -= nReal;
389 
390  // We can only respect the boundless wish so much
392  aFrm.SSize().AdjustHeight( -nDist );
393 
394  if( IsVertical() && !IsVertLR() )
395  {
396  aFrm.Pos().AdjustX(nDist );
397  }
398  }
399 
400  // growing happens upwards, so successors to not need to be invalidated
401  if( nReal )
402  {
403  InvalidateSize_();
404  InvalidatePos_();
405  InvalidatePage( pPage );
406  }
407  }
408  return nReal;
409 }
410 
411 SwTwips SwFootnoteContFrame::ShrinkFrame( SwTwips nDiff, bool bTst, bool bInfo )
412 {
413  SwPageFrame *pPage = FindPageFrame();
414  bool bShrink = false;
415  if ( pPage )
416  {
417  if( !pPage->IsFootnotePage() )
418  bShrink = true;
419  else
420  {
421  const SwViewShell *pSh = getRootFrame()->GetCurrShell();
422  if( pSh && pSh->GetViewOptions()->getBrowseMode() )
423  bShrink = true;
424  }
425  }
426  if( bShrink )
427  {
428  SwTwips nRet = SwLayoutFrame::ShrinkFrame( nDiff, bTst, bInfo );
429  if( IsInSct() && !bTst )
431  if ( !bTst && nRet )
432  {
433  InvalidatePos_();
434  InvalidatePage( pPage );
435  }
436  return nRet;
437  }
438  return 0;
439 }
440 
442  SwLayoutFrame( pFormat, pSib ),
443  mpFollow( nullptr ),
444  mpMaster( nullptr ),
445  mpReference( pCnt ),
446  mpAttribute( pAt ),
447  mbBackMoveLocked( false ),
448  // #i49383#
449  mbUnlockPosOfLowerObjs( true )
450 {
452 }
453 
455 {
456  if ( GetNext() )
457  {
458  SwFrame *pCnt = static_cast<SwLayoutFrame*>(GetNext())->ContainsAny();
459  if( pCnt )
460  {
461  pCnt->InvalidatePage( pPage );
462  pCnt->InvalidatePrt_();
463  do
464  { pCnt->InvalidatePos_();
465  if( pCnt->IsSctFrame() )
466  {
467  SwFrame* pTmp = static_cast<SwSectionFrame*>(pCnt)->ContainsAny();
468  if( pTmp )
469  pTmp->InvalidatePos_();
470  }
471  pCnt->GetUpper()->InvalidateSize_();
472  pCnt = pCnt->FindNext();
473  } while ( pCnt && GetUpper()->IsAnLower( pCnt ) );
474  }
475  }
476 }
477 
479 {
481  return true;
482  // needs to be in sync with the ::Cut logic
483  const SwLayoutFrame *pUp = GetUpper();
484  if (pUp)
485  {
486  if (GetPrev())
487  return false;
488 
489  // The last footnote takes its container along if it
490  // is deleted. Cut would put pUp->Lower() to the value
491  // of GetNext(), so if there is no GetNext then
492  // Cut would delete pUp. If that condition is true
493  // here then check if the container is delete-forbidden
494  return !GetNext() && pUp->IsDeleteForbidden();
495  }
496  return false;
497 }
498 
500 {
501  if ( GetNext() )
502  GetNext()->InvalidatePos();
503  else if ( GetPrev() )
504  GetPrev()->SetRetouche();
505 
506  // first move then shrink Upper
507  SwLayoutFrame *pUp = GetUpper();
508 
509  // correct chaining
510  SwFootnoteFrame *pFootnote = this;
511  if ( pFootnote->GetFollow() )
512  pFootnote->GetFollow()->SetMaster( pFootnote->GetMaster() );
513  if ( pFootnote->GetMaster() )
514  pFootnote->GetMaster()->SetFollow( pFootnote->GetFollow() );
515  pFootnote->SetFollow( nullptr );
516  pFootnote->SetMaster( nullptr );
517 
518  // cut all connections
520 
521  if ( pUp )
522  {
523  // The last footnote takes its container along
524  if (!pUp->Lower())
525  {
526  SwPageFrame *pPage = pUp->FindPageFrame();
527  if ( pPage )
528  {
529  SwLayoutFrame *pBody = pPage->FindBodyCont();
530  if( pBody && !pBody->ContainsContent() )
531  pPage->getRootFrame()->SetSuperfluous();
532  }
533  SwSectionFrame* pSect = pUp->FindSctFrame();
534  pUp->Cut();
536  // If the last footnote container was removed from a column
537  // section without a Follow, then this section can be shrunk.
538  if( pSect && !pSect->ToMaximize( false ) && !pSect->IsColLocked() )
539  pSect->InvalidateSize_();
540  }
541  else
542  { if ( getFrameArea().Height() )
543  pUp->Shrink( getFrameArea().Height() );
544  pUp->SetCompletePaint();
545  pUp->InvalidatePage();
546  }
547  }
548 }
549 
550 void SwFootnoteFrame::Paste( SwFrame* pParent, SwFrame* pSibling )
551 {
552  OSL_ENSURE( pParent, "no parent in Paste." );
553  OSL_ENSURE( pParent->IsLayoutFrame(), "Parent is ContentFrame." );
554  OSL_ENSURE( pParent != this, "I am my own parent." );
555  OSL_ENSURE( pSibling != this, "I am my own sibling." );
556  OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
557  "I am still somewhere registered." );
558 
559  // insert into tree structure
560  InsertBefore( static_cast<SwLayoutFrame*>(pParent), pSibling );
561 
562  SwRectFnSet aRectFnSet(this);
563  if( aRectFnSet.GetWidth(getFrameArea())!=aRectFnSet.GetWidth(pParent->getFramePrintArea()) )
564  InvalidateSize_();
565  InvalidatePos_();
566  SwPageFrame *pPage = FindPageFrame();
567  InvalidatePage( pPage );
568  if ( GetNext() )
569  GetNext()->InvalidatePos_();
570  if( aRectFnSet.GetHeight(getFrameArea()) )
571  pParent->Grow( aRectFnSet.GetHeight(getFrameArea()) );
572 
573  // If the predecessor is the master and/or the successor is the Follow,
574  // then take their content and destroy them.
575  if ( GetPrev() && GetPrev() == GetMaster() )
576  {
577  OSL_ENSURE( SwFlowFrame::CastFlowFrame( GetPrev()->GetLower() ),
578  "Footnote without content?" );
580  MoveSubTree( this, GetLower() );
581  SwFrame *pDel = GetPrev();
582  pDel->Cut();
583  SwFrame::DestroyFrame(pDel);
584  }
585  if ( GetNext() && GetNext() == GetFollow() )
586  {
587  OSL_ENSURE( SwFlowFrame::CastFlowFrame( GetNext()->GetLower() ),
588  "Footnote without content?" );
590  SwFrame *pDel = GetNext();
591  pDel->Cut();
592  SwFrame::DestroyFrame(pDel);
593  }
594 #if OSL_DEBUG_LEVEL > 0
595  SwDoc *pDoc = GetFormat()->GetDoc();
596  if ( GetPrev() )
597  {
598  OSL_ENSURE( lcl_FindFootnotePos( pDoc, static_cast<SwFootnoteFrame*>(GetPrev())->GetAttr() ) <=
599  lcl_FindFootnotePos( pDoc, GetAttr() ), "Prev is not FootnotePrev" );
600  }
601  if ( GetNext() )
602  {
603  OSL_ENSURE( lcl_FindFootnotePos( pDoc, GetAttr() ) <=
604  lcl_FindFootnotePos( pDoc, static_cast<SwFootnoteFrame*>(GetNext())->GetAttr() ),
605  "Next is not FootnoteNext" );
606  }
607 #endif
608  InvalidateNxtFootnoteCnts( pPage );
609 }
610 
614 {
616  SwPageFrame* pOldPage = pOldBoss->FindPageFrame();
617  SwPageFrame* pPage;
618  SwFootnoteBossFrame *pBoss = pOldBoss->IsColumnFrame() ?
619  static_cast<SwFootnoteBossFrame*>(pOldBoss->GetNext()) : nullptr; // next column, if existing
620  if( pBoss )
621  pPage = nullptr;
622  else
623  {
624  if( pOldBoss->GetUpper()->IsSctFrame() )
625  { // this can only be in a column area
626  SwLayoutFrame* pNxt = pOldBoss->GetNextSctLeaf( eMakePage );
627  if( pNxt )
628  {
629  OSL_ENSURE( pNxt->IsColBodyFrame(), "GetNextFootnoteLeaf: Funny Leaf" );
630  pBoss = static_cast<SwFootnoteBossFrame*>(pNxt->GetUpper());
631  pPage = pBoss->FindPageFrame();
632  }
633  else
634  return nullptr;
635  }
636  else
637  {
638  // next page
639  pPage = static_cast<SwPageFrame*>(pOldPage->GetNext());
640  // skip empty pages
641  if( pPage && pPage->IsEmptyPage() )
642  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
643  pBoss = pPage;
644  }
645  }
646  // What do we have until here?
647  // pBoss != NULL, pPage==NULL => pBoss is the next column on the same page
648  // pBoss != NULL, pPage!=NULL => pBoss and pPage are the following page (empty pages skipped)
649  // pBoss == NULL => pPage == NULL, so there are no following pages
650 
651  // If the footnote has already a Follow we do not need to search.
652  // However, if there are unwanted empty columns/pages between Footnote and Follow,
653  // create another Follow on the next best column/page and the rest will sort itself out.
654  SwFootnoteFrame *pFootnote = FindFootnoteFrame();
655  if ( pFootnote && pFootnote->GetFollow() )
656  {
657  SwFootnoteBossFrame* pTmpBoss = pFootnote->GetFollow()->FindFootnoteBossFrame();
658  // Following cases will be handled:
659  // 1. both "FootnoteBoss"es are neighboring columns/pages
660  // 2. the new one is the first column of a neighboring page
661  // 3. the new one is the first column in a section of the next page
662  while( pTmpBoss != pBoss && pTmpBoss && !pTmpBoss->GetPrev() )
663  pTmpBoss = pTmpBoss->GetUpper()->FindFootnoteBossFrame();
664  if( pTmpBoss == pBoss )
665  return pFootnote->GetFollow();
666  }
667 
668  // If no pBoss could be found or it is a "wrong" page, we need a new page.
669  if ( !pBoss || ( pPage && pPage->IsEndNotePage() && !pOldPage->IsEndNotePage() ) )
670  {
671  if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT )
672  {
673  pBoss = InsertPage( pOldPage, pOldPage->IsFootnotePage() );
674  static_cast<SwPageFrame*>(pBoss)->SetEndNotePage( pOldPage->IsEndNotePage() );
675  }
676  else
677  return nullptr;
678  }
679  if( pBoss->IsPageFrame() )
680  {
681  // If this page has columns, then go to the first one
682  SwLayoutFrame* pLay = pBoss->FindBodyCont();
683  if( pLay && pLay->Lower() && pLay->Lower()->IsColumnFrame() )
684  pBoss = static_cast<SwFootnoteBossFrame*>(pLay->Lower());
685  }
686  // found column/page - add myself
687  SwFootnoteContFrame *pCont = pBoss->FindFootnoteCont();
688  if ( !pCont && pBoss->GetMaxFootnoteHeight() &&
689  ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
690  pCont = pBoss->MakeFootnoteCont();
691  return pCont;
692 }
693 
696 {
697  // The predecessor of a footnote is (if possible)
698  // the master of the chain of the footnote.
699  SwFootnoteFrame *pFootnote = FindFootnoteFrame();
700  SwLayoutFrame *pRet = pFootnote->GetMaster();
701 
703  SwPageFrame *pOldPage = pOldBoss->FindPageFrame();
704 
705  if ( !pOldBoss->GetPrev() && !pOldPage->GetPrev() )
706  return pRet; // there is neither a predecessor column nor page
707 
708  if ( !pRet )
709  {
710  bool bEndn = pFootnote->GetAttr()->GetFootnote().IsEndNote();
711  SwFrame* pTmpRef = nullptr;
712  if( bEndn && pFootnote->IsInSct() )
713  {
714  SwSectionFrame* pSect = pFootnote->FindSctFrame();
715  if( pSect->IsEndnAtEnd() )
716  pTmpRef = pSect->FindLastContent( SwFindMode::LastCnt );
717  }
718  if( !pTmpRef )
719  pTmpRef = pFootnote->GetRef();
720  SwFootnoteBossFrame* pStop = pTmpRef->FindFootnoteBossFrame( !bEndn );
721 
722  const sal_uInt16 nNum = pStop->GetPhyPageNum();
723 
724  // Do not leave the corresponding page if the footnote should
725  // be shown at the document ending or the footnote is an endnote.
726  const bool bEndNote = pOldPage->IsEndNotePage();
727  const bool bFootnoteEndDoc = pOldPage->IsFootnotePage();
728  SwFootnoteBossFrame* pNxtBoss = pOldBoss;
729  SwSectionFrame *pSect = pNxtBoss->GetUpper()->IsSctFrame() ?
730  static_cast<SwSectionFrame*>(pNxtBoss->GetUpper()) : nullptr;
731 
732  do
733  {
734  if( pNxtBoss->IsColumnFrame() && pNxtBoss->GetPrev() )
735  pNxtBoss = static_cast<SwFootnoteBossFrame*>(pNxtBoss->GetPrev()); // one column backwards
736  else // one page backwards
737  {
738  SwLayoutFrame* pBody = nullptr;
739  if( pSect )
740  {
741  if( pSect->IsFootnoteLock() )
742  {
743  if( pNxtBoss == pOldBoss )
744  return nullptr;
745  pStop = pNxtBoss;
746  }
747  else
748  {
749  pSect = pSect->FindMaster();
750  if( !pSect || !pSect->Lower() )
751  return nullptr;
752  OSL_ENSURE( pSect->Lower()->IsColumnFrame(),
753  "GetPrevFootnoteLeaf: Where's the column?" );
754  pNxtBoss = static_cast<SwFootnoteBossFrame*>(pSect->Lower());
755  pBody = pSect;
756  }
757  }
758  else
759  {
760  SwPageFrame* pPage = static_cast<SwPageFrame*>(pNxtBoss->FindPageFrame()->GetPrev());
761  if( !pPage || pPage->GetPhyPageNum() < nNum ||
762  bEndNote != pPage->IsEndNotePage() || bFootnoteEndDoc != pPage->IsFootnotePage() )
763  return nullptr; // no further pages found
764  pNxtBoss = pPage;
765  pBody = pPage->FindBodyCont();
766  }
767  // We have the previous page, we might need to find the last column of it
768  if( pBody )
769  {
770  if ( pBody->Lower() && pBody->Lower()->IsColumnFrame() )
771  {
772  pNxtBoss = static_cast<SwFootnoteBossFrame*>(pBody->GetLastLower());
773  }
774  }
775  }
776  SwFootnoteContFrame *pCont = pNxtBoss->FindFootnoteCont();
777  if ( pCont )
778  {
779  pRet = pCont;
780  break;
781  }
782  if ( pStop == pNxtBoss )
783  {
784  // Reached the column/page of the reference.
785  // Try to add a container and paste our content.
786  if ( eMakeFootnote == MAKEPAGE_FTN && pNxtBoss->GetMaxFootnoteHeight() )
787  pRet = pNxtBoss->MakeFootnoteCont();
788  break;
789  }
790  } while( !pRet );
791  }
792  if ( pRet )
793  {
794  const SwFootnoteBossFrame* pNewBoss = pRet->FindFootnoteBossFrame();
795  bool bJump = false;
796  if( pOldBoss->IsColumnFrame() && pOldBoss->GetPrev() ) // a previous column exists
797  bJump = pOldBoss->GetPrev() != static_cast<SwFrame const *>(pNewBoss); // did we chose it?
798  else if( pNewBoss->IsColumnFrame() && pNewBoss->GetNext() )
799  bJump = true; // there is another column after the boss (not the old boss)
800  else
801  {
802  // Will be reached only if old and new boss are both either pages or the last (new)
803  // or first (old) column of a page. In this case, check if pages were skipped.
804  const sal_uInt16 nDiff = pOldPage->GetPhyPageNum() - pRet->FindPageFrame()->GetPhyPageNum();
805  if ( nDiff > 2 ||
806  (nDiff > 1 && !static_cast<SwPageFrame*>(pOldPage->GetPrev())->IsEmptyPage()) )
807  bJump = true;
808  }
809  if( bJump )
811  }
812  return pRet;
813 }
814 
816 {
817  if ( !IsInDocBody() )
818  return false;
819 
820  if ( IsInTab() )
821  {
822  // no footnotes in repeated headlines
823  const SwTabFrame *pTab = const_cast<SwFrame*>(this)->ImplFindTabFrame();
824  assert(pTab);
825  if ( pTab->IsFollow() )
826  return !pTab->IsInHeadline( *this );
827  }
828  return true;
829 }
830 
832 {
833  // page numbering only if set at the document
834  if ( GetFormat()->GetDoc()->GetFootnoteInfo().eNum == FTNNUM_PAGE )
835  {
836  SwPageFrame *pPage = static_cast<SwPageFrame*>(Lower());
837  while ( pPage && !pPage->IsFootnotePage() )
838  {
839  pPage->UpdateFootnoteNum();
840  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
841  }
842  }
843 }
844 
846 void sw_RemoveFootnotes( SwFootnoteBossFrame* pBoss, bool bPageOnly, bool bEndNotes )
847 {
848  do
849  {
850  SwFootnoteContFrame *pCont = pBoss->FindFootnoteCont();
851  if ( pCont )
852  {
853  SwFootnoteFrame *pFootnote = static_cast<SwFootnoteFrame*>(pCont->Lower());
854  assert(pFootnote);
855  if ( bPageOnly )
856  while ( pFootnote->GetMaster() )
857  pFootnote = pFootnote->GetMaster();
858  do
859  {
860  SwFootnoteFrame *pNxt = static_cast<SwFootnoteFrame*>(pFootnote->GetNext());
861  if ( !pFootnote->GetAttr()->GetFootnote().IsEndNote() ||
862  bEndNotes )
863  {
864  pFootnote->GetRef()->Prepare( PREP_FTN, static_cast<void*>(pFootnote->GetAttr()) );
865  if ( bPageOnly && !pNxt )
866  pNxt = pFootnote->GetFollow();
867  pFootnote->Cut();
868  SwFrame::DestroyFrame(pFootnote);
869  }
870  pFootnote = pNxt;
871 
872  } while ( pFootnote );
873  }
874  if( !pBoss->IsInSct() )
875  {
876  // A sectionframe with the Footnote/EndnAtEnd-flags may contain
877  // foot/endnotes. If the last lower frame of the bodyframe is
878  // a multicolumned sectionframe, it may contain footnotes, too.
879  SwLayoutFrame* pBody = pBoss->FindBodyCont();
880  if( pBody && pBody->Lower() )
881  {
882  SwFrame* pLow = pBody->Lower();
883  while (pLow)
884  {
885  if( pLow->IsSctFrame() && ( !pLow->GetNext() ||
886  static_cast<SwSectionFrame*>(pLow)->IsAnyNoteAtEnd() ) &&
887  static_cast<SwSectionFrame*>(pLow)->Lower() &&
888  static_cast<SwSectionFrame*>(pLow)->Lower()->IsColumnFrame() )
889  sw_RemoveFootnotes( static_cast<SwColumnFrame*>(static_cast<SwSectionFrame*>(pLow)->Lower()),
890  bPageOnly, bEndNotes );
891  pLow = pLow->GetNext();
892  }
893  }
894  }
895  // is there another column?
896  pBoss = pBoss->IsColumnFrame() ? static_cast<SwColumnFrame*>(pBoss->GetNext()) : nullptr;
897  } while( pBoss );
898 }
899 
900 void SwRootFrame::RemoveFootnotes( SwPageFrame *pPage, bool bPageOnly, bool bEndNotes )
901 {
902  if ( !pPage )
903  pPage = static_cast<SwPageFrame*>(Lower());
904 
905  do
906  { // On columned pages we have to clean up in all columns
907  SwFootnoteBossFrame* pBoss;
908  SwLayoutFrame* pBody = pPage->FindBodyCont();
909  if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrame() )
910  pBoss = static_cast<SwFootnoteBossFrame*>(pBody->Lower()); // the first column
911  else
912  pBoss = pPage; // no columns
913  sw_RemoveFootnotes( pBoss, bPageOnly, bEndNotes );
914  if ( !bPageOnly )
915  {
916  if ( pPage->IsFootnotePage() &&
917  (!pPage->IsEndNotePage() || bEndNotes) )
918  {
919  SwFrame *pDel = pPage;
920  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
921  pDel->Cut();
922  SwFrame::DestroyFrame(pDel);
923  }
924  else
925  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
926  }
927  else
928  break;
929 
930  } while ( pPage );
931 }
932 
935 {
936  SwPageFrame *pPage = static_cast<SwPageFrame*>(Lower());
937  while ( pPage && !pPage->IsFootnotePage() )
938  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
939  while ( pPage && pPage->IsEndNotePage() != bEndNote )
940  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
941 
942  if ( pPage )
943  SwFrame::CheckPageDescs( pPage, false );
944 }
945 
955 {
956  SAL_WARN_IF(FindFootnoteCont(), "sw.core", "footnote container exists already");
957 
958  SwFootnoteContFrame *pNew = new SwFootnoteContFrame( GetFormat()->GetDoc()->GetDfltFrameFormat(), this );
959  SwLayoutFrame *pLay = FindBodyCont();
960  pNew->Paste( this, pLay->GetNext() );
961  return pNew;
962 }
963 
965 {
966  SwFrame *pFrame = Lower();
967  while( pFrame && !pFrame->IsFootnoteContFrame() )
968  pFrame = pFrame->GetNext();
969 
970 #if OSL_DEBUG_LEVEL > 0
971  if ( pFrame )
972  {
973  SwFrame *pFootnote = pFrame->GetLower();
974  assert(pFootnote);
975  while ( pFootnote )
976  {
977  assert(pFootnote->IsFootnoteFrame() && "Neighbor of footnote must be a footnote");
978  pFootnote = pFootnote->GetNext();
979  }
980  }
981 #endif
982 
983  return static_cast<SwFootnoteContFrame*>(pFrame);
984 }
985 
988 {
989  SwFootnoteContFrame *pCont = nullptr;
990  if ( !GetFormat()->GetDoc()->GetFootnoteIdxs().empty() )
991  {
992  pCont = FindFootnoteCont();
993  if ( !pCont )
994  {
995  SwPageFrame *pPage = FindPageFrame();
996  SwFootnoteBossFrame* pBoss = this;
997  bool bEndNote = pPage->IsEndNotePage();
998  do
999  {
1000  bool bChgPage = lcl_NextFootnoteBoss( pBoss, pPage, bDontLeave );
1001  // Found another boss? When changing pages, also the endnote flag must match.
1002  if( pBoss && ( !bChgPage || pPage->IsEndNotePage() == bEndNote ) )
1003  pCont = pBoss->FindFootnoteCont();
1004  } while ( !pCont && pPage );
1005  }
1006  }
1007  return pCont;
1008 }
1009 
1011 {
1012  // search for the nearest footnote container
1014  if ( !pCont )
1015  return nullptr;
1016 
1017  // Starting from the first footnote, search the first
1018  // footnote that is referenced by the current column/page
1019 
1020  SwFootnoteFrame *pRet = static_cast<SwFootnoteFrame*>(pCont->Lower());
1021  const sal_uInt16 nRefNum = FindPageFrame()->GetPhyPageNum();
1022  const sal_uInt16 nRefCol = lcl_ColumnNum( this );
1023  sal_uInt16 nPgNum, nColNum; // page number, column number
1024  SwFootnoteBossFrame* pBoss;
1025  SwPageFrame* pPage;
1026  if( pRet )
1027  {
1028  pBoss = pRet->GetRef()->FindFootnoteBossFrame();
1029  OSL_ENSURE( pBoss, "FindFirstFootnote: No boss found" );
1030  if( !pBoss )
1031  return nullptr; // ?There must be a bug, but no GPF
1032  pPage = pBoss->FindPageFrame();
1033  nPgNum = pPage->GetPhyPageNum();
1034  if ( nPgNum == nRefNum )
1035  {
1036  nColNum = lcl_ColumnNum( pBoss );
1037  if( nColNum == nRefCol )
1038  return pRet; // found
1039  else if( nColNum > nRefCol )
1040  return nullptr; // at least one column too far
1041  }
1042  else if ( nPgNum > nRefNum )
1043  return nullptr; // at least one column too far
1044  }
1045  else
1046  return nullptr;
1047  // Done if Ref is on a subsequent page or on the same page in a subsequent column
1048 
1049  do
1050  {
1051  while ( pRet->GetFollow() )
1052  pRet = pRet->GetFollow();
1053 
1054  SwFootnoteFrame *pNxt = static_cast<SwFootnoteFrame*>(pRet->GetNext());
1055  if ( !pNxt )
1056  {
1057  pBoss = pRet->FindFootnoteBossFrame();
1058  pPage = pBoss->FindPageFrame();
1059  lcl_NextFootnoteBoss( pBoss, pPage, false ); // next FootnoteBoss
1060  pCont = pBoss ? pBoss->FindNearestFootnoteCont() : nullptr;
1061  if ( pCont )
1062  pNxt = static_cast<SwFootnoteFrame*>(pCont->Lower());
1063  }
1064  if ( pNxt )
1065  {
1066  pRet = pNxt;
1067  pBoss = pRet->GetRef()->FindFootnoteBossFrame();
1068  pPage = pBoss->FindPageFrame();
1069  nPgNum = pPage->GetPhyPageNum();
1070  if ( nPgNum == nRefNum )
1071  {
1072  nColNum = lcl_ColumnNum( pBoss );
1073  if( nColNum == nRefCol )
1074  break; // found
1075  else if( nColNum > nRefCol )
1076  pRet = nullptr; // at least one column too far
1077  }
1078  else if ( nPgNum > nRefNum )
1079  pRet = nullptr; // at least a page too far
1080  }
1081  else
1082  pRet = nullptr; // there is none
1083  } while( pRet );
1084  return pRet;
1085 }
1086 
1089 {
1090  const SwFootnoteFrame *pRet = const_cast<SwFootnoteBossFrame*>(this)->FindFirstFootnote();
1091  if ( pRet )
1092  {
1093  const sal_uInt16 nColNum = lcl_ColumnNum( this );
1094  const sal_uInt16 nPageNum = GetPhyPageNum();
1095  while ( pRet && (pRet->GetRef() != pCnt) )
1096  {
1097  while ( pRet->GetFollow() )
1098  pRet = pRet->GetFollow();
1099 
1100  if ( pRet->GetNext() )
1101  pRet = static_cast<const SwFootnoteFrame*>(pRet->GetNext());
1102  else
1103  { SwFootnoteBossFrame *pBoss = const_cast<SwFootnoteBossFrame*>(pRet->FindFootnoteBossFrame());
1104  SwPageFrame *pPage = pBoss->FindPageFrame();
1105  lcl_NextFootnoteBoss( pBoss, pPage, false ); // next FootnoteBoss
1106  SwFootnoteContFrame *pCont = pBoss ? pBoss->FindNearestFootnoteCont() : nullptr;
1107  pRet = pCont ? static_cast<SwFootnoteFrame*>(pCont->Lower()) : nullptr;
1108  }
1109  if ( pRet )
1110  {
1111  const SwFootnoteBossFrame* pBoss = pRet->GetRef()->FindFootnoteBossFrame();
1112  if( pBoss->GetPhyPageNum() != nPageNum ||
1113  nColNum != lcl_ColumnNum( pBoss ) )
1114  pRet = nullptr;
1115  }
1116  }
1117  }
1118  return pRet;
1119 }
1120 
1122 {
1123  // Destroy the incarnations of footnotes to an attribute, if they don't
1124  // belong to pAssumed
1125  OSL_ENSURE( !pCheck->GetMaster(), "given master is not a Master." );
1126 
1127  SwNodeIndex aIdx( *pCheck->GetAttr()->GetStartNode(), 1 );
1128  SwContentNode *pNd = aIdx.GetNode().GetContentNode();
1129  if ( !pNd )
1130  pNd = pCheck->GetFormat()->GetDoc()->
1131  GetNodes().GoNextSection( &aIdx, true, false );
1133  SwFrame* pFrame = aIter.First();
1134  while( pFrame )
1135  {
1136  if( pFrame->getRootFrame() == pCheck->getRootFrame() )
1137  {
1138  SwFrame *pTmp = pFrame->GetUpper();
1139  while ( pTmp && !pTmp->IsFootnoteFrame() )
1140  pTmp = pTmp->GetUpper();
1141 
1142  SwFootnoteFrame *pFootnote = static_cast<SwFootnoteFrame*>(pTmp);
1143  while ( pFootnote && pFootnote->GetMaster() )
1144  pFootnote = pFootnote->GetMaster();
1145  if ( pFootnote != pCheck )
1146  {
1147  while ( pFootnote )
1148  {
1149  SwFootnoteFrame *pNxt = pFootnote->GetFollow();
1150  pFootnote->Cut();
1151  SwFrame::DestroyFrame(pFootnote);
1152  pFootnote = pNxt;
1153  }
1154  }
1155  }
1156 
1157  pFrame = aIter.Next();
1158  }
1159 }
1160 
1162 {
1163  // Place the footnote in front of the footnote whose attribute
1164  // is in front of the new one (get position via the Doc).
1165  // If there is no footnote in this footnote-boss yet, create a new container.
1166  // If there is a container but no footnote for this footnote-boss yet, place
1167  // the footnote behind the last footnote of the closest previous column/page.
1168 
1169  ResetFootnote( pNew );
1170  SwFootnoteFrame *pSibling = FindFirstFootnote();
1171  bool bDontLeave = false;
1172 
1173  // Ok, a sibling has been found, but is the sibling in an acceptable
1174  // environment?
1175  if( IsInSct() )
1176  {
1177  SwSectionFrame* pMySect = ImplFindSctFrame();
1178  bool bEndnt = pNew->GetAttr()->GetFootnote().IsEndNote();
1179  if( bEndnt )
1180  {
1181  const SwSectionFormat* pEndFormat = pMySect->GetEndSectFormat();
1182  bDontLeave = nullptr != pEndFormat;
1183  if( pSibling )
1184  {
1185  if( pEndFormat )
1186  {
1187  if( !pSibling->IsInSct() ||
1188  !pSibling->ImplFindSctFrame()->IsDescendantFrom( pEndFormat ) )
1189  pSibling = nullptr;
1190  }
1191  else if( pSibling->IsInSct() )
1192  pSibling = nullptr;
1193  }
1194  }
1195  else
1196  {
1197  bDontLeave = pMySect->IsFootnoteAtEnd();
1198  if( pSibling )
1199  {
1200  if( pMySect->IsFootnoteAtEnd() )
1201  {
1202  if( !pSibling->IsInSct() ||
1203  !pMySect->IsAnFollow( pSibling->ImplFindSctFrame() ) )
1204  pSibling = nullptr;
1205  }
1206  else if( pSibling->IsInSct() )
1207  pSibling = nullptr;
1208  }
1209  }
1210  }
1211 
1212  if( pSibling && pSibling->FindPageFrame()->IsEndNotePage() !=
1214  pSibling = nullptr;
1215 
1216  // use the Doc to find out the position
1217  SwDoc *pDoc = GetFormat()->GetDoc();
1218  const sal_uLong nStPos = ::lcl_FindFootnotePos( pDoc, pNew->GetAttr() );
1219 
1220  sal_uLong nCmpPos = 0;
1221  sal_uLong nLastPos = 0;
1222  SwFootnoteContFrame *pParent = nullptr;
1223  if( pSibling )
1224  {
1225  nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1226  if( nCmpPos > nStPos )
1227  pSibling = nullptr;
1228  }
1229 
1230  if ( !pSibling )
1231  { pParent = FindFootnoteCont();
1232  if ( !pParent )
1233  {
1234  // There is no footnote container yet. Before creating one, keep in mind that
1235  // there might exist another following footnote that must be placed before the
1236  // new inserted one e.g. because it was divided over multiple pages etc.
1237  pParent = FindNearestFootnoteCont( bDontLeave );
1238  if ( pParent )
1239  {
1240  SwFootnoteFrame *pFootnote = static_cast<SwFootnoteFrame*>(pParent->Lower());
1241  if ( pFootnote )
1242  {
1243 
1244  nCmpPos = ::lcl_FindFootnotePos( pDoc, pFootnote->GetAttr() );
1245  if ( nCmpPos > nStPos )
1246  pParent = nullptr;
1247  }
1248  else
1249  pParent = nullptr;
1250  }
1251  }
1252  if ( !pParent )
1253  // here, we are sure that we can create a footnote container
1254  pParent = MakeFootnoteCont();
1255  else
1256  {
1257  // Based on the first footnote below the Parent, search for the first footnote whose
1258  // index is after the index of the newly inserted, to place the new one correctly
1259  pSibling = static_cast<SwFootnoteFrame*>(pParent->Lower());
1260  if ( !pSibling )
1261  {
1262  OSL_ENSURE( false, "Could not find space for footnote.");
1263  return;
1264  }
1265  nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1266 
1267  SwFootnoteBossFrame *pNxtB; // remember the last one to not
1268  SwFootnoteFrame *pLastSib = nullptr; // go too far.
1269 
1270  while ( pSibling && nCmpPos <= nStPos )
1271  {
1272  pLastSib = pSibling; // potential candidate
1273  nLastPos = nCmpPos;
1274 
1275  while ( pSibling->GetFollow() )
1276  pSibling = pSibling->GetFollow();
1277 
1278  if ( pSibling->GetNext() )
1279  {
1280  pSibling = static_cast<SwFootnoteFrame*>(pSibling->GetNext());
1281  OSL_ENSURE( !pSibling->GetMaster() || ( ENDNOTE > nStPos &&
1282  pSibling->GetAttr()->GetFootnote().IsEndNote() ),
1283  "InsertFootnote: Master expected I" );
1284  }
1285  else
1286  {
1287  pNxtB = pSibling->FindFootnoteBossFrame();
1288  SwPageFrame *pSibPage = pNxtB->FindPageFrame();
1289  bool bEndNote = pSibPage->IsEndNotePage();
1290  bool bChgPage = lcl_NextFootnoteBoss( pNxtB, pSibPage, bDontLeave );
1291  // When changing pages, also the endnote flag must match.
1292  SwFootnoteContFrame *pCont = pNxtB && ( !bChgPage ||
1293  pSibPage->IsEndNotePage() == bEndNote )
1294  ? pNxtB->FindNearestFootnoteCont( bDontLeave ) : nullptr;
1295  if( pCont )
1296  pSibling = static_cast<SwFootnoteFrame*>(pCont->Lower());
1297  else // no further FootnoteContainer, insert after pSibling
1298  break;
1299  }
1300  if ( pSibling )
1301  {
1302  nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1303  OSL_ENSURE( nCmpPos > nLastPos, "InsertFootnote: Order of FootnoteFrame's buggy" );
1304  }
1305  }
1306  // pLastSib is the last footnote before the new one and
1307  // pSibling is empty or the first one after the new one
1308  if ( pSibling && pLastSib && (pSibling != pLastSib) )
1309  {
1310  // too far?
1311  if ( nCmpPos > nStPos )
1312  pSibling = pLastSib;
1313  }
1314  else if ( !pSibling )
1315  {
1316  // Last chance: Take the last footnote of the parent.
1317  // Special case that happens e.g. when moving paragraphs with multiple footnotes.
1318  // To keep the order, use the parent of the last inspected footnote.
1319  pSibling = pLastSib;
1320  while( pSibling->GetFollow() )
1321  pSibling = pSibling->GetFollow();
1322  OSL_ENSURE( !pSibling->GetNext(), "InsertFootnote: Who's that guy?" );
1323  }
1324  }
1325  }
1326  else
1327  {
1328  // First footnote of the column/page found. Now search from there for the first one on the
1329  // same column/page whose index is after the given one. The last one found is the predecessor.
1331  !pNew->GetAttr()->GetFootnote().IsEndNote() );
1332  sal_uInt16 nRefNum = pBoss->GetPhyPageNum(); // page number of the new footnote
1333  sal_uInt16 nRefCol = lcl_ColumnNum( pBoss ); // column number of the new footnote
1334  bool bEnd = false;
1335  SwFootnoteFrame *pLastSib = nullptr;
1336  while ( pSibling && !bEnd && (nCmpPos <= nStPos) )
1337  {
1338  pLastSib = pSibling;
1339  nLastPos = nCmpPos;
1340 
1341  while ( pSibling->GetFollow() )
1342  pSibling = pSibling->GetFollow();
1343 
1344  SwFootnoteFrame *pFoll = static_cast<SwFootnoteFrame*>(pSibling->GetNext());
1345  if ( pFoll )
1346  {
1347  pBoss = pSibling->GetRef()->FindFootnoteBossFrame( !pSibling->
1348  GetAttr()->GetFootnote().IsEndNote() );
1349  sal_uInt16 nTmpRef;
1350  if( nStPos >= ENDNOTE ||
1351  (nTmpRef = pBoss->GetPhyPageNum()) < nRefNum ||
1352  ( nTmpRef == nRefNum && lcl_ColumnNum( pBoss ) <= nRefCol ))
1353  pSibling = pFoll;
1354  else
1355  bEnd = true;
1356  }
1357  else
1358  {
1359  SwFootnoteBossFrame* pNxtB = pSibling->FindFootnoteBossFrame();
1360  SwPageFrame *pSibPage = pNxtB->FindPageFrame();
1361  bool bEndNote = pSibPage->IsEndNotePage();
1362  bool bChgPage = lcl_NextFootnoteBoss( pNxtB, pSibPage, bDontLeave );
1363  // When changing pages, also the endnote flag must match.
1364  SwFootnoteContFrame *pCont = pNxtB && ( !bChgPage ||
1365  pSibPage->IsEndNotePage() == bEndNote )
1366  ? pNxtB->FindNearestFootnoteCont( bDontLeave ) : nullptr;
1367  if ( pCont )
1368  pSibling = static_cast<SwFootnoteFrame*>(pCont->Lower());
1369  else
1370  bEnd = true;
1371  }
1372  if ( !bEnd && pSibling )
1373  nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1374  if (pSibling && (pSibling != pLastSib))
1375  {
1376  // too far?
1377  if ( (nLastPos < nCmpPos) && (nCmpPos > nStPos) )
1378  {
1379  pSibling = pLastSib;
1380  bEnd = true;
1381  }
1382  }
1383  }
1384  }
1385  if ( pSibling )
1386  {
1387  nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1388  if ( nCmpPos < nStPos )
1389  {
1390  while ( pSibling->GetFollow() )
1391  pSibling = pSibling->GetFollow();
1392  pParent = static_cast<SwFootnoteContFrame*>(pSibling->GetUpper());
1393  pSibling = static_cast<SwFootnoteFrame*>(pSibling->GetNext());
1394  }
1395  else
1396  {
1397  if( pSibling->GetMaster() )
1398  {
1399  if( ENDNOTE > nCmpPos || nStPos >= ENDNOTE )
1400  {
1401  OSL_FAIL( "InsertFootnote: Master expected II" );
1402  do
1403  pSibling = pSibling->GetMaster();
1404  while ( pSibling->GetMaster() );
1405  }
1406  }
1407  pParent = static_cast<SwFootnoteContFrame*>(pSibling->GetUpper());
1408  }
1409  }
1410  OSL_ENSURE( pParent, "paste in space?" );
1411  pNew->Paste( pParent, pSibling );
1412 }
1413 
1415 {
1416  // If the footnote already exists, do nothing.
1417  if ( FindFootnote( pRef, pAttr ) )
1418  return;
1419 
1420  // If footnotes are inserted at the end of the document,
1421  // we only need to search from the relevant page on.
1422  // If there is none yet, we need to create one.
1423  // If it is an Endnote, we need to search for or create an
1424  // Endnote page.
1425  SwDoc *pDoc = GetFormat()->GetDoc();
1426  SwFootnoteBossFrame *pBoss = this;
1427  SwPageFrame *pPage = FindPageFrame();
1428  SwPageFrame *pMyPage = pPage;
1429  bool bChgPage = false;
1430  bool bEnd = false;
1431  if ( pAttr->GetFootnote().IsEndNote() )
1432  {
1433  bEnd = true;
1434  if( GetUpper()->IsSctFrame() &&
1435  static_cast<SwSectionFrame*>(GetUpper())->IsEndnAtEnd() )
1436  {
1437  SwFrame* pLast =
1438  static_cast<SwSectionFrame*>(GetUpper())->FindLastContent( SwFindMode::EndNote );
1439  if( pLast )
1440  {
1441  pBoss = pLast->FindFootnoteBossFrame();
1442  pPage = pBoss->FindPageFrame();
1443  }
1444  }
1445  else
1446  {
1447  while ( pPage->GetNext() && !pPage->IsEndNotePage() )
1448  {
1449  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
1450  bChgPage = true;
1451  }
1452  if ( !pPage->IsEndNotePage() )
1453  {
1454  SwPageDesc *pDesc = pDoc->GetEndNoteInfo().GetPageDesc( *pDoc );
1455  pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(),
1456  !pPage->OnRightPage(), false, false, true, nullptr );
1457  pPage->SetEndNotePage( true );
1458  bChgPage = true;
1459  }
1460  else
1461  {
1462  // At least we can search the approximately correct page.
1463  // To ensure to be finished in finite time even if hundreds
1464  // of footnotes exist
1465  SwPageFrame *pNxt = static_cast<SwPageFrame*>(pPage->GetNext());
1466  const sal_uLong nStPos = ::lcl_FindFootnotePos( pDoc, pAttr );
1467  while ( pNxt && pNxt->IsEndNotePage() )
1468  {
1469  SwFootnoteContFrame *pCont = pNxt->FindFootnoteCont();
1470  if ( pCont && pCont->Lower() )
1471  {
1472  OSL_ENSURE( pCont->Lower()->IsFootnoteFrame(), "no footnote in the container" );
1473  if ( nStPos > ::lcl_FindFootnotePos( pDoc,
1474  static_cast<SwFootnoteFrame*>(pCont->Lower())->GetAttr()))
1475  {
1476  pPage = pNxt;
1477  pNxt = static_cast<SwPageFrame*>(pPage->GetNext());
1478  continue;
1479  }
1480  }
1481  break;
1482  }
1483  }
1484  }
1485  }
1486  else if( FTNPOS_CHAPTER == pDoc->GetFootnoteInfo().ePos && ( !GetUpper()->
1487  IsSctFrame() || !static_cast<SwSectionFrame*>(GetUpper())->IsFootnoteAtEnd() ) )
1488  {
1489  while ( pPage->GetNext() && !pPage->IsFootnotePage() &&
1490  !static_cast<SwPageFrame*>(pPage->GetNext())->IsEndNotePage() )
1491  {
1492  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
1493  bChgPage = true;
1494  }
1495 
1496  if ( !pPage->IsFootnotePage() )
1497  {
1498  SwPageDesc *pDesc = pDoc->GetFootnoteInfo().GetPageDesc( *pDoc );
1499  pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(),
1500  !pPage->OnRightPage(), false, false, true, pPage->GetNext() );
1501  bChgPage = true;
1502  }
1503  else
1504  {
1505  // We can at least search the approximately correct page
1506  // to ensure that we will finish in finite time even if
1507  // hundreds of footnotes exist.
1508  SwPageFrame *pNxt = static_cast<SwPageFrame*>(pPage->GetNext());
1509  const sal_uLong nStPos = ::lcl_FindFootnotePos( pDoc, pAttr );
1510  while ( pNxt && pNxt->IsFootnotePage() && !pNxt->IsEndNotePage() )
1511  {
1512  SwFootnoteContFrame *pCont = pNxt->FindFootnoteCont();
1513  if ( pCont && pCont->Lower() )
1514  {
1515  OSL_ENSURE( pCont->Lower()->IsFootnoteFrame(), "no footnote in the container" );
1516  if ( nStPos > ::lcl_FindFootnotePos( pDoc,
1517  static_cast<SwFootnoteFrame*>(pCont->Lower())->GetAttr()))
1518  {
1519  pPage = pNxt;
1520  pNxt = static_cast<SwPageFrame*>(pPage->GetNext());
1521  continue;
1522  }
1523  }
1524  break;
1525  }
1526  }
1527  }
1528 
1529  // For now, create a footnote and the corresponding content frames
1530  if ( !pAttr->GetStartNode() )
1531  {
1532  OSL_ENSURE( false, "no footnote content." );
1533  return;
1534  }
1535 
1536  // If there is already a footnote content on the column/page,
1537  // another one cannot be created in a column area.
1538  if( pBoss->IsInSct() && pBoss->IsColumnFrame() && !pPage->IsFootnotePage() )
1539  {
1540  SwSectionFrame* pSct = pBoss->FindSctFrame();
1541  if( bEnd ? !pSct->IsEndnAtEnd() : !pSct->IsFootnoteAtEnd() )
1542  {
1543  SwFootnoteContFrame* pFootnoteCont = pSct->FindFootnoteBossFrame(!bEnd)->FindFootnoteCont();
1544  if( pFootnoteCont )
1545  {
1546  SwFootnoteFrame* pTmp = static_cast<SwFootnoteFrame*>(pFootnoteCont->Lower());
1547  if( bEnd )
1548  while( pTmp && !pTmp->GetAttr()->GetFootnote().IsEndNote() )
1549  pTmp = static_cast<SwFootnoteFrame*>(pTmp->GetNext());
1550  if( pTmp && *pTmp < pAttr )
1551  return;
1552  }
1553  }
1554  }
1555 
1556  SwFootnoteFrame *pNew = new SwFootnoteFrame( pDoc->GetDfltFrameFormat(), this, pRef, pAttr );
1557  {
1558  SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
1559  ::InsertCnt_( pNew, pDoc, aIdx.GetIndex() );
1560  }
1561  // If the page was changed or newly created,
1562  // we need to place ourselves in the first column
1563  if( bChgPage )
1564  {
1565  SwLayoutFrame* pBody = pPage->FindBodyCont();
1566  OSL_ENSURE( pBody, "AppendFootnote: NoPageBody?" );
1567  if( pBody->Lower() && pBody->Lower()->IsColumnFrame() )
1568  pBoss = static_cast<SwFootnoteBossFrame*>(pBody->Lower());
1569  else
1570  pBoss = pPage; // page if no columns exist
1571  }
1572  pBoss->InsertFootnote( pNew );
1573  if ( pNew->GetUpper() ) // inserted or not?
1574  {
1575  ::RegistFlys( pNew->FindPageFrame(), pNew );
1576  SwSectionFrame* pSect = FindSctFrame();
1577  // The content of a FootnoteContainer in a (column) section only need to be calculated
1578  // if the section stretches already to the bottom edge of the Upper.
1579  if( pSect && !pSect->IsJoinLocked() && ( bEnd ? !pSect->IsEndnAtEnd() :
1580  !pSect->IsFootnoteAtEnd() ) && pSect->Growable() )
1581  pSect->InvalidateSize();
1582  else
1583  {
1584  // #i49383# - disable unlock of position of
1585  // lower objects during format of footnote content.
1586  const bool bOldFootnoteFrameLocked( pNew->IsColLocked() );
1587  pNew->ColLock();
1588  pNew->KeepLockPosOfLowerObjs();
1589  // #i57914# - adjust fix #i49383#
1590  SwContentFrame *pCnt = pNew->ContainsContent();
1591  while ( pCnt && pCnt->FindFootnoteFrame()->GetAttr() == pAttr )
1592  {
1593  pCnt->Calc(getRootFrame()->GetCurrShell()->GetOut());
1594  // #i49383# - format anchored objects
1595  if ( pCnt->IsTextFrame() && pCnt->isFrameAreaDefinitionValid() )
1596  {
1598  *(pCnt->FindPageFrame()) ) )
1599  {
1600  // restart format with first content
1601  pCnt = pNew->ContainsContent();
1602  continue;
1603  }
1604  }
1605  pCnt = pCnt->FindNextCnt();
1606  }
1607  // #i49383#
1608  if ( !bOldFootnoteFrameLocked )
1609  {
1610  pNew->ColUnlock();
1611  }
1612  // #i57914# - adjust fix #i49383#
1613  // enable lock of lower object position before format of footnote frame.
1614  pNew->UnlockPosOfLowerObjs();
1615  pNew->Calc(getRootFrame()->GetCurrShell()->GetOut());
1616  // #i57914# - adjust fix #i49383#
1617  if ( !bOldFootnoteFrameLocked && !pNew->GetLower() &&
1618  !pNew->IsColLocked() && !pNew->IsBackMoveLocked() &&
1619  !pNew->IsDeleteForbidden() )
1620  {
1621  pNew->Cut();
1622  SwFrame::DestroyFrame(pNew);
1623  }
1624  }
1625  pMyPage->UpdateFootnoteNum();
1626  }
1627  else
1628  SwFrame::DestroyFrame(pNew);
1629 }
1630 
1632 {
1633  // the easiest and savest way goes via the attribute
1634  OSL_ENSURE( pAttr->GetStartNode(), "FootnoteAtr without StartNode." );
1635  SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
1636  SwContentNode *pNd = aIdx.GetNode().GetContentNode();
1637  if ( !pNd )
1638  pNd = pRef->GetAttrSet()->GetDoc()->
1639  GetNodes().GoNextSection( &aIdx, true, false );
1640  if ( !pNd )
1641  return nullptr;
1643  SwFrame* pFrame = aIter.First();
1644  if( pFrame )
1645  do
1646  {
1647  pFrame = pFrame->GetUpper();
1648  // #i28500#, #i27243# Due to the endnode collector, there are
1649  // SwFootnoteFrames, which are not in the layout. Therefore the
1650  // bInfFootnote flags are not set correctly, and a cell of FindFootnoteFrame
1651  // would return 0. Therefore we better call ImplFindFootnoteFrame().
1652  SwFootnoteFrame *pFootnote = pFrame->ImplFindFootnoteFrame();
1653  if ( pFootnote && pFootnote->GetRef() == pRef )
1654  {
1655  // The following condition becomes true, if the whole
1656  // footnotecontent is a section. While no frames exist,
1657  // the HiddenFlag of the section is set, this causes
1658  // the GoNextSection-function leaves the footnote.
1659  if( pFootnote->GetAttr() != pAttr )
1660  return nullptr;
1661  while ( pFootnote && pFootnote->GetMaster() )
1662  pFootnote = pFootnote->GetMaster();
1663  return pFootnote;
1664  }
1665 
1666  } while ( nullptr != (pFrame = aIter.Next()) );
1667 
1668  return nullptr;
1669 }
1670 
1672  const SwContentFrame *const pRef, const SwTextFootnote *const pAttr,
1673  bool bPrep )
1674 {
1675  bool ret(false);
1676  SwFootnoteFrame *pFootnote = FindFootnote( pRef, pAttr );
1677  if( pFootnote )
1678  {
1679  ret = true;
1680  do
1681  {
1682  SwFootnoteFrame *pFoll = pFootnote->GetFollow();
1683  pFootnote->Cut();
1684  SwFrame::DestroyFrame(pFootnote);
1685  pFootnote = pFoll;
1686  } while ( pFootnote );
1687  if( bPrep && pRef->IsFollow() )
1688  {
1689  OSL_ENSURE( pRef->IsTextFrame(), "NoTextFrame has Footnote?" );
1690  SwTextFrame* pMaster = pRef->FindMaster();
1691  if( !pMaster->IsLocked() )
1692  pMaster->Prepare( PREP_FTN_GONE );
1693  }
1694  }
1696  return ret;
1697 }
1698 
1700  SwContentFrame *pNew )
1701 {
1702  SwFootnoteFrame *pFootnote = FindFootnote( pOld, pAttr );
1703  while ( pFootnote )
1704  {
1705  pFootnote->SetRef( pNew );
1706  pFootnote = pFootnote->GetFollow();
1707  }
1708 }
1709 
1714  SwFootnoteBossFrame* _pOld,
1715  SwFootnoteFrames& _rFootnoteArr,
1716  const bool _bCollectOnlyPreviousFootnotes )
1717 {
1718  SwFootnoteFrame *pFootnote = _pOld->FindFirstFootnote();
1719  while( !pFootnote )
1720  {
1721  if( _pOld->IsColumnFrame() )
1722  {
1723  // visit columns
1724  while ( !pFootnote && _pOld->GetPrev() )
1725  {
1726  // Still no problem if no footnote was found yet. The loop is needed to pick up
1727  // following rows in tables. In all other cases it might correct bad contexts.
1728  _pOld = static_cast<SwFootnoteBossFrame*>(_pOld->GetPrev());
1729  pFootnote = _pOld->FindFirstFootnote();
1730  }
1731  }
1732  if( !pFootnote )
1733  {
1734  // previous page
1735  SwPageFrame* pPg;
1736  for ( SwFrame* pTmp = _pOld;
1737  nullptr != ( pPg = static_cast<SwPageFrame*>(pTmp->FindPageFrame()->GetPrev()))
1738  && pPg->IsEmptyPage() ;
1739  )
1740  {
1741  pTmp = pPg;
1742  }
1743  if( !pPg )
1744  return;
1745 
1746  SwLayoutFrame* pBody = pPg->FindBodyCont();
1747  if( pBody->Lower() && pBody->Lower()->IsColumnFrame() )
1748  {
1749  // multiple columns on one page => search last column
1750  _pOld = static_cast<SwFootnoteBossFrame*>(pBody->GetLastLower());
1751  }
1752  else
1753  _pOld = pPg; // single column page
1754  pFootnote = _pOld->FindFirstFootnote();
1755  }
1756  }
1757  // OD 03.04.2003 #108446# - consider new parameter <_bCollectOnlyPreviousFootnotes>
1758  SwFootnoteBossFrame* pRefBossFrame = nullptr;
1759  if ( _bCollectOnlyPreviousFootnotes )
1760  {
1761  pRefBossFrame = this;
1762  }
1763  CollectFootnotes_( _pRef, pFootnote, _rFootnoteArr, _bCollectOnlyPreviousFootnotes, pRefBossFrame );
1764 }
1765 
1766 static void FootnoteInArr( SwFootnoteFrames& rFootnoteArr, SwFootnoteFrame* pFootnote )
1767 {
1768  if ( rFootnoteArr.end() == std::find( rFootnoteArr.begin(), rFootnoteArr.end(), pFootnote ) )
1769  rFootnoteArr.push_back( pFootnote );
1770 }
1771 
1779  SwFootnoteFrame* _pFootnote,
1780  SwFootnoteFrames& _rFootnoteArr,
1781  bool _bCollectOnlyPreviousFootnotes,
1782  const SwFootnoteBossFrame* _pRefFootnoteBossFrame)
1783 {
1784  // OD 03.04.2003 #108446# - assert, that no reference footnote boss frame
1785  // is set, in spite of the order, that only previous footnotes has to be
1786  // collected.
1787  OSL_ENSURE( !_bCollectOnlyPreviousFootnotes || _pRefFootnoteBossFrame,
1788  "<SwFootnoteBossFrame::CollectFootnotes_(..)> - No reference footnote boss frame for collecting only previous footnotes set.\nCrash will be caused!" );
1789 
1790  // Collect all footnotes referenced by pRef (attribute by attribute), combine them
1791  // (the content might be divided over multiple pages) and cut them.
1792 
1793  // For robustness, we do not log the corresponding footnotes here. If a footnote
1794  // is touched twice, there might be a crash. This allows this function here to
1795  // also handle corrupt layouts in some degrees (without loops or even crashes).
1796  SwFootnoteFrames aNotFootnoteArr;
1797 
1798  // here we have a footnote placed in front of the first one of the reference
1799  OSL_ENSURE( !_pFootnote->GetMaster() || _pFootnote->GetRef() != _pRef, "move FollowFootnote?" );
1800  while ( _pFootnote->GetMaster() )
1801  _pFootnote = _pFootnote->GetMaster();
1802 
1803  bool bFound = false;
1804 
1805  do
1806  {
1807  // Search for the next footnote in this column/page so that
1808  // we do not start from zero again after cutting one footnote.
1809  SwFootnoteFrame *pNxtFootnote = _pFootnote;
1810  while ( pNxtFootnote->GetFollow() )
1811  pNxtFootnote = pNxtFootnote->GetFollow();
1812  pNxtFootnote = static_cast<SwFootnoteFrame*>(pNxtFootnote->GetNext());
1813 
1814  if ( !pNxtFootnote )
1815  {
1816  SwFootnoteBossFrame* pBoss = _pFootnote->FindFootnoteBossFrame();
1817  SwPageFrame* pPage = pBoss->FindPageFrame();
1818  do
1819  {
1820  lcl_NextFootnoteBoss( pBoss, pPage, false );
1821  if( pBoss )
1822  {
1823  SwLayoutFrame* pCont = pBoss->FindFootnoteCont();
1824  if( pCont )
1825  {
1826  pNxtFootnote = static_cast<SwFootnoteFrame*>(pCont->Lower());
1827  if( pNxtFootnote )
1828  {
1829  while( pNxtFootnote->GetMaster() )
1830  pNxtFootnote = pNxtFootnote->GetMaster();
1831  if( pNxtFootnote == _pFootnote )
1832  pNxtFootnote = nullptr;
1833  }
1834  }
1835  }
1836  } while( !pNxtFootnote && pBoss );
1837  }
1838  else if( !pNxtFootnote->GetAttr()->GetFootnote().IsEndNote() )
1839  {
1840  OSL_ENSURE( !pNxtFootnote->GetMaster(), "_CollectFootnote: Master expected" );
1841  while ( pNxtFootnote->GetMaster() )
1842  pNxtFootnote = pNxtFootnote->GetMaster();
1843  }
1844  if ( pNxtFootnote == _pFootnote )
1845  {
1846  OSL_FAIL( "_CollectFootnote: Vicious circle" );
1847  pNxtFootnote = nullptr;
1848  }
1849 
1850  // OD 03.04.2003 #108446# - determine, if found footnote has to be collected.
1851  bool bCollectFoundFootnote = false;
1852  if ( _pFootnote->GetRef() == _pRef && !_pFootnote->GetAttr()->GetFootnote().IsEndNote() )
1853  {
1854  if ( _bCollectOnlyPreviousFootnotes )
1855  {
1856  SwFootnoteBossFrame* pBossOfFoundFootnote = _pFootnote->FindFootnoteBossFrame( true );
1857  OSL_ENSURE( pBossOfFoundFootnote,
1858  "<SwFootnoteBossFrame::CollectFootnotes_(..)> - footnote boss frame of found footnote frame missing.\nWrong layout!" );
1859  if ( !pBossOfFoundFootnote || // don't crash, if no footnote boss is found.
1860  pBossOfFoundFootnote->IsBefore( _pRefFootnoteBossFrame )
1861  )
1862  {
1863  bCollectFoundFootnote = true;
1864  }
1865  }
1866  else
1867  {
1868  bCollectFoundFootnote = true;
1869  }
1870  }
1871 
1872  if ( bCollectFoundFootnote )
1873  {
1874  OSL_ENSURE( !_pFootnote->GetMaster(), "move FollowFootnote?" );
1875  SwFootnoteFrame *pNxt = _pFootnote->GetFollow();
1876  while ( pNxt )
1877  {
1878  SwFrame *pCnt = pNxt->ContainsAny();
1879  if ( pCnt )
1880  {
1881  // destroy the follow on the way as it is empty
1882  do
1883  { SwFrame *pNxtCnt = pCnt->GetNext();
1884  pCnt->Cut();
1885  pCnt->Paste( _pFootnote );
1886  pCnt = pNxtCnt;
1887  } while ( pCnt );
1888  }
1889  else
1890  {
1891  OSL_ENSURE( !pNxt, "footnote without content?" );
1892  pNxt->Cut();
1893  SwFrame::DestroyFrame(pNxt);
1894  }
1895  pNxt = _pFootnote->GetFollow();
1896  }
1897  _pFootnote->Cut();
1898  FootnoteInArr( _rFootnoteArr, _pFootnote );
1899  bFound = true;
1900  }
1901  else
1902  {
1903  FootnoteInArr( aNotFootnoteArr, _pFootnote );
1904  if( bFound )
1905  break;
1906  }
1907  if ( pNxtFootnote &&
1908  _rFootnoteArr.end() == std::find( _rFootnoteArr.begin(), _rFootnoteArr.end(), pNxtFootnote ) &&
1909  aNotFootnoteArr.end() == std::find( aNotFootnoteArr.begin(), aNotFootnoteArr.end(), pNxtFootnote ) )
1910  _pFootnote = pNxtFootnote;
1911  else
1912  break;
1913  }
1914  while ( _pFootnote );
1915 }
1916 
1918 {
1919  // All footnotes referenced by pRef need to be moved
1920  // to a new position (based on the new column/page)
1921  const sal_uInt16 nMyNum = FindPageFrame()->GetPhyPageNum();
1922  const sal_uInt16 nMyCol = lcl_ColumnNum( this );
1923  SwRectFnSet aRectFnSet(this);
1924 
1925  // #i21478# - keep last inserted footnote in order to
1926  // format the content of the following one.
1927  SwFootnoteFrame* pLastInsertedFootnote = nullptr;
1928  for (SwFootnoteFrame* pFootnote : rFootnoteArr)
1929  {
1930  SwFootnoteBossFrame* pRefBoss(pFootnote->GetRef()->FindFootnoteBossFrame(
1931  !pFootnote->GetAttr()->GetFootnote().IsEndNote()));
1932  if( pRefBoss != this )
1933  {
1934  const sal_uInt16 nRefNum = pRefBoss->FindPageFrame()->GetPhyPageNum();
1935  const sal_uInt16 nRefCol = lcl_ColumnNum( this );
1936  if( nRefNum < nMyNum || ( nRefNum == nMyNum && nRefCol <= nMyCol ) )
1937  pRefBoss = this;
1938  }
1939  pRefBoss->InsertFootnote( pFootnote );
1940 
1941  if ( pFootnote->GetUpper() ) // robust, e.g. with duplicates
1942  {
1943  // First condense the content so that footnote frames that do not fit on the page
1944  // do not do too much harm (Loop 66312). So, the footnote content first grows as
1945  // soon as the content gets formatted and it is sure that it fits on the page.
1946  SwFrame *pCnt = pFootnote->ContainsAny();
1947  while( pCnt )
1948  {
1949  if( pCnt->IsLayoutFrame() )
1950  {
1951  SwFrame* pTmp = static_cast<SwLayoutFrame*>(pCnt)->ContainsAny();
1952  while( pTmp && static_cast<SwLayoutFrame*>(pCnt)->IsAnLower( pTmp ) )
1953  {
1954  pTmp->Prepare( PREP_MOVEFTN );
1955 
1957  aRectFnSet.SetHeight(aFrm, 0);
1958 
1960  aRectFnSet.SetHeight(aPrt, 0);
1961 
1962  pTmp = pTmp->FindNext();
1963  }
1964  }
1965  else
1966  {
1967  pCnt->Prepare( PREP_MOVEFTN );
1968  }
1969 
1971  aRectFnSet.SetHeight(aFrm, 0);
1972 
1974  aRectFnSet.SetHeight(aPrt, 0);
1975 
1976  pCnt = pCnt->GetNext();
1977  }
1978 
1979  {
1981  aRectFnSet.SetHeight(aFrm, 0);
1982  }
1983 
1984  {
1986  aRectFnSet.SetHeight(aPrt, 0);
1987  }
1988 
1989  pFootnote->Calc(getRootFrame()->GetCurrShell()->GetOut());
1990  pFootnote->GetUpper()->Calc(getRootFrame()->GetCurrShell()->GetOut());
1991 
1992  if( bCalc )
1993  {
1994  SwTextFootnote *pAttr = pFootnote->GetAttr();
1995  pCnt = pFootnote->ContainsAny();
1996  bool bUnlock = !pFootnote->IsBackMoveLocked();
1997  pFootnote->LockBackMove();
1998 
1999  // #i49383# - disable unlock of position of
2000  // lower objects during format of footnote content.
2001  pFootnote->KeepLockPosOfLowerObjs();
2002  // #i57914# - adjust fix #i49383#
2003 
2004  while ( pCnt && pCnt->FindFootnoteFrame()->GetAttr() == pAttr )
2005  {
2006  pCnt->InvalidatePos_();
2007  pCnt->Calc(getRootFrame()->GetCurrShell()->GetOut());
2008  // #i49383# - format anchored objects
2009  if ( pCnt->IsTextFrame() && pCnt->isFrameAreaDefinitionValid() )
2010  {
2012  *(pCnt->FindPageFrame()) ) )
2013  {
2014  // restart format with first content
2015  pCnt = pFootnote->ContainsAny();
2016  continue;
2017  }
2018  }
2019  if( pCnt->IsSctFrame() )
2020  {
2021  // If the area is not empty, iterate also over the content
2022  SwFrame* pTmp = static_cast<SwSectionFrame*>(pCnt)->ContainsAny();
2023  if( pTmp )
2024  pCnt = pTmp;
2025  else
2026  pCnt = pCnt->FindNext();
2027  }
2028  else
2029  pCnt = pCnt->FindNext();
2030  }
2031  if( bUnlock )
2032  {
2033  pFootnote->UnlockBackMove();
2034  if( !pFootnote->ContainsAny() && !pFootnote->IsColLocked() )
2035  {
2036  pFootnote->Cut();
2037  SwFrame::DestroyFrame(pFootnote);
2038  // #i21478#
2039  pFootnote = nullptr;
2040  }
2041  }
2042  // #i49383#
2043  if ( pFootnote )
2044  {
2045  // #i57914# - adjust fix #i49383#
2046  // enable lock of lower object position before format of footnote frame.
2047  pFootnote->UnlockPosOfLowerObjs();
2048  pFootnote->Calc(getRootFrame()->GetCurrShell()->GetOut());
2049  }
2050  }
2051  }
2052  else
2053  {
2054  OSL_ENSURE( !pFootnote->GetMaster() && !pFootnote->GetFollow(),
2055  "DelFootnote and Master/Follow?" );
2056  SwFrame::DestroyFrame(pFootnote);
2057  // #i21478#
2058  pFootnote = nullptr;
2059  }
2060 
2061  // #i21478#
2062  if ( pFootnote )
2063  {
2064  pLastInsertedFootnote = pFootnote;
2065  }
2066  }
2067 
2068  // #i21478# - format content of footnote following
2069  // the new inserted ones.
2070  if ( bCalc && pLastInsertedFootnote )
2071  {
2072  if ( pLastInsertedFootnote->GetNext() )
2073  {
2074  SwFootnoteFrame* pNextFootnote = static_cast<SwFootnoteFrame*>(pLastInsertedFootnote->GetNext());
2075  SwTextFootnote* pAttr = pNextFootnote->GetAttr();
2076  SwFrame* pCnt = pNextFootnote->ContainsAny();
2077 
2078  bool bUnlock = !pNextFootnote->IsBackMoveLocked();
2079  pNextFootnote->LockBackMove();
2080  // #i49383# - disable unlock of position of
2081  // lower objects during format of footnote content.
2082  pNextFootnote->KeepLockPosOfLowerObjs();
2083  // #i57914# - adjust fix #i49383#
2084 
2085  while ( pCnt && pCnt->FindFootnoteFrame()->GetAttr() == pAttr )
2086  {
2087  pCnt->InvalidatePos_();
2088  pCnt->Calc(getRootFrame()->GetCurrShell()->GetOut());
2089  // #i49383# - format anchored objects
2090  if ( pCnt->IsTextFrame() && pCnt->isFrameAreaDefinitionValid() )
2091  {
2093  *(pCnt->FindPageFrame()) ) )
2094  {
2095  // restart format with first content
2096  pCnt = pNextFootnote->ContainsAny();
2097  continue;
2098  }
2099  }
2100  if( pCnt->IsSctFrame() )
2101  {
2102  // If the area is not empty, iterate also over the content
2103  SwFrame* pTmp = static_cast<SwSectionFrame*>(pCnt)->ContainsAny();
2104  if( pTmp )
2105  pCnt = pTmp;
2106  else
2107  pCnt = pCnt->FindNext();
2108  }
2109  else
2110  pCnt = pCnt->FindNext();
2111  }
2112  if( bUnlock )
2113  {
2114  pNextFootnote->UnlockBackMove();
2115  }
2116  // #i49383#
2117  // #i57914# - adjust fix #i49383#
2118  // enable lock of lower object position before format of footnote frame.
2119  pNextFootnote->UnlockPosOfLowerObjs();
2120  pNextFootnote->Calc(getRootFrame()->GetCurrShell()->GetOut());
2121  }
2122  }
2123 }
2124 
2126  SwTextFootnote const *pAttr )
2127 {
2128  if( ( GetFormat()->GetDoc()->GetFootnoteInfo().ePos == FTNPOS_CHAPTER &&
2129  (!GetUpper()->IsSctFrame() || !static_cast<SwSectionFrame*>(GetUpper())->IsFootnoteAtEnd()))
2130  || pAttr->GetFootnote().IsEndNote() )
2131  return;
2132 
2133  OSL_ENSURE( this == pSrc->FindFootnoteBossFrame( true ),
2134  "SwPageFrame::MoveFootnotes: source frame isn't on that FootnoteBoss" );
2135 
2136  SwFootnoteFrame *pFootnote = FindFirstFootnote();
2137  if( pFootnote )
2138  {
2139  ChangeFootnoteRef( pSrc, pAttr, pDest );
2140  SwFootnoteBossFrame *pDestBoss = pDest->FindFootnoteBossFrame( true );
2141  OSL_ENSURE( pDestBoss, "+SwPageFrame::MoveFootnotes: no destination boss" );
2142  if( pDestBoss ) // robust
2143  {
2144  SwFootnoteFrames aFootnoteArr;
2145  SwFootnoteBossFrame::CollectFootnotes_( pDest, pFootnote, aFootnoteArr );
2146  if ( !aFootnoteArr.empty() )
2147  {
2148  pDestBoss->MoveFootnotes_( aFootnoteArr, true );
2149  SwPageFrame* pSrcPage = FindPageFrame();
2150  SwPageFrame* pDestPage = pDestBoss->FindPageFrame();
2151  // update FootnoteNum only at page change
2152  if( pSrcPage != pDestPage )
2153  {
2154  if( pSrcPage->GetPhyPageNum() > pDestPage->GetPhyPageNum() )
2155  pSrcPage->UpdateFootnoteNum();
2156  pDestPage->UpdateFootnoteNum();
2157  }
2158  }
2159  }
2160  }
2161 }
2162 
2163 void SwFootnoteBossFrame::RearrangeFootnotes( const SwTwips nDeadLine, const bool bLock,
2164  const SwTextFootnote *pAttr )
2165 {
2166  // Format all footnotes of a column/page so that they might change the column/page.
2167 
2168  SwSaveFootnoteHeight aSave( this, nDeadLine );
2169  SwFootnoteFrame *pFootnote = FindFirstFootnote();
2170  if( pFootnote && pFootnote->GetPrev() && bLock )
2171  {
2172  SwFootnoteFrame* pFirst = static_cast<SwFootnoteFrame*>(pFootnote->GetUpper()->Lower());
2173  SwFrame* pContent = pFirst->ContainsAny();
2174  if( pContent )
2175  {
2176  bool bUnlock = !pFirst->IsBackMoveLocked();
2177  pFirst->LockBackMove();
2178  pFirst->Calc(getRootFrame()->GetCurrShell()->GetOut());
2179  pContent->Calc(getRootFrame()->GetCurrShell()->GetOut());
2180  // #i49383# - format anchored objects
2181  if ( pContent->IsTextFrame() && pContent->isFrameAreaDefinitionValid() )
2182  {
2184  *(pContent->FindPageFrame()) );
2185  }
2186  if( bUnlock )
2187  pFirst->UnlockBackMove();
2188  }
2189  pFootnote = FindFirstFootnote();
2190  }
2191  SwDoc *pDoc = GetFormat()->GetDoc();
2192  const sal_uLong nFootnotePos = pAttr ? ::lcl_FindFootnotePos( pDoc, pAttr ) : 0;
2193  SwFrame *pCnt = pFootnote ? pFootnote->ContainsAny() : nullptr;
2194  if ( pCnt )
2195  {
2196  bool bMore = true;
2197  bool bStart = pAttr == nullptr; // If no attribute is given, process all
2198  // #i49383# - disable unlock of position of
2199  // lower objects during format of footnote and footnote content.
2200  SwFootnoteFrame* pLastFootnoteFrame( nullptr );
2201  // footnote frame needs to be locked, if <bLock> isn't set.
2202  bool bUnlockLastFootnoteFrame( false );
2203  do
2204  {
2205  if( !bStart )
2206  bStart = ::lcl_FindFootnotePos( pDoc, pCnt->FindFootnoteFrame()->GetAttr() )
2207  == nFootnotePos;
2208  if( bStart )
2209  {
2210  pCnt->InvalidatePos_();
2211  pCnt->InvalidateSize_();
2212  pCnt->Prepare( PREP_ADJUST_FRM );
2213  SwFootnoteFrame* pFootnoteFrame = pCnt->FindFootnoteFrame();
2214  // #i49383#
2215  if ( pFootnoteFrame != pLastFootnoteFrame )
2216  {
2217  if ( pLastFootnoteFrame )
2218  {
2219  if ( !bLock && bUnlockLastFootnoteFrame )
2220  {
2221  pLastFootnoteFrame->ColUnlock();
2222  }
2223  // #i57914# - adjust fix #i49383#
2224  // enable lock of lower object position before format of footnote frame.
2225  pLastFootnoteFrame->UnlockPosOfLowerObjs();
2226  pLastFootnoteFrame->Calc(getRootFrame()->GetCurrShell()->GetOut());
2227  if ( !bLock && bUnlockLastFootnoteFrame &&
2228  !pLastFootnoteFrame->GetLower() &&
2229  !pLastFootnoteFrame->IsColLocked() &&
2230  !pLastFootnoteFrame->IsBackMoveLocked() &&
2231  !pLastFootnoteFrame->IsDeleteForbidden() )
2232  {
2233  pLastFootnoteFrame->Cut();
2234  SwFrame::DestroyFrame(pLastFootnoteFrame);
2235  pLastFootnoteFrame = nullptr;
2236  }
2237  }
2238  if ( !bLock )
2239  {
2240  bUnlockLastFootnoteFrame = !pFootnoteFrame->IsColLocked();
2241  pFootnoteFrame->ColLock();
2242  }
2243  pFootnoteFrame->KeepLockPosOfLowerObjs();
2244  pLastFootnoteFrame = pFootnoteFrame;
2245  }
2246  // OD 30.10.2002 #97265# - invalidate position of footnote
2247  // frame, if it's below its footnote container, in order to
2248  // assure its correct position, probably calculating its previous
2249  // footnote frames.
2250  {
2251  SwRectFnSet aRectFnSet(this);
2252  SwFrame* pFootnoteContFrame = pFootnoteFrame->GetUpper();
2253  if ( aRectFnSet.TopDist(pFootnoteFrame->getFrameArea(), aRectFnSet.GetPrtBottom(*pFootnoteContFrame)) > 0 )
2254  {
2255  pFootnoteFrame->InvalidatePos_();
2256  }
2257  }
2258  if ( bLock )
2259  {
2260  bool bUnlock = !pFootnoteFrame->IsBackMoveLocked();
2261  pFootnoteFrame->LockBackMove();
2262  pFootnoteFrame->Calc(getRootFrame()->GetCurrShell()->GetOut());
2263  pCnt->Calc(getRootFrame()->GetCurrShell()->GetOut());
2264  // #i49383# - format anchored objects
2265  if ( pCnt->IsTextFrame() && pCnt->isFrameAreaDefinitionValid() )
2266  {
2268  *(pCnt->FindPageFrame()) ) )
2269  {
2270  // restart format with first content
2271  pCnt = pFootnote->ContainsAny();
2272  continue;
2273  }
2274  }
2275  if( bUnlock )
2276  {
2277  pFootnoteFrame->UnlockBackMove();
2278  if( !pFootnoteFrame->Lower() &&
2279  !pFootnoteFrame->IsColLocked() )
2280  {
2281  // #i49383#
2282  OSL_ENSURE( pLastFootnoteFrame == pFootnoteFrame,
2283  "<SwFootnoteBossFrame::RearrangeFootnotes(..)> - <pLastFootnoteFrame> != <pFootnoteFrame>" );
2284  pLastFootnoteFrame = nullptr;
2285  pFootnoteFrame->Cut();
2286  SwFrame::DestroyFrame(pFootnoteFrame);
2287  }
2288  }
2289  }
2290  else
2291  {
2292  pFootnoteFrame->Calc(getRootFrame()->GetCurrShell()->GetOut());
2293  pCnt->Calc(getRootFrame()->GetCurrShell()->GetOut());
2294  // #i49383# - format anchored objects
2295  if ( pCnt->IsTextFrame() && pCnt->isFrameAreaDefinitionValid() )
2296  {
2298  *(pCnt->FindPageFrame()) ) )
2299  {
2300  // restart format with first content
2301  pCnt = pFootnote->ContainsAny();
2302  continue;
2303  }
2304  }
2305  }
2306  }
2307  SwSectionFrame *pDel = nullptr;
2308  if( pCnt->IsSctFrame() )
2309  {
2310  SwFrame* pTmp = static_cast<SwSectionFrame*>(pCnt)->ContainsAny();
2311  if( pTmp )
2312  {
2313  pCnt = pTmp;
2314  continue;
2315  }
2316  pDel = static_cast<SwSectionFrame*>(pCnt);
2317  }
2318  if ( pCnt->GetNext() )
2319  pCnt = pCnt->GetNext();
2320  else
2321  {
2322  pCnt = pCnt->FindNext();
2323  if ( pCnt )
2324  {
2325  SwFootnoteFrame* pFootnoteFrame = pCnt->FindFootnoteFrame();
2326  if( pFootnoteFrame->GetRef()->FindFootnoteBossFrame(
2327  pFootnoteFrame->GetAttr()->GetFootnote().IsEndNote() ) != this )
2328  bMore = false;
2329  }
2330  else
2331  bMore = false;
2332  }
2333  if( pDel )
2334  {
2335  bool bUnlockLastFootnoteFrameGuard = pLastFootnoteFrame && !pLastFootnoteFrame->IsColLocked();
2336  if (bUnlockLastFootnoteFrameGuard)
2337  pLastFootnoteFrame->ColLock();
2338  pDel->Cut();
2339  if (bUnlockLastFootnoteFrameGuard)
2340  pLastFootnoteFrame->ColUnlock();
2341  SwFrame::DestroyFrame(pDel);
2342  }
2343  if ( bMore )
2344  {
2345  // Go not further than to the provided footnote (if given)
2346  if ( pAttr &&
2347  (::lcl_FindFootnotePos( pDoc,
2348  pCnt->FindFootnoteFrame()->GetAttr()) > nFootnotePos ) )
2349  bMore = false;
2350  }
2351  } while ( bMore );
2352  // #i49383#
2353  if ( pLastFootnoteFrame )
2354  {
2355  if ( !bLock && bUnlockLastFootnoteFrame )
2356  {
2357  pLastFootnoteFrame->ColUnlock();
2358  }
2359  // #i57914# - adjust fix #i49383#
2360  // enable lock of lower object position before format of footnote frame.
2361  pLastFootnoteFrame->UnlockPosOfLowerObjs();
2362  pLastFootnoteFrame->Calc(getRootFrame()->GetCurrShell()->GetOut());
2363  if ( !bLock && bUnlockLastFootnoteFrame &&
2364  !pLastFootnoteFrame->GetLower() &&
2365  !pLastFootnoteFrame->IsColLocked() &&
2366  !pLastFootnoteFrame->IsBackMoveLocked() )
2367  {
2368  pLastFootnoteFrame->Cut();
2369  SwFrame::DestroyFrame(pLastFootnoteFrame);
2370  }
2371  }
2372  }
2373 }
2374 
2376 {
2377  // page numbering only if set at the document
2378  if ( GetFormat()->GetDoc()->GetFootnoteInfo().eNum != FTNNUM_PAGE )
2379  return;
2380 
2381  SwLayoutFrame* pBody = FindBodyCont();
2382  if( !pBody || !pBody->Lower() )
2383  return;
2384 
2385  SwContentFrame* pContent = pBody->ContainsContent();
2386  sal_uInt16 nNum = 0;
2387 
2388  while( pContent && pContent->FindPageFrame() == this )
2389  {
2390  if( static_cast<SwTextFrame*>(pContent)->HasFootnote() )
2391  {
2392  SwFootnoteBossFrame* pBoss = pContent->FindFootnoteBossFrame( true );
2393  if( pBoss->GetUpper()->IsSctFrame() &&
2394  static_cast<SwSectionFrame*>(pBoss->GetUpper())->IsOwnFootnoteNum() )
2395  pContent = static_cast<SwSectionFrame*>(pBoss->GetUpper())->FindLastContent();
2396  else
2397  {
2398  SwFootnoteFrame* pFootnote = const_cast<SwFootnoteFrame*>(pBoss->FindFirstFootnote( pContent ));
2399  while( pFootnote )
2400  {
2401  SwTextFootnote* pTextFootnote = pFootnote->GetAttr();
2402  if( !pTextFootnote->GetFootnote().IsEndNote() &&
2403  pTextFootnote->GetFootnote().GetNumStr().isEmpty() &&
2404  !pFootnote->GetMaster())
2405  {
2406  // sw_redlinehide: the layout can only keep one number
2407  // up to date; depending on its setting, this is either
2408  // the non-hidden or the hidden number; the other
2409  // number will simply be preserved as-is (so in case
2410  // there are 2 layouts, maybe both can be updated...)
2411  ++nNum;
2412  sal_uInt16 const nOldNum(pTextFootnote->GetFootnote().GetNumber());
2413  sal_uInt16 const nOldNumRLHidden(pTextFootnote->GetFootnote().GetNumberRLHidden());
2414  if (getRootFrame()->IsHideRedlines())
2415  {
2416  if (nNum != nOldNumRLHidden)
2417  {
2418  pTextFootnote->SetNumber(nOldNum, nNum, OUString());
2419  }
2420  }
2421  else
2422  {
2423  if (nNum != nOldNum)
2424  {
2425  pTextFootnote->SetNumber(nNum, nOldNumRLHidden, OUString());
2426  }
2427  }
2428  }
2429  if ( pFootnote->GetNext() )
2430  pFootnote = static_cast<SwFootnoteFrame*>(pFootnote->GetNext());
2431  else
2432  {
2433  SwFootnoteBossFrame* pTmpBoss = pFootnote->FindFootnoteBossFrame( true );
2434  if( pTmpBoss )
2435  {
2436  SwPageFrame* pPage = pTmpBoss->FindPageFrame();
2437  pFootnote = nullptr;
2438  lcl_NextFootnoteBoss( pTmpBoss, pPage, false );
2439  SwFootnoteContFrame *pCont = pTmpBoss ? pTmpBoss->FindNearestFootnoteCont() : nullptr;
2440  if ( pCont )
2441  pFootnote = static_cast<SwFootnoteFrame*>(pCont->Lower());
2442  }
2443  }
2444  if( pFootnote && pFootnote->GetRef() != pContent )
2445  pFootnote = nullptr;
2446  }
2447  }
2448  }
2449  pContent = pContent->FindNextCnt();
2450  }
2451 }
2452 
2454 {
2455  SwFrame *pBody = FindBodyCont();
2456  pBody->Calc(getRootFrame()->GetCurrShell()->GetOut());
2457 
2458  SwFrame *pCont = FindFootnoteCont();
2459  const SwTwips nMax = m_nMaxFootnoteHeight;// current should exceed MaxHeight
2460  SwRectFnSet aRectFnSet(this);
2461  if ( pCont )
2462  {
2463  pCont->Calc(getRootFrame()->GetCurrShell()->GetOut());
2464  m_nMaxFootnoteHeight = -aRectFnSet.BottomDist( pCont->getFrameArea(), nDeadLine );
2465  }
2466  else
2467  m_nMaxFootnoteHeight = -aRectFnSet.BottomDist( pBody->getFrameArea(), nDeadLine );
2468 
2469  const SwViewShell *pSh = getRootFrame() ? getRootFrame()->GetCurrShell() : nullptr;
2470  if( pSh && pSh->GetViewOptions()->getBrowseMode() )
2471  m_nMaxFootnoteHeight += pBody->Grow( LONG_MAX, true );
2472  if ( IsInSct() )
2474 
2475  if ( m_nMaxFootnoteHeight < 0 )
2477  if ( nMax != LONG_MAX && m_nMaxFootnoteHeight > nMax )
2478  m_nMaxFootnoteHeight = nMax;
2479 }
2480 
2482 {
2483  // To not fall below 20% of the page height
2484  // (in contrast to MSOffice where footnotes can fill a whole column/page)
2485 
2486  const SwPageFrame* pPg = FindPageFrame();
2487  OSL_ENSURE( pPg || IsInSct(), "Footnote lost page" );
2488 
2489  const SwFrame *pBody = FindBodyCont();
2490  SwTwips nRet;
2491  if( pBody )
2492  {
2493  SwRectFnSet aRectFnSet(this);
2494  if( IsInSct() )
2495  {
2496  nRet = 0;
2497  SwTwips nTmp = aRectFnSet.YDiff( aRectFnSet.GetPrtTop(*pBody),
2498  aRectFnSet.GetTop(getFrameArea()) );
2499  const SwSectionFrame* pSect = FindSctFrame();
2500  // Endnotes in a ftncontainer causes a deadline:
2501  // the bottom of the last contentfrm
2502  if( pSect->IsEndnAtEnd() ) // endnotes allowed?
2503  {
2504  OSL_ENSURE( !Lower() || !Lower()->GetNext() || Lower()->GetNext()->
2505  IsFootnoteContFrame(), "FootnoteContainer expected" );
2506  const SwFootnoteContFrame* pCont = Lower() ?
2507  static_cast<const SwFootnoteContFrame*>(Lower()->GetNext()) : nullptr;
2508  if( pCont )
2509  {
2510  const SwFootnoteFrame* pFootnote = static_cast<const SwFootnoteFrame*>(pCont->Lower());
2511  while( pFootnote)
2512  {
2513  if( pFootnote->GetAttr()->GetFootnote().IsEndNote() )
2514  { // endnote found
2515  const SwFrame* pFrame = static_cast<const SwLayoutFrame*>(Lower())->Lower();
2516  if( pFrame )
2517  {
2518  while( pFrame->GetNext() )
2519  pFrame = pFrame->GetNext(); // last cntntfrm
2520  nTmp += aRectFnSet.YDiff(
2521  aRectFnSet.GetTop(getFrameArea()),
2522  aRectFnSet.GetBottom(pFrame->getFrameArea()) );
2523  }
2524  break;
2525  }
2526  pFootnote = static_cast<const SwFootnoteFrame*>(pFootnote->GetNext());
2527  }
2528  }
2529  }
2530  if( nTmp < nRet )
2531  nRet = nTmp;
2532  }
2533  else
2534  nRet = - aRectFnSet.GetHeight(pPg->getFramePrintArea())/5;
2535  nRet += aRectFnSet.GetHeight(pBody->getFrameArea());
2536  if( nRet < 0 )
2537  nRet = 0;
2538  }
2539  else
2540  nRet = 0;
2541  if ( IsPageFrame() )
2542  {
2543  const SwViewShell *pSh = getRootFrame() ? getRootFrame()->GetCurrShell() : nullptr;
2544  if( pSh && pSh->GetViewOptions()->getBrowseMode() )
2545  nRet += BROWSE_HEIGHT - getFrameArea().Height();
2546  }
2547  return nRet;
2548 }
2549 
2563 {
2565  if( GetUpper() && !GetUpper()->IsPageBodyFrame() )
2566  {
2567  // column sections need grow/shrink
2568  if( GetUpper()->IsFlyFrame() )
2570  else
2571  {
2572  OSL_ENSURE( GetUpper()->IsSctFrame(), "NeighbourhoodAdjustment: Unexpected Upper" );
2573  if( !GetNext() && !GetPrev() )
2574  nRet = SwNeighbourAdjust::GrowAdjust; // section with a single column (FootnoteAtEnd)
2575  else
2576  {
2577  const SwFrame* pTmp = Lower();
2578  OSL_ENSURE( pTmp, "NeighbourhoodAdjustment: Missing Lower()" );
2579  if( !pTmp->GetNext() )
2581  else if( !GetUpper()->IsColLocked() )
2583  OSL_ENSURE( !pTmp->GetNext() || pTmp->GetNext()->IsFootnoteContFrame(),
2584  "NeighbourhoodAdjustment: Who's that guy?" );
2585  }
2586  }
2587  }
2588  return nRet;
2589 }
2590 
2592 {
2593  SwLayoutFrame *pBody = FindBodyCont();
2594  if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrame() )
2595  {
2596  SwColumnFrame* pCol = static_cast<SwColumnFrame*>(pBody->Lower());
2597  do
2598  {
2600  pCol = static_cast<SwColumnFrame*>(pCol->GetNext());
2601  } while ( pCol );
2602  }
2603 }
2604 
2606  SwFootnoteBossFrame *pNewBoss, const bool bFootnoteNums )
2607 {
2608  SwDoc *pDoc = GetFormat()->GetDoc();
2609  if ( pDoc->GetFootnoteIdxs().empty() )
2610  return false;
2611  if( pDoc->GetFootnoteInfo().ePos == FTNPOS_CHAPTER &&
2612  ( !IsInSct() || !FindSctFrame()->IsFootnoteAtEnd() ) )
2613  return true;
2614 
2615  if ( !pNewBoss )
2616  pNewBoss = FindFootnoteBossFrame( true );
2617  if ( pNewBoss == pOldBoss )
2618  return false;
2619 
2620  bool bMoved = false;
2621  if( !pStart )
2622  pStart = ContainsContent();
2623 
2624  SwFootnoteFrames aFootnoteArr;
2625 
2626  while ( IsAnLower( pStart ) )
2627  {
2628  if ( static_cast<SwTextFrame*>(pStart)->HasFootnote() )
2629  {
2630  // OD 03.04.2003 #108446# - To avoid unnecessary moves of footnotes
2631  // use new parameter <_bCollectOnlyPreviousFootnote> (4th parameter of
2632  // method <SwFootnoteBossFrame::CollectFootnote(..)>) to control, that only
2633  // footnotes have to be collected, that are positioned before the
2634  // new dedicated footnote boss frame.
2635  pNewBoss->CollectFootnotes( pStart, pOldBoss, aFootnoteArr, true );
2636  }
2637  pStart = pStart->GetNextContentFrame();
2638  }
2639 
2640  OSL_ENSURE( pOldBoss->IsInSct() == pNewBoss->IsInSct(),
2641  "MoveLowerFootnotes: Section confusion" );
2642  std::unique_ptr<SwFootnoteFrames> pFootnoteArr;
2643  SwLayoutFrame* pNewChief = nullptr;
2644  SwLayoutFrame* pOldChief = nullptr;
2645 
2646  bool bFoundCandidate = false;
2647  if (pStart && pOldBoss->IsInSct())
2648  {
2649  pOldChief = pOldBoss->FindSctFrame();
2650  pNewChief = pNewBoss->FindSctFrame();
2651  bFoundCandidate = pOldChief != pNewChief;
2652  }
2653 
2654  if (bFoundCandidate)
2655  {
2656  pFootnoteArr.reset(new SwFootnoteFrames);
2657  pOldChief = pOldBoss->FindFootnoteBossFrame( true );
2658  pNewChief = pNewBoss->FindFootnoteBossFrame( true );
2659  while( pOldChief->IsAnLower( pStart ) )
2660  {
2661  if ( static_cast<SwTextFrame*>(pStart)->HasFootnote() )
2662  static_cast<SwFootnoteBossFrame*>(pNewChief)->CollectFootnotes( pStart,
2663  pOldBoss, *pFootnoteArr );
2664  pStart = pStart->GetNextContentFrame();
2665  }
2666  if( pFootnoteArr->empty() )
2667  {
2668  pFootnoteArr.reset();
2669  }
2670  }
2671  else
2672  pFootnoteArr = nullptr;
2673 
2674  if ( !aFootnoteArr.empty() || pFootnoteArr )
2675  {
2676  if( !aFootnoteArr.empty() )
2677  pNewBoss->MoveFootnotes_( aFootnoteArr, true );
2678  if( pFootnoteArr )
2679  {
2680  static_cast<SwFootnoteBossFrame*>(pNewChief)->MoveFootnotes_( *pFootnoteArr, true );
2681  pFootnoteArr.reset();
2682  }
2683  bMoved = true;
2684 
2685  // update FootnoteNum only at page change
2686  if ( bFootnoteNums )
2687  {
2688  SwPageFrame* pOldPage = pOldBoss->FindPageFrame();
2689  SwPageFrame* pNewPage =pNewBoss->FindPageFrame();
2690  if( pOldPage != pNewPage )
2691  {
2692  pOldPage->UpdateFootnoteNum();
2693  pNewPage->UpdateFootnoteNum();
2694  }
2695  }
2696  }
2697  return bMoved;
2698 }
2699 
2701 {
2702  OSL_ENSURE( IsInFootnote(), "no footnote." );
2703  SwLayoutFrame *pFootnote = FindFootnoteFrame();
2704 
2705  // The first paragraph in the first footnote in the first column in the
2706  // sectionfrm at the top of the page has not to move forward, if the
2707  // columnbody is empty.
2708  if( pOldBoss->IsInSct() && !pOldBoss->GetIndPrev() && !GetIndPrev() &&
2709  !pFootnote->GetPrev() )
2710  {
2711  SwLayoutFrame* pBody = pOldBoss->FindBodyCont();
2712  if( !pBody || !pBody->Lower() )
2713  return true;
2714  }
2715 
2716  //fix(9538): if the footnote has neighbors behind itself, remove them temporarily
2717  SwLayoutFrame *pNxt = static_cast<SwLayoutFrame*>(pFootnote->GetNext());
2718  SwLayoutFrame *pLst = nullptr;
2719  while ( pNxt )
2720  {
2721  while ( pNxt->GetNext() )
2722  pNxt = static_cast<SwLayoutFrame*>(pNxt->GetNext());
2723  if ( pNxt == pLst )
2724  pNxt = nullptr;
2725  else
2726  { pLst = pNxt;
2727  SwContentFrame *pCnt = pNxt->ContainsContent();
2728  if( pCnt )
2729  pCnt->MoveFootnoteCntFwd( true, pOldBoss );
2730  pNxt = static_cast<SwLayoutFrame*>(pFootnote->GetNext());
2731  }
2732  }
2733 
2734  bool bSamePage = true;
2735  SwLayoutFrame *pNewUpper =
2736  GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, true );
2737 
2738  if ( pNewUpper )
2739  {
2740  SwFootnoteBossFrame * const pNewBoss = pNewUpper->FindFootnoteBossFrame();
2741  // Are we changing the column/page?
2742  bool bSameBoss = pNewBoss == pOldBoss;
2743  if ( !bSameBoss )
2744  {
2745  bSamePage = pOldBoss->FindPageFrame() == pNewBoss->FindPageFrame(); // page change?
2746  pNewUpper->Calc(getRootFrame()->GetCurrShell()->GetOut());
2747  }
2748 
2749  // The layout leaf of the footnote is either a footnote container or a footnote.
2750  // If it is a footnote and it has the same footnote reference like the old Upper,
2751  // then move the content inside of it.
2752  // If it is a container or the reference differs, create a new footnote and add
2753  // it into the container.
2754  // Create also a SectionFrame if currently in a area inside a footnote.
2755  SwFootnoteFrame* pTmpFootnote = pNewUpper->IsFootnoteFrame() ? static_cast<SwFootnoteFrame*>(pNewUpper) : nullptr;
2756  if( !pTmpFootnote )
2757  {
2758  OSL_ENSURE( pNewUpper->IsFootnoteContFrame(), "New Upper not a FootnoteCont.");
2759  SwFootnoteContFrame *pCont = static_cast<SwFootnoteContFrame*>(pNewUpper);
2760 
2761  // create footnote
2763  pTmpFootnote = new SwFootnoteFrame( pOld->GetFormat()->GetDoc()->GetDfltFrameFormat(),
2764  pOld, pOld->GetRef(), pOld->GetAttr() );
2765  // chaining of footnotes
2766  if ( pOld->GetFollow() )
2767  {
2768  pTmpFootnote->SetFollow( pOld->GetFollow() );
2769  pOld->GetFollow()->SetMaster( pTmpFootnote );
2770  }
2771  pOld->SetFollow( pTmpFootnote );
2772  pTmpFootnote->SetMaster( pOld );
2773  SwFrame* pNx = pCont->Lower();
2774  if( pNx && pTmpFootnote->GetAttr()->GetFootnote().IsEndNote() )
2775  while(pNx && !static_cast<SwFootnoteFrame*>(pNx)->GetAttr()->GetFootnote().IsEndNote())
2776  pNx = pNx->GetNext();
2777  pTmpFootnote->Paste( pCont, pNx );
2778  pTmpFootnote->Calc(getRootFrame()->GetCurrShell()->GetOut());
2779  }
2780  OSL_ENSURE( pTmpFootnote->GetAttr() == FindFootnoteFrame()->GetAttr(), "Wrong Footnote!" );
2781  // areas inside of footnotes get a special treatment
2782  SwLayoutFrame *pNewUp = pTmpFootnote;
2783  if( IsInSct() )
2784  {
2785  SwSectionFrame* pSect = FindSctFrame();
2786  // area inside of a footnote (or only footnote in an area)?
2787  if( pSect->IsInFootnote() )
2788  {
2789  if( pTmpFootnote->Lower() && pTmpFootnote->Lower()->IsSctFrame() &&
2790  pSect->GetFollow() == static_cast<SwSectionFrame*>(pTmpFootnote->Lower()) )
2791  pNewUp = static_cast<SwSectionFrame*>(pTmpFootnote->Lower());
2792  else
2793  {
2794  pNewUp = new SwSectionFrame( *pSect, false );
2795  pNewUp->InsertBefore( pTmpFootnote, pTmpFootnote->Lower() );
2796  static_cast<SwSectionFrame*>(pNewUp)->Init();
2797 
2798  {
2800  aFrm.Pos() = pTmpFootnote->getFrameArea().Pos();
2801  aFrm.Pos().AdjustY(1 ); // for notifications
2802  }
2803 
2804  // If the section frame has a successor then the latter needs
2805  // to be moved behind the new Follow of the section frame.
2806  SwFrame* pTmp = pSect->GetNext();
2807  if( pTmp )
2808  {
2809  SwFlowFrame* pTmpNxt;
2810  if( pTmp->IsContentFrame() )
2811  pTmpNxt = static_cast<SwContentFrame*>(pTmp);
2812  else if( pTmp->IsSctFrame() )
2813  pTmpNxt = static_cast<SwSectionFrame*>(pTmp);
2814  else
2815  {
2816  OSL_ENSURE( pTmp->IsTabFrame(), "GetNextSctLeaf: Wrong Type" );
2817  pTmpNxt = static_cast<SwTabFrame*>(pTmp);
2818  }
2819  pTmpNxt->MoveSubTree( pTmpFootnote, pNewUp->GetNext() );
2820  }
2821  }
2822  }
2823  }
2824 
2825  MoveSubTree( pNewUp, pNewUp->Lower() );
2826 
2827  if( !bSameBoss )
2829  }
2830  return bSamePage;
2831 }
2832 
2834  pBoss( pBs ),
2835  nOldHeight( pBs->GetMaxFootnoteHeight() )
2836 {
2837  pBoss->SetFootnoteDeadLine( nDeadLine );
2839 }
2840 
2842 {
2843  // If somebody tweaked the deadline meanwhile, we let it happen
2846 }
2847 
2848 #ifdef DBG_UTIL
2849 //JP 15.10.2001: in a non pro version test if the attribute has the same
2850 // meaning which his reference is
2851 
2852 // Normally, the pRef member and the GetRefFromAttr() result has to be
2853 // identically. Sometimes footnote will be moved from a master to its follow,
2854 // but the GetRef() is called first, so we have to ignore a master/follow
2855 // mismatch.
2856 
2858 {
2859  const SwContentFrame* pRefAttr = GetRefFromAttr();
2860  // check consistency: access to deleted frame?
2861  assert(mpReference == pRefAttr || mpReference->IsAnFollow(pRefAttr)
2862  || pRefAttr->IsAnFollow(mpReference));
2863  (void) pRefAttr;
2864  return mpReference;
2865 }
2866 
2868 {
2869  const SwContentFrame* pRefAttr = GetRefFromAttr();
2870  // check consistency: access to deleted frame?
2871  assert(mpReference == pRefAttr || mpReference->IsAnFollow(pRefAttr)
2872  || pRefAttr->IsAnFollow(mpReference));
2873  (void) pRefAttr;
2874  return mpReference;
2875 }
2876 #endif
2877 
2879 {
2880  SwFootnoteFrame* pThis = const_cast<SwFootnoteFrame*>(this);
2881  return pThis->GetRefFromAttr();
2882 }
2883 
2885 {
2886  assert(mpAttribute && "invalid Attribute");
2887  SwTextNode& rTNd = const_cast<SwTextNode&>(mpAttribute->GetTextNode());
2888  SwPosition aPos( rTNd, SwIndex( &rTNd, mpAttribute->GetStart() ));
2889  SwContentFrame* pCFrame = rTNd.getLayoutFrame(getRootFrame(), &aPos);
2890  return pCFrame;
2891 }
2892 
2898 {
2899  SwContentFrame* pLastContentFrame( nullptr );
2900 
2901  // find last lower, which is a content frame or contains content.
2902  // hidden text frames, empty sections and empty tables have to be skipped.
2903  SwFrame* pLastLowerOfFootnote( GetLower() );
2904  SwFrame* pTmpLastLower( pLastLowerOfFootnote );
2905  while ( pTmpLastLower && pTmpLastLower->GetNext() )
2906  {
2907  pTmpLastLower = pTmpLastLower->GetNext();
2908  if ( ( pTmpLastLower->IsTextFrame() &&
2909  !static_cast<SwTextFrame*>(pTmpLastLower)->IsHiddenNow() ) ||
2910  ( pTmpLastLower->IsSctFrame() &&
2911  static_cast<SwSectionFrame*>(pTmpLastLower)->GetSection() &&
2912  static_cast<SwSectionFrame*>(pTmpLastLower)->ContainsContent() ) ||
2913  ( pTmpLastLower->IsTabFrame() &&
2914  static_cast<SwTabFrame*>(pTmpLastLower)->ContainsContent() ) )
2915  {
2916  pLastLowerOfFootnote = pTmpLastLower;
2917  }
2918  }
2919 
2920  // determine last content frame depending on type of found last lower.
2921  if ( pLastLowerOfFootnote && pLastLowerOfFootnote->IsTabFrame() )
2922  {
2923  pLastContentFrame = static_cast<SwTabFrame*>(pLastLowerOfFootnote)->FindLastContent();
2924  }
2925  else if ( pLastLowerOfFootnote && pLastLowerOfFootnote->IsSctFrame() )
2926  {
2927  pLastContentFrame = static_cast<SwSectionFrame*>(pLastLowerOfFootnote)->FindLastContent();
2928  }
2929  else
2930  {
2931  pLastContentFrame = dynamic_cast<SwContentFrame*>(pLastLowerOfFootnote);
2932  }
2933 
2934  return pLastContentFrame;
2935 }
2936 
2937 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void InsertBefore(SwLayoutFrame *pParent, SwFrame *pBehind)
Insert SwFrame into existing structure.
Definition: wsfrm.cxx:820
void SetFollow(SwFootnoteFrame *pNew)
Definition: ftnfrm.hxx:110
bool IsAnLower(const SwFrame *) const
Definition: findfrm.cxx:206
SwSectionFrame * FindMaster() const
Definition: flowfrm.cxx:694
SwSaveFootnoteHeight(SwFootnoteBossFrame *pBs, const SwTwips nDeadLine)
Definition: ftnfrm.cxx:2833
bool IsBackMoveLocked()
Definition: ftnfrm.hxx:118
Base class of the Writer layout elements.
Definition: frame.hxx:295
Base class that provides the general functionalities for frames that are allowed at page breaks (flow...
Definition: flowfrm.hxx:58
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:149
SwFootnoteContFrame * FindNearestFootnoteCont(bool bDontLeave=false)
Search the next available footnote container.
Definition: ftnfrm.cxx:987
long BottomDist(const SwRect &rRect, long nPos) const
Definition: frame.hxx:1375
void ColLock()
Definition: ftnfrm.hxx:121
bool IsFollow() const
Definition: flowfrm.hxx:166
Marks a position in the document model.
Definition: pam.hxx:35
bool IsEndnAtEnd() const
Definition: sectfrm.hxx:148
SwContentFrame * GetNextContentFrame() const
Definition: cntfrm.hxx:98
bool IsInDocBody() const
Definition: frame.hxx:919
void Init()
SwTwips Grow(SwTwips, bool bTst=false, bool bInfo=false)
Definition: wsfrm.cxx:1462
bool IsInSct() const
Definition: frame.hxx:943
void RemoveFootnotes(SwPageFrame *pPage=nullptr, bool bPageOnly=false, bool bEndNotes=false)
Remove all footnotes (but no references)
Definition: ftnfrm.cxx:900
static void SetMoveBwdJump(bool bNew)
Definition: flowfrm.hxx:155
bool MoveFootnoteCntFwd(bool, SwFootnoteBossFrame *)
Definition: ftnfrm.cxx:2700
virtual void Format(vcl::RenderContext *pRenderContext, const SwBorderAttrs *pAttrs=nullptr) override
"format" the frame (Fixsize is not set here).
Definition: ftnfrm.cxx:187
SwFootnoteFrame * ImplFindFootnoteFrame()
Definition: findfrm.cxx:504
static void CheckPageDescs(SwPageFrame *pStart, bool bNotifyFields=true, SwPageFrame **ppPrev=nullptr)
Check all pages (starting from the given one) if they use the right frame format. ...
Definition: pagechg.cxx:1004
bool IsColLocked() const
Definition: frame.hxx:862
bool IsBefore(const SwLayoutFrame *_pCheckRefLayFrame) const
method to check relative position of layout frame to a given layout frame.
Definition: findfrm.cxx:233
virtual void Paste(SwFrame *pParent, SwFrame *pSibling=nullptr) override
Definition: ftnfrm.cxx:550
static SwFootnoteFrame * FindFootnote(const SwContentFrame *, const SwTextFootnote *)
Definition: ftnfrm.cxx:1631
void SetCompletePaint() const
Definition: frame.hxx:970
void SetMaster(SwFootnoteFrame *pNew)
Definition: ftnfrm.hxx:111
bool IsInFootnote() const
Definition: frame.hxx:925
sal_uIntPtr sal_uLong
const SwRect & getFramePrintArea() const
Definition: frame.hxx:176
SwTwips GetBottomDist() const
Definition: pagedesc.hxx:67
virtual bool IsDeleteForbidden() const override
Definition: ftnfrm.cxx:478
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:30
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1150
#define ENDNOTE
Definition: ftnfrm.cxx:41
void InvalidateSize_()
Definition: frame.hxx:749
Definition: doc.hxx:185
static sal_uInt16 lcl_ColumnNum(const SwFrame *pBoss)
Definition: ftnfrm.cxx:121
void SetColMaxFootnoteHeight()
Adapt the max. footnote height in each single column.
Definition: ftnfrm.cxx:2591
void SetMaxFootnoteHeight(const SwTwips nNewMax)
Definition: ftnboss.hxx:74
TElementType * Next()
Definition: calbck.hxx:376
void UpdateFootnoteNum()
Definition: ftnfrm.cxx:2375
void Height(long nNew)
Definition: swrect.hxx:189
void InsertFootnote(SwFootnoteFrame *)
Definition: ftnfrm.cxx:1161
sal_uInt16 sal_Char sal_Char * pDesc
void InvalidatePos()
Definition: frame.hxx:1019
long GetBottom(const SwRect &rRect) const
Definition: frame.hxx:1339
const_iterator find(const Value &x) const
virtual void Paste(SwFrame *pParent, SwFrame *pSibling=nullptr) override
Definition: wsfrm.cxx:1296
long SwTwips
Definition: swtypes.hxx:49
static void ChangeFootnoteRef(const SwContentFrame *pOld, const SwTextFootnote *, SwContentFrame *pNew)
Definition: ftnfrm.cxx:1699
static void DestroyFrame(SwFrame *const pFrame)
this is the only way to delete a SwFrame instance
Definition: ssfrm.cxx:382
void Pos(const Point &rNew)
Definition: swrect.hxx:167
bool IsEndNote() const
Definition: fmtftn.hxx:73
SwTwips GetMaxFootnoteHeight() const
Definition: ftnboss.hxx:93
SwFrame * FindNext()
Definition: frame.hxx:1117
virtual void Calc(vcl::RenderContext *pRenderContext) const
Definition: trvlfrm.cxx:1787
virtual void Cut() override
Definition: ftnfrm.cxx:499
bool IsFootnotePage() const
Foot note interface.
Definition: pagefrm.hxx:185
void InvalidateNxtFootnoteCnts(SwPageFrame const *pPage)
Definition: ftnfrm.cxx:454
long GetPrtTop(const SwFrame &rFrame) const
Definition: frame.hxx:1370
void KeepLockPosOfLowerObjs()
Definition: ftnfrm.hxx:129
void RearrangeFootnotes(const SwTwips nDeadLine, const bool bLock, const SwTextFootnote *pAttr=nullptr)
Definition: ftnfrm.cxx:2163
static SwFlowFrame * CastFlowFrame(SwFrame *pFrame)
Definition: flowfrm.cxx:2601
SwFootnoteContFrame(SwFrameFormat *, SwFrame *)
Definition: ftnfrm.cxx:149
css::chart::ChartAxisLabelPosition ePos
bool IsFootnoteFrame() const
Definition: frame.hxx:1178
bool ToMaximize(bool bCheckFollow) const
A sectionfrm has to maximize, if he has a follow or a ftncontainer at the end of the page...
Definition: sectfrm.cxx:2729
bool isFrameAreaDefinitionValid() const
Definition: frame.hxx:167
SwTwips GetTopDist() const
Definition: pagedesc.hxx:66
sal_uInt16 GetPhyPageNum() const
Definition: pagefrm.hxx:190
SwSectionFrame * ImplFindSctFrame()
Definition: findfrm.cxx:480
long YDiff(long n1, long n2) const
Definition: frame.hxx:1384
void SetFootnoteDeadLine(const SwTwips nDeadLine)
Definition: ftnfrm.cxx:2453
void SetRetouche() const
Definition: frame.hxx:979
const SwPageFootnoteInfo & GetFootnoteInfo() const
Definition: pagedesc.hxx:195
bool IsFlyFrame() const
Definition: frame.hxx:1186
long TopDist(const SwRect &rRect, long nPos) const
Definition: frame.hxx:1374
long GetPrtBottom(const SwFrame &rFrame) const
Definition: frame.hxx:1371
void InsertCnt_(SwLayoutFrame *pLay, SwDoc *pDoc, sal_uLong nIndex, bool bPages=false, sal_uLong nEndIndex=0, SwFrame *pPrv=nullptr)
Definition: frmtool.cxx:1322
void sw_RemoveFootnotes(SwFootnoteBossFrame *pBoss, bool bPageOnly, bool bEndNotes)
remove all footnotes (not the references) and all footnote pages
Definition: ftnfrm.cxx:846
void MoveFootnotes_(SwFootnoteFrames &rFootnoteArr, bool bCalc=false)
Definition: ftnfrm.cxx:1917
const SwRect & getFrameArea() const
Definition: frame.hxx:175
SwFootnoteContFrame * FindFootnoteCont()
Definition: ftnfrm.cxx:964
bool getBrowseMode() const
Definition: viewopt.hxx:426
bool IsEmptyPage() const
Definition: pagefrm.hxx:143
SwTextFootnote * mpAttribute
Definition: ftnfrm.hxx:73
bool IsInTab() const
Definition: frame.hxx:931
bool IsTextFrame() const
Definition: frame.hxx:1210
sal_Int32 GetStart() const
Definition: txatbase.hxx:82
void SetSuperfluous()
Remove superfluous Pages.
Definition: rootfrm.hxx:296
void setFramePrintAreaValid(bool bNew)
Definition: wsfrm.cxx:96
bool OnRightPage() const
Definition: frame.hxx:711
virtual SwTwips ShrinkFrame(SwTwips, bool bTst=false, bool bInfo=false) override
Definition: ftnfrm.cxx:411
bool IsPageBodyFrame() const
Definition: layfrm.hxx:213
const OUString & GetNumStr() const
Definition: fmtftn.hxx:70
bool IsSctFrame() const
Definition: frame.hxx:1190
void AppendFootnote(SwContentFrame *, SwTextFootnote *)
Definition: ftnfrm.cxx:1414
SwNeighbourAdjust NeighbourhoodAdjustment_() const
Obtain if pFrame's size adjustment should be processed.
Definition: ftnfrm.cxx:2562
virtual bool Prepare(const PrepareHint ePrep=PREP_CLEAR, const void *pVoid=nullptr, bool bNotify=true) override
SwContentFrame: the shortcut for the Frames If the void* casts wrongly, it's its own fault! The void*...
Definition: txtfrm.cxx:2710
void UnlockPosOfLowerObjs()
Definition: ftnfrm.hxx:125
SwLayoutFrame * GetNextSctLeaf(MakePageType eMakePage)
Returns the next layout sheet where the frame can be moved in.
Definition: sectfrm.cxx:1564
bool IsDescendantFrom(const SwSectionFormat *pSect) const
Definition: sectfrm.cxx:2507
const SwAttrSet * GetAttrSet() const
WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for SwTextFrame, use GetBreakItem()/GetPageDescItem() instead.
Definition: findfrm.cxx:674
SwPageFrame * InsertNewPage(SwPageDesc &rDesc, SwFrame *pUpper, bool bOdd, bool bFirst, bool bInsertEmpty, bool bFootnote, SwFrame *pSibling)
Definition: frmtool.cxx:2807
virtual void Paste(SwFrame *pParent, SwFrame *pSibling=nullptr)=0
bool IsFootnoteLock() const
Definition: sectfrm.hxx:157
virtual void Cut()=0
bool IsColumnFrame() const
Definition: frame.hxx:1158
void SubTop(SwRect &rRect, long nNew) const
Definition: frame.hxx:1354
void SetHeight(SwRect &rRect, long nNew) const
Definition: frame.hxx:1352
void SetNumber(sal_uInt16 nNumber, sal_uInt16 nNumberRLHidden, const OUString &sNumStr)
Definition: atrftn.cxx:341
SwFootnoteFrame * FindFootnoteFrame()
Definition: frame.hxx:1083
SwTabFrame * ImplFindTabFrame()
Definition: findfrm.cxx:468
Style of a layout element.
Definition: frmfmt.hxx:57
void SetWidth(SwRect &rRect, long nNew) const
Definition: frame.hxx:1351
bool IsContentFrame() const
Definition: frame.hxx:1206
void SetTop(SwRect &rRect, long nNew) const
Definition: frame.hxx:1347
static void FootnoteInArr(SwFootnoteFrames &rFootnoteArr, SwFootnoteFrame *pFootnote)
Definition: ftnfrm.cxx:1766
SwFrame * GetIndPrev() const
Definition: frame.hxx:702
const SwFrame * GetLastLower() const
Definition: findfrm.cxx:1817
const SwSectionFrame * GetFollow() const
Definition: sectfrm.hxx:160
static long lcl_Undersize(const SwFrame *pFrame)
Definition: ftnfrm.cxx:159
SwPageFrame * FindPageFrame()
Definition: frame.hxx:658
virtual bool IsDeleteForbidden() const
Definition: frame.hxx:863
SwFrame * m_pLower
Definition: layfrm.hxx:52
virtual void Cut() override
Definition: wsfrm.cxx:1393
const SwFrame * Lower() const
Definition: layfrm.hxx:100
SwContentFrame * FindNextCnt(const bool _bInSameFootnote=false)
Definition: findfrm.cxx:190
TElementType * First()
Definition: calbck.hxx:345
SwPageDesc * GetPageDesc()
Definition: pagefrm.hxx:129
SwTwips AdjustNeighbourhood(SwTwips nDiff, bool bTst=false)
Adjust surrounding neighbourhood after insertion.
Definition: wsfrm.cxx:1568
SwContentNode * GetContentNode()
Definition: node.hxx:615
void InvalidatePage(const SwPageFrame *pPage=nullptr) const
Invalidates the page in which the Frame is currently placed.
Definition: wsfrm.cxx:597
void AddHeight(SwRect &rRect, long nNew) const
Definition: frame.hxx:1359
SwLayoutFrame * GetUpper()
Definition: frame.hxx:656
sal_uInt16 GetNumberRLHidden() const
Definition: fmtftn.hxx:72
bool isFramePrintAreaValid() const
Definition: frame.hxx:164
SwFootnoteFrame * FindFirstFootnote()
Definition: ftnfrm.cxx:1010
Marks a character position inside a document model node.
Definition: index.hxx:37
bool IsEndNotePage() const
Definition: pagefrm.hxx:186
static sal_uLong lcl_FindFootnotePos(const SwDoc *pDoc, const SwTextFootnote *pAttr)
Search the position of an attribute in the FootnoteArray at the document, because all footnotes are l...
Definition: ftnfrm.cxx:45
long const nBorder
SwFootnoteBossFrame * FindFootnoteBossFrame(bool bFootnotes=false)
Definition: findfrm.cxx:435
SwFrame * GetPrev()
Definition: frame.hxx:655
Marks a node in the document model.
Definition: ndindex.hxx:31
void UnlockBackMove()
Definition: ftnfrm.hxx:117
const_iterator end() const
bool empty() const
SwFootnoteBossFrame * pBoss
Definition: ftnboss.hxx:34
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:119
void SSize(const Size &rNew)
Definition: swrect.hxx:176
SwNeighbourAdjust NeighbourhoodAdjustment() const
Definition: ftnboss.hxx:121
bool isFrameAreaSizeValid() const
Definition: frame.hxx:163
void AddBottom(SwRect &rRect, long nNew) const
Definition: frame.hxx:1355
SwContentFrame * FindLastContent(SwFindMode nMode=SwFindMode::None)
Definition: sectfrm.cxx:905
void InvalidatePos_()
Definition: frame.hxx:765
SwFootnoteContFrame * MakeFootnoteCont()
Insert a footnote container.
Definition: ftnfrm.cxx:954
void UpdateFootnoteNums()
Update the footnote numbers of all Pages.
Definition: ftnfrm.cxx:831
A page of the document layout.
Definition: pagefrm.hxx:40
const SwFormatFootnote & GetFootnote() const
Definition: txatbase.hxx:200
void LockBackMove()
Definition: ftnfrm.hxx:116
static sal_uInt16 nPgNum
Definition: viewport.cxx:63
const long LONG_MAX
SwFootnoteFrame(SwFrameFormat *, SwFrame *, SwContentFrame *, SwTextFootnote *)
Definition: ftnfrm.cxx:441
SwTwips Shrink(SwTwips, bool bTst=false, bool bInfo=false)
Definition: wsfrm.cxx:1507
void InvalidateSize()
Definition: frame.hxx:1005
SwLayoutFrame * GetPrevFootnoteLeaf(MakePageType eMakeFootnote)
Get the preceding layout leaf in that the frame can be moved.
Definition: ftnfrm.cxx:695
SwSectionFrame * FindSctFrame()
Definition: frame.hxx:1091
SwLayoutFrame * FindBodyCont()
Searches the first ContentFrame in BodyText below the page.
Definition: findfrm.cxx:42
const SwFootnoteFrame * GetMaster() const
Definition: ftnfrm.hxx:104
SwFrame * FindColFrame()
Definition: findfrm.cxx:529
const SwFrameFormat * GetDfltFrameFormat() const
Definition: doc.hxx:741
const_iterator begin() const
bool RemoveFootnote(const SwContentFrame *, const SwTextFootnote *, bool bPrep=true)
Definition: ftnfrm.cxx:1671
void CollectFootnotes(const SwContentFrame *_pRef, SwFootnoteBossFrame *_pOld, SwFootnoteFrames &_rFootnoteArr, const bool _bCollectOnlyPreviousFootnotes=false)
OD 03.04.2003 #108446# - add parameter <_bCollectOnlyPreviousFootnotes> in order to control...
Definition: ftnfrm.cxx:1713
long GetWidth(const SwRect &rRect) const
Definition: frame.hxx:1342
static bool FormatObjsAtFrame(SwFrame &_rAnchorFrame, const SwPageFrame &_rPageFrame, SwLayAction *_pLayAction=nullptr)
method to format all floating screen objects at the given anchor frame
bool IsLayoutFrame() const
Definition: frame.hxx:1146
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
SwNeighbourAdjust
Definition: ftnboss.hxx:42
Footnote information.
Definition: pagedesc.hxx:47
bool Growable() const
checks whether the SectionFrame is still able to grow, as case may be the environment has to be asked...
Definition: sectfrm.cxx:2136
static void ResetFootnote(const SwFootnoteFrame *pAssumed)
Definition: ftnfrm.cxx:1121
void SetRef(SwContentFrame *pNew)
Definition: ftnfrm.hxx:112
bool IsVertLR() const
Definition: frame.hxx:955
void MoveSubTree(SwLayoutFrame *pParent, SwFrame *pSibling=nullptr)
hook tree onto new parent with minimal operations and notifications
Definition: flowfrm.cxx:574
SwTwips GetVarSpace() const
Definition: ftnfrm.cxx:2481
SwLayoutFrame * GetLeaf(MakePageType eMakePage, bool bFwd)
Definition: flowfrm.cxx:783
void CheckFootnotePageDescs(bool bEndNote)
Change the page template of the footnote pages.
Definition: ftnfrm.cxx:934
MakePageType
Definition: frame.hxx:110
SwPageDesc * GetPageDesc(SwDoc &rDoc) const
Definition: docftn.cxx:106
bool IsTabFrame() const
Definition: frame.hxx:1194
virtual SwTwips ShrinkFrame(SwTwips, bool bTst=false, bool bInfo=false) override
Definition: wsfrm.cxx:2747
#define SAL_WARN_IF(condition, area, stream)
SwTextFrame * FindMaster() const
Definition: flowfrm.cxx:678
sal_uInt16 GetPhyPageNum() const
Definition: trvlfrm.cxx:1688
bool MoveLowerFootnotes(SwContentFrame *pStart, SwFootnoteBossFrame *pOldBoss, SwFootnoteBossFrame *pNewBoss, const bool bFootnoteNums)
Moving the Footnotes of all Lowers - starting from StartContent.
Definition: ftnfrm.cxx:2605
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:426
const SwFrame * ContainsAny(const bool _bInvestigateFootnoteForSections=false) const
Method doesn't investigate content of footnotes by default.
Definition: findfrm.cxx:125
const SwSectionFormat * GetEndSectFormat() const
Definition: sectfrm.hxx:136
void RemoveFromLayout()
Definition: wsfrm.cxx:994
const SwFootnoteFrame * GetFollow() const
Definition: ftnfrm.hxx:101
const SwDoc * GetDoc() const
Definition: swatrset.hxx:204
SwTwips m_nMaxFootnoteHeight
Definition: ftnboss.hxx:56
void InvalidateNextPos(bool bNoFootnote=false)
Definition: frame.hxx:1048
sal_uLong GetLineWidth() const
Definition: pagedesc.hxx:61
bool IsColBodyFrame() const
These SwFrame inlines are here, so that frame.hxx does not need to include layfrm.hxx.
Definition: layfrm.hxx:208
static bool lcl_NextFootnoteBoss(SwFootnoteBossFrame *&rpBoss, SwPageFrame *&rpPage, bool bDontLeave)
Definition: ftnfrm.cxx:79
bool operator<(const SwTextFootnote *pTextFootnote) const
Definition: ftnfrm.cxx:62
void setFrameAreaSizeValid(bool bNew)
Definition: wsfrm.cxx:88
const SwContentFrame * GetRef() const
Definition: ftnfrm.cxx:2857
SwFrame * GetLower()
Definition: findfrm.cxx:169
SwFrameType mnFrameType
Definition: frame.hxx:395
bool IsPageFrame() const
Definition: frame.hxx:1154
bool IsFootnoteAllowed() const
Definition: ftnfrm.cxx:815
const SwTextFootnote * GetAttr() const
Definition: ftnfrm.hxx:107
SwContentFrame * mpReference
Definition: ftnfrm.hxx:72
void MoveFootnotes(const SwContentFrame *pSrc, SwContentFrame *pDest, SwTextFootnote const *pAttr)
Definition: ftnfrm.cxx:2125
virtual void Cut() override
Definition: sectfrm.cxx:249
long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1343
bool IsHideRedlines() const
Replacement for sw::DocumentRedlineManager::GetRedlineFlags() (this is layout-level redline hiding)...
Definition: rootfrm.hxx:416
bool IsAnFollow(const SwFlowFrame *pFlow) const
Definition: flowfrm.cxx:667
const SfxPoolItem & GetAttr() const
Definition: txatbase.hxx:159
const SwContentFrame * GetRefFromAttr() const
Definition: ftnfrm.cxx:2878
SwLayoutFrame * GetNextFootnoteLeaf(MakePageType eMakePage)
Return the next layout leaf in that the frame can be moved.
Definition: ftnfrm.cxx:613
bool IsVertical() const
Definition: frame.hxx:949
#define BROWSE_HEIGHT
Definition: frmtool.hxx:52
long GetTop(const SwRect &rRect) const
Definition: frame.hxx:1338
void InvalidatePrt_()
Definition: frame.hxx:757
static void CollectFootnotes_(const SwContentFrame *_pRef, SwFootnoteFrame *_pFootnote, SwFootnoteFrames &_rFootnoteArr, const bool _bCollectOnlyPreviousFootnotes=false, const SwFootnoteBossFrame *_pRefFootnoteBossFrame=nullptr)
OD 03.04.2003 #108446# - add parameters <_bCollectOnlyPreviousFootnotes> and <_pRefFootnoteBossFrame>...
Definition: ftnfrm.cxx:1778
SwNodeIndex * GetStartNode() const
Definition: txtftn.hxx:41
SwFootnoteIdxs & GetFootnoteIdxs()
Definition: doc.hxx:628
SwFootnotePos ePos
Definition: ftninfo.hxx:96
bool IsFootnoteAtEnd() const
Definition: sectfrm.hxx:147
void RegistFlys(SwPageFrame *, const SwLayoutFrame *)
Definition: frmtool.cxx:2908
bool IsFootnoteBossFrame() const
Definition: frame.hxx:1162
void ColUnlock()
Definition: ftnfrm.hxx:122
SwPageFrame * InsertPage(SwPageFrame *pSibling, bool bFootnote)
Definition: pagechg.cxx:1289
bool IsFootnoteContFrame() const
Definition: frame.hxx:1174
virtual bool Prepare(const PrepareHint ePrep=PREP_CLEAR, const void *pVoid=nullptr, bool bNotify=true)
Definition: wsfrm.cxx:587
std::vector< SwFootnoteFrame * > SwFootnoteFrames
Definition: ftnboss.hxx:46
const SwContentFrame * ContainsContent() const
Checks if the frame contains one or more ContentFrame's anywhere in his subsidiary structure; if so t...
Definition: findfrm.cxx:66
void SetEndNotePage(bool b)
Definition: pagefrm.hxx:188
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:204
sal_uInt16 GetNumber() const
Definition: fmtftn.hxx:71
const SwTextNode & GetTextNode() const
Definition: txtftn.hxx:69
const SwTwips nOldHeight
Definition: ftnboss.hxx:35
const SwFootnoteInfo & GetFootnoteInfo() const
Definition: doc.hxx:624
SwRootFrame * getRootFrame()
Definition: frame.hxx:657
const SwEndNoteInfo & GetEndNoteInfo() const
Definition: doc.hxx:626
std::vector< SwTextFootnote * >::const_iterator const_iterator
virtual SwTwips GrowFrame(SwTwips, bool bTst=false, bool bInfo=false) override
Definition: ftnfrm.cxx:277
bool IsInHeadline(const SwFrame &rFrame) const
Definition: tabfrm.cxx:5319
virtual const SwFrameFormat * GetFormat() const
Definition: ssfrm.cxx:393
SwFrame * GetNext()
Definition: frame.hxx:654
SwContentFrame * FindLastContent()
search for last content in the current footnote frame
Definition: ftnfrm.cxx:2897
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo