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