Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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

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

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <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
79using namespace ::com::sun::star;
80
81bool bObjsDirect = true;
82bool bDontCreateObjects = false;
83bool bSetCompletePaintOnInvalidate = false;
84
85sal_uInt8 StackHack::nCnt = 0;
86bool StackHack::bLocked = false;
87
88SwFrameNotify::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
109SwFrameNotify::~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
416SwLayNotify::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
425static 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
451SwLayNotify::~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
628SwFlyNotify::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
637SwFlyNotify::~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
733SwContentNotify::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
758SwContentNotify::~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
979void 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
1043static 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
1150void 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
1176void 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
1223void 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
1274bool 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
1326void 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
1378namespace sw {
1379
1380void 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*/
1416static 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
1435void 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();
1
'pLayout' initialized here
1441 const bool bOldCallbackActionEnabled = pLayout && pLayout->IsCallbackActionEnabled();
2
Assuming 'pLayout' is null
1442 if( bOldCallbackActionEnabled
2.1
'bOldCallbackActionEnabled' is false
2.1
'bOldCallbackActionEnabled' is false
2.1
'bOldCallbackActionEnabled' is false
)
3
Taking false branch
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;
4
Assuming 'bPages' is false
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
4.1
'bPages' is false
4.1
'bPages' is false
4.1
'bPages' is false
)
5
Taking false branch
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() &&
6
Assuming the condition is false
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)
7
Assuming 'nEndIndex' is equal to 0
1533 {
1534 SwNode *pNd = pDoc->GetNodes()[nIndex];
1535 if ( pNd->IsContentNode() )
8
Calling 'SwNode::IsContentNode'
14
Returning from 'SwNode::IsContentNode'
15
Taking false branch
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() )
16
Calling 'SwNode::IsTableNode'
19
Returning from 'SwNode::IsTableNode'
20
Taking false branch
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() )
21
Calling 'SwNode::IsSectionNode'
24
Returning from 'SwNode::IsSectionNode'
25
Taking false branch
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() )
26
Calling 'SwNode::IsEndNode'
29
Returning from 'SwNode::IsEndNode'
30
Calling 'SwNode::IsSectionNode'
33
Returning from 'SwNode::IsSectionNode'
34
Taking true branch
1802 {
1803 if (pLayout->IsHideRedlines() && !pNd->IsCreateFrameWhenHidingRedlines())
35
Called C++ object pointer is null
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
1937void 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
2142SwBorderAttrs::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
2196SwBorderAttrs::~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
2206void SwBorderAttrs::CalcTop_()
2207{
2208 m_nTop = CalcTopLine() + m_rUL.GetUpper();
2209 m_bTop = false;
2210}
2211
2212void SwBorderAttrs::CalcBottom_()
2213{
2214 m_nBottom = CalcBottomLine() + m_rUL.GetLower();
2215 m_bBottom = false;
2216}
2217
2218long 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.
2247static 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
2266long 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
2317void 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
2324void 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
2331void 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
2338void 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
2345void 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
2362static 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.
2371bool 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
2382bool 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>
2404void 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>
2439void 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(..)>.
2470bool 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
2482bool 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>
2494void 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
2511void 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
2526void 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
2538static 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
2548SwBorderAttrAccess::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
2556SwCacheObj *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
2562SwBorderAttrs *SwBorderAttrAccess::Get()
2563{
2564 return static_cast<SwBorderAttrs*>(SwCacheAccess::Get());
2565}
2566
2567SwOrderIter::SwOrderIter( const SwPageFrame *pPg ) :
2568 m_pPage( pPg ),
2569 m_pCurrent( nullptr )
2570{
2571}
2572
2573void 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
2599const 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
2626const 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
2654void 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
2691static 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
2742SwFrame *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
2855static 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
2905void 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
2993namespace sw {
2994
2995bool 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
3006SwPageFrame * 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
3068static 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
3111void 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
3127void 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
3213static 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
3234static 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
3275void 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.
3453const 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
3485bool 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
3517const 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
3531bool 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
3558static 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
3598SwTwips 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
3614const 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
3627namespace {
3628
3629class SwFrameHolder : private SfxListener
3630{
3631 SwFrame* pFrame;
3632 bool bSet;
3633 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
3634public:
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
3644void 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
3656void SwFrameHolder::Reset()
3657{
3658 if (pFrame)
3659 EndListening(*pFrame);
3660 bSet = false;
3661 pFrame = nullptr;
3662}
3663
3664void SwFrameHolder::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
3665{
3666 if ( rHint.GetId() == SfxHintId::Dying && &rBC == pFrame )
3667 {
3668 pFrame = nullptr;
3669 }
3670}
3671
3672SwFrame* 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
3772bool 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#
3782SwRect 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*/
3813void 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
3849const 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
3875SwDeletionChecker::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
3887bool 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: */

/home/maarten/src/libreoffice/core/sw/inc/node.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_SW_INC_NODE_HXX
21#define INCLUDED_SW_INC_NODE_HXX
22
23#include <sal/types.h>
24
25#include "swdllapi.h"
26#include "ndarr.hxx"
27#include "ndtyp.hxx"
28#include "index.hxx"
29#include "fmtcol.hxx"
30
31#include <memory>
32#include <vector>
33
34class SwContentFrame;
35class SwContentNode;
36class SwDoc;
37class SwEndNode;
38class SwFrame;
39class SwFrameFormat;
40class SwGrfNode;
41class SwNoTextNode;
42class SwNodeIndex;
43class SwOLENode;
44class SwRect;
45class SwSection;
46class SwSectionFormat;
47class SwTOXBase;
48class SwSectionNode;
49class SwStartNode;
50class SwTabFrame;
51class SwRootFrame;
52class SwTable;
53class SwTableNode;
54class SwTableBox;
55class SwTextNode;
56class SwPageDesc;
57class SwViewShell;
58struct SwPosition;
59class IStyleAccess;
60class IDocumentSettingAccess;
61class IDocumentDeviceAccess;
62class IDocumentMarkAccess;
63class IDocumentRedlineAccess;
64class IDocumentStylePoolAccess;
65class IDocumentLinksAdministration;
66class IDocumentFieldsAccess;
67class IDocumentContentOperations;
68class IDocumentListItems;
69class Point;
70enum class SvxFrameDirection;
71typedef std::vector<SwOLENode*> SwOLENodes; // docary.hxx
72
73namespace drawinglayer::attribute {
74 class SdrAllFillAttributesHelper;
75 typedef std::shared_ptr< SdrAllFillAttributesHelper > SdrAllFillAttributesHelperPtr;
76}
77
78/// Base class of the Writer document model elements.
79class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwNode
80 : private BigPtrEntry
81{
82 friend class SwNodes;
83
84 SwNodeType m_nNodeType;
85
86 /// For text nodes: level of auto format. Was put here because we had still free bits.
87 sal_uInt8 m_nAFormatNumLvl : 3;
88 bool m_bIgnoreDontExpand : 1; ///< for Text Attributes - ignore the flag
89
90public:
91 /// sw_redlinehide: redline node merge state
92 enum class Merge { None, First, NonFirst, Hidden };
93 bool IsCreateFrameWhenHidingRedlines() const {
94 return m_eMerge == Merge::None || m_eMerge == Merge::First;
95 }
96 void SetRedlineMergeFlag(Merge const eMerge) { m_eMerge = eMerge; }
97 Merge GetRedlineMergeFlag() const { return m_eMerge; }
98private:
99 Merge m_eMerge;
100
101#ifdef DBG_UTIL
102 static long s_nSerial;
103 long m_nSerial;
104#endif
105
106 /// all SwFrameFormat that are anchored at the node
107 /// invariant: SwFrameFormat is in the list iff
108 /// SwFrameFormat::GetAnchor().GetContentAnchor() points to this node
109 std::unique_ptr<std::vector<SwFrameFormat*>> m_pAnchoredFlys;
110
111protected:
112 SwStartNode* m_pStartOfSection;
113
114 SwNode( const SwNodeIndex &rWhere, const SwNodeType nNodeId );
115
116 /// for the initial StartNode
117 SwNode( SwNodes& rNodes, sal_uLong nPos, const SwNodeType nNodeId );
118
119public:
120 /** the = 0 forces the class to be an abstract base class, but the dtor can be still called
121 from subclasses */
122 virtual ~SwNode() override = 0;
123
124#ifdef DBG_UTIL
125 long GetSerial() const { return m_nSerial; }
126#endif
127
128 sal_uInt16 GetSectionLevel() const;
129
130 inline sal_uLong StartOfSectionIndex() const;
131 const SwStartNode* StartOfSectionNode() const { return m_pStartOfSection; }
132 SwStartNode* StartOfSectionNode() { return m_pStartOfSection; }
133
134 inline sal_uLong EndOfSectionIndex() const;
135 inline const SwEndNode* EndOfSectionNode() const;
136 inline SwEndNode* EndOfSectionNode();
137
138 sal_uInt8 GetAutoFormatLvl() const { return m_nAFormatNumLvl; }
139 void SetAutoFormatLvl( sal_uInt8 nVal ) { m_nAFormatNumLvl = nVal; }
140
141 bool IsIgnoreDontExpand() const { return m_bIgnoreDontExpand; }
142 void SetIgnoreDontExpand( bool bNew ) { m_bIgnoreDontExpand = bNew; }
143
144 SwNodeType GetNodeType() const { return m_nNodeType; }
145
146 inline SwStartNode *GetStartNode();
147 inline const SwStartNode *GetStartNode() const;
148 inline SwContentNode *GetContentNode();
149 inline const SwContentNode *GetContentNode() const;
150 inline SwEndNode *GetEndNode();
151 inline const SwEndNode *GetEndNode() const;
152 inline SwTextNode *GetTextNode();
153 inline const SwTextNode *GetTextNode() const;
154 inline SwOLENode *GetOLENode();
155 inline const SwOLENode *GetOLENode() const;
156 inline SwNoTextNode *GetNoTextNode();
157 inline const SwNoTextNode *GetNoTextNode() const;
158 inline SwGrfNode *GetGrfNode();
159 inline const SwGrfNode *GetGrfNode() const;
160 inline SwTableNode *GetTableNode();
161 inline const SwTableNode *GetTableNode() const;
162 inline SwSectionNode *GetSectionNode();
163 inline const SwSectionNode *GetSectionNode() const;
164
165 inline bool IsStartNode() const;
166 inline bool IsContentNode() const;
167 inline bool IsEndNode() const;
168 inline bool IsTextNode() const;
169 inline bool IsTableNode() const;
170 inline bool IsSectionNode() const;
171 inline bool IsOLENode() const;
172 inline bool IsNoTextNode() const;
173 inline bool IsGrfNode() const;
174
175 /**
176 Checks if this node is in redlines.
177
178 @retval true this node is in redlines
179 @retval false else
180 */
181 bool IsInRedlines() const;
182
183 /** Search table node, in which it is. If it is in no table
184 @return 0. */
185 SwTableNode *FindTableNode();
186 inline const SwTableNode *FindTableNode() const;
187
188 /** Search section node, in which it is. If it is in no section
189 @return 0. */
190 SwSectionNode *FindSectionNode();
191 inline const SwSectionNode *FindSectionNode() const;
192
193 SwStartNode* FindSttNodeByType( SwStartNodeType eTyp );
194 inline const SwStartNode* FindSttNodeByType( SwStartNodeType eTyp ) const;
195
196 const SwStartNode* FindTableBoxStartNode() const
197 { return FindSttNodeByType( SwTableBoxStartNode ); }
198 const SwStartNode* FindFlyStartNode() const
199 { return FindSttNodeByType( SwFlyStartNode ); }
200 const SwStartNode* FindFootnoteStartNode() const
201 { return FindSttNodeByType( SwFootnoteStartNode ); }
202 const SwStartNode* FindHeaderStartNode() const
203 { return FindSttNodeByType( SwHeaderStartNode ); }
204 const SwStartNode* FindFooterStartNode() const
205 { return FindSttNodeByType( SwFooterStartNode ); }
206
207 /// Node is in which nodes-array/doc?
208 inline SwNodes& GetNodes();
209 inline const SwNodes& GetNodes() const;
210
211 SwDoc& GetDoc()
212 {
213 return GetNodes().GetDoc();
214 }
215
216 const SwDoc& GetDoc() const
217 {
218 return GetNodes().GetDoc();
219 }
220
221 /** Provides access to the document setting interface
222 */
223 const IDocumentSettingAccess* getIDocumentSettingAccess() const;
224
225 /** Provides access to the document device interface
226 */
227 const IDocumentDeviceAccess& getIDocumentDeviceAccess() const;
228
229 /** Provides access to the document bookmark interface
230 */
231 const IDocumentMarkAccess* getIDocumentMarkAccess() const;
232
233 /** Provides access to the document redline interface
234 */
235 const IDocumentRedlineAccess& getIDocumentRedlineAccess() const;
236
237 /** Provides access to the document style pool interface
238 */
239 const IDocumentStylePoolAccess& getIDocumentStylePoolAccess() const;
240
241 /** Provides access to the document draw model interface
242 */
243 const IDocumentDrawModelAccess& getIDocumentDrawModelAccess() const;
244
245 /** Provides access to the document layout interface
246 */
247 const IDocumentLayoutAccess& getIDocumentLayoutAccess() const;
248 IDocumentLayoutAccess& getIDocumentLayoutAccess();
249
250 /** Provides access to the document links administration interface
251 */
252 const IDocumentLinksAdministration& getIDocumentLinksAdministration() const;
253 IDocumentLinksAdministration& getIDocumentLinksAdministration();
254
255 /** Provides access to the document fields administration interface
256 */
257 const IDocumentFieldsAccess& getIDocumentFieldsAccess() const;
258 IDocumentFieldsAccess& getIDocumentFieldsAccess();
259
260 /** Provides access to the document content operations interface
261 */
262 IDocumentContentOperations& getIDocumentContentOperations();
263
264 /** Provides access to the document automatic styles interface
265 */
266 IStyleAccess& getIDocumentStyleAccess();
267
268 /** Provides access to the document's numbered items interface */
269 IDocumentListItems& getIDocumentListItems();
270
271 /// Is node in the visible area of the Shell?
272 bool IsInVisibleArea( SwViewShell const * pSh ) const;
273 /// Is node in a protected area?
274 bool IsInProtectSect() const;
275 /** Is node in something that is protected (range, frame,
276 table cells ... including anchor in case of frames or footnotes)? */
277 bool IsProtect() const;
278
279 /** Search PageDesc with which this node is formatted. If layout is existent
280 search over layout, else only the hard way is left: search over the nodes
281 to the front!! */
282 const SwPageDesc* FindPageDesc( size_t* pPgDescNdIdx = nullptr ) const;
283
284 /// If node is in a fly return the respective format.
285 SwFrameFormat* GetFlyFormat() const;
286
287 /// If node is in a table return the respective table box.
288 SwTableBox* GetTableBox() const;
289
290 sal_uLong GetIndex() const { return GetPos(); }
291
292 const SwTextNode* FindOutlineNodeOfLevel(sal_uInt8 nLvl, SwRootFrame const* pLayout = nullptr) const;
293
294 sal_uInt8 HasPrevNextLayNode() const;
295
296 std::vector<SwFrameFormat *> const* GetAnchoredFlys() const { return m_pAnchoredFlys.get(); }
297 void AddAnchoredFly(SwFrameFormat *);
298 void RemoveAnchoredFly(SwFrameFormat *);
299
300 /**
301 * Dumps the node structure to the given destination (file nodes.xml in the current directory by default)
302 */
303 virtual void dumpAsXml(xmlTextWriterPtr pWriter) const;
304
305private:
306 SwNode( const SwNode & rNodes ) = delete;
307 SwNode & operator= ( const SwNode & rNodes ) = delete;
308};
309
310/// Starts a section of nodes in the document model.
311class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwStartNode: public SwNode
312{
313 friend class SwNode;
314 friend class SwNodes;
315 friend class SwEndNode; ///< to set the theEndOfSection !!
316
317 SwEndNode* m_pEndOfSection;
318 SwStartNodeType m_eStartNodeType;
319
320 /// for the initial StartNode
321 SwStartNode( SwNodes& rNodes, sal_uLong nPos );
322
323protected:
324 SwStartNode( const SwNodeIndex &rWhere,
325 const SwNodeType nNodeType = SwNodeType::Start,
326 SwStartNodeType = SwNormalStartNode );
327public:
328 SwStartNodeType GetStartNodeType() const { return m_eStartNodeType; }
329
330 /// Call ChkCondcoll to all ContentNodes of section.
331 void CheckSectionCondColl() const;
332
333 virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override;
334
335private:
336 SwStartNode( const SwStartNode & rNode ) = delete;
337 SwStartNode & operator= ( const SwStartNode & rNode ) = delete;
338};
339
340/// Ends a section of nodes in the document model.
341class SwEndNode : public SwNode
342{
343 friend class SwNodes;
344 friend class SwTableNode; ///< To enable creation of its EndNote.
345 friend class SwSectionNode; ///< To enable creation of its EndNote.
346
347 /// for the initial StartNode
348 SwEndNode( SwNodes& rNodes, sal_uLong nPos, SwStartNode& rSttNd );
349
350protected:
351 SwEndNode( const SwNodeIndex &rWhere, SwStartNode& rSttNd );
352
353private:
354 SwEndNode( const SwEndNode & rNode ) = delete;
355 SwEndNode & operator= ( const SwEndNode & rNode ) = delete;
356};
357
358// SwContentNode
359
360class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwContentNode: public sw::BroadcastingModify, public SwNode, public SwIndexReg
361{
362
363 sw::WriterMultiListener m_aCondCollListener;
364 SwFormatColl* m_pCondColl;
365 mutable bool mbSetModifyAtAttr;
366
367protected:
368 SwContentNode( const SwNodeIndex &rWhere, const SwNodeType nNodeType,
369 SwFormatColl *pFormatColl );
370 /** the = 0 forces the class to be an abstract base class, but the dtor can be still called
371 from subclasses */
372 virtual ~SwContentNode() override = 0;
373
374 /** Attribute-set for all auto attributes of a ContentNode.
375 (e.g. TextNode or NoTextNode). */
376 std::shared_ptr<const SfxItemSet> mpAttrSet;
377
378 /// Make respective nodes create the specific AttrSets.
379 virtual void NewAttrSet( SwAttrPool& ) = 0;
380
381 /** There some functions that like to remove items from the internal
382 SwAttrSet (handle): */
383 sal_uInt16 ClearItemsFromAttrSet( const std::vector<sal_uInt16>& rWhichIds );
384
385 virtual void SwClientNotify( const SwModify&, const SfxHint& rHint) override;
386
387public:
388
389 /** MakeFrame will be called for a certain layout
390 pSib is another SwFrame of the same layout (e.g. the SwRootFrame itself, a sibling, the parent) */
391 virtual SwContentFrame *MakeFrame( SwFrame* pSib ) = 0;
392
393 virtual SwContentNode *JoinNext();
394 /** Is it possible to join two nodes?
395 In pIdx the second position can be returned. */
396 bool CanJoinNext( SwNodeIndex* pIdx =nullptr ) const;
397 bool CanJoinPrev( SwNodeIndex* pIdx =nullptr ) const;
398
399 void MakeStartIndex( SwIndex * pIdx ) { pIdx->Assign( this, 0 ); }
400 void MakeEndIndex( SwIndex * pIdx ) { pIdx->Assign( this, Len() ); }
401
402 bool GoNext(SwIndex *, sal_uInt16 nMode ) const;
403 bool GoPrevious(SwIndex *, sal_uInt16 nMode ) const;
404
405 /// @see GetFrameOfModify
406 SwContentFrame *getLayoutFrame( const SwRootFrame*,
407 const SwPosition *pPos = nullptr,
408 std::pair<Point, bool> const* pViewPosAndCalcFrame = nullptr) const;
409 /** @return the real size of the frame or an empty rectangle if
410 no layout exists. Needed for export filters. */
411 SwRect FindLayoutRect( const bool bPrtArea = false,
412 const Point* pPoint = nullptr ) const;
413 SwRect FindPageFrameRect() const;
414
415 /** Method creates all views of document for given node. The content
416 frames that are created are put in the respective layout. */
417 void MakeFramesForAdjacentContentNode(SwContentNode& rNode);
418
419 /** Method deletes all views of document for the node. The content-
420 frames are removed from the respective layout.
421 */
422 void DelFrames(SwRootFrame const* pLayout);
423
424 /** @return count of elements of node content. Default is 1.
425 There are differences between text node and formula node. */
426 virtual sal_Int32 Len() const;
427
428 virtual SwContentNode* MakeCopy(SwDoc&, const SwNodeIndex&, bool bNewFrames) const = 0;
429
430 /// Get information from Client.
431 virtual bool GetInfo( SfxPoolItem& ) const override;
432
433 /// SS for PoolItems: hard attributation.
434
435 /// If bInParent is FALSE search for attribute only in this node.
436 const SfxPoolItem& GetAttr( sal_uInt16 nWhich, bool bInParent=true ) const;
437 bool GetAttr( SfxItemSet& rSet ) const;
438 /// made virtual
439 virtual bool SetAttr( const SfxPoolItem& );
440 virtual bool SetAttr( const SfxItemSet& rSet );
441 virtual bool ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 = 0 );
442 virtual bool ResetAttr( const std::vector<sal_uInt16>& rWhichArr );
443 virtual sal_uInt16 ResetAllAttr();
444
445 /// Obtains attribute that is not delivered via conditional style!
446 const SfxPoolItem* GetNoCondAttr( sal_uInt16 nWhich, bool bInParents ) const;
447
448 /** Does node has already its own auto-attributes?
449 Access to SwAttrSet. */
450 inline const SwAttrSet &GetSwAttrSet() const;
451 const SwAttrSet *GetpSwAttrSet() const { return static_cast<const SwAttrSet*>(mpAttrSet.get()); }
452 bool HasSwAttrSet() const { return mpAttrSet != nullptr; }
453
454 virtual SwFormatColl* ChgFormatColl( SwFormatColl* );
455 SwFormatColl* GetFormatColl() const { return const_cast<SwFormatColl*>(static_cast<const SwFormatColl*>(GetRegisteredIn())); }
456
457//FEATURE::CONDCOLL
458 inline SwFormatColl& GetAnyFormatColl() const;
459 void SetCondFormatColl( SwFormatColl* );
460 inline SwFormatColl* GetCondFormatColl() const;
461
462 bool IsAnyCondition( SwCollCondition& rTmp ) const;
463 void ChkCondColl();
464//FEATURE::CONDCOLL
465
466 /** Invalidates NumRule at the node. NumRule is updated
467 on EndAction of a Shell at the latest. */
468 bool InvalidateNumRule();
469
470 /** determines the text direction for a certain
471 position. @return -1, if text direction could *not* be determined. */
472 SvxFrameDirection GetTextDirection( const SwPosition& rPos,
473 const Point* pPt ) const;
474
475 void SetModifyAtAttr( bool bSetModifyAtAttr ) const { mbSetModifyAtAttr = bSetModifyAtAttr; }
476 bool GetModifyAtAttr() const { return mbSetModifyAtAttr; }
477
478 static std::unique_ptr<SwOLENodes> CreateOLENodesArray( const SwFormatColl& rColl, bool bOnlyWithInvalidSize );
479
480 // Access to DrawingLayer FillAttributes in a preprocessed form for primitive usage
481 virtual drawinglayer::attribute::SdrAllFillAttributesHelperPtr getSdrAllFillAttributesHelper() const;
482
483 virtual void ModifyNotification(const SfxPoolItem* pOld, const SfxPoolItem* pNew) override
484 {
485 SwClientNotify(*this, sw::LegacyModifyHint(pOld, pNew));
486 }
487
488private:
489 SwContentNode( const SwContentNode & rNode ) = delete;
490 SwContentNode & operator= ( const SwContentNode & rNode ) = delete;
491};
492
493// SwTableNode
494
495class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwTableNode : public SwStartNode, public sw::BroadcastingModify
496{
497 friend class SwNodes;
498 std::unique_ptr<SwTable> m_pTable;
499protected:
500 virtual ~SwTableNode() override;
501
502public:
503 SwTableNode( const SwNodeIndex & );
504
505 const SwTable& GetTable() const { return *m_pTable; }
506 SwTable& GetTable() { return *m_pTable; }
507 SwTabFrame *MakeFrame( SwFrame* );
508
509 /// Creates the frms for the table node (i.e. the TabFrames).
510 void MakeOwnFrames(SwNodeIndex* pIdxBehind);
511
512 /** Method deletes all views of document for the node.
513 The content frames are removed from the respective layout. */
514 void DelFrames(SwRootFrame const* pLayout = nullptr);
515
516 /** Method creates all views of the document for the previous node.
517 The content frames that are created are put into the respective layout. */
518 void MakeFramesForAdjacentContentNode(const SwNodeIndex & rIdx);
519
520 SwTableNode* MakeCopy( SwDoc&, const SwNodeIndex& ) const;
521 void SetNewTable( std::unique_ptr<SwTable> , bool bNewFrames=true );
522
523 // Removes redline objects that relate to this table from the 'Extra Redlines' table
524 void RemoveRedlines();
525
526private:
527 SwTableNode( const SwTableNode & rNode ) = delete;
528 SwTableNode & operator= ( const SwTableNode & rNode ) = delete;
529};
530
531class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwSectionNode
532 : public SwStartNode
533{
534 friend class SwNodes;
535
536private:
537 SwSectionNode(const SwSectionNode&) = delete;
538 SwSectionNode& operator=(const SwSectionNode&) = delete;
539
540 std::unique_ptr<SwSection> const m_pSection;
541
542protected:
543 virtual ~SwSectionNode() override;
544
545public:
546 SwSectionNode(SwNodeIndex const&,
547 SwSectionFormat & rFormat, SwTOXBase const*const pTOXBase);
548
549 const SwSection& GetSection() const { return *m_pSection; }
550 SwSection& GetSection() { return *m_pSection; }
551
552 SwFrame *MakeFrame( SwFrame* );
553
554 /** Creates the frms for the SectionNode (i.e. the SectionFrames).
555 On default the frames are created until the end of the range.
556 When another NodeIndex pEnd is passed a MakeFrames is called up to it.
557 Used by TableToText. */
558 void MakeOwnFrames(SwNodeIndex* pIdxBehind, SwNodeIndex* pEnd = nullptr);
559
560 /** Method deletes all views of document for the node. The
561 content frames are removed from the respective layout. */
562 void DelFrames(SwRootFrame const* pLayout = nullptr, bool bForce = false);
563
564 /** Method creates all views of document for the previous node.
565 The content frames created are put into the respective layout. */
566 void MakeFramesForAdjacentContentNode(const SwNodeIndex & rIdx);
567
568 SwSectionNode* MakeCopy( SwDoc&, const SwNodeIndex& ) const;
569
570 /// Set pointer in format of section on itself.
571 void NodesArrChgd();
572
573 /** Check for not hidden areas whether there is content that is not in
574 a hidden sub-area. */
575 bool IsContentHidden() const;
576
577};
578
579/** This class is internal, used only during DocumentContentOperationsManager::CopyWithFlyInFly(), and for undo.
580
581Some of the nodes are then replaced with SwPlaceholderNode, and at the end of the operation, removed again.
582FIXME find out if this is really necessary, and if we can avoid creation of the SwPlaceholderNodes in the first place.
583*/
584class SwPlaceholderNode final : private SwNode
585{
586private:
587 friend class SwNodes;
588 SwPlaceholderNode(const SwNodeIndex &rWhere);
589};
590
591inline SwEndNode *SwNode::GetEndNode()
592{
593 return SwNodeType::End == m_nNodeType ? static_cast<SwEndNode*>(this) : nullptr;
594}
595inline const SwEndNode *SwNode::GetEndNode() const
596{
597 return SwNodeType::End == m_nNodeType ? static_cast<const SwEndNode*>(this) : nullptr;
598}
599inline SwStartNode *SwNode::GetStartNode()
600{
601 return SwNodeType::Start & m_nNodeType ? static_cast<SwStartNode*>(this) : nullptr;
602}
603inline const SwStartNode *SwNode::GetStartNode() const
604{
605 return SwNodeType::Start & m_nNodeType ? static_cast<const SwStartNode*>(this) : nullptr;
606}
607inline SwTableNode *SwNode::GetTableNode()
608{
609 return SwNodeType::Table == m_nNodeType ? static_cast<SwTableNode*>(this) : nullptr;
610}
611inline const SwTableNode *SwNode::GetTableNode() const
612{
613 return SwNodeType::Table == m_nNodeType ? static_cast<const SwTableNode*>(this) : nullptr;
614}
615inline SwSectionNode *SwNode::GetSectionNode()
616{
617 return SwNodeType::Section == m_nNodeType ? static_cast<SwSectionNode*>(this) : nullptr;
618}
619inline const SwSectionNode *SwNode::GetSectionNode() const
620{
621 return SwNodeType::Section == m_nNodeType ? static_cast<const SwSectionNode*>(this) : nullptr;
622}
623inline SwContentNode *SwNode::GetContentNode()
624{
625 return SwNodeType::ContentMask & m_nNodeType ? static_cast<SwContentNode*>(this) : nullptr;
626}
627inline const SwContentNode *SwNode::GetContentNode() const
628{
629 return SwNodeType::ContentMask & m_nNodeType ? static_cast<const SwContentNode*>(this) : nullptr;
630}
631
632inline bool SwNode::IsStartNode() const
633{
634 return bool(SwNodeType::Start & m_nNodeType);
635}
636inline bool SwNode::IsContentNode() const
637{
638 return bool(SwNodeType::ContentMask & m_nNodeType);
9
Calling 'Wrap::operator bool'
12
Returning from 'Wrap::operator bool'
13
Returning zero, which participates in a condition later
639}
640inline bool SwNode::IsEndNode() const
641{
642 return SwNodeType::End == m_nNodeType;
27
Assuming End is equal to field 'm_nNodeType'
28
Returning the value 1, which participates in a condition later
643}
644inline bool SwNode::IsTextNode() const
645{
646 return SwNodeType::Text == m_nNodeType;
647}
648inline bool SwNode::IsTableNode() const
649{
650 return SwNodeType::Table == m_nNodeType;
17
Assuming Table is not equal to field 'm_nNodeType'
18
Returning zero, which participates in a condition later
651}
652inline bool SwNode::IsSectionNode() const
653{
654 return SwNodeType::Section == m_nNodeType;
22
Assuming Section is not equal to field 'm_nNodeType'
23
Returning zero, which participates in a condition later
31
Assuming Section is equal to field 'm_nNodeType'
32
Returning the value 1, which participates in a condition later
655}
656inline bool SwNode::IsNoTextNode() const
657{
658 return bool(SwNodeType::NoTextMask & m_nNodeType);
659}
660inline bool SwNode::IsOLENode() const
661{
662 return SwNodeType::Ole == m_nNodeType;
663}
664inline bool SwNode::IsGrfNode() const
665{
666 return SwNodeType::Grf == m_nNodeType;
667}
668
669inline const SwStartNode* SwNode::FindSttNodeByType( SwStartNodeType eTyp ) const
670{
671 return const_cast<SwNode*>(this)->FindSttNodeByType( eTyp );
672}
673inline const SwTableNode* SwNode::FindTableNode() const
674{
675 return const_cast<SwNode*>(this)->FindTableNode();
676}
677inline const SwSectionNode* SwNode::FindSectionNode() const
678{
679 return const_cast<SwNode*>(this)->FindSectionNode();
680}
681inline sal_uLong SwNode::StartOfSectionIndex() const
682{
683 return m_pStartOfSection->GetIndex();
684}
685inline sal_uLong SwNode::EndOfSectionIndex() const
686{
687 const SwStartNode* pStNd = IsStartNode() ? static_cast<const SwStartNode*>(this) : m_pStartOfSection;
688 return pStNd->m_pEndOfSection->GetIndex();
689}
690inline const SwEndNode* SwNode::EndOfSectionNode() const
691{
692 const SwStartNode* pStNd = IsStartNode() ? static_cast<const SwStartNode*>(this) : m_pStartOfSection;
693 return pStNd->m_pEndOfSection;
694}
695inline SwEndNode* SwNode::EndOfSectionNode()
696{
697 const SwStartNode* pStNd = IsStartNode() ? static_cast<const SwStartNode*>(this) : m_pStartOfSection;
698 return pStNd->m_pEndOfSection;
699}
700
701inline SwNodes& SwNode::GetNodes()
702{
703 return static_cast<SwNodes&>(GetArray());
704}
705inline const SwNodes& SwNode::GetNodes() const
706{
707 return static_cast<SwNodes&>(GetArray());
708}
709
710inline SwFormatColl* SwContentNode::GetCondFormatColl() const
711{
712 return m_pCondColl;
713}
714
715inline SwFormatColl& SwContentNode::GetAnyFormatColl() const
716{
717 return m_pCondColl
718 ? *m_pCondColl
719 : *const_cast<SwFormatColl*>(static_cast<const SwFormatColl*>(GetRegisteredIn()));
720}
721
722inline const SwAttrSet& SwContentNode::GetSwAttrSet() const
723{
724 return mpAttrSet ? *GetpSwAttrSet() : GetAnyFormatColl().GetAttrSet();
725}
726
727//FEATURE::CONDCOLL
728
729inline const SfxPoolItem& SwContentNode::GetAttr( sal_uInt16 nWhich,
730 bool bInParents ) const
731{
732 return GetSwAttrSet().Get( nWhich, bInParents );
733}
734
735inline SwPlaceholderNode::SwPlaceholderNode(const SwNodeIndex &rWhere)
736 : SwNode(rWhere, SwNodeType::PlaceHolder)
737{
738}
739
740inline SwNodePtr SwNodes::operator[]( sal_uLong n ) const
741{
742 return static_cast<SwNodePtr>(BigPtrArray::operator[] ( n ));
743}
744
745#endif
746
747/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_O3TL_TYPED_FLAGS_SET_HXX
21#define INCLUDED_O3TL_TYPED_FLAGS_SET_HXX
22
23#include <sal/config.h>
24
25#include <cassert>
26#include <type_traits>
27
28#include <o3tl/underlyingenumvalue.hxx>
29#include <sal/types.h>
30
31namespace o3tl {
32
33namespace detail {
34
35template<typename T> constexpr
36typename std::enable_if<std::is_signed<T>::value, bool>::type isNonNegative(
37 T value)
38{
39 return value >= 0;
40}
41
42template<typename T> constexpr
43typename std::enable_if<std::is_unsigned<T>::value, bool>::type isNonNegative(T)
44{
45 return true;
46}
47
48}
49
50template<typename T> struct typed_flags {};
51
52/// Mark a (scoped) enumeration as a set of bit flags, with accompanying
53/// operations.
54///
55/// template<>
56/// struct o3tl::typed_flags<TheE>: o3tl::is_typed_flags<TheE, TheM> {};
57///
58/// All relevant values must be non-negative. (Typically, the enumeration's
59/// underlying type will either be fixed and unsigned, or it will be unfixed---
60/// and can thus default to a signed type---and all enumerators will have non-
61/// negative values.)
62///
63/// \param E the enumeration type.
64/// \param M the all-bits-set value for the bit flags.
65template<typename E, typename std::underlying_type<E>::type M>
66struct is_typed_flags {
67 static_assert(
68 M >= 0, "is_typed_flags expects only non-negative bit values");
69
70 typedef E Self;
71
72 class Wrap {
73 public:
74 typedef is_typed_flags Unwrapped;
75
76 explicit constexpr Wrap(typename std::underlying_type<E>::type value):
77 value_(value)
78 {
79 assert(detail::isNonNegative(value))(static_cast <bool> (detail::isNonNegative(value)) ? void
(0) : __assert_fail ("detail::isNonNegative(value)", "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 79, __extension__ __PRETTY_FUNCTION__))
;
80 assert((static_cast <bool> (static_cast<typename std::underlying_type
<E>::type>(~0) == M || (value & ~M) == 0) ? void
(0) : __assert_fail ("static_cast<typename std::underlying_type<E>::type>(~0) == M || (value & ~M) == 0"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 84, __extension__ __PRETTY_FUNCTION__))
81 static_cast<typename std::underlying_type<E>::type>(~0) == M(static_cast <bool> (static_cast<typename std::underlying_type
<E>::type>(~0) == M || (value & ~M) == 0) ? void
(0) : __assert_fail ("static_cast<typename std::underlying_type<E>::type>(~0) == M || (value & ~M) == 0"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 84, __extension__ __PRETTY_FUNCTION__))
82 // avoid "operands don't affect result" warnings when M(static_cast <bool> (static_cast<typename std::underlying_type
<E>::type>(~0) == M || (value & ~M) == 0) ? void
(0) : __assert_fail ("static_cast<typename std::underlying_type<E>::type>(~0) == M || (value & ~M) == 0"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 84, __extension__ __PRETTY_FUNCTION__))
83 // covers all bits of the underlying type(static_cast <bool> (static_cast<typename std::underlying_type
<E>::type>(~0) == M || (value & ~M) == 0) ? void
(0) : __assert_fail ("static_cast<typename std::underlying_type<E>::type>(~0) == M || (value & ~M) == 0"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 84, __extension__ __PRETTY_FUNCTION__))
84 || (value & ~M) == 0)(static_cast <bool> (static_cast<typename std::underlying_type
<E>::type>(~0) == M || (value & ~M) == 0) ? void
(0) : __assert_fail ("static_cast<typename std::underlying_type<E>::type>(~0) == M || (value & ~M) == 0"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 84, __extension__ __PRETTY_FUNCTION__))
;
85 }
86
87 constexpr operator E() const { return static_cast<E>(value_); }
88
89 explicit constexpr operator typename std::underlying_type<E>::type()
90 const
91 { return value_; }
92
93 explicit constexpr operator bool() const { return value_ != 0; }
10
Assuming field 'value_' is equal to 0
11
Returning zero, which participates in a condition later
94
95 private:
96 typename std::underlying_type<E>::type value_;
97 };
98
99 static typename std::underlying_type<E>::type const mask = M;
100};
101
102}
103
104template<typename E>
105constexpr typename o3tl::typed_flags<E>::Wrap operator ~(E rhs) {
106 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 108, __extension__ __PRETTY_FUNCTION__))
107 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 108, __extension__ __PRETTY_FUNCTION__))
108 o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 108, __extension__ __PRETTY_FUNCTION__))
;
109 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
110 o3tl::typed_flags<E>::mask
111 & ~o3tl::underlyingEnumValue(rhs));
112}
113
114template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ~(
115 typename o3tl::typed_flags<E>::Wrap rhs)
116{
117 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
118 o3tl::typed_flags<E>::mask
119 & ~o3tl::underlyingEnumValue<E>(rhs));
120}
121
122template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
123 E lhs, E rhs)
124{
125 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 127, __extension__ __PRETTY_FUNCTION__))
126 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 127, __extension__ __PRETTY_FUNCTION__))
127 o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 127, __extension__ __PRETTY_FUNCTION__))
;
128 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 130, __extension__ __PRETTY_FUNCTION__))
129 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 130, __extension__ __PRETTY_FUNCTION__))
130 o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 130, __extension__ __PRETTY_FUNCTION__))
;
131 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
132 o3tl::underlyingEnumValue(lhs)
133 ^ o3tl::underlyingEnumValue(rhs));
134}
135
136template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
137 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
138{
139 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 141, __extension__ __PRETTY_FUNCTION__))
140 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 141, __extension__ __PRETTY_FUNCTION__))
141 o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 141, __extension__ __PRETTY_FUNCTION__))
;
142 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
143 o3tl::underlyingEnumValue(lhs)
144 ^ o3tl::underlyingEnumValue<E>(rhs));
145}
146
147template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
148 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
149{
150 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 152, __extension__ __PRETTY_FUNCTION__))
151 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 152, __extension__ __PRETTY_FUNCTION__))
152 o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 152, __extension__ __PRETTY_FUNCTION__))
;
153 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
154 o3tl::underlyingEnumValue<E>(lhs)
155 ^ o3tl::underlyingEnumValue(rhs));
156}
157
158template<typename W> constexpr
159typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator ^(
160 W lhs, W rhs)
161{
162 return static_cast<W>(
163 o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(lhs)
164 ^ o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(rhs));
165}
166
167template<typename E>
168constexpr typename o3tl::typed_flags<E>::Wrap operator &(E lhs, E rhs) {
169 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 171, __extension__ __PRETTY_FUNCTION__))
170 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 171, __extension__ __PRETTY_FUNCTION__))
171 o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 171, __extension__ __PRETTY_FUNCTION__))
;
172 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 174, __extension__ __PRETTY_FUNCTION__))
173 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 174, __extension__ __PRETTY_FUNCTION__))
174 o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 174, __extension__ __PRETTY_FUNCTION__))
;
175 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
176 o3tl::underlyingEnumValue(lhs)
177 & o3tl::underlyingEnumValue(rhs));
178}
179
180template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator &(
181 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
182{
183 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 185, __extension__ __PRETTY_FUNCTION__))
184 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 185, __extension__ __PRETTY_FUNCTION__))
185 o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 185, __extension__ __PRETTY_FUNCTION__))
;
186 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
187 o3tl::underlyingEnumValue(lhs)
188 & o3tl::underlyingEnumValue<E>(rhs));
189}
190
191template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator &(
192 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
193{
194 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 196, __extension__ __PRETTY_FUNCTION__))
195 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 196, __extension__ __PRETTY_FUNCTION__))
196 o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 196, __extension__ __PRETTY_FUNCTION__))
;
197 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
198 o3tl::underlyingEnumValue<E>(lhs)
199 & o3tl::underlyingEnumValue(rhs));
200}
201
202template<typename W> constexpr
203typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator &(
204 W lhs, W rhs)
205{
206 return static_cast<W>(
207 o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(lhs)
208 & o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(rhs));
209}
210
211template<typename E>
212constexpr typename o3tl::typed_flags<E>::Wrap operator |(E lhs, E rhs) {
213 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 215, __extension__ __PRETTY_FUNCTION__))
214 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 215, __extension__ __PRETTY_FUNCTION__))
215 o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 215, __extension__ __PRETTY_FUNCTION__))
;
216 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 218, __extension__ __PRETTY_FUNCTION__))
217 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 218, __extension__ __PRETTY_FUNCTION__))
218 o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 218, __extension__ __PRETTY_FUNCTION__))
;
219 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
220 o3tl::underlyingEnumValue(lhs)
221 | o3tl::underlyingEnumValue(rhs));
222}
223
224template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator |(
225 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
226{
227 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 229, __extension__ __PRETTY_FUNCTION__))
228 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 229, __extension__ __PRETTY_FUNCTION__))
229 o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 229, __extension__ __PRETTY_FUNCTION__))
;
230 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
231 o3tl::underlyingEnumValue(lhs)
232 | o3tl::underlyingEnumValue<E>(rhs));
233}
234
235template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator |(
236 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
237{
238 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 240, __extension__ __PRETTY_FUNCTION__))
239 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 240, __extension__ __PRETTY_FUNCTION__))
240 o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 240, __extension__ __PRETTY_FUNCTION__))
;
241 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
242 o3tl::underlyingEnumValue<E>(lhs)
243 | o3tl::underlyingEnumValue(rhs));
244}
245
246template<typename W> constexpr
247typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator |(
248 W lhs, W rhs)
249{
250 return static_cast<W>(
251 o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(lhs)
252 | o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(rhs));
253}
254
255template<typename E>
256inline typename o3tl::typed_flags<E>::Self operator &=(E & lhs, E rhs) {
257 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 259, __extension__ __PRETTY_FUNCTION__))
258 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 259, __extension__ __PRETTY_FUNCTION__))
259 o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 259, __extension__ __PRETTY_FUNCTION__))
;
260 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 262, __extension__ __PRETTY_FUNCTION__))
261 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 262, __extension__ __PRETTY_FUNCTION__))
262 o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 262, __extension__ __PRETTY_FUNCTION__))
;
263 lhs = lhs & rhs;
264 return lhs;
265}
266
267template<typename E>
268inline typename o3tl::typed_flags<E>::Self operator &=(
269 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
270{
271 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 273, __extension__ __PRETTY_FUNCTION__))
272 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 273, __extension__ __PRETTY_FUNCTION__))
273 o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 273, __extension__ __PRETTY_FUNCTION__))
;
274 lhs = lhs & rhs;
275 return lhs;
276}
277
278template<typename E>
279inline typename o3tl::typed_flags<E>::Self operator |=(E & lhs, E rhs) {
280 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 282, __extension__ __PRETTY_FUNCTION__))
281 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 282, __extension__ __PRETTY_FUNCTION__))
282 o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 282, __extension__ __PRETTY_FUNCTION__))
;
283 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 285, __extension__ __PRETTY_FUNCTION__))
284 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 285, __extension__ __PRETTY_FUNCTION__))
285 o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 285, __extension__ __PRETTY_FUNCTION__))
;
286 lhs = lhs | rhs;
287 return lhs;
288}
289
290template<typename E>
291inline typename o3tl::typed_flags<E>::Self operator |=(
292 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
293{
294 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 296, __extension__ __PRETTY_FUNCTION__))
295 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 296, __extension__ __PRETTY_FUNCTION__))
296 o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 296, __extension__ __PRETTY_FUNCTION__))
;
297 lhs = lhs | rhs;
298 return lhs;
299}
300
301template<typename E>
302inline typename o3tl::typed_flags<E>::Self operator ^=(E & lhs, E rhs) {
303 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 305, __extension__ __PRETTY_FUNCTION__))
304 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 305, __extension__ __PRETTY_FUNCTION__))
305 o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 305, __extension__ __PRETTY_FUNCTION__))
;
306 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 308, __extension__ __PRETTY_FUNCTION__))
307 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 308, __extension__ __PRETTY_FUNCTION__))
308 o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 308, __extension__ __PRETTY_FUNCTION__))
;
309 lhs = lhs ^ rhs;
310 return lhs;
311}
312
313template<typename E>
314inline typename o3tl::typed_flags<E>::Self operator ^=(
315 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
316{
317 assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 319, __extension__ __PRETTY_FUNCTION__))
318 o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 319, __extension__ __PRETTY_FUNCTION__))
319 o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl::
underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))"
, "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx"
, 319, __extension__ __PRETTY_FUNCTION__))
;
320 lhs = lhs ^ rhs;
321 return lhs;
322}
323
324#endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */
325
326/* vim:set shiftwidth=4 softtabstop=4 expandtab: */