Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
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 glbltree.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 SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/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/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/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/sw/source/uibase/utlui/glbltree.cxx

/home/maarten/src/libreoffice/core/sw/source/uibase/utlui/glbltree.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 * 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 <o3tl/safeint.hxx>
21#include <svl/stritem.hxx>
22#include <sfx2/fcontnr.hxx>
23#include <sfx2/linkmgr.hxx>
24#include <sfx2/dispatch.hxx>
25#include <sfx2/viewfrm.hxx>
26#include <sfx2/docfile.hxx>
27#include <sfx2/docfilt.hxx>
28#include <vcl/commandevent.hxx>
29#include <vcl/event.hxx>
30#include <vcl/help.hxx>
31#include <sot/filelist.hxx>
32#include <svl/eitem.hxx>
33#include <vcl/graphicfilter.hxx>
34#include <vcl/settings.hxx>
35
36#include <sfx2/docinsert.hxx>
37#include <sfx2/filedlghelper.hxx>
38
39#include <wrtsh.hxx>
40#include <view.hxx>
41#include <docsh.hxx>
42#include <edglbldc.hxx>
43#include <section.hxx>
44#include <tox.hxx>
45#include <navipi.hxx>
46#include <edtwin.hxx>
47#include <toxmgr.hxx>
48
49#include <cmdid.h>
50#include <helpids.h>
51#include <strings.hrc>
52#include <bitmaps.hlst>
53#include <swabstdlg.hxx>
54#include <memory>
55
56using namespace ::com::sun::star::uno;
57
58#define GLOBAL_UPDATE_TIMEOUT2000 2000
59
60const SfxObjectShell* SwGlobalTree::pShowShell = nullptr;
61
62namespace {
63
64class SwGlobalFrameListener_Impl : public SfxListener
65{
66 bool bValid;
67public:
68 explicit SwGlobalFrameListener_Impl(SfxViewFrame& rFrame)
69 : bValid(true)
70 {
71 StartListening(rFrame);
72 }
73
74 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
75
76 bool IsValid() const {return bValid;}
77};
78
79}
80
81void SwGlobalFrameListener_Impl::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
82{
83 if( rHint.GetId() == SfxHintId::Dying)
84 bValid = false;
85}
86
87namespace {
88
89enum GLOBAL_CONTEXT_IDX
90{
91 IDX_STR_UPDATE = 0,
92 IDX_STR_EDIT_CONTENT = 1,
93 IDX_STR_EDIT_INSERT = 2,
94 IDX_STR_INDEX = 3,
95 IDX_STR_FILE = 4,
96 IDX_STR_NEW_FILE = 5,
97 IDX_STR_INSERT_TEXT = 6,
98 IDX_STR_DELETE = 7,
99 IDX_STR_UPDATE_SEL = 8,
100 IDX_STR_UPDATE_INDEX = 9,
101 IDX_STR_UPDATE_LINK = 10,
102 IDX_STR_UPDATE_ALL = 11,
103 IDX_STR_BROKEN_LINK = 12,
104 IDX_STR_EDIT_LINK = 13
105};
106
107}
108
109static const char* GLOBAL_CONTEXT_ARY[] =
110{
111 STR_UPDATEreinterpret_cast<char const *>("STR_UPDATE" "\004" u8"~Update"
)
,
112 STR_EDIT_CONTENTreinterpret_cast<char const *>("STR_EDIT_CONTENT" "\004"
u8"Edit")
,
113 STR_EDIT_INSERTreinterpret_cast<char const *>("STR_EDIT_INSERT" "\004"
u8"Insert")
,
114 STR_INDEXreinterpret_cast<char const *>("STR_INDEX" "\004" u8"~Index"
)
,
115 STR_FILEreinterpret_cast<char const *>("STR_FILE" "\004" u8"File"
)
,
116 STR_NEW_FILEreinterpret_cast<char const *>("STR_NEW_FILE" "\004" u8"New Document"
)
,
117 STR_INSERT_TEXTreinterpret_cast<char const *>("STR_INSERT_TEXT" "\004"
u8"Text")
,
118 STR_DELETEreinterpret_cast<char const *>("STR_DELETE" "\004" u8"Delete"
)
,
119 STR_UPDATE_SELreinterpret_cast<char const *>("STR_UPDATE_SEL" "\004" u8"Selection"
)
,
120 STR_UPDATE_INDEXreinterpret_cast<char const *>("STR_UPDATE_INDEX" "\004"
u8"Indexes")
,
121 STR_UPDATE_LINKreinterpret_cast<char const *>("STR_UPDATE_LINK" "\004"
u8"Links")
,
122 STR_UPDATE_ALLreinterpret_cast<char const *>("STR_UPDATE_ALL" "\004" u8"All"
)
,
123 STR_BROKEN_LINKreinterpret_cast<char const *>("STR_BROKEN_LINK" "\004"
u8"File not found: ")
,
124 STR_EDIT_LINKreinterpret_cast<char const *>("STR_EDIT_LINK" "\004" u8"Edit link"
)
125};
126
127SwGlobalTree::SwGlobalTree(std::unique_ptr<weld::TreeView> xTreeView, SwNavigationPI* pDialog)
128 : m_xTreeView(std::move(xTreeView))
129 , m_aDropTargetHelper(*this)
130 , m_xDialog(pDialog)
131 , m_pActiveShell(nullptr)
132{
133 Size aSize(m_xDialog->LogicToPixel(Size(110, 112), MapMode(MapUnit::MapAppFont)));;
134 m_xTreeView->set_size_request(aSize.Width(), aSize.Height());
135
136 m_aUpdateTimer.SetTimeout(GLOBAL_UPDATE_TIMEOUT2000);
137 m_aUpdateTimer.SetInvokeHandler(LINK(this, SwGlobalTree, Timeout)::tools::detail::makeLink( ::tools::detail::castTo<SwGlobalTree
*>(this), &SwGlobalTree::LinkStubTimeout)
);
138 m_aUpdateTimer.Start();
139 for (sal_uInt16 i = 0; i < GLOBAL_CONTEXT_COUNT14; i++)
140 {
141 m_aContextStrings[i] = SwResId(GLOBAL_CONTEXT_ARY[i]);
142 }
143 m_xTreeView->set_help_id(HID_NAVIGATOR_GLOB_TREELIST"SW_HID_NAVIGATOR_GLOB_TREELIST");
144 Select();
145 m_xTreeView->connect_row_activated(LINK(this, SwGlobalTree, DoubleClickHdl)::tools::detail::makeLink( ::tools::detail::castTo<SwGlobalTree
*>(this), &SwGlobalTree::LinkStubDoubleClickHdl)
);
146 m_xTreeView->connect_changed(LINK(this, SwGlobalTree, SelectHdl)::tools::detail::makeLink( ::tools::detail::castTo<SwGlobalTree
*>(this), &SwGlobalTree::LinkStubSelectHdl)
);
147 m_xTreeView->connect_focus_in(LINK(this, SwGlobalTree, FocusInHdl)::tools::detail::makeLink( ::tools::detail::castTo<SwGlobalTree
*>(this), &SwGlobalTree::LinkStubFocusInHdl)
);
148 m_xTreeView->connect_key_press(LINK(this, SwGlobalTree, KeyInputHdl)::tools::detail::makeLink( ::tools::detail::castTo<SwGlobalTree
*>(this), &SwGlobalTree::LinkStubKeyInputHdl)
);
149 m_xTreeView->connect_popup_menu(LINK(this, SwGlobalTree, CommandHdl)::tools::detail::makeLink( ::tools::detail::castTo<SwGlobalTree
*>(this), &SwGlobalTree::LinkStubCommandHdl)
);
150 m_xTreeView->connect_query_tooltip(LINK(this, SwGlobalTree, QueryTooltipHdl)::tools::detail::makeLink( ::tools::detail::castTo<SwGlobalTree
*>(this), &SwGlobalTree::LinkStubQueryTooltipHdl)
);
151}
152
153SwGlobalTree::~SwGlobalTree()
154{
155 m_pSwGlblDocContents.reset();
156 m_pDocInserter.reset();
157 m_aUpdateTimer.Stop();
158 m_xDialog.clear();
159}
160
161SwGlobalTreeDropTarget::SwGlobalTreeDropTarget(SwGlobalTree& rTreeView)
162 : DropTargetHelper(rTreeView.get_widget().get_drop_target())
163 , m_rTreeView(rTreeView)
164{
165}
166
167sal_Int8 SwGlobalTreeDropTarget::ExecuteDrop( const ExecuteDropEvent& rEvt )
168{
169 sal_Int8 nRet = DND_ACTION_NONEcss::datatransfer::dnd::DNDConstants::ACTION_NONE;
170
171 weld::TreeView& rWidget = m_rTreeView.get_widget();
172 std::unique_ptr<weld::TreeIter> xDropEntry(rWidget.make_iterator());
173 if (!rWidget.get_dest_row_at_pos(rEvt.maPosPixel, xDropEntry.get(), true))
174 xDropEntry.reset();
175
176 if (rWidget.get_drag_source() == &rWidget) // internal drag
177 m_rTreeView.MoveSelectionTo(xDropEntry.get());
178 else
179 {
180 TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
181
182 OUString sFileName;
183 const SwGlblDocContent* pCnt = xDropEntry ?
184 reinterpret_cast<const SwGlblDocContent*>(rWidget.get_id(*xDropEntry).toInt64()) :
185 nullptr;
186 if( aData.HasFormat( SotClipboardFormatId::FILE_LIST ))
187 {
188 nRet = rEvt.mnAction;
189 std::unique_ptr<SwGlblDocContents> pTempContents(new SwGlblDocContents);
190 int nAbsContPos = xDropEntry ?
191 rWidget.get_iter_index_in_parent(*xDropEntry):
192 - 1;
193 size_t nEntryCount = rWidget.n_children();
194
195 // Get data
196 FileList aFileList;
197 aData.GetFileList( SotClipboardFormatId::FILE_LIST, aFileList );
198 for ( size_t n = aFileList.Count(); n--; )
199 {
200 sFileName = aFileList.GetFile(n);
201 m_rTreeView.InsertRegion(pCnt, &sFileName);
202 // The list of contents must be newly fetched after inserting,
203 // to not work on an old content.
204 if(n)
205 {
206 m_rTreeView.GetActiveWrtShell()->GetGlobalDocContent(*pTempContents);
207 // If the file was successfully inserted,
208 // then the next content must also be fetched.
209 if(nEntryCount < pTempContents->size())
210 {
211 nEntryCount++;
212 nAbsContPos++;
213 pCnt = (*pTempContents)[ nAbsContPos ].get();
214 }
215 }
216 }
217 }
218 else if( !(sFileName =
219 SwNavigationPI::CreateDropFileName( aData )).isEmpty())
220 {
221 INetURLObject aTemp(sFileName);
222 GraphicDescriptor aDesc(aTemp);
223 if( !aDesc.Detect() ) // accept no graphics
224 {
225 nRet = rEvt.mnAction;
226 m_rTreeView.InsertRegion(pCnt, &sFileName);
227 }
228 }
229 }
230 return nRet;
231}
232
233sal_Int8 SwGlobalTreeDropTarget::AcceptDrop( const AcceptDropEvent& rEvt )
234{
235 // to enable the autoscroll when we're close to the edges
236 weld::TreeView& rWidget = m_rTreeView.get_widget();
237 rWidget.get_dest_row_at_pos(rEvt.maPosPixel, nullptr, true);
238
239 sal_Int8 nRet = rEvt.mnAction;
240
241 if (rWidget.get_drag_source() == &rWidget) // internal drag
242 return nRet;
243
244 if (IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE) ||
245 IsDropFormatSupported( SotClipboardFormatId::STRING) ||
246 IsDropFormatSupported( SotClipboardFormatId::FILE_LIST) ||
247 IsDropFormatSupported( SotClipboardFormatId::SOLK) ||
248 IsDropFormatSupported( SotClipboardFormatId::NETSCAPE_BOOKMARK )||
249 IsDropFormatSupported( SotClipboardFormatId::FILECONTENT) ||
250 IsDropFormatSupported( SotClipboardFormatId::FILEGRPDESCRIPTOR) ||
251 IsDropFormatSupported( SotClipboardFormatId::UNIFORMRESOURCELOCATOR) ||
252 IsDropFormatSupported( SotClipboardFormatId::FILENAME))
253 {
254 nRet = DND_ACTION_LINKcss::datatransfer::dnd::DNDConstants::ACTION_LINK;
255 }
256
257 return nRet;
258}
259
260IMPL_LINK(SwGlobalTree, CommandHdl, const CommandEvent&, rCEvt, bool)bool SwGlobalTree::LinkStubCommandHdl(void * instance, const CommandEvent
& data) { return static_cast<SwGlobalTree *>(instance
)->CommandHdl(data); } bool SwGlobalTree::CommandHdl(const
CommandEvent& rCEvt)
1
Calling 'SwGlobalTree::CommandHdl'
261{
262 if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
2
Assuming the condition is false
3
Taking false branch
263 return false;
264
265 bool bPop = false;
266 if (m_pActiveShell && !m_pActiveShell->GetView().GetDocShell()->IsReadOnly())
4
Assuming field 'm_pActiveShell' is non-null
5
Assuming the condition is true
6
Taking true branch
267 {
268 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xTreeView.get(), "modules/swriter/ui/mastercontextmenu.ui"));
269 std::unique_ptr<weld::Menu> xPopup = xBuilder->weld_menu("navmenu");
270
271 const MenuEnableFlags nEnableFlags = GetEnableFlags();
272
273 xPopup->set_sensitive("updatesel", bool(nEnableFlags & MenuEnableFlags::UpdateSel));
274
275 xPopup->set_sensitive("editlink", bool(nEnableFlags & MenuEnableFlags::EditLink));
276
277 //disabling if applicable
278 xPopup->set_sensitive("insertindex", bool(nEnableFlags & MenuEnableFlags::InsertIdx ));
279 xPopup->set_sensitive("insertfile", bool(nEnableFlags & MenuEnableFlags::InsertFile));
280 xPopup->set_sensitive("insertnewfile", bool(nEnableFlags & MenuEnableFlags::InsertFile));
281 xPopup->set_sensitive("inserttext", bool(nEnableFlags & MenuEnableFlags::InsertText));
282
283 xPopup->set_sensitive("update", bool(nEnableFlags & MenuEnableFlags::Update));
284 xPopup->set_sensitive("insert", bool(nEnableFlags & MenuEnableFlags::InsertIdx));
285 xPopup->set_sensitive("editcontent", bool(nEnableFlags & MenuEnableFlags::Edit));
286 xPopup->set_sensitive("deleteentry", bool(nEnableFlags & MenuEnableFlags::Delete));
287
288 OString sCommand = xPopup->popup_at_rect(m_xTreeView.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)));
289 if (!sCommand.isEmpty())
7
Taking true branch
290 ExecuteContextMenuAction(sCommand);
8
Calling 'SwGlobalTree::ExecuteContextMenuAction'
291
292 bPop = true;
293 }
294 return bPop;
295}
296
297void SwGlobalTree::TbxMenuHdl(const OString& rCommand, weld::Menu& rMenu)
298{
299 const MenuEnableFlags nEnableFlags = GetEnableFlags();
300 if (rCommand == "insert")
301 {
302 rMenu.set_sensitive("insertindex", bool(nEnableFlags & MenuEnableFlags::InsertIdx));
303 rMenu.set_sensitive("insertfile", bool(nEnableFlags & MenuEnableFlags::InsertFile));
304 rMenu.set_sensitive("insertnewfile", bool(nEnableFlags & MenuEnableFlags::InsertFile));
305 rMenu.set_sensitive("inserttext", bool(nEnableFlags & MenuEnableFlags::InsertText));
306 }
307 else if (rCommand == "update")
308 {
309 rMenu.set_sensitive("updatesel", bool(nEnableFlags & MenuEnableFlags::UpdateSel));
310 }
311}
312
313MenuEnableFlags SwGlobalTree::GetEnableFlags() const
314{
315 std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
316 bool bEntry = m_xTreeView->get_selected(xEntry.get());
317
318 sal_uLong nSelCount = m_xTreeView->count_selected_rows();
319 size_t nEntryCount = m_xTreeView->n_children();
320 std::unique_ptr<weld::TreeIter> xPrevEntry;
321 bool bPrevEntry = false;
322 if (bEntry)
323 {
324 xPrevEntry = m_xTreeView->make_iterator(xEntry.get());
325 bPrevEntry = m_xTreeView->iter_previous(*xPrevEntry);
326 }
327
328 MenuEnableFlags nRet = MenuEnableFlags::NONE;
329 if(nSelCount == 1 || !nEntryCount)
330 nRet |= MenuEnableFlags::InsertIdx|MenuEnableFlags::InsertFile;
331 if(nSelCount == 1)
332 {
333 nRet |= MenuEnableFlags::Edit;
334 if (bEntry && reinterpret_cast<SwGlblDocContent*>(m_xTreeView->get_id(*xEntry).toInt64())->GetType() != GLBLDOC_UNKNOWN &&
335 (!bPrevEntry || reinterpret_cast<SwGlblDocContent*>(m_xTreeView->get_id(*xPrevEntry).toInt64())->GetType() != GLBLDOC_UNKNOWN))
336 nRet |= MenuEnableFlags::InsertText;
337 if (bEntry && GLBLDOC_SECTION == reinterpret_cast<SwGlblDocContent*>(m_xTreeView->get_id(*xEntry).toInt64())->GetType())
338 nRet |= MenuEnableFlags::EditLink;
339 }
340 else if(!nEntryCount)
341 {
342 nRet |= MenuEnableFlags::InsertText;
343 }
344 if(nEntryCount)
345 nRet |= MenuEnableFlags::Update|MenuEnableFlags::Delete;
346 if(nSelCount)
347 nRet |= MenuEnableFlags::UpdateSel;
348 return nRet;
349}
350
351IMPL_LINK(SwGlobalTree, QueryTooltipHdl, const weld::TreeIter&, rIter, OUString)OUString SwGlobalTree::LinkStubQueryTooltipHdl(void * instance
, const weld::TreeIter& data) { return static_cast<SwGlobalTree
*>(instance)->QueryTooltipHdl(data); } OUString SwGlobalTree
::QueryTooltipHdl(const weld::TreeIter& rIter)
352{
353 OUString sEntry;
354
355 const SwGlblDocContent* pCont = reinterpret_cast<const SwGlblDocContent*>(m_xTreeView->get_id(rIter).toInt64());
356 if (pCont && GLBLDOC_SECTION == pCont->GetType())
357 {
358 const SwSection* pSect = pCont->GetSection();
359 sEntry = pSect->GetLinkFileName().getToken(0, sfx2::cTokenSeparator);
360 if (!pSect->IsConnectFlag())
361 sEntry = m_aContextStrings[IDX_STR_BROKEN_LINK] + sEntry;
362 }
363
364 return sEntry;
365}
366
367IMPL_LINK_NOARG(SwGlobalTree, SelectHdl, weld::TreeView&, void)void SwGlobalTree::LinkStubSelectHdl(void * instance, weld::TreeView
& data) { return static_cast<SwGlobalTree *>(instance
)->SelectHdl(data); } void SwGlobalTree::SelectHdl(__attribute__
((unused)) weld::TreeView&)
368{
369 Select();
370}
371
372void SwGlobalTree::Select()
373{
374 int nSelCount = m_xTreeView->count_selected_rows();
375 int nSel = m_xTreeView->get_selected_index();
376 int nAbsPos = nSel != -1 ? nSel : 0;
377 SwNavigationPI* pNavi = GetParentWindow();
378 bool bReadonly = !m_pActiveShell ||
379 m_pActiveShell->GetView().GetDocShell()->IsReadOnly();
380 pNavi->m_xGlobalToolBox->set_item_sensitive("edit", nSelCount == 1 && !bReadonly);
381 pNavi->m_xGlobalToolBox->set_item_sensitive("insert", nSelCount <= 1 && !bReadonly);
382 pNavi->m_xGlobalToolBox->set_item_sensitive("update", m_xTreeView->n_children() > 0 && !bReadonly);
383 pNavi->m_xGlobalToolBox->set_item_sensitive("moveup",
384 nSelCount == 1 && nAbsPos && !bReadonly);
385 pNavi->m_xGlobalToolBox->set_item_sensitive("movedown",
386 nSelCount == 1 && nAbsPos < m_xTreeView->n_children() - 1 && !bReadonly);
387
388}
389
390void SwGlobalTree::MoveSelectionTo(const weld::TreeIter* pDropEntry)
391{
392 int nSource = m_xTreeView->get_selected_index();
393
394 int nDest = pDropEntry ? m_xTreeView->get_iter_index_in_parent(*pDropEntry)
395 : m_pSwGlblDocContents->size();
396
397 if (m_pActiveShell->MoveGlobalDocContent(
398 *m_pSwGlblDocContents, nSource, nSource + 1, nDest ) &&
399 Update( false ))
400 Display();
401}
402
403IMPL_LINK_NOARG(SwGlobalTree, FocusInHdl, weld::Widget&, void)void SwGlobalTree::LinkStubFocusInHdl(void * instance, weld::
Widget& data) { return static_cast<SwGlobalTree *>(
instance)->FocusInHdl(data); } void SwGlobalTree::FocusInHdl
(__attribute__ ((unused)) weld::Widget&)
404{
405 if (Update(false))
406 Display();
407}
408
409IMPL_LINK(SwGlobalTree, KeyInputHdl, const KeyEvent&, rKEvt, bool)bool SwGlobalTree::LinkStubKeyInputHdl(void * instance, const
KeyEvent& data) { return static_cast<SwGlobalTree *>
(instance)->KeyInputHdl(data); } bool SwGlobalTree::KeyInputHdl
(const KeyEvent& rKEvt)
410{
411 bool bHandled = false;
412 const vcl::KeyCode aCode = rKEvt.GetKeyCode();
413 if (aCode.GetCode() == KEY_RETURN)
414 {
415 switch (aCode.GetModifier())
416 {
417 case KEY_MOD2:
418 // Switch boxes
419 GetParentWindow()->ToggleTree();
420 bHandled = true;
421 break;
422 }
423 }
424 return bHandled;
425}
426
427void SwGlobalTree::Display(bool bOnlyUpdateUserData)
428{
429 size_t nCount = m_pSwGlblDocContents->size();
430 size_t nChildren = m_xTreeView->n_children();
431 if (bOnlyUpdateUserData && nChildren == m_pSwGlblDocContents->size())
432 {
433 std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
434 bool bEntry = m_xTreeView->get_iter_first(*xEntry);
435 for (size_t i = 0; i < nCount && bEntry; i++)
436 {
437 const SwGlblDocContent* pCont = (*m_pSwGlblDocContents)[i].get();
438 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pCont)));
439 m_xTreeView->set_id(*xEntry, sId);
440 if (pCont->GetType() == GLBLDOC_SECTION && !pCont->GetSection()->IsConnectFlag())
441 m_xTreeView->set_font_color(*xEntry, COL_LIGHTRED);
442 else
443 m_xTreeView->set_font_color(*xEntry, COL_AUTO);
444 bEntry = m_xTreeView->iter_next(*xEntry);
445 assert(bEntry || i == nCount - 1)(static_cast <bool> (bEntry || i == nCount - 1) ? void (
0) : __assert_fail ("bEntry || i == nCount - 1", "/home/maarten/src/libreoffice/core/sw/source/uibase/utlui/glbltree.cxx"
, 445, __extension__ __PRETTY_FUNCTION__))
;
446 }
447 }
448 else
449 {
450 int nOldSelEntry = m_xTreeView->get_selected_index();
451 OUString sEntryName; // Name of the entry
452 int nSelPos = -1;
453 if (nOldSelEntry != -1)
454 {
455 sEntryName = m_xTreeView->get_text(nOldSelEntry);
456 nSelPos = nOldSelEntry;
457 }
458 m_xTreeView->freeze();
459 m_xTreeView->clear();
460 if (!m_pSwGlblDocContents)
461 Update( false );
462
463 int nSelEntry = -1;
464 for (size_t i = 0; i < nCount; ++i)
465 {
466 const SwGlblDocContent* pCont = (*m_pSwGlblDocContents)[i].get();
467
468 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pCont)));
469 OUString sEntry;
470 OUString aImage;
471 switch (pCont->GetType())
472 {
473 case GLBLDOC_UNKNOWN:
474 sEntry = m_aContextStrings[IDX_STR_INSERT_TEXT];
475 break;
476 case GLBLDOC_TOXBASE:
477 {
478 const SwTOXBase* pBase = pCont->GetTOX();
479 sEntry = pBase->GetTitle();
480 aImage = RID_BMP_NAVI_INDEX"sw/res/nc20009.png";
481 }
482 break;
483 case GLBLDOC_SECTION:
484 {
485 const SwSection* pSect = pCont->GetSection();
486 sEntry = pSect->GetSectionName();
487 aImage = RID_BMP_DROP_REGION"sw/res/sc20235.png";
488 }
489 break;
490 }
491
492 m_xTreeView->append(sId, sEntry);
493 if (!aImage.isEmpty())
494 m_xTreeView->set_image(i, aImage);
495
496 if (pCont->GetType() == GLBLDOC_SECTION && !pCont->GetSection()->IsConnectFlag())
497 m_xTreeView->set_font_color(i, COL_LIGHTRED);
498
499 if (sEntry == sEntryName)
500 nSelEntry = i;
501 }
502 m_xTreeView->thaw();
503 if (nSelEntry != -1)
504 m_xTreeView->select(nSelEntry);
505 else if (nSelPos != -1 && o3tl::make_unsigned(nSelPos) < nCount)
506 m_xTreeView->select(nSelPos);
507 else if (nCount)
508 m_xTreeView->select(0);
509 Select();
510 }
511}
512
513void SwGlobalTree::InsertRegion( const SwGlblDocContent* pCont, const OUString* pFileName )
514{
515 Sequence< OUString > aFileNames;
516 if ( !pFileName )
517 {
518 m_pDocInserter.reset(new ::sfx2::DocumentInserter(GetParentWindow()->GetFrameWeld(), "swriter", sfx2::DocumentInserter::Mode::InsertMulti));
519 m_pDocInserter->StartExecuteModal( LINK( this, SwGlobalTree, DialogClosedHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwGlobalTree
*>(this), &SwGlobalTree::LinkStubDialogClosedHdl)
);
520 }
521 else if ( !pFileName->isEmpty() )
522 {
523 aFileNames.realloc(1);
524 INetURLObject aFileName;
525 aFileName.SetSmartURL( *pFileName );
526 aFileNames.getArray()[0] = aFileName.GetMainURL( INetURLObject::DecodeMechanism::NONE );
527 InsertRegion( pCont, aFileNames );
528 }
529}
530
531void SwGlobalTree::EditContent(const SwGlblDocContent* pCont )
532{
533 sal_uInt16 nSlot = 0;
534 switch( pCont->GetType() )
535 {
536 case GLBLDOC_UNKNOWN:
537 m_pActiveShell->GetView().GetEditWin().GrabFocus();
538 break;
539 case GLBLDOC_TOXBASE:
540 {
541 const SwTOXBase* pBase = pCont->GetTOX();
542 if(pBase)
543 nSlot = FN_INSERT_MULTI_TOX((20000 + 1400) + 20);
544 }
545 break;
546 case GLBLDOC_SECTION:
547 {
548 OpenDoc(pCont);
549
550 nSlot = 0;
551 pCont = nullptr;
552 }
553 break;
554 }
555 if(pCont)
556 GotoContent(pCont);
557 if(nSlot)
558 {
559 m_pActiveShell->GetView().GetViewFrame()->GetDispatcher()->Execute(nSlot);
560 if(Update( false ))
561 Display();
562 }
563}
564
565void SwGlobalTree::ExecuteContextMenuAction(const OString& rSelectedPopupEntry)
566{
567 bool bUpdateHard = false;
568
569 int nEntry = m_xTreeView->get_selected_index();
570 SwGlblDocContent* pCont = nEntry != -1 ? reinterpret_cast<SwGlblDocContent*>(m_xTreeView->get_id(nEntry).toInt64()) : nullptr;
9
Assuming the condition is true
10
'?' condition is true
571 // If a RequestHelp is called during the dialogue,
572 // then the content gets lost. Because of that a copy
573 // is created in which only the DocPos is set correctly.
574 std::unique_ptr<SwGlblDocContent> pContCopy;
575 if(pCont)
11
Assuming 'pCont' is non-null
12
Taking true branch
576 pContCopy.reset(new SwGlblDocContent(pCont->GetDocPos()));
577 SfxDispatcher& rDispatch = *m_pActiveShell->GetView().GetViewFrame()->GetDispatcher();
578 sal_uInt16 nSlot = 0;
579 if (rSelectedPopupEntry == "updatesel")
13
Taking false branch
580 {
581 // Two passes: first update the areas, then the directories.
582 m_xTreeView->selected_foreach([this](weld::TreeIter& rSelEntry){
583 SwGlblDocContent* pContent = reinterpret_cast<SwGlblDocContent*>(m_xTreeView->get_id(rSelEntry).toInt64());
584 if (GLBLDOC_SECTION == pContent->GetType() &&
585 pContent->GetSection()->IsConnected())
586 {
587 const_cast<SwSection*>(pContent->GetSection())->UpdateNow();
588 }
589 return false;
590 });
591 m_xTreeView->selected_foreach([this](weld::TreeIter& rSelEntry){
592 SwGlblDocContent* pContent = reinterpret_cast<SwGlblDocContent*>(m_xTreeView->get_id(rSelEntry).toInt64());
593 if (GLBLDOC_TOXBASE == pContent->GetType())
594 m_pActiveShell->UpdateTableOf(*pContent->GetTOX());
595 return false;
596 });
597
598 bUpdateHard = true;
599 }
600 else if (rSelectedPopupEntry == "updateindex")
14
Taking false branch
601 {
602 nSlot = FN_UPDATE_TOX((20000 + 600) + 53);
603 bUpdateHard = true;
604 }
605 else if (rSelectedPopupEntry == "updatelinks" || rSelectedPopupEntry == "updateall")
15
Taking false branch
606 {
607 m_pActiveShell->GetLinkManager().UpdateAllLinks(true, false, nullptr);
608 if (rSelectedPopupEntry == "updateall")
609 nSlot = FN_UPDATE_TOX((20000 + 600) + 53);
610 pCont = nullptr;
611 bUpdateHard = true;
612 }
613 else if (rSelectedPopupEntry == "edit")
16
Taking false branch
614 {
615 OSL_ENSURE(pCont, "edit without entry ? " )do { if (true && (!(pCont))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/utlui/glbltree.cxx"
":" "615" ": "), "%s", "edit without entry ? "); } } while (
false)
;
616 if (pCont)
617 {
618 EditContent(pCont);
619 }
620 }
621 else if (rSelectedPopupEntry == "editlink")
17
Taking false branch
622 {
623 OSL_ENSURE(pCont, "edit without entry ? " )do { if (true && (!(pCont))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/utlui/glbltree.cxx"
":" "623" ": "), "%s", "edit without entry ? "); } } while (
false)
;
624 if (pCont)
625 {
626 SfxStringItem aName(FN_EDIT_REGION((20000 + 100) + 65),
627 pCont->GetSection()->GetSectionName());
628 rDispatch.ExecuteList(FN_EDIT_REGION((20000 + 100) + 65), SfxCallMode::ASYNCHRON,
629 { &aName });
630 }
631 }
632 else if (rSelectedPopupEntry == "deleteentry")
18
Taking false branch
633 {
634 // If several entries selected, then after each delete the array
635 // must be refilled. So you do not have to remember anything,
636 // deleting begins at the end.
637 std::vector<int> aRows = m_xTreeView->get_selected_rows();
638 std::sort(aRows.begin(), aRows.end());
639
640 std::unique_ptr<SwGlblDocContents> pTempContents;
641 m_pActiveShell->StartAction();
642 for (auto iter = aRows.rbegin(); iter != aRows.rend(); ++iter)
643 {
644 m_pActiveShell->DeleteGlobalDocContent(
645 pTempContents ? *pTempContents : *m_pSwGlblDocContents,
646 *iter);
647 pTempContents.reset(new SwGlblDocContents);
648 m_pActiveShell->GetGlobalDocContent(*pTempContents);
649 }
650 pTempContents.reset();
651 m_pActiveShell->EndAction();
652 pCont = nullptr;
653 }
654 else if (rSelectedPopupEntry == "insertindex")
19
Taking true branch
655 {
656 if(pContCopy)
20
Taking true branch
657 {
658 SfxItemSet aSet(
659 m_pActiveShell->GetView().GetPool(),
660 svl::Items<
661 RES_FRM_SIZE, RES_FRM_SIZE,
662 RES_LR_SPACE, RES_LR_SPACE,
663 RES_BACKGROUND, RES_BACKGROUND,
664 RES_COL, RES_COL,
665 SID_ATTR_PAGE_SIZETypedWhichId<SvxSizeItem>( 10000 + 51 ), SID_ATTR_PAGE_SIZETypedWhichId<SvxSizeItem>( 10000 + 51 ),
666 FN_PARAM_TOX_TYPE((20000 + 2400)+14), FN_PARAM_TOX_TYPE((20000 + 2400)+14)>{});
667
668 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
669 ScopedVclPtr<AbstractMultiTOXTabDialog> pDlg(pFact->CreateMultiTOXTabDialog(
21
Calling constructor for 'ScopedVclPtr<AbstractMultiTOXTabDialog>'
28
Returning from constructor for 'ScopedVclPtr<AbstractMultiTOXTabDialog>'
670 m_xDialog->GetFrameWeld(), aSet,
671 *m_pActiveShell,
672 nullptr,
673 true));
29
Calling implicit destructor for 'VclPtr<AbstractMultiTOXTabDialog>'
30
Calling '~Reference'
37
Returning from '~Reference'
38
Returning from destructor for 'VclPtr<AbstractMultiTOXTabDialog>'
674 if(RET_OK == pDlg->Execute())
39
Calling 'VclPtr::operator->'
675 {
676 SwTOXDescription& rDesc = pDlg->GetTOXDescription(
677 pDlg->GetCurrentTOXType());
678 SwTOXMgr aMgr(m_pActiveShell);
679 SwTOXBase* pToInsert = nullptr;
680 if(aMgr.UpdateOrInsertTOX(rDesc, &pToInsert, pDlg->GetOutputItemSet()))
681 m_pActiveShell->InsertGlobalDocContent( *pContCopy, *pToInsert );
682 }
683 pCont = nullptr;
684 }
685 }
686 else if (rSelectedPopupEntry == "insertfile")
687 {
688 m_pDocContent = std::move(pContCopy);
689 InsertRegion( m_pDocContent.get() );
690 pCont = nullptr;
691 }
692 else if (rSelectedPopupEntry == "insertnewfile")
693 {
694 SfxViewFrame* pGlobFrame = m_pActiveShell->GetView().GetViewFrame();
695 SwGlobalFrameListener_Impl aFrameListener(*pGlobFrame);
696
697 // Creating a new doc
698 SfxStringItem aFactory(SID_NEWDOCDIRECT(5000 + 537),
699 SwDocShell::Factory().GetFilterContainer()->GetName());
700
701 const SfxFrameItem* pItem = static_cast<const SfxFrameItem*>(
702 rDispatch.ExecuteList(SID_NEWDOCDIRECT(5000 + 537),
703 SfxCallMode::SYNCHRON, { &aFactory }));
704
705 // save at
706 SfxFrame* pFrame = pItem ? pItem->GetFrame() : nullptr;
707 SfxViewFrame* pViewFrame = pFrame ? pFrame->GetCurrentViewFrame() : nullptr;
708 if (pViewFrame)
709 {
710 const SfxBoolItem* pBool = static_cast<const SfxBoolItem*>(
711 pViewFrame->GetDispatcher()->Execute(
712 SID_SAVEASDOC(5000 + 502), SfxCallMode::SYNCHRON ));
713 SfxObjectShell& rObj = *pViewFrame->GetObjectShell();
714 const SfxMedium* pMedium = rObj.GetMedium();
715 OUString sNewFile(pMedium->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::ToIUri));
716 // Insert the area with the Doc-Name
717 // Bring the own Doc in the foreground
718 if(aFrameListener.IsValid() && !sNewFile.isEmpty())
719 {
720 pGlobFrame->ToTop();
721 // Due to the update the entries are invalid
722 if (nEntry != -1)
723 {
724 Update( false );
725 Display();
726 m_xTreeView->select(nEntry);
727 Select();
728 nEntry = m_xTreeView->get_selected_index();
729 pCont = nEntry != -1 ? reinterpret_cast<SwGlblDocContent*>(m_xTreeView->get_id(nEntry).toInt64()) : nullptr;
730 }
731 else
732 {
733 nEntry = -1;
734 pCont = nullptr;
735 }
736 if(pBool->GetValue())
737 {
738 InsertRegion(pCont, &sNewFile);
739 pViewFrame->ToTop();
740 }
741 else
742 pViewFrame->GetDispatcher()->Execute(SID_CLOSEWIN(5000 + 621), SfxCallMode::SYNCHRON);
743 }
744 else
745 {
746 pViewFrame->ToTop();
747 return;
748 }
749 }
750 }
751 else if (rSelectedPopupEntry == "inserttext")
752 {
753 if (pCont)
754 m_pActiveShell->InsertGlobalDocContent(*pCont);
755 else
756 {
757 m_pActiveShell->SplitNode(); // Empty document
758 m_pActiveShell->Up( false );
759 }
760 m_pActiveShell->GetView().GetEditWin().GrabFocus();
761 }
762 else if (rSelectedPopupEntry == "update")
763 pCont = nullptr;
764
765 if (pCont)
766 GotoContent(pCont);
767 if (nSlot)
768 rDispatch.Execute(nSlot);
769 if (Update(bUpdateHard))
770 Display();
771}
772
773IMPL_LINK_NOARG(SwGlobalTree, Timeout, Timer *, void)void SwGlobalTree::LinkStubTimeout(void * instance, Timer * data
) { return static_cast<SwGlobalTree *>(instance)->Timeout
(data); } void SwGlobalTree::Timeout(__attribute__ ((unused))
Timer *)
774{
775 if (!m_xTreeView->has_focus() && Update(false))
776 Display();
777}
778
779void SwGlobalTree::GotoContent(const SwGlblDocContent* pCont)
780{
781 m_pActiveShell->EnterStdMode();
782
783 switch( pCont->GetType() )
784 {
785 case GLBLDOC_UNKNOWN:
786 m_pActiveShell->GotoGlobalDocContent(*pCont);
787 break;
788 case GLBLDOC_TOXBASE:
789 {
790 const OUString sName = pCont->GetTOX()->GetTOXName();
791 if (!m_pActiveShell->GotoNextTOXBase(&sName))
792 m_pActiveShell->GotoPrevTOXBase(&sName);
793 }
794 break;
795 case GLBLDOC_SECTION:
796 break;
797 }
798
799}
800
801void SwGlobalTree::ShowTree()
802{
803 m_aUpdateTimer.Start();
804 m_xTreeView->show();
805}
806
807void SwGlobalTree::HideTree()
808{
809 m_aUpdateTimer.Stop();
810 m_xTreeView->hide();
811}
812
813void SwGlobalTree::ExecCommand(const OString &rCmd)
814{
815 int nEntry = m_xTreeView->get_selected_index();
816 if (nEntry == -1)
817 return;
818 if (rCmd == "edit")
819 {
820 const SwGlblDocContent* pCont = reinterpret_cast<const SwGlblDocContent*>(
821 m_xTreeView->get_id(nEntry).toInt64());
822 EditContent(pCont);
823 }
824 else
825 {
826 if (m_xTreeView->count_selected_rows() == 1)
827 {
828 bool bMove = false;
829 sal_uLong nSource = nEntry;
830 sal_uLong nDest = nSource;
831 if (rCmd == "movedown")
832 {
833 size_t nEntryCount = m_xTreeView->n_children();
834 bMove = nEntryCount > nSource + 1;
835 nDest+= 2;
836 }
837 else if (rCmd == "moveup")
838 {
839 bMove = 0 != nSource;
840 nDest--;
841 }
842 if( bMove && m_pActiveShell->MoveGlobalDocContent(
843 *m_pSwGlblDocContents, nSource, nSource + 1, nDest ) &&
844 Update( false ))
845 Display();
846 }
847 }
848}
849
850bool SwGlobalTree::Update(bool bHard)
851{
852 SwView* pActView = GetParentWindow()->GetCreateView();
853 bool bRet = false;
854 if (pActView && pActView->GetWrtShellPtr())
855 {
856 const SwWrtShell* pOldShell = m_pActiveShell;
857 m_pActiveShell = pActView->GetWrtShellPtr();
858 if(m_pActiveShell != pOldShell)
859 {
860 m_pSwGlblDocContents.reset();
861 }
862 if(!m_pSwGlblDocContents)
863 {
864 m_pSwGlblDocContents.reset(new SwGlblDocContents);
865 bRet = true;
866 m_pActiveShell->GetGlobalDocContent(*m_pSwGlblDocContents);
867 }
868 else
869 {
870 bool bCopy = false;
871 std::unique_ptr<SwGlblDocContents> pTempContents(new SwGlblDocContents);
872 m_pActiveShell->GetGlobalDocContent(*pTempContents);
873 size_t nChildren = m_xTreeView->n_children();
874 if (pTempContents->size() != m_pSwGlblDocContents->size() ||
875 pTempContents->size() != nChildren)
876 {
877 bRet = true;
878 bCopy = true;
879 }
880 else
881 {
882 for(size_t i = 0; i < pTempContents->size() && !bCopy; i++)
883 {
884 SwGlblDocContent* pLeft = (*pTempContents)[i].get();
885 SwGlblDocContent* pRight = (*m_pSwGlblDocContents)[i].get();
886 GlobalDocContentType eType = pLeft->GetType();
887 OUString sTemp = m_xTreeView->get_text(i);
888 if (
889 eType != pRight->GetType() ||
890 (
891 eType == GLBLDOC_SECTION &&
892 pLeft->GetSection()->GetSectionName() != sTemp
893 ) ||
894 (
895 eType == GLBLDOC_TOXBASE &&
896 pLeft->GetTOX()->GetTitle() != sTemp
897 )
898 )
899 {
900 bCopy = true;
901 }
902 }
903 }
904 if (bCopy || bHard)
905 {
906 *m_pSwGlblDocContents = std::move( *pTempContents );
907 bRet = true;
908 }
909 }
910 }
911 else
912 {
913 m_xTreeView->clear();
914 if(m_pSwGlblDocContents)
915 m_pSwGlblDocContents->clear();
916 }
917 // FIXME: Implement a test for changes!
918 return bRet;
919}
920
921void SwGlobalTree::OpenDoc(const SwGlblDocContent* pCont)
922{
923 const OUString sFileName(pCont->GetSection()->GetLinkFileName().getToken(0,
924 sfx2::cTokenSeparator));
925 bool bFound = false;
926 const SfxObjectShell* pCurr = SfxObjectShell::GetFirst();
927 while( !bFound && pCurr )
928 {
929 if(pCurr->GetMedium() &&
930 pCurr->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::ToIUri) == sFileName)
931 {
932 bFound = true;
933 SwGlobalTree::SetShowShell(pCurr);
934 Application::PostUserEvent(LINK(this, SwGlobalTree, ShowFrameHdl)::tools::detail::makeLink( ::tools::detail::castTo<SwGlobalTree
*>(this), &SwGlobalTree::LinkStubShowFrameHdl)
);
935 pCurr = nullptr;
936 }
937 else
938 pCurr = SfxObjectShell::GetNext(*pCurr);
939 }
940 if(!bFound)
941 {
942 SfxStringItem aURL(SID_FILE_NAME(5000 + 507), sFileName);
943 SfxBoolItem aReadOnly(SID_DOC_READONLY(5000 + 590), false);
944 SfxStringItem aTargetFrameName( SID_TARGETNAME(5000 + 560), "_blank" );
945 SfxStringItem aReferer(SID_REFERER(5000 + 654), m_pActiveShell->GetView().GetDocShell()->GetTitle());
946 m_pActiveShell->GetView().GetViewFrame()->GetDispatcher()->
947 ExecuteList(SID_OPENDOC(5000 + 501), SfxCallMode::ASYNCHRON,
948 { &aURL, &aReadOnly, &aReferer, &aTargetFrameName });
949 }
950}
951
952IMPL_LINK_NOARG( SwGlobalTree, DoubleClickHdl, weld::TreeView&, bool)bool SwGlobalTree::LinkStubDoubleClickHdl(void * instance, weld
::TreeView& data) { return static_cast<SwGlobalTree *>
(instance)->DoubleClickHdl(data); } bool SwGlobalTree::DoubleClickHdl
(__attribute__ ((unused)) weld::TreeView&)
953{
954 int nEntry = m_xTreeView->get_cursor_index();
955 SwGlblDocContent* pCont = reinterpret_cast<SwGlblDocContent*>(m_xTreeView->get_id(nEntry).toInt64());
956 if (pCont->GetType() == GLBLDOC_SECTION)
957 OpenDoc(pCont);
958 else
959 {
960 GotoContent(pCont);
961 m_pActiveShell->GetView().GetEditWin().GrabFocus();
962 }
963 return false;
964}
965
966SwNavigationPI* SwGlobalTree::GetParentWindow()
967{
968 return m_xDialog;
969}
970
971IMPL_STATIC_LINK_NOARG(SwGlobalTree, ShowFrameHdl, void*, void)void SwGlobalTree::LinkStubShowFrameHdl(void * instance, void
* data) { return ShowFrameHdl(static_cast<SwGlobalTree *>
(instance), data); } void SwGlobalTree::ShowFrameHdl( __attribute__
((unused)) SwGlobalTree *, __attribute__ ((unused)) void*)
972{
973 SfxViewFrame* pFirst = pShowShell ? SfxViewFrame::GetFirst(pShowShell) : nullptr;
974 if (pFirst)
975 pFirst->ToTop();
976 SwGlobalTree::SetShowShell(nullptr);
977}
978
979void SwGlobalTree::InsertRegion( const SwGlblDocContent* _pContent, const Sequence< OUString >& _rFiles )
980{
981 sal_Int32 nFiles = _rFiles.getLength();
982 if (!nFiles)
983 return;
984
985 size_t nEntryCount = m_xTreeView->n_children();
986
987 bool bMove = _pContent == nullptr;
988 const OUString* pFileNames = _rFiles.getConstArray();
989 SwWrtShell& rSh = GetParentWindow()->GetCreateView()->GetWrtShell();
990 rSh.StartAction();
991 // after insertion of the first new content the 'pCont' parameter becomes invalid
992 // find the index of the 'anchor' content to always use a current anchor content
993 size_t nAnchorContent = m_pSwGlblDocContents->size() - 1;
994 if (!bMove)
995 {
996 for (size_t nContent = 0; nContent < m_pSwGlblDocContents->size();
997 ++nContent)
998 {
999 if( *_pContent == *(*m_pSwGlblDocContents)[ nContent ] )
1000 {
1001 nAnchorContent = nContent;
1002 break;
1003 }
1004 }
1005 }
1006 SwGlblDocContents aTempContents;
1007 for ( sal_Int32 nFile = 0; nFile < nFiles; ++nFile )
1008 {
1009 //update the global document content after each inserted document
1010 rSh.GetGlobalDocContent(aTempContents);
1011 SwGlblDocContent* pAnchorContent = nullptr;
1012 OSL_ENSURE(aTempContents.size() > (nAnchorContent + nFile), "invalid anchor content -> last insertion failed")do { if (true && (!(aTempContents.size() > (nAnchorContent
+ nFile)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/utlui/glbltree.cxx"
":" "1012" ": "), "%s", "invalid anchor content -> last insertion failed"
); } } while (false)
;
1013 if ( aTempContents.size() > (nAnchorContent + nFile) )
1014 pAnchorContent = aTempContents[nAnchorContent + nFile].get();
1015 else
1016 pAnchorContent = aTempContents.back().get();
1017 OUString sFileName(pFileNames[nFile]);
1018 INetURLObject aFileUrl;
1019 aFileUrl.SetSmartURL( sFileName );
1020 OUString sSectionName(aFileUrl.GetLastName(
1021 INetURLObject::DecodeMechanism::Unambiguous).getToken(0, sfx2::cTokenSeparator));
1022 sal_uInt16 nSectCount = rSh.GetSectionFormatCount();
1023 OUString sTempSectionName(sSectionName);
1024 sal_uInt16 nAddNumber = 0;
1025 sal_uInt16 nCount = 0;
1026 // if applicable: add index if the range name is already in use.
1027 while ( nCount < nSectCount )
1028 {
1029 const SwSectionFormat& rFormat = rSh.GetSectionFormat(nCount);
1030 if ((rFormat.GetSection()->GetSectionName() == sTempSectionName)
1031 && rFormat.IsInNodesArr())
1032 {
1033 nCount = 0;
1034 nAddNumber++;
1035 sTempSectionName = sSectionName + ":" + OUString::number( nAddNumber );
1036 }
1037 else
1038 nCount++;
1039 }
1040
1041 if ( nAddNumber )
1042 sSectionName = sTempSectionName;
1043
1044 SwSectionData aSectionData(SectionType::Content, sSectionName);
1045 aSectionData.SetProtectFlag(true);
1046 aSectionData.SetHidden(false);
1047
1048 aSectionData.SetLinkFileName(sFileName);
1049 aSectionData.SetType(SectionType::FileLink);
1050 aSectionData.SetLinkFilePassword( OUString() );
1051
1052 rSh.InsertGlobalDocContent( *pAnchorContent, aSectionData );
1053 }
1054 if (bMove)
1055 {
1056 Update( false );
1057 rSh.MoveGlobalDocContent(
1058 *m_pSwGlblDocContents, nEntryCount, nEntryCount + nFiles, nEntryCount - nFiles );
1059 }
1060 rSh.EndAction();
1061 Update( false );
1062 Display();
1063
1064}
1065
1066IMPL_LINK( SwGlobalTree, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void )void SwGlobalTree::LinkStubDialogClosedHdl(void * instance, sfx2
::FileDialogHelper* data) { return static_cast<SwGlobalTree
*>(instance)->DialogClosedHdl(data); } void SwGlobalTree
::DialogClosedHdl(sfx2::FileDialogHelper* _pFileDlg)
1067{
1068 if ( ERRCODE_NONEErrCode(0) != _pFileDlg->GetError() )
1069 return;
1070
1071 SfxMediumList aMedList(m_pDocInserter->CreateMediumList());
1072 if ( aMedList.empty() )
1073 return;
1074
1075 Sequence< OUString >aFileNames( aMedList.size() );
1076 OUString* pFileNames = aFileNames.getArray();
1077 sal_Int32 nPos = 0;
1078 for (const std::unique_ptr<SfxMedium>& pMed : aMedList)
1079 {
1080 OUString sFileName = pMed->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE )
1081 + OUStringChar(sfx2::cTokenSeparator)
1082 + pMed->GetFilter()->GetFilterName()
1083 + OUStringChar(sfx2::cTokenSeparator);
1084 pFileNames[nPos++] = sFileName;
1085 }
1086 InsertRegion( m_pDocContent.get(), aFileNames );
1087 m_pDocContent.reset();
1088}
1089
1090/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.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_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
40
Calling 'Reference::get'
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
205 if (aTmp.get()) {
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
22
Calling implicit copy constructor for 'VclPtr<AbstractMultiTOXTabDialog>'
23
Calling copy constructor for 'Reference<AbstractMultiTOXTabDialog>'
26
Returning from copy constructor for 'Reference<AbstractMultiTOXTabDialog>'
27
Returning from copy constructor for 'VclPtr<AbstractMultiTOXTabDialog>'
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* 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)
24
Assuming field 'm_pBody' is non-null
25
Taking true branch
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
30.1
Field 'm_pBody' is non-null
30.1
Field 'm_pBody' is non-null
30.1
Field 'm_pBody' is non-null
30.1
Field 'm_pBody' is non-null
)
31
Taking true branch
113 m_pBody->release();
32
Calling 'VclReferenceBase::release'
36
Returning; memory was released
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
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 );
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;
41
Use of memory after it is freed
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)
33
Assuming the condition is true
34
Taking true branch
40 delete this;
35
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