Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 113, column 13
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name lokhelper.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SFX2_DLLIMPLEMENTATION -D ENABLE_CUPS -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/liborcus/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/liborcus/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sfx2/inc -I /home/maarten/src/libreoffice/core/sfx2/source/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sfx2/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx

/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx

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#include <sfx2/lokhelper.hxx>
11
12#include <com/sun/star/frame/Desktop.hpp>
13
14#include <comphelper/processfactory.hxx>
15#include <rtl/strbuf.hxx>
16#include <rtl/ustrbuf.hxx>
17#include <vcl/lok.hxx>
18#include <vcl/svapp.hxx>
19#include <vcl/commandevent.hxx>
20#include <sal/log.hxx>
21#include <sfx2/app.hxx>
22#include <sfx2/msg.hxx>
23#include <sfx2/viewsh.hxx>
24#include <sfx2/request.hxx>
25#include <sfx2/sfxsids.hrc>
26#include <sfx2/viewfrm.hxx>
27#include <LibreOfficeKit/LibreOfficeKitEnums.h>
28#include <comphelper/lok.hxx>
29#include <editeng/outliner.hxx>
30#include <sfx2/msgpool.hxx>
31
32#include <shellimpl.hxx>
33
34#include <boost/property_tree/json_parser.hpp>
35
36using namespace com::sun::star;
37
38namespace {
39/// Used to disable callbacks.
40/// Needed to avoid recursion when switching views,
41/// which can cause clients to invoke LOKit API and
42/// implicitly set the view, which might cause an
43/// infinite recursion if not detected and prevented.
44class DisableCallbacks
45{
46public:
47 DisableCallbacks()
48 {
49 assert(m_nDisabled >= 0 && "Expected non-negative DisabledCallbacks state when disabling.")(static_cast <bool> (m_nDisabled >= 0 && "Expected non-negative DisabledCallbacks state when disabling."
) ? void (0) : __assert_fail ("m_nDisabled >= 0 && \"Expected non-negative DisabledCallbacks state when disabling.\""
, "/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
, 49, __extension__ __PRETTY_FUNCTION__))
;
50 ++m_nDisabled;
51 }
52
53 ~DisableCallbacks()
54 {
55 assert(m_nDisabled > 0 && "Expected positive DisabledCallbacks state when re-enabling.")(static_cast <bool> (m_nDisabled > 0 && "Expected positive DisabledCallbacks state when re-enabling."
) ? void (0) : __assert_fail ("m_nDisabled > 0 && \"Expected positive DisabledCallbacks state when re-enabling.\""
, "/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
, 55, __extension__ __PRETTY_FUNCTION__))
;
56 --m_nDisabled;
57 }
58
59 static bool disabled() { return m_nDisabled != 0; }
60
61private:
62 static int m_nDisabled;
63};
64
65int DisableCallbacks::m_nDisabled = 0;
66}
67
68namespace
69{
70LanguageTag g_defaultLanguageTag("en-US", true);
71LOKDeviceFormFactor g_deviceFormFactor = LOKDeviceFormFactor::UNKNOWN;
72}
73
74int SfxLokHelper::createView()
75{
76 SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst();
77 if (!pViewFrame)
78 return -1;
79 SfxViewShell* pPrevViewShell = SfxViewShell::Current();
80 ViewShellDocId nId;
81 if (pPrevViewShell)
82 nId = pPrevViewShell->GetDocId();
83 SfxRequest aRequest(pViewFrame, SID_NEWWINDOW(5000 + 620));
84 pViewFrame->ExecView_Impl(aRequest);
85 SfxViewShell* pViewShell = SfxViewShell::Current();
86 if (!pViewShell)
87 return -1;
88 if (pPrevViewShell)
89 pViewShell->SetDocId(nId);
90 return static_cast<sal_Int32>(pViewShell->GetViewShellId());
91}
92
93void SfxLokHelper::destroyView(int nId)
94{
95 SfxApplication* pApp = SfxApplication::Get();
96 if (!pApp)
97 return;
98
99 int nViewShellId = nId;
100 SfxViewShellArr_Impl& rViewArr = pApp->GetViewShells_Impl();
101
102 for (SfxViewShell* pViewShell : rViewArr)
103 {
104 if (static_cast<sal_Int32>(pViewShell->GetViewShellId()) == nViewShellId)
105 {
106 SfxViewFrame* pViewFrame = pViewShell->GetViewFrame();
107 SfxRequest aRequest(pViewFrame, SID_CLOSEWIN(5000 + 621));
108 pViewFrame->Exec_Impl(aRequest);
109 break;
110 }
111 }
112}
113
114void SfxLokHelper::setView(int nId)
115{
116 SfxApplication* pApp = SfxApplication::Get();
117 if (!pApp)
118 return;
119
120 int nViewShellId = nId;
121 SfxViewShellArr_Impl& rViewArr = pApp->GetViewShells_Impl();
122
123 for (SfxViewShell* pViewShell : rViewArr)
124 {
125 if (static_cast<sal_Int32>(pViewShell->GetViewShellId()) == nViewShellId)
126 {
127 DisableCallbacks dc;
128
129 // update the current LOK language and locale for the dialog tunneling
130 comphelper::LibreOfficeKit::setLanguageTag(pViewShell->GetLOKLanguageTag());
131 comphelper::LibreOfficeKit::setLocale(pViewShell->GetLOKLocale());
132
133 if (pViewShell == SfxViewShell::Current())
134 return;
135
136 SfxViewFrame* pViewFrame = pViewShell->GetViewFrame();
137 pViewFrame->MakeActive_Impl(false);
138
139 // Make comphelper::dispatchCommand() find the correct frame.
140 uno::Reference<frame::XFrame> xFrame = pViewFrame->GetFrame().GetFrameInterface();
141 uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(comphelper::getProcessComponentContext());
142 xDesktop->setActiveFrame(xFrame);
143 return;
144 }
145 }
146
147}
148
149int SfxLokHelper::getView(SfxViewShell* pViewShell)
150{
151 if (!pViewShell)
152 pViewShell = SfxViewShell::Current();
153 // Still no valid view shell? Then no idea.
154 if (!pViewShell)
155 return -1;
156
157 return static_cast<sal_Int32>(pViewShell->GetViewShellId());
158}
159
160std::size_t SfxLokHelper::getViewsCount()
161{
162 SfxApplication* pApp = SfxApplication::Get();
163 if (!pApp)
164 return 0;
165
166 const SfxViewShell* const pCurrentViewShell = SfxViewShell::Current();
167 const ViewShellDocId nCurrentDocId = pCurrentViewShell ? pCurrentViewShell->GetDocId() : ViewShellDocId(-1);
168 std::size_t n = 0;
169 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
170 while (pViewShell)
171 {
172 if (pViewShell->GetDocId() == nCurrentDocId)
173 n++;
174 pViewShell = SfxViewShell::GetNext(*pViewShell);
175 }
176 return n;
177}
178
179bool SfxLokHelper::getViewIds(int* pArray, size_t nSize)
180{
181 SfxApplication* pApp = SfxApplication::Get();
182 if (!pApp)
183 return false;
184
185 const SfxViewShell* const pCurrentViewShell = SfxViewShell::Current();
186 const ViewShellDocId nCurrentDocId = pCurrentViewShell ? pCurrentViewShell->GetDocId() : ViewShellDocId(-1);
187 std::size_t n = 0;
188 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
189 while (pViewShell)
190 {
191 if (n == nSize)
192 return false;
193 if (pViewShell->GetDocId() == nCurrentDocId)
194 {
195 pArray[n] = static_cast<sal_Int32>(pViewShell->GetViewShellId());
196 n++;
197 }
198 pViewShell = SfxViewShell::GetNext(*pViewShell);
199 }
200 return true;
201}
202
203void SfxLokHelper::setDocumentIdOfView(int nId)
204{
205 SfxViewShell* pViewShell = SfxViewShell::Current();
206 assert(pViewShell)(static_cast <bool> (pViewShell) ? void (0) : __assert_fail
("pViewShell", "/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
, 206, __extension__ __PRETTY_FUNCTION__))
;
207 if (!pViewShell)
208 return;
209 pViewShell->SetDocId(ViewShellDocId(nId));
210}
211
212int SfxLokHelper::getDocumentIdOfView(int nViewId)
213{
214 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
215 while (pViewShell)
216 {
217 if (pViewShell->GetViewShellId() == ViewShellId(nViewId))
218 return static_cast<int>(pViewShell->GetDocId());
219 pViewShell = SfxViewShell::GetNext(*pViewShell);
220 }
221 return -1;
222}
223
224LanguageTag SfxLokHelper::getDefaultLanguage()
225{
226 return g_defaultLanguageTag;
227}
228
229void SfxLokHelper::setDefaultLanguage(const OUString& rBcp47LanguageTag)
230{
231 g_defaultLanguageTag = LanguageTag(rBcp47LanguageTag, true);
232}
233
234void SfxLokHelper::setViewLanguage(int nId, const OUString& rBcp47LanguageTag)
235{
236 SfxViewShellArr_Impl& rViewArr = SfxGetpApp()->GetViewShells_Impl();
237
238 for (SfxViewShell* pViewShell : rViewArr)
239 {
240 if (pViewShell->GetViewShellId() == ViewShellId(nId))
241 {
242 pViewShell->SetLOKLanguageTag(rBcp47LanguageTag);
243 return;
244 }
245 }
246}
247
248void SfxLokHelper::setViewLocale(int nId, const OUString& rBcp47LanguageTag)
249{
250 SfxViewShellArr_Impl& rViewArr = SfxGetpApp()->GetViewShells_Impl();
251
252 for (SfxViewShell* pViewShell : rViewArr)
253 {
254 if (pViewShell->GetViewShellId() == ViewShellId(nId))
255 {
256 pViewShell->SetLOKLocale(rBcp47LanguageTag);
257 return;
258 }
259 }
260}
261
262LOKDeviceFormFactor SfxLokHelper::getDeviceFormFactor()
263{
264 return g_deviceFormFactor;
265}
266
267void SfxLokHelper::setDeviceFormFactor(const OUString& rDeviceFormFactor)
268{
269 if (rDeviceFormFactor == "desktop")
270 g_deviceFormFactor = LOKDeviceFormFactor::DESKTOP;
271 else if (rDeviceFormFactor == "tablet")
272 g_deviceFormFactor = LOKDeviceFormFactor::TABLET;
273 else if (rDeviceFormFactor == "mobile")
274 g_deviceFormFactor = LOKDeviceFormFactor::MOBILE;
275 else
276 g_deviceFormFactor = LOKDeviceFormFactor::UNKNOWN;
277}
278
279static OString lcl_escapeQuotes(const OString &rStr)
280{
281 if (rStr.getLength() < 1)
282 return rStr;
283 // FIXME: need an optimized 'escape' method for O[U]String.
284 OStringBuffer aBuf(rStr.getLength() + 8);
285 for (sal_Int32 i = 0; i < rStr.getLength(); ++i)
286 {
287 if (rStr[i] == '"' || rStr[i] == '\\')
288 aBuf.append('\\');
289 aBuf.append(rStr[i]);
290 }
291 return aBuf.makeStringAndClear();
292}
293
294static OString lcl_generateJSON(SfxViewShell* pView, const boost::property_tree::ptree& rTree)
295{
296 boost::property_tree::ptree aMessageProps = rTree;
297 aMessageProps.put("viewId", SfxLokHelper::getView(pView));
298 aMessageProps.put("part", pView->getPart());
299 std::stringstream aStream;
300 boost::property_tree::write_json(aStream, aMessageProps, false /* pretty */);
301 return OString(aStream.str().c_str()).trim();
302}
303
304void SfxLokHelper::notifyOtherView(SfxViewShell* pThisView, SfxViewShell const* pOtherView, int nType, const OString& rKey, const OString& rPayload)
305{
306 if (DisableCallbacks::disabled())
307 return;
308
309 OString aPayload = OStringLiteral("{ \"viewId\": \"") + OString::number(SfxLokHelper::getView(pThisView)) +
310 "\", \"part\": \"" + OString::number(pThisView->getPart()) +
311 "\", \"" + rKey + "\": \"" + lcl_escapeQuotes(rPayload) + "\" }";
312
313 pOtherView->libreOfficeKitViewCallback(nType, aPayload.getStr());
314}
315
316void SfxLokHelper::notifyOtherView(SfxViewShell* pThisView, SfxViewShell const* pOtherView, int nType,
317 const boost::property_tree::ptree& rTree)
318{
319 if (DisableCallbacks::disabled())
320 return;
321
322 pOtherView->libreOfficeKitViewCallback(nType, lcl_generateJSON(pThisView, rTree).getStr());
323}
324
325void SfxLokHelper::notifyOtherViews(SfxViewShell* pThisView, int nType, const OString& rKey, const OString& rPayload)
326{
327 if (DisableCallbacks::disabled())
328 return;
329
330 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
331 while (pViewShell)
332 {
333 if (pViewShell != pThisView && pViewShell->GetDocId() == pThisView-> GetDocId())
334 notifyOtherView(pThisView, pViewShell, nType, rKey, rPayload);
335
336 pViewShell = SfxViewShell::GetNext(*pViewShell);
337 }
338}
339
340void SfxLokHelper::notifyOtherViews(SfxViewShell* pThisView, int nType, const boost::property_tree::ptree& rTree)
341{
342 if (SfxLokHelper::getViewsCount() <= 1 || DisableCallbacks::disabled())
343 return;
344
345 // Payload is only dependent on pThisView.
346 OString aPayload = lcl_generateJSON(pThisView, rTree);
347
348 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
349 while (pViewShell)
350 {
351 if (pViewShell != pThisView)
352 pViewShell->libreOfficeKitViewCallback(nType, aPayload.getStr());
353
354 pViewShell = SfxViewShell::GetNext(*pViewShell);
355 }
356}
357
358namespace {
359 OUString lcl_getNameForSlot(const SfxViewShell* pShell, sal_uInt16 nWhich)
360 {
361 if (pShell && pShell->GetFrame())
362 {
363 const SfxSlot* pSlot = SfxSlotPool::GetSlotPool(pShell->GetFrame()).GetSlot(nWhich);
364 if (pSlot)
365 {
366 const char* pName = pSlot->GetUnoName();
367 if (pName)
368 {
369 return ".uno:" + OStringToOUString(pName, RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11)));
370 }
371 }
372 }
373
374 return "";
375 }
376}
377
378void SfxLokHelper::sendUnoStatus(const SfxViewShell* pShell, const SfxPoolItem* pItem)
379{
380 if (!pShell || !pItem || pItem == INVALID_POOL_ITEMreinterpret_cast<SfxPoolItem*>(-1) || DisableCallbacks::disabled())
381 return;
382
383 boost::property_tree::ptree aItem = pItem->dumpAsJSON();
384
385 if (aItem.count("state"))
386 {
387 OUString sCommand = lcl_getNameForSlot(pShell, pItem->Which());
388 if (!sCommand.isEmpty())
389 aItem.put("commandName", sCommand);
390
391 std::stringstream aStream;
392 boost::property_tree::write_json(aStream, aItem);
393 pShell->libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, aStream.str().c_str());
394 }
395}
396
397void SfxLokHelper::notifyWindow(const SfxViewShell* pThisView,
398 vcl::LOKWindowId nLOKWindowId,
399 const OUString& rAction,
400 const std::vector<vcl::LOKPayloadItem>& rPayload)
401{
402 assert(pThisView)(static_cast <bool> (pThisView) ? void (0) : __assert_fail
("pThisView", "/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
, 402, __extension__ __PRETTY_FUNCTION__))
;
403
404 if (SfxLokHelper::getViewsCount() <= 0 || nLOKWindowId == 0 || DisableCallbacks::disabled())
405 return;
406
407 OStringBuffer aPayload;
408 aPayload.append("{ \"id\": \"").append(OString::number(nLOKWindowId)).append("\"");
409 aPayload.append(", \"action\": \"").append(OUStringToOString(rAction, RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)))).append("\"");
410
411 for (const auto& rItem: rPayload)
412 {
413 if (!rItem.first.isEmpty() && !rItem.second.isEmpty())
414 {
415 aPayload.append(", \"").append(rItem.first).append("\": \"")
416 .append(rItem.second).append("\"");
417 }
418 }
419 aPayload.append("}");
420
421 auto s = aPayload.makeStringAndClear();
422 pThisView->libreOfficeKitViewCallback(LOK_CALLBACK_WINDOW, s.getStr());
423}
424
425void SfxLokHelper::notifyInvalidation(SfxViewShell const* pThisView, const OString& rPayload)
426{
427 OStringBuffer aBuf(32);
428
429 if (DisableCallbacks::disabled())
430 return;
431
432 aBuf.append(rPayload);
433 if (comphelper::LibreOfficeKit::isPartInInvalidation())
434 {
435 aBuf.append(", ");
436 aBuf.append(static_cast<sal_Int32>(pThisView->getPart()));
437 }
438 pThisView->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_TILES, aBuf.makeStringAndClear().getStr());
439}
440
441void SfxLokHelper::notifyDocumentSizeChanged(SfxViewShell const* pThisView, const OString& rPayload, vcl::ITiledRenderable* pDoc, bool bInvalidateAll)
442{
443 if (!pDoc || pDoc->isDisposed() || !comphelper::LibreOfficeKit::isActive() || DisableCallbacks::disabled())
444 return;
445
446 if (bInvalidateAll)
447 {
448 for (int i = 0; i < pDoc->getParts(); ++i)
449 {
450 tools::Rectangle aRectangle(0, 0, 1000000000, 1000000000);
451 OString sPayload = aRectangle.toString() + ", " + OString::number(i);
452 pThisView->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_TILES, sPayload.getStr());
453 }
454 }
455 pThisView->libreOfficeKitViewCallback(LOK_CALLBACK_DOCUMENT_SIZE_CHANGED, rPayload.getStr());
456}
457
458void SfxLokHelper::notifyDocumentSizeChangedAllViews(vcl::ITiledRenderable* pDoc, bool bInvalidateAll)
459{
460 if (!comphelper::LibreOfficeKit::isActive() || DisableCallbacks::disabled())
461 return;
462
463 // FIXME: Do we know whether it is the views for the document that is in the "current" view that has changed?
464 const SfxViewShell* const pCurrentViewShell = SfxViewShell::Current();
465 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
466 while (pViewShell)
467 {
468 // FIXME: What if SfxViewShell::Current() returned null?
469 // Should we then do this for all views of all open documents
470 // or not?
471 if (pCurrentViewShell == nullptr || pViewShell->GetDocId() == pCurrentViewShell-> GetDocId())
472 SfxLokHelper::notifyDocumentSizeChanged(pViewShell, "", pDoc, bInvalidateAll);
473 pViewShell = SfxViewShell::GetNext(*pViewShell);
474 }
475}
476
477void SfxLokHelper::notifyVisCursorInvalidation(OutlinerViewShell const* pThisView, const OString& rRectangle, bool bMispelledWord, const OString& rHyperlink)
478{
479 if (DisableCallbacks::disabled())
480 return;
481
482 OString sPayload;
483 if (comphelper::LibreOfficeKit::isViewIdForVisCursorInvalidation())
484 {
485 OString sHyperlink = rHyperlink.isEmpty() ? "{}" : rHyperlink;
486 sPayload = OStringLiteral("{ \"viewId\": \"") + OString::number(SfxLokHelper::getView()) +
487 "\", \"rectangle\": \"" + rRectangle +
488 "\", \"mispelledWord\": \"" + OString::number(bMispelledWord ? 1 : 0) +
489 "\", \"hyperlink\": " + sHyperlink + " }";
490 }
491 else
492 {
493 sPayload = rRectangle;
494 }
495 pThisView->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, sPayload.getStr());
496}
497
498void SfxLokHelper::notifyAllViews(int nType, const OString& rPayload)
499{
500 if (DisableCallbacks::disabled())
501 return;
502
503 const auto payload = rPayload.getStr();
504 const SfxViewShell* const pCurrentViewShell = SfxViewShell::Current();
505 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
506 while (pViewShell)
507 {
508 if (pViewShell->GetDocId() == pCurrentViewShell->GetDocId())
509 pViewShell->libreOfficeKitViewCallback(nType, payload);
510 pViewShell = SfxViewShell::GetNext(*pViewShell);
511 }
512}
513
514void SfxLokHelper::notifyContextChange(SfxViewShell const* pViewShell, const OUString& aApplication, const OUString& aContext)
515{
516 if (DisableCallbacks::disabled())
517 return;
518
519 OString aBuffer =
520 OUStringToOString(aApplication.replace(' ', '_'), RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76))) +
521 " " +
522 OUStringToOString(aContext.replace(' ', '_'), RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)));
523 pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CONTEXT_CHANGED, aBuffer.getStr());
524}
525
526
527namespace
528{
529 struct LOKAsyncEventData
530 {
531 int mnView; // Window is not enough.
532 VclPtr<vcl::Window> mpWindow;
533 VclEventId mnEvent;
534 MouseEvent maMouseEvent;
535 KeyEvent maKeyEvent;
536 OUString maText;
537 };
538
539 void LOKPostAsyncEvent(void* pEv, void*)
540 {
541 LOKAsyncEventData* pLOKEv = static_cast<LOKAsyncEventData*>(pEv);
542 if (pLOKEv->mpWindow->IsDisposed())
25
Assuming the condition is false
26
Taking false branch
543 return;
544
545 int nView = SfxLokHelper::getView(nullptr);
546 if (nView
26.1
'nView' is equal to field 'mnView'
26.1
'nView' is equal to field 'mnView'
26.1
'nView' is equal to field 'mnView'
!= pLOKEv->mnView)
27
Taking false branch
547 {
548 SAL_INFO("sfx.view", "LOK - view mismatch " << nView << " vs. " << pLOKEv->mnView)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sfx.view")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "LOK - view mismatch "
<< nView << " vs. " << pLOKEv->mnView) ==
1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sfx.view"
), ("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "548" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "LOK - view mismatch " << nView <<
" vs. " << pLOKEv->mnView), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "LOK - view mismatch "
<< nView << " vs. " << pLOKEv->mnView; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sfx.view")
, ("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "548" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "LOK - view mismatch " << nView << " vs. "
<< pLOKEv->mnView) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sfx.view"), ("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "548" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "LOK - view mismatch " << nView <<
" vs. " << pLOKEv->mnView), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "LOK - view mismatch "
<< nView << " vs. " << pLOKEv->mnView; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sfx.view")
, ("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "548" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
549 SfxLokHelper::setView(pLOKEv->mnView);
550 }
551
552 if (!pLOKEv->mpWindow->HasChildPathFocus(true))
28
Assuming the condition is false
29
Taking false branch
553 {
554 SAL_INFO("sfx.view", "LOK - focus mismatch, switching focus")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sfx.view")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "LOK - focus mismatch, switching focus"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sfx.view"
), ("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "554" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "LOK - focus mismatch, switching focus"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "LOK - focus mismatch, switching focus"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sfx.view"), ("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "554" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "LOK - focus mismatch, switching focus") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sfx.view"), (
"/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "554" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "LOK - focus mismatch, switching focus"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "LOK - focus mismatch, switching focus"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sfx.view"), ("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "554" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
555 pLOKEv->mpWindow->GrabFocus();
556 }
557
558 VclPtr<vcl::Window> pFocusWindow = pLOKEv->mpWindow->GetFocusedWindow();
559 if (!pFocusWindow)
30
Taking true branch
560 pFocusWindow = pLOKEv->mpWindow;
561
562 switch (pLOKEv->mnEvent)
31
Control jumps to 'case WindowMouseMove:' at line 594
563 {
564 case VclEventId::WindowKeyInput:
565 {
566 sal_uInt16 nRepeat = pLOKEv->maKeyEvent.GetRepeat();
567 KeyEvent singlePress(pLOKEv->maKeyEvent.GetCharCode(),
568 pLOKEv->maKeyEvent.GetKeyCode());
569 for (sal_uInt16 i = 0; i <= nRepeat; ++i)
570 pFocusWindow->KeyInput(singlePress);
571 break;
572 }
573 case VclEventId::WindowKeyUp:
574 pFocusWindow->KeyUp(pLOKEv->maKeyEvent);
575 break;
576 case VclEventId::WindowMouseButtonDown:
577 pLOKEv->mpWindow->LogicMouseButtonDown(pLOKEv->maMouseEvent);
578 // Invoke the context menu
579 if (pLOKEv->maMouseEvent.GetButtons() & MOUSE_RIGHT(sal_uInt16(0x0004)))
580 {
581 const CommandEvent aCEvt(pLOKEv->maMouseEvent.GetPosPixel(), CommandEventId::ContextMenu, true, nullptr);
582 pLOKEv->mpWindow->Command(aCEvt);
583 }
584 break;
585 case VclEventId::WindowMouseButtonUp:
586 pLOKEv->mpWindow->LogicMouseButtonUp(pLOKEv->maMouseEvent);
587
588 // sometimes MouseButtonDown captures mouse and starts tracking, and VCL
589 // will not take care of releasing that with tiled rendering
590 if (pLOKEv->mpWindow->IsTracking())
591 pLOKEv->mpWindow->EndTracking();
592
593 break;
594 case VclEventId::WindowMouseMove:
595 pLOKEv->mpWindow->LogicMouseMove(pLOKEv->maMouseEvent);
596 break;
32
Execution continues on line 606
597 case VclEventId::ExtTextInput:
598 case VclEventId::EndExtTextInput:
599 pLOKEv->mpWindow->PostExtTextInputEvent(pLOKEv->mnEvent, pLOKEv->maText);
600 break;
601 default:
602 assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail (
"false", "/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
, 602, __extension__ __PRETTY_FUNCTION__))
;
603 break;
604 }
605
606 delete pLOKEv;
33
Calling implicit destructor for 'LOKAsyncEventData'
34
Calling implicit destructor for 'VclPtr<vcl::Window>'
35
Calling '~Reference'
42
Returning from '~Reference'
43
Returning from destructor for 'VclPtr<vcl::Window>'
44
Returning from destructor for 'LOKAsyncEventData'
607 }
45
Calling implicit destructor for 'VclPtr<vcl::Window>'
46
Calling '~Reference'
608
609 void postEventAsync(LOKAsyncEventData *pEvent)
610 {
611 if (!pEvent->mpWindow || pEvent->mpWindow->IsDisposed())
18
Assuming the condition is false
19
Taking false branch
612 {
613 SAL_WARN("vcl", "Async event post - but no valid window as destination " << pEvent->mpWindow.get())do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Async event post - but no valid window as destination "
<< pEvent->mpWindow.get()) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "613" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Async event post - but no valid window as destination "
<< pEvent->mpWindow.get()), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "Async event post - but no valid window as destination "
<< pEvent->mpWindow.get(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl"), ("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "613" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Async event post - but no valid window as destination "
<< pEvent->mpWindow.get()) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "613" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Async event post - but no valid window as destination "
<< pEvent->mpWindow.get()), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "Async event post - but no valid window as destination "
<< pEvent->mpWindow.get(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl"), ("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "613" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
614 delete pEvent;
615 return;
616 }
617
618 pEvent->mnView = SfxLokHelper::getView(nullptr);
619 if (vcl::lok::isUnipoll())
20
Assuming the condition is true
21
Taking true branch
620 {
621 if (!Application::IsMainThread())
22
Assuming the condition is false
23
Taking false branch
622 SAL_WARN("lok", "Posting event directly but not called from main thread!")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "lok")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Posting event directly but not called from main thread!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lok"
), ("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "622" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Posting event directly but not called from main thread!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Posting event directly but not called from main thread!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lok"),
("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "622" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Posting event directly but not called from main thread!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lok"
), ("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "622" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Posting event directly but not called from main thread!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Posting event directly but not called from main thread!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lok"),
("/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
":" "622" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
623 LOKPostAsyncEvent(pEvent, nullptr);
24
Calling 'LOKPostAsyncEvent'
624 }
625 else
626 Application::PostUserEvent(Link<void*, void>(pEvent, LOKPostAsyncEvent));
627 }
628}
629
630void SfxLokHelper::postKeyEventAsync(const VclPtr<vcl::Window> &xWindow,
631 int nType, int nCharCode, int nKeyCode, int nRepeat)
632{
633 LOKAsyncEventData* pLOKEv = new LOKAsyncEventData;
634 switch (nType)
635 {
636 case LOK_KEYEVENT_KEYINPUT:
637 pLOKEv->mnEvent = VclEventId::WindowKeyInput;
638 break;
639 case LOK_KEYEVENT_KEYUP:
640 pLOKEv->mnEvent = VclEventId::WindowKeyUp;
641 break;
642 default:
643 assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail (
"false", "/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
, 643, __extension__ __PRETTY_FUNCTION__))
;
644 }
645 pLOKEv->maKeyEvent = KeyEvent(nCharCode, nKeyCode, nRepeat);
646 pLOKEv->mpWindow = xWindow;
647 postEventAsync(pLOKEv);
648}
649
650void SfxLokHelper::postExtTextEventAsync(const VclPtr<vcl::Window> &xWindow,
651 int nType, const OUString &rText)
652{
653 LOKAsyncEventData* pLOKEv = new LOKAsyncEventData;
654 switch (nType)
655 {
656 case LOK_EXT_TEXTINPUT:
657 pLOKEv->mnEvent = VclEventId::ExtTextInput;
658 pLOKEv->maText = rText;
659 break;
660 case LOK_EXT_TEXTINPUT_END:
661 pLOKEv->mnEvent = VclEventId::EndExtTextInput;
662 pLOKEv->maText = "";
663 break;
664 default:
665 assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail (
"false", "/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
, 665, __extension__ __PRETTY_FUNCTION__))
;
666 }
667 pLOKEv->mpWindow = xWindow;
668 postEventAsync(pLOKEv);
669}
670
671void SfxLokHelper::postMouseEventAsync(const VclPtr<vcl::Window> &xWindow, LokMouseEventData const & rLokMouseEventData)
672{
673 LOKAsyncEventData* pLOKEv = new LOKAsyncEventData;
674 switch (rLokMouseEventData.mnType)
1
Control jumps to 'case LOK_MOUSEEVENT_MOUSEMOVE:' at line 682
675 {
676 case LOK_MOUSEEVENT_MOUSEBUTTONDOWN:
677 pLOKEv->mnEvent = VclEventId::WindowMouseButtonDown;
678 break;
679 case LOK_MOUSEEVENT_MOUSEBUTTONUP:
680 pLOKEv->mnEvent = VclEventId::WindowMouseButtonUp;
681 break;
682 case LOK_MOUSEEVENT_MOUSEMOVE:
683 pLOKEv->mnEvent = VclEventId::WindowMouseMove;
684 break;
2
Execution continues on line 690
685 default:
686 assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail (
"false", "/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
, 686, __extension__ __PRETTY_FUNCTION__))
;
687 }
688
689 // no reason - just always true so far.
690 assert (rLokMouseEventData.meModifiers == MouseEventModifiers::SIMPLECLICK)(static_cast <bool> (rLokMouseEventData.meModifiers == MouseEventModifiers
::SIMPLECLICK) ? void (0) : __assert_fail ("rLokMouseEventData.meModifiers == MouseEventModifiers::SIMPLECLICK"
, "/home/maarten/src/libreoffice/core/sfx2/source/view/lokhelper.cxx"
, 690, __extension__ __PRETTY_FUNCTION__))
;
3
Assuming field 'meModifiers' is equal to SIMPLECLICK
4
'?' condition is true
691
692 pLOKEv->maMouseEvent = MouseEvent(rLokMouseEventData.maPosition, rLokMouseEventData.mnCount,
693 rLokMouseEventData.meModifiers, rLokMouseEventData.mnButtons,
694 rLokMouseEventData.mnModifier);
695 if (rLokMouseEventData.maLogicPosition)
5
Assuming the condition is false
6
Taking false branch
696 {
697 pLOKEv->maMouseEvent.setLogicPosition(*rLokMouseEventData.maLogicPosition);
698 }
699 pLOKEv->mpWindow = xWindow;
7
Calling implicit copy assignment operator for 'VclPtr<vcl::Window>'
8
Calling copy assignment operator for 'Reference<vcl::Window>'
15
Returning from copy assignment operator for 'Reference<vcl::Window>'
16
Returning from copy assignment operator for 'VclPtr<vcl::Window>'
700 postEventAsync(pLOKEv);
17
Calling 'postEventAsync'
701}
702
703/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

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#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody
35.1
Field 'm_pBody' is non-null
46.1
Field 'm_pBody' is non-null
35.1
Field 'm_pBody' is non-null
46.1
Field 'm_pBody' is non-null
35.1
Field 'm_pBody' is non-null
46.1
Field 'm_pBody' is non-null
)
36
Taking true branch
47
Taking true branch
113 m_pBody->release();
37
Calling 'VclReferenceBase::release'
41
Returning; memory was released
48
Use of memory after it is freed
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
10
Assuming 'pBody' is non-null
11
Taking true branch
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
12
Assuming 'pOld' is null
13
Taking false branch
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
9
Calling 'Reference::set'
14
Returning from 'Reference::set'
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody)
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

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#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
38
Assuming the condition is true
39
Taking true branch
40 delete this;
40
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif