Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/layout/ftnfrm.cxx
Warning:line 2290, column 47
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ftnfrm.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/core/layout/ftnfrm.cxx

/home/maarten/src/libreoffice/core/sw/source/core/layout/ftnfrm.cxx

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

/home/maarten/src/libreoffice/core/sw/source/core/inc/frame.hxx

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#ifndef INCLUDED_SW_SOURCE_CORE_INC_FRAME_HXX
21#define INCLUDED_SW_SOURCE_CORE_INC_FRAME_HXX
22
23#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
24#include <editeng/borderline.hxx>
25#include <svl/poolitem.hxx>
26#include <swtypes.hxx>
27#include <swrect.hxx>
28#include <calbck.hxx>
29#include <svl/SfxBroadcaster.hxx>
30#include <o3tl/typed_flags_set.hxx>
31#include <com/sun/star/style/TabStop.hpp>
32#include <basegfx/matrix/b2dhommatrix.hxx>
33#include <vcl/outdev.hxx>
34
35#include <memory>
36
37namespace drawinglayer::processor2d { class BaseProcessor2D; }
38
39class SwLayoutFrame;
40class SwRootFrame;
41class SwPageFrame;
42class SwBodyFrame;
43class SwFlyFrame;
44class SwSectionFrame;
45class SwFootnoteFrame;
46class SwFootnoteBossFrame;
47class SwTabFrame;
48class SwRowFrame;
49class SwContentFrame;
50class SwAttrSet;
51class Color;
52class SwBorderAttrs;
53class SwCache;
54class SvxBrushItem;
55class SvxFormatBreakItem;
56class SwFormatPageDesc;
57class SwSelectionList;
58struct SwPosition;
59struct SwCursorMoveState;
60class SwFormat;
61class SwPrintData;
62class SwSortedObjs;
63class SwAnchoredObject;
64enum class SvxFrameDirection;
65class IDocumentDrawModelAccess;
66
67// Each FrameType is represented here as a bit.
68// The bits must be set in a way that it can be determined with masking of
69// which kind of FrameType an instance is _and_ from what classes it was derived.
70// Each frame has in its base class a member that must be set by the
71// constructors accordingly.
72enum class SwFrameType
73{
74 None = 0x0000,
75 Root = 0x0001,
76 Page = 0x0002,
77 Column = 0x0004,
78 Header = 0x0008,
79 Footer = 0x0010,
80 FtnCont = 0x0020,
81 Ftn = 0x0040,
82 Body = 0x0080,
83 Fly = 0x0100,
84 Section = 0x0200,
85// UNUSED 0x0400
86 Tab = 0x0800,
87 Row = 0x1000,
88 Cell = 0x2000,
89 Txt = 0x4000,
90 NoTxt = 0x8000,
91};
92
93namespace o3tl
94{
95 template<> struct typed_flags<SwFrameType> : is_typed_flags<SwFrameType, 0xfbff> {};
96};
97
98// for internal use some common combinations
99#define FRM_LAYOUTSwFrameType(0x3bFF) SwFrameType(0x3bFF)
100#define FRM_ALLSwFrameType(0xfbff) SwFrameType(0xfbff)
101#define FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt) (SwFrameType::Txt | SwFrameType::NoTxt)
102#define FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column) (SwFrameType::Page | SwFrameType::Column)
103#define FRM_ACCESSIBLE(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header |
SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType
::Tab | SwFrameType::Cell | SwFrameType::Txt)
(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header | SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType::Tab | SwFrameType::Cell | SwFrameType::Txt)
104#define FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell) (SwFrameType::Column | SwFrameType::Cell)
105#define FRM_NOTE_VERT(SwFrameType::FtnCont | SwFrameType::Ftn | SwFrameType::Section
| SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell | SwFrameType
::Txt)
(SwFrameType::FtnCont | SwFrameType::Ftn | SwFrameType::Section | SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell | SwFrameType::Txt)
106#define FRM_HEADFOOT(SwFrameType::Header | SwFrameType::Footer) (SwFrameType::Header | SwFrameType::Footer)
107#define FRM_BODYFTNC(SwFrameType::FtnCont | SwFrameType::Body) (SwFrameType::FtnCont | SwFrameType::Body)
108
109// for GetNextLeaf/GetPrevLeaf.
110enum MakePageType
111{
112 MAKEPAGE_NONE, // do not create page/footnote
113 MAKEPAGE_APPEND, // only append page if needed
114 MAKEPAGE_INSERT, // add or append page if needed
115 MAKEPAGE_FTN, // add footnote if needed
116 MAKEPAGE_NOSECTION // Don't create section frames
117};
118
119namespace drawinglayer::attribute {
120 class SdrAllFillAttributesHelper;
121 typedef std::shared_ptr< SdrAllFillAttributesHelper > SdrAllFillAttributesHelperPtr;
122}
123
124/// Helper class to isolate geometry-defining members of SwFrame
125/// and to control their accesses. Moved to own class to have no
126/// hidden accesses to 'private' members anymore.
127///
128/// Added most important flags about the state of this geometric
129/// information and if it is valid or not
130class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwFrameAreaDefinition
131{
132private:
133 friend void FriendHackInvalidateRowFrame(SwFrameAreaDefinition &);
134
135 // The absolute position and size of the SwFrame in the document.
136 // This values are set by the layouter implementations
137 SwRect maFrameArea;
138
139 // The 'inner' Frame Area defined by a SwRect relative to FrameArea:
140 // When identical to FrameArea, Pos() will be (0, 0) and Size identical.
141 SwRect maFramePrintArea;
142
143 // bitfield
144 bool mbFrameAreaPositionValid : 1;
145 bool mbFrameAreaSizeValid : 1;
146 bool mbFramePrintAreaValid : 1;
147
148 // #i65250#
149 // frame ID is now in general available - used for layout loop control
150 static sal_uInt32 mnLastFrameId;
151 const sal_uInt32 mnFrameId;
152
153protected:
154 // write access to mb*Valid flags
155 void setFrameAreaPositionValid(bool bNew);
156 void setFrameAreaSizeValid(bool bNew);
157 void setFramePrintAreaValid(bool bNew);
158
159public:
160 SwFrameAreaDefinition();
161 virtual ~SwFrameAreaDefinition();
162
163 // read access to mb*Valid flags
164 bool isFrameAreaPositionValid() const { return mbFrameAreaPositionValid; }
165 bool isFrameAreaSizeValid() const { return mbFrameAreaSizeValid; }
166 bool isFramePrintAreaValid() const { return mbFramePrintAreaValid; }
167
168 // syntactic sugar: test whole FrameAreaDefinition
169 bool isFrameAreaDefinitionValid() const { return isFrameAreaPositionValid() && isFrameAreaSizeValid() && isFramePrintAreaValid(); }
170
171 // #i65250#
172 sal_uInt32 GetFrameId() const { return mnFrameId; }
173
174 // read accesses to FrameArea definitions - only const access allowed.
175 // Do *not* const_cast results, it is necessary to track changes. use
176 // the below offered WriteAccess helper classes instead
177 const SwRect& getFrameArea() const { return maFrameArea; }
178 const SwRect& getFramePrintArea() const { return maFramePrintArea; }
179
180 // helper class(es) for FrameArea manipulation. These
181 // have to be used to apply changes to FrameAreas. They hold a copy of the
182 // SwRect for manipulation. It gets written back at destruction. Thus, this
183 // mechanism depends on scope usage, take care. It prevents errors using
184 // different instances of SwFrame in get/set methods which is more safe
185 class FrameAreaWriteAccess : public SwRect
186 {
187 private:
188 SwFrameAreaDefinition& mrTarget;
189
190 FrameAreaWriteAccess(const FrameAreaWriteAccess&) = delete;
191 FrameAreaWriteAccess& operator=(const FrameAreaWriteAccess&) = delete;
192
193 public:
194 FrameAreaWriteAccess(SwFrameAreaDefinition& rTarget) : SwRect(rTarget.getFrameArea()), mrTarget(rTarget) {}
195 ~FrameAreaWriteAccess();
196 void setSwRect(const SwRect& rNew) { *reinterpret_cast< SwRect* >(this) = rNew; }
197 };
198
199 // same helper for FramePrintArea
200 class FramePrintAreaWriteAccess : public SwRect
201 {
202 private:
203 SwFrameAreaDefinition& mrTarget;
204
205 FramePrintAreaWriteAccess(const FramePrintAreaWriteAccess&) = delete;
206 FramePrintAreaWriteAccess& operator=(const FramePrintAreaWriteAccess&) = delete;
207
208 public:
209 FramePrintAreaWriteAccess(SwFrameAreaDefinition& rTarget) : SwRect(rTarget.getFramePrintArea()), mrTarget(rTarget) {}
210 ~FramePrintAreaWriteAccess();
211 void setSwRect(const SwRect& rNew) { *reinterpret_cast< SwRect* >(this) = rNew; }
212 };
213
214 // RotateFlyFrame3 - Support for Transformations
215 // Hand out the Transformations for the current FrameAreaDefinition
216 // for the FrameArea and FramePrintArea.
217 // FramePrintArea is not relative to FrameArea in this
218 // transformation representation (to make it easier to use and understand).
219 // There is no 'set' method since SwFrame is a layout object. For
220 // some cases rotation will be included (used for SwGrfNode in inner
221 // SwFrame of a SwFlyFrame)
222 virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const;
223 virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const;
224
225 // RotateFlyFrame3 - Support for Transformations
226 // Modify current transformations by applying given translation
227 virtual void transform_translate(const Point& rOffset);
228};
229
230/// RotateFlyFrame3: Helper class when you want to make your SwFrame derivate
231/// transformable. It provides some tooling to do so. To use, add as member
232/// (see e.g. SwFlyFreeFrame which uses 'std::unique_ptr< TransformableSwFrame >')
233class TransformableSwFrame
234{
235private:
236 // The SwFrameAreaDefinition to work on
237 SwFrameAreaDefinition& mrSwFrameAreaDefinition;
238
239 // FrameAreaTransformation and FramePrintAreaTransformation
240 // !identity when needed (translate/scale is used (e.g. rotation))
241 basegfx::B2DHomMatrix maFrameAreaTransformation;
242 basegfx::B2DHomMatrix maFramePrintAreaTransformation;
243
244public:
245 TransformableSwFrame(SwFrameAreaDefinition& rSwFrameAreaDefinition)
246 : mrSwFrameAreaDefinition(rSwFrameAreaDefinition),
247 maFrameAreaTransformation(),
248 maFramePrintAreaTransformation()
249 {
250 }
251
252 // get SwFrameArea in transformation form
253 const basegfx::B2DHomMatrix& getLocalFrameAreaTransformation() const
254 {
255 return maFrameAreaTransformation;
256 }
257
258 // get SwFramePrintArea in transformation form
259 const basegfx::B2DHomMatrix& getLocalFramePrintAreaTransformation() const
260 {
261 return maFramePrintAreaTransformation;
262 }
263
264 // Helpers to re-create the untransformed SwRect(s) originally
265 // in the SwFrameAreaDefinition, based on the current Transformations.
266 SwRect getUntransformedFrameArea() const;
267 SwRect getUntransformedFramePrintArea() const;
268
269 // Helper method to re-create FrameAreaTransformations based on the
270 // current FrameAreaDefinition transformed by given rotation and Center
271 void createFrameAreaTransformations(
272 double fRotation,
273 const basegfx::B2DPoint& rCenter);
274
275 // Tooling method to reset the SwRect(s) in the current
276 // SwFrameAreaDefinition which are already adapted to
277 // Transformation back to the untransformed state, using
278 // the getUntransformedFrame*Area calls above when needed.
279 // Only the SwRect(s) are changed back, not the transformations.
280 void restoreFrameAreas();
281
282 // Re-Creates the SwRect(s) as BoundAreas based on the current
283 // set Transformations.
284 void adaptFrameAreasToTransformations();
285
286 // Modify current definitions by applying the given transformation
287 void transform(const basegfx::B2DHomMatrix& aTransform);
288};
289
290/**
291 * Base class of the Writer layout elements.
292 *
293 * This includes not only fly frames, but everything down to the paragraph
294 * level: pages, headers, footers, etc. (Inside a paragraph SwLinePortion
295 * instances are used.)
296 */
297class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwFrame : public SwFrameAreaDefinition, public SwClient, public SfxBroadcaster
298{
299 // the hidden Frame
300 friend class SwFlowFrame;
301 friend class SwLayoutFrame;
302 friend class SwLooping;
303 friend class SwDeletionChecker; // for GetDep()
304
305 // voids lower during creation of a column
306 friend SwFrame *SaveContent( SwLayoutFrame *, SwFrame* pStart );
307 friend void RestoreContent( SwFrame *, SwLayoutFrame *, SwFrame *pSibling );
308
309 // for validating a mistakenly invalidated one in SwContentFrame::MakeAll
310 friend void ValidateSz( SwFrame *pFrame );
311 // implemented in text/txtftn.cxx, prevents Footnote oscillation
312 friend void ValidateText( SwFrame *pFrame );
313
314 friend void MakeNxt( SwFrame *pFrame, SwFrame *pNxt );
315
316 // cache for (border) attributes
317 static SwCache *mpCache;
318
319 SwRootFrame *mpRoot;
320 SwLayoutFrame *mpUpper;
321 SwFrame *mpNext;
322 SwFrame *mpPrev;
323
324 // sw_redlinehide: hide these dangerous SwClient functions
325 using SwClient::GetRegisteredInNonConst;
326 using SwClient::GetRegisteredIn;
327
328 SwFrame *FindNext_();
329 SwFrame *FindPrev_();
330
331 /** method to determine next content frame in the same environment
332 for a flow frame (content frame, table frame, section frame)
333
334 #i27138# - adding documentation:
335 Travelling downwards through the layout to determine the next content
336 frame in the same environment. There are several environments in a
337 document, which form a closed context regarding this function. These
338 environments are:
339 - Each page header
340 - Each page footer
341 - Each unlinked fly frame
342 - Each group of linked fly frames
343 - All footnotes
344 - All document body frames
345 #i27138# - adding parameter <_bInSameFootnote>
346 Its default value is <false>. If its value is <true>, the environment
347 'All footnotes' is no longer treated. Instead each footnote is treated
348 as an own environment.
349
350 @param _bInSameFootnote
351 input parameter - boolean indicating, that the found next content
352 frame has to be in the same footnote frame. This parameter is only
353 relevant for flow frames in footnotes.
354
355 @return SwContentFrame*
356 pointer to the found next content frame. It's NULL, if none exists.
357 */
358 SwContentFrame* FindNextCnt_( const bool _bInSameFootnote );
359
360 /** method to determine previous content frame in the same environment
361 for a flow frame (content frame, table frame, section frame)
362
363 #i27138#
364 Travelling upwards through the layout to determine the previous content
365 frame in the same environment. There are several environments in a
366 document, which form a closed context regarding this function. These
367 environments are:
368 - Each page header
369 - Each page footer
370 - Each unlinked fly frame
371 - Each group of linked fly frames
372 - All footnotes
373 - All document body frames
374 #i27138# - adding parameter <_bInSameFootnote>
375 Its default value is <false>. If its value is <true>, the environment
376 'All footnotes' is no longer treated. Instead each footnote is treated
377 as an own environment.
378
379 The found previous content frame has to be in the same footnote frame. This is only
380 relevant for flow frames in footnotes.
381
382 @return SwContentFrame*
383 pointer to the found previous content frame. It's NULL, if none exists.
384 */
385 SwContentFrame* FindPrevCnt_();
386
387 void UpdateAttrFrame( const SfxPoolItem*, const SfxPoolItem*, sal_uInt8 & );
388 SwFrame* GetIndNext_();
389 void SetDirFlags( bool bVert );
390
391 const SwLayoutFrame* ImplGetNextLayoutLeaf( bool bFwd ) const;
392
393 SwPageFrame* ImplFindPageFrame();
394
395protected:
396 std::unique_ptr<SwSortedObjs> m_pDrawObjs; // draw objects, can be null
397 SwFrameType mnFrameType; //Who am I?
398
399 bool mbInDtor : 1;
400 bool mbInvalidR2L : 1;
401 bool mbDerivedR2L : 1;
402 bool mbRightToLeft : 1;
403 bool mbInvalidVert : 1;
404 bool mbDerivedVert : 1;
405 bool mbVertical : 1;
406
407 bool mbVertLR : 1;
408 bool mbVertLRBT : 1;
409
410 bool mbValidLineNum : 1;
411 bool mbFixSize : 1;
412
413 // if true, frame will be painted completely even content was changed
414 // only partially. For ContentFrames a border (from Action) will exclusively
415 // painted if <mbCompletePaint> is true.
416 bool mbCompletePaint : 1;
417
418 bool mbRetouche : 1; // frame is responsible for retouching
419
420 bool mbInfInvalid : 1; // InfoFlags are invalid
421 bool mbInfBody : 1; // Frame is in document body
422 bool mbInfTab : 1; // Frame is in a table
423 bool mbInfFly : 1; // Frame is in a Fly
424 bool mbInfFootnote : 1; // Frame is in a footnote
425 bool mbInfSct : 1; // Frame is in a section
426 bool mbColLocked : 1; // lock Grow/Shrink for column-wise section
427 // or fly frames, will be set in Format
428 bool m_isInDestroy : 1;
429 bool mbForbidDelete : 1;
430
431 void ColLock() { mbColLocked = true; }
432 void ColUnlock() { mbColLocked = false; }
433
434 virtual void DestroyImpl();
435 virtual ~SwFrame() override;
436
437 // Only used by SwRootFrame Ctor to get 'this' into mpRoot...
438 void setRootFrame( SwRootFrame* pRoot ) { mpRoot = pRoot; }
439
440 SwPageFrame *InsertPage( SwPageFrame *pSibling, bool bFootnote );
441 void PrepareMake(vcl::RenderContext* pRenderContext);
442 void OptPrepareMake();
443 virtual void MakePos();
444 // Format next frame of table frame to assure keeping attributes.
445 // In case of nested tables method <SwFrame::MakeAll()> is called to
446 // avoid formatting of superior table frame.
447 friend SwFrame* sw_FormatNextContentForKeep( SwTabFrame* pTabFrame );
448
449 virtual void MakeAll(vcl::RenderContext* pRenderContext) = 0;
450 // adjust frames of a page
451 SwTwips AdjustNeighbourhood( SwTwips nDiff, bool bTst = false );
452
453 // change only frame size not the size of PrtArea
454 virtual SwTwips ShrinkFrame( SwTwips, bool bTst = false, bool bInfo = false ) = 0;
455 virtual SwTwips GrowFrame ( SwTwips, bool bTst = false, bool bInfo = false ) = 0;
456
457 /// use these so we can grep for SwFrame's GetRegisteredIn accesses
458 /// beware that SwTextFrame may return sw::WriterMultiListener
459 SwModify *GetDep() { return GetRegisteredInNonConst(); }
460 const SwModify *GetDep() const { return GetRegisteredIn(); }
461
462 SwFrame( SwModify*, SwFrame* );
463
464 void CheckDir( SvxFrameDirection nDir, bool bVert, bool bOnlyBiDi, bool bBrowse );
465
466 /** enumeration for the different invalidations
467 #i28701#
468 */
469 enum InvalidationType
470 {
471 INVALID_SIZE, INVALID_PRTAREA, INVALID_POS, INVALID_LINENUM, INVALID_ALL
472 };
473
474 /** method to determine, if an invalidation is allowed.
475 #i28701
476 */
477 virtual bool InvalidationAllowed( const InvalidationType _nInvalid ) const;
478
479 /** method to perform additional actions on an invalidation
480
481 #i28701#
482 Method has *only* to contain actions, which has to be performed on
483 *every* assignment of the corresponding flag to <false>.
484 */
485 virtual void ActionOnInvalidation( const InvalidationType _nInvalid );
486
487 // draw shadow and borders
488 void PaintShadow( const SwRect&, SwRect&, const SwBorderAttrs& ) const;
489 virtual void Modify( const SfxPoolItem*, const SfxPoolItem* ) override;
490
491 virtual const IDocumentDrawModelAccess& getIDocumentDrawModelAccess( );
492
493public:
494 virtual css::uno::Sequence< css::style::TabStop > GetTabStopInfo( SwTwips )
495 {
496 return css::uno::Sequence< css::style::TabStop >();
497 }
498
499
500 SwFrameType GetType() const { return mnFrameType; }
501
502 static SwCache &GetCache() { return *mpCache; }
503 static SwCache *GetCachePtr() { return mpCache; }
504 static void SetCache( SwCache *pNew ) { mpCache = pNew; }
505
506 // change PrtArea size and FrameSize
507 SwTwips Shrink( SwTwips, bool bTst = false, bool bInfo = false );
508 SwTwips Grow ( SwTwips, bool bTst = false, bool bInfo = false );
509
510 // different methods for inserting in layout tree (for performance reasons)
511
512 // insert before pBehind or at the end of the chain below mpUpper
513 void InsertBefore( SwLayoutFrame* pParent, SwFrame* pBehind );
514 // insert after pBefore or at the beginning of the chain below mpUpper
515 void InsertBehind( SwLayoutFrame *pParent, SwFrame *pBefore );
516 // insert before pBehind or at the end of the chain while considering
517 // the siblings of pSct
518 bool InsertGroupBefore( SwFrame* pParent, SwFrame* pWhere, SwFrame* pSct );
519 void RemoveFromLayout();
520
521 // For internal use only - who ignores this will be put in a sack and has
522 // to stay there for two days
523 // Does special treatment for Get_[Next|Prev]Leaf() (for tables).
524 SwLayoutFrame *GetLeaf( MakePageType eMakePage, bool bFwd );
525 SwLayoutFrame *GetNextLeaf ( MakePageType eMakePage );
526 SwLayoutFrame *GetNextFootnoteLeaf( MakePageType eMakePage );
527 SwLayoutFrame *GetNextSctLeaf( MakePageType eMakePage );
528 SwLayoutFrame *GetNextCellLeaf();
529 SwLayoutFrame *GetPrevLeaf ();
530 SwLayoutFrame *GetPrevFootnoteLeaf( MakePageType eMakeFootnote );
531 SwLayoutFrame *GetPrevSctLeaf();
532 SwLayoutFrame *GetPrevCellLeaf();
533 const SwLayoutFrame *GetLeaf ( MakePageType eMakePage, bool bFwd,
534 const SwFrame *pAnch ) const;
535
536 bool WrongPageDesc( SwPageFrame* pNew );
537
538 //#i28701# - new methods to append/remove drawing objects
539 void AppendDrawObj( SwAnchoredObject& _rNewObj );
540 void RemoveDrawObj( SwAnchoredObject& _rToRemoveObj );
541
542 // work with chain of FlyFrames
543 void AppendFly( SwFlyFrame *pNew );
544 void RemoveFly( SwFlyFrame *pToRemove );
545 const SwSortedObjs *GetDrawObjs() const { return m_pDrawObjs.get(); }
546 SwSortedObjs *GetDrawObjs() { return m_pDrawObjs.get(); }
547 // #i28701# - change purpose of method and adjust its name
548 void InvalidateObjs( const bool _bNoInvaOfAsCharAnchoredObjs = true );
549
550 virtual void PaintSwFrameShadowAndBorder(
551 const SwRect&,
552 const SwPageFrame* pPage,
553 const SwBorderAttrs&) const;
554 void PaintBaBo( const SwRect&, const SwPageFrame *pPage,
555 const bool bOnlyTextBackground = false) const;
556 void PaintSwFrameBackground( const SwRect&, const SwPageFrame *pPage,
557 const SwBorderAttrs &,
558 const bool bLowerMode = false,
559 const bool bLowerBorder = false,
560 const bool bOnlyTextBackground = false ) const;
561 void PaintBorderLine( const SwRect&, const SwRect&, const SwPageFrame*,
562 const Color *pColor,
563 const SvxBorderLineStyle = SvxBorderLineStyle::SOLID ) const;
564
565 std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> CreateProcessor2D( ) const;
566 void ProcessPrimitives( const drawinglayer::primitive2d::Primitive2DContainer& rSequence ) const;
567
568 // retouch, not in the area of the given Rect!
569 void Retouch( const SwPageFrame *pPage, const SwRect &rRect ) const;
570
571 bool GetBackgroundBrush(
572 drawinglayer::attribute::SdrAllFillAttributesHelperPtr& rFillAttributes,
573 const SvxBrushItem*& rpBrush,
574 const Color*& rpColor,
575 SwRect &rOrigRect,
576 bool bLowerMode,
577 bool bConsiderTextBox ) const;
578
579 inline void SetCompletePaint() const;
580 inline void ResetCompletePaint() const;
581 bool IsCompletePaint() const { return mbCompletePaint; }
582
583 inline void SetRetouche() const;
584 inline void ResetRetouche() const;
585 bool IsRetouche() const { return mbRetouche; }
586
587 void SetInfFlags();
588 void InvalidateInfFlags() { mbInfInvalid = true; }
589 inline bool IsInDocBody() const; // use InfoFlags, determine flags
590 inline bool IsInFootnote() const; // if necessary
591 inline bool IsInTab() const;
592 inline bool IsInFly() const;
593 inline bool IsInSct() const;
594
595 // If frame is inside a split table row, this function returns
596 // the corresponding row frame in the follow table.
597 const SwRowFrame* IsInSplitTableRow() const;
598
599 // If frame is inside a follow flow row, this function returns
600 // the corresponding row frame master table
601 const SwRowFrame* IsInFollowFlowRow() const;
602
603 bool IsInBalancedSection() const;
604
605 inline bool IsVertical() const;
606 inline bool IsVertLR() const;
607 inline bool IsVertLRBT() const;
608
609 void SetDerivedVert( bool bNew ){ mbDerivedVert = bNew; }
610 void SetInvalidVert( bool bNew) { mbInvalidVert = bNew; }
611 inline bool IsRightToLeft() const;
612 void SetDerivedR2L( bool bNew ) { mbDerivedR2L = bNew; }
613
614 void CheckDirChange();
615 // returns upper left frame position for LTR and
616 // upper right frame position for Asian / RTL frames
617 Point GetFrameAnchorPos( bool bIgnoreFlysAnchoredAtThisFrame ) const;
618
619 /** determine, if frame is moveable in given environment
620
621 method replaced 'old' method <bool IsMoveable() const>.
622 Determines, if frame is moveable in given environment. if no environment
623 is given (parameter _pLayoutFrame == 0), the movability in the actual
624 environment (<GetUpper()) is checked.
625
626 @param _pLayoutFrame
627 input parameter - given environment (layout frame), in which the movability
628 will be checked. If not set ( == 0 ), actual environment is taken.
629
630 @return boolean, indicating, if frame is moveable in given environment
631 */
632 bool IsMoveable( const SwLayoutFrame* _pLayoutFrame = nullptr ) const;
633
634 // Is it permitted for the (Text)Frame to add a footnote in the current
635 // environment (not e.g. for repeating table headlines)
636 bool IsFootnoteAllowed() const;
637
638 virtual void Format( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttrs = nullptr );
639
640 virtual void CheckDirection( bool bVert );
641
642 void ReinitializeFrameSizeAttrFlags();
643
644 /// WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for
645 /// SwTextFrame, use GetBreakItem()/GetPageDescItem() instead
646 const SwAttrSet *GetAttrSet() const;
647 virtual const SvxFormatBreakItem& GetBreakItem() const;
648 virtual const SwFormatPageDesc& GetPageDescItem() const;
649
650 bool HasFixSize() const { return mbFixSize; }
651
652 // check all pages (starting from the given) and correct them if needed
653 static void CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields = true, SwPageFrame** ppPrev = nullptr);
654
655 // might return 0, with and without const
656 SwFrame *GetNext() { return mpNext; }
657 SwFrame *GetPrev() { return mpPrev; }
658 SwLayoutFrame *GetUpper() { return mpUpper; }
659 SwRootFrame *getRootFrame(){ return mpRoot; }
660 SwPageFrame *FindPageFrame() { return IsPageFrame() ? reinterpret_cast<SwPageFrame*>(this) : ImplFindPageFrame(); }
661 SwFrame *FindColFrame();
662 SwRowFrame *FindRowFrame();
663 SwFootnoteBossFrame *FindFootnoteBossFrame( bool bFootnotes = false );
664 SwTabFrame *ImplFindTabFrame();
665 SwFootnoteFrame *ImplFindFootnoteFrame();
666 SwFlyFrame *ImplFindFlyFrame();
667 SwSectionFrame *ImplFindSctFrame();
668 const SwBodyFrame *ImplFindBodyFrame() const;
669 SwFrame *FindFooterOrHeader();
670 SwFrame *GetLower();
671 const SwFrame *GetNext() const { return mpNext; }
672 const SwFrame *GetPrev() const { return mpPrev; }
673 const SwLayoutFrame *GetUpper() const { return mpUpper; }
674 const SwRootFrame *getRootFrame() const { return mpRoot; }
675 inline SwTabFrame *FindTabFrame();
676 inline SwFootnoteFrame *FindFootnoteFrame();
677 inline SwFlyFrame *FindFlyFrame();
678 inline SwSectionFrame *FindSctFrame();
679 inline SwFrame *FindNext();
680 // #i27138# - add parameter <_bInSameFootnote>
681 SwContentFrame* FindNextCnt( const bool _bInSameFootnote = false );
682 inline SwFrame *FindPrev();
683 inline const SwPageFrame *FindPageFrame() const;
684 inline const SwFootnoteBossFrame *FindFootnoteBossFrame( bool bFootnote = false ) const;
685 inline const SwFrame *FindColFrame() const;
686 inline const SwFrame *FindFooterOrHeader() const;
687 inline const SwTabFrame *FindTabFrame() const;
688 inline const SwFootnoteFrame *FindFootnoteFrame() const;
689 inline const SwFlyFrame *FindFlyFrame() const;
690 inline const SwSectionFrame *FindSctFrame() const;
691 inline const SwBodyFrame *FindBodyFrame() const;
692 inline const SwFrame *FindNext() const;
693 // #i27138# - add parameter <_bInSameFootnote>
694 const SwContentFrame* FindNextCnt( const bool _bInSameFootnote = false ) const;
695 inline const SwFrame *FindPrev() const;
696 const SwFrame *GetLower() const;
697
698 SwContentFrame* FindPrevCnt();
699
700 const SwContentFrame* FindPrevCnt() const;
701
702 // #i79774#
703 SwFrame* GetIndPrev_() const;
704 SwFrame* GetIndPrev() const
705 { return ( mpPrev || !IsInSct() ) ? mpPrev : GetIndPrev_(); }
706
707 SwFrame* GetIndNext()
708 { return ( mpNext || !IsInSct() ) ? mpNext : GetIndNext_(); }
709 const SwFrame* GetIndNext() const { return const_cast<SwFrame*>(this)->GetIndNext(); }
710
711 sal_uInt16 GetPhyPageNum() const; // page number without offset
712 sal_uInt16 GetVirtPageNum() const; // page number with offset
713 bool OnRightPage() const { return 0 != GetPhyPageNum() % 2; };
714 bool WannaRightPage() const;
715 bool OnFirstPage() const;
716
717 inline const SwLayoutFrame *GetPrevLayoutLeaf() const;
718 inline const SwLayoutFrame *GetNextLayoutLeaf() const;
719 inline SwLayoutFrame *GetPrevLayoutLeaf();
720 inline SwLayoutFrame *GetNextLayoutLeaf();
721
722 virtual void Calc(vcl::RenderContext* pRenderContext) const; // here might be "formatted"
723 inline void OptCalc() const; // here we assume (for optimization) that
724 // the predecessors are already formatted
725 Point GetRelPos() const;
726
727 // PaintArea is the area where content might be displayed.
728 // The margin of a page or the space between columns belongs to it.
729 SwRect GetPaintArea() const;
730
731 // UnionFrame is the union of Frame- and PrtArea, normally identical
732 // to the FrameArea except in case of negative Prt margins.
733 SwRect UnionFrame( bool bBorder = false ) const;
734
735 virtual Size ChgSize( const Size& aNewSize );
736
737 virtual void Cut() = 0;
738 virtual void Paste( SwFrame* pParent, SwFrame* pSibling = nullptr ) = 0;
739
740 void ValidateLineNum() { mbValidLineNum = true; }
741
742 bool GetValidLineNumFlag()const { return mbValidLineNum; }
743
744 // Only invalidate Frame
745 // #i28701# - add call to method <ActionOnInvalidation(..)>
746 // for all invalidation methods.
747 // #i28701# - use method <InvalidationAllowed(..)> to
748 // decide, if invalidation will to be performed or not.
749 // #i26945# - no additional invalidation, if it's already
750 // invalidate.
751 void InvalidateSize_()
752 {
753 if ( isFrameAreaSizeValid() && InvalidationAllowed( INVALID_SIZE ) )
754 {
755 setFrameAreaSizeValid(false);
756 ActionOnInvalidation( INVALID_SIZE );
757 }
758 }
759 void InvalidatePrt_()
760 {
761 if ( isFramePrintAreaValid() && InvalidationAllowed( INVALID_PRTAREA ) )
762 {
763 setFramePrintAreaValid(false);
764 ActionOnInvalidation( INVALID_PRTAREA );
765 }
766 }
767 void InvalidatePos_()
768 {
769 if ( isFrameAreaPositionValid() && InvalidationAllowed( INVALID_POS ) )
770 {
771 setFrameAreaPositionValid(false);
772 ActionOnInvalidation( INVALID_POS );
773 }
774 }
775 void InvalidateLineNum_()
776 {
777 if ( mbValidLineNum && InvalidationAllowed( INVALID_LINENUM ) )
778 {
779 mbValidLineNum = false;
780 ActionOnInvalidation( INVALID_LINENUM );
781 }
782 }
783 void InvalidateAll_()
784 {
785 if ( ( isFrameAreaSizeValid() || isFramePrintAreaValid() || isFrameAreaPositionValid() ) && InvalidationAllowed( INVALID_ALL ) )
786 {
787 setFrameAreaSizeValid(false);
788 setFrameAreaPositionValid(false);
789 setFramePrintAreaValid(false);
790 ActionOnInvalidation( INVALID_ALL );
791 }
792 }
793 // also notify page at the same time
794 inline void InvalidateSize();
795 inline void InvalidatePrt();
796 inline void InvalidatePos();
797 inline void InvalidateLineNum();
798 inline void InvalidateAll();
799 void ImplInvalidateSize();
800 void ImplInvalidatePrt();
801 void ImplInvalidatePos();
802 void ImplInvalidateLineNum();
803
804 inline void InvalidateNextPos( bool bNoFootnote = false );
805 void ImplInvalidateNextPos( bool bNoFootnote );
806
807 /** method to invalidate printing area of next frame
808 #i11859#
809 */
810 void InvalidateNextPrtArea();
811
812 void InvalidatePage( const SwPageFrame *pPage = nullptr ) const;
813
814 virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const;
815
816 virtual bool GetModelPositionForViewPoint( SwPosition *, Point&,
817 SwCursorMoveState* = nullptr, bool bTestBackground = false ) const;
818 virtual bool GetCharRect( SwRect &, const SwPosition&,
819 SwCursorMoveState* = nullptr, bool bAllowFarAway = true ) const;
820 virtual void PaintSwFrame( vcl::RenderContext& rRenderContext, SwRect const&,
821 SwPrintData const*const pPrintData = nullptr ) const;
822
823 // HACK: shortcut between frame and formatting
824 // It's your own fault if you cast void* incorrectly! In any case check
825 // the void* for 0.
826 virtual bool Prepare( const PrepareHint ePrep = PrepareHint::Clear,
827 const void *pVoid = nullptr, bool bNotify = true );
828
829 // true if it is the correct class, false otherwise
830 inline bool IsLayoutFrame() const;
831 inline bool IsRootFrame() const;
832 inline bool IsPageFrame() const;
833 inline bool IsColumnFrame() const;
834 inline bool IsFootnoteBossFrame() const; // footnote bosses might be PageFrames or ColumnFrames
835 inline bool IsHeaderFrame() const;
836 inline bool IsFooterFrame() const;
837 inline bool IsFootnoteContFrame() const;
838 inline bool IsFootnoteFrame() const;
839 inline bool IsBodyFrame() const;
840 inline bool IsColBodyFrame() const; // implemented in layfrm.hxx, BodyFrame above ColumnFrame
841 inline bool IsPageBodyFrame() const; // implemented in layfrm.hxx, BodyFrame above PageFrame
842 inline bool IsFlyFrame() const;
843 inline bool IsSctFrame() const;
844 inline bool IsTabFrame() const;
845 inline bool IsRowFrame() const;
846 inline bool IsCellFrame() const;
847 inline bool IsContentFrame() const;
848 inline bool IsTextFrame() const;
849 inline bool IsNoTextFrame() const;
850 // Frames where its PrtArea depends on their neighbors and that are
851 // positioned in the content flow
852 inline bool IsFlowFrame() const;
853 // Frames that are capable of retouching or that might need to retouch behind
854 // themselves
855 inline bool IsRetoucheFrame() const;
856 inline bool IsAccessibleFrame() const;
857
858 void PrepareCursor(); // CursorShell is allowed to call this
859
860 // Is the Frame (or the section containing it) protected? Same for Fly in
861 // Fly in ... and footnotes
862 bool IsProtected() const;
863
864 bool IsColLocked() const { return mbColLocked; }
865 virtual bool IsDeleteForbidden() const { return mbForbidDelete; }
866
867 /// this is the only way to delete a SwFrame instance
868 static void DestroyFrame(SwFrame *const pFrame);
869
870 bool IsInDtor() const { return mbInDtor; }
871
872 // No inline cause we need the function pointers
873 long GetTopMargin() const;
874 long GetBottomMargin() const;
875 long GetLeftMargin() const;
876 long GetRightMargin() const;
877 void SetTopBottomMargins( long, long );
878 void SetLeftRightMargins( long, long );
879 void SetRightLeftMargins( long, long );
880 long GetPrtLeft() const;
881 long GetPrtBottom() const;
882 long GetPrtRight() const;
883 long GetPrtTop() const;
884 bool SetMinLeft( long );
885 bool SetMaxBottom( long );
886 bool SetMaxRight( long );
887 void MakeBelowPos( const SwFrame*, const SwFrame*, bool );
888 void MakeLeftPos( const SwFrame*, const SwFrame*, bool );
889 void MakeRightPos( const SwFrame*, const SwFrame*, bool );
890 bool IsNeighbourFrame() const
891 { return bool(GetType() & FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell)); }
892
893 // NEW TABLES
894 // Some functions for covered/covering table cells. This way unnecessary
895 // includes can be avoided
896 virtual bool IsLeaveUpperAllowed() const;
897 virtual bool IsCoveredCell() const;
898 bool IsInCoveredCell() const;
899
900 // #i81146# new loop control
901 bool KnowsFormat( const SwFormat& rFormat ) const;
902 void RegisterToFormat( SwFormat& rFormat );
903 void ValidateThisAndAllLowers( const sal_uInt16 nStage );
904
905 void ForbidDelete() { mbForbidDelete = true; }
906 void AllowDelete() { mbForbidDelete = false; }
907
908 drawinglayer::attribute::SdrAllFillAttributesHelperPtr getSdrAllFillAttributesHelper() const;
909 bool supportsFullDrawingLayerFillAttributeSet() const;
910
911public:
912 // if writer is NULL, dumps the layout structure as XML in layout.xml
913 virtual void dumpAsXml(xmlTextWriterPtr writer = nullptr) const;
914 void dumpTopMostAsXml(xmlTextWriterPtr writer = nullptr) const;
915 void dumpInfosAsXml(xmlTextWriterPtr writer) const;
916 virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const;
917 void dumpChildrenAsXml(xmlTextWriterPtr writer) const;
918 bool IsCollapse() const;
919};
920
921inline bool SwFrame::IsInDocBody() const
922{
923 if ( mbInfInvalid )
924 const_cast<SwFrame*>(this)->SetInfFlags();
925 return mbInfBody;
926}
927inline bool SwFrame::IsInFootnote() const
928{
929 if ( mbInfInvalid )
930 const_cast<SwFrame*>(this)->SetInfFlags();
931 return mbInfFootnote;
932}
933inline bool SwFrame::IsInTab() const
934{
935 if ( mbInfInvalid )
936 const_cast<SwFrame*>(this)->SetInfFlags();
937 return mbInfTab;
938}
939inline bool SwFrame::IsInFly() const
940{
941 if ( mbInfInvalid )
942 const_cast<SwFrame*>(this)->SetInfFlags();
943 return mbInfFly;
944}
945inline bool SwFrame::IsInSct() const
946{
947 if ( mbInfInvalid )
948 const_cast<SwFrame*>(this)->SetInfFlags();
949 return mbInfSct;
950}
951bool SwFrame::IsVertical() const
952{
953 if( mbInvalidVert )
954 const_cast<SwFrame*>(this)->SetDirFlags( true );
955 return mbVertical;
956}
957inline bool SwFrame::IsVertLR() const
958{
959 return mbVertLR;
960}
961inline bool SwFrame::IsVertLRBT() const
962{
963 return mbVertLRBT;
964}
965inline bool SwFrame::IsRightToLeft() const
966{
967 if( mbInvalidR2L )
968 const_cast<SwFrame*>(this)->SetDirFlags( false );
969 return mbRightToLeft;
970}
971
972inline void SwFrame::SetCompletePaint() const
973{
974 const_cast<SwFrame*>(this)->mbCompletePaint = true;
975}
976inline void SwFrame::ResetCompletePaint() const
977{
978 const_cast<SwFrame*>(this)->mbCompletePaint = false;
979}
980
981inline void SwFrame::SetRetouche() const
982{
983 const_cast<SwFrame*>(this)->mbRetouche = true;
984}
985inline void SwFrame::ResetRetouche() const
986{
987 const_cast<SwFrame*>(this)->mbRetouche = false;
988}
989
990inline SwLayoutFrame *SwFrame::GetNextLayoutLeaf()
991{
992 return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetNextLayoutLeaf());
993}
994inline SwLayoutFrame *SwFrame::GetPrevLayoutLeaf()
995{
996 return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetPrevLayoutLeaf());
997}
998inline const SwLayoutFrame *SwFrame::GetNextLayoutLeaf() const
999{
1000 return ImplGetNextLayoutLeaf( true );
1001}
1002inline const SwLayoutFrame *SwFrame::GetPrevLayoutLeaf() const
1003{
1004 return ImplGetNextLayoutLeaf( false );
1005}
1006
1007inline void SwFrame::InvalidateSize()
1008{
1009 if ( isFrameAreaSizeValid() )
1010 {
1011 ImplInvalidateSize();
1012 }
1013}
1014inline void SwFrame::InvalidatePrt()
1015{
1016 if ( isFramePrintAreaValid() )
1017 {
1018 ImplInvalidatePrt();
1019 }
1020}
1021inline void SwFrame::InvalidatePos()
1022{
1023 if ( isFrameAreaPositionValid() )
1024 {
1025 ImplInvalidatePos();
1026 }
1027}
1028inline void SwFrame::InvalidateLineNum()
1029{
1030 if ( mbValidLineNum )
1031 ImplInvalidateLineNum();
1032}
1033inline void SwFrame::InvalidateAll()
1034{
1035 if ( InvalidationAllowed( INVALID_ALL ) )
1036 {
1037 if ( isFrameAreaDefinitionValid() )
1038 {
1039 ImplInvalidatePos();
1040 }
1041
1042 setFrameAreaSizeValid(false);
1043 setFrameAreaPositionValid(false);
1044 setFramePrintAreaValid(false);
1045
1046 // #i28701#
1047 ActionOnInvalidation( INVALID_ALL );
1048 }
1049}
1050inline void SwFrame::InvalidateNextPos( bool bNoFootnote )
1051{
1052 if ( mpNext && !mpNext->IsSctFrame() )
1053 mpNext->InvalidatePos();
1054 else
1055 ImplInvalidateNextPos( bNoFootnote );
1056}
1057
1058inline void SwFrame::OptCalc() const
1059{
1060 if ( !isFrameAreaPositionValid() || !isFramePrintAreaValid() || !isFrameAreaSizeValid() )
1061 {
1062 const_cast<SwFrame*>(this)->OptPrepareMake();
1063 }
1064}
1065inline const SwPageFrame *SwFrame::FindPageFrame() const
1066{
1067 return const_cast<SwFrame*>(this)->FindPageFrame();
1068}
1069inline const SwFrame *SwFrame::FindColFrame() const
1070{
1071 return const_cast<SwFrame*>(this)->FindColFrame();
1072}
1073inline const SwFrame *SwFrame::FindFooterOrHeader() const
1074{
1075 return const_cast<SwFrame*>(this)->FindFooterOrHeader();
1076}
1077inline SwTabFrame *SwFrame::FindTabFrame()
1078{
1079 return IsInTab() ? ImplFindTabFrame() : nullptr;
1080}
1081inline const SwFootnoteBossFrame *SwFrame::FindFootnoteBossFrame( bool bFootnote ) const
1082{
1083 return const_cast<SwFrame*>(this)->FindFootnoteBossFrame( bFootnote );
1084}
1085inline SwFootnoteFrame *SwFrame::FindFootnoteFrame()
1086{
1087 return IsInFootnote() ? ImplFindFootnoteFrame() : nullptr;
11
Assuming the condition is true
12
'?' condition is true
13
Returning pointer
1088}
1089inline SwFlyFrame *SwFrame::FindFlyFrame()
1090{
1091 return IsInFly() ? ImplFindFlyFrame() : nullptr;
1092}
1093inline SwSectionFrame *SwFrame::FindSctFrame()
1094{
1095 return IsInSct() ? ImplFindSctFrame() : nullptr;
1096}
1097
1098inline const SwBodyFrame *SwFrame::FindBodyFrame() const
1099{
1100 return IsInDocBody() ? ImplFindBodyFrame() : nullptr;
1101}
1102
1103inline const SwTabFrame *SwFrame::FindTabFrame() const
1104{
1105 return IsInTab() ? const_cast<SwFrame*>(this)->ImplFindTabFrame() : nullptr;
1106}
1107inline const SwFootnoteFrame *SwFrame::FindFootnoteFrame() const
1108{
1109 return IsInFootnote() ? const_cast<SwFrame*>(this)->ImplFindFootnoteFrame() : nullptr;
1110}
1111inline const SwFlyFrame *SwFrame::FindFlyFrame() const
1112{
1113 return IsInFly() ? const_cast<SwFrame*>(this)->ImplFindFlyFrame() : nullptr;
1114}
1115inline const SwSectionFrame *SwFrame::FindSctFrame() const
1116{
1117 return IsInSct() ? const_cast<SwFrame*>(this)->ImplFindSctFrame() : nullptr;
1118}
1119inline SwFrame *SwFrame::FindNext()
1120{
1121 if ( mpNext )
1122 return mpNext;
1123 else
1124 return FindNext_();
1125}
1126inline const SwFrame *SwFrame::FindNext() const
1127{
1128 if ( mpNext )
1129 return mpNext;
1130 else
1131 return const_cast<SwFrame*>(this)->FindNext_();
1132}
1133inline SwFrame *SwFrame::FindPrev()
1134{
1135 if ( mpPrev && !mpPrev->IsSctFrame() )
1136 return mpPrev;
1137 else
1138 return FindPrev_();
1139}
1140inline const SwFrame *SwFrame::FindPrev() const
1141{
1142 if ( mpPrev && !mpPrev->IsSctFrame() )
1143 return mpPrev;
1144 else
1145 return const_cast<SwFrame*>(this)->FindPrev_();
1146}
1147
1148inline bool SwFrame::IsLayoutFrame() const
1149{
1150 return bool(GetType() & FRM_LAYOUTSwFrameType(0x3bFF));
1151}
1152inline bool SwFrame::IsRootFrame() const
1153{
1154 return mnFrameType == SwFrameType::Root;
1155}
1156inline bool SwFrame::IsPageFrame() const
1157{
1158 return mnFrameType == SwFrameType::Page;
1159}
1160inline bool SwFrame::IsColumnFrame() const
1161{
1162 return mnFrameType == SwFrameType::Column;
1163}
1164inline bool SwFrame::IsFootnoteBossFrame() const
1165{
1166 return bool(GetType() & FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column));
1167}
1168inline bool SwFrame::IsHeaderFrame() const
1169{
1170 return mnFrameType == SwFrameType::Header;
1171}
1172inline bool SwFrame::IsFooterFrame() const
1173{
1174 return mnFrameType == SwFrameType::Footer;
1175}
1176inline bool SwFrame::IsFootnoteContFrame() const
1177{
1178 return mnFrameType == SwFrameType::FtnCont;
1179}
1180inline bool SwFrame::IsFootnoteFrame() const
1181{
1182 return mnFrameType == SwFrameType::Ftn;
1183}
1184inline bool SwFrame::IsBodyFrame() const
1185{
1186 return mnFrameType == SwFrameType::Body;
1187}
1188inline bool SwFrame::IsFlyFrame() const
1189{
1190 return mnFrameType == SwFrameType::Fly;
1191}
1192inline bool SwFrame::IsSctFrame() const
1193{
1194 return mnFrameType == SwFrameType::Section;
1195}
1196inline bool SwFrame::IsTabFrame() const
1197{
1198 return mnFrameType == SwFrameType::Tab;
1199}
1200inline bool SwFrame::IsRowFrame() const
1201{
1202 return mnFrameType == SwFrameType::Row;
1203}
1204inline bool SwFrame::IsCellFrame() const
1205{
1206 return mnFrameType == SwFrameType::Cell;
1207}
1208inline bool SwFrame::IsContentFrame() const
1209{
1210 return bool(GetType() & FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt));
1211}
1212inline bool SwFrame::IsTextFrame() const
1213{
1214 return mnFrameType == SwFrameType::Txt;
1215}
1216inline bool SwFrame::IsNoTextFrame() const
1217{
1218 return mnFrameType == SwFrameType::NoTxt;
1219}
1220inline bool SwFrame::IsFlowFrame() const
1221{
1222 return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section));
1223}
1224inline bool SwFrame::IsRetoucheFrame() const
1225{
1226 return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section|SwFrameType::Ftn));
1227}
1228inline bool SwFrame::IsAccessibleFrame() const
1229{
1230 return bool(GetType() & FRM_ACCESSIBLE(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header |
SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType
::Tab | SwFrameType::Cell | SwFrameType::Txt)
);
1231}
1232
1233//use this to protect a SwFrame for a given scope from getting deleted
1234class SwFrameDeleteGuard
1235{
1236private:
1237 SwFrame *m_pForbidFrame;
1238public:
1239 //Flag pFrame for SwFrameDeleteGuard lifetime that we shouldn't delete
1240 //it in e.g. SwSectionFrame::MergeNext etc because we will need it
1241 //again after the SwFrameDeleteGuard dtor
1242 explicit SwFrameDeleteGuard(SwFrame* pFrame)
1243 : m_pForbidFrame((pFrame && !pFrame->IsDeleteForbidden()) ?
1244 pFrame : nullptr)
1245 {
1246 if (m_pForbidFrame)
1247 m_pForbidFrame->ForbidDelete();
1248 }
1249
1250 SwFrameDeleteGuard(const SwFrameDeleteGuard&) =delete;
1251
1252 ~SwFrameDeleteGuard()
1253 {
1254 if (m_pForbidFrame)
1255 m_pForbidFrame->AllowDelete();
1256 }
1257
1258 SwFrameDeleteGuard& operator=(const SwFrameDeleteGuard&) =delete;
1259};
1260
1261typedef long (SwFrame::*SwFrameGet)() const;
1262typedef bool (SwFrame::*SwFrameMax)( long );
1263typedef void (SwFrame::*SwFrameMakePos)( const SwFrame*, const SwFrame*, bool );
1264typedef long (*SwOperator)( long, long );
1265typedef void (SwFrame::*SwFrameSet)( long, long );
1266
1267struct SwRectFnCollection
1268{
1269 SwRectGet fnGetTop;
1270 SwRectGet fnGetBottom;
1271 SwRectGet fnGetLeft;
1272 SwRectGet fnGetRight;
1273 SwRectGet fnGetWidth;
1274 SwRectGet fnGetHeight;
1275 SwRectPoint fnGetPos;
1276 SwRectSize fnGetSize;
1277
1278 SwRectSet fnSetTop;
1279 SwRectSet fnSetBottom;
1280 SwRectSet fnSetLeft;
1281 SwRectSet fnSetRight;
1282 SwRectSet fnSetWidth;
1283 SwRectSet fnSetHeight;
1284
1285 SwRectSet fnSubTop;
1286 SwRectSet fnAddBottom;
1287 SwRectSet fnSubLeft;
1288 SwRectSet fnAddRight;
1289 SwRectSet fnAddWidth;
1290 SwRectSet fnAddHeight;
1291
1292 SwRectSet fnSetPosX;
1293 SwRectSet fnSetPosY;
1294
1295 SwFrameGet fnGetTopMargin;
1296 SwFrameGet fnGetBottomMargin;
1297 SwFrameGet fnGetLeftMargin;
1298 SwFrameGet fnGetRightMargin;
1299 SwFrameSet fnSetXMargins;
1300 SwFrameSet fnSetYMargins;
1301 SwFrameGet fnGetPrtTop;
1302 SwFrameGet fnGetPrtBottom;
1303 SwFrameGet fnGetPrtLeft;
1304 SwFrameGet fnGetPrtRight;
1305 SwRectDist fnTopDist;
1306 SwRectDist fnBottomDist;
1307 SwRectDist fnLeftDist;
1308 SwRectDist fnRightDist;
1309 SwFrameMax fnSetLimit;
1310 SwRectMax fnOverStep;
1311
1312 SwRectSetPos fnSetPos;
1313 SwFrameMakePos fnMakePos;
1314 SwOperator fnXDiff;
1315 SwOperator fnYDiff;
1316 SwOperator fnXInc;
1317 SwOperator fnYInc;
1318
1319 SwRectSetTwice fnSetLeftAndWidth;
1320 SwRectSetTwice fnSetTopAndHeight;
1321};
1322
1323typedef SwRectFnCollection* SwRectFn;
1324
1325// This class allows to use proper methods regardless of orientation (LTR/RTL, horizontal or vertical)
1326extern SwRectFn fnRectHori, fnRectVert, fnRectVertL2R, fnRectVertL2RB2T;
1327class SwRectFnSet {
1328public:
1329 explicit SwRectFnSet(const SwFrame *pFrame)
1330 : m_bVert(pFrame->IsVertical())
1331 , m_bVertL2R(pFrame->IsVertLR())
1332 , m_bVertL2RB2T(pFrame->IsVertLRBT())
1333 {
1334 m_fnRect = m_bVert ? (m_bVertL2R ? (m_bVertL2RB2T ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert) : fnRectHori;
1335 }
1336
1337 void Refresh(const SwFrame *pFrame)
1338 {
1339 m_bVert = pFrame->IsVertical();
1340 m_bVertL2R = pFrame->IsVertLR();
1341 m_bVertL2RB2T = pFrame->IsVertLRBT();
1342 m_fnRect = m_bVert ? (m_bVertL2R ? (m_bVertL2RB2T ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert) : fnRectHori;
1343 }
1344
1345 bool IsVert() const { return m_bVert; }
1346 bool IsVertL2R() const { return m_bVertL2R; }
1347 SwRectFn FnRect() const { return m_fnRect; }
1348
1349 bool PosDiff(const SwRect &rRect1, const SwRect &rRect2) const
1350 {
1351 return ((rRect1.*m_fnRect->fnGetTop)() != (rRect2.*m_fnRect->fnGetTop)()
1352 || (rRect1.*m_fnRect->fnGetLeft)() != (rRect2.*m_fnRect->fnGetLeft)());
1353 }
1354
1355 long GetTop (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetTop) (); }
1356 long GetBottom(const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetBottom)(); }
1357 long GetLeft (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetLeft) (); }
1358 long GetRight (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetRight) (); }
1359 long GetWidth (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetWidth) (); }
1360 long GetHeight(const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetHeight)(); }
1361 Point GetPos (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetPos) (); }
1362 Size GetSize (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetSize) (); }
1363
1364 void SetTop (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetTop) (nNew); }
1365 void SetBottom(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetBottom)(nNew); }
1366 void SetLeft (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetLeft) (nNew); }
1367 void SetRight (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetRight) (nNew); }
1368 void SetWidth (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetWidth) (nNew); }
1369 void SetHeight(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetHeight)(nNew); }
1370
1371 void SubTop (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSubTop) (nNew); }
1372 void AddBottom(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddBottom)(nNew); }
1373 void SubLeft (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSubLeft) (nNew); }
1374 void AddRight (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddRight) (nNew); }
1375 void AddWidth (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddWidth) (nNew); }
1376 void AddHeight(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddHeight)(nNew); }
1377
1378 void SetPosX(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetPosX)(nNew); }
1379 void SetPosY(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetPosY)(nNew); }
1380
1381 long GetTopMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetTopMargin) (); }
1382 long GetBottomMargin(const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetBottomMargin)(); }
1383 long GetLeftMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetLeftMargin) (); }
1384 long GetRightMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetRightMargin) (); }
1385 void SetXMargins(SwFrame& rFrame, long nLeft, long nRight) const { (rFrame.*m_fnRect->fnSetXMargins)(nLeft, nRight); }
1386 void SetYMargins(SwFrame& rFrame, long nTop, long nBottom) const { (rFrame.*m_fnRect->fnSetYMargins)(nTop, nBottom); }
1387 long GetPrtTop (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtTop) (); }
1388 long GetPrtBottom (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtBottom) (); }
1389 long GetPrtLeft (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtLeft) (); }
1390 long GetPrtRight (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtRight) (); }
1391 long TopDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnTopDist) (nPos); }
1392 long BottomDist(const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnBottomDist) (nPos); }
1393 long LeftDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnLeftDist) (nPos); }
1394 long RightDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnRightDist) (nPos); }
1395 void SetLimit (SwFrame& rFrame, long nNew) const { (rFrame.*m_fnRect->fnSetLimit) (nNew); }
1396 bool OverStep (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnOverStep) (nPos); }
1397
1398 void SetPos(SwRect& rRect, const Point& rNew) const { (rRect.*m_fnRect->fnSetPos)(rNew); }
1399 void MakePos(SwFrame& rFrame, const SwFrame* pUp, const SwFrame* pPrv, bool bNotify) const { (rFrame.*m_fnRect->fnMakePos)(pUp, pPrv, bNotify); }
1400 long XDiff(long n1, long n2) const { return (m_fnRect->fnXDiff) (n1, n2); }
1401 long YDiff(long n1, long n2) const { return (m_fnRect->fnYDiff) (n1, n2); }
1402 long XInc (long n1, long n2) const { return (m_fnRect->fnXInc) (n1, n2); }
1403 long YInc (long n1, long n2) const { return (m_fnRect->fnYInc) (n1, n2); }
1404
1405 void SetLeftAndWidth(SwRect& rRect, long nLeft, long nWidth) const { (rRect.*m_fnRect->fnSetLeftAndWidth)(nLeft, nWidth); }
1406 void SetTopAndHeight(SwRect& rRect, long nTop, long nHeight) const { (rRect.*m_fnRect->fnSetTopAndHeight)(nTop, nHeight); }
1407
1408private:
1409 bool m_bVert;
1410 bool m_bVertL2R;
1411 bool m_bVertL2RB2T;
1412 SwRectFn m_fnRect;
1413};
1414
1415#endif
1416
1417/* vim:set shiftwidth=4 softtabstop=4 expandtab: */