Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/dialog/weldeditview.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 <basegfx/matrix/b2dhommatrix.hxx>
23
#include <com/sun/star/accessibility/AccessibleRole.hpp>
24
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
25
#include <com/sun/star/accessibility/XAccessible.hpp>
26
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
27
#include <comphelper/OAccessible.hxx>
28
#include <cppuhelper/supportsservice.hxx>
29
#include <drawinglayer/processor2d/baseprocessor2d.hxx>
30
#include <drawinglayer/processor2d/processor2dtools.hxx>
31
#include <comphelper/lok.hxx>
32
#include <editeng/eeitem.hxx>
33
#include <editeng/fhgtitem.hxx>
34
#include <editeng/fontitem.hxx>
35
#include <editeng/outliner.hxx>
36
#include <editeng/unoedhlp.hxx>
37
#include <editeng/unoedsrc.hxx>
38
#include <i18nlangtag/languagetag.hxx>
39
#include <osl/diagnose.h>
40
#include <svl/itempool.hxx>
41
#include <svl/itemset.hxx>
42
#include <sal/log.hxx>
43
#include <svx/sdr/overlay/overlayselection.hxx>
44
#include <svtools/optionsdrawinglayer.hxx>
45
#include <svx/AccessibleTextHelper.hxx>
46
#include <svx/weldeditview.hxx>
47
#include <comphelper/diagnose_ex.hxx>
48
#include <vcl/canvastools.hxx>
49
#include <vcl/cursor.hxx>
50
#include <vcl/event.hxx>
51
#include <vcl/ptrstyle.hxx>
52
#include <vcl/settings.hxx>
53
#include <vcl/svapp.hxx>
54
#include <vcl/window.hxx>
55
#include <vcl/uitest/uiobject.hxx>
56
57
0
void WeldEditView::SetText(const OUString& rStr) { GetEditEngine()->SetText(rStr); }
58
59
0
OUString WeldEditView::GetText() const { return GetEditEngine()->GetText(); }
60
61
void WeldEditView::SetModifyHdl(const Link<LinkParamNone*, void>& rLink)
62
0
{
63
0
    GetEditEngine()->SetModifyHdl(rLink);
64
0
}
65
66
0
EditView* WeldEditView::GetEditView() const { return m_xEditView.get(); }
67
68
0
EditEngine* WeldEditView::GetEditEngine() const { return m_xEditEngine.get(); }
69
70
bool WeldEditView::HasSelection() const
71
0
{
72
0
    EditView* pEditView = GetEditView();
73
0
    return pEditView && pEditView->HasSelection();
74
0
}
75
76
void WeldEditView::Delete()
77
0
{
78
0
    if (EditView* pEditView = GetEditView())
79
0
        pEditView->DeleteSelected();
80
0
}
81
82
void WeldEditView::Cut()
83
0
{
84
0
    if (EditView* pEditView = GetEditView())
85
0
        pEditView->Cut();
86
0
}
87
88
void WeldEditView::Copy()
89
0
{
90
0
    if (EditView* pEditView = GetEditView())
91
0
        pEditView->Copy();
92
0
}
93
94
void WeldEditView::Paste()
95
0
{
96
0
    if (EditView* pEditView = GetEditView())
97
0
        pEditView->Paste();
98
0
}
99
100
WeldEditView::WeldEditView()
101
0
    : m_bAcceptsTab(false)
102
0
    , m_aCursorTimer("WeldEditView CursorTimer")
103
0
    , m_bCursorVisible(false)
104
0
{
105
0
    m_aCursorTimer.SetInvokeHandler(LINK(this, WeldEditView, BlinkTimerHdl));
106
0
}
107
108
IMPL_LINK_NOARG(WeldEditView, BlinkTimerHdl, Timer*, void)
109
0
{
110
0
    m_bCursorVisible = !m_bCursorVisible;
111
0
    if (!m_aCachedCursorPixRect.IsEmpty())
112
0
    {
113
0
        OutputDevice& rDevice = EditViewOutputDevice();
114
0
        Invalidate(rDevice.PixelToLogic(m_aCachedCursorPixRect), weld::InvalidateFlags::Cursor);
115
0
    }
116
0
    else
117
0
        Invalidate();
118
0
}
119
120
// tdf#127033 want to use UI font so override makeEditEngine to enable that
121
void WeldEditView::makeEditEngine()
122
0
{
123
0
    rtl::Reference<SfxItemPool> pItemPool = EditEngine::CreatePool();
124
125
0
    vcl::Font aAppFont(Application::GetSettings().GetStyleSettings().GetAppFont());
126
127
0
    pItemPool->SetUserDefaultItem(SvxFontItem(aAppFont.GetFamilyTypeMaybeAskConfig(),
128
0
                                              aAppFont.GetFamilyName(), u""_ustr, PITCH_DONTKNOW,
129
0
                                              RTL_TEXTENCODING_DONTKNOW, EE_CHAR_FONTINFO));
130
0
    pItemPool->SetUserDefaultItem(SvxFontItem(aAppFont.GetFamilyTypeMaybeAskConfig(),
131
0
                                              aAppFont.GetFamilyName(), u""_ustr, PITCH_DONTKNOW,
132
0
                                              RTL_TEXTENCODING_DONTKNOW, EE_CHAR_FONTINFO_CJK));
133
0
    pItemPool->SetUserDefaultItem(SvxFontItem(aAppFont.GetFamilyTypeMaybeAskConfig(),
134
0
                                              aAppFont.GetFamilyName(), u""_ustr, PITCH_DONTKNOW,
135
0
                                              RTL_TEXTENCODING_DONTKNOW, EE_CHAR_FONTINFO_CTL));
136
137
0
    pItemPool->SetUserDefaultItem(
138
0
        SvxFontHeightItem(aAppFont.GetFontHeight() * 20, 100, EE_CHAR_FONTHEIGHT));
139
0
    pItemPool->SetUserDefaultItem(
140
0
        SvxFontHeightItem(aAppFont.GetFontHeight() * 20, 100, EE_CHAR_FONTHEIGHT_CJK));
141
0
    pItemPool->SetUserDefaultItem(
142
0
        SvxFontHeightItem(aAppFont.GetFontHeight() * 20, 100, EE_CHAR_FONTHEIGHT_CTL));
143
144
0
    m_xEditEngine.reset(new EditEngine(pItemPool.get()));
145
0
}
146
147
void WeldEditView::Resize()
148
0
{
149
0
    if (EditView* pEditView = GetEditView())
150
0
    {
151
0
        OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
152
0
        Size aOutputSize(rDevice.PixelToLogic(GetOutputSizePixel()));
153
        // Resizes the edit engine to adjust to the size of the output area
154
0
        pEditView->SetOutputArea(tools::Rectangle(Point(0, 0), aOutputSize));
155
0
        GetEditEngine()->SetPaperSize(aOutputSize);
156
0
        pEditView->ShowCursor();
157
158
0
        const tools::Long nMaxVisAreaStart
159
0
            = pEditView->getEditEngine().GetTextHeight() - aOutputSize.Height();
160
0
        tools::Rectangle aVisArea(pEditView->GetVisArea());
161
0
        if (aVisArea.Top() > nMaxVisAreaStart)
162
0
        {
163
0
            aVisArea.SetTop(std::max<tools::Long>(nMaxVisAreaStart, 0));
164
0
            aVisArea.SetSize(aOutputSize);
165
0
            pEditView->SetVisArea(aVisArea);
166
0
            pEditView->ShowCursor();
167
0
        }
168
169
0
        EditViewScrollStateChange();
170
0
    }
171
0
    weld::CustomWidgetController::Resize();
172
0
}
173
174
void WeldEditView::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
175
0
{
176
0
    DoPaint(rRenderContext, rRect);
177
0
}
178
179
void WeldEditView::PaintSelection(vcl::RenderContext& rRenderContext, tools::Rectangle const& rRect,
180
                                  std::vector<tools::Rectangle> const& rLogicRects,
181
                                  Color const color)
182
0
{
183
0
    if (rLogicRects.empty())
184
0
    {
185
0
        return;
186
0
    }
187
188
0
    std::vector<basegfx::B2DRange> aLogicRanges;
189
0
    aLogicRanges.reserve(rLogicRects.size());
190
191
0
    tools::Long nMinX(LONG_MAX), nMaxX(0), nMinY(LONG_MAX), nMaxY(0);
192
0
    for (const auto& aRect : rLogicRects)
193
0
    {
194
0
        nMinX = std::min(nMinX, aRect.Left());
195
0
        nMinY = std::min(nMinY, aRect.Top());
196
0
        nMaxX = std::max(nMaxX, aRect.Right());
197
0
        nMaxY = std::max(nMaxY, aRect.Bottom());
198
0
    }
199
200
0
    const Size aLogicPixel(rRenderContext.PixelToLogic(Size(1, 1)));
201
0
    for (const auto& aRect : rLogicRects)
202
0
    {
203
        // Extend each range by one pixel so multiple lines touch each
204
        // other if adjacent, so the whole set is drawn with a single
205
        // border around the lot. But keep the selection within the
206
        // original max extents.
207
0
        auto nTop = aRect.Top();
208
0
        if (nTop > nMinY)
209
0
            nTop -= aLogicPixel.Height();
210
0
        auto nBottom = aRect.Bottom();
211
0
        if (nBottom < nMaxY)
212
0
            nBottom += aLogicPixel.Height();
213
0
        auto nLeft = aRect.Left();
214
0
        if (nLeft > nMinX)
215
0
            nLeft -= aLogicPixel.Width();
216
0
        auto nRight = aRect.Right();
217
0
        if (nRight < nMaxX)
218
0
            nRight += aLogicPixel.Width();
219
220
0
        aLogicRanges.emplace_back(nLeft, nTop, nRight, nBottom);
221
0
    }
222
223
0
    sdr::overlay::OverlaySelection aCursorOverlay(sdr::overlay::OverlayType::Transparent, color,
224
0
                                                  std::move(aLogicRanges), true);
225
226
0
    drawinglayer::geometry::ViewInformation2D aViewInformation2D;
227
0
    aViewInformation2D.setViewTransformation(rRenderContext.GetViewTransformation());
228
0
    aViewInformation2D.setViewport(vcl::unotools::b2DRectangleFromRectangle(rRect));
229
230
0
    std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> xProcessor(
231
0
        drawinglayer::processor2d::createProcessor2DFromOutputDevice(rRenderContext,
232
0
                                                                     aViewInformation2D));
233
234
0
    xProcessor->process(aCursorOverlay.getOverlayObjectPrimitive2DSequence());
235
0
}
236
237
void WeldEditView::DoPaint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
238
0
{
239
0
    EditView* const pEditView{ GetEditView() };
240
241
0
    if (pEditView == nullptr)
242
0
    {
243
0
        return;
244
0
    }
245
246
    // Fast path: blink-only repaint with valid cache
247
0
    weld::InvalidateFlags ePending = GetInvalidateFlags();
248
0
    if (ePending == weld::InvalidateFlags::Cursor && !m_aCachedCursorPixRect.IsEmpty())
249
0
    {
250
0
        VirtualDevice& rSrc = m_bCursorVisible ? *m_xCursorOnDev : *m_xCursorOffDev;
251
        // Blit cached bitmap in pixel coordinates to avoid rounding issues
252
0
        bool bMapMode = rRenderContext.IsMapModeEnabled();
253
0
        rRenderContext.EnableMapMode(false);
254
0
        rRenderContext.DrawOutDev(m_aCachedCursorPixRect.TopLeft(),
255
0
                                  m_aCachedCursorPixRect.GetSize(), Point(0, 0),
256
0
                                  m_aCachedCursorPixRect.GetSize(), rSrc);
257
0
        rRenderContext.EnableMapMode(bMapMode);
258
0
        return;
259
0
    }
260
261
0
    auto popIt = rRenderContext.ScopedPush(vcl::PushFlags::ALL);
262
0
    rRenderContext.SetClipRegion();
263
264
0
    pEditView->DrawText_ToEditView(
265
0
        comphelper::LibreOfficeKit::isActive() ? rRenderContext.PixelToLogic(rRect) : rRect,
266
0
        &rRenderContext);
267
268
0
    if (HasFocus())
269
0
    {
270
0
        pEditView->ShowCursor(false);
271
0
        vcl::Cursor* pCursor = pEditView->GetCursor();
272
273
        // Get the pixel bounding rect the cursor will occupy
274
0
        tools::Rectangle aPixRect = pCursor->GetBoundRect(rRenderContext);
275
0
        if (!aPixRect.IsEmpty())
276
0
        {
277
0
            m_aCachedCursorPixRect = aPixRect;
278
0
            Size aPixSize = aPixRect.GetSize();
279
280
            // Cache in pixel coordinates to avoid rounding issues
281
0
            bool bMapMode = rRenderContext.IsMapModeEnabled();
282
0
            rRenderContext.EnableMapMode(false);
283
284
            // Cache "cursor off" — text without cursor (before drawing cursor)
285
0
            m_xCursorOffDev->SetOutputSizePixel(aPixSize);
286
0
            m_xCursorOffDev->SetMapMode(MapMode(MapUnit::MapPixel));
287
0
            m_xCursorOffDev->DrawOutDev(Point(0, 0), aPixSize, aPixRect.TopLeft(), aPixSize,
288
0
                                        rRenderContext);
289
290
            // Draw cursor, then cache "cursor on"
291
0
            rRenderContext.EnableMapMode(bMapMode);
292
0
            pCursor->DrawToDevice(rRenderContext);
293
0
            rRenderContext.EnableMapMode(false);
294
295
0
            m_xCursorOnDev->SetOutputSizePixel(aPixSize);
296
0
            m_xCursorOnDev->SetMapMode(MapMode(MapUnit::MapPixel));
297
0
            m_xCursorOnDev->DrawOutDev(Point(0, 0), aPixSize, aPixRect.TopLeft(), aPixSize,
298
0
                                       rRenderContext);
299
300
0
            rRenderContext.EnableMapMode(bMapMode);
301
302
            // If cursor should be hidden, restore to clean state
303
0
            if (!m_bCursorVisible)
304
0
            {
305
0
                rRenderContext.EnableMapMode(false);
306
0
                rRenderContext.DrawOutDev(aPixRect.TopLeft(), aPixSize, Point(0, 0), aPixSize,
307
0
                                          *m_xCursorOffDev);
308
0
                rRenderContext.EnableMapMode(bMapMode);
309
0
            }
310
0
        }
311
0
    }
312
313
    // get logic selection
314
0
    std::vector<tools::Rectangle> aLogicRects;
315
0
    pEditView->GetSelectionRectangles(aLogicRects);
316
317
    // get the system's highlight color
318
0
    const Color aHighlight(SvtOptionsDrawinglayer::getHilightColor());
319
0
    PaintSelection(rRenderContext, rRect, aLogicRects, aHighlight);
320
0
}
321
322
bool WeldEditView::MouseMove(const MouseEvent& rMEvt)
323
0
{
324
0
    EditView* pEditView = GetEditView();
325
0
    return pEditView && pEditView->MouseMove(rMEvt);
326
0
}
327
328
bool WeldEditView::MouseButtonDown(const MouseEvent& rMEvt)
329
0
{
330
0
    if (!IsMouseCaptured())
331
0
        CaptureMouse();
332
333
0
    if (!HasFocus() && CanFocus())
334
0
        GrabFocus();
335
336
0
    EditView* pEditView = GetEditView();
337
0
    return pEditView && pEditView->MouseButtonDown(rMEvt);
338
0
}
339
340
bool WeldEditView::MouseButtonUp(const MouseEvent& rMEvt)
341
0
{
342
0
    if (IsMouseCaptured())
343
0
        ReleaseMouse();
344
0
    EditView* pEditView = GetEditView();
345
0
    return pEditView && pEditView->MouseButtonUp(rMEvt);
346
0
}
347
348
bool WeldEditView::KeyInput(const KeyEvent& rKEvt)
349
0
{
350
0
    EditView* pEditView = GetEditView();
351
352
0
    sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
353
354
0
    if (nKey == KEY_TAB && !GetAcceptsTab())
355
0
    {
356
0
        return false;
357
0
    }
358
0
    else if (pEditView && !pEditView->PostKeyEvent(rKEvt))
359
0
    {
360
0
        if (rKEvt.GetKeyCode().IsMod1() && !rKEvt.GetKeyCode().IsMod2())
361
0
        {
362
0
            if (nKey == KEY_A)
363
0
            {
364
0
                if (GetEditEngine()->GetParagraphCount())
365
0
                {
366
0
                    pEditView->SetSelection(ESelection::All());
367
0
                }
368
0
                return true;
369
0
            }
370
0
        }
371
372
0
        return false;
373
0
    }
374
375
0
    return true;
376
0
}
377
378
bool WeldEditView::Command(const CommandEvent& rCEvt)
379
0
{
380
0
    EditView* pEditView = GetEditView();
381
0
    if (!pEditView)
382
0
        return false;
383
0
    return pEditView->Command(rCEvt);
384
0
}
385
386
Point WeldEditView::EditViewPointerPosPixel() const
387
0
{
388
0
    return GetDrawingArea()->get_pointer_position();
389
0
}
390
391
class WeldEditAccessible;
392
393
namespace
394
{
395
class WeldViewForwarder : public SvxViewForwarder
396
{
397
    WeldEditAccessible& m_rEditAcc;
398
399
    WeldViewForwarder(const WeldViewForwarder&) = delete;
400
    WeldViewForwarder& operator=(const WeldViewForwarder&) = delete;
401
402
public:
403
    explicit WeldViewForwarder(WeldEditAccessible& rAcc)
404
0
        : m_rEditAcc(rAcc)
405
0
    {
406
0
    }
407
408
    virtual bool IsValid() const override;
409
    virtual Point LogicToPixel(const Point& rPoint, const MapMode& rMapMode) const override;
410
    virtual Point PixelToLogic(const Point& rPoint, const MapMode& rMapMode) const override;
411
};
412
}
413
414
class WeldEditAccessible;
415
416
namespace
417
{
418
class WeldEditSource;
419
420
/* analog to SvxEditEngineForwarder */
421
class WeldTextForwarder : public SvxTextForwarder
422
{
423
    WeldEditAccessible& m_rEditAcc;
424
    WeldEditSource& m_rEditSource;
425
426
    DECL_LINK(NotifyHdl, EENotify&, void);
427
428
    WeldTextForwarder(const WeldTextForwarder&) = delete;
429
    WeldTextForwarder& operator=(const WeldTextForwarder&) = delete;
430
431
public:
432
    WeldTextForwarder(WeldEditAccessible& rAcc, WeldEditSource& rSource);
433
    virtual ~WeldTextForwarder() override;
434
435
    virtual sal_Int32 GetParagraphCount() const override;
436
    virtual sal_Int32 GetTextLen(sal_Int32 nParagraph) const override;
437
    virtual OUString GetText(const ESelection& rSel) const override;
438
    virtual SfxItemSet GetAttribs(const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib
439
                                                          = EditEngineAttribs::All) const override;
440
    virtual SfxItemSet GetParaAttribs(sal_Int32 nPara) const override;
441
    virtual void SetParaAttribs(sal_Int32 nPara, const SfxItemSet& rSet) override;
442
    virtual void RemoveAttribs(const ESelection& rSelection) override;
443
    virtual void GetPortions(sal_Int32 nPara, std::vector<sal_Int32>& rList) const override;
444
445
    virtual OUString GetStyleSheet(sal_Int32 nPara) const override;
446
    virtual void SetStyleSheet(sal_Int32 nPara, const OUString& rStyleName) override;
447
448
    virtual SfxItemState GetItemState(const ESelection& rSel, sal_uInt16 nWhich) const override;
449
    virtual SfxItemState GetItemState(sal_Int32 nPara, sal_uInt16 nWhich) const override;
450
451
    virtual void QuickInsertText(const OUString& rText, const ESelection& rSel) override;
452
    virtual void QuickInsertField(const SvxFieldItem& rFld, const ESelection& rSel) override;
453
    virtual void QuickSetAttribs(const SfxItemSet& rSet, const ESelection& rSel) override;
454
    virtual void QuickInsertLineBreak(const ESelection& rSel) override;
455
456
    virtual SfxItemPool* GetPool() const override;
457
458
    virtual OUString CalcFieldValue(const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos,
459
                                    std::optional<Color>& rpTxtColor,
460
                                    std::optional<Color>& rpFldColor,
461
                                    std::optional<FontLineStyle>& rpFldLineStyle) override;
462
    virtual void FieldClicked(const SvxFieldItem&) override;
463
    virtual bool IsValid() const override;
464
465
    virtual LanguageType GetLanguage(sal_Int32, sal_Int32) const override;
466
    virtual std::vector<EFieldInfo> GetFieldInfo(sal_Int32 nPara) const override;
467
    virtual EBulletInfo GetBulletInfo(sal_Int32 nPara) const override;
468
    virtual tools::Rectangle GetCharBounds(sal_Int32 nPara, sal_Int32 nIndex) const override;
469
    virtual tools::Rectangle GetParaBounds(sal_Int32 nPara) const override;
470
    virtual MapMode GetMapMode() const override;
471
    virtual OutputDevice* GetRefDevice() const override;
472
    virtual bool GetIndexAtPoint(const Point&, sal_Int32& nPara, sal_Int32& nIndex) const override;
473
    virtual bool GetWordIndices(sal_Int32 nPara, sal_Int32 nIndex, sal_Int32& nStart,
474
                                sal_Int32& nEnd) const override;
475
    virtual bool GetAttributeRun(sal_Int32& nStartIndex, sal_Int32& nEndIndex, sal_Int32 nPara,
476
                                 sal_Int32 nIndex, bool bInCell = false) const override;
477
    virtual sal_Int32 GetLineCount(sal_Int32 nPara) const override;
478
    virtual sal_Int32 GetLineLen(sal_Int32 nPara, sal_Int32 nLine) const override;
479
    virtual void GetLineBoundaries(/*out*/ sal_Int32& rStart, /*out*/ sal_Int32& rEnd,
480
                                   sal_Int32 nParagraph, sal_Int32 nLine) const override;
481
    virtual sal_Int32 GetLineNumberAtIndex(sal_Int32 nPara, sal_Int32 nLine) const override;
482
    virtual bool Delete(const ESelection&) override;
483
    virtual bool InsertText(const OUString&, const ESelection&) override;
484
    virtual bool QuickFormatDoc(bool bFull = false) override;
485
486
0
    virtual bool SupportsOutlineDepth() const override { return false; };
487
    virtual sal_Int16 GetDepth(sal_Int32 nPara) const override;
488
    virtual bool SetDepth(sal_Int32 nPara, sal_Int16 nNewDepth) override;
489
490
    virtual const SfxItemSet* GetEmptyItemSetPtr() override;
491
    // implementation functions for XParagraphAppend and XTextPortionAppend
492
    virtual void AppendParagraph() override;
493
    virtual sal_Int32 AppendTextPortion(sal_Int32 nPara, const OUString& rText,
494
                                        const SfxItemSet& rSet) override;
495
496
    virtual void CopyText(const SvxTextForwarder& rSource) override;
497
};
498
499
/* analog to SvxEditEngineViewForwarder */
500
class WeldEditViewForwarder : public SvxEditViewForwarder
501
{
502
    WeldEditAccessible& m_rEditAcc;
503
504
    WeldEditViewForwarder(const WeldEditViewForwarder&) = delete;
505
    WeldEditViewForwarder& operator=(const WeldEditViewForwarder&) = delete;
506
507
public:
508
    explicit WeldEditViewForwarder(WeldEditAccessible& rAcc);
509
510
    virtual bool IsValid() const override;
511
512
    virtual Point LogicToPixel(const Point& rPoint, const MapMode& rMapMode) const override;
513
    virtual Point PixelToLogic(const Point& rPoint, const MapMode& rMapMode) const override;
514
515
    virtual bool GetSelection(ESelection& rSelection) const override;
516
    virtual bool SetSelection(const ESelection& rSelection) override;
517
    virtual bool Copy() override;
518
    virtual bool Cut() override;
519
    virtual bool Paste() override;
520
};
521
522
class WeldEditSource : public SvxEditSource
523
{
524
    SfxBroadcaster m_aBroadCaster;
525
    WeldViewForwarder m_aViewFwd;
526
    WeldTextForwarder m_aTextFwd;
527
    WeldEditViewForwarder m_aEditViewFwd;
528
    WeldEditAccessible& m_rEditAcc;
529
530
    WeldEditSource(const WeldEditSource& rSrc)
531
0
        : SvxEditSource()
532
0
        , m_aViewFwd(rSrc.m_rEditAcc)
533
0
        , m_aTextFwd(rSrc.m_rEditAcc, *this)
534
0
        , m_aEditViewFwd(rSrc.m_rEditAcc)
535
0
        , m_rEditAcc(rSrc.m_rEditAcc)
536
0
    {
537
0
    }
538
539
    WeldEditSource& operator=(const WeldEditSource&) = delete;
540
541
public:
542
    WeldEditSource(WeldEditAccessible& rAcc)
543
0
        : m_aViewFwd(rAcc)
544
0
        , m_aTextFwd(rAcc, *this)
545
0
        , m_aEditViewFwd(rAcc)
546
0
        , m_rEditAcc(rAcc)
547
0
    {
548
0
    }
549
550
    virtual std::unique_ptr<SvxEditSource> Clone() const override
551
0
    {
552
0
        return std::unique_ptr<SvxEditSource>(new WeldEditSource(*this));
553
0
    }
554
555
0
    virtual SvxTextForwarder* GetTextForwarder() override { return &m_aTextFwd; }
556
557
0
    virtual SvxViewForwarder* GetViewForwarder() override { return &m_aViewFwd; }
558
559
    virtual SvxEditViewForwarder* GetEditViewForwarder(bool /*bCreate*/) override
560
0
    {
561
0
        return &m_aEditViewFwd;
562
0
    }
563
564
    virtual void UpdateData() override
565
0
    {
566
        // would possibly only by needed if the XText interface is implemented
567
        // and its text needs to be updated.
568
0
    }
569
    virtual SfxBroadcaster& GetBroadcaster() const override
570
0
    {
571
0
        return const_cast<WeldEditSource*>(this)->m_aBroadCaster;
572
0
    }
573
};
574
}
575
576
class WeldEditAccessible : public comphelper::OAccessible
577
{
578
    weld::CustomWidgetController* m_pController;
579
    EditEngine* m_pEditEngine;
580
    EditView* m_pEditView;
581
    std::unique_ptr<::accessibility::AccessibleTextHelper> m_xTextHelper;
582
583
public:
584
    WeldEditAccessible(weld::CustomWidgetController* pController)
585
0
        : m_pController(pController)
586
0
        , m_pEditEngine(nullptr)
587
0
        , m_pEditView(nullptr)
588
0
    {
589
0
    }
590
591
0
    ::accessibility::AccessibleTextHelper* GetTextHelper() { return m_xTextHelper.get(); }
592
593
    void Init(EditEngine* pEditEngine, EditView* pEditView)
594
0
    {
595
0
        m_pEditEngine = pEditEngine;
596
0
        m_pEditView = pEditView;
597
0
        m_xTextHelper.reset(
598
0
            new ::accessibility::AccessibleTextHelper(std::make_unique<WeldEditSource>(*this)));
599
0
        m_xTextHelper->SetEventSource(this);
600
0
    }
601
602
0
    EditEngine* GetEditEngine() { return m_pEditEngine; }
603
0
    EditView* GetEditView() { return m_pEditView; }
604
605
    void SAL_CALL dispose() override
606
0
    {
607
0
        if (!isAlive())
608
0
            return;
609
610
        // remove handler before current object gets destroyed
611
        // (avoid handler being called for already dead object)
612
0
        m_pEditEngine->SetNotifyHdl(Link<EENotify&, void>());
613
614
0
        m_pEditEngine = nullptr;
615
0
        m_pEditView = nullptr;
616
0
        m_pController = nullptr; // implicitly results in AccessibleStateType::DEFUNC set
617
618
        //! make TextHelper implicitly release C++ references to some core objects
619
0
        m_xTextHelper->SetEditSource(::std::unique_ptr<SvxEditSource>());
620
621
        //! make TextHelper release references
622
        //! (e.g. the one set by the 'SetEventSource' call)
623
0
        m_xTextHelper->Dispose();
624
0
        m_xTextHelper.reset();
625
626
0
        OAccessible::dispose();
627
0
    }
628
629
    // XAccessibleComponent
630
631
    virtual css::uno::Reference<css::accessibility::XAccessible>
632
        SAL_CALL getAccessibleAtPoint(const css::awt::Point& rPoint) override
633
0
    {
634
0
        SolarMutexGuard aGuard;
635
0
        if (!m_xTextHelper)
636
0
            throw css::uno::RuntimeException();
637
638
0
        return m_xTextHelper->GetAt(rPoint);
639
0
    }
640
641
    virtual css::awt::Rectangle implGetBounds() override
642
0
    {
643
0
        if (!m_pController)
644
0
            throw css::uno::RuntimeException();
645
646
0
        const Point aOutPos;
647
0
        const Size aOutSize(m_pController->GetOutputSizePixel());
648
0
        css::awt::Rectangle aRet;
649
650
0
        aRet.X = aOutPos.X();
651
0
        aRet.Y = aOutPos.Y();
652
0
        aRet.Width = aOutSize.Width();
653
0
        aRet.Height = aOutSize.Height();
654
655
0
        return aRet;
656
0
    }
657
658
    virtual css::awt::Point SAL_CALL getLocationOnScreen() override
659
0
    {
660
0
        SolarMutexGuard aGuard;
661
0
        if (!m_pController)
662
0
            throw css::uno::RuntimeException();
663
664
0
        css::awt::Point aScreenLoc(0, 0);
665
666
0
        if (weld::DrawingArea* pDrawingArea = m_pController->GetDrawingArea())
667
0
        {
668
0
            AbsoluteScreenPixelPoint aPos = pDrawingArea->get_accessible_location_on_screen();
669
0
            aScreenLoc.X = aPos.X();
670
0
            aScreenLoc.Y = aPos.Y();
671
0
        }
672
673
0
        return aScreenLoc;
674
0
    }
675
676
0
    virtual void SAL_CALL grabFocus() override { m_pController->GrabFocus(); }
677
678
    virtual sal_Int32 SAL_CALL getForeground() override
679
0
    {
680
0
        SolarMutexGuard aGuard;
681
0
        if (!m_pController)
682
0
            throw css::uno::RuntimeException();
683
684
0
        Color nCol = m_pEditEngine->GetAutoColor();
685
0
        return static_cast<sal_Int32>(nCol);
686
0
    }
687
688
    virtual sal_Int32 SAL_CALL getBackground() override
689
0
    {
690
0
        SolarMutexGuard aGuard;
691
0
        if (!m_pController)
692
0
            throw css::uno::RuntimeException();
693
694
0
        Color nCol = m_pEditEngine->GetBackgroundColor();
695
0
        return static_cast<sal_Int32>(nCol);
696
0
    }
697
698
    // XAccessibleContext
699
    virtual sal_Int64 SAL_CALL getAccessibleChildCount() override
700
0
    {
701
0
        if (m_xTextHelper)
702
0
            return m_xTextHelper->GetChildCount();
703
0
        return 0;
704
0
    }
705
706
    virtual css::uno::Reference<css::accessibility::XAccessible>
707
        SAL_CALL getAccessibleChild(sal_Int64 i) override
708
0
    {
709
0
        if (m_xTextHelper)
710
0
            return m_xTextHelper->GetChild(i);
711
0
        throw css::lang::IndexOutOfBoundsException(); // there is no child...
712
0
    }
713
714
    virtual css::uno::Reference<css::accessibility::XAccessible>
715
        SAL_CALL getAccessibleParent() override
716
0
    {
717
0
        SolarMutexGuard aGuard;
718
0
        if (!m_pController)
719
0
            throw css::uno::RuntimeException();
720
721
0
        return m_pController->GetDrawingArea()->get_accessible_parent();
722
0
    }
723
724
    virtual sal_Int64 SAL_CALL getAccessibleIndexInParent() override
725
0
    {
726
0
        SolarMutexGuard aGuard;
727
0
        if (!m_pController)
728
0
            throw css::uno::RuntimeException();
729
730
        // -1 for child not found/no parent (according to specification)
731
0
        sal_Int64 nRet = -1;
732
733
0
        css::uno::Reference<css::accessibility::XAccessible> xParent(getAccessibleParent());
734
0
        if (!xParent)
735
0
            return nRet;
736
737
0
        try
738
0
        {
739
0
            css::uno::Reference<css::accessibility::XAccessibleContext> xParentContext(
740
0
                xParent->getAccessibleContext());
741
742
            //  iterate over parent's children and search for this object
743
0
            if (xParentContext.is())
744
0
            {
745
0
                sal_Int64 nChildCount = xParentContext->getAccessibleChildCount();
746
0
                for (sal_Int64 nChild = 0; (nChild < nChildCount) && (-1 == nRet); ++nChild)
747
0
                {
748
0
                    css::uno::Reference<css::accessibility::XAccessible> xChild(
749
0
                        xParentContext->getAccessibleChild(nChild));
750
0
                    if (xChild.get() == this)
751
0
                        nRet = nChild;
752
0
                }
753
0
            }
754
0
        }
755
0
        catch (const css::uno::Exception&)
756
0
        {
757
0
            TOOLS_WARN_EXCEPTION("svx", "WeldEditAccessible::getAccessibleIndexInParent");
758
0
        }
759
760
0
        return nRet;
761
0
    }
762
763
    virtual sal_Int16 SAL_CALL getAccessibleRole() override
764
0
    {
765
0
        return css::accessibility::AccessibleRole::TEXT_FRAME;
766
0
    }
767
768
    virtual OUString SAL_CALL getAccessibleDescription() override
769
0
    {
770
0
        SolarMutexGuard aGuard;
771
772
0
        OUString aRet;
773
774
0
        if (m_pController)
775
0
        {
776
0
            aRet = m_pController->GetAccessibleDescription();
777
0
        }
778
779
0
        return aRet;
780
0
    }
781
782
    virtual OUString SAL_CALL getAccessibleId() override
783
0
    {
784
0
        SolarMutexGuard aGuard;
785
786
0
        if (m_pController)
787
0
            return m_pController->GetAccessibleId();
788
789
0
        return OUString();
790
0
    }
791
792
    virtual OUString SAL_CALL getAccessibleName() override
793
0
    {
794
0
        SolarMutexGuard aGuard;
795
796
0
        OUString aRet;
797
798
0
        if (m_pController)
799
0
        {
800
0
            aRet = m_pController->GetAccessibleName();
801
0
        }
802
803
0
        return aRet;
804
0
    }
805
806
    virtual css::uno::Reference<css::accessibility::XAccessibleRelationSet>
807
        SAL_CALL getAccessibleRelationSet() override
808
0
    {
809
0
        SolarMutexGuard aGuard;
810
0
        if (!m_pController)
811
0
            throw css::uno::RuntimeException();
812
813
0
        return m_pController->GetDrawingArea()->get_accessible_relation_set();
814
0
    }
815
816
    virtual sal_Int64 SAL_CALL getAccessibleStateSet() override
817
0
    {
818
0
        SolarMutexGuard aGuard;
819
0
        sal_Int64 nStateSet = 0;
820
821
0
        if (!m_pController || !m_xTextHelper)
822
0
            nStateSet |= css::accessibility::AccessibleStateType::DEFUNC;
823
0
        else
824
0
        {
825
0
            nStateSet |= css::accessibility::AccessibleStateType::MULTI_LINE;
826
0
            nStateSet |= css::accessibility::AccessibleStateType::ENABLED;
827
0
            nStateSet |= css::accessibility::AccessibleStateType::EDITABLE;
828
0
            nStateSet |= css::accessibility::AccessibleStateType::FOCUSABLE;
829
0
            nStateSet |= css::accessibility::AccessibleStateType::SELECTABLE;
830
0
            if (m_pController->HasFocus())
831
0
                nStateSet |= css::accessibility::AccessibleStateType::FOCUSED;
832
0
            if (m_pController->IsVisible())
833
0
                nStateSet |= css::accessibility::AccessibleStateType::SHOWING;
834
0
            if (m_pController->IsReallyVisible())
835
0
                nStateSet |= css::accessibility::AccessibleStateType::VISIBLE;
836
0
            if (COL_TRANSPARENT != m_pEditEngine->GetBackgroundColor())
837
0
                nStateSet |= css::accessibility::AccessibleStateType::OPAQUE;
838
0
        }
839
840
0
        return nStateSet;
841
0
    }
842
843
    virtual css::lang::Locale SAL_CALL getLocale() override
844
0
    {
845
0
        SolarMutexGuard aGuard;
846
0
        return LanguageTag(m_pEditEngine->GetDefaultLanguage()).getLocale();
847
0
    }
848
849
    // XAccessibleEventBroadcaster
850
    virtual void SAL_CALL addAccessibleEventListener(
851
        const css::uno::Reference<css::accessibility::XAccessibleEventListener>& rListener) override
852
0
    {
853
0
        if (!m_xTextHelper) // not disposing (about to destroy view shell)
854
0
            return;
855
0
        m_xTextHelper->AddEventListener(rListener);
856
0
    }
857
858
    virtual void SAL_CALL removeAccessibleEventListener(
859
        const css::uno::Reference<css::accessibility::XAccessibleEventListener>& rListener) override
860
0
    {
861
0
        if (!m_xTextHelper) // not disposing (about to destroy view shell)
862
0
            return;
863
0
        m_xTextHelper->RemoveEventListener(rListener);
864
0
    }
865
};
866
867
rtl::Reference<comphelper::OAccessible> WeldEditView::CreateAccessible()
868
0
{
869
0
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
870
0
    if (!m_xAccessible.is())
871
0
        m_xAccessible.set(new WeldEditAccessible(this));
872
0
#endif
873
0
    return m_xAccessible;
874
0
}
875
876
WeldEditView::~WeldEditView()
877
0
{
878
0
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
879
0
    if (m_xAccessible.is())
880
0
    {
881
0
        m_xAccessible->dispose();
882
0
        m_xAccessible.clear();
883
0
    }
884
0
#endif
885
0
}
886
887
0
bool WeldViewForwarder::IsValid() const { return m_rEditAcc.GetEditView() != nullptr; }
888
889
Point WeldViewForwarder::LogicToPixel(const Point& rPoint, const MapMode& rMapMode) const
890
0
{
891
0
    EditView* pEditView = m_rEditAcc.GetEditView();
892
0
    if (!pEditView)
893
0
        return Point();
894
0
    OutputDevice& rOutDev = pEditView->GetOutputDevice();
895
0
    MapMode aMapMode(rOutDev.GetMapMode());
896
0
    Point aPoint(OutputDevice::LogicToLogic(rPoint, rMapMode, MapMode(aMapMode.GetMapUnit())));
897
0
    aMapMode.SetOrigin(Point());
898
0
    return rOutDev.LogicToPixel(aPoint, aMapMode);
899
0
}
900
901
Point WeldViewForwarder::PixelToLogic(const Point& rPoint, const MapMode& rMapMode) const
902
0
{
903
0
    EditView* pEditView = m_rEditAcc.GetEditView();
904
0
    if (!pEditView)
905
0
        return Point();
906
0
    OutputDevice& rOutDev = pEditView->GetOutputDevice();
907
0
    MapMode aMapMode(rOutDev.GetMapMode());
908
0
    aMapMode.SetOrigin(Point());
909
0
    Point aPoint(rOutDev.PixelToLogic(rPoint, aMapMode));
910
0
    return OutputDevice::LogicToLogic(aPoint, MapMode(aMapMode.GetMapUnit()), rMapMode);
911
0
}
912
913
WeldTextForwarder::WeldTextForwarder(WeldEditAccessible& rAcc, WeldEditSource& rSource)
914
0
    : m_rEditAcc(rAcc)
915
0
    , m_rEditSource(rSource)
916
0
{
917
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
918
0
    if (pEditEngine)
919
0
        pEditEngine->SetNotifyHdl(LINK(this, WeldTextForwarder, NotifyHdl));
920
0
}
921
922
WeldTextForwarder::~WeldTextForwarder()
923
0
{
924
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
925
0
    if (pEditEngine)
926
0
        pEditEngine->SetNotifyHdl(Link<EENotify&, void>());
927
0
}
928
929
IMPL_LINK(WeldTextForwarder, NotifyHdl, EENotify&, rNotify, void)
930
0
{
931
0
    if (EditEngine* pEditEngine = m_rEditAcc.GetEditEngine())
932
0
    {
933
0
        if (rNotify.eNotificationType == EE_NOTIFY_PROCESSNOTIFICATIONS
934
0
            && !pEditEngine->IsUpdateLayout())
935
0
        {
936
            // tdf#143088 an UpdateMode of false will just to on to cause
937
            // AccessibleTextHelper_Impl::GetTextForwarder to throw an
938
            // exception as a Frozen EditEngine is considered Invalid so return
939
            // early instead
940
0
            return;
941
0
        }
942
0
    }
943
944
0
    ::std::unique_ptr<SfxHint> aHint = SvxEditSourceHelper::EENotification2Hint(&rNotify);
945
0
    if (aHint)
946
0
        m_rEditSource.GetBroadcaster().Broadcast(*aHint);
947
0
}
948
949
sal_Int32 WeldTextForwarder::GetParagraphCount() const
950
0
{
951
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
952
0
    return pEditEngine ? pEditEngine->GetParagraphCount() : 0;
953
0
}
954
955
sal_Int32 WeldTextForwarder::GetTextLen(sal_Int32 nParagraph) const
956
0
{
957
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
958
0
    return pEditEngine ? pEditEngine->GetTextLen(nParagraph) : 0;
959
0
}
960
961
OUString WeldTextForwarder::GetText(const ESelection& rSel) const
962
0
{
963
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
964
0
    OUString aRet;
965
0
    if (pEditEngine)
966
0
        aRet = pEditEngine->GetText(rSel);
967
0
    return convertLineEnd(aRet, GetSystemLineEnd());
968
0
}
969
970
SfxItemSet WeldTextForwarder::GetAttribs(const ESelection& rSel,
971
                                         EditEngineAttribs nOnlyHardAttrib) const
972
0
{
973
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
974
0
    assert(pEditEngine && "EditEngine missing");
975
0
    if (rSel.start.nPara == rSel.end.nPara)
976
0
    {
977
0
        GetAttribsFlags nFlags = GetAttribsFlags::NONE;
978
0
        switch (nOnlyHardAttrib)
979
0
        {
980
0
            case EditEngineAttribs::All:
981
0
                nFlags = GetAttribsFlags::ALL;
982
0
                break;
983
0
            case EditEngineAttribs::OnlyHard:
984
0
                nFlags = GetAttribsFlags::CHARATTRIBS;
985
0
                break;
986
0
            default:
987
0
                SAL_WARN("svx", "unknown flags for WeldTextForwarder::GetAttribs");
988
0
        }
989
990
0
        return pEditEngine->GetAttribs(rSel.start.nPara, rSel.start.nIndex, rSel.end.nIndex,
991
0
                                       nFlags);
992
0
    }
993
0
    else
994
0
    {
995
0
        return pEditEngine->GetAttribs(rSel, nOnlyHardAttrib);
996
0
    }
997
0
}
998
999
SfxItemSet WeldTextForwarder::GetParaAttribs(sal_Int32 nPara) const
1000
0
{
1001
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1002
0
    assert(pEditEngine && "EditEngine missing");
1003
1004
0
    SfxItemSet aSet(pEditEngine->GetParaAttribs(nPara));
1005
1006
0
    sal_uInt16 nWhich = EE_PARA_START;
1007
0
    while (nWhich <= EE_PARA_END)
1008
0
    {
1009
0
        if (aSet.GetItemState(nWhich) != SfxItemState::SET)
1010
0
        {
1011
0
            if (pEditEngine->HasParaAttrib(nPara, nWhich))
1012
0
                aSet.Put(pEditEngine->GetParaAttrib(nPara, nWhich));
1013
0
        }
1014
0
        nWhich++;
1015
0
    }
1016
1017
0
    return aSet;
1018
0
}
1019
1020
void WeldTextForwarder::SetParaAttribs(sal_Int32 nPara, const SfxItemSet& rSet)
1021
0
{
1022
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1023
0
    if (pEditEngine)
1024
0
        pEditEngine->SetParaAttribs(nPara, rSet);
1025
0
}
1026
1027
SfxItemPool* WeldTextForwarder::GetPool() const
1028
0
{
1029
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1030
0
    return pEditEngine ? pEditEngine->GetEmptyItemSet().GetPool() : nullptr;
1031
0
}
1032
1033
void WeldTextForwarder::RemoveAttribs(const ESelection& rSelection)
1034
0
{
1035
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1036
0
    if (pEditEngine)
1037
0
        pEditEngine->RemoveAttribs(rSelection, false /*bRemoveParaAttribs*/, 0);
1038
0
}
1039
1040
void WeldTextForwarder::GetPortions(sal_Int32 nPara, std::vector<sal_Int32>& rList) const
1041
0
{
1042
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1043
0
    if (pEditEngine)
1044
0
        pEditEngine->GetPortions(nPara, rList);
1045
0
}
1046
1047
OUString WeldTextForwarder::GetStyleSheet(sal_Int32 nPara) const
1048
0
{
1049
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1050
0
    if (auto pStyle = pEditEngine ? pEditEngine->GetStyleSheet(nPara) : nullptr)
1051
0
        return pStyle->GetName();
1052
0
    return OUString();
1053
0
}
1054
1055
void WeldTextForwarder::SetStyleSheet(sal_Int32 nPara, const OUString& rStyleName)
1056
0
{
1057
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1058
0
    auto pStyleSheetPool = pEditEngine ? pEditEngine->GetStyleSheetPool() : nullptr;
1059
0
    if (auto pStyle
1060
0
        = pStyleSheetPool ? pStyleSheetPool->Find(rStyleName, SfxStyleFamily::Para) : nullptr)
1061
0
        pEditEngine->SetStyleSheet(nPara, static_cast<SfxStyleSheet*>(pStyle));
1062
0
}
1063
1064
void WeldTextForwarder::QuickInsertText(const OUString& rText, const ESelection& rSel)
1065
0
{
1066
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1067
0
    if (pEditEngine)
1068
0
        pEditEngine->QuickInsertText(rText, rSel);
1069
0
}
1070
1071
void WeldTextForwarder::QuickInsertLineBreak(const ESelection& rSel)
1072
0
{
1073
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1074
0
    if (pEditEngine)
1075
0
        pEditEngine->QuickInsertLineBreak(rSel);
1076
0
}
1077
1078
void WeldTextForwarder::QuickInsertField(const SvxFieldItem& rFld, const ESelection& rSel)
1079
0
{
1080
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1081
0
    if (pEditEngine)
1082
0
        pEditEngine->QuickInsertField(rFld, rSel);
1083
0
}
1084
1085
void WeldTextForwarder::QuickSetAttribs(const SfxItemSet& rSet, const ESelection& rSel)
1086
0
{
1087
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1088
0
    if (pEditEngine)
1089
0
        pEditEngine->QuickSetAttribs(rSet, rSel);
1090
0
}
1091
1092
bool WeldTextForwarder::IsValid() const
1093
0
{
1094
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1095
    // cannot reliably query EditEngine state
1096
    // while in the middle of an update
1097
0
    return pEditEngine && pEditEngine->IsUpdateLayout();
1098
0
}
1099
1100
OUString WeldTextForwarder::CalcFieldValue(const SvxFieldItem& rField, sal_Int32 nPara,
1101
                                           sal_Int32 nPos, std::optional<Color>& rpTxtColor,
1102
                                           std::optional<Color>& rpFldColor,
1103
                                           std::optional<FontLineStyle>& rpFldLineStyle)
1104
0
{
1105
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1106
0
    return pEditEngine ? pEditEngine->CalcFieldValue(rField, nPara, nPos, rpTxtColor, rpFldColor,
1107
0
                                                     rpFldLineStyle)
1108
0
                       : OUString();
1109
0
}
1110
1111
0
void WeldTextForwarder::FieldClicked(const SvxFieldItem&) {}
1112
1113
static SfxItemState GetSvxEditEngineItemState(EditEngine const& rEditEngine, const ESelection& rSel,
1114
                                              sal_uInt16 nWhich)
1115
0
{
1116
0
    std::vector<EECharAttrib> aAttribs;
1117
1118
0
    const SfxPoolItem* pLastItem = nullptr;
1119
1120
0
    SfxItemState eState = SfxItemState::DEFAULT;
1121
1122
    // check all paragraphs inside the selection
1123
0
    for (sal_Int32 nPara = rSel.start.nPara; nPara <= rSel.end.nPara; nPara++)
1124
0
    {
1125
0
        SfxItemState eParaState = SfxItemState::DEFAULT;
1126
1127
        // calculate start and endpos for this paragraph
1128
0
        sal_Int32 nPos = 0;
1129
0
        if (rSel.start.nPara == nPara)
1130
0
            nPos = rSel.start.nIndex;
1131
1132
0
        sal_Int32 nEndPos = rSel.end.nIndex;
1133
0
        if (rSel.end.nPara != nPara)
1134
0
            nEndPos = rEditEngine.GetTextLen(nPara);
1135
1136
        // get list of char attribs
1137
0
        rEditEngine.GetCharAttribs(nPara, aAttribs);
1138
1139
0
        bool bEmpty = true; // we found no item inside the selection of this paragraph
1140
0
        bool bGaps = false; // we found items but there are gaps between them
1141
0
        sal_Int32 nLastEnd = nPos;
1142
1143
0
        const SfxPoolItem* pParaItem = nullptr;
1144
1145
0
        for (const auto& rAttrib : aAttribs)
1146
0
        {
1147
0
            assert(rAttrib.pAttr && "GetCharAttribs gives corrupt data");
1148
1149
0
            const bool bEmptyPortion = (rAttrib.nStart == rAttrib.nEnd);
1150
0
            if ((!bEmptyPortion && (rAttrib.nStart >= nEndPos))
1151
0
                || (bEmptyPortion && (rAttrib.nStart > nEndPos)))
1152
0
                break; // break if we are already behind our selection
1153
1154
0
            if ((!bEmptyPortion && (rAttrib.nEnd <= nPos))
1155
0
                || (bEmptyPortion && (rAttrib.nEnd < nPos)))
1156
0
                continue; // or if the attribute ends before our selection
1157
1158
0
            if (rAttrib.pAttr->Which() != nWhich)
1159
0
                continue; // skip if is not the searched item
1160
1161
            // if we already found an item
1162
0
            if (pParaItem)
1163
0
            {
1164
                // ... and its different to this one than the state is don't care
1165
0
                if (*pParaItem != *(rAttrib.pAttr))
1166
0
                    return SfxItemState::INVALID;
1167
0
            }
1168
0
            else
1169
0
            {
1170
0
                pParaItem = rAttrib.pAttr;
1171
0
            }
1172
1173
0
            if (bEmpty)
1174
0
                bEmpty = false;
1175
1176
0
            if (!bGaps && rAttrib.nStart > nLastEnd)
1177
0
                bGaps = true;
1178
1179
0
            nLastEnd = rAttrib.nEnd;
1180
0
        }
1181
1182
0
        if (!bEmpty && !bGaps && nLastEnd < (nEndPos - 1))
1183
0
            bGaps = true;
1184
0
        if (bEmpty)
1185
0
            eParaState = SfxItemState::DEFAULT;
1186
0
        else if (bGaps)
1187
0
            eParaState = SfxItemState::INVALID;
1188
0
        else
1189
0
            eParaState = SfxItemState::SET;
1190
1191
        // if we already found an item check if we found the same
1192
0
        if (pLastItem)
1193
0
        {
1194
0
            if ((pParaItem == nullptr) || (*pLastItem != *pParaItem))
1195
0
                return SfxItemState::INVALID;
1196
0
        }
1197
0
        else
1198
0
        {
1199
0
            pLastItem = pParaItem;
1200
0
            eState = eParaState;
1201
0
        }
1202
0
    }
1203
1204
0
    return eState;
1205
0
}
1206
1207
SfxItemState WeldTextForwarder::GetItemState(const ESelection& rSel, sal_uInt16 nWhich) const
1208
0
{
1209
0
    SfxItemState nState = SfxItemState::DISABLED;
1210
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1211
0
    if (pEditEngine)
1212
0
        nState = GetSvxEditEngineItemState(*pEditEngine, rSel, nWhich);
1213
0
    return nState;
1214
0
}
1215
1216
SfxItemState WeldTextForwarder::GetItemState(sal_Int32 nPara, sal_uInt16 nWhich) const
1217
0
{
1218
0
    SfxItemState nState = SfxItemState::DISABLED;
1219
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1220
0
    if (pEditEngine)
1221
0
    {
1222
0
        const SfxItemSet& rSet = pEditEngine->GetParaAttribs(nPara);
1223
0
        nState = rSet.GetItemState(nWhich);
1224
0
    }
1225
0
    return nState;
1226
0
}
1227
1228
LanguageType WeldTextForwarder::GetLanguage(sal_Int32 nPara, sal_Int32 nIndex) const
1229
0
{
1230
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1231
0
    return pEditEngine ? pEditEngine->GetLanguage(nPara, nIndex).nLang : LANGUAGE_NONE;
1232
0
}
1233
1234
std::vector<EFieldInfo> WeldTextForwarder::GetFieldInfo(sal_Int32 nPara) const
1235
0
{
1236
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1237
0
    if (!pEditEngine)
1238
0
        return {};
1239
0
    return pEditEngine->GetFieldInfo(nPara);
1240
0
}
1241
1242
0
EBulletInfo WeldTextForwarder::GetBulletInfo(sal_Int32 /*nPara*/) const { return EBulletInfo(); }
1243
1244
tools::Rectangle WeldTextForwarder::GetCharBounds(sal_Int32 nPara, sal_Int32 nIndex) const
1245
0
{
1246
0
    tools::Rectangle aRect(0, 0, 0, 0);
1247
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1248
1249
0
    if (pEditEngine)
1250
0
    {
1251
        // Handle virtual position one-past-the end of the string
1252
0
        if (nIndex >= pEditEngine->GetTextLen(nPara))
1253
0
        {
1254
0
            if (nIndex)
1255
0
                aRect = pEditEngine->GetCharacterBounds(EPaM(nPara, nIndex - 1));
1256
1257
0
            aRect.Move(aRect.Right() - aRect.Left(), 0);
1258
0
            aRect.SetSize(Size(1, pEditEngine->GetTextHeight()));
1259
0
        }
1260
0
        else
1261
0
        {
1262
0
            aRect = pEditEngine->GetCharacterBounds(EPaM(nPara, nIndex));
1263
0
        }
1264
0
    }
1265
0
    return aRect;
1266
0
}
1267
1268
tools::Rectangle WeldTextForwarder::GetParaBounds(sal_Int32 nPara) const
1269
0
{
1270
0
    tools::Rectangle aRect(0, 0, 0, 0);
1271
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1272
1273
0
    if (pEditEngine)
1274
0
    {
1275
0
        const Point aPnt = pEditEngine->GetDocPosTopLeft(nPara);
1276
0
        const sal_Int32 nWidth = pEditEngine->CalcTextWidth();
1277
0
        const sal_Int32 nHeight = pEditEngine->GetTextHeight(nPara);
1278
0
        aRect = tools::Rectangle(aPnt.X(), aPnt.Y(), aPnt.X() + nWidth, aPnt.Y() + nHeight);
1279
0
    }
1280
1281
0
    return aRect;
1282
0
}
1283
1284
MapMode WeldTextForwarder::GetMapMode() const
1285
0
{
1286
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1287
0
    return pEditEngine ? pEditEngine->GetRefMapMode() : MapMode(MapUnit::Map100thMM);
1288
0
}
1289
1290
OutputDevice* WeldTextForwarder::GetRefDevice() const
1291
0
{
1292
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1293
0
    return pEditEngine ? pEditEngine->GetRefDevice() : nullptr;
1294
0
}
1295
1296
bool WeldTextForwarder::GetIndexAtPoint(const Point& rPos, sal_Int32& nPara,
1297
                                        sal_Int32& nIndex) const
1298
0
{
1299
0
    bool bRes = false;
1300
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1301
0
    if (pEditEngine)
1302
0
    {
1303
0
        EPaM aDocPos = pEditEngine->FindDocPosition(rPos);
1304
0
        nPara = aDocPos.nPara;
1305
0
        nIndex = aDocPos.nIndex;
1306
0
        bRes = true;
1307
0
    }
1308
0
    return bRes;
1309
0
}
1310
1311
bool WeldTextForwarder::GetWordIndices(sal_Int32 nPara, sal_Int32 nIndex, sal_Int32& nStart,
1312
                                       sal_Int32& nEnd) const
1313
0
{
1314
0
    bool bRes = false;
1315
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1316
0
    if (pEditEngine)
1317
0
    {
1318
0
        ESelection aRes
1319
0
            = pEditEngine->GetWord(ESelection(nPara, nIndex), css::i18n::WordType::DICTIONARY_WORD);
1320
1321
0
        if (aRes.start.nPara == nPara && aRes.start.nPara == aRes.end.nPara)
1322
0
        {
1323
0
            nStart = aRes.start.nIndex;
1324
0
            nEnd = aRes.end.nIndex;
1325
1326
0
            bRes = true;
1327
0
        }
1328
0
    }
1329
1330
0
    return bRes;
1331
0
}
1332
1333
bool WeldTextForwarder::GetAttributeRun(sal_Int32& nStartIndex, sal_Int32& nEndIndex,
1334
                                        sal_Int32 nPara, sal_Int32 nIndex, bool bInCell) const
1335
0
{
1336
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1337
0
    if (!pEditEngine)
1338
0
        return false;
1339
0
    SvxEditSourceHelper::GetAttributeRun(nStartIndex, nEndIndex, *pEditEngine, nPara, nIndex,
1340
0
                                         bInCell);
1341
0
    return true;
1342
0
}
1343
1344
sal_Int32 WeldTextForwarder::GetLineCount(sal_Int32 nPara) const
1345
0
{
1346
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1347
0
    return pEditEngine ? pEditEngine->GetLineCount(nPara) : 0;
1348
0
}
1349
1350
sal_Int32 WeldTextForwarder::GetLineLen(sal_Int32 nPara, sal_Int32 nLine) const
1351
0
{
1352
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1353
0
    return pEditEngine ? pEditEngine->GetLineLen(nPara, nLine) : 0;
1354
0
}
1355
1356
void WeldTextForwarder::GetLineBoundaries(/*out*/ sal_Int32& rStart, /*out*/ sal_Int32& rEnd,
1357
                                          sal_Int32 nPara, sal_Int32 nLine) const
1358
0
{
1359
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1360
0
    if (pEditEngine)
1361
0
        pEditEngine->GetLineBoundaries(rStart, rEnd, nPara, nLine);
1362
0
    else
1363
0
        rStart = rEnd = 0;
1364
0
}
1365
1366
sal_Int32 WeldTextForwarder::GetLineNumberAtIndex(sal_Int32 nPara, sal_Int32 nIndex) const
1367
0
{
1368
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1369
0
    return pEditEngine ? pEditEngine->GetLineNumberAtIndex(nPara, nIndex) : 0;
1370
0
}
1371
1372
bool WeldTextForwarder::QuickFormatDoc(bool /*bFull*/)
1373
0
{
1374
0
    bool bRes = false;
1375
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1376
0
    if (pEditEngine)
1377
0
    {
1378
0
        pEditEngine->QuickFormatDoc();
1379
0
        bRes = true;
1380
0
    }
1381
0
    return bRes;
1382
0
}
1383
1384
sal_Int16 WeldTextForwarder::GetDepth(sal_Int32 /*nPara*/) const
1385
0
{
1386
    // math has no outliner...
1387
0
    return -1;
1388
0
}
1389
1390
bool WeldTextForwarder::SetDepth(sal_Int32 /*nPara*/, sal_Int16 nNewDepth)
1391
0
{
1392
    // math has no outliner...
1393
0
    return -1 == nNewDepth; // is it the value from 'GetDepth' ?
1394
0
}
1395
1396
bool WeldTextForwarder::Delete(const ESelection& rSelection)
1397
0
{
1398
0
    bool bRes = false;
1399
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1400
0
    if (pEditEngine)
1401
0
    {
1402
0
        pEditEngine->QuickDelete(rSelection);
1403
0
        pEditEngine->QuickFormatDoc();
1404
0
        bRes = true;
1405
0
    }
1406
0
    return bRes;
1407
0
}
1408
1409
bool WeldTextForwarder::InsertText(const OUString& rStr, const ESelection& rSelection)
1410
0
{
1411
0
    bool bRes = false;
1412
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1413
0
    if (pEditEngine)
1414
0
    {
1415
0
        pEditEngine->QuickInsertText(rStr, rSelection);
1416
0
        pEditEngine->QuickFormatDoc();
1417
0
        bRes = true;
1418
0
    }
1419
0
    return bRes;
1420
0
}
1421
1422
const SfxItemSet* WeldTextForwarder::GetEmptyItemSetPtr()
1423
0
{
1424
0
    const SfxItemSet* pItemSet = nullptr;
1425
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1426
0
    if (pEditEngine)
1427
0
    {
1428
0
        pItemSet = &pEditEngine->GetEmptyItemSet();
1429
0
    }
1430
0
    return pItemSet;
1431
0
}
1432
1433
void WeldTextForwarder::AppendParagraph()
1434
0
{
1435
    // append an empty paragraph
1436
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1437
0
    if (pEditEngine)
1438
0
    {
1439
0
        sal_Int32 nParaCount = pEditEngine->GetParagraphCount();
1440
0
        pEditEngine->InsertParagraph(nParaCount, OUString());
1441
0
    }
1442
0
}
1443
1444
sal_Int32 WeldTextForwarder::AppendTextPortion(sal_Int32 nPara, const OUString& rText,
1445
                                               const SfxItemSet& rSet)
1446
0
{
1447
0
    sal_uInt16 nRes = 0;
1448
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1449
0
    if (pEditEngine && nPara < pEditEngine->GetParagraphCount())
1450
0
    {
1451
        // append text
1452
0
        ESelection aSel(nPara, pEditEngine->GetTextLen(nPara));
1453
0
        pEditEngine->QuickInsertText(rText, aSel);
1454
1455
        // set attributes for new appended text
1456
0
        nRes = aSel.end.nIndex = pEditEngine->GetTextLen(nPara);
1457
0
        pEditEngine->QuickSetAttribs(rSet, aSel);
1458
0
    }
1459
0
    return nRes;
1460
0
}
1461
1462
void WeldTextForwarder::CopyText(const SvxTextForwarder& rSource)
1463
0
{
1464
0
    const WeldTextForwarder* pSourceForwarder = dynamic_cast<const WeldTextForwarder*>(&rSource);
1465
0
    if (!pSourceForwarder)
1466
0
        return;
1467
0
    EditEngine* pSourceEditEngine = pSourceForwarder->m_rEditAcc.GetEditEngine();
1468
0
    EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1469
0
    if (pEditEngine && pSourceEditEngine)
1470
0
    {
1471
0
        std::unique_ptr<EditTextObject> pNewTextObject = pSourceEditEngine->CreateTextObject();
1472
0
        pEditEngine->SetText(*pNewTextObject);
1473
0
    }
1474
0
}
1475
1476
WeldEditViewForwarder::WeldEditViewForwarder(WeldEditAccessible& rAcc)
1477
0
    : m_rEditAcc(rAcc)
1478
0
{
1479
0
}
1480
1481
0
bool WeldEditViewForwarder::IsValid() const { return m_rEditAcc.GetEditView() != nullptr; }
1482
1483
Point WeldEditViewForwarder::LogicToPixel(const Point& rPoint, const MapMode& rMapMode) const
1484
0
{
1485
0
    EditView* pEditView = m_rEditAcc.GetEditView();
1486
0
    if (!pEditView)
1487
0
        return Point();
1488
0
    OutputDevice& rOutDev = pEditView->GetOutputDevice();
1489
0
    MapMode aMapMode(rOutDev.GetMapMode());
1490
0
    Point aPoint(OutputDevice::LogicToLogic(rPoint, rMapMode, MapMode(aMapMode.GetMapUnit())));
1491
0
    aMapMode.SetOrigin(Point());
1492
0
    return rOutDev.LogicToPixel(aPoint, aMapMode);
1493
0
}
1494
1495
Point WeldEditViewForwarder::PixelToLogic(const Point& rPoint, const MapMode& rMapMode) const
1496
0
{
1497
0
    EditView* pEditView = m_rEditAcc.GetEditView();
1498
0
    if (!pEditView)
1499
0
        return Point();
1500
0
    OutputDevice& rOutDev = pEditView->GetOutputDevice();
1501
0
    MapMode aMapMode(rOutDev.GetMapMode());
1502
0
    aMapMode.SetOrigin(Point());
1503
0
    Point aPoint(rOutDev.PixelToLogic(rPoint, aMapMode));
1504
0
    return OutputDevice::LogicToLogic(aPoint, MapMode(aMapMode.GetMapUnit()), rMapMode);
1505
0
}
1506
1507
bool WeldEditViewForwarder::GetSelection(ESelection& rSelection) const
1508
0
{
1509
0
    bool bRes = false;
1510
0
    EditView* pEditView = m_rEditAcc.GetEditView();
1511
0
    if (pEditView)
1512
0
    {
1513
0
        rSelection = pEditView->GetSelection();
1514
0
        bRes = true;
1515
0
    }
1516
0
    return bRes;
1517
0
}
1518
1519
bool WeldEditViewForwarder::SetSelection(const ESelection& rSelection)
1520
0
{
1521
0
    bool bRes = false;
1522
0
    EditView* pEditView = m_rEditAcc.GetEditView();
1523
0
    if (pEditView)
1524
0
    {
1525
0
        pEditView->SetSelection(rSelection);
1526
0
        bRes = true;
1527
0
    }
1528
0
    return bRes;
1529
0
}
1530
1531
bool WeldEditViewForwarder::Copy()
1532
0
{
1533
0
    bool bRes = false;
1534
0
    EditView* pEditView = m_rEditAcc.GetEditView();
1535
0
    if (pEditView)
1536
0
    {
1537
0
        pEditView->Copy();
1538
0
        bRes = true;
1539
0
    }
1540
0
    return bRes;
1541
0
}
1542
1543
bool WeldEditViewForwarder::Cut()
1544
0
{
1545
0
    bool bRes = false;
1546
0
    EditView* pEditView = m_rEditAcc.GetEditView();
1547
0
    if (pEditView)
1548
0
    {
1549
0
        pEditView->Cut();
1550
0
        bRes = true;
1551
0
    }
1552
0
    return bRes;
1553
0
}
1554
1555
bool WeldEditViewForwarder::Paste()
1556
0
{
1557
0
    bool bRes = false;
1558
0
    EditView* pEditView = m_rEditAcc.GetEditView();
1559
0
    if (pEditView)
1560
0
    {
1561
0
        pEditView->Paste();
1562
0
        bRes = true;
1563
0
    }
1564
0
    return bRes;
1565
0
}
1566
1567
void WeldEditView::SetDrawingArea(weld::DrawingArea* pDrawingArea)
1568
0
{
1569
0
    Size aSize(pDrawingArea->get_size_request());
1570
0
    if (aSize.Width() == -1)
1571
0
        aSize.setWidth(500);
1572
0
    if (aSize.Height() == -1)
1573
0
        aSize.setHeight(100);
1574
0
    pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
1575
1576
0
    SetOutputSizePixel(aSize);
1577
1578
0
    weld::CustomWidgetController::SetDrawingArea(pDrawingArea);
1579
1580
0
    EnableRTL(false);
1581
1582
0
    const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1583
0
    Color aBgColor = rStyleSettings.GetFieldColor();
1584
1585
0
    OutputDevice& rDevice = pDrawingArea->get_ref_device();
1586
1587
0
    rDevice.SetMapMode(MapMode(MapUnit::MapTwip));
1588
0
    rDevice.SetBackground(aBgColor);
1589
1590
0
    Size aOutputSize(rDevice.PixelToLogic(aSize));
1591
1592
0
    makeEditEngine();
1593
0
    m_xEditEngine->SetPaperSize(aOutputSize);
1594
0
    m_xEditEngine->SetRefDevice(&rDevice);
1595
1596
0
    m_xEditEngine->SetControlWord(m_xEditEngine->GetControlWord() | EEControlBits::MARKFIELDS);
1597
1598
0
    m_xEditView.reset(new EditView(*m_xEditEngine, nullptr));
1599
0
    m_xEditView->setEditViewCallbacks(this);
1600
0
    m_xEditView->SetOutputArea(tools::Rectangle(Point(0, 0), aOutputSize));
1601
1602
0
    m_xEditView->SetBackgroundColor(aBgColor);
1603
0
    m_xEditEngine->SetBackgroundColor(aBgColor);
1604
0
    m_xEditEngine->InsertView(m_xEditView.get());
1605
1606
0
    pDrawingArea->set_cursor(PointerStyle::Text);
1607
1608
0
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
1609
0
    InitAccessible();
1610
0
#endif
1611
0
}
1612
1613
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
1614
void WeldEditView::InitAccessible()
1615
0
{
1616
0
    if (m_xAccessible.is())
1617
0
        m_xAccessible->Init(GetEditEngine(), GetEditView());
1618
0
}
1619
#endif
1620
1621
int WeldEditView::GetSurroundingText(OUString& rSurrounding)
1622
0
{
1623
0
    EditView* pEditView = GetEditView();
1624
0
    if (!pEditView)
1625
0
        return -1;
1626
0
    rSurrounding = pEditView->GetSurroundingText();
1627
0
    return pEditView->GetSurroundingTextSelection().Min();
1628
0
}
1629
1630
bool WeldEditView::DeleteSurroundingText(const Selection& rRange)
1631
0
{
1632
0
    EditView* pEditView = GetEditView();
1633
0
    if (!pEditView)
1634
0
        return false;
1635
0
    return pEditView->DeleteSurroundingText(rRange);
1636
0
}
1637
1638
void WeldEditView::GetFocus()
1639
0
{
1640
0
    EditView* pEditView = GetEditView();
1641
0
    if (pEditView)
1642
0
    {
1643
0
        pEditView->ShowCursor(false);
1644
1645
0
        m_bCursorVisible = true;
1646
0
        m_aCachedCursorPixRect = tools::Rectangle();
1647
0
        sal_uInt64 nBlinkTime = Application::GetSettings().GetStyleSettings().GetCursorBlinkTime();
1648
0
        if (nBlinkTime != STYLE_CURSOR_NOBLINKTIME)
1649
0
        {
1650
0
            m_aCursorTimer.SetTimeout(nBlinkTime);
1651
0
            m_aCursorTimer.Start();
1652
0
        }
1653
1654
0
        Invalidate(); // redraw with cursor
1655
0
    }
1656
1657
0
    weld::CustomWidgetController::GetFocus();
1658
1659
0
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
1660
0
    if (m_xAccessible.is())
1661
0
    {
1662
        // Note: will implicitly send the AccessibleStateType::FOCUSED event
1663
0
        ::accessibility::AccessibleTextHelper* pHelper = m_xAccessible->GetTextHelper();
1664
0
        if (pHelper)
1665
0
            pHelper->SetFocus();
1666
0
    }
1667
0
#endif
1668
0
}
1669
1670
void WeldEditView::LoseFocus()
1671
0
{
1672
0
    m_aCursorTimer.Stop();
1673
0
    m_bCursorVisible = false;
1674
0
    m_aCachedCursorPixRect = tools::Rectangle();
1675
1676
0
    weld::CustomWidgetController::LoseFocus();
1677
0
    Invalidate(); // redraw without cursor
1678
1679
0
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
1680
0
    if (m_xAccessible.is())
1681
0
    {
1682
        // Note: will implicitly send the AccessibleStateType::FOCUSED event
1683
0
        ::accessibility::AccessibleTextHelper* pHelper = m_xAccessible->GetTextHelper();
1684
0
        if (pHelper)
1685
0
            pHelper->SetFocus(false);
1686
0
    }
1687
0
#endif
1688
0
}
1689
1690
0
bool WeldEditView::CanFocus() const { return true; }
1691
1692
css::uno::Reference<css::datatransfer::dnd::XDropTarget> WeldEditView::GetDropTarget()
1693
0
{
1694
0
    if (!m_xDropTarget)
1695
0
        m_xDropTarget = weld::CustomWidgetController::GetDropTarget();
1696
0
    return m_xDropTarget;
1697
0
}
1698
1699
css::uno::Reference<css::datatransfer::clipboard::XClipboard> WeldEditView::GetClipboard() const
1700
0
{
1701
0
    return weld::CustomWidgetController::GetClipboard();
1702
0
}
1703
1704
void WeldEditView::EditViewSelectionChange()
1705
0
{
1706
0
    Invalidate();
1707
1708
0
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
1709
0
    if (m_xAccessible.is())
1710
0
    {
1711
0
        ::accessibility::AccessibleTextHelper* pHelper = m_xAccessible->GetTextHelper();
1712
0
        if (pHelper)
1713
0
            pHelper->UpdateSelection();
1714
0
    }
1715
0
#endif
1716
0
}
1717
1718
namespace
1719
{
1720
class WeldEditViewUIObject final : public DrawingAreaUIObject
1721
{
1722
private:
1723
    WeldEditView* mpEditView;
1724
1725
public:
1726
    WeldEditViewUIObject(const VclPtr<vcl::Window>& rDrawingArea)
1727
0
        : DrawingAreaUIObject(rDrawingArea)
1728
0
        , mpEditView(static_cast<WeldEditView*>(mpController))
1729
0
    {
1730
0
    }
1731
1732
    static std::unique_ptr<UIObject> create(vcl::Window* pWindow)
1733
0
    {
1734
0
        return std::unique_ptr<UIObject>(new WeldEditViewUIObject(pWindow));
1735
0
    }
1736
1737
    virtual StringMap get_state() override
1738
0
    {
1739
0
        StringMap aMap = WindowUIObject::get_state();
1740
0
        aMap[u"Text"_ustr] = mpEditView->GetText();
1741
0
        return aMap;
1742
0
    }
1743
1744
private:
1745
0
    virtual OUString get_name() const override { return u"WeldEditViewUIObject"_ustr; }
1746
};
1747
}
1748
1749
0
FactoryFunction WeldEditView::GetUITestFactory() const { return WeldEditViewUIObject::create; }
1750
1751
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */