Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

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 edtwin.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/uibase/docvw/edtwin.cxx

/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.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 <swtypes.hxx>
21#include <hintids.hxx>
22#include <com/sun/star/accessibility/XAccessible.hpp>
23#include <comphelper/string.hxx>
24#include <com/sun/star/i18n/XBreakIterator.hpp>
25#include <com/sun/star/i18n/ScriptType.hpp>
26#include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
27#include <com/sun/star/i18n/XExtendedInputSequenceChecker.hpp>
28
29#include <com/sun/star/i18n/UnicodeScript.hpp>
30#include <com/sun/star/i18n/CalendarFieldIndex.hpp>
31#include <com/sun/star/ui/ContextMenuExecuteEvent.hpp>
32
33#include <vcl/inputctx.hxx>
34#include <vcl/help.hxx>
35#include <vcl/weld.hxx>
36#include <vcl/ptrstyle.hxx>
37#include <svl/macitem.hxx>
38#include <unotools/securityoptions.hxx>
39#include <basic/sbxvar.hxx>
40#include <svl/ctloptions.hxx>
41#include <basic/sbx.hxx>
42#include <svl/eitem.hxx>
43#include <svl/stritem.hxx>
44#include <sfx2/ipclient.hxx>
45#include <sfx2/viewfrm.hxx>
46#include <sfx2/request.hxx>
47#include <sfx2/bindings.hxx>
48#include <sfx2/dispatch.hxx>
49#include <svl/ptitem.hxx>
50#include <editeng/sizeitem.hxx>
51#include <editeng/langitem.hxx>
52#include <svx/svdview.hxx>
53#include <svx/svdhdl.hxx>
54#include <svx/svdoutl.hxx>
55#include <editeng/editeng.hxx>
56#include <editeng/editview.hxx>
57#include <editeng/svxacorr.hxx>
58#include <editeng/flditem.hxx>
59#include <editeng/colritem.hxx>
60#include <unotools/charclass.hxx>
61#include <unotools/datetime.hxx>
62
63#include <comphelper/lok.hxx>
64#include <sfx2/lokhelper.hxx>
65
66#include <editeng/acorrcfg.hxx>
67#include <SwSmartTagMgr.hxx>
68#include <edtdd.hxx>
69#include <edtwin.hxx>
70#include <view.hxx>
71#include <wrtsh.hxx>
72#include <IDocumentDrawModelAccess.hxx>
73#include <IDocumentUndoRedo.hxx>
74#include <textboxhelper.hxx>
75#include <dcontact.hxx>
76#include <fldbas.hxx>
77#include <swmodule.hxx>
78#include <docsh.hxx>
79#include <viewopt.hxx>
80#include <drawbase.hxx>
81#include <dselect.hxx>
82#include <textsh.hxx>
83#include <shdwcrsr.hxx>
84#include <txatbase.hxx>
85#include <fmtanchr.hxx>
86#include <fmtornt.hxx>
87#include <fmthdft.hxx>
88#include <frmfmt.hxx>
89#include <modcfg.hxx>
90#include <fmtcol.hxx>
91#include <wview.hxx>
92#include <gloslst.hxx>
93#include <inputwin.hxx>
94#include <gloshdl.hxx>
95#include <swundo.hxx>
96#include <drwtxtsh.hxx>
97#include <fchrfmt.hxx>
98#include "romenu.hxx"
99#include <initui.hxx>
100#include <frmatr.hxx>
101#include <extinput.hxx>
102#include <acmplwrd.hxx>
103#include <swcalwrp.hxx>
104#include <swdtflvr.hxx>
105#include <breakit.hxx>
106#include <checkit.hxx>
107#include <pagefrm.hxx>
108
109#include <helpids.h>
110#include <cmdid.h>
111#include <uitool.hxx>
112#include <fmtfollowtextflow.hxx>
113#include <toolkit/helper/vclunohelper.hxx>
114#include <charfmt.hxx>
115#include <numrule.hxx>
116#include <pagedesc.hxx>
117#include <svtools/ruler.hxx>
118#include <formatclipboard.hxx>
119#include <vcl/svapp.hxx>
120#include <wordcountdialog.hxx>
121#include <fmtfld.hxx>
122
123#include <IMark.hxx>
124#include <doc.hxx>
125#include <xmloff/odffields.hxx>
126
127#include <PostItMgr.hxx>
128#include <FrameControlsManager.hxx>
129#include <AnnotationWin.hxx>
130
131#include <algorithm>
132#include <vector>
133
134#include <rootfrm.hxx>
135
136#include <unotools/syslocaleoptions.hxx>
137#include <i18nlangtag/mslangid.hxx>
138#include <salhelper/singletonref.hxx>
139#include <sfx2/event.hxx>
140#include <memory>
141
142#include <IDocumentOutlineNodes.hxx>
143#include <ndtxt.hxx>
144#include <cntfrm.hxx>
145#include <txtfrm.hxx>
146#include <strings.hrc>
147
148using namespace sw::mark;
149using namespace ::com::sun::star;
150
151/**
152 * Globals
153 */
154static bool g_bInputLanguageSwitched = false;
155
156// Usually in MouseButtonUp a selection is revoked when the selection is
157// not currently being pulled open. Unfortunately in MouseButtonDown there
158// is being selected at double/triple click. That selection is completely
159// finished in the Handler and thus can't be distinguished in the Up.
160// To resolve this g_bHoldSelection is set in Down and evaluated in Up.
161static bool g_bHoldSelection = false;
162
163bool g_bFrameDrag = false;
164static bool g_bValidCursorPos = false;
165static bool g_bModePushed = false;
166bool g_bDDTimerStarted = false;
167bool g_bFlushCharBuffer = false;
168bool g_bDDINetAttr = false;
169static SdrHdlKind g_eSdrMoveHdl = SdrHdlKind::User;
170
171QuickHelpData* SwEditWin::m_pQuickHlpData = nullptr;
172
173long SwEditWin::m_nDDStartPosY = 0;
174long SwEditWin::m_nDDStartPosX = 0;
175
176static SfxShell* lcl_GetTextShellFromDispatcher( SwView const & rView );
177
178/// Check if the selected shape has a TextBox: if so, go into that instead.
179static bool lcl_goIntoTextBox(SwEditWin& rEditWin, SwWrtShell& rSh)
180{
181 SdrMark* pMark = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0);
182 if (!pMark)
183 return false;
184
185 SdrObject* pSdrObject = pMark->GetMarkedSdrObj();
186 SwFrameFormat* pObjectFormat = ::FindFrameFormat(pSdrObject);
187 if (SwFrameFormat* pTextBoxFormat = SwTextBoxHelper::getOtherTextBoxFormat(pObjectFormat, RES_DRAWFRMFMT))
188 {
189 SdrObject* pTextBox = pTextBoxFormat->FindRealSdrObject();
190 SdrView* pSdrView = rSh.GetDrawView();
191 // Unmark the shape.
192 pSdrView->UnmarkAllObj();
193 // Mark the textbox.
194 rSh.SelectObj(Point(), SW_ALLOW_TEXTBOX8, pTextBox);
195 // Clear the DrawFuncPtr.
196 rEditWin.StopInsFrame();
197 return true;
198 }
199 return false;
200}
201
202class SwAnchorMarker
203{
204 SdrHdl* pHdl;
205 Point aHdlPos;
206 Point aLastPos;
207 bool bTopRightHandle;
208public:
209 explicit SwAnchorMarker( SdrHdl* pH )
210 : pHdl( pH )
211 , aHdlPos( pH->GetPos() )
212 , aLastPos( pH->GetPos() )
213 , bTopRightHandle( pH->GetKind() == SdrHdlKind::Anchor_TR )
214 {}
215 const Point& GetLastPos() const { return aLastPos; }
216 void SetLastPos( const Point& rNew ) { aLastPos = rNew; }
217 void SetPos( const Point& rNew ) { pHdl->SetPos( rNew ); }
218 const Point& GetHdlPos() const { return aHdlPos; }
219 SdrHdl* GetHdl() const { return pHdl; }
220 void ChgHdl( SdrHdl* pNew )
221 {
222 pHdl = pNew;
223 if ( pHdl )
224 {
225 bTopRightHandle = (pHdl->GetKind() == SdrHdlKind::Anchor_TR);
226 }
227 }
228 Point GetPosForHitTest( const OutputDevice& rOut )
229 {
230 Point aHitTestPos( pHdl->GetPos() );
231 aHitTestPos = rOut.LogicToPixel( aHitTestPos );
232 if ( bTopRightHandle )
233 {
234 aHitTestPos += Point( -1, 1 );
235 }
236 else
237 {
238 aHitTestPos += Point( 1, 1 );
239 }
240 aHitTestPos = rOut.PixelToLogic( aHitTestPos );
241
242 return aHitTestPos;
243 }
244};
245
246/// Assists with auto-completion of AutoComplete words and AutoText names.
247struct QuickHelpData
248{
249 /// Strings that at least partially match an input word, and match length.
250 std::vector<std::pair<OUString, sal_uInt16>> m_aHelpStrings;
251 /// Index of the current help string.
252 sal_uInt16 nCurArrPos;
253 static constexpr sal_uInt16 nNoPos = std::numeric_limits<sal_uInt16>::max();
254
255 /// Help data stores AutoText names rather than AutoComplete words.
256 bool m_bIsAutoText;
257 /// Display help string as a tip rather than inline.
258 bool m_bIsTip;
259 /// Tip ID when a help string is displayed as a tip.
260 void* nTipId;
261 /// Append a space character to the displayed help string (if appropriate).
262 bool m_bAppendSpace;
263
264 /// Help string is currently displayed.
265 bool m_bIsDisplayed;
266
267 QuickHelpData() { ClearContent(); }
268
269 void Move( QuickHelpData& rCpy );
270 void ClearContent();
271 void Start(SwWrtShell& rSh, bool bRestart);
272 void Stop( SwWrtShell& rSh );
273
274 bool HasContent() const { return !m_aHelpStrings.empty() && nCurArrPos != nNoPos; }
275 const OUString& CurStr() const { return m_aHelpStrings[nCurArrPos].first; }
276 sal_uInt16 CurLen() const { return m_aHelpStrings[nCurArrPos].second; }
277
278 /// Next help string.
279 void Next( bool bEndLess )
280 {
281 if( ++nCurArrPos >= m_aHelpStrings.size() )
282 nCurArrPos = (bEndLess && !m_bIsAutoText ) ? 0 : nCurArrPos-1;
283 }
284 /// Previous help string.
285 void Previous( bool bEndLess )
286 {
287 if( 0 == nCurArrPos-- )
288 nCurArrPos = (bEndLess && !m_bIsAutoText ) ? m_aHelpStrings.size()-1 : 0;
289 }
290
291 // Fills internal structures with hopefully helpful information.
292 void FillStrArr( SwWrtShell const & rSh, const OUString& rWord );
293 void SortAndFilter(const OUString &rOrigWord);
294};
295
296/**
297 * Avoid minimal movement shiver
298 */
299#define HIT_PIX2 2 /* hit tolerance in pixel */
300#define MIN_MOVE4 4
301
302static bool IsMinMove(const Point &rStartPos, const Point &rLPt)
303{
304 return std::abs(rStartPos.X() - rLPt.X()) > MIN_MOVE4 ||
305 std::abs(rStartPos.Y() - rLPt.Y()) > MIN_MOVE4;
306}
307
308/**
309 * For MouseButtonDown - determine whether a DrawObject
310 * a NO SwgFrame was hit! Shift/Ctrl should only result
311 * in selecting, with DrawObjects; at SwgFlys to trigger
312 * hyperlinks if applicable (Download/NewWindow!)
313 */
314static bool IsDrawObjSelectable( const SwWrtShell& rSh, const Point& rPt )
315{
316 bool bRet = true;
317 SdrObject* pObj;
318 switch( rSh.GetObjCntType( rPt, pObj ))
319 {
320 case OBJCNT_NONE:
321 case OBJCNT_FLY:
322 case OBJCNT_GRF:
323 case OBJCNT_OLE:
324 bRet = false;
325 break;
326 default:; //prevent warning
327 }
328 return bRet;
329}
330
331/*
332 * Switch pointer
333 */
334void SwEditWin::UpdatePointer(const Point &rLPt, sal_uInt16 nModifier )
335{
336 SetQuickHelpText(OUString());
337 SwWrtShell &rSh = m_rView.GetWrtShell();
338 if( m_pApplyTempl )
339 {
340 PointerStyle eStyle = PointerStyle::Fill;
341 if ( rSh.IsOverReadOnlyPos( rLPt ) )
342 {
343 m_pUserMarker.reset();
344
345 eStyle = PointerStyle::NotAllowed;
346 }
347 else
348 {
349 SwRect aRect;
350 SwRect* pRect = &aRect;
351 const SwFrameFormat* pFormat = nullptr;
352
353 bool bFrameIsValidTarget = false;
354 if( m_pApplyTempl->m_pFormatClipboard )
355 bFrameIsValidTarget = m_pApplyTempl->m_pFormatClipboard->HasContentForThisType( SelectionType::Frame );
356 else if( !m_pApplyTempl->nColor )
357 bFrameIsValidTarget = ( m_pApplyTempl->eType == SfxStyleFamily::Frame );
358
359 if( bFrameIsValidTarget &&
360 nullptr !=(pFormat = rSh.GetFormatFromObj( rLPt, &pRect )) &&
361 dynamic_cast<const SwFlyFrameFormat*>( pFormat) )
362 {
363 //turn on highlight for frame
364 tools::Rectangle aTmp( pRect->SVRect() );
365
366 if ( !m_pUserMarker )
367 {
368 m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp ));
369 }
370 }
371 else
372 {
373 m_pUserMarker.reset();
374 }
375
376 rSh.SwCursorShell::SetVisibleCursor( rLPt );
377 }
378 SetPointer( eStyle );
379 return;
380 }
381
382 if( !rSh.VisArea().Width() )
383 return;
384
385 CurrShell aCurr(&rSh);
386
387 if ( IsChainMode() )
388 {
389 SwRect aRect;
390 SwChainRet nChainable = rSh.Chainable( aRect, *rSh.GetFlyFrameFormat(), rLPt );
391 PointerStyle eStyle = nChainable != SwChainRet::OK
392 ? PointerStyle::ChainNotAllowed : PointerStyle::Chain;
393 if ( nChainable == SwChainRet::OK )
394 {
395 tools::Rectangle aTmp( aRect.SVRect() );
396
397 if ( !m_pUserMarker )
398 {
399 m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp ));
400 }
401 }
402 else
403 {
404 m_pUserMarker.reset();
405 }
406
407 SetPointer( eStyle );
408 return;
409 }
410
411 bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
412 if ( !bExecHyperlinks )
413 {
414 SvtSecurityOptions aSecOpts;
415 const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
416 if ( ( bSecureOption && nModifier == KEY_MOD1 ) ||
417 ( !bSecureOption && nModifier != KEY_MOD1 ) )
418 bExecHyperlinks = true;
419 }
420
421 const bool bExecSmarttags = nModifier == KEY_MOD1;
422
423 SdrView *pSdrView = rSh.GetDrawView();
424 bool bPrefSdrPointer = false;
425 bool bHitHandle = false;
426 bool bCntAtPos = false;
427 bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
428 rSh.IsCursorReadonly();
429 m_aActHitType = SdrHitKind::NONE;
430 PointerStyle eStyle = PointerStyle::Text;
431 if ( !pSdrView )
432 bCntAtPos = true;
433 else if ( (bHitHandle = (pSdrView->PickHandle(rLPt) != nullptr)) )
434 {
435 m_aActHitType = SdrHitKind::Object;
436 bPrefSdrPointer = true;
437 }
438 else
439 {
440 const bool bNotInSelObj = !rSh.IsInsideSelectedObj( rLPt );
441 if ( m_rView.GetDrawFuncPtr() && !m_bInsDraw && bNotInSelObj )
442 {
443 m_aActHitType = SdrHitKind::Object;
444 if (IsObjectSelect())
445 eStyle = PointerStyle::Arrow;
446 else
447 bPrefSdrPointer = true;
448 }
449 else
450 {
451 SdrPageView* pPV = nullptr;
452 pSdrView->SetHitTolerancePixel( HIT_PIX2 );
453 SdrObject* pObj = (bNotInSelObj && bExecHyperlinks) ?
454 pSdrView->PickObj(rLPt, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO) :
455 nullptr;
456 if (pObj)
457 {
458 SdrObjMacroHitRec aTmp;
459 aTmp.aPos = rLPt;
460 aTmp.pPageView = pPV;
461 SetPointer( pObj->GetMacroPointer( aTmp ) );
462 return;
463 }
464 else
465 {
466 // dvo: IsObjSelectable() eventually calls SdrView::PickObj, so
467 // apparently this is used to determine whether this is a
468 // drawling layer object or not.
469 if ( rSh.IsObjSelectable( rLPt ) )
470 {
471 if (pSdrView->IsTextEdit())
472 {
473 m_aActHitType = SdrHitKind::NONE;
474 bPrefSdrPointer = true;
475 }
476 else
477 {
478 SdrViewEvent aVEvt;
479 SdrHitKind eHit = pSdrView->PickAnything(rLPt, aVEvt);
480
481 if (eHit == SdrHitKind::UrlField && bExecHyperlinks)
482 {
483 m_aActHitType = SdrHitKind::Object;
484 bPrefSdrPointer = true;
485 }
486 else
487 {
488 // if we're over a selected object, we show an
489 // ARROW by default. We only show a MOVE if 1) the
490 // object is selected, and 2) it may be moved
491 // (i.e., position is not protected).
492 bool bMovable =
493 (!bNotInSelObj) &&
494 (rSh.IsObjSelected() || rSh.IsFrameSelected()) &&
495 (rSh.IsSelObjProtected(FlyProtectFlags::Pos) == FlyProtectFlags::NONE);
496
497 SdrObject* pSelectableObj = rSh.GetObjAt(rLPt);
498 // Don't update pointer if this is a background image only.
499 if (pSelectableObj->GetLayer() != rSh.GetDoc()->getIDocumentDrawModelAccess().GetHellId())
500 eStyle = bMovable ? PointerStyle::Move : PointerStyle::Arrow;
501 m_aActHitType = SdrHitKind::Object;
502 }
503 }
504 }
505 else
506 {
507 if ( rSh.IsFrameSelected() && !bNotInSelObj )
508 {
509 // dvo: this branch appears to be dead and should be
510 // removed in a future version. Reason: The condition
511 // !bNotInSelObj means that this branch will only be
512 // executed in the cursor points inside a selected
513 // object. However, if this is the case, the previous
514 // if( rSh.IsObjSelectable(rLPt) ) must always be true:
515 // rLPt is inside a selected object, then obviously
516 // rLPt is over a selectable object.
517 if (rSh.IsSelObjProtected(FlyProtectFlags::Size) != FlyProtectFlags::NONE)
518 eStyle = PointerStyle::NotAllowed;
519 else
520 eStyle = PointerStyle::Move;
521 m_aActHitType = SdrHitKind::Object;
522 }
523 else
524 {
525 if ( m_rView.GetDrawFuncPtr() )
526 bPrefSdrPointer = true;
527 else
528 bCntAtPos = true;
529 }
530 }
531 }
532 }
533 }
534 if ( bPrefSdrPointer )
535 {
536 if (bIsDocReadOnly || (rSh.IsObjSelected() && rSh.IsSelObjProtected(FlyProtectFlags::Content) != FlyProtectFlags::NONE))
537 SetPointer( PointerStyle::NotAllowed );
538 else
539 {
540 if (m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->IsInsertForm() && !bHitHandle)
541 SetPointer( PointerStyle::DrawRect );
542 else
543 SetPointer( pSdrView->GetPreferredPointer( rLPt, rSh.GetOut() ) );
544 }
545 }
546 else
547 {
548 if( !rSh.IsPageAtPos( rLPt ) || m_pAnchorMarker )
549 eStyle = PointerStyle::Arrow;
550 else
551 {
552 // Even if we already have something, prefer URLs if possible.
553 SwContentAtPos aUrlPos(IsAttrAtPos::InetAttr);
554 if (bCntAtPos || rSh.GetContentAtPos(rLPt, aUrlPos))
555 {
556 SwContentAtPos aSwContentAtPos(
557 IsAttrAtPos::Field |
558 IsAttrAtPos::ClickField |
559 IsAttrAtPos::InetAttr |
560 IsAttrAtPos::Ftn |
561 IsAttrAtPos::SmartTag |
562 IsAttrAtPos::Outline);
563 if( rSh.GetContentAtPos( rLPt, aSwContentAtPos) )
564 {
565 if (IsAttrAtPos::Outline == aSwContentAtPos.eContentAtPos)
566 {
567 if (nModifier == KEY_MOD1
568 && GetView().GetWrtShell().GetViewOptions()->IsShowOutlineContentVisibilityButton())
569 {
570 eStyle = PointerStyle::RefHand;
571 // set quick help
572 if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode())
573 {
574 const SwNodes& rNds = GetView().GetWrtShell().GetDoc()->GetNodes();
575 SwOutlineNodes::size_type nPos;
576 rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), &nPos);
577 SwOutlineNodes::size_type nOutlineNodesCount
578 = rSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount();
579 int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos);
580 OUString sQuickHelp(SwResId(STR_ClICK_OUTLINE_CONTENT_TOGGLE_VISIBILITYreinterpret_cast<char const *>("STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY"
"\004" u8"Click to Toggle Outline Content Visibility")
));
581 if (nPos + 1 < nOutlineNodesCount
582 && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos + 1) > nLevel)
583 sQuickHelp += " (" + SwResId(STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXTreinterpret_cast<char const *>("STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT"
"\004" u8"right-click to include sub levels")
) + ")";
584 SetQuickHelpText(sQuickHelp);
585 }
586 }
587 }
588 // Is edit inline input field
589 else if (IsAttrAtPos::Field == aSwContentAtPos.eContentAtPos
590 && aSwContentAtPos.pFndTextAttr != nullptr
591 && aSwContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD)
592 {
593 const SwField *pCursorField = rSh.CursorInsideInputField() ? rSh.GetCurField( true ) : nullptr;
594 if (!(pCursorField && pCursorField == aSwContentAtPos.pFndTextAttr->GetFormatField().GetField()))
595 eStyle = PointerStyle::RefHand;
596 }
597 else
598 {
599 const bool bClickToFollow = IsAttrAtPos::InetAttr == aSwContentAtPos.eContentAtPos ||
600 IsAttrAtPos::SmartTag == aSwContentAtPos.eContentAtPos;
601 if( !bClickToFollow ||
602 (IsAttrAtPos::InetAttr == aSwContentAtPos.eContentAtPos && bExecHyperlinks) ||
603 (IsAttrAtPos::SmartTag == aSwContentAtPos.eContentAtPos && bExecSmarttags) )
604 eStyle = PointerStyle::RefHand;
605 }
606 }
607 }
608 }
609
610 // which kind of text pointer have we to show - horz / vert - ?
611 if( PointerStyle::Text == eStyle && rSh.IsInVerticalText( &rLPt ))
612 eStyle = PointerStyle::TextVertical;
613 else if (rSh.GetViewOptions()->CanHideWhitespace() &&
614 rSh.GetLayout()->IsBetweenPages(rLPt))
615 {
616 if (rSh.GetViewOptions()->IsHideWhitespaceMode())
617 eStyle = PointerStyle::ShowWhitespace;
618 else
619 eStyle = PointerStyle::HideWhitespace;
620 }
621
622 SetPointer( eStyle );
623 }
624}
625
626/**
627 * Increase timer for selection
628 */
629IMPL_LINK_NOARG(SwEditWin, TimerHandler, Timer *, void)void SwEditWin::LinkStubTimerHandler(void * instance, Timer *
data) { return static_cast<SwEditWin *>(instance)->
TimerHandler(data); } void SwEditWin::TimerHandler(__attribute__
((unused)) Timer *)
630{
631 SwWrtShell &rSh = m_rView.GetWrtShell();
632 Point aModPt( m_aMovePos );
633 const SwRect aOldVis( rSh.VisArea() );
634 bool bDone = false;
635
636 if ( !rSh.VisArea().IsInside( aModPt ) )
637 {
638 if ( m_bInsDraw )
639 {
640 const int nMaxScroll = 40;
641 m_rView.Scroll( tools::Rectangle(aModPt,Size(1,1)), nMaxScroll, nMaxScroll);
642 bDone = true;
643 }
644 else if ( g_bFrameDrag )
645 {
646 rSh.Drag(&aModPt, false);
647 bDone = true;
648 }
649 if ( !bDone )
650 aModPt = rSh.GetContentPos( aModPt,aModPt.Y() > rSh.VisArea().Bottom() );
651 }
652 if ( !bDone && !(g_bFrameDrag || m_bInsDraw) )
653 {
654 if ( m_xRowColumnSelectionStart )
655 {
656 Point aPos( aModPt );
657 rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag );
658 }
659 else
660 rSh.CallSetCursor( &aModPt, false );
661
662 // It can be that a "jump" over a table cannot be accomplished like
663 // that. So we jump over the table by Up/Down here.
664 const SwRect& rVisArea = rSh.VisArea();
665 if( aOldVis == rVisArea && !rSh.IsStartOfDoc() && !rSh.IsEndOfDoc() )
666 {
667 // take the center point of VisArea to
668 // decide in which direction the user want.
669 if( aModPt.Y() < ( rVisArea.Top() + rVisArea.Height() / 2 ) )
670 rSh.Up( true );
671 else
672 rSh.Down( true );
673 }
674 }
675
676 m_aMovePos += rSh.VisArea().Pos() - aOldVis.Pos();
677 JustifyAreaTimer();
678}
679
680void SwEditWin::JustifyAreaTimer()
681{
682 const tools::Rectangle &rVisArea = GetView().GetVisArea();
683#ifdef UNX1
684 const long coMinLen = 100;
685#else
686 const long coMinLen = 50;
687#endif
688 long const nTimeout = 800,
689 nDiff = std::max(
690 std::max( m_aMovePos.Y() - rVisArea.Bottom(), rVisArea.Top() - m_aMovePos.Y() ),
691 std::max( m_aMovePos.X() - rVisArea.Right(), rVisArea.Left() - m_aMovePos.X()));
692 m_aTimer.SetTimeout( std::max( coMinLen, nTimeout - nDiff*2L) );
693}
694
695void SwEditWin::LeaveArea(const Point &rPos)
696{
697 m_aMovePos = rPos;
698 JustifyAreaTimer();
699 if( !m_aTimer.IsActive() )
700 m_aTimer.Start();
701 m_pShadCursor.reset();
702}
703
704inline void SwEditWin::EnterArea()
705{
706 m_aTimer.Stop();
707}
708
709/**
710 * Insert mode for frames
711 */
712void SwEditWin::InsFrame(sal_uInt16 nCols)
713{
714 StdDrawMode( OBJ_NONE, false );
715 m_bInsFrame = true;
716 m_nInsFrameColCount = nCols;
717}
718
719void SwEditWin::StdDrawMode( SdrObjKind eSdrObjectKind, bool bObjSelect )
720{
721 SetSdrDrawMode( eSdrObjectKind );
722
723 if (bObjSelect)
724 m_rView.SetDrawFuncPtr(std::make_unique<DrawSelection>( &m_rView.GetWrtShell(), this, &m_rView ));
725 else
726 m_rView.SetDrawFuncPtr(std::make_unique<SwDrawBase>( &m_rView.GetWrtShell(), this, &m_rView ));
727
728 m_rView.SetSelDrawSlot();
729 SetSdrDrawMode( eSdrObjectKind );
730 if (bObjSelect)
731 m_rView.GetDrawFuncPtr()->Activate( SID_OBJECT_SELECT( 10000 + 128 ) );
732 else
733 m_rView.GetDrawFuncPtr()->Activate( sal::static_int_cast< sal_uInt16 >(eSdrObjectKind) );
734 m_bInsFrame = false;
735 m_nInsFrameColCount = 1;
736}
737
738void SwEditWin::StopInsFrame()
739{
740 if (m_rView.GetDrawFuncPtr())
741 {
742 m_rView.GetDrawFuncPtr()->Deactivate();
743 m_rView.SetDrawFuncPtr(nullptr);
744 }
745 m_rView.LeaveDrawCreate(); // leave construction mode
746 m_bInsFrame = false;
747 m_nInsFrameColCount = 1;
748}
749
750bool SwEditWin::IsInputSequenceCheckingRequired( const OUString &rText, const SwPaM& rCursor )
751{
752 const SvtCTLOptions& rCTLOptions = SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->GetCTLOptions();
753 if ( !rCTLOptions.IsCTLFontEnabled() ||
754 !rCTLOptions.IsCTLSequenceChecking() )
755 return false;
756
757 if ( 0 == rCursor.Start()->nContent.GetIndex() ) /* first char needs not to be checked */
758 return false;
759
760 SwBreakIt *pBreakIter = SwBreakIt::Get();
761 uno::Reference < i18n::XBreakIterator > xBI = pBreakIter->GetBreakIter();
762 assert(xBI.is())(static_cast <bool> (xBI.is()) ? void (0) : __assert_fail
("xBI.is()", "/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
, 762, __extension__ __PRETTY_FUNCTION__))
;
763 long nCTLScriptPos = -1;
764
765 if (xBI->getScriptType( rText, 0 ) == i18n::ScriptType::COMPLEX)
766 nCTLScriptPos = 0;
767 else
768 nCTLScriptPos = xBI->nextScript( rText, 0, i18n::ScriptType::COMPLEX );
769
770 return (0 <= nCTLScriptPos && nCTLScriptPos <= rText.getLength());
771}
772
773//return INVALID_HINT if language should not be explicitly overridden, the correct
774//HintId to use for the eBufferLanguage otherwise
775static sal_uInt16 lcl_isNonDefaultLanguage(LanguageType eBufferLanguage, SwView const & rView,
776 const OUString &rInBuffer)
777{
778 sal_uInt16 nWhich = INVALID_HINT;
779
780 //If the option to IgnoreLanguageChange is set, short-circuit this method
781 //which results in the document/paragraph language remaining the same
782 //despite a change to the keyboard/input language
783 SvtSysLocaleOptions aSysLocaleOptions;
784 if(aSysLocaleOptions.IsIgnoreLanguageChange())
785 {
786 return INVALID_HINT;
787 }
788
789 bool bLang = true;
790 if(eBufferLanguage != LANGUAGE_DONTKNOWLanguageType(0x03FF))
791 {
792 switch( SvtLanguageOptions::GetI18NScriptTypeOfLanguage( eBufferLanguage ))
793 {
794 case i18n::ScriptType::ASIAN: nWhich = RES_CHRATR_CJK_LANGUAGE; break;
795 case i18n::ScriptType::COMPLEX: nWhich = RES_CHRATR_CTL_LANGUAGE; break;
796 case i18n::ScriptType::LATIN: nWhich = RES_CHRATR_LANGUAGE; break;
797 default: bLang = false;
798 }
799 if(bLang)
800 {
801 SfxItemSet aLangSet(rView.GetPool(), {{nWhich, nWhich}});
802 SwWrtShell& rSh = rView.GetWrtShell();
803 rSh.GetCurAttr(aLangSet);
804 if(SfxItemState::DEFAULT <= aLangSet.GetItemState(nWhich))
805 {
806 LanguageType eLang = static_cast<const SvxLanguageItem&>(aLangSet.Get(nWhich)).GetLanguage();
807 if ( eLang == eBufferLanguage )
808 {
809 // current language attribute equal to language reported from system
810 bLang = false;
811 }
812 else if ( !g_bInputLanguageSwitched && RES_CHRATR_LANGUAGE == nWhich )
813 {
814 // special case: switching between two "LATIN" languages
815 // In case the current keyboard setting might be suitable
816 // for both languages we can't safely assume that the user
817 // wants to use the language reported from the system,
818 // except if we knew that it was explicitly switched (thus
819 // the check for "bInputLangeSwitched").
820
821 // The language reported by the system could be just the
822 // system default language that the user is not even aware
823 // of, because no language selection tool is installed at
824 // all. In this case the OOo language should get preference
825 // as it might have been selected by the user explicitly.
826
827 // Usually this case happens if the OOo language is
828 // different to the system language but the system keyboard
829 // is still suitable for the OOo language (e.g. writing
830 // English texts with a German keyboard).
831
832 // For non-latin keyboards overwriting the attribute is
833 // still valid. We do this for cyrillic and greek ATM. In
834 // future versions of OOo this should be replaced by a
835 // configuration switch that allows to give the preference
836 // to the OOo setting or the system setting explicitly
837 // and/or a better handling of the script type.
838 i18n::UnicodeScript eType = !rInBuffer.isEmpty() ?
839 GetAppCharClass().getScript( rInBuffer, 0 ) :
840 i18n::UnicodeScript_kScriptCount;
841
842 bool bSystemIsNonLatin = false;
843 switch ( eType )
844 {
845 case i18n::UnicodeScript_kGreek:
846 case i18n::UnicodeScript_kCyrillic:
847 // in case other UnicodeScripts require special
848 // keyboards they can be added here
849 bSystemIsNonLatin = true;
850 break;
851 default:
852 break;
853 }
854
855 bool bOOoLangIsNonLatin = MsLangId::isNonLatinWestern( eLang);
856
857 bLang = (bSystemIsNonLatin != bOOoLangIsNonLatin);
858 }
859 }
860 }
861 }
862 return bLang ? nWhich : INVALID_HINT;
863}
864
865/**
866 * Character buffer is inserted into the document
867 */
868void SwEditWin::FlushInBuffer()
869{
870 if ( m_aInBuffer.isEmpty() )
871 return;
872
873 SwWrtShell& rSh = m_rView.GetWrtShell();
874
875 // generate new sequence input checker if not already done
876 if ( !pCheckIt )
877 pCheckIt = new SwCheckIt;
878
879 uno::Reference < i18n::XExtendedInputSequenceChecker > xISC = pCheckIt->xCheck;
880 if ( xISC.is() && IsInputSequenceCheckingRequired( m_aInBuffer, *rSh.GetCursor() ) )
881 {
882
883 // apply (Thai) input sequence checking/correction
884
885 rSh.Push(); // push current cursor to stack
886
887 // get text from the beginning (i.e left side) of current selection
888 // to the start of the paragraph
889 rSh.NormalizePam(); // make point be the first (left) one
890 if (!rSh.GetCursor()->HasMark())
891 rSh.GetCursor()->SetMark();
892 rSh.GetCursor()->GetMark()->nContent = 0;
893
894 const OUString aOldText( rSh.GetCursor()->GetText() );
895 const sal_Int32 nOldLen = aOldText.getLength();
896
897 SvtCTLOptions& rCTLOptions = SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->GetCTLOptions();
898
899 sal_Int32 nExpandSelection = 0;
900 if (nOldLen > 0)
901 {
902 sal_Int32 nTmpPos = nOldLen;
903 sal_Int16 nCheckMode = rCTLOptions.IsCTLSequenceCheckingRestricted() ?
904 i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;
905
906 OUString aNewText( aOldText );
907 if (rCTLOptions.IsCTLSequenceCheckingTypeAndReplace())
908 {
909 for( sal_Int32 k = 0; k < m_aInBuffer.getLength(); ++k)
910 {
911 const sal_Unicode cChar = m_aInBuffer[k];
912 const sal_Int32 nPrevPos =xISC->correctInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode );
913
914 // valid sequence or sequence could be corrected:
915 if (nPrevPos != aNewText.getLength())
916 nTmpPos = nPrevPos + 1;
917 }
918
919 // find position of first character that has changed
920 sal_Int32 nNewLen = aNewText.getLength();
921 const sal_Unicode *pOldText = aOldText.getStr();
922 const sal_Unicode *pNewText = aNewText.getStr();
923 sal_Int32 nChgPos = 0;
924 while ( nChgPos < nOldLen && nChgPos < nNewLen &&
925 pOldText[nChgPos] == pNewText[nChgPos] )
926 ++nChgPos;
927
928 const sal_Int32 nChgLen = nNewLen - nChgPos;
929 if (nChgLen)
930 {
931 m_aInBuffer = aNewText.copy( nChgPos, nChgLen );
932 nExpandSelection = nOldLen - nChgPos;
933 }
934 else
935 m_aInBuffer.clear();
936 }
937 else
938 {
939 for( sal_Int32 k = 0; k < m_aInBuffer.getLength(); ++k )
940 {
941 const sal_Unicode cChar = m_aInBuffer[k];
942 if (xISC->checkInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode ))
943 {
944 // character can be inserted:
945 aNewText += OUStringChar( cChar );
946 ++nTmpPos;
947 }
948 }
949 m_aInBuffer = aNewText.copy( aOldText.getLength() ); // copy new text to be inserted to buffer
950 }
951 }
952
953 // at this point now we will insert the buffer text 'normally' some lines below...
954
955 rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
956
957 if (m_aInBuffer.isEmpty())
958 return;
959
960 // if text prior to the original selection needs to be changed
961 // as well, we now expand the selection accordingly.
962 SwPaM &rCursor = *rSh.GetCursor();
963 const sal_Int32 nCursorStartPos = rCursor.Start()->nContent.GetIndex();
964 OSL_ENSURE( nCursorStartPos >= nExpandSelection, "cannot expand selection as specified!!" )do { if (true && (!(nCursorStartPos >= nExpandSelection
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
":" "964" ": "), "%s", "cannot expand selection as specified!!"
); } } while (false)
;
965 if (nExpandSelection && nCursorStartPos >= nExpandSelection)
966 {
967 if (!rCursor.HasMark())
968 rCursor.SetMark();
969 rCursor.Start()->nContent -= nExpandSelection;
970 }
971 }
972
973 uno::Reference< frame::XDispatchRecorder > xRecorder =
974 m_rView.GetViewFrame()->GetBindings().GetRecorder();
975 if ( xRecorder.is() )
976 {
977 // determine shell
978 SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
979 // generate request and record
980 if (pSfxShell)
981 {
982 SfxRequest aReq( m_rView.GetViewFrame(), FN_INSERT_STRING((20000 + 300)+31) );
983 aReq.AppendItem( SfxStringItem( FN_INSERT_STRING((20000 + 300)+31), m_aInBuffer ) );
984 aReq.Done();
985 }
986 }
987
988 sal_uInt16 nWhich = lcl_isNonDefaultLanguage(m_eBufferLanguage, m_rView, m_aInBuffer);
989 if (nWhich != INVALID_HINT )
990 {
991 SvxLanguageItem aLangItem( m_eBufferLanguage, nWhich );
992 rSh.SetAttrItem( aLangItem );
993 }
994
995 rSh.Insert( m_aInBuffer );
996 m_eBufferLanguage = LANGUAGE_DONTKNOWLanguageType(0x03FF);
997 m_aInBuffer.clear();
998 g_bFlushCharBuffer = false;
999
1000}
1001
1002#define MOVE_LEFT_SMALL0 0
1003#define MOVE_UP_SMALL1 1
1004#define MOVE_RIGHT_BIG2 2
1005#define MOVE_DOWN_BIG3 3
1006#define MOVE_LEFT_BIG4 4
1007#define MOVE_UP_BIG5 5
1008#define MOVE_RIGHT_SMALL6 6
1009#define MOVE_DOWN_SMALL7 7
1010
1011// #i121236# Support for shift key in writer
1012#define MOVE_LEFT_HUGE8 8
1013#define MOVE_UP_HUGE9 9
1014#define MOVE_RIGHT_HUGE10 10
1015#define MOVE_DOWN_HUGE11 11
1016
1017void SwEditWin::ChangeFly( sal_uInt8 nDir, bool bWeb )
1018{
1019 SwWrtShell &rSh = m_rView.GetWrtShell();
1020 SwRect aTmp = rSh.GetFlyRect();
1021 if( !aTmp.HasArea() ||
1022 rSh.IsSelObjProtected( FlyProtectFlags::Pos ) != FlyProtectFlags::NONE )
1023 return;
1024
1025 SfxItemSet aSet(
1026 rSh.GetAttrPool(),
1027 svl::Items<
1028 RES_FRM_SIZE, RES_FRM_SIZE,
1029 RES_PROTECT, RES_PROTECT,
1030 RES_VERT_ORIENT, RES_ANCHOR,
1031 RES_COL, RES_COL,
1032 RES_FOLLOW_TEXT_FLOW, RES_FOLLOW_TEXT_FLOW>{});
1033 rSh.GetFlyFrameAttr( aSet );
1034 RndStdIds eAnchorId = aSet.Get(RES_ANCHOR).GetAnchorId();
1035 Size aSnap;
1036 bool bHuge(MOVE_LEFT_HUGE8 == nDir ||
1037 MOVE_UP_HUGE9 == nDir ||
1038 MOVE_RIGHT_HUGE10 == nDir ||
1039 MOVE_DOWN_HUGE11 == nDir);
1040
1041 if(MOVE_LEFT_SMALL0 == nDir ||
1042 MOVE_UP_SMALL1 == nDir ||
1043 MOVE_RIGHT_SMALL6 == nDir ||
1044 MOVE_DOWN_SMALL7 == nDir )
1045 {
1046 aSnap = PixelToLogic(Size(1,1));
1047 }
1048 else
1049 {
1050 aSnap = rSh.GetViewOptions()->GetSnapSize();
1051 short nDiv = rSh.GetViewOptions()->GetDivisionX();
1052 if ( nDiv > 0 )
1053 aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) );
1054 nDiv = rSh.GetViewOptions()->GetDivisionY();
1055 if ( nDiv > 0 )
1056 aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) );
1057 }
1058
1059 if(bHuge)
1060 {
1061 // #i121236# 567twips == 1cm, but just take three times the normal snap
1062 aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3);
1063 }
1064
1065 SwRect aBoundRect;
1066 Point aRefPoint;
1067 // adjustment for allowing vertical position
1068 // aligned to page for fly frame anchored to paragraph or to character.
1069 {
1070 const SwFormatVertOrient& aVert( aSet.Get(RES_VERT_ORIENT) );
1071 const bool bFollowTextFlow =
1072 aSet.Get(RES_FOLLOW_TEXT_FLOW).GetValue();
1073 const SwPosition* pToCharContentPos = aSet.Get(RES_ANCHOR).GetContentAnchor();
1074 rSh.CalcBoundRect( aBoundRect, eAnchorId,
1075 text::RelOrientation::FRAME, aVert.GetRelationOrient(),
1076 pToCharContentPos, bFollowTextFlow,
1077 false, &aRefPoint );
1078 }
1079 long nLeft = std::min( aTmp.Left() - aBoundRect.Left(), aSnap.Width() );
1080 long nRight = std::min( aBoundRect.Right() - aTmp.Right(), aSnap.Width() );
1081 long nUp = std::min( aTmp.Top() - aBoundRect.Top(), aSnap.Height() );
1082 long nDown = std::min( aBoundRect.Bottom() - aTmp.Bottom(), aSnap.Height() );
1083
1084 switch ( nDir )
1085 {
1086 case MOVE_LEFT_BIG4:
1087 case MOVE_LEFT_HUGE8:
1088 case MOVE_LEFT_SMALL0: aTmp.Left( aTmp.Left() - nLeft );
1089 break;
1090
1091 case MOVE_UP_BIG5:
1092 case MOVE_UP_HUGE9:
1093 case MOVE_UP_SMALL1: aTmp.Top( aTmp.Top() - nUp );
1094 break;
1095
1096 case MOVE_RIGHT_SMALL6:
1097 if( aTmp.Width() < aSnap.Width() + MINFLY23 )
1098 break;
1099 nRight = aSnap.Width();
1100 [[fallthrough]];
1101 case MOVE_RIGHT_HUGE10:
1102 case MOVE_RIGHT_BIG2: aTmp.Left( aTmp.Left() + nRight );
1103 break;
1104
1105 case MOVE_DOWN_SMALL7:
1106 if( aTmp.Height() < aSnap.Height() + MINFLY23 )
1107 break;
1108 nDown = aSnap.Height();
1109 [[fallthrough]];
1110 case MOVE_DOWN_HUGE11:
1111 case MOVE_DOWN_BIG3: aTmp.Top( aTmp.Top() + nDown );
1112 break;
1113
1114 default: OSL_ENSURE(true, "ChangeFly: Unknown direction." )do { if (true && (!(true))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
":" "1114" ": "), "%s", "ChangeFly: Unknown direction."); } }
while (false)
;
1115 }
1116 bool bSet = false;
1117 if ((RndStdIds::FLY_AS_CHAR == eAnchorId) && ( nDir % 2 ))
1118 {
1119 long aDiff = aTmp.Top() - aRefPoint.Y();
1120 if( aDiff > 0 )
1121 aDiff = 0;
1122 else if ( aDiff < -aTmp.Height() )
1123 aDiff = -aTmp.Height();
1124 SwFormatVertOrient aVert( aSet.Get(RES_VERT_ORIENT) );
1125 sal_Int16 eNew;
1126 if( bWeb )
1127 {
1128 eNew = aVert.GetVertOrient();
1129 bool bDown = 0 != ( nDir & 0x02 );
1130 switch( eNew )
1131 {
1132 case text::VertOrientation::CHAR_TOP:
1133 if( bDown ) eNew = text::VertOrientation::CENTER;
1134 break;
1135 case text::VertOrientation::CENTER:
1136 eNew = bDown ? text::VertOrientation::TOP : text::VertOrientation::CHAR_TOP;
1137 break;
1138 case text::VertOrientation::TOP:
1139 if( !bDown ) eNew = text::VertOrientation::CENTER;
1140 break;
1141 case text::VertOrientation::LINE_TOP:
1142 if( bDown ) eNew = text::VertOrientation::LINE_CENTER;
1143 break;
1144 case text::VertOrientation::LINE_CENTER:
1145 eNew = bDown ? text::VertOrientation::LINE_BOTTOM : text::VertOrientation::LINE_TOP;
1146 break;
1147 case text::VertOrientation::LINE_BOTTOM:
1148 if( !bDown ) eNew = text::VertOrientation::LINE_CENTER;
1149 break;
1150 default:; //prevent warning
1151 }
1152 }
1153 else
1154 {
1155 aVert.SetPos( aDiff );
1156 eNew = text::VertOrientation::NONE;
1157 }
1158 aVert.SetVertOrient( eNew );
1159 aSet.Put( aVert );
1160 bSet = true;
1161 }
1162 if (bWeb && (RndStdIds::FLY_AT_PARA == eAnchorId)
1163 && ( nDir==MOVE_LEFT_SMALL0 || nDir==MOVE_RIGHT_BIG2 ))
1164 {
1165 SwFormatHoriOrient aHori( aSet.Get(RES_HORI_ORIENT) );
1166 sal_Int16 eNew;
1167 eNew = aHori.GetHoriOrient();
1168 switch( eNew )
1169 {
1170 case text::HoriOrientation::RIGHT:
1171 if( nDir==MOVE_LEFT_SMALL0 )
1172 eNew = text::HoriOrientation::LEFT;
1173 break;
1174 case text::HoriOrientation::LEFT:
1175 if( nDir==MOVE_RIGHT_BIG2 )
1176 eNew = text::HoriOrientation::RIGHT;
1177 break;
1178 default:; //prevent warning
1179 }
1180 if( eNew != aHori.GetHoriOrient() )
1181 {
1182 aHori.SetHoriOrient( eNew );
1183 aSet.Put( aHori );
1184 bSet = true;
1185 }
1186 }
1187 rSh.StartAllAction();
1188 if( bSet )
1189 rSh.SetFlyFrameAttr( aSet );
1190 bool bSetPos = (RndStdIds::FLY_AS_CHAR != eAnchorId);
1191 if(bSetPos && bWeb)
1192 {
1193 bSetPos = RndStdIds::FLY_AT_PAGE == eAnchorId;
1194 }
1195 if( bSetPos )
1196 rSh.SetFlyPos( aTmp.Pos() );
1197 rSh.EndAllAction();
1198
1199}
1200
1201void SwEditWin::ChangeDrawing( sal_uInt8 nDir )
1202{
1203 // start undo action in order to get only one
1204 // undo action for this change.
1205 SwWrtShell &rSh = m_rView.GetWrtShell();
1206 rSh.StartUndo();
1207
1208 long nX = 0;
1209 long nY = 0;
1210 const bool bOnePixel(
1211 MOVE_LEFT_SMALL0 == nDir ||
1212 MOVE_UP_SMALL1 == nDir ||
1213 MOVE_RIGHT_SMALL6 == nDir ||
1214 MOVE_DOWN_SMALL7 == nDir);
1215 const bool bHuge(
1216 MOVE_LEFT_HUGE8 == nDir ||
1217 MOVE_UP_HUGE9 == nDir ||
1218 MOVE_RIGHT_HUGE10 == nDir ||
1219 MOVE_DOWN_HUGE11 == nDir);
1220 SwMove nAnchorDir = SwMove::UP;
1221 switch(nDir)
1222 {
1223 case MOVE_LEFT_SMALL0:
1224 case MOVE_LEFT_HUGE8:
1225 case MOVE_LEFT_BIG4:
1226 nX = -1;
1227 nAnchorDir = SwMove::LEFT;
1228 break;
1229 case MOVE_UP_SMALL1:
1230 case MOVE_UP_HUGE9:
1231 case MOVE_UP_BIG5:
1232 nY = -1;
1233 break;
1234 case MOVE_RIGHT_SMALL6:
1235 case MOVE_RIGHT_HUGE10:
1236 case MOVE_RIGHT_BIG2:
1237 nX = +1;
1238 nAnchorDir = SwMove::RIGHT;
1239 break;
1240 case MOVE_DOWN_SMALL7:
1241 case MOVE_DOWN_HUGE11:
1242 case MOVE_DOWN_BIG3:
1243 nY = +1;
1244 nAnchorDir = SwMove::DOWN;
1245 break;
1246 }
1247
1248 if(0 != nX || 0 != nY)
1249 {
1250 FlyProtectFlags nProtect = rSh.IsSelObjProtected( FlyProtectFlags::Pos|FlyProtectFlags::Size );
1251 Size aSnap( rSh.GetViewOptions()->GetSnapSize() );
1252 short nDiv = rSh.GetViewOptions()->GetDivisionX();
1253 if ( nDiv > 0 )
1254 aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) );
1255 nDiv = rSh.GetViewOptions()->GetDivisionY();
1256 if ( nDiv > 0 )
1257 aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) );
1258
1259 if(bOnePixel)
1260 {
1261 aSnap = PixelToLogic(Size(1,1));
1262 }
1263 else if(bHuge)
1264 {
1265 // #i121236# 567twips == 1cm, but just take three times the normal snap
1266 aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3);
1267 }
1268
1269 nX *= aSnap.Width();
1270 nY *= aSnap.Height();
1271
1272 SdrView *pSdrView = rSh.GetDrawView();
1273 const SdrHdlList& rHdlList = pSdrView->GetHdlList();
1274 SdrHdl* pHdl = rHdlList.GetFocusHdl();
1275 rSh.StartAllAction();
1276 if(nullptr == pHdl)
1277 {
1278 // now move the selected draw objects
1279 // if the object's position is not protected
1280 if(!(nProtect&FlyProtectFlags::Pos))
1281 {
1282 // Check if object is anchored as character and move direction
1283 bool bDummy1, bDummy2;
1284 const bool bVertAnchor = rSh.IsFrameVertical( true, bDummy1, bDummy2 );
1285 bool bHoriMove = !bVertAnchor == !( nDir % 2 );
1286 bool bMoveAllowed =
1287 !bHoriMove || (rSh.GetAnchorId() != RndStdIds::FLY_AS_CHAR);
1288 if ( bMoveAllowed )
1289 {
1290 pSdrView->MoveAllMarked(Size(nX, nY));
1291 rSh.SetModified();
1292 }
1293 }
1294 }
1295 else
1296 {
1297 // move handle with index nHandleIndex
1298 if (nX || nY)
1299 {
1300 if( SdrHdlKind::Anchor == pHdl->GetKind() ||
1301 SdrHdlKind::Anchor_TR == pHdl->GetKind() )
1302 {
1303 // anchor move cannot be allowed when position is protected
1304 if(!(nProtect&FlyProtectFlags::Pos))
1305 rSh.MoveAnchor( nAnchorDir );
1306 }
1307 //now resize if size is protected
1308 else if(!(nProtect&FlyProtectFlags::Size))
1309 {
1310 // now move the Handle (nX, nY)
1311 Point aStartPoint(pHdl->GetPos());
1312 Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
1313 const SdrDragStat& rDragStat = pSdrView->GetDragStat();
1314
1315 // start dragging
1316 pSdrView->BegDragObj(aStartPoint, nullptr, pHdl, 0);
1317
1318 if(pSdrView->IsDragObj())
1319 {
1320 bool bWasNoSnap = rDragStat.IsNoSnap();
1321 bool bWasSnapEnabled = pSdrView->IsSnapEnabled();
1322
1323 // switch snapping off
1324 if(!bWasNoSnap)
1325 const_cast<SdrDragStat&>(rDragStat).SetNoSnap();
1326 if(bWasSnapEnabled)
1327 pSdrView->SetSnapEnabled(false);
1328
1329 pSdrView->MovAction(aEndPoint);
1330 pSdrView->EndDragObj();
1331 rSh.SetModified();
1332
1333 // restore snap
1334 if(!bWasNoSnap)
1335 const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap);
1336 if(bWasSnapEnabled)
1337 pSdrView->SetSnapEnabled(bWasSnapEnabled);
1338 }
1339 }
1340 }
1341 }
1342 rSh.EndAllAction();
1343 }
1344
1345 rSh.EndUndo();
1346}
1347
1348/**
1349 * KeyEvents
1350 */
1351void SwEditWin::KeyInput(const KeyEvent &rKEvt)
1352{
1353 SwWrtShell &rSh = m_rView.GetWrtShell();
1354
1355 if (comphelper::LibreOfficeKit::isActive() && m_rView.GetPostItMgr())
1356 {
1357 if (vcl::Window* pWindow = m_rView.GetPostItMgr()->GetActiveSidebarWin())
1358 {
1359 pWindow->KeyInput(rKEvt);
1360 return;
1361 }
1362 }
1363
1364 if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
1365 {
1366 // not allowed if outline content is folded
1367 sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
1368 if ((rSh.IsSttPara() && (nKey == KEY_BACKSPACE || nKey == KEY_LEFT))
1369 || (rSh.IsEndOfPara() && (nKey == KEY_DELETE || nKey == KEY_RETURN || nKey == KEY_RIGHT)))
1370 {
1371 SwContentNode* pContentNode = rSh.GetCurrentShellCursor().GetContentNode();
1372 SwOutlineNodes::size_type nPos;
1373 if (rSh.GetDoc()->GetNodes().GetOutLineNds().Seek_Entry(pContentNode, &nPos))
1374 {
1375 bool bOutlineContentVisibleAttr = true;
1376 pContentNode->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
1377 if (!bOutlineContentVisibleAttr)
1378 return; // outline node is folded
1379 if (rSh.IsSttPara() && (nKey == KEY_BACKSPACE || nKey == KEY_LEFT) && (nPos-1 != SwOutlineNodes::npos))
1380 {
1381 bOutlineContentVisibleAttr = true;
1382 rSh.GetDoc()->GetNodes().GetOutLineNds()[nPos-1]->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
1383 if (!bOutlineContentVisibleAttr)
1384 return; // previous outline node is folded
1385 }
1386 }
1387 }
1388 }
1389
1390 if( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE &&
1391 m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard )
1392 {
1393 m_pApplyTempl->m_pFormatClipboard->Erase();
1394 SetApplyTemplate(SwApplyTemplate());
1395 m_rView.GetViewFrame()->GetBindings().Invalidate(SID_FORMATPAINTBRUSHTypedWhichId<SfxBoolItem>(5000 + 715));
1396 }
1397 else if ( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE &&
1398 rSh.IsHeaderFooterEdit( ) )
1399 {
1400 bool bHeader = bool(FrameTypeFlags::HEADER & rSh.GetFrameType(nullptr,false));
1401 if ( bHeader )
1402 rSh.SttPg();
1403 else
1404 rSh.EndPg();
1405 rSh.ToggleHeaderFooterEdit();
1406 }
1407
1408 SfxObjectShell *pObjSh = m_rView.GetViewFrame()->GetObjectShell();
1409 if ( m_bLockInput || (pObjSh && pObjSh->GetProgress()) )
1410 // When the progress bar is active or a progress is
1411 // running on a document, no order is being taken
1412 return;
1413
1414 m_pShadCursor.reset();
1415 m_aKeyInputFlushTimer.Stop();
1416
1417 bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
1418 rSh.IsCursorReadonly();
1419
1420 //if the language changes the buffer must be flushed
1421 LanguageType eNewLanguage = GetInputLanguage();
1422 if(!bIsDocReadOnly && m_eBufferLanguage != eNewLanguage && !m_aInBuffer.isEmpty())
1423 {
1424 FlushInBuffer();
1425 }
1426 m_eBufferLanguage = eNewLanguage;
1427
1428 QuickHelpData aTmpQHD;
1429 if( m_pQuickHlpData->m_bIsDisplayed )
1430 {
1431 aTmpQHD.Move( *m_pQuickHlpData );
1432 m_pQuickHlpData->Stop( rSh );
1433 }
1434
1435 // OS:the DrawView also needs a readonly-Flag as well
1436 if ( !bIsDocReadOnly && rSh.GetDrawView() && rSh.GetDrawView()->KeyInput( rKEvt, this ) )
1437 {
1438 rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll( false );
1439 rSh.SetModified();
1440 return; // Event evaluated by SdrView
1441 }
1442
1443 if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
1444 {
1445 StopInsFrame();
1446 rSh.Edit();
1447 }
1448
1449 bool bFlushBuffer = false;
1450 bool bNormalChar = false;
1451 bool bAppendSpace = m_pQuickHlpData->m_bAppendSpace;
1452 m_pQuickHlpData->m_bAppendSpace = false;
1453
1454 if ( getenv("SW_DEBUG") && rKEvt.GetKeyCode().GetCode() == KEY_F12 )
1455 {
1456 if( rKEvt.GetKeyCode().IsShift())
1457 {
1458 GetView().GetDocShell()->GetDoc()->dumpAsXml();
1459 return;
1460 }
1461 else
1462 {
1463 SwRootFrame* pLayout = GetView().GetDocShell()->GetWrtShell()->GetLayout();
1464 pLayout->dumpAsXml( );
1465 return;
1466 }
1467 }
1468
1469 KeyEvent aKeyEvent( rKEvt );
1470 // look for vertical mappings
1471 if( !bIsDocReadOnly && !rSh.IsSelFrameMode() && !rSh.IsObjSelected() )
1472 {
1473 // must changed from switch to if, because the Linux
1474 // compiler has problem with the code. Has to remove if the new general
1475 // handler exist.
1476 sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
1477
1478 if( KEY_UP == nKey || KEY_DOWN == nKey ||
1479 KEY_LEFT == nKey || KEY_RIGHT == nKey )
1480 {
1481 // In general, we want to map the direction keys if we are inside
1482 // some vertical formatted text.
1483 // 1. Exception: For a table cursor in a horizontal table, the
1484 // directions should never be mapped.
1485 // 2. Exception: For a table cursor in a vertical table, the
1486 // directions should always be mapped.
1487 const bool bVertText = rSh.IsInVerticalText();
1488 const bool bTableCursor = rSh.GetTableCursor();
1489 const bool bVertTable = rSh.IsTableVertical();
1490 if( ( bVertText && ( !bTableCursor || bVertTable ) ) ||
1491 ( bTableCursor && bVertTable ) )
1492 {
1493 SvxFrameDirection eDirection = rSh.GetTextDirection();
1494 if (eDirection == SvxFrameDirection::Vertical_LR_BT)
1495 {
1496 // Map from physical to logical, so rotate clockwise.
1497 if (KEY_UP == nKey)
1498 nKey = KEY_RIGHT;
1499 else if (KEY_DOWN == nKey)
1500 nKey = KEY_LEFT;
1501 else if (KEY_LEFT == nKey)
1502 nKey = KEY_UP;
1503 else /* KEY_RIGHT == nKey */
1504 nKey = KEY_DOWN;
1505 }
1506 else
1507 {
1508 // Attempt to integrate cursor travelling for mongolian layout does not work.
1509 // Thus, back to previous mapping of cursor keys to direction keys.
1510 if( KEY_UP == nKey ) nKey = KEY_LEFT;
1511 else if( KEY_DOWN == nKey ) nKey = KEY_RIGHT;
1512 else if( KEY_LEFT == nKey ) nKey = KEY_DOWN;
1513 else /* KEY_RIGHT == nKey */ nKey = KEY_UP;
1514 }
1515 }
1516
1517 if ( rSh.IsInRightToLeftText() )
1518 {
1519 if( KEY_LEFT == nKey ) nKey = KEY_RIGHT;
1520 else if( KEY_RIGHT == nKey ) nKey = KEY_LEFT;
1521 }
1522
1523 aKeyEvent = KeyEvent( rKEvt.GetCharCode(),
1524 vcl::KeyCode( nKey, rKEvt.GetKeyCode().GetModifier() ),
1525 rKEvt.GetRepeat() );
1526 }
1527 }
1528
1529 const vcl::KeyCode& rKeyCode = aKeyEvent.GetKeyCode();
1530 sal_Unicode aCh = aKeyEvent.GetCharCode();
1531
1532 // enable switching to notes anchor with Ctrl - Alt - Page Up/Down
1533 // pressing this inside a note will switch to next/previous note
1534 if ((rKeyCode.IsMod1() && rKeyCode.IsMod2()) && ((rKeyCode.GetCode() == KEY_PAGEUP) || (rKeyCode.GetCode() == KEY_PAGEDOWN)))
1535 {
1536 const bool bNext = rKeyCode.GetCode()==KEY_PAGEDOWN;
1537 const SwFieldType* pFieldType = rSh.GetFieldType( 0, SwFieldIds::Postit );
1538 rSh.MoveFieldType( pFieldType, bNext );
1539 return;
1540 }
1541
1542 const SwFrameFormat* pFlyFormat = rSh.GetFlyFrameFormat();
1543 if( pFlyFormat )
1544 {
1545 SvMacroItemId nEvent;
1546
1547 if( 32 <= aCh &&
1548 0 == (( KEY_MOD1 | KEY_MOD2 ) & rKeyCode.GetModifier() ))
1549 nEvent = SvMacroItemId::SwFrmKeyInputAlpha;
1550 else
1551 nEvent = SvMacroItemId::SwFrmKeyInputNoAlpha;
1552
1553 const SvxMacro* pMacro = pFlyFormat->GetMacro().GetMacroTable().Get( nEvent );
1554 if( pMacro )
1555 {
1556 SbxArrayRef xArgs = new SbxArray;
1557 SbxVariableRef xVar = new SbxVariable;
1558 xVar->PutString( pFlyFormat->GetName() );
1559 xArgs->Put32( xVar.get(), 1 );
1560
1561 xVar = new SbxVariable;
1562 if( SvMacroItemId::SwFrmKeyInputAlpha == nEvent )
1563 xVar->PutChar( aCh );
1564 else
1565 xVar->PutUShort( rKeyCode.GetModifier() | rKeyCode.GetCode() );
1566 xArgs->Put32( xVar.get(), 2 );
1567
1568 OUString sRet;
1569 rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
1570 if( !sRet.isEmpty() && sRet.toInt32()!=0 )
1571 return ;
1572 }
1573 }
1574 SelectionType nLclSelectionType;
1575 //A is converted to 1
1576 if( rKeyCode.GetFullCode() == (KEY_A | KEY_MOD1 |KEY_SHIFT)
1577 && rSh.HasDrawView() &&
1578 (bool(nLclSelectionType = rSh.GetSelectionType()) &&
1579 ((nLclSelectionType & (SelectionType::Frame|SelectionType::Graphic)) ||
1580 ((nLclSelectionType & (SelectionType::DrawObject|SelectionType::DbForm)) &&
1581 rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1))))
1582 {
1583 SdrHdlList& rHdlList = const_cast<SdrHdlList&>(rSh.GetDrawView()->GetHdlList());
1584 SdrHdl* pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor);
1585 if ( ! pAnchor )
1586 pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor_TR);
1587 if(pAnchor)
1588 rHdlList.SetFocusHdl(pAnchor);
1589 return;
1590 }
1591
1592 SvxAutoCorrCfg* pACfg = nullptr;
1593 SvxAutoCorrect* pACorr = nullptr;
1594
1595 uno::Reference< frame::XDispatchRecorder > xRecorder =
1596 m_rView.GetViewFrame()->GetBindings().GetRecorder();
1597 if ( !xRecorder.is() )
1598 {
1599 pACfg = &SvxAutoCorrCfg::Get();
1600 pACorr = pACfg->GetAutoCorrect();
1601 }
1602
1603 SwModuleOptions* pModOpt = SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->GetModuleConfig();
1604
1605 OUString sFormulaEntry;
1606
1607 enum class SwKeyState { CheckKey, InsChar, InsTab,
1608 NoNum, NumOff, NumOrNoNum, NumDown, NumUp,
1609 NumIndentInc, NumIndentDec,
1610
1611 OutlineLvOff,
1612 NextCell, PrevCell, OutlineUp, OutlineDown,
1613 GlossaryExpand, NextPrevGlossary,
1614 AutoFormatByInput,
1615 NextObject, PrevObject,
1616 KeyToView,
1617 LaunchOLEObject, GoIntoFly, GoIntoDrawing,
1618 EnterDrawHandleMode,
1619 CheckDocReadOnlyKeys,
1620 CheckAutoCorrect, EditFormula,
1621 ColLeftBig, ColRightBig,
1622 ColLeftSmall, ColRightSmall,
1623 ColBottomBig,
1624 ColBottomSmall,
1625 CellLeftBig, CellRightBig,
1626 CellLeftSmall, CellRightSmall,
1627 CellTopBig, CellBottomBig,
1628 CellTopSmall, CellBottomSmall,
1629
1630 Fly_Change, Draw_Change,
1631 SpecialInsert,
1632 EnterCharCell,
1633 GotoNextFieldMark,
1634 GotoPrevFieldMark,
1635 End };
1636
1637 SwKeyState eKeyState = bIsDocReadOnly ? SwKeyState::CheckDocReadOnlyKeys : SwKeyState::CheckKey;
1638 SwKeyState eNextKeyState = SwKeyState::End;
1639 sal_uInt8 nDir = 0;
1640
1641 if (m_nKS_NUMDOWN_Count > 0)
1642 m_nKS_NUMDOWN_Count--;
1643
1644 if (m_nKS_NUMINDENTINC_Count > 0)
1645 m_nKS_NUMINDENTINC_Count--;
1646
1647 while( SwKeyState::End != eKeyState )
1648 {
1649 SwKeyState eFlyState = SwKeyState::KeyToView;
1650
1651 switch( eKeyState )
1652 {
1653 case SwKeyState::CheckKey:
1654 eKeyState = SwKeyState::KeyToView; // default forward to View
1655
1656#if OSL_DEBUG_LEVEL1 > 1
1657//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1658 // for switching cursor behaviour in ReadOnly regions
1659 if( 0x7210 == rKeyCode.GetFullCode() )
1660 rSh.SetReadOnlyAvailable( !rSh.IsReadOnlyAvailable() );
1661 else
1662//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1663#endif
1664
1665 if (!comphelper::LibreOfficeKit::isActive() &&
1666 !rKeyCode.IsMod2() && '=' == aCh &&
1667 !rSh.IsTableMode() && rSh.GetTableFormat() &&
1668 rSh.IsSttPara() &&
1669 !rSh.HasReadonlySel())
1670 {
1671 // at the beginning of the table's cell a '=' ->
1672 // call EditRow (F2-functionality)
1673 // [Avoid this for LibreOfficeKit, as the separate input window
1674 // steals the focus & things go wrong - the user never gets
1675 // the focus back.]
1676 rSh.Push();
1677 if( !rSh.MoveSection( GoCurrSection, fnSectionStart) &&
1678 !rSh.IsTableBoxTextFormat() )
1679 {
1680 // is at the beginning of the box
1681 eKeyState = SwKeyState::EditFormula;
1682 if( rSh.HasMark() )
1683 rSh.SwapPam();
1684 else
1685 rSh.SttSelect();
1686 rSh.MoveSection( GoCurrSection, fnSectionEnd );
1687 rSh.Pop();
1688 rSh.EndSelect();
1689 sFormulaEntry = "=";
1690 }
1691 else
1692 rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
1693 }
1694 else
1695 {
1696 if( pACorr && aTmpQHD.HasContent() && !rSh.HasSelection() &&
1697 !rSh.HasReadonlySel() && !aTmpQHD.m_bIsAutoText &&
1698 pACorr->GetSwFlags().nAutoCmpltExpandKey ==
1699 (rKeyCode.GetModifier() | rKeyCode.GetCode()) )
1700 {
1701 eKeyState = SwKeyState::GlossaryExpand;
1702 break;
1703 }
1704
1705 switch( rKeyCode.GetModifier() | rKeyCode.GetCode() )
1706 {
1707 case KEY_RIGHT | KEY_MOD2:
1708 eKeyState = SwKeyState::ColRightBig;
1709 eFlyState = SwKeyState::Fly_Change;
1710 nDir = MOVE_RIGHT_SMALL6;
1711 goto KEYINPUT_CHECKTABLE;
1712
1713 case KEY_LEFT | KEY_MOD2:
1714 eKeyState = SwKeyState::ColRightSmall;
1715 eFlyState = SwKeyState::Fly_Change;
1716 nDir = MOVE_LEFT_SMALL0;
1717 goto KEYINPUT_CHECKTABLE;
1718
1719 case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT:
1720 eKeyState = SwKeyState::ColLeftSmall;
1721 goto KEYINPUT_CHECKTABLE;
1722
1723 case KEY_LEFT | KEY_MOD2 | KEY_SHIFT:
1724 eKeyState = SwKeyState::ColLeftBig;
1725 goto KEYINPUT_CHECKTABLE;
1726
1727 case KEY_RIGHT | KEY_MOD2 | KEY_MOD1:
1728 eKeyState = SwKeyState::CellRightBig;
1729 goto KEYINPUT_CHECKTABLE;
1730
1731 case KEY_LEFT | KEY_MOD2 | KEY_MOD1:
1732 eKeyState = SwKeyState::CellRightSmall;
1733 goto KEYINPUT_CHECKTABLE;
1734
1735 case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1736 eKeyState = SwKeyState::CellLeftSmall;
1737 goto KEYINPUT_CHECKTABLE;
1738
1739 case KEY_LEFT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1740 eKeyState = SwKeyState::CellLeftBig;
1741 goto KEYINPUT_CHECKTABLE;
1742
1743 case KEY_UP | KEY_MOD2:
1744 eKeyState = SwKeyState::ColBottomSmall;
1745 eFlyState = SwKeyState::Fly_Change;
1746 nDir = MOVE_UP_SMALL1;
1747 goto KEYINPUT_CHECKTABLE;
1748
1749 case KEY_DOWN | KEY_MOD2:
1750 eKeyState = SwKeyState::ColBottomBig;
1751 eFlyState = SwKeyState::Fly_Change;
1752 nDir = MOVE_DOWN_SMALL7;
1753 goto KEYINPUT_CHECKTABLE;
1754
1755 case KEY_UP | KEY_MOD2 | KEY_MOD1:
1756 eKeyState = SwKeyState::CellBottomSmall;
1757 goto KEYINPUT_CHECKTABLE;
1758
1759 case KEY_DOWN | KEY_MOD2 | KEY_MOD1:
1760 eKeyState = SwKeyState::CellBottomBig;
1761 goto KEYINPUT_CHECKTABLE;
1762
1763 case KEY_UP | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1764 eKeyState = SwKeyState::CellTopBig;
1765 goto KEYINPUT_CHECKTABLE;
1766
1767 case KEY_DOWN | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1768 eKeyState = SwKeyState::CellTopSmall;
1769 goto KEYINPUT_CHECKTABLE;
1770
1771KEYINPUT_CHECKTABLE:
1772 if( rSh.IsTableMode() || !rSh.GetTableFormat() )
1773 {
1774 if(!pFlyFormat && SwKeyState::KeyToView != eFlyState &&
1775 (rSh.GetSelectionType() & (SelectionType::DrawObject|SelectionType::DbForm)) &&
1776 rSh.GetDrawView()->AreObjectsMarked())
1777 eKeyState = SwKeyState::Draw_Change;
1778
1779 if( pFlyFormat )
1780 eKeyState = eFlyState;
1781 else if( SwKeyState::Draw_Change != eKeyState)
1782 eKeyState = SwKeyState::EnterCharCell;
1783 }
1784 break;
1785
1786 // huge object move
1787 case KEY_RIGHT | KEY_SHIFT:
1788 case KEY_LEFT | KEY_SHIFT:
1789 case KEY_UP | KEY_SHIFT:
1790 case KEY_DOWN | KEY_SHIFT:
1791 {
1792 const SelectionType nSelectionType = rSh.GetSelectionType();
1793 if ( ( pFlyFormat
1794 && ( nSelectionType & (SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic) ) )
1795 || ( ( nSelectionType & (SelectionType::DrawObject|SelectionType::DbForm) )
1796 && rSh.GetDrawView()->AreObjectsMarked() ) )
1797 {
1798 eKeyState = pFlyFormat ? SwKeyState::Fly_Change : SwKeyState::Draw_Change;
1799 switch ( rKeyCode.GetCode() )
1800 {
1801 case KEY_RIGHT: nDir = MOVE_RIGHT_HUGE10; break;
1802 case KEY_LEFT: nDir = MOVE_LEFT_HUGE8; break;
1803 case KEY_UP: nDir = MOVE_UP_HUGE9; break;
1804 case KEY_DOWN: nDir = MOVE_DOWN_HUGE11; break;
1805 }
1806 }
1807 break;
1808 }
1809
1810 case KEY_LEFT:
1811 case KEY_LEFT | KEY_MOD1:
1812 {
1813 bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1814 if(!bMod1)
1815 {
1816 eFlyState = SwKeyState::Fly_Change;
1817 nDir = MOVE_LEFT_BIG4;
1818 }
1819 goto KEYINPUT_CHECKTABLE_INSDEL;
1820 }
1821 case KEY_RIGHT | KEY_MOD1:
1822 {
1823 goto KEYINPUT_CHECKTABLE_INSDEL;
1824 }
1825 case KEY_UP:
1826 case KEY_UP | KEY_MOD1:
1827 {
1828 bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1829 if(!bMod1)
1830 {
1831 eFlyState = SwKeyState::Fly_Change;
1832 nDir = MOVE_UP_BIG5;
1833 }
1834 goto KEYINPUT_CHECKTABLE_INSDEL;
1835 }
1836 case KEY_DOWN:
1837 case KEY_DOWN | KEY_MOD1:
1838 {
1839 bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1840 if(!bMod1)
1841 {
1842 eFlyState = SwKeyState::Fly_Change;
1843 nDir = MOVE_DOWN_BIG3;
1844 }
1845 goto KEYINPUT_CHECKTABLE_INSDEL;
1846 }
1847
1848KEYINPUT_CHECKTABLE_INSDEL:
1849 if( rSh.IsTableMode() || !rSh.GetTableFormat() )
1850 {
1851 const SelectionType nSelectionType = rSh.GetSelectionType();
1852
1853 eKeyState = SwKeyState::KeyToView;
1854 if(SwKeyState::KeyToView != eFlyState)
1855 {
1856 if((nSelectionType & (SelectionType::DrawObject|SelectionType::DbForm)) &&
1857 rSh.GetDrawView()->AreObjectsMarked())
1858 eKeyState = SwKeyState::Draw_Change;
1859 else if(nSelectionType & (SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic))
1860 eKeyState = SwKeyState::Fly_Change;
1861 }
1862 }
1863 break;
1864
1865
1866 case KEY_DELETE:
1867 if ( !rSh.HasReadonlySel() || rSh.CursorInsideInputField())
1868 {
1869 if (rSh.IsInFrontOfLabel() && rSh.NumOrNoNum())
1870 eKeyState = SwKeyState::NumOrNoNum;
1871 }
1872 else if (!rSh.IsCursorInParagraphMetadataField())
1873 {
1874 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui"));
1875 std::unique_ptr<weld::MessageDialog> xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog"));
1876 xInfo->run();
1877 eKeyState = SwKeyState::End;
1878 }
1879 break;
1880
1881 case KEY_RETURN:
1882 {
1883 if ( !rSh.HasReadonlySel()
1884 && !rSh.CursorInsideInputField() )
1885 {
1886 const SelectionType nSelectionType = rSh.GetSelectionType();
1887 if(nSelectionType & SelectionType::Ole)
1888 eKeyState = SwKeyState::LaunchOLEObject;
1889 else if(nSelectionType & SelectionType::Frame)
1890 eKeyState = SwKeyState::GoIntoFly;
1891 else if((nSelectionType & SelectionType::DrawObject) &&
1892 !(nSelectionType & SelectionType::DrawObjectEditMode) &&
1893 rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1)
1894 {
1895 eKeyState = SwKeyState::GoIntoDrawing;
1896 if (lcl_goIntoTextBox(*this, rSh))
1897 eKeyState = SwKeyState::GoIntoFly;
1898 }
1899 else if( aTmpQHD.HasContent() && !rSh.HasSelection() &&
1900 aTmpQHD.m_bIsAutoText )
1901 eKeyState = SwKeyState::GlossaryExpand;
1902
1903 //RETURN and empty paragraph in numbering -> end numbering
1904 else if( m_aInBuffer.isEmpty() &&
1905 rSh.GetNumRuleAtCurrCursorPos() &&
1906 !rSh.GetNumRuleAtCurrCursorPos()->IsOutlineRule() &&
1907 !rSh.HasSelection() &&
1908 rSh.IsSttPara() && rSh.IsEndPara() )
1909 {
1910 eKeyState = SwKeyState::NumOff;
1911 eNextKeyState = SwKeyState::OutlineLvOff;
1912 }
1913 //RETURN for new paragraph with AutoFormatting
1914 else if( pACfg && pACfg->IsAutoFormatByInput() &&
1915 !(nSelectionType & (SelectionType::Graphic |
1916 SelectionType::Ole | SelectionType::Frame |
1917 SelectionType::TableCell | SelectionType::DrawObject |
1918 SelectionType::DrawObjectEditMode)) )
1919 {
1920 eKeyState = SwKeyState::AutoFormatByInput;
1921 }
1922 else
1923 {
1924 eNextKeyState = eKeyState;
1925 eKeyState = SwKeyState::CheckAutoCorrect;
1926 }
1927 }
1928 }
1929 break;
1930 case KEY_RETURN | KEY_MOD2:
1931 {
1932 if ( !rSh.HasReadonlySel()
1933 && !rSh.IsSttPara()
1934 && rSh.GetNumRuleAtCurrCursorPos()
1935 && !rSh.CursorInsideInputField() )
1936 {
1937 eKeyState = SwKeyState::NoNum;
1938 }
1939 else if( rSh.CanSpecialInsert() )
1940 eKeyState = SwKeyState::SpecialInsert;
1941 }
1942 break;
1943 case KEY_BACKSPACE:
1944 case KEY_BACKSPACE | KEY_SHIFT:
1945 if ( !rSh.HasReadonlySel() || rSh.CursorInsideInputField())
1946 {
1947 bool bDone = false;
1948 // try to add comment for code snip:
1949 // Remove the paragraph indent, if the cursor is at the
1950 // beginning of a paragraph, there is no selection
1951 // and no numbering rule found at the current paragraph
1952 // Also try to remove indent, if current paragraph
1953 // has numbering rule, but isn't counted and only
1954 // key <backspace> is hit.
1955 const bool bOnlyBackspaceKey( KEY_BACKSPACE == rKeyCode.GetFullCode() );
1956 if ( rSh.IsSttPara()
1957 && !rSh.HasSelection()
1958 && ( rSh.GetNumRuleAtCurrCursorPos() == nullptr
1959 || ( rSh.IsNoNum() && bOnlyBackspaceKey ) ) )
1960 {
1961 bDone = rSh.TryRemoveIndent();
1962 }
1963
1964 if (bDone)
1965 eKeyState = SwKeyState::End;
1966 else
1967 {
1968 if ( rSh.IsSttPara() && !rSh.IsNoNum() )
1969 {
1970 if (m_nKS_NUMDOWN_Count > 0 &&
1971 0 < rSh.GetNumLevel())
1972 {
1973 eKeyState = SwKeyState::NumUp;
1974 m_nKS_NUMDOWN_Count = 2;
1975 bDone = true;
1976 }
1977 else if (m_nKS_NUMINDENTINC_Count > 0)
1978 {
1979 eKeyState = SwKeyState::NumIndentDec;
1980 m_nKS_NUMINDENTINC_Count = 2;
1981 bDone = true;
1982 }
1983 }
1984
1985 // If the cursor is in an empty paragraph, which has
1986 // a numbering, but not the outline numbering, and
1987 // there is no selection, the numbering has to be
1988 // deleted on key <Backspace>.
1989 // Otherwise method <SwEditShell::NumOrNoNum(..)>
1990 // should only change the <IsCounted()> state of
1991 // the current paragraph depending of the key.
1992 // On <backspace> it is set to <false>,
1993 // on <shift-backspace> it is set to <true>.
1994 // Thus, assure that method <SwEditShell::NumOrNum(..)>
1995 // is only called for the intended purpose.
1996 if ( !bDone && rSh.IsSttPara() )
1997 {
1998 bool bCallNumOrNoNum( false );
1999 if ( bOnlyBackspaceKey && !rSh.IsNoNum() )
2000 {
2001 bCallNumOrNoNum = true;
2002 }
2003 else if ( !bOnlyBackspaceKey && rSh.IsNoNum() )
2004 {
2005 bCallNumOrNoNum = true;
2006 }
2007 else if ( bOnlyBackspaceKey
2008 && rSh.IsSttPara()
2009 && rSh.IsEndPara()
2010 && !rSh.HasSelection() )
2011 {
2012 const SwNumRule* pCurrNumRule( rSh.GetNumRuleAtCurrCursorPos() );
2013 if ( pCurrNumRule != nullptr
2014 && pCurrNumRule != rSh.GetOutlineNumRule() )
2015 {
2016 bCallNumOrNoNum = true;
2017 }
2018 }
2019 if ( bCallNumOrNoNum
2020 && rSh.NumOrNoNum( !bOnlyBackspaceKey ) )
2021 {
2022 eKeyState = SwKeyState::NumOrNoNum;
2023 }
2024 }
2025 }
2026 }
2027 else if (!rSh.IsCursorInParagraphMetadataField())
2028 {
2029 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui"));
2030 std::unique_ptr<weld::MessageDialog> xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog"));
2031 xInfo->run();
2032 eKeyState = SwKeyState::End;
2033 }
2034 break;
2035
2036 case KEY_RIGHT:
2037 {
2038 eFlyState = SwKeyState::Fly_Change;
2039 nDir = MOVE_RIGHT_BIG2;
2040 goto KEYINPUT_CHECKTABLE_INSDEL;
2041 }
2042 case KEY_TAB:
2043 {
2044
2045 if (rSh.IsFormProtected() || rSh.GetCurrentFieldmark() || rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENTu'\x0006')
2046 {
2047 eKeyState = SwKeyState::GotoNextFieldMark;
2048 }
2049 else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2050 {
2051 GetView().GetViewFrame()->GetDispatcher()->Execute( FN_GOTO_NEXT_INPUTFLD((20000 + 100) + 47) );
2052 eKeyState = SwKeyState::End;
2053 }
2054 else if( rSh.GetNumRuleAtCurrCursorPos()
2055 && rSh.IsSttOfPara()
2056 && !rSh.HasReadonlySel() )
2057 {
2058 if ( !rSh.IsMultiSelection()
2059 && rSh.IsFirstOfNumRuleAtCursorPos()
2060 && numfunc::ChangeIndentOnTabAtFirstPosOfFirstListItem() )
2061 eKeyState = SwKeyState::NumIndentInc;
2062 else
2063 {
2064 if (numfunc::NumDownChangesIndent(rSh))
2065 {
2066 eKeyState = SwKeyState::NumDown;
2067 }
2068 else
2069 {
2070 eKeyState = SwKeyState::InsTab;
2071 }
2072 }
2073 }
2074 else if ( rSh.GetTableFormat() )
2075 {
2076 if( rSh.HasSelection() || rSh.HasReadonlySel() )
2077 eKeyState = SwKeyState::NextCell;
2078 else
2079 {
2080 eKeyState = SwKeyState::CheckAutoCorrect;
2081 eNextKeyState = SwKeyState::NextCell;
2082 }
2083 }
2084 else if ( rSh.GetSelectionType() &
2085 (SelectionType::Graphic |
2086 SelectionType::Frame |
2087 SelectionType::Ole |
2088 SelectionType::DrawObject |
2089 SelectionType::DbForm))
2090
2091 eKeyState = SwKeyState::NextObject;
2092 else
2093 {
2094 eKeyState = SwKeyState::InsTab;
2095 if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() )
2096 {
2097 SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
2098 if( pColl &&
2099
2100 pColl->IsAssignedToListLevelOfOutlineStyle()
2101 && MAXLEVEL-1 > pColl->GetAssignedOutlineStyleLevel() )
2102 eKeyState = SwKeyState::OutlineDown;
2103 }
2104 }
2105 }
2106 break;
2107 case KEY_TAB | KEY_SHIFT:
2108 {
2109 if (rSh.IsFormProtected() || rSh.GetCurrentFieldmark()|| rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENTu'\x0006')
2110 {
2111 eKeyState = SwKeyState::GotoPrevFieldMark;
2112 }
2113 else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2114 {
2115 GetView().GetViewFrame()->GetDispatcher()->Execute( FN_GOTO_PREV_INPUTFLD((20000 + 100) + 48) );
2116 eKeyState = SwKeyState::End;
2117 }
2118 else if( rSh.GetNumRuleAtCurrCursorPos()
2119 && rSh.IsSttOfPara()
2120 && !rSh.HasReadonlySel() )
2121 {
2122 if ( !rSh.IsMultiSelection()
2123 && rSh.IsFirstOfNumRuleAtCursorPos()
2124 && numfunc::ChangeIndentOnTabAtFirstPosOfFirstListItem() )
2125 eKeyState = SwKeyState::NumIndentDec;
2126 else
2127 eKeyState = SwKeyState::NumUp;
2128 }
2129 else if ( rSh.GetTableFormat() )
2130 {
2131 if( rSh.HasSelection() || rSh.HasReadonlySel() )
2132 eKeyState = SwKeyState::PrevCell;
2133 else
2134 {
2135 eKeyState = SwKeyState::CheckAutoCorrect;
2136 eNextKeyState = SwKeyState::PrevCell;
2137 }
2138 }
2139 else if ( rSh.GetSelectionType() &
2140 (SelectionType::Graphic |
2141 SelectionType::Frame |
2142 SelectionType::Ole |
2143 SelectionType::DrawObject |
2144 SelectionType::DbForm))
2145
2146 eKeyState = SwKeyState::PrevObject;
2147 else
2148 {
2149 eKeyState = SwKeyState::End;
2150 if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() )
2151 {
2152 SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
2153 if( pColl &&
2154 pColl->IsAssignedToListLevelOfOutlineStyle() &&
2155 0 < pColl->GetAssignedOutlineStyleLevel())
2156 eKeyState = SwKeyState::OutlineUp;
2157 }
2158 }
2159 }
2160 break;
2161 case KEY_TAB | KEY_MOD1:
2162 case KEY_TAB | KEY_MOD2:
2163 if( !rSh.HasReadonlySel() )
2164 {
2165 if( aTmpQHD.HasContent() && !rSh.HasSelection() )
2166 {
2167 // Next auto-complete suggestion
2168 aTmpQHD.Next( pACorr &&
2169 pACorr->GetSwFlags().bAutoCmpltEndless );
2170 eKeyState = SwKeyState::NextPrevGlossary;
2171 }
2172 else if( rSh.GetTableFormat() )
2173 eKeyState = SwKeyState::InsTab;
2174 else if((rSh.GetSelectionType() &
2175 (SelectionType::DrawObject|SelectionType::DbForm|
2176 SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic)) &&
2177 rSh.GetDrawView()->AreObjectsMarked())
2178 eKeyState = SwKeyState::EnterDrawHandleMode;
2179 else
2180 {
2181 eKeyState = SwKeyState::InsTab;
2182 }
2183 }
2184 break;
2185
2186 case KEY_TAB | KEY_MOD1 | KEY_SHIFT:
2187 {
2188 if( aTmpQHD.HasContent() && !rSh.HasSelection() &&
2189 !rSh.HasReadonlySel() )
2190 {
2191 // Previous auto-complete suggestion.
2192 aTmpQHD.Previous( pACorr &&
2193 pACorr->GetSwFlags().bAutoCmpltEndless );
2194 eKeyState = SwKeyState::NextPrevGlossary;
2195 }
2196 else if((rSh.GetSelectionType() & (SelectionType::DrawObject|SelectionType::DbForm|
2197 SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic)) &&
2198 rSh.GetDrawView()->AreObjectsMarked())
2199 {
2200 eKeyState = SwKeyState::EnterDrawHandleMode;
2201 }
2202 }
2203 break;
2204 case KEY_F2 :
2205 if( !rSh.HasReadonlySel() )
2206 {
2207 const SelectionType nSelectionType = rSh.GetSelectionType();
2208 if(nSelectionType & SelectionType::Frame)
2209 eKeyState = SwKeyState::GoIntoFly;
2210 else if(nSelectionType & SelectionType::DrawObject)
2211 {
2212 eKeyState = SwKeyState::GoIntoDrawing;
2213 if (lcl_goIntoTextBox(*this, rSh))
2214 eKeyState = SwKeyState::GoIntoFly;
2215 }
2216 }
2217 break;
2218 }
2219 }
2220 break;
2221 case SwKeyState::CheckDocReadOnlyKeys:
2222 {
2223 eKeyState = SwKeyState::KeyToView;
2224 switch( rKeyCode.GetModifier() | rKeyCode.GetCode() )
2225 {
2226 case KEY_TAB:
2227 case KEY_TAB | KEY_SHIFT:
2228 bNormalChar = false;
2229 eKeyState = SwKeyState::End;
2230 if ( rSh.GetSelectionType() &
2231 (SelectionType::Graphic |
2232 SelectionType::Frame |
2233 SelectionType::Ole |
2234 SelectionType::DrawObject |
2235 SelectionType::DbForm))
2236
2237 {
2238 eKeyState = (rKeyCode.GetModifier() & KEY_SHIFT) ?
2239 SwKeyState::PrevObject : SwKeyState::NextObject;
2240 }
2241 else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2242 {
2243 GetView().GetViewFrame()->GetDispatcher()->Execute(
2244 KEY_SHIFT != rKeyCode.GetModifier() ? FN_GOTO_NEXT_INPUTFLD((20000 + 100) + 47) : FN_GOTO_PREV_INPUTFLD((20000 + 100) + 48) );
2245 }
2246 else
2247 {
2248 rSh.SelectNextPrevHyperlink( KEY_SHIFT != rKeyCode.GetModifier() );
2249 }
2250 break;
2251 case KEY_RETURN:
2252 {
2253 const SelectionType nSelectionType = rSh.GetSelectionType();
2254 if(nSelectionType & SelectionType::Frame)
2255 eKeyState = SwKeyState::GoIntoFly;
2256 else
2257 {
2258 SfxItemSet aSet(rSh.GetAttrPool(), svl::Items<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT>{});
2259 rSh.GetCurAttr(aSet);
2260 if(SfxItemState::SET == aSet.GetItemState(RES_TXTATR_INETFMT, false))
2261 {
2262 const SfxPoolItem& rItem = aSet.Get(RES_TXTATR_INETFMT);
2263 bNormalChar = false;
2264 eKeyState = SwKeyState::End;
2265 rSh.ClickToINetAttr(static_cast<const SwFormatINetFormat&>(rItem));
2266 }
2267 }
2268 }
2269 break;
2270 }
2271 }
2272 break;
2273
2274 case SwKeyState::EnterCharCell:
2275 {
2276 eKeyState = SwKeyState::KeyToView;
2277 switch ( rKeyCode.GetModifier() | rKeyCode.GetCode() )
2278 {
2279 case KEY_RIGHT | KEY_MOD2:
2280 rSh.Right( CRSR_SKIP_CHARS, false, 1, false );
2281 eKeyState = SwKeyState::End;
2282 FlushInBuffer();
2283 break;
2284 case KEY_LEFT | KEY_MOD2:
2285 rSh.Left( CRSR_SKIP_CHARS, false, 1, false );
2286 eKeyState = SwKeyState::End;
2287 FlushInBuffer();
2288 break;
2289 }
2290 }
2291 break;
2292
2293 case SwKeyState::KeyToView:
2294 {
2295 eKeyState = SwKeyState::End;
2296 bNormalChar =
2297 !rKeyCode.IsMod2() &&
2298 rKeyCode.GetModifier() != KEY_MOD1 &&
2299 rKeyCode.GetModifier() != (KEY_MOD1|KEY_SHIFT) &&
2300 SW_ISPRINTABLE( aCh );
2301
2302 if( bNormalChar && rSh.IsInFrontOfLabel() )
2303 {
2304 rSh.NumOrNoNum();
2305 }
2306
2307 if( !m_aInBuffer.isEmpty() && ( !bNormalChar || bIsDocReadOnly ))
2308 FlushInBuffer();
2309
2310 if (rSh.HasReadonlySel()
2311 && ( rKeyCode.GetFunction() == KeyFuncType::PASTE
2312 || rKeyCode.GetFunction() == KeyFuncType::CUT))
2313 {
2314 auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog"));
2315 weld::DialogController::runAsync(xInfo, [](int) {});
2316 eKeyState = SwKeyState::End;
2317 }
2318 else if( m_rView.KeyInput( aKeyEvent ) )
2319 {
2320 bFlushBuffer = true;
2321 bNormalChar = false;
2322 }
2323 else
2324 {
2325 // Because Sfx accelerators are only called when they were
2326 // enabled at the last status update, copy has to called
2327 // 'forcefully' by us if necessary.
2328 if( rKeyCode.GetFunction() == KeyFuncType::COPY )
2329 GetView().GetViewFrame()->GetBindings().Execute(SID_COPY(5000 + 711));
2330
2331 if( !bIsDocReadOnly && bNormalChar )
2332 {
2333 const SelectionType nSelectionType = rSh.GetSelectionType();
2334 const bool bDrawObject = (nSelectionType & SelectionType::DrawObject) &&
2335 !(nSelectionType & SelectionType::DrawObjectEditMode) &&
2336 rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1;
2337
2338 bool bTextBox = false;
2339 if (bDrawObject && lcl_goIntoTextBox(*this, rSh))
2340 // A draw shape was selected, but it has a TextBox,
2341 // start editing that instead when the normal
2342 // character is pressed.
2343 bTextBox = true;
2344
2345 if (bDrawObject && !bTextBox)
2346 {
2347 SdrObject* pObj = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
2348 if(pObj)
2349 {
2350 EnterDrawTextMode(pObj->GetLogicRect().Center());
2351 if ( dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr )
2352 static_cast<SwDrawTextShell*>(m_rView.GetCurShell())->Init();
2353 rSh.GetDrawView()->KeyInput( rKEvt, this );
2354 }
2355 }
2356 else if (nSelectionType & SelectionType::Frame || bTextBox)
2357 {
2358 rSh.UnSelectFrame();
2359 rSh.LeaveSelFrameMode();
2360 m_rView.AttrChangedNotify(nullptr);
2361 rSh.MoveSection( GoCurrSection, fnSectionEnd );
2362 }
2363 eKeyState = SwKeyState::InsChar;
2364 }
2365 else
2366 {
2367 bNormalChar = false;
2368 Window::KeyInput( aKeyEvent );
2369 }
2370 }
2371 }
2372 break;
2373 case SwKeyState::LaunchOLEObject:
2374 {
2375 rSh.LaunchOLEObj();
2376 eKeyState = SwKeyState::End;
2377 }
2378 break;
2379 case SwKeyState::GoIntoFly:
2380 {
2381 rSh.UnSelectFrame();
2382 rSh.LeaveSelFrameMode();
2383 m_rView.AttrChangedNotify(nullptr);
2384 rSh.MoveSection( GoCurrSection, fnSectionEnd );
2385 eKeyState = SwKeyState::End;
2386 }
2387 break;
2388 case SwKeyState::GoIntoDrawing:
2389 {
2390 if (SdrMark* pMark = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0))
2391 {
2392 SdrObject* pObj = pMark->GetMarkedSdrObj();
2393 if(pObj)
2394 {
2395 EnterDrawTextMode(pObj->GetLogicRect().Center());
2396 if (dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr )
2397 static_cast<SwDrawTextShell*>(m_rView.GetCurShell())->Init();
2398 }
2399 }
2400 eKeyState = SwKeyState::End;
2401 }
2402 break;
2403 case SwKeyState::EnterDrawHandleMode:
2404 {
2405 const SdrHdlList& rHdlList = rSh.GetDrawView()->GetHdlList();
2406 bool bForward(!aKeyEvent.GetKeyCode().IsShift());
2407
2408 const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward);
2409 eKeyState = SwKeyState::End;
2410 }
2411 break;
2412 case SwKeyState::InsTab:
2413 if( dynamic_cast<const SwWebView*>( &m_rView) != nullptr) // no Tab for WebView
2414 {
2415 // then it should be passed along
2416 Window::KeyInput( aKeyEvent );
2417 eKeyState = SwKeyState::End;
2418 break;
2419 }
2420 aCh = '\t';
2421 [[fallthrough]];
2422 case SwKeyState::InsChar:
2423 if (rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENTu'\x0006')
2424 {
2425 ::sw::mark::ICheckboxFieldmark* pFieldmark =
2426 dynamic_cast< ::sw::mark::ICheckboxFieldmark* >
2427 (rSh.GetCurrentFieldmark());
2428 OSL_ENSURE(pFieldmark,do { if (true && (!(pFieldmark))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
":" "2429" ": "), "%s", "Where is my FieldMark??"); } } while
(false)
2429 "Where is my FieldMark??")do { if (true && (!(pFieldmark))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
":" "2429" ": "), "%s", "Where is my FieldMark??"); } } while
(false)
;
2430 if(pFieldmark)
2431 {
2432 pFieldmark->SetChecked(!pFieldmark->IsChecked());
2433 OSL_ENSURE(pFieldmark->IsExpanded(),do { if (true && (!(pFieldmark->IsExpanded()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
":" "2434" ": "), "%s", "where is the otherpos?"); } } while
(false)
2434 "where is the otherpos?")do { if (true && (!(pFieldmark->IsExpanded()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
":" "2434" ": "), "%s", "where is the otherpos?"); } } while
(false)
;
2435 if (pFieldmark->IsExpanded())
2436 {
2437 rSh.CalcLayout();
2438 }
2439 }
2440 eKeyState = SwKeyState::End;
2441 }
2442 else if ( !rSh.HasReadonlySel()
2443 || rSh.CursorInsideInputField() )
2444 {
2445 const bool bIsNormalChar =
2446 GetAppCharClass().isLetterNumeric( OUString( aCh ), 0 );
2447 if( bAppendSpace && bIsNormalChar &&
2448 (!m_aInBuffer.isEmpty() || !rSh.IsSttPara() || !rSh.IsEndPara() ))
2449 {
2450 // insert a blank ahead of the character. this ends up
2451 // between the expanded text and the new "non-word-separator".
2452 m_aInBuffer += " ";
2453 }
2454
2455 const bool bIsAutoCorrectChar = SvxAutoCorrect::IsAutoCorrectChar( aCh );
2456 if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) &&
2457 pACfg->IsAutoFormatByInput() &&
2458 (( pACorr->IsAutoCorrFlag( ACFlags::ChgWeightUnderl ) &&
2459 ( '*' == aCh || '_' == aCh ) ) ||
2460 ( pACorr->IsAutoCorrFlag( ACFlags::ChgQuotes ) && ('\"' == aCh ))||
2461 ( pACorr->IsAutoCorrFlag( ACFlags::ChgSglQuotes ) && ( '\'' == aCh))))
2462 {
2463 FlushInBuffer();
2464 rSh.AutoCorrect( *pACorr, aCh );
2465 if( '\"' != aCh && '\'' != aCh ) // only call when "*_"!
2466 rSh.UpdateAttr();
2467 }
2468 else if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) &&
2469 pACfg->IsAutoFormatByInput() &&
2470 pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
2471 ACFlags::ChgOrdinalNumber | ACFlags::AddNonBrkSpace |
2472 ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr |
2473 ACFlags::Autocorrect | ACFlags::TransliterateRTL ) &&
2474 '\"' != aCh && '\'' != aCh && '*' != aCh && '_' != aCh
2475 )
2476 {
2477 FlushInBuffer();
2478 rSh.AutoCorrect( *pACorr, aCh );
2479 }
2480 else
2481 {
2482 OUStringBuffer aBuf(m_aInBuffer);
2483 comphelper::string::padToLength(aBuf,
2484 m_aInBuffer.getLength() + aKeyEvent.GetRepeat() + 1, aCh);
2485 m_aInBuffer = aBuf.makeStringAndClear();
2486 g_bFlushCharBuffer = Application::AnyInput( VclInputFlags::KEYBOARD );
2487 bFlushBuffer = !g_bFlushCharBuffer;
2488 if( g_bFlushCharBuffer )
2489 m_aKeyInputFlushTimer.Start();
2490 }
2491 eKeyState = SwKeyState::End;
2492 }
2493 else
2494 {
2495 auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog"));
2496 weld::DialogController::runAsync(xInfo, [](int) {});
2497 eKeyState = SwKeyState::End;
2498 }
2499 break;
2500
2501 case SwKeyState::CheckAutoCorrect:
2502 {
2503 if( pACorr && pACfg->IsAutoFormatByInput() &&
2504 pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
2505 ACFlags::ChgOrdinalNumber | ACFlags::TransliterateRTL |
2506 ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr |
2507 ACFlags::Autocorrect ) &&
2508 !rSh.HasReadonlySel() )
2509 {
2510 FlushInBuffer();
2511 rSh.AutoCorrect( *pACorr, u'\0' );
2512 }
2513 eKeyState = eNextKeyState;
2514 }
2515 break;
2516
2517 default:
2518 {
2519 sal_uInt16 nSlotId = 0;
2520 FlushInBuffer();
2521 switch( eKeyState )
2522 {
2523 case SwKeyState::SpecialInsert:
2524 rSh.DoSpecialInsert();
2525 break;
2526
2527 case SwKeyState::NoNum:
2528 rSh.NoNum();
2529 break;
2530
2531 case SwKeyState::NumOff:
2532 // shell change - so record in advance
2533 rSh.DelNumRules();
2534 break;
2535 case SwKeyState::OutlineLvOff: // delete autofmt outlinelevel later
2536 break;
2537
2538 case SwKeyState::NumDown:
2539 rSh.NumUpDown();
2540 m_nKS_NUMDOWN_Count = 2;
2541 break;
2542 case SwKeyState::NumUp:
2543 rSh.NumUpDown( false );
2544 break;
2545
2546 case SwKeyState::NumIndentInc:
2547 rSh.ChangeIndentOfAllListLevels(360);
2548 m_nKS_NUMINDENTINC_Count = 2;
2549 break;
2550
2551 case SwKeyState::GotoNextFieldMark:
2552 {
2553 ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkAfter();
2554 if(pFieldmark) rSh.GotoFieldmark(pFieldmark);
2555 }
2556 break;
2557
2558 case SwKeyState::GotoPrevFieldMark:
2559 {
2560 ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkBefore();
2561 if( pFieldmark )
2562 rSh.GotoFieldmark(pFieldmark);
2563 }
2564 break;
2565
2566 case SwKeyState::NumIndentDec:
2567 rSh.ChangeIndentOfAllListLevels(-360);
2568 break;
2569
2570 case SwKeyState::OutlineDown:
2571 rSh.OutlineUpDown();
2572 break;
2573 case SwKeyState::OutlineUp:
2574 rSh.OutlineUpDown( -1 );
2575 break;
2576
2577 case SwKeyState::NextCell:
2578 // always 'flush' in tables
2579 rSh.GoNextCell(!rSh.HasReadonlySel());
2580 nSlotId = FN_GOTO_NEXT_CELL((20000 + 400) + 145);
2581 break;
2582 case SwKeyState::PrevCell:
2583 rSh.GoPrevCell();
2584 nSlotId = FN_GOTO_PREV_CELL((20000 + 400) + 146);
2585 break;
2586 case SwKeyState::AutoFormatByInput:
2587 rSh.SplitNode( true );
2588 break;
2589
2590 case SwKeyState::NextObject:
2591 case SwKeyState::PrevObject:
2592 if(rSh.GotoObj( SwKeyState::NextObject == eKeyState, GotoObjFlags::Any))
2593 {
2594 if( rSh.IsFrameSelected() &&
2595 m_rView.GetDrawFuncPtr() )
2596 {
2597 m_rView.GetDrawFuncPtr()->Deactivate();
2598 m_rView.SetDrawFuncPtr(nullptr);
2599 m_rView.LeaveDrawCreate();
2600 m_rView.AttrChangedNotify(nullptr);
2601 }
2602 rSh.HideCursor();
2603 rSh.EnterSelFrameMode();
2604 }
2605 break;
2606 case SwKeyState::GlossaryExpand:
2607 {
2608 // replace the word or abbreviation with the auto text
2609 rSh.StartUndo( SwUndoId::START );
2610
2611 OUString sFnd(aTmpQHD.CurStr());
2612 if( aTmpQHD.m_bIsAutoText )
2613 {
2614 SwGlossaryList* pList = ::GetGlossaryList();
2615 OUString sShrtNm;
2616 OUString sGroup;
2617 if(pList->GetShortName( sFnd, sShrtNm, sGroup))
2618 {
2619 rSh.SttSelect();
2620 rSh.ExtendSelection(false, aTmpQHD.CurLen());
2621 SwGlossaryHdl* pGlosHdl = GetView().GetGlosHdl();
2622 pGlosHdl->SetCurGroup(sGroup, true);
2623 pGlosHdl->InsertGlossary( sShrtNm);
2624 m_pQuickHlpData->m_bAppendSpace = true;
2625 }
2626 }
2627 else
2628 {
2629 sFnd = sFnd.copy(aTmpQHD.CurLen());
2630 rSh.Insert( sFnd );
2631 m_pQuickHlpData->m_bAppendSpace = !pACorr ||
2632 pACorr->GetSwFlags().bAutoCmpltAppendBlanc;
2633 }
2634 rSh.EndUndo( SwUndoId::END );
2635 }
2636 break;
2637
2638 case SwKeyState::NextPrevGlossary:
2639 m_pQuickHlpData->Move( aTmpQHD );
2640 m_pQuickHlpData->Start(rSh, false);
2641 break;
2642
2643 case SwKeyState::EditFormula:
2644 {
2645 const sal_uInt16 nId = SwInputChild::GetChildWindowId();
2646
2647 SfxViewFrame* pVFrame = GetView().GetViewFrame();
2648 pVFrame->ToggleChildWindow( nId );
2649 SwInputChild* pChildWin = static_cast<SwInputChild*>(pVFrame->
2650 GetChildWindow( nId ));
2651 if( pChildWin )
2652 pChildWin->SetFormula( sFormulaEntry );
2653 }
2654 break;
2655
2656 case SwKeyState::ColLeftBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2657 case SwKeyState::ColRightBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2658 case SwKeyState::ColLeftSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft, pModOpt->GetTableHMove() ); break;
2659 case SwKeyState::ColRightSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight, pModOpt->GetTableHMove() ); break;
2660 case SwKeyState::ColBottomBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2661 case SwKeyState::ColBottomSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom, pModOpt->GetTableVMove() ); break;
2662 case SwKeyState::CellLeftBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2663 case SwKeyState::CellRightBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2664 case SwKeyState::CellLeftSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft, pModOpt->GetTableHMove() ); break;
2665 case SwKeyState::CellRightSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight, pModOpt->GetTableHMove() ); break;
2666 case SwKeyState::CellTopBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2667 case SwKeyState::CellBottomBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2668 case SwKeyState::CellTopSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop, pModOpt->GetTableVMove() ); break;
2669 case SwKeyState::CellBottomSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom, pModOpt->GetTableVMove() ); break;
2670
2671 case SwKeyState::Fly_Change:
2672 {
2673 SdrView *pSdrView = rSh.GetDrawView();
2674 const SdrHdlList& rHdlList = pSdrView->GetHdlList();
2675 if(rHdlList.GetFocusHdl())
2676 ChangeDrawing( nDir );
2677 else
2678 ChangeFly( nDir, dynamic_cast<const SwWebView*>( &m_rView) != nullptr );
2679 }
2680 break;
2681 case SwKeyState::Draw_Change :
2682 ChangeDrawing( nDir );
2683 break;
2684 default:
2685 break;
2686 }
2687 if( nSlotId && m_rView.GetViewFrame()->GetBindings().GetRecorder().is() )
2688 {
2689 SfxRequest aReq(m_rView.GetViewFrame(), nSlotId );
2690 aReq.Done();
2691 }
2692 eKeyState = SwKeyState::End;
2693 }
2694 }
2695 }
2696
2697 // x11 backend doesn't like not having this
2698 if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
2699 GetFrameControlsManager().SetOutlineContentVisibilityButtons();
2700
2701 // update the page number in the statusbar
2702 sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
2703 if( KEY_UP == nKey || KEY_DOWN == nKey || KEY_PAGEUP == nKey || KEY_PAGEDOWN == nKey )
2704 GetView().GetViewFrame()->GetBindings().Update( FN_STAT_PAGE((20000 + 1180) + 1) );
2705
2706 // in case the buffered characters are inserted
2707 if( bFlushBuffer && !m_aInBuffer.isEmpty() )
2708 {
2709 // bFlushCharBuffer was not reset here
2710 // why not?
2711 bool bSave = g_bFlushCharBuffer;
2712 FlushInBuffer();
2713 g_bFlushCharBuffer = bSave;
2714
2715 // maybe show Tip-Help
2716 if (bNormalChar)
2717 {
2718 const bool bAutoTextShown
2719 = pACfg && pACfg->IsAutoTextTip() && ShowAutoText(rSh.GetChunkForAutoText());
2720 if (!bAutoTextShown && pACorr && pACorr->GetSwFlags().bAutoCompleteWords)
2721 ShowAutoCorrectQuickHelp(rSh.GetPrevAutoCorrWord(*pACorr), *pACorr);
2722 }
2723 }
2724
2725 // get the word count dialog to update itself
2726 SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
2727 if( pWrdCnt )
2728 pWrdCnt->UpdateCounts();
2729
2730}
2731
2732/**
2733 * MouseEvents
2734 */
2735void SwEditWin::RstMBDownFlags()
2736{
2737 // Not on all systems a MouseButtonUp is used ahead
2738 // of the modal dialog (like on WINDOWS).
2739 // So reset the statuses here and release the mouse
2740 // for the dialog.
2741 m_bMBPressed = false;
2742 g_bNoInterrupt = false;
2743 EnterArea();
2744 ReleaseMouse();
2745}
2746
2747/**
2748 * Determines if the current position has a clickable url over a background
2749 * frame. In that case, ctrl-click should select the url, not the frame.
2750 */
2751static bool lcl_urlOverBackground(SwWrtShell& rSh, const Point& rDocPos)
2752{
2753 SwContentAtPos aSwContentAtPos(IsAttrAtPos::InetAttr);
2754 SdrObject* pSelectableObj = rSh.GetObjAt(rDocPos);
2755
2756 return rSh.GetContentAtPos(rDocPos, aSwContentAtPos) && pSelectableObj->GetLayer() == rSh.GetDoc()->getIDocumentDrawModelAccess().GetHellId();
2757}
2758
2759void SwEditWin::MoveCursor( SwWrtShell &rSh, const Point& rDocPos,
2760 const bool bOnlyText, bool bLockView )
2761{
2762 const bool bTmpNoInterrupt = g_bNoInterrupt;
2763 g_bNoInterrupt = false;
2764
2765 int nTmpSetCursor = 0;
2766
2767 if( !rSh.IsViewLocked() && bLockView )
2768 rSh.LockView( true );
2769 else
2770 bLockView = false;
2771
2772 {
2773 // only temporary generate move context because otherwise
2774 // the query to the content form doesn't work!!!
2775 SwMvContext aMvContext( &rSh );
2776 nTmpSetCursor = rSh.CallSetCursor(&rDocPos, bOnlyText);
2777 g_bValidCursorPos = !(CRSR_POSCHG & nTmpSetCursor);
2778 }
2779
2780 // notify the edit window that from now on we do not use the input language
2781 if ( !(CRSR_POSOLD & nTmpSetCursor) )
2782 SetUseInputLanguage( false );
2783
2784 if( bLockView )
2785 rSh.LockView( false );
2786
2787 g_bNoInterrupt = bTmpNoInterrupt;
2788}
2789
2790void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt)
2791{
2792 SwWrtShell &rSh = m_rView.GetWrtShell();
2793 const SwField *pCursorField = rSh.CursorInsideInputField() ? rSh.GetCurField( true ) : nullptr;
2794
2795 // We have to check if a context menu is shown and we have an UI
2796 // active inplace client. In that case we have to ignore the mouse
2797 // button down event. Otherwise we would crash (context menu has been
2798 // opened by inplace client and we would deactivate the inplace client,
2799 // the context menu is closed by VCL asynchronously which in the end
2800 // would work on deleted objects or the context menu has no parent anymore)
2801 SfxInPlaceClient* pIPClient = rSh.GetSfxViewShell()->GetIPClient();
2802 bool bIsOleActive = ( pIPClient && pIPClient->IsObjectInPlaceActive() );
2803
2804 if ( bIsOleActive && PopupMenu::IsInExecute() )
2805 return;
2806
2807 MouseEvent rMEvt(_rMEvt);
2808
2809 if (m_rView.GetPostItMgr()->IsHit(rMEvt.GetPosPixel()))
2810 return;
2811
2812 if (comphelper::LibreOfficeKit::isActive())
2813 {
2814 if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
2815 {
2816 pWindow->MouseButtonDown(rMEvt);
2817 return;
2818 }
2819 }
2820
2821 m_rView.GetPostItMgr()->SetActiveSidebarWin(nullptr);
2822
2823 GrabFocus();
2824
2825 //ignore key modifiers for format paintbrush
2826 {
2827 bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard
2828 && m_pApplyTempl->m_pFormatClipboard->HasContent();
2829 if( bExecFormatPaintbrush )
2830 rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(),
2831 _rMEvt.GetMode(), _rMEvt.GetButtons() );
2832 }
2833
2834 m_bWasShdwCursor = nullptr != m_pShadCursor;
2835 m_pShadCursor.reset();
2836
2837 const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) );
2838
2839 FrameControlType eControl;
2840 bool bOverFly = false;
2841 bool bPageAnchored = false;
2842 bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored );
2843
2844 bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly();
2845 if (bOverHeaderFooterFly && (!bIsDocReadOnly && rSh.GetCurField()))
2846 // We have a field here, that should have priority over header/footer fly.
2847 bOverHeaderFooterFly = false;
2848
2849 // Are we clicking on a blank header/footer area?
2850 if ( IsInHeaderFooter( aDocPos, eControl ) || bOverHeaderFooterFly )
2851 {
2852 const SwPageFrame* pPageFrame = rSh.GetLayout()->GetPageAtPos( aDocPos );
2853
2854 // Is it active?
2855 bool bActive = true;
2856 const SwPageDesc* pDesc = pPageFrame->GetPageDesc();
2857
2858 const SwFrameFormat* pFormat = pDesc->GetLeftFormat();
2859 if ( pPageFrame->OnRightPage() )
2860 pFormat = pDesc->GetRightFormat();
2861
2862 if ( pFormat )
2863 {
2864 if ( eControl == FrameControlType::Header )
2865 bActive = pFormat->GetHeader().IsActive();
2866 else
2867 bActive = pFormat->GetFooter().IsActive();
2868 }
2869
2870 if ( !bActive )
2871 {
2872 // When in Hide-Whitespace mode, we don't want header
2873 // and footer controls.
2874 if (!rSh.GetViewOptions()->IsHideWhitespaceMode())
2875 {
2876 SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint());
2877 const bool bWasInHeader = aPam.GetPoint()->nNode.GetNode().FindHeaderStartNode() != nullptr;
2878 const bool bWasInFooter = aPam.GetPoint()->nNode.GetNode().FindFooterStartNode() != nullptr;
2879
2880 // Is the cursor in a part like similar to the one we clicked on? For example,
2881 // if the cursor is in a header and we click on an empty header... don't change anything to
2882 // keep consistent behaviour due to header edit mode (and the same for the footer as well).
2883
2884 // Otherwise, we hide the header/footer control if a separator is shown, and vice versa.
2885 if (!(bWasInHeader && eControl == FrameControlType::Header) &&
2886 !(bWasInFooter && eControl == FrameControlType::Footer))
2887 {
2888 const bool bSeparatorWasVisible = rSh.IsShowHeaderFooterSeparator(eControl);
2889 rSh.SetShowHeaderFooterSeparator(eControl, !bSeparatorWasVisible);
2890
2891 // Repaint everything
2892 Invalidate();
2893
2894 // tdf#84929. If the footer control had not been showing, do not change the cursor position,
2895 // because the user may have scrolled to turn on the separator control and
2896 // if the cursor cannot be positioned on-screen, then the user would need to scroll back again to use the control.
2897 // This should only be done for the footer. The cursor can always be re-positioned near the header. tdf#134023.
2898 if ( eControl == FrameControlType::Footer && !bSeparatorWasVisible
2899 && rSh.GetViewOptions()->IsUseHeaderFooterMenu() && !Application::IsHeadlessModeEnabled() )
2900 return;
2901 }
2902 }
2903 }
2904 else
2905 {
2906 // Make sure we have the proper Header/Footer separators shown
2907 // as these may be changed if clicking on an empty Header/Footer
2908 rSh.SetShowHeaderFooterSeparator( FrameControlType::Header, eControl == FrameControlType::Header );
2909 rSh.SetShowHeaderFooterSeparator( FrameControlType::Footer, eControl == FrameControlType::Footer );
2910
2911 if ( !rSh.IsHeaderFooterEdit() )
2912 {
2913 rSh.ToggleHeaderFooterEdit();
2914
2915 // Repaint everything
2916 rSh.GetWin()->Invalidate();
2917 }
2918 }
2919 }
2920 else
2921 {
2922 if ( rSh.IsHeaderFooterEdit( ) )
2923 rSh.ToggleHeaderFooterEdit( );
2924 else
2925 {
2926 // Make sure that the separators are hidden
2927 rSh.SetShowHeaderFooterSeparator( FrameControlType::Header, false );
2928 rSh.SetShowHeaderFooterSeparator( FrameControlType::Footer, false );
2929
2930 // Repaint everything
2931 // FIXME fdo#67358 for unknown reasons this causes painting
2932 // problems when resizing table columns, so disable it
2933// rSh.GetWin()->Invalidate();
2934 }
2935
2936 // Toggle Hide-Whitespace if between pages.
2937 if (rSh.GetViewOptions()->CanHideWhitespace() &&
2938 rSh.GetLayout()->IsBetweenPages(aDocPos))
2939 {
2940 if (_rMEvt.GetClicks() >= 2)
2941 {
2942 SwViewOption aOpt(*rSh.GetViewOptions());
2943 aOpt.SetHideWhitespaceMode(!aOpt.IsHideWhitespaceMode());
2944 rSh.ApplyViewOptions(aOpt);
2945 }
2946
2947 return;
2948 }
2949 }
2950
2951 if ( IsChainMode() )
2952 {
2953 SetChainMode( false );
2954 SwRect aDummy;
2955 SwFlyFrameFormat *pFormat = static_cast<SwFlyFrameFormat*>(rSh.GetFlyFrameFormat());
2956 if ( rSh.Chainable( aDummy, *pFormat, aDocPos ) == SwChainRet::OK )
2957 rSh.Chain( *pFormat, aDocPos );
2958 UpdatePointer( aDocPos, rMEvt.GetModifier() );
2959 return;
2960 }
2961
2962 // After GrabFocus a shell should be pushed. That should actually
2963 // work but in practice ...
2964 m_rView.SelectShellForDrop();
2965
2966 bool bCallBase = true;
2967
2968 if( m_pQuickHlpData->m_bIsDisplayed )
2969 m_pQuickHlpData->Stop( rSh );
2970 m_pQuickHlpData->m_bAppendSpace = false;
2971
2972 if( rSh.FinishOLEObj() )
2973 return; // end InPlace and the click doesn't count anymore
2974
2975 CurrShell aCurr( &rSh );
2976
2977 SdrView *pSdrView = rSh.GetDrawView();
2978 if ( pSdrView )
2979 {
2980 if (pSdrView->MouseButtonDown( rMEvt, this ) )
2981 {
2982 rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
2983 return; // SdrView's event evaluated
2984 }
2985 }
2986
2987 m_bIsInMove = false;
2988 m_aStartPos = rMEvt.GetPosPixel();
2989 m_aRszMvHdlPt.setX( 0 );
2990 m_aRszMvHdlPt.setY( 0 );
2991
2992 SwTab nMouseTabCol = SwTab::COL_NONE;
2993 const bool bTmp = !rSh.IsDrawCreate() && !m_pApplyTempl && !rSh.IsInSelect() &&
2994 rMEvt.GetClicks() == 1 && MOUSE_LEFT(sal_uInt16(0x0001)) == rMEvt.GetButtons();
2995 if ( bTmp &&
2996 SwTab::COL_NONE != (nMouseTabCol = rSh.WhichMouseTabCol( aDocPos ) ) &&
2997 !rSh.IsObjSelectable( aDocPos ) )
2998 {
2999 // Enhanced table selection
3000 if ( SwTab::SEL_HORI <= nMouseTabCol && SwTab::COLSEL_VERT >= nMouseTabCol )
3001 {
3002 rSh.EnterStdMode();
3003 rSh.SelectTableRowCol( aDocPos );
3004 if( SwTab::SEL_HORI != nMouseTabCol && SwTab::SEL_HORI_RTL != nMouseTabCol)
3005 {
3006 m_xRowColumnSelectionStart = aDocPos;
3007 m_bIsRowDrag = SwTab::ROWSEL_HORI == nMouseTabCol||
3008 SwTab::ROWSEL_HORI_RTL == nMouseTabCol ||
3009 SwTab::COLSEL_VERT == nMouseTabCol;
3010 m_bMBPressed = true;
3011 CaptureMouse();
3012 }
3013 return;
3014 }
3015
3016 if ( !rSh.IsTableMode() )
3017 {
3018 // comes from table columns out of the document.
3019 if(SwTab::COL_VERT == nMouseTabCol || SwTab::COL_HORI == nMouseTabCol)
3020 m_rView.SetTabColFromDoc( true );
3021 else
3022 m_rView.SetTabRowFromDoc( true );
3023
3024 m_rView.SetTabColFromDocPos( aDocPos );
3025 m_rView.InvalidateRulerPos();
3026 SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
3027 rBind.Update();
3028 if ( RulerColumnDrag( rMEvt,
3029 (SwTab::COL_VERT == nMouseTabCol || SwTab::ROW_HORI == nMouseTabCol)) )
3030 {
3031 m_rView.SetTabColFromDoc( false );
3032 m_rView.SetTabRowFromDoc( false );
3033 m_rView.InvalidateRulerPos();
3034 rBind.Update();
3035 bCallBase = false;
3036 }
3037 else
3038 {
3039 return;
3040 }
3041 }
3042 }
3043 else if (bTmp &&
3044 rSh.IsNumLabel(aDocPos))
3045 {
3046 SwTextNode* pNodeAtPos = rSh.GetNumRuleNodeAtPos( aDocPos );
3047 m_rView.SetNumRuleNodeFromDoc( pNodeAtPos );
3048 m_rView.InvalidateRulerPos();
3049 SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
3050 rBind.Update();
3051
3052 if ( RulerMarginDrag( rMEvt,
3053 SwFEShell::IsVerticalModeAtNdAndPos( *pNodeAtPos, aDocPos ) ) )
3054 {
3055 m_rView.SetNumRuleNodeFromDoc( nullptr );
3056 m_rView.InvalidateRulerPos();
3057 rBind.Update();
3058 bCallBase = false;
3059 }
3060 else
3061 {
3062 // Make sure the pointer is set to 0, otherwise it may point to
3063 // nowhere after deleting the corresponding text node.
3064 m_rView.SetNumRuleNodeFromDoc( nullptr );
3065 return;
3066 }
3067 }
3068
3069 if ( rSh.IsInSelect() )
3070 rSh.EndSelect();
3071
3072 // query against LEFT because otherwise for example also a right
3073 // click releases the selection.
3074 if ( MOUSE_LEFT(sal_uInt16(0x0001)) == rMEvt.GetButtons() )
3075 {
3076 bool bOnlyText = false;
3077 m_bMBPressed = true;
3078 g_bNoInterrupt = true;
3079 m_nKS_NUMDOWN_Count = 0;
3080
3081 CaptureMouse();
3082
3083 // reset cursor position if applicable
3084 rSh.ResetCursorStack();
3085
3086 switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
3087 {
3088 case MOUSE_LEFT(sal_uInt16(0x0001)):
3089 case MOUSE_LEFT(sal_uInt16(0x0001)) + KEY_SHIFT:
3090 case MOUSE_LEFT(sal_uInt16(0x0001)) + KEY_MOD2:
3091 if( rSh.IsObjSelected() )
3092 {
3093 SdrHdl* pHdl;
3094 if( !bIsDocReadOnly &&
3095 !m_pAnchorMarker &&
3096 pSdrView &&
3097 nullptr != ( pHdl = pSdrView->PickHandle(aDocPos) ) &&
3098 ( pHdl->GetKind() == SdrHdlKind::Anchor ||
3099 pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
3100 {
3101 // #i121463# Set selected during drag
3102 pHdl->SetSelected();
3103 m_pAnchorMarker.reset( new SwAnchorMarker( pHdl ) );
3104 UpdatePointer( aDocPos, rMEvt.GetModifier() );
3105 return;
3106 }
3107 }
3108 if ( EnterDrawMode( rMEvt, aDocPos ) )
3109 {
3110 g_bNoInterrupt = false;
3111 return;
3112 }
3113 else if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
3114 {
3115 StopInsFrame();
3116 rSh.Edit();
3117 }
3118
3119 // Without SHIFT because otherwise Toggle doesn't work at selection
3120 if (rMEvt.GetClicks() == 1)
3121 {
3122 if ( rSh.IsSelFrameMode())
3123 {
3124 SdrHdl* pHdl = rSh.GetDrawView()->PickHandle(aDocPos);
3125 bool bHitHandle = pHdl && pHdl->GetKind() != SdrHdlKind::Anchor &&
3126 pHdl->GetKind() != SdrHdlKind::Anchor_TR;
3127
3128 if ((rSh.IsInsideSelectedObj(aDocPos) || bHitHandle) &&
3129 (rMEvt.GetModifier() != KEY_SHIFT || bHitHandle))
3130 {
3131 rSh.EnterSelFrameMode( &aDocPos );
3132 if ( !m_pApplyTempl )
3133 {
3134 // only if no position to size was hit.
3135 if (!bHitHandle)
3136 {
3137 StartDDTimer();
3138 SwEditWin::m_nDDStartPosY = aDocPos.Y();
3139 SwEditWin::m_nDDStartPosX = aDocPos.X();
3140 }
3141 g_bFrameDrag = true;
3142 }
3143 g_bNoInterrupt = false;
3144 return;
3145 }
3146 }
3147 }
3148 }
3149
3150 bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
3151 if ( !bExecHyperlinks )
3152 {
3153 SvtSecurityOptions aSecOpts;
3154 const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
3155 if ( ( bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) ||
3156 ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) )
3157 bExecHyperlinks = true;
3158 }
3159
3160 // Enhanced selection
3161 sal_uInt8 nNumberOfClicks = static_cast< sal_uInt8 >(rMEvt.GetClicks() % 4);
3162 if ( 0 == nNumberOfClicks && 0 < rMEvt.GetClicks() )
3163 nNumberOfClicks = 4;
3164
3165 bool bExecDrawTextLink = false;
3166
3167 switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
3168 {
3169 case MOUSE_LEFT(sal_uInt16(0x0001)):
3170 case MOUSE_LEFT(sal_uInt16(0x0001)) + KEY_MOD1:
3171 case MOUSE_LEFT(sal_uInt16(0x0001)) + KEY_MOD2:
3172 {
3173
3174 // fdo#79604: first, check if a link has been clicked - do not
3175 // select fly in this case!
3176 if (1 == nNumberOfClicks)
3177 {
3178 UpdatePointer( aDocPos, rMEvt.GetModifier() );
3179 SwEditWin::m_nDDStartPosY = aDocPos.Y();
3180 SwEditWin::m_nDDStartPosX = aDocPos.X();
3181
3182 // hit a URL in DrawText object?
3183 if (bExecHyperlinks && pSdrView)
3184 {
3185 SdrViewEvent aVEvt;
3186 pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
3187
3188 if (aVEvt.eEvent == SdrEventKind::ExecuteUrl)
3189 bExecDrawTextLink = true;
3190 }
3191 }
3192
3193 if (1 == nNumberOfClicks && !bExecDrawTextLink)
3194 {
3195 // only try to select frame, if pointer already was
3196 // switched accordingly
3197 if ( m_aActHitType != SdrHitKind::NONE && !rSh.IsSelFrameMode() &&
3198 !GetView().GetViewFrame()->GetDispatcher()->IsLocked())
3199 {
3200 // Test if there is a draw object at that position and if it should be selected.
3201 bool bShould = rSh.ShouldObjectBeSelected(aDocPos);
3202
3203 if(bShould)
3204 {
3205 m_rView.NoRotate();
3206 rSh.HideCursor();
3207
3208 bool bUnLockView = !rSh.IsViewLocked();
3209 rSh.LockView( true );
3210 bool bSelObj = rSh.SelectObj( aDocPos,
3211 rMEvt.IsMod1() ? SW_ENTER_GROUP2 : 0);
3212 if( bUnLockView )
3213 rSh.LockView( false );
3214
3215 if( bSelObj )
3216 {
3217 // if the frame was deselected in the macro
3218 // the cursor just has to be displayed again
3219 if( FrameTypeFlags::NONE == rSh.GetSelFrameType() )
3220 rSh.ShowCursor();
3221 else
3222 {
3223 if (rSh.IsFrameSelected() && m_rView.GetDrawFuncPtr())
3224 {
3225 m_rView.GetDrawFuncPtr()->Deactivate();
3226 m_rView.SetDrawFuncPtr(nullptr);
3227 m_rView.LeaveDrawCreate();
3228 m_rView.AttrChangedNotify(nullptr);
3229 }
3230
3231 rSh.EnterSelFrameMode( &aDocPos );
3232 g_bFrameDrag = true;
3233 UpdatePointer( aDocPos, rMEvt.GetModifier() );
3234 }
3235 return;
3236 }
3237 else
3238 bOnlyText = rSh.IsObjSelectable( aDocPos );
3239
3240 if (!m_rView.GetDrawFuncPtr())
3241 rSh.ShowCursor();
3242 }
3243 else
3244 bOnlyText = KEY_MOD1 != rMEvt.GetModifier();
3245 }
3246 else if ( rSh.IsSelFrameMode() &&
3247 (m_aActHitType == SdrHitKind::NONE ||
3248 !rSh.IsInsideSelectedObj( aDocPos )))
3249 {
3250 m_rView.NoRotate();
3251 SdrHdl *pHdl;
3252 if( !bIsDocReadOnly && !m_pAnchorMarker && nullptr !=
3253 ( pHdl = pSdrView->PickHandle(aDocPos) ) &&
3254 ( pHdl->GetKind() == SdrHdlKind::Anchor ||
3255 pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
3256 {
3257 m_pAnchorMarker.reset( new SwAnchorMarker( pHdl ) );
3258 UpdatePointer( aDocPos, rMEvt.GetModifier() );
3259 return;
3260 }
3261 else
3262 {
3263 bool bUnLockView = !rSh.IsViewLocked();
3264 rSh.LockView( true );
3265 sal_uInt8 nFlag = rMEvt.IsShift() ? SW_ADD_SELECT1 :0;
3266 if( rMEvt.IsMod1() )
3267 nFlag = nFlag | SW_ENTER_GROUP2;
3268
3269 if ( rSh.IsSelFrameMode() )
3270 {
3271 rSh.UnSelectFrame();
3272 rSh.LeaveSelFrameMode();
3273 m_rView.AttrChangedNotify(nullptr);
3274 }
3275
3276 bool bSelObj = rSh.SelectObj( aDocPos, nFlag );
3277 if( bUnLockView )
3278 rSh.LockView( false );
3279
3280 if( !bSelObj )
3281 {
3282 // move cursor here so that it is not drawn in the
3283 // frame first; ShowCursor() happens in LeaveSelFrameMode()
3284 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
3285 rSh.LeaveSelFrameMode();
3286 m_rView.AttrChangedNotify(nullptr);
3287 bCallBase = false;
3288 }
3289 else
3290 {
3291 rSh.HideCursor();
3292 rSh.EnterSelFrameMode( &aDocPos );
3293 rSh.SelFlyGrabCursor();
3294 rSh.MakeSelVisible();
3295 g_bFrameDrag = true;
3296 if( rSh.IsFrameSelected() &&
3297 m_rView.GetDrawFuncPtr() )
3298 {
3299 m_rView.GetDrawFuncPtr()->Deactivate();
3300 m_rView.SetDrawFuncPtr(nullptr);
3301 m_rView.LeaveDrawCreate();
3302 m_rView.AttrChangedNotify(nullptr);
3303 }
3304 UpdatePointer( aDocPos, rMEvt.GetModifier() );
3305 return;
3306 }
3307 }
3308 }
3309 }
3310
3311 switch ( nNumberOfClicks )
3312 {
3313 case 1:
3314 break;
3315 case 2:
3316 {
3317 g_bFrameDrag = false;
3318 if ( !bIsDocReadOnly && rSh.IsInsideSelectedObj(aDocPos) &&
3319 FlyProtectFlags::NONE == rSh.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent ) )
3320 {
3321 /* This is no good: on the one hand GetSelectionType is used as flag field
3322 * (take a look into the GetSelectionType method) and on the other hand the
3323 * return value is used in a switch without proper masking (very nice), this must lead to trouble
3324 */
3325 switch ( rSh.GetSelectionType() & ~SelectionType( SelectionType::FontWork | SelectionType::ExtrudedCustomShape ) )
3326 {
3327 case SelectionType::Graphic:
3328 RstMBDownFlags();
3329 if (!comphelper::LibreOfficeKit::isActive())
3330 {
3331 GetView().GetViewFrame()->GetBindings().Execute(
3332 FN_FORMAT_GRAFIC_DLG((20000 + 400) + 58), nullptr,
3333 SfxCallMode::RECORD|SfxCallMode::SLOT);
3334 }
3335 return;
3336
3337 // double click on OLE object --> OLE-InPlace
3338 case SelectionType::Ole:
3339 if (rSh.IsSelObjProtected(FlyProtectFlags::Content) == FlyProtectFlags::NONE)
3340 {
3341 RstMBDownFlags();
3342 rSh.LaunchOLEObj();
3343 }
3344 return;
3345
3346 case SelectionType::Frame:
3347 RstMBDownFlags();
3348 if (!comphelper::LibreOfficeKit::isActive())
3349 {
3350 GetView().GetViewFrame()->GetBindings().Execute(
3351 FN_FORMAT_FRAME_DLG((20000 + 400) + 56), nullptr,
3352 SfxCallMode::RECORD|SfxCallMode::SLOT);
3353 }
3354 return;
3355
3356 case SelectionType::DrawObject:
3357 RstMBDownFlags();
3358 EnterDrawTextMode(aDocPos);
3359 if ( dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr )
3360 static_cast<SwDrawTextShell*>(m_rView.GetCurShell())->Init();
3361 return;
3362
3363 default: break;
3364 }
3365 }
3366
3367 // if the cursor position was corrected or if a Fly
3368 // was selected in ReadOnlyMode, no word selection, except when tiled rendering.
3369 if ((!g_bValidCursorPos || rSh.IsFrameSelected()) && !comphelper::LibreOfficeKit::isActive())
3370 return;
3371
3372 SwField *pField;
3373 bool bFootnote = false;
3374
3375 if( !bIsDocReadOnly &&
3376 (nullptr != (pField = rSh.GetCurField(true)) ||
3377 ( bFootnote = rSh.GetCurFootnote() ) ) )
3378 {
3379 RstMBDownFlags();
3380 if( bFootnote )
3381 GetView().GetViewFrame()->GetBindings().Execute( FN_EDIT_FOOTNOTE((20000 + 100) + 62) );
3382 else
3383 {
3384 SwFieldTypesEnum nTypeId = pField->GetTypeId();
3385 SfxViewFrame* pVFrame = GetView().GetViewFrame();
3386 switch( nTypeId )
3387 {
3388 case SwFieldTypesEnum::Postit:
3389 case SwFieldTypesEnum::Script:
3390 {
3391 // if it's a Readonly region, status has to be enabled
3392 sal_uInt16 nSlot = SwFieldTypesEnum::Postit == nTypeId ? FN_POSTIT((20000 + 300) + 29) : FN_JAVAEDIT((20000 + 1400) + 10);
3393 SfxBoolItem aItem(nSlot, true);
3394 pVFrame->GetBindings().SetState(aItem);
3395 pVFrame->GetBindings().Execute(nSlot);
3396 break;
3397 }
3398 case SwFieldTypesEnum::Authority :
3399 pVFrame->GetBindings().Execute(FN_EDIT_AUTH_ENTRY_DLG((20000 + 1800) + 33));
3400 break;
3401 case SwFieldTypesEnum::Input:
3402 case SwFieldTypesEnum::Dropdown:
3403 case SwFieldTypesEnum::SetInput:
3404 pVFrame->GetBindings().Execute(FN_UPDATE_INPUTFIELDS((20000 + 100) + 43));
3405 break;
3406 default:
3407 pVFrame->GetBindings().Execute(FN_EDIT_FIELD((20000 + 100) + 4 ));
3408 }
3409 }
3410 return;
3411 }
3412 // in extended mode double and triple
3413 // click has no effect.
3414 if ( rSh.IsExtMode() || rSh.IsBlockMode() )
3415 return;
3416
3417 // select word, AdditionalMode if applicable
3418 if ( KEY_MOD1 == rMEvt.GetModifier() && !rSh.IsAddMode() )
3419 {
3420 rSh.EnterAddMode();
3421 rSh.SelWrd( &aDocPos );
3422 rSh.LeaveAddMode();
3423 }
3424 else
3425 {
3426 if (!rSh.SelWrd(&aDocPos) && comphelper::LibreOfficeKit::isActive())
3427 // Double click did not select any word: try to
3428 // select the current cell in case we are in a
3429 // table.
3430 rSh.SelTableBox();
3431 }
3432
3433 SwContentAtPos aContentAtPos(IsAttrAtPos::FormControl);
3434 if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) &&
3435 aContentAtPos.aFnd.pFieldmark != nullptr)
3436 {
3437 IFieldmark *pFieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
3438 if ( pFieldBM->GetFieldname( ) == ODF_FORMDROPDOWN"vnd.oasis.opendocument.field.FORMDROPDOWN" || pFieldBM->GetFieldname( ) == ODF_FORMDATE"vnd.oasis.opendocument.field.FORMDATE" )
3439 {
3440 RstMBDownFlags();
3441 rSh.getIDocumentMarkAccess()->ClearFieldActivation();
3442 GetView().GetViewFrame()->GetBindings().Execute(SID_FM_CTL_PROPERTIES( 10000 + 613 ));
3443 return;
3444 }
3445 }
3446
3447 g_bHoldSelection = true;
3448 return;
3449 }
3450 case 3:
3451 case 4:
3452 {
3453 g_bFrameDrag = false;
3454 // in extended mode double and triple
3455 // click has no effect.
3456 if ( rSh.IsExtMode() )
3457 return;
3458
3459 // if the cursor position was corrected or if a Fly
3460 // was selected in ReadOnlyMode, no word selection.
3461 if ( !g_bValidCursorPos || rSh.IsFrameSelected() )
3462 return;
3463
3464 // select line, AdditionalMode if applicable
3465 const bool bMod = KEY_MOD1 == rMEvt.GetModifier() &&
3466 !rSh.IsAddMode();
3467
3468 if ( bMod )
3469 rSh.EnterAddMode();
3470
3471 // Enhanced selection
3472 if ( 3 == nNumberOfClicks )
3473 rSh.SelSentence( &aDocPos );
3474 else
3475 rSh.SelPara( &aDocPos );
3476
3477 if ( bMod )
3478 rSh.LeaveAddMode();
3479
3480 g_bHoldSelection = true;
3481 return;
3482 }
3483
3484 default:
3485 return;
3486 }
3487
3488 [[fallthrough]];
3489 }
3490 case MOUSE_LEFT(sal_uInt16(0x0001)) + KEY_SHIFT:
3491 case MOUSE_LEFT(sal_uInt16(0x0001)) + KEY_SHIFT + KEY_MOD1:
3492 {
3493 bool bLockView = m_bWasShdwCursor;
3494
3495 switch ( rMEvt.GetModifier() )
3496 {
3497 case KEY_MOD1 + KEY_SHIFT:
3498 {
3499 if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) )
3500 {
3501 m_rView.NoRotate();
3502 rSh.HideCursor();
3503 if ( rSh.IsSelFrameMode() )
3504 rSh.SelectObj(aDocPos, SW_ADD_SELECT1 | SW_ENTER_GROUP2);
3505 else
3506 { if ( rSh.SelectObj( aDocPos, SW_ADD_SELECT1 | SW_ENTER_GROUP2 ) )
3507 {
3508 rSh.EnterSelFrameMode( &aDocPos );
3509 SwEditWin::m_nDDStartPosY = aDocPos.Y();
3510 SwEditWin::m_nDDStartPosX = aDocPos.X();
3511 g_bFrameDrag = true;
3512 return;
3513 }
3514 }
3515 }
3516 else if( rSh.IsSelFrameMode() &&
3517 rSh.GetDrawView()->PickHandle( aDocPos ))
3518 {
3519 g_bFrameDrag = true;
3520 g_bNoInterrupt = false;
3521 return;
3522 }
3523 }
3524 break;
3525 case KEY_MOD1:
3526 if ( !bExecDrawTextLink )
3527 {
3528 if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
3529 {
3530 SwContentAtPos aContentAtPos(IsAttrAtPos::Outline);
3531 if(rSh.GetContentAtPos(aDocPos, aContentAtPos))
3532 {
3533 // move cursor to outline para start and toggle outline content visibility
3534 MoveCursor(rSh, aDocPos, bOnlyText, bLockView);
3535 SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint());
3536 SwOutlineNodes::size_type nPos;
3537 if (rSh.GetNodes().GetOutLineNds().Seek_Entry( &aPam.GetPoint()->nNode.GetNode(), &nPos))
3538 rSh.ToggleOutlineContentVisibility(nPos);
3539 return;
3540 }
3541 }
3542 if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) && !lcl_urlOverBackground( rSh, aDocPos ) )
3543 {
3544 m_rView.NoRotate();
3545 rSh.HideCursor();
3546 if ( rSh.IsSelFrameMode() )
3547 rSh.SelectObj(aDocPos, SW_ENTER_GROUP2);
3548 else
3549 { if ( rSh.SelectObj( aDocPos, SW_ENTER_GROUP2 ) )
3550 {
3551 rSh.EnterSelFrameMode( &aDocPos );
3552 SwEditWin::m_nDDStartPosY = aDocPos.Y();
3553 SwEditWin::m_nDDStartPosX = aDocPos.X();
3554 g_bFrameDrag = true;
3555 return;
3556 }
3557 }
3558 }
3559 else if( rSh.IsSelFrameMode() &&
3560 rSh.GetDrawView()->PickHandle( aDocPos ))
3561 {
3562 g_bFrameDrag = true;
3563 g_bNoInterrupt = false;
3564 return;
3565 }
3566 else
3567 {
3568 if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() )
3569 {
3570 rSh.PushMode();
3571 g_bModePushed = true;
3572
3573 bool bUnLockView = !rSh.IsViewLocked();
3574 rSh.LockView( true );
3575 rSh.EnterAddMode();
3576 if( bUnLockView )
3577 rSh.LockView( false );
3578 }
3579 bCallBase = false;
3580 }
3581 }
3582 break;
3583 case KEY_MOD2:
3584 {
3585 if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() )
3586 {
3587 rSh.PushMode();
3588 g_bModePushed = true;
3589 bool bUnLockView = !rSh.IsViewLocked();
3590 rSh.LockView( true );
3591 rSh.EnterBlockMode();
3592 if( bUnLockView )
3593 rSh.LockView( false );
3594 }
3595 bCallBase = false;
3596 }
3597 break;
3598 case KEY_SHIFT:
3599 {
3600 if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) )
3601 {
3602 m_rView.NoRotate();
3603 rSh.HideCursor();
3604 if ( rSh.IsSelFrameMode() )
3605 {
3606 rSh.SelectObj(aDocPos, SW_ADD_SELECT1);
3607
3608 const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
3609 if (rMarkList.GetMark(0) == nullptr)
3610 {
3611 rSh.LeaveSelFrameMode();
3612 m_rView.AttrChangedNotify(nullptr);
3613 g_bFrameDrag = false;
3614 }
3615 }
3616 else
3617 { if ( rSh.SelectObj( aDocPos ) )
3618 {
3619 rSh.EnterSelFrameMode( &aDocPos );
3620 SwEditWin::m_nDDStartPosY = aDocPos.Y();
3621 SwEditWin::m_nDDStartPosX = aDocPos.X();
3622 g_bFrameDrag = true;
3623 return;
3624 }
3625 }
3626 }
3627 else
3628 {
3629 if ( rSh.IsSelFrameMode() &&
3630 rSh.IsInsideSelectedObj( aDocPos ) )
3631 {
3632 rSh.EnterSelFrameMode( &aDocPos );
3633 SwEditWin::m_nDDStartPosY = aDocPos.Y();
3634 SwEditWin::m_nDDStartPosX = aDocPos.X();
3635 g_bFrameDrag = true;
3636 return;
3637 }
3638 if ( rSh.IsSelFrameMode() )
3639 {
3640 rSh.UnSelectFrame();
3641 rSh.LeaveSelFrameMode();
3642 m_rView.AttrChangedNotify(nullptr);
3643 g_bFrameDrag = false;
3644 }
3645 if ( !rSh.IsExtMode() )
3646 {
3647 // don't start a selection when an
3648 // URL field or a graphic is clicked
3649 bool bSttSelect = rSh.HasSelection() ||
3650 PointerStyle::RefHand != GetPointer();
3651
3652 if( !bSttSelect )
3653 {
3654 bSttSelect = true;
3655 if( bExecHyperlinks )
3656 {
3657 SwContentAtPos aContentAtPos(
3658 IsAttrAtPos::Ftn |
3659 IsAttrAtPos::InetAttr );
3660
3661 if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) )
3662 {
3663 if( !rSh.IsViewLocked() &&
3664 !rSh.IsReadOnlyAvailable() &&
3665 aContentAtPos.IsInProtectSect() )
3666 bLockView = true;
3667
3668 bSttSelect = false;
3669 }
3670 else if( rSh.IsURLGrfAtPos( aDocPos ))
3671 bSttSelect = false;
3672 }
3673 }
3674
3675 if( bSttSelect )
3676 rSh.SttSelect();
3677 }
3678 }
3679 bCallBase = false;
3680 break;
3681 }
3682 default:
3683 if( !rSh.IsViewLocked() )
3684 {
3685 SwContentAtPos aContentAtPos( IsAttrAtPos::ClickField |
3686 IsAttrAtPos::InetAttr );
3687 if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) &&
3688 !rSh.IsReadOnlyAvailable() &&
3689 aContentAtPos.IsInProtectSect() )
3690 bLockView = true;
3691 }
3692 }
3693
3694 if ( rSh.IsGCAttr() )
3695 {
3696 rSh.GCAttr();
3697 rSh.ClearGCAttr();
3698 }
3699
3700 SwContentAtPos aFieldAtPos(IsAttrAtPos::Field);
3701 bool bEditableFieldClicked = false;
3702
3703 // Are we clicking on a field?
3704 if (rSh.GetContentAtPos(aDocPos, aFieldAtPos))
3705 {
3706 bool bEditableField = (aFieldAtPos.pFndTextAttr != nullptr
3707 && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD);
3708
3709 if (!bEditableField)
3710 {
3711 rSh.CallSetCursor(&aDocPos, bOnlyText);
3712 // Unfortunately the cursor may be on field
3713 // position or on position after field depending on which
3714 // half of the field was clicked on.
3715 SwTextAttr const*const pTextField(aFieldAtPos.pFndTextAttr);
3716 if (pTextField && rSh.GetCurrentShellCursor().GetPoint()->nContent
3717 .GetIndex() != pTextField->GetStart())
3718 {
3719 assert(rSh.GetCurrentShellCursor().GetPoint()->nContent(static_cast <bool> (rSh.GetCurrentShellCursor().GetPoint
()->nContent .GetIndex() == (pTextField->GetStart() + 1
)) ? void (0) : __assert_fail ("rSh.GetCurrentShellCursor().GetPoint()->nContent .GetIndex() == (pTextField->GetStart() + 1)"
, "/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
, 3720, __extension__ __PRETTY_FUNCTION__))
3720 .GetIndex() == (pTextField->GetStart() + 1))(static_cast <bool> (rSh.GetCurrentShellCursor().GetPoint
()->nContent .GetIndex() == (pTextField->GetStart() + 1
)) ? void (0) : __assert_fail ("rSh.GetCurrentShellCursor().GetPoint()->nContent .GetIndex() == (pTextField->GetStart() + 1)"
, "/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
, 3720, __extension__ __PRETTY_FUNCTION__))
;
3721 rSh.Left( CRSR_SKIP_CHARS, false, 1, false );
3722 }
3723 // don't go into the !bOverSelect block below - it moves
3724 // the cursor
3725 break;
3726 }
3727 else
3728 {
3729 bEditableFieldClicked = true;
3730 }
3731 }
3732
3733 bool bOverSelect = rSh.TestCurrPam( aDocPos );
3734 bool bOverURLGrf = false;
3735 if( !bOverSelect )
3736 bOverURLGrf = bOverSelect = nullptr != rSh.IsURLGrfAtPos( aDocPos );
3737
3738 if ( !bOverSelect || rSh.IsInSelect() )
3739 {
3740 MoveCursor( rSh, aDocPos, bOnlyText, bLockView );
3741 bCallBase = false;
3742 }
3743 if (!bOverURLGrf && !bExecDrawTextLink && !bOnlyText)
3744 {
3745 const SelectionType nSelType = rSh.GetSelectionType();
3746 // Check in general, if an object is selectable at given position.
3747 // Thus, also text fly frames in background become selectable via Ctrl-Click.
3748 if ( ( nSelType & SelectionType::Ole ||
3749 nSelType & SelectionType::Graphic ||
3750 rSh.IsObjSelectable( aDocPos ) ) && !lcl_urlOverBackground( rSh, aDocPos ) )
3751 {
3752 SwMvContext aMvContext( &rSh );
3753 rSh.EnterSelFrameMode();
3754 bCallBase = false;
3755 }
3756 }
3757 if ( !bOverSelect && bEditableFieldClicked && (!pCursorField ||
3758 pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField()))
3759 {
3760 // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART
3761 // and CH_TXT_ATR_INPUTFIELDEND
3762 rSh.SttSelect();
3763 rSh.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1,
3764 *(aFieldAtPos.pFndTextAttr->End()) - 1 );
3765 }
3766 // don't reset here any longer so that, in case through MouseMove
3767 // with pressed Ctrl key a multiple-selection should happen,
3768 // the previous selection is not released in Drag.
3769 break;
3770 }
3771 }
3772 }
3773 else if (MOUSE_RIGHT(sal_uInt16(0x0004)) == rMEvt.GetButtons())
3774 {
3775 if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton() && rMEvt.GetModifier() == KEY_MOD1)
3776 {
3777 SwContentAtPos aContentAtPos(IsAttrAtPos::Outline);
3778 if(rSh.GetContentAtPos(aDocPos, aContentAtPos))
3779 {
3780 // move cursor to para start toggle outline content visibility and set the same visibility for subs
3781 MoveCursor(rSh, aDocPos, false, true);
3782 SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint());
3783 SwOutlineNodes::size_type nPos;
3784 if (rSh.GetNodes().GetOutLineNds().Seek_Entry(&aPam.GetPoint()->nNode.GetNode(), &nPos))
3785 {
3786 SwOutlineNodes::size_type nOutlineNodesCount = rSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount();
3787 int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos);
3788 bool bFold = rSh.IsOutlineContentFolded(nPos);
3789 do
3790 {
3791 if (rSh.IsOutlineContentFolded(nPos) == bFold)
3792 rSh.ToggleOutlineContentVisibility(nPos);
3793 } while (++nPos < nOutlineNodesCount
3794 && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nLevel);
3795 return;
3796 }
3797 }
3798 }
3799 else if ( !rMEvt.GetModifier()
3800 && static_cast< sal_uInt8 >(rMEvt.GetClicks() % 4) == 1
3801 && !rSh.TestCurrPam( aDocPos ) )
3802 {
3803 SwContentAtPos aFieldAtPos(IsAttrAtPos::Field);
3804
3805 // Are we clicking on a field?
3806 if (g_bValidCursorPos
3807 && rSh.GetContentAtPos(aDocPos, aFieldAtPos)
3808 && aFieldAtPos.pFndTextAttr != nullptr
3809 && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD
3810 && (!pCursorField || pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField()))
3811 {
3812 // Move the cursor
3813 MoveCursor( rSh, aDocPos, rSh.IsObjSelectable( aDocPos ), m_bWasShdwCursor );
3814 bCallBase = false;
3815
3816 // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART
3817 // and CH_TXT_ATR_INPUTFIELDEND
3818 rSh.SttSelect();
3819 rSh.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1,
3820 *(aFieldAtPos.pFndTextAttr->End()) - 1 );
3821 }
3822 }
3823 }
3824
3825 if (bCallBase)
3826 Window::MouseButtonDown(rMEvt);
3827}
3828
3829bool SwEditWin::changeMousePointer(Point const & rDocPoint)
3830{
3831 SwWrtShell & rShell = m_rView.GetWrtShell();
3832
3833 SwTab nMouseTabCol;
3834 if ( SwTab::COL_NONE != (nMouseTabCol = rShell.WhichMouseTabCol( rDocPoint ) ) &&
3835 !rShell.IsObjSelectable( rDocPoint ) )
3836 {
3837 PointerStyle nPointer = PointerStyle::Null;
3838 bool bChkTableSel = false;
3839
3840 switch ( nMouseTabCol )
3841 {
3842 case SwTab::COL_VERT :
3843 case SwTab::ROW_HORI :
3844 nPointer = PointerStyle::VSizeBar;
3845 bChkTableSel = true;
3846 break;
3847 case SwTab::ROW_VERT :
3848 case SwTab::COL_HORI :
3849 nPointer = PointerStyle::HSizeBar;
3850 bChkTableSel = true;
3851 break;
3852 // Enhanced table selection
3853 case SwTab::SEL_HORI :
3854 nPointer = PointerStyle::TabSelectSE;
3855 break;
3856 case SwTab::SEL_HORI_RTL :
3857 case SwTab::SEL_VERT :
3858 nPointer = PointerStyle::TabSelectSW;
3859 break;
3860 case SwTab::COLSEL_HORI :
3861 case SwTab::ROWSEL_VERT :
3862 nPointer = PointerStyle::TabSelectS;
3863 break;
3864 case SwTab::ROWSEL_HORI :
3865 nPointer = PointerStyle::TabSelectE;
3866 break;
3867 case SwTab::ROWSEL_HORI_RTL :
3868 case SwTab::COLSEL_VERT :
3869 nPointer = PointerStyle::TabSelectW;
3870 break;
3871 default: break; // prevent compiler warning
3872 }
3873
3874 if ( PointerStyle::Null != nPointer &&
3875 // i#35543 - Enhanced table selection is explicitly allowed in table mode
3876 ( !bChkTableSel || !rShell.IsTableMode() ) &&
3877 !comphelper::LibreOfficeKit::isActive() )
3878 {
3879 SetPointer( nPointer );
3880 }
3881
3882 return true;
3883 }
3884 else if (rShell.IsNumLabel(rDocPoint, RULER_MOUSE_MARGINWIDTH))
3885 {
3886 // i#42921 - consider vertical mode
3887 SwTextNode* pNodeAtPos = rShell.GetNumRuleNodeAtPos( rDocPoint );
3888 const PointerStyle nPointer =
3889 SwFEShell::IsVerticalModeAtNdAndPos( *pNodeAtPos, rDocPoint )
3890 ? PointerStyle::VSizeBar
3891 : PointerStyle::HSizeBar;
3892 SetPointer( nPointer );
3893
3894 return true;
3895 }
3896 return false;
3897}
3898
3899void SwEditWin::MouseMove(const MouseEvent& _rMEvt)
3900{
3901 MouseEvent rMEvt(_rMEvt);
3902
3903 if (comphelper::LibreOfficeKit::isActive())
3904 {
3905 if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
3906 {
3907 pWindow->MouseMove(rMEvt);
3908 return;
3909 }
3910 }
3911
3912 //ignore key modifiers for format paintbrush
3913 {
3914 bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard
3915 && m_pApplyTempl->m_pFormatClipboard->HasContent();
3916 if( bExecFormatPaintbrush )
3917 rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(),
3918 _rMEvt.GetMode(), _rMEvt.GetButtons() );
3919 }
3920
3921 // as long as an action is running the MouseMove should be disconnected
3922 // otherwise bug 40102 occurs
3923 SwWrtShell &rSh = m_rView.GetWrtShell();
3924 if( rSh.ActionPend() )
3925 return ;
3926
3927 if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
3928 {
3929 // add/remove outline collapse button
3930 SwContentAtPos aSwContentAtPos(IsAttrAtPos::Outline);
3931 if (rSh.GetContentAtPos(PixelToLogic(rMEvt.GetPosPixel()), aSwContentAtPos))
3932 {
3933 if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode())
3934 {
3935 const SwNodes& rNds = rSh.GetDoc()->GetNodes();
3936 SwOutlineNodes::size_type nPos;
3937 SwContentFrame* pContentFrame = aSwContentAtPos.aFnd.pNode->GetTextNode()->getLayoutFrame(nullptr);
3938 if (pContentFrame != m_pSavedOutlineFrame)
3939 {
3940 // remove collapse button when saved frame is not frame at mouse position
3941 if (m_pSavedOutlineFrame && /* is it possible that m_pSavedOutlineFrame is removed? */ !m_pSavedOutlineFrame->IsInDtor() &&
3942 rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos) &&
3943 !rSh.IsOutlineContentFolded(nPos))
3944 {
3945 GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame);
3946 }
3947 m_pSavedOutlineFrame = pContentFrame;
3948 }
3949 // show collapse button
3950 if (rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), &nPos) &&
3951 !rSh.IsOutlineContentFolded(nPos))
3952 {
3953 GetFrameControlsManager().SetOutlineContentVisibilityButton(aSwContentAtPos.aFnd.pNode->GetTextNode());
3954 }
3955 }
3956 }
3957 else if (m_pSavedOutlineFrame && !m_pSavedOutlineFrame->IsInDtor())
3958 {
3959 // current pointer pos is not over an outline frame
3960 // previous frame was an outline frame
3961 // remove collapse button if showing
3962 const SwNodes& rNds = rSh.GetDoc()->GetNodes();
3963 SwOutlineNodes::size_type nPos;
3964 if (rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos) &&
3965 !rSh.IsOutlineContentFolded(nPos))
3966 {
3967 GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame);
3968 }
3969 m_pSavedOutlineFrame = nullptr;
3970 }
3971 }
3972
3973 if( m_pShadCursor && 0 != (rMEvt.GetModifier() + rMEvt.GetButtons() ) )
3974 {
3975 m_pShadCursor.reset();
3976 }
3977
3978 bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly();
3979
3980 CurrShell aCurr( &rSh );
3981
3982 //aPixPt == Point in Pixel, relative to ChildWin
3983 //aDocPt == Point in Twips, document coordinates
3984 const Point aPixPt( rMEvt.GetPosPixel() );
3985 const Point aDocPt( PixelToLogic( aPixPt ) );
3986
3987 if ( IsChainMode() )
3988 {
3989 UpdatePointer( aDocPt, rMEvt.GetModifier() );
3990 return;
3991 }
3992
3993 SdrView *pSdrView = rSh.GetDrawView();
3994
3995 const SwCallMouseEvent aLastCallEvent( m_aSaveCallEvent );
3996 m_aSaveCallEvent.Clear();
3997
3998 if ( !bIsDocReadOnly && pSdrView && pSdrView->MouseMove(rMEvt,this) )
3999 {
4000 SetPointer( PointerStyle::Text );
4001 return; // evaluate SdrView's event
4002 }
4003
4004 const Point aOldPt( rSh.VisArea().Pos() );
4005 const bool bInsWin = rSh.VisArea().IsInside( aDocPt ) || comphelper::LibreOfficeKit::isActive();
4006
4007 if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
4008 {
4009 if (m_pSavedOutlineFrame && !bInsWin)
4010 {
4011 // the mouse pointer has left the building
4012 // 86 the collapse button if showing
4013 const SwNodes& rNds = rSh.GetDoc()->GetNodes();
4014 SwOutlineNodes::size_type nPos;
4015 rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos);
4016 if (!rSh.IsOutlineContentFolded(nPos))
4017 GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame);
4018 m_pSavedOutlineFrame = nullptr;
4019 }
4020 }
4021
4022 if( m_pShadCursor && !bInsWin )
4023 {
4024 m_pShadCursor.reset();
4025 }
4026
4027 if( bInsWin && m_xRowColumnSelectionStart )
4028 {
4029 EnterArea();
4030 Point aPos( aDocPt );
4031 if( rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag ))
4032 return;
4033 }
4034
4035 // position is necessary for OS/2 because obviously after a MB-Down
4036 // a MB-Move is called immediately.
4037 if( g_bDDTimerStarted )
4038 {
4039 Point aDD( SwEditWin::m_nDDStartPosX, SwEditWin::m_nDDStartPosY );
4040 aDD = LogicToPixel( aDD );
4041 tools::Rectangle aRect( aDD.X()-3, aDD.Y()-3, aDD.X()+3, aDD.Y()+3 );
4042 if ( !aRect.IsInside( aPixPt ) )
4043 StopDDTimer( &rSh, aDocPt );
4044 }
4045
4046 if(m_rView.GetDrawFuncPtr())
4047 {
4048 if( m_bInsDraw )
4049 {
4050 m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
4051 if ( !bInsWin )
4052 {
4053 Point aTmp( aDocPt );
4054 aTmp += rSh.VisArea().Pos() - aOldPt;
4055 LeaveArea( aTmp );
4056 }
4057 else
4058 EnterArea();
4059 return;
4060 }
4061 else if(!rSh.IsFrameSelected() && !rSh.IsObjSelected())
4062 {
4063 SfxBindings &rBnd = rSh.GetView().GetViewFrame()->GetBindings();
4064 Point aRelPos = rSh.GetRelativePagePosition(aDocPt);
4065 if(aRelPos.X() >= 0)
4066 {
4067 FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( &GetView()) != nullptr );
4068 SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->PutItem(SfxUInt16Item(SID_ATTR_METRICTypedWhichId<SfxUInt16Item>(((((10000 + 1499) + 1) + 499
) + 1) + 8)
, static_cast< sal_uInt16 >(eMetric)));
4069 const SfxPointItem aTmp1( SID_ATTR_POSITIONTypedWhichId<SfxPointItem>( 10000 + 223 ), aRelPos );
4070 rBnd.SetState( aTmp1 );
4071 }
4072 else
4073 {
4074 rBnd.Invalidate(SID_ATTR_POSITIONTypedWhichId<SfxPointItem>( 10000 + 223 ));
4075 }
4076 rBnd.Invalidate(SID_ATTR_SIZETypedWhichId<SvxSizeItem>( 10000 + 224 ));
4077 const SfxStringItem aCell( SID_TABLE_CELL( 10000 + 225 ), OUString() );
4078 rBnd.SetState( aCell );
4079 }
4080 }
4081
4082 // determine if we only change the mouse pointer and return
4083 if (!bIsDocReadOnly && bInsWin && !m_pApplyTempl && !rSh.IsInSelect() && changeMousePointer(aDocPt))
4084 {
4085 return;
4086 }
4087
4088 bool bDelShadCursor = true;
4089
4090 switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
4091 {
4092 case MOUSE_LEFT(sal_uInt16(0x0001)):
4093 if( m_pAnchorMarker )
4094 {
4095 // Now we need to refresh the SdrHdl pointer of m_pAnchorMarker.
4096 // This looks a little bit tricky, but it solves the following
4097 // problem: the m_pAnchorMarker contains a pointer to an SdrHdl,
4098 // if the FindAnchorPos-call cause a scrolling of the visible
4099 // area, it's possible that the SdrHdl will be destroyed and a
4100 // new one will initialized at the original position(GetHdlPos).
4101 // So the m_pAnchorMarker has to find the right SdrHdl, if it's
4102 // the old one, it will find it with position aOld, if this one
4103 // is destroyed, it will find a new one at position GetHdlPos().
4104
4105 const Point aOld = m_pAnchorMarker->GetPosForHitTest( *(rSh.GetOut()) );
4106 Point aNew = rSh.FindAnchorPos( aDocPt );
4107 SdrHdl* pHdl;
4108 if( pSdrView && (nullptr!=( pHdl = pSdrView->PickHandle( aOld ) )||
4109 nullptr !=(pHdl = pSdrView->PickHandle( m_pAnchorMarker->GetHdlPos()) ) ) &&
4110 ( pHdl->GetKind() == SdrHdlKind::Anchor ||
4111 pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
4112 {
4113 m_pAnchorMarker->ChgHdl( pHdl );
4114 if( aNew.X() || aNew.Y() )
4115 {
4116 m_pAnchorMarker->SetPos( aNew );
4117 m_pAnchorMarker->SetLastPos( aDocPt );
4118 }
4119 }
4120 else
4121 {
4122 m_pAnchorMarker.reset();
4123 }
4124 }
4125 if ( m_bInsDraw )
4126 {
4127 if ( !m_bMBPressed )
4128 break;
4129 if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
4130 {
4131 if ( !bInsWin )
4132 LeaveArea( aDocPt );
4133 else
4134 EnterArea();
4135 if ( m_rView.GetDrawFuncPtr() )
4136 {
4137 pSdrView->SetOrtho(false);
4138 m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
4139 }
4140 m_bIsInMove = true;
4141 }
4142 return;
4143 }
4144
4145 {
4146 SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
4147 if (pWrdCnt)
4148 pWrdCnt->UpdateCounts();
4149 }
4150 [[fallthrough]];
4151
4152 case MOUSE_LEFT(sal_uInt16(0x0001)) + KEY_SHIFT:
4153 case MOUSE_LEFT(sal_uInt16(0x0001)) + KEY_SHIFT + KEY_MOD1:
4154 if ( !m_bMBPressed )
4155 break;
4156 [[fallthrough]];
4157 case MOUSE_LEFT(sal_uInt16(0x0001)) + KEY_MOD1:
4158 if ( g_bFrameDrag && rSh.IsSelFrameMode() )
4159 {
4160 if( !m_bMBPressed )
4161 break;
4162
4163 if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
4164 {
4165 // event processing for resizing
4166 if (pSdrView && pSdrView->AreObjectsMarked())
4167 {
4168 const Point aSttPt( PixelToLogic( m_aStartPos ) );
4169
4170 // can we start?
4171 if( SdrHdlKind::User == g_eSdrMoveHdl )
4172 {
4173 SdrHdl* pHdl = pSdrView->PickHandle( aSttPt );
4174 g_eSdrMoveHdl = pHdl ? pHdl->GetKind() : SdrHdlKind::Move;
4175 }
4176
4177 const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
4178 const SvxMacro* pMacro = nullptr;
4179
4180 SvMacroItemId nEvent = SdrHdlKind::Move == g_eSdrMoveHdl
4181 ? SvMacroItemId::SwFrmMove
4182 : SvMacroItemId::SwFrmResize;
4183
4184 if (nullptr != pFlyFormat)
4185 pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
4186 if (nullptr != pMacro &&
4187 // or notify only e.g. every 20 Twip?
4188 m_aRszMvHdlPt != aDocPt )
4189 {
4190 m_aRszMvHdlPt = aDocPt;
4191 sal_uInt32 nPos = 0;
4192 SbxArrayRef xArgs = new SbxArray;
4193 SbxVariableRef xVar = new SbxVariable;
4194 xVar->PutString( pFlyFormat->GetName() );
4195 xArgs->Put32( xVar.get(), ++nPos );
4196
4197 if( SvMacroItemId::SwFrmResize == nEvent )
4198 {
4199 xVar = new SbxVariable;
4200 xVar->PutUShort( static_cast< sal_uInt16 >(g_eSdrMoveHdl) );
4201 xArgs->Put32( xVar.get(), ++nPos );
4202 }
4203
4204 xVar = new SbxVariable;
4205 xVar->PutLong( aDocPt.X() - aSttPt.X() );
4206 xArgs->Put32( xVar.get(), ++nPos );
4207 xVar = new SbxVariable;
4208 xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
4209 xArgs->Put32( xVar.get(), ++nPos );
4210
4211 OUString sRet;
4212
4213 ReleaseMouse();
4214
4215 rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
4216
4217 CaptureMouse();
4218
4219 if( !sRet.isEmpty() && sRet.toInt32()!=0 )
4220 return ;
4221 }
4222 }
4223 // event processing for resizing
4224
4225 if( bIsDocReadOnly )
4226 break;
4227
4228 bool bResizeKeepRatio = rSh.GetSelectionType() & SelectionType::Graphic ||
4229 rSh.GetSelectionType() & SelectionType::Media ||
4230 rSh.GetSelectionType() & SelectionType::Ole;
4231 bool bisResize = g_eSdrMoveHdl != SdrHdlKind::Move;
4232
4233 if (pSdrView)
4234 {
4235 // Resize proportionally when media is selected and the user drags on a corner
4236 const Point aSttPt(PixelToLogic(m_aStartPos));
4237 SdrHdl* pHdl = pSdrView->PickHandle(aSttPt);
4238 if (pHdl)
4239 bResizeKeepRatio = bResizeKeepRatio && pHdl->IsCornerHdl();
4240
4241 if (pSdrView->GetDragMode() == SdrDragMode::Crop)
4242 bisResize = false;
4243 if (rMEvt.IsShift())
4244 {
4245 pSdrView->SetAngleSnapEnabled(!bResizeKeepRatio);
4246 if (bisResize)
4247 pSdrView->SetOrtho(!bResizeKeepRatio);
4248 else
4249 pSdrView->SetOrtho(true);
4250 }
4251 else
4252 {
4253 pSdrView->SetAngleSnapEnabled(bResizeKeepRatio);
4254 if (bisResize)
4255 pSdrView->SetOrtho(bResizeKeepRatio);
4256 else
4257 pSdrView->SetOrtho(false);
4258 }
4259 }
4260
4261 rSh.Drag( &aDocPt, rMEvt.IsShift() );
4262 m_bIsInMove = true;
4263 }
4264 else if( bIsDocReadOnly )
4265 break;
4266
4267 if ( !bInsWin )
4268 {
4269 Point aTmp( aDocPt );
4270 aTmp += rSh.VisArea().Pos() - aOldPt;
4271 LeaveArea( aTmp );
4272 }
4273 else if(m_bIsInMove)
4274 EnterArea();
4275 return;
4276 }
4277 if ( !rSh.IsSelFrameMode() && !g_bDDINetAttr &&
4278 (IsMinMove( m_aStartPos,aPixPt ) || m_bIsInMove) &&
4279 (rSh.IsInSelect() || !rSh.TestCurrPam( aDocPt )) )
4280 {
4281 if ( pSdrView )
4282 {
4283 if ( rMEvt.IsShift() )
4284 pSdrView->SetOrtho(true);
4285 else
4286 pSdrView->SetOrtho(false);
4287 }
4288 if ( !bInsWin )
4289 {
4290 Point aTmp( aDocPt );
4291 aTmp += rSh.VisArea().Pos() - aOldPt;
4292 LeaveArea( aTmp );
4293 }
4294 else
4295 {
4296 if( !rMEvt.IsSynthetic() &&
4297 ( MOUSE_LEFT(sal_uInt16(0x0001)) != rMEvt.GetButtons() ||
4298 KEY_MOD1 != rMEvt.GetModifier() ||
4299 !rSh.Is_FnDragEQBeginDrag() ||
4300 rSh.IsAddMode() ) )
4301 {
4302 rSh.Drag( &aDocPt, false );
4303
4304 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
4305 EnterArea();
4306 }
4307 }
4308 }
4309 g_bDDINetAttr = false;
4310 break;
4311 case 0:
4312 {
4313 if ( m_pApplyTempl )
4314 {
4315 UpdatePointer(aDocPt); // maybe a frame has to be marked here
4316 break;
4317 }
4318 // change ui if mouse is over SwPostItField
4319 // TODO: do the same thing for redlines IsAttrAtPos::Redline
4320 SwContentAtPos aContentAtPos( IsAttrAtPos::Field);
4321 if (rSh.GetContentAtPos(aDocPt, aContentAtPos, false))
4322 {
4323 const SwField* pField = aContentAtPos.aFnd.pField;
4324 if (pField->Which()== SwFieldIds::Postit)
4325 {
4326 m_rView.GetPostItMgr()->SetShadowState(reinterpret_cast<const SwPostItField*>(pField),false);
4327 }
4328 else
4329 m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
4330 }
4331 else
4332 m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
4333 [[fallthrough]];
4334 }
4335 case KEY_SHIFT:
4336 case KEY_MOD2:
4337 case KEY_MOD1:
4338 if ( !m_bInsDraw )
4339 {
4340 bool bTstShdwCursor = true;
4341
4342 UpdatePointer( aDocPt, rMEvt.GetModifier() );
4343
4344 const SwFrameFormat* pFormat = nullptr;
4345 const SwFormatINetFormat* pINet = nullptr;
4346 SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
4347 if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
4348 pINet = static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr);
4349
4350 const void* pTmp = pINet;
4351
4352 if( pINet ||
4353 nullptr != ( pTmp = pFormat = rSh.GetFormatFromAnyObj( aDocPt )))
4354 {
4355 bTstShdwCursor = false;
4356 if( pTmp == pINet )
4357 m_aSaveCallEvent.Set( pINet );
4358 else
4359 {
4360 IMapObject* pIMapObj = pFormat->GetIMapObject( aDocPt );
4361 if( pIMapObj )
4362 m_aSaveCallEvent.Set( pFormat, pIMapObj );
4363 else
4364 m_aSaveCallEvent.Set( EVENT_OBJECT_URLITEM, pFormat );
4365 }
4366
4367 // should be over an InternetField with an
4368 // embedded macro?
4369 if( m_aSaveCallEvent != aLastCallEvent )
4370 {
4371 if( aLastCallEvent.HasEvent() )
4372 rSh.CallEvent( SvMacroItemId::OnMouseOut,
4373 aLastCallEvent, true );
4374 // 0 says that the object doesn't have any table
4375 if( !rSh.CallEvent( SvMacroItemId::OnMouseOver,
4376 m_aSaveCallEvent ))
4377 m_aSaveCallEvent.Clear();
4378 }
4379 }
4380 else if( aLastCallEvent.HasEvent() )
4381 {
4382 // cursor was on an object
4383 rSh.CallEvent( SvMacroItemId::OnMouseOut,
4384 aLastCallEvent, true );
4385 }
4386
4387 if( bTstShdwCursor && bInsWin && !bIsDocReadOnly &&
4388 !m_bInsFrame &&
4389 !rSh.GetViewOptions()->getBrowseMode() &&
4390 rSh.GetViewOptions()->IsShadowCursor() &&
4391 !(rMEvt.GetModifier() + rMEvt.GetButtons()) &&
4392 !rSh.HasSelection() && !GetConnectMetaFile() )
4393 {
4394 SwRect aRect;
4395 sal_Int16 eOrient;
4396 SwFillMode eMode = rSh.GetViewOptions()->GetShdwCursorFillMode();
4397 if( rSh.GetShadowCursorPos( aDocPt, eMode, aRect, eOrient ))
4398 {
4399 if( !m_pShadCursor )
4400 m_pShadCursor.reset( new SwShadowCursor( *this,
4401 SwViewOption::GetDirectCursorColor() ) );
4402 if( text::HoriOrientation::RIGHT != eOrient && text::HoriOrientation::CENTER != eOrient )
4403 eOrient = text::HoriOrientation::LEFT;
4404 m_pShadCursor->SetPos( aRect.Pos(), aRect.Height(), static_cast< sal_uInt16 >(eOrient) );
4405 bDelShadCursor = false;
4406 }
4407 }
4408 }
4409 break;
4410 case MOUSE_LEFT(sal_uInt16(0x0001)) + KEY_MOD2:
4411 if( rSh.IsBlockMode() && !rMEvt.IsSynthetic() )
4412 {
4413 rSh.Drag( &aDocPt, false );
4414 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
4415 EnterArea();
4416 }
4417 break;
4418 }
4419
4420 if( bDelShadCursor && m_pShadCursor )
4421 {
4422 m_pShadCursor.reset();
4423 }
4424 m_bWasShdwCursor = false;
4425}
4426
4427/**
4428 * Button Up
4429 */
4430void SwEditWin::MouseButtonUp(const MouseEvent& rMEvt)
4431{
4432 if (comphelper::LibreOfficeKit::isActive())
4433 {
4434 if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
4435 {
4436 pWindow->MouseButtonUp(rMEvt);
4437 return;
4438 }
4439 }
4440
4441 bool bCallBase = true;
4442
4443 bool bCallShadowCursor = m_bWasShdwCursor;
4444 m_bWasShdwCursor = false;
4445 if( m_pShadCursor )
4446 {
4447 m_pShadCursor.reset();
4448 }
4449
4450 m_xRowColumnSelectionStart.reset();
4451
4452 SdrHdlKind eOldSdrMoveHdl = g_eSdrMoveHdl;
4453 g_eSdrMoveHdl = SdrHdlKind::User; // for MoveEvents - reset again
4454
4455 // preventively reset
4456 m_rView.SetTabColFromDoc( false );
4457 m_rView.SetNumRuleNodeFromDoc(nullptr);
4458
4459 SwWrtShell &rSh = m_rView.GetWrtShell();
4460 CurrShell aCurr( &rSh );
4461 SdrView *pSdrView = rSh.GetDrawView();
4462 if ( pSdrView )
4463 {
4464 // tdf34555: ortho was always reset before being used in EndSdrDrag
4465 // Now, it is reset only if not in Crop mode.
4466 if (pSdrView->GetDragMode() != SdrDragMode::Crop && !rMEvt.IsShift())
4467 pSdrView->SetOrtho(false);
4468
4469 if ( pSdrView->MouseButtonUp( rMEvt,this ) )
4470 {
4471 rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
4472 return; // SdrView's event evaluated
4473 }
4474 }
4475 // only process MouseButtonUp when the Down went to that windows as well.
4476 if ( !m_bMBPressed )
4477 {
4478 // Undo for the watering can is already in CommandHdl
4479 // that's the way it should be!
4480
4481 return;
4482 }
4483
4484 Point aDocPt( PixelToLogic( rMEvt.GetPosPixel() ) );
4485
4486 if ( g_bDDTimerStarted )
4487 {
4488 StopDDTimer( &rSh, aDocPt );
4489 m_bMBPressed = false;
4490 if ( rSh.IsSelFrameMode() )
4491 {
4492 rSh.EndDrag( &aDocPt, false );
4493 g_bFrameDrag = false;
4494 }
4495 g_bNoInterrupt = false;
4496 const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) );
4497 if ((PixelToLogic(m_aStartPos).Y() == (aDocPos.Y())) && (PixelToLogic(m_aStartPos).X() == (aDocPos.X())))//To make sure it was not moved
4498 {
4499 SdrPageView* pPV = nullptr;
4500 SdrObject* pObj = pSdrView ? pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER) : nullptr;
4501 if (pObj)
4502 {
4503 SwFrameFormat* pFormat = GetUserCall(pObj)->GetFormat();
4504 SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_FLYFRMFMT);
4505 if (!pShapeFormat)
4506 {
4507 pSdrView->UnmarkAllObj();
4508 pSdrView->MarkObj(pObj,pPV);
4509 }
4510 else
4511 {
4512 // If the fly frame is a textbox of a shape, then select the shape instead.
4513 SdrObject* pShape = pShapeFormat->FindSdrObject();
4514 pSdrView->UnmarkAllObj();
4515 pSdrView->MarkObj(pShape, pPV);
4516 }
4517 }
4518 }
4519 ReleaseMouse();
4520 return;
4521 }
4522
4523 if( m_pAnchorMarker )
4524 {
4525 if(m_pAnchorMarker->GetHdl())
4526 {
4527 // #i121463# delete selected after drag
4528 m_pAnchorMarker->GetHdl()->SetSelected(false);
4529 }
4530
4531 Point aPnt( m_pAnchorMarker->GetLastPos() );
4532 m_pAnchorMarker.reset();
4533 if( aPnt.X() || aPnt.Y() )
4534 rSh.FindAnchorPos( aPnt, true );
4535 }
4536 if ( m_bInsDraw && m_rView.GetDrawFuncPtr() )
4537 {
4538 if ( m_rView.GetDrawFuncPtr()->MouseButtonUp( rMEvt ) )
4539 {
4540 if (m_rView.GetDrawFuncPtr()) // could have been destroyed in MouseButtonUp
4541 {
4542 m_rView.GetDrawFuncPtr()->Deactivate();
4543
4544 if (!m_rView.IsDrawMode())
4545 {
4546 m_rView.SetDrawFuncPtr(nullptr);
4547 SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
4548 rBind.Invalidate( SID_ATTR_SIZETypedWhichId<SvxSizeItem>( 10000 + 224 ) );
4549 rBind.Invalidate( SID_TABLE_CELL( 10000 + 225 ) );
4550 }
4551 }
4552
4553 if ( rSh.IsObjSelected() )
4554 {
4555 rSh.EnterSelFrameMode();
4556 if (!m_rView.GetDrawFuncPtr())
4557 StdDrawMode( OBJ_NONE, true );
4558 }
4559 else if ( rSh.IsFrameSelected() )
4560 {
4561 rSh.EnterSelFrameMode();
4562 StopInsFrame();
4563 }
4564 else
4565 {
4566 const Point aDocPos( PixelToLogic( m_aStartPos ) );
4567 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4568 rSh.Edit();
4569 }
4570
4571 m_rView.AttrChangedNotify(nullptr);
4572 }
4573 else if (rMEvt.GetButtons() == MOUSE_RIGHT(sal_uInt16(0x0004)) && rSh.IsDrawCreate())
4574 m_rView.GetDrawFuncPtr()->BreakCreate(); // abort drawing
4575
4576 g_bNoInterrupt = false;
4577 if (IsMouseCaptured())
4578 ReleaseMouse();
4579 return;
4580 }
4581 bool bPopMode = false;
4582 switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
4583 {
4584 case MOUSE_LEFT(sal_uInt16(0x0001)):
4585 if ( m_bInsDraw && rSh.IsDrawCreate() )
4586 {
4587 if ( m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->MouseButtonUp(rMEvt) )
4588 {
4589 m_rView.GetDrawFuncPtr()->Deactivate();
4590 m_rView.AttrChangedNotify(nullptr);
4591 if ( rSh.IsObjSelected() )
4592 rSh.EnterSelFrameMode();
4593 if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
4594 StopInsFrame();
4595 }
4596 bCallBase = false;
4597 break;
4598 }
4599 [[fallthrough]];
4600 case MOUSE_LEFT(sal_uInt16(0x0001)) + KEY_MOD1:
4601 case MOUSE_LEFT(sal_uInt16(0x0001)) + KEY_MOD2:
4602 case MOUSE_LEFT(sal_uInt16(0x0001)) + KEY_SHIFT + KEY_MOD1:
4603 if ( g_bFrameDrag && rSh.IsSelFrameMode() )
4604 {
4605 if ( rMEvt.IsMod1() ) // copy and don't move.
4606 {
4607 // abort drag, use internal Copy instead
4608 tools::Rectangle aRect;
4609 rSh.GetDrawView()->TakeActionRect( aRect );
4610 if (!aRect.IsEmpty())
4611 {
4612 rSh.BreakDrag();
4613 Point aEndPt, aSttPt;
4614 if ( rSh.GetSelFrameType() & FrameTypeFlags::FLY_ATCNT )
4615 {
4616 aEndPt = aRect.TopLeft();
4617 aSttPt = rSh.GetDrawView()->GetAllMarkedRect().TopLeft();
4618 }
4619 else
4620 {
4621 aEndPt = aRect.Center();
4622 aSttPt = rSh.GetDrawView()->GetAllMarkedRect().Center();
4623 }
4624 if ( aSttPt != aEndPt )
4625 {
4626 rSh.StartUndo( SwUndoId::UI_DRAG_AND_COPY );
4627 rSh.Copy(rSh, aSttPt, aEndPt);
4628 rSh.EndUndo( SwUndoId::UI_DRAG_AND_COPY );
4629 }
4630 }
4631 else {
4632 rSh.EndDrag( &aDocPt, false );
4633 }
4634 }
4635 else
4636 {
4637 {
4638 const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
4639 const SvxMacro* pMacro = nullptr;
4640
4641 SvMacroItemId nEvent = SdrHdlKind::Move == eOldSdrMoveHdl
4642 ? SvMacroItemId::SwFrmMove
4643 : SvMacroItemId::SwFrmResize;
4644
4645 if (nullptr != pFlyFormat)
4646 pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
4647 if (nullptr != pMacro)
4648 {
4649 const Point aSttPt( PixelToLogic( m_aStartPos ) );
4650 m_aRszMvHdlPt = aDocPt;
4651 sal_uInt32 nPos = 0;
4652 SbxArrayRef xArgs = new SbxArray;
4653 SbxVariableRef xVar = new SbxVariable;
4654 xVar->PutString( pFlyFormat->GetName() );
4655 xArgs->Put32( xVar.get(), ++nPos );
4656
4657 if( SvMacroItemId::SwFrmResize == nEvent )
4658 {
4659 xVar = new SbxVariable;
4660 xVar->PutUShort( static_cast< sal_uInt16 >(eOldSdrMoveHdl) );
4661 xArgs->Put32( xVar.get(), ++nPos );
4662 }
4663
4664 xVar = new SbxVariable;
4665 xVar->PutLong( aDocPt.X() - aSttPt.X() );
4666 xArgs->Put32( xVar.get(), ++nPos );
4667 xVar = new SbxVariable;
4668 xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
4669 xArgs->Put32( xVar.get(), ++nPos );
4670
4671 xVar = new SbxVariable;
4672 xVar->PutUShort( 1 );
4673 xArgs->Put32( xVar.get(), ++nPos );
4674
4675 ReleaseMouse();
4676
4677 rSh.ExecMacro( *pMacro, nullptr, xArgs.get() );
4678
4679 CaptureMouse();
4680 }
4681 }
4682 rSh.EndDrag( &aDocPt, false );
4683 }
4684 g_bFrameDrag = false;
4685 bCallBase = false;
4686 break;
4687 }
4688 bPopMode = true;
4689 [[fallthrough]];
4690 case MOUSE_LEFT(sal_uInt16(0x0001)) + KEY_SHIFT:
4691 if (rSh.IsSelFrameMode())
4692 {
4693
4694 rSh.EndDrag( &aDocPt, false );
4695 g_bFrameDrag = false;
4696 bCallBase = false;
4697 break;
4698 }
4699
4700 if( g_bHoldSelection )
4701 {
4702 // the EndDrag should be called in any case
4703 g_bHoldSelection = false;
4704 rSh.EndDrag( &aDocPt, false );
4705 }
4706 else
4707 {
4708 SwContentAtPos aFieldAtPos ( IsAttrAtPos::Field );
4709 if ( !rSh.IsInSelect() && rSh.TestCurrPam( aDocPt ) &&
4710 !rSh.GetContentAtPos( aDocPt, aFieldAtPos ) )
4711 {
4712 const bool bTmpNoInterrupt = g_bNoInterrupt;
4713 g_bNoInterrupt = false;
4714 { // create only temporary move context because otherwise
4715 // the query to the content form doesn't work!!!
4716 SwMvContext aMvContext( &rSh );
4717 const Point aDocPos( PixelToLogic( m_aStartPos ) );
4718 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4719 }
4720 g_bNoInterrupt = bTmpNoInterrupt;
4721
4722 }
4723 else
4724 {
4725 bool bInSel = rSh.IsInSelect();
4726 rSh.EndDrag( &aDocPt, false );
4727
4728 // Internetfield? --> call link (load doc!!)
4729 if( !bInSel )
4730 {
4731 LoadUrlFlags nFilter = LoadUrlFlags::NONE;
4732 if( KEY_MOD1 == rMEvt.GetModifier() )
4733 nFilter |= LoadUrlFlags::NewView;
4734
4735 bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
4736 if ( !bExecHyperlinks )
4737 {
4738 SvtSecurityOptions aSecOpts;
4739 const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
4740 if ( ( bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) ||
4741 ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) )
4742 bExecHyperlinks = true;
4743 }
4744
4745 const bool bExecSmarttags = rMEvt.GetModifier() == KEY_MOD1;
4746
4747 if(m_pApplyTempl)
4748 bExecHyperlinks = false;
4749
4750 SwContentAtPos aContentAtPos( IsAttrAtPos::Field |
4751 IsAttrAtPos::InetAttr |
4752 IsAttrAtPos::SmartTag | IsAttrAtPos::FormControl);
4753
4754 if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
4755 {
4756 // Do it again if we're not on a field/hyperlink to update the cursor accordingly
4757 if ( IsAttrAtPos::Field != aContentAtPos.eContentAtPos
4758 && IsAttrAtPos::InetAttr != aContentAtPos.eContentAtPos )
4759 rSh.GetContentAtPos( aDocPt, aContentAtPos, true );
4760
4761 bool bViewLocked = rSh.IsViewLocked();
4762 if( !bViewLocked && !rSh.IsReadOnlyAvailable() &&
4763 aContentAtPos.IsInProtectSect() )
4764 rSh.LockView( true );
4765
4766 ReleaseMouse();
4767
4768 if( IsAttrAtPos::Field == aContentAtPos.eContentAtPos )
4769 {
4770 bool bAddMode(false);
4771 // AdditionalMode if applicable
4772 if (KEY_MOD1 == rMEvt.GetModifier()
4773 && !rSh.IsAddMode())
4774 {
4775 bAddMode = true;
4776 rSh.EnterAddMode();
4777 }
4778 if ( aContentAtPos.pFndTextAttr != nullptr
4779 && aContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD )
4780 {
4781 if (!rSh.IsInSelect())
4782 {
4783 // create only temporary move context because otherwise
4784 // the query to the content form doesn't work!!!
4785 SwMvContext aMvContext( &rSh );
4786 const Point aDocPos( PixelToLogic( m_aStartPos ) );
4787 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4788 }
4789 else
4790 {
4791 g_bValidCursorPos = true;
4792 }
4793 }
4794 else
4795 {
4796 rSh.ClickToField( *aContentAtPos.aFnd.pField );
4797 // a bit of a mystery what this is good for?
4798 // in this case we assume it's valid since we
4799 // just selected a field
4800 g_bValidCursorPos = true;
4801 }
4802 if (bAddMode)
4803 {
4804 rSh.LeaveAddMode();
4805 }
4806 }
4807 else if ( IsAttrAtPos::SmartTag == aContentAtPos.eContentAtPos )
4808 {
4809 // execute smarttag menu
4810 if ( bExecSmarttags && SwSmartTagMgr::Get().IsSmartTagsEnabled() )
4811 m_rView.ExecSmartTagPopup( aDocPt );
4812 }
4813 else if ( IsAttrAtPos::FormControl == aContentAtPos.eContentAtPos )
4814 {
4815 OSL_ENSURE( aContentAtPos.aFnd.pFieldmark != nullptr, "where is my field ptr???")do { if (true && (!(aContentAtPos.aFnd.pFieldmark != nullptr
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
":" "4815" ": "), "%s", "where is my field ptr???"); } } while
(false)
;
4816 if ( aContentAtPos.aFnd.pFieldmark != nullptr)
4817 {
4818 IFieldmark *fieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
4819 if ( fieldBM->GetFieldname( ) == ODF_FORMCHECKBOX"vnd.oasis.opendocument.field.FORMCHECKBOX" )
4820 {
4821 ICheckboxFieldmark& rCheckboxFm = dynamic_cast<ICheckboxFieldmark&>(*fieldBM);
4822 rCheckboxFm.SetChecked(!rCheckboxFm.IsChecked());
4823 rCheckboxFm.Invalidate();
4824 rSh.InvalidateWindows( m_rView.GetVisArea() );
4825 }
4826 }
4827 }
4828 else if ( IsAttrAtPos::InetAttr == aContentAtPos.eContentAtPos )
4829 {
4830 if (comphelper::LibreOfficeKit::isActive())
4831 {
4832 OUString val((*static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)).GetValue());
4833 if (val.startsWith("#"))
4834 bExecHyperlinks = true;
4835 }
4836 if ( bExecHyperlinks && aContentAtPos.aFnd.pAttr )
4837 rSh.ClickToINetAttr( *static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr), nFilter );
4838 }
4839
4840 rSh.LockView( bViewLocked );
4841 bCallShadowCursor = false;
4842 }
4843 else
4844 {
4845 aContentAtPos = SwContentAtPos( IsAttrAtPos::Ftn );
4846 if( !rSh.GetContentAtPos( aDocPt, aContentAtPos, true ) && bExecHyperlinks )
4847 {
4848 SdrViewEvent aVEvt;
4849
4850 if (pSdrView)
4851 pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
4852
4853 if (pSdrView && aVEvt.eEvent == SdrEventKind::ExecuteUrl)
4854 {
4855 // hit URL field
4856 const SvxURLField *pField = aVEvt.pURLField;
4857 if (pField)
4858 {
4859 const OUString& sURL(pField->GetURL());
4860 const OUString& sTarget(pField->GetTargetFrame());
4861 ::LoadURL(rSh, sURL, nFilter, sTarget);
4862 }
4863 bCallShadowCursor = false;
4864 }
4865 else
4866 {
4867 // hit graphic
4868 ReleaseMouse();
4869 if( rSh.ClickToINetGrf( aDocPt, nFilter ))
4870 bCallShadowCursor = false;
4871 }
4872 }
4873 }
4874
4875 if( bCallShadowCursor &&
4876 rSh.GetViewOptions()->IsShadowCursor() &&
4877 MOUSE_LEFT(sal_uInt16(0x0001)) == (rMEvt.GetModifier() + rMEvt.GetButtons()) &&
4878 !rSh.HasSelection() &&
4879 !GetConnectMetaFile() &&
4880 rSh.VisArea().IsInside( aDocPt ))
4881 {
4882 SwUndoId nLastUndoId(SwUndoId::EMPTY);
4883 if (rSh.GetLastUndoInfo(nullptr, & nLastUndoId))
4884 {
4885 if (SwUndoId::INS_FROM_SHADOWCRSR == nLastUndoId)
4886 {
4887 rSh.Undo();
4888 }
4889 }
4890 SwFillMode eMode = rSh.GetViewOptions()->GetShdwCursorFillMode();
4891 rSh.SetShadowCursorPos( aDocPt, eMode );
4892 }
4893 }
4894 }
4895 bCallBase = false;
4896
4897 }
4898
4899 // reset pushed mode in Down again if applicable
4900 if ( bPopMode && g_bModePushed )
4901 {
4902 rSh.PopMode();
4903 g_bModePushed = false;
4904 bCallBase = false;
4905 }
4906 break;
4907
4908 default:
4909 ReleaseMouse();
4910 return;
4911 }
4912
4913 if( m_pApplyTempl )
4914 {
4915 SelectionType eSelection = rSh.GetSelectionType();
4916 SwFormatClipboard* pFormatClipboard = m_pApplyTempl->m_pFormatClipboard;
4917 if( pFormatClipboard )//apply format paintbrush
4918 {
4919 //get some parameters
4920 SwWrtShell& rWrtShell = m_rView.GetWrtShell();
4921 SfxStyleSheetBasePool* pPool=nullptr;
4922 bool bNoCharacterFormats = false;
4923 bool bNoParagraphFormats = true;
4924 {
4925 SwDocShell* pDocSh = m_rView.GetDocShell();
4926 if(pDocSh)
4927 pPool = pDocSh->GetStyleSheetPool();
4928 if( (rMEvt.GetModifier()&KEY_MOD1) && (rMEvt.GetModifier()&KEY_SHIFT) )
4929 {
4930 bNoCharacterFormats = true;
4931 bNoParagraphFormats = false;
4932 }
4933 else if( rMEvt.GetModifier() & KEY_MOD1 )
4934 bNoParagraphFormats = false;
4935 }
4936 //execute paste
4937 pFormatClipboard->Paste( rWrtShell, pPool, bNoCharacterFormats, bNoParagraphFormats );
4938
4939 //if the clipboard is empty after paste remove the ApplyTemplate
4940 if(!pFormatClipboard->HasContent())
4941 SetApplyTemplate(SwApplyTemplate());
4942
4943 //tdf#38101 remove temporary highlighting
4944 m_pUserMarker.reset();
4945 }
4946 else if( m_pApplyTempl->nColor )
4947 {
4948 sal_uInt16 nId = 0;
4949 switch( m_pApplyTempl->nColor )
4950 {
4951 case SID_ATTR_CHAR_COLOR_EXT(10000 + 488):
4952 nId = RES_CHRATR_COLOR;
4953 break;
4954 case SID_ATTR_CHAR_COLOR_BACKGROUND_EXT(10000 + 490):
4955 nId = RES_CHRATR_BACKGROUND;
4956 break;
4957 }
4958 if( nId && (SelectionType::Text|SelectionType::Table) & eSelection)
4959 {
4960 if( rSh.IsSelection() && !rSh.HasReadonlySel() )
4961 {
4962 m_pApplyTempl->nUndo =
4963 std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4964 if (nId == RES_CHRATR_BACKGROUND)
4965 ApplyCharBackground(m_aWaterCanTextBackColor, rSh);
4966 else
4967 rSh.SetAttrItem( SvxColorItem( m_aWaterCanTextColor, nId ) );
4968 rSh.UnSetVisibleCursor();
4969 rSh.EnterStdMode();
4970 rSh.SetVisibleCursor(aDocPt);
4971 bCallBase = false;
4972 m_aTemplateTimer.Stop();
4973 }
4974 else if(rMEvt.GetClicks() == 1)
4975 {
4976 // no selection -> so turn off watering can
4977 m_aTemplateTimer.Start();
4978 }
4979 }
4980 }
4981 else
4982 {
4983 OUString aStyleName;
4984 switch ( m_pApplyTempl->eType )
4985 {
4986 case SfxStyleFamily::Para:
4987 if( (( SelectionType::Text | SelectionType::Table )
4988 & eSelection ) && !rSh.HasReadonlySel() )
4989 {
4990 rSh.SetTextFormatColl( m_pApplyTempl->aColl.pTextColl );
4991 m_pApplyTempl->nUndo =
4992 std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4993 bCallBase = false;
4994 if ( m_pApplyTempl->aColl.pTextColl )
4995 aStyleName = m_pApplyTempl->aColl.pTextColl->GetName();
4996 }
4997 break;
4998 case SfxStyleFamily::Char:
4999 if( (( SelectionType::Text | SelectionType::Table )
5000 & eSelection ) && !rSh.HasReadonlySel() )
5001 {
5002 rSh.SetAttrItem( SwFormatCharFormat(m_pApplyTempl->aColl.pCharFormat) );
5003 rSh.UnSetVisibleCursor();
5004 rSh.EnterStdMode();
5005 rSh.SetVisibleCursor(aDocPt);
5006 m_pApplyTempl->nUndo =
5007 std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
5008 bCallBase = false;
5009 if ( m_pApplyTempl->aColl.pCharFormat )
5010 aStyleName = m_pApplyTempl->aColl.pCharFormat->GetName();
5011 }
5012 break;
5013 case SfxStyleFamily::Frame :
5014 {
5015 const SwFrameFormat* pFormat = rSh.GetFormatFromObj( aDocPt );
5016 if(dynamic_cast<const SwFlyFrameFormat*>( pFormat) )
5017 {
5018 rSh.SetFrameFormat( m_pApplyTempl->aColl.pFrameFormat, false, &aDocPt );
5019 m_pApplyTempl->nUndo =
5020 std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
5021 bCallBase = false;
5022 if( m_pApplyTempl->aColl.pFrameFormat )
5023 aStyleName = m_pApplyTempl->aColl.pFrameFormat->GetName();
5024 }
5025 break;
5026 }
5027 case SfxStyleFamily::Page:
5028 // no Undo with page templates
5029 rSh.ChgCurPageDesc( *m_pApplyTempl->aColl.pPageDesc );
5030 if ( m_pApplyTempl->aColl.pPageDesc )
5031 aStyleName = m_pApplyTempl->aColl.pPageDesc->GetName();
5032 m_pApplyTempl->nUndo =
5033 std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
5034 bCallBase = false;
5035 break;
5036 case SfxStyleFamily::Pseudo:
5037 if( !rSh.HasReadonlySel() )
5038 {
5039 rSh.SetCurNumRule( *m_pApplyTempl->aColl.pNumRule,
5040 false,
5041 m_pApplyTempl->aColl.pNumRule->GetDefaultListId() );
5042 bCallBase = false;
5043 m_pApplyTempl->nUndo =
5044 std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
5045 if( m_pApplyTempl->aColl.pNumRule )
5046 aStyleName = m_pApplyTempl->aColl.pNumRule->GetName();
5047 }
5048 break;
5049 default: break;
5050 }
5051
5052 uno::Reference< frame::XDispatchRecorder > xRecorder =
5053 m_rView.GetViewFrame()->GetBindings().GetRecorder();
5054 if ( !aStyleName.isEmpty() && xRecorder.is() )
5055 {
5056 SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
5057 if ( pSfxShell )
5058 {
5059 SfxRequest aReq( m_rView.GetViewFrame(), SID_STYLE_APPLY(5000 + 552) );
5060 aReq.AppendItem( SfxStringItem( SID_STYLE_APPLY(5000 + 552), aStyleName ) );
5061 aReq.AppendItem( SfxUInt16Item( SID_STYLE_FAMILYTypedWhichId<SfxUInt16Item>(5000 + 553), static_cast<sal_uInt16>(m_pApplyTempl->eType) ) );
5062 aReq.Done();
5063 }
5064 }
5065 }
5066
5067 }
5068 ReleaseMouse();
5069 // Only processed MouseEvents arrive here; only at these this mode can
5070 // be reset.
5071 m_bMBPressed = false;
5072
5073 // Make this call just to be sure. Selecting has finished surely by now.
5074 // Otherwise the timeout's timer could give problems.
5075 EnterArea();
5076 g_bNoInterrupt = false;
5077
5078 if (bCallBase)
5079 Window::MouseButtonUp(rMEvt);
5080
5081 if (!(pSdrView && rMEvt.GetClicks() == 1 && comphelper::LibreOfficeKit::isActive()))
5082 return;
5083
5084 // When tiled rendering, single click on a shape text starts editing already.
5085 SdrViewEvent aViewEvent;
5086 SdrHitKind eHit = pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONUP, aViewEvent);
5087 const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
5088 if (eHit == SdrHitKind::TextEditObj && rMarkList.GetMarkCount() == 1)
5089 {
5090 if (SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj())
5091 {
5092 EnterDrawTextMode(pObj->GetLogicRect().Center());
5093 if ( dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr )
5094 static_cast<SwDrawTextShell*>(m_rView.GetCurShell())->Init();
5095 }
5096 }
5097}
5098
5099/**
5100 * Apply template
5101 */
5102void SwEditWin::SetApplyTemplate(const SwApplyTemplate &rTempl)
5103{
5104 static bool bIdle = false;
5105 m_pApplyTempl.reset();
5106 SwWrtShell &rSh = m_rView.GetWrtShell();
5107
5108 if(rTempl.m_pFormatClipboard)
5109 {
5110 m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
5111 m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
5112 SetPointer( PointerStyle::Fill );//@todo #i20119# maybe better a new brush pointer here in future
5113 rSh.NoEdit( false );
5114 bIdle = rSh.GetViewOptions()->IsIdle();
5115 rSh.GetViewOptions()->SetIdle( false );
5116 }
5117 else if(rTempl.nColor)
5118 {
5119 m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
5120 m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
5121 SetPointer( PointerStyle::Fill );
5122 rSh.NoEdit( false );
5123 bIdle = rSh.GetViewOptions()->IsIdle();
5124 rSh.GetViewOptions()->SetIdle( false );
5125 }
5126 else if( rTempl.eType != SfxStyleFamily::None )
5127 {
5128 m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
5129 m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
5130 SetPointer( PointerStyle::Fill );
5131 rSh.NoEdit( false );
5132 bIdle = rSh.GetViewOptions()->IsIdle();
5133 rSh.GetViewOptions()->SetIdle( false );
5134 }
5135 else
5136 {
5137 SetPointer( PointerStyle::Text );
5138 rSh.UnSetVisibleCursor();
5139
5140 rSh.GetViewOptions()->SetIdle( bIdle );
5141 if ( !rSh.IsSelFrameMode() )
5142 rSh.Edit();
5143 }
5144
5145 static sal_uInt16 aInva[] =
5146 {
5147 SID_STYLE_WATERCAN(5000 + 554),
5148 SID_ATTR_CHAR_COLOR_EXT(10000 + 488),
5149 SID_ATTR_CHAR_COLOR_BACKGROUND_EXT(10000 + 490),
5150 0
5151 };
5152 m_rView.GetViewFrame()->GetBindings().Invalidate(aInva);
5153}
5154
5155/**
5156 * Ctor
5157 */
5158SwEditWin::SwEditWin(vcl::Window *pParent, SwView &rMyView):
5159 Window(pParent, WinBits(WB_CLIPCHILDREN | WB_DIALOGCONTROL)),
5160 DropTargetHelper( this ),
5161 DragSourceHelper( this ),
5162
5163 m_eBufferLanguage(LANGUAGE_DONTKNOWLanguageType(0x03FF)),
5164 m_pUserMarkerObj( nullptr ),
5165
5166 m_rView( rMyView ),
5167
5168 m_aActHitType(SdrHitKind::NONE),
5169 m_nDropFormat( SotClipboardFormatId::NONE ),
5170 m_nDropAction( 0 ),
5171 m_nDropDestination( SotExchangeDest::NONE ),
5172
5173 m_eBezierMode(SID_BEZIER_INSERT( 10000 + 119 )),
5174 m_nInsFrameColCount( 1 ),
5175 m_eDrawMode(OBJ_NONE),
5176
5177 m_bMBPressed(false),
5178 m_bInsDraw(false),
5179 m_bInsFrame(false),
5180 m_bIsInMove(false),
5181 m_bIsInDrag(false),
5182 m_bOldIdle(false),
5183 m_bOldIdleSet(false),
5184 m_bChainMode(false),
5185 m_bWasShdwCursor(false),
5186 m_bLockInput(false),
5187 m_bIsRowDrag(false),
5188 m_bUseInputLanguage(false),
5189 m_bObjectSelect(false),
5190 m_nKS_NUMDOWN_Count(0),
5191 m_nKS_NUMINDENTINC_Count(0),
5192 m_pFrameControlsManager(new SwFrameControlsManager(this))
5193{
5194 set_id("writer_edit");
5195 SetHelpId(HID_EDIT_WIN"SW_HID_EDIT_WIN");
5196 EnableChildTransparentMode();
5197 SetDialogControlFlags( DialogControlFlags::Return | DialogControlFlags::WantFocus );
5198
5199 m_bMBPressed = m_bInsDraw = m_bInsFrame =
5200 m_bIsInDrag = m_bOldIdle = m_bOldIdleSet = m_bChainMode = m_bWasShdwCursor = false;
5201 // initially use the input language
5202 m_bUseInputLanguage = true;
5203
5204 SetMapMode(MapMode(MapUnit::MapTwip));
5205
5206 SetPointer( PointerStyle::Text );
5207 m_aTimer.SetInvokeHandler(LINK(this, SwEditWin, TimerHandler)::tools::detail::makeLink( ::tools::detail::castTo<SwEditWin
*>(this), &SwEditWin::LinkStubTimerHandler)
);
5208
5209 m_aKeyInputFlushTimer.SetTimeout( 200 );
5210 m_aKeyInputFlushTimer.SetInvokeHandler(LINK(this, SwEditWin, KeyInputFlushHandler)::tools::detail::makeLink( ::tools::detail::castTo<SwEditWin
*>(this), &SwEditWin::LinkStubKeyInputFlushHandler)
);
5211
5212 // TemplatePointer for colors should be reset without
5213 // selection after single click, but not after double-click (tdf#122442)
5214 m_aTemplateTimer.SetTimeout(GetSettings().GetMouseSettings().GetDoubleClickTime());
5215 m_aTemplateTimer.SetInvokeHandler(LINK(this, SwEditWin, TemplateTimerHdl)::tools::detail::makeLink( ::tools::detail::castTo<SwEditWin
*>(this), &SwEditWin::LinkStubTemplateTimerHdl)
);
5216
5217 // temporary solution!!! Should set the font of the current
5218 // insert position at every cursor movement!
5219 if( !rMyView.GetDocShell()->IsReadOnly() )
5220 {
5221 vcl::Font aFont;
5222 SetInputContext( InputContext( aFont, InputContextFlags::Text |
5223 InputContextFlags::ExtText ) );
5224 }
5225}
5226
5227SwEditWin::~SwEditWin()
5228{
5229 disposeOnce();
5230}
5231
5232void SwEditWin::dispose()
5233{
5234 m_pShadCursor.reset();
5235
5236 if( m_pQuickHlpData->m_bIsDisplayed && m_rView.GetWrtShellPtr() )
5237 m_pQuickHlpData->Stop( m_rView.GetWrtShell() );
5238 g_bExecuteDrag = false;
5239 m_pApplyTempl.reset();
5240
5241 m_rView.SetDrawFuncPtr(nullptr);
5242
5243 m_pUserMarker.reset();
5244
5245 m_pAnchorMarker.reset();
5246
5247 m_pFrameControlsManager->dispose();
5248 m_pFrameControlsManager.reset();
5249
5250 DragSourceHelper::dispose();
5251 DropTargetHelper::dispose();
5252 vcl::Window::dispose();
5253}
5254
5255/**
5256 * Turn on DrawTextEditMode
5257 */
5258void SwEditWin::EnterDrawTextMode( const Point& aDocPos )
5259{
5260 if ( m_rView.EnterDrawTextMode(aDocPos) )
5261 {
5262 if (m_rView.GetDrawFuncPtr())
5263 {
5264 m_rView.GetDrawFuncPtr()->Deactivate();
5265 m_rView.SetDrawFuncPtr(nullptr);
5266 m_rView.LeaveDrawCreate();
5267 }
5268 m_rView.NoRotate();
5269 m_rView.AttrChangedNotify(nullptr);
5270 }
5271}
5272
5273/**
5274 * Turn on DrawMode
5275 */
5276bool SwEditWin::EnterDrawMode(const MouseEvent& rMEvt, const Point& aDocPos)
5277{
5278 SwWrtShell &rSh = m_rView.GetWrtShell();
5279 SdrView *pSdrView = rSh.GetDrawView();
5280
5281 if ( m_rView.GetDrawFuncPtr() )
5282 {
5283 if (rSh.IsDrawCreate())
5284 return true;
5285
5286 bool bRet = m_rView.GetDrawFuncPtr()->MouseButtonDown( rMEvt );
5287 m_rView.AttrChangedNotify(nullptr);
5288 return bRet;
5289 }
5290
5291 if ( pSdrView && pSdrView->IsTextEdit() )
5292 {
5293 bool bUnLockView = !rSh.IsViewLocked();
5294 rSh.LockView( true );
5295
5296 rSh.EndTextEdit(); // clicked aside, end Edit
5297 rSh.SelectObj( aDocPos );
5298 if ( !rSh.IsObjSelected() && !rSh.IsFrameSelected() )
5299 rSh.LeaveSelFrameMode();
5300 else
5301 {
5302 SwEditWin::m_nDDStartPosY = aDocPos.Y();
5303 SwEditWin::m_nDDStartPosX = aDocPos.X();
5304 g_bFrameDrag = true;
5305 }
5306 if( bUnLockView )
5307 rSh.LockView( false );
5308 m_rView.AttrChangedNotify(nullptr);
5309 return true;
5310 }
5311 return false;
5312}
5313
5314bool SwEditWin::IsDrawSelMode() const
5315{
5316 return IsObjectSelect();
5317}
5318
5319void SwEditWin::GetFocus()
5320{
5321 if ( m_rView.GetPostItMgr()->HasActiveSidebarWin() )
5322 {
5323 m_rView.GetPostItMgr()->GrabFocusOnActiveSidebarWin();
5324 }
5325 else
5326 {
5327 m_rView.GotFocus();
5328 Window::GetFocus();
5329 m_rView.GetWrtShell().InvalidateAccessibleFocus();
5330 }
5331}
5332
5333void SwEditWin::LoseFocus()
5334{
5335 if (m_rView.GetWrtShellPtr())
5336 m_rView.GetWrtShell().InvalidateAccessibleFocus();
5337 Window::LoseFocus();
5338 if( m_pQuickHlpData && m_pQuickHlpData->m_bIsDisplayed )
5339 m_pQuickHlpData->Stop( m_rView.GetWrtShell() );
5340}
5341
5342void SwEditWin::Command( const CommandEvent& rCEvt )
5343{
5344 SwWrtShell &rSh = m_rView.GetWrtShell();
5345
5346 if ( !m_rView.GetViewFrame() )
1
Assuming the condition is false
2
Taking false branch
5347 {
5348 // If ViewFrame dies shortly, no popup anymore!
5349 Window::Command(rCEvt);
5350 return;
5351 }
5352
5353 // The command event is send to the window after a possible context
5354 // menu from an inplace client has been closed. Now we have the chance
5355 // to deactivate the inplace client without any problem regarding parent
5356 // windows and code on the stack.
5357 SfxInPlaceClient* pIPClient = rSh.GetSfxViewShell()->GetIPClient();
5358 bool bIsOleActive = ( pIPClient && pIPClient->IsObjectInPlaceActive() );
3
Assuming 'pIPClient' is null
5359 if ( bIsOleActive
3.1
'bIsOleActive' is false
3.1
'bIsOleActive' is false
3.1
'bIsOleActive' is false
3.1
'bIsOleActive' is false
&& ( rCEvt.GetCommand() == CommandEventId::ContextMenu ))
5360 {
5361 rSh.FinishOLEObj();
5362 return;
5363 }
5364
5365 bool bCallBase = true;
5366
5367 switch ( rCEvt.GetCommand() )
4
Control jumps to 'case ContextMenu:' at line 5369
5368 {
5369 case CommandEventId::ContextMenu:
5370 {
5371 const sal_uInt16 nId = SwInputChild::GetChildWindowId();
5372 SwInputChild* pChildWin = static_cast<SwInputChild*>(GetView().GetViewFrame()->
5373 GetChildWindow( nId ));
5374
5375 if (m_rView.GetPostItMgr()->IsHit(rCEvt.GetMousePosPixel()))
5
Assuming the condition is false
6
Taking false branch
5376 return;
5377
5378 Point aDocPos( PixelToLogic( rCEvt.GetMousePosPixel() ) );
5379 if ( !rCEvt.IsMouseEvent() )
7
Assuming the condition is false
8
Taking false branch
5380 aDocPos = rSh.GetCharRect().Center();
5381
5382 // Don't trigger the command on a frame anchored to header/footer is not editing it
5383 FrameControlType eControl;
5384 bool bOverFly = false;
5385 bool bPageAnchored = false;
5386 bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored );
5387 // !bOverHeaderFooterFly doesn't mean we have a frame to select
5388 if ( !bPageAnchored
8.1
'bPageAnchored' is false
8.1
'bPageAnchored' is false
8.1
'bPageAnchored' is false
8.1
'bPageAnchored' is false
&& rCEvt.IsMouseEvent( ) &&
10
Taking false branch
5389 ( ( rSh.IsHeaderFooterEdit( ) && !bOverHeaderFooterFly && bOverFly ) ||
9
Assuming the condition is false
5390 ( !rSh.IsHeaderFooterEdit( ) && bOverHeaderFooterFly
9.1
'bOverHeaderFooterFly' is false
9.1
'bOverHeaderFooterFly' is false
9.1
'bOverHeaderFooterFly' is false
9.1
'bOverHeaderFooterFly' is false
) ) )
5391 {
5392 return;
5393 }
5394
5395 if((!pChildWin || pChildWin->GetView() != &m_rView) &&
11
Assuming 'pChildWin' is null
14
Taking true branch
5396 !rSh.IsDrawCreate() && !IsDrawAction())
12
Assuming the condition is true
13
Assuming the condition is true
5397 {
5398 CurrShell aCurr( &rSh );
5399 if (!m_pApplyTempl)
15
Taking true branch
5400 {
5401 if (g_bNoInterrupt)
16
Assuming 'g_bNoInterrupt' is false
17
Taking false branch
5402 {
5403 ReleaseMouse();
5404 g_bNoInterrupt = false;
5405 m_bMBPressed = false;
5406 }
5407 if ( rCEvt.IsMouseEvent() )
18
Taking true branch
5408 {
5409 SelectMenuPosition(rSh, rCEvt.GetMousePosPixel());
5410 m_rView.StopShellTimer();
5411 }
5412 const Point aPixPos = LogicToPixel( aDocPos );
5413
5414 if ( m_rView.GetDocShell()->IsReadOnly() )
19
Assuming the condition is true
20
Taking true branch
5415 {
5416 SwReadOnlyPopup aROPopup(aDocPos, m_rView);
5417
5418 ui::ContextMenuExecuteEvent aEvent;
5419 aEvent.SourceWindow = VCLUnoHelper::GetInterface( this );
5420 aEvent.ExecutePosition.X = aPixPos.X();
5421 aEvent.ExecutePosition.Y = aPixPos.Y();
5422 ScopedVclPtr<Menu> pMenu;
5423 if (GetView().TryContextMenuInterception(aROPopup.GetMenu(), "private:resource/ReadonlyContextMenu", pMenu, aEvent))
21
Assuming the condition is false
22
Taking false branch
5424 {
5425 if ( pMenu )
5426 {
5427 sal_uInt16 nExecId = static_cast<PopupMenu*>(pMenu.get())->Execute(this, aPixPos);
5428 if( !::ExecuteMenuCommand( *static_cast<PopupMenu*>(pMenu.get()), *m_rView.GetViewFrame(), nExecId ))
5429 aROPopup.Execute(this, nExecId);
5430 }
5431 else
5432 aROPopup.Execute(this, aPixPos);
5433 }
5434 }
23
Calling '~ScopedVclPtr'
5435 else if ( !m_rView.ExecSpellPopup( aDocPos ) )
5436 SfxDispatcher::ExecutePopup(this, &aPixPos);
5437 }
5438 else if (m_pApplyTempl->nUndo < rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount())
5439 {
5440 // Undo until we reach the point when we entered this context.
5441 rSh.Do(SwWrtShell::UNDO);
5442 }
5443 bCallBase = false;
5444 }
5445 }
5446 break;
5447
5448 case CommandEventId::Wheel:
5449 case CommandEventId::StartAutoScroll:
5450 case CommandEventId::AutoScroll:
5451 if (m_pSavedOutlineFrame && rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
5452 {
5453 GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame);
5454 m_pSavedOutlineFrame = nullptr;
5455 }
5456 m_pShadCursor.reset();
5457 bCallBase = !m_rView.HandleWheelCommands( rCEvt );
5458 break;
5459
5460 case CommandEventId::LongPress:
5461 case CommandEventId::Swipe: //nothing yet
5462 break;
5463
5464 case CommandEventId::StartExtTextInput:
5465 {
5466 bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
5467 rSh.IsCursorReadonly();
5468 if(!bIsDocReadOnly)
5469 {
5470 if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() )
5471 {
5472 bCallBase = false;
5473 rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt );
5474 }
5475 else
5476 {
5477 if( rSh.HasSelection() )
5478 rSh.DelRight();
5479
5480 bCallBase = false;
5481 LanguageType eInputLanguage = GetInputLanguage();
5482 rSh.CreateExtTextInput(eInputLanguage);
5483 }
5484 }
5485 break;
5486 }
5487 case CommandEventId::EndExtTextInput:
5488 {
5489 bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
5490 rSh.IsCursorReadonly();
5491 if(!bIsDocReadOnly)
5492 {
5493 if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() )
5494 {
5495 bCallBase = false;
5496 rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt );
5497 }
5498 else
5499 {
5500 bCallBase = false;
5501 OUString sRecord = rSh.DeleteExtTextInput();
5502 uno::Reference< frame::XDispatchRecorder > xRecorder =
5503 m_rView.GetViewFrame()->GetBindings().GetRecorder();
5504
5505 if ( !sRecord.isEmpty() )
5506 {
5507 // convert quotes in IME text
5508 // works on the last input character, this is especially in Korean text often done
5509 // quotes that are inside of the string are not replaced!
5510 const sal_Unicode aCh = sRecord[sRecord.getLength() - 1];
5511 SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get();
5512 SvxAutoCorrect* pACorr = rACfg.GetAutoCorrect();
5513 if(pACorr &&
5514 (( pACorr->IsAutoCorrFlag( ACFlags::ChgQuotes ) && ('\"' == aCh ))||
5515 ( pACorr->IsAutoCorrFlag( ACFlags::ChgSglQuotes ) && ( '\'' == aCh))))
5516 {
5517 rSh.DelLeft();
5518 rSh.AutoCorrect( *pACorr, aCh );
5519 }
5520
5521 if ( xRecorder.is() )
5522 {
5523 // determine Shell
5524 SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
5525 // generate request and record
5526 if (pSfxShell)
5527 {
5528 SfxRequest aReq( m_rView.GetViewFrame(), FN_INSERT_STRING((20000 + 300)+31) );
5529 aReq.AppendItem( SfxStringItem( FN_INSERT_STRING((20000 + 300)+31), sRecord ) );
5530 aReq.Done();
5531 }
5532 }
5533 }
5534 }
5535 }
5536 }
5537 break;
5538 case CommandEventId::ExtTextInput:
5539 {
5540 bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
5541 rSh.IsCursorReadonly();
5542 if(!bIsDocReadOnly)
5543 {
5544 if( m_pQuickHlpData->m_bIsDisplayed )
5545 m_pQuickHlpData->Stop( rSh );
5546
5547 if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() )
5548 {
5549 bCallBase = false;
5550 rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt );
5551 }
5552 else
5553 {
5554 const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData();
5555 if( pData )
5556 {
5557 bCallBase = false;
5558 rSh.SetExtTextInputData( *pData );
5559 }
5560 }
5561 uno::Reference< frame::XDispatchRecorder > xRecorder =
5562 m_rView.GetViewFrame()->GetBindings().GetRecorder();
5563 if(!xRecorder.is())
5564 {
5565 SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get();
5566 if (!rACfg.IsAutoTextTip() || !ShowAutoText(rSh.GetChunkForAutoText()))
5567 {
5568 SvxAutoCorrect* pACorr = rACfg.GetAutoCorrect();
5569 if (pACorr && pACorr->GetSwFlags().bAutoCompleteWords)
5570 ShowAutoCorrectQuickHelp(rSh.GetPrevAutoCorrWord(*pACorr), *pACorr);
5571 }
5572 }
5573 }
5574 }
5575 break;
5576 case CommandEventId::CursorPos:
5577 // will be handled by the base class
5578 break;
5579
5580 case CommandEventId::PasteSelection:
5581 if( !m_rView.GetDocShell()->IsReadOnly() )
5582 {
5583 TransferableDataHelper aDataHelper(
5584 TransferableDataHelper::CreateFromSelection( this ));
5585 if( !aDataHelper.GetXTransferable().is() )
5586 break;
5587
5588 SotExchangeDest nDropDestination = GetDropDestination( rCEvt.GetMousePosPixel() );
5589 if( !bool(nDropDestination) )
5590 break;
5591 SotClipboardFormatId nDropFormat;
5592 sal_uInt8 nEventAction, nDropAction;
5593 SotExchangeActionFlags nActionFlags;
5594 nDropAction = SotExchange::GetExchangeAction(
5595 aDataHelper.GetDataFlavorExVector(),
5596 nDropDestination, EXCHG_IN_ACTION_COPY(sal_uInt8(css::datatransfer::dnd::DNDConstants::ACTION_COPY)
)
,
5597 EXCHG_IN_ACTION_COPY(sal_uInt8(css::datatransfer::dnd::DNDConstants::ACTION_COPY)
)
, nDropFormat,
5598 nEventAction,
5599 SotClipboardFormatId::NONE, nullptr,
5600 &nActionFlags );
5601 if( EXCHG_INOUT_ACTION_NONE(sal_uInt8(css::datatransfer::dnd::DNDConstants::ACTION_NONE)
)
!= nDropAction )
5602 {
5603 const Point aDocPt( PixelToLogic( rCEvt.GetMousePosPixel() ) );
5604 SwTransferable::PasteData( aDataHelper, rSh, nDropAction, nActionFlags,
5605 nDropFormat, nDropDestination, false,
5606 false, &aDocPt, EXCHG_IN_ACTION_COPY(sal_uInt8(css::datatransfer::dnd::DNDConstants::ACTION_COPY)
)
,
5607 true );
5608 }
5609 }
5610 break;
5611 case CommandEventId::ModKeyChange :
5612 {
5613 const CommandModKeyData* pCommandData = rCEvt.GetModKeyData();
5614 if (!pCommandData->IsDown() && pCommandData->IsMod1() && !pCommandData->IsMod2())
5615 {
5616 sal_uInt16 nSlot = 0;
5617 if(pCommandData->IsLeftShift() && !pCommandData->IsRightShift())
5618 nSlot = SID_ATTR_PARA_LEFT_TO_RIGHT( 10000 + 950 );
5619 else if(!pCommandData->IsLeftShift() && pCommandData->IsRightShift())
5620 nSlot = SID_ATTR_PARA_RIGHT_TO_LEFT( 10000 + 951 );
5621 if(nSlot && SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->GetCTLOptions().IsCTLFontEnabled())
5622 GetView().GetViewFrame()->GetDispatcher()->Execute(nSlot);
5623 }
5624 }
5625 break;
5626 case CommandEventId::InputLanguageChange :
5627 // i#42732 - update state of fontname if input language changes
5628 g_bInputLanguageSwitched = true;
5629 SetUseInputLanguage( true );
5630 break;
5631 case CommandEventId::SelectionChange:
5632 {
5633 const CommandSelectionChangeData *pData = rCEvt.GetSelectionChangeData();
5634 rSh.SttCursorMove();
5635 rSh.GoStartSentence();
5636 rSh.GetCursor()->GetPoint()->nContent += sal::static_int_cast<sal_uInt16, sal_uLong>(pData->GetStart());
5637 rSh.SetMark();
5638 rSh.GetCursor()->GetMark()->nContent += sal::static_int_cast<sal_uInt16, sal_uLong>(pData->GetEnd() - pData->GetStart());
5639 rSh.EndCursorMove( true );
5640 }
5641 break;
5642 case CommandEventId::PrepareReconversion:
5643 if( rSh.HasSelection() )
5644 {
5645 SwPaM *pCursor = rSh.GetCursor();
5646
5647 if( rSh.IsMultiSelection() )
5648 {
5649 if (pCursor && !pCursor->HasMark() &&
5650 pCursor->GetPoint() == pCursor->GetMark())
5651 {
5652 rSh.GoPrevCursor();
5653 pCursor = rSh.GetCursor();
5654 }
5655
5656 // Cancel all selections other than the last selected one.
5657 while( rSh.GetCursor()->GetNext() != rSh.GetCursor() )
5658 delete rSh.GetCursor()->GetNext();
5659 }
5660
5661 if( pCursor )
5662 {
5663 sal_uLong nPosNodeIdx = pCursor->GetPoint()->nNode.GetIndex();
5664 const sal_Int32 nPosIdx = pCursor->GetPoint()->nContent.GetIndex();
5665 sal_uLong nMarkNodeIdx = pCursor->GetMark()->nNode.GetIndex();
5666 const sal_Int32 nMarkIdx = pCursor->GetMark()->nContent.GetIndex();
5667
5668 if( !rSh.GetCursor()->HasMark() )
5669 rSh.GetCursor()->SetMark();
5670
5671 rSh.SttCursorMove();
5672
5673 if( nPosNodeIdx < nMarkNodeIdx )
5674 {
5675 rSh.GetCursor()->GetPoint()->nNode = nPosNodeIdx;
5676 rSh.GetCursor()->GetPoint()->nContent = nPosIdx;
5677 rSh.GetCursor()->GetMark()->nNode = nPosNodeIdx;
5678 rSh.GetCursor()->GetMark()->nContent =
5679 rSh.GetCursor()->GetContentNode()->Len();
5680 }
5681 else if( nPosNodeIdx == nMarkNodeIdx )
5682 {
5683 rSh.GetCursor()->GetPoint()->nNode = nPosNodeIdx;
5684 rSh.GetCursor()->GetPoint()->nContent = nPosIdx;
5685 rSh.GetCursor()->GetMark()->nNode = nMarkNodeIdx;
5686 rSh.GetCursor()->GetMark()->nContent = nMarkIdx;
5687 }
5688 else
5689 {
5690 rSh.GetCursor()->GetMark()->nNode = nMarkNodeIdx;
5691 rSh.GetCursor()->GetMark()->nContent = nMarkIdx;
5692 rSh.GetCursor()->GetPoint()->nNode = nMarkNodeIdx;
5693 rSh.GetCursor()->GetPoint()->nContent =
5694 rSh.GetCursor()->GetContentNode( false )->Len();
5695 }
5696
5697 rSh.EndCursorMove( true );
5698 }
5699 }
5700 break;
5701 case CommandEventId::QueryCharPosition:
5702 {
5703 bool bVertical = rSh.IsInVerticalText();
5704 const SwPosition& rPos = *rSh.GetCursor()->GetPoint();
5705 SwDocShell* pDocSh = m_rView.GetDocShell();
5706 SwDoc *pDoc = pDocSh->GetDoc();
5707 SwExtTextInput* pInput = pDoc->GetExtTextInput( rPos.nNode.GetNode(), rPos.nContent.GetIndex() );
5708 if ( pInput )
5709 {
5710 const SwPosition& rStart = *pInput->Start();
5711 const SwPosition& rEnd = *pInput->End();
5712 int nSize = 0;
5713 for ( SwIndex nIndex = rStart.nContent; nIndex < rEnd.nContent; ++nIndex )
5714 {
5715 ++nSize;
5716 }
5717 vcl::Window& rWin = rSh.GetView().GetEditWin();
5718 if ( nSize == 0 )
5719 {
5720 // When the composition does not exist, use Caret rect instead.
5721 const SwRect& aCaretRect ( rSh.GetCharRect() );
5722 tools::Rectangle aRect( aCaretRect.Left(), aCaretRect.Top(), aCaretRect.Right(), aCaretRect.Bottom() );
5723 rWin.SetCompositionCharRect( &aRect, 1, bVertical );
5724 }
5725 else
5726 {
5727 std::unique_ptr<tools::Rectangle[]> aRects(new tools::Rectangle[ nSize ]);
5728 int nRectIndex = 0;
5729 for ( SwIndex nIndex = rStart.nContent; nIndex < rEnd.nContent; ++nIndex )
5730 {
5731 const SwPosition aPos( rStart.nNode, nIndex );
5732 SwRect aRect ( rSh.GetCharRect() );
5733 rSh.GetCharRectAt( aRect, &aPos );
5734 aRects[ nRectIndex ] = tools::Rectangle( aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom() );
5735 ++nRectIndex;
5736 }
5737 rWin.SetCompositionCharRect( aRects.get(), nSize, bVertical );
5738 }
5739 }
5740 bCallBase = false;
5741 }
5742 break;
5743 default:
5744 SAL_WARN("sw.ui", "unknown command.")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ui")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "unknown command.") == 1) { ::sal_detail_log( (::
SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ui"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
":" "5744" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "unknown command."), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"unknown command."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ui"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
":" "5744" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "unknown command.") == 1) { ::sal_detail_log( (::
SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ui"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
":" "5744" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "unknown command."), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"unknown command."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ui"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
":" "5744" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
5745 break;
5746 }
5747 if (bCallBase)
5748 Window::Command(rCEvt);
5749}
5750
5751/* i#18686 select the object/cursor at the mouse
5752 position of the context menu request */
5753void SwEditWin::SelectMenuPosition(SwWrtShell& rSh, const Point& rMousePos )
5754{
5755 const Point aDocPos( PixelToLogic( rMousePos ) );
5756 const bool bIsInsideSelectedObj( rSh.IsInsideSelectedObj( aDocPos ) );
5757 //create a synthetic mouse event out of the coordinates
5758 MouseEvent aMEvt(rMousePos);
5759 SdrView *pSdrView = rSh.GetDrawView();
5760 if ( pSdrView )
5761 {
5762 // no close of insert_draw and reset of
5763 // draw mode, if context menu position is inside a selected object.
5764 if ( !bIsInsideSelectedObj && m_rView.GetDrawFuncPtr() )
5765 {
5766
5767 m_rView.GetDrawFuncPtr()->Deactivate();
5768 m_rView.SetDrawFuncPtr(nullptr);
5769 m_rView.LeaveDrawCreate();
5770 SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
5771 rBind.Invalidate( SID_ATTR_SIZETypedWhichId<SvxSizeItem>( 10000 + 224 ) );
5772 rBind.Invalidate( SID_TABLE_CELL( 10000 + 225 ) );
5773 }
5774
5775 // if draw text is active and there's a text selection
5776 // at the mouse position then do nothing
5777 if(rSh.GetSelectionType() & SelectionType::DrawObjectEditMode)
5778 {
5779 OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
5780 ESelection aSelection = pOLV->GetSelection();
5781 if(!aSelection.IsZero())
5782 {
5783 SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner();
5784 bool bVertical = pOutliner->IsVertical();
5785 const EditEngine& rEditEng = pOutliner->GetEditEngine();
5786 Point aEEPos(aDocPos);
5787 const tools::Rectangle& rOutputArea = pOLV->GetOutputArea();
5788 // regard vertical mode
5789 if(bVertical)
5790 {
5791 aEEPos -= rOutputArea.TopRight();
5792 //invert the horizontal direction and exchange X and Y
5793 long nTemp = -aEEPos.X();
5794 aEEPos.setX( aEEPos.Y() );
5795 aEEPos.setY( nTemp );
5796 }
5797 else
5798 aEEPos -= rOutputArea.TopLeft();
5799
5800 EPosition aDocPosition = rEditEng.FindDocPosition(aEEPos);
5801 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
5802 // make it a forward selection - otherwise the IsLess/IsGreater do not work :-(
5803 aSelection.Adjust();
5804 if(!(aCompare < aSelection) && !(aCompare > aSelection))
5805 {
5806 return;
5807 }
5808 }
5809
5810 }
5811
5812 if (pSdrView->MouseButtonDown( aMEvt, this ) )
5813 {
5814 pSdrView->MouseButtonUp( aMEvt, this );
5815 rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
5816 return;
5817 }
5818 }
5819 rSh.ResetCursorStack();
5820
5821 if ( EnterDrawMode( aMEvt, aDocPos ) )
5822 {
5823 return;
5824 }
5825 if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
5826 {
5827 StopInsFrame();
5828 rSh.Edit();
5829 }
5830
5831 UpdatePointer( aDocPos );
5832
5833 if( !rSh.IsSelFrameMode() &&
5834 !GetView().GetViewFrame()->GetDispatcher()->IsLocked() )
5835 {
5836 // Test if there is a draw object at that position and if it should be selected.
5837 bool bShould = rSh.ShouldObjectBeSelected(aDocPos);
5838
5839 if(bShould)
5840 {
5841 m_rView.NoRotate();
5842 rSh.HideCursor();
5843
5844 bool bUnLockView = !rSh.IsViewLocked();
5845 rSh.LockView( true );
5846 bool bSelObj = rSh.SelectObj( aDocPos );
5847 if( bUnLockView )
5848 rSh.LockView( false );
5849
5850 if( bSelObj )
5851 {
5852 // in case the frame was deselected in the macro
5853 // just the cursor has to be displayed again.
5854 if( FrameTypeFlags::NONE == rSh.GetSelFrameType() )
5855 rSh.ShowCursor();
5856 else
5857 {
5858 if (rSh.IsFrameSelected() && m_rView.GetDrawFuncPtr())
5859 {
5860 m_rView.GetDrawFuncPtr()->Deactivate();
5861 m_rView.SetDrawFuncPtr(nullptr);
5862 m_rView.LeaveDrawCreate();
5863 m_rView.AttrChangedNotify(nullptr);
5864 }
5865
5866 rSh.EnterSelFrameMode( &aDocPos );
5867 g_bFrameDrag = true;
5868 UpdatePointer( aDocPos );
5869 return;
5870 }
5871 }
5872
5873 if (!m_rView.GetDrawFuncPtr())
5874 rSh.ShowCursor();
5875 }
5876 }
5877 else if ( rSh.IsSelFrameMode() &&
5878 (m_aActHitType == SdrHitKind::NONE ||
5879 !bIsInsideSelectedObj))
5880 {
5881 m_rView.NoRotate();
5882 bool bUnLockView = !rSh.IsViewLocked();
5883 rSh.LockView( true );
5884
5885 if ( rSh.IsSelFrameMode() )
5886 {
5887 rSh.UnSelectFrame();
5888 rSh.LeaveSelFrameMode();
5889 m_rView.AttrChangedNotify(nullptr);
5890 }
5891
5892 bool bSelObj = rSh.SelectObj( aDocPos, 0/*nFlag*/ );
5893 if( bUnLockView )
5894 rSh.LockView( false );
5895
5896 if( !bSelObj )
5897 {
5898 // move cursor here so that it is not drawn in the
5899 // frame at first; ShowCursor() happens in LeaveSelFrameMode()
5900 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
5901 rSh.LeaveSelFrameMode();
5902 m_rView.LeaveDrawCreate();
5903 m_rView.AttrChangedNotify(nullptr);
5904 }
5905 else
5906 {
5907 rSh.HideCursor();
5908 rSh.EnterSelFrameMode( &aDocPos );
5909 rSh.SelFlyGrabCursor();
5910 rSh.MakeSelVisible();
5911 g_bFrameDrag = true;
5912 if( rSh.IsFrameSelected() &&
5913 m_rView.GetDrawFuncPtr() )
5914 {
5915 m_rView.GetDrawFuncPtr()->Deactivate();
5916 m_rView.SetDrawFuncPtr(nullptr);
5917 m_rView.LeaveDrawCreate();
5918 m_rView.AttrChangedNotify(nullptr);
5919 }
5920 UpdatePointer( aDocPos );
5921 }
5922 }
5923 else if ( rSh.IsSelFrameMode() && bIsInsideSelectedObj )
5924 {
5925 // Object at the mouse cursor is already selected - do nothing
5926 return;
5927 }
5928
5929 if ( rSh.IsGCAttr() )
5930 {
5931 rSh.GCAttr();
5932 rSh.ClearGCAttr();
5933 }
5934
5935 bool bOverSelect = rSh.TestCurrPam( aDocPos );
5936 bool bOverURLGrf = false;
5937 if( !bOverSelect )
5938 bOverURLGrf = bOverSelect = nullptr != rSh.IsURLGrfAtPos( aDocPos );
5939
5940 if ( !bOverSelect )
5941 {
5942 // create only temporary move context because otherwise
5943 // the query against the content form doesn't work!!!
5944 SwMvContext aMvContext( &rSh );
5945 rSh.CallSetCursor(&aDocPos, false);
5946 }
5947 if( !bOverURLGrf )
5948 {
5949 const SelectionType nSelType = rSh.GetSelectionType();
5950 if( nSelType == SelectionType::Ole ||
5951 nSelType == SelectionType::Graphic )
5952 {
5953 SwMvContext aMvContext( &rSh );
5954 if( !rSh.IsFrameSelected() )
5955 rSh.GotoNextFly();
5956 rSh.EnterSelFrameMode();
5957 }
5958 }
5959}
5960
5961static SfxShell* lcl_GetTextShellFromDispatcher( SwView const & rView )
5962{
5963 // determine Shell
5964 SfxShell* pShell;
5965 SfxDispatcher* pDispatcher = rView.GetViewFrame()->GetDispatcher();
5966 for(sal_uInt16 i = 0; true; ++i )
5967 {
5968 pShell = pDispatcher->GetShell( i );
5969 if( !pShell || dynamic_cast< const SwTextShell *>( pShell ) != nullptr )
5970 break;
5971 }
5972 return pShell;
5973}
5974
5975IMPL_LINK_NOARG(SwEditWin, KeyInputFlushHandler, Timer *, void)void SwEditWin::LinkStubKeyInputFlushHandler(void * instance,
Timer * data) { return static_cast<SwEditWin *>(instance
)->KeyInputFlushHandler(data); } void SwEditWin::KeyInputFlushHandler
(__attribute__ ((unused)) Timer *)
5976{
5977 FlushInBuffer();
5978}
5979
5980void SwEditWin::InitStaticData()
5981{
5982 m_pQuickHlpData = new QuickHelpData();
5983}
5984
5985void SwEditWin::FinitStaticData()
5986{
5987 delete m_pQuickHlpData;
5988}
5989/* i#3370 - remove quick help to prevent saving
5990 * of autocorrection suggestions */
5991void SwEditWin::StopQuickHelp()
5992{
5993 if( HasFocus() && m_pQuickHlpData && m_pQuickHlpData->m_bIsDisplayed )
5994 m_pQuickHlpData->Stop( m_rView.GetWrtShell() );
5995}
5996
5997IMPL_LINK_NOARG(SwEditWin, TemplateTimerHdl, Timer *, void)void SwEditWin::LinkStubTemplateTimerHdl(void * instance, Timer
* data) { return static_cast<SwEditWin *>(instance)->
TemplateTimerHdl(data); } void SwEditWin::TemplateTimerHdl(__attribute__
((unused)) Timer *)
5998{
5999 SetApplyTemplate(SwApplyTemplate());
6000}
6001
6002void SwEditWin::SetChainMode( bool bOn )
6003{
6004 if ( !m_bChainMode )
6005 StopInsFrame();
6006
6007 m_pUserMarker.reset();
6008
6009 m_bChainMode = bOn;
6010
6011 static sal_uInt16 aInva[] =
6012 {
6013 FN_FRAME_CHAIN((20000 + 1600) + 136), FN_FRAME_UNCHAIN((20000 + 1600) + 137), 0
6014 };
6015 m_rView.GetViewFrame()->GetBindings().Invalidate(aInva);
6016}
6017
6018uno::Reference< css::accessibility::XAccessible > SwEditWin::CreateAccessible()
6019{
6020 SolarMutexGuard aGuard; // this should have happened already!!!
6021 SwWrtShell *pSh = m_rView.GetWrtShellPtr();
6022 OSL_ENSURE( pSh, "no writer shell, no accessible object" )do { if (true && (!(pSh))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
":" "6022" ": "), "%s", "no writer shell, no accessible object"
); } } while (false)
;
6023 uno::Reference<
6024 css::accessibility::XAccessible > xAcc;
6025 if( pSh )
6026 xAcc = pSh->CreateAccessible();
6027
6028 return xAcc;
6029}
6030
6031void QuickHelpData::Move( QuickHelpData& rCpy )
6032{
6033 m_aHelpStrings.clear();
6034 m_aHelpStrings.swap( rCpy.m_aHelpStrings );
6035
6036 m_bIsDisplayed = rCpy.m_bIsDisplayed;
6037 nCurArrPos = rCpy.nCurArrPos;
6038 m_bAppendSpace = rCpy.m_bAppendSpace;
6039 m_bIsTip = rCpy.m_bIsTip;
6040 m_bIsAutoText = rCpy.m_bIsAutoText;
6041}
6042
6043void QuickHelpData::ClearContent()
6044{
6045 nCurArrPos = nNoPos;
6046 m_bIsDisplayed = m_bAppendSpace = false;
6047 nTipId = nullptr;
6048 m_aHelpStrings.clear();
6049 m_bIsTip = true;
6050 m_bIsAutoText = true;
6051}
6052
6053void QuickHelpData::Start(SwWrtShell& rSh, const bool bRestart)
6054{
6055 if (bRestart)
6056 {
6057 nCurArrPos = 0;
6058 }
6059 m_bIsDisplayed = true;
6060
6061 vcl::Window& rWin = rSh.GetView().GetEditWin();
6062 if( m_bIsTip )
6063 {
6064 Point aPt( rWin.OutputToScreenPixel( rWin.LogicToPixel(
6065 rSh.GetCharRect().Pos() )));
6066 aPt.AdjustY( -3 );
6067 nTipId = Help::ShowPopover(&rWin, tools::Rectangle( aPt, Size( 1, 1 )),
6068 CurStr(),
6069 QuickHelpFlags::Left | QuickHelpFlags::Bottom);
6070 }
6071 else
6072 {
6073 OUString sStr(CurStr());
6074 sStr = sStr.copy(CurLen());
6075 sal_uInt16 nL = sStr.getLength();
6076 const ExtTextInputAttr nVal = ExtTextInputAttr::DottedUnderline |
6077 ExtTextInputAttr::Highlight;
6078 const std::vector<ExtTextInputAttr> aAttrs( nL, nVal );
6079 CommandExtTextInputData aCETID( sStr, aAttrs.data(), nL,
6080 0, false );
6081
6082 //fdo#33092. If the current input language is the default
6083 //language that text would appear in if typed, then don't
6084 //force a language on for the ExtTextInput.
6085 LanguageType eInputLanguage = rWin.GetInputLanguage();
6086 if (lcl_isNonDefaultLanguage(eInputLanguage,
6087 rSh.GetView(), sStr) == INVALID_HINT)
6088 {
6089 eInputLanguage = LANGUAGE_DONTKNOWLanguageType(0x03FF);
6090 }
6091
6092 rSh.CreateExtTextInput(eInputLanguage);
6093 rSh.SetExtTextInputData( aCETID );
6094 }
6095}
6096
6097void QuickHelpData::Stop( SwWrtShell& rSh )
6098{
6099 if( !m_bIsTip )
6100 rSh.DeleteExtTextInput( false );
6101 else if( nTipId )
6102 {
6103 vcl::Window& rWin = rSh.GetView().GetEditWin();
6104 Help::HidePopover(&rWin, nTipId);
6105 }
6106 ClearContent();
6107}
6108
6109void QuickHelpData::FillStrArr( SwWrtShell const & rSh, const OUString& rWord )
6110{
6111 enum Capitalization { CASE_LOWER, CASE_UPPER, CASE_SENTENCE, CASE_OTHER };
6112
6113 // Determine word capitalization
6114 const CharClass& rCC = GetAppCharClass();
6115 const OUString sWordLower = rCC.lowercase( rWord );
6116 Capitalization aWordCase = CASE_OTHER;
6117 if ( !rWord.isEmpty() )
6118 {
6119 if ( rWord[0] == sWordLower[0] )
6120 {
6121 if ( rWord == sWordLower )
6122 aWordCase = CASE_LOWER;
6123 }
6124 else
6125 {
6126 // First character is not lower case i.e. assume upper or title case
6127 OUString sWordSentence = sWordLower.replaceAt( 0, 1, OUString(rWord[0]) );
6128 if ( rWord == sWordSentence )
6129 aWordCase = CASE_SENTENCE;
6130 else
6131 {
6132 if ( rWord == rCC.uppercase( rWord ) )
6133 aWordCase = CASE_UPPER;
6134 }
6135 }
6136 }
6137
6138 salhelper::SingletonRef<SwCalendarWrapper>* pCalendar = s_getCalendarWrapper();
6139 (*pCalendar)->LoadDefaultCalendar( rSh.GetCurLang() );
6140
6141 // Add matching calendar month and day names
6142 for ( const auto& aNames : { (*pCalendar)->getMonths(), (*pCalendar)->getDays() } )
6143 {
6144 for ( const auto& rName : aNames )
6145 {
6146 const OUString& rStr( rName.FullName );
6147 // Check string longer than word and case insensitive match
6148 if( rStr.getLength() > rWord.getLength() &&
6149 rCC.lowercase( rStr, 0, rWord.getLength() ) == sWordLower )
6150 {
6151 OUString sStr;
6152
6153 //fdo#61251 if it's an exact match, ensure unchanged replacement
6154 //exists as a candidate
6155 if (rStr.startsWith(rWord))
6156 m_aHelpStrings.emplace_back(rStr, rWord.getLength());
6157 else
6158 sStr = rStr; // to be added if no case conversion is performed below
6159
6160 if ( aWordCase == CASE_LOWER )
6161 sStr = rCC.lowercase(rStr);
6162 else if ( aWordCase == CASE_SENTENCE )
6163 sStr = rCC.lowercase(rStr).replaceAt(0, 1, OUString(rStr[0]));
6164 else if ( aWordCase == CASE_UPPER )
6165 sStr = rCC.uppercase(rStr);
6166
6167 if (!sStr.isEmpty())
6168 m_aHelpStrings.emplace_back(sStr, rWord.getLength());
6169 }
6170 }
6171 }
6172
6173 // Add matching current date in ISO 8601 format, for example 2016-01-30
6174 OUString rStrToday;
6175
6176 // do not suggest for single years, for example for "2016",
6177 // only for "201" or "2016-..." (to avoid unintentional text
6178 // insertion at line ending, for example typing "30 January 2016")
6179 if (!rWord.isEmpty() && rWord.getLength() != 4 && rWord[0] == '2')
6180 {
6181 rStrToday = utl::toISO8601(DateTime(Date(Date::SYSTEM)).GetUNODateTime());
6182 if (rStrToday.startsWith(rWord))
6183 m_aHelpStrings.emplace_back(rStrToday, rWord.getLength());
6184 }
6185
6186 // Add matching words from AutoCompleteWord list
6187 const SwAutoCompleteWord& rACList = SwEditShell::GetAutoCompleteWords();
6188 std::vector<OUString> strings;
6189
6190 if ( !rACList.GetWordsMatching( rWord, strings ) )
6191 return;
6192
6193 for (const OUString & aCompletedString : strings)
6194 {
6195 // when we have a matching current date, avoid to suggest
6196 // other words with the same matching starting characters,
6197 // for example 2016-01-3 instead of 2016-01-30
6198 if (!rStrToday.isEmpty() && aCompletedString.startsWith(rWord))
6199 continue;
6200
6201 OUString sStr;
6202
6203 //fdo#61251 if it's an exact match, ensure unchanged replacement
6204 //exists as a candidate
6205 if (aCompletedString.startsWith(rWord))
6206 m_aHelpStrings.emplace_back(aCompletedString, rWord.getLength());
6207 else
6208 sStr = aCompletedString; // to be added if no case conversion is performed below
6209
6210 if (aWordCase == CASE_LOWER)
6211 sStr = rCC.lowercase(aCompletedString);
6212 else if (aWordCase == CASE_SENTENCE)
6213 sStr = rCC.lowercase(aCompletedString)
6214 .replaceAt(0, 1, OUString(aCompletedString[0]));
6215 else if (aWordCase == CASE_UPPER)
6216 sStr = rCC.uppercase(aCompletedString);
6217
6218 if (!sStr.isEmpty())
6219 m_aHelpStrings.emplace_back(aCompletedString, rWord.getLength());
6220 }
6221}
6222
6223namespace {
6224
6225class CompareIgnoreCaseAsciiFavorExact
6226{
6227 const OUString &m_rOrigWord;
6228public:
6229 explicit CompareIgnoreCaseAsciiFavorExact(const OUString& rOrigWord)
6230 : m_rOrigWord(rOrigWord)
6231 {
6232 }
6233
6234 bool operator()(const std::pair<OUString, sal_uInt16>& s1,
6235 const std::pair<OUString, sal_uInt16>& s2) const
6236 {
6237 int nRet = s1.first.compareToIgnoreAsciiCase(s2.first);
6238 if (nRet == 0)
6239 {
6240 //fdo#61251 sort stuff that starts with the exact rOrigWord before
6241 //another ignore-case candidate
6242 int n1StartsWithOrig = s1.first.startsWith(m_rOrigWord) ? 0 : 1;
6243 int n2StartsWithOrig = s2.first.startsWith(m_rOrigWord) ? 0 : 1;
6244 return n1StartsWithOrig < n2StartsWithOrig;
6245 }
6246 return nRet < 0;
6247 }
6248};
6249
6250struct EqualIgnoreCaseAscii
6251{
6252 bool operator()(const std::pair<OUString, sal_uInt16>& s1,
6253 const std::pair<OUString, sal_uInt16>& s2) const
6254 {
6255 return s1.first.equalsIgnoreAsciiCase(s2.first);
6256 }
6257};
6258
6259} // anonymous namespace
6260
6261// TODO Implement an i18n aware sort
6262void QuickHelpData::SortAndFilter(const OUString &rOrigWord)
6263{
6264 std::sort( m_aHelpStrings.begin(),
6265 m_aHelpStrings.end(),
6266 CompareIgnoreCaseAsciiFavorExact(rOrigWord) );
6267
6268 const auto& it
6269 = std::unique(m_aHelpStrings.begin(), m_aHelpStrings.end(), EqualIgnoreCaseAscii());
6270 m_aHelpStrings.erase( it, m_aHelpStrings.end() );
6271
6272 nCurArrPos = 0;
6273}
6274
6275// For a given chunk of typed text between 3 and 9 characters long that may start at a word boundary
6276// or in a whitespace and may include whitespaces, SwEditShell::GetChunkForAutoTextcreates a list of
6277// possible candidates for long AutoText names. Let's say, we have typed text "lorem ipsum dr f";
6278// and the cursor is right after the "f". SwEditShell::GetChunkForAutoText would take " dr f",
6279// since it's the longest chunk to the left of the cursor no longer than 9 characters, not starting
6280// in the middle of a word. Then it would create this list from it (in this order, longest first):
6281// " dr f"
6282// " dr f"
6283// "dr f"
6284// It cannot add "r f", because it starts in the middle of the word "dr"; also it cannot give " f",
6285// because it's only 2 characters long.
6286// Now the result of SwEditShell::GetChunkForAutoText is passed here to SwEditWin::ShowAutoText, and
6287// then to SwGlossaryList::HasLongName, where all existing autotext entries' long names are tested
6288// if they start with one of the list elements. The matches are sorted according the position of the
6289// candidate that matched first, then alphabetically inside the group of suggestions for a given
6290// candidate. Say, if we have these AutoText entry long names:
6291// "Dr Frodo"
6292// "Dr Credo"
6293// "Or Bilbo"
6294// "dr foo"
6295// " Dr Fuzz"
6296// " dr Faust"
6297// the resulting list would be:
6298// " Dr Fuzz" -> matches the first (longest) item in the candidates list
6299// " dr Faust" -> matches the second candidate item
6300// "Dr Foo" -> first item of the two matching the third candidate; alphabetically sorted
6301// "Dr Frodo" -> second item of the two matching the third candidate; alphabetically sorted
6302// Each of the resulting suggestions knows the length of the candidate it replaces, so accepting the
6303// first suggestion would replace 6 characters before cursor, while tabbing to and accepting the
6304// last suggestion would replace only 4 characters to the left of cursor.
6305bool SwEditWin::ShowAutoText(const std::vector<OUString>& rChunkCandidates)
6306{
6307 m_pQuickHlpData->ClearContent();
6308 if (!rChunkCandidates.empty())
6309 {
6310 SwGlossaryList* pList = ::GetGlossaryList();
6311 pList->HasLongName(rChunkCandidates, m_pQuickHlpData->m_aHelpStrings);
6312 }
6313
6314 if (!m_pQuickHlpData->m_aHelpStrings.empty())
6315 {
6316 m_pQuickHlpData->Start(m_rView.GetWrtShell(), true);
6317 }
6318 return !m_pQuickHlpData->m_aHelpStrings.empty();
6319}
6320
6321void SwEditWin::ShowAutoCorrectQuickHelp(
6322 const OUString& rWord, SvxAutoCorrect& rACorr )
6323{
6324 if (rWord.isEmpty())
6325 return;
6326 SwWrtShell& rSh = m_rView.GetWrtShell();
6327 m_pQuickHlpData->ClearContent();
6328
6329 if( m_pQuickHlpData->m_aHelpStrings.empty() &&
6330 rACorr.GetSwFlags().bAutoCompleteWords )
6331 {
6332 m_pQuickHlpData->m_bIsAutoText = false;
6333 m_pQuickHlpData->m_bIsTip = rACorr.GetSwFlags().bAutoCmpltShowAsTip;
6334
6335 // Get the necessary data to show help text.
6336 m_pQuickHlpData->FillStrArr( rSh, rWord );
6337 }
6338
6339 if( !m_pQuickHlpData->m_aHelpStrings.empty() )
6340 {
6341 m_pQuickHlpData->SortAndFilter(rWord);
6342 m_pQuickHlpData->Start(rSh, true);
6343 }
6344}
6345
6346bool SwEditWin::IsInHeaderFooter( const Point &rDocPt, FrameControlType &rControl ) const
6347{
6348 SwWrtShell &rSh = m_rView.GetWrtShell();
6349 const SwPageFrame* pPageFrame = rSh.GetLayout()->GetPageAtPos( rDocPt );
6350
6351 if ( pPageFrame && pPageFrame->IsOverHeaderFooterArea( rDocPt, rControl ) )
6352 return true;
6353
6354 if ( rSh.IsShowHeaderFooterSeparator( FrameControlType::Header ) || rSh.IsShowHeaderFooterSeparator( FrameControlType::Footer ) )
6355 {
6356 SwFrameControlsManager &rMgr = rSh.GetView().GetEditWin().GetFrameControlsManager();
6357 Point aPoint( LogicToPixel( rDocPt ) );
6358
6359 if ( rSh.IsShowHeaderFooterSeparator( FrameControlType::Header ) )
6360 {
6361 SwFrameControlPtr pControl = rMgr.GetControl( FrameControlType::Header, pPageFrame );
6362 if ( pControl && pControl->Contains( aPoint ) )
6363 {
6364 rControl = FrameControlType::Header;
6365 return true;
6366 }
6367 }
6368
6369 if ( rSh.IsShowHeaderFooterSeparator( FrameControlType::Footer ) )
6370 {
6371 SwFrameControlPtr pControl = rMgr.GetControl( FrameControlType::Footer, pPageFrame );
6372 if ( pControl && pControl->Contains( aPoint ) )
6373 {
6374 rControl = FrameControlType::Footer;
6375 return true;
6376 }
6377 }
6378 }
6379
6380 return false;
6381}
6382
6383bool SwEditWin::IsOverHeaderFooterFly( const Point& rDocPos, FrameControlType& rControl, bool& bOverFly, bool& bPageAnchored ) const
6384{
6385 bool bRet = false;
6386 Point aPt( rDocPos );
6387 SwWrtShell &rSh = m_rView.GetWrtShell();
6388 SwPaM aPam( *rSh.GetCurrentShellCursor().GetPoint() );
6389 rSh.GetLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aPt, nullptr, true );
6390
6391 const SwStartNode* pStartFly = aPam.GetPoint()->nNode.GetNode().FindFlyStartNode();
6392 if ( pStartFly )
6393 {
6394 bOverFly = true;
6395 SwFrameFormat* pFlyFormat = pStartFly->GetFlyFormat( );
6396 if ( pFlyFormat )
6397 {
6398 const SwPosition* pAnchor = pFlyFormat->GetAnchor( ).GetContentAnchor( );
6399 if ( pAnchor )
6400 {
6401 bool bInHeader = pAnchor->nNode.GetNode( ).FindHeaderStartNode( ) != nullptr;
6402 bool bInFooter = pAnchor->nNode.GetNode( ).FindFooterStartNode( ) != nullptr;
6403
6404 bRet = bInHeader || bInFooter;
6405 if ( bInHeader )
6406 rControl = FrameControlType::Header;
6407 else if ( bInFooter )
6408 rControl = FrameControlType::Footer;
6409 }
6410 else
6411 bPageAnchored = pFlyFormat->GetAnchor( ).GetAnchorId( ) == RndStdIds::FLY_AT_PAGE;
6412 }
6413 }
6414 else
6415 bOverFly = false;
6416 return bRet;
6417}
6418
6419void SwEditWin::SetUseInputLanguage( bool bNew )
6420{
6421 if ( bNew || m_bUseInputLanguage )
6422 {
6423 SfxBindings& rBind = GetView().GetViewFrame()->GetBindings();
6424 rBind.Invalidate( SID_ATTR_CHAR_FONT( 10000 + 7 ) );
6425 rBind.Invalidate( SID_ATTR_CHAR_FONTHEIGHT( 10000 + 15 ) );
6426 }
6427 m_bUseInputLanguage = bNew;
6428}
6429
6430OUString SwEditWin::GetSurroundingText() const
6431{
6432 OUString sReturn;
6433 SwWrtShell& rSh = m_rView.GetWrtShell();
6434 if( rSh.HasSelection() && !rSh.IsMultiSelection() && rSh.IsSelOnePara() )
6435 rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR );
6436 else if( !rSh.HasSelection() )
6437 {
6438 SwPosition *pPos = rSh.GetCursor()->GetPoint();
6439 const sal_Int32 nPos = pPos->nContent.GetIndex();
6440
6441 // get the sentence around the cursor
6442 rSh.HideCursor();
6443 rSh.GoStartSentence();
6444 rSh.SetMark();
6445 rSh.GoEndSentence();
6446 rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR );
6447
6448 pPos->nContent = nPos;
6449 rSh.ClearMark();
6450 rSh.HideCursor();
6451 }
6452
6453 return sReturn;
6454}
6455
6456Selection SwEditWin::GetSurroundingTextSelection() const
6457{
6458 SwWrtShell& rSh = m_rView.GetWrtShell();
6459 if( rSh.HasSelection() )
6460 {
6461 OUString sReturn;
6462 rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR );
6463 return Selection( 0, sReturn.getLength() );
6464 }
6465 else
6466 {
6467 // Return the position of the visible cursor in the sentence
6468 // around the visible cursor.
6469 SwPosition *pPos = rSh.GetCursor()->GetPoint();
6470 const sal_Int32 nPos = pPos->nContent.GetIndex();
6471
6472 rSh.HideCursor();
6473 rSh.GoStartSentence();
6474 const sal_Int32 nStartPos = rSh.GetCursor()->GetPoint()->nContent.GetIndex();
6475
6476 pPos->nContent = nPos;
6477 rSh.ClearMark();
6478 rSh.ShowCursor();
6479
6480 return Selection( nPos - nStartPos, nPos - nStartPos );
6481 }
6482}
6483
6484void SwEditWin::LogicInvalidate(const tools::Rectangle* pRectangle)
6485{
6486 OString sRectangle;
6487 if (!pRectangle)
6488 sRectangle = "EMPTY";
6489 else
6490 sRectangle = pRectangle->toString();
6491
6492 SfxLokHelper::notifyInvalidation(&m_rView, sRectangle);
6493}
6494
6495void SwEditWin::LogicMouseButtonDown(const MouseEvent& rMouseEvent)
6496{
6497 // When we're not doing tiled rendering, then positions must be passed as pixels.
6498 assert(comphelper::LibreOfficeKit::isActive())(static_cast <bool> (comphelper::LibreOfficeKit::isActive
()) ? void (0) : __assert_fail ("comphelper::LibreOfficeKit::isActive()"
, "/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
, 6498, __extension__ __PRETTY_FUNCTION__))
;
6499
6500 Point aPoint = GetPointerPosPixel();
6501 SetLastMousePos(rMouseEvent.GetPosPixel());
6502
6503 MouseButtonDown(rMouseEvent);
6504
6505 SetPointerPosPixel(aPoint);
6506}
6507
6508void SwEditWin::LogicMouseButtonUp(const MouseEvent& rMouseEvent)
6509{
6510 // When we're not doing tiled rendering, then positions must be passed as pixels.
6511 assert(comphelper::LibreOfficeKit::isActive())(static_cast <bool> (comphelper::LibreOfficeKit::isActive
()) ? void (0) : __assert_fail ("comphelper::LibreOfficeKit::isActive()"
, "/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
, 6511, __extension__ __PRETTY_FUNCTION__))
;
6512
6513 Point aPoint = GetPointerPosPixel();
6514 SetLastMousePos(rMouseEvent.GetPosPixel());
6515
6516 MouseButtonUp(rMouseEvent);
6517
6518 SetPointerPosPixel(aPoint);
6519}
6520
6521void SwEditWin::LogicMouseMove(const MouseEvent& rMouseEvent)
6522{
6523 // When we're not doing tiled rendering, then positions must be passed as pixels.
6524 assert(comphelper::LibreOfficeKit::isActive())(static_cast <bool> (comphelper::LibreOfficeKit::isActive
()) ? void (0) : __assert_fail ("comphelper::LibreOfficeKit::isActive()"
, "/home/maarten/src/libreoffice/core/sw/source/uibase/docvw/edtwin.cxx"
, 6524, __extension__ __PRETTY_FUNCTION__))
;
6525
6526 Point aPoint = GetPointerPosPixel();
6527 SetLastMousePos(rMouseEvent.GetPosPixel());
6528
6529 MouseMove(rMouseEvent);
6530
6531 SetPointerPosPixel(aPoint);
6532}
6533
6534void SwEditWin::SetCursorTwipPosition(const Point& rPosition, bool bPoint, bool bClearMark)
6535{
6536 if (SdrView* pSdrView = m_rView.GetWrtShell().GetDrawView())
6537 {
6538 // Editing shape text, then route the call to editeng.
6539 if (pSdrView->GetTextEditObject())
6540 {
6541 EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView();
6542 rEditView.SetCursorLogicPosition(rPosition, bPoint, bClearMark);
6543 return;
6544 }
6545 }
6546
6547 if (m_rView.GetPostItMgr())
6548 {
6549 if (sw::annotation::SwAnnotationWin* pWin = m_rView.GetPostItMgr()->GetActiveSidebarWin())
6550 {
6551 // Editing postit text.
6552 pWin->SetCursorLogicPosition(rPosition, bPoint, bClearMark);
6553 return;
6554 }
6555 }
6556
6557 // Not an SwWrtShell, as that would make SwCursorShell::GetCursor() inaccessible.
6558 SwEditShell& rShell = m_rView.GetWrtShell();
6559
6560 bool bCreateSelection = false;
6561 {
6562 SwMvContext aMvContext(&rShell);
6563 if (bClearMark)
6564 rShell.ClearMark();
6565 else
6566 bCreateSelection = !rShell.HasMark();
6567
6568 if (bCreateSelection)
6569 m_rView.GetWrtShell().SttSelect();
6570
6571 // If the mark is to be updated, then exchange the point and mark before
6572 // and after, as we can't easily set the mark.
6573 if (!bPoint)
6574 rShell.getShellCursor(/*bBlock=*/false)->Exchange();
6575 rShell.SetCursor(rPosition);
6576 if (!bPoint)
6577 rShell.getShellCursor(/*bBlock=*/false)->Exchange();
6578 }
6579
6580 if (bCreateSelection)
6581 m_rView.GetWrtShell().EndSelect();
6582}
6583
6584void SwEditWin::SetGraphicTwipPosition(bool bStart, const Point& rPosition)
6585{
6586 if (bStart)
6587 {
6588 MouseEvent aClickEvent(rPosition, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT(sal_uInt16(0x0001)));
6589 MouseButtonDown(aClickEvent);
6590 MouseEvent aMoveEvent(Point(rPosition.getX() + MIN_MOVE4 + 1, rPosition.getY()), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT(sal_uInt16(0x0001)));
6591 MouseMove(aMoveEvent);
6592 }
6593 else
6594 {
6595 MouseEvent aMoveEvent(Point(rPosition.getX() - MIN_MOVE4 - 1, rPosition.getY()), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT(sal_uInt16(0x0001)));
6596 MouseMove(aMoveEvent);
6597 MouseEvent aClickEvent(rPosition, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT(sal_uInt16(0x0001)));
6598 MouseButtonUp(aClickEvent);
6599 }
6600}
6601
6602void SwEditWin::SetOutlineContentVisibilityButtons()
6603{
6604 SwWrtShell& rSh = m_rView.GetWrtShell();
6605 const SwOutlineNodes& rOutlineNodes = rSh.GetDoc()->GetNodes().GetOutLineNds();
6606 if (!rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
6607 {
6608 for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNodes.size(); ++nPos)
6609 {
6610 bool bOutlineContentVisibleAttr = true;
6611 rOutlineNodes[nPos]->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
6612 if (!bOutlineContentVisibleAttr)
6613 {
6614 // unfold and then set outline content visible attr to false for persistence
6615 rSh.ToggleOutlineContentVisibility(nPos);
6616 rOutlineNodes[nPos]->GetTextNode()->SetAttrOutlineContentVisible(false);
6617 }
6618 }
6619 GetFrameControlsManager().HideControls(FrameControlType::Outline);
6620 }
6621 else
6622 {
6623 for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNodes.size(); ++nPos)
6624 {
6625 bool bOutlineContentVisibleAttr = true;
6626 rOutlineNodes[nPos]->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
6627 if (!bOutlineContentVisibleAttr)
6628 rSh.ToggleOutlineContentVisibility(nPos, true);
6629 }
6630 }
6631 GetView().Invalidate(); // set state of dependent slots (FN_TOGGLE_OUTLINE_CONTENT_VISIBILITY)
6632}
6633
6634SwFrameControlsManager& SwEditWin::GetFrameControlsManager()
6635{
6636 return *m_pFrameControlsManager;
6637}
6638
6639/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.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_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
25
Calling copy constructor for 'Reference<Menu>'
28
Returning from copy constructor for 'Reference<Menu>'
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
29
Calling 'Reference::clear'
36
Returning; memory was released
205 if (aTmp.get()) {
37
Calling 'Reference::get'
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
24
Calling 'VclPtr::disposeAndClear'
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.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_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
26
Assuming field 'm_pBody' is non-null
27
Taking true branch
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
113 m_pBody->release();
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody
29.1
Field 'm_pBody' is non-null
29.1
Field 'm_pBody' is non-null
29.1
Field 'm_pBody' is non-null
29.1
Field 'm_pBody' is non-null
)
30
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
31
Calling 'VclReferenceBase::release'
35
Returning; memory was released
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
38
Use of memory after it is freed
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.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_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
32
Assuming the condition is true
33
Taking true branch
40 delete this;
34
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif