Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx
Warning:line 656, column 50
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 txtftn.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/text/txtftn.cxx

/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.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 <viewsh.hxx>
21#include <doc.hxx>
22#include <IDocumentLayoutAccess.hxx>
23#include <pagefrm.hxx>
24#include <rootfrm.hxx>
25#include <ndtxt.hxx>
26#include <SwPortionHandler.hxx>
27#include <txtftn.hxx>
28#include <flyfrm.hxx>
29#include <fmtftn.hxx>
30#include <ftninfo.hxx>
31#include <charfmt.hxx>
32#include <rowfrm.hxx>
33#include <editeng/brushitem.hxx>
34#include <editeng/charrotateitem.hxx>
35#include <tabfrm.hxx>
36#include <sortedobjs.hxx>
37
38#include <swfont.hxx>
39#include "porftn.hxx"
40#include "porfly.hxx"
41#include "porlay.hxx"
42#include <txtfrm.hxx>
43#include "itrform2.hxx"
44#include <ftnfrm.hxx>
45#include <pagedesc.hxx>
46#include "redlnitr.hxx"
47#include <sectfrm.hxx>
48#include <layouter.hxx>
49#include <frmtool.hxx>
50#include <ndindex.hxx>
51#include <IDocumentSettingAccess.hxx>
52
53#include <com/sun/star/beans/XPropertySet.hpp>
54#include <com/sun/star/awt/CharSet.hpp>
55#include <com/sun/star/text/XTextRange.hpp>
56
57using namespace ::com::sun::star;
58
59bool SwTextFrame::IsFootnoteNumFrame_() const
60{
61 if (IsInTab())
62 return false; // tdf#102073 first frame in cell doesn't have mpPrev set
63 const SwFootnoteFrame* pFootnote = FindFootnoteFrame()->GetMaster();
64 while( pFootnote && !pFootnote->ContainsContent() )
65 pFootnote = pFootnote->GetMaster();
66 return !pFootnote;
67}
68
69/**
70 * Looks for the TextFrame matching the SwTextFootnote within a master-follow chain
71 */
72SwTextFrame *SwTextFrame::FindFootnoteRef( const SwTextFootnote *pFootnote )
73{
74 SwTextFrame *pFrame = this;
75 const bool bFwd = MapModelToView(&pFootnote->GetTextNode(), pFootnote->GetStart()) >= GetOffset();
76 while( pFrame )
77 {
78 if( SwFootnoteBossFrame::FindFootnote( pFrame, pFootnote ) )
79 return pFrame;
80 pFrame = bFwd ? pFrame->GetFollow() :
81 pFrame->IsFollow() ? pFrame->FindMaster() : nullptr;
82 }
83 return pFrame;
84}
85
86void SwTextFrame::SetHasRotatedPortions(bool bHasRotatedPortions)
87{
88 mbHasRotatedPortions = bHasRotatedPortions;
89}
90
91#ifdef DBG_UTIL
92void SwTextFrame::CalcFootnoteFlag(TextFrameIndex nStop) // For testing the SplitFrame
93#else
94void SwTextFrame::CalcFootnoteFlag()
95#endif
96{
97 mbFootnote = false;
98
99#ifdef DBG_UTIL
100 const TextFrameIndex nEnd = nStop != TextFrameIndex(COMPLETE_STRING)
101 ? nStop
102 : GetFollow() ? GetFollow()->GetOffset() : TextFrameIndex(COMPLETE_STRING);
103#else
104 const TextFrameIndex nEnd = GetFollow()
105 ? GetFollow()->GetOffset()
106 : TextFrameIndex(COMPLETE_STRING);
107#endif
108
109 SwTextNode const* pNode(nullptr);
110 sw::MergedAttrIter iter(*this);
111 for (SwTextAttr const* pHt = iter.NextAttr(&pNode); pHt; pHt = iter.NextAttr(&pNode))
112 {
113 if ( pHt->Which() == RES_TXTATR_FTN )
114 {
115 TextFrameIndex const nIdx(MapModelToView(pNode, pHt->GetStart()));
116 if ( nEnd < nIdx )
117 break;
118 if( GetOffset() <= nIdx )
119 {
120 mbFootnote = true;
121 break;
122 }
123 }
124 }
125}
126
127bool SwTextFrame::CalcPrepFootnoteAdjust()
128{
129 OSL_ENSURE( HasFootnote(), "Who´s calling me?" )do { if (true && (!(HasFootnote()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "129" ": "), "%s", "Who´s calling me?"); } } while (false
)
;
130 SwFootnoteBossFrame *pBoss = FindFootnoteBossFrame( true );
131 const SwFootnoteFrame *pFootnote = pBoss->FindFirstFootnote( this );
132 if (pFootnote && FTNPOS_CHAPTER != GetDoc().GetFootnoteInfo().m_ePos &&
133 ( !pBoss->GetUpper()->IsSctFrame() ||
134 !static_cast<SwSectionFrame*>(pBoss->GetUpper())->IsFootnoteAtEnd() ) )
135 {
136 const SwFootnoteContFrame *pCont = pBoss->FindFootnoteCont();
137 bool bReArrange = true;
138
139 SwRectFnSet aRectFnSet(this);
140 if ( pCont && aRectFnSet.YDiff( aRectFnSet.GetTop(pCont->getFrameArea()),
141 aRectFnSet.GetBottom(getFrameArea()) ) > 0 )
142 {
143 pBoss->RearrangeFootnotes( aRectFnSet.GetBottom(getFrameArea()), false,
144 pFootnote->GetAttr() );
145 ValidateBodyFrame();
146 ValidateFrame();
147 pFootnote = pBoss->FindFirstFootnote( this );
148 }
149 else
150 bReArrange = false;
151 if( !pCont || !pFootnote || bReArrange != (pFootnote->FindFootnoteBossFrame() == pBoss) )
152 {
153 SwTextFormatInfo aInf( getRootFrame()->GetCurrShell()->GetOut(), this );
154 SwTextFormatter aLine( this, &aInf );
155 aLine.TruncLines();
156 SetPara( nullptr ); // May be deleted!
157 ResetPreps();
158 return false;
159 }
160 }
161 return true;
162}
163
164/**
165 * Local helper function. Checks if nLower should be taken as the boundary
166 * for the footnote.
167 */
168static SwTwips lcl_GetFootnoteLower( const SwTextFrame* pFrame, SwTwips nLower )
169{
170 // nLower is an absolute value. It denotes the bottom of the line
171 // containing the footnote.
172 SwRectFnSet aRectFnSet(pFrame);
173
174 OSL_ENSURE( !pFrame->IsVertical() || !pFrame->IsSwapped(),do { if (true && (!(!pFrame->IsVertical() || !pFrame
->IsSwapped()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "175" ": "), "%s", "lcl_GetFootnoteLower with swapped frame"
); } } while (false)
175 "lcl_GetFootnoteLower with swapped frame" )do { if (true && (!(!pFrame->IsVertical() || !pFrame
->IsSwapped()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "175" ": "), "%s", "lcl_GetFootnoteLower with swapped frame"
); } } while (false)
;
176
177 SwTwips nAdd;
178 SwTwips nRet = nLower;
179
180 // Check if text is inside a table.
181 if ( pFrame->IsInTab() )
182 {
183 // If pFrame is inside a table, we have to check if
184 // a) The table is not allowed to split or
185 // b) The table row is not allowed to split
186
187 // Inside a table, there are no footnotes,
188 // see SwFrame::FindFootnoteBossFrame. So we don't have to check
189 // the case that pFrame is inside a (footnote collecting) section
190 // within the table.
191 const SwFrame* pRow = pFrame;
192 while( !pRow->IsRowFrame() || !pRow->GetUpper()->IsTabFrame() )
193 pRow = pRow->GetUpper();
194 const SwTabFrame* pTabFrame = static_cast<const SwTabFrame*>(pRow->GetUpper());
195
196 OSL_ENSURE( pTabFrame && pRow &&do { if (true && (!(pTabFrame && pRow &&
pRow->GetUpper()->IsTabFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "197" ": "), "%s", "Upper of row should be tab"); } } while
(false)
197 pRow->GetUpper()->IsTabFrame(), "Upper of row should be tab" )do { if (true && (!(pTabFrame && pRow &&
pRow->GetUpper()->IsTabFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "197" ": "), "%s", "Upper of row should be tab"); } } while
(false)
;
198
199 const bool bDontSplit = !pTabFrame->IsFollow() &&
200 !pTabFrame->IsLayoutSplitAllowed();
201
202 SwTwips nMin = 0;
203 if ( bDontSplit )
204 nMin = aRectFnSet.GetBottom(pTabFrame->getFrameArea());
205 else if ( !static_cast<const SwRowFrame*>(pRow)->IsRowSplitAllowed() )
206 nMin = aRectFnSet.GetBottom(pRow->getFrameArea());
207
208 if ( nMin && aRectFnSet.YDiff( nMin, nLower ) > 0 )
209 nRet = nMin;
210
211 nAdd = aRectFnSet.GetBottomMargin(*pRow->GetUpper());
212 }
213 else
214 nAdd = aRectFnSet.GetBottomMargin(*pFrame);
215
216 if( nAdd > 0 )
217 {
218 if ( aRectFnSet.IsVert() )
219 nRet -= nAdd;
220 else
221 nRet += nAdd;
222 }
223
224 // #i10770#: If there are fly frames anchored at previous paragraphs,
225 // the deadline should consider their lower borders.
226 const SwFrame* pStartFrame = pFrame->GetUpper()->GetLower();
227 OSL_ENSURE( pStartFrame, "Upper has no lower" )do { if (true && (!(pStartFrame))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "227" ": "), "%s", "Upper has no lower"); } } while (false
)
;
228 SwTwips nFlyLower = aRectFnSet.IsVert() ? LONG_MAX9223372036854775807L : 0;
229 while ( pStartFrame != pFrame )
230 {
231 OSL_ENSURE( pStartFrame, "Frame chain is broken" )do { if (true && (!(pStartFrame))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "231" ": "), "%s", "Frame chain is broken"); } } while (
false)
;
232 if ( pStartFrame->GetDrawObjs() )
233 {
234 const SwSortedObjs &rObjs = *pStartFrame->GetDrawObjs();
235 for (SwAnchoredObject* pAnchoredObj : rObjs)
236 {
237 SwRect aRect( pAnchoredObj->GetObjRect() );
238
239 if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) == nullptr ||
240 static_cast<SwFlyFrame*>(pAnchoredObj)->isFrameAreaDefinitionValid() )
241 {
242 const SwTwips nBottom = aRectFnSet.GetBottom(aRect);
243 if ( aRectFnSet.YDiff( nBottom, nFlyLower ) > 0 )
244 nFlyLower = nBottom;
245 }
246 }
247 }
248
249 pStartFrame = pStartFrame->GetNext();
250 }
251
252 if ( aRectFnSet.IsVert() )
253 nRet = std::min( nRet, nFlyLower );
254 else
255 nRet = std::max( nRet, nFlyLower );
256
257 return nRet;
258}
259
260SwTwips SwTextFrame::GetFootnoteLine( const SwTextFootnote *pFootnote ) const
261{
262 OSL_ENSURE( ! IsVertical() || ! IsSwapped(),do { if (true && (!(! IsVertical() || ! IsSwapped()))
) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "263" ": "), "%s", "SwTextFrame::GetFootnoteLine with swapped frame"
); } } while (false)
263 "SwTextFrame::GetFootnoteLine with swapped frame" )do { if (true && (!(! IsVertical() || ! IsSwapped()))
) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "263" ": "), "%s", "SwTextFrame::GetFootnoteLine with swapped frame"
); } } while (false)
;
264
265 SwTextFrame *pThis = const_cast<SwTextFrame*>(this);
266
267 if( !HasPara() )
268 {
269 // #109071# GetFormatted() does not work here, because most probably
270 // the frame is currently locked. We return the previous value.
271 return pThis->mnFootnoteLine > 0 ?
272 pThis->mnFootnoteLine :
273 IsVertical() ? getFrameArea().Left() : getFrameArea().Bottom();
274 }
275
276 SwTwips nRet;
277 {
278 SwSwapIfNotSwapped swap(const_cast<SwTextFrame *>(this));
279
280 SwTextInfo aInf( pThis );
281 SwTextIter aLine( pThis, &aInf );
282 TextFrameIndex const nPos(MapModelToView(
283 &pFootnote->GetTextNode(), pFootnote->GetStart()));
284 aLine.CharToLine( nPos );
285
286 nRet = aLine.Y() + SwTwips(aLine.GetLineHeight());
287 if( IsVertical() )
288 nRet = SwitchHorizontalToVertical( nRet );
289 }
290
291 nRet = lcl_GetFootnoteLower( pThis, nRet );
292
293 pThis->mnFootnoteLine = nRet;
294 return nRet;
295}
296
297/**
298 * Calculates the maximum reachable height for the TextFrame in the Footnote Area.
299 * The cell's bottom margin with the Footnote Reference limit's this height.
300 */
301SwTwips SwTextFrame::GetFootnoteFrameHeight_() const
302{
303 OSL_ENSURE( !IsFollow() && IsInFootnote(), "SwTextFrame::SetFootnoteLine: moon walk" )do { if (true && (!(!IsFollow() && IsInFootnote
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "303" ": "), "%s", "SwTextFrame::SetFootnoteLine: moon walk"
); } } while (false)
;
304
305 const SwFootnoteFrame *pFootnoteFrame = FindFootnoteFrame();
306 const SwTextFrame *pRef = static_cast<const SwTextFrame *>(pFootnoteFrame->GetRef());
307 const SwFootnoteBossFrame *pBoss = FindFootnoteBossFrame();
308 if( pBoss != pRef->FindFootnoteBossFrame( !pFootnoteFrame->GetAttr()->
309 GetFootnote().IsEndNote() ) )
310 return 0;
311
312 SwSwapIfSwapped swap(const_cast<SwTextFrame *>(this));
313
314 SwTwips nHeight = pRef->IsInFootnoteConnect() ?
315 1 : pRef->GetFootnoteLine( pFootnoteFrame->GetAttr() );
316 if( nHeight )
317 {
318 // As odd as it may seem: the first Footnote on the page may not touch the
319 // Footnote Reference, when entering text in the Footnote Area.
320 const SwFrame *pCont = pFootnoteFrame->GetUpper();
321
322 // Height within the Container which we're allowed to consume anyways
323 SwRectFnSet aRectFnSet(pCont);
324 SwTwips nTmp = aRectFnSet.YDiff( aRectFnSet.GetPrtBottom(*pCont),
325 aRectFnSet.GetTop(getFrameArea()) );
326
327#if OSL_DEBUG_LEVEL1 > 0
328 if( nTmp < 0 )
329 {
330 bool bInvalidPos = false;
331 const SwLayoutFrame* pTmp = GetUpper();
332 while( !bInvalidPos && pTmp )
333 {
334 bInvalidPos = !pTmp->isFrameAreaPositionValid() ||
335 !pTmp->Lower()->isFrameAreaPositionValid();
336 if( pTmp == pCont )
337 break;
338 pTmp = pTmp->GetUpper();
339 }
340 OSL_ENSURE( bInvalidPos, "Hanging below FootnoteCont" )do { if (true && (!(bInvalidPos))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "340" ": "), "%s", "Hanging below FootnoteCont"); } } while
(false)
;
341 }
342#endif
343
344 if ( aRectFnSet.YDiff( aRectFnSet.GetTop(pCont->getFrameArea()), nHeight) > 0 )
345 {
346 // Growth potential of the container
347 if ( !pRef->IsInFootnoteConnect() )
348 {
349 SwSaveFootnoteHeight aSave( const_cast<SwFootnoteBossFrame*>(pBoss), nHeight );
350 nHeight = const_cast<SwFootnoteContFrame*>(static_cast<const SwFootnoteContFrame*>(pCont))->Grow( LONG_MAX9223372036854775807L, true );
351 }
352 else
353 nHeight = const_cast<SwFootnoteContFrame*>(static_cast<const SwFootnoteContFrame*>(pCont))->Grow( LONG_MAX9223372036854775807L, true );
354
355 nHeight += nTmp;
356 if( nHeight < 0 )
357 nHeight = 0;
358 }
359 else
360 { // The container has to shrink
361 nTmp += aRectFnSet.YDiff( aRectFnSet.GetTop(pCont->getFrameArea()), nHeight);
362 if( nTmp > 0 )
363 nHeight = nTmp;
364 else
365 nHeight = 0;
366 }
367 }
368
369 return nHeight;
370}
371
372SwTextFrame *SwTextFrame::FindQuoVadisFrame()
373{
374 // Check whether we're in a FootnoteFrame
375 if( GetIndPrev() || !IsInFootnote() )
376 return nullptr;
377
378 // To the preceding FootnoteFrame
379 SwFootnoteFrame *pFootnoteFrame = FindFootnoteFrame()->GetMaster();
380 if( !pFootnoteFrame )
381 return nullptr;
382
383 // Now the last Content
384 SwContentFrame *pCnt = pFootnoteFrame->ContainsContent();
385 if( !pCnt )
386 return nullptr;
387 SwContentFrame *pLast;
388 do
389 { pLast = pCnt;
390 pCnt = pCnt->GetNextContentFrame();
391 } while( pCnt && pFootnoteFrame->IsAnLower( pCnt ) );
392 return static_cast<SwTextFrame*>(pLast);
393}
394
395void SwTextFrame::RemoveFootnote(TextFrameIndex const nStart, TextFrameIndex const nLen)
396{
397 if ( !IsFootnoteAllowed() )
398 return;
399
400 bool bRollBack = nLen != TextFrameIndex(COMPLETE_STRING);
401 TextFrameIndex nEnd;
402 SwTextFrame* pSource;
403 if( bRollBack )
404 {
405 nEnd = nStart + nLen;
406 pSource = GetFollow();
407 if( !pSource )
408 return;
409 }
410 else
411 {
412 nEnd = TextFrameIndex(COMPLETE_STRING);
413 pSource = this;
414 }
415
416 SwPageFrame* pUpdate = nullptr;
417 bool bRemove = false;
418 SwFootnoteBossFrame *pFootnoteBoss = nullptr;
419 SwFootnoteBossFrame *pEndBoss = nullptr;
420 bool bFootnoteEndDoc = FTNPOS_CHAPTER == GetDoc().GetFootnoteInfo().m_ePos;
421 SwTextNode const* pNode(nullptr);
422 sw::MergedAttrIterReverse iter(*this);
423 for (SwTextAttr const* pHt = iter.PrevAttr(&pNode); pHt; pHt = iter.PrevAttr(&pNode))
424 {
425 if (RES_TXTATR_FTN != pHt->Which())
426 continue;
427
428 TextFrameIndex const nIdx(MapModelToView(pNode, pHt->GetStart()));
429 if (nStart > nIdx)
430 break;
431
432 if (nEnd >= nIdx)
433 {
434 SwTextFootnote const*const pFootnote(static_cast<SwTextFootnote const*>(pHt));
435 const bool bEndn = pFootnote->GetFootnote().IsEndNote();
436
437 if (bEndn)
438 {
439 if (!pEndBoss)
440 pEndBoss = pSource->FindFootnoteBossFrame();
441 }
442 else
443 {
444 if (!pFootnoteBoss)
445 {
446 pFootnoteBoss = pSource->FindFootnoteBossFrame( true );
447 if( pFootnoteBoss->GetUpper()->IsSctFrame() )
448 {
449 SwSectionFrame* pSect = static_cast<SwSectionFrame*>(
450 pFootnoteBoss->GetUpper());
451 if (pSect->IsFootnoteAtEnd())
452 bFootnoteEndDoc = false;
453 }
454 }
455 }
456
457 // We don't delete, but move instead.
458 // Three cases are to be considered:
459 // 1) There's neither Follow nor PrevFollow:
460 // -> RemoveFootnote() (maybe even a OSL_ENSURE(value))
461 //
462 // 2) nStart > GetOffset, I have a Follow
463 // -> Footnote moves into Follow
464 //
465 // 3) nStart < GetOffset, I am a Follow
466 // -> Footnote moves into the PrevFollow
467 //
468 // Both need to be on one Page/in one Column
469 SwFootnoteFrame *pFootnoteFrame = SwFootnoteBossFrame::FindFootnote(pSource, pFootnote);
470
471 if (pFootnoteFrame)
472 {
473 const bool bEndDoc = bEndn || bFootnoteEndDoc;
474 if( bRollBack )
475 {
476 while (pFootnoteFrame)
477 {
478 pFootnoteFrame->SetRef( this );
479 pFootnoteFrame = pFootnoteFrame->GetFollow();
480 SetFootnote( true );
481 }
482 }
483 else if (GetFollow())
484 {
485 SwContentFrame *pDest = GetFollow();
486 while (pDest->GetFollow() && static_cast<SwTextFrame*>(pDest->
487 GetFollow())->GetOffset() <= nIdx)
488 pDest = pDest->GetFollow();
489 OSL_ENSURE( !SwFootnoteBossFrame::FindFootnote(do { if (true && (!(!SwFootnoteBossFrame::FindFootnote
( pDest,pFootnote)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "490" ": "), "%s", "SwTextFrame::RemoveFootnote: footnote exists"
); } } while (false)
490 pDest,pFootnote),"SwTextFrame::RemoveFootnote: footnote exists")do { if (true && (!(!SwFootnoteBossFrame::FindFootnote
( pDest,pFootnote)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "490" ": "), "%s", "SwTextFrame::RemoveFootnote: footnote exists"
); } } while (false)
;
491
492 // Never deregister; always move
493 if (bEndDoc ||
494 !pFootnoteFrame->FindFootnoteBossFrame()->IsBefore(pDest->FindFootnoteBossFrame(!bEndn))
495 )
496 {
497 SwPageFrame* pTmp = pFootnoteFrame->FindPageFrame();
498 if( pUpdate && pUpdate != pTmp )
499 pUpdate->UpdateFootnoteNum();
500 pUpdate = pTmp;
501 while ( pFootnoteFrame )
502 {
503 pFootnoteFrame->SetRef( pDest );
504 pFootnoteFrame = pFootnoteFrame->GetFollow();
505 }
506 }
507 else
508 {
509 pFootnoteBoss->MoveFootnotes( this, pDest, pFootnote );
510 bRemove = true;
511 }
512 static_cast<SwTextFrame*>(pDest)->SetFootnote( true );
513
514 OSL_ENSURE( SwFootnoteBossFrame::FindFootnote( pDest,do { if (true && (!(SwFootnoteBossFrame::FindFootnote
( pDest, pFootnote)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "515" ": "), "%s", "SwTextFrame::RemoveFootnote: footnote ChgRef failed"
); } } while (false)
515 pFootnote),"SwTextFrame::RemoveFootnote: footnote ChgRef failed")do { if (true && (!(SwFootnoteBossFrame::FindFootnote
( pDest, pFootnote)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "515" ": "), "%s", "SwTextFrame::RemoveFootnote: footnote ChgRef failed"
); } } while (false)
;
516 }
517 else
518 {
519 if (!bEndDoc || ( bEndn && pEndBoss->IsInSct() &&
520 !SwLayouter::Collecting( &GetDoc(),
521 pEndBoss->FindSctFrame(), nullptr ) ))
522 {
523 if( bEndn )
524 pEndBoss->RemoveFootnote( this, pFootnote );
525 else
526 pFootnoteBoss->RemoveFootnote( this, pFootnote );
527 bRemove = bRemove || !bEndDoc;
528 OSL_ENSURE( !SwFootnoteBossFrame::FindFootnote( this, pFootnote ),do { if (true && (!(!SwFootnoteBossFrame::FindFootnote
( this, pFootnote )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "529" ": "), "%s", "SwTextFrame::RemoveFootnote: can't get off that footnote"
); } } while (false)
529 "SwTextFrame::RemoveFootnote: can't get off that footnote" )do { if (true && (!(!SwFootnoteBossFrame::FindFootnote
( this, pFootnote )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "529" ": "), "%s", "SwTextFrame::RemoveFootnote: can't get off that footnote"
); } } while (false)
;
530 }
531 }
532 }
533 }
534 }
535 if (pUpdate)
536 pUpdate->UpdateFootnoteNum();
537
538 // We break the oscillation
539 if (bRemove && !bFootnoteEndDoc && HasPara())
540 {
541 ValidateBodyFrame();
542 ValidateFrame();
543 }
544
545 // We call the RemoveFootnote from within the FindBreak, because the last line is
546 // to be passed to the Follow. The Offset of the Follow is, however, outdated;
547 // it'll be set soon. CalcFntFlag depends on a correctly set Follow Offset.
548 // Therefore we temporarily calculate the Follow Offset here
549 TextFrameIndex nOldOfst(COMPLETE_STRING);
550 if( HasFollow() && nStart > GetOffset() )
551 {
552 nOldOfst = GetFollow()->GetOffset();
553 GetFollow()->ManipOfst(nStart + (bRollBack ? nLen : TextFrameIndex(0)));
554 }
555 pSource->CalcFootnoteFlag();
556 if (nOldOfst < TextFrameIndex(COMPLETE_STRING))
557 GetFollow()->ManipOfst( nOldOfst );
558}
559
560
561/**
562 * We basically only have two possibilities:
563 *
564 * a) The Footnote is already present
565 * => we move it, if another pSrcFrame has been found
566 *
567 * b) The Footnote is not present
568 * => we have it created for us
569 *
570 * Whether the Footnote ends up on our Page/Column, doesn't matter in this
571 * context.
572 *
573 * Optimization for Endnotes.
574 *
575 * Another problem: if the Deadline falls within the Footnote Area, we need
576 * to move the Footnote.
577 *
578 * @returns false on any type of error
579 */
580void SwTextFrame::ConnectFootnote( SwTextFootnote *pFootnote, const SwTwips nDeadLine )
581{
582 OSL_ENSURE( !IsVertical() || !IsSwapped(),do { if (true && (!(!IsVertical() || !IsSwapped()))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "583" ": "), "%s", "SwTextFrame::ConnectFootnote with swapped frame"
); } } while (false)
16
Assuming the condition is true
17
Taking false branch
18
Loop condition is false. Exiting loop
583 "SwTextFrame::ConnectFootnote with swapped frame" )do { if (true && (!(!IsVertical() || !IsSwapped()))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "583" ": "), "%s", "SwTextFrame::ConnectFootnote with swapped frame"
); } } while (false)
;
584
585 mbFootnote = true;
586 mbInFootnoteConnect = true; // Just reset!
587 // See if pFootnote is an endnote on a separate endnote page.
588 const IDocumentSettingAccess& rSettings = GetDoc().getIDocumentSettingAccess();
589 const bool bContinuousEndnotes = rSettings.get(DocumentSettingId::CONTINUOUS_ENDNOTES);
590 const bool bEnd = pFootnote->GetFootnote().IsEndNote();
591
592 // We want to store this value, because it is needed as a fallback
593 // in GetFootnoteLine(), if there is no paragraph information available
594 mnFootnoteLine = nDeadLine;
595
596 // We always need a parent (Page/Column)
597 SwSectionFrame *pSect;
598 SwContentFrame *pContent = this;
599 if( bEnd && IsInSct() )
19
Assuming 'bEnd' is true
20
Assuming the condition is false
21
Taking false branch
600 {
601 pSect = FindSctFrame();
602 if( pSect->IsEndnAtEnd() )
603 pContent = pSect->FindLastContent( SwFindMode::EndNote );
604 if( !pContent )
605 pContent = this;
606 }
607
608 SwFootnoteBossFrame *pBoss = pContent->FindFootnoteBossFrame( !bEnd );
609
610 pSect = pBoss->FindSctFrame();
22
Calling 'SwFrame::FindSctFrame'
26
Returning from 'SwFrame::FindSctFrame'
611 bool bDocEnd = bEnd
26.1
'bEnd' is true
26.1
'bEnd' is true
? !( pSect && pSect->IsEndnAtEnd() ) :
27
'?' condition is true
28
Assuming 'pSect' is non-null
29
Assuming the condition is false
612 ( !( pSect && pSect->IsFootnoteAtEnd() ) &&
613 FTNPOS_CHAPTER == GetDoc().GetFootnoteInfo().m_ePos);
614
615 // Footnote can be registered with the Follow
616 SwContentFrame *pSrcFrame = FindFootnoteRef( pFootnote );
617
618 if( bDocEnd
29.1
'bDocEnd' is false
29.1
'bDocEnd' is false
)
30
Taking false branch
619 {
620 if ((pSect || bContinuousEndnotes) && pSrcFrame)
621 {
622 SwFootnoteFrame *pFootnoteFrame = SwFootnoteBossFrame::FindFootnote( pSrcFrame, pFootnote );
623 if (pFootnoteFrame && (pFootnoteFrame->IsInSct() || bContinuousEndnotes))
624 {
625 // We either have a foot/endnote that goes to the end of the section or are in Word
626 // compatibility mode where endnotes go to the end of the document. Handle both
627 // cases by removing the footnote here, then later appending them to the correct
628 // last page of the document or section.
629 pBoss->RemoveFootnote( pSrcFrame, pFootnote );
630 pSrcFrame = nullptr;
631 }
632 }
633 }
634 else if( bEnd
30.1
'bEnd' is true
30.1
'bEnd' is true
&& pSect
30.2
'pSect' is non-null
30.2
'pSect' is non-null
)
31
Taking true branch
635 {
636 SwFootnoteFrame *pFootnoteFrame = pSrcFrame ? SwFootnoteBossFrame::FindFootnote( pSrcFrame, pFootnote ) : nullptr;
32
Assuming 'pSrcFrame' is non-null
33
'?' condition is true
34
'pFootnoteFrame' initialized here
637 if( pFootnoteFrame && !pFootnoteFrame->GetUpper() )
35
Assuming 'pFootnoteFrame' is null
638 pFootnoteFrame = nullptr;
639 SwDoc *const pDoc = &GetDoc();
640 if( SwLayouter::Collecting( pDoc, pSect, pFootnoteFrame ) )
36
Assuming the condition is false
37
Taking false branch
641 {
642 if( !pSrcFrame )
643 {
644 SwFootnoteFrame *pNew = new SwFootnoteFrame(pDoc->GetDfltFrameFormat(),this,this,pFootnote);
645 SwNodeIndex aIdx( *pFootnote->GetStartNode(), 1 );
646 ::InsertCnt_( pNew, pDoc, aIdx.GetIndex() );
647 pDoc->getIDocumentLayoutAccess().GetLayouter()->CollectEndnote( pNew );
648 }
649 else if( pSrcFrame != this )
650 SwFootnoteBossFrame::ChangeFootnoteRef( pSrcFrame, pFootnote, this );
651 mbInFootnoteConnect = false;
652 return;
653 }
654 else if( pSrcFrame
37.1
'pSrcFrame' is non-null
37.1
'pSrcFrame' is non-null
)
38
Taking true branch
655 {
656 SwFootnoteBossFrame *pFootnoteBoss = pFootnoteFrame->FindFootnoteBossFrame();
39
Called C++ object pointer is null
657 if( !pFootnoteBoss->IsInSct() ||
658 pFootnoteBoss->ImplFindSctFrame()->GetSection()!=pSect->GetSection() )
659 {
660 pBoss->RemoveFootnote( pSrcFrame, pFootnote );
661 pSrcFrame = nullptr;
662 }
663 }
664 }
665
666 if( bDocEnd || bEnd )
667 {
668 if( !pSrcFrame )
669 pBoss->AppendFootnote( this, pFootnote );
670 else if( pSrcFrame != this )
671 SwFootnoteBossFrame::ChangeFootnoteRef( pSrcFrame, pFootnote, this );
672 mbInFootnoteConnect = false;
673 return;
674 }
675
676 SwSaveFootnoteHeight aHeight( pBoss, nDeadLine );
677
678 if( !pSrcFrame ) // No Footnote was found at all
679 pBoss->AppendFootnote( this, pFootnote );
680 else
681 {
682 SwFootnoteFrame *pFootnoteFrame = SwFootnoteBossFrame::FindFootnote( pSrcFrame, pFootnote );
683 SwFootnoteBossFrame *pFootnoteBoss = pFootnoteFrame->FindFootnoteBossFrame();
684
685 bool bBrutal = false;
686
687 if( pFootnoteBoss == pBoss ) // Ref and Footnote are on the same Page/Column
688 {
689 SwFrame *pCont = pFootnoteFrame->GetUpper();
690
691 SwRectFnSet aRectFnSet(pCont);
692 long nDiff = aRectFnSet.YDiff( aRectFnSet.GetTop(pCont->getFrameArea()),
693 nDeadLine );
694
695 if( nDiff >= 0 )
696 {
697 // If the Footnote has been registered to a Follow, we need to
698 // rewire it now too
699 if ( pSrcFrame != this )
700 SwFootnoteBossFrame::ChangeFootnoteRef( pSrcFrame, pFootnote, this );
701
702 // We have some room left, so the Footnote can grow
703 if ( pFootnoteFrame->GetFollow() && nDiff > 0 )
704 {
705 SwFrameDeleteGuard aDeleteGuard(pCont);
706 SwTwips nHeight = aRectFnSet.GetHeight(pCont->getFrameArea());
707 pBoss->RearrangeFootnotes( nDeadLine, false, pFootnote );
708 ValidateBodyFrame();
709 ValidateFrame();
710 SwViewShell *pSh = getRootFrame()->GetCurrShell();
711 if ( pSh && nHeight == aRectFnSet.GetHeight(pCont->getFrameArea()) )
712 // So that we don't miss anything
713 pSh->InvalidateWindows( pCont->getFrameArea() );
714 }
715 mbInFootnoteConnect = false;
716 return;
717 }
718 else
719 bBrutal = true;
720 }
721 else
722 {
723 // Ref and Footnote are not on one Page; attempt to move is necessary
724 SwFrame* pTmp = this;
725 while( pTmp->GetNext() && pSrcFrame != pTmp )
726 pTmp = pTmp->GetNext();
727 if( pSrcFrame == pTmp )
728 bBrutal = true;
729 else
730 { // If our Parent is in a column Area, but the Page already has a
731 // FootnoteContainer, we can only brute force it
732 if( pSect && pSect->FindFootnoteBossFrame( !bEnd )->FindFootnoteCont() )
733 bBrutal = true;
734
735 else if ( !pFootnoteFrame->GetPrev() ||
736 pFootnoteBoss->IsBefore( pBoss )
737 )
738 {
739 SwFootnoteBossFrame *pSrcBoss = pSrcFrame->FindFootnoteBossFrame( !bEnd );
740 pSrcBoss->MoveFootnotes( pSrcFrame, this, pFootnote );
741 }
742 else
743 SwFootnoteBossFrame::ChangeFootnoteRef( pSrcFrame, pFootnote, this );
744 }
745 }
746
747 // The brute force method: Remove Footnote and append.
748 // We need to call SetFootnoteDeadLine(), as we can more easily adapt the
749 // nMaxFootnoteHeight after RemoveFootnote
750 if( bBrutal )
751 {
752 pBoss->RemoveFootnote( pSrcFrame, pFootnote, false );
753 std::unique_ptr<SwSaveFootnoteHeight> pHeight(bEnd ? nullptr : new SwSaveFootnoteHeight( pBoss, nDeadLine ));
754 pBoss->AppendFootnote( this, pFootnote );
755 }
756 }
757
758 // In column Areas, that not yet reach the Page's border a RearrangeFootnotes is not
759 // useful yet, as the Footnote container has not yet been calculated
760 if( !pSect || !pSect->Growable() )
761 {
762 // Validate environment, to avoid oscillation
763 SwSaveFootnoteHeight aNochmal( pBoss, nDeadLine );
764 ValidateBodyFrame();
765 pBoss->RearrangeFootnotes( nDeadLine, true );
766 ValidateFrame();
767 }
768 else if( pSect->IsFootnoteAtEnd() )
769 {
770 ValidateBodyFrame();
771 ValidateFrame();
772 }
773
774 mbInFootnoteConnect = false;
775}
776
777/**
778 * The portion for the Footnote Reference in the Text
779 */
780SwFootnotePortion *SwTextFormatter::NewFootnotePortion( SwTextFormatInfo &rInf,
781 SwTextAttr *pHint )
782{
783 OSL_ENSURE( ! m_pFrame->IsVertical() || m_pFrame->IsSwapped(),do { if (true && (!(! m_pFrame->IsVertical() || m_pFrame
->IsSwapped()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "784" ": "), "%s", "NewFootnotePortion with unswapped frame"
); } } while (false)
1
Assuming the condition is false
2
Assuming the condition is false
3
Taking false branch
4
Loop condition is false. Exiting loop
784 "NewFootnotePortion with unswapped frame" )do { if (true && (!(! m_pFrame->IsVertical() || m_pFrame
->IsSwapped()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "784" ": "), "%s", "NewFootnotePortion with unswapped frame"
); } } while (false)
;
785
786 SwTextFootnote *pFootnote = static_cast<SwTextFootnote*>(pHint);
787
788 if( !m_pFrame->IsFootnoteAllowed() )
5
Assuming the condition is false
6
Taking false branch
789 return new SwFootnotePortion("", pFootnote);
790
791 const SwFormatFootnote& rFootnote = pFootnote->GetFootnote();
792 SwDoc *const pDoc = &m_pFrame->GetDoc();
793
794 if( rInf.IsTest() )
7
Assuming the condition is false
8
Taking false branch
795 return new SwFootnotePortion(rFootnote.GetViewNumStr(*pDoc, m_pFrame->getRootFrame()), pFootnote);
796
797 SwSwapIfSwapped swap(m_pFrame);
798
799 sal_uInt16 nReal;
800 {
801 sal_uInt16 nOldReal = m_pCurr->GetRealHeight();
802 sal_uInt16 nOldAscent = m_pCurr->GetAscent();
803 sal_uInt16 nOldHeight = m_pCurr->Height();
804 CalcRealHeight();
805 nReal = m_pCurr->GetRealHeight();
806 if( nReal < nOldReal )
9
Assuming 'nReal' is >= 'nOldReal'
10
Taking false branch
807 nReal = nOldReal;
808 m_pCurr->SetRealHeight( nOldReal );
809 m_pCurr->Height( nOldHeight );
810 m_pCurr->SetAscent( nOldAscent );
811 }
812
813 SwTwips nLower = Y() + nReal;
814
815 const bool bVertical = m_pFrame->IsVertical();
816 if( bVertical )
11
Assuming 'bVertical' is false
12
Taking false branch
817 nLower = m_pFrame->SwitchHorizontalToVertical( nLower );
818
819 nLower = lcl_GetFootnoteLower( m_pFrame, nLower );
820
821 // We just refresh.
822 // The Connect does not do anything useful in this case, but will
823 // mostly throw away the Footnote and create it anew.
824 if( !rInf.IsQuick() )
13
Assuming the condition is true
14
Taking true branch
825 m_pFrame->ConnectFootnote( pFootnote, nLower );
15
Calling 'SwTextFrame::ConnectFootnote'
826
827 SwTextFrame *pScrFrame = m_pFrame->FindFootnoteRef( pFootnote );
828 SwFootnoteBossFrame *pBoss = m_pFrame->FindFootnoteBossFrame( !rFootnote.IsEndNote() );
829 SwFootnoteFrame *pFootnoteFrame = nullptr;
830 if( pScrFrame )
831 pFootnoteFrame = SwFootnoteBossFrame::FindFootnote( pScrFrame, pFootnote );
832
833 // We see whether our Append has caused some Footnote to
834 // still be on the Page/Column. If not, our line disappears too,
835 // which will lead to the following undesired behaviour:
836 // Footnote1 still fits onto the Page/Column, but Footnote2 doesn't.
837 // The Footnote2 Reference remains on the Page/Column. The Footnote itself
838 // is on the next Page/Column.
839 //
840 // Exception: If the Page/Column cannot accommodate another line,
841 // the Footnote Reference should be moved to the next one.
842 if( !rFootnote.IsEndNote() )
843 {
844 SwSectionFrame *pSct = pBoss->FindSctFrame();
845 bool bAtSctEnd = pSct && pSct->IsFootnoteAtEnd();
846 if( FTNPOS_CHAPTER != pDoc->GetFootnoteInfo().m_ePos || bAtSctEnd )
847 {
848 SwFrame* pFootnoteCont = pBoss->FindFootnoteCont();
849 // If the Parent is within an Area, it can only be a Column of this
850 // Area. If this one is not the first Column, we can avoid it.
851 if( !m_pFrame->IsInTab() && ( GetLineNr() > 1 || m_pFrame->GetPrev() ||
852 ( !bAtSctEnd && m_pFrame->GetIndPrev() ) ||
853 ( pSct && pBoss->GetPrev() ) ) )
854 {
855 if( !pFootnoteCont )
856 {
857 rInf.SetStop( true );
858 return nullptr;
859 }
860 else
861 {
862 // There must not be any Footnote Containers in column Areas and at the same time on the
863 // Page/Page column
864 if( pSct && !bAtSctEnd ) // Is the Container in a (column) Area?
865 {
866 SwFootnoteBossFrame* pTmp = pBoss->FindSctFrame()->FindFootnoteBossFrame( true );
867 SwFootnoteContFrame* pFootnoteC = pTmp->FindFootnoteCont();
868 if( pFootnoteC )
869 {
870 SwFootnoteFrame* pTmpFrame = static_cast<SwFootnoteFrame*>(pFootnoteC->Lower());
871 if( pTmpFrame && *pTmpFrame < pFootnote )
872 {
873 rInf.SetStop( true );
874 return nullptr;
875 }
876 }
877 }
878 // Is this the last Line that fits?
879 SwTwips nTmpBot = Y() + nReal * 2;
880
881 if( bVertical )
882 nTmpBot = m_pFrame->SwitchHorizontalToVertical( nTmpBot );
883
884 SwRectFnSet aRectFnSet(pFootnoteCont);
885
886 const long nDiff = aRectFnSet.YDiff(
887 aRectFnSet.GetTop(pFootnoteCont->getFrameArea()),
888 nTmpBot );
889
890 if( pScrFrame && nDiff < 0 )
891 {
892 if( pFootnoteFrame )
893 {
894 SwFootnoteBossFrame *pFootnoteBoss = pFootnoteFrame->FindFootnoteBossFrame();
895 if( pFootnoteBoss != pBoss )
896 {
897 // We're in the last Line and the Footnote has moved
898 // to another Page. We also want to be on that Page!
899 rInf.SetStop( true );
900 return nullptr;
901 }
902 }
903 }
904 }
905 }
906 }
907 }
908 // Finally: Create FootnotePortion and exit ...
909 SwFootnotePortion *pRet = new SwFootnotePortion(
910 rFootnote.GetViewNumStr(*pDoc, m_pFrame->getRootFrame()),
911 pFootnote, nReal );
912 rInf.SetFootnoteInside( true );
913
914 return pRet;
915}
916
917/**
918 * The portion for the Footnote Numbering in the Footnote Area
919 */
920SwNumberPortion *SwTextFormatter::NewFootnoteNumPortion( SwTextFormatInfo const &rInf ) const
921{
922 OSL_ENSURE( m_pFrame->IsInFootnote() && !m_pFrame->GetIndPrev() && !rInf.IsFootnoteDone(),do { if (true && (!(m_pFrame->IsInFootnote() &&
!m_pFrame->GetIndPrev() && !rInf.IsFootnoteDone()
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "923" ": "), "%s", "This is the wrong place for a ftnnumber"
); } } while (false)
923 "This is the wrong place for a ftnnumber" )do { if (true && (!(m_pFrame->IsInFootnote() &&
!m_pFrame->GetIndPrev() && !rInf.IsFootnoteDone()
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "923" ": "), "%s", "This is the wrong place for a ftnnumber"
); } } while (false)
;
924 if( rInf.GetTextStart() != m_nStart ||
925 rInf.GetTextStart() != rInf.GetIdx() )
926 return nullptr;
927
928 const SwFootnoteFrame* pFootnoteFrame = m_pFrame->FindFootnoteFrame();
929 const SwTextFootnote* pFootnote = pFootnoteFrame->GetAttr();
930
931 // Aha! So we're in the Footnote Area!
932 SwFormatFootnote& rFootnote = const_cast<SwFormatFootnote&>(pFootnote->GetFootnote());
933
934 SwDoc *const pDoc = &m_pFrame->GetDoc();
935 OUString aFootnoteText(rFootnote.GetViewNumStr(*pDoc, m_pFrame->getRootFrame(), true));
936
937 const SwEndNoteInfo* pInfo;
938 if( rFootnote.IsEndNote() )
939 pInfo = &pDoc->GetEndNoteInfo();
940 else
941 pInfo = &pDoc->GetFootnoteInfo();
942
943 const SwAttrSet* pParSet = &rInf.GetCharAttr();
944 const IDocumentSettingAccess* pIDSA = &pDoc->getIDocumentSettingAccess();
945 std::unique_ptr<SwFont> pNumFnt(new SwFont( pParSet, pIDSA ));
946
947 // #i37142#
948 // Underline style of paragraph font should not be considered
949 // Overline style of paragraph font should not be considered
950 // Weight style of paragraph font should not be considered
951 // Posture style of paragraph font should not be considered
952 // See also #i18463# and SwTextFormatter::NewNumberPortion()
953 pNumFnt->SetUnderline( LINESTYLE_NONE );
954 pNumFnt->SetOverline( LINESTYLE_NONE );
955 pNumFnt->SetItalic( ITALIC_NONE, SwFontScript::Latin );
956 pNumFnt->SetItalic( ITALIC_NONE, SwFontScript::CJK );
957 pNumFnt->SetItalic( ITALIC_NONE, SwFontScript::CTL );
958 pNumFnt->SetWeight( WEIGHT_NORMAL, SwFontScript::Latin );
959 pNumFnt->SetWeight( WEIGHT_NORMAL, SwFontScript::CJK );
960 pNumFnt->SetWeight( WEIGHT_NORMAL, SwFontScript::CTL );
961
962 const auto xAnchor = rFootnote.getAnchor(*pDoc);
963 uno::Reference<beans::XPropertySet> xAnchorProps(xAnchor, uno::UNO_QUERY);
964 if (xAnchorProps.is())
965 {
966 auto aAny = xAnchorProps->getPropertyValue("CharFontCharSet");
967 sal_Int16 eCharSet;
968 if ((aAny >>= eCharSet) && eCharSet == awt::CharSet::SYMBOL)
969 {
970 OUString aFontName;
971 aAny = xAnchorProps->getPropertyValue("CharFontName");
972 if (aAny >>= aFontName)
973 {
974 pNumFnt->SetName(aFontName, SwFontScript::Latin);
975 pNumFnt->SetName(aFontName, SwFontScript::CJK);
976 pNumFnt->SetName(aFontName, SwFontScript::CTL);
977 pNumFnt->SetCharSet(RTL_TEXTENCODING_SYMBOL(((rtl_TextEncoding) 10)), SwFontScript::Latin);
978 pNumFnt->SetCharSet(RTL_TEXTENCODING_SYMBOL(((rtl_TextEncoding) 10)), SwFontScript::CJK);
979 pNumFnt->SetCharSet(RTL_TEXTENCODING_SYMBOL(((rtl_TextEncoding) 10)), SwFontScript::CTL);
980 }
981 }
982 }
983
984 const SwAttrSet& rSet = pInfo->GetCharFormat(*pDoc)->GetAttrSet();
985 pNumFnt->SetDiffFnt(&rSet, pIDSA );
986 pNumFnt->SetVertical( pNumFnt->GetOrientation(), m_pFrame->IsVertical() );
987
988 SwFootnoteNumPortion* pNewPor = new SwFootnoteNumPortion( aFootnoteText, std::move(pNumFnt) );
989 pNewPor->SetLeft( !m_pFrame->IsRightToLeft() );
990 return pNewPor;
991}
992
993static OUString lcl_GetPageNumber( const SwPageFrame* pPage )
994{
995 OSL_ENSURE( pPage, "GetPageNumber: Homeless TextFrame" )do { if (true && (!(pPage))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "995" ": "), "%s", "GetPageNumber: Homeless TextFrame");
} } while (false)
;
996 const sal_uInt16 nVirtNum = pPage->GetVirtPageNum();
997 const SvxNumberType& rNum = pPage->GetPageDesc()->GetNumType();
998 return rNum.GetNumStr( nVirtNum );
999}
1000
1001SwErgoSumPortion *SwTextFormatter::NewErgoSumPortion( SwTextFormatInfo const &rInf ) const
1002{
1003 // We cannot assume we're a Follow
1004 if( !m_pFrame->IsInFootnote() || m_pFrame->GetPrev() ||
1005 rInf.IsErgoDone() || rInf.GetIdx() != m_pFrame->GetOffset() ||
1006 m_pFrame->ImplFindFootnoteFrame()->GetAttr()->GetFootnote().IsEndNote() )
1007 return nullptr;
1008
1009 // we are in the footnote container
1010 const SwFootnoteInfo &rFootnoteInfo = m_pFrame->GetDoc().GetFootnoteInfo();
1011 SwTextFrame *pQuoFrame = m_pFrame->FindQuoVadisFrame();
1012 if( !pQuoFrame )
1013 return nullptr;
1014 const SwPageFrame* pPage = m_pFrame->FindPageFrame();
1015 const SwPageFrame* pQuoPage = pQuoFrame->FindPageFrame();
1016 if( pPage == pQuoFrame->FindPageFrame() )
1017 return nullptr; // If the QuoVadis is on the same Column/Page
1018 const OUString aPage = lcl_GetPageNumber( pPage );
1019 SwParaPortion *pPara = pQuoFrame->GetPara();
1020 if( pPara )
1021 pPara->SetErgoSumNum( aPage );
1022 if( rFootnoteInfo.m_aErgoSum.isEmpty() )
1023 return nullptr;
1024 SwErgoSumPortion *pErgo = new SwErgoSumPortion( rFootnoteInfo.m_aErgoSum,
1025 lcl_GetPageNumber( pQuoPage ) );
1026 return pErgo;
1027}
1028
1029TextFrameIndex SwTextFormatter::FormatQuoVadis(TextFrameIndex const nOffset)
1030{
1031 OSL_ENSURE( ! m_pFrame->IsVertical() || ! m_pFrame->IsSwapped(),do { if (true && (!(! m_pFrame->IsVertical() || ! m_pFrame
->IsSwapped()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "1032" ": "), "%s", "SwTextFormatter::FormatQuoVadis with swapped frame"
); } } while (false)
1032 "SwTextFormatter::FormatQuoVadis with swapped frame" )do { if (true && (!(! m_pFrame->IsVertical() || ! m_pFrame
->IsSwapped()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "1032" ": "), "%s", "SwTextFormatter::FormatQuoVadis with swapped frame"
); } } while (false)
;
1033
1034 if( !m_pFrame->IsInFootnote() || m_pFrame->ImplFindFootnoteFrame()->GetAttr()->GetFootnote().IsEndNote() )
1035 return nOffset;
1036
1037 const SwFrame* pErgoFrame = m_pFrame->FindFootnoteFrame()->GetFollow();
1038 if( !pErgoFrame && m_pFrame->HasFollow() )
1039 pErgoFrame = m_pFrame->GetFollow();
1040 if( !pErgoFrame )
1041 return nOffset;
1042
1043 if( pErgoFrame == m_pFrame->GetNext() )
1044 {
1045 SwFrame *pCol = m_pFrame->FindColFrame();
1046 while( pCol && !pCol->GetNext() )
1047 pCol = pCol->GetUpper()->FindColFrame();
1048 if( pCol )
1049 return nOffset;
1050 }
1051 else
1052 {
1053 const SwPageFrame* pPage = m_pFrame->FindPageFrame();
1054 const SwPageFrame* pErgoPage = pErgoFrame->FindPageFrame();
1055 if( pPage == pErgoPage )
1056 return nOffset; // If the ErgoSum is on the same Page
1057 }
1058
1059 SwTextFormatInfo &rInf = GetInfo();
1060 const SwFootnoteInfo &rFootnoteInfo = m_pFrame->GetDoc().GetFootnoteInfo();
1061 if( rFootnoteInfo.m_aQuoVadis.isEmpty() )
1062 return nOffset;
1063
1064 // A remark on QuoVadis/ErgoSum:
1065 // We use the Font set for the Paragraph for these texts.
1066 // Thus, we initialize:
1067 // TODO: ResetFont();
1068 FeedInf( rInf );
1069 SeekStartAndChg( rInf, true );
1070 if( GetRedln() && m_pCurr->HasRedline() )
1071 {
1072 std::pair<SwTextNode const*, sal_Int32> const pos(
1073 GetTextFrame()->MapViewToModel(nOffset));
1074 GetRedln()->Seek(*m_pFont, pos.first->GetIndex(), pos.second, 0);
1075 }
1076
1077 // A tricky special case: Flyfrms extend into the Line and are at the
1078 // position we want to insert the Quovadis text
1079 // Let's see if it is that bad indeed:
1080 SwLinePortion *pPor = m_pCurr->GetFirstPortion();
1081 sal_uInt16 nLastLeft = 0;
1082 while( pPor )
1083 {
1084 if ( pPor->IsFlyPortion() )
1085 nLastLeft = static_cast<SwFlyPortion*>(pPor)->GetFix() +
1086 static_cast<SwFlyPortion*>(pPor)->Width();
1087 pPor = pPor->GetNextPortion();
1088 }
1089
1090 // The old game all over again: we want the Line to wrap around
1091 // at a certain point, so we adjust the width.
1092 // nLastLeft is now basically the right margin
1093 const sal_uInt16 nOldRealWidth = rInf.RealWidth();
1094 rInf.RealWidth( nOldRealWidth - nLastLeft );
1095
1096 OUString aErgo = lcl_GetPageNumber( pErgoFrame->FindPageFrame() );
1097 SwQuoVadisPortion *pQuo = new SwQuoVadisPortion(rFootnoteInfo.m_aQuoVadis, aErgo );
1098 pQuo->SetAscent( rInf.GetAscent() );
1099 pQuo->Height( rInf.GetTextHeight() );
1100 pQuo->Format( rInf );
1101 sal_uInt16 nQuoWidth = pQuo->Width();
1102 SwLinePortion* pCurrPor = pQuo;
1103
1104 while ( rInf.GetRest() )
1105 {
1106 SwLinePortion* pFollow = rInf.GetRest();
1107 rInf.SetRest( nullptr );
1108 pCurrPor->Move( rInf );
1109
1110 OSL_ENSURE( pFollow->IsQuoVadisPortion(),do { if (true && (!(pFollow->IsQuoVadisPortion()))
) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "1111" ": "), "%s", "Quo Vadis, rest of QuoVadisPortion"
); } } while (false)
1111 "Quo Vadis, rest of QuoVadisPortion" )do { if (true && (!(pFollow->IsQuoVadisPortion()))
) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx"
":" "1111" ": "), "%s", "Quo Vadis, rest of QuoVadisPortion"
); } } while (false)
;
1112
1113 // format the rest and append it to the other QuoVadis parts
1114 pFollow->Format( rInf );
1115 nQuoWidth = nQuoWidth + pFollow->Width();
1116
1117 pCurrPor->Append( pFollow );
1118 pCurrPor = pFollow;
1119 }
1120
1121 Right( Right() - nQuoWidth );
1122
1123 TextFrameIndex nRet;
1124 {
1125 SwSwapIfNotSwapped swap(m_pFrame);
1126
1127 nRet = FormatLine( m_nStart );
1128 }
1129
1130 Right( rInf.Left() + nOldRealWidth - 1 );
1131
1132 nLastLeft = nOldRealWidth - m_pCurr->Width();
1133 FeedInf( rInf );
1134
1135 // It's possible that there's a Margin Portion at the end, which would
1136 // just cause a lot of trouble, when respanning
1137 pPor = m_pCurr->FindLastPortion();
1138 SwGluePortion *pGlue = pPor->IsMarginPortion() ? static_cast<SwMarginPortion*>(pPor) : nullptr;
1139 if( pGlue )
1140 {
1141 pGlue->Height( 0 );
1142 pGlue->Width( 0 );
1143 pGlue->SetLen(TextFrameIndex(0));
1144 pGlue->SetAscent( 0 );
1145 pGlue->SetNextPortion( nullptr );
1146 pGlue->SetFixWidth(0);
1147 }
1148
1149 // Luxury: We make sure the QuoVadis text appears on the right, by
1150 // using Glues.
1151 nLastLeft = nLastLeft - nQuoWidth;
1152 if( nLastLeft )
1153 {
1154 if( nLastLeft > pQuo->GetAscent() ) // Minimum distance
1155 {
1156 switch( GetAdjust() )
1157 {
1158 case SvxAdjust::Block:
1159 {
1160 if( !m_pCurr->GetLen() ||
1161 CH_BREAK != GetInfo().GetChar(m_nStart + m_pCurr->GetLen() - TextFrameIndex(1)))
1162 nLastLeft = pQuo->GetAscent();
1163 nQuoWidth = nQuoWidth + nLastLeft;
1164 break;
1165 }
1166 case SvxAdjust::Right:
1167 {
1168 nLastLeft = pQuo->GetAscent();
1169 nQuoWidth = nQuoWidth + nLastLeft;
1170 break;
1171 }
1172 case SvxAdjust::Center:
1173 {
1174 nQuoWidth = nQuoWidth + pQuo->GetAscent();
1175 long nDiff = nLastLeft - nQuoWidth;
1176 if( nDiff < 0 )
1177 {
1178 nLastLeft = pQuo->GetAscent();
1179 nQuoWidth = static_cast<sal_uInt16>(-nDiff + nLastLeft);
1180 }
1181 else
1182 {
1183 nQuoWidth = 0;
1184 nLastLeft = sal_uInt16(( pQuo->GetAscent() + nDiff ) / 2);
1185 }
1186 break;
1187 }
1188 default:
1189 nQuoWidth = nQuoWidth + nLastLeft;
1190 }
1191 }
1192 else
1193 nQuoWidth = nQuoWidth + nLastLeft;
1194 if( nLastLeft )
1195 {
1196 pGlue = new SwGluePortion(0);
1197 pGlue->Width( nLastLeft );
1198 pPor->Append( pGlue );
1199 pPor = pPor->GetNextPortion();
1200 }
1201 }
1202
1203 // Finally: we insert the QuoVadis Portion
1204 pCurrPor = pQuo;
1205 while ( pCurrPor )
1206 {
1207 // pPor->Append deletes the pPortion pointer of pPor.
1208 // Therefore we have to keep a pointer to the next portion
1209 pQuo = static_cast<SwQuoVadisPortion*>(pCurrPor->GetNextPortion());
1210 pPor->Append( pCurrPor );
1211 pPor = pPor->GetNextPortion();
1212 pCurrPor = pQuo;
1213 }
1214
1215 m_pCurr->Width( m_pCurr->Width() + nQuoWidth );
1216
1217 // And adjust again, due to the adjustment and due to the following special
1218 // case:
1219 // The DummyUser has set a smaller Font in the Line than the one used
1220 // by the QuoVadis text ...
1221 CalcAdjustLine( m_pCurr );
1222
1223 return nRet;
1224}
1225
1226/**
1227 * This function creates a Line that reaches to the other Page Margin.
1228 * DummyLines or DummyPortions make sure, that oscillations stop, because
1229 * there's no way to flow back.
1230 * They are used for Footnotes in paragraph-bound Frames and for Footnote
1231 * oscillations
1232 */
1233void SwTextFormatter::MakeDummyLine()
1234{
1235 sal_uInt16 nRstHeight = GetFrameRstHeight();
1236 if( m_pCurr && nRstHeight > m_pCurr->Height() )
1237 {
1238 SwLineLayout *pLay = new SwLineLayout;
1239 nRstHeight = nRstHeight - m_pCurr->Height();
1240 pLay->Height( nRstHeight );
1241 pLay->SetAscent( nRstHeight );
1242 Insert( pLay );
1243 Next();
1244 }
1245}
1246
1247namespace {
1248
1249class SwFootnoteSave
1250{
1251 SwTextSizeInfo *pInf;
1252 SwFont *pFnt;
1253 std::unique_ptr<SwFont> pOld;
1254
1255 SwFootnoteSave(const SwFootnoteSave&) = delete;
1256 SwFootnoteSave& operator=(const SwFootnoteSave&) = delete;
1257
1258public:
1259 SwFootnoteSave( const SwTextSizeInfo &rInf,
1260 const SwTextFootnote *pTextFootnote,
1261 const bool bApplyGivenScriptType,
1262 const SwFontScript nGivenScriptType );
1263 ~SwFootnoteSave() COVERITY_NOEXCEPT_FALSE;
1264};
1265
1266}
1267
1268SwFootnoteSave::SwFootnoteSave( const SwTextSizeInfo &rInf,
1269 const SwTextFootnote* pTextFootnote,
1270 const bool bApplyGivenScriptType,
1271 const SwFontScript nGivenScriptType )
1272 : pInf( &const_cast<SwTextSizeInfo&>(rInf) )
1273 , pFnt( nullptr )
1274{
1275 if( pTextFootnote && rInf.GetTextFrame() )
1276 {
1277 pFnt = const_cast<SwTextSizeInfo&>(rInf).GetFont();
1278 pOld.reset( new SwFont( *pFnt ) );
1279 pOld->GetTox() = pFnt->GetTox();
1280 pFnt->GetTox() = 0;
1281 SwFormatFootnote& rFootnote = const_cast<SwFormatFootnote&>(pTextFootnote->GetFootnote());
1282 const SwDoc *const pDoc = &rInf.GetTextFrame()->GetDoc();
1283
1284 // #i98418#
1285 if ( bApplyGivenScriptType )
1286 {
1287 pFnt->SetActual( nGivenScriptType );
1288 }
1289 else
1290 {
1291 // examine text and set script
1292 OUString aTmpStr(rFootnote.GetViewNumStr(*pDoc, rInf.GetTextFrame()->getRootFrame()));
1293 pFnt->SetActual( SwScriptInfo::WhichFont(0, aTmpStr) );
1294 }
1295
1296 const SwEndNoteInfo* pInfo;
1297 if( rFootnote.IsEndNote() )
1298 pInfo = &pDoc->GetEndNoteInfo();
1299 else
1300 pInfo = &pDoc->GetFootnoteInfo();
1301 const SwAttrSet& rSet = pInfo->GetAnchorCharFormat(const_cast<SwDoc&>(*pDoc))->GetAttrSet();
1302 pFnt->SetDiffFnt( &rSet, &pDoc->getIDocumentSettingAccess() );
1303
1304 // we reduce footnote size, if we are inside a double line portion
1305 if ( ! pOld->GetEscapement() && 50 == pOld->GetPropr() )
1306 {
1307 Size aSize = pFnt->GetSize( pFnt->GetActual() );
1308 pFnt->SetSize( Size( aSize.Width() / 2,
1309 aSize.Height() / 2 ),
1310 pFnt->GetActual() );
1311 }
1312
1313 // set the correct rotation at the footnote font
1314 const SfxPoolItem* pItem;
1315 if( SfxItemState::SET == rSet.GetItemState( RES_CHRATR_ROTATE,
1316 true, &pItem ))
1317 pFnt->SetVertical( static_cast<const SvxCharRotateItem*>(pItem)->GetValue(),
1318 rInf.GetTextFrame()->IsVertical() );
1319
1320 pFnt->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
1321
1322 if( SfxItemState::SET == rSet.GetItemState( RES_CHRATR_BACKGROUND,
1323 true, &pItem ))
1324 pFnt->SetBackColor( new Color( static_cast<const SvxBrushItem*>(pItem)->GetColor() ) );
1325 }
1326 else
1327 pFnt = nullptr;
1328}
1329
1330SwFootnoteSave::~SwFootnoteSave() COVERITY_NOEXCEPT_FALSE
1331{
1332 if( pFnt )
1333 {
1334 // Put back SwFont
1335 *pFnt = *pOld;
1336 pFnt->GetTox() = pOld->GetTox();
1337 pFnt->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
1338 pOld.reset();
1339 }
1340}
1341
1342SwFootnotePortion::SwFootnotePortion( const OUString &rExpand,
1343 SwTextFootnote *pFootn, sal_uInt16 nReal )
1344 : SwFieldPortion( rExpand, nullptr )
1345 , pFootnote(pFootn)
1346 , nOrigHeight( nReal )
1347 // #i98418#
1348 , mbPreferredScriptTypeSet( false )
1349 , mnPreferredScriptType( SwFontScript::Latin )
1350{
1351 SetLen(TextFrameIndex(1));
1352 SetWhichPor( PortionType::Footnote );
1353}
1354
1355bool SwFootnotePortion::GetExpText( const SwTextSizeInfo &, OUString &rText ) const
1356{
1357 rText = m_aExpand;
1358 return true;
1359}
1360
1361bool SwFootnotePortion::Format( SwTextFormatInfo &rInf )
1362{
1363 // #i98418#
1364// SwFootnoteSave aFootnoteSave( rInf, pFootnote );
1365 SwFootnoteSave aFootnoteSave( rInf, pFootnote, mbPreferredScriptTypeSet, mnPreferredScriptType );
1366 // the idx is manipulated in SwExpandPortion::Format
1367 // this flag indicates, that a footnote is allowed to trigger
1368 // an underflow during SwTextGuess::Guess
1369 rInf.SetFakeLineStart( rInf.GetIdx() > rInf.GetLineStart() );
1370 const bool bFull = SwFieldPortion::Format( rInf );
1371 rInf.SetFakeLineStart( false );
1372 SetAscent( rInf.GetAscent() );
1373 Height( rInf.GetTextHeight() );
1374 rInf.SetFootnoteDone( !bFull );
1375 if( !bFull )
1376 rInf.SetParaFootnote();
1377 return bFull;
1378}
1379
1380void SwFootnotePortion::Paint( const SwTextPaintInfo &rInf ) const
1381{
1382 // #i98418#
1383// SwFootnoteSave aFootnoteSave( rInf, pFootnote );
1384 SwFootnoteSave aFootnoteSave( rInf, pFootnote, mbPreferredScriptTypeSet, mnPreferredScriptType );
1385 rInf.DrawViewOpt( *this, PortionType::Footnote );
1386 SwExpandPortion::Paint( rInf );
1387}
1388
1389SwPosSize SwFootnotePortion::GetTextSize( const SwTextSizeInfo &rInfo ) const
1390{
1391 // #i98418#
1392// SwFootnoteSave aFootnoteSave( rInfo, pFootnote );
1393 SwFootnoteSave aFootnoteSave( rInfo, pFootnote, mbPreferredScriptTypeSet, mnPreferredScriptType );
1394 return SwExpandPortion::GetTextSize( rInfo );
1395}
1396
1397// #i98418#
1398void SwFootnotePortion::SetPreferredScriptType( SwFontScript nPreferredScriptType )
1399{
1400 mbPreferredScriptTypeSet = true;
1401 mnPreferredScriptType = nPreferredScriptType;
1402}
1403
1404SwFieldPortion *SwQuoVadisPortion::Clone( const OUString &rExpand ) const
1405{
1406 return new SwQuoVadisPortion( rExpand, aErgo );
1407}
1408
1409SwQuoVadisPortion::SwQuoVadisPortion( const OUString &rExp, const OUString& rStr )
1410 : SwFieldPortion( rExp ), aErgo(rStr)
1411{
1412 SetLen(TextFrameIndex(0));
1413 SetWhichPor( PortionType::QuoVadis );
1414}
1415
1416bool SwQuoVadisPortion::Format( SwTextFormatInfo &rInf )
1417{
1418 // First try; maybe the Text fits
1419 CheckScript( rInf );
1420 bool bFull = SwFieldPortion::Format( rInf );
1421 SetLen(TextFrameIndex(0));
1422
1423 if( bFull )
1424 {
1425 // Second try; we make the String shorter
1426 m_aExpand = "...";
1427 bFull = SwFieldPortion::Format( rInf );
1428 SetLen(TextFrameIndex(0));
1429 if( bFull )
1430 // Third try; we're done: we crush
1431 Width( sal_uInt16(rInf.Width() - rInf.X()) );
1432
1433 // No multiline Fields for QuoVadis and ErgoSum
1434 if( rInf.GetRest() )
1435 {
1436 delete rInf.GetRest();
1437 rInf.SetRest( nullptr );
1438 }
1439 }
1440 return bFull;
1441}
1442
1443bool SwQuoVadisPortion::GetExpText( const SwTextSizeInfo &, OUString &rText ) const
1444{
1445 rText = m_aExpand;
1446 // if this QuoVadisPortion has a follow, the follow is responsible for
1447 // the ergo text.
1448 if ( ! HasFollow() )
1449 rText += aErgo;
1450 return true;
1451}
1452
1453void SwQuoVadisPortion::HandlePortion( SwPortionHandler& rPH ) const
1454{
1455 rPH.Special( GetLen(), m_aExpand + aErgo, GetWhichPor() );
1456}
1457
1458void SwQuoVadisPortion::Paint( const SwTextPaintInfo &rInf ) const
1459{
1460 // We _always_ want to output per DrawStretchText, because nErgo
1461 // can quickly switch
1462 if( PrtWidth() )
1463 {
1464 rInf.DrawViewOpt( *this, PortionType::QuoVadis );
1465 SwTextSlot aDiffText( &rInf, this, true, false );
1466 SwFontSave aSave( rInf, m_pFont.get() );
1467 rInf.DrawText( *this, rInf.GetLen(), true );
1468 }
1469}
1470
1471SwFieldPortion *SwErgoSumPortion::Clone( const OUString &rExpand ) const
1472{
1473 return new SwErgoSumPortion( rExpand, OUString() );
1474}
1475
1476SwErgoSumPortion::SwErgoSumPortion(const OUString &rExp, const OUString& rStr)
1477 : SwFieldPortion( rExp )
1478{
1479 SetLen(TextFrameIndex(0));
1480 m_aExpand += rStr;
1481
1482 // One blank distance to the text
1483 m_aExpand += " ";
1484 SetWhichPor( PortionType::ErgoSum );
1485}
1486
1487TextFrameIndex SwErgoSumPortion::GetModelPositionForViewPoint(const sal_uInt16) const
1488{
1489 return TextFrameIndex(0);
1490}
1491
1492bool SwErgoSumPortion::Format( SwTextFormatInfo &rInf )
1493{
1494 const bool bFull = SwFieldPortion::Format( rInf );
1495 SetLen(TextFrameIndex(0));
1496 rInf.SetErgoDone( true );
1497
1498 // No multiline Fields for QuoVadis and ErgoSum
1499 if( bFull && rInf.GetRest() )
1500 {
1501 delete rInf.GetRest();
1502 rInf.SetRest( nullptr );
1503 }
1504
1505 // We return false in order to get some text into the current line,
1506 // even if it's full (better than looping)
1507 return false;
1508}
1509
1510void SwParaPortion::SetErgoSumNum( const OUString& rErgo )
1511{
1512 SwLineLayout *pLay = this;
1513 while( pLay->GetNext() )
1514 {
1515 pLay = pLay->GetNext();
1516 }
1517 SwLinePortion *pPor = pLay;
1518 SwQuoVadisPortion *pQuo = nullptr;
1519 while( pPor && !pQuo )
1520 {
1521 if ( pPor->IsQuoVadisPortion() )
1522 pQuo = static_cast<SwQuoVadisPortion*>(pPor);
1523 pPor = pPor->GetNextPortion();
1524 }
1525 if( pQuo )
1526 pQuo->SetNumber( rErgo );
1527}
1528
1529/**
1530 * Is called in SwTextFrame::Prepare()
1531 */
1532bool SwParaPortion::UpdateQuoVadis( const OUString &rQuo )
1533{
1534 SwLineLayout *pLay = this;
1535 while( pLay->GetNext() )
1536 {
1537 pLay = pLay->GetNext();
1538 }
1539 SwLinePortion *pPor = pLay;
1540 SwQuoVadisPortion *pQuo = nullptr;
1541 while( pPor && !pQuo )
1542 {
1543 if ( pPor->IsQuoVadisPortion() )
1544 pQuo = static_cast<SwQuoVadisPortion*>(pPor);
1545 pPor = pPor->GetNextPortion();
1546 }
1547
1548 if( !pQuo )
1549 return false;
1550
1551 return pQuo->GetQuoText() == rQuo;
1552}
1553
1554/* 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;
1088}
1089inline SwFlyFrame *SwFrame::FindFlyFrame()
1090{
1091 return IsInFly() ? ImplFindFlyFrame() : nullptr;
1092}
1093inline SwSectionFrame *SwFrame::FindSctFrame()
1094{
1095 return IsInSct() ? ImplFindSctFrame() : nullptr;
23
Assuming the condition is true
24
'?' condition is true
25
Returning pointer, which participates in a condition later
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: */