Bug Summary

File:home/maarten/src/libreoffice/core/sd/source/ui/func/fudraw.cxx
Warning:line 469, column 9
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 fudraw.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 -isystem /usr/include/dbus-1.0 -isystem /usr/lib64/dbus-1.0/include -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 SD_DLLIMPLEMENTATION -D SDUI_DLL_NAME="libsduilo.so" -D SYSTEM_LIBXML -D ENABLE_SDREMOTE -D ENABLE_SDREMOTE_BLUETOOTH -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/external/bluez_bluetooth/inc -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/sd/inc -I /home/maarten/src/libreoffice/core/sd/source/ui/inc -I /home/maarten/src/libreoffice/core/sd/source/ui/slidesorter/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sd/sdi -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/oox/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -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/sd/source/ui/func/fudraw.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 <sal/config.h>
21
22#include <vcl/svapp.hxx>
23#include <vcl/ptrstyle.hxx>
24#include <editeng/flditem.hxx>
25#include <svx/svdogrp.hxx>
26#include <svx/svdoole2.hxx>
27#include <tools/urlobj.hxx>
28#include <vcl/help.hxx>
29#include <svx/bmpmask.hxx>
30#include <svx/svdotext.hxx>
31#include <svx/ImageMapInfo.hxx>
32#include <sfx2/dispatch.hxx>
33#include <sfx2/bindings.hxx>
34#include <sfx2/sfxhelp.hxx>
35#include <svx/svdpagv.hxx>
36#include <vcl/imapobj.hxx>
37#include <svx/svxids.hrc>
38#include <svx/obj3d.hxx>
39#include <svx/scene3d.hxx>
40#include <sfx2/viewfrm.hxx>
41
42#include <strings.hrc>
43
44
45#include <sdmod.hxx>
46#include <fudraw.hxx>
47#include <ViewShell.hxx>
48#include <FrameView.hxx>
49#include <View.hxx>
50#include <Window.hxx>
51#include <drawdoc.hxx>
52#include <DrawDocShell.hxx>
53#include <sdresid.hxx>
54#include <fusel.hxx>
55#include <vcl/weld.hxx>
56#include <svx/sdrhittesthelper.hxx>
57
58using namespace ::com::sun::star;
59
60namespace sd {
61
62
63/**
64 * Base-class for all drawmodul-specific functions
65 */
66FuDraw::FuDraw(ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView,
67 SdDrawDocument* pDoc, SfxRequest& rReq)
68 : FuPoor(pViewSh, pWin, pView, pDoc, rReq)
69 , aNewPointer(PointerStyle::Arrow)
70 , aOldPointer(PointerStyle::Arrow)
71 , bMBDown(false)
72 , bDragHelpLine(false)
73 , nHelpLine(0)
74 , bPermanent(false)
75{
76}
77
78FuDraw::~FuDraw()
79{
80 mpView->BrkAction();
81}
82
83
84/**
85 * Code shared by MouseButtonDown and MouseMove
86 */
87void FuDraw::DoModifiers(const MouseEvent& rMEvt, bool bSnapModPressed)
88{
89 FrameView* pFrameView = mpViewShell->GetFrameView();
90 bool bGridSnap = pFrameView->IsGridSnap();
91 bGridSnap = (bSnapModPressed != bGridSnap);
92
93 if (mpView->IsGridSnap() != bGridSnap)
94 mpView->SetGridSnap(bGridSnap);
95
96 bool bBordSnap = pFrameView->IsBordSnap();
97 bBordSnap = (bSnapModPressed != bBordSnap);
98
99 if (mpView->IsBordSnap() != bBordSnap)
100 mpView->SetBordSnap(bBordSnap);
101
102 bool bHlplSnap = pFrameView->IsHlplSnap();
103 bHlplSnap = (bSnapModPressed != bHlplSnap);
104
105 if (mpView->IsHlplSnap() != bHlplSnap)
106 mpView->SetHlplSnap(bHlplSnap);
107
108 bool bOFrmSnap = pFrameView->IsOFrmSnap();
109 bOFrmSnap = (bSnapModPressed != bOFrmSnap);
110
111 if (mpView->IsOFrmSnap() != bOFrmSnap)
112 mpView->SetOFrmSnap(bOFrmSnap);
113
114 bool bOPntSnap = pFrameView->IsOPntSnap();
115 bOPntSnap = (bSnapModPressed != bOPntSnap);
116
117 if (mpView->IsOPntSnap() != bOPntSnap)
118 mpView->SetOPntSnap(bOPntSnap);
119
120 bool bOConSnap = pFrameView->IsOConSnap();
121 bOConSnap = (bSnapModPressed != bOConSnap);
122
123 if (mpView->IsOConSnap() != bOConSnap)
124 mpView->SetOConSnap(bOConSnap);
125
126 bool bAngleSnap = rMEvt.IsShift() == !pFrameView->IsAngleSnapEnabled();
127
128 if (mpView->IsAngleSnapEnabled() != bAngleSnap)
129 mpView->SetAngleSnapEnabled(bAngleSnap);
130
131 bool bCenter = rMEvt.IsMod2();
132
133 if ( mpView->IsCreate1stPointAsCenter() != bCenter ||
134 mpView->IsResizeAtCenter() != bCenter )
135 {
136 mpView->SetCreate1stPointAsCenter(bCenter);
137 mpView->SetResizeAtCenter(bCenter);
138 }
139}
140
141
142bool FuDraw::MouseButtonDown(const MouseEvent& rMEvt)
143{
144 // remember button state for creation of own MouseEvents
145 SetMouseButtonCode(rMEvt.GetButtons());
146
147 bool bReturn = false;
148 bDragHelpLine = false;
149 aMDPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() );
150
151 if ( rMEvt.IsLeft() )
152 {
153 FrameView* pFrameView = mpViewShell->GetFrameView();
154
155 bool bOrtho = false;
156
157 bool bRestricted = true;
158
159 if (mpView->IsDragObj())
160 {
161 // object is dragged (move, resize,...)
162 const SdrHdl* pHdl = mpView->GetDragStat().GetHdl();
163
164 if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl()))
165 {
166 // Move
167 bRestricted = false;
168 }
169 }
170
171 // #i33136#
172 if(bRestricted && doConstructOrthogonal())
173 {
174 // Restrict movement:
175 // rectangle->quadrat, ellipse->circle etc.
176 bOrtho = !rMEvt.IsShift();
177 }
178 else
179 {
180 bOrtho = rMEvt.IsShift() != pFrameView->IsOrtho();
181 }
182 if (!mpView->IsSnapEnabled())
183 mpView->SetSnapEnabled(true);
184
185 bool bSnapModPressed = rMEvt.IsMod1();
186 if (mpView->IsOrtho() != bOrtho)
187 mpView->SetOrtho(bOrtho);
188
189 DoModifiers(rMEvt, bSnapModPressed);
190
191 SdrPageView* pPV = nullptr;
192 sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() );
193
194 // look only for HelpLines when they are visible (!)
195 bool bHelpLine(false);
196 if(mpView->IsHlplVisible())
197 bHelpLine = mpView->PickHelpLine(aMDPos, nHitLog, *mpWindow, nHelpLine, pPV);
198 bool bHitHdl = (mpView->PickHandle(aMDPos) != nullptr);
199
200 if ( bHelpLine
201 && !mpView->IsCreateObj()
202 && ((mpView->GetEditMode() == SdrViewEditMode::Edit && !bHitHdl) || (rMEvt.IsShift() && bSnapModPressed)) )
203 {
204 mpWindow->CaptureMouse();
205 mpView->BegDragHelpLine(nHelpLine, pPV);
206 bDragHelpLine = mpView->IsDragHelpLine();
207 bReturn = true;
208 }
209 }
210 ForcePointer(&rMEvt);
211
212 return bReturn;
213}
214
215bool FuDraw::MouseMove(const MouseEvent& rMEvt)
216{
217 FrameView* pFrameView = mpViewShell->GetFrameView();
218 Point aPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() );
219
220 bool bOrtho = false;
221 bool bRestricted = true;
222
223 if (mpView->IsDragObj())
224 {
225 // object is dragged (move, resize, ...)
226 const SdrHdl* pHdl = mpView->GetDragStat().GetHdl();
227
228 if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl()))
229 {
230 // Move
231 bRestricted = false;
232 }
233 }
234
235 if (mpView->IsAction())
236 {
237 // #i33136# and fdo#88339
238 if(bRestricted && doConstructOrthogonal())
239 {
240 // Scale proportionally by default:
241 // rectangle->quadrat, ellipse->circle, Images etc.
242 bOrtho = !rMEvt.IsShift();
243 }
244 else
245 {
246 bOrtho = rMEvt.IsShift() != pFrameView->IsOrtho();
247 }
248
249 bool bSnapModPressed = rMEvt.IsMod2();
250 mpView->SetDragWithCopy(rMEvt.IsMod1() && pFrameView->IsDragWithCopy());
251
252 if (mpView->IsOrtho() != bOrtho)
253 mpView->SetOrtho(bOrtho);
254 DoModifiers(rMEvt, bSnapModPressed);
255
256
257 if ( mpView->IsDragHelpLine() )
258 mpView->MovDragHelpLine(aPos);
259 }
260
261 bool bReturn = mpView->MouseMove(rMEvt, mpWindow);
262
263 if (mpView->IsAction())
264 {
265 // Because the flag set back if necessary in MouseMove
266 if (mpView->IsOrtho() != bOrtho)
267 mpView->SetOrtho(bOrtho);
268 }
269
270 ForcePointer(&rMEvt);
271
272 return bReturn;
273}
274
275bool FuDraw::MouseButtonUp(const MouseEvent& rMEvt)
276{
277 if (mpView && mpView->IsDragHelpLine())
1
Assuming field 'mpView' is null
278 mpView->EndDragHelpLine();
279
280 if ( bDragHelpLine )
2
Assuming field 'bDragHelpLine' is false
3
Taking false branch
281 {
282 ::tools::Rectangle aOutputArea(Point(0,0), mpWindow->GetOutputSizePixel());
283
284 if (mpView && !aOutputArea.IsInside(rMEvt.GetPosPixel()))
285 mpView->GetSdrPageView()->DeleteHelpLine(nHelpLine);
286
287 mpWindow->ReleaseMouse();
288 }
289
290 if (mpView
3.1
Field 'mpView' is null
)
4
Taking false branch
291 {
292 FrameView* pFrameView = mpViewShell->GetFrameView();
293 mpView->SetOrtho( pFrameView->IsOrtho() );
294 mpView->SetAngleSnapEnabled( pFrameView->IsAngleSnapEnabled() );
295 mpView->SetSnapEnabled(true);
296 mpView->SetCreate1stPointAsCenter(false);
297 mpView->SetResizeAtCenter(false);
298 mpView->SetDragWithCopy(pFrameView->IsDragWithCopy());
299 mpView->SetGridSnap(pFrameView->IsGridSnap());
300 mpView->SetBordSnap(pFrameView->IsBordSnap());
301 mpView->SetHlplSnap(pFrameView->IsHlplSnap());
302 mpView->SetOFrmSnap(pFrameView->IsOFrmSnap());
303 mpView->SetOPntSnap(pFrameView->IsOPntSnap());
304 mpView->SetOConSnap(pFrameView->IsOConSnap());
305 }
306
307 bIsInDragMode = false;
308 ForcePointer(&rMEvt);
5
Calling 'FuDraw::ForcePointer'
309 FuPoor::MouseButtonUp(rMEvt);
310
311 return false;
312}
313
314/**
315 * Process keyboard input
316 * @returns sal_True if a KeyEvent is being processed, sal_False otherwise
317 */
318bool FuDraw::KeyInput(const KeyEvent& rKEvt)
319{
320 bool bReturn = false;
321
322 switch ( rKEvt.GetKeyCode().GetCode() )
323 {
324 case KEY_ESCAPE:
325 {
326 bReturn = FuDraw::cancel();
327 }
328 break;
329
330 case KEY_DELETE:
331 case KEY_BACKSPACE:
332 {
333 if (!mpDocSh->IsReadOnly())
334 {
335 if (mpView->IsPresObjSelected(false, true, false, true))
336 {
337 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(mpWindow->GetFrameWeld(),
338 VclMessageType::Info, VclButtonsType::Ok,
339 SdResId(STR_ACTION_NOTPOSSIBLEreinterpret_cast<char const *>("STR_ACTION_NOTPOSSIBLE"
"\004" u8"This function cannot be run \nwith the selected objects."
)
)));
340 xInfoBox->run();
341 }
342 else
343 {
344 // wait-mousepointer while deleting object
345 weld::WaitObject aWait(mpViewShell->GetFrameWeld());
346 // delete object
347 mpView->DeleteMarked();
348 }
349 }
350 bReturn = true;
351 }
352 break;
353
354 case KEY_TAB:
355 {
356 vcl::KeyCode aCode = rKEvt.GetKeyCode();
357
358 if ( !aCode.IsMod1() && !aCode.IsMod2() )
359 {
360 // Moved next line which was a bugfix itself into
361 // the scope which really does the object selection travel
362 // and thus is allowed to call SelectionHasChanged().
363
364 // Switch to FuSelect.
365 mpViewShell->GetViewFrame()->GetDispatcher()->Execute(
366 SID_OBJECT_SELECT( 10000 + 128 ),
367 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
368
369 // changeover to the next object
370 if(!mpView->MarkNextObj( !aCode.IsShift() ))
371 {
372 //If there is only one object, don't do the UnmarkAllObj() & MarkNextObj().
373 if ( mpView->HasMultipleMarkableObjects() && mpView->AreObjectsMarked() )
374 {
375 // No next object: go over open end and get first from
376 // the other side
377 mpView->UnmarkAllObj();
378 mpView->MarkNextObj(!aCode.IsShift());
379 }
380 }
381
382 if(mpView->AreObjectsMarked())
383 mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
384
385 bReturn = true;
386 }
387 }
388 break;
389
390 case KEY_END:
391 {
392 vcl::KeyCode aCode = rKEvt.GetKeyCode();
393
394 if ( aCode.IsMod1() )
395 {
396 // mark last object
397 mpView->UnmarkAllObj();
398 mpView->MarkNextObj();
399
400 if(mpView->AreObjectsMarked())
401 mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
402
403 bReturn = true;
404 }
405 }
406 break;
407
408 case KEY_HOME:
409 {
410 vcl::KeyCode aCode = rKEvt.GetKeyCode();
411
412 if ( aCode.IsMod1() )
413 {
414 // mark first object
415 mpView->UnmarkAllObj();
416 mpView->MarkNextObj(true);
417
418 if(mpView->AreObjectsMarked())
419 mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
420
421 bReturn = true;
422 }
423 }
424 break;
425
426 default:
427 break;
428 }
429
430 if (!bReturn)
431 {
432 bReturn = FuPoor::KeyInput(rKEvt);
433 }
434 else
435 {
436 mpWindow->ReleaseMouse();
437 }
438
439 return bReturn;
440}
441
442void FuDraw::Activate()
443{
444 FuPoor::Activate();
445 ForcePointer();
446}
447
448/**
449 * Toggle mouse-pointer
450 */
451void FuDraw::ForcePointer(const MouseEvent* pMEvt)
452{
453 Point aPnt;
454 sal_uInt16 nModifier = 0;
455 bool bLeftDown = false;
456 bool bDefPointer = true;
457
458 if (pMEvt
5.1
'pMEvt' is non-null
)
6
Taking true branch
459 {
460 aPnt = mpWindow->PixelToLogic(pMEvt->GetPosPixel());
461 nModifier = pMEvt->GetModifier();
462 bLeftDown = pMEvt->IsLeft();
463 }
464 else
465 {
466 aPnt = mpWindow->PixelToLogic(mpWindow->GetPointerPosPixel());
467 }
468
469 if (mpView->IsDragObj())
7
Called C++ object pointer is null
470 {
471 if (SD_MOD()( static_cast<SdModule*>(SfxApplication::GetModule(SfxToolsModule
::Draw)) )
->GetWaterCan() && !mpView->PickHandle(aPnt))
472 {
473 // water can mode
474 bDefPointer = false;
475 mpWindow->SetPointer(PointerStyle::Fill);
476 }
477 }
478 else
479 {
480 SdrHdl* pHdl = mpView->PickHandle(aPnt);
481
482 if (SD_MOD()( static_cast<SdModule*>(SfxApplication::GetModule(SfxToolsModule
::Draw)) )
->GetWaterCan() && !pHdl)
483 {
484 // water can mode
485 bDefPointer = false;
486 mpWindow->SetPointer(PointerStyle::Fill);
487 }
488 else if (!pHdl &&
489 mpViewShell->GetViewFrame()->HasChildWindow(SvxBmpMaskChildWindow::GetChildWindowId()))
490 {
491 // pipette mode
492 SfxChildWindow* pWnd = mpViewShell->GetViewFrame()->GetChildWindow(SvxBmpMaskChildWindow::GetChildWindowId());
493 SvxBmpMask* pMask = pWnd ? static_cast<SvxBmpMask*>(pWnd->GetWindow()) : nullptr;
494 if (pMask && pMask->IsEyedropping())
495 {
496 bDefPointer = false;
497 mpWindow->SetPointer(PointerStyle::RefHand);
498 }
499 }
500 else if (!mpView->IsAction())
501 {
502 SdrObject* pObj = nullptr;
503 SdrPageView* pPV = nullptr;
504 SdrViewEvent aVEvt;
505 SdrHitKind eHit = SdrHitKind::NONE;
506 SdrDragMode eDragMode = mpView->GetDragMode();
507
508 if (pMEvt)
509 {
510 eHit = mpView->PickAnything(*pMEvt, SdrMouseEventKind::MOVE, aVEvt);
511 }
512
513 if ((eDragMode == SdrDragMode::Rotate) && (eHit == SdrHitKind::MarkedObject))
514 {
515 // The goal of this request is show always the rotation arrow for 3D-objects at rotation mode
516 // Independent of the settings at Tools->Options->Draw "Objects always moveable"
517 // 2D-objects acquit in another way. Otherwise, the rotation of 3d-objects around any axes
518 // wouldn't be possible per default.
519 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
520 SdrObject* pObject = rMarkList.GetMark(0)->GetMarkedSdrObj();
521 if ((dynamic_cast<const E3dObject* >(pObject) != nullptr) && (rMarkList.GetMarkCount() == 1))
522 {
523 mpWindow->SetPointer(PointerStyle::Rotate);
524 bDefPointer = false; // Otherwise it'll be called Joe's routine and the mousepointer will reconfigurate again
525 }
526 }
527
528 if (eHit == SdrHitKind::NONE)
529 {
530 // found nothing -> look after at the masterpage
531 pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER);
532 }
533 else if (eHit == SdrHitKind::UnmarkedObject)
534 {
535 pObj = aVEvt.pObj;
536 }
537 else if (eHit == SdrHitKind::TextEditObj && dynamic_cast< const FuSelection *>( this ) != nullptr)
538 {
539 sal_uInt16 nSdrObjKind = aVEvt.pObj->GetObjIdentifier();
540
541 if ( nSdrObjKind != OBJ_TEXT &&
542 nSdrObjKind != OBJ_TITLETEXT &&
543 nSdrObjKind != OBJ_OUTLINETEXT &&
544 aVEvt.pObj->IsEmptyPresObj() )
545 {
546 pObj = nullptr;
547 bDefPointer = false;
548 mpWindow->SetPointer(PointerStyle::Arrow);
549 }
550 }
551
552 if (pObj && pMEvt && !pMEvt->IsMod2()
553 && dynamic_cast<const FuSelection*>(this) != nullptr)
554 {
555 // test for ImageMap
556 bDefPointer = !SetPointer(pObj, aPnt);
557
558 if (bDefPointer
559 && (dynamic_cast<const SdrObjGroup*>(pObj) != nullptr
560 || dynamic_cast<const E3dScene*>(pObj) != nullptr))
561 {
562 // take a glance into the group
563 pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV,
564 SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::DEEP);
565 if (pObj)
566 bDefPointer = !SetPointer(pObj, aPnt);
567 }
568 }
569 }
570 }
571
572 if (bDefPointer)
573 {
574 mpWindow->SetPointer(mpView->GetPreferredPointer(
575 aPnt, mpWindow, nModifier, bLeftDown));
576 }
577}
578
579/**
580 * Set cursor to pointer when in clickable area of an ImageMap
581 *
582 * @return True when pointer was set
583 */
584bool FuDraw::SetPointer(const SdrObject* pObj, const Point& rPos)
585{
586 bool bImageMapInfo = SvxIMapInfo::GetIMapInfo(pObj) != nullptr;
587
588 if (!bImageMapInfo)
589 return false;
590
591 const SdrLayerIDSet* pVisiLayer = &mpView->GetSdrPageView()->GetVisibleLayers();
592 sal_uInt16 nHitLog(sal_uInt16(mpWindow->PixelToLogic(Size(HITPIX, 0)).Width()));
593 long n2HitLog(nHitLog * 2);
594 Point aHitPosR(rPos);
595 Point aHitPosL(rPos);
596 Point aHitPosT(rPos);
597 Point aHitPosB(rPos);
598
599 aHitPosR.AdjustX(n2HitLog);
600 aHitPosL.AdjustX(-n2HitLog);
601 aHitPosT.AdjustY(n2HitLog);
602 aHitPosB.AdjustY(-n2HitLog);
603
604 if (!pObj->IsClosedObj()
605 || (SdrObjectPrimitiveHit(*pObj, aHitPosR, nHitLog, *mpView->GetSdrPageView(), pVisiLayer,
606 false)
607 && SdrObjectPrimitiveHit(*pObj, aHitPosL, nHitLog, *mpView->GetSdrPageView(),
608 pVisiLayer, false)
609 && SdrObjectPrimitiveHit(*pObj, aHitPosT, nHitLog, *mpView->GetSdrPageView(),
610 pVisiLayer, false)
611 && SdrObjectPrimitiveHit(*pObj, aHitPosB, nHitLog, *mpView->GetSdrPageView(),
612 pVisiLayer, false)))
613 {
614 // hit inside the object (without margin) or open object
615 if (SvxIMapInfo::GetHitIMapObject(pObj, rPos))
616 {
617 mpWindow->SetPointer(PointerStyle::RefHand);
618 return true;
619 }
620 }
621
622 return false;
623}
624
625/**
626 * Response of doubleclick
627 */
628void FuDraw::DoubleClick(const MouseEvent& rMEvt)
629{
630 sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() );
631
632 if ( mpView->AreObjectsMarked() )
633 {
634 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
635
636 if (rMarkList.GetMarkCount() == 1)
637 {
638 SdrMark* pMark = rMarkList.GetMark(0);
639 SdrObject* pObj = pMark->GetMarkedSdrObj();
640
641 SdrInventor nInv = pObj->GetObjInventor();
642 sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier();
643
644 if (nInv == SdrInventor::Default && nSdrObjKind == OBJ_OLE2)
645 {
646 // activate OLE-object
647 SfxInt16Item aItem(SID_OBJECT(5000 + 575), 0);
648 mpViewShell->GetViewFrame()->
649 GetDispatcher()->ExecuteList(SID_OBJECT(5000 + 575),
650 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
651 { &aItem });
652 }
653 else if (nInv == SdrInventor::Default && nSdrObjKind == OBJ_GRAF && pObj->IsEmptyPresObj() )
654 {
655 mpViewShell->GetViewFrame()->
656 GetDispatcher()->Execute( SID_INSERT_GRAPHICTypedWhichId<SfxStringItem>( 10000 + 241 ),
657 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
658 }
659 else if ( ( dynamic_cast< const SdrTextObj *>( pObj ) != nullptr || dynamic_cast< const SdrObjGroup *>( pObj ) != nullptr ) &&
660 !SD_MOD()( static_cast<SdModule*>(SfxApplication::GetModule(SfxToolsModule
::Draw)) )
->GetWaterCan() &&
661 mpViewShell->GetFrameView()->IsDoubleClickTextEdit() &&
662 !mpDocSh->IsReadOnly())
663 {
664 SfxUInt16Item aItem(SID_TEXTEDIT(27000 +76), 2);
665 mpViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(
666 SID_TEXTEDIT(27000 +76),
667 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
668 { &aItem });
669 }
670 else if (nInv == SdrInventor::Default && nSdrObjKind == OBJ_GRUP)
671 {
672 // hit group -> select subobject
673 mpView->UnMarkAll();
674 mpView->MarkObj(aMDPos, nHitLog, rMEvt.IsShift(), true);
675 }
676 }
677 }
678 else
679 mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT( 10000 + 128 ), SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
680}
681
682bool FuDraw::RequestHelp(const HelpEvent& rHEvt)
683{
684 bool bReturn = false;
685
686 if (Help::IsBalloonHelpEnabled() || Help::IsQuickHelpEnabled())
687 {
688 SdrViewEvent aVEvt;
689
690 MouseEvent aMEvt(mpWindow->GetPointerPosPixel(), 1, MouseEventModifiers::NONE, MOUSE_LEFT(sal_uInt16(0x0001)));
691
692 SdrHitKind eHit = mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
693
694 SdrObject* pObj = aVEvt.pObj;
695
696 if (eHit != SdrHitKind::NONE && pObj != nullptr)
697 {
698 Point aPosPixel = rHEvt.GetMousePosPixel();
699
700 bReturn = SetHelpText(pObj, aPosPixel, aVEvt);
701
702 if (!bReturn && (dynamic_cast< const SdrObjGroup *>( pObj ) != nullptr || dynamic_cast< const E3dScene* >(pObj) != nullptr))
703 {
704 // take a glance into the group
705 SdrPageView* pPV = nullptr;
706
707 Point aPos(mpWindow->PixelToLogic(mpWindow->ScreenToOutputPixel(aPosPixel)));
708
709 pObj = mpView->PickObj(aPos, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::DEEP);
710 if (pObj)
711 bReturn = SetHelpText(pObj, aPosPixel, aVEvt);
712 }
713 }
714 }
715
716 if (!bReturn)
717 {
718 bReturn = FuPoor::RequestHelp(rHEvt);
719 }
720
721 if (!bReturn)
722 bReturn = mpView->RequestHelp(rHEvt);
723
724 return bReturn;
725}
726
727bool FuDraw::SetHelpText(const SdrObject* pObj, const Point& rPosPixel, const SdrViewEvent& rVEvt)
728{
729 OUString aHelpText;
730 Point aPos(mpWindow->PixelToLogic(mpWindow->ScreenToOutputPixel(rPosPixel)));
731 IMapObject* pIMapObj = SvxIMapInfo::GetHitIMapObject(pObj, aPos);
732
733 if (!rVEvt.pURLField && !pIMapObj)
734 return false;
735
736 OUString aURL;
737 if (rVEvt.pURLField)
738 aURL = INetURLObject::decode(rVEvt.pURLField->GetURL(),
739 INetURLObject::DecodeMechanism::WithCharset);
740 else if (pIMapObj)
741 {
742 aURL = pIMapObj->GetAltText() +
743 " (" +
744 INetURLObject::decode(pIMapObj->GetURL(),
745 INetURLObject::DecodeMechanism::WithCharset) +
746 ")";
747 }
748 else
749 return false;
750
751 aHelpText = SfxHelp::GetURLHelpText(aURL);
752
753 if (aHelpText.isEmpty())
754 return false;
755
756 ::tools::Rectangle aLogicPix = mpWindow->LogicToPixel(pObj->GetLogicRect());
757 ::tools::Rectangle aScreenRect(mpWindow->OutputToScreenPixel(aLogicPix.TopLeft()),
758 mpWindow->OutputToScreenPixel(aLogicPix.BottomRight()));
759
760 if (Help::IsBalloonHelpEnabled())
761 Help::ShowBalloon( static_cast<vcl::Window*>(mpWindow), rPosPixel, aScreenRect, aHelpText);
762 else if (Help::IsQuickHelpEnabled())
763 Help::ShowQuickHelp( static_cast<vcl::Window*>(mpWindow), aScreenRect, aHelpText);
764
765 return true;
766}
767
768/** is called when the current function should be aborted. <p>
769 This is used when a function gets a KEY_ESCAPE but can also
770 be called directly.
771
772 @returns true if an active function was aborted
773*/
774bool FuDraw::cancel()
775{
776 bool bReturn = false;
777
778 if ( mpView->IsAction() )
779 {
780 mpView->BrkAction();
781 bReturn = true;
782 }
783 else if ( mpView->IsTextEdit() )
784 {
785 mpView->SdrEndTextEdit();
786 bReturn = true;
787
788 SfxBindings& rBindings = mpViewShell->GetViewFrame()->GetBindings();
789 rBindings.Invalidate( SID_DEC_INDENT( 10000 + 461 ) );
790 rBindings.Invalidate( SID_INC_INDENT( 10000 + 462 ) );
791 rBindings.Invalidate( SID_PARASPACE_INCREASE( 10000 + 1145 ) );
792 rBindings.Invalidate( SID_PARASPACE_DECREASE( 10000 + 1146 ) );
793 }
794 else if ( mpView->AreObjectsMarked() )
795 {
796 const SdrHdlList& rHdlList = mpView->GetHdlList();
797 SdrHdl* pHdl = rHdlList.GetFocusHdl();
798
799 if(pHdl)
800 {
801 const_cast<SdrHdlList&>(rHdlList).ResetFocusHdl();
802 }
803 else
804 {
805 mpView->UnmarkAll();
806 }
807
808 // Switch to FuSelect.
809 mpViewShell->GetViewFrame()->GetDispatcher()->Execute(
810 SID_OBJECT_SELECT( 10000 + 128 ),
811 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
812
813 bReturn = true;
814 }
815
816 return bReturn;
817}
818
819} // end of namespace sd
820
821/* vim:set shiftwidth=4 softtabstop=4 expandtab: */