File: | home/maarten/src/libreoffice/core/sw/source/core/text/txtftn.cxx |
Warning: | line 656, column 50 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |||||||||
57 | using namespace ::com::sun::star; | ||||||||
58 | |||||||||
59 | bool 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 | */ | ||||||||
72 | SwTextFrame *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 | |||||||||
86 | void SwTextFrame::SetHasRotatedPortions(bool bHasRotatedPortions) | ||||||||
87 | { | ||||||||
88 | mbHasRotatedPortions = bHasRotatedPortions; | ||||||||
89 | } | ||||||||
90 | |||||||||
91 | #ifdef DBG_UTIL | ||||||||
92 | void SwTextFrame::CalcFootnoteFlag(TextFrameIndex nStop) // For testing the SplitFrame | ||||||||
93 | #else | ||||||||
94 | void 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 | |||||||||
127 | bool 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 | */ | ||||||||
168 | static 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 | |||||||||
260 | SwTwips 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 | */ | ||||||||
301 | SwTwips 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 | |||||||||
372 | SwTextFrame *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 | |||||||||
395 | void 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 | */ | ||||||||
580 | void 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) | ||||||||
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() ) | ||||||||
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(); | ||||||||
611 | bool bDocEnd = bEnd
| ||||||||
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
| ||||||||
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
| ||||||||
635 | { | ||||||||
636 | SwFootnoteFrame *pFootnoteFrame = pSrcFrame ? SwFootnoteBossFrame::FindFootnote( pSrcFrame, pFootnote ) : nullptr; | ||||||||
637 | if( pFootnoteFrame && !pFootnoteFrame->GetUpper() ) | ||||||||
638 | pFootnoteFrame = nullptr; | ||||||||
639 | SwDoc *const pDoc = &GetDoc(); | ||||||||
640 | if( SwLayouter::Collecting( pDoc, pSect, pFootnoteFrame ) ) | ||||||||
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
| ||||||||
655 | { | ||||||||
656 | SwFootnoteBossFrame *pFootnoteBoss = pFootnoteFrame->FindFootnoteBossFrame(); | ||||||||
| |||||||||
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 | */ | ||||||||
780 | SwFootnotePortion *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) | ||||||||
| |||||||||
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() ) | ||||||||
789 | return new SwFootnotePortion("", pFootnote); | ||||||||
790 | |||||||||
791 | const SwFormatFootnote& rFootnote = pFootnote->GetFootnote(); | ||||||||
792 | SwDoc *const pDoc = &m_pFrame->GetDoc(); | ||||||||
793 | |||||||||
794 | if( rInf.IsTest() ) | ||||||||
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 ) | ||||||||
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 ) | ||||||||
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() ) | ||||||||
825 | m_pFrame->ConnectFootnote( pFootnote, nLower ); | ||||||||
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 | */ | ||||||||
920 | SwNumberPortion *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 | |||||||||
993 | static 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 | |||||||||
1001 | SwErgoSumPortion *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 | |||||||||
1029 | TextFrameIndex 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 | */ | ||||||||
1233 | void 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 | |||||||||
1247 | namespace { | ||||||||
1248 | |||||||||
1249 | class 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 | |||||||||
1258 | public: | ||||||||
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 | |||||||||
1268 | SwFootnoteSave::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 | |||||||||
1330 | SwFootnoteSave::~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 | |||||||||
1342 | SwFootnotePortion::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 | |||||||||
1355 | bool SwFootnotePortion::GetExpText( const SwTextSizeInfo &, OUString &rText ) const | ||||||||
1356 | { | ||||||||
1357 | rText = m_aExpand; | ||||||||
1358 | return true; | ||||||||
1359 | } | ||||||||
1360 | |||||||||
1361 | bool 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 | |||||||||
1380 | void 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 | |||||||||
1389 | SwPosSize 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# | ||||||||
1398 | void SwFootnotePortion::SetPreferredScriptType( SwFontScript nPreferredScriptType ) | ||||||||
1399 | { | ||||||||
1400 | mbPreferredScriptTypeSet = true; | ||||||||
1401 | mnPreferredScriptType = nPreferredScriptType; | ||||||||
1402 | } | ||||||||
1403 | |||||||||
1404 | SwFieldPortion *SwQuoVadisPortion::Clone( const OUString &rExpand ) const | ||||||||
1405 | { | ||||||||
1406 | return new SwQuoVadisPortion( rExpand, aErgo ); | ||||||||
1407 | } | ||||||||
1408 | |||||||||
1409 | SwQuoVadisPortion::SwQuoVadisPortion( const OUString &rExp, const OUString& rStr ) | ||||||||
1410 | : SwFieldPortion( rExp ), aErgo(rStr) | ||||||||
1411 | { | ||||||||
1412 | SetLen(TextFrameIndex(0)); | ||||||||
1413 | SetWhichPor( PortionType::QuoVadis ); | ||||||||
1414 | } | ||||||||
1415 | |||||||||
1416 | bool 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 | |||||||||
1443 | bool 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 | |||||||||
1453 | void SwQuoVadisPortion::HandlePortion( SwPortionHandler& rPH ) const | ||||||||
1454 | { | ||||||||
1455 | rPH.Special( GetLen(), m_aExpand + aErgo, GetWhichPor() ); | ||||||||
1456 | } | ||||||||
1457 | |||||||||
1458 | void 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 | |||||||||
1471 | SwFieldPortion *SwErgoSumPortion::Clone( const OUString &rExpand ) const | ||||||||
1472 | { | ||||||||
1473 | return new SwErgoSumPortion( rExpand, OUString() ); | ||||||||
1474 | } | ||||||||
1475 | |||||||||
1476 | SwErgoSumPortion::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 | |||||||||
1487 | TextFrameIndex SwErgoSumPortion::GetModelPositionForViewPoint(const sal_uInt16) const | ||||||||
1488 | { | ||||||||
1489 | return TextFrameIndex(0); | ||||||||
1490 | } | ||||||||
1491 | |||||||||
1492 | bool 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 | |||||||||
1510 | void 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 | */ | ||||||||
1532 | bool 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: */ |
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 | |
37 | namespace drawinglayer::processor2d { class BaseProcessor2D; } |
38 | |
39 | class SwLayoutFrame; |
40 | class SwRootFrame; |
41 | class SwPageFrame; |
42 | class SwBodyFrame; |
43 | class SwFlyFrame; |
44 | class SwSectionFrame; |
45 | class SwFootnoteFrame; |
46 | class SwFootnoteBossFrame; |
47 | class SwTabFrame; |
48 | class SwRowFrame; |
49 | class SwContentFrame; |
50 | class SwAttrSet; |
51 | class Color; |
52 | class SwBorderAttrs; |
53 | class SwCache; |
54 | class SvxBrushItem; |
55 | class SvxFormatBreakItem; |
56 | class SwFormatPageDesc; |
57 | class SwSelectionList; |
58 | struct SwPosition; |
59 | struct SwCursorMoveState; |
60 | class SwFormat; |
61 | class SwPrintData; |
62 | class SwSortedObjs; |
63 | class SwAnchoredObject; |
64 | enum class SvxFrameDirection; |
65 | class 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. |
72 | enum 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 | |
93 | namespace 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. |
110 | enum 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 | |
119 | namespace 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 |
130 | class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwFrameAreaDefinition |
131 | { |
132 | private: |
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 | |
153 | protected: |
154 | // write access to mb*Valid flags |
155 | void setFrameAreaPositionValid(bool bNew); |
156 | void setFrameAreaSizeValid(bool bNew); |
157 | void setFramePrintAreaValid(bool bNew); |
158 | |
159 | public: |
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 >') |
233 | class TransformableSwFrame |
234 | { |
235 | private: |
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 | |
244 | public: |
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 | */ |
297 | class 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 | |
395 | protected: |
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 | |
493 | public: |
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 | |
911 | public: |
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 | |
921 | inline bool SwFrame::IsInDocBody() const |
922 | { |
923 | if ( mbInfInvalid ) |
924 | const_cast<SwFrame*>(this)->SetInfFlags(); |
925 | return mbInfBody; |
926 | } |
927 | inline bool SwFrame::IsInFootnote() const |
928 | { |
929 | if ( mbInfInvalid ) |
930 | const_cast<SwFrame*>(this)->SetInfFlags(); |
931 | return mbInfFootnote; |
932 | } |
933 | inline bool SwFrame::IsInTab() const |
934 | { |
935 | if ( mbInfInvalid ) |
936 | const_cast<SwFrame*>(this)->SetInfFlags(); |
937 | return mbInfTab; |
938 | } |
939 | inline bool SwFrame::IsInFly() const |
940 | { |
941 | if ( mbInfInvalid ) |
942 | const_cast<SwFrame*>(this)->SetInfFlags(); |
943 | return mbInfFly; |
944 | } |
945 | inline bool SwFrame::IsInSct() const |
946 | { |
947 | if ( mbInfInvalid ) |
948 | const_cast<SwFrame*>(this)->SetInfFlags(); |
949 | return mbInfSct; |
950 | } |
951 | bool SwFrame::IsVertical() const |
952 | { |
953 | if( mbInvalidVert ) |
954 | const_cast<SwFrame*>(this)->SetDirFlags( true ); |
955 | return mbVertical; |
956 | } |
957 | inline bool SwFrame::IsVertLR() const |
958 | { |
959 | return mbVertLR; |
960 | } |
961 | inline bool SwFrame::IsVertLRBT() const |
962 | { |
963 | return mbVertLRBT; |
964 | } |
965 | inline bool SwFrame::IsRightToLeft() const |
966 | { |
967 | if( mbInvalidR2L ) |
968 | const_cast<SwFrame*>(this)->SetDirFlags( false ); |
969 | return mbRightToLeft; |
970 | } |
971 | |
972 | inline void SwFrame::SetCompletePaint() const |
973 | { |
974 | const_cast<SwFrame*>(this)->mbCompletePaint = true; |
975 | } |
976 | inline void SwFrame::ResetCompletePaint() const |
977 | { |
978 | const_cast<SwFrame*>(this)->mbCompletePaint = false; |
979 | } |
980 | |
981 | inline void SwFrame::SetRetouche() const |
982 | { |
983 | const_cast<SwFrame*>(this)->mbRetouche = true; |
984 | } |
985 | inline void SwFrame::ResetRetouche() const |
986 | { |
987 | const_cast<SwFrame*>(this)->mbRetouche = false; |
988 | } |
989 | |
990 | inline SwLayoutFrame *SwFrame::GetNextLayoutLeaf() |
991 | { |
992 | return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetNextLayoutLeaf()); |
993 | } |
994 | inline SwLayoutFrame *SwFrame::GetPrevLayoutLeaf() |
995 | { |
996 | return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetPrevLayoutLeaf()); |
997 | } |
998 | inline const SwLayoutFrame *SwFrame::GetNextLayoutLeaf() const |
999 | { |
1000 | return ImplGetNextLayoutLeaf( true ); |
1001 | } |
1002 | inline const SwLayoutFrame *SwFrame::GetPrevLayoutLeaf() const |
1003 | { |
1004 | return ImplGetNextLayoutLeaf( false ); |
1005 | } |
1006 | |
1007 | inline void SwFrame::InvalidateSize() |
1008 | { |
1009 | if ( isFrameAreaSizeValid() ) |
1010 | { |
1011 | ImplInvalidateSize(); |
1012 | } |
1013 | } |
1014 | inline void SwFrame::InvalidatePrt() |
1015 | { |
1016 | if ( isFramePrintAreaValid() ) |
1017 | { |
1018 | ImplInvalidatePrt(); |
1019 | } |
1020 | } |
1021 | inline void SwFrame::InvalidatePos() |
1022 | { |
1023 | if ( isFrameAreaPositionValid() ) |
1024 | { |
1025 | ImplInvalidatePos(); |
1026 | } |
1027 | } |
1028 | inline void SwFrame::InvalidateLineNum() |
1029 | { |
1030 | if ( mbValidLineNum ) |
1031 | ImplInvalidateLineNum(); |
1032 | } |
1033 | inline 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 | } |
1050 | inline void SwFrame::InvalidateNextPos( bool bNoFootnote ) |
1051 | { |
1052 | if ( mpNext && !mpNext->IsSctFrame() ) |
1053 | mpNext->InvalidatePos(); |
1054 | else |
1055 | ImplInvalidateNextPos( bNoFootnote ); |
1056 | } |
1057 | |
1058 | inline void SwFrame::OptCalc() const |
1059 | { |
1060 | if ( !isFrameAreaPositionValid() || !isFramePrintAreaValid() || !isFrameAreaSizeValid() ) |
1061 | { |
1062 | const_cast<SwFrame*>(this)->OptPrepareMake(); |
1063 | } |
1064 | } |
1065 | inline const SwPageFrame *SwFrame::FindPageFrame() const |
1066 | { |
1067 | return const_cast<SwFrame*>(this)->FindPageFrame(); |
1068 | } |
1069 | inline const SwFrame *SwFrame::FindColFrame() const |
1070 | { |
1071 | return const_cast<SwFrame*>(this)->FindColFrame(); |
1072 | } |
1073 | inline const SwFrame *SwFrame::FindFooterOrHeader() const |
1074 | { |
1075 | return const_cast<SwFrame*>(this)->FindFooterOrHeader(); |
1076 | } |
1077 | inline SwTabFrame *SwFrame::FindTabFrame() |
1078 | { |
1079 | return IsInTab() ? ImplFindTabFrame() : nullptr; |
1080 | } |
1081 | inline const SwFootnoteBossFrame *SwFrame::FindFootnoteBossFrame( bool bFootnote ) const |
1082 | { |
1083 | return const_cast<SwFrame*>(this)->FindFootnoteBossFrame( bFootnote ); |
1084 | } |
1085 | inline SwFootnoteFrame *SwFrame::FindFootnoteFrame() |
1086 | { |
1087 | return IsInFootnote() ? ImplFindFootnoteFrame() : nullptr; |
1088 | } |
1089 | inline SwFlyFrame *SwFrame::FindFlyFrame() |
1090 | { |
1091 | return IsInFly() ? ImplFindFlyFrame() : nullptr; |
1092 | } |
1093 | inline SwSectionFrame *SwFrame::FindSctFrame() |
1094 | { |
1095 | return IsInSct() ? ImplFindSctFrame() : nullptr; |
1096 | } |
1097 | |
1098 | inline const SwBodyFrame *SwFrame::FindBodyFrame() const |
1099 | { |
1100 | return IsInDocBody() ? ImplFindBodyFrame() : nullptr; |
1101 | } |
1102 | |
1103 | inline const SwTabFrame *SwFrame::FindTabFrame() const |
1104 | { |
1105 | return IsInTab() ? const_cast<SwFrame*>(this)->ImplFindTabFrame() : nullptr; |
1106 | } |
1107 | inline const SwFootnoteFrame *SwFrame::FindFootnoteFrame() const |
1108 | { |
1109 | return IsInFootnote() ? const_cast<SwFrame*>(this)->ImplFindFootnoteFrame() : nullptr; |
1110 | } |
1111 | inline const SwFlyFrame *SwFrame::FindFlyFrame() const |
1112 | { |
1113 | return IsInFly() ? const_cast<SwFrame*>(this)->ImplFindFlyFrame() : nullptr; |
1114 | } |
1115 | inline const SwSectionFrame *SwFrame::FindSctFrame() const |
1116 | { |
1117 | return IsInSct() ? const_cast<SwFrame*>(this)->ImplFindSctFrame() : nullptr; |
1118 | } |
1119 | inline SwFrame *SwFrame::FindNext() |
1120 | { |
1121 | if ( mpNext ) |
1122 | return mpNext; |
1123 | else |
1124 | return FindNext_(); |
1125 | } |
1126 | inline const SwFrame *SwFrame::FindNext() const |
1127 | { |
1128 | if ( mpNext ) |
1129 | return mpNext; |
1130 | else |
1131 | return const_cast<SwFrame*>(this)->FindNext_(); |
1132 | } |
1133 | inline SwFrame *SwFrame::FindPrev() |
1134 | { |
1135 | if ( mpPrev && !mpPrev->IsSctFrame() ) |
1136 | return mpPrev; |
1137 | else |
1138 | return FindPrev_(); |
1139 | } |
1140 | inline 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 | |
1148 | inline bool SwFrame::IsLayoutFrame() const |
1149 | { |
1150 | return bool(GetType() & FRM_LAYOUTSwFrameType(0x3bFF)); |
1151 | } |
1152 | inline bool SwFrame::IsRootFrame() const |
1153 | { |
1154 | return mnFrameType == SwFrameType::Root; |
1155 | } |
1156 | inline bool SwFrame::IsPageFrame() const |
1157 | { |
1158 | return mnFrameType == SwFrameType::Page; |
1159 | } |
1160 | inline bool SwFrame::IsColumnFrame() const |
1161 | { |
1162 | return mnFrameType == SwFrameType::Column; |
1163 | } |
1164 | inline bool SwFrame::IsFootnoteBossFrame() const |
1165 | { |
1166 | return bool(GetType() & FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column)); |
1167 | } |
1168 | inline bool SwFrame::IsHeaderFrame() const |
1169 | { |
1170 | return mnFrameType == SwFrameType::Header; |
1171 | } |
1172 | inline bool SwFrame::IsFooterFrame() const |
1173 | { |
1174 | return mnFrameType == SwFrameType::Footer; |
1175 | } |
1176 | inline bool SwFrame::IsFootnoteContFrame() const |
1177 | { |
1178 | return mnFrameType == SwFrameType::FtnCont; |
1179 | } |
1180 | inline bool SwFrame::IsFootnoteFrame() const |
1181 | { |
1182 | return mnFrameType == SwFrameType::Ftn; |
1183 | } |
1184 | inline bool SwFrame::IsBodyFrame() const |
1185 | { |
1186 | return mnFrameType == SwFrameType::Body; |
1187 | } |
1188 | inline bool SwFrame::IsFlyFrame() const |
1189 | { |
1190 | return mnFrameType == SwFrameType::Fly; |
1191 | } |
1192 | inline bool SwFrame::IsSctFrame() const |
1193 | { |
1194 | return mnFrameType == SwFrameType::Section; |
1195 | } |
1196 | inline bool SwFrame::IsTabFrame() const |
1197 | { |
1198 | return mnFrameType == SwFrameType::Tab; |
1199 | } |
1200 | inline bool SwFrame::IsRowFrame() const |
1201 | { |
1202 | return mnFrameType == SwFrameType::Row; |
1203 | } |
1204 | inline bool SwFrame::IsCellFrame() const |
1205 | { |
1206 | return mnFrameType == SwFrameType::Cell; |
1207 | } |
1208 | inline bool SwFrame::IsContentFrame() const |
1209 | { |
1210 | return bool(GetType() & FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)); |
1211 | } |
1212 | inline bool SwFrame::IsTextFrame() const |
1213 | { |
1214 | return mnFrameType == SwFrameType::Txt; |
1215 | } |
1216 | inline bool SwFrame::IsNoTextFrame() const |
1217 | { |
1218 | return mnFrameType == SwFrameType::NoTxt; |
1219 | } |
1220 | inline bool SwFrame::IsFlowFrame() const |
1221 | { |
1222 | return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section)); |
1223 | } |
1224 | inline bool SwFrame::IsRetoucheFrame() const |
1225 | { |
1226 | return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section|SwFrameType::Ftn)); |
1227 | } |
1228 | inline 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 |
1234 | class SwFrameDeleteGuard |
1235 | { |
1236 | private: |
1237 | SwFrame *m_pForbidFrame; |
1238 | public: |
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 | |
1261 | typedef long (SwFrame::*SwFrameGet)() const; |
1262 | typedef bool (SwFrame::*SwFrameMax)( long ); |
1263 | typedef void (SwFrame::*SwFrameMakePos)( const SwFrame*, const SwFrame*, bool ); |
1264 | typedef long (*SwOperator)( long, long ); |
1265 | typedef void (SwFrame::*SwFrameSet)( long, long ); |
1266 | |
1267 | struct 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 | |
1323 | typedef SwRectFnCollection* SwRectFn; |
1324 | |
1325 | // This class allows to use proper methods regardless of orientation (LTR/RTL, horizontal or vertical) |
1326 | extern SwRectFn fnRectHori, fnRectVert, fnRectVertL2R, fnRectVertL2RB2T; |
1327 | class SwRectFnSet { |
1328 | public: |
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 | |
1408 | private: |
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: */ |