Coverage Report

Created: 2025-07-07 10:01

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