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.
323  assert(GetUpper() && GetUpper()->IsFootnoteBossFrame());
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.SSize().AdjustHeight( -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  if( bEndn && pFootnote->IsInSct() )
754  {
755  SwSectionFrame* pSect = pFootnote->FindSctFrame();
756  if( pSect->IsEndnAtEnd() )
757  pTmpRef = pSect->FindLastContent( SwFindMode::LastCnt );
758  }
759  if( !pTmpRef )
760  pTmpRef = pFootnote->GetRef();
761  SwFootnoteBossFrame* pStop = pTmpRef->FindFootnoteBossFrame( !bEndn );
762 
763  const sal_uInt16 nNum = pStop->GetPhyPageNum();
764 
765  // Do not leave the corresponding page if the footnote should
766  // be shown at the document ending or the footnote is an endnote.
767  const bool bEndNote = pOldPage->IsEndNotePage();
768  const bool bFootnoteEndDoc = pOldPage->IsFootnotePage();
769  SwFootnoteBossFrame* pNxtBoss = pOldBoss;
770  SwSectionFrame *pSect = pNxtBoss->GetUpper()->IsSctFrame() ?
771  static_cast<SwSectionFrame*>(pNxtBoss->GetUpper()) : nullptr;
772 
773  do
774  {
775  if( pNxtBoss->IsColumnFrame() && pNxtBoss->GetPrev() )
776  pNxtBoss = static_cast<SwFootnoteBossFrame*>(pNxtBoss->GetPrev()); // one column backwards
777  else // one page backwards
778  {
779  SwLayoutFrame* pBody = nullptr;
780  if( pSect )
781  {
782  if( pSect->IsFootnoteLock() )
783  {
784  if( pNxtBoss == pOldBoss )
785  return nullptr;
786  pStop = pNxtBoss;
787  }
788  else
789  {
790  pSect = pSect->FindMaster();
791  if( !pSect || !pSect->Lower() )
792  return nullptr;
793  OSL_ENSURE( pSect->Lower()->IsColumnFrame(),
794  "GetPrevFootnoteLeaf: Where's the column?" );
795  pNxtBoss = static_cast<SwFootnoteBossFrame*>(pSect->Lower());
796  pBody = pSect;
797  }
798  }
799  else
800  {
801  SwPageFrame* pPage = static_cast<SwPageFrame*>(pNxtBoss->FindPageFrame()->GetPrev());
802  if( !pPage || pPage->GetPhyPageNum() < nNum ||
803  bEndNote != pPage->IsEndNotePage() || bFootnoteEndDoc != pPage->IsFootnotePage() )
804  return nullptr; // no further pages found
805  pNxtBoss = pPage;
806  pBody = pPage->FindBodyCont();
807  }
808  // We have the previous page, we might need to find the last column of it
809  if( pBody )
810  {
811  if ( pBody->Lower() && pBody->Lower()->IsColumnFrame() )
812  {
813  pNxtBoss = static_cast<SwFootnoteBossFrame*>(pBody->GetLastLower());
814  }
815  }
816  }
817  SwFootnoteContFrame *pCont = pNxtBoss->FindFootnoteCont();
818  if ( pCont )
819  {
820  pRet = pCont;
821  break;
822  }
823  if ( pStop == pNxtBoss )
824  {
825  // Reached the column/page of the reference.
826  // Try to add a container and paste our content.
827  if ( eMakeFootnote == MAKEPAGE_FTN && pNxtBoss->GetMaxFootnoteHeight() )
828  pRet = pNxtBoss->MakeFootnoteCont();
829  break;
830  }
831  } while( !pRet );
832  }
833  if ( pRet )
834  {
835  const SwFootnoteBossFrame* pNewBoss = pRet->FindFootnoteBossFrame();
836  bool bJump = false;
837  if( pOldBoss->IsColumnFrame() && pOldBoss->GetPrev() ) // a previous column exists
838  bJump = pOldBoss->GetPrev() != static_cast<SwFrame const *>(pNewBoss); // did we chose it?
839  else if( pNewBoss->IsColumnFrame() && pNewBoss->GetNext() )
840  bJump = true; // there is another column after the boss (not the old boss)
841  else
842  {
843  // Will be reached only if old and new boss are both either pages or the last (new)
844  // or first (old) column of a page. In this case, check if pages were skipped.
845  const sal_uInt16 nDiff = pOldPage->GetPhyPageNum() - pRet->FindPageFrame()->GetPhyPageNum();
846  if ( nDiff > 2 ||
847  (nDiff > 1 && !static_cast<SwPageFrame*>(pOldPage->GetPrev())->IsEmptyPage()) )
848  bJump = true;
849  }
850  if( bJump )
852  }
853  return pRet;
854 }
855 
857 {
858  if ( !IsInDocBody() )
859  return false;
860 
861  if ( IsInTab() )
862  {
863  // no footnotes in repeated headlines
864  const SwTabFrame *pTab = const_cast<SwFrame*>(this)->ImplFindTabFrame();
865  assert(pTab);
866  if ( pTab->IsFollow() )
867  return !pTab->IsInHeadline( *this );
868  }
869  return true;
870 }
871 
873 {
874  // page numbering only if set at the document
875  if ( GetFormat()->GetDoc()->GetFootnoteInfo().m_eNum == FTNNUM_PAGE )
876  {
877  SwPageFrame *pPage = static_cast<SwPageFrame*>(Lower());
878  while ( pPage && !pPage->IsFootnotePage() )
879  {
880  pPage->UpdateFootnoteNum();
881  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
882  }
883  }
884 }
885 
887 void sw_RemoveFootnotes( SwFootnoteBossFrame* pBoss, bool bPageOnly, bool bEndNotes )
888 {
889  do
890  {
891  SwFootnoteContFrame *pCont = pBoss->FindFootnoteCont();
892  if ( pCont )
893  {
894  SwFootnoteFrame *pFootnote = static_cast<SwFootnoteFrame*>(pCont->Lower());
895  assert(pFootnote);
896  if ( bPageOnly )
897  while ( pFootnote->GetMaster() )
898  pFootnote = pFootnote->GetMaster();
899  do
900  {
901  SwFootnoteFrame *pNxt = static_cast<SwFootnoteFrame*>(pFootnote->GetNext());
902  if ( !pFootnote->GetAttr()->GetFootnote().IsEndNote() ||
903  bEndNotes )
904  {
905  pFootnote->GetRef()->Prepare( PrepareHint::FootnoteInvalidation, static_cast<void*>(pFootnote->GetAttr()) );
906  if ( bPageOnly && !pNxt )
907  pNxt = pFootnote->GetFollow();
908  pFootnote->Cut();
909  SwFrame::DestroyFrame(pFootnote);
910  }
911  pFootnote = pNxt;
912 
913  } while ( pFootnote );
914  }
915  if( !pBoss->IsInSct() )
916  {
917  // A sectionframe with the Footnote/EndnAtEnd-flags may contain
918  // foot/endnotes. If the last lower frame of the bodyframe is
919  // a multicolumned sectionframe, it may contain footnotes, too.
920  SwLayoutFrame* pBody = pBoss->FindBodyCont();
921  if( pBody && pBody->Lower() )
922  {
923  SwFrame* pLow = pBody->Lower();
924  while (pLow)
925  {
926  if( pLow->IsSctFrame() && ( !pLow->GetNext() ||
927  static_cast<SwSectionFrame*>(pLow)->IsAnyNoteAtEnd() ) &&
928  static_cast<SwSectionFrame*>(pLow)->Lower() &&
929  static_cast<SwSectionFrame*>(pLow)->Lower()->IsColumnFrame() )
930  sw_RemoveFootnotes( static_cast<SwColumnFrame*>(static_cast<SwSectionFrame*>(pLow)->Lower()),
931  bPageOnly, bEndNotes );
932  pLow = pLow->GetNext();
933  }
934  }
935  }
936  // is there another column?
937  pBoss = pBoss->IsColumnFrame() ? static_cast<SwColumnFrame*>(pBoss->GetNext()) : nullptr;
938  } while( pBoss );
939 }
940 
941 void SwRootFrame::RemoveFootnotes( SwPageFrame *pPage, bool bPageOnly, bool bEndNotes )
942 {
943  if ( !pPage )
944  pPage = static_cast<SwPageFrame*>(Lower());
945 
946  do
947  { // On columned pages we have to clean up in all columns
948  SwFootnoteBossFrame* pBoss;
949  SwLayoutFrame* pBody = pPage->FindBodyCont();
950  if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrame() )
951  pBoss = static_cast<SwFootnoteBossFrame*>(pBody->Lower()); // the first column
952  else
953  pBoss = pPage; // no columns
954  sw_RemoveFootnotes( pBoss, bPageOnly, bEndNotes );
955  if ( !bPageOnly )
956  {
957  if ( pPage->IsFootnotePage() &&
958  (!pPage->IsEndNotePage() || bEndNotes) )
959  {
960  SwFrame *pDel = pPage;
961  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
962  pDel->Cut();
963  SwFrame::DestroyFrame(pDel);
964  }
965  else
966  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
967  }
968  else
969  break;
970 
971  } while ( pPage );
972 }
973 
976 {
977  SwPageFrame *pPage = static_cast<SwPageFrame*>(Lower());
978  while ( pPage && !pPage->IsFootnotePage() )
979  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
980  while ( pPage && pPage->IsEndNotePage() != bEndNote )
981  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
982 
983  if ( pPage )
984  SwFrame::CheckPageDescs( pPage, false );
985 }
986 
996 {
997  SAL_WARN_IF(FindFootnoteCont(), "sw.core", "footnote container exists already");
998 
999  SwFootnoteContFrame *pNew = new SwFootnoteContFrame( GetFormat()->GetDoc()->GetDfltFrameFormat(), this );
1000  SwLayoutFrame *pLay = FindBodyCont();
1001  pNew->Paste( this, pLay->GetNext() );
1002  return pNew;
1003 }
1004 
1006 {
1007  SwFrame *pFrame = Lower();
1008  while( pFrame && !pFrame->IsFootnoteContFrame() )
1009  pFrame = pFrame->GetNext();
1010 
1011 #if OSL_DEBUG_LEVEL > 0
1012  if ( pFrame )
1013  {
1014  SwFrame *pFootnote = pFrame->GetLower();
1015  assert(pFootnote);
1016  while ( pFootnote )
1017  {
1018  assert(pFootnote->IsFootnoteFrame() && "Neighbor of footnote must be a footnote");
1019  pFootnote = pFootnote->GetNext();
1020  }
1021  }
1022 #endif
1023 
1024  return static_cast<SwFootnoteContFrame*>(pFrame);
1025 }
1026 
1029 {
1030  SwFootnoteContFrame *pCont = nullptr;
1031  if ( !GetFormat()->GetDoc()->GetFootnoteIdxs().empty() )
1032  {
1033  pCont = FindFootnoteCont();
1034  if ( !pCont )
1035  {
1036  SwPageFrame *pPage = FindPageFrame();
1037  SwFootnoteBossFrame* pBoss = this;
1038  bool bEndNote = pPage->IsEndNotePage();
1039  do
1040  {
1041  bool bChgPage = lcl_NextFootnoteBoss( pBoss, pPage, bDontLeave );
1042  // Found another boss? When changing pages, also the endnote flag must match.
1043  if( pBoss && ( !bChgPage || pPage->IsEndNotePage() == bEndNote ) )
1044  pCont = pBoss->FindFootnoteCont();
1045  } while ( !pCont && pPage );
1046  }
1047  }
1048  return pCont;
1049 }
1050 
1052 {
1053  // search for the nearest footnote container
1055  if ( !pCont )
1056  return nullptr;
1057 
1058  // Starting from the first footnote, search the first
1059  // footnote that is referenced by the current column/page
1060 
1061  SwFootnoteFrame *pRet = static_cast<SwFootnoteFrame*>(pCont->Lower());
1062  const sal_uInt16 nRefNum = FindPageFrame()->GetPhyPageNum();
1063  const sal_uInt16 nRefCol = lcl_ColumnNum( this );
1064  sal_uInt16 nPgNum, nColNum; // page number, column number
1065  SwFootnoteBossFrame* pBoss;
1066  SwPageFrame* pPage;
1067  if( pRet )
1068  {
1069  pBoss = pRet->GetRef()->FindFootnoteBossFrame();
1070  OSL_ENSURE( pBoss, "FindFirstFootnote: No boss found" );
1071  if( !pBoss )
1072  return nullptr; // ?There must be a bug, but no GPF
1073  pPage = pBoss->FindPageFrame();
1074  nPgNum = pPage->GetPhyPageNum();
1075  if ( nPgNum == nRefNum )
1076  {
1077  nColNum = lcl_ColumnNum( pBoss );
1078  if( nColNum == nRefCol )
1079  return pRet; // found
1080  else if( nColNum > nRefCol )
1081  return nullptr; // at least one column too far
1082  }
1083  else if ( nPgNum > nRefNum )
1084  return nullptr; // at least one column too far
1085  }
1086  else
1087  return nullptr;
1088  // Done if Ref is on a subsequent page or on the same page in a subsequent column
1089 
1090  do
1091  {
1092  while ( pRet->GetFollow() )
1093  pRet = pRet->GetFollow();
1094 
1095  SwFootnoteFrame *pNxt = static_cast<SwFootnoteFrame*>(pRet->GetNext());
1096  if ( !pNxt )
1097  {
1098  pBoss = pRet->FindFootnoteBossFrame();
1099  pPage = pBoss->FindPageFrame();
1100  lcl_NextFootnoteBoss( pBoss, pPage, false ); // next FootnoteBoss
1101  pCont = pBoss ? pBoss->FindNearestFootnoteCont() : nullptr;
1102  if ( pCont )
1103  pNxt = static_cast<SwFootnoteFrame*>(pCont->Lower());
1104  }
1105  if ( pNxt )
1106  {
1107  pRet = pNxt;
1108  pBoss = pRet->GetRef()->FindFootnoteBossFrame();
1109  pPage = pBoss->FindPageFrame();
1110  nPgNum = pPage->GetPhyPageNum();
1111  if ( nPgNum == nRefNum )
1112  {
1113  nColNum = lcl_ColumnNum( pBoss );
1114  if( nColNum == nRefCol )
1115  break; // found
1116  else if( nColNum > nRefCol )
1117  pRet = nullptr; // at least one column too far
1118  }
1119  else if ( nPgNum > nRefNum )
1120  pRet = nullptr; // at least a page too far
1121  }
1122  else
1123  pRet = nullptr; // there is none
1124  } while( pRet );
1125  return pRet;
1126 }
1127 
1130 {
1131  const SwFootnoteFrame *pRet = const_cast<SwFootnoteBossFrame*>(this)->FindFirstFootnote();
1132  if ( pRet )
1133  {
1134  const sal_uInt16 nColNum = lcl_ColumnNum( this );
1135  const sal_uInt16 nPageNum = GetPhyPageNum();
1136  while ( pRet && (pRet->GetRef() != pCnt) )
1137  {
1138  while ( pRet->GetFollow() )
1139  pRet = pRet->GetFollow();
1140 
1141  if ( pRet->GetNext() )
1142  pRet = static_cast<const SwFootnoteFrame*>(pRet->GetNext());
1143  else
1144  { SwFootnoteBossFrame *pBoss = const_cast<SwFootnoteBossFrame*>(pRet->FindFootnoteBossFrame());
1145  SwPageFrame *pPage = pBoss->FindPageFrame();
1146  lcl_NextFootnoteBoss( pBoss, pPage, false ); // next FootnoteBoss
1147  SwFootnoteContFrame *pCont = pBoss ? pBoss->FindNearestFootnoteCont() : nullptr;
1148  pRet = pCont ? static_cast<SwFootnoteFrame*>(pCont->Lower()) : nullptr;
1149  }
1150  if ( pRet )
1151  {
1152  const SwFootnoteBossFrame* pBoss = pRet->GetRef()->FindFootnoteBossFrame();
1153  if( pBoss->GetPhyPageNum() != nPageNum ||
1154  nColNum != lcl_ColumnNum( pBoss ) )
1155  pRet = nullptr;
1156  }
1157  }
1158  }
1159  return pRet;
1160 }
1161 
1163 {
1164  // Destroy the incarnations of footnotes to an attribute, if they don't
1165  // belong to pAssumed
1166  OSL_ENSURE( !pCheck->GetMaster(), "given master is not a Master." );
1167 
1168  SwNodeIndex aIdx( *pCheck->GetAttr()->GetStartNode(), 1 );
1169  SwContentNode *pNd = aIdx.GetNode().GetContentNode();
1170  if ( !pNd )
1171  pNd = pCheck->GetFormat()->GetDoc()->
1172  GetNodes().GoNextSection( &aIdx, true, false );
1174  SwFrame* pFrame = aIter.First();
1175  while( pFrame )
1176  {
1177  if( pFrame->getRootFrame() == pCheck->getRootFrame() )
1178  {
1179  SwFrame *pTmp = pFrame->GetUpper();
1180  while ( pTmp && !pTmp->IsFootnoteFrame() )
1181  pTmp = pTmp->GetUpper();
1182 
1183  SwFootnoteFrame *pFootnote = static_cast<SwFootnoteFrame*>(pTmp);
1184  while ( pFootnote && pFootnote->GetMaster() )
1185  pFootnote = pFootnote->GetMaster();
1186  if ( pFootnote != pCheck )
1187  {
1188  while (pFootnote && !pFootnote->IsDeleteForbidden())
1189  {
1190  SwFootnoteFrame *pNxt = pFootnote->GetFollow();
1191  pFootnote->Cut();
1192  SwFrame::DestroyFrame(pFootnote);
1193  pFootnote = pNxt;
1194  }
1195  }
1196  }
1197 
1198  pFrame = aIter.Next();
1199  }
1200 }
1201 
1203 {
1204  // Place the footnote in front of the footnote whose attribute
1205  // is in front of the new one (get position via the Doc).
1206  // If there is no footnote in this footnote-boss yet, create a new container.
1207  // If there is a container but no footnote for this footnote-boss yet, place
1208  // the footnote behind the last footnote of the closest previous column/page.
1209 
1210  ResetFootnote( pNew );
1211  SwFootnoteFrame *pSibling = FindFirstFootnote();
1212  bool bDontLeave = false;
1213 
1214  // Ok, a sibling has been found, but is the sibling in an acceptable
1215  // environment?
1216  if( IsInSct() )
1217  {
1218  SwSectionFrame* pMySect = ImplFindSctFrame();
1219  bool bEndnt = pNew->GetAttr()->GetFootnote().IsEndNote();
1220  if( bEndnt )
1221  {
1222  const SwSectionFormat* pEndFormat = pMySect->GetEndSectFormat();
1223  bDontLeave = nullptr != pEndFormat;
1224  if( pSibling )
1225  {
1226  if( pEndFormat )
1227  {
1228  if( !pSibling->IsInSct() ||
1229  !pSibling->ImplFindSctFrame()->IsDescendantFrom( pEndFormat ) )
1230  pSibling = nullptr;
1231  }
1232  else if( pSibling->IsInSct() )
1233  pSibling = nullptr;
1234  }
1235  }
1236  else
1237  {
1238  bDontLeave = pMySect->IsFootnoteAtEnd();
1239  if( pSibling )
1240  {
1241  if( pMySect->IsFootnoteAtEnd() )
1242  {
1243  if( !pSibling->IsInSct() ||
1244  !pMySect->IsAnFollow( pSibling->ImplFindSctFrame() ) )
1245  pSibling = nullptr;
1246  }
1247  else if( pSibling->IsInSct() )
1248  pSibling = nullptr;
1249  }
1250  }
1251  }
1252 
1253  if( pSibling && pSibling->FindPageFrame()->IsEndNotePage() !=
1255  pSibling = nullptr;
1256 
1257  // use the Doc to find out the position
1258  SwDoc *pDoc = GetFormat()->GetDoc();
1259  const sal_uLong nStPos = ::lcl_FindFootnotePos( pDoc, pNew->GetAttr() );
1260 
1261  sal_uLong nCmpPos = 0;
1262  sal_uLong nLastPos = 0;
1263  SwFootnoteContFrame *pParent = nullptr;
1264  if( pSibling )
1265  {
1266  nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1267  if( nCmpPos > nStPos )
1268  pSibling = nullptr;
1269  }
1270 
1271  if ( !pSibling )
1272  { pParent = FindFootnoteCont();
1273  if ( !pParent )
1274  {
1275  // There is no footnote container yet. Before creating one, keep in mind that
1276  // there might exist another following footnote that must be placed before the
1277  // new inserted one e.g. because it was divided over multiple pages etc.
1278  pParent = FindNearestFootnoteCont( bDontLeave );
1279  if ( pParent )
1280  {
1281  SwFootnoteFrame *pFootnote = static_cast<SwFootnoteFrame*>(pParent->Lower());
1282  if ( pFootnote )
1283  {
1284 
1285  nCmpPos = ::lcl_FindFootnotePos( pDoc, pFootnote->GetAttr() );
1286  if ( nCmpPos > nStPos )
1287  pParent = nullptr;
1288  }
1289  else
1290  pParent = nullptr;
1291  }
1292  }
1293  if ( !pParent )
1294  // here, we are sure that we can create a footnote container
1295  pParent = MakeFootnoteCont();
1296  else
1297  {
1298  // Based on the first footnote below the Parent, search for the first footnote whose
1299  // index is after the index of the newly inserted, to place the new one correctly
1300  pSibling = static_cast<SwFootnoteFrame*>(pParent->Lower());
1301  if ( !pSibling )
1302  {
1303  OSL_ENSURE( false, "Could not find space for footnote.");
1304  return;
1305  }
1306  nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1307 
1308  SwFootnoteBossFrame *pNxtB; // remember the last one to not
1309  SwFootnoteFrame *pLastSib = nullptr; // go too far.
1310 
1311  while ( pSibling && nCmpPos <= nStPos )
1312  {
1313  pLastSib = pSibling; // potential candidate
1314  nLastPos = nCmpPos;
1315 
1316  while ( pSibling->GetFollow() )
1317  pSibling = pSibling->GetFollow();
1318 
1319  if ( pSibling->GetNext() )
1320  {
1321  pSibling = static_cast<SwFootnoteFrame*>(pSibling->GetNext());
1322  OSL_ENSURE( !pSibling->GetMaster() || ( ENDNOTE > nStPos &&
1323  pSibling->GetAttr()->GetFootnote().IsEndNote() ),
1324  "InsertFootnote: Master expected I" );
1325  }
1326  else
1327  {
1328  pNxtB = pSibling->FindFootnoteBossFrame();
1329  SwPageFrame *pSibPage = pNxtB->FindPageFrame();
1330  bool bEndNote = pSibPage->IsEndNotePage();
1331  bool bChgPage = lcl_NextFootnoteBoss( pNxtB, pSibPage, bDontLeave );
1332  // When changing pages, also the endnote flag must match.
1333  SwFootnoteContFrame *pCont = pNxtB && ( !bChgPage ||
1334  pSibPage->IsEndNotePage() == bEndNote )
1335  ? pNxtB->FindNearestFootnoteCont( bDontLeave ) : nullptr;
1336  if( pCont )
1337  pSibling = static_cast<SwFootnoteFrame*>(pCont->Lower());
1338  else // no further FootnoteContainer, insert after pSibling
1339  break;
1340  }
1341  if ( pSibling )
1342  {
1343  nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1344  OSL_ENSURE( nCmpPos > nLastPos, "InsertFootnote: Order of FootnoteFrame's buggy" );
1345  }
1346  }
1347  // pLastSib is the last footnote before the new one and
1348  // pSibling is empty or the first one after the new one
1349  if ( pSibling && pLastSib && (pSibling != pLastSib) )
1350  {
1351  // too far?
1352  if ( nCmpPos > nStPos )
1353  pSibling = pLastSib;
1354  }
1355  else if ( !pSibling )
1356  {
1357  // Last chance: Take the last footnote of the parent.
1358  // Special case that happens e.g. when moving paragraphs with multiple footnotes.
1359  // To keep the order, use the parent of the last inspected footnote.
1360  pSibling = pLastSib;
1361  while( pSibling->GetFollow() )
1362  pSibling = pSibling->GetFollow();
1363  OSL_ENSURE( !pSibling->GetNext(), "InsertFootnote: Who's that guy?" );
1364  }
1365  }
1366  }
1367  else
1368  {
1369  // First footnote of the column/page found. Now search from there for the first one on the
1370  // same column/page whose index is after the given one. The last one found is the predecessor.
1372  !pNew->GetAttr()->GetFootnote().IsEndNote() );
1373  sal_uInt16 nRefNum = pBoss->GetPhyPageNum(); // page number of the new footnote
1374  sal_uInt16 nRefCol = lcl_ColumnNum( pBoss ); // column number of the new footnote
1375  bool bEnd = false;
1376  SwFootnoteFrame *pLastSib = nullptr;
1377  while ( pSibling && !bEnd && (nCmpPos <= nStPos) )
1378  {
1379  pLastSib = pSibling;
1380  nLastPos = nCmpPos;
1381 
1382  while ( pSibling->GetFollow() )
1383  pSibling = pSibling->GetFollow();
1384 
1385  SwFootnoteFrame *pFoll = static_cast<SwFootnoteFrame*>(pSibling->GetNext());
1386  if ( pFoll )
1387  {
1388  pBoss = pSibling->GetRef()->FindFootnoteBossFrame( !pSibling->
1389  GetAttr()->GetFootnote().IsEndNote() );
1390  sal_uInt16 nTmpRef;
1391  if( nStPos >= ENDNOTE ||
1392  (nTmpRef = pBoss->GetPhyPageNum()) < nRefNum ||
1393  ( nTmpRef == nRefNum && lcl_ColumnNum( pBoss ) <= nRefCol ))
1394  pSibling = pFoll;
1395  else
1396  bEnd = true;
1397  }
1398  else
1399  {
1400  SwFootnoteBossFrame* pNxtB = pSibling->FindFootnoteBossFrame();
1401  SwPageFrame *pSibPage = pNxtB->FindPageFrame();
1402  bool bEndNote = pSibPage->IsEndNotePage();
1403  bool bChgPage = lcl_NextFootnoteBoss( pNxtB, pSibPage, bDontLeave );
1404  // When changing pages, also the endnote flag must match.
1405  SwFootnoteContFrame *pCont = pNxtB && ( !bChgPage ||
1406  pSibPage->IsEndNotePage() == bEndNote )
1407  ? pNxtB->FindNearestFootnoteCont( bDontLeave ) : nullptr;
1408  if ( pCont )
1409  pSibling = static_cast<SwFootnoteFrame*>(pCont->Lower());
1410  else
1411  bEnd = true;
1412  }
1413  if ( !bEnd && pSibling )
1414  nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1415  if (pSibling && (pSibling != pLastSib))
1416  {
1417  // too far?
1418  if ( (nLastPos < nCmpPos) && (nCmpPos > nStPos) )
1419  {
1420  pSibling = pLastSib;
1421  bEnd = true;
1422  }
1423  }
1424  }
1425  }
1426  if ( pSibling )
1427  {
1428  nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1429  if ( nCmpPos < nStPos )
1430  {
1431  while ( pSibling->GetFollow() )
1432  pSibling = pSibling->GetFollow();
1433  pParent = static_cast<SwFootnoteContFrame*>(pSibling->GetUpper());
1434  pSibling = static_cast<SwFootnoteFrame*>(pSibling->GetNext());
1435  }
1436  else
1437  {
1438  if( pSibling->GetMaster() )
1439  {
1440  if( ENDNOTE > nCmpPos || nStPos >= ENDNOTE )
1441  {
1442  OSL_FAIL( "InsertFootnote: Master expected II" );
1443  do
1444  pSibling = pSibling->GetMaster();
1445  while ( pSibling->GetMaster() );
1446  }
1447  }
1448  pParent = static_cast<SwFootnoteContFrame*>(pSibling->GetUpper());
1449  }
1450  }
1451  OSL_ENSURE( pParent, "paste in space?" );
1452  pNew->Paste( pParent, pSibling );
1453 }
1454 
1455 static SwPageFrame* lcl_GetApproximateFootnotePage(const bool bEnd, const SwPageFrame* pPage,
1456  const SwDoc *pDoc, const SwTextFootnote *pAttr)
1457 {
1458  // We can at least search the approximately correct page
1459  // to ensure that we will finish in finite time even if
1460  // hundreds of footnotes exist.
1461  const SwPageFrame *pNxt = static_cast<const SwPageFrame*>(pPage->GetNext());
1462  const sal_uLong nStPos = ::lcl_FindFootnotePos(pDoc, pAttr);
1463  while (pNxt && (bEnd ? pNxt->IsEndNotePage() : pNxt->IsFootnotePage() && !pNxt->IsEndNotePage()))
1464  {
1465  const SwFootnoteContFrame *pCont = pNxt->FindFootnoteCont();
1466  if (pCont && pCont->Lower())
1467  {
1468  OSL_ENSURE( pCont->Lower()->IsFootnoteFrame(), "no footnote in the container" );
1469  if (nStPos > ::lcl_FindFootnotePos(pDoc,
1470  static_cast<const SwFootnoteFrame*>(pCont->Lower())->GetAttr()))
1471  {
1472  pPage = pNxt;
1473  pNxt = static_cast<const SwPageFrame*>(pPage->GetNext());
1474  continue;
1475  }
1476  }
1477  break;
1478  }
1479  return const_cast<SwPageFrame*>(pPage);
1480 }
1481 
1483 {
1484  // If the footnote already exists, do nothing.
1485  if ( FindFootnote( pRef, pAttr ) )
1486  return;
1487 
1488  // If footnotes are inserted at the end of the document,
1489  // we only need to search from the relevant page on.
1490  // If there is none yet, we need to create one.
1491  // If it is an Endnote, we need to search for or create an
1492  // Endnote page.
1493  SwDoc *pDoc = GetFormat()->GetDoc();
1494  SwFootnoteBossFrame *pBoss = this;
1495  SwPageFrame *pPage = FindPageFrame();
1496  SwPageFrame *pMyPage = pPage;
1497  bool bChgPage = false;
1498  const bool bEnd = pAttr->GetFootnote().IsEndNote();
1499  if (bEnd)
1500  {
1501  const IDocumentSettingAccess& rSettings = *pAttr->GetTextNode().getIDocumentSettingAccess();
1502  if( GetUpper()->IsSctFrame() &&
1503  static_cast<SwSectionFrame*>(GetUpper())->IsEndnAtEnd() )
1504  {
1505  // Endnotes at the end of the section.
1506  SwFrame* pLast =
1507  static_cast<SwSectionFrame*>(GetUpper())->FindLastContent( SwFindMode::EndNote );
1508  if( pLast )
1509  {
1510  pBoss = pLast->FindFootnoteBossFrame();
1511  pPage = pBoss->FindPageFrame();
1512  }
1513  }
1514  else if (rSettings.get(DocumentSettingId::CONTINUOUS_ENDNOTES))
1515  {
1516  // Endnotes at the end of the document.
1517  pBoss = getRootFrame()->GetLastPage();
1518  pPage = pBoss->FindPageFrame();
1519  }
1520  else
1521  {
1522  // Endnotes on a separate page.
1523  while ( pPage->GetNext() && !pPage->IsEndNotePage() )
1524  {
1525  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
1526  bChgPage = true;
1527  }
1528  if ( !pPage->IsEndNotePage() )
1529  {
1530  SwPageDesc *pDesc = pDoc->GetEndNoteInfo().GetPageDesc( *pDoc );
1531  pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(),
1532  !pPage->OnRightPage(), false, false, true, nullptr );
1533  pPage->SetEndNotePage( true );
1534  bChgPage = true;
1535  }
1536  else
1537  pPage = lcl_GetApproximateFootnotePage(true, pPage, pDoc, pAttr);
1538  }
1539  }
1540  else if( FTNPOS_CHAPTER == pDoc->GetFootnoteInfo().m_ePos && ( !GetUpper()->
1541  IsSctFrame() || !static_cast<SwSectionFrame*>(GetUpper())->IsFootnoteAtEnd() ) )
1542  {
1543  while ( pPage->GetNext() && !pPage->IsFootnotePage() &&
1544  !static_cast<SwPageFrame*>(pPage->GetNext())->IsEndNotePage() )
1545  {
1546  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
1547  bChgPage = true;
1548  }
1549 
1550  if ( !pPage->IsFootnotePage() )
1551  {
1552  SwPageDesc *pDesc = pDoc->GetFootnoteInfo().GetPageDesc( *pDoc );
1553  pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(),
1554  !pPage->OnRightPage(), false, false, true, pPage->GetNext() );
1555  bChgPage = true;
1556  }
1557  else
1558  pPage = lcl_GetApproximateFootnotePage(false, pPage, pDoc, pAttr);
1559  }
1560 
1561  // For now, create a footnote and the corresponding content frames
1562  if ( !pAttr->GetStartNode() )
1563  {
1564  OSL_ENSURE( false, "no footnote content." );
1565  return;
1566  }
1567 
1568  // If there is already a footnote content on the column/page,
1569  // another one cannot be created in a column area.
1570  if( pBoss->IsInSct() && pBoss->IsColumnFrame() && !pPage->IsFootnotePage() )
1571  {
1572  SwSectionFrame* pSct = pBoss->FindSctFrame();
1573  if( bEnd ? !pSct->IsEndnAtEnd() : !pSct->IsFootnoteAtEnd() )
1574  {
1575  SwFootnoteContFrame* pFootnoteCont = pSct->FindFootnoteBossFrame(!bEnd)->FindFootnoteCont();
1576  if( pFootnoteCont )
1577  {
1578  SwFootnoteFrame* pTmp = static_cast<SwFootnoteFrame*>(pFootnoteCont->Lower());
1579  if( bEnd )
1580  while( pTmp && !pTmp->GetAttr()->GetFootnote().IsEndNote() )
1581  pTmp = static_cast<SwFootnoteFrame*>(pTmp->GetNext());
1582  if( pTmp && *pTmp < pAttr )
1583  return;
1584  }
1585  }
1586  }
1587 
1588  SwFootnoteFrame *pNew = new SwFootnoteFrame( pDoc->GetDfltFrameFormat(), this, pRef, pAttr );
1589  {
1590  SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
1591  ::InsertCnt_( pNew, pDoc, aIdx.GetIndex() );
1592  }
1593  // If the page was changed or newly created,
1594  // we need to place ourselves in the first column
1595  if( bChgPage )
1596  {
1597  SwLayoutFrame* pBody = pPage->FindBodyCont();
1598  OSL_ENSURE( pBody, "AppendFootnote: NoPageBody?" );
1599  if( pBody->Lower() && pBody->Lower()->IsColumnFrame() )
1600  pBoss = static_cast<SwFootnoteBossFrame*>(pBody->Lower());
1601  else
1602  pBoss = pPage; // page if no columns exist
1603  }
1604  pBoss->InsertFootnote( pNew );
1605  if ( pNew->GetUpper() ) // inserted or not?
1606  {
1607  ::RegistFlys( pNew->FindPageFrame(), pNew );
1608  SwSectionFrame* pSect = FindSctFrame();
1609  // The content of a FootnoteContainer in a (column) section only need to be calculated
1610  // if the section stretches already to the bottom edge of the Upper.
1611  if( pSect && !pSect->IsJoinLocked() && ( bEnd ? !pSect->IsEndnAtEnd() :
1612  !pSect->IsFootnoteAtEnd() ) && pSect->Growable() )
1613  pSect->InvalidateSize();
1614  else
1615  {
1616  // #i49383# - disable unlock of position of
1617  // lower objects during format of footnote content.
1618  const bool bOldFootnoteFrameLocked( pNew->IsColLocked() );
1619  pNew->ColLock();
1620  pNew->KeepLockPosOfLowerObjs();
1621  // #i57914# - adjust fix #i49383#
1622  SwContentFrame *pCnt = pNew->ContainsContent();
1623  while ( pCnt && pCnt->FindFootnoteFrame()->GetAttr() == pAttr )
1624  {
1625  pCnt->Calc(getRootFrame()->GetCurrShell()->GetOut());
1626  // #i49383# - format anchored objects
1627  if ( pCnt->IsTextFrame() && pCnt->isFrameAreaDefinitionValid() )
1628  {
1630  *(pCnt->FindPageFrame()) ) )
1631  {
1632  // restart format with first content
1633  pCnt = pNew->ContainsContent();
1634  continue;
1635  }
1636  }
1637  pCnt = pCnt->FindNextCnt();
1638  }
1639  // #i49383#
1640  if ( !bOldFootnoteFrameLocked )
1641  {
1642  pNew->ColUnlock();
1643  }
1644  // #i57914# - adjust fix #i49383#
1645  // enable lock of lower object position before format of footnote frame.
1646  pNew->UnlockPosOfLowerObjs();
1647  pNew->Calc(getRootFrame()->GetCurrShell()->GetOut());
1648  // #i57914# - adjust fix #i49383#
1649  if ( !bOldFootnoteFrameLocked && !pNew->GetLower() &&
1650  !pNew->IsColLocked() && !pNew->IsBackMoveLocked() &&
1651  !pNew->IsDeleteForbidden() )
1652  {
1653  pNew->Cut();
1654  SwFrame::DestroyFrame(pNew);
1655  }
1656  }
1657  pMyPage->UpdateFootnoteNum();
1658  }
1659  else
1660  SwFrame::DestroyFrame(pNew);
1661 }
1662 
1664 {
1665  // the easiest and savest way goes via the attribute
1666  OSL_ENSURE( pAttr->GetStartNode(), "FootnoteAtr without StartNode." );
1667  SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
1668  SwContentNode *pNd = aIdx.GetNode().GetContentNode();
1669  if ( !pNd )
1670  pNd = pRef->GetAttrSet()->GetDoc()->
1671  GetNodes().GoNextSection( &aIdx, true, false );
1672  if ( !pNd )
1673  return nullptr;
1675  SwFrame* pFrame = aIter.First();
1676  if( pFrame )
1677  do
1678  {
1679  pFrame = pFrame->GetUpper();
1680  // #i28500#, #i27243# Due to the endnode collector, there are
1681  // SwFootnoteFrames, which are not in the layout. Therefore the
1682  // bInfFootnote flags are not set correctly, and a cell of FindFootnoteFrame
1683  // would return 0. Therefore we better call ImplFindFootnoteFrame().
1684  SwFootnoteFrame *pFootnote = pFrame->ImplFindFootnoteFrame();
1685  if ( pFootnote && pFootnote->GetRef() == pRef )
1686  {
1687  // The following condition becomes true, if the whole
1688  // footnotecontent is a section. While no frames exist,
1689  // the HiddenFlag of the section is set, this causes
1690  // the GoNextSection-function leaves the footnote.
1691  if( pFootnote->GetAttr() != pAttr )
1692  return nullptr;
1693  while ( pFootnote && pFootnote->GetMaster() )
1694  pFootnote = pFootnote->GetMaster();
1695  return pFootnote;
1696  }
1697 
1698  } while ( nullptr != (pFrame = aIter.Next()) );
1699 
1700  return nullptr;
1701 }
1702 
1704  const SwContentFrame *const pRef, const SwTextFootnote *const pAttr,
1705  bool bPrep )
1706 {
1707  bool ret(false);
1708  SwFootnoteFrame *pFootnote = FindFootnote( pRef, pAttr );
1709  if( pFootnote )
1710  {
1711  ret = true;
1712  do
1713  {
1714  SwFootnoteFrame *pFoll = pFootnote->GetFollow();
1715  pFootnote->Cut();
1716  SwFrame::DestroyFrame(pFootnote);
1717  pFootnote = pFoll;
1718  } while ( pFootnote );
1719  if( bPrep && pRef->IsFollow() )
1720  {
1721  OSL_ENSURE( pRef->IsTextFrame(), "NoTextFrame has Footnote?" );
1722  SwTextFrame* pMaster = pRef->FindMaster();
1723  if( !pMaster->IsLocked() )
1725  }
1726  }
1728  return ret;
1729 }
1730 
1732  SwContentFrame *pNew )
1733 {
1734  SwFootnoteFrame *pFootnote = FindFootnote( pOld, pAttr );
1735  while ( pFootnote )
1736  {
1737  pFootnote->SetRef( pNew );
1738  pFootnote = pFootnote->GetFollow();
1739  }
1740 }
1741 
1746  SwFootnoteBossFrame* _pOld,
1747  SwFootnoteFrames& _rFootnoteArr,
1748  const bool _bCollectOnlyPreviousFootnotes )
1749 {
1750  SwFootnoteFrame *pFootnote = _pOld->FindFirstFootnote();
1751  while( !pFootnote )
1752  {
1753  if( _pOld->IsColumnFrame() )
1754  {
1755  // visit columns
1756  while ( !pFootnote && _pOld->GetPrev() )
1757  {
1758  // Still no problem if no footnote was found yet. The loop is needed to pick up
1759  // following rows in tables. In all other cases it might correct bad contexts.
1760  _pOld = static_cast<SwFootnoteBossFrame*>(_pOld->GetPrev());
1761  pFootnote = _pOld->FindFirstFootnote();
1762  }
1763  }
1764  if( !pFootnote )
1765  {
1766  // previous page
1767  SwPageFrame* pPg;
1768  for ( SwFrame* pTmp = _pOld;
1769  nullptr != ( pPg = static_cast<SwPageFrame*>(pTmp->FindPageFrame()->GetPrev()))
1770  && pPg->IsEmptyPage() ;
1771  )
1772  {
1773  pTmp = pPg;
1774  }
1775  if( !pPg )
1776  return;
1777 
1778  SwLayoutFrame* pBody = pPg->FindBodyCont();
1779  if( pBody->Lower() && pBody->Lower()->IsColumnFrame() )
1780  {
1781  // multiple columns on one page => search last column
1782  _pOld = static_cast<SwFootnoteBossFrame*>(pBody->GetLastLower());
1783  }
1784  else
1785  _pOld = pPg; // single column page
1786  pFootnote = _pOld->FindFirstFootnote();
1787  }
1788  }
1789 
1790  CollectFootnotes_(_pRef, pFootnote, _rFootnoteArr, _bCollectOnlyPreviousFootnotes ? this : nullptr);
1791 }
1792 
1793 static void FootnoteInArr( SwFootnoteFrames& rFootnoteArr, SwFootnoteFrame* pFootnote )
1794 {
1795  if ( rFootnoteArr.end() == std::find( rFootnoteArr.begin(), rFootnoteArr.end(), pFootnote ) )
1796  rFootnoteArr.push_back( pFootnote );
1797 }
1798 
1800  SwFootnoteFrame* _pFootnote,
1801  SwFootnoteFrames& _rFootnoteArr,
1802  const SwFootnoteBossFrame* _pRefFootnoteBossFrame)
1803 {
1804  // Collect all footnotes referenced by pRef (attribute by attribute), combine them
1805  // (the content might be divided over multiple pages) and cut them.
1806 
1807  // For robustness, we do not log the corresponding footnotes here. If a footnote
1808  // is touched twice, there might be a crash. This allows this function here to
1809  // also handle corrupt layouts in some degrees (without loops or even crashes).
1810  SwFootnoteFrames aNotFootnoteArr;
1811 
1812  // here we have a footnote placed in front of the first one of the reference
1813  OSL_ENSURE( !_pFootnote->GetMaster() || _pFootnote->GetRef() != _pRef, "move FollowFootnote?" );
1814  while ( _pFootnote->GetMaster() )
1815  _pFootnote = _pFootnote->GetMaster();
1816 
1817  bool bFound = false;
1818 
1819  do
1820  {
1821  // Search for the next footnote in this column/page so that
1822  // we do not start from zero again after cutting one footnote.
1823  SwFootnoteFrame *pNxtFootnote = _pFootnote;
1824  while ( pNxtFootnote->GetFollow() )
1825  pNxtFootnote = pNxtFootnote->GetFollow();
1826  pNxtFootnote = static_cast<SwFootnoteFrame*>(pNxtFootnote->GetNext());
1827 
1828  if ( !pNxtFootnote )
1829  {
1830  SwFootnoteBossFrame* pBoss = _pFootnote->FindFootnoteBossFrame();
1831  SwPageFrame* pPage = pBoss->FindPageFrame();
1832  do
1833  {
1834  lcl_NextFootnoteBoss( pBoss, pPage, false );
1835  if( pBoss )
1836  {
1837  SwLayoutFrame* pCont = pBoss->FindFootnoteCont();
1838  if( pCont )
1839  {
1840  pNxtFootnote = static_cast<SwFootnoteFrame*>(pCont->Lower());
1841  if( pNxtFootnote )
1842  {
1843  while( pNxtFootnote->GetMaster() )
1844  pNxtFootnote = pNxtFootnote->GetMaster();
1845  if( pNxtFootnote == _pFootnote )
1846  pNxtFootnote = nullptr;
1847  }
1848  }
1849  }
1850  } while( !pNxtFootnote && pBoss );
1851  }
1852  else if( !pNxtFootnote->GetAttr()->GetFootnote().IsEndNote() )
1853  {
1854  OSL_ENSURE( !pNxtFootnote->GetMaster(), "_CollectFootnote: Master expected" );
1855  while ( pNxtFootnote->GetMaster() )
1856  pNxtFootnote = pNxtFootnote->GetMaster();
1857  }
1858  if ( pNxtFootnote == _pFootnote )
1859  {
1860  OSL_FAIL( "_CollectFootnote: Vicious circle" );
1861  pNxtFootnote = nullptr;
1862  }
1863 
1864  // OD 03.04.2003 #108446# - determine, if found footnote has to be collected.
1865  bool bCollectFoundFootnote = false;
1866  // Ignore endnotes which are on a separate endnote page.
1867  bool bEndNote = _pFootnote->GetAttr()->GetFootnote().IsEndNote();
1868  const IDocumentSettingAccess& rSettings
1869  = _pFootnote->GetAttrSet()->GetDoc()->getIDocumentSettingAccess();
1870  bool bContinuousEndnotes = rSettings.get(DocumentSettingId::CONTINUOUS_ENDNOTES);
1871  if (_pFootnote->GetRef() == _pRef && (!bEndNote || bContinuousEndnotes))
1872  {
1873  if (_pRefFootnoteBossFrame)
1874  {
1875  SwFootnoteBossFrame* pBossOfFoundFootnote = _pFootnote->FindFootnoteBossFrame( true );
1876  OSL_ENSURE( pBossOfFoundFootnote,
1877  "<SwFootnoteBossFrame::CollectFootnotes_(..)> - footnote boss frame of found footnote frame missing.\nWrong layout!" );
1878  if ( !pBossOfFoundFootnote || // don't crash, if no footnote boss is found.
1879  pBossOfFoundFootnote->IsBefore( _pRefFootnoteBossFrame )
1880  )
1881  {
1882  bCollectFoundFootnote = true;
1883  }
1884  }
1885  else
1886  {
1887  bCollectFoundFootnote = true;
1888  }
1889  }
1890 
1891  if ( bCollectFoundFootnote )
1892  {
1893  OSL_ENSURE( !_pFootnote->GetMaster(), "move FollowFootnote?" );
1894  SwFootnoteFrame *pNxt = _pFootnote->GetFollow();
1895  while ( pNxt )
1896  {
1897  SwFrame *pCnt = pNxt->ContainsAny();
1898  if ( pCnt )
1899  {
1900  // destroy the follow on the way as it is empty
1901  do
1902  { SwFrame *pNxtCnt = pCnt->GetNext();
1903  pCnt->Cut();
1904  pCnt->Paste( _pFootnote );
1905  pCnt = pNxtCnt;
1906  } while ( pCnt );
1907  }
1908  else
1909  {
1910  OSL_ENSURE( !pNxt, "footnote without content?" );
1911  pNxt->Cut();
1912  SwFrame::DestroyFrame(pNxt);
1913  }
1914  pNxt = _pFootnote->GetFollow();
1915  }
1916  _pFootnote->Cut();
1917  FootnoteInArr( _rFootnoteArr, _pFootnote );
1918  bFound = true;
1919  }
1920  else
1921  {
1922  FootnoteInArr( aNotFootnoteArr, _pFootnote );
1923  if( bFound )
1924  break;
1925  }
1926  if ( pNxtFootnote &&
1927  _rFootnoteArr.end() == std::find( _rFootnoteArr.begin(), _rFootnoteArr.end(), pNxtFootnote ) &&
1928  aNotFootnoteArr.end() == std::find( aNotFootnoteArr.begin(), aNotFootnoteArr.end(), pNxtFootnote ) )
1929  _pFootnote = pNxtFootnote;
1930  else
1931  break;
1932  }
1933  while ( _pFootnote );
1934 }
1935 
1937 {
1938  // All footnotes referenced by pRef need to be moved
1939  // to a new position (based on the new column/page)
1940  const sal_uInt16 nMyNum = FindPageFrame()->GetPhyPageNum();
1941  const sal_uInt16 nMyCol = lcl_ColumnNum( this );
1942  SwRectFnSet aRectFnSet(this);
1943 
1944  // #i21478# - keep last inserted footnote in order to
1945  // format the content of the following one.
1946  SwFootnoteFrame* pLastInsertedFootnote = nullptr;
1947  for (SwFootnoteFrame* pFootnote : rFootnoteArr)
1948  {
1949  SwFootnoteBossFrame* pRefBoss(pFootnote->GetRef()->FindFootnoteBossFrame(
1950  !pFootnote->GetAttr()->GetFootnote().IsEndNote()));
1951  if( pRefBoss != this )
1952  {
1953  const sal_uInt16 nRefNum = pRefBoss->FindPageFrame()->GetPhyPageNum();
1954  const sal_uInt16 nRefCol = lcl_ColumnNum( this );
1955  if( nRefNum < nMyNum || ( nRefNum == nMyNum && nRefCol <= nMyCol ) )
1956  pRefBoss = this;
1957  }
1958  pRefBoss->InsertFootnote( pFootnote );
1959 
1960  if ( pFootnote->GetUpper() ) // robust, e.g. with duplicates
1961  {
1962  // First condense the content so that footnote frames that do not fit on the page
1963  // do not do too much harm (Loop 66312). So, the footnote content first grows as
1964  // soon as the content gets formatted and it is sure that it fits on the page.
1965  SwFrame *pCnt = pFootnote->ContainsAny();
1966  while( pCnt )
1967  {
1968  if( pCnt->IsLayoutFrame() )
1969  {
1970  SwFrame* pTmp = static_cast<SwLayoutFrame*>(pCnt)->ContainsAny();
1971  while( pTmp && static_cast<SwLayoutFrame*>(pCnt)->IsAnLower( pTmp ) )
1972  {
1974 
1976  aRectFnSet.SetHeight(aFrm, 0);
1977 
1979  aRectFnSet.SetHeight(aPrt, 0);
1980 
1981  pTmp = pTmp->FindNext();
1982  }
1983  }
1984  else
1985  {
1987  }
1988 
1990  aRectFnSet.SetHeight(aFrm, 0);
1991 
1993  aRectFnSet.SetHeight(aPrt, 0);
1994 
1995  pCnt = pCnt->GetNext();
1996  }
1997 
1998  {
2000  aRectFnSet.SetHeight(aFrm, 0);
2001  }
2002 
2003  {
2005  aRectFnSet.SetHeight(aPrt, 0);
2006  }
2007 
2008  pFootnote->Calc(getRootFrame()->GetCurrShell()->GetOut());
2009  pFootnote->GetUpper()->Calc(getRootFrame()->GetCurrShell()->GetOut());
2010 
2011  if( bCalc )
2012  {
2013  SwTextFootnote *pAttr = pFootnote->GetAttr();
2014  pCnt = pFootnote->ContainsAny();
2015  bool bUnlock = !pFootnote->IsBackMoveLocked();
2016  pFootnote->LockBackMove();
2017 
2018  // #i49383# - disable unlock of position of
2019  // lower objects during format of footnote content.
2020  pFootnote->KeepLockPosOfLowerObjs();
2021  // #i57914# - adjust fix #i49383#
2022 
2023  while ( pCnt && pCnt->FindFootnoteFrame()->GetAttr() == pAttr )
2024  {
2025  pCnt->InvalidatePos_();
2026  pCnt->Calc(getRootFrame()->GetCurrShell()->GetOut());
2027  // #i49383# - format anchored objects
2028  if ( pCnt->IsTextFrame() && pCnt->isFrameAreaDefinitionValid() )
2029  {
2031  *(pCnt->FindPageFrame()) ) )
2032  {
2033  // restart format with first content
2034  pCnt = pFootnote->ContainsAny();
2035  continue;
2036  }
2037  }
2038  if( pCnt->IsSctFrame() )
2039  {
2040  // If the area is not empty, iterate also over the content
2041  SwFrame* pTmp = static_cast<SwSectionFrame*>(pCnt)->ContainsAny();
2042  if( pTmp )
2043  pCnt = pTmp;
2044  else
2045  pCnt = pCnt->FindNext();
2046  }
2047  else
2048  pCnt = pCnt->FindNext();
2049  }
2050  if( bUnlock )
2051  {
2052  pFootnote->UnlockBackMove();
2053  if( !pFootnote->ContainsAny() && !pFootnote->IsColLocked() )
2054  {
2055  pFootnote->Cut();
2056  SwFrame::DestroyFrame(pFootnote);
2057  // #i21478#
2058  pFootnote = nullptr;
2059  }
2060  }
2061  // #i49383#
2062  if ( pFootnote )
2063  {
2064  // #i57914# - adjust fix #i49383#
2065  // enable lock of lower object position before format of footnote frame.
2066  pFootnote->UnlockPosOfLowerObjs();
2067  pFootnote->Calc(getRootFrame()->GetCurrShell()->GetOut());
2068  }
2069  }
2070  }
2071  else
2072  {
2073  OSL_ENSURE( !pFootnote->GetMaster() && !pFootnote->GetFollow(),
2074  "DelFootnote and Master/Follow?" );
2075  SwFrame::DestroyFrame(pFootnote);
2076  // #i21478#
2077  pFootnote = nullptr;
2078  }
2079 
2080  // #i21478#
2081  if ( pFootnote )
2082  {
2083  pLastInsertedFootnote = pFootnote;
2084  }
2085  }
2086 
2087  // #i21478# - format content of footnote following
2088  // the new inserted ones.
2089  if ( bCalc && pLastInsertedFootnote )
2090  {
2091  if ( pLastInsertedFootnote->GetNext() )
2092  {
2093  SwFootnoteFrame* pNextFootnote = static_cast<SwFootnoteFrame*>(pLastInsertedFootnote->GetNext());
2094  SwTextFootnote* pAttr = pNextFootnote->GetAttr();
2095  SwFrame* pCnt = pNextFootnote->ContainsAny();
2096 
2097  bool bUnlock = !pNextFootnote->IsBackMoveLocked();
2098  pNextFootnote->LockBackMove();
2099  // #i49383# - disable unlock of position of
2100  // lower objects during format of footnote content.
2101  pNextFootnote->KeepLockPosOfLowerObjs();
2102  // #i57914# - adjust fix #i49383#
2103 
2104  while ( pCnt && pCnt->FindFootnoteFrame()->GetAttr() == pAttr )
2105  {
2106  pCnt->InvalidatePos_();
2107  pCnt->Calc(getRootFrame()->GetCurrShell()->GetOut());
2108  // #i49383# - format anchored objects
2109  if ( pCnt->IsTextFrame() && pCnt->isFrameAreaDefinitionValid() )
2110  {
2112  *(pCnt->FindPageFrame()) ) )
2113  {
2114  // restart format with first content
2115  pCnt = pNextFootnote->ContainsAny();
2116  continue;
2117  }
2118  }
2119  if( pCnt->IsSctFrame() )
2120  {
2121  // If the area is not empty, iterate also over the content
2122  SwFrame* pTmp = static_cast<SwSectionFrame*>(pCnt)->ContainsAny();
2123  if( pTmp )
2124  pCnt = pTmp;
2125  else
2126  pCnt = pCnt->FindNext();
2127  }
2128  else
2129  pCnt = pCnt->FindNext();
2130  }
2131  if( bUnlock )
2132  {
2133  pNextFootnote->UnlockBackMove();
2134  }
2135  // #i49383#
2136  // #i57914# - adjust fix #i49383#
2137  // enable lock of lower object position before format of footnote frame.
2138  pNextFootnote->UnlockPosOfLowerObjs();
2139  pNextFootnote->Calc(getRootFrame()->GetCurrShell()->GetOut());
2140  }
2141  }
2142 }
2143 
2145  SwTextFootnote const *pAttr )
2146 {
2147  if( ( GetFormat()->GetDoc()->GetFootnoteInfo().m_ePos == FTNPOS_CHAPTER &&
2148  (!GetUpper()->IsSctFrame() || !static_cast<SwSectionFrame*>(GetUpper())->IsFootnoteAtEnd()))
2149  || pAttr->GetFootnote().IsEndNote() )
2150  return;
2151 
2152  OSL_ENSURE( this == pSrc->FindFootnoteBossFrame( true ),
2153  "SwPageFrame::MoveFootnotes: source frame isn't on that FootnoteBoss" );
2154 
2155  SwFootnoteFrame *pFootnote = FindFirstFootnote();
2156  if( pFootnote )
2157  {
2158  ChangeFootnoteRef( pSrc, pAttr, pDest );
2159  SwFootnoteBossFrame *pDestBoss = pDest->FindFootnoteBossFrame( true );
2160  OSL_ENSURE( pDestBoss, "+SwPageFrame::MoveFootnotes: no destination boss" );
2161  if( pDestBoss ) // robust
2162  {
2163  SwFootnoteFrames aFootnoteArr;
2164  SwFootnoteBossFrame::CollectFootnotes_(pDest, pFootnote, aFootnoteArr, nullptr);
2165  if ( !aFootnoteArr.empty() )
2166  {
2167  pDestBoss->MoveFootnotes_( aFootnoteArr, true );
2168  SwPageFrame* pSrcPage = FindPageFrame();
2169  SwPageFrame* pDestPage = pDestBoss->FindPageFrame();
2170  // update FootnoteNum only at page change
2171  if( pSrcPage != pDestPage )
2172  {
2173  if( pSrcPage->GetPhyPageNum() > pDestPage->GetPhyPageNum() )
2174  pSrcPage->UpdateFootnoteNum();
2175  pDestPage->UpdateFootnoteNum();
2176  }
2177  }
2178  }
2179  }
2180 }
2181 
2182 void SwFootnoteBossFrame::RearrangeFootnotes( const SwTwips nDeadLine, const bool bLock,
2183  const SwTextFootnote *pAttr )
2184 {
2185  // Format all footnotes of a column/page so that they might change the column/page.
2186 
2187  SwSaveFootnoteHeight aSave( this, nDeadLine );
2188  SwFootnoteFrame *pFootnote = FindFirstFootnote();
2189  if( pFootnote && pFootnote->GetPrev() && bLock )
2190  {
2191  SwFootnoteFrame* pFirst = static_cast<SwFootnoteFrame*>(pFootnote->GetUpper()->Lower());
2192  SwFrame* pContent = pFirst->ContainsAny();
2193  if( pContent )
2194  {
2195  bool bUnlock = !pFirst->IsBackMoveLocked();
2196  pFirst->LockBackMove();
2197  pFirst->Calc(getRootFrame()->GetCurrShell()->GetOut());
2198  pContent->Calc(getRootFrame()->GetCurrShell()->GetOut());
2199  // #i49383# - format anchored objects
2200  if ( pContent->IsTextFrame() && pContent->isFrameAreaDefinitionValid() )
2201  {
2203  *(pContent->FindPageFrame()) );
2204  }
2205  if( bUnlock )
2206  pFirst->UnlockBackMove();
2207  }
2208  pFootnote = FindFirstFootnote();
2209  }
2210  SwDoc *pDoc = GetFormat()->GetDoc();
2211  const sal_uLong nFootnotePos = pAttr ? ::lcl_FindFootnotePos( pDoc, pAttr ) : 0;
2212  SwFrame *pCnt = pFootnote ? pFootnote->ContainsAny() : nullptr;
2213  if ( pCnt )
2214  {
2215  bool bMore = true;
2216  bool bStart = pAttr == nullptr; // If no attribute is given, process all
2217  // #i49383# - disable unlock of position of
2218  // lower objects during format of footnote and footnote content.
2219  SwFootnoteFrame* pLastFootnoteFrame( nullptr );
2220  // footnote frame needs to be locked, if <bLock> isn't set.
2221  bool bUnlockLastFootnoteFrame( false );
2222  do
2223  {
2224  if( !bStart )
2225  bStart = ::lcl_FindFootnotePos( pDoc, pCnt->FindFootnoteFrame()->GetAttr() )
2226  == nFootnotePos;
2227  if( bStart )
2228  {
2229  pCnt->InvalidatePos_();
2230  pCnt->InvalidateSize_();
2232  SwFootnoteFrame* pFootnoteFrame = pCnt->FindFootnoteFrame();
2233  // #i49383#
2234  if ( pFootnoteFrame != pLastFootnoteFrame )
2235  {
2236  if ( pLastFootnoteFrame )
2237  {
2238  if ( !bLock && bUnlockLastFootnoteFrame )
2239  {
2240  pLastFootnoteFrame->ColUnlock();
2241  }
2242  // #i57914# - adjust fix #i49383#
2243  // enable lock of lower object position before format of footnote frame.
2244  pLastFootnoteFrame->UnlockPosOfLowerObjs();
2245  pLastFootnoteFrame->Calc(getRootFrame()->GetCurrShell()->GetOut());
2246  if ( !bLock && bUnlockLastFootnoteFrame &&
2247  !pLastFootnoteFrame->GetLower() &&
2248  !pLastFootnoteFrame->IsColLocked() &&
2249  !pLastFootnoteFrame->IsBackMoveLocked() &&
2250  !pLastFootnoteFrame->IsDeleteForbidden() )
2251  {
2252  pLastFootnoteFrame->Cut();
2253  SwFrame::DestroyFrame(pLastFootnoteFrame);
2254  pLastFootnoteFrame = nullptr;
2255  }
2256  }
2257  if ( !bLock )
2258  {
2259  bUnlockLastFootnoteFrame = !pFootnoteFrame->IsColLocked();
2260  pFootnoteFrame->ColLock();
2261  }
2262  pFootnoteFrame->KeepLockPosOfLowerObjs();
2263  pLastFootnoteFrame = pFootnoteFrame;
2264  }
2265  // OD 30.10.2002 #97265# - invalidate position of footnote
2266  // frame, if it's below its footnote container, in order to
2267  // assure its correct position, probably calculating its previous
2268  // footnote frames.
2269  {
2270  SwRectFnSet aRectFnSet(this);
2271  SwFrame* pFootnoteContFrame = pFootnoteFrame->GetUpper();
2272  if ( aRectFnSet.TopDist(pFootnoteFrame->getFrameArea(), aRectFnSet.GetPrtBottom(*pFootnoteContFrame)) > 0 )
2273  {
2274  pFootnoteFrame->InvalidatePos_();
2275  }
2276  }
2277  if ( bLock )
2278  {
2279  bool bUnlock = !pFootnoteFrame->IsBackMoveLocked();
2280  pFootnoteFrame->LockBackMove();
2281  pFootnoteFrame->Calc(getRootFrame()->GetCurrShell()->GetOut());
2282  pCnt->Calc(getRootFrame()->GetCurrShell()->GetOut());
2283  // #i49383# - format anchored objects
2284  if ( pCnt->IsTextFrame() && pCnt->isFrameAreaDefinitionValid() )
2285  {
2286  SwFrameDeleteGuard aDeleteGuard(pFootnote);
2288  *(pCnt->FindPageFrame()) ) )
2289  {
2290  // restart format with first content
2291  pCnt = pFootnote ? pFootnote->ContainsAny() : nullptr;
2292  if (!pCnt)
2293  bMore = false;
2294  continue;
2295  }
2296  }
2297  if( bUnlock )
2298  {
2299  pFootnoteFrame->UnlockBackMove();
2300  if( !pFootnoteFrame->Lower() &&
2301  !pFootnoteFrame->IsColLocked() )
2302  {
2303  // #i49383#
2304  OSL_ENSURE( pLastFootnoteFrame == pFootnoteFrame,
2305  "<SwFootnoteBossFrame::RearrangeFootnotes(..)> - <pLastFootnoteFrame> != <pFootnoteFrame>" );
2306  pLastFootnoteFrame = nullptr;
2307  pFootnoteFrame->Cut();
2308  SwFrame::DestroyFrame(pFootnoteFrame);
2309  if (pFootnote == pFootnoteFrame)
2310  pFootnote = nullptr;
2311  }
2312  }
2313  }
2314  else
2315  {
2316  pFootnoteFrame->Calc(getRootFrame()->GetCurrShell()->GetOut());
2317  pCnt->Calc(getRootFrame()->GetCurrShell()->GetOut());
2318  // #i49383# - format anchored objects
2319  if ( pCnt->IsTextFrame() && pCnt->isFrameAreaDefinitionValid() )
2320  {
2322  *(pCnt->FindPageFrame()) ) )
2323  {
2324  // restart format with first content
2325  pCnt = pFootnote->ContainsAny();
2326  continue;
2327  }
2328  }
2329  }
2330  }
2331  SwSectionFrame *pDel = nullptr;
2332  if( pCnt->IsSctFrame() )
2333  {
2334  SwFrame* pTmp = static_cast<SwSectionFrame*>(pCnt)->ContainsAny();
2335  if( pTmp )
2336  {
2337  pCnt = pTmp;
2338  continue;
2339  }
2340  pDel = static_cast<SwSectionFrame*>(pCnt);
2341  }
2342  if ( pCnt->GetNext() )
2343  pCnt = pCnt->GetNext();
2344  else
2345  {
2346  pCnt = pCnt->FindNext();
2347  if ( pCnt )
2348  {
2349  SwFootnoteFrame* pFootnoteFrame = pCnt->FindFootnoteFrame();
2350  if( pFootnoteFrame->GetRef()->FindFootnoteBossFrame(
2351  pFootnoteFrame->GetAttr()->GetFootnote().IsEndNote() ) != this )
2352  bMore = false;
2353  }
2354  else
2355  bMore = false;
2356  }
2357  if( pDel )
2358  {
2359  bool bUnlockLastFootnoteFrameGuard = pLastFootnoteFrame && !pLastFootnoteFrame->IsColLocked();
2360  if (bUnlockLastFootnoteFrameGuard)
2361  pLastFootnoteFrame->ColLock();
2362  pDel->Cut();
2363  if (bUnlockLastFootnoteFrameGuard)
2364  pLastFootnoteFrame->ColUnlock();
2365  SwFrame::DestroyFrame(pDel);
2366  }
2367  if ( bMore )
2368  {
2369  // Go not further than to the provided footnote (if given)
2370  if ( pAttr &&
2371  (::lcl_FindFootnotePos( pDoc,
2372  pCnt->FindFootnoteFrame()->GetAttr()) > nFootnotePos ) )
2373  bMore = false;
2374  }
2375  } while ( bMore );
2376  // #i49383#
2377  if ( pLastFootnoteFrame )
2378  {
2379  if ( !bLock && bUnlockLastFootnoteFrame )
2380  {
2381  pLastFootnoteFrame->ColUnlock();
2382  }
2383  // #i57914# - adjust fix #i49383#
2384  // enable lock of lower object position before format of footnote frame.
2385  pLastFootnoteFrame->UnlockPosOfLowerObjs();
2386  pLastFootnoteFrame->Calc(getRootFrame()->GetCurrShell()->GetOut());
2387  if ( !bLock && bUnlockLastFootnoteFrame &&
2388  !pLastFootnoteFrame->GetLower() &&
2389  !pLastFootnoteFrame->IsColLocked() &&
2390  !pLastFootnoteFrame->IsBackMoveLocked() )
2391  {
2392  pLastFootnoteFrame->Cut();
2393  SwFrame::DestroyFrame(pLastFootnoteFrame);
2394  }
2395  }
2396  }
2397 }
2398 
2400 {
2401  // page numbering only if set at the document
2402  if ( GetFormat()->GetDoc()->GetFootnoteInfo().m_eNum != FTNNUM_PAGE )
2403  return;
2404 
2405  SwLayoutFrame* pBody = FindBodyCont();
2406  if( !pBody || !pBody->Lower() )
2407  return;
2408 
2410  sal_uInt16 nNum = 0;
2411 
2412  while( pContent && pContent->FindPageFrame() == this )
2413  {
2414  if( static_cast<SwTextFrame*>(pContent)->HasFootnote() )
2415  {
2416  SwFootnoteBossFrame* pBoss = pContent->FindFootnoteBossFrame( true );
2417  if( pBoss->GetUpper()->IsSctFrame() &&
2418  static_cast<SwSectionFrame*>(pBoss->GetUpper())->IsOwnFootnoteNum() )
2419  pContent = static_cast<SwSectionFrame*>(pBoss->GetUpper())->FindLastContent();
2420  else
2421  {
2422  SwFootnoteFrame* pFootnote = const_cast<SwFootnoteFrame*>(pBoss->FindFirstFootnote( pContent ));
2423  while( pFootnote )
2424  {
2425  SwTextFootnote* pTextFootnote = pFootnote->GetAttr();
2426  if( !pTextFootnote->GetFootnote().IsEndNote() &&
2427  pTextFootnote->GetFootnote().GetNumStr().isEmpty() &&
2428  !pFootnote->GetMaster())
2429  {
2430  // sw_redlinehide: the layout can only keep one number
2431  // up to date; depending on its setting, this is either
2432  // the non-hidden or the hidden number; the other
2433  // number will simply be preserved as-is (so in case
2434  // there are 2 layouts, maybe both can be updated...)
2435  ++nNum;
2436  sal_uInt16 const nOldNum(pTextFootnote->GetFootnote().GetNumber());
2437  sal_uInt16 const nOldNumRLHidden(pTextFootnote->GetFootnote().GetNumberRLHidden());
2438  if (getRootFrame()->IsHideRedlines())
2439  {
2440  if (nNum != nOldNumRLHidden)
2441  {
2442  pTextFootnote->SetNumber(nOldNum, nNum, OUString());
2443  }
2444  }
2445  else
2446  {
2447  if (nNum != nOldNum)
2448  {
2449  pTextFootnote->SetNumber(nNum, nOldNumRLHidden, OUString());
2450  }
2451  }
2452  }
2453  if ( pFootnote->GetNext() )
2454  pFootnote = static_cast<SwFootnoteFrame*>(pFootnote->GetNext());
2455  else
2456  {
2457  SwFootnoteBossFrame* pTmpBoss = pFootnote->FindFootnoteBossFrame( true );
2458  if( pTmpBoss )
2459  {
2460  SwPageFrame* pPage = pTmpBoss->FindPageFrame();
2461  pFootnote = nullptr;
2462  lcl_NextFootnoteBoss( pTmpBoss, pPage, false );
2463  SwFootnoteContFrame *pCont = pTmpBoss ? pTmpBoss->FindNearestFootnoteCont() : nullptr;
2464  if ( pCont )
2465  pFootnote = static_cast<SwFootnoteFrame*>(pCont->Lower());
2466  }
2467  }
2468  if( pFootnote && pFootnote->GetRef() != pContent )
2469  pFootnote = nullptr;
2470  }
2471  }
2472  }
2473  pContent = pContent->FindNextCnt();
2474  }
2475 }
2476 
2478 {
2479  SwFrame *pBody = FindBodyCont();
2480  pBody->Calc(getRootFrame()->GetCurrShell()->GetOut());
2481 
2482  SwFrame *pCont = FindFootnoteCont();
2483  const SwTwips nMax = m_nMaxFootnoteHeight;// current should exceed MaxHeight
2484  SwRectFnSet aRectFnSet(this);
2485  if ( pCont )
2486  {
2487  pCont->Calc(getRootFrame()->GetCurrShell()->GetOut());
2488  m_nMaxFootnoteHeight = -aRectFnSet.BottomDist( pCont->getFrameArea(), nDeadLine );
2489  }
2490  else
2491  m_nMaxFootnoteHeight = -aRectFnSet.BottomDist( pBody->getFrameArea(), nDeadLine );
2492 
2493  const SwViewShell *pSh = getRootFrame() ? getRootFrame()->GetCurrShell() : nullptr;
2494  if( pSh && pSh->GetViewOptions()->getBrowseMode() )
2495  m_nMaxFootnoteHeight += pBody->Grow( LONG_MAX, true );
2496  if ( IsInSct() )
2498 
2499  if ( m_nMaxFootnoteHeight < 0 )
2501  if ( nMax != LONG_MAX && m_nMaxFootnoteHeight > nMax )
2502  m_nMaxFootnoteHeight = nMax;
2503 }
2504 
2506 {
2507  // To not fall below 20% of the page height
2508  // (in contrast to MSOffice where footnotes can fill a whole column/page)
2509 
2510  const SwPageFrame* pPg = FindPageFrame();
2511  OSL_ENSURE( pPg || IsInSct(), "Footnote lost page" );
2512 
2513  const SwFrame *pBody = FindBodyCont();
2514  SwTwips nRet;
2515  if( pBody )
2516  {
2517  SwRectFnSet aRectFnSet(this);
2518  if( IsInSct() )
2519  {
2520  nRet = 0;
2521  SwTwips nTmp = aRectFnSet.YDiff( aRectFnSet.GetPrtTop(*pBody),
2522  aRectFnSet.GetTop(getFrameArea()) );
2523  const SwSectionFrame* pSect = FindSctFrame();
2524  // Endnotes in a ftncontainer causes a deadline:
2525  // the bottom of the last contentfrm
2526  if( pSect->IsEndnAtEnd() ) // endnotes allowed?
2527  {
2528  OSL_ENSURE( !Lower() || !Lower()->GetNext() || Lower()->GetNext()->
2529  IsFootnoteContFrame(), "FootnoteContainer expected" );
2530  const SwFootnoteContFrame* pCont = Lower() ?
2531  static_cast<const SwFootnoteContFrame*>(Lower()->GetNext()) : nullptr;
2532  if( pCont )
2533  {
2534  const SwFootnoteFrame* pFootnote = static_cast<const SwFootnoteFrame*>(pCont->Lower());
2535  while( pFootnote)
2536  {
2537  if( pFootnote->GetAttr()->GetFootnote().IsEndNote() )
2538  { // endnote found
2539  const SwFrame* pFrame = static_cast<const SwLayoutFrame*>(Lower())->Lower();
2540  if( pFrame )
2541  {
2542  while( pFrame->GetNext() )
2543  pFrame = pFrame->GetNext(); // last cntntfrm
2544  nTmp += aRectFnSet.YDiff(
2545  aRectFnSet.GetTop(getFrameArea()),
2546  aRectFnSet.GetBottom(pFrame->getFrameArea()) );
2547  }
2548  break;
2549  }
2550  pFootnote = static_cast<const SwFootnoteFrame*>(pFootnote->GetNext());
2551  }
2552  }
2553  }
2554  if( nTmp < nRet )
2555  nRet = nTmp;
2556  }
2557  else
2558  nRet = - aRectFnSet.GetHeight(pPg->getFramePrintArea())/5;
2559  nRet += aRectFnSet.GetHeight(pBody->getFrameArea());
2560  if( nRet < 0 )
2561  nRet = 0;
2562  }
2563  else
2564  nRet = 0;
2565  if ( IsPageFrame() )
2566  {
2567  const SwViewShell *pSh = getRootFrame() ? getRootFrame()->GetCurrShell() : nullptr;
2568  if( pSh && pSh->GetViewOptions()->getBrowseMode() )
2569  nRet += BROWSE_HEIGHT - getFrameArea().Height();
2570  }
2571  return nRet;
2572 }
2573 
2587 {
2589  if( GetUpper() && !GetUpper()->IsPageBodyFrame() )
2590  {
2591  // column sections need grow/shrink
2592  if( GetUpper()->IsFlyFrame() )
2594  else
2595  {
2596  OSL_ENSURE( GetUpper()->IsSctFrame(), "NeighbourhoodAdjustment: Unexpected Upper" );
2597  if( !GetNext() && !GetPrev() )
2598  nRet = SwNeighbourAdjust::GrowAdjust; // section with a single column (FootnoteAtEnd)
2599  else
2600  {
2601  const SwFrame* pTmp = Lower();
2602  OSL_ENSURE( pTmp, "NeighbourhoodAdjustment: Missing Lower()" );
2603  if( !pTmp->GetNext() )
2605  else if( !GetUpper()->IsColLocked() )
2607  OSL_ENSURE( !pTmp->GetNext() || pTmp->GetNext()->IsFootnoteContFrame(),
2608  "NeighbourhoodAdjustment: Who's that guy?" );
2609  }
2610  }
2611  }
2612  return nRet;
2613 }
2614 
2616 {
2617  SwLayoutFrame *pBody = FindBodyCont();
2618  if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrame() )
2619  {
2620  SwColumnFrame* pCol = static_cast<SwColumnFrame*>(pBody->Lower());
2621  do
2622  {
2624  pCol = static_cast<SwColumnFrame*>(pCol->GetNext());
2625  } while ( pCol );
2626  }
2627 }
2628 
2630  SwFootnoteBossFrame *pNewBoss, const bool bFootnoteNums )
2631 {
2632  SwDoc *pDoc = GetFormat()->GetDoc();
2633  if ( pDoc->GetFootnoteIdxs().empty() )
2634  return false;
2635  if( pDoc->GetFootnoteInfo().m_ePos == FTNPOS_CHAPTER &&
2636  ( !IsInSct() || !FindSctFrame()->IsFootnoteAtEnd() ) )
2637  return true;
2638 
2639  if ( !pNewBoss )
2640  pNewBoss = FindFootnoteBossFrame( true );
2641  if ( pNewBoss == pOldBoss )
2642  return false;
2643 
2644  bool bMoved = false;
2645  if( !pStart )
2646  pStart = ContainsContent();
2647 
2648  SwFootnoteFrames aFootnoteArr;
2649 
2650  while ( IsAnLower( pStart ) )
2651  {
2652  if ( static_cast<SwTextFrame*>(pStart)->HasFootnote() )
2653  {
2654  // OD 03.04.2003 #108446# - To avoid unnecessary moves of footnotes
2655  // use new parameter <_bCollectOnlyPreviousFootnote> (4th parameter of
2656  // method <SwFootnoteBossFrame::CollectFootnote(..)>) to control, that only
2657  // footnotes have to be collected, that are positioned before the
2658  // new dedicated footnote boss frame.
2659  pNewBoss->CollectFootnotes( pStart, pOldBoss, aFootnoteArr, true );
2660  }
2661  pStart = pStart->GetNextContentFrame();
2662  }
2663 
2664  OSL_ENSURE( pOldBoss->IsInSct() == pNewBoss->IsInSct(),
2665  "MoveLowerFootnotes: Section confusion" );
2666  std::unique_ptr<SwFootnoteFrames> pFootnoteArr;
2667  SwLayoutFrame* pNewChief = nullptr;
2668  SwLayoutFrame* pOldChief = nullptr;
2669 
2670  bool bFoundCandidate = false;
2671  if (pStart && pOldBoss->IsInSct())
2672  {
2673  pOldChief = pOldBoss->FindSctFrame();
2674  pNewChief = pNewBoss->FindSctFrame();
2675  bFoundCandidate = pOldChief != pNewChief;
2676  }
2677 
2678  if (bFoundCandidate)
2679  {
2680  pFootnoteArr.reset(new SwFootnoteFrames);
2681  pOldChief = pOldBoss->FindFootnoteBossFrame( true );
2682  pNewChief = pNewBoss->FindFootnoteBossFrame( true );
2683  while( pOldChief->IsAnLower( pStart ) )
2684  {
2685  if ( static_cast<SwTextFrame*>(pStart)->HasFootnote() )
2686  static_cast<SwFootnoteBossFrame*>(pNewChief)->CollectFootnotes( pStart,
2687  pOldBoss, *pFootnoteArr );
2688  pStart = pStart->GetNextContentFrame();
2689  }
2690  if( pFootnoteArr->empty() )
2691  {
2692  pFootnoteArr.reset();
2693  }
2694  }
2695  else
2696  pFootnoteArr = nullptr;
2697 
2698  if ( !aFootnoteArr.empty() || pFootnoteArr )
2699  {
2700  if( !aFootnoteArr.empty() )
2701  pNewBoss->MoveFootnotes_( aFootnoteArr, true );
2702  if( pFootnoteArr )
2703  {
2704  assert(pNewChief);
2705  static_cast<SwFootnoteBossFrame*>(pNewChief)->MoveFootnotes_( *pFootnoteArr, true );
2706  pFootnoteArr.reset();
2707  }
2708  bMoved = true;
2709 
2710  // update FootnoteNum only at page change
2711  if ( bFootnoteNums )
2712  {
2713  SwPageFrame* pOldPage = pOldBoss->FindPageFrame();
2714  SwPageFrame* pNewPage =pNewBoss->FindPageFrame();
2715  if( pOldPage != pNewPage )
2716  {
2717  pOldPage->UpdateFootnoteNum();
2718  pNewPage->UpdateFootnoteNum();
2719  }
2720  }
2721  }
2722  return bMoved;
2723 }
2724 
2726 {
2727  OSL_ENSURE( IsInFootnote(), "no footnote." );
2728  SwLayoutFrame *pFootnote = FindFootnoteFrame();
2729 
2730  // The first paragraph in the first footnote in the first column in the
2731  // sectionfrm at the top of the page has not to move forward, if the
2732  // columnbody is empty.
2733  if( pOldBoss->IsInSct() && !pOldBoss->GetIndPrev() && !GetIndPrev() &&
2734  !pFootnote->GetPrev() )
2735  {
2736  SwLayoutFrame* pBody = pOldBoss->FindBodyCont();
2737  if( !pBody || !pBody->Lower() )
2738  return true;
2739  }
2740 
2741  //fix(9538): if the footnote has neighbors behind itself, remove them temporarily
2742  SwLayoutFrame *pNxt = static_cast<SwLayoutFrame*>(pFootnote->GetNext());
2743  SwLayoutFrame *pLst = nullptr;
2744  while ( pNxt )
2745  {
2746  while ( pNxt->GetNext() )
2747  pNxt = static_cast<SwLayoutFrame*>(pNxt->GetNext());
2748  if ( pNxt == pLst )
2749  pNxt = nullptr;
2750  else
2751  { pLst = pNxt;
2752  SwContentFrame *pCnt = pNxt->ContainsContent();
2753  if( pCnt )
2754  pCnt->MoveFootnoteCntFwd( true, pOldBoss );
2755  pNxt = static_cast<SwLayoutFrame*>(pFootnote->GetNext());
2756  }
2757  }
2758 
2759  bool bSamePage = true;
2760  SwLayoutFrame *pNewUpper =
2761  GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, true );
2762 
2763  if ( pNewUpper )
2764  {
2765  SwFootnoteBossFrame * const pNewBoss = pNewUpper->FindFootnoteBossFrame();
2766  // Are we changing the column/page?
2767  bool bSameBoss = pNewBoss == pOldBoss;
2768  if ( !bSameBoss )
2769  {
2770  bSamePage = pOldBoss->FindPageFrame() == pNewBoss->FindPageFrame(); // page change?
2771  pNewUpper->Calc(getRootFrame()->GetCurrShell()->GetOut());
2772  }
2773 
2774  // The layout leaf of the footnote is either a footnote container or a footnote.
2775  // If it is a footnote and it has the same footnote reference like the old Upper,
2776  // then move the content inside of it.
2777  // If it is a container or the reference differs, create a new footnote and add
2778  // it into the container.
2779  // Create also a SectionFrame if currently in an area inside a footnote.
2780  SwFootnoteFrame* pTmpFootnote = pNewUpper->IsFootnoteFrame() ? static_cast<SwFootnoteFrame*>(pNewUpper) : nullptr;
2781  if (!pTmpFootnote && pNewUpper->IsFootnoteContFrame())
2782  {
2783  SwFootnoteContFrame *pCont = static_cast<SwFootnoteContFrame*>(pNewUpper);
2784  pTmpFootnote = SwFootnoteContFrame::AppendChained(this, true);
2785  SwFrame* pNx = pCont->Lower();
2786  if( pNx && pTmpFootnote->GetAttr()->GetFootnote().IsEndNote() )
2787  while(pNx && !static_cast<SwFootnoteFrame*>(pNx)->GetAttr()->GetFootnote().IsEndNote())
2788  pNx = pNx->GetNext();
2789  pTmpFootnote->Paste( pCont, pNx );
2790  pTmpFootnote->Calc(getRootFrame()->GetCurrShell()->GetOut());
2791  }
2792  OSL_ENSURE( pTmpFootnote->GetAttr() == FindFootnoteFrame()->GetAttr(), "Wrong Footnote!" );
2793  // areas inside of footnotes get a special treatment
2794  SwLayoutFrame *pNewUp = pTmpFootnote;
2795  if( IsInSct() )
2796  {
2797  SwSectionFrame* pSect = FindSctFrame();
2798  // area inside of a footnote (or only footnote in an area)?
2799  if( pSect->IsInFootnote() )
2800  {
2801  if( pTmpFootnote->Lower() && pTmpFootnote->Lower()->IsSctFrame() &&
2802  pSect->GetFollow() == static_cast<SwSectionFrame*>(pTmpFootnote->Lower()) )
2803  pNewUp = static_cast<SwSectionFrame*>(pTmpFootnote->Lower());
2804  else
2805  {
2806  pNewUp = new SwSectionFrame( *pSect, false );
2807  pNewUp->InsertBefore( pTmpFootnote, pTmpFootnote->Lower() );
2808  static_cast<SwSectionFrame*>(pNewUp)->Init();
2809 
2810  {
2812  aFrm.Pos() = pTmpFootnote->getFrameArea().Pos();
2813  aFrm.Pos().AdjustY(1 ); // for notifications
2814  }
2815 
2816  // If the section frame has a successor then the latter needs
2817  // to be moved behind the new Follow of the section frame.
2818  SwFrame* pTmp = pSect->GetNext();
2819  if( pTmp )
2820  {
2821  SwFlowFrame* pTmpNxt;
2822  if( pTmp->IsContentFrame() )
2823  pTmpNxt = static_cast<SwContentFrame*>(pTmp);
2824  else if( pTmp->IsSctFrame() )
2825  pTmpNxt = static_cast<SwSectionFrame*>(pTmp);
2826  else
2827  {
2828  OSL_ENSURE( pTmp->IsTabFrame(), "GetNextSctLeaf: Wrong Type" );
2829  pTmpNxt = static_cast<SwTabFrame*>(pTmp);
2830  }
2831  pTmpNxt->MoveSubTree( pTmpFootnote, pNewUp->GetNext() );
2832  }
2833  }
2834  }
2835  }
2836 
2837  MoveSubTree( pNewUp, pNewUp->Lower() );
2838 
2839  if( !bSameBoss )
2841  }
2842  return bSamePage;
2843 }
2844 
2846  pBoss( pBs ),
2847  nOldHeight( pBs->GetMaxFootnoteHeight() )
2848 {
2849  pBoss->SetFootnoteDeadLine( nDeadLine );
2851 }
2852 
2854 {
2855  // If somebody tweaked the deadline meanwhile, we let it happen
2858 }
2859 
2860 #ifdef DBG_UTIL
2861 //JP 15.10.2001: in a non pro version test if the attribute has the same
2862 // meaning which his reference is
2863 
2864 // Normally, the pRef member and the GetRefFromAttr() result has to be
2865 // identically. Sometimes footnote will be moved from a master to its follow,
2866 // but the GetRef() is called first, so we have to ignore a master/follow
2867 // mismatch.
2868 
2870 {
2871  const SwContentFrame* pRefAttr = GetRefFromAttr();
2872  // check consistency: access to deleted frame?
2873  assert(mpReference == pRefAttr || mpReference->IsAnFollow(pRefAttr)
2874  || pRefAttr->IsAnFollow(mpReference));
2875  (void) pRefAttr;
2876  return mpReference;
2877 }
2878 
2880 {
2881  const SwContentFrame* pRefAttr = GetRefFromAttr();
2882  // check consistency: access to deleted frame?
2883  assert(mpReference == pRefAttr || mpReference->IsAnFollow(pRefAttr)
2884  || pRefAttr->IsAnFollow(mpReference));
2885  (void) pRefAttr;
2886  return mpReference;
2887 }
2888 #endif
2889 
2891 {
2892  SwFootnoteFrame* pThis = const_cast<SwFootnoteFrame*>(this);
2893  return pThis->GetRefFromAttr();
2894 }
2895 
2897 {
2898  assert(mpAttribute && "invalid Attribute");
2899  SwTextNode& rTNd = const_cast<SwTextNode&>(mpAttribute->GetTextNode());
2900  SwPosition aPos( rTNd, SwIndex( &rTNd, mpAttribute->GetStart() ));
2901  SwContentFrame* pCFrame = rTNd.getLayoutFrame(getRootFrame(), &aPos);
2902  return pCFrame;
2903 }
2904 
2910 {
2911  SwContentFrame* pLastContentFrame( nullptr );
2912 
2913  // find last lower, which is a content frame or contains content.
2914  // hidden text frames, empty sections and empty tables have to be skipped.
2915  SwFrame* pLastLowerOfFootnote( GetLower() );
2916  SwFrame* pTmpLastLower( pLastLowerOfFootnote );
2917  while ( pTmpLastLower && pTmpLastLower->GetNext() )
2918  {
2919  pTmpLastLower = pTmpLastLower->GetNext();
2920  if ( ( pTmpLastLower->IsTextFrame() &&
2921  !static_cast<SwTextFrame*>(pTmpLastLower)->IsHiddenNow() ) ||
2922  ( pTmpLastLower->IsSctFrame() &&
2923  static_cast<SwSectionFrame*>(pTmpLastLower)->GetSection() &&
2924  static_cast<SwSectionFrame*>(pTmpLastLower)->ContainsContent() ) ||
2925  ( pTmpLastLower->IsTabFrame() &&
2926  static_cast<SwTabFrame*>(pTmpLastLower)->ContainsContent() ) )
2927  {
2928  pLastLowerOfFootnote = pTmpLastLower;
2929  }
2930  }
2931 
2932  // determine last content frame depending on type of found last lower.
2933  if ( pLastLowerOfFootnote && pLastLowerOfFootnote->IsTabFrame() )
2934  {
2935  pLastContentFrame = static_cast<SwTabFrame*>(pLastLowerOfFootnote)->FindLastContent();
2936  }
2937  else if ( pLastLowerOfFootnote && pLastLowerOfFootnote->IsSctFrame() )
2938  {
2939  pLastContentFrame = static_cast<SwSectionFrame*>(pLastLowerOfFootnote)->FindLastContent();
2940  }
2941  else
2942  {
2943  pLastContentFrame = dynamic_cast<SwContentFrame*>(pLastLowerOfFootnote);
2944  }
2945 
2946  return pLastContentFrame;
2947 }
2948 
2949 /* 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:695
SwSaveFootnoteHeight(SwFootnoteBossFrame *pBs, const SwTwips nDeadLine)
Definition: ftnfrm.cxx:2845
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:149
SwFootnoteContFrame * FindNearestFootnoteCont(bool bDontLeave=false)
Search the next available footnote container.
Definition: ftnfrm.cxx:1028
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:1383
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:1462
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:941
static void SetMoveBwdJump(bool bNew)
Definition: flowfrm.hxx:155
bool MoveFootnoteCntFwd(bool, SwFootnoteBossFrame *)
Definition: ftnfrm.cxx:2725
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:1799
static SwFootnoteFrame * FindFootnote(const SwContentFrame *, const SwTextFootnote *)
Definition: ftnfrm.cxx:1663
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:2709
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:1148
#define ENDNOTE
Definition: ftnfrm.cxx:42
void InvalidateSize_()
Definition: frame.hxx:751
Definition: doc.hxx:186
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:2615
void SetMaxFootnoteHeight(const SwTwips nNewMax)
Definition: ftnboss.hxx:77
TElementType * Next()
Definition: calbck.hxx:373
void UpdateFootnoteNum()
Definition: ftnfrm.cxx:2399
void Height(long nNew)
Definition: swrect.hxx:190
void InsertFootnote(SwFootnoteFrame *)
Definition: ftnfrm.cxx:1202
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:1296
long SwTwips
Definition: swtypes.hxx:49
static void ChangeFootnoteRef(const SwContentFrame *pOld, const SwTextFootnote *, SwContentFrame *pNew)
Definition: ftnfrm.cxx:1731
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:168
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:1785
virtual void Cut() override
Definition: ftnfrm.cxx:540
bool IsFootnotePage() const
Foot note interface.
Definition: pagefrm.hxx:185
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:2182
static SwFlowFrame * CastFlowFrame(SwFrame *pFrame)
Definition: flowfrm.cxx:2606
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:190
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:2477
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:887
void MoveFootnotes_(SwFootnoteFrames &rFootnoteArr, bool bCalc=false)
Definition: ftnfrm.cxx:1936
const SwRect & getFrameArea() const
Definition: frame.hxx:177
SwFootnoteContFrame * FindFootnoteCont()
Definition: ftnfrm.cxx:1005
bool getBrowseMode() const
Definition: viewopt.hxx:444
bool IsEmptyPage() const
Definition: pagefrm.hxx:143
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:2901
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:1482
SwNeighbourAdjust NeighbourhoodAdjustment_() const
Obtain if pFrame's size adjustment should be processed.
Definition: ftnfrm.cxx:2586
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:1568
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:356
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:1793
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:1393
const SwFrame * Lower() const
Definition: layfrm.hxx:101
SwContentFrame * FindNextCnt(const bool _bInSameFootnote=false)
Definition: findfrm.cxx:190
TElementType * First()
Definition: calbck.hxx:342
SwPageDesc * GetPageDesc()
Definition: pagefrm.hxx:129
SwTwips AdjustNeighbourhood(SwTwips nDiff, bool bTst=false)
Adjust surrounding neighbourhood after insertion.
Definition: wsfrm.cxx:1568
SwContentNode * GetContentNode()
Definition: node.hxx:615
void InvalidatePage(const SwPageFrame *pPage=nullptr) const
Invalidates the page in which the Frame is currently placed.
Definition: wsfrm.cxx:597
void AddHeight(SwRect &rRect, long nNew) const
Definition: frame.hxx: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:1051
Marks a character position inside a document model node.
Definition: index.hxx:37
::rtl::Reference< Content > pContent
bool IsEndNotePage() const
Definition: pagefrm.hxx:186
static sal_uLong lcl_FindFootnotePos(const SwDoc *pDoc, const SwTextFootnote *pAttr)
Search the position of an attribute in the FootnoteArray at the document, because all footnotes are l...
Definition: ftnfrm.cxx: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:2064
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
void SSize(const Size &rNew)
Definition: swrect.hxx:177
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:905
void InvalidatePos_()
Definition: frame.hxx:767
SwFootnoteContFrame * MakeFootnoteCont()
Insert a footnote container.
Definition: ftnfrm.cxx:995
void UpdateFootnoteNums()
Update the footnote numbers of all Pages.
Definition: ftnfrm.cxx:872
A page of the document layout.
Definition: pagefrm.hxx:40
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:1507
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:744
const_iterator begin() const
bool RemoveFootnote(const SwContentFrame *, const SwTextFootnote *, bool bPrep=true)
Definition: ftnfrm.cxx:1703
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:1745
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:2140
static void ResetFootnote(const SwFootnoteFrame *pAssumed)
Definition: ftnfrm.cxx:1162
void SetRef(SwContentFrame *pNew)
Definition: ftnfrm.hxx:127
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:576
SwTwips GetVarSpace() const
Definition: ftnfrm.cxx:2505
SwLayoutFrame * GetLeaf(MakePageType eMakePage, bool bFwd)
Definition: flowfrm.cxx:784
void CheckFootnotePageDescs(bool bEndNote)
Change the page template of the footnote pages.
Definition: ftnfrm.cxx:975
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:1455
virtual SwTwips ShrinkFrame(SwTwips, bool bTst=false, bool bInfo=false) override
Definition: wsfrm.cxx:2745
#define SAL_WARN_IF(condition, area, stream)
SwTextFrame * FindMaster() const
Definition: flowfrm.cxx:679
sal_uInt16 GetPhyPageNum() const
Definition: trvlfrm.cxx:1692
bool MoveLowerFootnotes(SwContentFrame *pStart, SwFootnoteBossFrame *pOldBoss, SwFootnoteBossFrame *pNewBoss, const bool bFootnoteNums)
Moving the Footnotes of all Lowers - starting from StartContent.
Definition: ftnfrm.cxx:2629
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:426
const SwFrame * ContainsAny(const bool _bInvestigateFootnoteForSections=false) const
Method doesn't investigate content of footnotes by default.
Definition: findfrm.cxx:125
bool IsBackMoveLocked() const
Definition: ftnfrm.hxx:133
const SwSectionFormat * GetEndSectFormat() const
Definition: sectfrm.hxx:136
void RemoveFromLayout()
Definition: wsfrm.cxx:994
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:2869
SwFrameType mnFrameType
Definition: frame.hxx:397
bool IsPageFrame() const
Definition: frame.hxx:1156
bool IsFootnoteAllowed() const
Definition: ftnfrm.cxx:856
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:2144
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:668
const SfxPoolItem & GetAttr() const
Definition: txatbase.hxx:159
const SwContentFrame * GetRefFromAttr() const
Definition: ftnfrm.cxx:2890
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:630
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:3006
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:188
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:626
SwRootFrame * getRootFrame()
Definition: frame.hxx:659
const SwEndNoteInfo & GetEndNoteInfo() const
Definition: doc.hxx:628
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:5424
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:2909
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo