Bug Summary

File:home/maarten/src/libreoffice/core/vcl/source/control/listbox.cxx
Warning:line 286, column 5
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 listbox.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 /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/glm -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/libmount -isystem /usr/include/blkid -isystem /usr/include/cairo -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/pixman-1 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/libxml2 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/dbus-1.0 -isystem /usr/lib64/dbus-1.0/include -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -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 VCL_DLLIMPLEMENTATION -D DLLIMPLEMENTATION_UITEST -D CUI_DLL_NAME="libcuilo.so" -D DESKTOP_DETECTOR_DLL_NAME="libdesktop_detectorlo.so" -D TK_DLL_NAME="libtklo.so" -D SYSTEM_ZLIB -D GLM_FORCE_CTOR_INIT -D SK_USER_CONFIG_HEADER=</home/maarten/src/libreoffice/core/config_host/config_skia.h> -D SKIA_DLL -D ENABLE_CUPS -D HAVE_VALGRIND_HEADERS -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/core -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/effects -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/config -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/ports -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/third_party/vulkan -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/tools/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia -I /home/maarten/src/libreoffice/core/external/skia/inc/ -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/mdds/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/lcms2/include -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/workdir/UnpackedTarball/harfbuzz/src -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/graphite/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/workdir/UnpackedTarball/pdfium -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium/public -D COMPONENT_BUILD -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libpng -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libjpeg-turbo -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/vcl/inc -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/CustomTarget/officecfg/registry -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libxml2 -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/vcl/source/control/listbox.cxx

/home/maarten/src/libreoffice/core/vcl/source/control/listbox.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
21#include <vcl/commandevent.hxx>
22#include <vcl/event.hxx>
23#include <vcl/toolkit/lstbox.hxx>
24#include <vcl/settings.hxx>
25#include <vcl/uitest/uiobject.hxx>
26#include <sal/log.hxx>
27
28#include <svdata.hxx>
29#include <controldata.hxx>
30#include <listbox.hxx>
31#include <dndeventdispatcher.hxx>
32#include <comphelper/lok.hxx>
33
34#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
35#include <boost/property_tree/ptree.hpp>
36#include <tools/json_writer.hxx>
37
38ListBox::ListBox(WindowType nType)
39 : Control(nType)
40 , mpImplLB(nullptr)
41{
42 ImplInitListBoxData();
43}
44
45ListBox::ListBox( vcl::Window* pParent, WinBits nStyle ) : Control( WindowType::LISTBOX )
46{
47 ImplInitListBoxData();
48 ImplInit( pParent, nStyle );
49}
50
51ListBox::~ListBox()
52{
53 disposeOnce();
54}
55
56void ListBox::dispose()
57{
58 CallEventListeners( VclEventId::ObjectDying );
59
60 mpImplLB.disposeAndClear();
61 mpFloatWin.disposeAndClear();
62 mpImplWin.disposeAndClear();
63 mpBtn.disposeAndClear();
64
65 Control::dispose();
66}
67
68void ListBox::ImplInitListBoxData()
69{
70 mpFloatWin = nullptr;
71 mpImplWin = nullptr;
72 mpBtn = nullptr;
73 mnDDHeight = 0;
74 mnLineCount = 0;
75 m_nMaxWidthChars = -1;
76 mbDDAutoSize = true;
77}
78
79void ListBox::ImplInit( vcl::Window* pParent, WinBits nStyle )
80{
81 nStyle = ImplInitStyle( nStyle );
82 if ( !(nStyle & WB_NOBORDER) && ( nStyle & WB_DROPDOWN ) )
83 nStyle |= WB_BORDER;
84
85 Control::ImplInit( pParent, nStyle, nullptr );
86
87 css::uno::Reference< css::datatransfer::dnd::XDropTargetListener> xDrop = new DNDEventDispatcher(this);
88
89 if( nStyle & WB_DROPDOWN )
90 {
91 sal_Int32 nLeft, nTop, nRight, nBottom;
92 GetBorder( nLeft, nTop, nRight, nBottom );
93 mnDDHeight = static_cast<sal_uInt16>(GetTextHeight() + nTop + nBottom + 4);
94
95 if( IsNativeWidgetEnabled() &&
96 IsNativeControlSupported( ControlType::Listbox, ControlPart::Entire ) )
97 {
98 ImplControlValue aControlValue;
99 tools::Rectangle aCtrlRegion( Point( 0, 0 ), Size( 20, mnDDHeight ) );
100 tools::Rectangle aBoundingRgn( aCtrlRegion );
101 tools::Rectangle aContentRgn( aCtrlRegion );
102 if( GetNativeControlRegion( ControlType::Listbox, ControlPart::Entire, aCtrlRegion,
103 ControlState::ENABLED, aControlValue,
104 aBoundingRgn, aContentRgn ) )
105 {
106 sal_Int32 nHeight = aBoundingRgn.GetHeight();
107 if( nHeight > mnDDHeight )
108 mnDDHeight = static_cast<sal_uInt16>(nHeight);
109 }
110 }
111
112 mpFloatWin = VclPtr<ImplListBoxFloatingWindow>::Create( this );
113 if (!IsNativeControlSupported(ControlType::Pushbutton, ControlPart::Focus))
114 mpFloatWin->RequestDoubleBuffering(true);
115 mpFloatWin->SetAutoWidth( true );
116 mpFloatWin->SetPopupModeEndHdl( LINK( this, ListBox, ImplPopupModeEndHdl )::tools::detail::makeLink( ::tools::detail::castTo<ListBox
*>(this), &ListBox::LinkStubImplPopupModeEndHdl)
);
117 mpFloatWin->GetDropTarget()->addDropTargetListener(xDrop);
118
119 mpImplWin = VclPtr<ImplWin>::Create( this, (nStyle & (WB_LEFT|WB_RIGHT|WB_CENTER))|WB_NOBORDER );
120 mpImplWin->SetMBDownHdl( LINK( this, ListBox, ImplClickBtnHdl )::tools::detail::makeLink( ::tools::detail::castTo<ListBox
*>(this), &ListBox::LinkStubImplClickBtnHdl)
);
121 mpImplWin->Show();
122 mpImplWin->GetDropTarget()->addDropTargetListener(xDrop);
123 mpImplWin->SetEdgeBlending(false);
124
125 mpBtn = VclPtr<ImplBtn>::Create( this, WB_NOLIGHTBORDER | WB_RECTSTYLE );
126 ImplInitDropDownButton( mpBtn );
127 mpBtn->SetMBDownHdl( LINK( this, ListBox, ImplClickBtnHdl )::tools::detail::makeLink( ::tools::detail::castTo<ListBox
*>(this), &ListBox::LinkStubImplClickBtnHdl)
);
128 mpBtn->Show();
129 mpBtn->GetDropTarget()->addDropTargetListener(xDrop);
130 }
131
132 vcl::Window* pLBParent = this;
133 if ( mpFloatWin )
134 pLBParent = mpFloatWin;
135 mpImplLB = VclPtr<ImplListBox>::Create( pLBParent, nStyle&(~WB_BORDER) );
136 mpImplLB->SetSelectHdl( LINK( this, ListBox, ImplSelectHdl )::tools::detail::makeLink( ::tools::detail::castTo<ListBox
*>(this), &ListBox::LinkStubImplSelectHdl)
);
137 mpImplLB->SetScrollHdl( LINK( this, ListBox, ImplScrollHdl )::tools::detail::makeLink( ::tools::detail::castTo<ListBox
*>(this), &ListBox::LinkStubImplScrollHdl)
);
138 mpImplLB->SetCancelHdl( LINK( this, ListBox, ImplCancelHdl )::tools::detail::makeLink( ::tools::detail::castTo<ListBox
*>(this), &ListBox::LinkStubImplCancelHdl)
);
139 mpImplLB->SetDoubleClickHdl( LINK( this, ListBox, ImplDoubleClickHdl )::tools::detail::makeLink( ::tools::detail::castTo<ListBox
*>(this), &ListBox::LinkStubImplDoubleClickHdl)
);
140 mpImplLB->SetFocusHdl( LINK( this, ListBox, ImplFocusHdl )::tools::detail::makeLink( ::tools::detail::castTo<ListBox
*>(this), &ListBox::LinkStubImplFocusHdl)
);
141 mpImplLB->SetListItemSelectHdl( LINK( this, ListBox, ImplListItemSelectHdl )::tools::detail::makeLink( ::tools::detail::castTo<ListBox
*>(this), &ListBox::LinkStubImplListItemSelectHdl)
);
142 mpImplLB->SetPosPixel( Point() );
143 mpImplLB->SetEdgeBlending(false);
144 mpImplLB->Show();
145
146 mpImplLB->GetDropTarget()->addDropTargetListener(xDrop);
147
148 if ( mpFloatWin )
149 {
150 mpFloatWin->SetImplListBox( mpImplLB );
151 mpImplLB->SetSelectionChangedHdl( LINK( this, ListBox, ImplSelectionChangedHdl )::tools::detail::makeLink( ::tools::detail::castTo<ListBox
*>(this), &ListBox::LinkStubImplSelectionChangedHdl)
);
152 }
153 else
154 mpImplLB->GetMainWindow()->AllowGrabFocus( true );
155
156 SetCompoundControl( true );
157}
158
159WinBits ListBox::ImplInitStyle( WinBits nStyle )
160{
161 if ( !(nStyle & WB_NOTABSTOP) )
162 nStyle |= WB_TABSTOP;
163 if ( !(nStyle & WB_NOGROUP) )
164 nStyle |= WB_GROUP;
165 return nStyle;
166}
167
168IMPL_LINK_NOARG(ListBox, ImplSelectHdl, LinkParamNone*, void)void ListBox::LinkStubImplSelectHdl(void * instance, LinkParamNone
* data) { return static_cast<ListBox *>(instance)->ImplSelectHdl
(data); } void ListBox::ImplSelectHdl(__attribute__ ((unused)
) LinkParamNone*)
169{
170 bool bPopup = IsInDropDown();
171 if( IsDropDownBox() )
172 {
173 if( !mpImplLB->IsTravelSelect() )
174 {
175 mpFloatWin->EndPopupMode();
176 mpImplWin->GrabFocus();
177 }
178
179 mpImplWin->SetItemPos( GetSelectedEntryPos() );
180 mpImplWin->SetString( GetSelectedEntry() );
181 if( mpImplLB->GetEntryList()->HasImages() )
182 {
183 Image aImage = mpImplLB->GetEntryList()->GetEntryImage( GetSelectedEntryPos() );
184 mpImplWin->SetImage( aImage );
185 }
186 mpImplWin->Invalidate();
187 }
188
189 if ( ( !IsTravelSelect() || mpImplLB->IsSelectionChanged() ) || ( bPopup && !IsMultiSelectionEnabled() ) )
190 Select();
191}
192
193IMPL_LINK( ListBox, ImplFocusHdl, sal_Int32, nPos, void )void ListBox::LinkStubImplFocusHdl(void * instance, sal_Int32
data) { return static_cast<ListBox *>(instance)->ImplFocusHdl
(data); } void ListBox::ImplFocusHdl(sal_Int32 nPos)
194{
195 CallEventListeners( VclEventId::ListboxFocus, reinterpret_cast<void*>(nPos) );
196}
197
198IMPL_LINK_NOARG( ListBox, ImplListItemSelectHdl, LinkParamNone*, void )void ListBox::LinkStubImplListItemSelectHdl(void * instance, LinkParamNone
* data) { return static_cast<ListBox *>(instance)->ImplListItemSelectHdl
(data); } void ListBox::ImplListItemSelectHdl(__attribute__ (
(unused)) LinkParamNone*)
199{
200 CallEventListeners( VclEventId::DropdownSelect );
201}
202
203IMPL_LINK_NOARG(ListBox, ImplScrollHdl, ImplListBox*, void)void ListBox::LinkStubImplScrollHdl(void * instance, ImplListBox
* data) { return static_cast<ListBox *>(instance)->ImplScrollHdl
(data); } void ListBox::ImplScrollHdl(__attribute__ ((unused)
) ImplListBox*)
204{
205 CallEventListeners( VclEventId::ListboxScrolled );
206}
207
208IMPL_LINK_NOARG(ListBox, ImplCancelHdl, LinkParamNone*, void)void ListBox::LinkStubImplCancelHdl(void * instance, LinkParamNone
* data) { return static_cast<ListBox *>(instance)->ImplCancelHdl
(data); } void ListBox::ImplCancelHdl(__attribute__ ((unused)
) LinkParamNone*)
209{
210 if( IsInDropDown() )
211 mpFloatWin->EndPopupMode();
212}
213
214IMPL_LINK( ListBox, ImplSelectionChangedHdl, sal_Int32, nChanged, void )void ListBox::LinkStubImplSelectionChangedHdl(void * instance
, sal_Int32 data) { return static_cast<ListBox *>(instance
)->ImplSelectionChangedHdl(data); } void ListBox::ImplSelectionChangedHdl
(sal_Int32 nChanged)
215{
216 if ( mpImplLB->IsTrackingSelect() )
217 return;
218
219 const ImplEntryList* pEntryList = mpImplLB->GetEntryList();
220 if ( pEntryList->IsEntryPosSelected( nChanged ) )
221 {
222 // FIXME? This should've been turned into an ImplPaintEntry some time ago...
223 if ( nChanged < pEntryList->GetMRUCount() )
224 nChanged = pEntryList->FindEntry( pEntryList->GetEntryText( nChanged ) );
225 mpImplWin->SetItemPos( nChanged );
226 mpImplWin->SetString( mpImplLB->GetEntryList()->GetEntryText( nChanged ) );
227 if( mpImplLB->GetEntryList()->HasImages() )
228 {
229 Image aImage = mpImplLB->GetEntryList()->GetEntryImage( nChanged );
230 mpImplWin->SetImage( aImage );
231 }
232 }
233 else
234 {
235 mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND(((sal_Int32) 0x7FFFFFFF)) );
236 mpImplWin->SetString( OUString() );
237 Image aImage;
238 mpImplWin->SetImage( aImage );
239 }
240 mpImplWin->Invalidate();
241}
242
243IMPL_LINK_NOARG(ListBox, ImplDoubleClickHdl, ImplListBoxWindow*, void)void ListBox::LinkStubImplDoubleClickHdl(void * instance, ImplListBoxWindow
* data) { return static_cast<ListBox *>(instance)->ImplDoubleClickHdl
(data); } void ListBox::ImplDoubleClickHdl(__attribute__ ((unused
)) ImplListBoxWindow*)
244{
245 DoubleClick();
246}
247
248IMPL_LINK_NOARG(ListBox, ImplClickBtnHdl, void*, void)void ListBox::LinkStubImplClickBtnHdl(void * instance, void* data
) { return static_cast<ListBox *>(instance)->ImplClickBtnHdl
(data); } void ListBox::ImplClickBtnHdl(__attribute__ ((unused
)) void*)
249{
250 if( mpFloatWin->IsInPopupMode() )
251 return;
252
253 CallEventListeners( VclEventId::DropdownPreOpen );
254 mpImplWin->GrabFocus();
255 mpBtn->SetPressed( true );
256 mpFloatWin->StartFloat( true );
257 CallEventListeners( VclEventId::DropdownOpen );
258
259 ImplClearLayoutData();
260 if( mpImplLB )
261 mpImplLB->GetMainWindow()->ImplClearLayoutData();
262 if( mpImplWin )
263 mpImplWin->ImplClearLayoutData();
264}
265
266IMPL_LINK_NOARG(ListBox, ImplPopupModeEndHdl, FloatingWindow*, void)void ListBox::LinkStubImplPopupModeEndHdl(void * instance, FloatingWindow
* data) { return static_cast<ListBox *>(instance)->ImplPopupModeEndHdl
(data); } void ListBox::ImplPopupModeEndHdl(__attribute__ ((unused
)) FloatingWindow*)
1
Calling 'ListBox::ImplPopupModeEndHdl'
267{
268 if( mpFloatWin->IsPopupModeCanceled() )
2
Assuming the condition is true
3
Taking true branch
269 {
270 if ( ( mpFloatWin->GetPopupModeStartSaveSelection() != LISTBOX_ENTRY_NOTFOUND(((sal_Int32) 0x7FFFFFFF)) )
4
Assuming the condition is true
6
Taking true branch
271 && !IsEntryPosSelected( mpFloatWin->GetPopupModeStartSaveSelection() ) )
5
Assuming the condition is true
272 {
273 mpImplLB->SelectEntry( mpFloatWin->GetPopupModeStartSaveSelection(), true );
274 bool bTravelSelect = mpImplLB->IsTravelSelect();
275 mpImplLB->SetTravelSelect( true );
276
277 VclPtr<vcl::Window> xWindow = this;
278 Select();
279 if ( xWindow->IsDisposed() )
7
Assuming the condition is false
8
Taking false branch
280 return;
281
282 mpImplLB->SetTravelSelect( bTravelSelect );
283 }
9
Calling implicit destructor for 'VclPtr<vcl::Window>'
10
Calling '~Reference'
17
Returning from '~Reference'
18
Returning from destructor for 'VclPtr<vcl::Window>'
284 }
285
286 ImplClearLayoutData();
19
Use of memory after it is freed
287 if( mpImplLB )
288 mpImplLB->GetMainWindow()->ImplClearLayoutData();
289 if( mpImplWin )
290 mpImplWin->ImplClearLayoutData();
291
292 mpBtn->SetPressed( false );
293 CallEventListeners( VclEventId::DropdownClose );
294}
295
296void ListBox::ToggleDropDown()
297{
298 if( !IsDropDownBox() )
299 return;
300
301 if( mpFloatWin->IsInPopupMode() )
302 mpFloatWin->EndPopupMode();
303 else
304 {
305 CallEventListeners( VclEventId::DropdownPreOpen );
306 mpImplWin->GrabFocus();
307 mpBtn->SetPressed( true );
308 mpFloatWin->StartFloat( true );
309 CallEventListeners( VclEventId::DropdownOpen );
310 }
311}
312
313void ListBox::ApplySettings(vcl::RenderContext& rRenderContext)
314{
315 rRenderContext.SetBackground();
316}
317
318void ListBox::Draw( OutputDevice* pDev, const Point& rPos, DrawFlags nFlags )
319{
320 mpImplLB->GetMainWindow()->ApplySettings(*pDev);
321
322 Point aPos = pDev->LogicToPixel( rPos );
323 Size aSize = GetSizePixel();
324 vcl::Font aFont = mpImplLB->GetMainWindow()->GetDrawPixelFont( pDev );
325
326 pDev->Push();
327 pDev->SetMapMode();
328 pDev->SetFont( aFont );
329 pDev->SetTextFillColor();
330
331 // Border/Background
332 pDev->SetLineColor();
333 pDev->SetFillColor();
334 bool bBorder = (GetStyle() & WB_BORDER);
335 bool bBackground = IsControlBackground();
336 if ( bBorder || bBackground )
337 {
338 tools::Rectangle aRect( aPos, aSize );
339 if ( bBorder )
340 {
341 ImplDrawFrame( pDev, aRect );
342 }
343 if ( bBackground )
344 {
345 pDev->SetFillColor( GetControlBackground() );
346 pDev->DrawRect( aRect );
347 }
348 }
349
350 // Content
351 if ( nFlags & DrawFlags::Mono )
352 {
353 pDev->SetTextColor( COL_BLACK );
354 }
355 else
356 {
357 if ( !IsEnabled() )
358 {
359 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
360 pDev->SetTextColor( rStyleSettings.GetDisableColor() );
361 }
362 else
363 {
364 pDev->SetTextColor( GetTextColor() );
365 }
366 }
367
368 const long nOnePixel = GetDrawPixel( pDev, 1 );
369 const long nOffX = 3*nOnePixel;
370 DrawTextFlags nTextStyle = DrawTextFlags::VCenter;
371 tools::Rectangle aTextRect( aPos, aSize );
372
373 if ( GetStyle() & WB_CENTER )
374 nTextStyle |= DrawTextFlags::Center;
375 else if ( GetStyle() & WB_RIGHT )
376 nTextStyle |= DrawTextFlags::Right;
377 else
378 nTextStyle |= DrawTextFlags::Left;
379
380 aTextRect.AdjustLeft(nOffX );
381 aTextRect.AdjustRight( -nOffX );
382
383 if ( IsDropDownBox() )
384 {
385 OUString aText = GetSelectedEntry();
386 long nTextHeight = pDev->GetTextHeight();
387 long nTextWidth = pDev->GetTextWidth( aText );
388 long nOffY = (aSize.Height()-nTextHeight) / 2;
389
390 // Clipping?
391 if ( (nOffY < 0) ||
392 ((nOffY+nTextHeight) > aSize.Height()) ||
393 ((nOffX+nTextWidth) > aSize.Width()) )
394 {
395 tools::Rectangle aClip( aPos, aSize );
396 if ( nTextHeight > aSize.Height() )
397 aClip.AdjustBottom(nTextHeight-aSize.Height()+1 ); // So that HP Printers don't optimize this away
398 pDev->IntersectClipRegion( aClip );
399 }
400
401 pDev->DrawText( aTextRect, aText, nTextStyle );
402 }
403 else
404 {
405 long nTextHeight = pDev->GetTextHeight();
406 sal_uInt16 nLines = ( nTextHeight > 0 ) ? static_cast<sal_uInt16>(aSize.Height() / nTextHeight) : 1;
407 tools::Rectangle aClip( aPos, aSize );
408
409 pDev->IntersectClipRegion( aClip );
410
411 if ( !nLines )
412 nLines = 1;
413
414 for ( sal_uInt16 n = 0; n < nLines; n++ )
415 {
416 sal_Int32 nEntry = n+mpImplLB->GetTopEntry();
417 bool bSelected = mpImplLB->GetEntryList()->IsEntryPosSelected( nEntry );
418 if ( bSelected )
419 {
420 pDev->SetFillColor( COL_BLACK );
421 pDev->DrawRect( tools::Rectangle( Point( aPos.X(), aPos.Y() + n*nTextHeight ),
422 Point( aPos.X() + aSize.Width(), aPos.Y() + (n+1)*nTextHeight + 2*nOnePixel ) ) );
423 pDev->SetFillColor();
424 pDev->SetTextColor( COL_WHITE );
425 }
426
427 aTextRect.SetTop( aPos.Y() + n*nTextHeight );
428 aTextRect.SetBottom( aTextRect.Top() + nTextHeight );
429
430 pDev->DrawText( aTextRect, mpImplLB->GetEntryList()->GetEntryText( nEntry ), nTextStyle );
431
432 if ( bSelected )
433 pDev->SetTextColor( COL_BLACK );
434 }
435 }
436
437 pDev->Pop();
438}
439
440void ListBox::GetFocus()
441{
442 if ( mpImplLB )
443 {
444 if( IsDropDownBox() )
445 mpImplWin->GrabFocus();
446 else
447 mpImplLB->GrabFocus();
448 }
449
450 Control::GetFocus();
451}
452
453void ListBox::LoseFocus()
454{
455 if( IsDropDownBox() )
456 {
457 if (mpImplWin)
458 mpImplWin->HideFocus();
459 }
460 else
461 {
462 if (mpImplLB)
463 mpImplLB->HideFocus();
464 }
465
466 Control::LoseFocus();
467}
468
469void ListBox::DataChanged( const DataChangedEvent& rDCEvt )
470{
471 Control::DataChanged( rDCEvt );
472
473 if ( !((rDCEvt.GetType() == DataChangedEventType::FONTS) ||
474 (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
475 ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
476 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE))) )
477 return;
478
479 SetBackground(); // Due to a hack in Window::UpdateSettings the background must be reset
480 // otherwise it will overpaint NWF drawn listboxes
481 Resize();
482 mpImplLB->Resize(); // Is not called by ListBox::Resize() if the ImplLB does not change
483
484 if ( mpImplWin )
485 {
486 mpImplWin->SetSettings( GetSettings() ); // If not yet set...
487 mpImplWin->ApplySettings(*mpImplWin);
488
489 mpBtn->SetSettings( GetSettings() );
490 ImplInitDropDownButton( mpBtn );
491 }
492
493 if ( IsDropDownBox() )
494 Invalidate();
495}
496
497void ListBox::EnableAutoSize( bool bAuto )
498{
499 mbDDAutoSize = bAuto;
500 if ( mpFloatWin )
501 {
502 if ( bAuto && !mpFloatWin->GetDropDownLineCount() )
503 {
504 // use GetListBoxMaximumLineCount here; before, was on fixed number of five
505 AdaptDropDownLineCountToMaximum();
506 }
507 else if ( !bAuto )
508 {
509 mpFloatWin->SetDropDownLineCount( 0 );
510 }
511 }
512}
513
514void ListBox::SetDropDownLineCount( sal_uInt16 nLines )
515{
516 mnLineCount = nLines;
517 if ( mpFloatWin )
518 mpFloatWin->SetDropDownLineCount( mnLineCount );
519}
520
521void ListBox::AdaptDropDownLineCountToMaximum()
522{
523 // Adapt to maximum allowed number.
524 // Limit for LOK as we can't render outside of the dialog canvas.
525 if (comphelper::LibreOfficeKit::isActive())
526 SetDropDownLineCount(11);
527 else
528 SetDropDownLineCount(GetSettings().GetStyleSettings().GetListBoxMaximumLineCount());
529}
530
531sal_uInt16 ListBox::GetDropDownLineCount() const
532{
533 if ( mpFloatWin )
534 return mpFloatWin->GetDropDownLineCount();
535 return mnLineCount;
536}
537
538void ListBox::setPosSizePixel( long nX, long nY, long nWidth, long nHeight, PosSizeFlags nFlags )
539{
540 if( IsDropDownBox() && ( nFlags & PosSizeFlags::Size ) )
541 {
542 Size aPrefSz = mpFloatWin->GetPrefSize();
543 if ( ( nFlags & PosSizeFlags::Height ) && ( nHeight >= 2*mnDDHeight ) )
544 aPrefSz.setHeight( nHeight-mnDDHeight );
545 if ( nFlags & PosSizeFlags::Width )
546 aPrefSz.setWidth( nWidth );
547 mpFloatWin->SetPrefSize( aPrefSz );
548
549 if (IsAutoSizeEnabled())
550 nHeight = mnDDHeight;
551 }
552
553 Control::setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
554}
555
556void ListBox::Resize()
557{
558 Size aOutSz = GetOutputSizePixel();
559 if( IsDropDownBox() )
560 {
561 // Initialize the dropdown button size with the standard scrollbar width
562 long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
563 long nBottom = aOutSz.Height();
564
565 // Note: in case of no border, pBorder will actually be this
566 vcl::Window *pBorder = GetWindow( GetWindowType::Border );
567 ImplControlValue aControlValue;
568 Point aPoint;
569 tools::Rectangle aContent, aBound;
570
571 // Use the full extent of the control
572 tools::Rectangle aArea( aPoint, pBorder->GetOutputSizePixel() );
573
574 if ( GetNativeControlRegion( ControlType::Listbox, ControlPart::ButtonDown,
575 aArea, ControlState::NONE, aControlValue, aBound, aContent) )
576 {
577 // Convert back from border space to local coordinates
578 aPoint = pBorder->ScreenToOutputPixel( OutputToScreenPixel( aPoint ) );
579 aContent.Move( -aPoint.X(), -aPoint.Y() );
580
581 // Use the themes drop down size for the button
582 aOutSz.setWidth( aContent.Left() );
583 mpBtn->setPosSizePixel( aContent.Left(), 0, aContent.GetWidth(), nBottom );
584
585 // Adjust the size of the edit field
586 if ( GetNativeControlRegion( ControlType::Listbox, ControlPart::SubEdit,
587 aArea, ControlState::NONE, aControlValue, aBound, aContent) )
588 {
589 // Convert back from border space to local coordinates
590 aContent.Move( -aPoint.X(), -aPoint.Y() );
591
592 // Use the themes drop down size
593 if( ! (GetStyle() & WB_BORDER) && ImplGetSVData()->maNWFData.mbNoFocusRects )
594 {
595 // No border but focus ring behavior -> we have a problem; the
596 // native rect relies on the border to draw the focus
597 // let's do the best we can and center vertically, so it doesn't look
598 // completely wrong.
599 Size aSz( GetOutputSizePixel() );
600 long nDiff = aContent.Top() - (aSz.Height() - aContent.GetHeight())/2;
601 aContent.AdjustTop( -nDiff );
602 aContent.AdjustBottom( -nDiff );
603 }
604 mpImplWin->SetPosSizePixel( aContent.TopLeft(), aContent.GetSize() );
605 }
606 else
607 mpImplWin->SetSizePixel( aOutSz );
608 }
609 else
610 {
611 nSBWidth = CalcZoom( nSBWidth );
612 mpImplWin->setPosSizePixel( 0, 0, aOutSz.Width() - nSBWidth, aOutSz.Height() );
613 mpBtn->setPosSizePixel( aOutSz.Width() - nSBWidth, 0, nSBWidth, aOutSz.Height() );
614 }
615 }
616 else
617 {
618 mpImplLB->SetSizePixel( aOutSz );
619 }
620
621 // Retain FloatingWindow size even when it's invisible, as we still process KEY_PGUP/DOWN ...
622 if ( mpFloatWin )
623 mpFloatWin->SetSizePixel( mpFloatWin->CalcFloatSize() );
624
625 Control::Resize();
626}
627
628void ListBox::FillLayoutData() const
629{
630 mpControlData->mpLayoutData.reset( new vcl::ControlLayoutData );
631 const ImplListBoxWindow* rMainWin = mpImplLB->GetMainWindow();
632 if( mpFloatWin )
633 {
634 // Dropdown mode
635 AppendLayoutData( *mpImplWin );
636 mpImplWin->SetLayoutDataParent( this );
637 if( mpFloatWin->IsReallyVisible() )
638 {
639 AppendLayoutData( *rMainWin );
640 rMainWin->SetLayoutDataParent( this );
641 }
642 }
643 else
644 {
645 AppendLayoutData( *rMainWin );
646 rMainWin->SetLayoutDataParent( this );
647 }
648}
649
650long ListBox::GetIndexForPoint( const Point& rPoint, sal_Int32& rPos ) const
651{
652 if( !HasLayoutData() )
653 FillLayoutData();
654
655 // Check whether rPoint fits at all
656 long nIndex = Control::GetIndexForPoint( rPoint );
657 if( nIndex != -1 )
658 {
659 // Point must be either in main list window
660 // or in impl window (dropdown case)
661 ImplListBoxWindow* rMain = mpImplLB->GetMainWindow();
662
663 // Convert coordinates to ImplListBoxWindow pixel coordinate space
664 Point aConvPoint = LogicToPixel( rPoint );
665 aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint );
666 aConvPoint = rMain->AbsoluteScreenToOutputPixel( aConvPoint );
667 aConvPoint = rMain->PixelToLogic( aConvPoint );
668
669 // Try to find entry
670 sal_Int32 nEntry = rMain->GetEntryPosForPoint( aConvPoint );
671 if( nEntry == LISTBOX_ENTRY_NOTFOUND(((sal_Int32) 0x7FFFFFFF)) )
672 {
673 // Not found, maybe dropdown case
674 if( mpImplWin && mpImplWin->IsReallyVisible() )
675 {
676 // Convert to impl window pixel coordinates
677 aConvPoint = LogicToPixel( rPoint );
678 aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint );
679 aConvPoint = mpImplWin->AbsoluteScreenToOutputPixel( aConvPoint );
680
681 // Check whether converted point is inside impl window
682 Size aImplWinSize = mpImplWin->GetOutputSizePixel();
683 if( aConvPoint.X() >= 0 && aConvPoint.Y() >= 0 && aConvPoint.X() < aImplWinSize.Width() && aConvPoint.Y() < aImplWinSize.Height() )
684 {
685 // Inside the impl window, the position is the current item pos
686 rPos = mpImplWin->GetItemPos();
687 }
688 else
689 nIndex = -1;
690 }
691 else
692 nIndex = -1;
693 }
694 else
695 rPos = nEntry;
696
697 SAL_WARN_IF( nIndex == -1, "vcl", "found index for point, but relative index failed" )do { if (true && (nIndex == -1)) { 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() << "found index for point, but relative index failed"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"
), ("/home/maarten/src/libreoffice/core/vcl/source/control/listbox.cxx"
":" "697" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "found index for point, but relative index failed"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "found index for point, but relative index failed";
::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), (
"/home/maarten/src/libreoffice/core/vcl/source/control/listbox.cxx"
":" "697" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "found index for point, but relative index failed"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"
), ("/home/maarten/src/libreoffice/core/vcl/source/control/listbox.cxx"
":" "697" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "found index for point, but relative index failed"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "found index for point, but relative index failed";
::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), (
"/home/maarten/src/libreoffice/core/vcl/source/control/listbox.cxx"
":" "697" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
698 }
699
700 // Get line relative index
701 if( nIndex != -1 )
702 nIndex = ToRelativeLineIndex( nIndex );
703
704 return nIndex;
705}
706
707void ListBox::StateChanged( StateChangedType nType )
708{
709 if( nType == StateChangedType::ReadOnly )
710 {
711 if( mpImplWin )
712 mpImplWin->Enable( !IsReadOnly() );
713 if( mpBtn )
714 mpBtn->Enable( !IsReadOnly() );
715 }
716 else if( nType == StateChangedType::Enable )
717 {
718 mpImplLB->Enable( IsEnabled() );
719 if( mpImplWin )
720 {
721 mpImplWin->Enable( IsEnabled() );
722 if ( IsNativeControlSupported(ControlType::Listbox, ControlPart::Entire)
723 && ! IsNativeControlSupported(ControlType::Listbox, ControlPart::ButtonDown) )
724 {
725 GetWindow( GetWindowType::Border )->Invalidate( InvalidateFlags::NoErase );
726 }
727 else
728 mpImplWin->Invalidate();
729 }
730 if( mpBtn )
731 mpBtn->Enable( IsEnabled() );
732 }
733 else if( nType == StateChangedType::UpdateMode )
734 {
735 mpImplLB->SetUpdateMode( IsUpdateMode() );
736 }
737 else if ( nType == StateChangedType::Zoom )
738 {
739 mpImplLB->SetZoom( GetZoom() );
740 if ( mpImplWin )
741 {
742 mpImplWin->SetZoom( GetZoom() );
743 mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
744 mpImplWin->Invalidate();
745 }
746 Resize();
747 }
748 else if ( nType == StateChangedType::ControlFont )
749 {
750 mpImplLB->SetControlFont( GetControlFont() );
751 if ( mpImplWin )
752 {
753 mpImplWin->SetControlFont( GetControlFont() );
754 mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
755 mpImplWin->Invalidate();
756 }
757 Resize();
758 }
759 else if ( nType == StateChangedType::ControlForeground )
760 {
761 mpImplLB->SetControlForeground( GetControlForeground() );
762 if ( mpImplWin )
763 {
764 mpImplWin->SetControlForeground( GetControlForeground() );
765 mpImplWin->SetTextColor( GetControlForeground() );
766 mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
767 mpImplWin->Invalidate();
768 }
769 }
770 else if ( nType == StateChangedType::ControlBackground )
771 {
772 mpImplLB->SetControlBackground( GetControlBackground() );
773 if ( mpImplWin )
774 {
775 if ( mpImplWin->IsNativeControlSupported(ControlType::Listbox, ControlPart::Entire) )
776 {
777 // Transparent background
778 mpImplWin->SetBackground();
779 mpImplWin->SetControlBackground();
780 }
781 else
782 {
783 mpImplWin->SetBackground( mpImplLB->GetMainWindow()->GetControlBackground() );
784 mpImplWin->SetControlBackground( mpImplLB->GetMainWindow()->GetControlBackground() );
785 }
786 mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
787 mpImplWin->Invalidate();
788 }
789 }
790 else if ( nType == StateChangedType::Style )
791 {
792 SetStyle( ImplInitStyle( GetStyle() ) );
793 mpImplLB->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT ) != 0 );
794 bool bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) != 0;
795 mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode );
796 }
797 else if( nType == StateChangedType::Mirroring )
798 {
799 if( mpBtn )
800 {
801 mpBtn->EnableRTL( IsRTLEnabled() );
802 ImplInitDropDownButton( mpBtn );
803 }
804 mpImplLB->EnableRTL( IsRTLEnabled() );
805 if( mpImplWin )
806 mpImplWin->EnableRTL( IsRTLEnabled() );
807 Resize();
808 }
809
810 Control::StateChanged( nType );
811}
812
813bool ListBox::PreNotify( NotifyEvent& rNEvt )
814{
815 bool bDone = false;
816 if ( mpImplLB )
817 {
818 if( ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ) && ( rNEvt.GetWindow() == mpImplWin ) )
819 {
820 KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
821 switch( aKeyEvt.GetKeyCode().GetCode() )
822 {
823 case KEY_DOWN:
824 {
825 if( mpFloatWin && !mpFloatWin->IsInPopupMode() &&
826 aKeyEvt.GetKeyCode().IsMod2() )
827 {
828 CallEventListeners( VclEventId::DropdownPreOpen );
829 mpBtn->SetPressed( true );
830 mpFloatWin->StartFloat( false );
831 CallEventListeners( VclEventId::DropdownOpen );
832 bDone = true;
833 }
834 else
835 {
836 bDone = mpImplLB->ProcessKeyInput( aKeyEvt );
837 }
838 }
839 break;
840 case KEY_UP:
841 {
842 if( mpFloatWin && mpFloatWin->IsInPopupMode() &&
843 aKeyEvt.GetKeyCode().IsMod2() )
844 {
845 mpFloatWin->EndPopupMode();
846 bDone = true;
847 }
848 else
849 {
850 bDone = mpImplLB->ProcessKeyInput( aKeyEvt );
851 }
852 }
853 break;
854 case KEY_RETURN:
855 {
856 if( IsInDropDown() )
857 {
858 mpImplLB->ProcessKeyInput( aKeyEvt );
859 bDone = true;
860 }
861 }
862 break;
863
864 default:
865 {
866 bDone = mpImplLB->ProcessKeyInput( aKeyEvt );
867 }
868 }
869 }
870 else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
871 {
872 if ( IsInDropDown() && !HasChildPathFocus( true ) )
873 mpFloatWin->EndPopupMode();
874 }
875 else if ( (rNEvt.GetType() == MouseNotifyEvent::COMMAND) &&
876 (rNEvt.GetCommandEvent()->GetCommand() == CommandEventId::Wheel) &&
877 (rNEvt.GetWindow() == mpImplWin) )
878 {
879 MouseWheelBehaviour nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() );
880 if ( ( nWheelBehavior == MouseWheelBehaviour::ALWAYS )
881 || ( ( nWheelBehavior == MouseWheelBehaviour::FocusOnly )
882 && HasChildPathFocus()
883 )
884 )
885 {
886 bDone = mpImplLB->HandleWheelAsCursorTravel(*rNEvt.GetCommandEvent(), *this);
887 }
888 else
889 {
890 bDone = false; // Don't consume this event, let the default handling take it (i.e. scroll the context)
891 }
892 }
893 }
894
895 return bDone || Control::PreNotify( rNEvt );
896}
897
898void ListBox::Select()
899{
900 ImplCallEventListenersAndHandler( VclEventId::ListboxSelect, [this] () { maSelectHdl.Call(*this); } );
901}
902
903void ListBox::DoubleClick()
904{
905 ImplCallEventListenersAndHandler( VclEventId::ListboxDoubleClick, {} );
906}
907
908void ListBox::Clear()
909{
910 if (!mpImplLB)
911 return;
912 mpImplLB->Clear();
913 if( IsDropDownBox() )
914 {
915 mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND(((sal_Int32) 0x7FFFFFFF)) );
916 mpImplWin->SetString( OUString() );
917 Image aImage;
918 mpImplWin->SetImage( aImage );
919 mpImplWin->Invalidate();
920 }
921 CallEventListeners( VclEventId::ListboxItemRemoved, reinterpret_cast<void*>(-1) );
922}
923
924void ListBox::SetNoSelection()
925{
926 mpImplLB->SetNoSelection();
927 if( IsDropDownBox() )
928 {
929 mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND(((sal_Int32) 0x7FFFFFFF)) );
930 mpImplWin->SetString( OUString() );
931 Image aImage;
932 mpImplWin->SetImage( aImage );
933 mpImplWin->Invalidate();
934 }
935}
936
937sal_Int32 ListBox::InsertEntry( const OUString& rStr, sal_Int32 nPos )
938{
939 sal_Int32 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr );
940 nRealPos = sal::static_int_cast<sal_Int32>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
941 CallEventListeners( VclEventId::ListboxItemAdded, reinterpret_cast<void*>(nRealPos) );
942 return nRealPos;
943}
944
945sal_Int32 ListBox::InsertEntry( const OUString& rStr, const Image& rImage, sal_Int32 nPos )
946{
947 sal_Int32 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr, rImage );
948 nRealPos = sal::static_int_cast<sal_Int32>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
949 CallEventListeners( VclEventId::ListboxItemAdded, reinterpret_cast<void*>(nRealPos) );
950 return nRealPos;
951}
952
953void ListBox::RemoveEntry( sal_Int32 nPos )
954{
955 mpImplLB->RemoveEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
956 CallEventListeners( VclEventId::ListboxItemRemoved, reinterpret_cast<void*>(nPos) );
957}
958
959Image ListBox::GetEntryImage( sal_Int32 nPos ) const
960{
961 if ( mpImplLB && mpImplLB->GetEntryList()->HasEntryImage( nPos ) )
962 return mpImplLB->GetEntryList()->GetEntryImage( nPos );
963 return Image();
964}
965
966sal_Int32 ListBox::GetEntryPos( const OUString& rStr ) const
967{
968 if (!mpImplLB)
969 return LISTBOX_ENTRY_NOTFOUND(((sal_Int32) 0x7FFFFFFF));
970 sal_Int32 nPos = mpImplLB->GetEntryList()->FindEntry( rStr );
971 if ( nPos != LISTBOX_ENTRY_NOTFOUND(((sal_Int32) 0x7FFFFFFF)) )
972 nPos = nPos - mpImplLB->GetEntryList()->GetMRUCount();
973 return nPos;
974}
975
976OUString ListBox::GetEntry( sal_Int32 nPos ) const
977{
978 if (!mpImplLB)
979 return OUString();
980 return mpImplLB->GetEntryList()->GetEntryText( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
981}
982
983sal_Int32 ListBox::GetEntryCount() const
984{
985 if (!mpImplLB)
986 return 0;
987 return mpImplLB->GetEntryList()->GetEntryCount() - mpImplLB->GetEntryList()->GetMRUCount();
988}
989
990OUString ListBox::GetSelectedEntry(sal_Int32 nIndex) const
991{
992 return GetEntry( GetSelectedEntryPos( nIndex ) );
993}
994
995sal_Int32 ListBox::GetSelectedEntryCount() const
996{
997 if (!mpImplLB)
998 return 0;
999 return mpImplLB->GetEntryList()->GetSelectedEntryCount();
1000}
1001
1002sal_Int32 ListBox::GetSelectedEntryPos( sal_Int32 nIndex ) const
1003{
1004 if (!mpImplLB || !mpImplLB->GetEntryList())
1005 return LISTBOX_ENTRY_NOTFOUND(((sal_Int32) 0x7FFFFFFF));
1006
1007 sal_Int32 nPos = mpImplLB->GetEntryList()->GetSelectedEntryPos( nIndex );
1008 if ( nPos != LISTBOX_ENTRY_NOTFOUND(((sal_Int32) 0x7FFFFFFF)) )
1009 {
1010 if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() )
1011 nPos = mpImplLB->GetEntryList()->FindEntry( mpImplLB->GetEntryList()->GetEntryText( nPos ) );
1012 nPos = nPos - mpImplLB->GetEntryList()->GetMRUCount();
1013 }
1014 return nPos;
1015}
1016
1017bool ListBox::IsEntryPosSelected( sal_Int32 nPos ) const
1018{
1019 return mpImplLB->GetEntryList()->IsEntryPosSelected( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1020}
1021
1022void ListBox::SelectEntry( const OUString& rStr, bool bSelect )
1023{
1024 SelectEntryPos( GetEntryPos( rStr ), bSelect );
1025}
1026
1027void ListBox::SelectEntryPos( sal_Int32 nPos, bool bSelect )
1028{
1029 if (!mpImplLB)
1030 return;
1031
1032 if ( 0 <= nPos && nPos < mpImplLB->GetEntryList()->GetEntryCount() )
1033 {
1034 sal_Int32 nCurrentPos = mpImplLB->GetCurrentPos();
1035 mpImplLB->SelectEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), bSelect );
1036 //Only when bSelect == true, send both Selection & Focus events
1037 if (nCurrentPos != nPos && bSelect)
1038 {
1039 CallEventListeners( VclEventId::ListboxSelect, reinterpret_cast<void*>(nPos));
1040 if (HasFocus())
1041 CallEventListeners( VclEventId::ListboxFocus, reinterpret_cast<void*>(nPos));
1042 }
1043 }
1044}
1045
1046void ListBox::SelectEntriesPos( const std::vector<sal_Int32>& rPositions, bool bSelect )
1047{
1048 if (!mpImplLB)
1049 return;
1050
1051 bool bCallListeners = false;
1052
1053 const sal_Int32 nCurrentPos = mpImplLB->GetCurrentPos();
1054 const auto nEntryCount = mpImplLB->GetEntryList()->GetEntryCount();
1055 const auto nMRUCount = mpImplLB->GetEntryList()->GetMRUCount();
1056
1057 for (auto nPos : rPositions)
1058 {
1059 if (0 <= nPos && nPos < nEntryCount)
1060 {
1061 mpImplLB->SelectEntry(nPos + nMRUCount, bSelect);
1062 if (nCurrentPos != nPos && bSelect)
1063 bCallListeners = true;
1064 }
1065 }
1066
1067 //Only when bSelect == true, send both Selection & Focus events
1068 if (bCallListeners)
1069 {
1070 CallEventListeners(VclEventId::ListboxSelect);
1071 if (HasFocus())
1072 CallEventListeners(VclEventId::ListboxFocus);
1073 }
1074}
1075
1076void ListBox::SetEntryData( sal_Int32 nPos, void* pNewData )
1077{
1078 mpImplLB->SetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount(), pNewData );
1079}
1080
1081void* ListBox::GetEntryData( sal_Int32 nPos ) const
1082{
1083 return mpImplLB->GetEntryList()->GetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1084}
1085
1086void ListBox::SetEntryFlags( sal_Int32 nPos, ListBoxEntryFlags nFlags )
1087{
1088 mpImplLB->SetEntryFlags( nPos + mpImplLB->GetEntryList()->GetMRUCount(), nFlags );
1089}
1090
1091void ListBox::SetTopEntry( sal_Int32 nPos )
1092{
1093 mpImplLB->SetTopEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1094}
1095
1096sal_Int32 ListBox::GetTopEntry() const
1097{
1098 sal_Int32 nPos = GetEntryCount() ? mpImplLB->GetTopEntry() : LISTBOX_ENTRY_NOTFOUND(((sal_Int32) 0x7FFFFFFF));
1099 if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() )
1100 nPos = 0;
1101 return nPos;
1102}
1103
1104bool ListBox::IsTravelSelect() const
1105{
1106 return mpImplLB->IsTravelSelect();
1107}
1108
1109bool ListBox::IsInDropDown() const
1110{
1111 // when the dropdown is dismissed, first mbInPopupMode is set to false, and on the next event iteration then
1112 // mbPopupMode is set to false
1113 return mpFloatWin && mpFloatWin->IsInPopupMode() && mpFloatWin->ImplIsInPrivatePopupMode();
1114}
1115
1116tools::Rectangle ListBox::GetBoundingRectangle( sal_Int32 nItem ) const
1117{
1118 tools::Rectangle aRect = mpImplLB->GetMainWindow()->GetBoundingRectangle( nItem );
1119 tools::Rectangle aOffset = mpImplLB->GetMainWindow()->GetWindowExtentsRelative( static_cast<vcl::Window*>(const_cast<ListBox *>(this)) );
1120 aRect.Move( aOffset.TopLeft().X(), aOffset.TopLeft().Y() );
1121 return aRect;
1122}
1123
1124void ListBox::EnableMultiSelection( bool bMulti )
1125{
1126 mpImplLB->EnableMultiSelection( bMulti );
1127
1128 // WB_SIMPLEMODE:
1129 // The MultiListBox behaves just like a normal ListBox
1130 // MultiSelection is possible via corresponding additional keys
1131 bool bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) != 0;
1132 mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode );
1133
1134 // In a MultiSelection, we can't see us travelling without focus
1135 if ( mpFloatWin )
1136 mpImplLB->GetMainWindow()->AllowGrabFocus( bMulti );
1137}
1138
1139bool ListBox::IsMultiSelectionEnabled() const
1140{
1141 return mpImplLB->IsMultiSelectionEnabled();
1142}
1143
1144Size ListBox::CalcMinimumSize() const
1145{
1146 Size aSz;
1147
1148 if (!mpImplLB)
1149 return aSz;
1150
1151 aSz = CalcSubEditSize();
1152
1153 bool bAddScrollWidth = false;
1154
1155 if (IsDropDownBox())
1156 {
1157 aSz.AdjustHeight(4 ); // add a space between entry and border
1158 aSz.AdjustWidth(4 ); // add a little breathing space
1159 bAddScrollWidth = true;
1160 }
1161 else
1162 bAddScrollWidth = (GetStyle() & WB_VSCROLL) == WB_VSCROLL;
1163
1164 if (bAddScrollWidth)
1165 {
1166 // Try native borders; scrollbar size may not be a good indicator
1167 // See how large the edit area inside is to estimate what is needed for the dropdown
1168 ImplControlValue aControlValue;
1169 tools::Rectangle aContent, aBound;
1170 Size aTestSize( 100, 20 );
1171 tools::Rectangle aArea( Point(), aTestSize );
1172 if( GetNativeControlRegion( ControlType::Listbox, ControlPart::SubEdit, aArea, ControlState::NONE,
1173 aControlValue, aBound, aContent) )
1174 {
1175 // use the themes drop down size
1176 aSz.AdjustWidth(aTestSize.Width() - aContent.GetWidth() );
1177 }
1178 else
1179 aSz.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() );
1180 }
1181
1182 aSz = CalcWindowSize( aSz );
1183
1184 if (IsDropDownBox()) // Check minimum height of dropdown box
1185 {
1186 ImplControlValue aControlValue;
1187 tools::Rectangle aRect( Point( 0, 0 ), aSz );
1188 tools::Rectangle aContent, aBound;
1189 if( GetNativeControlRegion( ControlType::Listbox, ControlPart::Entire, aRect, ControlState::NONE,
1190 aControlValue, aBound, aContent) )
1191 {
1192 if( aBound.GetHeight() > aSz.Height() )
1193 aSz.setHeight( aBound.GetHeight() );
1194 }
1195 }
1196
1197 return aSz;
1198}
1199
1200Size ListBox::CalcSubEditSize() const
1201{
1202 Size aSz;
1203
1204 if (!mpImplLB)
1205 return aSz;
1206
1207 if ( !IsDropDownBox() )
1208 aSz = mpImplLB->CalcSize (mnLineCount ? mnLineCount : mpImplLB->GetEntryList()->GetEntryCount());
1209 else
1210 {
1211 aSz.setHeight( mpImplLB->GetEntryHeight() );
1212 // Size to maximum entry width
1213 aSz.setWidth( mpImplLB->GetMaxEntryWidth() );
1214
1215 if (m_nMaxWidthChars != -1)
1216 {
1217 long nMaxWidth = m_nMaxWidthChars * approximate_char_width();
1218 aSz.setWidth( std::min(aSz.Width(), nMaxWidth) );
1219 }
1220
1221 // Do not create ultrathin ListBoxes, it doesn't look good
1222 if( aSz.Width() < GetSettings().GetStyleSettings().GetScrollBarSize() )
1223 aSz.setWidth( GetSettings().GetStyleSettings().GetScrollBarSize() );
1224 }
1225
1226 return aSz;
1227}
1228
1229Size ListBox::GetOptimalSize() const
1230{
1231 return CalcMinimumSize();
1232}
1233
1234Size ListBox::CalcAdjustedSize( const Size& rPrefSize ) const
1235{
1236 Size aSz = rPrefSize;
1237 sal_Int32 nLeft, nTop, nRight, nBottom;
1238 static_cast<vcl::Window*>(const_cast<ListBox *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
1239 aSz.AdjustHeight( -(nTop+nBottom) );
1240 if ( !IsDropDownBox() )
1241 {
1242 long nEntryHeight = CalcBlockSize( 1, 1 ).Height();
1243 long nLines = aSz.Height() / nEntryHeight;
1244 if ( nLines < 1 )
1245 nLines = 1;
1246 aSz.setHeight( nLines * nEntryHeight );
1247 }
1248 else
1249 {
1250 aSz.setHeight( mnDDHeight );
1251 }
1252 aSz.AdjustHeight(nTop+nBottom );
1253
1254 aSz = CalcWindowSize( aSz );
1255 return aSz;
1256}
1257
1258Size ListBox::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
1259{
1260 // ScrollBars are shown if needed
1261 Size aMinSz = CalcMinimumSize();
1262 // aMinSz = ImplCalcOutSz( aMinSz );
1263
1264 Size aSz;
1265
1266 // Height
1267 if ( nLines )
1268 {
1269 if ( !IsDropDownBox() )
1270 aSz.setHeight( mpImplLB->CalcSize( nLines ).Height() );
1271 else
1272 aSz.setHeight( mnDDHeight );
1273 }
1274 else
1275 aSz.setHeight( aMinSz.Height() );
1276
1277 // Width
1278 if ( nColumns )
1279 aSz.setWidth( nColumns * GetTextWidth( OUString('X') ) );
1280 else
1281 aSz.setWidth( aMinSz.Width() );
1282
1283 if ( IsDropDownBox() )
1284 aSz.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() );
1285
1286 if ( !IsDropDownBox() )
1287 {
1288 if ( aSz.Width() < aMinSz.Width() )
1289 aSz.AdjustHeight(GetSettings().GetStyleSettings().GetScrollBarSize() );
1290 if ( aSz.Height() < aMinSz.Height() )
1291 aSz.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() );
1292 }
1293
1294 aSz = CalcWindowSize( aSz );
1295 return aSz;
1296}
1297
1298void ListBox::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
1299{
1300 float nCharWidth = approximate_char_width();
1301 if ( !IsDropDownBox() )
1302 {
1303 Size aOutSz = mpImplLB->GetMainWindow()->GetOutputSizePixel();
1304 rnCols = static_cast<sal_uInt16>(aOutSz.Width()/nCharWidth);
1305 rnLines = static_cast<sal_uInt16>(aOutSz.Height()/mpImplLB->GetEntryHeightWithMargin());
1306 }
1307 else
1308 {
1309 Size aOutSz = mpImplWin->GetOutputSizePixel();
1310 rnCols = static_cast<sal_uInt16>(aOutSz.Width()/nCharWidth);
1311 rnLines = 1;
1312 }
1313}
1314
1315void ListBox::SetReadOnly( bool bReadOnly )
1316{
1317 if ( mpImplLB->IsReadOnly() != bReadOnly )
1318 {
1319 mpImplLB->SetReadOnly( bReadOnly );
1320 CompatStateChanged( StateChangedType::ReadOnly );
1321 }
1322}
1323
1324bool ListBox::IsReadOnly() const
1325{
1326 return mpImplLB->IsReadOnly();
1327}
1328
1329void ListBox::SetSeparatorPos( sal_Int32 n )
1330{
1331 mpImplLB->SetSeparatorPos( n );
1332}
1333
1334sal_Int32 ListBox::GetSeparatorPos() const
1335{
1336 return mpImplLB->GetSeparatorPos();
1337}
1338
1339void ListBox::AddSeparator( sal_Int32 n )
1340{
1341 mpImplLB->AddSeparator( n );
1342}
1343
1344sal_uInt16 ListBox::GetDisplayLineCount() const
1345{
1346 return mpImplLB->GetDisplayLineCount();
1347}
1348
1349tools::Rectangle ListBox::GetDropDownPosSizePixel() const
1350{
1351 return mpFloatWin ? mpFloatWin->GetWindowExtentsRelative(this) : tools::Rectangle();
1352}
1353
1354const Wallpaper& ListBox::GetDisplayBackground() const
1355{
1356 // !!! Recursion does not occur because the ImplListBox is initialized by default
1357 // to a non-transparent color in Window::ImplInitData
1358 return mpImplLB->GetDisplayBackground();
1359}
1360
1361void ListBox::setMaxWidthChars(sal_Int32 nWidth)
1362{
1363 if (nWidth != m_nMaxWidthChars)
1364 {
1365 m_nMaxWidthChars = nWidth;
1366 queue_resize();
1367 }
1368}
1369
1370bool ListBox::set_property(const OString &rKey, const OUString &rValue)
1371{
1372 if (rKey == "active")
1373 SelectEntryPos(rValue.toInt32());
1374 else if (rKey == "max-width-chars")
1375 setMaxWidthChars(rValue.toInt32());
1376 else if (rKey == "can-focus")
1377 {
1378 // as far as I can see in Gtk, setting a ComboBox as can.focus means
1379 // the focus gets stuck in it, so try here to behave like gtk does
1380 // with the settings that work, i.e. can.focus of false doesn't
1381 // set the hard WB_NOTABSTOP
1382 WinBits nBits = GetStyle();
1383 nBits &= ~(WB_TABSTOP|WB_NOTABSTOP);
1384 if (toBool(rValue))
1385 nBits |= WB_TABSTOP;
1386 SetStyle(nBits);
1387 }
1388 else
1389 return Control::set_property(rKey, rValue);
1390 return true;
1391}
1392
1393FactoryFunction ListBox::GetUITestFactory() const
1394{
1395 return ListBoxUIObject::create;
1396}
1397
1398void ListBox::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
1399{
1400 Control::DumpAsPropertyTree(rJsonWriter);
1401
1402 {
1403 auto entriesNode = rJsonWriter.startNode("entries");
1404 for (int i = 0; i < GetEntryCount(); ++i)
1405 {
1406 auto entryNode = rJsonWriter.startNode("");
1407 rJsonWriter.put("", GetEntry(i));
1408 }
1409 }
1410
1411 rJsonWriter.put("selectedCount", GetSelectedEntryCount());
1412
1413 {
1414 auto entriesNode = rJsonWriter.startNode("selectedEntries");
1415 for (int i = 0; i < GetSelectedEntryCount(); ++i)
1416 {
1417 auto entryNode = rJsonWriter.startNode("");
1418 rJsonWriter.put("", GetSelectedEntryPos(i));
1419 }
1420 }
1421}
1422
1423MultiListBox::MultiListBox( vcl::Window* pParent, WinBits nStyle ) :
1424 ListBox( WindowType::MULTILISTBOX )
1425{
1426 ImplInit( pParent, nStyle );
1427 EnableMultiSelection( true );
1428}
1429
1430/* 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
10.1
Field 'm_pBody' is non-null
10.1
Field 'm_pBody' is non-null
10.1
Field 'm_pBody' is non-null
)
11
Taking true branch
113 m_pBody->release();
12
Calling 'VclReferenceBase::release'
16
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;
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)
13
Assuming the condition is true
14
Taking true branch
40 delete this;
15
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