Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx
Warning:line 1599, column 35
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 feshview.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/frmedt/feshview.cxx

/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.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 <hintids.hxx>
21#include <svx/strings.hrc>
22#include <svx/sdrobjectfilter.hxx>
23#include <svx/svddrgmt.hxx>
24#include <svx/svditer.hxx>
25#include <svx/svdobj.hxx>
26#include <svx/svdouno.hxx>
27#include <svx/svdogrp.hxx>
28#include <svx/svdocirc.hxx>
29#include <svx/svdopath.hxx>
30#include <svx/sxciaitm.hxx>
31#include <svx/svdocapt.hxx>
32#include <svx/xlnwtit.hxx>
33#include <svx/xlnstwit.hxx>
34#include <svx/xlnedwit.hxx>
35#include <svx/xlnedit.hxx>
36#include <svx/xlnstit.hxx>
37#include <svx/svdomeas.hxx>
38#include <svx/sdtagitm.hxx>
39#include <svx/sdtacitm.hxx>
40#include <svx/sdtaaitm.hxx>
41#include <editeng/opaqitem.hxx>
42#include <editeng/protitem.hxx>
43#include <svx/svdpage.hxx>
44#include <svx/svdpagv.hxx>
45#include <svx/dialmgr.hxx>
46#include <tools/globname.hxx>
47#include <sot/exchange.hxx>
48#include <IDocumentDrawModelAccess.hxx>
49#include <IDocumentSettingAccess.hxx>
50#include <DocumentSettingManager.hxx>
51#include <IDocumentState.hxx>
52#include <IDocumentLayoutAccess.hxx>
53#include <drawdoc.hxx>
54#include <textboxhelper.hxx>
55#include <frmfmt.hxx>
56#include <frmatr.hxx>
57#include <frmtool.hxx>
58#include <fmtfsize.hxx>
59#include <fmtanchr.hxx>
60#include <fmtornt.hxx>
61#include <fmtsrnd.hxx>
62#include <fmtcntnt.hxx>
63#include <fmtflcnt.hxx>
64#include <fmtcnct.hxx>
65#include <swmodule.hxx>
66#include <fesh.hxx>
67#include <rootfrm.hxx>
68#include <pagefrm.hxx>
69#include <sectfrm.hxx>
70#include <doc.hxx>
71#include <IDocumentUndoRedo.hxx>
72#include <dview.hxx>
73#include <dflyobj.hxx>
74#include <dcontact.hxx>
75#include <viewimp.hxx>
76#include <flyfrm.hxx>
77#include <pam.hxx>
78#include <ndole.hxx>
79#include <ndgrf.hxx>
80#include <ndtxt.hxx>
81#include <viewopt.hxx>
82#include <swundo.hxx>
83#include <notxtfrm.hxx>
84#include <txtfrm.hxx>
85#include <mdiexp.hxx>
86#include <sortedobjs.hxx>
87#include <HandleAnchorNodeChg.hxx>
88#include <basegfx/polygon/b2dpolygon.hxx>
89#include <comphelper/lok.hxx>
90#include <sfx2/lokhelper.hxx>
91#include <LibreOfficeKit/LibreOfficeKitEnums.h>
92#include <calbck.hxx>
93#include <basegfx/polygon/b2dpolygontools.hxx>
94#include <svx/svxids.hrc>
95
96#include <com/sun/star/embed/EmbedMisc.hpp>
97#include <com/sun/star/embed/Aspects.hpp>
98#include <com/sun/star/embed/XEmbeddedObject.hpp>
99
100#include <svx/srchdlg.hxx>
101
102#define SCROLLVAL75 75
103
104using namespace com::sun::star;
105
106/**
107 * set line starts and ends for the object to be created
108 */
109
110namespace {
111
112::basegfx::B2DPolyPolygon getPolygon(const char* pResId, const SdrModel& rModel)
113{
114 ::basegfx::B2DPolyPolygon aRetval;
115 XLineEndListRef pLineEndList(rModel.GetLineEndList());
116
117 if( pLineEndList.is() )
118 {
119 OUString aArrowName( SvxResId(pResId) );
120 long nCount = pLineEndList->Count();
121 long nIndex;
122 for( nIndex = 0; nIndex < nCount; nIndex++ )
123 {
124 const XLineEndEntry* pEntry = pLineEndList->GetLineEnd(nIndex);
125 if( pEntry->GetName() == aArrowName )
126 {
127 aRetval = pEntry->GetLineEnd();
128 break;
129 }
130 }
131 }
132
133 return aRetval;
134}
135
136}
137
138SwFlyFrame *GetFlyFromMarked( const SdrMarkList *pLst, SwViewShell *pSh )
139{
140 if ( !pLst )
141 pLst = pSh->HasDrawView() ? &pSh->Imp()->GetDrawView()->GetMarkedObjectList():nullptr;
142
143 if ( pLst && pLst->GetMarkCount() == 1 )
144 {
145 SdrObject *pO = pLst->GetMark( 0 )->GetMarkedSdrObj();
146 if (SwVirtFlyDrawObj* pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pO))
147 return pVirtO->GetFlyFrame();
148 }
149 return nullptr;
150}
151
152static void lcl_GrabCursor( SwFEShell* pSh, SwFlyFrame* pOldSelFly)
153{
154 const SwFrameFormat *pFlyFormat = pSh->SelFlyGrabCursor();
155 if( pFlyFormat && !pSh->ActionPend() &&
156 (!pOldSelFly || pOldSelFly->GetFormat() != pFlyFormat) )
157 {
158 // now call set macro if applicable
159 pSh->GetFlyMacroLnk().Call( static_cast<const SwFlyFrameFormat*>(pFlyFormat) );
160 // if a dialog was started inside a macro, then
161 // MouseButtonUp arrives at macro and not to us. Therefore
162 // flag is always set here and will never be switched to
163 // respective Shell !!!!!!!
164
165 g_bNoInterrupt = false;
166 }
167 else if( !pFlyFormat || RES_DRAWFRMFMT == pFlyFormat->Which() )
168 {
169 // --> assure consistent cursor
170 pSh->KillPams();
171 pSh->ClearMark();
172 pSh->SetCursor( pSh->Imp()->GetDrawView()->GetAllMarkedRect().TopLeft(), true);
173 }
174}
175
176bool SwFEShell::SelectObj( const Point& rPt, sal_uInt8 nFlag, SdrObject *pObj )
177{
178 SwDrawView *pDView = Imp()->GetDrawView();
179 if(!pDView)
180 return false;
181 CurrShell aCurr( this );
182 StartAction(); // action is necessary to assure only one AttrChgdNotify
183 // (e.g. due to Unmark->MarkListHasChgd) arrives
184
185 const SdrMarkList &rMrkList = pDView->GetMarkedObjectList();
186 const bool bHadSelection = rMrkList.GetMarkCount();
187 const bool bAddSelect = 0 != (SW_ADD_SELECT1 & nFlag);
188 const bool bEnterGroup = 0 != (SW_ENTER_GROUP2 & nFlag);
189 SwFlyFrame* pOldSelFly = nullptr;
190 const Point aOldPos( pDView->GetAllMarkedRect().TopLeft() );
191
192 if( bHadSelection )
193 {
194 // call Unmark when !bAddSelect or if fly was selected
195 bool bUnmark = !bAddSelect;
196
197 if ( rMrkList.GetMarkCount() == 1 )
198 {
199 // if fly was selected, deselect it first
200 pOldSelFly = ::GetFlyFromMarked( &rMrkList, this );
201 if ( pOldSelFly )
202 {
203 const sal_uInt16 nType = GetCntType();
204 if( nType != CNT_TXT0x0001 || (SW_LEAVE_FRAME4 & nFlag) ||
205 ( pOldSelFly->GetFormat()->GetProtect().IsContentProtected()
206 && !IsReadOnlyAvailable() ))
207 {
208 // If a fly is deselected, which contains graphic, OLE or
209 // otherwise, the cursor should be removed from it.
210 // Similar if a fly with protected content is deselected.
211 // For simplicity we put the cursor next to the upper-left
212 // corner.
213 Point aPt( pOldSelFly->getFrameArea().Pos() );
214 aPt.setX(aPt.getX() - 1);
215 bool bUnLockView = !IsViewLocked();
216 LockView( true );
217 SetCursor( aPt, true );
218 if( bUnLockView )
219 LockView( false );
220 }
221 if ( nType & CNT_GRF0x0002 &&
222 static_cast<SwNoTextFrame*>(pOldSelFly->Lower())->HasAnimation() )
223 {
224 GetWin()->Invalidate( pOldSelFly->getFrameArea().SVRect() );
225 }
226
227 // Cancel crop mode
228 if ( SdrDragMode::Crop == GetDragMode() )
229 SetDragMode( SdrDragMode::Move );
230
231 bUnmark = true;
232 }
233 }
234 if ( bUnmark )
235 {
236 pDView->UnmarkAll();
237 if (pOldSelFly)
238 pOldSelFly->SelectionHasChanged(this);
239 }
240 }
241 else
242 {
243 KillPams();
244 ClearMark();
245 }
246
247 if ( pObj )
248 {
249 OSL_ENSURE( !bEnterGroup, "SW_ENTER_GROUP is not supported" )do { if (true && (!(!bEnterGroup))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "249" ": "), "%s", "SW_ENTER_GROUP is not supported"); }
} while (false)
;
250 pDView->MarkObj( pObj, Imp()->GetPageView() );
251 }
252 else
253 {
254 // tolerance limit of Drawing-SS
255 const auto nHdlSizePixel = Imp()->GetDrawView()->GetMarkHdlSizePixel();
256 const short nMinMove = static_cast<short>(GetOut()->PixelToLogic(Size(nHdlSizePixel/2, 0)).Width());
257 pDView->MarkObj( rPt, nMinMove, bAddSelect, bEnterGroup );
258 }
259
260 const bool bRet = 0 != rMrkList.GetMarkCount();
261
262 if ( rMrkList.GetMarkCount() > 1 )
263 {
264 // It sucks if Drawing objects were selected and now
265 // additionally a fly is selected.
266 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
267 {
268 SdrObject *pTmpObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
269 bool bForget = dynamic_cast<const SwVirtFlyDrawObj*>( pTmpObj) != nullptr;
270 if( bForget )
271 {
272 pDView->UnmarkAll();
273 pDView->MarkObj( pTmpObj, Imp()->GetPageView(), bAddSelect, bEnterGroup );
274 break;
275 }
276 }
277 }
278
279 if ( rMrkList.GetMarkCount() == 1 )
280 {
281 SwFlyFrame *pSelFly = ::GetFlyFromMarked( &rMrkList, this );
282 if (pSelFly)
283 pSelFly->SelectionHasChanged(this);
284 }
285
286 if (!(nFlag & SW_ALLOW_TEXTBOX8))
287 {
288 // If the fly frame is a textbox of a shape, then select the shape instead.
289 for (size_t i = 0; i < rMrkList.GetMarkCount(); ++i)
290 {
291 SdrObject* pObject = rMrkList.GetMark(i)->GetMarkedSdrObj();
292 SwFrameFormat* pFormat = GetUserCall(pObject)->GetFormat();
293 if (SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_FLYFRMFMT))
294 {
295 SdrObject* pShape = pShapeFormat->FindSdrObject();
296 pDView->UnmarkAll();
297 pDView->MarkObj(pShape, Imp()->GetPageView(), bAddSelect, bEnterGroup);
298 break;
299 }
300 }
301 }
302
303 if ( bRet )
304 {
305 ::lcl_GrabCursor(this, pOldSelFly);
306 if ( GetCntType() & CNT_GRF0x0002 )
307 {
308 const SwFlyFrame *pTmp = GetFlyFromMarked( &rMrkList, this );
309 OSL_ENSURE( pTmp, "Graphic without Fly" )do { if (true && (!(pTmp))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "309" ": "), "%s", "Graphic without Fly"); } } while (false
)
;
310 if ( static_cast<const SwNoTextFrame*>(pTmp->Lower())->HasAnimation() )
311 static_cast<const SwNoTextFrame*>(pTmp->Lower())->StopAnimation( GetOut() );
312 }
313 }
314 else if ( !pOldSelFly && bHadSelection )
315 SetCursor( aOldPos, true);
316
317 if( bRet || !bHadSelection )
318 CallChgLnk();
319
320 // update status line
321 ::FrameNotify( this, bRet ? FLY_DRAG_START : FLY_DRAG_END );
322
323 EndAction();
324 return bRet;
325}
326
327/*
328 * Description: MoveAnchor( nDir ) looked for an another Anchor for
329 * the selected drawing object (or fly frame) in the given direction.
330 * An object "as character" doesn't moves anyway.
331 * A page bounded object could move to the previous/next page with up/down,
332 * an object bounded "at paragraph" moves to the previous/next paragraph, too.
333 * An object bounded "at character" moves to the previous/next paragraph
334 * with up/down and to the previous/next character with left/right.
335 * If the anchor for at paragraph/character bounded objects has vertical or
336 * right_to_left text direction, the directions for up/down/left/right will
337 * interpreted accordingly.
338 * An object bounded "at fly" takes the center of the actual anchor and looks
339 * for the nearest fly frame in the given direction.
340 */
341
342static bool LessX( Point const & aPt1, Point const & aPt2, bool bOld )
343{
344 return aPt1.getX() < aPt2.getX()
345 || ( aPt1.getX() == aPt2.getX()
346 && ( aPt1.getY() < aPt2.getY()
347 || ( aPt1.getY() == aPt2.getY() && bOld ) ) );
348}
349static bool LessY( Point const & aPt1, Point const & aPt2, bool bOld )
350{
351 return aPt1.getY() < aPt2.getY()
352 || ( aPt1.getY() == aPt2.getY()
353 && ( aPt1.getX() < aPt2.getX()
354 || ( aPt1.getX() == aPt2.getX() && bOld ) ) );
355}
356
357bool SwFEShell::MoveAnchor( SwMove nDir )
358{
359 if (!Imp()->GetDrawView())
360 return false;
361 const SdrMarkList& pMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
362 if (1 != pMrkList.GetMarkCount())
363 return false;
364 SwFrame* pOld;
365 SwFlyFrame* pFly = nullptr;
366 SdrObject *pObj = pMrkList.GetMark( 0 )->GetMarkedSdrObj();
367 if (SwVirtFlyDrawObj* pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pObj))
368 {
369 pFly = pVirtO->GetFlyFrame();
370 pOld = pFly->AnchorFrame();
371 }
372 else
373 pOld = static_cast<SwDrawContact*>(GetUserCall(pObj))->GetAnchorFrame( pObj );
374 bool bRet = false;
375 if( pOld )
376 {
377 SwFrame* pNew = pOld;
378 // #i28701#
379 SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj );
380 SwFrameFormat& rFormat = pAnchoredObj->GetFrameFormat();
381 SwFormatAnchor aAnch( rFormat.GetAnchor() );
382 RndStdIds nAnchorId = aAnch.GetAnchorId();
383 if ( RndStdIds::FLY_AS_CHAR == nAnchorId )
384 return false;
385 if( pOld->IsVertical() )
386 {
387 if( pOld->IsTextFrame() )
388 {
389 switch( nDir ) {
390 case SwMove::UP: nDir = SwMove::LEFT; break;
391 case SwMove::DOWN: nDir = SwMove::RIGHT; break;
392 case SwMove::LEFT: nDir = SwMove::DOWN; break;
393 case SwMove::RIGHT: nDir = SwMove::UP; break;
394 }
395 if( pOld->IsRightToLeft() )
396 {
397 if( nDir == SwMove::LEFT )
398 nDir = SwMove::RIGHT;
399 else if( nDir == SwMove::RIGHT )
400 nDir = SwMove::LEFT;
401 }
402 }
403 }
404 switch ( nAnchorId ) {
405 case RndStdIds::FLY_AT_PAGE:
406 {
407 OSL_ENSURE( pOld->IsPageFrame(), "Wrong anchor, page expected." )do { if (true && (!(pOld->IsPageFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "407" ": "), "%s", "Wrong anchor, page expected."); } } while
(false)
;
408 if( SwMove::UP == nDir )
409 pNew = pOld->GetPrev();
410 else if( SwMove::DOWN == nDir )
411 pNew = pOld->GetNext();
412 if( pNew && pNew != pOld )
413 {
414 aAnch.SetPageNum( static_cast<SwPageFrame*>(pNew)->GetPhyPageNum() );
415 bRet = true;
416 }
417 break;
418 }
419 case RndStdIds::FLY_AT_CHAR:
420 {
421 OSL_ENSURE(pOld->IsTextFrame(), "Wrong anchor, text frame expected.")do { if (true && (!(pOld->IsTextFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "421" ": "), "%s", "Wrong anchor, text frame expected.")
; } } while (false)
;
422 if( SwMove::LEFT == nDir || SwMove::RIGHT == nDir )
423 {
424 SwPosition pos = *aAnch.GetContentAnchor();
425 SwTextFrame *const pOldFrame(static_cast<SwTextFrame*>(pOld));
426 TextFrameIndex const nAct(pOldFrame->MapModelToViewPos(pos));
427 if( SwMove::LEFT == nDir )
428 {
429 bRet = true;
430 if( nAct )
431 {
432 pos = pOldFrame->MapViewToModelPos(nAct - TextFrameIndex(1));
433 }
434 else
435 nDir = SwMove::UP;
436 }
437 else
438 {
439 TextFrameIndex const nMax(pOldFrame->GetText().getLength());
440 if( nAct < nMax )
441 {
442 bRet = true;
443 pos = pOldFrame->MapViewToModelPos(nAct + TextFrameIndex(1));
444 }
445 else
446 nDir = SwMove::DOWN;
447 }
448 if( pos != *aAnch.GetContentAnchor())
449 aAnch.SetAnchor( &pos );
450 }
451 [[fallthrough]];
452 }
453 case RndStdIds::FLY_AT_PARA:
454 {
455 OSL_ENSURE(pOld->IsTextFrame(), "Wrong anchor, text frame expected.")do { if (true && (!(pOld->IsTextFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "455" ": "), "%s", "Wrong anchor, text frame expected.")
; } } while (false)
;
456 if( SwMove::UP == nDir )
457 pNew = pOld->FindPrev();
458 else if( SwMove::DOWN == nDir )
459 pNew = pOld->FindNext();
460 if( pNew && pNew != pOld && pNew->IsContentFrame() )
461 {
462 SwTextFrame *const pNewFrame(static_cast<SwTextFrame*>(pNew));
463 SwPosition const pos = pNewFrame->MapViewToModelPos(
464 TextFrameIndex(
465 (bRet && pNewFrame->GetText().getLength() != 0)
466 ? pNewFrame->GetText().getLength() - 1
467 : 0));
468 aAnch.SetAnchor( &pos );
469 bRet = true;
470 }
471 else if( SwMove::UP == nDir || SwMove::DOWN == nDir )
472 bRet = false;
473 break;
474 }
475 case RndStdIds::FLY_AT_FLY:
476 {
477 OSL_ENSURE( pOld->IsFlyFrame(), "Wrong anchor, fly frame expected.")do { if (true && (!(pOld->IsFlyFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "477" ": "), "%s", "Wrong anchor, fly frame expected.");
} } while (false)
;
478 SwPageFrame* pPage = pOld->FindPageFrame();
479 OSL_ENSURE( pPage, "Where's my page?" )do { if (true && (!(pPage))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "479" ": "), "%s", "Where's my page?"); } } while (false
)
;
480 SwFlyFrame* pNewFly = nullptr;
481 if( pPage->GetSortedObjs() )
482 {
483 bool bOld = false;
484 Point aCenter( pOld->getFrameArea().Left() + pOld->getFrameArea().Width()/2,
485 pOld->getFrameArea().Top() + pOld->getFrameArea().Height()/2 );
486 Point aBest;
487 for(SwAnchoredObject* pAnchObj : *pPage->GetSortedObjs())
488 {
489 if( dynamic_cast<const SwFlyFrame*>( pAnchObj) != nullptr )
490 {
491 SwFlyFrame* pTmp = static_cast<SwFlyFrame*>(pAnchObj);
492 if( pTmp == pOld )
493 bOld = true;
494 else
495 {
496 const SwFlyFrame* pCheck = pFly ? pTmp : nullptr;
497 while( pCheck )
498 {
499 if( pCheck == pFly )
500 break;
501 const SwFrame *pNxt = pCheck->GetAnchorFrame();
502 pCheck = pNxt ? pNxt->FindFlyFrame() : nullptr;
503 }
504 if( pCheck || pTmp->IsProtected() )
505 continue;
506 Point aNew( pTmp->getFrameArea().Left() +
507 pTmp->getFrameArea().Width()/2,
508 pTmp->getFrameArea().Top() +
509 pTmp->getFrameArea().Height()/2 );
510 bool bAccept = false;
511 switch( nDir ) {
512 case SwMove::RIGHT:
513 {
514 bAccept = LessX( aCenter, aNew, bOld )
515 && ( !pNewFly ||
516 LessX( aNew, aBest, false ) );
517 break;
518 }
519 case SwMove::LEFT:
520 {
521 bAccept = LessX( aNew, aCenter, !bOld )
522 && ( !pNewFly ||
523 LessX( aBest, aNew, true ) );
524 break;
525 }
526 case SwMove::UP:
527 {
528 bAccept = LessY( aNew, aCenter, !bOld )
529 && ( !pNewFly ||
530 LessY( aBest, aNew, true ) );
531 break;
532 }
533 case SwMove::DOWN:
534 {
535 bAccept = LessY( aCenter, aNew, bOld )
536 && ( !pNewFly ||
537 LessY( aNew, aBest, false ) );
538 break;
539 }
540 }
541 if( bAccept )
542 {
543 pNewFly = pTmp;
544 aBest = aNew;
545 }
546 }
547 }
548 }
549 }
550
551 if( pNewFly )
552 {
553 SwPosition aPos( *pNewFly->GetFormat()->
554 GetContent().GetContentIdx());
555 aAnch.SetAnchor( &aPos );
556 bRet = true;
557 }
558 break;
559 }
560 default: break;
561 }
562 if( bRet )
563 {
564 StartAllAction();
565 // --> handle change of anchor node:
566 // if count of the anchor frame also change, the fly frames have to be
567 // re-created. Thus, delete all fly frames except the <this> before the
568 // anchor attribute is change and re-create them afterwards.
569 {
570 std::unique_ptr<SwHandleAnchorNodeChg, o3tl::default_delete<SwHandleAnchorNodeChg>> pHandleAnchorNodeChg;
571 SwFlyFrameFormat* pFlyFrameFormat( dynamic_cast<SwFlyFrameFormat*>(&rFormat) );
572 if ( pFlyFrameFormat )
573 {
574 pHandleAnchorNodeChg.reset(
575 new SwHandleAnchorNodeChg( *pFlyFrameFormat, aAnch ));
576 }
577 rFormat.GetDoc()->SetAttr( aAnch, rFormat );
578 }
579 // #i28701# - no call of method
580 // <CheckCharRectAndTopOfLine()> for to-character anchored
581 // Writer fly frame needed. This method call can cause a
582 // format of the anchor frame, which is no longer intended.
583 // Instead clear the anchor character rectangle and
584 // the top of line values for all to-character anchored objects.
585 pAnchoredObj->ClearCharRectAndTopOfLine();
586 EndAllAction();
587 }
588 }
589 return bRet;
590}
591
592const SdrMarkList* SwFEShell::GetMarkList_() const
593{
594 const SdrMarkList* pMarkList = nullptr;
595 if( Imp()->GetDrawView() != nullptr )
596 pMarkList = &Imp()->GetDrawView()->GetMarkedObjectList();
597 return pMarkList;
598}
599
600FrameTypeFlags SwFEShell::GetSelFrameType() const
601{
602 FrameTypeFlags eType;
603
604 // get marked frame list, and check if anything is selected
605 const SdrMarkList* pMarkList = GetMarkList_();
606 if( pMarkList == nullptr || pMarkList->GetMarkCount() == 0 )
607 eType = FrameTypeFlags::NONE;
608 else
609 {
610 // obtain marked item as fly frame; if no fly frame, it must
611 // be a draw object
612 const SwFlyFrame* pFly = ::GetFlyFromMarked(pMarkList, const_cast<SwFEShell*>(this));
613 if ( pFly != nullptr )
614 {
615 if( pFly->IsFlyLayFrame() )
616 eType = FrameTypeFlags::FLY_FREE;
617 else if( pFly->IsFlyAtContentFrame() )
618 eType = FrameTypeFlags::FLY_ATCNT;
619 else
620 {
621 OSL_ENSURE( pFly->IsFlyInContentFrame(), "New frametype?" )do { if (true && (!(pFly->IsFlyInContentFrame())))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "621" ": "), "%s", "New frametype?"); } } while (false)
;
622 eType = FrameTypeFlags::FLY_INCNT;
623 }
624 }
625 else
626 eType = FrameTypeFlags::DRAWOBJ;
627 }
628
629 return eType;
630}
631
632// does the draw selection contain a control?
633bool SwFEShell::IsSelContainsControl() const
634{
635 bool bRet = false;
636
637 // basically, copy the mechanism from GetSelFrameType(), but call
638 // CheckControl... if you get a drawing object
639 const SdrMarkList* pMarkList = GetMarkList_();
640 if( pMarkList != nullptr && pMarkList->GetMarkCount() == 1 )
641 {
642 // if we have one marked object, get the SdrObject and check
643 // whether it contains a control
644 const SdrObject* pSdrObject = pMarkList->GetMark( 0 )->GetMarkedSdrObj();
645 bRet = pSdrObject && ::CheckControlLayer( pSdrObject );
646 }
647 return bRet;
648}
649
650void SwFEShell::ScrollTo( const Point &rPt )
651{
652 const SwRect aRect( rPt, rPt );
653 if ( IsScrollMDI( this, aRect ) &&
654 (!Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ||
655 Imp()->IsDragPossible( rPt )) )
656 {
657 ScrollMDI( this, aRect, SCROLLVAL75, SCROLLVAL75 );
658 }
659}
660
661void SwFEShell::SetDragMode( SdrDragMode eDragMode )
662{
663 if ( Imp()->HasDrawView() )
664 Imp()->GetDrawView()->SetDragMode( eDragMode );
665}
666
667SdrDragMode SwFEShell::GetDragMode() const
668{
669 SdrDragMode nRet = SdrDragMode(0);
670 if ( Imp()->HasDrawView() )
671 {
672 nRet = Imp()->GetDrawView()->GetDragMode();
673 }
674 return nRet;
675}
676
677void SwFEShell::StartCropImage()
678{
679 if ( !Imp()->HasDrawView() )
680 {
681 return;
682 }
683 SdrView *pView = Imp()->GetDrawView();
684 if (!pView) return;
685
686 const SdrMarkList &rMarkList = pView->GetMarkedObjectList();
687 if( 0 == rMarkList.GetMarkCount() ) {
688 // No object selected
689 return;
690 }
691
692 // If more than a single SwVirtFlyDrawObj is selected, select only the first SwVirtFlyDrawObj
693 if ( rMarkList.GetMarkCount() > 1 )
694 {
695 for ( size_t i = 0; i < rMarkList.GetMarkCount(); ++i )
696 {
697 SdrObject *pTmpObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
698 bool bForget = dynamic_cast<const SwVirtFlyDrawObj*>( pTmpObj) != nullptr;
699 if( bForget )
700 {
701 pView->UnmarkAll();
702 pView->MarkObj( pTmpObj, Imp()->GetPageView() );
703 break;
704 }
705 }
706 }
707
708 // Activate CROP mode
709 pView->SetEditMode( SdrViewEditMode::Edit );
710 SetDragMode( SdrDragMode::Crop );
711}
712
713void SwFEShell::BeginDrag( const Point* pPt, bool bIsShift)
714{
715 SdrView *pView = Imp()->GetDrawView();
716 if ( pView && pView->AreObjectsMarked() )
717 {
718 m_pChainFrom.reset();
719 m_pChainTo.reset();
720 SdrHdl* pHdl = pView->PickHandle( *pPt );
721 if (pView->BegDragObj( *pPt, nullptr, pHdl ))
722 pView->GetDragMethod()->SetShiftPressed( bIsShift );
723 ::FrameNotify( this );
724 }
725}
726
727void SwFEShell::Drag( const Point *pPt, bool )
728{
729 OSL_ENSURE( Imp()->HasDrawView(), "Drag without DrawView?" )do { if (true && (!(Imp()->HasDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "729" ": "), "%s", "Drag without DrawView?"); } } while (
false)
;
730 if ( HasDrawViewDrag() )
731 {
732 ScrollTo( *pPt );
733 Imp()->GetDrawView()->MovDragObj( *pPt );
734 Imp()->GetDrawView()->ShowDragAnchor();
735 ::FrameNotify( this );
736 }
737}
738
739void SwFEShell::EndDrag()
740{
741 OSL_ENSURE( Imp()->HasDrawView(), "EndDrag without DrawView?" )do { if (true && (!(Imp()->HasDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "741" ": "), "%s", "EndDrag without DrawView?"); } } while
(false)
;
742 SdrView *pView = Imp()->GetDrawView();
743 if ( !pView->IsDragObj() )
744 return;
745
746 for(SwViewShell& rSh : GetRingContainer())
747 rSh.StartAction();
748
749 StartUndo( SwUndoId::START );
750
751 // #50778# Bug during dragging: In StartAction a HideShowXor is called.
752 // In EndDragObj() this is reversed, for no reason and even wrong.
753 // To restore consistency we should bring up the Xor again.
754
755 // Reanimation from the hack #50778 to fix bug #97057
756 // May be not the best solution, but the one with lowest risc at the moment.
757 // pView->ShowShownXor( GetOut() );
758
759 pView->EndDragObj();
760
761 // DrawUndo on to flyframes are not stored
762 // The flys change the flag.
763 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
764 ChgAnchor( RndStdIds::FLY_AT_PARA, true );
765
766 EndUndo( SwUndoId::END );
767
768 for(SwViewShell& rSh : GetRingContainer())
769 {
770 rSh.EndAction();
771 if( dynamic_cast<const SwCursorShell *>(&rSh) != nullptr )
772 static_cast<SwCursorShell*>(&rSh)->CallChgLnk();
773 }
774
775 GetDoc()->getIDocumentState().SetModified();
776 ::FrameNotify( this );
777}
778
779void SwFEShell::BreakDrag()
780{
781 OSL_ENSURE( Imp()->HasDrawView(), "BreakDrag without DrawView?" )do { if (true && (!(Imp()->HasDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "781" ": "), "%s", "BreakDrag without DrawView?"); } } while
(false)
;
782 if( HasDrawViewDrag() )
783 Imp()->GetDrawView()->BrkDragObj();
784 SetChainMarker();
785}
786
787// If a fly is selected, pulls the crsr in the first ContentFrame
788const SwFrameFormat* SwFEShell::SelFlyGrabCursor()
789{
790 if ( Imp()->HasDrawView() )
791 {
792 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
793 SwFlyFrame *pFly = ::GetFlyFromMarked( &rMrkList, this );
794
795 if( pFly )
796 {
797 SwContentFrame *pCFrame = pFly->ContainsContent();
798 if ( pCFrame )
799 {
800 // --> assure, that the cursor is consistent.
801 KillPams();
802 ClearMark();
803 SwPaM *pCursor = GetCursor();
804
805 if (pCFrame->IsTextFrame())
806 {
807 *pCursor->GetPoint() = static_cast<SwTextFrame *>(pCFrame)
808 ->MapViewToModelPos(TextFrameIndex(0));
809 }
810 else
811 {
812 assert(pCFrame->IsNoTextFrame())(static_cast <bool> (pCFrame->IsNoTextFrame()) ? void
(0) : __assert_fail ("pCFrame->IsNoTextFrame()", "/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
, 812, __extension__ __PRETTY_FUNCTION__))
;
813 SwContentNode *const pCNode = static_cast<SwNoTextFrame *>(pCFrame)->GetNode();
814 pCursor->GetPoint()->nNode = *pCNode;
815 pCursor->GetPoint()->nContent.Assign( pCNode, 0 );
816 }
817
818 SwRect& rChrRect = const_cast<SwRect&>(GetCharRect());
819 rChrRect = pFly->getFramePrintArea();
820 rChrRect.Pos() += pFly->getFrameArea().Pos();
821 GetCursorDocPos() = rChrRect.Pos();
822 }
823 return pFly->GetFormat();
824 }
825 }
826 return nullptr;
827}
828
829// Selection to above/below (Z-Order)
830static void lcl_NotifyNeighbours( const SdrMarkList *pLst )
831{
832 // Rules for evasion have changed.
833 // 1. The environment of the fly and everything inside should be notified
834 // 2. The content of the frame itself has to be notified
835 // 3. Frames displaced by the frame have to be notified
836 // 4. Also Drawing objects can displace frames
837 for( size_t j = 0; j < pLst->GetMarkCount(); ++j )
838 {
839 SwPageFrame *pPage;
840 bool bCheckNeighbours = false;
841 sal_Int16 aHori = text::HoriOrientation::NONE;
842 SwRect aRect;
843 SdrObject *pO = pLst->GetMark( j )->GetMarkedSdrObj();
844 if (SwVirtFlyDrawObj* pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pO))
845 {
846 SwFlyFrame *pFly = pVirtO->GetFlyFrame();
847
848 const SwFormatHoriOrient &rHori = pFly->GetFormat()->GetHoriOrient();
849 aHori = rHori.GetHoriOrient();
850 if( text::HoriOrientation::NONE != aHori && text::HoriOrientation::CENTER != aHori &&
851 pFly->IsFlyAtContentFrame() )
852 {
853 bCheckNeighbours = true;
854 pFly->InvalidatePos();
855 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pFly);
856 aFrm.Pos().AdjustY(1 );
857 }
858
859 pPage = pFly->FindPageFrame();
860 aRect = pFly->getFrameArea();
861 }
862 else
863 {
864 SwFrame* pAnch = static_cast<SwDrawContact*>( GetUserCall(pO) )->GetAnchorFrame( pO );
865 if( !pAnch )
866 continue;
867 pPage = pAnch->FindPageFrame();
868 // #i68520# - naming changed
869 aRect = GetBoundRectOfAnchoredObj( pO );
870 }
871
872 const size_t nCount = pPage->GetSortedObjs() ? pPage->GetSortedObjs()->size() : 0;
873 for ( size_t i = 0; i < nCount; ++i )
874 {
875 SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i];
876 if ( dynamic_cast<const SwFlyFrame*>( pAnchoredObj) == nullptr )
877 continue;
878
879 SwFlyFrame* pAct = static_cast<SwFlyFrame*>(pAnchoredObj);
880 SwRect aTmpCalcPnt( pAct->getFramePrintArea() );
881 aTmpCalcPnt += pAct->getFrameArea().Pos();
882 if ( aRect.IsOver( aTmpCalcPnt ) )
883 {
884 SwContentFrame *pCnt = pAct->ContainsContent();
885 while ( pCnt )
886 {
887 aTmpCalcPnt = pCnt->getFramePrintArea();
888 aTmpCalcPnt += pCnt->getFrameArea().Pos();
889 if ( aRect.IsOver( aTmpCalcPnt ) )
890 static_cast<SwFrame*>(pCnt)->Prepare( PrepareHint::FlyFrameAttributesChanged );
891 pCnt = pCnt->GetNextContentFrame();
892 }
893 }
894 if ( bCheckNeighbours && pAct->IsFlyAtContentFrame() )
895 {
896 const SwFormatHoriOrient &rH = pAct->GetFormat()->GetHoriOrient();
897 if ( rH.GetHoriOrient() == aHori &&
898 pAct->getFrameArea().Top() <= aRect.Bottom() &&
899 pAct->getFrameArea().Bottom() >= aRect.Top() )
900 {
901 pAct->InvalidatePos();
902 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pAct);
903 aFrm.Pos().AdjustY(1 );
904 }
905 }
906 }
907 }
908}
909
910void SwFEShell::SetLineEnds(SfxItemSet& rAttr, SdrObject const & rObj, sal_uInt16 nSlotId)
911{
912 SdrModel& rModel(rObj.getSdrModelFromSdrObject());
913
914 if ( !(nSlotId == SID_LINE_ARROW_START( 10000 + 1165 ) ||
915 nSlotId == SID_LINE_ARROW_END( 10000 + 1166 ) ||
916 nSlotId == SID_LINE_ARROWS( 10000 + 1163 ) ||
917 nSlotId == SID_LINE_ARROW_CIRCLE( 10000 + 1159 ) ||
918 nSlotId == SID_LINE_CIRCLE_ARROW( 10000 + 1161 ) ||
919 nSlotId == SID_LINE_ARROW_SQUARE( 10000 + 1160 ) ||
920 nSlotId == SID_LINE_SQUARE_ARROW( 10000 + 1162 ) ||
921 nSlotId == SID_DRAW_MEASURELINE( 10000 + 1167 )) )
922 return;
923
924 // set attributes of line start and ends
925
926 // arrowhead
927 ::basegfx::B2DPolyPolygon aArrow( getPolygon( RID_SVXSTR_ARROWreinterpret_cast<char const *>("RID_SVXSTR_ARROW" "\004"
u8"Arrow")
, rModel ) );
928 if( !aArrow.count() )
929 {
930 ::basegfx::B2DPolygon aNewArrow;
931 aNewArrow.append(::basegfx::B2DPoint(10.0, 0.0));
932 aNewArrow.append(::basegfx::B2DPoint(0.0, 30.0));
933 aNewArrow.append(::basegfx::B2DPoint(20.0, 30.0));
934 aNewArrow.setClosed(true);
935 aArrow.append(aNewArrow);
936 }
937
938 // Circles
939 ::basegfx::B2DPolyPolygon aCircle( getPolygon( RID_SVXSTR_CIRCLEreinterpret_cast<char const *>("RID_SVXSTR_CIRCLE" "\004"
u8"Circle")
, rModel ) );
940 if( !aCircle.count() )
941 {
942 ::basegfx::B2DPolygon aNewCircle = ::basegfx::utils::createPolygonFromEllipse(::basegfx::B2DPoint(0.0, 0.0), 250.0, 250.0);
943 aNewCircle.setClosed(true);
944 aCircle.append(aNewCircle);
945 }
946
947 // Square
948 ::basegfx::B2DPolyPolygon aSquare( getPolygon( RID_SVXSTR_SQUAREreinterpret_cast<char const *>("RID_SVXSTR_SQUARE" "\004"
u8"Square")
, rModel ) );
949 if( !aSquare.count() )
950 {
951 ::basegfx::B2DPolygon aNewSquare;
952 aNewSquare.append(::basegfx::B2DPoint(0.0, 0.0));
953 aNewSquare.append(::basegfx::B2DPoint(10.0, 0.0));
954 aNewSquare.append(::basegfx::B2DPoint(10.0, 10.0));
955 aNewSquare.append(::basegfx::B2DPoint(0.0, 10.0));
956 aNewSquare.setClosed(true);
957 aSquare.append(aNewSquare);
958 }
959
960 SfxItemSet aSet( rModel.GetItemPool() );
961 long nWidth = 100; // (1/100th mm)
962
963 // determine line width and calculate with it the line end width
964 if( aSet.GetItemState( XATTR_LINEWIDTH ) != SfxItemState::DONTCARE )
965 {
966 long nValue = aSet.Get( XATTR_LINEWIDTH ).GetValue();
967 if( nValue > 0 )
968 nWidth = nValue * 3;
969 }
970
971 switch (nSlotId)
972 {
973 case SID_LINE_ARROWS( 10000 + 1163 ):
974 case SID_DRAW_MEASURELINE( 10000 + 1167 ):
975 {
976 // connector with arrow ends
977 rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_ARROWreinterpret_cast<char const *>("RID_SVXSTR_ARROW" "\004"
u8"Arrow")
), aArrow));
978 rAttr.Put(XLineStartWidthItem(nWidth));
979 rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_ARROWreinterpret_cast<char const *>("RID_SVXSTR_ARROW" "\004"
u8"Arrow")
), aArrow));
980 rAttr.Put(XLineEndWidthItem(nWidth));
981 }
982 break;
983
984 case SID_LINE_ARROW_START( 10000 + 1165 ):
985 case SID_LINE_ARROW_CIRCLE( 10000 + 1159 ):
986 case SID_LINE_ARROW_SQUARE( 10000 + 1160 ):
987 {
988 // connector with arrow start
989 rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_ARROWreinterpret_cast<char const *>("RID_SVXSTR_ARROW" "\004"
u8"Arrow")
), aArrow));
990 rAttr.Put(XLineStartWidthItem(nWidth));
991 }
992 break;
993
994 case SID_LINE_ARROW_END( 10000 + 1166 ):
995 case SID_LINE_CIRCLE_ARROW( 10000 + 1161 ):
996 case SID_LINE_SQUARE_ARROW( 10000 + 1162 ):
997 {
998 // connector with arrow end
999 rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_ARROWreinterpret_cast<char const *>("RID_SVXSTR_ARROW" "\004"
u8"Arrow")
), aArrow));
1000 rAttr.Put(XLineEndWidthItem(nWidth));
1001 }
1002 break;
1003 }
1004
1005 // and again, for the still missing ends
1006 switch (nSlotId)
1007 {
1008 case SID_LINE_CIRCLE_ARROW( 10000 + 1161 ):
1009 {
1010 // circle start
1011 rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_CIRCLEreinterpret_cast<char const *>("RID_SVXSTR_CIRCLE" "\004"
u8"Circle")
), aCircle));
1012 rAttr.Put(XLineStartWidthItem(nWidth));
1013 }
1014 break;
1015
1016 case SID_LINE_ARROW_SQUARE( 10000 + 1160 ):
1017 {
1018 // square end
1019 rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_SQUAREreinterpret_cast<char const *>("RID_SVXSTR_SQUARE" "\004"
u8"Square")
), aSquare));
1020 rAttr.Put(XLineEndWidthItem(nWidth));
1021 }
1022 break;
1023
1024 case SID_LINE_SQUARE_ARROW( 10000 + 1162 ):
1025 {
1026 // square start
1027 rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_SQUAREreinterpret_cast<char const *>("RID_SVXSTR_SQUARE" "\004"
u8"Square")
), aSquare));
1028 rAttr.Put(XLineStartWidthItem(nWidth));
1029 }
1030 break;
1031 }
1032
1033}
1034
1035void SwFEShell::SelectionToTop( bool bTop )
1036{
1037 OSL_ENSURE( Imp()->HasDrawView(), "SelectionToTop without DrawView?" )do { if (true && (!(Imp()->HasDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "1037" ": "), "%s", "SelectionToTop without DrawView?");
} } while (false)
;
1038 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
1039 OSL_ENSURE( rMrkList.GetMarkCount(), "No object selected." )do { if (true && (!(rMrkList.GetMarkCount()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "1039" ": "), "%s", "No object selected."); } } while (false
)
;
1040
1041 SwFlyFrame *pFly = ::GetFlyFromMarked( &rMrkList, this );
1042 if ( pFly && pFly->IsFlyInContentFrame() )
1043 return;
1044
1045 StartAllAction();
1046 if ( bTop )
1047 Imp()->GetDrawView()->PutMarkedToTop();
1048 else
1049 Imp()->GetDrawView()->MovMarkedToTop();
1050 ::lcl_NotifyNeighbours( &rMrkList );
1051 GetDoc()->getIDocumentState().SetModified();
1052 EndAllAction();
1053}
1054
1055void SwFEShell::SelectionToBottom( bool bBottom )
1056{
1057 OSL_ENSURE( Imp()->HasDrawView(), "SelectionToBottom without DrawView?" )do { if (true && (!(Imp()->HasDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "1057" ": "), "%s", "SelectionToBottom without DrawView?"
); } } while (false)
;
1058 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
1059 OSL_ENSURE( rMrkList.GetMarkCount(), "No object selected." )do { if (true && (!(rMrkList.GetMarkCount()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "1059" ": "), "%s", "No object selected."); } } while (false
)
;
1060
1061 SwFlyFrame *pFly = ::GetFlyFromMarked( &rMrkList, this );
1062 if ( pFly && pFly->IsFlyInContentFrame() )
1063 return;
1064
1065 StartAllAction();
1066 if ( bBottom )
1067 Imp()->GetDrawView()->PutMarkedToBtm();
1068 else
1069 Imp()->GetDrawView()->MovMarkedToBtm();
1070 ::lcl_NotifyNeighbours( &rMrkList );
1071 GetDoc()->getIDocumentState().SetModified();
1072 EndAllAction();
1073}
1074
1075// Object above/below the document? 2 Controls, 1 Heaven, 0 Hell,
1076// SDRLAYER_NOTFOUND Ambiguous
1077SdrLayerID SwFEShell::GetLayerId() const
1078{
1079 if ( !Imp()->HasDrawView() )
1080 return SDRLAYER_NOTFOUND;
1081
1082 SdrLayerID nRet = SDRLAYER_NOTFOUND;
1083 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
1084 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
1085 {
1086 const SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
1087 if( !pObj )
1088 continue;
1089 if ( nRet == SDRLAYER_NOTFOUND )
1090 nRet = pObj->GetLayer();
1091 else if ( nRet != pObj->GetLayer() )
1092 {
1093 return SDRLAYER_NOTFOUND;
1094 }
1095 }
1096 return nRet;
1097}
1098
1099// Object above/below the document
1100// Note: only visible objects can be marked. Thus, objects with invisible
1101// layer IDs have not to be considered.
1102// If <SwFEShell> exists, layout exists!!
1103void SwFEShell::ChangeOpaque( SdrLayerID nLayerId )
1104{
1105 if ( !Imp()->HasDrawView() )
1106 return;
1107
1108 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
1109 const IDocumentDrawModelAccess& rIDDMA = getIDocumentDrawModelAccess();
1110 // correct type of <nControls>
1111 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
1112 {
1113 SdrObject* pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
1114 if( !pObj )
1115 continue;
1116 // or group objects containing controls.
1117 // --> #i113730#
1118 // consider that a member of a drawing group has been selected.
1119 const SwContact* pContact = ::GetUserCall( pObj );
1120 OSL_ENSURE( pContact && pContact->GetMaster(), "<SwFEShell::ChangeOpaque(..)> - missing contact or missing master object at contact!" )do { if (true && (!(pContact && pContact->
GetMaster()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "1120" ": "), "%s", "<SwFEShell::ChangeOpaque(..)> - missing contact or missing master object at contact!"
); } } while (false)
;
1121 const bool bControlObj = ( pContact && pContact->GetMaster() )
1122 ? ::CheckControlLayer( pContact->GetMaster() )
1123 : ::CheckControlLayer( pObj );
1124 if ( !bControlObj && pObj->GetLayer() != nLayerId )
1125 {
1126 pObj->SetLayer( nLayerId );
1127 InvalidateWindows( SwRect( pObj->GetCurrentBoundRect() ) );
1128 if (SwVirtFlyDrawObj* pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pObj))
1129 {
1130 SwFormat *pFormat = pVirtO->GetFlyFrame()->GetFormat();
1131 SvxOpaqueItem aOpa( pFormat->GetOpaque() );
1132 aOpa.SetValue( nLayerId == rIDDMA.GetHellId() );
1133 pFormat->SetFormatAttr( aOpa );
1134 }
1135 }
1136 }
1137 GetDoc()->getIDocumentState().SetModified();
1138}
1139
1140void SwFEShell::SelectionToHeaven()
1141{
1142 ChangeOpaque( getIDocumentDrawModelAccess().GetHeavenId() );
1143}
1144
1145void SwFEShell::SelectionToHell()
1146{
1147 ChangeOpaque( getIDocumentDrawModelAccess().GetHellId() );
1148}
1149
1150size_t SwFEShell::IsObjSelected() const
1151{
1152 if ( IsFrameSelected() || !Imp()->HasDrawView() )
1153 return 0;
1154
1155 return Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount();
1156}
1157
1158bool SwFEShell::IsFrameSelected() const
1159{
1160 if ( !Imp()->HasDrawView() )
1161 return false;
1162 else
1163 return nullptr != ::GetFlyFromMarked( &Imp()->GetDrawView()->GetMarkedObjectList(),
1164 const_cast<SwFEShell*>(this) );
1165}
1166
1167bool SwFEShell::IsObjSelected( const SdrObject& rObj ) const
1168{
1169 if ( IsFrameSelected() || !Imp()->HasDrawView() )
1170 return false;
1171 else
1172 return Imp()->GetDrawView()->IsObjMarked( &rObj );
1173}
1174
1175bool SwFEShell::IsRotationOfSwGrfNodePossible() const
1176{
1177 // RotGrfFlyFrame: check if RotationMode is possible
1178 const SdrView *pSdrView = Imp()->GetDrawView();
1179
1180 if(pSdrView)
1181 {
1182 const SdrMarkList& rList(pSdrView->GetMarkedObjectList());
1183
1184 if(1 == rList.GetMarkCount())
1185 {
1186 const SwVirtFlyDrawObj* pVirtFlyDraw(dynamic_cast< const SwVirtFlyDrawObj* >(rList.GetMark(0)->GetMarkedSdrObj()));
1187
1188 if(nullptr != pVirtFlyDraw)
1189 {
1190 return pVirtFlyDraw->ContainsSwGrfNode();
1191 }
1192 }
1193 }
1194
1195 return false;
1196}
1197
1198bool SwFEShell::IsObjSameLevelWithMarked(const SdrObject* pObj) const
1199{
1200 if (pObj)
1201 {
1202 const SdrMarkList& aMarkList = Imp()->GetDrawView()->GetMarkedObjectList();
1203 if (aMarkList.GetMarkCount() == 0)
1204 {
1205 return true;
1206 }
1207 SdrMark* pM=aMarkList.GetMark(0);
1208 if (pM)
1209 {
1210 SdrObject* pMarkObj = pM->GetMarkedSdrObj();
1211 if (pMarkObj && pMarkObj->getParentSdrObjectFromSdrObject() == pObj->getParentSdrObjectFromSdrObject())
1212 return true;
1213 }
1214 }
1215 return false;
1216}
1217
1218void SwFEShell::EndTextEdit()
1219{
1220 // Terminate the TextEditMode. If required (default if the object
1221 // does not contain any more text and does not carry attributes) the object
1222 // is deleted. All other objects marked are preserved.
1223
1224 OSL_ENSURE( Imp()->HasDrawView() && Imp()->GetDrawView()->IsTextEdit(),do { if (true && (!(Imp()->HasDrawView() &&
Imp()->GetDrawView()->IsTextEdit()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "1225" ": "), "%s", "EndTextEdit a no Object"); } } while
(false)
1225 "EndTextEdit a no Object" )do { if (true && (!(Imp()->HasDrawView() &&
Imp()->GetDrawView()->IsTextEdit()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "1225" ": "), "%s", "EndTextEdit a no Object"); } } while
(false)
;
1226
1227 StartAllAction();
1228 SdrView *pView = Imp()->GetDrawView();
1229 SdrObject *pObj = pView->GetTextEditObject();
1230 SdrObjUserCall* pUserCall = GetUserCall(pObj);
1231 if( nullptr != pUserCall )
1232 {
1233 SdrObject *pTmp = static_cast<SwContact*>(pUserCall)->GetMaster();
1234 if( !pTmp )
1235 pTmp = pObj;
1236 pUserCall->Changed( *pTmp, SdrUserCallType::Resize, pTmp->GetLastBoundRect() );
1237 }
1238 if ( !pObj->getParentSdrObjectFromSdrObject() )
1239 {
1240 if ( SdrEndTextEditKind::ShouldBeDeleted == pView->SdrEndTextEdit(true) )
1241 {
1242 if ( pView->GetMarkedObjectList().GetMarkCount() > 1 )
1243 {
1244 SdrMarkList aSave( pView->GetMarkedObjectList() );
1245 aSave.DeleteMark( aSave.FindObject( pObj ) );
1246 if ( aSave.GetMarkCount() )
1247 {
1248 pView->UnmarkAll();
1249 pView->MarkObj( pObj, Imp()->GetPageView() );
1250 }
1251 DelSelectedObj();
1252 for ( size_t i = 0; i < aSave.GetMarkCount(); ++i )
1253 pView->MarkObj( aSave.GetMark( i )->GetMarkedSdrObj(), Imp()->GetPageView() );
1254 }
1255 else
1256 DelSelectedObj();
1257 }
1258 }
1259 else
1260 pView->SdrEndTextEdit();
1261
1262 if (comphelper::LibreOfficeKit::isActive())
1263 SfxLokHelper::notifyOtherViews(GetSfxViewShell(), LOK_CALLBACK_VIEW_LOCK, "rectangle", "EMPTY");
1264
1265 EndAllAction();
1266}
1267
1268bool SwFEShell::IsInsideSelectedObj( const Point &rPt )
1269{
1270 if( Imp()->HasDrawView() )
1271 {
1272 SwDrawView *pDView = Imp()->GetDrawView();
1273
1274 if( pDView->GetMarkedObjectList().GetMarkCount() &&
1275 pDView->IsMarkedObjHit( rPt ) )
1276 {
1277 return true;
1278 }
1279 }
1280 return false;
1281}
1282
1283bool SwFEShell::IsObjSelectable( const Point& rPt )
1284{
1285 CurrShell aCurr(this);
1286 SwDrawView *pDView = Imp()->GetDrawView();
1287 bool bRet = false;
1288 if( pDView )
1289 {
1290 SdrPageView* pPV;
1291 const auto nOld = pDView->GetHitTolerancePixel();
1292 pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 );
1293
1294 bRet = pDView->PickObj(rPt, pDView->getHitTolLog(), pPV, SdrSearchOptions::PICKMARKABLE) != nullptr;
1295 pDView->SetHitTolerancePixel( nOld );
1296 }
1297 return bRet;
1298}
1299
1300SdrObject* SwFEShell::GetObjAt( const Point& rPt )
1301{
1302 SdrObject* pRet = nullptr;
1303 CurrShell aCurr(this);
1304 SwDrawView *pDView = Imp()->GetDrawView();
1305 if( pDView )
1306 {
1307 SdrPageView* pPV;
1308 const auto nOld = pDView->GetHitTolerancePixel();
1309 pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 );
1310
1311 pRet = pDView->PickObj(rPt, pDView->getHitTolLog(), pPV, SdrSearchOptions::PICKMARKABLE);
1312 pDView->SetHitTolerancePixel( nOld );
1313 }
1314 return pRet;
1315}
1316
1317// Test if there is an object at that position and if it should be selected.
1318bool SwFEShell::ShouldObjectBeSelected(const Point& rPt)
1319{
1320 CurrShell aCurr(this);
1321 SwDrawView *pDrawView = Imp()->GetDrawView();
1322 bool bRet(false);
1323
1324 if(pDrawView)
1325 {
1326 SdrPageView* pPV;
1327 const auto nOld(pDrawView->GetHitTolerancePixel());
1328
1329 pDrawView->SetHitTolerancePixel(pDrawView->GetMarkHdlSizePixel()/2);
1330 SdrObject* pObj = pDrawView->PickObj(rPt, pDrawView->getHitTolLog(), pPV, SdrSearchOptions::PICKMARKABLE);
1331 pDrawView->SetHitTolerancePixel(nOld);
1332
1333 if (pObj)
1334 {
1335 bRet = true;
1336 const IDocumentDrawModelAccess& rIDDMA = getIDocumentDrawModelAccess();
1337 // #i89920#
1338 // Do not select object in background which is overlapping this text
1339 // at the given position.
1340 bool bObjInBackground( false );
1341 {
1342 if ( pObj->GetLayer() == rIDDMA.GetHellId() )
1343 {
1344 const SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj );
1345 const SwFrameFormat& rFormat = pAnchoredObj->GetFrameFormat();
1346 const SwFormatSurround& rSurround = rFormat.GetSurround();
1347 if ( rSurround.GetSurround() == css::text::WrapTextMode_THROUGH )
1348 {
1349 bObjInBackground = true;
1350 }
1351 }
1352 }
1353 if ( bObjInBackground )
1354 {
1355 const SwPageFrame* pPageFrame = GetLayout()->GetPageAtPos( rPt );
1356 if( pPageFrame )
1357 {
1358 const SwContentFrame* pContentFrame( pPageFrame->ContainsContent() );
1359 while ( pContentFrame )
1360 {
1361 if ( pContentFrame->UnionFrame().IsInside( rPt ) )
1362 {
1363 const SwTextFrame* pTextFrame =
1364 dynamic_cast<const SwTextFrame*>(pContentFrame);
1365 if ( pTextFrame )
1366 {
1367 SwPosition aPos(GetDoc()->GetNodes());
1368 Point aTmpPt( rPt );
1369 if (pTextFrame->GetKeyCursorOfst(&aPos, aTmpPt))
1370 {
1371 SwRect aCursorCharRect;
1372 if (pTextFrame->GetCharRect(aCursorCharRect,
1373 aPos))
1374 {
1375 if ( aCursorCharRect.IsOver( SwRect( pObj->GetLastBoundRect() ) ) )
1376 {
1377 bRet = false;
1378 }
1379 }
1380 }
1381 }
1382 else
1383 {
1384 bRet = false;
1385 }
1386 break;
1387 }
1388
1389 pContentFrame = pContentFrame->GetNextContentFrame();
1390 }
1391 }
1392 }
1393
1394 // Don't select header / footer objects in body edition and vice-versa
1395 SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
1396 if (pContact && !pContact->ObjAnchoredAtPage() )
1397 {
1398 const SwPosition& rPos = pContact->GetContentAnchor();
1399 bool bInHdrFtr = GetDoc()->IsInHeaderFooter( rPos.nNode );
1400 if (IsHeaderFooterEdit() != bInHdrFtr)
1401 {
1402 bRet = false;
1403 }
1404 }
1405
1406 if ( bRet )
1407 {
1408 const SdrPage* pPage = rIDDMA.GetDrawModel()->GetPage(0);
1409 for(size_t a = pObj->GetOrdNum()+1; bRet && a < pPage->GetObjCount(); ++a)
1410 {
1411 SdrObject *pCandidate = pPage->GetObj(a);
1412
1413 SwVirtFlyDrawObj* pDrawObj = dynamic_cast<SwVirtFlyDrawObj*>(pCandidate);
1414 if (pDrawObj && pDrawObj->GetCurrentBoundRect().IsInside(rPt))
1415 {
1416 bRet = false;
1417 }
1418 }
1419 }
1420 }
1421 }
1422
1423 return bRet;
1424}
1425
1426/*
1427 * If an object was selected, we assume its upper-left corner
1428 * otherwise the middle of the current CharRects.
1429 * Does the object include a control or groups,
1430 * which comprise only controls
1431 */
1432static bool lcl_IsControlGroup( const SdrObject *pObj )
1433{
1434 bool bRet = false;
1435 if(dynamic_cast<const SdrUnoObj*>( pObj) != nullptr)
1436 bRet = true;
1437 else if( auto pObjGroup = dynamic_cast<const SdrObjGroup*>( pObj) )
1438 {
1439 bRet = true;
1440 const SdrObjList *pLst = pObjGroup->GetSubList();
1441 for ( size_t i = 0; i < pLst->GetObjCount(); ++i )
1442 if( !::lcl_IsControlGroup( pLst->GetObj( i ) ) )
1443 return false;
1444 }
1445 return bRet;
1446}
1447
1448namespace
1449{
1450 class MarkableObjectsOnly : public svx::ISdrObjectFilter
1451 {
1452 public:
1453 explicit MarkableObjectsOnly( SdrPageView* i_pPV )
1454 :m_pPV( i_pPV )
1455 {
1456 }
1457
1458 virtual bool includeObject( const SdrObject& i_rObject ) const override
1459 {
1460 return m_pPV && m_pPV->GetView().IsObjMarkable( &i_rObject, m_pPV );
1461 }
1462
1463 private:
1464 SdrPageView* m_pPV;
1465 };
1466}
1467
1468const SdrObject* SwFEShell::GetBestObject( bool bNext, GotoObjFlags eType, bool bFlat, const svx::ISdrObjectFilter* pFilter )
1469{
1470 if( !Imp()->HasDrawView() )
1
Calling 'SwViewShellImp::HasDrawView'
11
Returning from 'SwViewShellImp::HasDrawView'
12
Taking false branch
1471 return nullptr;
1472
1473 const SdrObject *pBest = nullptr,
1474 *pTop = nullptr;
1475
1476 const long nTmp = bNext ? LONG_MAX9223372036854775807L : 0;
13
Assuming 'bNext' is false
14
'?' condition is false
1477 Point aBestPos( nTmp, nTmp );
1478 Point aTopPos( nTmp, nTmp );
1479 Point aCurPos;
1480 Point aPos;
1481 bool bNoDraw((GotoObjFlags::DrawAny & eType) == GotoObjFlags::NONE);
15
Assuming the condition is false
1482 bool bNoFly((GotoObjFlags::FlyAny & eType) == GotoObjFlags::NONE);
16
Assuming the condition is false
1483
1484 if( !bNoFly
16.1
'bNoFly' is false
16.1
'bNoFly' is false
16.1
'bNoFly' is false
16.1
'bNoFly' is false
16.1
'bNoFly' is false
&& bNoDraw
16.2
'bNoDraw' is false
16.2
'bNoDraw' is false
16.2
'bNoDraw' is false
16.2
'bNoDraw' is false
16.2
'bNoDraw' is false
)
17
Taking false branch
1485 {
1486 SwFlyFrame *pFly = GetCurrFrame( false )->FindFlyFrame();
1487 if( pFly )
1488 pBest = pFly->GetVirtDrawObj();
1489 }
1490 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
1491 SdrPageView* pPV = Imp()->GetDrawView()->GetSdrPageView();
1492
1493 MarkableObjectsOnly aDefaultFilter( pPV );
1494 if ( !pFilter )
18
Assuming 'pFilter' is non-null
19
Taking false branch
1495 pFilter = &aDefaultFilter;
1496
1497 if( !pBest
19.1
'pBest' is null
19.1
'pBest' is null
19.1
'pBest' is null
19.1
'pBest' is null
19.1
'pBest' is null
|| rMrkList.GetMarkCount() == 1 )
1498 {
1499 // Determine starting point
1500 SdrObjList* pList = nullptr;
1501 if ( rMrkList.GetMarkCount() )
20
Assuming the condition is false
21
Taking false branch
1502 {
1503 const SdrObject* pStartObj = rMrkList.GetMark(0)->GetMarkedSdrObj();
1504 if( auto pVirtFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>( pStartObj) )
1505 aPos = pVirtFlyDrawObj->GetFlyFrame()->getFrameArea().Pos();
1506 else
1507 aPos = pStartObj->GetSnapRect().TopLeft();
1508
1509 // If an object inside a group is selected, we want to
1510 // iterate over the group members.
1511 if ( ! pStartObj->GetUserCall() )
1512 pList = pStartObj->getParentSdrObjListFromSdrObject();
1513 }
1514 else
1515 {
1516 // If no object is selected, we check if we just entered a group.
1517 // In this case we want to iterate over the group members.
1518 aPos = GetCharRect().Center();
1519 const SdrObject* pStartObj = pPV ? pPV->GetCurrentGroup() : nullptr;
22
Assuming 'pPV' is null
23
'?' condition is false
1520 if ( dynamic_cast<const SdrObjGroup*>( pStartObj
23.1
'pStartObj' is null
23.1
'pStartObj' is null
23.1
'pStartObj' is null
23.1
'pStartObj' is null
23.1
'pStartObj' is null
) )
24
Taking false branch
1521 pList = pStartObj->GetSubList();
1522 }
1523
1524 if ( ! pList
24.1
'pList' is null
24.1
'pList' is null
24.1
'pList' is null
24.1
'pList' is null
24.1
'pList' is null
)
25
Taking true branch
1525 {
1526 // Here we are if
1527 // A No object has been selected and no group has been entered or
1528 // B An object has been selected and it is not inside a group
1529 pList = getIDocumentDrawModelAccess().GetDrawModel()->GetPage( 0 );
1530 }
1531
1532 OSL_ENSURE( pList, "No object list to iterate" )do { if (true && (!(pList))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "1532" ": "), "%s", "No object list to iterate"); } } while
(false)
;
26
Assuming 'pList' is non-null
27
Taking false branch
28
Loop condition is false. Exiting loop
1533
1534 SdrObjListIter aObjIter( pList, bFlat ? SdrIterMode::Flat : SdrIterMode::DeepNoGroups );
29
Assuming 'bFlat' is false
30
'?' condition is false
1535 while ( aObjIter.IsMore() )
31
Calling 'SdrObjListIter::IsMore'
36
Returning from 'SdrObjListIter::IsMore'
37
Loop condition is true. Entering loop body
1536 {
1537 SdrObject* pObj = aObjIter.Next();
38
Calling 'SdrObjListIter::Next'
43
Returning from 'SdrObjListIter::Next'
1538 SwVirtFlyDrawObj *pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pObj);
1539 if( ( bNoFly
43.1
'bNoFly' is false
43.1
'bNoFly' is false
43.1
'bNoFly' is false
43.1
'bNoFly' is false
43.1
'bNoFly' is false
&& pVirtO ) ||
49
Taking false branch
1540 ( bNoDraw
43.2
'bNoDraw' is false
43.2
'bNoDraw' is false
43.2
'bNoDraw' is false
43.2
'bNoDraw' is false
43.2
'bNoDraw' is false
&& !pVirtO ) ||
1541 // Ignore TextBoxes of draw shapes here, so that
1542 // SwFEShell::SelectObj() won't jump back on this list, meaning
1543 // we never jump to the next draw shape.
1544 (pVirtO && pVirtO->IsTextBox()) ||
44
Assuming 'pVirtO' is non-null
45
Assuming the condition is false
1545 ( eType == GotoObjFlags::DrawSimple && lcl_IsControlGroup( pObj ) ) ||
46
Assuming 'eType' is not equal to DrawSimple
1546 ( eType == GotoObjFlags::DrawControl && !lcl_IsControlGroup( pObj ) ) ||
47
Assuming 'eType' is not equal to DrawControl
1547 !pFilter->includeObject( *pObj ) )
48
Assuming the condition is false
1548 continue;
1549 if (pVirtO
49.1
'pVirtO' is non-null
49.1
'pVirtO' is non-null
49.1
'pVirtO' is non-null
49.1
'pVirtO' is non-null
49.1
'pVirtO' is non-null
)
50
Taking true branch
1550 {
1551 SwFlyFrame *pFly = pVirtO->GetFlyFrame();
1552 if( GotoObjFlags::FlyAny != ( GotoObjFlags::FlyAny & eType ) )
51
Assuming the condition is false
52
Taking false branch
1553 {
1554 switch ( eType )
1555 {
1556 case GotoObjFlags::FlyFrame:
1557 if ( pFly->Lower() && pFly->Lower()->IsNoTextFrame() )
1558 continue;
1559 break;
1560 case GotoObjFlags::FlyGrf:
1561 if ( pFly->Lower() &&
1562 (!pFly->Lower()->IsNoTextFrame() ||
1563 !static_cast<SwNoTextFrame*>(pFly->Lower())->GetNode()->GetGrfNode()))
1564 continue;
1565 break;
1566 case GotoObjFlags::FlyOLE:
1567 if ( pFly->Lower() &&
1568 (!pFly->Lower()->IsNoTextFrame() ||
1569 !static_cast<SwNoTextFrame*>(pFly->Lower())->GetNode()->GetOLENode()))
1570 continue;
1571 break;
1572 default: break;
1573 }
1574 }
1575 aCurPos = pFly->getFrameArea().Pos();
1576 }
1577 else
1578 aCurPos = pObj->GetSnapRect().TopLeft();
1579
1580 // Special case if another object is on same Y.
1581 if( aCurPos != aPos && // only when it is not me
53
Calling 'operator!='
62
Returning from 'operator!='
66
Taking true branch
1582 aCurPos.getY() == aPos.getY() && // Y positions equal
63
Assuming the condition is true
1583 (bNext
63.1
'bNext' is false
63.1
'bNext' is false
63.1
'bNext' is false
63.1
'bNext' is false
63.1
'bNext' is false
? (aCurPos.getX() > aPos.getX()) : // lies next to me
64
'?' condition is false
1584 (aCurPos.getX() < aPos.getX())) ) // " reverse
65
Assuming the condition is true
1585 {
1586 aBestPos = Point( nTmp, nTmp );
1587 SdrObjListIter aTmpIter( pList, bFlat
66.1
'bFlat' is false
66.1
'bFlat' is false
66.1
'bFlat' is false
66.1
'bFlat' is false
66.1
'bFlat' is false
? SdrIterMode::Flat : SdrIterMode::DeepNoGroups );
67
'?' condition is false
1588 while ( aTmpIter.IsMore() )
68
Calling 'SdrObjListIter::IsMore'
73
Returning from 'SdrObjListIter::IsMore'
74
Loop condition is true. Entering loop body
1589 {
1590 SdrObject* pTmpObj = aTmpIter.Next();
75
Calling 'SdrObjListIter::Next'
81
Returning from 'SdrObjListIter::Next'
82
'pTmpObj' initialized here
1591 pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pTmpObj);
1592 if( ( bNoFly
82.1
'bNoFly' is false
82.1
'bNoFly' is false
82.1
'bNoFly' is false
82.1
'bNoFly' is false
82.1
'bNoFly' is false
&& pVirtO ) || ( bNoDraw
82.2
'bNoDraw' is false
82.2
'bNoDraw' is false
82.2
'bNoDraw' is false
82.2
'bNoDraw' is false
82.2
'bNoDraw' is false
&& !pVirtO ) )
1593 continue;
1594 if (pVirtO)
83
Assuming 'pVirtO' is null
84
Taking false branch
1595 {
1596 aCurPos = pVirtO->GetFlyFrame()->getFrameArea().Pos();
1597 }
1598 else
1599 aCurPos = pTmpObj->GetCurrentBoundRect().TopLeft();
85
Called C++ object pointer is null
1600
1601 if( aCurPos != aPos && aCurPos.Y() == aPos.Y() &&
1602 (bNext? (aCurPos.getX() > aPos.getX()) : // lies next to me
1603 (aCurPos.getX() < aPos.getX())) && // " reverse
1604 (bNext? (aCurPos.getX() < aBestPos.getX()) : // better as best
1605 (aCurPos.getX() > aBestPos.getX())) ) // " reverse
1606 {
1607 aBestPos = aCurPos;
1608 pBest = pTmpObj;
1609 }
1610 }
1611 break;
1612 }
1613
1614 if( (
1615 (bNext? (aPos.getY() < aCurPos.getY()) : // only below me
1616 (aPos.getY() > aCurPos.getY())) && // " reverse
1617 (bNext? (aBestPos.getY() > aCurPos.getY()) : // closer below
1618 (aBestPos.getY() < aCurPos.getY()))
1619 ) || // " reverse
1620 (aBestPos.getY() == aCurPos.getY() &&
1621 (bNext? (aBestPos.getX() > aCurPos.getX()) : // further left
1622 (aBestPos.getX() < aCurPos.getX())))) // " reverse
1623
1624 {
1625 aBestPos = aCurPos;
1626 pBest = pObj;
1627 }
1628
1629 if( (bNext? (aTopPos.getY() > aCurPos.getY()) : // higher as best
1630 (aTopPos.getY() < aCurPos.getY())) || // " reverse
1631 (aTopPos.getY() == aCurPos.getY() &&
1632 (bNext? (aTopPos.getX() > aCurPos.getX()) : // further left
1633 (aTopPos.getX() < aCurPos.getX())))) // " reverse
1634 {
1635 aTopPos = aCurPos;
1636 pTop = pObj;
1637 }
1638 }
1639 // unfortunately nothing found
1640 if( bNext ? (aBestPos.getX() == LONG_MAX9223372036854775807L) : (aBestPos.getX() == 0) )
1641 {
1642 pBest = pTop;
1643 SvxSearchDialogWrapper::SetSearchLabel( bNext ? SearchLabel::EndWrapped : SearchLabel::StartWrapped );
1644 }
1645 }
1646
1647 return pBest;
1648}
1649
1650bool SwFEShell::GotoObj( bool bNext, GotoObjFlags eType )
1651{
1652 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
1653
1654 const SdrObject* pBest = GetBestObject( bNext, eType );
1655
1656 if ( !pBest )
1657 {
1658 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
1659 return false;
1660 }
1661
1662 const SwVirtFlyDrawObj *pVirtO = dynamic_cast<const SwVirtFlyDrawObj*>(pBest);
1663 if (pVirtO)
1664 {
1665 const SwRect& rFrame = pVirtO->GetFlyFrame()->getFrameArea();
1666 SelectObj( rFrame.Pos(), 0, const_cast<SdrObject*>(pBest) );
1667 if( !ActionPend() )
1668 MakeVisible( rFrame );
1669 }
1670 else
1671 {
1672 SelectObj( Point(), 0, const_cast<SdrObject*>(pBest) );
1673 if( !ActionPend() )
1674 MakeVisible( pBest->GetCurrentBoundRect() );
1675 }
1676 CallChgLnk();
1677 return true;
1678}
1679
1680bool SwFEShell::BeginCreate( sal_uInt16 /*SdrObjKind ?*/ eSdrObjectKind, const Point &rPos )
1681{
1682 bool bRet = false;
1683
1684 if ( !Imp()->HasDrawView() )
1685 Imp()->MakeDrawView();
1686
1687 if ( GetPageNumber( rPos ) )
1688 {
1689 Imp()->GetDrawView()->SetCurrentObj( eSdrObjectKind );
1690 if ( eSdrObjectKind == OBJ_CAPTION )
1691 bRet = Imp()->GetDrawView()->BegCreateCaptionObj(
1692 rPos, Size( lMinBorder - MINFLY23, lMinBorder - MINFLY23 ),
1693 GetOut() );
1694 else
1695 bRet = Imp()->GetDrawView()->BegCreateObj( rPos, GetOut() );
1696 }
1697 if ( bRet )
1698 {
1699 ::FrameNotify( this, FLY_DRAG_START );
1700 }
1701 return bRet;
1702}
1703
1704bool SwFEShell::BeginCreate( sal_uInt16 /*SdrObjKind ?*/ eSdrObjectKind, SdrInventor eObjInventor,
1705 const Point &rPos )
1706{
1707 bool bRet = false;
1708
1709 if ( !Imp()->HasDrawView() )
1710 Imp()->MakeDrawView();
1711
1712 if ( GetPageNumber( rPos ) )
1713 {
1714 Imp()->GetDrawView()->SetCurrentObj( eSdrObjectKind, eObjInventor );
1715 bRet = Imp()->GetDrawView()->BegCreateObj( rPos, GetOut() );
1716 }
1717 if ( bRet )
1718 ::FrameNotify( this, FLY_DRAG_START );
1719 return bRet;
1720}
1721
1722void SwFEShell::MoveCreate( const Point &rPos )
1723{
1724 OSL_ENSURE( Imp()->HasDrawView(), "MoveCreate without DrawView?" )do { if (true && (!(Imp()->HasDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "1724" ": "), "%s", "MoveCreate without DrawView?"); } }
while (false)
;
1725 if ( GetPageNumber( rPos ) )
1726 {
1727 ScrollTo( rPos );
1728 Imp()->GetDrawView()->MovCreateObj( rPos );
1729 ::FrameNotify( this );
1730 }
1731}
1732
1733bool SwFEShell::EndCreate( SdrCreateCmd eSdrCreateCmd )
1734{
1735 // To assure undo-object from the DrawEngine is not stored,
1736 // (we create our own undo-object!), temporarily switch-off Undo
1737 OSL_ENSURE( Imp()->HasDrawView(), "EndCreate without DrawView?" )do { if (true && (!(Imp()->HasDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "1737" ": "), "%s", "EndCreate without DrawView?"); } } while
(false)
;
1738 if( !Imp()->GetDrawView()->IsGroupEntered() )
1739 {
1740 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
1741 }
1742 bool bCreate = Imp()->GetDrawView()->EndCreateObj( eSdrCreateCmd );
1743 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
1744
1745 if ( !bCreate )
1746 {
1747 ::FrameNotify( this, FLY_DRAG_END );
1748 return false;
1749 }
1750
1751 if ( eSdrCreateCmd == SdrCreateCmd::NextPoint )
1752 {
1753 ::FrameNotify( this );
1754 return true;
1755 }
1756 return ImpEndCreate();
1757}
1758
1759bool SwFEShell::ImpEndCreate()
1760{
1761 OSL_ENSURE( Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1,do { if (true && (!(Imp()->GetDrawView()->GetMarkedObjectList
().GetMarkCount() == 1))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "1762" ": "), "%s", "New object not selected."); } } while
(false)
1762 "New object not selected." )do { if (true && (!(Imp()->GetDrawView()->GetMarkedObjectList
().GetMarkCount() == 1))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "1762" ": "), "%s", "New object not selected."); } } while
(false)
;
1763
1764 SdrObject& rSdrObj = *Imp()->GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
1765
1766 if( rSdrObj.GetSnapRect().IsEmpty() )
1767 {
1768 // preferably we forget the object, only gives problems
1769 Imp()->GetDrawView()->DeleteMarked();
1770 Imp()->GetDrawView()->UnmarkAll();
1771 ::FrameNotify( this, FLY_DRAG_END );
1772 return false;
1773 }
1774
1775 if( rSdrObj.getParentSdrObjectFromSdrObject() )
1776 {
1777 Point aTmpPos( rSdrObj.GetSnapRect().TopLeft() );
1778 Point aNewAnchor( rSdrObj.getParentSdrObjectFromSdrObject()->GetAnchorPos() );
1779 // OD 2004-04-05 #i26791# - direct object positioning for group members
1780 rSdrObj.NbcSetRelativePos( aTmpPos - aNewAnchor );
1781 rSdrObj.NbcSetAnchorPos( aNewAnchor );
1782 ::FrameNotify( this );
1783 return true;
1784 }
1785
1786 LockPaint();
1787 StartAllAction();
1788
1789 Imp()->GetDrawView()->UnmarkAll();
1790
1791 const tools::Rectangle &rBound = rSdrObj.GetSnapRect();
1792 Point aPt( rBound.TopRight() );
1793
1794 // alien identifier should end up on defaults
1795 // duplications possible!!
1796 sal_uInt16 nIdent = SdrInventor::Default == rSdrObj.GetObjInventor()
1797 ? rSdrObj.GetObjIdentifier()
1798 : 0xFFFF;
1799
1800 // default for controls character bound, otherwise paragraph bound.
1801 SwFormatAnchor aAnch;
1802 const SwFrame *pAnch = nullptr;
1803 bool bCharBound = false;
1804 if( dynamic_cast<const SdrUnoObj*>( &rSdrObj) != nullptr )
1805 {
1806 SwPosition aPos( GetDoc()->GetNodes() );
1807 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
1808 Point aPoint( aPt.getX(), aPt.getY() + rBound.GetHeight()/2 );
1809 GetLayout()->GetModelPositionForViewPoint( &aPos, aPoint, &aState );
1810
1811 // characterbinding not allowed in readonly-content
1812 if( !aPos.nNode.GetNode().IsProtect() )
1813 {
1814 std::pair<Point, bool> const tmp(aPoint, true);
1815 pAnch = aPos.nNode.GetNode().GetContentNode()->getLayoutFrame(GetLayout(), &aPos, &tmp);
1816 SwRect aTmp;
1817 pAnch->GetCharRect( aTmp, aPos );
1818
1819 // The crsr should not be too far away
1820 bCharBound = true;
1821 tools::Rectangle aRect( aTmp.SVRect() );
1822 aRect.AdjustLeft( -(MM50283*2) );
1823 aRect.AdjustTop( -(MM50283*2) );
1824 aRect.AdjustRight(MM50283*2 );
1825 aRect.AdjustBottom(MM50283*2 );
1826
1827 if( !aRect.IsOver( rBound ) && !::GetHtmlMode( GetDoc()->GetDocShell() ))
1828 bCharBound = false;
1829
1830 // anchor in header/footer also not allowed.
1831 if( bCharBound )
1832 bCharBound = !GetDoc()->IsInHeaderFooter( aPos.nNode );
1833
1834 if( bCharBound )
1835 {
1836 aAnch.SetType( RndStdIds::FLY_AS_CHAR );
1837 aAnch.SetAnchor( &aPos );
1838 }
1839 }
1840 }
1841
1842 if( !bCharBound )
1843 {
1844 // allow native drawing objects in header/footer.
1845 // Thus, set <bBodyOnly> to <false> for these objects using value
1846 // of <nIdent> - value <0xFFFF> indicates control objects, which aren't
1847 // allowed in header/footer.
1848 //bool bBodyOnly = OBJ_NONE != nIdent;
1849 bool bBodyOnly = 0xFFFF == nIdent;
1850 bool bAtPage = false;
1851 const SwFrame* pPage = nullptr;
1852 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
1853 Point aPoint( aPt );
1854 SwPosition aPos( GetDoc()->GetNodes() );
1855 GetLayout()->GetModelPositionForViewPoint( &aPos, aPoint, &aState );
1856
1857 // do not set in ReadnOnly-content
1858 if (aPos.nNode.GetNode().IsProtect())
1859 {
1860 // then only page bound. Or should we
1861 // search the next not-readonly position?
1862 bAtPage = true;
1863 }
1864
1865 SwContentNode* pCNode = aPos.nNode.GetNode().GetContentNode();
1866 std::pair<Point, bool> const tmp(aPoint, false);
1867 pAnch = pCNode ? pCNode->getLayoutFrame(GetLayout(), nullptr, &tmp) : nullptr;
1868 if (!pAnch)
1869 {
1870 // Hidden content. Anchor to the page instead
1871 bAtPage = true;
1872 }
1873
1874 if( !bAtPage )
1875 {
1876 const SwFlyFrame *pTmp = pAnch->FindFlyFrame();
1877 if( pTmp )
1878 {
1879 const SwFrame* pTmpFrame = pAnch;
1880 SwRect aBound( rBound );
1881 while( pTmp )
1882 {
1883 if( pTmp->getFrameArea().IsInside( aBound ) )
1884 {
1885 if( !bBodyOnly || !pTmp->FindFooterOrHeader() )
1886 pPage = pTmpFrame;
1887 break;
1888 }
1889 pTmp = pTmp->GetAnchorFrame()
1890 ? pTmp->GetAnchorFrame()->FindFlyFrame()
1891 : nullptr;
1892 pTmpFrame = pTmp;
1893 }
1894 }
1895
1896 if( !pPage )
1897 pPage = pAnch->FindPageFrame();
1898
1899 // Always via FindAnchor, to assure the frame will be bound
1900 // to the previous. With GetCrsOfst we can also reach the next. THIS IS WRONG.
1901 pAnch = ::FindAnchor( pPage, aPt, bBodyOnly );
1902 if (pAnch->IsTextFrame())
1903 {
1904 std::pair<SwTextNode const*, sal_Int32> const pos(
1905 static_cast<SwTextFrame const*>(pAnch)->MapViewToModel(TextFrameIndex(0)));
1906 aPos.nNode = *pos.first;
1907 }
1908 else
1909 {
1910 aPos.nNode = *static_cast<const SwNoTextFrame*>(pAnch)->GetNode();
1911 }
1912
1913 // do not set in ReadnOnly-content
1914 if( aPos.nNode.GetNode().IsProtect() )
1915 // then only page bound. Or should we
1916 // search the next not-readonly position?
1917 bAtPage = true;
1918 else
1919 {
1920 aAnch.SetType( RndStdIds::FLY_AT_PARA );
1921 aAnch.SetAnchor( &aPos );
1922 }
1923 }
1924
1925 if( bAtPage )
1926 {
1927 pPage = pAnch ? pAnch->FindPageFrame() : GetLayout()->GetPageAtPos(aPoint);
1928
1929 aAnch.SetType( RndStdIds::FLY_AT_PAGE );
1930 aAnch.SetPageNum( pPage->GetPhyPageNum() );
1931 pAnch = pPage; // page becomes an anchor
1932 }
1933 }
1934
1935 SfxItemSet aSet( GetDoc()->GetAttrPool(), svl::Items<RES_FRM_SIZE, RES_FRM_SIZE,
1936 RES_SURROUND, RES_ANCHOR>{} );
1937 aSet.Put( aAnch );
1938
1939 // OD 2004-03-30 #i26791# - determine relative object position
1940 SwTwips nXOffset;
1941 SwTwips nYOffset = rBound.Top() - pAnch->getFrameArea().Top();
1942 {
1943 if( pAnch->IsVertical() )
1944 {
1945 nXOffset = nYOffset;
1946 nYOffset = pAnch->getFrameArea().Left()+pAnch->getFrameArea().Width()-rBound.Right();
1947 }
1948 else if( pAnch->IsRightToLeft() )
1949 nXOffset = pAnch->getFrameArea().Left()+pAnch->getFrameArea().Width()-rBound.Right();
1950 else
1951 nXOffset = rBound.Left() - pAnch->getFrameArea().Left();
1952 if (pAnch->IsTextFrame())
1953 {
1954 const SwTextFrame* pTmp = static_cast<const SwTextFrame*>(pAnch);
1955 if (pTmp->IsFollow())
1956 {
1957 do {
1958 pTmp = pTmp->FindMaster();
1959 OSL_ENSURE(pTmp, "Where's my Master?")do { if (true && (!(pTmp))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "1959" ": "), "%s", "Where's my Master?"); } } while (false
)
;
1960 // OD 2004-03-30 #i26791# - correction: add frame area height
1961 // of master frames.
1962 nYOffset += pTmp->IsVertical() ?
1963 pTmp->getFrameArea().Width() : pTmp->getFrameArea().Height();
1964 } while (pTmp->IsFollow());
1965 }
1966
1967 nYOffset -= pTmp->GetBaseVertOffsetForFly(false);
1968 }
1969 }
1970
1971 if( OBJ_NONE == nIdent )
1972 {
1973 // For OBJ_NONE a fly is inserted.
1974 const long nWidth = rBound.Right() - rBound.Left();
1975 const long nHeight= rBound.Bottom() - rBound.Top();
1976 aSet.Put( SwFormatFrameSize( SwFrameSize::Minimum, std::max( nWidth, long(MINFLY23) ),
1977 std::max( nHeight, long(MINFLY23) )));
1978
1979 SwFormatHoriOrient aHori( nXOffset, text::HoriOrientation::NONE, text::RelOrientation::FRAME );
1980 SwFormatVertOrient aVert( nYOffset, text::VertOrientation::NONE, text::RelOrientation::FRAME );
1981 aSet.Put( SwFormatSurround( css::text::WrapTextMode_PARALLEL ) );
1982 aSet.Put( aHori );
1983 aSet.Put( aVert );
1984
1985 // Quickly store the square
1986 const SwRect aFlyRect( rBound );
1987
1988 // Throw away generated object, now the fly can nicely
1989 // via the available SS be generated.
1990 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false); // see above
1991 // #i52858# - method name changed
1992 SdrPage *pPg = getIDocumentDrawModelAccess().GetOrCreateDrawModel()->GetPage( 0 );
1993 if( !pPg )
1994 {
1995 SdrModel* pTmpSdrModel = getIDocumentDrawModelAccess().GetDrawModel();
1996 pPg = pTmpSdrModel->AllocPage( false );
1997 pTmpSdrModel->InsertPage( pPg );
1998 }
1999 pPg->RecalcObjOrdNums();
2000 SdrObject* pRemovedObject = pPg->RemoveObject( rSdrObj.GetOrdNumDirect() );
2001 SdrObject::Free( pRemovedObject );
2002 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
2003
2004 SwFlyFrame* pFlyFrame;
2005 if( NewFlyFrame( aSet, true ) &&
2006 ::GetHtmlMode( GetDoc()->GetDocShell() ) &&
2007 nullptr != ( pFlyFrame = GetSelectedFlyFrame() ))
2008 {
2009 SfxItemSet aHtmlSet( GetDoc()->GetAttrPool(), svl::Items<RES_VERT_ORIENT, RES_HORI_ORIENT>{} );
2010 // horizontal orientation:
2011 const bool bLeftFrame = aFlyRect.Left() <
2012 pAnch->getFrameArea().Left() + pAnch->getFramePrintArea().Left(),
2013 bLeftPrt = aFlyRect.Left() + aFlyRect.Width() <
2014 pAnch->getFrameArea().Left() + pAnch->getFramePrintArea().Width()/2;
2015 if( bLeftFrame || bLeftPrt )
2016 {
2017 aHori.SetHoriOrient( text::HoriOrientation::LEFT );
2018 aHori.SetRelationOrient( bLeftFrame ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
2019 }
2020 else
2021 {
2022 const bool bRightFrame = aFlyRect.Left() >
2023 pAnch->getFrameArea().Left() + pAnch->getFramePrintArea().Width();
2024 aHori.SetHoriOrient( text::HoriOrientation::RIGHT );
2025 aHori.SetRelationOrient( bRightFrame ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
2026 }
2027 aHtmlSet.Put( aHori );
2028 aVert.SetVertOrient( text::VertOrientation::TOP );
2029 aVert.SetRelationOrient( text::RelOrientation::PRINT_AREA );
2030 aHtmlSet.Put( aVert );
2031
2032 GetDoc()->SetAttr( aHtmlSet, *pFlyFrame->GetFormat() );
2033 }
2034 }
2035 else
2036 {
2037 if (rSdrObj.GetName().isEmpty())
2038 {
2039 bool bRestore = GetDoc()->GetIDocumentUndoRedo().DoesDrawUndo();
2040 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
2041 rSdrObj.SetName(GetUniqueShapeName());
2042 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(bRestore);
2043 }
2044
2045 Point aRelNullPt;
2046 if( OBJ_CAPTION == nIdent )
2047 aRelNullPt = static_cast<SdrCaptionObj&>(rSdrObj).GetTailPos();
2048 else
2049 aRelNullPt = rBound.TopLeft();
2050
2051 aSet.Put( aAnch );
2052 aSet.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH ) );
2053 // OD 2004-03-30 #i26791# - set horizontal position
2054 SwFormatHoriOrient aHori( nXOffset, text::HoriOrientation::NONE, text::RelOrientation::FRAME );
2055 aSet.Put( aHori );
2056 // OD 2004-03-30 #i26791# - set vertical position
2057 if( pAnch->IsTextFrame() && static_cast<const SwTextFrame*>(pAnch)->IsFollow() )
2058 {
2059 const SwTextFrame* pTmp = static_cast<const SwTextFrame*>(pAnch);
2060 do {
2061 pTmp = pTmp->FindMaster();
2062 assert(pTmp && "Where's my Master?")(static_cast <bool> (pTmp && "Where's my Master?"
) ? void (0) : __assert_fail ("pTmp && \"Where's my Master?\""
, "/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
, 2062, __extension__ __PRETTY_FUNCTION__))
;
2063 nYOffset += pTmp->IsVertical() ?
2064 pTmp->getFramePrintArea().Width() : pTmp->getFramePrintArea().Height();
2065 } while ( pTmp->IsFollow() );
2066 }
2067 SwFormatVertOrient aVert( nYOffset, text::VertOrientation::NONE, text::RelOrientation::FRAME );
2068 aSet.Put( aVert );
2069 SwDrawFrameFormat* pFormat = static_cast<SwDrawFrameFormat*>(getIDocumentLayoutAccess().MakeLayoutFormat( RndStdIds::DRAW_OBJECT, &aSet ));
2070 // #i36010# - set layout direction of the position
2071 pFormat->SetPositionLayoutDir(
2072 text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
2073 // #i44344#, #i44681# - positioning attributes already set
2074 pFormat->PosAttrSet();
2075 pFormat->SetName(rSdrObj.GetName());
2076
2077 SwDrawContact *pContact = new SwDrawContact( pFormat, &rSdrObj );
2078 // #i35635#
2079 pContact->MoveObjToVisibleLayer( &rSdrObj );
2080 if( bCharBound )
2081 {
2082 OSL_ENSURE( aAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR, "wrong AnchorType" )do { if (true && (!(aAnch.GetAnchorId() == RndStdIds::
FLY_AS_CHAR))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "2082" ": "), "%s", "wrong AnchorType"); } } while (false
)
;
2083 SwTextNode *pNd = aAnch.GetContentAnchor()->nNode.GetNode().GetTextNode();
2084 SwFormatFlyCnt aFormat( pFormat );
2085 pNd->InsertItem(aFormat,
2086 aAnch.GetContentAnchor()->nContent.GetIndex(), 0 );
2087 SwFormatVertOrient aVertical( pFormat->GetVertOrient() );
2088 aVertical.SetVertOrient( text::VertOrientation::LINE_CENTER );
2089 pFormat->SetFormatAttr( aVertical );
2090 }
2091 if( pAnch->IsTextFrame() && static_cast<const SwTextFrame*>(pAnch)->IsFollow() )
2092 {
2093 const SwTextFrame* pTmp = static_cast<const SwTextFrame*>(pAnch);
2094 do {
2095 pTmp = pTmp->FindMaster();
2096 OSL_ENSURE( pTmp, "Where's my Master?" )do { if (true && (!(pTmp))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "2096" ": "), "%s", "Where's my Master?"); } } while (false
)
;
2097 } while( pTmp->IsFollow() );
2098 pAnch = pTmp;
2099 }
2100
2101 pContact->ConnectToLayout();
2102
2103 // mark object at frame the object is inserted at.
2104 {
2105 SdrObject* pMarkObj = pContact->GetDrawObjectByAnchorFrame( *pAnch );
2106 if ( pMarkObj )
2107 {
2108 Imp()->GetDrawView()->MarkObj( pMarkObj, Imp()->GetPageView() );
2109 }
2110 else
2111 {
2112 Imp()->GetDrawView()->MarkObj( &rSdrObj, Imp()->GetPageView() );
2113 }
2114 }
2115 }
2116
2117 GetDoc()->getIDocumentState().SetModified();
2118
2119 KillPams();
2120 EndAllActionAndCall();
2121 UnlockPaint();
2122 return true;
2123}
2124
2125void SwFEShell::BreakCreate()
2126{
2127 OSL_ENSURE( Imp()->HasDrawView(), "BreakCreate without DrawView?" )do { if (true && (!(Imp()->HasDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "2127" ": "), "%s", "BreakCreate without DrawView?"); } }
while (false)
;
2128 Imp()->GetDrawView()->BrkCreateObj();
2129 ::FrameNotify( this, FLY_DRAG_END );
2130}
2131
2132bool SwFEShell::IsDrawCreate() const
2133{
2134 return Imp()->HasDrawView() && Imp()->GetDrawView()->IsCreateObj();
2135}
2136
2137bool SwFEShell::BeginMark( const Point &rPos )
2138{
2139 if ( !Imp()->HasDrawView() )
2140 Imp()->MakeDrawView();
2141
2142 if ( GetPageNumber( rPos ) )
2143 {
2144 SwDrawView* pDView = Imp()->GetDrawView();
2145
2146 if (pDView->HasMarkablePoints())
2147 return pDView->BegMarkPoints( rPos );
2148 else
2149 {
2150 pDView->BegMarkObj( rPos );
2151 return true;
2152 }
2153 }
2154 else
2155 return false;
2156}
2157
2158void SwFEShell::MoveMark( const Point &rPos )
2159{
2160 OSL_ENSURE( Imp()->HasDrawView(), "MoveMark without DrawView?" )do { if (true && (!(Imp()->HasDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "2160" ": "), "%s", "MoveMark without DrawView?"); } } while
(false)
;
2161
2162 if ( GetPageNumber( rPos ) )
2163 {
2164 ScrollTo( rPos );
2165 SwDrawView* pDView = Imp()->GetDrawView();
2166
2167 if (pDView->IsInsObjPoint())
2168 pDView->MovInsObjPoint( rPos );
2169 else if (pDView->IsMarkPoints())
2170 pDView->MovMarkPoints( rPos );
2171 else
2172 pDView->MovAction( rPos );
2173 }
2174}
2175
2176bool SwFEShell::EndMark()
2177{
2178 bool bRet = false;
2179 OSL_ENSURE( Imp()->HasDrawView(), "EndMark without DrawView?" )do { if (true && (!(Imp()->HasDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "2179" ": "), "%s", "EndMark without DrawView?"); } } while
(false)
;
2180
2181 if (Imp()->GetDrawView()->IsMarkObj())
2182 {
2183 bRet = Imp()->GetDrawView()->EndMarkObj();
2184
2185 if ( bRet )
2186 {
2187 bool bShowHdl = false;
2188 SwDrawView* pDView = Imp()->GetDrawView();
2189 // frames are not selected this way, except when
2190 // it is only one frame
2191 SdrMarkList &rMrkList = const_cast<SdrMarkList&>(pDView->GetMarkedObjectList());
2192 SwFlyFrame* pOldSelFly = ::GetFlyFromMarked( &rMrkList, this );
2193
2194 if ( rMrkList.GetMarkCount() > 1 )
2195 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
2196 {
2197 SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
2198 if( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) != nullptr )
2199 {
2200 if ( !bShowHdl )
2201 {
2202 bShowHdl = true;
2203 }
2204 rMrkList.DeleteMark( i );
2205 --i; // no exceptions
2206 }
2207 }
2208
2209 if( bShowHdl )
2210 {
2211 pDView->MarkListHasChanged();
2212 pDView->AdjustMarkHdl();
2213 }
2214
2215 if ( rMrkList.GetMarkCount() )
2216 ::lcl_GrabCursor(this, pOldSelFly);
2217 else
2218 bRet = false;
2219 }
2220 if ( bRet )
2221 ::FrameNotify( this, FLY_DRAG_START );
2222 }
2223 else
2224 {
2225 if (Imp()->GetDrawView()->IsMarkPoints())
2226 bRet = Imp()->GetDrawView()->EndMarkPoints();
2227 }
2228
2229 SetChainMarker();
2230 return bRet;
2231}
2232
2233RndStdIds SwFEShell::GetAnchorId() const
2234{
2235 RndStdIds nRet = RndStdIds(SHRT_MAX32767);
2236 if ( Imp()->HasDrawView() )
2237 {
2238 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2239 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
2240 {
2241 SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
2242 if ( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) != nullptr )
2243 {
2244 nRet = RndStdIds::UNKNOWN;
2245 break;
2246 }
2247 SwDrawContact *pContact = static_cast<SwDrawContact*>(GetUserCall(pObj));
2248 RndStdIds nId = pContact->GetFormat()->GetAnchor().GetAnchorId();
2249 if ( nRet == RndStdIds(SHRT_MAX32767) )
2250 nRet = nId;
2251 else if ( nRet != nId )
2252 {
2253 nRet = RndStdIds::UNKNOWN;
2254 break;
2255 }
2256 }
2257 }
2258 if ( nRet == RndStdIds(SHRT_MAX32767) )
2259 nRet = RndStdIds::UNKNOWN;
2260 return nRet;
2261}
2262
2263void SwFEShell::ChgAnchor( RndStdIds eAnchorId, bool bSameOnly, bool bPosCorr )
2264{
2265 OSL_ENSURE( Imp()->HasDrawView(), "ChgAnchor without DrawView?" )do { if (true && (!(Imp()->HasDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "2265" ": "), "%s", "ChgAnchor without DrawView?"); } } while
(false)
;
2266 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2267 if( rMrkList.GetMarkCount() &&
2268 !rMrkList.GetMark( 0 )->GetMarkedSdrObj()->getParentSdrObjectFromSdrObject() )
2269 {
2270 StartAllAction();
2271
2272 if( GetDoc()->ChgAnchor( rMrkList, eAnchorId, bSameOnly, bPosCorr ))
2273 Imp()->GetDrawView()->UnmarkAll();
2274
2275 EndAllAction();
2276
2277 ::FrameNotify( this );
2278 }
2279}
2280
2281void SwFEShell::DelSelectedObj()
2282{
2283 OSL_ENSURE( Imp()->HasDrawView(), "DelSelectedObj(), no DrawView available" )do { if (true && (!(Imp()->HasDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "2283" ": "), "%s", "DelSelectedObj(), no DrawView available"
); } } while (false)
;
2284 if ( Imp()->HasDrawView() )
2285 {
2286 StartAllAction();
2287 Imp()->GetDrawView()->DeleteMarked();
2288 EndAllAction();
2289 ::FrameNotify( this, FLY_DRAG_END );
2290 }
2291}
2292
2293// For the statusline to request the current conditions
2294Size SwFEShell::GetObjSize() const
2295{
2296 tools::Rectangle aRect;
2297 if ( Imp()->HasDrawView() )
2298 {
2299 if ( Imp()->GetDrawView()->IsAction() )
2300 Imp()->GetDrawView()->TakeActionRect( aRect );
2301 else
2302 aRect = Imp()->GetDrawView()->GetAllMarkedRect();
2303 }
2304 return aRect.GetSize();
2305}
2306
2307Point SwFEShell::GetAnchorObjDiff() const
2308{
2309 const SdrView *pView = Imp()->GetDrawView();
2310 OSL_ENSURE( pView, "GetAnchorObjDiff without DrawView?" )do { if (true && (!(pView))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "2310" ": "), "%s", "GetAnchorObjDiff without DrawView?"
); } } while (false)
;
2311
2312 tools::Rectangle aRect;
2313 if ( Imp()->GetDrawView()->IsAction() )
2314 Imp()->GetDrawView()->TakeActionRect( aRect );
2315 else
2316 aRect = Imp()->GetDrawView()->GetAllMarkedRect();
2317
2318 Point aRet( aRect.TopLeft() );
2319
2320 if ( IsFrameSelected() )
2321 {
2322 SwFlyFrame *pFly = GetSelectedFlyFrame();
2323 aRet -= pFly->GetAnchorFrame()->getFrameArea().Pos();
2324 }
2325 else
2326 {
2327 const SdrObject *pObj = pView->GetMarkedObjectList().GetMarkCount() == 1 ?
2328 pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj() : nullptr;
2329 if ( pObj )
2330 aRet -= pObj->GetAnchorPos();
2331 }
2332
2333 return aRet;
2334}
2335
2336Point SwFEShell::GetObjAbsPos() const
2337{
2338 OSL_ENSURE( Imp()->GetDrawView(), "GetObjAbsPos() without DrawView?" )do { if (true && (!(Imp()->GetDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "2338" ": "), "%s", "GetObjAbsPos() without DrawView?");
} } while (false)
;
2339 return Imp()->GetDrawView()->GetDragStat().GetActionRect().TopLeft();
2340}
2341
2342bool SwFEShell::IsGroupSelected()
2343{
2344 if ( IsObjSelected() )
2345 {
2346 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2347 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
2348 {
2349 SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
2350 // consider 'virtual' drawing objects.
2351 // Thus, use corresponding method instead of checking type.
2352 if ( pObj->IsGroupObject() &&
2353 // --> #i38505# No ungroup allowed for 3d objects
2354 !pObj->Is3DObj() &&
2355 RndStdIds::FLY_AS_CHAR != static_cast<SwDrawContact*>(GetUserCall(pObj))->
2356 GetFormat()->GetAnchor().GetAnchorId() )
2357 {
2358 return true;
2359 }
2360 }
2361 }
2362 return false;
2363}
2364
2365namespace
2366{
2367 bool HasSuitableGroupingAnchor(const SdrObject* pObj)
2368 {
2369 bool bSuitable = true;
2370 SwFrameFormat* pFrameFormat(::FindFrameFormat(const_cast<SdrObject*>(pObj)));
2371 if (!pFrameFormat)
2372 {
2373 OSL_FAIL( "<HasSuitableGroupingAnchor> - missing frame format" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "2373" ": "), "%s", "<HasSuitableGroupingAnchor> - missing frame format"
); } } while (false)
;
2374 bSuitable = false;
2375 }
2376 else if (RndStdIds::FLY_AS_CHAR == pFrameFormat->GetAnchor().GetAnchorId())
2377 {
2378 bSuitable = false;
2379 }
2380 return bSuitable;
2381 }
2382}
2383
2384// Change return type.
2385// Adjustments for drawing objects in header/footer:
2386// allow group, only if all selected objects are in the same header/footer
2387// or not in header/footer.
2388bool SwFEShell::IsGroupAllowed() const
2389{
2390 bool bIsGroupAllowed = false;
2391 if ( IsObjSelected() > 1 )
2392 {
2393 bIsGroupAllowed = true;
2394 const SdrObject* pUpGroup = nullptr;
2395 const SwFrame* pHeaderFooterFrame = nullptr;
2396 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2397 for ( size_t i = 0; bIsGroupAllowed && i < rMrkList.GetMarkCount(); ++i )
2398 {
2399 const SdrObject* pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
2400 if ( i )
2401 bIsGroupAllowed = pObj->getParentSdrObjectFromSdrObject() == pUpGroup;
2402 else
2403 pUpGroup = pObj->getParentSdrObjectFromSdrObject();
2404
2405 if ( bIsGroupAllowed )
2406 bIsGroupAllowed = HasSuitableGroupingAnchor(pObj);
2407
2408 // check, if all selected objects are in the
2409 // same header/footer or not in header/footer.
2410 if ( bIsGroupAllowed )
2411 {
2412 const SwFrame* pAnchorFrame = nullptr;
2413 if ( auto pVirtFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>( pObj) )
2414 {
2415 const SwFlyFrame* pFlyFrame = pVirtFlyDrawObj->GetFlyFrame();
2416 if ( pFlyFrame )
2417 {
2418 pAnchorFrame = pFlyFrame->GetAnchorFrame();
2419 }
2420 }
2421 else
2422 {
2423 SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(GetUserCall( pObj ));
2424 if ( pDrawContact )
2425 {
2426 pAnchorFrame = pDrawContact->GetAnchorFrame( pObj );
2427 }
2428 }
2429 if ( pAnchorFrame )
2430 {
2431 if ( i )
2432 {
2433 bIsGroupAllowed =
2434 ( pAnchorFrame->FindFooterOrHeader() == pHeaderFooterFrame );
2435 }
2436 else
2437 {
2438 pHeaderFooterFrame = pAnchorFrame->FindFooterOrHeader();
2439 }
2440 }
2441 }
2442 }
2443 }
2444
2445 return bIsGroupAllowed;
2446}
2447
2448bool SwFEShell::IsUnGroupAllowed() const
2449{
2450 bool bIsUnGroupAllowed = false;
2451
2452 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2453 for (size_t i = 0; i < rMrkList.GetMarkCount(); ++i)
2454 {
2455 const SdrObject* pObj = rMrkList.GetMark(i)->GetMarkedSdrObj();
2456 bIsUnGroupAllowed = HasSuitableGroupingAnchor(pObj);
2457 if (!bIsUnGroupAllowed)
2458 break;
2459 }
2460
2461 return bIsUnGroupAllowed;
2462}
2463
2464// The group gets the anchor and the contactobject of the first in the selection
2465void SwFEShell::GroupSelection()
2466{
2467 if ( IsGroupAllowed() )
2468 {
2469 StartAllAction();
2470 StartUndo( SwUndoId::START );
2471
2472 GetDoc()->GroupSelection( *Imp()->GetDrawView() );
2473
2474 EndUndo( SwUndoId::END );
2475 EndAllAction();
2476 }
2477}
2478
2479// The individual objects get a copy of the anchor and the contactobject of the group
2480void SwFEShell::UnGroupSelection()
2481{
2482 if ( IsGroupSelected() )
2483 {
2484 StartAllAction();
2485 StartUndo( SwUndoId::START );
2486
2487 GetDoc()->UnGroupSelection( *Imp()->GetDrawView() );
2488
2489 EndUndo( SwUndoId::END );
2490 EndAllAction();
2491 }
2492}
2493
2494void SwFEShell::MirrorSelection( bool bHorizontal )
2495{
2496 SdrView *pView = Imp()->GetDrawView();
2497 if ( IsObjSelected() && pView->IsMirrorAllowed() )
2498 {
2499 if ( bHorizontal )
2500 pView->MirrorAllMarkedHorizontal();
2501 else
2502 pView->MirrorAllMarkedVertical();
2503 }
2504}
2505
2506// jump to named frame (Graphic/OLE)
2507
2508bool SwFEShell::GotoFly( const OUString& rName, FlyCntType eType, bool bSelFrame )
2509{
2510 bool bRet = false;
2511 static SwNodeType const aChkArr[ 4 ] = {
2512 /* FLYCNTTYPE_ALL */ SwNodeType::NONE,
2513 /* FLYCNTTYPE_FRM */ SwNodeType::Text,
2514 /* FLYCNTTYPE_GRF */ SwNodeType::Grf,
2515 /* FLYCNTTYPE_OLE */ SwNodeType::Ole
2516 };
2517
2518 const SwFlyFrameFormat* pFlyFormat = mxDoc->FindFlyByName( rName, aChkArr[ eType]);
2519 if( pFlyFormat )
2520 {
2521 CurrShell aCurr( this );
2522
2523 SwFlyFrame* pFrame = SwIterator<SwFlyFrame,SwFormat>( *pFlyFormat ).First();
2524 if( pFrame )
2525 {
2526 if( bSelFrame )
2527 {
2528 // first make visible, to get a11y events in proper order
2529 if (!ActionPend())
2530 MakeVisible( pFrame->getFrameArea() );
2531 SelectObj( pFrame->getFrameArea().Pos(), 0, pFrame->GetVirtDrawObj() );
2532 }
2533 else
2534 {
2535 SwContentFrame *pCFrame = pFrame->ContainsContent();
2536 if ( pCFrame )
2537 {
2538 ClearMark();
2539 SwPaM* pCursor = GetCursor();
2540
2541 if (pCFrame->IsTextFrame())
2542 {
2543 *pCursor->GetPoint() = static_cast<SwTextFrame *>(pCFrame)
2544 ->MapViewToModelPos(TextFrameIndex(0));
2545 }
2546 else
2547 {
2548 assert(pCFrame->IsNoTextFrame())(static_cast <bool> (pCFrame->IsNoTextFrame()) ? void
(0) : __assert_fail ("pCFrame->IsNoTextFrame()", "/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
, 2548, __extension__ __PRETTY_FUNCTION__))
;
2549 SwContentNode *const pCNode = static_cast<SwNoTextFrame *>(pCFrame)->GetNode();
2550
2551 pCursor->GetPoint()->nNode = *pCNode;
2552 pCursor->GetPoint()->nContent.Assign( pCNode, 0 );
2553 }
2554
2555 SwRect& rChrRect = const_cast<SwRect&>(GetCharRect());
2556 rChrRect = pFrame->getFramePrintArea();
2557 rChrRect.Pos() += pFrame->getFrameArea().Pos();
2558 GetCursorDocPos() = rChrRect.Pos();
2559 }
2560 }
2561 bRet = true;
2562 }
2563 }
2564 return bRet;
2565}
2566
2567size_t SwFEShell::GetFlyCount( FlyCntType eType, bool bIgnoreTextBoxes ) const
2568{
2569 return GetDoc()->GetFlyCount(eType, bIgnoreTextBoxes);
2570}
2571
2572const SwFrameFormat* SwFEShell::GetFlyNum(size_t nIdx, FlyCntType eType, bool bIgnoreTextBoxes ) const
2573{
2574 return GetDoc()->GetFlyNum(nIdx, eType, bIgnoreTextBoxes);
2575}
2576
2577std::vector<SwFrameFormat const*> SwFEShell::GetFlyFrameFormats(
2578 FlyCntType const eType, bool const bIgnoreTextBoxes)
2579{
2580 return GetDoc()->GetFlyFrameFormats(eType, bIgnoreTextBoxes);
2581}
2582
2583// show the current selected object
2584void SwFEShell::MakeSelVisible()
2585{
2586 if ( Imp()->HasDrawView() &&
2587 Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2588 {
2589 GetCurrFrame(); // just to trigger formatting in case the selected object is not formatted.
2590 MakeVisible( Imp()->GetDrawView()->GetAllMarkedRect() );
2591 }
2592 else
2593 SwCursorShell::MakeSelVisible();
2594}
2595
2596// how is the selected object protected?
2597FlyProtectFlags SwFEShell::IsSelObjProtected( FlyProtectFlags eType ) const
2598{
2599 FlyProtectFlags nChk = FlyProtectFlags::NONE;
2600 const bool bParent(eType & FlyProtectFlags::Parent);
2601 if( Imp()->HasDrawView() )
2602 {
2603 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2604 for( size_t i = rMrkList.GetMarkCount(); i; )
2605 {
2606 SdrObject *pObj = rMrkList.GetMark( --i )->GetMarkedSdrObj();
2607 if( !bParent )
2608 {
2609 nChk |= ( pObj->IsMoveProtect() ? FlyProtectFlags::Pos : FlyProtectFlags::NONE ) |
2610 ( pObj->IsResizeProtect()? FlyProtectFlags::Size : FlyProtectFlags::NONE );
2611
2612 if (SwVirtFlyDrawObj* pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pObj))
2613 {
2614 SwFlyFrame *pFly = pVirtO->GetFlyFrame();
2615 if ( (FlyProtectFlags::Content & eType) && pFly->GetFormat()->GetProtect().IsContentProtected() )
2616 nChk |= FlyProtectFlags::Content;
2617
2618 if ( pFly->Lower() && pFly->Lower()->IsNoTextFrame() )
2619 {
2620 SwOLENode *pNd = static_cast<SwNoTextFrame*>(pFly->Lower())->GetNode()->GetOLENode();
2621 uno::Reference < embed::XEmbeddedObject > xObj( pNd ? pNd->GetOLEObj().GetOleRef() : nullptr );
2622 if ( xObj.is() )
2623 {
2624 // TODO/LATER: use correct aspect
2625 const bool bNeverResize = (embed::EmbedMisc::EMBED_NEVERRESIZE & xObj->getStatus( embed::Aspects::MSOLE_CONTENT ));
2626 if ( ( (FlyProtectFlags::Content & eType) || (FlyProtectFlags::Size & eType) ) && bNeverResize )
2627 {
2628 nChk |= FlyProtectFlags::Size;
2629 nChk |= FlyProtectFlags::Fixed;
2630 }
2631
2632 // set FlyProtectFlags::Pos if it is a Math object anchored 'as char' and baseline alignment is activated
2633 const bool bProtectMathPos = SotExchange::IsMath( xObj->getClassID() )
2634 && RndStdIds::FLY_AS_CHAR == pFly->GetFormat()->GetAnchor().GetAnchorId()
2635 && mxDoc->GetDocumentSettingManager().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT );
2636 if ((FlyProtectFlags::Pos & eType) && bProtectMathPos)
2637 nChk |= FlyProtectFlags::Pos;
2638 }
2639 }
2640 }
2641 nChk &= eType;
2642 if( nChk == eType )
2643 return eType;
2644 }
2645 const SwFrame* pAnch;
2646 if (SwVirtFlyDrawObj* pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pObj))
2647 pAnch = pVirtO->GetFlyFrame()->GetAnchorFrame();
2648 else
2649 {
2650 SwDrawContact* pTmp = static_cast<SwDrawContact*>(GetUserCall(pObj));
2651 pAnch = pTmp ? pTmp->GetAnchorFrame( pObj ) : nullptr;
2652 }
2653 if( pAnch && pAnch->IsProtected() )
2654 return eType;
2655 }
2656 }
2657 return nChk;
2658}
2659
2660bool SwFEShell::GetObjAttr( SfxItemSet &rSet ) const
2661{
2662 if ( !IsObjSelected() )
2663 return false;
2664
2665 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2666 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
2667 {
2668 SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
2669 SwDrawContact *pContact = static_cast<SwDrawContact*>(GetUserCall(pObj));
2670 // --> make code robust
2671 OSL_ENSURE( pContact, "<SwFEShell::GetObjAttr(..)> - missing <pContact>." )do { if (true && (!(pContact))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "2671" ": "), "%s", "<SwFEShell::GetObjAttr(..)> - missing <pContact>."
); } } while (false)
;
2672 if ( pContact )
2673 {
2674 if ( i )
2675 rSet.MergeValues( pContact->GetFormat()->GetAttrSet() );
2676 else
2677 rSet.Put( pContact->GetFormat()->GetAttrSet() );
2678 }
2679 }
2680 return true;
2681}
2682
2683void SwFEShell::SetObjAttr( const SfxItemSet& rSet )
2684{
2685 CurrShell aCurr( this );
2686
2687 if ( !rSet.Count() )
2688 {
2689 OSL_ENSURE( false, "SetObjAttr, empty set." )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "2689" ": "), "%s", "SetObjAttr, empty set."); } } while
(false)
;
2690 return;
2691 }
2692
2693 StartAllAction();
2694 StartUndo( SwUndoId::INSATTR );
2695
2696 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2697 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
2698 {
2699 SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
2700 SwDrawContact *pContact = static_cast<SwDrawContact*>(GetUserCall(pObj));
2701 GetDoc()->SetAttr( rSet, *pContact->GetFormat() );
2702 }
2703
2704 EndUndo( SwUndoId::INSATTR );
2705 EndAllActionAndCall();
2706 GetDoc()->getIDocumentState().SetModified();
2707}
2708
2709bool SwFEShell::IsAlignPossible() const
2710{
2711 return Imp()->GetDrawView()->IsAlignPossible();
2712}
2713
2714void SwFEShell::CheckUnboundObjects()
2715{
2716 CurrShell aCurr( this );
2717
2718 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2719 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
2720 {
2721 SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
2722 if ( !GetUserCall(pObj) )
2723 {
2724 const tools::Rectangle &rBound = pObj->GetSnapRect();
2725 const Point aPt( rBound.TopLeft() );
2726 const SwFrame *pPage = GetLayout()->Lower();
2727 const SwFrame *pLast = pPage;
2728 while ( pPage && !pPage->getFrameArea().IsInside( aPt ) )
2729 {
2730 if ( aPt.Y() > pPage->getFrameArea().Bottom() )
2731 pLast = pPage;
2732 pPage = pPage->GetNext();
2733 }
2734 if ( !pPage )
2735 pPage = pLast;
2736 OSL_ENSURE( pPage, "Page not found." )do { if (true && (!(pPage))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "2736" ": "), "%s", "Page not found."); } } while (false
)
;
2737
2738 // Alien identifier should roll into the default,
2739 // Duplications are possible!!
2740 sal_uInt16 nIdent =
2741 Imp()->GetDrawView()->GetCurrentObjInventor() == SdrInventor::Default ?
2742 Imp()->GetDrawView()->GetCurrentObjIdentifier() : 0xFFFF;
2743
2744 SwFormatAnchor aAnch;
2745 {
2746 const SwContentFrame *const pAnch = ::FindAnchor(pPage, aPt, true);
2747 SwPosition aPos( pAnch->IsTextFrame()
2748 ? *static_cast<SwTextFrame const*>(pAnch)->GetTextNodeForParaProps()
2749 : *static_cast<SwNoTextFrame const*>(pAnch)->GetNode() );
2750 aAnch.SetType( RndStdIds::FLY_AT_PARA );
2751 aAnch.SetAnchor( &aPos );
2752 const_cast<SwRect&>(GetCharRect()).Pos() = aPt;
2753 }
2754
2755 // First the action here, to assure GetCharRect delivers current values.
2756 StartAllAction();
2757
2758 SfxItemSet aSet( GetAttrPool(), svl::Items<RES_FRM_SIZE, RES_FRM_SIZE,
2759 RES_SURROUND, RES_ANCHOR>{} );
2760 aSet.Put( aAnch );
2761
2762 Point aRelNullPt;
2763
2764 if( OBJ_CAPTION == nIdent )
2765 aRelNullPt = static_cast<SdrCaptionObj*>(pObj)->GetTailPos();
2766 else
2767 aRelNullPt = rBound.TopLeft();
2768
2769 aSet.Put( aAnch );
2770 aSet.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH ) );
2771 SwFrameFormat* pFormat = getIDocumentLayoutAccess().MakeLayoutFormat( RndStdIds::DRAW_OBJECT, &aSet );
2772
2773 SwDrawContact *pContact = new SwDrawContact(
2774 static_cast<SwDrawFrameFormat*>(pFormat), pObj );
2775
2776 // #i35635#
2777 pContact->MoveObjToVisibleLayer( pObj );
2778 pContact->ConnectToLayout();
2779
2780 EndAllAction();
2781 }
2782 }
2783}
2784
2785void SwFEShell::SetCalcFieldValueHdl(Outliner* pOutliner)
2786{
2787 GetDoc()->SetCalcFieldValueHdl(pOutliner);
2788}
2789
2790SwChainRet SwFEShell::Chainable( SwRect &rRect, const SwFrameFormat &rSource,
2791 const Point &rPt ) const
2792{
2793 rRect.Clear();
2794
2795 // The source is not allowed to have a follow.
2796 const SwFormatChain &rChain = rSource.GetChain();
2797 if ( rChain.GetNext() )
2798 return SwChainRet::SOURCE_CHAINED;
2799
2800 SwChainRet nRet = SwChainRet::NOT_FOUND;
2801 if( Imp()->HasDrawView() )
2802 {
2803 SdrPageView* pPView;
2804 SwDrawView *pDView = const_cast<SwDrawView*>(Imp()->GetDrawView());
2805 const auto nOld = pDView->GetHitTolerancePixel();
2806 pDView->SetHitTolerancePixel( 0 );
2807 SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPView, SdrSearchOptions::PICKMARKABLE);
2808 SwVirtFlyDrawObj* pDrawObj = dynamic_cast<SwVirtFlyDrawObj*>(pObj);
2809 if (pDrawObj)
2810 {
2811 SwFlyFrame *pFly = pDrawObj->GetFlyFrame();
2812 rRect = pFly->getFrameArea();
2813
2814 // Target and source should not be equal and the list
2815 // should not be cyclic
2816 SwFrameFormat *pFormat = pFly->GetFormat();
2817 nRet = GetDoc()->Chainable(rSource, *pFormat);
2818 }
2819 pDView->SetHitTolerancePixel( nOld );
2820 }
2821 return nRet;
2822}
2823
2824void SwFEShell::Chain( SwFrameFormat &rSource, const SwFrameFormat &rDest )
2825{
2826 GetDoc()->Chain(rSource, rDest);
2827}
2828
2829SwChainRet SwFEShell::Chain( SwFrameFormat &rSource, const Point &rPt )
2830{
2831 SwRect aDummy;
2832 SwChainRet nErr = Chainable( aDummy, rSource, rPt );
2833 if ( nErr == SwChainRet::OK )
2834 {
2835 StartAllAction();
2836 SdrPageView* pPView;
2837 SwDrawView *pDView = Imp()->GetDrawView();
2838 const auto nOld = pDView->GetHitTolerancePixel();
2839 pDView->SetHitTolerancePixel( 0 );
2840 SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPView, SdrSearchOptions::PICKMARKABLE);
2841 pDView->SetHitTolerancePixel( nOld );
2842 SwFlyFrame *pFly = static_cast<SwVirtFlyDrawObj*>(pObj)->GetFlyFrame();
2843
2844 SwFlyFrameFormat *pFormat = pFly->GetFormat();
2845 GetDoc()->Chain(rSource, *pFormat);
2846 EndAllAction();
2847 SetChainMarker();
2848 }
2849 return nErr;
2850}
2851
2852void SwFEShell::Unchain( SwFrameFormat &rFormat )
2853{
2854 StartAllAction();
2855 GetDoc()->Unchain(rFormat);
2856 EndAllAction();
2857}
2858
2859void SwFEShell::HideChainMarker()
2860{
2861 m_pChainFrom.reset();
2862 m_pChainTo.reset();
2863}
2864
2865void SwFEShell::SetChainMarker()
2866{
2867 bool bDelFrom = true,
2868 bDelTo = true;
2869 if ( IsFrameSelected() )
2870 {
2871 SwFlyFrame *pFly = GetSelectedFlyFrame();
2872
2873 if ( pFly->GetPrevLink() )
2874 {
2875 bDelFrom = false;
2876 const SwFrame *pPre = pFly->GetPrevLink();
2877
2878 Point aStart( pPre->getFrameArea().Right(), pPre->getFrameArea().Bottom());
2879 Point aEnd(pFly->getFrameArea().Pos());
2880
2881 if (!m_pChainFrom)
2882 {
2883 m_pChainFrom.reset(
2884 new SdrDropMarkerOverlay( *GetDrawView(), aStart, aEnd ));
2885 }
2886 }
2887 if ( pFly->GetNextLink() )
2888 {
2889 bDelTo = false;
2890 const SwFlyFrame *pNxt = pFly->GetNextLink();
2891
2892 Point aStart( pFly->getFrameArea().Right(), pFly->getFrameArea().Bottom());
2893 Point aEnd(pNxt->getFrameArea().Pos());
2894
2895 if (!m_pChainTo)
2896 {
2897 m_pChainTo.reset(
2898 new SdrDropMarkerOverlay( *GetDrawView(), aStart, aEnd ));
2899 }
2900 }
2901 }
2902
2903 if ( bDelFrom )
2904 {
2905 m_pChainFrom.reset();
2906 }
2907
2908 if ( bDelTo )
2909 {
2910 m_pChainTo.reset();
2911 }
2912}
2913
2914long SwFEShell::GetSectionWidth( SwFormat const & rFormat ) const
2915{
2916 SwFrame *pFrame = GetCurrFrame();
2917 // Is the cursor at this moment in a SectionFrame?
2918 if( pFrame && pFrame->IsInSct() )
2919 {
2920 SwSectionFrame* pSect = pFrame->FindSctFrame();
2921 do
2922 {
2923 // Is it the right one?
2924 if( pSect->KnowsFormat( rFormat ) )
2925 return pSect->getFrameArea().Width();
2926 // for nested areas
2927 pSect = pSect->GetUpper()->FindSctFrame();
2928 }
2929 while( pSect );
2930 }
2931 SwIterator<SwSectionFrame,SwFormat> aIter( rFormat );
2932 for ( SwSectionFrame* pSct = aIter.First(); pSct; pSct = aIter.Next() )
2933 {
2934 if( !pSct->IsFollow() )
2935 {
2936 return pSct->getFrameArea().Width();
2937 }
2938 }
2939 return 0;
2940}
2941
2942 void SwFEShell::CreateDefaultShape( sal_uInt16 /*SdrObjKind ?*/ eSdrObjectKind, const tools::Rectangle& rRect,
2943 sal_uInt16 nSlotId)
2944{
2945 SdrView* pDrawView = GetDrawView();
2946 SdrModel* pDrawModel = pDrawView->GetModel();
2947 SdrObject* pObj = SdrObjFactory::MakeNewObject(
2948 *pDrawModel,
2949 SdrInventor::Default,
2950 eSdrObjectKind);
2951
2952 if(pObj)
2953 {
2954 tools::Rectangle aRect(rRect);
2955 if(OBJ_CARC == eSdrObjectKind || OBJ_CCUT == eSdrObjectKind)
2956 {
2957 // force quadratic
2958 if(aRect.GetWidth() > aRect.GetHeight())
2959 {
2960 aRect = tools::Rectangle(
2961 Point(aRect.Left() + ((aRect.GetWidth() - aRect.GetHeight()) / 2), aRect.Top()),
2962 Size(aRect.GetHeight(), aRect.GetHeight()));
2963 }
2964 else
2965 {
2966 aRect = tools::Rectangle(
2967 Point(aRect.Left(), aRect.Top() + ((aRect.GetHeight() - aRect.GetWidth()) / 2)),
2968 Size(aRect.GetWidth(), aRect.GetWidth()));
2969 }
2970 }
2971 pObj->SetLogicRect(aRect);
2972
2973 Point aStart = aRect.TopLeft();
2974 Point aEnd = aRect.BottomRight();
2975
2976 if(dynamic_cast<const SdrCircObj*>( pObj) != nullptr)
2977 {
2978 SfxItemSet aAttr(pDrawModel->GetItemPool());
2979 aAttr.Put(makeSdrCircStartAngleItem(9000));
2980 aAttr.Put(makeSdrCircEndAngleItem(0));
2981 pObj->SetMergedItemSet(aAttr);
2982 }
2983 else if(dynamic_cast<const SdrPathObj*>( pObj) != nullptr)
2984 {
2985 basegfx::B2DPolyPolygon aPoly;
2986
2987 switch(eSdrObjectKind)
2988 {
2989 case OBJ_PATHLINE:
2990 case OBJ_PATHFILL:
2991 {
2992 basegfx::B2DPolygon aInnerPoly;
2993
2994 aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom()));
2995
2996 const basegfx::B2DPoint aCenterBottom(aRect.Center().getX(), aRect.Bottom());
2997 aInnerPoly.appendBezierSegment(
2998 aCenterBottom,
2999 aCenterBottom,
3000 basegfx::B2DPoint(aRect.Center().getX(), aRect.Center().getY()));
3001
3002 const basegfx::B2DPoint aCenterTop(aRect.Center().getX(), aRect.Top());
3003 aInnerPoly.appendBezierSegment(
3004 aCenterTop,
3005 aCenterTop,
3006 basegfx::B2DPoint(aRect.Right(), aRect.Top()));
3007
3008 aInnerPoly.setClosed(true);
3009 aPoly.append(aInnerPoly);
3010 }
3011 break;
3012 case OBJ_FREELINE:
3013 case OBJ_FREEFILL:
3014 {
3015 basegfx::B2DPolygon aInnerPoly;
3016
3017 aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom()));
3018
3019 aInnerPoly.appendBezierSegment(
3020 basegfx::B2DPoint(aRect.Left(), aRect.Top()),
3021 basegfx::B2DPoint(aRect.Center().getX(), aRect.Top()),
3022 basegfx::B2DPoint(aRect.Center().getX(), aRect.Center().getY()));
3023
3024 aInnerPoly.appendBezierSegment(
3025 basegfx::B2DPoint(aRect.Center().getX(), aRect.Bottom()),
3026 basegfx::B2DPoint(aRect.Right(), aRect.Bottom()),
3027 basegfx::B2DPoint(aRect.Right(), aRect.Top()));
3028
3029 aInnerPoly.append(basegfx::B2DPoint(aRect.Right(), aRect.Bottom()));
3030 aInnerPoly.setClosed(true);
3031 aPoly.append(aInnerPoly);
3032 }
3033 break;
3034 case OBJ_POLY:
3035 case OBJ_PLIN:
3036 {
3037 basegfx::B2DPolygon aInnerPoly;
3038 sal_Int32 nWdt(aRect.GetWidth());
3039 sal_Int32 nHgt(aRect.GetHeight());
3040
3041 aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom()));
3042 aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 30) / 100, aRect.Top() + (nHgt * 70) / 100));
3043 aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Top() + (nHgt * 15) / 100));
3044 aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 65) / 100, aRect.Top()));
3045 aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + nWdt, aRect.Top() + (nHgt * 30) / 100));
3046 aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 80) / 100, aRect.Top() + (nHgt * 50) / 100));
3047 aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 80) / 100, aRect.Top() + (nHgt * 75) / 100));
3048 aInnerPoly.append(basegfx::B2DPoint(aRect.Bottom(), aRect.Right()));
3049
3050 if(OBJ_PLIN == eSdrObjectKind)
3051 {
3052 aInnerPoly.append(basegfx::B2DPoint(aRect.Center().getX(), aRect.Bottom()));
3053 }
3054 else
3055 {
3056 aInnerPoly.setClosed(true);
3057 }
3058
3059 aPoly.append(aInnerPoly);
3060 }
3061 break;
3062 case OBJ_LINE :
3063 {
3064 sal_Int32 nYMiddle((aRect.Top() + aRect.Bottom()) / 2);
3065 basegfx::B2DPolygon aTempPoly;
3066 aTempPoly.append(basegfx::B2DPoint(aRect.TopLeft().getX(), nYMiddle));
3067 aTempPoly.append(basegfx::B2DPoint(aRect.BottomRight().getX(), nYMiddle));
3068 aPoly.append(aTempPoly);
3069
3070 SfxItemSet aAttr(pObj->getSdrModelFromSdrObject().GetItemPool());
3071 SetLineEnds(aAttr, *pObj, nSlotId);
3072 pObj->SetMergedItemSet(aAttr);
3073 }
3074 break;
3075 }
3076
3077 static_cast<SdrPathObj*>(pObj)->SetPathPoly(aPoly);
3078 }
3079 else if(dynamic_cast<const SdrMeasureObj*>( pObj) != nullptr)
3080 {
3081 sal_Int32 nYMiddle((aRect.Top() + aRect.Bottom()) / 2);
3082 static_cast<SdrMeasureObj*>(pObj)->SetPoint(Point(aStart.X(), nYMiddle), 0);
3083 static_cast<SdrMeasureObj*>(pObj)->SetPoint(Point(aEnd.X(), nYMiddle), 1);
3084
3085 SfxItemSet aAttr(pObj->getSdrModelFromSdrObject().GetItemPool());
3086 SetLineEnds(aAttr, *pObj, nSlotId);
3087 pObj->SetMergedItemSet(aAttr);
3088 }
3089 else if(dynamic_cast<const SdrCaptionObj*>( pObj) != nullptr)
3090 {
3091 bool bVerticalText = ( SID_DRAW_TEXT_VERTICAL( 10000 + 905 ) == nSlotId ||
3092 SID_DRAW_CAPTION_VERTICAL( 10000 + 906 ) == nSlotId );
3093 static_cast<SdrTextObj*>(pObj)->SetVerticalWriting(bVerticalText);
3094 if(bVerticalText)
3095 {
3096 SfxItemSet aSet(pObj->GetMergedItemSet());
3097 aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER));
3098 aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
3099 pObj->SetMergedItemSet(aSet);
3100 }
3101
3102 static_cast<SdrCaptionObj*>(pObj)->SetLogicRect(aRect);
3103 static_cast<SdrCaptionObj*>(pObj)->SetTailPos(
3104 aRect.TopLeft() - Point(aRect.GetWidth() / 2, aRect.GetHeight() / 2));
3105 }
3106 else if(dynamic_cast<const SdrTextObj*>( pObj) != nullptr)
3107 {
3108 SdrTextObj* pText = static_cast<SdrTextObj*>(pObj);
3109 pText->SetLogicRect(aRect);
3110
3111 bool bVertical = (SID_DRAW_TEXT_VERTICAL( 10000 + 905 ) == nSlotId);
3112 bool bMarquee = (SID_DRAW_TEXT_MARQUEE( 10000 + 465 ) == nSlotId);
3113
3114 pText->SetVerticalWriting(bVertical);
3115
3116 if(bVertical)
3117 {
3118 SfxItemSet aSet(pDrawModel->GetItemPool());
3119 aSet.Put(makeSdrTextAutoGrowWidthItem(true));
3120 aSet.Put(makeSdrTextAutoGrowHeightItem(false));
3121 aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP));
3122 aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
3123 pText->SetMergedItemSet(aSet);
3124 }
3125
3126 if(bMarquee)
3127 {
3128 SfxItemSet aSet(pDrawModel->GetItemPool(), svl::Items<SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST>{});
3129 aSet.Put( makeSdrTextAutoGrowWidthItem( false ) );
3130 aSet.Put( makeSdrTextAutoGrowHeightItem( false ) );
3131 aSet.Put( SdrTextAniKindItem( SdrTextAniKind::Slide ) );
3132 aSet.Put( SdrTextAniDirectionItem( SdrTextAniDirection::Left ) );
3133 aSet.Put( SdrTextAniCountItem( 1 ) );
3134 aSet.Put( SdrTextAniAmountItem( static_cast<sal_Int16>(GetWin()->PixelToLogic(Size(2,1)).Width())) );
3135 pObj->SetMergedItemSetAndBroadcast(aSet);
3136 }
3137 }
3138 SdrPageView* pPageView = pDrawView->GetSdrPageView();
3139 SdrCreateView::SetupObjLayer(pPageView, pDrawView->GetActiveLayer(), pObj);
3140 pDrawView->InsertObjectAtView(pObj, *pPageView);
3141 }
3142 ImpEndCreate();
3143}
3144
3145/** SwFEShell::GetShapeBackgrd
3146 method determines background color of the page the selected drawing
3147 object is on and returns this color.
3148 If no color is found, because no drawing object is selected or ...,
3149 color COL_BLACK (default color on constructing object of class Color)
3150 is returned.
3151
3152 @returns an object of class Color
3153*/
3154Color SwFEShell::GetShapeBackgrd() const
3155{
3156 Color aRetColor;
3157
3158 // check, if a draw view exists
3159 OSL_ENSURE( Imp()->GetDrawView(), "wrong usage of SwFEShell::GetShapeBackgrd - no draw view!")do { if (true && (!(Imp()->GetDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "3159" ": "), "%s", "wrong usage of SwFEShell::GetShapeBackgrd - no draw view!"
); } } while (false)
;
3160 if( Imp()->GetDrawView() )
3161 {
3162 // determine list of selected objects
3163 const SdrMarkList* pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
3164 // check, if exactly one object is selected.
3165 OSL_ENSURE( pMrkList->GetMarkCount() == 1, "wrong usage of SwFEShell::GetShapeBackgrd - no selected object!")do { if (true && (!(pMrkList->GetMarkCount() == 1)
)) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "3165" ": "), "%s", "wrong usage of SwFEShell::GetShapeBackgrd - no selected object!"
); } } while (false)
;
3166 if ( pMrkList->GetMarkCount() == 1)
3167 {
3168 // get selected object
3169 const SdrObject *pSdrObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
3170 // check, if selected object is a shape (drawing object)
3171 OSL_ENSURE( dynamic_cast<const SwVirtFlyDrawObj*>( pSdrObj) == nullptr, "wrong usage of SwFEShell::GetShapeBackgrd - selected object is not a drawing object!")do { if (true && (!(dynamic_cast<const SwVirtFlyDrawObj
*>( pSdrObj) == nullptr))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "3171" ": "), "%s", "wrong usage of SwFEShell::GetShapeBackgrd - selected object is not a drawing object!"
); } } while (false)
;
3172 if ( dynamic_cast<const SwVirtFlyDrawObj*>( pSdrObj) == nullptr )
3173 {
3174 // determine page frame of the frame the shape is anchored.
3175 const SwFrame* pAnchorFrame =
3176 static_cast<SwDrawContact*>(GetUserCall(pSdrObj))->GetAnchorFrame( pSdrObj );
3177 OSL_ENSURE( pAnchorFrame, "inconsistent model - no anchor at shape!")do { if (true && (!(pAnchorFrame))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "3177" ": "), "%s", "inconsistent model - no anchor at shape!"
); } } while (false)
;
3178 if ( pAnchorFrame )
3179 {
3180 const SwPageFrame* pPageFrame = pAnchorFrame->FindPageFrame();
3181 OSL_ENSURE( pPageFrame, "inconsistent model - no page!")do { if (true && (!(pPageFrame))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "3181" ": "), "%s", "inconsistent model - no page!"); } }
while (false)
;
3182 if ( pPageFrame )
3183 {
3184 aRetColor = pPageFrame->GetDrawBackgrdColor();
3185 }
3186 }
3187 }
3188 }
3189 }
3190
3191 return aRetColor;
3192}
3193
3194/** Is default horizontal text direction for selected drawing object right-to-left
3195 Because drawing objects only painted for each page only, the default
3196 horizontal text direction of a drawing object is given by the corresponding
3197 page property.
3198
3199 @returns boolean, indicating, if the horizontal text direction of the
3200 page, the selected drawing object is on, is right-to-left.
3201*/
3202bool SwFEShell::IsShapeDefaultHoriTextDirR2L() const
3203{
3204 bool bRet = false;
3205
3206 // check, if a draw view exists
3207 OSL_ENSURE( Imp()->GetDrawView(), "wrong usage of SwFEShell::GetShapeBackgrd - no draw view!")do { if (true && (!(Imp()->GetDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "3207" ": "), "%s", "wrong usage of SwFEShell::GetShapeBackgrd - no draw view!"
); } } while (false)
;
3208 if( Imp()->GetDrawView() )
3209 {
3210 // determine list of selected objects
3211 const SdrMarkList* pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
3212 // check, if exactly one object is selected.
3213 OSL_ENSURE( pMrkList->GetMarkCount() == 1, "wrong usage of SwFEShell::GetShapeBackgrd - no selected object!")do { if (true && (!(pMrkList->GetMarkCount() == 1)
)) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "3213" ": "), "%s", "wrong usage of SwFEShell::GetShapeBackgrd - no selected object!"
); } } while (false)
;
3214 if ( pMrkList->GetMarkCount() == 1)
3215 {
3216 // get selected object
3217 const SdrObject *pSdrObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
3218 // check, if selected object is a shape (drawing object)
3219 OSL_ENSURE( dynamic_cast<const SwVirtFlyDrawObj*>( pSdrObj) == nullptr, "wrong usage of SwFEShell::GetShapeBackgrd - selected object is not a drawing object!")do { if (true && (!(dynamic_cast<const SwVirtFlyDrawObj
*>( pSdrObj) == nullptr))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "3219" ": "), "%s", "wrong usage of SwFEShell::GetShapeBackgrd - selected object is not a drawing object!"
); } } while (false)
;
3220 if ( dynamic_cast<const SwVirtFlyDrawObj*>( pSdrObj) == nullptr )
3221 {
3222 // determine page frame of the frame the shape is anchored.
3223 const SwFrame* pAnchorFrame =
3224 static_cast<SwDrawContact*>(GetUserCall(pSdrObj))->GetAnchorFrame( pSdrObj );
3225 OSL_ENSURE( pAnchorFrame, "inconsistent model - no anchor at shape!")do { if (true && (!(pAnchorFrame))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "3225" ": "), "%s", "inconsistent model - no anchor at shape!"
); } } while (false)
;
3226 if ( pAnchorFrame )
3227 {
3228 const SwPageFrame* pPageFrame = pAnchorFrame->FindPageFrame();
3229 OSL_ENSURE( pPageFrame, "inconsistent model - no page!")do { if (true && (!(pPageFrame))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/feshview.cxx"
":" "3229" ": "), "%s", "inconsistent model - no page!"); } }
while (false)
;
3230 if ( pPageFrame )
3231 {
3232 bRet = pPageFrame->IsRightToLeft();
3233 }
3234 }
3235 }
3236 }
3237 }
3238
3239 return bRet;
3240}
3241
3242Point SwFEShell::GetRelativePagePosition(const Point& rDocPos)
3243{
3244 Point aRet(-1, -1);
3245 const SwFrame *pPage = GetLayout()->Lower();
3246 while ( pPage && !pPage->getFrameArea().IsInside( rDocPos ) )
3247 {
3248 pPage = pPage->GetNext();
3249 }
3250 if(pPage)
3251 {
3252 aRet = rDocPos - pPage->getFrameArea().TopLeft();
3253 }
3254 return aRet;
3255}
3256
3257/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/sw/source/core/inc/viewimp.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#ifndef INCLUDED_SW_SOURCE_CORE_INC_VIEWIMP_HXX
20#define INCLUDED_SW_SOURCE_CORE_INC_VIEWIMP_HXX
21
22#include <tools/color.hxx>
23#include <svx/svdtypes.hxx>
24#include <swrect.hxx>
25#include <vector>
26#include <memory>
27
28class OutputDevice;
29class SwViewShell;
30class SwFlyFrame;
31class SwViewOption;
32class SwRegionRects;
33class SwFrame;
34class SwLayAction;
35class SwLayIdle;
36class SwDrawView;
37class SdrPageView;
38class SwPageFrame;
39class SwAccessibleMap;
40class SdrObject;
41class Fraction;
42class SwPrintData;
43class SwPagePreviewLayout;
44struct PreviewPage;
45class SwTextFrame;
46// --> OD #i76669#
47namespace sdr::contact { class ViewObjectContactRedirector; }
48// <--
49
50class SwViewShellImp
51{
52 friend class SwViewShell;
53
54 friend class SwLayAction; // Lay- and IdleAction register and deregister
55 friend class SwLayIdle;
56
57 // for paint of page preview
58 friend class SwPagePreviewLayout;
59
60 SwViewShell *m_pShell; // If someone passes an Imp, but needs a SwViewShell, we
61 // keep a backlink here
62
63 std::unique_ptr<SwDrawView> m_pDrawView; // Our DrawView
64 SdrPageView *m_pSdrPageView; // Exactly one Page for our DrawView
65
66 SwPageFrame *m_pFirstVisiblePage; // Always points to the first visible Page
67 std::unique_ptr<SwRegionRects> m_pRegion; // Collector of Paintrects from the LayAction
68
69 SwLayAction *m_pLayAction; // Is set if an Action object exists
70 // Is registered by the SwLayAction ctor and deregistered by the dtor
71 SwLayIdle *m_pIdleAct; // The same as SwLayAction for SwLayIdle
72
73 /// note: the map is *uniquely* owned here - the shared_ptr is only
74 /// used so that SwAccessibleContext can check via weak_ptr that it's alive
75 std::shared_ptr<SwAccessibleMap> m_pAccessibleMap;
76
77 bool m_bFirstPageInvalid : 1; // Pointer to the first Page invalid?
78 bool m_bResetHdlHiddenPaint : 1; // Ditto
79 bool m_bSmoothUpdate : 1; // For SmoothScroll
80 bool m_bStopSmooth : 1;
81
82 sal_uInt16 m_nRestoreActions ; // Count for the Action that need to be restored (UNO)
83 SwRect m_aSmoothRect;
84
85 std::unique_ptr<SwPagePreviewLayout> m_pPagePreviewLayout;
86
87 void SetFirstVisPage(OutputDevice const * pRenderContext); // Recalculate the first visible Page
88
89 void StartAction(); // Show handle and hide
90 void EndAction(); // Called by SwViewShell::ImplXXXAction
91 void LockPaint(); // Ditto; called by SwViewShell::ImplLockPaint
92 void UnlockPaint();
93
94private:
95
96 SwAccessibleMap *CreateAccessibleMap();
97
98 /** invalidate CONTENT_FLOWS_FROM/_TO relation for paragraphs
99
100 #i27138#
101 implementation for wrapper method
102 <SwViewShell::InvalidateAccessibleParaFlowRelation(..)>
103
104 @param _pFromTextFrame
105 input parameter - paragraph frame, for which the relation CONTENT_FLOWS_FROM
106 has to be invalidated.
107 If NULL, no CONTENT_FLOWS_FROM relation has to be invalidated
108
109 @param _pToTextFrame
110 input parameter - paragraph frame, for which the relation CONTENT_FLOWS_TO
111 has to be invalidated.
112 If NULL, no CONTENT_FLOWS_TO relation has to be invalidated
113 */
114 void InvalidateAccessibleParaFlowRelation_( const SwTextFrame* _pFromTextFrame,
115 const SwTextFrame* _pToTextFrame );
116
117 /** invalidate text selection for paragraphs
118
119 #i27301#
120 implementation for wrapper method
121 <SwViewShell::InvalidateAccessibleParaTextSelection(..)>
122 */
123 void InvalidateAccessibleParaTextSelection_();
124
125 /** invalidate attributes for paragraphs and paragraph's characters
126
127 #i88069#
128 implementation for wrapper method
129 <SwViewShell::InvalidateAccessibleParaAttrs(..)>
130 */
131 void InvalidateAccessibleParaAttrs_( const SwTextFrame& rTextFrame );
132
133public:
134 SwViewShellImp( SwViewShell * );
135 ~SwViewShellImp();
136 void Init( const SwViewOption * ); /// Only for SwViewShell::Init()
137
138 const SwViewShell *GetShell() const { return m_pShell; }
139 SwViewShell *GetShell() { return m_pShell; }
140
141 Color GetRetoucheColor() const;
142
143 /// Management of the first visible Page
144 const SwPageFrame *GetFirstVisPage(OutputDevice const * pRenderContext) const;
145 SwPageFrame *GetFirstVisPage(OutputDevice const * pRenderContext);
146 void SetFirstVisPageInvalid() { m_bFirstPageInvalid = true; }
147
148 bool AddPaintRect( const SwRect &rRect );
149 SwRegionRects *GetRegion() { return m_pRegion.get(); }
150 void DelRegion();
151
152 /// New Interface for StarView Drawing
153 bool HasDrawView() const { return nullptr != m_pDrawView; }
2
Calling 'operator!=<SwDrawView, std::default_delete<SwDrawView>>'
9
Returning from 'operator!=<SwDrawView, std::default_delete<SwDrawView>>'
10
Returning the value 1, which participates in a condition later
154 SwDrawView* GetDrawView() { return m_pDrawView.get(); }
155 const SwDrawView* GetDrawView() const { return m_pDrawView.get(); }
156 SdrPageView*GetPageView() { return m_pSdrPageView; }
157 const SdrPageView*GetPageView() const { return m_pSdrPageView; }
158 void MakeDrawView();
159
160 /**
161 * @param _pPageBackgrdColor for setting this color as the background color
162 * at the outliner of the draw view for painting layers "hell" and "heaven"
163 *
164 * @param _bIsPageRightToLeft for the horizontal text direction of the page
165 * in order to set the default horizontal text direction at the outliner of
166 * the draw view for painting layers "hell" and "heaven"
167 */
168 void PaintLayer( const SdrLayerID _nLayerID,
169 SwPrintData const*const pPrintData,
170 SwPageFrame const& rPageFrame,
171 const SwRect& _rRect,
172 const Color* _pPageBackgrdColor,
173 const bool _bIsPageRightToLeft,
174 sdr::contact::ViewObjectContactRedirector* pRedirector );
175
176 /**
177 * Is passed to the DrawEngine as a Link and decides what is painted
178 * or not and in what way
179 */
180
181 // Interface Drawing
182 bool IsDragPossible( const Point &rPoint );
183 void NotifySizeChg( const Size &rNewSz );
184
185 /// SS for the Lay-/IdleAction and relatives
186 bool IsAction() const { return m_pLayAction != nullptr; }
187 bool IsIdleAction() const { return m_pIdleAct != nullptr; }
188 SwLayAction &GetLayAction() { return *m_pLayAction; }
189 const SwLayAction &GetLayAction() const { return *m_pLayAction; }
190
191 /**
192 * If an Action is running we ask it to check whether it's time
193 * to enable the WaitCursor
194 */
195 void CheckWaitCursor();
196
197 /// Asks the LayAction if present
198 bool IsCalcLayoutProgress() const;
199
200 /**
201 * @returns true if a LayAction is running
202 *
203 * There we also set the Flag for ExpressionFields
204 */
205 bool IsUpdateExpFields();
206
207 void SetRestoreActions(sal_uInt16 nSet){m_nRestoreActions = nSet;}
208 sal_uInt16 GetRestoreActions() const{return m_nRestoreActions;}
209
210 void InitPagePreviewLayout();
211
212 SwPagePreviewLayout* PagePreviewLayout()
213 {
214 return m_pPagePreviewLayout.get();
215 }
216
217 /// Is this view accessible?
218 bool IsAccessible() const { return m_pAccessibleMap != nullptr; }
219
220 inline SwAccessibleMap& GetAccessibleMap();
221
222 /// Update (this) accessible view
223 void UpdateAccessible();
224
225 /// Remove a frame from the accessible view
226 void DisposeAccessible( const SwFrame *pFrame, const SdrObject *pObj,
227 bool bRecursive, bool bCanSkipInvisible );
228 inline void DisposeAccessibleFrame( const SwFrame *pFrame,
229 bool bRecursive = false );
230 inline void DisposeAccessibleObj( const SdrObject *pObj, bool bCanSkipInvisible );
231
232 /// Move a frame's position in the accessible view
233 void MoveAccessible( const SwFrame *pFrame, const SdrObject *pObj,
234 const SwRect& rOldFrame );
235 inline void MoveAccessibleFrame( const SwFrame *pFrame, const SwRect& rOldFrame );
236
237 /// Add a frame in the accessible view
238 inline void AddAccessibleFrame( const SwFrame *pFrame );
239
240 inline void AddAccessibleObj( const SdrObject *pObj );
241
242 /// Invalidate accessible frame's content
243 void InvalidateAccessibleFrameContent( const SwFrame *pFrame );
244
245 /// Invalidate accessible frame's cursor position
246 void InvalidateAccessibleCursorPosition( const SwFrame *pFrame );
247
248 /// Invalidate editable state for all accessible frames
249 void InvalidateAccessibleEditableState( bool bAllShells,
250 const SwFrame *pFrame=nullptr );
251
252 /// Invalidate frame's relation set (for chained frames)
253 void InvalidateAccessibleRelationSet( const SwFlyFrame *pMaster,
254 const SwFlyFrame *pFollow );
255
256 /// update data for accessible preview
257 /// change method signature due to new page preview functionality
258 void UpdateAccessiblePreview( const std::vector<std::unique_ptr<PreviewPage>>& _rPreviewPages,
259 const Fraction& _rScale,
260 const SwPageFrame* _pSelectedPageFrame,
261 const Size& _rPreviewWinSize );
262
263 void InvalidateAccessiblePreviewSelection( sal_uInt16 nSelPage );
264
265 /// Fire all accessible events that have been collected so far
266 void FireAccessibleEvents();
267};
268
269inline SwAccessibleMap& SwViewShellImp::GetAccessibleMap()
270{
271 if( !m_pAccessibleMap )
272 CreateAccessibleMap();
273
274 return *m_pAccessibleMap;
275}
276
277inline void SwViewShellImp::DisposeAccessibleFrame( const SwFrame *pFrame,
278 bool bRecursive )
279{
280 DisposeAccessible( pFrame, nullptr, bRecursive, true );
281}
282
283inline void SwViewShellImp::DisposeAccessibleObj( const SdrObject *pObj, bool bCanSkipInvisible )
284{
285 DisposeAccessible( nullptr, pObj, false, bCanSkipInvisible );
286}
287
288inline void SwViewShellImp::MoveAccessibleFrame( const SwFrame *pFrame,
289 const SwRect& rOldFrame )
290{
291 MoveAccessible( pFrame, nullptr, rOldFrame );
292}
293
294inline void SwViewShellImp::AddAccessibleFrame( const SwFrame *pFrame )
295{
296 SwRect aEmptyRect;
297 MoveAccessible( pFrame, nullptr, aEmptyRect );
298}
299
300inline void SwViewShellImp::AddAccessibleObj( const SdrObject *pObj )
301{
302 SwRect aEmptyRect;
303 MoveAccessible( nullptr, pObj, aEmptyRect );
304}
305#endif // INCLUDED_SW_SOURCE_CORE_INC_VIEWIMP_HXX
306
307/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/bits/unique_ptr.h

1// unique_ptr implementation -*- C++ -*-
2
3// Copyright (C) 2008-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/unique_ptr.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{memory}
28 */
29
30#ifndef _UNIQUE_PTR_H1
31#define _UNIQUE_PTR_H1 1
32
33#include <bits/c++config.h>
34#include <debug/assertions.h>
35#include <type_traits>
36#include <utility>
37#include <tuple>
38#include <bits/stl_function.h>
39#include <bits/functional_hash.h>
40#if __cplusplus201703L > 201703L
41# include <compare>
42# include <ostream>
43#endif
44
45namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
46{
47_GLIBCXX_BEGIN_NAMESPACE_VERSION
48
49 /**
50 * @addtogroup pointer_abstractions
51 * @{
52 */
53
54#if _GLIBCXX_USE_DEPRECATED1
55#pragma GCC diagnostic push
56#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
57 template<typename> class auto_ptr;
58#pragma GCC diagnostic pop
59#endif
60
61 /// Primary template of default_delete, used by unique_ptr for single objects
62 template<typename _Tp>
63 struct default_delete
64 {
65 /// Default constructor
66 constexpr default_delete() noexcept = default;
67
68 /** @brief Converting constructor.
69 *
70 * Allows conversion from a deleter for objects of another type, `_Up`,
71 * only if `_Up*` is convertible to `_Tp*`.
72 */
73 template<typename _Up,
74 typename = _Require<is_convertible<_Up*, _Tp*>>>
75 default_delete(const default_delete<_Up>&) noexcept { }
76
77 /// Calls `delete __ptr`
78 void
79 operator()(_Tp* __ptr) const
80 {
81 static_assert(!is_void<_Tp>::value,
82 "can't delete pointer to incomplete type");
83 static_assert(sizeof(_Tp)>0,
84 "can't delete pointer to incomplete type");
85 delete __ptr;
86 }
87 };
88
89 // _GLIBCXX_RESOLVE_LIB_DEFECTS
90 // DR 740 - omit specialization for array objects with a compile time length
91
92 /// Specialization of default_delete for arrays, used by `unique_ptr<T[]>`
93 template<typename _Tp>
94 struct default_delete<_Tp[]>
95 {
96 public:
97 /// Default constructor
98 constexpr default_delete() noexcept = default;
99
100 /** @brief Converting constructor.
101 *
102 * Allows conversion from a deleter for arrays of another type, such as
103 * a const-qualified version of `_Tp`.
104 *
105 * Conversions from types derived from `_Tp` are not allowed because
106 * it is undefined to `delete[]` an array of derived types through a
107 * pointer to the base type.
108 */
109 template<typename _Up,
110 typename = _Require<is_convertible<_Up(*)[], _Tp(*)[]>>>
111 default_delete(const default_delete<_Up[]>&) noexcept { }
112
113 /// Calls `delete[] __ptr`
114 template<typename _Up>
115 typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type
116 operator()(_Up* __ptr) const
117 {
118 static_assert(sizeof(_Tp)>0,
119 "can't delete pointer to incomplete type");
120 delete [] __ptr;
121 }
122 };
123
124 /// @cond undocumented
125
126 // Manages the pointer and deleter of a unique_ptr
127 template <typename _Tp, typename _Dp>
128 class __uniq_ptr_impl
129 {
130 template <typename _Up, typename _Ep, typename = void>
131 struct _Ptr
132 {
133 using type = _Up*;
134 };
135
136 template <typename _Up, typename _Ep>
137 struct
138 _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>>
139 {
140 using type = typename remove_reference<_Ep>::type::pointer;
141 };
142
143 public:
144 using _DeleterConstraint = enable_if<
145 __and_<__not_<is_pointer<_Dp>>,
146 is_default_constructible<_Dp>>::value>;
147
148 using pointer = typename _Ptr<_Tp, _Dp>::type;
149
150 static_assert( !is_rvalue_reference<_Dp>::value,
151 "unique_ptr's deleter type must be a function object type"
152 " or an lvalue reference type" );
153
154 __uniq_ptr_impl() = default;
155 __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; }
156
157 template<typename _Del>
158 __uniq_ptr_impl(pointer __p, _Del&& __d)
159 : _M_t(__p, std::forward<_Del>(__d)) { }
160
161 __uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept
162 : _M_t(std::move(__u._M_t))
163 { __u._M_ptr() = nullptr; }
164
165 __uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept
166 {
167 reset(__u.release());
168 _M_deleter() = std::forward<_Dp>(__u._M_deleter());
169 return *this;
170 }
171
172 pointer& _M_ptr() { return std::get<0>(_M_t); }
173 pointer _M_ptr() const { return std::get<0>(_M_t); }
174 _Dp& _M_deleter() { return std::get<1>(_M_t); }
175 const _Dp& _M_deleter() const { return std::get<1>(_M_t); }
176
177 void reset(pointer __p) noexcept
178 {
179 const pointer __old_p = _M_ptr();
180 _M_ptr() = __p;
181 if (__old_p)
182 _M_deleter()(__old_p);
183 }
184
185 pointer release() noexcept
186 {
187 pointer __p = _M_ptr();
188 _M_ptr() = nullptr;
189 return __p;
190 }
191
192 void
193 swap(__uniq_ptr_impl& __rhs) noexcept
194 {
195 using std::swap;
196 swap(this->_M_ptr(), __rhs._M_ptr());
197 swap(this->_M_deleter(), __rhs._M_deleter());
198 }
199
200 private:
201 tuple<pointer, _Dp> _M_t;
202 };
203
204 // Defines move construction + assignment as either defaulted or deleted.
205 template <typename _Tp, typename _Dp,
206 bool = is_move_constructible<_Dp>::value,
207 bool = is_move_assignable<_Dp>::value>
208 struct __uniq_ptr_data : __uniq_ptr_impl<_Tp, _Dp>
209 {
210 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
211 __uniq_ptr_data(__uniq_ptr_data&&) = default;
212 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default;
213 };
214
215 template <typename _Tp, typename _Dp>
216 struct __uniq_ptr_data<_Tp, _Dp, true, false> : __uniq_ptr_impl<_Tp, _Dp>
217 {
218 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
219 __uniq_ptr_data(__uniq_ptr_data&&) = default;
220 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete;
221 };
222
223 template <typename _Tp, typename _Dp>
224 struct __uniq_ptr_data<_Tp, _Dp, false, true> : __uniq_ptr_impl<_Tp, _Dp>
225 {
226 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
227 __uniq_ptr_data(__uniq_ptr_data&&) = delete;
228 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default;
229 };
230
231 template <typename _Tp, typename _Dp>
232 struct __uniq_ptr_data<_Tp, _Dp, false, false> : __uniq_ptr_impl<_Tp, _Dp>
233 {
234 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
235 __uniq_ptr_data(__uniq_ptr_data&&) = delete;
236 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete;
237 };
238 /// @endcond
239
240 /// 20.7.1.2 unique_ptr for single objects.
241 template <typename _Tp, typename _Dp = default_delete<_Tp>>
242 class unique_ptr
243 {
244 template <typename _Up>
245 using _DeleterConstraint =
246 typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
247
248 __uniq_ptr_data<_Tp, _Dp> _M_t;
249
250 public:
251 using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
252 using element_type = _Tp;
253 using deleter_type = _Dp;
254
255 private:
256 // helper template for detecting a safe conversion from another
257 // unique_ptr
258 template<typename _Up, typename _Ep>
259 using __safe_conversion_up = __and_<
260 is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
261 __not_<is_array<_Up>>
262 >;
263
264 public:
265 // Constructors.
266
267 /// Default constructor, creates a unique_ptr that owns nothing.
268 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
269 constexpr unique_ptr() noexcept
270 : _M_t()
271 { }
272
273 /** Takes ownership of a pointer.
274 *
275 * @param __p A pointer to an object of @c element_type
276 *
277 * The deleter will be value-initialized.
278 */
279 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
280 explicit
281 unique_ptr(pointer __p) noexcept
282 : _M_t(__p)
283 { }
284
285 /** Takes ownership of a pointer.
286 *
287 * @param __p A pointer to an object of @c element_type
288 * @param __d A reference to a deleter.
289 *
290 * The deleter will be initialized with @p __d
291 */
292 template<typename _Del = deleter_type,
293 typename = _Require<is_copy_constructible<_Del>>>
294 unique_ptr(pointer __p, const deleter_type& __d) noexcept
295 : _M_t(__p, __d) { }
296
297 /** Takes ownership of a pointer.
298 *
299 * @param __p A pointer to an object of @c element_type
300 * @param __d An rvalue reference to a (non-reference) deleter.
301 *
302 * The deleter will be initialized with @p std::move(__d)
303 */
304 template<typename _Del = deleter_type,
305 typename = _Require<is_move_constructible<_Del>>>
306 unique_ptr(pointer __p,
307 __enable_if_t<!is_lvalue_reference<_Del>::value,
308 _Del&&> __d) noexcept
309 : _M_t(__p, std::move(__d))
310 { }
311
312 template<typename _Del = deleter_type,
313 typename _DelUnref = typename remove_reference<_Del>::type>
314 unique_ptr(pointer,
315 __enable_if_t<is_lvalue_reference<_Del>::value,
316 _DelUnref&&>) = delete;
317
318 /// Creates a unique_ptr that owns nothing.
319 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
320 constexpr unique_ptr(nullptr_t) noexcept
321 : _M_t()
322 { }
323
324 // Move constructors.
325
326 /// Move constructor.
327 unique_ptr(unique_ptr&&) = default;
328
329 /** @brief Converting constructor from another type
330 *
331 * Requires that the pointer owned by @p __u is convertible to the
332 * type of pointer owned by this object, @p __u does not own an array,
333 * and @p __u has a compatible deleter type.
334 */
335 template<typename _Up, typename _Ep, typename = _Require<
336 __safe_conversion_up<_Up, _Ep>,
337 typename conditional<is_reference<_Dp>::value,
338 is_same<_Ep, _Dp>,
339 is_convertible<_Ep, _Dp>>::type>>
340 unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
341 : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
342 { }
343
344#if _GLIBCXX_USE_DEPRECATED1
345#pragma GCC diagnostic push
346#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
347 /// Converting constructor from @c auto_ptr
348 template<typename _Up, typename = _Require<
349 is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>>
350 unique_ptr(auto_ptr<_Up>&& __u) noexcept;
351#pragma GCC diagnostic pop
352#endif
353
354 /// Destructor, invokes the deleter if the stored pointer is not null.
355 ~unique_ptr() noexcept
356 {
357 static_assert(__is_invocable<deleter_type&, pointer>::value,
358 "unique_ptr's deleter must be invocable with a pointer");
359 auto& __ptr = _M_t._M_ptr();
360 if (__ptr != nullptr)
361 get_deleter()(std::move(__ptr));
362 __ptr = pointer();
363 }
364
365 // Assignment.
366
367 /** @brief Move assignment operator.
368 *
369 * Invokes the deleter if this object owns a pointer.
370 */
371 unique_ptr& operator=(unique_ptr&&) = default;
372
373 /** @brief Assignment from another type.
374 *
375 * @param __u The object to transfer ownership from, which owns a
376 * convertible pointer to a non-array object.
377 *
378 * Invokes the deleter if this object owns a pointer.
379 */
380 template<typename _Up, typename _Ep>
381 typename enable_if< __and_<
382 __safe_conversion_up<_Up, _Ep>,
383 is_assignable<deleter_type&, _Ep&&>
384 >::value,
385 unique_ptr&>::type
386 operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
387 {
388 reset(__u.release());
389 get_deleter() = std::forward<_Ep>(__u.get_deleter());
390 return *this;
391 }
392
393 /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
394 unique_ptr&
395 operator=(nullptr_t) noexcept
396 {
397 reset();
398 return *this;
399 }
400
401 // Observers.
402
403 /// Dereference the stored pointer.
404 typename add_lvalue_reference<element_type>::type
405 operator*() const
406 {
407 __glibcxx_assert(get() != pointer());
408 return *get();
409 }
410
411 /// Return the stored pointer.
412 pointer
413 operator->() const noexcept
414 {
415 _GLIBCXX_DEBUG_PEDASSERT(get() != pointer());
416 return get();
417 }
418
419 /// Return the stored pointer.
420 pointer
421 get() const noexcept
422 { return _M_t._M_ptr(); }
423
424 /// Return a reference to the stored deleter.
425 deleter_type&
426 get_deleter() noexcept
427 { return _M_t._M_deleter(); }
428
429 /// Return a reference to the stored deleter.
430 const deleter_type&
431 get_deleter() const noexcept
432 { return _M_t._M_deleter(); }
433
434 /// Return @c true if the stored pointer is not null.
435 explicit operator bool() const noexcept
436 { return get() == pointer() ? false : true; }
4
Assuming the condition is false
5
'?' condition is false
6
Returning the value 1, which participates in a condition later
437
438 // Modifiers.
439
440 /// Release ownership of any stored pointer.
441 pointer
442 release() noexcept
443 { return _M_t.release(); }
444
445 /** @brief Replace the stored pointer.
446 *
447 * @param __p The new pointer to store.
448 *
449 * The deleter will be invoked if a pointer is already owned.
450 */
451 void
452 reset(pointer __p = pointer()) noexcept
453 {
454 static_assert(__is_invocable<deleter_type&, pointer>::value,
455 "unique_ptr's deleter must be invocable with a pointer");
456 _M_t.reset(std::move(__p));
457 }
458
459 /// Exchange the pointer and deleter with another object.
460 void
461 swap(unique_ptr& __u) noexcept
462 {
463 static_assert(__is_swappable<_Dp>::value, "deleter must be swappable");
464 _M_t.swap(__u._M_t);
465 }
466
467 // Disable copy from lvalue.
468 unique_ptr(const unique_ptr&) = delete;
469 unique_ptr& operator=(const unique_ptr&) = delete;
470 };
471
472 /// 20.7.1.3 unique_ptr for array objects with a runtime length
473 // [unique.ptr.runtime]
474 // _GLIBCXX_RESOLVE_LIB_DEFECTS
475 // DR 740 - omit specialization for array objects with a compile time length
476 template<typename _Tp, typename _Dp>
477 class unique_ptr<_Tp[], _Dp>
478 {
479 template <typename _Up>
480 using _DeleterConstraint =
481 typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
482
483 __uniq_ptr_data<_Tp, _Dp> _M_t;
484
485 template<typename _Up>
486 using __remove_cv = typename remove_cv<_Up>::type;
487
488 // like is_base_of<_Tp, _Up> but false if unqualified types are the same
489 template<typename _Up>
490 using __is_derived_Tp
491 = __and_< is_base_of<_Tp, _Up>,
492 __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >;
493
494 public:
495 using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
496 using element_type = _Tp;
497 using deleter_type = _Dp;
498
499 // helper template for detecting a safe conversion from another
500 // unique_ptr
501 template<typename _Up, typename _Ep,
502 typename _UPtr = unique_ptr<_Up, _Ep>,
503 typename _UP_pointer = typename _UPtr::pointer,
504 typename _UP_element_type = typename _UPtr::element_type>
505 using __safe_conversion_up = __and_<
506 is_array<_Up>,
507 is_same<pointer, element_type*>,
508 is_same<_UP_pointer, _UP_element_type*>,
509 is_convertible<_UP_element_type(*)[], element_type(*)[]>
510 >;
511
512 // helper template for detecting a safe conversion from a raw pointer
513 template<typename _Up>
514 using __safe_conversion_raw = __and_<
515 __or_<__or_<is_same<_Up, pointer>,
516 is_same<_Up, nullptr_t>>,
517 __and_<is_pointer<_Up>,
518 is_same<pointer, element_type*>,
519 is_convertible<
520 typename remove_pointer<_Up>::type(*)[],
521 element_type(*)[]>
522 >
523 >
524 >;
525
526 // Constructors.
527
528 /// Default constructor, creates a unique_ptr that owns nothing.
529 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
530 constexpr unique_ptr() noexcept
531 : _M_t()
532 { }
533
534 /** Takes ownership of a pointer.
535 *
536 * @param __p A pointer to an array of a type safely convertible
537 * to an array of @c element_type
538 *
539 * The deleter will be value-initialized.
540 */
541 template<typename _Up,
542 typename _Vp = _Dp,
543 typename = _DeleterConstraint<_Vp>,
544 typename = typename enable_if<
545 __safe_conversion_raw<_Up>::value, bool>::type>
546 explicit
547 unique_ptr(_Up __p) noexcept
548 : _M_t(__p)
549 { }
550
551 /** Takes ownership of a pointer.
552 *
553 * @param __p A pointer to an array of a type safely convertible
554 * to an array of @c element_type
555 * @param __d A reference to a deleter.
556 *
557 * The deleter will be initialized with @p __d
558 */
559 template<typename _Up, typename _Del = deleter_type,
560 typename = _Require<__safe_conversion_raw<_Up>,
561 is_copy_constructible<_Del>>>
562 unique_ptr(_Up __p, const deleter_type& __d) noexcept
563 : _M_t(__p, __d) { }
564
565 /** Takes ownership of a pointer.
566 *
567 * @param __p A pointer to an array of a type safely convertible
568 * to an array of @c element_type
569 * @param __d A reference to a deleter.
570 *
571 * The deleter will be initialized with @p std::move(__d)
572 */
573 template<typename _Up, typename _Del = deleter_type,
574 typename = _Require<__safe_conversion_raw<_Up>,
575 is_move_constructible<_Del>>>
576 unique_ptr(_Up __p,
577 __enable_if_t<!is_lvalue_reference<_Del>::value,
578 _Del&&> __d) noexcept
579 : _M_t(std::move(__p), std::move(__d))
580 { }
581
582 template<typename _Up, typename _Del = deleter_type,
583 typename _DelUnref = typename remove_reference<_Del>::type,
584 typename = _Require<__safe_conversion_raw<_Up>>>
585 unique_ptr(_Up,
586 __enable_if_t<is_lvalue_reference<_Del>::value,
587 _DelUnref&&>) = delete;
588
589 /// Move constructor.
590 unique_ptr(unique_ptr&&) = default;
591
592 /// Creates a unique_ptr that owns nothing.
593 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
594 constexpr unique_ptr(nullptr_t) noexcept
595 : _M_t()
596 { }
597
598 template<typename _Up, typename _Ep, typename = _Require<
599 __safe_conversion_up<_Up, _Ep>,
600 typename conditional<is_reference<_Dp>::value,
601 is_same<_Ep, _Dp>,
602 is_convertible<_Ep, _Dp>>::type>>
603 unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
604 : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
605 { }
606
607 /// Destructor, invokes the deleter if the stored pointer is not null.
608 ~unique_ptr()
609 {
610 auto& __ptr = _M_t._M_ptr();
611 if (__ptr != nullptr)
612 get_deleter()(__ptr);
613 __ptr = pointer();
614 }
615
616 // Assignment.
617
618 /** @brief Move assignment operator.
619 *
620 * Invokes the deleter if this object owns a pointer.
621 */
622 unique_ptr&
623 operator=(unique_ptr&&) = default;
624
625 /** @brief Assignment from another type.
626 *
627 * @param __u The object to transfer ownership from, which owns a
628 * convertible pointer to an array object.
629 *
630 * Invokes the deleter if this object owns a pointer.
631 */
632 template<typename _Up, typename _Ep>
633 typename
634 enable_if<__and_<__safe_conversion_up<_Up, _Ep>,
635 is_assignable<deleter_type&, _Ep&&>
636 >::value,
637 unique_ptr&>::type
638 operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
639 {
640 reset(__u.release());
641 get_deleter() = std::forward<_Ep>(__u.get_deleter());
642 return *this;
643 }
644
645 /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
646 unique_ptr&
647 operator=(nullptr_t) noexcept
648 {
649 reset();
650 return *this;
651 }
652
653 // Observers.
654
655 /// Access an element of owned array.
656 typename std::add_lvalue_reference<element_type>::type
657 operator[](size_t __i) const
658 {
659 __glibcxx_assert(get() != pointer());
660 return get()[__i];
661 }
662
663 /// Return the stored pointer.
664 pointer
665 get() const noexcept
666 { return _M_t._M_ptr(); }
667
668 /// Return a reference to the stored deleter.
669 deleter_type&
670 get_deleter() noexcept
671 { return _M_t._M_deleter(); }
672
673 /// Return a reference to the stored deleter.
674 const deleter_type&
675 get_deleter() const noexcept
676 { return _M_t._M_deleter(); }
677
678 /// Return @c true if the stored pointer is not null.
679 explicit operator bool() const noexcept
680 { return get() == pointer() ? false : true; }
681
682 // Modifiers.
683
684 /// Release ownership of any stored pointer.
685 pointer
686 release() noexcept
687 { return _M_t.release(); }
688
689 /** @brief Replace the stored pointer.
690 *
691 * @param __p The new pointer to store.
692 *
693 * The deleter will be invoked if a pointer is already owned.
694 */
695 template <typename _Up,
696 typename = _Require<
697 __or_<is_same<_Up, pointer>,
698 __and_<is_same<pointer, element_type*>,
699 is_pointer<_Up>,
700 is_convertible<
701 typename remove_pointer<_Up>::type(*)[],
702 element_type(*)[]
703 >
704 >
705 >
706 >>
707 void
708 reset(_Up __p) noexcept
709 { _M_t.reset(std::move(__p)); }
710
711 void reset(nullptr_t = nullptr) noexcept
712 { reset(pointer()); }
713
714 /// Exchange the pointer and deleter with another object.
715 void
716 swap(unique_ptr& __u) noexcept
717 {
718 static_assert(__is_swappable<_Dp>::value, "deleter must be swappable");
719 _M_t.swap(__u._M_t);
720 }
721
722 // Disable copy from lvalue.
723 unique_ptr(const unique_ptr&) = delete;
724 unique_ptr& operator=(const unique_ptr&) = delete;
725 };
726
727 /// @relates unique_ptr @{
728
729 /// Swap overload for unique_ptr
730 template<typename _Tp, typename _Dp>
731 inline
732#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
733 // Constrained free swap overload, see p0185r1
734 typename enable_if<__is_swappable<_Dp>::value>::type
735#else
736 void
737#endif
738 swap(unique_ptr<_Tp, _Dp>& __x,
739 unique_ptr<_Tp, _Dp>& __y) noexcept
740 { __x.swap(__y); }
741
742#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
743 template<typename _Tp, typename _Dp>
744 typename enable_if<!__is_swappable<_Dp>::value>::type
745 swap(unique_ptr<_Tp, _Dp>&,
746 unique_ptr<_Tp, _Dp>&) = delete;
747#endif
748
749 /// Equality operator for unique_ptr objects, compares the owned pointers
750 template<typename _Tp, typename _Dp,
751 typename _Up, typename _Ep>
752 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
753 operator==(const unique_ptr<_Tp, _Dp>& __x,
754 const unique_ptr<_Up, _Ep>& __y)
755 { return __x.get() == __y.get(); }
756
757 /// unique_ptr comparison with nullptr
758 template<typename _Tp, typename _Dp>
759 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
760 operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
761 { return !__x; }
762
763#ifndef __cpp_lib_three_way_comparison
764 /// unique_ptr comparison with nullptr
765 template<typename _Tp, typename _Dp>
766 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
767 operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
768 { return !__x; }
769
770 /// Inequality operator for unique_ptr objects, compares the owned pointers
771 template<typename _Tp, typename _Dp,
772 typename _Up, typename _Ep>
773 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
774 operator!=(const unique_ptr<_Tp, _Dp>& __x,
775 const unique_ptr<_Up, _Ep>& __y)
776 { return __x.get() != __y.get(); }
777
778 /// unique_ptr comparison with nullptr
779 template<typename _Tp, typename _Dp>
780 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
781 operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
782 { return (bool)__x; }
783
784 /// unique_ptr comparison with nullptr
785 template<typename _Tp, typename _Dp>
786 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
787 operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
788 { return (bool)__x; }
3
Calling 'unique_ptr::operator bool'
7
Returning from 'unique_ptr::operator bool'
8
Returning the value 1, which participates in a condition later
789#endif // three way comparison
790
791 /// Relational operator for unique_ptr objects, compares the owned pointers
792 template<typename _Tp, typename _Dp,
793 typename _Up, typename _Ep>
794 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
795 operator<(const unique_ptr<_Tp, _Dp>& __x,
796 const unique_ptr<_Up, _Ep>& __y)
797 {
798 typedef typename
799 std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
800 typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
801 return std::less<_CT>()(__x.get(), __y.get());
802 }
803
804 /// unique_ptr comparison with nullptr
805 template<typename _Tp, typename _Dp>
806 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
807 operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
808 {
809 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
810 nullptr);
811 }
812
813 /// unique_ptr comparison with nullptr
814 template<typename _Tp, typename _Dp>
815 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
816 operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
817 {
818 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
819 __x.get());
820 }
821
822 /// Relational operator for unique_ptr objects, compares the owned pointers
823 template<typename _Tp, typename _Dp,
824 typename _Up, typename _Ep>
825 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
826 operator<=(const unique_ptr<_Tp, _Dp>& __x,
827 const unique_ptr<_Up, _Ep>& __y)
828 { return !(__y < __x); }
829
830 /// unique_ptr comparison with nullptr
831 template<typename _Tp, typename _Dp>
832 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
833 operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
834 { return !(nullptr < __x); }
835
836 /// unique_ptr comparison with nullptr
837 template<typename _Tp, typename _Dp>
838 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
839 operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
840 { return !(__x < nullptr); }
841
842 /// Relational operator for unique_ptr objects, compares the owned pointers
843 template<typename _Tp, typename _Dp,
844 typename _Up, typename _Ep>
845 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
846 operator>(const unique_ptr<_Tp, _Dp>& __x,
847 const unique_ptr<_Up, _Ep>& __y)
848 { return (__y < __x); }
849
850 /// unique_ptr comparison with nullptr
851 template<typename _Tp, typename _Dp>
852 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
853 operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
854 {
855 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
856 __x.get());
857 }
858
859 /// unique_ptr comparison with nullptr
860 template<typename _Tp, typename _Dp>
861 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
862 operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
863 {
864 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
865 nullptr);
866 }
867
868 /// Relational operator for unique_ptr objects, compares the owned pointers
869 template<typename _Tp, typename _Dp,
870 typename _Up, typename _Ep>
871 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
872 operator>=(const unique_ptr<_Tp, _Dp>& __x,
873 const unique_ptr<_Up, _Ep>& __y)
874 { return !(__x < __y); }
875
876 /// unique_ptr comparison with nullptr
877 template<typename _Tp, typename _Dp>
878 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
879 operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
880 { return !(__x < nullptr); }
881
882 /// unique_ptr comparison with nullptr
883 template<typename _Tp, typename _Dp>
884 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
885 operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
886 { return !(nullptr < __x); }
887
888#ifdef __cpp_lib_three_way_comparison
889 template<typename _Tp, typename _Dp, typename _Up, typename _Ep>
890 requires three_way_comparable_with<typename unique_ptr<_Tp, _Dp>::pointer,
891 typename unique_ptr<_Up, _Ep>::pointer>
892 inline
893 compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer,
894 typename unique_ptr<_Up, _Ep>::pointer>
895 operator<=>(const unique_ptr<_Tp, _Dp>& __x,
896 const unique_ptr<_Up, _Ep>& __y)
897 { return compare_three_way()(__x.get(), __y.get()); }
898
899 template<typename _Tp, typename _Dp>
900 requires three_way_comparable<typename unique_ptr<_Tp, _Dp>::pointer>
901 inline
902 compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer>
903 operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
904 {
905 using pointer = typename unique_ptr<_Tp, _Dp>::pointer;
906 return compare_three_way()(__x.get(), static_cast<pointer>(nullptr));
907 }
908#endif
909 // @} relates unique_ptr
910
911 /// @cond undocumented
912 template<typename _Up, typename _Ptr = typename _Up::pointer,
913 bool = __poison_hash<_Ptr>::__enable_hash_call>
914 struct __uniq_ptr_hash
915#if ! _GLIBCXX_INLINE_VERSION0
916 : private __poison_hash<_Ptr>
917#endif
918 {
919 size_t
920 operator()(const _Up& __u) const
921 noexcept(noexcept(std::declval<hash<_Ptr>>()(std::declval<_Ptr>())))
922 { return hash<_Ptr>()(__u.get()); }
923 };
924
925 template<typename _Up, typename _Ptr>
926 struct __uniq_ptr_hash<_Up, _Ptr, false>
927 : private __poison_hash<_Ptr>
928 { };
929 /// @endcond
930
931 /// std::hash specialization for unique_ptr.
932 template<typename _Tp, typename _Dp>
933 struct hash<unique_ptr<_Tp, _Dp>>
934 : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>,
935 public __uniq_ptr_hash<unique_ptr<_Tp, _Dp>>
936 { };
937
938#if __cplusplus201703L >= 201402L
939 /// @relates unique_ptr @{
940#define __cpp_lib_make_unique201304 201304
941
942 /// @cond undocumented
943
944 template<typename _Tp>
945 struct _MakeUniq
946 { typedef unique_ptr<_Tp> __single_object; };
947
948 template<typename _Tp>
949 struct _MakeUniq<_Tp[]>
950 { typedef unique_ptr<_Tp[]> __array; };
951
952 template<typename _Tp, size_t _Bound>
953 struct _MakeUniq<_Tp[_Bound]>
954 { struct __invalid_type { }; };
955
956 /// @endcond
957
958 /// std::make_unique for single objects
959 template<typename _Tp, typename... _Args>
960 inline typename _MakeUniq<_Tp>::__single_object
961 make_unique(_Args&&... __args)
962 { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
963
964 /// std::make_unique for arrays of unknown bound
965 template<typename _Tp>
966 inline typename _MakeUniq<_Tp>::__array
967 make_unique(size_t __num)
968 { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); }
969
970 /// Disable std::make_unique for arrays of known bound
971 template<typename _Tp, typename... _Args>
972 inline typename _MakeUniq<_Tp>::__invalid_type
973 make_unique(_Args&&...) = delete;
974 // @} relates unique_ptr
975#endif // C++14
976
977#if __cplusplus201703L > 201703L && __cpp_concepts
978 // _GLIBCXX_RESOLVE_LIB_DEFECTS
979 // 2948. unique_ptr does not define operator<< for stream output
980 /// Stream output operator for unique_ptr
981 template<typename _CharT, typename _Traits, typename _Tp, typename _Dp>
982 inline basic_ostream<_CharT, _Traits>&
983 operator<<(basic_ostream<_CharT, _Traits>& __os,
984 const unique_ptr<_Tp, _Dp>& __p)
985 requires requires { __os << __p.get(); }
986 {
987 __os << __p.get();
988 return __os;
989 }
990#endif // C++20
991
992 // @} group pointer_abstractions
993
994#if __cplusplus201703L >= 201703L
995 namespace __detail::__variant
996 {
997 template<typename> struct _Never_valueless_alt; // see <variant>
998
999 // Provide the strong exception-safety guarantee when emplacing a
1000 // unique_ptr into a variant.
1001 template<typename _Tp, typename _Del>
1002 struct _Never_valueless_alt<std::unique_ptr<_Tp, _Del>>
1003 : std::true_type
1004 { };
1005 } // namespace __detail::__variant
1006#endif // C++17
1007
1008_GLIBCXX_END_NAMESPACE_VERSION
1009} // namespace
1010
1011#endif /* _UNIQUE_PTR_H */

/home/maarten/src/libreoffice/core/include/svx/svditer.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_SVX_SVDITER_HXX
21#define INCLUDED_SVX_SVDITER_HXX
22
23#include <vector>
24
25#include <svx/svxdllapi.h>
26
27class SdrObjList;
28class SdrObject;
29class SdrPage;
30class SdrMarkList;
31
32// SdrObjListIter methods:
33// SdrIterMode::Flat : Flat over the list
34// SdrIterMode::DeepWithGroups : With recursive descent parser, Next() also returns group objects
35// SdrIterMode::DeepNoGroups : With recursive descent parser, Next() returns no group objects
36enum class SdrIterMode { Flat, DeepWithGroups, DeepNoGroups };
37
38class SVXCORE_DLLPUBLIC__attribute__ ((visibility("default"))) SdrObjListIter
39{
40 std::vector< const SdrObject* > maObjList;
41 size_t mnIndex;
42 bool mbReverse;
43 bool mbUseZOrder;
44
45 void ImpProcessObjectList(const SdrObjList& rSdrObjList, SdrIterMode eMode);
46 void ImpProcessMarkList(const SdrMarkList& rMarkList, SdrIterMode eMode);
47 void ImpProcessObj(const SdrObject& rSdrObject, SdrIterMode eMode);
48
49public:
50 explicit SdrObjListIter(const SdrObjList* pObjList, SdrIterMode eMode = SdrIterMode::DeepNoGroups, bool bReverse = false);
51 explicit SdrObjListIter(const SdrObjList* pObjList, bool bUseZOrder, SdrIterMode eMode = SdrIterMode::DeepNoGroups, bool bReverse = false);
52
53 /* SJ: the following function can now be used with every
54 SdrObject and is no longer limited to group objects */
55 explicit SdrObjListIter(const SdrObject& rSdrObject, SdrIterMode eMode = SdrIterMode::DeepNoGroups, bool bReverse = false);
56 explicit SdrObjListIter(const SdrPage* pSdrPage, SdrIterMode eMode = SdrIterMode::DeepNoGroups, bool bReverse = false);
57
58 /** Iterates over a list of marked objects received from the SdrMarkView. TTTT used in sc */
59 explicit SdrObjListIter(const SdrMarkList& rMarkList, SdrIterMode eMode = SdrIterMode::DeepNoGroups);
60
61 void Reset() { mnIndex = (mbReverse ? maObjList.size() : 0L); }
62 bool IsMore() const { return (mbReverse ? mnIndex != 0 : ( mnIndex < maObjList.size())); }
32
Assuming field 'mbReverse' is true
33
'?' condition is true
34
Assuming field 'mnIndex' is not equal to 0
35
Returning the value 1, which participates in a condition later
69
Assuming field 'mbReverse' is true
70
'?' condition is true
71
Assuming field 'mnIndex' is not equal to 0
72
Returning the value 1, which participates in a condition later
63 SdrObject* Next()
64 {
65 const size_t idx(mbReverse
38.1
Field 'mbReverse' is true
75.1
Field 'mbReverse' is true
38.1
Field 'mbReverse' is true
75.1
Field 'mbReverse' is true
38.1
Field 'mbReverse' is true
75.1
Field 'mbReverse' is true
38.1
Field 'mbReverse' is true
75.1
Field 'mbReverse' is true
38.1
Field 'mbReverse' is true
75.1
Field 'mbReverse' is true
? --mnIndex : mnIndex++);
39
'?' condition is true
76
'?' condition is true
66 return (idx < maObjList.size()) ? const_cast< SdrObject* >(maObjList[idx]) : nullptr;
40
Assuming the condition is true
41
'?' condition is true
42
Returning pointer, which participates in a condition later
77
Assuming the condition is true
78
'?' condition is true
79
Returning pointer, which participates in a condition later
80
Returning pointer
67 }
68
69 size_t Count() { return maObjList.size(); }
70};
71
72#endif // INCLUDED_SVX_SVDITER_HXX
73
74/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/tools/gen.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#ifndef INCLUDED_TOOLS_GEN_HXX
20#define INCLUDED_TOOLS_GEN_HXX
21
22#include <tools/toolsdllapi.h>
23
24#include <limits.h>
25#include <algorithm>
26#include <ostream>
27#include <config_options.h>
28
29class SvStream;
30namespace rtl
31{
32 class OString;
33}
34
35enum TriState { TRISTATE_FALSE, TRISTATE_TRUE, TRISTATE_INDET };
36
37// Pair
38
39class SAL_WARN_UNUSED__attribute__((warn_unused)) Pair
40{
41public:
42 Pair() : nA(0), nB(0) {}
43 Pair( long _nA, long _nB ) : nA(_nA), nB(_nB) {}
44
45 long A() const { return nA; }
46 long B() const { return nB; }
47
48 long& A() { return nA; }
49 long& B() { return nB; }
50
51 TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) rtl::OString toString() const;
52
53protected:
54 long nA;
55 long nB;
56};
57
58namespace tools::detail {
59
60// Used to implement operator == for subclasses of Pair:
61inline bool equal(Pair const & p1, Pair const & p2)
62{
63 return p1.A() == p2.A() && p1.B() == p2.B();
56
Assuming the condition is false
57
Returning zero, which participates in a condition later
64}
65
66}
67
68// Point
69
70class Size;
71class SAL_WARN_UNUSED__attribute__((warn_unused)) UNLESS_MERGELIBS(SAL_DLLPUBLIC_EXPORT)__attribute__ ((visibility("default"))) Point final : protected Pair
72{
73public:
74 Point() {}
75 Point( long nX, long nY ) : Pair( nX, nY ) {}
76
77 long X() const { return nA; }
78 long Y() const { return nB; }
79
80 void Move( long nHorzMove, long nVertMove );
81 void Move( Size const & s );
82 long AdjustX( long nHorzMove ) { nA += nHorzMove; return nA; }
83 long AdjustY( long nVertMove ) { nB += nVertMove; return nB; }
84
85 void RotateAround( long& rX, long& rY, short nOrientation ) const;
86 void RotateAround( Point&, short nOrientation ) const;
87
88 Point& operator += ( const Point& rPoint );
89 Point& operator -= ( const Point& rPoint );
90 Point& operator *= ( const long nVal );
91 Point& operator /= ( const long nVal );
92
93 friend inline Point operator+( const Point &rVal1, const Point &rVal2 );
94 friend inline Point operator-( const Point &rVal1, const Point &rVal2 );
95 friend inline Point operator*( const Point &rVal1, const long nVal2 );
96 friend inline Point operator/( const Point &rVal1, const long nVal2 );
97
98 long getX() const { return X(); }
99 long getY() const { return Y(); }
100 void setX(long nX) { nA = nX; }
101 void setY(long nY) { nB = nY; }
102
103 Pair const & toPair() const { return *this; }
104 Pair & toPair() { return *this; }
105
106 using Pair::toString;
107};
108
109inline void Point::Move( long nHorzMove, long nVertMove )
110{
111 nA += nHorzMove;
112 nB += nVertMove;
113}
114
115inline Point& Point::operator += ( const Point& rPoint )
116{
117 nA += rPoint.nA;
118 nB += rPoint.nB;
119 return *this;
120}
121
122inline Point& Point::operator -= ( const Point& rPoint )
123{
124 nA -= rPoint.nA;
125 nB -= rPoint.nB;
126 return *this;
127}
128
129inline Point& Point::operator *= ( const long nVal )
130{
131 nA *= nVal;
132 nB *= nVal;
133 return *this;
134}
135
136inline Point& Point::operator /= ( const long nVal )
137{
138 nA /= nVal;
139 nB /= nVal;
140 return *this;
141}
142
143inline Point operator+( const Point &rVal1, const Point &rVal2 )
144{
145 return Point( rVal1.nA+rVal2.nA, rVal1.nB+rVal2.nB );
146}
147
148inline Point operator-( const Point &rVal1, const Point &rVal2 )
149{
150 return Point( rVal1.nA-rVal2.nA, rVal1.nB-rVal2.nB );
151}
152
153inline Point operator*( const Point &rVal1, const long nVal2 )
154{
155 return Point( rVal1.nA*nVal2, rVal1.nB*nVal2 );
156}
157
158inline Point operator/( const Point &rVal1, const long nVal2 )
159{
160 return Point( rVal1.nA/nVal2, rVal1.nB/nVal2 );
161}
162
163inline bool operator ==(Point const & p1, Point const & p2)
164{
165 return tools::detail::equal(p1.toPair(), p2.toPair());
55
Calling 'equal'
58
Returning from 'equal'
59
Returning zero, which participates in a condition later
166}
167
168inline bool operator !=(Point const & p1, Point const & p2)
169{
170 return !(p1 == p2);
54
Calling 'operator=='
60
Returning from 'operator=='
61
Returning the value 1, which participates in a condition later
171}
172
173template< typename charT, typename traits >
174inline std::basic_ostream<charT, traits> & operator <<(
175 std::basic_ostream<charT, traits> & stream, const Point& point )
176{
177 return stream << point.X() << ',' << point.Y();
178}
179
180// Size
181
182class SAL_WARN_UNUSED__attribute__((warn_unused)) Size final : protected Pair
183{
184public:
185 Size() {}
186 Size( long nWidth, long nHeight ) : Pair( nWidth, nHeight ) {}
187
188 long Width() const { return nA; }
189 long Height() const { return nB; }
190
191 long AdjustWidth( long n ) { nA += n; return nA; }
192 long AdjustHeight( long n ) { nB += n; return nB; }
193
194 long getWidth() const { return Width(); }
195 long getHeight() const { return Height(); }
196 void setWidth(long nWidth) { nA = nWidth; }
197 void setHeight(long nHeight) { nB = nHeight; }
198
199 bool IsEmpty() const { return nA <= 0 || nB <= 0; }
200
201 void extendBy(long x, long y)
202 {
203 nA += x;
204 nB += y;
205 }
206
207 Pair const & toPair() const { return *this; }
208 Pair & toPair() { return *this; }
209
210 using Pair::toString;
211};
212
213inline bool operator ==(Size const & s1, Size const & s2)
214{
215 return tools::detail::equal(s1.toPair(), s2.toPair());
216}
217
218inline bool operator !=(Size const & s1, Size const & s2)
219{
220 return !(s1 == s2);
221}
222
223template< typename charT, typename traits >
224inline std::basic_ostream<charT, traits> & operator <<(
225 std::basic_ostream<charT, traits> & stream, const Size& size )
226{
227 return stream << size.Width() << 'x' << size.Height();
228}
229
230inline void Point::Move( Size const & s )
231{
232 AdjustX(s.Width());
233 AdjustY(s.Height());
234}
235
236// Range
237
238#define RANGE_MAX9223372036854775807L LONG_MAX9223372036854775807L
239
240class SAL_WARN_UNUSED__attribute__((warn_unused)) Range final : protected Pair
241{
242public:
243 Range() {}
244 Range( long nMin, long nMax ) : Pair( nMin, nMax ) {}
245
246 long Min() const { return nA; }
247 long Max() const { return nB; }
248 long Len() const { return nB - nA + 1; }
249
250 long& Min() { return nA; }
251 long& Max() { return nB; }
252
253 bool IsInside( long nIs ) const;
254
255 void Justify();
256
257 Pair const & toPair() const { return *this; }
258 Pair & toPair() { return *this; }
259
260 using Pair::toString;
261};
262
263inline bool Range::IsInside( long nIs ) const
264{
265 return ((nA <= nIs) && (nIs <= nB ));
266}
267
268inline void Range::Justify()
269{
270 if ( nA > nB )
271 {
272 long nHelp = nA;
273 nA = nB;
274 nB = nHelp;
275 }
276}
277
278inline bool operator ==(Range const & r1, Range const & r2)
279{
280 return tools::detail::equal(r1.toPair(), r2.toPair());
281}
282
283inline bool operator !=(Range const & r1, Range const & r2)
284{
285 return !(r1 == r2);
286}
287
288template< typename charT, typename traits >
289inline std::basic_ostream<charT, traits> & operator <<(
290 std::basic_ostream<charT, traits> & stream, const Range& range )
291{
292 return stream << range.Min() << '-' << range.Max();
293}
294
295// Selection
296
297#define SELECTION_MIN(-9223372036854775807L -1L) LONG_MIN(-9223372036854775807L -1L)
298#define SELECTION_MAX9223372036854775807L LONG_MAX9223372036854775807L
299
300class SAL_WARN_UNUSED__attribute__((warn_unused)) Selection final : protected Pair
301{
302public:
303 Selection() {}
304 Selection( long nPos ) : Pair( nPos, nPos ) {}
305 Selection( long nMin, long nMax ) : Pair( nMin, nMax ) {}
306
307 long Min() const { return nA; }
308 long Max() const { return nB; }
309 long Len() const { return nB - nA; }
310
311 long& Min() { return nA; }
312 long& Max() { return nB; }
313
314 bool IsInside( long nIs ) const;
315
316 void Justify();
317
318 bool operator !() const { return !Len(); }
319
320 long getMin() const { return Min(); }
321 void setMin(long nMin) { Min() = nMin; }
322 void setMax(long nMax) { Max() = nMax; }
323
324 Pair const & toPair() const { return *this; }
325 Pair & toPair() { return *this; }
326
327 using Pair::toString;
328};
329
330inline bool Selection::IsInside( long nIs ) const
331{
332 return ((nA <= nIs) && (nIs < nB ));
333}
334
335inline void Selection::Justify()
336{
337 if ( nA > nB )
338 {
339 long nHelp = nA;
340 nA = nB;
341 nB = nHelp;
342 }
343}
344
345inline bool operator ==(Selection const & s1, Selection const & s2)
346{
347 return tools::detail::equal(s1.toPair(), s2.toPair());
348}
349
350inline bool operator !=(Selection const & s1, Selection const & s2)
351{
352 return !(s1 == s2);
353}
354
355template< typename charT, typename traits >
356inline std::basic_ostream<charT, traits> & operator <<(
357 std::basic_ostream<charT, traits> & stream, const Selection& selection )
358{
359 return stream << selection.Min() << '-' << selection.Max();
360}
361// Rectangle
362
363#define RECT_MAX9223372036854775807L LONG_MAX9223372036854775807L
364#define RECT_MIN(-9223372036854775807L -1L) LONG_MIN(-9223372036854775807L -1L)
365
366/// Note: this class is a true marvel of engineering: because the author
367/// could not decide whether it's better to have a closed or half-open
368/// interval, they just implemented *both* in the same class!
369///
370/// If you have the misfortune of having to use this class, don't immediately
371/// despair but first take note that the uppercase GetWidth() / GetHeight()
372/// etc. methods interpret the interval as closed, while the lowercase
373/// getWidth() / getHeight() etc. methods interpret the interval as half-open.
374/// Ok, now is the time for despair.
375namespace tools
376{
377class SAL_WARN_UNUSED__attribute__((warn_unused)) TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) Rectangle final
378{
379 static constexpr short RECT_EMPTY = -32767;
380public:
381 Rectangle();
382 Rectangle( const Point& rLT, const Point& rRB );
383 Rectangle( long nLeft, long nTop,
384 long nRight, long nBottom );
385 /// Constructs an empty Rectangle, with top/left at the specified params
386 Rectangle( long nLeft, long nTop );
387 Rectangle( const Point& rLT, const Size& rSize );
388
389 static Rectangle Justify( const Point& rLT, const Point& rRB );
390
391 long Left() const { return nLeft; }
392 long Right() const;
393 long Top() const { return nTop; }
394 long Bottom() const;
395
396 void SetLeft(long v) { nLeft = v; }
397 void SetRight(long v) { nRight = v; }
398 void SetTop(long v) { nTop = v; }
399 void SetBottom(long v) { nBottom = v; }
400
401 inline Point TopLeft() const;
402 inline Point TopRight() const;
403 inline Point TopCenter() const;
404 inline Point BottomLeft() const;
405 inline Point BottomRight() const;
406 inline Point BottomCenter() const;
407 inline Point LeftCenter() const;
408 inline Point RightCenter() const;
409 inline Point Center() const;
410
411 /// Move the top and left edges by a delta, preserving width and height
412 inline void Move( long nHorzMoveDelta, long nVertMoveDelta );
413 void Move( Size const & s ) { Move(s.Width(), s.Height()); }
414 long AdjustLeft( long nHorzMoveDelta ) { nLeft += nHorzMoveDelta; return nLeft; }
415 long AdjustRight( long nHorzMoveDelta );
416 long AdjustTop( long nVertMoveDelta ) { nTop += nVertMoveDelta; return nTop; }
417 long AdjustBottom( long nVertMoveDelta );
418 inline void SetPos( const Point& rPoint );
419 void SetSize( const Size& rSize );
420 inline Size GetSize() const;
421
422 /// Returns the difference between right and left, assuming the range is inclusive.
423 inline long GetWidth() const;
424 /// Returns the difference between bottom and top, assuming the range is inclusive.
425 inline long GetHeight() const;
426
427 tools::Rectangle& Union( const tools::Rectangle& rRect );
428 tools::Rectangle& Intersection( const tools::Rectangle& rRect );
429 inline tools::Rectangle GetUnion( const tools::Rectangle& rRect ) const;
430 inline tools::Rectangle GetIntersection( const tools::Rectangle& rRect ) const;
431
432 void Justify();
433
434 bool IsInside( const Point& rPOINT ) const;
435 bool IsInside( const tools::Rectangle& rRect ) const;
436 bool IsOver( const tools::Rectangle& rRect ) const;
437
438 void SetEmpty() { nRight = nBottom = RECT_EMPTY; }
439 void SetWidthEmpty() { nRight = RECT_EMPTY; }
440 void SetHeightEmpty() { nBottom = RECT_EMPTY; }
441 inline bool IsEmpty() const;
442 bool IsWidthEmpty() const { return nRight == RECT_EMPTY; }
443 bool IsHeightEmpty() const { return nBottom == RECT_EMPTY; }
444
445 inline bool operator == ( const tools::Rectangle& rRect ) const;
446 inline bool operator != ( const tools::Rectangle& rRect ) const;
447
448 inline tools::Rectangle& operator += ( const Point& rPt );
449 inline tools::Rectangle& operator -= ( const Point& rPt );
450
451 friend inline tools::Rectangle operator + ( const tools::Rectangle& rRect, const Point& rPt );
452 friend inline tools::Rectangle operator - ( const tools::Rectangle& rRect, const Point& rPt );
453
454 // ONE
455 long getX() const { return nLeft; }
456 long getY() const { return nTop; }
457 /// Returns the difference between right and left, assuming the range includes one end, but not the other.
458 long getWidth() const;
459 /// Returns the difference between bottom and top, assuming the range includes one end, but not the other.
460 long getHeight() const;
461 /// Set the left edge of the rectangle to x, preserving the width
462 void setX( long x );
463 /// Set the top edge of the rectangle to y, preserving the height
464 void setY( long y );
465 void setWidth( long n ) { nRight = nLeft + n; }
466 void setHeight( long n ) { nBottom = nTop + n; }
467 /// Returns the string representation of the rectangle, format is "x, y, width, height".
468 rtl::OString toString() const;
469
470 /**
471 * Expands the rectangle in all directions by the input value.
472 */
473 void expand(long nExpandBy);
474 void shrink(long nShrinkBy);
475
476 /**
477 * Sanitizing variants for handling data from the outside
478 */
479 void SaturatingSetSize(const Size& rSize);
480 void SaturatingSetX(long x);
481 void SaturatingSetY(long y);
482
483private:
484 long nLeft;
485 long nTop;
486 long nRight;
487 long nBottom;
488};
489}
490
491inline tools::Rectangle::Rectangle()
492{
493 nLeft = nTop = 0;
494 nRight = nBottom = RECT_EMPTY;
495}
496
497inline tools::Rectangle::Rectangle( const Point& rLT, const Point& rRB )
498{
499 nLeft = rLT.X();
500 nTop = rLT.Y();
501 nRight = rRB.X();
502 nBottom = rRB.Y();
503}
504
505inline tools::Rectangle::Rectangle( long _nLeft, long _nTop,
506 long _nRight, long _nBottom )
507{
508 nLeft = _nLeft;
509 nTop = _nTop;
510 nRight = _nRight;
511 nBottom = _nBottom;
512}
513
514inline tools::Rectangle::Rectangle( long _nLeft, long _nTop )
515{
516 nLeft = _nLeft;
517 nTop = _nTop;
518 nRight = nBottom = RECT_EMPTY;
519}
520
521inline tools::Rectangle::Rectangle( const Point& rLT, const Size& rSize )
522{
523 nLeft = rLT.X();
524 nTop = rLT.Y();
525 nRight = rSize.Width() ? nLeft+(rSize.Width()-1) : RECT_EMPTY;
526 nBottom = rSize.Height() ? nTop+(rSize.Height()-1) : RECT_EMPTY;
527}
528
529inline bool tools::Rectangle::IsEmpty() const
530{
531 return (nRight == RECT_EMPTY) || (nBottom == RECT_EMPTY);
532}
533
534inline Point tools::Rectangle::TopLeft() const
535{
536 return Point( nLeft, nTop );
537}
538
539inline Point tools::Rectangle::TopRight() const
540{
541 return Point( (nRight == RECT_EMPTY) ? nLeft : nRight, nTop );
542}
543
544inline Point tools::Rectangle::BottomLeft() const
545{
546 return Point( nLeft, (nBottom == RECT_EMPTY) ? nTop : nBottom );
547}
548
549inline Point tools::Rectangle::BottomRight() const
550{
551 return Point( (nRight == RECT_EMPTY) ? nLeft : nRight,
552 (nBottom == RECT_EMPTY) ? nTop : nBottom );
553}
554
555inline Point tools::Rectangle::TopCenter() const
556{
557 if ( IsEmpty() )
558 return Point( nLeft, nTop );
559 else
560 return Point( std::min( nLeft, nRight ) + std::abs( (nRight - nLeft)/2 ),
561 std::min( nTop, nBottom) );
562}
563
564inline Point tools::Rectangle::BottomCenter() const
565{
566 if ( IsEmpty() )
567 return Point( nLeft, nTop );
568 else
569 return Point( std::min( nLeft, nRight ) + std::abs( (nRight - nLeft)/2 ),
570 std::max( nTop, nBottom) );
571}
572
573inline Point tools::Rectangle::LeftCenter() const
574{
575 if ( IsEmpty() )
576 return Point( nLeft, nTop );
577 else
578 return Point( std::min( nLeft, nRight ), nTop + (nBottom - nTop)/2 );
579}
580
581inline Point tools::Rectangle::RightCenter() const
582{
583 if ( IsEmpty() )
584 return Point( nLeft, nTop );
585 else
586 return Point( std::max( nLeft, nRight ), nTop + (nBottom - nTop)/2 );
587}
588
589inline Point tools::Rectangle::Center() const
590{
591 if ( IsEmpty() )
592 return Point( nLeft, nTop );
593 else
594 return Point( nLeft+(nRight-nLeft)/2 , nTop+(nBottom-nTop)/2 );
595}
596
597inline void tools::Rectangle::Move( long nHorzMove, long nVertMove )
598{
599 nLeft += nHorzMove;
600 nTop += nVertMove;
601 if ( nRight != RECT_EMPTY )
602 nRight += nHorzMove;
603 if ( nBottom != RECT_EMPTY )
604 nBottom += nVertMove;
605}
606
607inline void tools::Rectangle::SetPos( const Point& rPoint )
608{
609 if ( nRight != RECT_EMPTY )
610 nRight += rPoint.X() - nLeft;
611 if ( nBottom != RECT_EMPTY )
612 nBottom += rPoint.Y() - nTop;
613 nLeft = rPoint.X();
614 nTop = rPoint.Y();
615}
616
617inline long tools::Rectangle::GetWidth() const
618{
619 long n;
620 if ( nRight == RECT_EMPTY )
621 n = 0;
622 else
623 {
624 n = nRight - nLeft;
625 if( n < 0 )
626 n--;
627 else
628 n++;
629 }
630
631 return n;
632}
633
634inline long tools::Rectangle::GetHeight() const
635{
636 long n;
637 if ( nBottom == RECT_EMPTY )
638 n = 0;
639 else
640 {
641 n = nBottom - nTop;
642 if ( n < 0 )
643 n--;
644 else
645 n++;
646 }
647
648 return n;
649}
650
651inline Size tools::Rectangle::GetSize() const
652{
653 return Size( GetWidth(), GetHeight() );
654}
655
656inline tools::Rectangle tools::Rectangle::GetUnion( const tools::Rectangle& rRect ) const
657{
658 tools::Rectangle aTmpRect( *this );
659 return aTmpRect.Union( rRect );
660}
661
662inline tools::Rectangle tools::Rectangle::GetIntersection( const tools::Rectangle& rRect ) const
663{
664 tools::Rectangle aTmpRect( *this );
665 return aTmpRect.Intersection( rRect );
666}
667
668inline bool tools::Rectangle::operator == ( const tools::Rectangle& rRect ) const
669{
670 return (nLeft == rRect.nLeft ) &&
671 (nTop == rRect.nTop ) &&
672 (nRight == rRect.nRight ) &&
673 (nBottom == rRect.nBottom );
674}
675
676inline bool tools::Rectangle::operator != ( const tools::Rectangle& rRect ) const
677{
678 return (nLeft != rRect.nLeft ) ||
679 (nTop != rRect.nTop ) ||
680 (nRight != rRect.nRight ) ||
681 (nBottom != rRect.nBottom );
682}
683
684inline tools::Rectangle& tools::Rectangle::operator +=( const Point& rPt )
685{
686 nLeft += rPt.X();
687 nTop += rPt.Y();
688 if ( nRight != RECT_EMPTY )
689 nRight += rPt.X();
690 if ( nBottom != RECT_EMPTY )
691 nBottom += rPt.Y();
692 return *this;
693}
694
695inline tools::Rectangle& tools::Rectangle::operator -= ( const Point& rPt )
696{
697 nLeft -= rPt.X();
698 nTop -= rPt.Y();
699 if ( nRight != RECT_EMPTY )
700 nRight -= rPt.X();
701 if ( nBottom != RECT_EMPTY )
702 nBottom -= rPt.Y();
703 return *this;
704}
705
706namespace tools
707{
708inline Rectangle operator + ( const Rectangle& rRect, const Point& rPt )
709{
710 return rRect.IsEmpty()
711 ? Rectangle( rRect.nLeft + rPt.X(), rRect.nTop + rPt.Y() )
712 : Rectangle( rRect.nLeft + rPt.X(), rRect.nTop + rPt.Y(),
713 rRect.nRight + rPt.X(), rRect.nBottom + rPt.Y() );
714}
715
716inline Rectangle operator - ( const Rectangle& rRect, const Point& rPt )
717{
718 return rRect.IsEmpty()
719 ? Rectangle( rRect.nLeft - rPt.X(), rRect.nTop - rPt.Y() )
720 : Rectangle( rRect.nLeft - rPt.X(), rRect.nTop - rPt.Y(),
721 rRect.nRight - rPt.X(), rRect.nBottom - rPt.Y() );
722}
723}
724
725template< typename charT, typename traits >
726inline std::basic_ostream<charT, traits> & operator <<(
727 std::basic_ostream<charT, traits> & stream, const tools::Rectangle& rectangle )
728{
729 if (rectangle.IsEmpty())
730 return stream << "EMPTY";
731 else
732 return stream << rectangle.getWidth() << 'x' << rectangle.getHeight()
733 << "@(" << rectangle.getX() << ',' << rectangle.getY() << ")";
734}
735
736#endif
737
738/* vim:set shiftwidth=4 softtabstop=4 expandtab: */