Coverage Report

Created: 2026-09-28 10:59

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