File: | home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx |
Warning: | line 3498, column 16 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 <svx/svdpage.hxx> | |||
21 | #include <editeng/brushitem.hxx> | |||
22 | #include <editeng/shaditem.hxx> | |||
23 | #include <editeng/ulspitem.hxx> | |||
24 | #include <editeng/boxitem.hxx> | |||
25 | #include <editeng/lspcitem.hxx> | |||
26 | #include <editeng/fhgtitem.hxx> | |||
27 | #include <sal/log.hxx> | |||
28 | ||||
29 | #include <drawdoc.hxx> | |||
30 | #include <fmtornt.hxx> | |||
31 | #include <fmthdft.hxx> | |||
32 | #include <fmtfsize.hxx> | |||
33 | #include <fmtsrnd.hxx> | |||
34 | #include <docary.hxx> | |||
35 | #include <lineinfo.hxx> | |||
36 | #include <swmodule.hxx> | |||
37 | #include <pagefrm.hxx> | |||
38 | #include <colfrm.hxx> | |||
39 | #include <fesh.hxx> | |||
40 | #include <viewimp.hxx> | |||
41 | #include <viewopt.hxx> | |||
42 | #include <dflyobj.hxx> | |||
43 | #include <dcontact.hxx> | |||
44 | #include <frmatr.hxx> | |||
45 | #include <frmtool.hxx> | |||
46 | #include <tabfrm.hxx> | |||
47 | #include <rowfrm.hxx> | |||
48 | #include <ftnfrm.hxx> | |||
49 | #include <txtfrm.hxx> | |||
50 | #include <notxtfrm.hxx> | |||
51 | #include <flyfrms.hxx> | |||
52 | #include <layact.hxx> | |||
53 | #include <pagedesc.hxx> | |||
54 | #include <section.hxx> | |||
55 | #include <sectfrm.hxx> | |||
56 | #include <node2lay.hxx> | |||
57 | #include <ndole.hxx> | |||
58 | #include <hints.hxx> | |||
59 | #include "layhelp.hxx" | |||
60 | #include <laycache.hxx> | |||
61 | #include <rootfrm.hxx> | |||
62 | #include <paratr.hxx> | |||
63 | #include <redline.hxx> | |||
64 | #include <sortedobjs.hxx> | |||
65 | #include <objectformatter.hxx> | |||
66 | #include <calbck.hxx> | |||
67 | #include <ndtxt.hxx> | |||
68 | #include <undobj.hxx> | |||
69 | #include <DocumentSettingManager.hxx> | |||
70 | #include <IDocumentDrawModelAccess.hxx> | |||
71 | #include <IDocumentTimerAccess.hxx> | |||
72 | #include <IDocumentRedlineAccess.hxx> | |||
73 | #include <IDocumentFieldsAccess.hxx> | |||
74 | #include <IDocumentState.hxx> | |||
75 | #include <frameformats.hxx> | |||
76 | #include <boost/circular_buffer.hpp> | |||
77 | #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx> | |||
78 | ||||
79 | using namespace ::com::sun::star; | |||
80 | ||||
81 | bool bObjsDirect = true; | |||
82 | bool bDontCreateObjects = false; | |||
83 | bool bSetCompletePaintOnInvalidate = false; | |||
84 | ||||
85 | sal_uInt8 StackHack::nCnt = 0; | |||
86 | bool StackHack::bLocked = false; | |||
87 | ||||
88 | SwFrameNotify::SwFrameNotify( SwFrame *pF ) : | |||
89 | mpFrame( pF ), | |||
90 | maFrame( pF->getFrameArea() ), | |||
91 | maPrt( pF->getFramePrintArea() ), | |||
92 | mbInvaKeep( false ), | |||
93 | mbValidSize( pF->isFrameAreaSizeValid() ) | |||
94 | { | |||
95 | if ( pF->IsTextFrame() ) | |||
96 | { | |||
97 | mnFlyAnchorOfst = static_cast<SwTextFrame*>(pF)->GetBaseOffsetForFly( true ); | |||
98 | mnFlyAnchorOfstNoWrap = static_cast<SwTextFrame*>(pF)->GetBaseOffsetForFly( false ); | |||
99 | } | |||
100 | else | |||
101 | { | |||
102 | mnFlyAnchorOfst = 0; | |||
103 | mnFlyAnchorOfstNoWrap = 0; | |||
104 | } | |||
105 | ||||
106 | mbHadFollow = pF->IsContentFrame() && static_cast<SwContentFrame*>(pF)->GetFollow(); | |||
107 | } | |||
108 | ||||
109 | SwFrameNotify::~SwFrameNotify() COVERITY_NOEXCEPT_FALSE | |||
110 | { | |||
111 | SwRectFnSet aRectFnSet(mpFrame); | |||
112 | const bool bAbsP = aRectFnSet.PosDiff(maFrame, mpFrame->getFrameArea()); | |||
113 | const bool bChgWidth = | |||
114 | aRectFnSet.GetWidth(maFrame) != aRectFnSet.GetWidth(mpFrame->getFrameArea()); | |||
115 | const bool bChgHeight = | |||
116 | aRectFnSet.GetHeight(maFrame)!=aRectFnSet.GetHeight(mpFrame->getFrameArea()); | |||
117 | const bool bChgFlyBasePos = mpFrame->IsTextFrame() && | |||
118 | ( ( mnFlyAnchorOfst != static_cast<SwTextFrame*>(mpFrame)->GetBaseOffsetForFly( true ) ) || | |||
119 | ( mnFlyAnchorOfstNoWrap != static_cast<SwTextFrame*>(mpFrame)->GetBaseOffsetForFly( false ) ) ); | |||
120 | ||||
121 | if ( mpFrame->IsFlowFrame() && !mpFrame->IsInFootnote() ) | |||
122 | { | |||
123 | SwFlowFrame *pFlow = SwFlowFrame::CastFlowFrame( mpFrame ); | |||
124 | ||||
125 | if ( !pFlow->IsFollow() ) | |||
126 | { | |||
127 | if ( !mpFrame->GetIndPrev() ) | |||
128 | { | |||
129 | if ( mbInvaKeep ) | |||
130 | { | |||
131 | SwFrame *pPre = mpFrame->FindPrev(); | |||
132 | if ( pPre && pPre->IsFlowFrame() ) | |||
133 | { | |||
134 | // 1. pPre wants to keep with me: | |||
135 | bool bInvalidPrePos = SwFlowFrame::CastFlowFrame(pPre)->IsKeep(pPre->GetAttrSet()->GetKeep(), pPre->GetBreakItem()) | |||
136 | && pPre->GetIndPrev(); | |||
137 | ||||
138 | // 2. pPre is a table and the last row wants to keep with me: | |||
139 | if ( !bInvalidPrePos && pPre->IsTabFrame() ) | |||
140 | { | |||
141 | SwTabFrame* pPreTab = static_cast<SwTabFrame*>(pPre); | |||
142 | if ( pPreTab->GetFormat()->GetDoc()->GetDocumentSettingManager().get(DocumentSettingId::TABLE_ROW_KEEP) ) | |||
143 | { | |||
144 | SwRowFrame* pLastRow = static_cast<SwRowFrame*>(pPreTab->GetLastLower()); | |||
145 | if ( pLastRow && pLastRow->ShouldRowKeepWithNext() ) | |||
146 | bInvalidPrePos = true; | |||
147 | } | |||
148 | } | |||
149 | ||||
150 | if ( bInvalidPrePos ) | |||
151 | pPre->InvalidatePos(); | |||
152 | } | |||
153 | } | |||
154 | } | |||
155 | else if ( !pFlow->HasFollow() ) | |||
156 | { | |||
157 | long nOldHeight = aRectFnSet.GetHeight(maFrame); | |||
158 | long nNewHeight = aRectFnSet.GetHeight(mpFrame->getFrameArea()); | |||
159 | if( (nOldHeight > nNewHeight) || (!nOldHeight && nNewHeight) ) | |||
160 | pFlow->CheckKeep(); | |||
161 | } | |||
162 | } | |||
163 | } | |||
164 | ||||
165 | if ( bAbsP ) | |||
166 | { | |||
167 | mpFrame->SetCompletePaint(); | |||
168 | ||||
169 | SwFrame* pNxt = mpFrame->GetIndNext(); | |||
170 | // #121888# - skip empty section frames | |||
171 | while ( pNxt && | |||
172 | pNxt->IsSctFrame() && !static_cast<SwSectionFrame*>(pNxt)->GetSection() ) | |||
173 | { | |||
174 | pNxt = pNxt->GetIndNext(); | |||
175 | } | |||
176 | ||||
177 | if ( pNxt ) | |||
178 | pNxt->InvalidatePos(); | |||
179 | else | |||
180 | { | |||
181 | // #104100# - correct condition for setting retouche | |||
182 | // flag for vertical layout. | |||
183 | if( mpFrame->IsRetoucheFrame() && | |||
184 | aRectFnSet.TopDist( maFrame, aRectFnSet.GetTop(mpFrame->getFrameArea()) ) > 0 ) | |||
185 | { | |||
186 | mpFrame->SetRetouche(); | |||
187 | } | |||
188 | ||||
189 | // A fresh follow frame does not have to be invalidated, because | |||
190 | // it is already formatted: | |||
191 | if ( mbHadFollow || !mpFrame->IsContentFrame() || !static_cast<SwContentFrame*>(mpFrame)->GetFollow() ) | |||
192 | { | |||
193 | if ( !mpFrame->IsTabFrame() || !static_cast<SwTabFrame*>(mpFrame)->GetFollow() ) | |||
194 | mpFrame->InvalidateNextPos(); | |||
195 | } | |||
196 | } | |||
197 | } | |||
198 | ||||
199 | //For each resize of the background graphics is a repaint necessary. | |||
200 | const bool bPrtWidth = | |||
201 | aRectFnSet.GetWidth(maPrt) != aRectFnSet.GetWidth(mpFrame->getFramePrintArea()); | |||
202 | const bool bPrtHeight = | |||
203 | aRectFnSet.GetHeight(maPrt)!=aRectFnSet.GetHeight(mpFrame->getFramePrintArea()); | |||
204 | if ( bPrtWidth || bPrtHeight ) | |||
205 | { | |||
206 | bool bUseNewFillProperties(false); | |||
207 | if (mpFrame->supportsFullDrawingLayerFillAttributeSet()) | |||
208 | { | |||
209 | drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes(mpFrame->getSdrAllFillAttributesHelper()); | |||
210 | if(aFillAttributes && aFillAttributes->isUsed()) | |||
211 | { | |||
212 | bUseNewFillProperties = true; | |||
213 | // use SetCompletePaint if needed | |||
214 | if(aFillAttributes->needCompleteRepaint()) | |||
215 | { | |||
216 | mpFrame->SetCompletePaint(); | |||
217 | } | |||
218 | } | |||
219 | } | |||
220 | if (!bUseNewFillProperties) | |||
221 | { | |||
222 | const SvxGraphicPosition ePos = mpFrame->GetAttrSet()->GetBackground().GetGraphicPos(); | |||
223 | if(GPOS_NONE != ePos && GPOS_TILED != ePos) | |||
224 | mpFrame->SetCompletePaint(); | |||
225 | } | |||
226 | } | |||
227 | else | |||
228 | { | |||
229 | // #97597# - consider case that *only* margins between | |||
230 | // frame and printing area has changed. Then, frame has to be repainted, | |||
231 | // in order to force paint of the margin areas. | |||
232 | if ( !bAbsP && (bChgWidth || bChgHeight) ) | |||
233 | { | |||
234 | mpFrame->SetCompletePaint(); | |||
235 | } | |||
236 | } | |||
237 | ||||
238 | const bool bPrtP = aRectFnSet.PosDiff( maPrt, mpFrame->getFramePrintArea() ); | |||
239 | if ( bAbsP || bPrtP || bChgWidth || bChgHeight || | |||
240 | bPrtWidth || bPrtHeight || bChgFlyBasePos ) | |||
241 | { | |||
242 | if( mpFrame->IsAccessibleFrame() ) | |||
243 | { | |||
244 | SwRootFrame *pRootFrame = mpFrame->getRootFrame(); | |||
245 | if( pRootFrame && pRootFrame->IsAnyShellAccessible() && | |||
246 | pRootFrame->GetCurrShell() ) | |||
247 | { | |||
248 | pRootFrame->GetCurrShell()->Imp()->MoveAccessibleFrame( mpFrame, maFrame ); | |||
249 | } | |||
250 | } | |||
251 | ||||
252 | // Notification of anchored objects | |||
253 | if ( mpFrame->GetDrawObjs() ) | |||
254 | { | |||
255 | const SwSortedObjs &rObjs = *mpFrame->GetDrawObjs(); | |||
256 | SwPageFrame* pPageFrame = nullptr; | |||
257 | for (SwAnchoredObject* pObj : rObjs) | |||
258 | { | |||
259 | // OD 2004-03-31 #i26791# - no general distinction between | |||
260 | // Writer fly frames and drawing objects | |||
261 | bool bNotify = false; | |||
262 | bool bNotifySize = false; | |||
263 | SwContact* pContact = ::GetUserCall( pObj->GetDrawObj() ); | |||
264 | const bool bAnchoredAsChar = pContact->ObjAnchoredAsChar(); | |||
265 | if ( !bAnchoredAsChar ) | |||
266 | { | |||
267 | // Notify object, which aren't anchored as-character: | |||
268 | ||||
269 | // always notify objects, if frame position has changed | |||
270 | // or if the object is to-page|to-fly anchored. | |||
271 | if ( bAbsP || | |||
272 | pContact->ObjAnchoredAtPage() || | |||
273 | pContact->ObjAnchoredAtFly() ) | |||
274 | { | |||
275 | bNotify = true; | |||
276 | ||||
277 | // assure that to-fly anchored Writer fly frames are | |||
278 | // registered at the correct page frame, if frame | |||
279 | // position has changed. | |||
280 | if ( bAbsP && pContact->ObjAnchoredAtFly() && | |||
281 | dynamic_cast<const SwFlyFrame*>( pObj) != nullptr ) | |||
282 | { | |||
283 | // determine to-fly anchored Writer fly frame | |||
284 | SwFlyFrame* pFlyFrame = static_cast<SwFlyFrame*>(pObj); | |||
285 | // determine page frame of to-fly anchored | |||
286 | // Writer fly frame | |||
287 | SwPageFrame* pFlyPageFrame = pFlyFrame->FindPageFrame(); | |||
288 | // determine page frame, if needed. | |||
289 | if ( !pPageFrame ) | |||
290 | { | |||
291 | pPageFrame = mpFrame->FindPageFrame(); | |||
292 | } | |||
293 | if ( pPageFrame != pFlyPageFrame ) | |||
294 | { | |||
295 | OSL_ENSURE( pFlyPageFrame, "~SwFrameNotify: Fly from Nowhere" )do { if (true && (!(pFlyPageFrame))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "295" ": "), "%s", "~SwFrameNotify: Fly from Nowhere"); } } while (false); | |||
296 | if( pFlyPageFrame ) | |||
297 | pFlyPageFrame->MoveFly( pFlyFrame, pPageFrame ); | |||
298 | else | |||
299 | pPageFrame->AppendFlyToPage( pFlyFrame ); | |||
300 | } | |||
301 | } | |||
302 | } | |||
303 | // otherwise the objects are notified in dependence to | |||
304 | // its positioning and alignment | |||
305 | else | |||
306 | { | |||
307 | const SwFormatVertOrient& rVert = | |||
308 | pContact->GetFormat()->GetVertOrient(); | |||
309 | if ( ( rVert.GetVertOrient() == text::VertOrientation::CENTER || | |||
310 | rVert.GetVertOrient() == text::VertOrientation::BOTTOM || | |||
311 | rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) && | |||
312 | ( bChgHeight || bPrtHeight ) ) | |||
313 | { | |||
314 | bNotify = true; | |||
315 | } | |||
316 | if ( !bNotify ) | |||
317 | { | |||
318 | const SwFormatHoriOrient& rHori = | |||
319 | pContact->GetFormat()->GetHoriOrient(); | |||
320 | if ( ( rHori.GetHoriOrient() != text::HoriOrientation::NONE || | |||
321 | rHori.GetRelationOrient()== text::RelOrientation::PRINT_AREA || | |||
322 | rHori.GetRelationOrient()== text::RelOrientation::FRAME ) && | |||
323 | ( bChgWidth || bPrtWidth || bChgFlyBasePos ) ) | |||
324 | { | |||
325 | bNotify = true; | |||
326 | } | |||
327 | } | |||
328 | } | |||
329 | } | |||
330 | else if ( bPrtWidth ) | |||
331 | { | |||
332 | // Notify as-character anchored objects, if printing area | |||
333 | // width has changed. | |||
334 | bNotify = true; | |||
335 | bNotifySize = true; | |||
336 | } | |||
337 | ||||
338 | // perform notification via the corresponding invalidations | |||
339 | if ( bNotify ) | |||
340 | { | |||
341 | if ( dynamic_cast<const SwFlyFrame*>( pObj) != nullptr ) | |||
342 | { | |||
343 | SwFlyFrame* pFlyFrame = static_cast<SwFlyFrame*>(pObj); | |||
344 | if ( bNotifySize ) | |||
345 | pFlyFrame->InvalidateSize_(); | |||
346 | // #115759# - no invalidation of | |||
347 | // position for as-character anchored objects. | |||
348 | if ( !bAnchoredAsChar ) | |||
349 | { | |||
350 | pFlyFrame->InvalidatePos_(); | |||
351 | } | |||
352 | pFlyFrame->Invalidate_(); | |||
353 | } | |||
354 | else if ( dynamic_cast<const SwAnchoredDrawObject*>( pObj) != nullptr ) | |||
355 | { | |||
356 | // #115759# - no invalidation of | |||
357 | // position for as-character anchored objects. | |||
358 | if ( !bAnchoredAsChar ) | |||
359 | { | |||
360 | pObj->InvalidateObjPos(); | |||
361 | } | |||
362 | } | |||
363 | else | |||
364 | { | |||
365 | OSL_FAIL( "<SwContentNotify::~SwContentNotify()> - unknown anchored object type." )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "365" ": "), "%s", "<SwContentNotify::~SwContentNotify()> - unknown anchored object type." ); } } while (false); | |||
366 | } | |||
367 | } | |||
368 | } | |||
369 | } | |||
370 | } | |||
371 | else if( mpFrame->IsTextFrame() && mbValidSize != mpFrame->isFrameAreaSizeValid() ) | |||
372 | { | |||
373 | SwRootFrame *pRootFrame = mpFrame->getRootFrame(); | |||
374 | if( pRootFrame && pRootFrame->IsAnyShellAccessible() && | |||
375 | pRootFrame->GetCurrShell() ) | |||
376 | { | |||
377 | pRootFrame->GetCurrShell()->Imp()->InvalidateAccessibleFrameContent( mpFrame ); | |||
378 | } | |||
379 | } | |||
380 | ||||
381 | // #i9046# Automatic frame width | |||
382 | SwFlyFrame* pFly = nullptr; | |||
383 | // #i35879# Do not trust the inf flags. pFrame does not | |||
384 | // necessarily have to have an upper! | |||
385 | if ( mpFrame->IsFlyFrame() || nullptr == ( pFly = mpFrame->ImplFindFlyFrame() )) | |||
386 | return; | |||
387 | ||||
388 | // #i61999# | |||
389 | // no invalidation of columned Writer fly frames, because automatic | |||
390 | // width doesn't make sense for such Writer fly frames. | |||
391 | if ( !pFly->Lower() || pFly->Lower()->IsColumnFrame() ) | |||
392 | return; | |||
393 | ||||
394 | const SwFormatFrameSize &rFrameSz = pFly->GetFormat()->GetFrameSize(); | |||
395 | ||||
396 | // This could be optimized. Basically the fly frame only has to | |||
397 | // be invalidated, if the first line of pFrame (if pFrame is a content | |||
398 | // frame, for other frame types it's the print area) has changed its | |||
399 | // size and pFrame was responsible for the current width of pFly. On | |||
400 | // the other hand, this is only rarely used and re-calculation of | |||
401 | // the fly frame does not cause too much trouble. So we keep it this | |||
402 | // way: | |||
403 | if ( SwFrameSize::Fixed != rFrameSz.GetWidthSizeType() ) | |||
404 | { | |||
405 | // #i50668#, #i50998# - invalidation of position | |||
406 | // of as-character anchored fly frames not needed and can cause | |||
407 | // layout loops | |||
408 | if ( dynamic_cast<const SwFlyInContentFrame*>( pFly) == nullptr ) | |||
409 | { | |||
410 | pFly->InvalidatePos(); | |||
411 | } | |||
412 | pFly->InvalidateSize(); | |||
413 | } | |||
414 | } | |||
415 | ||||
416 | SwLayNotify::SwLayNotify( SwLayoutFrame *pLayFrame ) : | |||
417 | SwFrameNotify( pLayFrame ), | |||
418 | m_bLowersComplete( false ) | |||
419 | { | |||
420 | } | |||
421 | ||||
422 | // OD 2004-05-11 #i28701# - local method to invalidate the position of all | |||
423 | // frames inclusive its floating screen objects, which are lowers of the given | |||
424 | // layout frame | |||
425 | static void lcl_InvalidatePosOfLowers( SwLayoutFrame& _rLayoutFrame ) | |||
426 | { | |||
427 | if( _rLayoutFrame.IsFlyFrame() && _rLayoutFrame.GetDrawObjs() ) | |||
428 | { | |||
429 | _rLayoutFrame.InvalidateObjs( false ); | |||
430 | } | |||
431 | ||||
432 | SwFrame* pLowerFrame = _rLayoutFrame.Lower(); | |||
433 | while ( pLowerFrame ) | |||
434 | { | |||
435 | pLowerFrame->InvalidatePos(); | |||
436 | if ( pLowerFrame->IsTextFrame() ) | |||
437 | { | |||
438 | static_cast<SwTextFrame*>(pLowerFrame)->Prepare( PrepareHint::FramePositionChanged ); | |||
439 | } | |||
440 | else if ( pLowerFrame->IsTabFrame() ) | |||
441 | { | |||
442 | pLowerFrame->InvalidatePrt(); | |||
443 | } | |||
444 | ||||
445 | pLowerFrame->InvalidateObjs( false ); | |||
446 | ||||
447 | pLowerFrame = pLowerFrame->GetNext(); | |||
448 | } | |||
449 | } | |||
450 | ||||
451 | SwLayNotify::~SwLayNotify() | |||
452 | { | |||
453 | SwLayoutFrame *pLay = static_cast<SwLayoutFrame*>(mpFrame); | |||
454 | SwRectFnSet aRectFnSet(pLay); | |||
455 | bool bNotify = false; | |||
456 | if ( pLay->getFramePrintArea().SSize() != maPrt.SSize() ) | |||
457 | { | |||
458 | if ( !IsLowersComplete() ) | |||
459 | { | |||
460 | bool bInvaPercent; | |||
461 | ||||
462 | if ( pLay->IsRowFrame() ) | |||
463 | { | |||
464 | bInvaPercent = true; | |||
465 | long nNew = aRectFnSet.GetHeight(pLay->getFramePrintArea()); | |||
466 | if( nNew != aRectFnSet.GetHeight(maPrt) ) | |||
467 | static_cast<SwRowFrame*>(pLay)->AdjustCells( nNew, true); | |||
468 | if( aRectFnSet.GetWidth(pLay->getFramePrintArea()) | |||
469 | != aRectFnSet.GetWidth(maPrt) ) | |||
470 | static_cast<SwRowFrame*>(pLay)->AdjustCells( 0, false ); | |||
471 | } | |||
472 | else | |||
473 | { | |||
474 | //Proportional adoption of the internal. | |||
475 | //1. If the formatted is no Fly | |||
476 | //2. If he contains no columns | |||
477 | //3. If the Fly has a fixed height and the columns | |||
478 | // are next to be. | |||
479 | // Hoehe danebenliegen. | |||
480 | //4. Never at SectionFrames. | |||
481 | bool bLow; | |||
482 | if( pLay->IsFlyFrame() ) | |||
483 | { | |||
484 | if ( pLay->Lower() ) | |||
485 | { | |||
486 | bLow = !pLay->Lower()->IsColumnFrame() || | |||
487 | aRectFnSet.GetHeight(pLay->Lower()->getFrameArea()) | |||
488 | != aRectFnSet.GetHeight(pLay->getFramePrintArea()); | |||
489 | } | |||
490 | else | |||
491 | bLow = false; | |||
492 | } | |||
493 | else if( pLay->IsSctFrame() ) | |||
494 | { | |||
495 | if ( pLay->Lower() ) | |||
496 | { | |||
497 | if( pLay->Lower()->IsColumnFrame() && pLay->Lower()->GetNext() ) | |||
498 | bLow = pLay->Lower()->getFrameArea().Height() != pLay->getFramePrintArea().Height(); | |||
499 | else | |||
500 | bLow = pLay->getFramePrintArea().Width() != maPrt.Width(); | |||
501 | } | |||
502 | else | |||
503 | bLow = false; | |||
504 | } | |||
505 | else if( pLay->IsFooterFrame() && !pLay->HasFixSize() ) | |||
506 | bLow = pLay->getFramePrintArea().Width() != maPrt.Width(); | |||
507 | else | |||
508 | bLow = true; | |||
509 | bInvaPercent = bLow; | |||
510 | if ( bLow ) | |||
511 | { | |||
512 | pLay->ChgLowersProp( maPrt.SSize() ); | |||
513 | } | |||
514 | // If the PrtArea has been extended, it might be possible that the chain of parts | |||
515 | // can take another frame. As a result, the "possible right one" needs to be | |||
516 | // invalidated. This only pays off if this or its Uppers are moveable sections. | |||
517 | // A PrtArea has been extended if width or height are larger than before. | |||
518 | if ( (pLay->getFramePrintArea().Height() > maPrt.Height() || | |||
519 | pLay->getFramePrintArea().Width() > maPrt.Width()) && | |||
520 | (pLay->IsMoveable() || pLay->IsFlyFrame()) ) | |||
521 | { | |||
522 | SwFrame *pTmpFrame = pLay->Lower(); | |||
523 | if ( pTmpFrame && pTmpFrame->IsFlowFrame() ) | |||
524 | { | |||
525 | while ( pTmpFrame->GetNext() ) | |||
526 | pTmpFrame = pTmpFrame->GetNext(); | |||
527 | pTmpFrame->InvalidateNextPos(); | |||
528 | } | |||
529 | } | |||
530 | } | |||
531 | bNotify = true; | |||
532 | //EXPENSIVE!! But how we do it more elegant? | |||
533 | if( bInvaPercent ) | |||
534 | pLay->InvaPercentLowers( pLay->getFramePrintArea().Height() - maPrt.Height() ); | |||
535 | } | |||
536 | if ( pLay->IsTabFrame() ) | |||
537 | //So that _only_ the shadow is drawn while resizing. | |||
538 | static_cast<SwTabFrame*>(pLay)->SetComplete(); | |||
539 | else | |||
540 | { | |||
541 | const SwViewShell *pSh = pLay->getRootFrame()->GetCurrShell(); | |||
542 | if( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) || | |||
543 | !(pLay->GetType() & (SwFrameType::Body | SwFrameType::Page)) ) | |||
544 | //Thereby the subordinates are retouched clean. | |||
545 | //Example problem: Take the Flys with the handles and downsize. | |||
546 | //Not for body and page, otherwise it flickers when loading HTML. | |||
547 | pLay->SetCompletePaint(); | |||
548 | } | |||
549 | } | |||
550 | //Notify Lower if the position has changed. | |||
551 | const bool bPrtPos = aRectFnSet.PosDiff( maPrt, pLay->getFramePrintArea() ); | |||
552 | const bool bPos = bPrtPos || aRectFnSet.PosDiff( maFrame, pLay->getFrameArea() ); | |||
553 | const bool bSize = pLay->getFrameArea().SSize() != maFrame.SSize(); | |||
554 | ||||
555 | if ( bPos && pLay->Lower() && !IsLowersComplete() ) | |||
556 | { | |||
557 | pLay->Lower()->InvalidatePos(); | |||
558 | SwFootnoteFrame* pFtnFrame = pLay->Lower()->IsFootnoteFrame() ? | |||
559 | static_cast<SwFootnoteFrame*>(pLay->Lower()) : nullptr; | |||
560 | SwFrame* pFtnLower = pFtnFrame ? pFtnFrame->Lower() : nullptr; | |||
561 | if (pFtnLower) | |||
562 | pFtnLower->InvalidatePos(); | |||
563 | } | |||
564 | ||||
565 | if ( bPrtPos ) | |||
566 | pLay->SetCompletePaint(); | |||
567 | ||||
568 | //Inform the Follower if the SSize has changed. | |||
569 | if ( bSize ) | |||
570 | { | |||
571 | if( pLay->GetNext() ) | |||
572 | { | |||
573 | if ( pLay->GetNext()->IsLayoutFrame() ) | |||
574 | pLay->GetNext()->InvalidatePos_(); | |||
575 | else | |||
576 | pLay->GetNext()->InvalidatePos(); | |||
577 | } | |||
578 | else if( pLay->IsSctFrame() ) | |||
579 | pLay->InvalidateNextPos(); | |||
580 | } | |||
581 | if ( !IsLowersComplete() && | |||
582 | !(pLay->GetType()&(SwFrameType::Fly|SwFrameType::Section) && | |||
583 | pLay->Lower() && pLay->Lower()->IsColumnFrame()) && | |||
584 | (bPos || bNotify) && | |||
585 | !(pLay->GetType() & (SwFrameType::Row|SwFrameType::Tab|SwFrameType::FtnCont|SwFrameType::Page|SwFrameType::Root))) | |||
586 | { | |||
587 | // #i44016# - force unlock of position of lower objects. | |||
588 | // #i43913# - no unlock of position of objects, | |||
589 | // if <pLay> is a cell frame, and its table frame resp. its parent table | |||
590 | // frame is locked. | |||
591 | // #i47458# - force unlock of position of lower objects, | |||
592 | // only if position of layout frame has changed. | |||
593 | bool bUnlockPosOfObjs( bPos ); | |||
594 | if ( bUnlockPosOfObjs && pLay->IsCellFrame() ) | |||
595 | { | |||
596 | SwTabFrame* pTabFrame( pLay->FindTabFrame() ); | |||
597 | if ( pTabFrame && | |||
598 | ( pTabFrame->IsJoinLocked() || | |||
599 | ( pTabFrame->IsFollow() && | |||
600 | pTabFrame->FindMaster()->IsJoinLocked() ) ) ) | |||
601 | { | |||
602 | bUnlockPosOfObjs = false; | |||
603 | } | |||
604 | } | |||
605 | // #i49383# - check for footnote frame, if unlock | |||
606 | // of position of lower objects is allowed. | |||
607 | else if ( bUnlockPosOfObjs && pLay->IsFootnoteFrame() ) | |||
608 | { | |||
609 | bUnlockPosOfObjs = static_cast<SwFootnoteFrame*>(pLay)->IsUnlockPosOfLowerObjs(); | |||
610 | } | |||
611 | // #i51303# - no unlock of object positions for sections | |||
612 | else if ( bUnlockPosOfObjs && pLay->IsSctFrame() ) | |||
613 | { | |||
614 | bUnlockPosOfObjs = false; | |||
615 | } | |||
616 | pLay->NotifyLowerObjs( bUnlockPosOfObjs ); | |||
617 | } | |||
618 | if ( bPos && pLay->IsFootnoteFrame() && pLay->Lower() ) | |||
619 | { | |||
620 | // OD 2004-05-11 #i28701# | |||
621 | ::lcl_InvalidatePosOfLowers( *pLay ); | |||
622 | } | |||
623 | if( ( bPos || bSize ) && pLay->IsFlyFrame() && static_cast<SwFlyFrame*>(pLay)->GetAnchorFrame() | |||
624 | && static_cast<SwFlyFrame*>(pLay)->GetAnchorFrame()->IsFlyFrame() ) | |||
625 | static_cast<SwFlyFrame*>(pLay)->AnchorFrame()->InvalidateSize(); | |||
626 | } | |||
627 | ||||
628 | SwFlyNotify::SwFlyNotify( SwFlyFrame *pFlyFrame ) : | |||
629 | SwLayNotify( pFlyFrame ), | |||
630 | // #115759# - keep correct page frame - the page frame | |||
631 | // the Writer fly frame is currently registered at. | |||
632 | pOldPage( pFlyFrame->GetPageFrame() ), | |||
633 | aFrameAndSpace( pFlyFrame->GetObjRectWithSpaces() ) | |||
634 | { | |||
635 | } | |||
636 | ||||
637 | SwFlyNotify::~SwFlyNotify() | |||
638 | { | |||
639 | SwFlyFrame *pFly = static_cast<SwFlyFrame*>(mpFrame); | |||
640 | if ( pFly->IsNotifyBack() ) | |||
641 | { | |||
642 | SwViewShell *pSh = pFly->getRootFrame()->GetCurrShell(); | |||
643 | SwViewShellImp *pImp = pSh ? pSh->Imp() : nullptr; | |||
644 | if ( !pImp || !pImp->IsAction() || !pImp->GetLayAction().IsAgain() ) | |||
645 | { | |||
646 | //If in the LayAction the IsAgain is set it can be | |||
647 | //that the old page is destroyed in the meantime! | |||
648 | ::Notify( pFly, pOldPage, aFrameAndSpace, &maPrt ); | |||
649 | // #i35640# - additional notify anchor text frame, | |||
650 | // if Writer fly frame has changed its page | |||
651 | if ( pFly->GetAnchorFrame()->IsTextFrame() && | |||
652 | pFly->GetPageFrame() != pOldPage ) | |||
653 | { | |||
654 | pFly->AnchorFrame()->Prepare( PrepareHint::FlyFrameLeave ); | |||
655 | } | |||
656 | } | |||
657 | pFly->ResetNotifyBack(); | |||
658 | } | |||
659 | ||||
660 | //Have the size or the position changed, | |||
661 | //so should the view know this. | |||
662 | SwRectFnSet aRectFnSet(pFly); | |||
663 | const bool bPosChgd = aRectFnSet.PosDiff( maFrame, pFly->getFrameArea() ); | |||
664 | const bool bFrameChgd = pFly->getFrameArea().SSize() != maFrame.SSize(); | |||
665 | const bool bPrtChgd = maPrt != pFly->getFramePrintArea(); | |||
666 | if ( bPosChgd || bFrameChgd || bPrtChgd ) | |||
667 | { | |||
668 | pFly->NotifyDrawObj(); | |||
669 | } | |||
670 | if ( bPosChgd && maFrame.Pos().X() != FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) ) | |||
671 | { | |||
672 | // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames. | |||
673 | // reason: New positioning and alignment (e.g. to-paragraph anchored, | |||
674 | // but aligned at page) are introduced. | |||
675 | // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower | |||
676 | // floating screen objects by calling method <SwLayoutFrame::NotifyLowerObjs()>. | |||
677 | ||||
678 | if ( pFly->IsFlyAtContentFrame() ) | |||
679 | { | |||
680 | SwFrame *pNxt = pFly->AnchorFrame()->FindNext(); | |||
681 | if ( pNxt ) | |||
682 | { | |||
683 | pNxt->InvalidatePos(); | |||
684 | } | |||
685 | } | |||
686 | ||||
687 | // #i26945# - notify anchor. | |||
688 | // Needed for negative positioned Writer fly frames | |||
689 | if ( pFly->GetAnchorFrame()->IsTextFrame() ) | |||
690 | { | |||
691 | pFly->AnchorFrame()->Prepare( PrepareHint::FlyFrameLeave ); | |||
692 | } | |||
693 | } | |||
694 | ||||
695 | // OD 2004-05-13 #i28701# | |||
696 | // #i45180# - no adjustment of layout process flags and | |||
697 | // further notifications/invalidations, if format is called by grow/shrink | |||
698 | if ( !(pFly->ConsiderObjWrapInfluenceOnObjPos() && | |||
699 | ( dynamic_cast<const SwFlyFreeFrame*>( pFly) == nullptr || | |||
700 | !static_cast<SwFlyFreeFrame*>(pFly)->IsNoMoveOnCheckClip() )) ) | |||
701 | return; | |||
702 | ||||
703 | // #i54138# - suppress restart of the layout process | |||
704 | // on changed frame height. | |||
705 | // Note: It doesn't seem to be necessary and can cause layout loops. | |||
706 | if ( bPosChgd ) | |||
707 | { | |||
708 | // indicate a restart of the layout process | |||
709 | pFly->SetRestartLayoutProcess( true ); | |||
710 | } | |||
711 | else | |||
712 | { | |||
713 | // lock position | |||
714 | pFly->LockPosition(); | |||
715 | } | |||
716 | ||||
717 | if ( pFly->ConsiderForTextWrap() ) | |||
718 | return; | |||
719 | ||||
720 | // indicate that object has to be considered for text wrap | |||
721 | pFly->SetConsiderForTextWrap( true ); | |||
722 | // invalidate 'background' in order to allow its 'background' | |||
723 | // to wrap around it. | |||
724 | pFly->NotifyBackground( pFly->GetPageFrame(), | |||
725 | pFly->GetObjRectWithSpaces(), | |||
726 | PrepareHint::FlyFrameArrive ); | |||
727 | // invalidate position of anchor frame in order to force | |||
728 | // a re-format of the anchor frame, which also causes a | |||
729 | // re-format of the invalid previous frames of the anchor frame. | |||
730 | pFly->AnchorFrame()->InvalidatePos(); | |||
731 | } | |||
732 | ||||
733 | SwContentNotify::SwContentNotify( SwContentFrame *pContentFrame ) : | |||
734 | SwFrameNotify( pContentFrame ), | |||
735 | // OD 08.01.2004 #i11859# | |||
736 | mbChkHeightOfLastLine( false ), | |||
737 | mnHeightOfLastLine( 0 ), | |||
738 | // OD 2004-02-26 #i25029# | |||
739 | mbInvalidatePrevPrtArea( false ), | |||
740 | mbBordersJoinedWithPrev( false ) | |||
741 | { | |||
742 | // OD 08.01.2004 #i11859# | |||
743 | if ( !pContentFrame->IsTextFrame() ) | |||
744 | return; | |||
745 | ||||
746 | SwTextFrame* pTextFrame = static_cast<SwTextFrame*>(pContentFrame); | |||
747 | if (!pTextFrame->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::OLD_LINE_SPACING)) | |||
748 | { | |||
749 | const SvxLineSpacingItem &rSpace = pTextFrame->GetAttrSet()->GetLineSpacing(); | |||
750 | if ( rSpace.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop ) | |||
751 | { | |||
752 | mbChkHeightOfLastLine = true; | |||
753 | mnHeightOfLastLine = pTextFrame->GetHeightOfLastLine(); | |||
754 | } | |||
755 | } | |||
756 | } | |||
757 | ||||
758 | SwContentNotify::~SwContentNotify() | |||
759 | { | |||
760 | SwContentFrame *pCnt = static_cast<SwContentFrame*>(mpFrame); | |||
761 | if ( bSetCompletePaintOnInvalidate ) | |||
762 | pCnt->SetCompletePaint(); | |||
763 | ||||
764 | SwRectFnSet aRectFnSet(pCnt); | |||
765 | if ( pCnt->IsInTab() && ( aRectFnSet.PosDiff( pCnt->getFrameArea(), maFrame ) || | |||
766 | pCnt->getFrameArea().SSize() != maFrame.SSize())) | |||
767 | { | |||
768 | SwLayoutFrame* pCell = pCnt->GetUpper(); | |||
769 | while( !pCell->IsCellFrame() && pCell->GetUpper() ) | |||
770 | pCell = pCell->GetUpper(); | |||
771 | OSL_ENSURE( pCell->IsCellFrame(), "Where's my cell?" )do { if (true && (!(pCell->IsCellFrame()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "771" ": "), "%s", "Where's my cell?"); } } while (false ); | |||
772 | if ( text::VertOrientation::NONE != pCell->GetFormat()->GetVertOrient().GetVertOrient() ) | |||
773 | pCell->InvalidatePrt(); //for the vertical align. | |||
774 | } | |||
775 | ||||
776 | // OD 2004-02-26 #i25029# | |||
777 | if ( mbInvalidatePrevPrtArea && mbBordersJoinedWithPrev && | |||
778 | pCnt->IsTextFrame() && | |||
779 | !pCnt->IsFollow() && !pCnt->GetIndPrev() ) | |||
780 | { | |||
781 | // determine previous frame | |||
782 | SwFrame* pPrevFrame = pCnt->FindPrev(); | |||
783 | // skip empty section frames and hidden text frames | |||
784 | { | |||
785 | while ( pPrevFrame && | |||
786 | ( ( pPrevFrame->IsSctFrame() && | |||
787 | !static_cast<SwSectionFrame*>(pPrevFrame)->GetSection() ) || | |||
788 | ( pPrevFrame->IsTextFrame() && | |||
789 | static_cast<SwTextFrame*>(pPrevFrame)->IsHiddenNow() ) ) ) | |||
790 | { | |||
791 | pPrevFrame = pPrevFrame->FindPrev(); | |||
792 | } | |||
793 | } | |||
794 | ||||
795 | // Invalidate printing area of found previous frame | |||
796 | if ( pPrevFrame ) | |||
797 | { | |||
798 | if ( pPrevFrame->IsSctFrame() ) | |||
799 | { | |||
800 | if ( pCnt->IsInSct() ) | |||
801 | { | |||
802 | // Note: found previous frame is a section frame and | |||
803 | // <pCnt> is also inside a section. | |||
804 | // Thus due to <mbBordersJoinedWithPrev>, | |||
805 | // <pCnt> had joined its borders/shadow with the | |||
806 | // last content of the found section. | |||
807 | // Invalidate printing area of last content in found section. | |||
808 | SwFrame* pLstContentOfSctFrame = | |||
809 | static_cast<SwSectionFrame*>(pPrevFrame)->FindLastContent(); | |||
810 | if ( pLstContentOfSctFrame ) | |||
811 | { | |||
812 | pLstContentOfSctFrame->InvalidatePrt(); | |||
813 | } | |||
814 | } | |||
815 | } | |||
816 | else | |||
817 | { | |||
818 | pPrevFrame->InvalidatePrt(); | |||
819 | } | |||
820 | } | |||
821 | } | |||
822 | ||||
823 | const bool bFirst = aRectFnSet.GetWidth(maFrame) == 0; | |||
824 | ||||
825 | if ( pCnt->IsNoTextFrame() ) | |||
826 | { | |||
827 | //Active PlugIn's or OLE-Objects should know something of the change | |||
828 | //thereby they move their window appropriate. | |||
829 | SwViewShell *pSh = pCnt->getRootFrame()->GetCurrShell(); | |||
830 | if ( pSh ) | |||
831 | { | |||
832 | SwOLENode *const pNd(static_cast<SwNoTextFrame*>(pCnt)->GetNode()->GetOLENode()); | |||
833 | if (nullptr != pNd && | |||
834 | (pNd->GetOLEObj().IsOleRef() || | |||
835 | pNd->IsOLESizeInvalid()) ) | |||
836 | { | |||
837 | const bool bNoTextFramePrtAreaChanged = | |||
838 | ( maPrt.SSize().Width() != 0 && | |||
839 | maPrt.SSize().Height() != 0 ) && | |||
840 | maPrt.SSize() != pCnt->getFramePrintArea().SSize(); | |||
841 | OSL_ENSURE( pCnt->IsInFly(), "OLE not in FlyFrame" )do { if (true && (!(pCnt->IsInFly()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "841" ": "), "%s", "OLE not in FlyFrame"); } } while (false ); | |||
842 | SwFlyFrame *pFly = pCnt->FindFlyFrame(); | |||
843 | svt::EmbeddedObjectRef& xObj = pNd->GetOLEObj().GetObject(); | |||
844 | SwFEShell *pFESh = nullptr; | |||
845 | for(SwViewShell& rCurrentShell : pSh->GetRingContainer()) | |||
846 | { if ( dynamic_cast<const SwCursorShell*>( &rCurrentShell) != nullptr ) | |||
847 | { | |||
848 | pFESh = static_cast<SwFEShell*>(&rCurrentShell); | |||
849 | // #108369#: Here used to be the condition if (!bFirst). | |||
850 | // I think this should mean "do not call CalcAndSetScale" | |||
851 | // if the frame is formatted for the first time. | |||
852 | // Unfortunately this is not valid anymore since the | |||
853 | // SwNoTextFrame already gets a width during CalcLowerPreps. | |||
854 | // Nevertheless, the indention of !bFirst seemed to be | |||
855 | // to assure that the OLE objects have already been notified | |||
856 | // if necessary before calling CalcAndSetScale. | |||
857 | // So I replaced !bFirst by !IsOLESizeInvalid. There is | |||
858 | // one additional problem specific to the word import: | |||
859 | // The layout is calculated _before_ calling PrtOLENotify, | |||
860 | // and the OLE objects are not invalidated during import. | |||
861 | // Therefore I added the condition !IsUpdateExpField, | |||
862 | // have a look at the occurrence of CalcLayout in | |||
863 | // uiview/view.cxx. | |||
864 | if ( !pNd->IsOLESizeInvalid() && | |||
865 | !pSh->GetDoc()->getIDocumentState().IsUpdateExpField() ) | |||
866 | pFESh->CalcAndSetScale( xObj, | |||
867 | &pFly->getFramePrintArea(), &pFly->getFrameArea(), | |||
868 | bNoTextFramePrtAreaChanged ); | |||
869 | } | |||
870 | } | |||
871 | ||||
872 | if ( pFESh && pNd->IsOLESizeInvalid() ) | |||
873 | { | |||
874 | pNd->SetOLESizeInvalid( false ); | |||
875 | pFESh->CalcAndSetScale( xObj ); // create client | |||
876 | } | |||
877 | } | |||
878 | // ditto animated graphics | |||
879 | if ( getFrameArea().HasArea() && static_cast<SwNoTextFrame*>(pCnt)->HasAnimation() ) | |||
880 | { | |||
881 | static_cast<SwNoTextFrame*>(pCnt)->StopAnimation(); | |||
882 | pSh->InvalidateWindows( getFrameArea() ); | |||
883 | } | |||
884 | } | |||
885 | } | |||
886 | ||||
887 | if ( bFirst ) | |||
888 | { | |||
889 | pCnt->SetRetouche(); //fix(13870) | |||
890 | ||||
891 | SwDoc& rDoc = pCnt->IsTextFrame() | |||
892 | ? static_cast<SwTextFrame*>(pCnt)->GetDoc() | |||
893 | : static_cast<SwNoTextFrame*>(pCnt)->GetNode()->GetDoc(); | |||
894 | if ( !rDoc.GetSpzFrameFormats()->empty() && | |||
895 | rDoc.DoesContainAtPageObjWithContentAnchor() && !rDoc.getIDocumentState().IsNewDoc() ) | |||
896 | { | |||
897 | // If certain import filters for foreign file format import | |||
898 | // AT_PAGE anchored objects, the corresponding page number is | |||
899 | // typically not known. In this case the content position is | |||
900 | // stored at which the anchored object is found in the | |||
901 | // imported document. | |||
902 | // When this content is formatted it is the time at which | |||
903 | // the page is known. Thus, this data can be corrected now. | |||
904 | ||||
905 | const SwPageFrame *pPage = nullptr; | |||
906 | SwFrameFormats *pTable = rDoc.GetSpzFrameFormats(); | |||
907 | ||||
908 | for ( size_t i = 0; i < pTable->size(); ++i ) | |||
909 | { | |||
910 | SwFrameFormat *pFormat = (*pTable)[i]; | |||
911 | const SwFormatAnchor &rAnch = pFormat->GetAnchor(); | |||
912 | if ( RndStdIds::FLY_AT_PAGE != rAnch.GetAnchorId() || | |||
913 | rAnch.GetContentAnchor() == nullptr ) | |||
914 | { | |||
915 | continue; | |||
916 | } | |||
917 | ||||
918 | if (FrameContainsNode(*pCnt, rAnch.GetContentAnchor()->nNode.GetIndex())) | |||
919 | { | |||
920 | OSL_FAIL( "<SwContentNotify::~SwContentNotify()> - to page anchored object with content position." )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "920" ": "), "%s", "<SwContentNotify::~SwContentNotify()> - to page anchored object with content position." ); } } while (false); | |||
921 | if ( !pPage ) | |||
922 | { | |||
923 | pPage = pCnt->FindPageFrame(); | |||
924 | } | |||
925 | SwFormatAnchor aAnch( rAnch ); | |||
926 | aAnch.SetAnchor( nullptr ); | |||
927 | aAnch.SetPageNum( pPage->GetPhyPageNum() ); | |||
928 | pFormat->SetFormatAttr( aAnch ); | |||
929 | if ( RES_DRAWFRMFMT != pFormat->Which() ) | |||
930 | { | |||
931 | pFormat->MakeFrames(); | |||
932 | } | |||
933 | } | |||
934 | } | |||
935 | } | |||
936 | } | |||
937 | ||||
938 | // OD 12.01.2004 #i11859# - invalidate printing area of following frame, | |||
939 | // if height of last line has changed. | |||
940 | if ( pCnt->IsTextFrame() && mbChkHeightOfLastLine ) | |||
941 | { | |||
942 | if ( mnHeightOfLastLine != static_cast<SwTextFrame*>(pCnt)->GetHeightOfLastLine() ) | |||
943 | { | |||
944 | pCnt->InvalidateNextPrtArea(); | |||
945 | } | |||
946 | } | |||
947 | ||||
948 | // #i44049# | |||
949 | if ( pCnt->IsTextFrame() && aRectFnSet.PosDiff( maFrame, pCnt->getFrameArea() ) ) | |||
950 | { | |||
951 | pCnt->InvalidateObjs(); | |||
952 | } | |||
953 | ||||
954 | // #i43255# - move code to invalidate at-character | |||
955 | // anchored objects due to a change of its anchor character from | |||
956 | // method <SwTextFrame::Format(..)>. | |||
957 | if ( !pCnt->IsTextFrame() ) | |||
958 | return; | |||
959 | ||||
960 | SwTextFrame* pMasterFrame = pCnt->IsFollow() | |||
961 | ? static_cast<SwTextFrame*>(pCnt)->FindMaster() | |||
962 | : static_cast<SwTextFrame*>(pCnt); | |||
963 | if ( pMasterFrame && !pMasterFrame->IsFlyLock() && | |||
964 | pMasterFrame->GetDrawObjs() ) | |||
965 | { | |||
966 | SwSortedObjs* pObjs = pMasterFrame->GetDrawObjs(); | |||
967 | for (SwAnchoredObject* pAnchoredObj : *pObjs) | |||
968 | { | |||
969 | if ( pAnchoredObj->GetFrameFormat().GetAnchor().GetAnchorId() | |||
970 | == RndStdIds::FLY_AT_CHAR ) | |||
971 | { | |||
972 | pAnchoredObj->CheckCharRectAndTopOfLine( !pMasterFrame->IsEmpty() ); | |||
973 | } | |||
974 | } | |||
975 | } | |||
976 | } | |||
977 | ||||
978 | // note this *cannot* be static because it's a friend | |||
979 | void AppendObj(SwFrame *const pFrame, SwPageFrame *const pPage, SwFrameFormat *const pFormat, const SwFormatAnchor & rAnch) | |||
980 | { | |||
981 | const bool bFlyAtFly = rAnch.GetAnchorId() == RndStdIds::FLY_AT_FLY; // LAYER_IMPL | |||
982 | //Is a frame or a SdrObject described? | |||
983 | const bool bSdrObj = RES_DRAWFRMFMT == pFormat->Which(); | |||
984 | // OD 23.06.2003 #108784# - append also drawing objects anchored | |||
985 | // as character. | |||
986 | const bool bDrawObjInContent = bSdrObj && | |||
987 | (rAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR); | |||
988 | ||||
989 | if( !(bFlyAtFly || | |||
990 | (rAnch.GetAnchorId() == RndStdIds::FLY_AT_PARA) || | |||
991 | (rAnch.GetAnchorId() == RndStdIds::FLY_AT_CHAR) || | |||
992 | bDrawObjInContent) ) | |||
993 | return; | |||
994 | ||||
995 | SdrObject* pSdrObj = nullptr; | |||
996 | if ( bSdrObj && nullptr == (pSdrObj = pFormat->FindSdrObject()) ) | |||
997 | { | |||
998 | OSL_ENSURE( !bSdrObj, "DrawObject not found." )do { if (true && (!(!bSdrObj))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "998" ": "), "%s", "DrawObject not found."); } } while ( false); | |||
999 | pFormat->GetDoc()->DelFrameFormat( pFormat ); | |||
1000 | return; | |||
1001 | } | |||
1002 | if ( pSdrObj ) | |||
1003 | { | |||
1004 | if ( !pSdrObj->getSdrPageFromSdrObject() ) | |||
1005 | { | |||
1006 | pFormat->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)-> | |||
1007 | InsertObject(pSdrObj, pSdrObj->GetOrdNumDirect()); | |||
1008 | } | |||
1009 | ||||
1010 | SwDrawContact* pNew = | |||
1011 | static_cast<SwDrawContact*>(GetUserCall( pSdrObj )); | |||
1012 | if ( !pNew->GetAnchorFrame() ) | |||
1013 | { | |||
1014 | pFrame->AppendDrawObj( *(pNew->GetAnchoredObj( nullptr )) ); | |||
1015 | } | |||
1016 | // OD 19.06.2003 #108784# - add 'virtual' drawing object, | |||
1017 | // if necessary. But control objects have to be excluded. | |||
1018 | else if ( !::CheckControlLayer( pSdrObj ) && | |||
1019 | pNew->GetAnchorFrame() != pFrame && | |||
1020 | !pNew->GetDrawObjectByAnchorFrame( *pFrame ) ) | |||
1021 | { | |||
1022 | SwDrawVirtObj* pDrawVirtObj = pNew->AddVirtObj(); | |||
1023 | pFrame->AppendDrawObj( *(pNew->GetAnchoredObj( pDrawVirtObj )) ); | |||
1024 | ||||
1025 | pDrawVirtObj->ActionChanged(); | |||
1026 | } | |||
1027 | } | |||
1028 | else | |||
1029 | { | |||
1030 | SwFlyFrame *pFly; | |||
1031 | if( bFlyAtFly ) | |||
1032 | pFly = new SwFlyLayFrame( static_cast<SwFlyFrameFormat*>(pFormat), pFrame, pFrame ); | |||
1033 | else | |||
1034 | pFly = new SwFlyAtContentFrame( static_cast<SwFlyFrameFormat*>(pFormat), pFrame, pFrame ); | |||
1035 | pFly->Lock(); | |||
1036 | pFrame->AppendFly( pFly ); | |||
1037 | pFly->Unlock(); | |||
1038 | if ( pPage ) | |||
1039 | ::RegistFlys( pPage, pFly ); | |||
1040 | } | |||
1041 | } | |||
1042 | ||||
1043 | static bool IsShown(sal_uLong const nIndex, | |||
1044 | const SwFormatAnchor & rAnch, | |||
1045 | std::vector<sw::Extent>::const_iterator const*const pIter, | |||
1046 | std::vector<sw::Extent>::const_iterator const*const pEnd, | |||
1047 | SwTextNode const*const pFirstNode, SwTextNode const*const pLastNode) | |||
1048 | { | |||
1049 | assert(!pIter || *pIter == *pEnd || (*pIter)->pNode->GetIndex() == nIndex)(static_cast <bool> (!pIter || *pIter == *pEnd || (*pIter )->pNode->GetIndex() == nIndex) ? void (0) : __assert_fail ("!pIter || *pIter == *pEnd || (*pIter)->pNode->GetIndex() == nIndex" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1049, __extension__ __PRETTY_FUNCTION__)); | |||
1050 | SwPosition const& rAnchor(*rAnch.GetContentAnchor()); | |||
1051 | if (rAnchor.nNode.GetIndex() != nIndex) | |||
1052 | { | |||
1053 | return false; | |||
1054 | } | |||
1055 | if (rAnch.GetAnchorId() == RndStdIds::FLY_AT_PARA) | |||
1056 | { | |||
1057 | return pIter == nullptr // not merged | |||
1058 | || pIter != pEnd // at least one char visible in node | |||
1059 | || !IsSelectFrameAnchoredAtPara(rAnchor, | |||
1060 | SwPosition(const_cast<SwTextNode&>(*pFirstNode), 0), | |||
1061 | SwPosition(const_cast<SwTextNode&>(*pLastNode), pLastNode->Len())); | |||
1062 | } | |||
1063 | if (pIter) | |||
1064 | { | |||
1065 | // note: frames are not sorted by anchor position. | |||
1066 | assert(pEnd)(static_cast <bool> (pEnd) ? void (0) : __assert_fail ( "pEnd", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1066, __extension__ __PRETTY_FUNCTION__)); | |||
1067 | assert(pFirstNode)(static_cast <bool> (pFirstNode) ? void (0) : __assert_fail ("pFirstNode", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1067, __extension__ __PRETTY_FUNCTION__)); | |||
1068 | assert(pLastNode)(static_cast <bool> (pLastNode) ? void (0) : __assert_fail ("pLastNode", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1068, __extension__ __PRETTY_FUNCTION__)); | |||
1069 | assert(rAnch.GetAnchorId() != RndStdIds::FLY_AT_FLY)(static_cast <bool> (rAnch.GetAnchorId() != RndStdIds:: FLY_AT_FLY) ? void (0) : __assert_fail ("rAnch.GetAnchorId() != RndStdIds::FLY_AT_FLY" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1069, __extension__ __PRETTY_FUNCTION__)); | |||
1070 | for (auto iter = *pIter; iter != *pEnd; ++iter) | |||
1071 | { | |||
1072 | assert(iter->nStart != iter->nEnd)(static_cast <bool> (iter->nStart != iter->nEnd) ? void (0) : __assert_fail ("iter->nStart != iter->nEnd" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1072, __extension__ __PRETTY_FUNCTION__)); // TODO possible? | |||
1073 | assert(iter->pNode->GetIndex() == nIndex)(static_cast <bool> (iter->pNode->GetIndex() == nIndex ) ? void (0) : __assert_fail ("iter->pNode->GetIndex() == nIndex" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1073, __extension__ __PRETTY_FUNCTION__)); | |||
1074 | if (rAnchor.nContent.GetIndex() < iter->nStart) | |||
1075 | { | |||
1076 | return false; | |||
1077 | } | |||
1078 | if (rAnch.GetAnchorId() == RndStdIds::FLY_AT_CHAR) | |||
1079 | { | |||
1080 | // if there is an extent then obviously the node was not | |||
1081 | // deleted fully... | |||
1082 | // show if start <= pos <= end | |||
1083 | // *or* if first-node/0 *and* not StartOfSection | |||
1084 | // *or* if last-node/Len *and* not EndOfSection | |||
1085 | ||||
1086 | // first determine the extent to compare to, then | |||
1087 | // construct start/end positions for the deletion *before* the | |||
1088 | // extent and compare once. | |||
1089 | // the interesting corner cases are on the edge of the extent! | |||
1090 | // no need to check for > the last extent because those | |||
1091 | // are never visible. | |||
1092 | if (rAnchor.nContent.GetIndex() <= iter->nEnd) | |||
1093 | { | |||
1094 | if (iter->nStart == 0) | |||
1095 | { | |||
1096 | return true; | |||
1097 | } | |||
1098 | else | |||
1099 | { | |||
1100 | SwPosition const start( | |||
1101 | const_cast<SwTextNode&>( | |||
1102 | iter == *pIter | |||
1103 | ? *pFirstNode // simplification | |||
1104 | : *iter->pNode), | |||
1105 | iter == *pIter // first extent? | |||
1106 | ? iter->pNode == pFirstNode | |||
1107 | ? 0 // at start of 1st node | |||
1108 | : pFirstNode->Len() // previous node; simplification but should get right result | |||
1109 | : (iter-1)->nEnd); // previous extent | |||
1110 | SwPosition const end(*iter->pNode, iter->nStart); | |||
1111 | return !IsDestroyFrameAnchoredAtChar(rAnchor, start, end); | |||
1112 | } | |||
1113 | } | |||
1114 | else if (iter == *pEnd - 1) // special case: after last extent | |||
1115 | { | |||
1116 | if (iter->nEnd == iter->pNode->Len()) | |||
1117 | { | |||
1118 | return true; // special case: end of node | |||
1119 | } | |||
1120 | else | |||
1121 | { | |||
1122 | SwPosition const start(*iter->pNode, iter->nEnd); | |||
1123 | SwPosition const end( | |||
1124 | const_cast<SwTextNode&>(*pLastNode), // simplification | |||
1125 | iter->pNode == pLastNode | |||
1126 | ? iter->pNode->Len() | |||
1127 | : 0); | |||
1128 | return !IsDestroyFrameAnchoredAtChar(rAnchor, start, end); | |||
1129 | } | |||
1130 | } | |||
1131 | } | |||
1132 | else | |||
1133 | { | |||
1134 | assert(rAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR)(static_cast <bool> (rAnch.GetAnchorId() == RndStdIds:: FLY_AS_CHAR) ? void (0) : __assert_fail ("rAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1134, __extension__ __PRETTY_FUNCTION__)); | |||
1135 | // for AS_CHAR obviously must be < | |||
1136 | if (rAnchor.nContent.GetIndex() < iter->nEnd) | |||
1137 | { | |||
1138 | return true; | |||
1139 | } | |||
1140 | } | |||
1141 | } | |||
1142 | return false; | |||
1143 | } | |||
1144 | else | |||
1145 | { | |||
1146 | return true; | |||
1147 | } | |||
1148 | } | |||
1149 | ||||
1150 | void RemoveHiddenObjsOfNode(SwTextNode const& rNode, | |||
1151 | std::vector<sw::Extent>::const_iterator const*const pIter, | |||
1152 | std::vector<sw::Extent>::const_iterator const*const pEnd, | |||
1153 | SwTextNode const*const pFirstNode, SwTextNode const*const pLastNode) | |||
1154 | { | |||
1155 | std::vector<SwFrameFormat*> const*const pFlys(rNode.GetAnchoredFlys()); | |||
1156 | if (!pFlys) | |||
1157 | { | |||
1158 | return; | |||
1159 | } | |||
1160 | for (SwFrameFormat * pFrameFormat : *pFlys) | |||
1161 | { | |||
1162 | SwFormatAnchor const& rAnchor = pFrameFormat->GetAnchor(); | |||
1163 | if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR | |||
1164 | || (rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR | |||
1165 | && RES_DRAWFRMFMT == pFrameFormat->Which())) | |||
1166 | { | |||
1167 | assert(rAnchor.GetContentAnchor()->nNode.GetIndex() == rNode.GetIndex())(static_cast <bool> (rAnchor.GetContentAnchor()->nNode .GetIndex() == rNode.GetIndex()) ? void (0) : __assert_fail ( "rAnchor.GetContentAnchor()->nNode.GetIndex() == rNode.GetIndex()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1167, __extension__ __PRETTY_FUNCTION__)); | |||
1168 | if (!IsShown(rNode.GetIndex(), rAnchor, pIter, pEnd, pFirstNode, pLastNode)) | |||
1169 | { | |||
1170 | pFrameFormat->DelFrames(); | |||
1171 | } | |||
1172 | } | |||
1173 | } | |||
1174 | } | |||
1175 | ||||
1176 | void AppendObjsOfNode(SwFrameFormats const*const pTable, sal_uLong const nIndex, | |||
1177 | SwFrame *const pFrame, SwPageFrame *const pPage, SwDoc *const pDoc, | |||
1178 | std::vector<sw::Extent>::const_iterator const*const pIter, | |||
1179 | std::vector<sw::Extent>::const_iterator const*const pEnd, | |||
1180 | SwTextNode const*const pFirstNode, SwTextNode const*const pLastNode) | |||
1181 | { | |||
1182 | #if OSL_DEBUG_LEVEL1 > 0 | |||
1183 | std::vector<SwFrameFormat*> checkFormats; | |||
1184 | for ( size_t i = 0; i < pTable->size(); ++i ) | |||
1185 | { | |||
1186 | SwFrameFormat *pFormat = (*pTable)[i]; | |||
1187 | const SwFormatAnchor &rAnch = pFormat->GetAnchor(); | |||
1188 | if ( rAnch.GetContentAnchor() && | |||
1189 | IsShown(nIndex, rAnch, pIter, pEnd, pFirstNode, pLastNode)) | |||
1190 | { | |||
1191 | checkFormats.push_back( pFormat ); | |||
1192 | } | |||
1193 | } | |||
1194 | #else | |||
1195 | (void)pTable; | |||
1196 | #endif | |||
1197 | ||||
1198 | SwNode const& rNode(*pDoc->GetNodes()[nIndex]); | |||
1199 | std::vector<SwFrameFormat*> const*const pFlys(rNode.GetAnchoredFlys()); | |||
1200 | for (size_t it = 0; pFlys && it != pFlys->size(); ) | |||
1201 | { | |||
1202 | SwFrameFormat *const pFormat = (*pFlys)[it]; | |||
1203 | const SwFormatAnchor &rAnch = pFormat->GetAnchor(); | |||
1204 | if ( rAnch.GetContentAnchor() && | |||
1205 | IsShown(nIndex, rAnch, pIter, pEnd, pFirstNode, pLastNode)) | |||
1206 | { | |||
1207 | #if OSL_DEBUG_LEVEL1 > 0 | |||
1208 | std::vector<SwFrameFormat*>::iterator checkPos = std::find( checkFormats.begin(), checkFormats.end(), pFormat ); | |||
1209 | assert( checkPos != checkFormats.end())(static_cast <bool> (checkPos != checkFormats.end()) ? void (0) : __assert_fail ("checkPos != checkFormats.end()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1209, __extension__ __PRETTY_FUNCTION__)); | |||
1210 | checkFormats.erase( checkPos ); | |||
1211 | #endif | |||
1212 | AppendObj(pFrame, pPage, pFormat, rAnch); | |||
1213 | } | |||
1214 | ++it; | |||
1215 | } | |||
1216 | ||||
1217 | #if OSL_DEBUG_LEVEL1 > 0 | |||
1218 | assert( checkFormats.empty())(static_cast <bool> (checkFormats.empty()) ? void (0) : __assert_fail ("checkFormats.empty()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1218, __extension__ __PRETTY_FUNCTION__)); | |||
1219 | #endif | |||
1220 | } | |||
1221 | ||||
1222 | ||||
1223 | void AppendObjs(const SwFrameFormats *const pTable, sal_uLong const nIndex, | |||
1224 | SwFrame *const pFrame, SwPageFrame *const pPage, SwDoc *const pDoc) | |||
1225 | { | |||
1226 | if (pFrame->IsTextFrame()) | |||
1227 | { | |||
1228 | SwTextFrame const*const pTextFrame(static_cast<SwTextFrame const*>(pFrame)); | |||
1229 | if (sw::MergedPara const*const pMerged = pTextFrame->GetMergedPara()) | |||
1230 | { | |||
1231 | std::vector<sw::Extent>::const_iterator iterFirst(pMerged->extents.begin()); | |||
1232 | std::vector<sw::Extent>::const_iterator iter(iterFirst); | |||
1233 | SwTextNode const* pNode(pMerged->pFirstNode); | |||
1234 | for ( ; ; ++iter) | |||
1235 | { | |||
1236 | if (iter == pMerged->extents.end() | |||
1237 | || iter->pNode != pNode) | |||
1238 | { | |||
1239 | AppendObjsOfNode(pTable, pNode->GetIndex(), pFrame, pPage, pDoc, | |||
1240 | &iterFirst, &iter, pMerged->pFirstNode, pMerged->pLastNode); | |||
1241 | sal_uLong const until = iter == pMerged->extents.end() | |||
1242 | ? pMerged->pLastNode->GetIndex() + 1 | |||
1243 | : iter->pNode->GetIndex(); | |||
1244 | for (sal_uLong i = pNode->GetIndex() + 1; i < until; ++i) | |||
1245 | { | |||
1246 | // let's show at-para flys on nodes that contain start/end of | |||
1247 | // redline too, even if there's no text there | |||
1248 | SwNode const*const pTmp(pNode->GetNodes()[i]); | |||
1249 | if (pTmp->GetRedlineMergeFlag() == SwNode::Merge::NonFirst) | |||
1250 | { | |||
1251 | AppendObjsOfNode(pTable, pTmp->GetIndex(), pFrame, pPage, pDoc, &iter, &iter, pMerged->pFirstNode, pMerged->pLastNode); | |||
1252 | } | |||
1253 | } | |||
1254 | if (iter == pMerged->extents.end()) | |||
1255 | { | |||
1256 | break; | |||
1257 | } | |||
1258 | pNode = iter->pNode; | |||
1259 | iterFirst = iter; | |||
1260 | } | |||
1261 | } | |||
1262 | } | |||
1263 | else | |||
1264 | { | |||
1265 | return AppendObjsOfNode(pTable, nIndex, pFrame, pPage, pDoc, nullptr, nullptr, nullptr, nullptr); | |||
1266 | } | |||
1267 | } | |||
1268 | else | |||
1269 | { | |||
1270 | return AppendObjsOfNode(pTable, nIndex, pFrame, pPage, pDoc, nullptr, nullptr, nullptr, nullptr); | |||
1271 | } | |||
1272 | } | |||
1273 | ||||
1274 | bool IsAnchoredObjShown(SwTextFrame const& rFrame, SwFormatAnchor const& rAnchor) | |||
1275 | { | |||
1276 | assert(rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA ||(static_cast <bool> (rAnchor.GetAnchorId() == RndStdIds ::FLY_AT_PARA || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR || rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR) ? void ( 0) : __assert_fail ("rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR || rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1278, __extension__ __PRETTY_FUNCTION__)) | |||
1277 | rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR ||(static_cast <bool> (rAnchor.GetAnchorId() == RndStdIds ::FLY_AT_PARA || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR || rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR) ? void ( 0) : __assert_fail ("rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR || rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1278, __extension__ __PRETTY_FUNCTION__)) | |||
1278 | rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR)(static_cast <bool> (rAnchor.GetAnchorId() == RndStdIds ::FLY_AT_PARA || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR || rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR) ? void ( 0) : __assert_fail ("rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR || rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1278, __extension__ __PRETTY_FUNCTION__)); | |||
1279 | bool ret(true); | |||
1280 | if (auto const pMergedPara = rFrame.GetMergedPara()) | |||
1281 | { | |||
1282 | ret = false; | |||
1283 | auto const pAnchor(rAnchor.GetContentAnchor()); | |||
1284 | auto iterFirst(pMergedPara->extents.cbegin()); | |||
1285 | if (iterFirst == pMergedPara->extents.end() | |||
1286 | && (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA | |||
1287 | || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR)) | |||
1288 | { | |||
1289 | ret = (&pAnchor->nNode.GetNode() == pMergedPara->pFirstNode | |||
1290 | && (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA | |||
1291 | || pAnchor->nContent == 0)) | |||
1292 | || (&pAnchor->nNode.GetNode() == pMergedPara->pLastNode | |||
1293 | && (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA | |||
1294 | || pAnchor->nContent == pMergedPara->pLastNode->Len())); | |||
1295 | } | |||
1296 | auto iter(iterFirst); | |||
1297 | SwTextNode const* pNode(pMergedPara->pFirstNode); | |||
1298 | for ( ; ; ++iter) | |||
1299 | { | |||
1300 | if (iter == pMergedPara->extents.end() | |||
1301 | || iter->pNode != pNode) | |||
1302 | { | |||
1303 | assert(pNode->GetRedlineMergeFlag() != SwNode::Merge::Hidden)(static_cast <bool> (pNode->GetRedlineMergeFlag() != SwNode::Merge::Hidden) ? void (0) : __assert_fail ("pNode->GetRedlineMergeFlag() != SwNode::Merge::Hidden" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1303, __extension__ __PRETTY_FUNCTION__)); | |||
1304 | if (pNode == &pAnchor->nNode.GetNode()) | |||
1305 | { | |||
1306 | ret = IsShown(pNode->GetIndex(), rAnchor, &iterFirst, &iter, | |||
1307 | pMergedPara->pFirstNode, pMergedPara->pLastNode); | |||
1308 | break; | |||
1309 | } | |||
1310 | if (iter == pMergedPara->extents.end()) | |||
1311 | { | |||
1312 | break; | |||
1313 | } | |||
1314 | pNode = iter->pNode; | |||
1315 | if (pAnchor->nNode.GetIndex() < pNode->GetIndex()) | |||
1316 | { | |||
1317 | break; | |||
1318 | } | |||
1319 | iterFirst = iter; | |||
1320 | } | |||
1321 | } | |||
1322 | } | |||
1323 | return ret; | |||
1324 | } | |||
1325 | ||||
1326 | void AppendAllObjs(const SwFrameFormats* pTable, const SwFrame* pSib) | |||
1327 | { | |||
1328 | //Connecting of all Objects, which are described in the SpzTable with the | |||
1329 | //layout. | |||
1330 | ||||
1331 | boost::circular_buffer<SwFrameFormat*> vFormatsToConnect(pTable->size()); | |||
1332 | for(const auto& pFormat : *pTable) | |||
1333 | { | |||
1334 | const auto& rAnch = pFormat->GetAnchor(); | |||
1335 | // Formats can still remain, because we neither use character bound | |||
1336 | // frames nor objects which are anchored to character bounds. | |||
1337 | if ((rAnch.GetAnchorId() != RndStdIds::FLY_AT_PAGE) && (rAnch.GetAnchorId() != RndStdIds::FLY_AS_CHAR)) | |||
1338 | { | |||
1339 | auto pContentAnchor = rAnch.GetContentAnchor(); | |||
1340 | // formats in header/footer have no dependencies | |||
1341 | if(pContentAnchor && pFormat->GetDoc()->IsInHeaderFooter(pContentAnchor->nNode)) | |||
1342 | pFormat->MakeFrames(); | |||
1343 | else | |||
1344 | vFormatsToConnect.push_back(pFormat); | |||
1345 | } | |||
1346 | } | |||
1347 | const SwRootFrame* pRoot = pSib ? pSib->getRootFrame() : nullptr; | |||
1348 | const SwFrameFormat* pFirstRequeued(nullptr); | |||
1349 | while(!vFormatsToConnect.empty()) | |||
1350 | { | |||
1351 | auto& pFormat = vFormatsToConnect.front(); | |||
1352 | bool isConnected(false); | |||
1353 | pFormat->CallSwClientNotify(sw::GetObjectConnectedHint(isConnected, pRoot)); | |||
1354 | if(!isConnected) | |||
1355 | { | |||
1356 | pFormat->MakeFrames(); | |||
1357 | pFormat->CallSwClientNotify(sw::GetObjectConnectedHint(isConnected, pRoot)); | |||
1358 | } | |||
1359 | // do this *before* push_back! the circular_buffer can be "full"! | |||
1360 | vFormatsToConnect.pop_front(); | |||
1361 | if (!isConnected) | |||
1362 | { | |||
1363 | if(pFirstRequeued == pFormat) | |||
1364 | // If nothing happens anymore we can stop. | |||
1365 | break; | |||
1366 | if(!pFirstRequeued) | |||
1367 | pFirstRequeued = pFormat; | |||
1368 | assert(!vFormatsToConnect.full())(static_cast <bool> (!vFormatsToConnect.full()) ? void ( 0) : __assert_fail ("!vFormatsToConnect.full()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1368, __extension__ __PRETTY_FUNCTION__)); | |||
1369 | vFormatsToConnect.push_back(pFormat); | |||
1370 | } | |||
1371 | else | |||
1372 | { | |||
1373 | pFirstRequeued = nullptr; | |||
1374 | } | |||
1375 | } | |||
1376 | } | |||
1377 | ||||
1378 | namespace sw { | |||
1379 | ||||
1380 | void RecreateStartTextFrames(SwTextNode & rNode) | |||
1381 | { | |||
1382 | std::vector<SwTextFrame*> frames; | |||
1383 | SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(rNode); | |||
1384 | for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next()) | |||
1385 | { | |||
1386 | if (pFrame->getRootFrame()->IsHideRedlines()) | |||
1387 | { | |||
1388 | frames.push_back(pFrame); | |||
1389 | } | |||
1390 | } | |||
1391 | auto eMode(sw::FrameMode::Existing); | |||
1392 | for (SwTextFrame * pFrame : frames) | |||
1393 | { | |||
1394 | // SplitNode could have moved the original frame to the start node | |||
1395 | // & created a new one on end, or could have created new frame on | |||
1396 | // start node... grab start node's frame and recreate MergedPara. | |||
1397 | SwTextNode & rFirstNode(pFrame->GetMergedPara() | |||
1398 | ? *pFrame->GetMergedPara()->pFirstNode | |||
1399 | : rNode); | |||
1400 | assert(rFirstNode.GetIndex() <= rNode.GetIndex())(static_cast <bool> (rFirstNode.GetIndex() <= rNode. GetIndex()) ? void (0) : __assert_fail ("rFirstNode.GetIndex() <= rNode.GetIndex()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1400, __extension__ __PRETTY_FUNCTION__)); | |||
1401 | // clear old one first to avoid DelFrames confusing updates & asserts... | |||
1402 | pFrame->SetMergedPara(nullptr); | |||
1403 | pFrame->SetMergedPara(sw::CheckParaRedlineMerge( | |||
1404 | *pFrame, rFirstNode, eMode)); | |||
1405 | eMode = sw::FrameMode::New; // Existing is not idempotent! | |||
1406 | // note: this may or may not delete frames on the end node | |||
1407 | } | |||
1408 | } | |||
1409 | ||||
1410 | } // namespace sw | |||
1411 | ||||
1412 | /** local method to set 'working' position for newly inserted frames | |||
1413 | ||||
1414 | OD 12.08.2003 #i17969# | |||
1415 | */ | |||
1416 | static void lcl_SetPos( SwFrame& _rNewFrame, | |||
1417 | const SwLayoutFrame& _rLayFrame ) | |||
1418 | { | |||
1419 | SwRectFnSet aRectFnSet(&_rLayFrame); | |||
1420 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(_rNewFrame); | |||
1421 | aRectFnSet.SetPos( aFrm, aRectFnSet.GetPos(_rLayFrame.getFrameArea()) ); | |||
1422 | ||||
1423 | // move position by one SwTwip in text flow direction in order to get | |||
1424 | // notifications for a new calculated position after its formatting. | |||
1425 | if ( aRectFnSet.IsVert() ) | |||
1426 | { | |||
1427 | aFrm.Pos().AdjustX( -1 ); | |||
1428 | } | |||
1429 | else | |||
1430 | { | |||
1431 | aFrm.Pos().AdjustY(1 ); | |||
1432 | } | |||
1433 | } | |||
1434 | ||||
1435 | void InsertCnt_( SwLayoutFrame *pLay, SwDoc *pDoc, | |||
1436 | sal_uLong nIndex, bool bPages, sal_uLong nEndIndex, | |||
1437 | SwFrame *pPrv, sw::FrameMode const eMode ) | |||
1438 | { | |||
1439 | pDoc->getIDocumentTimerAccess().BlockIdling(); | |||
1440 | SwRootFrame* pLayout = pLay->getRootFrame(); | |||
1441 | const bool bOldCallbackActionEnabled = pLayout && pLayout->IsCallbackActionEnabled(); | |||
1442 | if( bOldCallbackActionEnabled ) | |||
1443 | pLayout->SetCallbackActionEnabled( false ); | |||
1444 | ||||
1445 | //In the generation of the Layout bPages=true will be handed over. | |||
1446 | //Then will be new pages generated all x paragraphs already times in advance. | |||
1447 | //On breaks and/or pagedescriptorchanges the corresponding will be generated | |||
1448 | //immediately. | |||
1449 | //The advantage is, that on one hand already a nearly realistic number of | |||
1450 | //pages are created, but above all there are no almost endless long chain | |||
1451 | //of paragraphs, which must be moved expensively until it reaches a tolerable | |||
1452 | //reduced level. | |||
1453 | //We'd like to think that 20 Paragraphs fit on one page. | |||
1454 | //So that it does not become in extreme situations so violent we calculate depending | |||
1455 | //on the node something to it. | |||
1456 | //If in the DocStatistic a usable given pagenumber | |||
1457 | //(Will be cared for while writing), so it will be presumed that this will be | |||
1458 | //number of pages. | |||
1459 | const bool bStartPercent = bPages && !nEndIndex; | |||
1460 | ||||
1461 | SwPageFrame *pPage = pLay->FindPageFrame(); | |||
1462 | const SwFrameFormats *pTable = pDoc->GetSpzFrameFormats(); | |||
1463 | SwFrame *pFrame = nullptr; | |||
1464 | std::unique_ptr<SwActualSection> pActualSection; | |||
1465 | std::unique_ptr<SwLayHelper> pPageMaker; | |||
1466 | ||||
1467 | //If the layout will be created (bPages == true) we do head on the progress | |||
1468 | //Flys and DrawObjects are not connected immediately, this | |||
1469 | //happens only at the end of the function. | |||
1470 | if ( bPages ) | |||
1471 | { | |||
1472 | // Attention: the SwLayHelper class uses references to the content-, | |||
1473 | // page-, layout-frame etc. and may change them! | |||
1474 | pPageMaker.reset(new SwLayHelper( pDoc, pFrame, pPrv, pPage, pLay, | |||
1475 | pActualSection, nIndex, 0 == nEndIndex )); | |||
1476 | if( bStartPercent ) | |||
1477 | { | |||
1478 | const sal_uLong nPageCount = pPageMaker->CalcPageCount(); | |||
1479 | if( nPageCount ) | |||
1480 | bObjsDirect = false; | |||
1481 | } | |||
1482 | } | |||
1483 | else | |||
1484 | pPageMaker = nullptr; | |||
1485 | ||||
1486 | if( pLay->IsInSct() && | |||
1487 | ( pLay->IsSctFrame() || pLay->GetUpper() ) ) // Hereby will newbies | |||
1488 | // be intercepted, of which flags could not determined yet, | |||
1489 | // for e.g. while inserting a table | |||
1490 | { | |||
1491 | SwSectionFrame* pSct = pLay->FindSctFrame(); | |||
1492 | // If content will be inserted in a footnote, which in a column area, | |||
1493 | // the column area it is not allowed to be broken up. | |||
1494 | // Only if in the inner of the footnote lies an area, is this a candidate | |||
1495 | // for pActualSection. | |||
1496 | // The same applies for areas in tables, if inside the table will be | |||
1497 | // something inserted, it's only allowed to break up areas, which | |||
1498 | // lies in the inside also. | |||
1499 | if( ( !pLay->IsInFootnote() || pSct->IsInFootnote() ) && | |||
1500 | ( !pLay->IsInTab() || pSct->IsInTab() ) ) | |||
1501 | { | |||
1502 | pActualSection.reset(new SwActualSection(nullptr, pSct, pSct->GetSection()->GetFormat()->GetSectionNode())); | |||
1503 | // tdf#132236 for SwUndoDelete: find outer sections whose start | |||
1504 | // nodes aren't contained in the range but whose end nodes are, | |||
1505 | // because section frames may need to be created for them | |||
1506 | SwActualSection * pUpperSection(pActualSection.get()); | |||
1507 | while (pUpperSection->GetSectionNode()->EndOfSectionIndex() < nEndIndex) | |||
1508 | { | |||
1509 | SwStartNode *const pStart(pUpperSection->GetSectionNode()->StartOfSectionNode()); | |||
1510 | if (!pStart->IsSectionNode()) | |||
1511 | { | |||
1512 | break; | |||
1513 | } | |||
1514 | // note: these don't have a section frame, check it in EndNode case! | |||
1515 | auto const pTmp(new SwActualSection(nullptr, nullptr, static_cast<SwSectionNode*>(pStart))); | |||
1516 | pUpperSection->SetUpper(pTmp); | |||
1517 | pUpperSection = pTmp; | |||
1518 | } | |||
1519 | OSL_ENSURE( !pLay->Lower() || !pLay->Lower()->IsColumnFrame(),do { if (true && (!(!pLay->Lower() || !pLay->Lower ()->IsColumnFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "1520" ": "), "%s", "InsertCnt_: Wrong Call"); } } while (false) | |||
1520 | "InsertCnt_: Wrong Call" )do { if (true && (!(!pLay->Lower() || !pLay->Lower ()->IsColumnFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "1520" ": "), "%s", "InsertCnt_: Wrong Call"); } } while (false); | |||
1521 | } | |||
1522 | } | |||
1523 | ||||
1524 | //If a section is "open", the pActualSection points to an SwActualSection. | |||
1525 | //If the page breaks, for "open" sections a follow will created. | |||
1526 | //For nested sections (which have, however, not a nested layout), | |||
1527 | //the SwActualSection class has a member, which points to an upper(section). | |||
1528 | //When the "inner" section finishes, the upper will used instead. | |||
1529 | ||||
1530 | // Do not consider the end node. The caller (Section/MakeFrames()) has to | |||
1531 | // ensure that the end of this range is positioned before EndIndex! | |||
1532 | for ( ; nEndIndex == 0 || nIndex < nEndIndex; ++nIndex) | |||
1533 | { | |||
1534 | SwNode *pNd = pDoc->GetNodes()[nIndex]; | |||
1535 | if ( pNd->IsContentNode() ) | |||
1536 | { | |||
1537 | SwContentNode* pNode = static_cast<SwContentNode*>(pNd); | |||
1538 | if (pLayout->IsHideRedlines() && !pNd->IsCreateFrameWhenHidingRedlines()) | |||
1539 | { | |||
1540 | if (pNd->IsTextNode() | |||
1541 | && pNd->GetRedlineMergeFlag() == SwNode::Merge::NonFirst) | |||
1542 | { // must have a frame already | |||
1543 | assert(static_cast<SwTextFrame*>(pNode->getLayoutFrame(pLayout))->GetMergedPara())(static_cast <bool> (static_cast<SwTextFrame*>(pNode ->getLayoutFrame(pLayout))->GetMergedPara()) ? void (0) : __assert_fail ("static_cast<SwTextFrame*>(pNode->getLayoutFrame(pLayout))->GetMergedPara()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1543, __extension__ __PRETTY_FUNCTION__)); | |||
1544 | } | |||
1545 | continue; // skip it | |||
1546 | } | |||
1547 | pFrame = pNode->IsTextNode() | |||
1548 | ? sw::MakeTextFrame(*pNode->GetTextNode(), pLay, eMode) | |||
1549 | : pNode->MakeFrame(pLay); | |||
1550 | if( pPageMaker ) | |||
1551 | pPageMaker->CheckInsert( nIndex ); | |||
1552 | ||||
1553 | pFrame->InsertBehind( pLay, pPrv ); | |||
1554 | // #i27138# | |||
1555 | // notify accessibility paragraphs objects about changed | |||
1556 | // CONTENT_FLOWS_FROM/_TO relation. | |||
1557 | // Relation CONTENT_FLOWS_FROM for next paragraph will change | |||
1558 | // and relation CONTENT_FLOWS_TO for previous paragraph will change. | |||
1559 | if ( pFrame->IsTextFrame() ) | |||
1560 | { | |||
1561 | SwViewShell* pViewShell( pFrame->getRootFrame()->GetCurrShell() ); | |||
1562 | // no notification, if <SwViewShell> is in construction | |||
1563 | if ( pViewShell && !pViewShell->IsInConstructor() && | |||
1564 | pViewShell->GetLayout() && | |||
1565 | pViewShell->GetLayout()->IsAnyShellAccessible() && | |||
1566 | pFrame->FindPageFrame() != nullptr) | |||
1567 | { | |||
1568 | pViewShell->InvalidateAccessibleParaFlowRelation( | |||
1569 | dynamic_cast<SwTextFrame*>(pFrame->FindNextCnt( true )), | |||
1570 | dynamic_cast<SwTextFrame*>(pFrame->FindPrevCnt()) ); | |||
1571 | // #i68958# | |||
1572 | // The information flags of the text frame are validated | |||
1573 | // in methods <FindNextCnt(..)> and <FindPrevCnt(..)>. | |||
1574 | // The information flags have to be invalidated, because | |||
1575 | // it is possible, that the one of its upper frames | |||
1576 | // isn't inserted into the layout. | |||
1577 | pFrame->InvalidateInfFlags(); | |||
1578 | } | |||
1579 | } | |||
1580 | // OD 12.08.2003 #i17969# - consider horizontal/vertical layout | |||
1581 | // for setting position at newly inserted frame | |||
1582 | lcl_SetPos( *pFrame, *pLay ); | |||
1583 | pPrv = pFrame; | |||
1584 | ||||
1585 | if ( !pTable->empty() && bObjsDirect && !bDontCreateObjects ) | |||
1586 | AppendObjs( pTable, nIndex, pFrame, pPage, pDoc ); | |||
1587 | } | |||
1588 | else if ( pNd->IsTableNode() ) | |||
1589 | { //Should we have encountered a table? | |||
1590 | SwTableNode *pTableNode = static_cast<SwTableNode*>(pNd); | |||
1591 | if (pLayout->IsHideRedlines()) | |||
1592 | { | |||
1593 | // in the problematic case, there can be only 1 redline... | |||
1594 | SwPosition const tmp(*pNd); | |||
1595 | SwRangeRedline const*const pRedline( | |||
1596 | pDoc->getIDocumentRedlineAccess().GetRedline(tmp, nullptr)); | |||
1597 | // pathology: redline that starts on a TableNode; cannot | |||
1598 | // be created in UI but by import filters... | |||
1599 | if (pRedline | |||
1600 | && pRedline->GetType() == RedlineType::Delete | |||
1601 | && &pRedline->Start()->nNode.GetNode() == pNd) | |||
1602 | { | |||
1603 | SAL_WARN("sw.pageframe", "skipping table frame creation on bizarre redline")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.pageframe")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "skipping table frame creation on bizarre redline" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.pageframe" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "1603" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "skipping table frame creation on bizarre redline" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "skipping table frame creation on bizarre redline"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.pageframe" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "1603" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "skipping table frame creation on bizarre redline" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.pageframe" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "1603" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "skipping table frame creation on bizarre redline" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "skipping table frame creation on bizarre redline"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.pageframe" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "1603" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
1604 | while (true) | |||
1605 | { | |||
1606 | pTableNode->GetNodes()[nIndex]->SetRedlineMergeFlag(SwNode::Merge::Hidden); | |||
1607 | if (nIndex == pTableNode->EndOfSectionIndex()) | |||
1608 | { | |||
1609 | break; | |||
1610 | } | |||
1611 | ++nIndex; | |||
1612 | } | |||
1613 | continue; | |||
1614 | } | |||
1615 | } | |||
1616 | if (pLayout->IsHideRedlines() && !pNd->IsCreateFrameWhenHidingRedlines()) | |||
1617 | { | |||
1618 | assert(pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden)(static_cast <bool> (pNd->GetRedlineMergeFlag() == SwNode ::Merge::Hidden) ? void (0) : __assert_fail ("pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1618, __extension__ __PRETTY_FUNCTION__)); | |||
1619 | nIndex = pTableNode->EndOfSectionIndex(); | |||
1620 | continue; // skip it | |||
1621 | } | |||
1622 | ||||
1623 | // #108116# loading may produce table structures that GCLines | |||
1624 | // needs to clean up. To keep table formulas correct, change | |||
1625 | // all table formulas to internal (BOXPTR) representation. | |||
1626 | SwTableFormulaUpdate aMsgHint( &pTableNode->GetTable() ); | |||
1627 | aMsgHint.m_eFlags = TBL_BOXPTR; | |||
1628 | pDoc->getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint ); | |||
1629 | pTableNode->GetTable().GCLines(); | |||
1630 | ||||
1631 | pFrame = pTableNode->MakeFrame( pLay ); | |||
1632 | ||||
1633 | if( pPageMaker ) | |||
1634 | pPageMaker->CheckInsert( nIndex ); | |||
1635 | ||||
1636 | pFrame->InsertBehind( pLay, pPrv ); | |||
1637 | if (pPage) // would null in SwCellFrame ctor | |||
1638 | { // tdf#134931 call ResetTurbo(); not sure if Paste() would be | |||
1639 | pFrame->InvalidatePage(pPage); // better than InsertBehind()? | |||
1640 | } | |||
1641 | // #i27138# | |||
1642 | // notify accessibility paragraphs objects about changed | |||
1643 | // CONTENT_FLOWS_FROM/_TO relation. | |||
1644 | // Relation CONTENT_FLOWS_FROM for next paragraph will change | |||
1645 | // and relation CONTENT_FLOWS_TO for previous paragraph will change. | |||
1646 | { | |||
1647 | SwViewShell* pViewShell( pFrame->getRootFrame()->GetCurrShell() ); | |||
1648 | // no notification, if <SwViewShell> is in construction | |||
1649 | if ( pViewShell && !pViewShell->IsInConstructor() && | |||
1650 | pViewShell->GetLayout() && | |||
1651 | pViewShell->GetLayout()->IsAnyShellAccessible() && | |||
1652 | pFrame->FindPageFrame() != nullptr) | |||
1653 | { | |||
1654 | pViewShell->InvalidateAccessibleParaFlowRelation( | |||
1655 | dynamic_cast<SwTextFrame*>(pFrame->FindNextCnt( true )), | |||
1656 | dynamic_cast<SwTextFrame*>(pFrame->FindPrevCnt()) ); | |||
1657 | } | |||
1658 | } | |||
1659 | if ( bObjsDirect && !pTable->empty() ) | |||
1660 | static_cast<SwTabFrame*>(pFrame)->RegistFlys(); | |||
1661 | // OD 12.08.2003 #i17969# - consider horizontal/vertical layout | |||
1662 | // for setting position at newly inserted frame | |||
1663 | lcl_SetPos( *pFrame, *pLay ); | |||
1664 | ||||
1665 | pPrv = pFrame; | |||
1666 | //Set the index to the endnode of the table section. | |||
1667 | nIndex = pTableNode->EndOfSectionIndex(); | |||
1668 | ||||
1669 | SwTabFrame* pTmpFrame = static_cast<SwTabFrame*>(pFrame); | |||
1670 | while ( pTmpFrame ) | |||
1671 | { | |||
1672 | pTmpFrame->CheckDirChange(); | |||
1673 | pTmpFrame = pTmpFrame->IsFollow() ? pTmpFrame->FindMaster() : nullptr; | |||
1674 | } | |||
1675 | ||||
1676 | } | |||
1677 | else if ( pNd->IsSectionNode() ) | |||
1678 | { | |||
1679 | if (pLayout->IsHideRedlines() && !pNd->IsCreateFrameWhenHidingRedlines()) | |||
1680 | { | |||
1681 | assert(pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden)(static_cast <bool> (pNd->GetRedlineMergeFlag() == SwNode ::Merge::Hidden) ? void (0) : __assert_fail ("pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1681, __extension__ __PRETTY_FUNCTION__)); | |||
1682 | continue; // skip it | |||
1683 | } | |||
1684 | SwSectionNode *pNode = static_cast<SwSectionNode*>(pNd); | |||
1685 | if( pNode->GetSection().CalcHiddenFlag() ) | |||
1686 | // is hidden, skip the area | |||
1687 | nIndex = pNode->EndOfSectionIndex(); | |||
1688 | else | |||
1689 | { | |||
1690 | pFrame = pNode->MakeFrame( pLay ); | |||
1691 | pActualSection.reset( new SwActualSection( pActualSection.release(), | |||
1692 | static_cast<SwSectionFrame*>(pFrame), pNode ) ); | |||
1693 | if ( pActualSection->GetUpper() ) | |||
1694 | { | |||
1695 | //Insert behind the Upper, the "Follow" of the Upper will be | |||
1696 | //generated at the EndNode. | |||
1697 | SwSectionFrame *pTmp = pActualSection->GetUpper()->GetSectionFrame(); | |||
1698 | pFrame->InsertBehind( pTmp->GetUpper(), pTmp ); | |||
1699 | // OD 25.03.2003 #108339# - direct initialization of section | |||
1700 | // after insertion in the layout | |||
1701 | static_cast<SwSectionFrame*>(pFrame)->Init(); | |||
1702 | } | |||
1703 | else | |||
1704 | { | |||
1705 | pFrame->InsertBehind( pLay, pPrv ); | |||
1706 | // OD 25.03.2003 #108339# - direct initialization of section | |||
1707 | // after insertion in the layout | |||
1708 | static_cast<SwSectionFrame*>(pFrame)->Init(); | |||
1709 | ||||
1710 | // #i33963# | |||
1711 | // Do not trust the IsInFootnote flag. If we are currently | |||
1712 | // building up a table, the upper of pPrv may be a cell | |||
1713 | // frame, but the cell frame does not have an upper yet. | |||
1714 | if( pPrv && nullptr != pPrv->ImplFindFootnoteFrame() ) | |||
1715 | { | |||
1716 | if( pPrv->IsSctFrame() ) | |||
1717 | pPrv = static_cast<SwSectionFrame*>(pPrv)->ContainsContent(); | |||
1718 | if( pPrv && pPrv->IsTextFrame() ) | |||
1719 | static_cast<SwTextFrame*>(pPrv)->Prepare( PrepareHint::QuoVadis, nullptr, false ); | |||
1720 | } | |||
1721 | } | |||
1722 | if (nIndex + 1 == nEndIndex) | |||
1723 | { // tdf#131684 tdf#132236 fix upper of frame moved in | |||
1724 | // SwUndoDelete; can't be done there unfortunately | |||
1725 | // because empty section frames are deleted here | |||
1726 | SwFrame *const pNext( | |||
1727 | // if there's a parent section, it has been split | |||
1728 | // into 2 SwSectionFrame already :( | |||
1729 | ( pFrame->GetNext() | |||
1730 | && pFrame->GetNext()->IsSctFrame() | |||
1731 | && pActualSection->GetUpper() | |||
1732 | && pActualSection->GetUpper()->GetSectionNode() == | |||
1733 | static_cast<SwSectionFrame const*>(pFrame->GetNext())->GetSection()->GetFormat()->GetSectionNode()) | |||
1734 | ? static_cast<SwSectionFrame *>(pFrame->GetNext())->ContainsContent() | |||
1735 | : pFrame->GetNext()); | |||
1736 | if (pNext | |||
1737 | && pNext->IsTextFrame() | |||
1738 | && static_cast<SwTextFrame*>(pNext)->GetTextNodeFirst() == pDoc->GetNodes()[nEndIndex] | |||
1739 | && (pNext->GetUpper() == pFrame->GetUpper() | |||
1740 | || pFrame->GetNext()->IsSctFrame())) // checked above | |||
1741 | { | |||
1742 | pNext->Cut(); | |||
1743 | pNext->InvalidateInfFlags(); // mbInfSct changed | |||
1744 | // could have columns | |||
1745 | SwSectionFrame *const pSection(static_cast<SwSectionFrame*>(pFrame)); | |||
1746 | assert(!pSection->Lower() || pSection->Lower()->IsLayoutFrame())(static_cast <bool> (!pSection->Lower() || pSection-> Lower()->IsLayoutFrame()) ? void (0) : __assert_fail ("!pSection->Lower() || pSection->Lower()->IsLayoutFrame()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1746, __extension__ __PRETTY_FUNCTION__)); | |||
1747 | SwLayoutFrame *const pParent(pSection->Lower() ? pSection->GetNextLayoutLeaf() : pSection); | |||
1748 | assert(!pParent->Lower())(static_cast <bool> (!pParent->Lower()) ? void (0) : __assert_fail ("!pParent->Lower()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1748, __extension__ __PRETTY_FUNCTION__)); | |||
1749 | // paste invalidates, section could have indent... | |||
1750 | pNext->Paste(pParent, nullptr); | |||
1751 | } | |||
1752 | } | |||
1753 | // #i27138# | |||
1754 | // notify accessibility paragraphs objects about changed | |||
1755 | // CONTENT_FLOWS_FROM/_TO relation. | |||
1756 | // Relation CONTENT_FLOWS_FROM for next paragraph will change | |||
1757 | // and relation CONTENT_FLOWS_TO for previous paragraph will change. | |||
1758 | { | |||
1759 | SwViewShell* pViewShell( pFrame->getRootFrame()->GetCurrShell() ); | |||
1760 | // no notification, if <SwViewShell> is in construction | |||
1761 | if ( pViewShell && !pViewShell->IsInConstructor() && | |||
1762 | pViewShell->GetLayout() && | |||
1763 | pViewShell->GetLayout()->IsAnyShellAccessible() && | |||
1764 | pFrame->FindPageFrame() != nullptr) | |||
1765 | { | |||
1766 | pViewShell->InvalidateAccessibleParaFlowRelation( | |||
1767 | dynamic_cast<SwTextFrame*>(pFrame->FindNextCnt( true )), | |||
1768 | dynamic_cast<SwTextFrame*>(pFrame->FindPrevCnt()) ); | |||
1769 | } | |||
1770 | } | |||
1771 | pFrame->CheckDirChange(); | |||
1772 | ||||
1773 | // OD 12.08.2003 #i17969# - consider horizontal/vertical layout | |||
1774 | // for setting position at newly inserted frame | |||
1775 | lcl_SetPos( *pFrame, *pLay ); | |||
1776 | ||||
1777 | // OD 20.11.2002 #105405# - no page, no invalidate. | |||
1778 | if ( pPage ) | |||
1779 | { | |||
1780 | // OD 18.09.2002 #100522# | |||
1781 | // invalidate page in order to force format and paint of | |||
1782 | // inserted section frame | |||
1783 | pFrame->InvalidatePage( pPage ); | |||
1784 | ||||
1785 | // FME 10.11.2003 #112243# | |||
1786 | // Invalidate fly content flag: | |||
1787 | if ( pFrame->IsInFly() ) | |||
1788 | pPage->InvalidateFlyContent(); | |||
1789 | ||||
1790 | // OD 14.11.2002 #104684# - invalidate page content in order to | |||
1791 | // force format and paint of section content. | |||
1792 | pPage->InvalidateContent(); | |||
1793 | } | |||
1794 | ||||
1795 | pLay = static_cast<SwLayoutFrame*>(pFrame); | |||
1796 | if ( pLay->Lower() && pLay->Lower()->IsLayoutFrame() ) | |||
1797 | pLay = pLay->GetNextLayoutLeaf(); | |||
1798 | pPrv = nullptr; | |||
1799 | } | |||
1800 | } | |||
1801 | else if ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() ) | |||
1802 | { | |||
1803 | if (pLayout->IsHideRedlines() && !pNd->IsCreateFrameWhenHidingRedlines()) | |||
1804 | { | |||
1805 | assert(pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden)(static_cast <bool> (pNd->GetRedlineMergeFlag() == SwNode ::Merge::Hidden) ? void (0) : __assert_fail ("pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1805, __extension__ __PRETTY_FUNCTION__)); | |||
1806 | continue; // skip it | |||
1807 | } | |||
1808 | assert(pActualSection && "Section end without section start?")(static_cast <bool> (pActualSection && "Section end without section start?" ) ? void (0) : __assert_fail ("pActualSection && \"Section end without section start?\"" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1808, __extension__ __PRETTY_FUNCTION__)); | |||
1809 | assert(pActualSection->GetSectionNode() == pNd->StartOfSectionNode())(static_cast <bool> (pActualSection->GetSectionNode( ) == pNd->StartOfSectionNode()) ? void (0) : __assert_fail ("pActualSection->GetSectionNode() == pNd->StartOfSectionNode()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1809, __extension__ __PRETTY_FUNCTION__)); | |||
1810 | ||||
1811 | //Close the section, where appropriate activate the surrounding | |||
1812 | //section again. | |||
1813 | pActualSection.reset(pActualSection->GetUpper()); | |||
1814 | pLay = pLay->FindSctFrame(); | |||
1815 | if ( pActualSection ) | |||
1816 | { | |||
1817 | //Could be, that the last SectionFrame remains empty. | |||
1818 | //Then now is the time to remove them. | |||
1819 | if ( !pLay->ContainsContent() ) | |||
1820 | { | |||
1821 | SwFrame *pTmpFrame = pLay; | |||
1822 | pLay = pTmpFrame->GetUpper(); | |||
1823 | pPrv = pTmpFrame->GetPrev(); | |||
1824 | pTmpFrame->RemoveFromLayout(); | |||
1825 | SwFrame::DestroyFrame(pTmpFrame); | |||
1826 | } | |||
1827 | else | |||
1828 | { | |||
1829 | pPrv = pLay; | |||
1830 | pLay = pLay->GetUpper(); | |||
1831 | } | |||
1832 | ||||
1833 | // new section frame | |||
1834 | pFrame = pActualSection->GetSectionNode()->MakeFrame( pLay ); | |||
1835 | pFrame->InsertBehind( pLay, pPrv ); | |||
1836 | static_cast<SwSectionFrame*>(pFrame)->Init(); | |||
1837 | ||||
1838 | // OD 12.08.2003 #i17969# - consider horizontal/vertical layout | |||
1839 | // for setting position at newly inserted frame | |||
1840 | lcl_SetPos( *pFrame, *pLay ); | |||
1841 | ||||
1842 | SwSectionFrame* pOuterSectionFrame = pActualSection->GetSectionFrame(); | |||
1843 | ||||
1844 | // a follow has to be appended to the new section frame | |||
1845 | SwSectionFrame* pFollow = pOuterSectionFrame ? pOuterSectionFrame->GetFollow() : nullptr; | |||
1846 | if ( pFollow ) | |||
1847 | { | |||
1848 | pOuterSectionFrame->SetFollow( nullptr ); | |||
1849 | pOuterSectionFrame->InvalidateSize(); | |||
1850 | static_cast<SwSectionFrame*>(pFrame)->SetFollow( pFollow ); | |||
1851 | } | |||
1852 | ||||
1853 | // We don't want to leave empty parts back. | |||
1854 | if (pOuterSectionFrame && | |||
1855 | ! pOuterSectionFrame->IsColLocked() && | |||
1856 | ! pOuterSectionFrame->ContainsContent() ) | |||
1857 | { | |||
1858 | pOuterSectionFrame->DelEmpty( true ); | |||
1859 | SwFrame::DestroyFrame(pOuterSectionFrame); | |||
1860 | } | |||
1861 | pActualSection->SetSectionFrame( static_cast<SwSectionFrame*>(pFrame) ); | |||
1862 | ||||
1863 | pLay = static_cast<SwLayoutFrame*>(pFrame); | |||
1864 | if ( pLay->Lower() && pLay->Lower()->IsLayoutFrame() ) | |||
1865 | pLay = pLay->GetNextLayoutLeaf(); | |||
1866 | pPrv = nullptr; | |||
1867 | } | |||
1868 | else | |||
1869 | { | |||
1870 | //Nothing more with sections, it goes on right behind | |||
1871 | //the SectionFrame. | |||
1872 | pPrv = pLay; | |||
1873 | pLay = pLay->GetUpper(); | |||
1874 | } | |||
1875 | } | |||
1876 | else if( pNd->IsStartNode() && | |||
1877 | SwFlyStartNode == static_cast<SwStartNode*>(pNd)->GetStartNodeType() ) | |||
1878 | { | |||
1879 | if (pLayout->IsHideRedlines() && !pNd->IsCreateFrameWhenHidingRedlines()) | |||
1880 | { | |||
1881 | assert(pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden)(static_cast <bool> (pNd->GetRedlineMergeFlag() == SwNode ::Merge::Hidden) ? void (0) : __assert_fail ("pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1881, __extension__ __PRETTY_FUNCTION__)); | |||
1882 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1882, __extension__ __PRETTY_FUNCTION__)); // actually a fly-section can't be deleted? | |||
1883 | continue; // skip it | |||
1884 | } | |||
1885 | if ( !pTable->empty() && bObjsDirect && !bDontCreateObjects ) | |||
1886 | { | |||
1887 | SwFlyFrame* pFly = pLay->FindFlyFrame(); | |||
1888 | if( pFly ) | |||
1889 | AppendObjs( pTable, nIndex, pFly, pPage, pDoc ); | |||
1890 | } | |||
1891 | } | |||
1892 | else | |||
1893 | { | |||
1894 | assert(!pLayout->IsHideRedlines()(static_cast <bool> (!pLayout->IsHideRedlines() || pNd ->GetRedlineMergeFlag() != SwNode::Merge::Hidden) ? void ( 0) : __assert_fail ("!pLayout->IsHideRedlines() || pNd->GetRedlineMergeFlag() != SwNode::Merge::Hidden" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1895, __extension__ __PRETTY_FUNCTION__)) | |||
1895 | || pNd->GetRedlineMergeFlag() != SwNode::Merge::Hidden)(static_cast <bool> (!pLayout->IsHideRedlines() || pNd ->GetRedlineMergeFlag() != SwNode::Merge::Hidden) ? void ( 0) : __assert_fail ("!pLayout->IsHideRedlines() || pNd->GetRedlineMergeFlag() != SwNode::Merge::Hidden" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1895, __extension__ __PRETTY_FUNCTION__)); | |||
1896 | // Neither Content nor table nor section, so we are done. | |||
1897 | break; | |||
1898 | } | |||
1899 | } | |||
1900 | ||||
1901 | if ( pActualSection ) | |||
1902 | { | |||
1903 | // Might happen that an empty (Follow-)Section is left over. | |||
1904 | if ( !(pLay = pActualSection->GetSectionFrame())->ContainsContent() ) | |||
1905 | { | |||
1906 | pLay->RemoveFromLayout(); | |||
1907 | SwFrame::DestroyFrame(pLay); | |||
1908 | } | |||
1909 | pActualSection.reset(); | |||
1910 | } | |||
1911 | ||||
1912 | if ( bPages ) // let the Flys connect to each other | |||
1913 | { | |||
1914 | if ( !bDontCreateObjects ) | |||
1915 | AppendAllObjs( pTable, pLayout ); | |||
1916 | bObjsDirect = true; | |||
1917 | } | |||
1918 | ||||
1919 | if( pPageMaker ) | |||
1920 | { | |||
1921 | pPageMaker->CheckFlyCache( pPage ); | |||
1922 | pPageMaker.reset(); | |||
1923 | if( pDoc->GetLayoutCache() ) | |||
1924 | { | |||
1925 | #ifdef DBG_UTIL | |||
1926 | pDoc->GetLayoutCache()->CompareLayout( *pDoc ); | |||
1927 | #endif | |||
1928 | pDoc->GetLayoutCache()->ClearImpl(); | |||
1929 | } | |||
1930 | } | |||
1931 | ||||
1932 | pDoc->getIDocumentTimerAccess().UnblockIdling(); | |||
1933 | if( bOldCallbackActionEnabled ) | |||
1934 | pLayout->SetCallbackActionEnabled( bOldCallbackActionEnabled ); | |||
1935 | } | |||
1936 | ||||
1937 | void MakeFrames( SwDoc *pDoc, const SwNodeIndex &rSttIdx, | |||
1938 | const SwNodeIndex &rEndIdx ) | |||
1939 | { | |||
1940 | bObjsDirect = false; | |||
1941 | ||||
1942 | SwNodeIndex aTmp( rSttIdx ); | |||
1943 | sal_uLong nEndIdx = rEndIdx.GetIndex(); | |||
1944 | SwNode* pNd = pDoc->GetNodes().FindPrvNxtFrameNode( aTmp, | |||
1945 | pDoc->GetNodes()[ nEndIdx-1 ]); | |||
1946 | if ( pNd ) | |||
1947 | { | |||
1948 | bool bApres = aTmp < rSttIdx; | |||
1949 | SwNode2Layout aNode2Layout( *pNd, rSttIdx.GetIndex() ); | |||
1950 | SwFrame* pFrame; | |||
1951 | sw::FrameMode eMode = sw::FrameMode::Existing; | |||
1952 | while( nullptr != (pFrame = aNode2Layout.NextFrame()) ) | |||
1953 | { | |||
1954 | SwLayoutFrame *pUpper = pFrame->GetUpper(); | |||
1955 | SwFootnoteFrame* pFootnoteFrame = pUpper->FindFootnoteFrame(); | |||
1956 | bool bOldLock, bOldFootnote; | |||
1957 | if( pFootnoteFrame ) | |||
1958 | { | |||
1959 | bOldFootnote = pFootnoteFrame->IsColLocked(); | |||
1960 | pFootnoteFrame->ColLock(); | |||
1961 | } | |||
1962 | else | |||
1963 | bOldFootnote = true; | |||
1964 | SwSectionFrame* pSct = pUpper->FindSctFrame(); | |||
1965 | // Inside of footnotes only those areas are interesting that are inside of them. But | |||
1966 | // not the ones (e.g. column areas) in which are the footnote containers positioned. | |||
1967 | // #109767# Table frame is in section, insert section in cell frame. | |||
1968 | if( pSct && ((pFootnoteFrame && !pSct->IsInFootnote()) || pUpper->IsCellFrame()) ) | |||
1969 | pSct = nullptr; | |||
1970 | if( pSct ) | |||
1971 | { // to prevent pTmp->MoveFwd from destroying the SectionFrame | |||
1972 | bOldLock = pSct->IsColLocked(); | |||
1973 | pSct->ColLock(); | |||
1974 | } | |||
1975 | else | |||
1976 | bOldLock = true; | |||
1977 | ||||
1978 | // If pFrame cannot be moved, it is not possible to move it to the next page. This applies | |||
1979 | // also for frames (in the first column of a frame pFrame is moveable) and column | |||
1980 | // sections of tables (also here pFrame is moveable). | |||
1981 | bool bMoveNext = nEndIdx - rSttIdx.GetIndex() > 120; | |||
1982 | bool bAllowMove = !pFrame->IsInFly() && pFrame->IsMoveable() && | |||
1983 | (!pFrame->IsInTab() || pFrame->IsTabFrame() ); | |||
1984 | if ( bMoveNext && bAllowMove ) | |||
1985 | { | |||
1986 | SwFrame *pMove = pFrame; | |||
1987 | SwFrame *pPrev = pFrame->GetPrev(); | |||
1988 | SwFlowFrame *pTmp = SwFlowFrame::CastFlowFrame( pMove ); | |||
1989 | assert(pTmp)(static_cast <bool> (pTmp) ? void (0) : __assert_fail ( "pTmp", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1989, __extension__ __PRETTY_FUNCTION__)); | |||
1990 | ||||
1991 | if ( bApres ) | |||
1992 | { | |||
1993 | // The rest of this page should be empty. Thus, the following one has to move to | |||
1994 | // the next page (it might also be located in the following column). | |||
1995 | assert(!pTmp->HasFollow() && "prev. node's frame is not last")(static_cast <bool> (!pTmp->HasFollow() && "prev. node's frame is not last" ) ? void (0) : __assert_fail ("!pTmp->HasFollow() && \"prev. node's frame is not last\"" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 1995, __extension__ __PRETTY_FUNCTION__)); | |||
1996 | pPrev = pFrame; | |||
1997 | // If the surrounding SectionFrame has a "next" one, | |||
1998 | // so this one needs to be moved as well. | |||
1999 | pMove = pFrame->GetIndNext(); | |||
2000 | SwColumnFrame* pCol = static_cast<SwColumnFrame*>(pFrame->FindColFrame()); | |||
2001 | if( pCol ) | |||
2002 | pCol = static_cast<SwColumnFrame*>(pCol->GetNext()); | |||
2003 | do | |||
2004 | { | |||
2005 | if( pCol && !pMove ) | |||
2006 | { // No successor so far, look into the next column | |||
2007 | pMove = pCol->ContainsAny(); | |||
2008 | if( pCol->GetNext() ) | |||
2009 | pCol = static_cast<SwColumnFrame*>(pCol->GetNext()); | |||
2010 | else if( pCol->IsInSct() ) | |||
2011 | { // If there is no following column but we are in a column frame, | |||
2012 | // there might be (page) columns outside of it. | |||
2013 | pCol = static_cast<SwColumnFrame*>(pCol->FindSctFrame()->FindColFrame()); | |||
2014 | if( pCol ) | |||
2015 | pCol = static_cast<SwColumnFrame*>(pCol->GetNext()); | |||
2016 | } | |||
2017 | else | |||
2018 | pCol = nullptr; | |||
2019 | } | |||
2020 | // skip invalid SectionFrames | |||
2021 | while( pMove && pMove->IsSctFrame() && | |||
2022 | !static_cast<SwSectionFrame*>(pMove)->GetSection() ) | |||
2023 | pMove = pMove->GetNext(); | |||
2024 | } while( !pMove && pCol ); | |||
2025 | ||||
2026 | if( pMove ) | |||
2027 | { | |||
2028 | if ( pMove->IsContentFrame() ) | |||
2029 | pTmp = static_cast<SwContentFrame*>(pMove); | |||
2030 | else if ( pMove->IsTabFrame() ) | |||
2031 | pTmp = static_cast<SwTabFrame*>(pMove); | |||
2032 | else if ( pMove->IsSctFrame() ) | |||
2033 | { | |||
2034 | pMove = static_cast<SwSectionFrame*>(pMove)->ContainsAny(); | |||
2035 | if( pMove ) | |||
2036 | pTmp = SwFlowFrame::CastFlowFrame( pMove ); | |||
2037 | else | |||
2038 | pTmp = nullptr; | |||
2039 | } | |||
2040 | } | |||
2041 | else | |||
2042 | pTmp = nullptr; | |||
2043 | } | |||
2044 | else | |||
2045 | { | |||
2046 | assert(!pTmp->IsFollow() && "next node's frame is not master")(static_cast <bool> (!pTmp->IsFollow() && "next node's frame is not master" ) ? void (0) : __assert_fail ("!pTmp->IsFollow() && \"next node's frame is not master\"" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 2046, __extension__ __PRETTY_FUNCTION__)); | |||
2047 | // move the _content_ of a section frame | |||
2048 | if( pMove->IsSctFrame() ) | |||
2049 | { | |||
2050 | while( pMove && pMove->IsSctFrame() && | |||
2051 | !static_cast<SwSectionFrame*>(pMove)->GetSection() ) | |||
2052 | pMove = pMove->GetNext(); | |||
2053 | if( pMove && pMove->IsSctFrame() ) | |||
2054 | pMove = static_cast<SwSectionFrame*>(pMove)->ContainsAny(); | |||
2055 | if( pMove ) | |||
2056 | pTmp = SwFlowFrame::CastFlowFrame( pMove ); | |||
2057 | else | |||
2058 | pTmp = nullptr; | |||
2059 | } | |||
2060 | } | |||
2061 | ||||
2062 | if( pTmp ) | |||
2063 | { | |||
2064 | SwFrame* pOldUp = pTmp->GetFrame().GetUpper(); | |||
2065 | // MoveFwd==true means that we are still on the same page. | |||
2066 | // But since we want to move if possible! | |||
2067 | bool bTmpOldLock = pTmp->IsJoinLocked(); | |||
2068 | pTmp->LockJoin(); | |||
2069 | while( pTmp->MoveFwd( true, false, true ) ) | |||
2070 | { | |||
2071 | if( pOldUp == pTmp->GetFrame().GetUpper() ) | |||
2072 | break; | |||
2073 | pOldUp = pTmp->GetFrame().GetUpper(); | |||
2074 | } | |||
2075 | if( !bTmpOldLock ) | |||
2076 | pTmp->UnlockJoin(); | |||
2077 | } | |||
2078 | ::InsertCnt_( pUpper, pDoc, rSttIdx.GetIndex(), | |||
2079 | pFrame->IsInDocBody(), nEndIdx, pPrev, eMode ); | |||
2080 | } | |||
2081 | else | |||
2082 | { | |||
2083 | bool bSplit; | |||
2084 | SwFrame* pPrv = bApres ? pFrame : pFrame->GetPrev(); | |||
2085 | // If the section frame is inserted into another one, it must be split. | |||
2086 | if( pSct && rSttIdx.GetNode().IsSectionNode() ) | |||
2087 | { | |||
2088 | bSplit = pSct->SplitSect( pFrame, bApres ); | |||
2089 | if( !bSplit && !bApres ) | |||
2090 | { | |||
2091 | pUpper = pSct->GetUpper(); | |||
2092 | pPrv = pSct->GetPrev(); | |||
2093 | } | |||
2094 | } | |||
2095 | else | |||
2096 | bSplit = false; | |||
2097 | ||||
2098 | ::InsertCnt_( pUpper, pDoc, rSttIdx.GetIndex(), false, | |||
2099 | nEndIdx, pPrv, eMode ); | |||
2100 | // OD 23.06.2003 #108784# - correction: append objects doesn't | |||
2101 | // depend on value of <bAllowMove> | |||
2102 | if( !bDontCreateObjects ) | |||
2103 | { | |||
2104 | const SwFrameFormats *pTable = pDoc->GetSpzFrameFormats(); | |||
2105 | if( !pTable->empty() ) | |||
2106 | AppendAllObjs( pTable, pUpper ); | |||
2107 | } | |||
2108 | ||||
2109 | // If nothing was added (e.g. a hidden section), the split must be reversed. | |||
2110 | if( bSplit && pSct && pSct->GetNext() | |||
2111 | && pSct->GetNext()->IsSctFrame() ) | |||
2112 | pSct->MergeNext( static_cast<SwSectionFrame*>(pSct->GetNext()) ); | |||
2113 | if( pFrame->IsInFly() ) | |||
2114 | pFrame->FindFlyFrame()->Invalidate_(); | |||
2115 | if( pFrame->IsInTab() ) | |||
2116 | pFrame->InvalidateSize(); | |||
2117 | } | |||
2118 | ||||
2119 | SwPageFrame *pPage = pUpper->FindPageFrame(); | |||
2120 | SwFrame::CheckPageDescs( pPage, false ); | |||
2121 | if( !bOldFootnote ) | |||
2122 | pFootnoteFrame->ColUnlock(); | |||
2123 | if( !bOldLock ) | |||
2124 | { | |||
2125 | pSct->ColUnlock(); | |||
2126 | // pSct might be empty (e.g. when inserting linked section containing further | |||
2127 | // sections) and can be destroyed in such cases. | |||
2128 | if( !pSct->ContainsContent() ) | |||
2129 | { | |||
2130 | pSct->DelEmpty( true ); | |||
2131 | pUpper->getRootFrame()->RemoveFromList( pSct ); | |||
2132 | SwFrame::DestroyFrame(pSct); | |||
2133 | } | |||
2134 | } | |||
2135 | eMode = sw::FrameMode::New; // use Existing only once! | |||
2136 | } | |||
2137 | } | |||
2138 | ||||
2139 | bObjsDirect = true; | |||
2140 | } | |||
2141 | ||||
2142 | SwBorderAttrs::SwBorderAttrs(const SwModify *pMod, const SwFrame *pConstructor) | |||
2143 | : SwCacheObj(pMod) | |||
2144 | , m_rAttrSet(pConstructor->IsContentFrame() | |||
2145 | ? pConstructor->IsTextFrame() | |||
2146 | ? static_cast<const SwTextFrame*>(pConstructor)->GetTextNodeForParaProps()->GetSwAttrSet() | |||
2147 | : static_cast<const SwNoTextFrame*>(pConstructor)->GetNode()->GetSwAttrSet() | |||
2148 | : static_cast<const SwLayoutFrame*>(pConstructor)->GetFormat()->GetAttrSet()) | |||
2149 | , m_rUL(m_rAttrSet.GetULSpace()) | |||
2150 | // #i96772# | |||
2151 | // LRSpaceItem is copied due to the possibility that it is adjusted - see below | |||
2152 | , m_rLR(m_rAttrSet.GetLRSpace().Clone()) | |||
2153 | , m_rBox(m_rAttrSet.GetBox()) | |||
2154 | , m_rShadow(m_rAttrSet.GetShadow()) | |||
2155 | , m_aFrameSize(m_rAttrSet.GetFrameSize().GetSize()) | |||
2156 | , m_bIsLine(false) | |||
2157 | , m_bJoinedWithPrev(false) | |||
2158 | , m_bJoinedWithNext(false) | |||
2159 | , m_nTopLine(0) | |||
2160 | , m_nBottomLine(0) | |||
2161 | , m_nLeftLine(0) | |||
2162 | , m_nRightLine(0) | |||
2163 | , m_nTop(0) | |||
2164 | , m_nBottom(0) | |||
2165 | , m_nGetTopLine(0) | |||
2166 | , m_nGetBottomLine(0) | |||
2167 | , m_nLineSpacing(0) | |||
2168 | { | |||
2169 | // #i96772# | |||
2170 | const SwTextFrame* pTextFrame = dynamic_cast<const SwTextFrame*>(pConstructor); | |||
2171 | if ( pTextFrame ) | |||
2172 | { | |||
2173 | pTextFrame->GetTextNodeForParaProps()->ClearLRSpaceItemDueToListLevelIndents( m_rLR ); | |||
2174 | } | |||
2175 | else if ( pConstructor->IsNoTextFrame() ) | |||
2176 | { | |||
2177 | m_rLR = std::make_shared<SvxLRSpaceItem>(RES_LR_SPACE); | |||
2178 | } | |||
2179 | ||||
2180 | // Caution: The USHORTs for the cached values are not initialized by intention! | |||
2181 | ||||
2182 | // everything needs to be calculated at least once: | |||
2183 | m_bTopLine = m_bBottomLine = m_bLeftLine = m_bRightLine = | |||
2184 | m_bTop = m_bBottom = m_bLine = true; | |||
2185 | ||||
2186 | // except this one: calculate line spacing before cell border only for text frames | |||
2187 | m_bLineSpacing = bool(pTextFrame); | |||
2188 | ||||
2189 | m_bCacheGetLine = m_bCachedGetTopLine = m_bCachedGetBottomLine = false; | |||
2190 | // OD 21.05.2003 #108789# - init cache status for values <m_bJoinedWithPrev> | |||
2191 | // and <m_bJoinedWithNext>, which aren't initialized by default. | |||
2192 | m_bCachedJoinedWithPrev = false; | |||
2193 | m_bCachedJoinedWithNext = false; | |||
2194 | } | |||
2195 | ||||
2196 | SwBorderAttrs::~SwBorderAttrs() | |||
2197 | { | |||
2198 | const_cast<SwModify *>(static_cast<SwModify const *>(m_pOwner))->SetInCache( false ); | |||
2199 | } | |||
2200 | ||||
2201 | /* All calc methods calculate a safety distance in addition to the values given by the attributes. | |||
2202 | * This safety distance is only added when working with borders and/or shadows to prevent that | |||
2203 | * e.g. borders are painted over. | |||
2204 | */ | |||
2205 | ||||
2206 | void SwBorderAttrs::CalcTop_() | |||
2207 | { | |||
2208 | m_nTop = CalcTopLine() + m_rUL.GetUpper(); | |||
2209 | m_bTop = false; | |||
2210 | } | |||
2211 | ||||
2212 | void SwBorderAttrs::CalcBottom_() | |||
2213 | { | |||
2214 | m_nBottom = CalcBottomLine() + m_rUL.GetLower(); | |||
2215 | m_bBottom = false; | |||
2216 | } | |||
2217 | ||||
2218 | long SwBorderAttrs::CalcRight( const SwFrame* pCaller ) const | |||
2219 | { | |||
2220 | long nRight=0; | |||
2221 | ||||
2222 | if (!pCaller->IsTextFrame() || !static_cast<const SwTextFrame*>(pCaller)->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::INVERT_BORDER_SPACING)) { | |||
2223 | // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left | |||
2224 | // and right border are painted on the right respectively left. | |||
2225 | if ( pCaller->IsCellFrame() && pCaller->IsRightToLeft() ) | |||
2226 | nRight = CalcLeftLine(); | |||
2227 | else | |||
2228 | nRight = CalcRightLine(); | |||
2229 | ||||
2230 | } | |||
2231 | // for paragraphs, "left" is "before text" and "right" is "after text" | |||
2232 | if ( pCaller->IsTextFrame() && pCaller->IsRightToLeft() ) | |||
2233 | nRight += m_rLR->GetLeft(); | |||
2234 | else | |||
2235 | nRight += m_rLR->GetRight(); | |||
2236 | ||||
2237 | // correction: retrieve left margin for numbering in R2L-layout | |||
2238 | if ( pCaller->IsTextFrame() && pCaller->IsRightToLeft() ) | |||
2239 | { | |||
2240 | nRight += static_cast<const SwTextFrame*>(pCaller)->GetTextNodeForParaProps()->GetLeftMarginWithNum(); | |||
2241 | } | |||
2242 | ||||
2243 | return nRight; | |||
2244 | } | |||
2245 | ||||
2246 | /// Tries to detect if this paragraph has a floating table attached. | |||
2247 | static bool lcl_hasTabFrame(const SwTextFrame* pTextFrame) | |||
2248 | { | |||
2249 | if (pTextFrame->GetDrawObjs()) | |||
2250 | { | |||
2251 | const SwSortedObjs* pSortedObjs = pTextFrame->GetDrawObjs(); | |||
2252 | if (pSortedObjs->size() > 0) | |||
2253 | { | |||
2254 | SwAnchoredObject* pObject = (*pSortedObjs)[0]; | |||
2255 | if (dynamic_cast<const SwFlyFrame*>(pObject) != nullptr) | |||
2256 | { | |||
2257 | SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pObject); | |||
2258 | if (pFly->Lower() && pFly->Lower()->IsTabFrame()) | |||
2259 | return true; | |||
2260 | } | |||
2261 | } | |||
2262 | } | |||
2263 | return false; | |||
2264 | } | |||
2265 | ||||
2266 | long SwBorderAttrs::CalcLeft( const SwFrame *pCaller ) const | |||
2267 | { | |||
2268 | long nLeft=0; | |||
2269 | ||||
2270 | if (!pCaller->IsTextFrame() || !static_cast<const SwTextFrame*>(pCaller)->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::INVERT_BORDER_SPACING)) | |||
2271 | { | |||
2272 | // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left | |||
2273 | // and right border are painted on the right respectively left. | |||
2274 | if ( pCaller->IsCellFrame() && pCaller->IsRightToLeft() ) | |||
2275 | nLeft = CalcRightLine(); | |||
2276 | else | |||
2277 | nLeft = CalcLeftLine(); | |||
2278 | } | |||
2279 | ||||
2280 | // for paragraphs, "left" is "before text" and "right" is "after text" | |||
2281 | if ( pCaller->IsTextFrame() && pCaller->IsRightToLeft() ) | |||
2282 | nLeft += m_rLR->GetRight(); | |||
2283 | else | |||
2284 | { | |||
2285 | bool bIgnoreMargin = false; | |||
2286 | if (pCaller->IsTextFrame()) | |||
2287 | { | |||
2288 | const SwTextFrame* pTextFrame = static_cast<const SwTextFrame*>(pCaller); | |||
2289 | if (pTextFrame->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::FLOATTABLE_NOMARGINS)) | |||
2290 | { | |||
2291 | // If this is explicitly requested, ignore the margins next to the floating table. | |||
2292 | if (lcl_hasTabFrame(pTextFrame)) | |||
2293 | bIgnoreMargin = true; | |||
2294 | // TODO here we only handle the first two paragraphs, would be nice to generalize this. | |||
2295 | else if (pTextFrame->FindPrev() && pTextFrame->FindPrev()->IsTextFrame() && lcl_hasTabFrame(static_cast<const SwTextFrame*>(pTextFrame->FindPrev()))) | |||
2296 | bIgnoreMargin = true; | |||
2297 | } | |||
2298 | } | |||
2299 | if (!bIgnoreMargin) | |||
2300 | nLeft += m_rLR->GetLeft(); | |||
2301 | } | |||
2302 | ||||
2303 | // correction: do not retrieve left margin for numbering in R2L-layout | |||
2304 | if ( pCaller->IsTextFrame() && !pCaller->IsRightToLeft() ) | |||
2305 | { | |||
2306 | nLeft += static_cast<const SwTextFrame*>(pCaller)->GetTextNodeForParaProps()->GetLeftMarginWithNum(); | |||
2307 | } | |||
2308 | ||||
2309 | return nLeft; | |||
2310 | } | |||
2311 | ||||
2312 | /* Calculated values for borders and shadows. | |||
2313 | * It might be that a distance is wanted even without lines. This will be | |||
2314 | * considered here and not by the attribute (e.g. bBorderDist for cells). | |||
2315 | */ | |||
2316 | ||||
2317 | void SwBorderAttrs::CalcTopLine_() | |||
2318 | { | |||
2319 | m_nTopLine = m_rBox.CalcLineSpace( SvxBoxItemLine::TOP, /*bEvenIfNoLine*/true ); | |||
2320 | m_nTopLine = m_nTopLine + m_rShadow.CalcShadowSpace(SvxShadowItemSide::TOP); | |||
2321 | m_bTopLine = false; | |||
2322 | } | |||
2323 | ||||
2324 | void SwBorderAttrs::CalcBottomLine_() | |||
2325 | { | |||
2326 | m_nBottomLine = m_rBox.CalcLineSpace( SvxBoxItemLine::BOTTOM, true ); | |||
2327 | m_nBottomLine = m_nBottomLine + m_rShadow.CalcShadowSpace(SvxShadowItemSide::BOTTOM); | |||
2328 | m_bBottomLine = false; | |||
2329 | } | |||
2330 | ||||
2331 | void SwBorderAttrs::CalcLeftLine_() | |||
2332 | { | |||
2333 | m_nLeftLine = m_rBox.CalcLineSpace( SvxBoxItemLine::LEFT, true); | |||
2334 | m_nLeftLine = m_nLeftLine + m_rShadow.CalcShadowSpace(SvxShadowItemSide::LEFT); | |||
2335 | m_bLeftLine = false; | |||
2336 | } | |||
2337 | ||||
2338 | void SwBorderAttrs::CalcRightLine_() | |||
2339 | { | |||
2340 | m_nRightLine = m_rBox.CalcLineSpace( SvxBoxItemLine::RIGHT, true ); | |||
2341 | m_nRightLine = m_nRightLine + m_rShadow.CalcShadowSpace(SvxShadowItemSide::RIGHT); | |||
2342 | m_bRightLine = false; | |||
2343 | } | |||
2344 | ||||
2345 | void SwBorderAttrs::IsLine_() | |||
2346 | { | |||
2347 | m_bIsLine = m_rBox.GetTop() || m_rBox.GetBottom() || | |||
2348 | m_rBox.GetLeft()|| m_rBox.GetRight(); | |||
2349 | m_bLine = false; | |||
2350 | } | |||
2351 | ||||
2352 | /* The borders of neighboring paragraphs are condensed by following algorithm: | |||
2353 | * | |||
2354 | * 1. No top border if the predecessor has the same top border and (3) applies. | |||
2355 | * In addition, the paragraph needs to have a border at least one side (left/right/bottom). | |||
2356 | * 2. No bottom border if the successor has the same bottom border and (3) applies. | |||
2357 | * In addition, the paragraph needs to have a border at least one side (left/right/top). | |||
2358 | * 3. The borders on the left and right side are identical between the current and the | |||
2359 | * pre-/succeeding paragraph. | |||
2360 | */ | |||
2361 | ||||
2362 | static bool CmpLines( const editeng::SvxBorderLine *pL1, const editeng::SvxBorderLine *pL2 ) | |||
2363 | { | |||
2364 | return ( ((pL1 && pL2) && (*pL1 == *pL2)) || (!pL1 && !pL2) ); | |||
2365 | } | |||
2366 | ||||
2367 | // OD 21.05.2003 #108789# - change name of 1st parameter - "rAttrs" -> "rCmpAttrs" | |||
2368 | // OD 21.05.2003 #108789# - compare <CalcRight()> and <rCmpAttrs.CalcRight()> | |||
2369 | // instead of only the right LR-spacing, because R2L-layout has to be | |||
2370 | // considered. | |||
2371 | bool SwBorderAttrs::CmpLeftRight( const SwBorderAttrs &rCmpAttrs, | |||
2372 | const SwFrame *pCaller, | |||
2373 | const SwFrame *pCmp ) const | |||
2374 | { | |||
2375 | return ( CmpLines( rCmpAttrs.GetBox().GetLeft(), GetBox().GetLeft() ) && | |||
2376 | CmpLines( rCmpAttrs.GetBox().GetRight(),GetBox().GetRight() ) && | |||
2377 | CalcLeft( pCaller ) == rCmpAttrs.CalcLeft( pCmp ) && | |||
2378 | // OD 21.05.2003 #108789# - compare <CalcRight> with <rCmpAttrs.CalcRight>. | |||
2379 | CalcRight( pCaller ) == rCmpAttrs.CalcRight( pCmp ) ); | |||
2380 | } | |||
2381 | ||||
2382 | bool SwBorderAttrs::JoinWithCmp( const SwFrame& _rCallerFrame, | |||
2383 | const SwFrame& _rCmpFrame ) const | |||
2384 | { | |||
2385 | bool bReturnVal = false; | |||
2386 | ||||
2387 | SwBorderAttrAccess aCmpAccess( SwFrame::GetCache(), &_rCmpFrame ); | |||
2388 | const SwBorderAttrs &rCmpAttrs = *aCmpAccess.Get(); | |||
2389 | if ( m_rShadow == rCmpAttrs.GetShadow() && | |||
2390 | CmpLines( m_rBox.GetTop(), rCmpAttrs.GetBox().GetTop() ) && | |||
2391 | CmpLines( m_rBox.GetBottom(), rCmpAttrs.GetBox().GetBottom() ) && | |||
2392 | CmpLeftRight( rCmpAttrs, &_rCallerFrame, &_rCmpFrame ) | |||
2393 | ) | |||
2394 | { | |||
2395 | bReturnVal = true; | |||
2396 | } | |||
2397 | ||||
2398 | return bReturnVal; | |||
2399 | } | |||
2400 | ||||
2401 | // OD 21.05.2003 #108789# - method to determine, if borders are joined with | |||
2402 | // previous frame. Calculated value saved in cached value <m_bJoinedWithPrev> | |||
2403 | // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrame> | |||
2404 | void SwBorderAttrs::CalcJoinedWithPrev( const SwFrame& _rFrame, | |||
2405 | const SwFrame* _pPrevFrame ) | |||
2406 | { | |||
2407 | // set default | |||
2408 | m_bJoinedWithPrev = false; | |||
2409 | ||||
2410 | if ( _rFrame.IsTextFrame() ) | |||
2411 | { | |||
2412 | // text frame can potentially join with previous text frame, if | |||
2413 | // corresponding attribute set is set at previous text frame. | |||
2414 | // OD 2004-02-26 #i25029# - If parameter <_pPrevFrame> is set, take this | |||
2415 | // one as previous frame. | |||
2416 | const SwFrame* pPrevFrame = _pPrevFrame ? _pPrevFrame : _rFrame.GetPrev(); | |||
2417 | // OD 2004-02-13 #i25029# - skip hidden text frames. | |||
2418 | while ( pPrevFrame && pPrevFrame->IsTextFrame() && | |||
2419 | static_cast<const SwTextFrame*>(pPrevFrame)->IsHiddenNow() ) | |||
2420 | { | |||
2421 | pPrevFrame = pPrevFrame->GetPrev(); | |||
2422 | } | |||
2423 | if ( pPrevFrame && pPrevFrame->IsTextFrame() && | |||
2424 | pPrevFrame->GetAttrSet()->GetParaConnectBorder().GetValue() | |||
2425 | ) | |||
2426 | { | |||
2427 | m_bJoinedWithPrev = JoinWithCmp( _rFrame, *pPrevFrame ); | |||
2428 | } | |||
2429 | } | |||
2430 | ||||
2431 | // valid cache status, if demanded | |||
2432 | // OD 2004-02-26 #i25029# - Do not validate cache, if parameter <_pPrevFrame> | |||
2433 | // is set. | |||
2434 | m_bCachedJoinedWithPrev = m_bCacheGetLine && !_pPrevFrame; | |||
2435 | } | |||
2436 | ||||
2437 | // OD 21.05.2003 #108789# - method to determine, if borders are joined with | |||
2438 | // next frame. Calculated value saved in cached value <m_bJoinedWithNext> | |||
2439 | void SwBorderAttrs::CalcJoinedWithNext( const SwFrame& _rFrame ) | |||
2440 | { | |||
2441 | // set default | |||
2442 | m_bJoinedWithNext = false; | |||
2443 | ||||
2444 | if ( _rFrame.IsTextFrame() ) | |||
2445 | { | |||
2446 | // text frame can potentially join with next text frame, if | |||
2447 | // corresponding attribute set is set at current text frame. | |||
2448 | // OD 2004-02-13 #i25029# - get next frame, but skip hidden text frames. | |||
2449 | const SwFrame* pNextFrame = _rFrame.GetNext(); | |||
2450 | while ( pNextFrame && pNextFrame->IsTextFrame() && | |||
2451 | static_cast<const SwTextFrame*>(pNextFrame)->IsHiddenNow() ) | |||
2452 | { | |||
2453 | pNextFrame = pNextFrame->GetNext(); | |||
2454 | } | |||
2455 | if ( pNextFrame && pNextFrame->IsTextFrame() && | |||
2456 | _rFrame.GetAttrSet()->GetParaConnectBorder().GetValue() | |||
2457 | ) | |||
2458 | { | |||
2459 | m_bJoinedWithNext = JoinWithCmp( _rFrame, *pNextFrame ); | |||
2460 | } | |||
2461 | } | |||
2462 | ||||
2463 | // valid cache status, if demanded | |||
2464 | m_bCachedJoinedWithNext = m_bCacheGetLine; | |||
2465 | } | |||
2466 | ||||
2467 | // OD 21.05.2003 #108789# - accessor for cached values <m_bJoinedWithPrev> | |||
2468 | // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrame>, which is passed to | |||
2469 | // method <_CalcJoindWithPrev(..)>. | |||
2470 | bool SwBorderAttrs::JoinedWithPrev( const SwFrame& _rFrame, | |||
2471 | const SwFrame* _pPrevFrame ) const | |||
2472 | { | |||
2473 | if ( !m_bCachedJoinedWithPrev || _pPrevFrame ) | |||
2474 | { | |||
2475 | // OD 2004-02-26 #i25029# - pass <_pPrevFrame> as 2nd parameter | |||
2476 | const_cast<SwBorderAttrs*>(this)->CalcJoinedWithPrev( _rFrame, _pPrevFrame ); | |||
2477 | } | |||
2478 | ||||
2479 | return m_bJoinedWithPrev; | |||
2480 | } | |||
2481 | ||||
2482 | bool SwBorderAttrs::JoinedWithNext( const SwFrame& _rFrame ) const | |||
2483 | { | |||
2484 | if ( !m_bCachedJoinedWithNext ) | |||
2485 | { | |||
2486 | const_cast<SwBorderAttrs*>(this)->CalcJoinedWithNext( _rFrame ); | |||
2487 | } | |||
2488 | ||||
2489 | return m_bJoinedWithNext; | |||
2490 | } | |||
2491 | ||||
2492 | // OD 2004-02-26 #i25029# - added 2nd parameter <_pPrevFrame>, which is passed to | |||
2493 | // method <JoinedWithPrev> | |||
2494 | void SwBorderAttrs::GetTopLine_( const SwFrame& _rFrame, | |||
2495 | const SwFrame* _pPrevFrame ) | |||
2496 | { | |||
2497 | sal_uInt16 nRet = CalcTopLine(); | |||
2498 | ||||
2499 | // OD 21.05.2003 #108789# - use new method <JoinWithPrev()> | |||
2500 | // OD 2004-02-26 #i25029# - add 2nd parameter | |||
2501 | if ( JoinedWithPrev( _rFrame, _pPrevFrame ) ) | |||
2502 | { | |||
2503 | nRet = 0; | |||
2504 | } | |||
2505 | ||||
2506 | m_bCachedGetTopLine = m_bCacheGetLine; | |||
2507 | ||||
2508 | m_nGetTopLine = nRet; | |||
2509 | } | |||
2510 | ||||
2511 | void SwBorderAttrs::GetBottomLine_( const SwFrame& _rFrame ) | |||
2512 | { | |||
2513 | sal_uInt16 nRet = CalcBottomLine(); | |||
2514 | ||||
2515 | // OD 21.05.2003 #108789# - use new method <JoinWithPrev()> | |||
2516 | if ( JoinedWithNext( _rFrame ) ) | |||
2517 | { | |||
2518 | nRet = 0; | |||
2519 | } | |||
2520 | ||||
2521 | m_bCachedGetBottomLine = m_bCacheGetLine; | |||
2522 | ||||
2523 | m_nGetBottomLine = nRet; | |||
2524 | } | |||
2525 | ||||
2526 | void SwBorderAttrs::CalcLineSpacing_() | |||
2527 | { | |||
2528 | // tdf#125300 compatibility option AddParaLineSpacingToTableCells needs also line spacing | |||
2529 | const SvxLineSpacingItem &rSpace = m_rAttrSet.GetLineSpacing(); | |||
2530 | if ( rSpace.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop && rSpace.GetPropLineSpace() > 100 ) | |||
2531 | { | |||
2532 | sal_Int32 nFontSize = m_rAttrSet.Get(RES_CHRATR_FONTSIZE).GetHeight(); | |||
2533 | m_nLineSpacing = nFontSize * (rSpace.GetPropLineSpace() - 100) * 1.15 / 100; | |||
2534 | } | |||
2535 | m_bLineSpacing = false; | |||
2536 | } | |||
2537 | ||||
2538 | static SwModify const* GetCacheOwner(SwFrame const& rFrame) | |||
2539 | { | |||
2540 | return rFrame.IsContentFrame() | |||
2541 | ? static_cast<SwModify const*>(rFrame.IsTextFrame() | |||
2542 | // sw_redlinehide: presumably this caches the border attrs at the model level and can be shared across different layouts so we want the ParaProps node here | |||
2543 | ? static_cast<const SwTextFrame&>(rFrame).GetTextNodeForParaProps() | |||
2544 | : static_cast<const SwNoTextFrame&>(rFrame).GetNode()) | |||
2545 | : static_cast<SwModify const*>(static_cast<const SwLayoutFrame&>(rFrame).GetFormat()); | |||
2546 | } | |||
2547 | ||||
2548 | SwBorderAttrAccess::SwBorderAttrAccess( SwCache &rCach, const SwFrame *pFrame ) : | |||
2549 | SwCacheAccess( rCach, | |||
2550 | static_cast<void const *>(GetCacheOwner(*pFrame)), | |||
2551 | GetCacheOwner(*pFrame)->IsInCache()), | |||
2552 | m_pConstructor( pFrame ) | |||
2553 | { | |||
2554 | } | |||
2555 | ||||
2556 | SwCacheObj *SwBorderAttrAccess::NewObj() | |||
2557 | { | |||
2558 | const_cast<SwModify *>(static_cast<SwModify const *>(m_pOwner))->SetInCache( true ); | |||
2559 | return new SwBorderAttrs( static_cast<SwModify const *>(m_pOwner), m_pConstructor ); | |||
2560 | } | |||
2561 | ||||
2562 | SwBorderAttrs *SwBorderAttrAccess::Get() | |||
2563 | { | |||
2564 | return static_cast<SwBorderAttrs*>(SwCacheAccess::Get()); | |||
2565 | } | |||
2566 | ||||
2567 | SwOrderIter::SwOrderIter( const SwPageFrame *pPg ) : | |||
2568 | m_pPage( pPg ), | |||
2569 | m_pCurrent( nullptr ) | |||
2570 | { | |||
2571 | } | |||
2572 | ||||
2573 | void SwOrderIter::Top() | |||
2574 | { | |||
2575 | m_pCurrent = nullptr; | |||
2576 | if ( !m_pPage->GetSortedObjs() ) | |||
2577 | return; | |||
2578 | ||||
2579 | const SwSortedObjs *pObjs = m_pPage->GetSortedObjs(); | |||
2580 | if ( !pObjs->size() ) | |||
2581 | return; | |||
2582 | ||||
2583 | sal_uInt32 nTopOrd = 0; | |||
2584 | (*pObjs)[0]->GetDrawObj()->GetOrdNum(); // force updating | |||
2585 | for (SwAnchoredObject* i : *pObjs) | |||
2586 | { | |||
2587 | const SdrObject* pObj = i->GetDrawObj(); | |||
2588 | if ( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) == nullptr ) | |||
2589 | continue; | |||
2590 | sal_uInt32 nTmp = pObj->GetOrdNumDirect(); | |||
2591 | if ( nTmp >= nTopOrd ) | |||
2592 | { | |||
2593 | nTopOrd = nTmp; | |||
2594 | m_pCurrent = pObj; | |||
2595 | } | |||
2596 | } | |||
2597 | } | |||
2598 | ||||
2599 | const SdrObject *SwOrderIter::Bottom() | |||
2600 | { | |||
2601 | m_pCurrent = nullptr; | |||
2602 | if ( m_pPage->GetSortedObjs() ) | |||
2603 | { | |||
2604 | sal_uInt32 nBotOrd = USHRT_MAX(32767 *2 +1); | |||
2605 | const SwSortedObjs *pObjs = m_pPage->GetSortedObjs(); | |||
2606 | if ( pObjs->size() ) | |||
2607 | { | |||
2608 | (*pObjs)[0]->GetDrawObj()->GetOrdNum(); // force updating | |||
2609 | for (SwAnchoredObject* i : *pObjs) | |||
2610 | { | |||
2611 | const SdrObject* pObj = i->GetDrawObj(); | |||
2612 | if ( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) == nullptr ) | |||
2613 | continue; | |||
2614 | sal_uInt32 nTmp = pObj->GetOrdNumDirect(); | |||
2615 | if ( nTmp < nBotOrd ) | |||
2616 | { | |||
2617 | nBotOrd = nTmp; | |||
2618 | m_pCurrent = pObj; | |||
2619 | } | |||
2620 | } | |||
2621 | } | |||
2622 | } | |||
2623 | return m_pCurrent; | |||
2624 | } | |||
2625 | ||||
2626 | const SdrObject *SwOrderIter::Next() | |||
2627 | { | |||
2628 | const sal_uInt32 nCurOrd = m_pCurrent ? m_pCurrent->GetOrdNumDirect() : 0; | |||
2629 | m_pCurrent = nullptr; | |||
2630 | if ( m_pPage->GetSortedObjs() ) | |||
2631 | { | |||
2632 | sal_uInt32 nOrd = USHRT_MAX(32767 *2 +1); | |||
2633 | const SwSortedObjs *pObjs = m_pPage->GetSortedObjs(); | |||
2634 | if ( pObjs->size() ) | |||
2635 | { | |||
2636 | (*pObjs)[0]->GetDrawObj()->GetOrdNum(); // force updating | |||
2637 | for (SwAnchoredObject* i : *pObjs) | |||
2638 | { | |||
2639 | const SdrObject* pObj = i->GetDrawObj(); | |||
2640 | if ( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) == nullptr ) | |||
2641 | continue; | |||
2642 | sal_uInt32 nTmp = pObj->GetOrdNumDirect(); | |||
2643 | if ( nTmp > nCurOrd && nTmp < nOrd ) | |||
2644 | { | |||
2645 | nOrd = nTmp; | |||
2646 | m_pCurrent = pObj; | |||
2647 | } | |||
2648 | } | |||
2649 | } | |||
2650 | } | |||
2651 | return m_pCurrent; | |||
2652 | } | |||
2653 | ||||
2654 | void SwOrderIter::Prev() | |||
2655 | { | |||
2656 | const sal_uInt32 nCurOrd = m_pCurrent ? m_pCurrent->GetOrdNumDirect() : 0; | |||
2657 | m_pCurrent = nullptr; | |||
2658 | if ( !m_pPage->GetSortedObjs() ) | |||
2659 | return; | |||
2660 | ||||
2661 | const SwSortedObjs *pObjs = m_pPage->GetSortedObjs(); | |||
2662 | if ( !pObjs->size() ) | |||
2663 | return; | |||
2664 | ||||
2665 | sal_uInt32 nOrd = 0; | |||
2666 | (*pObjs)[0]->GetDrawObj()->GetOrdNum(); // force updating | |||
2667 | for (SwAnchoredObject* i : *pObjs) | |||
2668 | { | |||
2669 | const SdrObject* pObj = i->GetDrawObj(); | |||
2670 | if ( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) == nullptr ) | |||
2671 | continue; | |||
2672 | sal_uInt32 nTmp = pObj->GetOrdNumDirect(); | |||
2673 | if ( nTmp < nCurOrd && nTmp >= nOrd ) | |||
2674 | { | |||
2675 | nOrd = nTmp; | |||
2676 | m_pCurrent = pObj; | |||
2677 | } | |||
2678 | } | |||
2679 | } | |||
2680 | ||||
2681 | /// Keep and restore the substructure of a layout frame for an action. | |||
2682 | // New algorithm: | |||
2683 | // Do not look at each neighbor one by one to set all pointers correctly. | |||
2684 | // It is sufficient to detach a part of a chain and check if another chain needs to be added | |||
2685 | // when attaching it again. Only the pointers necessary for the chain connection need to be | |||
2686 | // adjusted. The correction happens in RestoreContent(). In between all access is restricted. | |||
2687 | // During this action, the Flys are detached from the page. | |||
2688 | ||||
2689 | // #115759# - 'remove' also drawing object from page and | |||
2690 | // at-fly anchored objects from page | |||
2691 | static void lcl_RemoveObjsFromPage( SwFrame* _pFrame ) | |||
2692 | { | |||
2693 | OSL_ENSURE( _pFrame->GetDrawObjs(), "no DrawObjs in lcl_RemoveObjsFromPage." )do { if (true && (!(_pFrame->GetDrawObjs()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "2693" ": "), "%s", "no DrawObjs in lcl_RemoveObjsFromPage." ); } } while (false); | |||
2694 | SwSortedObjs &rObjs = *_pFrame->GetDrawObjs(); | |||
2695 | for (SwAnchoredObject* pObj : rObjs) | |||
2696 | { | |||
2697 | // #115759# - reset member, at which the anchored | |||
2698 | // object orients its vertical position | |||
2699 | pObj->ClearVertPosOrientFrame(); | |||
2700 | // #i43913# | |||
2701 | pObj->ResetLayoutProcessBools(); | |||
2702 | // #115759# - remove also lower objects of as-character | |||
2703 | // anchored Writer fly frames from page | |||
2704 | if ( dynamic_cast<const SwFlyFrame*>( pObj) != nullptr ) | |||
2705 | { | |||
2706 | SwFlyFrame* pFlyFrame = static_cast<SwFlyFrame*>(pObj); | |||
2707 | ||||
2708 | // #115759# - remove also direct lowers of Writer | |||
2709 | // fly frame from page | |||
2710 | if ( pFlyFrame->GetDrawObjs() ) | |||
2711 | { | |||
2712 | ::lcl_RemoveObjsFromPage( pFlyFrame ); | |||
2713 | } | |||
2714 | ||||
2715 | SwContentFrame* pCnt = pFlyFrame->ContainsContent(); | |||
2716 | while ( pCnt ) | |||
2717 | { | |||
2718 | if ( pCnt->GetDrawObjs() ) | |||
2719 | ::lcl_RemoveObjsFromPage( pCnt ); | |||
2720 | pCnt = pCnt->GetNextContentFrame(); | |||
2721 | } | |||
2722 | if ( pFlyFrame->IsFlyFreeFrame() ) | |||
2723 | { | |||
2724 | // #i28701# - use new method <GetPageFrame()> | |||
2725 | if (SwPageFrame *pPg = pFlyFrame->GetPageFrame()) | |||
2726 | pPg->RemoveFlyFromPage(pFlyFrame); | |||
2727 | } | |||
2728 | } | |||
2729 | // #115759# - remove also drawing objects from page | |||
2730 | else if ( dynamic_cast<const SwAnchoredDrawObject*>( pObj) != nullptr ) | |||
2731 | { | |||
2732 | if (pObj->GetFrameFormat().GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR) | |||
2733 | { | |||
2734 | if (SwPageFrame *pPg = pObj->GetPageFrame()) | |||
2735 | pPg->RemoveDrawObjFromPage( | |||
2736 | *static_cast<SwAnchoredDrawObject*>(pObj) ); | |||
2737 | } | |||
2738 | } | |||
2739 | } | |||
2740 | } | |||
2741 | ||||
2742 | SwFrame *SaveContent( SwLayoutFrame *pLay, SwFrame *pStart ) | |||
2743 | { | |||
2744 | if( pLay->IsSctFrame() && pLay->Lower() && pLay->Lower()->IsColumnFrame() ) | |||
2745 | sw_RemoveFootnotes( static_cast<SwColumnFrame*>(pLay->Lower()), true, true ); | |||
2746 | ||||
2747 | SwFrame *pSav = pLay->ContainsAny(); | |||
2748 | if ( nullptr == pSav ) | |||
2749 | return nullptr; | |||
2750 | ||||
2751 | if( pSav->IsInFootnote() && !pLay->IsInFootnote() ) | |||
2752 | { | |||
2753 | do | |||
2754 | pSav = pSav->FindNext(); | |||
2755 | while( pSav && pSav->IsInFootnote() ); | |||
2756 | if( !pSav || !pLay->IsAnLower( pSav ) ) | |||
2757 | return nullptr; | |||
2758 | } | |||
2759 | ||||
2760 | // Tables should be saved as a whole, exception: | |||
2761 | // The contents of a section or a cell inside a table should be saved | |||
2762 | if ( pSav->IsInTab() && !( ( pLay->IsSctFrame() || pLay->IsCellFrame() ) && pLay->IsInTab() ) ) | |||
2763 | while ( !pSav->IsTabFrame() ) | |||
2764 | pSav = pSav->GetUpper(); | |||
2765 | ||||
2766 | if( pSav->IsInSct() ) | |||
2767 | { // search the upmost section inside of pLay | |||
2768 | SwFrame* pSect = pLay->FindSctFrame(); | |||
2769 | SwFrame *pTmp = pSav; | |||
2770 | do | |||
2771 | { | |||
2772 | pSav = pTmp; | |||
2773 | pTmp = (pSav && pSav->GetUpper()) ? pSav->GetUpper()->FindSctFrame() : nullptr; | |||
2774 | } while ( pTmp != pSect ); | |||
2775 | } | |||
2776 | ||||
2777 | SwFrame *pFloat = pSav; | |||
2778 | if( !pStart ) | |||
2779 | pStart = pSav; | |||
2780 | bool bGo = pStart == pSav; | |||
2781 | do | |||
2782 | { | |||
2783 | if( bGo ) | |||
2784 | pFloat->GetUpper()->m_pLower = nullptr; // detach the chain part | |||
2785 | ||||
2786 | // search the end of the chain part, remove Flys on the way | |||
2787 | do | |||
2788 | { | |||
2789 | if( bGo ) | |||
2790 | { | |||
2791 | if ( pFloat->IsContentFrame() ) | |||
2792 | { | |||
2793 | if ( pFloat->GetDrawObjs() ) | |||
2794 | ::lcl_RemoveObjsFromPage( static_cast<SwContentFrame*>(pFloat) ); | |||
2795 | } | |||
2796 | else if ( pFloat->IsTabFrame() || pFloat->IsSctFrame() ) | |||
2797 | { | |||
2798 | SwContentFrame *pCnt = static_cast<SwLayoutFrame*>(pFloat)->ContainsContent(); | |||
2799 | if( pCnt ) | |||
2800 | { | |||
2801 | do | |||
2802 | { if ( pCnt->GetDrawObjs() ) | |||
2803 | ::lcl_RemoveObjsFromPage( pCnt ); | |||
2804 | pCnt = pCnt->GetNextContentFrame(); | |||
2805 | } while ( pCnt && static_cast<SwLayoutFrame*>(pFloat)->IsAnLower( pCnt ) ); | |||
2806 | } | |||
2807 | } | |||
2808 | else { | |||
2809 | OSL_ENSURE( !pFloat, "new FloatFrame?" )do { if (true && (!(!pFloat))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "2809" ": "), "%s", "new FloatFrame?"); } } while (false ); | |||
2810 | } | |||
2811 | } | |||
2812 | if ( pFloat->GetNext() ) | |||
2813 | { | |||
2814 | if( bGo ) | |||
2815 | pFloat->mpUpper = nullptr; | |||
2816 | pFloat = pFloat->GetNext(); | |||
2817 | if( !bGo && pFloat == pStart ) | |||
2818 | { | |||
2819 | bGo = true; | |||
2820 | pFloat->mpPrev->mpNext = nullptr; | |||
2821 | pFloat->mpPrev = nullptr; | |||
2822 | } | |||
2823 | } | |||
2824 | else | |||
2825 | break; | |||
2826 | ||||
2827 | } while ( pFloat ); | |||
2828 | ||||
2829 | // search next chain part and connect both chains | |||
2830 | SwFrame *pTmp = pFloat->FindNext(); | |||
2831 | if( bGo ) | |||
2832 | pFloat->mpUpper = nullptr; | |||
2833 | ||||
2834 | if( !pLay->IsInFootnote() ) | |||
2835 | while( pTmp && pTmp->IsInFootnote() ) | |||
2836 | pTmp = pTmp->FindNext(); | |||
2837 | ||||
2838 | if ( !pLay->IsAnLower( pTmp ) ) | |||
2839 | pTmp = nullptr; | |||
2840 | ||||
2841 | if ( pTmp && bGo ) | |||
2842 | { | |||
2843 | pFloat->mpNext = pTmp; // connect both chains | |||
2844 | pFloat->mpNext->mpPrev = pFloat; | |||
2845 | } | |||
2846 | pFloat = pTmp; | |||
2847 | bGo = bGo || ( pStart == pFloat ); | |||
2848 | } while ( pFloat ); | |||
2849 | ||||
2850 | return bGo ? pStart : nullptr; | |||
2851 | } | |||
2852 | ||||
2853 | // #115759# - add also drawing objects to page and at-fly | |||
2854 | // anchored objects to page | |||
2855 | static void lcl_AddObjsToPage( SwFrame* _pFrame, SwPageFrame* _pPage ) | |||
2856 | { | |||
2857 | OSL_ENSURE( _pFrame->GetDrawObjs(), "no DrawObjs in lcl_AddObjsToPage." )do { if (true && (!(_pFrame->GetDrawObjs()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "2857" ": "), "%s", "no DrawObjs in lcl_AddObjsToPage.") ; } } while (false); | |||
2858 | SwSortedObjs &rObjs = *_pFrame->GetDrawObjs(); | |||
2859 | for (SwAnchoredObject* pObj : rObjs) | |||
2860 | { | |||
2861 | // #115759# - unlock position of anchored object | |||
2862 | // in order to get the object's position calculated. | |||
2863 | pObj->UnlockPosition(); | |||
2864 | // #115759# - add also lower objects of as-character | |||
2865 | // anchored Writer fly frames from page | |||
2866 | if ( dynamic_cast<const SwFlyFrame*>( pObj) != nullptr ) | |||
2867 | { | |||
2868 | SwFlyFrame* pFlyFrame = static_cast<SwFlyFrame*>(pObj); | |||
2869 | if ( dynamic_cast<const SwFlyFreeFrame*>( pObj) != nullptr ) | |||
2870 | { | |||
2871 | _pPage->AppendFlyToPage( pFlyFrame ); | |||
2872 | } | |||
2873 | pFlyFrame->InvalidatePos_(); | |||
2874 | pFlyFrame->InvalidateSize_(); | |||
2875 | pFlyFrame->InvalidatePage( _pPage ); | |||
2876 | ||||
2877 | // #115759# - add also at-fly anchored objects | |||
2878 | // to page | |||
2879 | if ( pFlyFrame->GetDrawObjs() ) | |||
2880 | { | |||
2881 | ::lcl_AddObjsToPage( pFlyFrame, _pPage ); | |||
2882 | } | |||
2883 | ||||
2884 | SwContentFrame *pCnt = pFlyFrame->ContainsContent(); | |||
2885 | while ( pCnt ) | |||
2886 | { | |||
2887 | if ( pCnt->GetDrawObjs() ) | |||
2888 | ::lcl_AddObjsToPage( pCnt, _pPage ); | |||
2889 | pCnt = pCnt->GetNextContentFrame(); | |||
2890 | } | |||
2891 | } | |||
2892 | // #115759# - remove also drawing objects from page | |||
2893 | else if ( dynamic_cast<const SwAnchoredDrawObject*>( pObj) != nullptr ) | |||
2894 | { | |||
2895 | if (pObj->GetFrameFormat().GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR) | |||
2896 | { | |||
2897 | pObj->InvalidateObjPos(); | |||
2898 | _pPage->AppendDrawObjToPage( | |||
2899 | *static_cast<SwAnchoredDrawObject*>(pObj) ); | |||
2900 | } | |||
2901 | } | |||
2902 | } | |||
2903 | } | |||
2904 | ||||
2905 | void RestoreContent( SwFrame *pSav, SwLayoutFrame *pParent, SwFrame *pSibling ) | |||
2906 | { | |||
2907 | OSL_ENSURE( pSav && pParent, "no Save or Parent provided for RestoreContent." )do { if (true && (!(pSav && pParent))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "2907" ": "), "%s", "no Save or Parent provided for RestoreContent." ); } } while (false); | |||
2908 | SwRectFnSet aRectFnSet(pParent); | |||
2909 | ||||
2910 | // If there are already FlowFrames below the new parent, so add the chain (starting with pSav) | |||
2911 | // after the last one. The parts are inserted and invalidated if needed. | |||
2912 | // On the way, the Flys of the ContentFrames are registered at the page. | |||
2913 | ||||
2914 | SwPageFrame *pPage = pParent->FindPageFrame(); | |||
2915 | ||||
2916 | if ( pPage ) | |||
2917 | pPage->InvalidatePage( pPage ); | |||
2918 | ||||
2919 | // determine predecessor and establish connection or initialize | |||
2920 | pSav->mpPrev = pSibling; | |||
2921 | SwFrame* pNxt; | |||
2922 | if ( pSibling ) | |||
2923 | { | |||
2924 | pNxt = pSibling->mpNext; | |||
2925 | pSibling->mpNext = pSav; | |||
2926 | pSibling->InvalidatePrt_(); | |||
2927 | pSibling->InvalidatePage( pPage ); | |||
2928 | SwFlowFrame *pFlowFrame = dynamic_cast<SwFlowFrame*>(pSibling); | |||
2929 | if (pFlowFrame && pFlowFrame->GetFollow()) | |||
2930 | pSibling->Prepare( PrepareHint::Clear, nullptr, false ); | |||
2931 | } | |||
2932 | else | |||
2933 | { pNxt = pParent->m_pLower; | |||
2934 | pParent->m_pLower = pSav; | |||
2935 | pSav->mpUpper = pParent; // set here already, so that it is explicit when invalidating | |||
2936 | ||||
2937 | if ( pSav->IsContentFrame() ) | |||
2938 | static_cast<SwContentFrame*>(pSav)->InvalidatePage( pPage ); | |||
2939 | else | |||
2940 | { // pSav might be an empty SectFrame | |||
2941 | SwContentFrame* pCnt = pParent->ContainsContent(); | |||
2942 | if( pCnt ) | |||
2943 | pCnt->InvalidatePage( pPage ); | |||
2944 | } | |||
2945 | } | |||
2946 | ||||
2947 | // the parent needs to grow appropriately | |||
2948 | SwTwips nGrowVal = 0; | |||
2949 | SwFrame* pLast; | |||
2950 | do | |||
2951 | { pSav->mpUpper = pParent; | |||
2952 | nGrowVal += aRectFnSet.GetHeight(pSav->getFrameArea()); | |||
2953 | pSav->InvalidateAll_(); | |||
2954 | ||||
2955 | // register Flys, if TextFrames than also invalidate appropriately | |||
2956 | if ( pSav->IsContentFrame() ) | |||
2957 | { | |||
2958 | if ( pSav->IsTextFrame() && | |||
2959 | static_cast<SwTextFrame*>(pSav)->GetCacheIdx() != USHRT_MAX(32767 *2 +1) ) | |||
2960 | static_cast<SwTextFrame*>(pSav)->Init(); // I am its friend | |||
2961 | ||||
2962 | if ( pPage && pSav->GetDrawObjs() ) | |||
2963 | ::lcl_AddObjsToPage( static_cast<SwContentFrame*>(pSav), pPage ); | |||
2964 | } | |||
2965 | else | |||
2966 | { SwContentFrame *pBlub = static_cast<SwLayoutFrame*>(pSav)->ContainsContent(); | |||
2967 | if( pBlub ) | |||
2968 | { | |||
2969 | do | |||
2970 | { if ( pPage && pBlub->GetDrawObjs() ) | |||
2971 | ::lcl_AddObjsToPage( pBlub, pPage ); | |||
2972 | if( pBlub->IsTextFrame() && static_cast<SwTextFrame*>(pBlub)->HasFootnote() && | |||
2973 | static_cast<SwTextFrame*>(pBlub)->GetCacheIdx() != USHRT_MAX(32767 *2 +1) ) | |||
2974 | static_cast<SwTextFrame*>(pBlub)->Init(); // I am its friend | |||
2975 | pBlub = pBlub->GetNextContentFrame(); | |||
2976 | } while ( pBlub && static_cast<SwLayoutFrame*>(pSav)->IsAnLower( pBlub )); | |||
2977 | } | |||
2978 | } | |||
2979 | pLast = pSav; | |||
2980 | pSav = pSav->GetNext(); | |||
2981 | ||||
2982 | } while ( pSav ); | |||
2983 | ||||
2984 | if( pNxt ) | |||
2985 | { | |||
2986 | pLast->mpNext = pNxt; | |||
2987 | pNxt->mpPrev = pLast; | |||
2988 | } | |||
2989 | ||||
2990 | pParent->Grow( nGrowVal ); | |||
2991 | } | |||
2992 | ||||
2993 | namespace sw { | |||
2994 | ||||
2995 | bool IsRightPageByNumber(SwRootFrame const& rLayout, sal_uInt16 const nPageNum) | |||
2996 | { | |||
2997 | assert(rLayout.GetLower())(static_cast <bool> (rLayout.GetLower()) ? void (0) : __assert_fail ("rLayout.GetLower()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 2997, __extension__ __PRETTY_FUNCTION__)); | |||
2998 | // unfortunately can only get SwPageDesc, not SwFormatPageDesc here... | |||
2999 | auto const nFirstVirtPageNum(rLayout.GetLower()->GetVirtPageNum()); | |||
3000 | bool const isFirstPageOfLayoutOdd(nFirstVirtPageNum % 2 == 1); | |||
3001 | return ((nPageNum % 2) == 1) == isFirstPageOfLayoutOdd; | |||
3002 | } | |||
3003 | ||||
3004 | } // namespace sw | |||
3005 | ||||
3006 | SwPageFrame * InsertNewPage( SwPageDesc &rDesc, SwFrame *pUpper, | |||
3007 | bool const isRightPage, bool const bFirst, bool bInsertEmpty, | |||
3008 | bool const bFootnote, | |||
3009 | SwFrame *pSibling, | |||
3010 | bool const bVeryFirstPage ) | |||
3011 | { | |||
3012 | assert(pUpper)(static_cast <bool> (pUpper) ? void (0) : __assert_fail ("pUpper", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 3012, __extension__ __PRETTY_FUNCTION__)); | |||
3013 | assert(pUpper->IsRootFrame())(static_cast <bool> (pUpper->IsRootFrame()) ? void ( 0) : __assert_fail ("pUpper->IsRootFrame()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 3013, __extension__ __PRETTY_FUNCTION__)); | |||
3014 | assert(!pSibling || static_cast<SwLayoutFrame const*>(pUpper)->Lower() != pSibling)(static_cast <bool> (!pSibling || static_cast<SwLayoutFrame const*>(pUpper)->Lower() != pSibling) ? void (0) : __assert_fail ("!pSibling || static_cast<SwLayoutFrame const*>(pUpper)->Lower() != pSibling" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" , 3014, __extension__ __PRETTY_FUNCTION__)); // currently no insert before 1st page | |||
3015 | SwPageFrame *pRet; | |||
3016 | SwDoc *pDoc = static_cast<SwLayoutFrame*>(pUpper)->GetFormat()->GetDoc(); | |||
3017 | if (bFirst) | |||
3018 | { | |||
3019 | if (rDesc.IsFirstShared()) | |||
3020 | { | |||
3021 | // We need to fallback to left or right page format, decide it now. | |||
3022 | // FIXME: is this still needed? | |||
3023 | if (isRightPage) | |||
3024 | { | |||
3025 | rDesc.GetFirstMaster().SetFormatAttr( rDesc.GetMaster().GetHeader() ); | |||
3026 | rDesc.GetFirstMaster().SetFormatAttr( rDesc.GetMaster().GetFooter() ); | |||
3027 | // fdo#60250 copy margins for mirrored pages | |||
3028 | rDesc.GetFirstMaster().SetFormatAttr( rDesc.GetMaster().GetLRSpace() ); | |||
3029 | } | |||
3030 | else | |||
3031 | { | |||
3032 | rDesc.GetFirstLeft().SetFormatAttr( rDesc.GetLeft().GetHeader() ); | |||
3033 | rDesc.GetFirstLeft().SetFormatAttr( rDesc.GetLeft().GetFooter() ); | |||
3034 | rDesc.GetFirstLeft().SetFormatAttr( rDesc.GetLeft().GetLRSpace() ); | |||
3035 | } | |||
3036 | } | |||
3037 | } | |||
3038 | SwFrameFormat *pFormat(isRightPage ? rDesc.GetRightFormat(bFirst) : rDesc.GetLeftFormat(bFirst)); | |||
3039 | // If there is no FrameFormat for this page, add an empty page | |||
3040 | if ( !pFormat ) | |||
3041 | { | |||
3042 | pFormat = isRightPage ? rDesc.GetLeftFormat(bVeryFirstPage) : rDesc.GetRightFormat(bVeryFirstPage); | |||
3043 | OSL_ENSURE( pFormat, "Descriptor without any format?!" )do { if (true && (!(pFormat))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "3043" ": "), "%s", "Descriptor without any format?!"); } } while (false); | |||
3044 | bInsertEmpty = !bInsertEmpty; | |||
3045 | } | |||
3046 | if( bInsertEmpty ) | |||
3047 | { | |||
3048 | SwPageDesc *pTmpDesc = pSibling && pSibling->GetPrev() ? | |||
3049 | static_cast<SwPageFrame*>(pSibling->GetPrev())->GetPageDesc() : &rDesc; | |||
3050 | pRet = new SwPageFrame( pDoc->GetEmptyPageFormat(), pUpper, pTmpDesc ); | |||
3051 | SAL_INFO( "sw.pageframe", "InsertNewPage - insert empty p: " << pRet << " d: " << pTmpDesc )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "sw.pageframe")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "InsertNewPage - insert empty p: " << pRet << " d: " << pTmpDesc) == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "3051" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "InsertNewPage - insert empty p: " << pRet << " d: " << pTmpDesc), 0); } else { ::std:: ostringstream sal_detail_stream; sal_detail_stream << "InsertNewPage - insert empty p: " << pRet << " d: " << pTmpDesc; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "3051" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "InsertNewPage - insert empty p: " << pRet << " d: " << pTmpDesc) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.pageframe"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "3051" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "InsertNewPage - insert empty p: " << pRet << " d: " << pTmpDesc), 0); } else { ::std:: ostringstream sal_detail_stream; sal_detail_stream << "InsertNewPage - insert empty p: " << pRet << " d: " << pTmpDesc; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "3051" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
3052 | pRet->Paste( pUpper, pSibling ); | |||
3053 | pRet->PreparePage( bFootnote ); | |||
3054 | } | |||
3055 | pRet = new SwPageFrame( pFormat, pUpper, &rDesc ); | |||
3056 | SAL_INFO( "sw.pageframe", "InsertNewPage p: " << pRet << " d: " << &rDesc << " f: " << pFormat )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "sw.pageframe")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "InsertNewPage p: " << pRet << " d: " << &rDesc << " f: " << pFormat) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.pageframe"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "3056" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "InsertNewPage p: " << pRet << " d: " << &rDesc << " f: " << pFormat) , 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "InsertNewPage p: " << pRet << " d: " << &rDesc << " f: " << pFormat; ::sal::detail:: log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "3056" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "InsertNewPage p: " << pRet << " d: " << &rDesc << " f: " << pFormat) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "3056" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "InsertNewPage p: " << pRet << " d: " << &rDesc << " f: " << pFormat) , 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "InsertNewPage p: " << pRet << " d: " << &rDesc << " f: " << pFormat; ::sal::detail:: log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.pageframe"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "3056" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
3057 | pRet->Paste( pUpper, pSibling ); | |||
3058 | pRet->PreparePage( bFootnote ); | |||
3059 | if ( pRet->GetNext() ) | |||
3060 | SwRootFrame::AssertPageFlys( pRet ); | |||
3061 | return pRet; | |||
3062 | } | |||
3063 | ||||
3064 | /* The following two methods search the layout structure recursively and | |||
3065 | * register all Flys at the page that have a Frame in this structure as an anchor. | |||
3066 | */ | |||
3067 | ||||
3068 | static void lcl_Regist( SwPageFrame *pPage, const SwFrame *pAnch ) | |||
3069 | { | |||
3070 | SwSortedObjs *pObjs = const_cast<SwSortedObjs*>(pAnch->GetDrawObjs()); | |||
3071 | for (SwAnchoredObject* pObj : *pObjs) | |||
3072 | { | |||
3073 | if (SwFlyFrame* pFly = dynamic_cast<SwFlyFrame*>(pObj)) | |||
3074 | { | |||
3075 | // register (not if already known) | |||
3076 | // #i28701# - use new method <GetPageFrame()> | |||
3077 | SwPageFrame *pPg = pFly->IsFlyFreeFrame() | |||
3078 | ? pFly->GetPageFrame() : pFly->FindPageFrame(); | |||
3079 | if ( pPg != pPage ) | |||
3080 | { | |||
3081 | if ( pPg ) | |||
3082 | pPg->RemoveFlyFromPage( pFly ); | |||
3083 | pPage->AppendFlyToPage( pFly ); | |||
3084 | } | |||
3085 | ::RegistFlys( pPage, pFly ); | |||
3086 | } | |||
3087 | else | |||
3088 | { | |||
3089 | // #i87493# | |||
3090 | if ( pPage != pObj->GetPageFrame() ) | |||
3091 | { | |||
3092 | // #i28701# | |||
3093 | if (SwPageFrame *pPg = pObj->GetPageFrame()) | |||
3094 | pPg->RemoveDrawObjFromPage( *pObj ); | |||
3095 | pPage->AppendDrawObjToPage( *pObj ); | |||
3096 | } | |||
3097 | } | |||
3098 | ||||
3099 | const SwFlyFrame* pFly = pAnch->FindFlyFrame(); | |||
3100 | if ( pFly && | |||
3101 | pObj->GetDrawObj()->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() && | |||
3102 | pObj->GetDrawObj()->getSdrPageFromSdrObject() ) | |||
3103 | { | |||
3104 | //#i119945# set pFly's OrdNum to pObj's. So when pFly is removed by Undo, the original OrdNum will not be changed. | |||
3105 | pObj->DrawObj()->getSdrPageFromSdrObject()->SetObjectOrdNum( pFly->GetVirtDrawObj()->GetOrdNumDirect(), | |||
3106 | pObj->GetDrawObj()->GetOrdNumDirect() ); | |||
3107 | } | |||
3108 | } | |||
3109 | } | |||
3110 | ||||
3111 | void RegistFlys( SwPageFrame *pPage, const SwLayoutFrame *pLay ) | |||
3112 | { | |||
3113 | if ( pLay->GetDrawObjs() ) | |||
3114 | ::lcl_Regist( pPage, pLay ); | |||
3115 | const SwFrame *pFrame = pLay->Lower(); | |||
3116 | while ( pFrame ) | |||
3117 | { | |||
3118 | if ( pFrame->IsLayoutFrame() ) | |||
3119 | ::RegistFlys( pPage, static_cast<const SwLayoutFrame*>(pFrame) ); | |||
3120 | else if ( pFrame->GetDrawObjs() ) | |||
3121 | ::lcl_Regist( pPage, pFrame ); | |||
3122 | pFrame = pFrame->GetNext(); | |||
3123 | } | |||
3124 | } | |||
3125 | ||||
3126 | /// Notify the background based on the difference between old and new rectangle | |||
3127 | void Notify( SwFlyFrame *pFly, SwPageFrame *pOld, const SwRect &rOld, | |||
3128 | const SwRect* pOldPrt ) | |||
3129 | { | |||
3130 | const SwRect aFrame( pFly->GetObjRectWithSpaces() ); | |||
3131 | if ( rOld.Pos() != aFrame.Pos() ) | |||
3132 | { // changed position, invalidate old and new area | |||
3133 | if ( rOld.HasArea() && | |||
3134 | rOld.Left()+pFly->GetFormat()->GetLRSpace().GetLeft() < FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) ) | |||
3135 | { | |||
3136 | pFly->NotifyBackground( pOld, rOld, PrepareHint::FlyFrameLeave ); | |||
3137 | } | |||
3138 | pFly->NotifyBackground( pFly->FindPageFrame(), aFrame, PrepareHint::FlyFrameArrive ); | |||
3139 | } | |||
3140 | else if ( rOld.SSize() != aFrame.SSize() ) | |||
3141 | { // changed size, invalidate the area that was left or is now overlapped | |||
3142 | // For simplicity, we purposely invalidate a Twip even if not needed. | |||
3143 | ||||
3144 | SwViewShell *pSh = pFly->getRootFrame()->GetCurrShell(); | |||
3145 | if( pSh && rOld.HasArea() ) | |||
3146 | pSh->InvalidateWindows( rOld ); | |||
3147 | ||||
3148 | // #i51941# - consider case that fly frame isn't | |||
3149 | // registered at the old page <pOld> | |||
3150 | SwPageFrame* pPageFrame = pFly->FindPageFrame(); | |||
3151 | if ( pOld != pPageFrame ) | |||
3152 | { | |||
3153 | pFly->NotifyBackground( pPageFrame, aFrame, PrepareHint::FlyFrameArrive ); | |||
3154 | } | |||
3155 | ||||
3156 | if ( rOld.Left() != aFrame.Left() ) | |||
3157 | { | |||
3158 | SwRect aTmp( rOld ); | |||
3159 | aTmp.Union( aFrame ); | |||
3160 | aTmp.Left( std::min(aFrame.Left(), rOld.Left()) ); | |||
3161 | aTmp.Right( std::max(aFrame.Left(), rOld.Left()) ); | |||
3162 | pFly->NotifyBackground( pOld, aTmp, PrepareHint::FlyFrameSizeChanged ); | |||
3163 | } | |||
3164 | SwTwips nOld = rOld.Right(); | |||
3165 | SwTwips nNew = aFrame.Right(); | |||
3166 | if ( nOld != nNew ) | |||
3167 | { | |||
3168 | SwRect aTmp( rOld ); | |||
3169 | aTmp.Union( aFrame ); | |||
3170 | aTmp.Left( std::min(nNew, nOld) ); | |||
3171 | aTmp.Right( std::max(nNew, nOld) ); | |||
3172 | pFly->NotifyBackground( pOld, aTmp, PrepareHint::FlyFrameSizeChanged ); | |||
3173 | } | |||
3174 | if ( rOld.Top() != aFrame.Top() ) | |||
3175 | { | |||
3176 | SwRect aTmp( rOld ); | |||
3177 | aTmp.Union( aFrame ); | |||
3178 | aTmp.Top( std::min(aFrame.Top(), rOld.Top()) ); | |||
3179 | aTmp.Bottom( std::max(aFrame.Top(), rOld.Top()) ); | |||
3180 | pFly->NotifyBackground( pOld, aTmp, PrepareHint::FlyFrameSizeChanged ); | |||
3181 | } | |||
3182 | nOld = rOld.Bottom(); | |||
3183 | nNew = aFrame.Bottom(); | |||
3184 | if ( nOld != nNew ) | |||
3185 | { | |||
3186 | SwRect aTmp( rOld ); | |||
3187 | aTmp.Union( aFrame ); | |||
3188 | aTmp.Top( std::min(nNew, nOld) ); | |||
3189 | aTmp.Bottom( std::max(nNew, nOld) ); | |||
3190 | pFly->NotifyBackground( pOld, aTmp, PrepareHint::FlyFrameSizeChanged ); | |||
3191 | } | |||
3192 | } | |||
3193 | else if(pOldPrt && *pOldPrt != pFly->getFramePrintArea()) | |||
3194 | { | |||
3195 | bool bNotifyBackground(pFly->GetFormat()->GetSurround().IsContour()); | |||
3196 | ||||
3197 | if(!bNotifyBackground && | |||
3198 | pFly->IsFlyFreeFrame() && | |||
3199 | static_cast< const SwFlyFreeFrame* >(pFly)->supportsAutoContour()) | |||
3200 | { | |||
3201 | // RotateFlyFrame3: Also notify for FlyFrames which allow AutoContour | |||
3202 | bNotifyBackground = true; | |||
3203 | } | |||
3204 | ||||
3205 | if(bNotifyBackground) | |||
3206 | { | |||
3207 | // #i24097# | |||
3208 | pFly->NotifyBackground( pFly->FindPageFrame(), aFrame, PrepareHint::FlyFrameArrive ); | |||
3209 | } | |||
3210 | } | |||
3211 | } | |||
3212 | ||||
3213 | static void lcl_CheckFlowBack( SwFrame* pFrame, const SwRect &rRect ) | |||
3214 | { | |||
3215 | SwTwips nBottom = rRect.Bottom(); | |||
3216 | while( pFrame ) | |||
3217 | { | |||
3218 | if( pFrame->IsLayoutFrame() ) | |||
3219 | { | |||
3220 | if( rRect.IsOver( pFrame->getFrameArea() ) ) | |||
3221 | lcl_CheckFlowBack( static_cast<SwLayoutFrame*>(pFrame)->Lower(), rRect ); | |||
3222 | } | |||
3223 | else if( !pFrame->GetNext() && nBottom > pFrame->getFrameArea().Bottom() ) | |||
3224 | { | |||
3225 | if( pFrame->IsContentFrame() && static_cast<SwContentFrame*>(pFrame)->HasFollow() ) | |||
3226 | pFrame->InvalidateSize(); | |||
3227 | else | |||
3228 | pFrame->InvalidateNextPos(); | |||
3229 | } | |||
3230 | pFrame = pFrame->GetNext(); | |||
3231 | } | |||
3232 | } | |||
3233 | ||||
3234 | static void lcl_NotifyContent( const SdrObject *pThis, SwContentFrame *pCnt, | |||
3235 | const SwRect &rRect, const PrepareHint eHint ) | |||
3236 | { | |||
3237 | if ( !pCnt->IsTextFrame() ) | |||
3238 | return; | |||
3239 | ||||
3240 | SwRect aCntPrt( pCnt->getFramePrintArea() ); | |||
3241 | aCntPrt.Pos() += pCnt->getFrameArea().Pos(); | |||
3242 | if ( eHint == PrepareHint::FlyFrameAttributesChanged ) | |||
3243 | { | |||
3244 | // #i35640# - use given rectangle <rRect> instead | |||
3245 | // of current bound rectangle | |||
3246 | if ( aCntPrt.IsOver( rRect ) ) | |||
3247 | pCnt->Prepare( PrepareHint::FlyFrameAttributesChanged ); | |||
3248 | } | |||
3249 | // #i23129# - only invalidate, if the text frame | |||
3250 | // printing area overlaps with the given rectangle. | |||
3251 | else if ( aCntPrt.IsOver( rRect ) ) | |||
3252 | pCnt->Prepare( eHint, static_cast<void*>(&aCntPrt.Intersection_( rRect )) ); | |||
3253 | if ( !pCnt->GetDrawObjs() ) | |||
3254 | return; | |||
3255 | ||||
3256 | const SwSortedObjs &rObjs = *pCnt->GetDrawObjs(); | |||
3257 | for (SwAnchoredObject* pObj : rObjs) | |||
3258 | { | |||
3259 | if ( dynamic_cast<const SwFlyFrame*>( pObj) != nullptr ) | |||
3260 | { | |||
3261 | SwFlyFrame *pFly = static_cast<SwFlyFrame*>(pObj); | |||
3262 | if ( pFly->IsFlyInContentFrame() ) | |||
3263 | { | |||
3264 | SwContentFrame *pContent = pFly->ContainsContent(); | |||
3265 | while ( pContent ) | |||
3266 | { | |||
3267 | ::lcl_NotifyContent( pThis, pContent, rRect, eHint ); | |||
3268 | pContent = pContent->GetNextContentFrame(); | |||
3269 | } | |||
3270 | } | |||
3271 | } | |||
3272 | } | |||
3273 | } | |||
3274 | ||||
3275 | void Notify_Background( const SdrObject* pObj, | |||
3276 | SwPageFrame* pPage, | |||
3277 | const SwRect& rRect, | |||
3278 | const PrepareHint eHint, | |||
3279 | const bool bInva ) | |||
3280 | { | |||
3281 | // If the frame was positioned correctly for the first time, do not inform the old area | |||
3282 | if ( eHint == PrepareHint::FlyFrameLeave && rRect.Top() == FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) ) | |||
3283 | return; | |||
3284 | ||||
3285 | SwLayoutFrame* pArea; | |||
3286 | SwFlyFrame *pFlyFrame = nullptr; | |||
3287 | SwFrame* pAnchor; | |||
3288 | if( auto pVirtFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>( pObj) ) | |||
3289 | { | |||
3290 | pFlyFrame = const_cast<SwVirtFlyDrawObj*>(pVirtFlyDrawObj)->GetFlyFrame(); | |||
3291 | pAnchor = pFlyFrame->AnchorFrame(); | |||
3292 | } | |||
3293 | else | |||
3294 | { | |||
3295 | pFlyFrame = nullptr; | |||
3296 | pAnchor = const_cast<SwFrame*>( | |||
3297 | GetUserCall(pObj)->GetAnchoredObj( pObj )->GetAnchorFrame() ); | |||
3298 | } | |||
3299 | if( PrepareHint::FlyFrameLeave != eHint && pAnchor->IsInFly() ) | |||
3300 | pArea = pAnchor->FindFlyFrame(); | |||
3301 | else | |||
3302 | pArea = pPage; | |||
3303 | SwContentFrame *pCnt = nullptr; | |||
3304 | if ( pArea ) | |||
3305 | { | |||
3306 | if( PrepareHint::FlyFrameArrive != eHint ) | |||
3307 | lcl_CheckFlowBack( pArea, rRect ); | |||
3308 | ||||
3309 | // Only the Flys following this anchor are reacting. Thus, those do not | |||
3310 | // need to be processed. | |||
3311 | // An exception is LEAVE, since the Fly might come "from above". | |||
3312 | // If the anchor is positioned on the previous page, the whole page | |||
3313 | // needs to be processed (47722). | |||
3314 | // OD 2004-05-13 #i28701# - If the wrapping style has to be considered | |||
3315 | // on the object positioning, the complete area has to be processed, | |||
3316 | // because content frames before the anchor frame also have to consider | |||
3317 | // the object for the text wrapping. | |||
3318 | // #i3317# - The complete area has always been | |||
3319 | // processed. | |||
3320 | { | |||
3321 | pCnt = pArea->ContainsContent(); | |||
3322 | } | |||
3323 | } | |||
3324 | SwFrame *pLastTab = nullptr; | |||
3325 | ||||
3326 | bool isValidTableBeforeAnchor(false); | |||
3327 | while ( pCnt && pArea && pArea->IsAnLower( pCnt ) ) | |||
3328 | { | |||
3329 | ::lcl_NotifyContent( pObj, pCnt, rRect, eHint ); | |||
3330 | if ( pCnt->IsInTab() ) | |||
3331 | { | |||
3332 | SwTabFrame *pTab = pCnt->FindTabFrame(); | |||
3333 | if ( pTab != pLastTab ) | |||
3334 | { | |||
3335 | pLastTab = pTab; | |||
3336 | isValidTableBeforeAnchor = false; | |||
3337 | if (PrepareHint::FlyFrameArrive == eHint | |||
3338 | && pFlyFrame // TODO: do it for draw objects too? | |||
3339 | && pTab->IsFollow() // table starts on previous page? | |||
3340 | // "through" means they will actually overlap anyway | |||
3341 | && css::text::WrapTextMode_THROUGH != pFlyFrame->GetFormat()->GetSurround().GetSurround() | |||
3342 | // if it's anchored in footer it can't move to other page | |||
3343 | && !pAnchor->FindFooterOrHeader()) | |||
3344 | { | |||
3345 | SwFrame * pTmp(pAnchor->GetPrev()); | |||
3346 | while (pTmp) | |||
3347 | { | |||
3348 | if (pTmp == pTab) | |||
3349 | { | |||
3350 | // tdf#99460 the table shouldn't be moved by the fly | |||
3351 | isValidTableBeforeAnchor = true; | |||
3352 | break; | |||
3353 | } | |||
3354 | pTmp = pTmp->GetPrev(); | |||
3355 | } | |||
3356 | } | |||
3357 | // #i40606# - use <GetLastBoundRect()> | |||
3358 | // instead of <GetCurrentBoundRect()>, because a recalculation | |||
3359 | // of the bounding rectangle isn't intended here. | |||
3360 | if (!isValidTableBeforeAnchor | |||
3361 | && (pTab->getFrameArea().IsOver(pObj->GetLastBoundRect()) || | |||
3362 | pTab->getFrameArea().IsOver(rRect))) | |||
3363 | { | |||
3364 | if ( !pFlyFrame || !pFlyFrame->IsLowerOf( pTab ) ) | |||
3365 | pTab->InvalidatePrt(); | |||
3366 | } | |||
3367 | } | |||
3368 | SwLayoutFrame* pCell = pCnt->GetUpper(); | |||
3369 | // #i40606# - use <GetLastBoundRect()> | |||
3370 | // instead of <GetCurrentBoundRect()>, because a recalculation | |||
3371 | // of the bounding rectangle isn't intended here. | |||
3372 | if (!isValidTableBeforeAnchor && pCell->IsCellFrame() && | |||
3373 | ( pCell->getFrameArea().IsOver( pObj->GetLastBoundRect() ) || | |||
3374 | pCell->getFrameArea().IsOver( rRect ) ) ) | |||
3375 | { | |||
3376 | const SwFormatVertOrient &rOri = pCell->GetFormat()->GetVertOrient(); | |||
3377 | if ( text::VertOrientation::NONE != rOri.GetVertOrient() ) | |||
3378 | pCell->InvalidatePrt(); | |||
3379 | } | |||
3380 | } | |||
3381 | pCnt = pCnt->GetNextContentFrame(); | |||
3382 | } | |||
3383 | // #128702# - make code robust | |||
3384 | if ( pPage && pPage->GetSortedObjs() ) | |||
3385 | { | |||
3386 | pObj->GetOrdNum(); | |||
3387 | const SwSortedObjs &rObjs = *pPage->GetSortedObjs(); | |||
3388 | for (SwAnchoredObject* pAnchoredObj : rObjs) | |||
3389 | { | |||
3390 | if ( dynamic_cast<const SwFlyFrame*>( pAnchoredObj) != nullptr ) | |||
3391 | { | |||
3392 | if( pAnchoredObj->GetDrawObj() == pObj ) | |||
3393 | continue; | |||
3394 | SwFlyFrame *pFly = static_cast<SwFlyFrame*>(pAnchoredObj); | |||
3395 | if ( pFly->getFrameArea().Top() == FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) ) | |||
3396 | continue; | |||
3397 | ||||
3398 | if ( !pFlyFrame || | |||
3399 | (!pFly->IsLowerOf( pFlyFrame ) && | |||
3400 | pFly->GetVirtDrawObj()->GetOrdNumDirect() < pObj->GetOrdNumDirect())) | |||
3401 | { | |||
3402 | pCnt = pFly->ContainsContent(); | |||
3403 | while ( pCnt ) | |||
3404 | { | |||
3405 | ::lcl_NotifyContent( pObj, pCnt, rRect, eHint ); | |||
3406 | pCnt = pCnt->GetNextContentFrame(); | |||
3407 | } | |||
3408 | } | |||
3409 | if( pFly->IsFlyLayFrame() ) | |||
3410 | { | |||
3411 | if( pFly->Lower() && pFly->Lower()->IsColumnFrame() && | |||
3412 | pFly->getFrameArea().Bottom() >= rRect.Top() && | |||
3413 | pFly->getFrameArea().Top() <= rRect.Bottom() && | |||
3414 | pFly->getFrameArea().Right() >= rRect.Left() && | |||
3415 | pFly->getFrameArea().Left() <= rRect.Right() ) | |||
3416 | { | |||
3417 | pFly->InvalidateSize(); | |||
3418 | } | |||
3419 | } | |||
3420 | // Flys above myself might sidestep if they have an automatic | |||
3421 | // alignment. This happens independently of my attributes since | |||
3422 | // this might have been changed as well. | |||
3423 | else if ( pFly->IsFlyAtContentFrame() && | |||
3424 | pObj->GetOrdNumDirect() < | |||
3425 | pFly->GetVirtDrawObj()->GetOrdNumDirect() && | |||
3426 | pFlyFrame && !pFly->IsLowerOf( pFlyFrame ) ) | |||
3427 | { | |||
3428 | const SwFormatHoriOrient &rH = pFly->GetFormat()->GetHoriOrient(); | |||
3429 | if ( text::HoriOrientation::NONE != rH.GetHoriOrient() && | |||
3430 | text::HoriOrientation::CENTER != rH.GetHoriOrient() && | |||
3431 | ( !pFly->IsAutoPos() || text::RelOrientation::CHAR != rH.GetRelationOrient() ) && | |||
3432 | (pFly->getFrameArea().Bottom() >= rRect.Top() && | |||
3433 | pFly->getFrameArea().Top() <= rRect.Bottom()) ) | |||
3434 | pFly->InvalidatePos(); | |||
3435 | } | |||
3436 | } | |||
3437 | } | |||
3438 | } | |||
3439 | if ( pFlyFrame && pAnchor->GetUpper() && pAnchor->IsInTab() )//MA_FLY_HEIGHT | |||
3440 | pAnchor->GetUpper()->InvalidateSize(); | |||
3441 | ||||
3442 | // #i82258# - make code robust | |||
3443 | SwViewShell* pSh = nullptr; | |||
3444 | if ( bInva && pPage && | |||
3445 | nullptr != (pSh = pPage->getRootFrame()->GetCurrShell()) ) | |||
3446 | { | |||
3447 | pSh->InvalidateWindows( rRect ); | |||
3448 | } | |||
3449 | } | |||
3450 | ||||
3451 | /// Provides the Upper of an anchor in paragraph-bound objects. If the latter | |||
3452 | /// is a chained border or a footnote, the "virtual" Upper might be returned. | |||
3453 | const SwFrame* GetVirtualUpper( const SwFrame* pFrame, const Point& rPos ) | |||
3454 | { | |||
3455 | if( pFrame->IsTextFrame() ) | |||
3456 | { | |||
3457 | pFrame = pFrame->GetUpper(); | |||
3458 | if( !pFrame->getFrameArea().IsInside( rPos ) ) | |||
3459 | { | |||
3460 | if( pFrame->IsFootnoteFrame() ) | |||
3461 | { | |||
3462 | const SwFootnoteFrame* pTmp = static_cast<const SwFootnoteFrame*>(pFrame)->GetFollow(); | |||
3463 | while( pTmp ) | |||
3464 | { | |||
3465 | if( pTmp->getFrameArea().IsInside( rPos ) ) | |||
3466 | return pTmp; | |||
3467 | pTmp = pTmp->GetFollow(); | |||
3468 | } | |||
3469 | } | |||
3470 | else | |||
3471 | { | |||
3472 | SwFlyFrame* pTmp = const_cast<SwFlyFrame*>(pFrame->FindFlyFrame()); | |||
3473 | while( pTmp ) | |||
3474 | { | |||
3475 | if( pTmp->getFrameArea().IsInside( rPos ) ) | |||
3476 | return pTmp; | |||
3477 | pTmp = pTmp->GetNextLink(); | |||
3478 | } | |||
3479 | } | |||
3480 | } | |||
3481 | } | |||
3482 | return pFrame; | |||
3483 | } | |||
3484 | ||||
3485 | bool Is_Lower_Of(const SwFrame *pCurrFrame, const SdrObject* pObj) | |||
3486 | { | |||
3487 | Point aPos; | |||
3488 | const SwFrame* pFrame; | |||
3489 | if (const SwVirtFlyDrawObj *pFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>(pObj)) | |||
| ||||
3490 | { | |||
3491 | const SwFlyFrame* pFly = pFlyDrawObj->GetFlyFrame(); | |||
3492 | pFrame = pFly->GetAnchorFrame(); | |||
3493 | aPos = pFly->getFrameArea().Pos(); | |||
3494 | } | |||
3495 | else | |||
3496 | { | |||
3497 | pFrame = static_cast<SwDrawContact*>(GetUserCall(pObj))->GetAnchorFrame(pObj); | |||
3498 | aPos = pObj->GetCurrentBoundRect().TopLeft(); | |||
| ||||
3499 | } | |||
3500 | OSL_ENSURE( pFrame, "8-( Fly is lost in Space." )do { if (true && (!(pFrame))) { sal_detail_logFormat( (SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "3500" ": "), "%s", "8-( Fly is lost in Space."); } } while (false); | |||
3501 | pFrame = GetVirtualUpper( pFrame, aPos ); | |||
3502 | do | |||
3503 | { if ( pFrame == pCurrFrame ) | |||
3504 | return true; | |||
3505 | if( pFrame->IsFlyFrame() ) | |||
3506 | { | |||
3507 | aPos = pFrame->getFrameArea().Pos(); | |||
3508 | pFrame = GetVirtualUpper( static_cast<const SwFlyFrame*>(pFrame)->GetAnchorFrame(), aPos ); | |||
3509 | } | |||
3510 | else | |||
3511 | pFrame = pFrame->GetUpper(); | |||
3512 | } while ( pFrame ); | |||
3513 | return false; | |||
3514 | } | |||
3515 | ||||
3516 | /// provides the area of a frame in that no Fly from another area can overlap | |||
3517 | const SwFrame *FindContext( const SwFrame *pFrame, SwFrameType nAdditionalContextType ) | |||
3518 | { | |||
3519 | const SwFrameType nTyp = SwFrameType::Root | SwFrameType::Header | SwFrameType::Footer | SwFrameType::FtnCont | | |||
3520 | SwFrameType::Ftn | SwFrameType::Fly | | |||
3521 | SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell | | |||
3522 | nAdditionalContextType; | |||
3523 | do | |||
3524 | { if ( pFrame->GetType() & nTyp ) | |||
3525 | break; | |||
3526 | pFrame = pFrame->GetUpper(); | |||
3527 | } while( pFrame ); | |||
3528 | return pFrame; | |||
3529 | } | |||
3530 | ||||
3531 | bool IsFrameInSameContext( const SwFrame *pInnerFrame, const SwFrame *pFrame ) | |||
3532 | { | |||
3533 | const SwFrame *pContext = FindContext( pInnerFrame, SwFrameType::None ); | |||
3534 | ||||
3535 | const SwFrameType nTyp = SwFrameType::Root | SwFrameType::Header | SwFrameType::Footer | SwFrameType::FtnCont | | |||
3536 | SwFrameType::Ftn | SwFrameType::Fly | | |||
3537 | SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell; | |||
3538 | do | |||
3539 | { if ( pFrame->GetType() & nTyp ) | |||
3540 | { | |||
3541 | if( pFrame == pContext ) | |||
3542 | return true; | |||
3543 | if( pFrame->IsCellFrame() ) | |||
3544 | return false; | |||
3545 | } | |||
3546 | if( pFrame->IsFlyFrame() ) | |||
3547 | { | |||
3548 | Point aPos( pFrame->getFrameArea().Pos() ); | |||
3549 | pFrame = GetVirtualUpper( static_cast<const SwFlyFrame*>(pFrame)->GetAnchorFrame(), aPos ); | |||
3550 | } | |||
3551 | else | |||
3552 | pFrame = pFrame->GetUpper(); | |||
3553 | } while( pFrame ); | |||
3554 | ||||
3555 | return false; | |||
3556 | } | |||
3557 | ||||
3558 | static SwTwips lcl_CalcCellRstHeight( SwLayoutFrame *pCell ) | |||
3559 | { | |||
3560 | SwFrame *pLow = pCell->Lower(); | |||
3561 | if ( pLow && (pLow->IsContentFrame() || pLow->IsSctFrame()) ) | |||
3562 | { | |||
3563 | long nHeight = 0, nFlyAdd = 0; | |||
3564 | do | |||
3565 | { | |||
3566 | long nLow = pLow->getFrameArea().Height(); | |||
3567 | if( pLow->IsTextFrame() && static_cast<SwTextFrame*>(pLow)->IsUndersized() ) | |||
3568 | nLow += static_cast<SwTextFrame*>(pLow)->GetParHeight()-pLow->getFramePrintArea().Height(); | |||
3569 | else if( pLow->IsSctFrame() && static_cast<SwSectionFrame*>(pLow)->IsUndersized() ) | |||
3570 | nLow += static_cast<SwSectionFrame*>(pLow)->Undersize(); | |||
3571 | nFlyAdd = std::max( 0L, nFlyAdd - nLow ); | |||
3572 | nFlyAdd = std::max( nFlyAdd, ::CalcHeightWithFlys( pLow ) ); | |||
3573 | nHeight += nLow; | |||
3574 | pLow = pLow->GetNext(); | |||
3575 | } while ( pLow ); | |||
3576 | if ( nFlyAdd ) | |||
3577 | nHeight += nFlyAdd; | |||
3578 | ||||
3579 | // The border cannot be calculated based on PrtArea and Frame, since both can be invalid. | |||
3580 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), pCell ); | |||
3581 | const SwBorderAttrs &rAttrs = *aAccess.Get(); | |||
3582 | nHeight += rAttrs.CalcTop() + rAttrs.CalcBottom(); | |||
3583 | ||||
3584 | return pCell->getFrameArea().Height() - nHeight; | |||
3585 | } | |||
3586 | else | |||
3587 | { | |||
3588 | long nRstHeight = 0; | |||
3589 | while (pLow && pLow->IsLayoutFrame()) | |||
3590 | { | |||
3591 | nRstHeight += ::CalcRowRstHeight(static_cast<SwLayoutFrame*>(pLow)); | |||
3592 | pLow = pLow->GetNext(); | |||
3593 | } | |||
3594 | return nRstHeight; | |||
3595 | } | |||
3596 | } | |||
3597 | ||||
3598 | SwTwips CalcRowRstHeight( SwLayoutFrame *pRow ) | |||
3599 | { | |||
3600 | SwFrame *pLow = pRow->Lower(); | |||
3601 | if (!(pLow && pLow->IsLayoutFrame())) | |||
3602 | { | |||
3603 | return 0; | |||
3604 | } | |||
3605 | SwTwips nRstHeight = LONG_MAX9223372036854775807L; | |||
3606 | while (pLow && pLow->IsLayoutFrame()) | |||
3607 | { | |||
3608 | nRstHeight = std::min(nRstHeight, ::lcl_CalcCellRstHeight(static_cast<SwLayoutFrame*>(pLow))); | |||
3609 | pLow = pLow->GetNext(); | |||
3610 | } | |||
3611 | return nRstHeight; | |||
3612 | } | |||
3613 | ||||
3614 | const SwFrame* FindPage( const SwRect &rRect, const SwFrame *pPage ) | |||
3615 | { | |||
3616 | if ( !rRect.IsOver( pPage->getFrameArea() ) ) | |||
3617 | { | |||
3618 | const SwRootFrame* pRootFrame = static_cast<const SwRootFrame*>(pPage->GetUpper()); | |||
3619 | const SwFrame* pTmpPage = pRootFrame ? pRootFrame->GetPageAtPos( rRect.TopLeft(), &rRect.SSize(), true ) : nullptr; | |||
3620 | if ( pTmpPage ) | |||
3621 | pPage = pTmpPage; | |||
3622 | } | |||
3623 | ||||
3624 | return pPage; | |||
3625 | } | |||
3626 | ||||
3627 | namespace { | |||
3628 | ||||
3629 | class SwFrameHolder : private SfxListener | |||
3630 | { | |||
3631 | SwFrame* pFrame; | |||
3632 | bool bSet; | |||
3633 | virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; | |||
3634 | public: | |||
3635 | SwFrameHolder() : pFrame(nullptr), bSet(false) {} | |||
3636 | void SetFrame( SwFrame* pHold ); | |||
3637 | SwFrame* GetFrame() { return pFrame; } | |||
3638 | void Reset(); | |||
3639 | bool IsSet() const { return bSet; } | |||
3640 | }; | |||
3641 | ||||
3642 | } | |||
3643 | ||||
3644 | void SwFrameHolder::SetFrame( SwFrame* pHold ) | |||
3645 | { | |||
3646 | bSet = true; | |||
3647 | if (pFrame != pHold) | |||
3648 | { | |||
3649 | if (pFrame) | |||
3650 | EndListening(*pFrame); | |||
3651 | StartListening(*pHold); | |||
3652 | pFrame = pHold; | |||
3653 | } | |||
3654 | } | |||
3655 | ||||
3656 | void SwFrameHolder::Reset() | |||
3657 | { | |||
3658 | if (pFrame) | |||
3659 | EndListening(*pFrame); | |||
3660 | bSet = false; | |||
3661 | pFrame = nullptr; | |||
3662 | } | |||
3663 | ||||
3664 | void SwFrameHolder::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) | |||
3665 | { | |||
3666 | if ( rHint.GetId() == SfxHintId::Dying && &rBC == pFrame ) | |||
3667 | { | |||
3668 | pFrame = nullptr; | |||
3669 | } | |||
3670 | } | |||
3671 | ||||
3672 | SwFrame* GetFrameOfModify(SwRootFrame const*const pLayout, SwModify const& rMod, | |||
3673 | SwFrameType const nFrameType, SwPosition const*const pPos, | |||
3674 | std::pair<Point, bool> const*const pViewPosAndCalcFrame) | |||
3675 | { | |||
3676 | SwFrame *pMinFrame = nullptr, *pTmpFrame; | |||
3677 | SwFrameHolder aHolder; | |||
3678 | SwRect aCalcRect; | |||
3679 | bool bClientIterChanged = false; | |||
3680 | ||||
3681 | SwIterator<SwFrame, SwModify, sw::IteratorMode::UnwrapMulti> aIter(rMod); | |||
3682 | do { | |||
3683 | pMinFrame = nullptr; | |||
3684 | aHolder.Reset(); | |||
3685 | sal_uInt64 nMinDist = 0; | |||
3686 | bClientIterChanged = false; | |||
3687 | ||||
3688 | for( pTmpFrame = aIter.First(); pTmpFrame; pTmpFrame = aIter.Next() ) | |||
3689 | { | |||
3690 | if( pTmpFrame->GetType() & nFrameType && | |||
3691 | ( !pLayout || pLayout == pTmpFrame->getRootFrame() ) && | |||
3692 | (!pTmpFrame->IsFlowFrame() || | |||
3693 | !SwFlowFrame::CastFlowFrame( pTmpFrame )->IsFollow() )) | |||
3694 | { | |||
3695 | if (pViewPosAndCalcFrame) | |||
3696 | { | |||
3697 | // watch for Frame being deleted | |||
3698 | if ( pMinFrame ) | |||
3699 | aHolder.SetFrame( pMinFrame ); | |||
3700 | else | |||
3701 | aHolder.Reset(); | |||
3702 | ||||
3703 | if (pViewPosAndCalcFrame->second) | |||
3704 | { | |||
3705 | // tdf#108118 prevent recursion | |||
3706 | DisableCallbackAction a(*pTmpFrame->getRootFrame()); | |||
3707 | // - format parent Writer | |||
3708 | // fly frame, if it isn't been formatted yet. | |||
3709 | // Note: The Writer fly frame could be the frame itself. | |||
3710 | SwFlyFrame* pFlyFrame( pTmpFrame->FindFlyFrame() ); | |||
3711 | if ( pFlyFrame && | |||
3712 | pFlyFrame->getFrameArea().Pos().X() == FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) && | |||
3713 | pFlyFrame->getFrameArea().Pos().Y() == FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) ) | |||
3714 | { | |||
3715 | SwObjectFormatter::FormatObj( *pFlyFrame ); | |||
3716 | } | |||
3717 | pTmpFrame->Calc(pLayout ? pLayout->GetCurrShell()->GetOut() : nullptr); | |||
3718 | } | |||
3719 | ||||
3720 | // aIter.IsChanged checks if the current pTmpFrame has been deleted while | |||
3721 | // it is the current iterator | |||
3722 | // FrameHolder watches for deletion of the current pMinFrame | |||
3723 | if( aIter.IsChanged() || ( aHolder.IsSet() && !aHolder.GetFrame() ) ) | |||
3724 | { | |||
3725 | // restart iteration | |||
3726 | bClientIterChanged = true; | |||
3727 | break; | |||
3728 | } | |||
3729 | ||||
3730 | // for Flys go via the parent if the Fly is not yet "formatted" | |||
3731 | if (!pViewPosAndCalcFrame->second && | |||
3732 | pTmpFrame->GetType() & SwFrameType::Fly && | |||
3733 | static_cast<SwFlyFrame*>(pTmpFrame)->GetAnchorFrame() && | |||
3734 | FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) == pTmpFrame->getFrameArea().Pos().getX() && | |||
3735 | FAR_AWAY(((sal_Int32) 0x7FFFFFFF) - 20000) == pTmpFrame->getFrameArea().Pos().getY() ) | |||
3736 | aCalcRect = static_cast<SwFlyFrame*>(pTmpFrame)->GetAnchorFrame()->getFrameArea(); | |||
3737 | else | |||
3738 | aCalcRect = pTmpFrame->getFrameArea(); | |||
3739 | ||||
3740 | if (aCalcRect.IsInside(pViewPosAndCalcFrame->first)) | |||
3741 | { | |||
3742 | pMinFrame = pTmpFrame; | |||
3743 | break; | |||
3744 | } | |||
3745 | ||||
3746 | // Point not in rectangle. Compare distances: | |||
3747 | const Point aCalcRectCenter = aCalcRect.Center(); | |||
3748 | const Point aDiff = aCalcRectCenter - pViewPosAndCalcFrame->first; | |||
3749 | const sal_uInt64 nCurrentDist = sal_Int64(aDiff.getX()) * sal_Int64(aDiff.getX()) + sal_Int64(aDiff.getY()) * sal_Int64(aDiff.getY()); // opt: no sqrt | |||
3750 | if ( !pMinFrame || nCurrentDist < nMinDist ) | |||
3751 | { | |||
3752 | pMinFrame = pTmpFrame; | |||
3753 | nMinDist = nCurrentDist; | |||
3754 | } | |||
3755 | } | |||
3756 | else | |||
3757 | { | |||
3758 | // if no pViewPosAndCalcFrame is provided, take the first one | |||
3759 | pMinFrame = pTmpFrame; | |||
3760 | break; | |||
3761 | } | |||
3762 | } | |||
3763 | } | |||
3764 | } while( bClientIterChanged ); | |||
3765 | ||||
3766 | if( pPos && pMinFrame && pMinFrame->IsTextFrame() ) | |||
3767 | return static_cast<SwTextFrame*>(pMinFrame)->GetFrameAtPos( *pPos ); | |||
3768 | ||||
3769 | return pMinFrame; | |||
3770 | } | |||
3771 | ||||
3772 | bool IsExtraData( const SwDoc *pDoc ) | |||
3773 | { | |||
3774 | const SwLineNumberInfo &rInf = pDoc->GetLineNumberInfo(); | |||
3775 | return rInf.IsPaintLineNumbers() || | |||
3776 | rInf.IsCountInFlys() || | |||
3777 | (static_cast<sal_Int16>(SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule ::Writer)))->GetRedlineMarkPos()) != text::HoriOrientation::NONE && | |||
3778 | !pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty()); | |||
3779 | } | |||
3780 | ||||
3781 | // OD 22.09.2003 #110978# | |||
3782 | SwRect SwPageFrame::PrtWithoutHeaderAndFooter() const | |||
3783 | { | |||
3784 | SwRect aPrtWithoutHeaderFooter( getFramePrintArea() ); | |||
3785 | aPrtWithoutHeaderFooter.Pos() += getFrameArea().Pos(); | |||
3786 | ||||
3787 | const SwFrame* pLowerFrame = Lower(); | |||
3788 | while ( pLowerFrame ) | |||
3789 | { | |||
3790 | // Note: independent on text direction page header and page footer are | |||
3791 | // always at top respectively at bottom of the page frame. | |||
3792 | if ( pLowerFrame->IsHeaderFrame() ) | |||
3793 | { | |||
3794 | aPrtWithoutHeaderFooter.AddTop( pLowerFrame->getFrameArea().Height() ); | |||
3795 | } | |||
3796 | if ( pLowerFrame->IsFooterFrame() ) | |||
3797 | { | |||
3798 | aPrtWithoutHeaderFooter.AddBottom( - pLowerFrame->getFrameArea().Height() ); | |||
3799 | } | |||
3800 | ||||
3801 | pLowerFrame = pLowerFrame->GetNext(); | |||
3802 | } | |||
3803 | ||||
3804 | return aPrtWithoutHeaderFooter; | |||
3805 | } | |||
3806 | ||||
3807 | /** method to determine the spacing values of a frame | |||
3808 | ||||
3809 | OD 2004-03-10 #i28701# | |||
3810 | OD 2009-08-28 #i102458# | |||
3811 | Add output parameter <obIsLineSpacingProportional> | |||
3812 | */ | |||
3813 | void GetSpacingValuesOfFrame( const SwFrame& rFrame, | |||
3814 | SwTwips& onLowerSpacing, | |||
3815 | SwTwips& onLineSpacing, | |||
3816 | bool& obIsLineSpacingProportional, | |||
3817 | bool bIdenticalStyles ) | |||
3818 | { | |||
3819 | if ( !rFrame.IsFlowFrame() ) | |||
3820 | { | |||
3821 | onLowerSpacing = 0; | |||
3822 | onLineSpacing = 0; | |||
3823 | } | |||
3824 | else | |||
3825 | { | |||
3826 | const SvxULSpaceItem& rULSpace = rFrame.GetAttrSet()->GetULSpace(); | |||
3827 | // check contextual spacing if the style of actual and next paragraphs are identical | |||
3828 | if (bIdenticalStyles) | |||
3829 | onLowerSpacing = (rULSpace.GetContext() ? 0 : rULSpace.GetLower()); | |||
3830 | else | |||
3831 | onLowerSpacing = rULSpace.GetLower(); | |||
3832 | ||||
3833 | onLineSpacing = 0; | |||
3834 | obIsLineSpacingProportional = false; | |||
3835 | if ( rFrame.IsTextFrame() ) | |||
3836 | { | |||
3837 | onLineSpacing = static_cast<const SwTextFrame&>(rFrame).GetLineSpace(); | |||
3838 | obIsLineSpacingProportional = | |||
3839 | onLineSpacing != 0 && | |||
3840 | static_cast<const SwTextFrame&>(rFrame).GetLineSpace( true ) == 0; | |||
3841 | } | |||
3842 | ||||
3843 | OSL_ENSURE( onLowerSpacing >= 0 && onLineSpacing >= 0,do { if (true && (!(onLowerSpacing >= 0 && onLineSpacing >= 0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "3844" ": "), "%s", "<GetSpacingValuesOfFrame(..)> - spacing values aren't positive!" ); } } while (false) | |||
3844 | "<GetSpacingValuesOfFrame(..)> - spacing values aren't positive!" )do { if (true && (!(onLowerSpacing >= 0 && onLineSpacing >= 0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/frmtool.cxx" ":" "3844" ": "), "%s", "<GetSpacingValuesOfFrame(..)> - spacing values aren't positive!" ); } } while (false); | |||
3845 | } | |||
3846 | } | |||
3847 | ||||
3848 | /// get the content of the table cell, skipping content from nested tables | |||
3849 | const SwContentFrame* GetCellContent( const SwLayoutFrame& rCell ) | |||
3850 | { | |||
3851 | const SwContentFrame* pContent = rCell.ContainsContent(); | |||
3852 | const SwTabFrame* pTab = rCell.FindTabFrame(); | |||
3853 | ||||
3854 | while ( pContent && rCell.IsAnLower( pContent ) ) | |||
3855 | { | |||
3856 | const SwTabFrame* pTmpTab = pContent->FindTabFrame(); | |||
3857 | if ( pTmpTab != pTab ) | |||
3858 | { | |||
3859 | SwFrame const*const pTmp = pTmpTab->FindLastContentOrTable(); | |||
3860 | if (pTmp) | |||
3861 | { | |||
3862 | pContent = pTmp->FindNextCnt(); | |||
3863 | } | |||
3864 | else | |||
3865 | { | |||
3866 | pContent = nullptr; | |||
3867 | } | |||
3868 | } | |||
3869 | else | |||
3870 | break; | |||
3871 | } | |||
3872 | return pContent; | |||
3873 | } | |||
3874 | ||||
3875 | SwDeletionChecker::SwDeletionChecker(const SwFrame* pFrame) | |||
3876 | : mpFrame( pFrame ) | |||
3877 | , mpRegIn( pFrame | |||
3878 | ? pFrame->IsTextFrame() | |||
3879 | // sw_redlinehide: GetDep() may be a member of SwTextFrame! | |||
3880 | ? static_cast<SwTextFrame const*>(pFrame)->GetTextNodeFirst() | |||
3881 | : const_cast<SwFrame*>(pFrame)->GetDep() | |||
3882 | : nullptr ) | |||
3883 | { | |||
3884 | } | |||
3885 | ||||
3886 | /// Can be used to check if a frame has been deleted | |||
3887 | bool SwDeletionChecker::HasBeenDeleted() const | |||
3888 | { | |||
3889 | if ( !mpFrame || !mpRegIn ) | |||
3890 | return false; | |||
3891 | ||||
3892 | SwIterator<SwFrame, SwModify, sw::IteratorMode::UnwrapMulti> aIter(*mpRegIn); | |||
3893 | SwFrame* pLast = aIter.First(); | |||
3894 | while ( pLast ) | |||
3895 | { | |||
3896 | if ( pLast == mpFrame ) | |||
3897 | return false; | |||
3898 | pLast = aIter.Next(); | |||
3899 | } | |||
3900 | ||||
3901 | return true; | |||
3902 | } | |||
3903 | ||||
3904 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |