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