Coverage Report

Created: 2026-06-30 11:14

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