Coverage Report

Created: 2026-08-14 10:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/sfx2/lokhelper.hxx
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
10
#ifndef INCLUDED_SFX2_LOKHELPER_HXX
11
#define INCLUDED_SFX2_LOKHELPER_HXX
12
13
#include <com/sun/star/ui/XAcceleratorConfiguration.hpp>
14
#include <com/sun/star/security/XCertificate.hpp>
15
#include <com/sun/star/xml/crypto/XCertificateCreator.hpp>
16
17
#include <vcl/IDialogRenderable.hxx>
18
#include <vcl/ITiledRenderable.hxx>
19
#include <vcl/event.hxx>
20
#include <vcl/vclptr.hxx>
21
#include <vcl/window.hxx>
22
#include <sfx2/dllapi.h>
23
#include <sfx2/viewsh.hxx>
24
#include <tools/gen.hxx>
25
#include <cstddef>
26
#include <rtl/strbuf.hxx>
27
#include <rtl/string.hxx>
28
#include <list>
29
#include <optional>
30
#include <string_view>
31
#include <unordered_map>
32
33
#include <boost/property_tree/ptree_fwd.hpp>
34
35
#define LOK_NOTIFY_LOG_TO_CLIENT 1
36
37
#define LOK_LOG_STREAM(level, area, stream) \
38
0
    do { \
39
0
            ::std::ostringstream lok_detail_stream; \
40
0
            lok_detail_stream << level << ':'; \
41
0
            if (std::strcmp(level, "debug") != 0) \
42
0
                lok_detail_stream << area << ':'; \
43
0
            const char* const where = SAL_WHERE; \
44
0
            lok_detail_stream << where << stream; \
45
0
            SfxLokHelper::notifyLog(lok_detail_stream); \
46
0
        } while (false)
47
48
#if LOK_NOTIFY_LOG_TO_CLIENT > 0
49
#define LOK_INFO(area, stream) \
50
0
    LOK_LOG_STREAM("info", area, stream) \
51
52
#define LOK_WARN(area, stream) \
53
0
    LOK_LOG_STREAM("warn", area, stream)
54
55
#else
56
#define LOK_INFO(area, stream) \
57
    SAL_INFO(area, stream) \
58
59
#define LOK_WARN(area, stream) \
60
    SAL_WARN(area, stream)
61
62
#endif
63
64
struct SFX2_DLLPUBLIC LokMouseEventData
65
{
66
    int mnType;
67
    Point maPosition;
68
    int mnCount;
69
    MouseEventModifiers meModifiers;
70
    int mnButtons;
71
    int mnModifier;
72
    std::optional<Point> maLogicPosition;
73
74
    LokMouseEventData(int nType, Point aPosition, int nCount, MouseEventModifiers eModifiers, int nButtons, int nModifier)
75
0
        : mnType(nType)
76
0
        , maPosition(aPosition)
77
0
        , mnCount(nCount)
78
0
        , meModifiers(eModifiers)
79
0
        , mnButtons(nButtons)
80
0
        , mnModifier(nModifier)
81
0
    {}
82
};
83
84
namespace com::sun::star::ui { struct ContextChangeEventObject; };
85
86
class SFX2_DLLPUBLIC SfxLokHelper
87
{
88
public:
89
    /// Gets the short cut accelerators.
90
    static std::unordered_map<OUString, css::uno::Reference<css::ui::XAcceleratorConfiguration>>& getAcceleratorConfs();
91
    /// Create a new view shell from the current view frame.
92
    /// This assumes a single document is ever loaded.
93
    static int createView();
94
    /// Create a new view shell for the given DocId, for multi-document support.
95
    static int createView(int nDocId);
96
    /// Destroy a view shell from the global shell list.
97
    static void destroyView(int nId);
98
    /// Set a view shell as current one.
99
    static void setView(int nId);
100
    /// Determines if a call to setView() is in progress or not.
101
    static bool isSettingView();
102
    /// Set the edit mode for a document with callbacks disabled.
103
    static void setEditMode(int nMode, vcl::ITiledRenderable* pDoc);
104
    /// Get view shell with id
105
    static SfxViewShell* getViewOfId(int nId);
106
    /// Get view id of view shell
107
    static int getView(const SfxViewShell& rViewShell);
108
    /// Get the currently active view shell id
109
    static int getCurrentView();
110
    /// Get the number of views of the current DocId.
111
    static std::size_t getViewsCount(int nDocId);
112
    /// Get the number of docs
113
    static std::size_t getDocsCount();
114
    /// Get the most recently active viewId of the DocId.
115
    static int getViewId(int nDocId);
116
    /// Get viewIds of views of the DocId.
117
    static bool getViewIds(int nDocId, int* pArray, size_t nSize);
118
    /// Set View Blocked for some uno commands
119
    static void setBlockedCommandList(int nViewId, const char* blockedCommandList);
120
    /// Get the document id for a view
121
    static int getDocumentIdOfView(int nViewId);
122
    /// Get the default language that should be used for views
123
    static const LanguageTag & getDefaultLanguage();
124
    /// Set language of the given view.
125
    static void setViewLanguage(int nId, const OUString& rBcp47LanguageTag);
126
    /// Set the default language for views.
127
    static void setDefaultLanguage(const OUString& rBcp47LanguageTag);
128
    /// Enable/Disable AT support for the given view.
129
    static void setAccessibilityState(int nId, bool nEnabled);
130
    // Set the readonly state of the view.
131
    static void setViewReadOnly(int nId, bool readOnly);
132
    /// Get the language used by the loading view (used for all save operations).
133
    static const LanguageTag & getLoadLanguage();
134
    /// Set the language used by the loading view (used for all save operations).
135
    static void setLoadLanguage(const OUString& rBcp47LanguageTag);
136
    /// Set the locale for the given view.
137
    static void setViewLocale(int nId, const OUString& rBcp47LanguageTag);
138
    /// Set color preview state for the given view.
139
    static void setColorPreviewState(int nId, bool nEnabled);
140
141
    /// Set timezone of the given view.
142
    /// @isSet true to use @rTimezone, even if it's empty. Otherwise, no timezone.
143
    /// @rTimezone the value to set (which could be empty).
144
    static void setDefaultTimezone(bool isSet, const OUString& rTimezone);
145
    /// Get timezone of the given view. See @setDefaultTimezone.
146
    static std::pair<bool, OUString> getDefaultTimezone();
147
    /// Set the timezone of the given view.
148
    static void setViewTimezone(int nId, bool isSet, const OUString& rTimezone);
149
    /// Get the timezone of the given view.
150
    static std::pair<bool, OUString> getViewTimezone(int nId);
151
152
    /// Iterate over any view shell, except pThisViewShell, passing it to the f function.
153
    template<typename ViewShellType, typename FunctionType>
154
    static void forEachOtherView(ViewShellType* pThisViewShell, FunctionType f);
155
156
    /// Invoke the LOK callback of all other views showing the same document as pThisView, with a payload of rKey-rPayload.
157
    static void notifyOtherViews(const SfxViewShell* pThisView, int nType, std::string_view rKey,
158
                                 const OString& rPayload);
159
    /// Invoke the LOK callback of all views except pThisView, with a JSON payload created from the given property tree.
160
    static void notifyOtherViews(const SfxViewShell* pThisView, int nType,
161
                                 const boost::property_tree::ptree& rTree);
162
    /// Same as notifyOtherViews(), but works on a selected "other" view, not on all of them.
163
    static void notifyOtherView(const SfxViewShell& rThisView, SfxViewShell const* pOtherView,
164
                                int nType, std::string_view rKey, const OString& rPayload);
165
    /// Same as notifyOtherViews(), the property-tree version, but works on a selected "other" view, not on all of them.
166
    static void notifyOtherView(const SfxViewShell& rThisView, SfxViewShell const* pOtherView,
167
                                int nType, const boost::property_tree::ptree& rTree);
168
169
    /// Emits a LOK_CALLBACK_STATE_CHANGED
170
    static void sendUnoStatus(const SfxViewShell* pShell, const SfxPoolItem* pItem);
171
    /// Emits a LOK_CALLBACK_WINDOW
172
    static void notifyWindow(const SfxViewShell* pThisView,
173
                             vcl::LOKWindowId nWindowId,
174
                             std::u16string_view rAction,
175
                             const std::vector<vcl::LOKPayloadItem>& rPayload = std::vector<vcl::LOKPayloadItem>());
176
    /// Emits a LOK_CALLBACK_DOCUMENT_SIZE_CHANGED - if @bInvalidateAll - first invalidates all parts
177
    static void notifyDocumentSizeChanged(SfxViewShell const* pThisView, const OString& rPayload, vcl::ITiledRenderable* pDoc, bool bInvalidateAll = true);
178
    /// Emits a LOK_CALLBACK_DOCUMENT_SIZE_CHANGED for all views of the same document - if @bInvalidateAll - first invalidates all parts
179
    static void notifyDocumentSizeChangedAllViews(vcl::ITiledRenderable* pDoc, bool bInvalidateAll = true);
180
    /// Emits a LOK_CALLBACK_STATE_CHANGED for all views of the same document - with payload ".uno:CurrentPageResize"
181
    static void notifyCurrentPageSizeChangedAllViews(const vcl::ITiledRenderable* pDoc);
182
    /// Emits a LOK_CALLBACK_DOCUMENT_SIZE_CHANGED for all views of the same document with the same part
183
    static void notifyPartSizeChangedAllViews(vcl::ITiledRenderable* pDoc, int nPart);
184
    /// Emits a LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR
185
    static void notifyCursorInvalidation(SfxViewShell const* pThisView, tools::Rectangle const * pRect, bool bControlEvent, int windowID);
186
    /// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to setOptionalFeatures() if needed.
187
    static void notifyInvalidation(SfxViewShell const* pThisView, int nPart, tools::Rectangle const *);
188
    /// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to setOptionalFeatures() if needed
189
    /// uses the Part reported by pThisView
190
    static void notifyInvalidation(SfxViewShell const* pThisView, tools::Rectangle const *);
191
    /// Notifies all views with the given type and payload.
192
    static void notifyAllViews(int nType, const OString& rPayload);
193
194
    /// Notify about the editing context change.
195
    static void notifyContextChange(const css::ui::ContextChangeEventObject& rEvent);
196
197
    /// Emits an LOK_CALLBACK_VIEW_RENDER_STATE
198
    static void notifyViewRenderState(SfxViewShell const* pViewShell, vcl::ITiledRenderable* pDoc);
199
200
    // Notify about the given type needing an update.
201
    static void notifyUpdate(SfxViewShell const* pViewShell, int nType);
202
    // Notify about the given type needing a per-viewid update.
203
    static void notifyUpdatePerViewId(SfxViewShell const& rViewShell, int nType);
204
    /// Same as notifyUpdatePerViewId(), pTargetShell will be notified, relevant viewId in pViewShell,
205
    /// pSourceView->getLOKPayload() will be called to get the data.
206
    static void notifyUpdatePerViewId(SfxViewShell const& rTargetShell, SfxViewShell const* pViewShell,
207
        SfxViewShell const& rSourceShell, int nType);
208
    // Notify other views about the given type needing a per-viewid update.
209
    static void notifyOtherViewsUpdatePerViewId(SfxViewShell const* pViewShell, int nType);
210
211
    static OString makePayloadJSON(const SfxViewShell* pThisView, int nViewId, std::string_view rKey, const OString& rPayload);
212
    /// Makes a LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR payload, but tweaks it according to setOptionalFeatures() if needed.
213
    static OString makeVisCursorInvalidation(int nViewId, const OString& rRectangle,
214
                                             bool bMispelledWord = false, const OString& rHyperlink = ""_ostr);
215
216
    /// Helper for posting async key event
217
    static void postKeyEventAsync(const VclPtr<vcl::Window> &xWindow,
218
                                  int nType, int nCharCode, int nKeyCode, int nRepeat = 0);
219
220
    /// Helper for posting input event
221
    static void postExtTextEventAsync(const VclPtr<vcl::Window> &xWindow,
222
                                      int nType, const OUString &rText);
223
224
    /// Helper for posting async mouse event
225
    static void postMouseEventAsync(const VclPtr<vcl::Window> &xWindow, LokMouseEventData const & rLokMouseEventData);
226
227
    /// A special value to signify 'infinity'.
228
    /// This value is chosen such that sal_Int32 will not overflow when manipulated.
229
    static const tools::Long MaxTwips = 1e9;
230
231
    /// Helper for diagnosing run-time problems
232
    static void dumpState(rtl::OStringBuffer &rState);
233
234
    /// Process the mouse event in the currently active in-place component (if any).
235
    /// Returns true if the event has been processed, and no further processing is necessary.
236
    static bool testInPlaceComponentMouseEventHit(SfxViewShell* pViewShell, int nType, int nX,
237
                                                  int nY, int nCount, int nButtons, int nModifier,
238
                                                  double fScaleX, double fScaleY,
239
                                                  bool bNegativeX = false);
240
241
    static VclPtr<vcl::Window> getInPlaceDocWindow(SfxViewShell* pViewShell);
242
243
    /// Sends Network Access error to LOK
244
    static void sendNetworkAccessError(std::string_view rAction);
245
246
    static void notifyLog(const std::ostringstream& stream);
247
248
    /// Extracts base64 data inside begin/end markers.
249
    static std::string extractCertificate(const std::string& rCert);
250
    /// Extracts multiple certificates in base64 from inside begin/end markers.
251
    static std::vector<std::string> extractCertificates(const std::string& rCerts);
252
    /// Takes a single CA certificate to add them to the list of trusted certificates.
253
    static css::uno::Reference<css::security::XCertificate> addCertificate(const css::uno::Reference<css::xml::crypto::XCertificateCreator>& xCertificateCreator, const css::uno::Sequence<sal_Int8>& rCert);
254
    /// Takes a CA chain to add them to the list of trusted certificates.
255
    static void addCertificates(const std::vector<std::string>& rCerts);
256
    /// Parses a private key + certificate pair.
257
    static css::uno::Reference<css::security::XCertificate> getSigningCertificate(const std::string& rCert, const std::string& rKey);
258
    /// Decides if it's OK to call getCommandValues(rCommand).
259
    static bool supportsCommand(std::u16string_view rCommand);
260
    /// Returns information about a given command in JSON format.
261
    static void getCommandValues(tools::JsonWriter& rJsonWriter, std::string_view rCommand);
262
    /// Parses key-value parameters of rCommand.
263
    static std::map<OUString, OUString> parseCommandParameters(std::u16string_view rCommand);
264
    /// Registers function pointers in comphelper/ to set/get of the current LOK view.
265
    static void registerViewCallbacks();
266
267
    static void dispatchUnoCommand(const boost::property_tree::ptree& tree);
268
269
private:
270
    static int createView(SfxViewFrame& rViewFrame, ViewShellDocId docId);
271
};
272
273
template<typename ViewShellType, typename FunctionType>
274
void SfxLokHelper::forEachOtherView(ViewShellType* pThisViewShell, FunctionType f)
275
0
{
276
0
    SfxViewShell* pViewShell = SfxViewShell::GetFirst();
277
0
    while (pViewShell)
278
0
    {
279
0
        auto pOtherViewShell = dynamic_cast<ViewShellType*>(pViewShell);
280
0
        if (pOtherViewShell != nullptr && pOtherViewShell != pThisViewShell && pOtherViewShell->GetDocId() == pThisViewShell->GetDocId())
281
0
        {
282
0
            f(pOtherViewShell);
283
0
        }
284
0
        pViewShell = SfxViewShell::GetNext(*pViewShell);
285
0
    }
286
0
}
Unexecuted instantiation: tabview3.cxx:void SfxLokHelper::forEachOtherView<ScTabViewShell, ScTabView::OnLibreOfficeKitTabChanged()::$_0>(ScTabViewShell*, ScTabView::OnLibreOfficeKitTabChanged()::$_0)
Unexecuted instantiation: tabview3.cxx:void SfxLokHelper::forEachOtherView<ScTabViewShell, ScTabView::KillEditView(bool)::$_0>(ScTabViewShell*, ScTabView::KillEditView(bool)::$_0)
Unexecuted instantiation: tabview5.cxx:void SfxLokHelper::forEachOtherView<ScTabViewShell, ScTabView::~ScTabView()::$_0>(ScTabViewShell*, ScTabView::~ScTabView()::$_0)
Unexecuted instantiation: tabvwsh3.cxx:void SfxLokHelper::forEachOtherView<ScTabViewShell, ScTabViewShell::Execute(SfxRequest&)::$_2>(ScTabViewShell*, ScTabViewShell::Execute(SfxRequest&)::$_2)
Unexecuted instantiation: tabvwsh3.cxx:void SfxLokHelper::forEachOtherView<ScTabViewShell, ScTabViewShell::Execute(SfxRequest&)::$_3>(ScTabViewShell*, ScTabViewShell::Execute(SfxRequest&)::$_3)
Unexecuted instantiation: viewdata.cxx:void SfxLokHelper::forEachOtherView<ScTabViewShell, (anonymous namespace)::lcl_LOKRemoveWindow(ScTabViewShell*, ScSplitPos)::$_0>(ScTabViewShell*, (anonymous namespace)::lcl_LOKRemoveWindow(ScTabViewShell*, ScSplitPos)::$_0)
Unexecuted instantiation: viewdata.cxx:void SfxLokHelper::forEachOtherView<ScTabViewShell, ScViewData::SetEditEngine(ScSplitPos, ScEditEngineDefaulter&, vcl::Window*, short, int)::$_0>(ScTabViewShell*, ScViewData::SetEditEngine(ScSplitPos, ScEditEngineDefaulter&, vcl::Window*, short, int)::$_0)
287
288
/// If LOK is active, switch to the language/locale of the provided shell and back on delete.
289
class SfxLokLanguageGuard
290
{
291
    bool m_bSetLanguage;
292
    const SfxViewShell* m_pOldShell;
293
294
public:
295
    SfxLokLanguageGuard(const SfxViewShell* pNewShell);
296
    ~SfxLokLanguageGuard();
297
};
298
299
typedef std::list<SfxViewShell*> ViewShellList;
300
301
/// Used to keep track of the last N views that text edited a document through an EditView
302
class SFX2_DLLPUBLIC LOKEditViewHistory
303
{
304
public:
305
    typedef std::list<SfxViewShell*> ViewShellList;
306
    typedef std::unordered_map<int, ViewShellList> EditViewHistoryMap;
307
308
    static void Update(bool bRemove = false);
309
    static ViewShellList GetHistoryForDoc(ViewShellDocId aDocId);
310
    static ViewShellList GetSortedViewsForDoc(ViewShellDocId aDocId);
311
private:
312
    static EditViewHistoryMap maEditViewHistory;
313
};
314
315
#endif
316
317
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */