LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / desktop / inc / lib / init.hxx
blobb3b4338545173de6a95b7d14ac06728b893fe703
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #pragma once
12 #include <map>
13 #include <unordered_map>
14 #include <memory>
15 #include <mutex>
16 #include <set>
17 #include <string_view>
19 #include <boost/property_tree/ptree.hpp>
20 #include <boost/variant.hpp>
21 #include <boost/container/flat_map.hpp>
23 #include <osl/thread.h>
24 #include <rtl/ref.hxx>
25 #include <rtl/strbuf.hxx>
26 #include <vcl/idle.hxx>
27 #include <LibreOfficeKit/LibreOfficeKit.h>
28 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
29 #include <com/sun/star/beans/PropertyValue.hpp>
30 #include <com/sun/star/lang/XComponent.hpp>
31 #include <tools/gen.hxx>
32 #include <sfx2/lokcallback.hxx>
33 #include <sfx2/lokhelper.hxx>
35 #include <desktop/dllapi.h>
37 class LOKInteractionHandler;
39 namespace desktop {
41 /// Represents an invalidated rectangle inside a given document part.
42 struct RectangleAndPart
44 tools::Rectangle m_aRectangle;
45 int m_nPart;
46 int m_nMode;
48 // This is the "EMPTY" rectangle, which somewhat confusingly actually means
49 // to drop all rectangles (see LOK_CALLBACK_INVALIDATE_TILES documentation),
50 // and so it is actually an infinite rectangle and not an empty one.
51 constexpr static tools::Rectangle emptyAllRectangle = {0, 0, SfxLokHelper::MaxTwips, SfxLokHelper::MaxTwips};
53 RectangleAndPart()
54 : m_nPart(INT_MIN) // -1 is reserved to mean "all parts".
55 , m_nMode(0)
59 RectangleAndPart(const tools::Rectangle* pRect, int nPart, int nMode)
60 : m_aRectangle( pRect ? SanitizedRectangle(*pRect) : emptyAllRectangle)
61 , m_nPart(nPart)
62 , m_nMode(nMode)
66 OString toString() const
68 if (m_nPart >= -1)
69 return (isInfinite() ? "EMPTY" : m_aRectangle.toString())
70 + ", " + OString::number(m_nPart) + ", " + OString::number(m_nMode);
71 else
72 return (isInfinite() ? "EMPTY" : m_aRectangle.toString());
75 /// Infinite Rectangle is both sides are
76 /// equal or longer than SfxLokHelper::MaxTwips.
77 bool isInfinite() const
79 return m_aRectangle.GetWidth() >= SfxLokHelper::MaxTwips &&
80 m_aRectangle.GetHeight() >= SfxLokHelper::MaxTwips;
83 /// Empty Rectangle is when it has zero dimensions.
84 bool isEmpty() const
86 return m_aRectangle.IsEmpty();
89 static RectangleAndPart Create(const std::string& rPayload);
90 /// Makes sure a rectangle is valid (apparently some code does not like negative coordinates for example).
91 static tools::Rectangle SanitizedRectangle(tools::Long nLeft, tools::Long nTop, tools::Long nWidth, tools::Long nHeight);
92 static tools::Rectangle SanitizedRectangle(const tools::Rectangle& rect);
95 /// One instance of this per view, handles flushing callbacks
96 class DESKTOP_DLLPUBLIC CallbackFlushHandler final : public Idle, public SfxLokCallbackInterface
98 public:
99 explicit CallbackFlushHandler(LibreOfficeKitDocument* pDocument, LibreOfficeKitCallback pCallback, void* pData);
100 virtual ~CallbackFlushHandler() override;
101 virtual void Invoke() override;
102 // TODO This should be dropped and the binary libreOfficeKitViewCallback() variants should be called?
103 void queue(const int type, const char* data);
105 /// Disables callbacks on this handler. Must match with identical count
106 /// of enableCallbacks. Used during painting and changing views.
107 void disableCallbacks() { ++m_nDisableCallbacks; }
108 /// Enables callbacks on this handler. Must match with identical count
109 /// of disableCallbacks. Used during painting and changing views.
110 void enableCallbacks() { --m_nDisableCallbacks; }
111 /// Returns true iff callbacks are disabled.
112 bool callbacksDisabled() const { return m_nDisableCallbacks != 0; }
114 void addViewStates(int viewId);
115 void removeViewStates(int viewId);
117 void setViewId( int viewId ) { m_viewId = viewId; }
119 // SfxLockCallbackInterface
120 virtual void libreOfficeKitViewCallback(int nType, const char* pPayload) override;
121 virtual void libreOfficeKitViewCallbackWithViewId(int nType, const char* pPayload, int nViewId) override;
122 virtual void libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle* pRect, int nPart, int nMode) override;
123 virtual void libreOfficeKitViewUpdatedCallback(int nType) override;
124 virtual void libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) override;
125 virtual void libreOfficeKitViewAddPendingInvalidateTiles() override;
126 virtual void dumpState(rtl::OStringBuffer &rState) override;
128 private:
129 struct CallbackData
131 CallbackData(const char* payload)
132 : PayloadString(payload ? payload : "(nil)")
136 CallbackData(const char* payload, int viewId)
137 : PayloadString(payload ? payload : "(nil)")
138 , PayloadObject(viewId)
142 CallbackData(const tools::Rectangle* pRect, int viewId)
143 : PayloadObject(RectangleAndPart(pRect, viewId, 0))
144 { // PayloadString will be done on demand
147 CallbackData(const tools::Rectangle* pRect, int part, int mode)
148 : PayloadObject(RectangleAndPart(pRect, part, mode))
149 { // PayloadString will be done on demand
152 const std::string& getPayload() const;
153 /// Update a RectangleAndPart object and update PayloadString if necessary.
154 void updateRectangleAndPart(const RectangleAndPart& rRectAndPart);
155 /// Return the parsed RectangleAndPart instance.
156 const RectangleAndPart& getRectangleAndPart() const;
157 /// Parse and set the JSON object and return it. Clobbers PayloadString.
158 boost::property_tree::ptree& setJson(const std::string& payload);
159 /// Set a Json object and update PayloadString.
160 void setJson(const boost::property_tree::ptree& rTree);
161 /// Return the parsed JSON instance.
162 const boost::property_tree::ptree& getJson() const;
164 int getViewId() const;
166 bool isEmpty() const
168 return PayloadString.empty() && PayloadObject.which() == 0;
170 void clear()
172 PayloadString.clear();
173 PayloadObject = boost::blank();
176 /// Validate that the payload and parsed object match.
177 bool validate() const;
179 /// Returns true iff there is cached data.
180 bool isCached() const { return PayloadObject.which() != 0; }
182 private:
183 mutable std::string PayloadString;
185 /// The parsed payload cache. Update validate() when changing this.
186 mutable boost::variant<boost::blank, RectangleAndPart, boost::property_tree::ptree, int> PayloadObject;
189 typedef std::vector<int> queue_type1;
190 typedef std::vector<CallbackData> queue_type2;
192 void startTimer();
193 bool removeAll(int type);
194 bool removeAll(int type, const std::function<bool (const CallbackData&)>& rTestFunc);
195 bool processInvalidateTilesEvent(int type, CallbackData& aCallbackData);
196 bool processWindowEvent(int type, CallbackData& aCallbackData);
197 queue_type2::iterator toQueue2(queue_type1::iterator);
198 queue_type2::reverse_iterator toQueue2(queue_type1::reverse_iterator);
199 void queue(const int type, CallbackData& data);
200 void enqueueUpdatedTypes();
201 void enqueueUpdatedType( int type, const SfxViewShell* sourceViewShell, int viewId );
203 /** we frequently want to scan the queue, and mostly when we do so, we only care about the element type
204 so we split the queue in 2 to make the scanning cache friendly. */
205 queue_type1 m_queue1;
206 queue_type2 m_queue2;
207 std::map<int, std::string> m_states;
208 std::unordered_map<std::string, std::string> m_lastStateChange;
209 std::unordered_map<int, std::unordered_map<int, std::string>> m_viewStates;
211 // For some types only the last message matters (see isUpdatedType()) or only the last message
212 // per each viewId value matters (see isUpdatedTypePerViewId()), so instead of using push model
213 // where we'd get flooded by repeated messages (which might be costly to generate and process),
214 // the preferred way is that libreOfficeKitViewUpdatedCallback()
215 // or libreOfficeKitViewUpdatedCallbackPerViewId() get called to notify about such a message being
216 // needed, and we'll set a flag here to fetch the actual message before flushing.
217 void setUpdatedType( int nType, bool value );
218 void setUpdatedTypePerViewId( int nType, int nViewId, int nSourceViewId, bool value );
219 void resetUpdatedType( int nType);
220 void resetUpdatedTypePerViewId( int nType, int nViewId );
221 std::vector<bool> m_updatedTypes; // index is type, value is if set
222 struct PerViewIdData
224 bool set = false; // value is if set
225 int sourceViewId;
227 // Flat_map is used in preference to unordered_map because the map is accessed very often.
228 boost::container::flat_map<int, std::vector<PerViewIdData>> m_updatedTypesPerViewId; // key is view, index is type
230 LibreOfficeKitDocument* m_pDocument;
231 int m_viewId = -1; // view id of the associated SfxViewShell
232 LibreOfficeKitCallback m_pCallback;
233 void *m_pData;
234 int m_nDisableCallbacks;
235 std::recursive_mutex m_mutex;
236 class TimeoutIdle : public Timer
238 public:
239 TimeoutIdle( CallbackFlushHandler* handler );
240 virtual void Invoke() override;
241 private:
242 CallbackFlushHandler* mHandler;
244 TimeoutIdle m_TimeoutIdle;
247 struct DESKTOP_DLLPUBLIC LibLODocument_Impl : public _LibreOfficeKitDocument
249 css::uno::Reference<css::lang::XComponent> mxComponent;
250 std::shared_ptr< LibreOfficeKitDocumentClass > m_pDocumentClass;
251 std::map<size_t, std::shared_ptr<CallbackFlushHandler>> mpCallbackFlushHandlers;
252 const int mnDocumentId;
253 std::set<OUString> maFontsMissing;
255 explicit LibLODocument_Impl(const css::uno::Reference<css::lang::XComponent>& xComponent,
256 int nDocumentId);
257 ~LibLODocument_Impl();
260 struct DESKTOP_DLLPUBLIC LibLibreOffice_Impl : public _LibreOfficeKit
262 OUString maLastExceptionMsg;
263 std::shared_ptr< LibreOfficeKitClass > m_pOfficeClass;
264 oslThread maThread;
265 LibreOfficeKitCallback mpCallback;
266 void *mpCallbackData;
267 int64_t mOptionalFeatures;
268 std::map<OString, rtl::Reference<LOKInteractionHandler>> mInteractionMap;
270 LibLibreOffice_Impl();
271 ~LibLibreOffice_Impl();
273 bool hasOptionalFeature(LibreOfficeKitOptionalFeatures const feature)
275 return (mOptionalFeatures & feature) != 0;
278 void dumpState(rtl::OStringBuffer &aState);
281 /// Helper function to extract the value from parameters delimited by
282 /// comma, like: Name1=Value1,Name2=Value2,Name3=Value3.
283 /// @param rOptions When extracted, the Param=Value is removed from it.
284 DESKTOP_DLLPUBLIC OUString extractParameter(OUString& aOptions, std::u16string_view rName);
286 /// Helper function to convert JSON to a vector of PropertyValues.
287 /// Public to be unit-test-able.
288 DESKTOP_DLLPUBLIC std::vector<com::sun::star::beans::PropertyValue> jsonToPropertyValuesVector(const char* pJSON);
291 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */