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 wrtsh1.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/wrtsh/wrtsh1.cxx

/home/maarten/src/libreoffice/core/sw/source/uibase/wrtsh/wrtsh1.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 <com/sun/star/beans/XPropertySet.hpp>
21#include <com/sun/star/container/XChild.hpp>
22#include <com/sun/star/embed/EmbedMisc.hpp>
23#include <com/sun/star/embed/EmbedStates.hpp>
24#include <com/sun/star/embed/EmbedVerbs.hpp>
25#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
26#include <com/sun/star/chart2/XChartDocument.hpp>
27#include <com/sun/star/util/XModifiable.hpp>
28
29#include <hintids.hxx>
30#include <sot/exchange.hxx>
31#include <svx/hdft.hxx>
32#include <svx/svdview.hxx>
33#include <svl/itemiter.hxx>
34#include <tools/bigint.hxx>
35#include <svtools/insdlg.hxx>
36#include <sfx2/ipclient.hxx>
37#include <editeng/formatbreakitem.hxx>
38#include <editeng/svxacorr.hxx>
39#include <editeng/ulspitem.hxx>
40#include <vcl/graph.hxx>
41#include <unotools/charclass.hxx>
42#include <comphelper/storagehelper.hxx>
43#include <svx/svxdlg.hxx>
44#include <svx/extrusionbar.hxx>
45#include <svx/fontworkbar.hxx>
46#include <dialoghelp.hxx>
47#include <frmfmt.hxx>
48#include <fmtftn.hxx>
49#include <fmthdft.hxx>
50#include <fmtpdsc.hxx>
51#include <txtfrm.hxx>
52#include <wdocsh.hxx>
53#include <swmodule.hxx>
54#include <wrtsh.hxx>
55#include <view.hxx>
56#include <cmdid.h>
57#include <pagedesc.hxx>
58#include <frmmgr.hxx>
59#include <swundo.hxx>
60#include <swcli.hxx>
61#include <poolfmt.hxx>
62#include <edtwin.hxx>
63#include <fmtcol.hxx>
64#include <swtable.hxx>
65#include <viscrs.hxx>
66#include <swdtflvr.hxx>
67#include <doc.hxx>
68#include <IDocumentSettingAccess.hxx>
69#include <SwCapObjType.hxx>
70#include <SwStyleNameMapper.hxx>
71#include <sfx2/request.hxx>
72#include <paratr.hxx>
73#include <ndtxt.hxx>
74#include <editeng/acorrcfg.hxx>
75#include <IMark.hxx>
76#include <sfx2/bindings.hxx>
77#include <flyfrm.hxx>
78
79// -> #111827#
80#include <SwRewriter.hxx>
81#include <strings.hrc>
82// <- #111827#
83
84#include <toolkit/helper/vclunohelper.hxx>
85#include <sfx2/viewfrm.hxx>
86#include <vcl/uitest/logger.hxx>
87#include <vcl/uitest/eventdescription.hxx>
88
89#include <PostItMgr.hxx>
90#include <FrameControlsManager.hxx>
91#include <fldmgr.hxx>
92#include <docufld.hxx>
93#include <IDocumentFieldsAccess.hxx>
94#include <fmtfld.hxx>
95
96#include <sfx2/msgpool.hxx>
97#include <sfx2/msg.hxx>
98#include <svtools/embedhlp.hxx>
99#include <svx/postattr.hxx>
100#include <comphelper/lok.hxx>
101#include <memory>
102
103#include <frmtool.hxx>
104#include <viewopt.hxx>
105
106using namespace sw::mark;
107using namespace com::sun::star;
108namespace {
109
110void collectUIInformation(const OUString& rAction, const OUString& aParameters)
111{
112 EventDescription aDescription;
113 aDescription.aAction = rAction;
114 aDescription.aParameters = {{"parameters", aParameters}};
115 aDescription.aID = "writer_edit";
116 aDescription.aKeyWord = "SwEditWinUIObject";
117 aDescription.aParent = "MainWindow";
118 UITestLogger::getInstance().logEvent(aDescription);
119}
120
121}
122
123#define BITFLD_INI_LISTm_bClearMark = m_bIns = true; m_bAddMode = m_bBlockMode = m_bExtMode
= m_bInSelect = m_bLayoutMode = m_bSelWrd = m_bSelLn = m_bRetainSelection
= false; m_bIsInClickToEdit = false;
\
124 m_bClearMark = \
125 m_bIns = true;\
126 m_bAddMode = \
127 m_bBlockMode = \
128 m_bExtMode = \
129 m_bInSelect = \
130 m_bLayoutMode = \
131 m_bSelWrd = \
132 m_bSelLn = \
133 m_bRetainSelection = false; \
134 m_bIsInClickToEdit = false;
135
136static SvxAutoCorrect* lcl_IsAutoCorr()
137{
138 SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
139 if( pACorr && !pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
140 ACFlags::AddNonBrkSpace | ACFlags::ChgOrdinalNumber | ACFlags::TransliterateRTL |
141 ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr | ACFlags::Autocorrect ))
142 pACorr = nullptr;
143 return pACorr;
144}
145
146void SwWrtShell::NoEdit(bool bHideCursor)
147{
148 if(bHideCursor)
149 HideCursor();
150}
151
152void SwWrtShell::Edit()
153{
154 if (CanInsert())
155 {
156 ShowCursor();
157 }
158}
159
160bool SwWrtShell::IsEndWrd()
161{
162 SwMvContext aMvContext(this);
163 if(IsEndPara() && !IsSttPara())
164 return true;
165
166 return IsEndWord();
167}
168
169// Insert string
170void SwWrtShell::InsertByWord( const OUString & rStr)
171{
172 if( rStr.isEmpty() )
173 return;
174
175 bool bDelim = GetAppCharClass().isLetterNumeric( rStr, 0 );
176 sal_Int32 nPos = 0, nStt = 0;
177 for( ; nPos < rStr.getLength(); nPos++ )
178 {
179 bool bTmpDelim = GetAppCharClass().isLetterNumeric( rStr, nPos );
180 if( bTmpDelim != bDelim )
181 {
182 Insert( rStr.copy( nStt, nPos - nStt ));
183 nStt = nPos;
184 }
185 }
186 if( nStt != nPos )
187 Insert( rStr.copy( nStt, nPos - nStt ));
188}
189
190void SwWrtShell::Insert( const OUString &rStr )
191{
192 ResetCursorStack();
193 if( !CanInsert() )
194 return;
195
196 bool bStarted = false;
197 bool bHasSel = HasSelection(),
198 bCallIns = m_bIns /*|| bHasSel*/;
199 bool bDeleted = false;
200
201 typedef svl::Items<RES_CHRATR_BEGIN, RES_CHRATR_RSID - 1,
202 RES_CHRATR_RSID + 1, RES_CHRATR_END - 1,
203 RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT> CharItems;
204 SfxItemSet aCharAttrSet(GetAttrPool(), CharItems{});
205
206 if( bHasSel || ( !m_bIns && SelectHiddenRange() ) )
207 {
208 // Only here parenthesizing, because the normal
209 // insert is already in parentheses at Editshell.
210 StartAllAction();
211
212 SwRewriter aRewriter;
213
214 aRewriter.AddRule(UndoArg1, GetCursorDescr());
215 aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDSreinterpret_cast<char const *>("STR_YIELDS" "\004" u8"→"
)
));
216 {
217 OUString aTmpStr = SwResId(STR_START_QUOTEreinterpret_cast<char const *>("STR_START_QUOTE" "\004"
u8"“")
) +
218 rStr + SwResId(STR_END_QUOTEreinterpret_cast<char const *>("STR_END_QUOTE" "\004" u8"”"
)
);
219
220 aRewriter.AddRule(UndoArg3, aTmpStr);
221 }
222
223 // tdf#79717 Save character formatting of the start of the selection
224 const SwPosition *pStart = GetCursor()->Start();
225 SwPaM aPaM(pStart->nNode.GetNode(), pStart->nContent.GetIndex(),
226 pStart->nNode.GetNode(), pStart->nContent.GetIndex() + 1);
227 GetPaMAttr(&aPaM, aCharAttrSet);
228
229 StartUndo(SwUndoId::REPLACE, &aRewriter);
230 bStarted = true;
231 bDeleted = DelRight();
232 }
233
234 bCallIns ?
235 SwEditShell::Insert2( rStr, bDeleted ) : SwEditShell::Overwrite( rStr );
236
237 if( bDeleted )
238 {
239 // tdf#79717 Restore formatting of the deleted selection
240 SwPosition* pEnd = GetCursor()->Start();
241 SwPaM aPaM(pEnd->nNode.GetNode(), pEnd->nContent.GetIndex() - rStr.getLength(),
242 pEnd->nNode.GetNode(), pEnd->nContent.GetIndex());
243
244 std::set<sal_uInt16> aAttribs;
245 for (sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; ++i)
246 if (i != sal_uInt16(RES_CHRATR_RSID))
247 aAttribs.insert(aAttribs.end(), i);
248 aAttribs.insert(aAttribs.end(), RES_TXTATR_CHARFMT);
249 ResetAttr(aAttribs, &aPaM);
250
251 SetAttrSet(aCharAttrSet, SetAttrMode::DEFAULT, &aPaM);
252 }
253
254 if( bStarted )
255 {
256 EndUndo();
257 EndAllAction();
258 }
259}
260
261// Maximum height limit not possible, because the maximum height
262// of the current frame can not be obtained.
263
264void SwWrtShell::Insert( const OUString &rPath, const OUString &rFilter,
265 const Graphic &rGrf, SwFlyFrameAttrMgr *pFrameMgr,
266 RndStdIds nAnchorType )
267{
268 ResetCursorStack();
269 if ( !CanInsert() )
270 return;
271
272 StartAllAction();
273
274 SwRewriter aRewriter;
275 aRewriter.AddRule(UndoArg1, SwResId(STR_GRAPHICreinterpret_cast<char const *>("STR_GRAPHIC" "\004" u8"image"
)
));
276
277 StartUndo(SwUndoId::INSERT, &aRewriter);
278
279 if ( HasSelection() )
280 DelRight();
281 // Inserted graphics in its own paragraph,
282 // if at the end of a non-empty paragraph.
283 //For i120928,avoid to split node
284
285 EnterSelFrameMode();
286
287 bool bSetGrfSize = true;
288 bool bOwnMgr = false;
289
290 if ( !pFrameMgr )
291 {
292 bOwnMgr = true;
293 pFrameMgr = new SwFlyFrameAttrMgr( true, this, Frmmgr_Type::GRF, nullptr );
294
295 // CAUTION
296 // GetAttrSet makes an adjustment
297 // While pasting is a SwFrameSize present
298 // because of the DEF-Framesize
299 // These must be removed explicitly for the optimal size.
300 pFrameMgr->DelAttr(RES_FRM_SIZE);
301
302 if (nAnchorType != RndStdIds::FLY_AT_PARA)
303 // Something other than at-para was requested.
304 pFrameMgr->SetAnchor(nAnchorType);
305 }
306 else
307 {
308 Size aSz( pFrameMgr->GetSize() );
309 if ( !aSz.Width() || !aSz.Height() )
310 {
311 aSz.setWidth(567);
312 aSz.setHeight( 567);
313 pFrameMgr->SetSize( aSz );
314 }
315 else if ( aSz.Width() != DFLT_WIDTH && aSz.Height() != DFLT_HEIGHT )
316 bSetGrfSize = false;
317
318 pFrameMgr->SetHeightSizeType(SwFrameSize::Fixed);
319 }
320
321 // Insert the graphic
322 SwFEShell::Insert(rPath, rFilter, &rGrf, &pFrameMgr->GetAttrSet());
323 if ( bOwnMgr )
324 pFrameMgr->UpdateAttrMgr();
325
326 if( bSetGrfSize )
327 {
328 Size aGrfSize, aBound = GetGraphicDefaultSize();
329 GetGrfSize( aGrfSize );
330
331 // Add the margin attributes to GrfSize,
332 // because these counts at the margin additionally
333 aGrfSize.AdjustWidth(pFrameMgr->CalcWidthBorder() );
334 aGrfSize.AdjustHeight(pFrameMgr->CalcHeightBorder() );
335
336 const BigInt aTempWidth( aGrfSize.Width() );
337 const BigInt aTempHeight( aGrfSize.Height());
338
339 // Fit width if necessary, scale down the height proportional thereafter.
340 if( aGrfSize.Width() > aBound.Width() )
341 {
342 aGrfSize.setWidth( aBound.Width() );
343 aGrfSize.setHeight( BigInt(aBound.Width()) * aTempHeight / aTempWidth );
344 }
345 // Fit height if necessary, scale down the width proportional thereafter.
346 if( aGrfSize.Height() > aBound.Height() )
347 {
348 aGrfSize.setHeight( aBound.Height() );
349 aGrfSize.setWidth( BigInt(aBound.Height()) * aTempWidth / aTempHeight );
350 }
351 pFrameMgr->SetSize( aGrfSize );
352 pFrameMgr->UpdateFlyFrame();
353 }
354 if ( bOwnMgr )
355 delete pFrameMgr;
356
357 EndUndo();
358 EndAllAction();
359}
360
361// Insert an OLE-Object into the CORE.
362// if no object is transferred, then one will be created.
363
364void SwWrtShell::InsertObject( const svt::EmbeddedObjectRef& xRef, SvGlobalName const *pName,
365 sal_uInt16 nSlotId )
366{
367 ResetCursorStack();
368 if( !CanInsert() )
1
Taking false branch
369 return;
370
371 if( !xRef.is() )
2
Assuming the condition is true
3
Taking true branch
372 {
373 // temporary storage
374 svt::EmbeddedObjectRef xObj;
375 uno::Reference < embed::XStorage > xStor = comphelper::OStorageHelper::GetTemporaryStorage();
376 bool bDoVerb = true;
377 if ( pName )
4
Assuming 'pName' is null
5
Taking false branch
378 {
379 comphelper::EmbeddedObjectContainer aCnt( xStor );
380 OUString aName;
381 // TODO/LATER: get aspect?
382 xObj.Assign( aCnt.CreateEmbeddedObject( pName->GetByteSequence(), aName ), embed::Aspects::MSOLE_CONTENT );
383 }
384 else
385 {
386 SvObjectServerList aServerList;
387 switch (nSlotId)
6
Control jumps to 'case 5563:' at line 397
388 {
389 case SID_INSERT_OBJECT(5000 + 561):
390 {
391 aServerList.FillInsertObjects();
392 aServerList.Remove( SwDocShell::Factory().GetClassId() );
393 [[fallthrough]];
394 }
395
396 // TODO/LATER: recording! Convert properties to items
397 case SID_INSERT_FLOATINGFRAME(5000 + 563):
398 {
399 SfxSlotPool* pSlotPool = SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->GetSlotPool();
400 const SfxSlot* pSlot = pSlotPool->GetSlot(nSlotId);
401 OString aCmd = OStringLiteral(".uno:") + pSlot->GetUnoName();
402 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
403 ScopedVclPtr<SfxAbstractInsertObjectDialog> pDlg(pFact->CreateInsertObjectDialog(GetFrameWeld(mxDoc->GetDocShell()),
7
Calling constructor for 'ScopedVclPtr<SfxAbstractInsertObjectDialog>'
14
Returning from constructor for 'ScopedVclPtr<SfxAbstractInsertObjectDialog>'
404 OUString::fromUtf8( aCmd ), xStor, &aServerList));
15
Calling implicit destructor for 'VclPtr<SfxAbstractInsertObjectDialog>'
16
Calling '~Reference'
23
Returning from '~Reference'
24
Returning from destructor for 'VclPtr<SfxAbstractInsertObjectDialog>'
405 if (pDlg)
25
Calling 'VclPtr::operator bool'
406 {
407 pDlg->Execute();
408 bDoVerb = pDlg->IsCreateNew();
409 OUString aIconMediaType;
410 uno::Reference< io::XInputStream > xIconMetaFile = pDlg->GetIconIfIconified( &aIconMediaType );
411 xObj.Assign( pDlg->GetObject(),
412 xIconMetaFile.is() ? embed::Aspects::MSOLE_ICON : embed::Aspects::MSOLE_CONTENT );
413 if ( xIconMetaFile.is() )
414 xObj.SetGraphicStream( xIconMetaFile, aIconMediaType );
415 }
416
417 break;
418 }
419
420 default:
421 break;
422 }
423 }
424
425 if ( xObj.is() )
426 {
427 if( InsertOleObject( xObj ) && bDoVerb )
428 {
429 SfxInPlaceClient* pClient = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin() );
430 if ( !pClient )
431 {
432 pClient = new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
433 SetCheckForOLEInCaption( true );
434 }
435
436 if ( xObj.GetViewAspect() == embed::Aspects::MSOLE_ICON )
437 {
438 SwRect aArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() );
439 aArea.Pos() += GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, xObj.GetObject() ).Pos();
440 MapMode aMapMode( MapUnit::MapTwip );
441 Size aSize = xObj.GetSize( &aMapMode );
442 aArea.Width( aSize.Width() );
443 aArea.Height( aSize.Height() );
444 RequestObjectResize( aArea, xObj.GetObject() );
445 }
446 else
447 CalcAndSetScale( xObj );
448
449 //#50270# We don't need to handle error, this is handled by the
450 //DoVerb in the SfxViewShell
451 pClient->DoVerb(embed::EmbedVerbs::MS_OLEVERB_SHOW);
452
453 // TODO/LATER: set document name - should be done in Client
454 }
455 }
456 }
457 else
458 {
459 if( HasSelection() )
460 DelRight();
461 InsertOleObject( xRef );
462 }
463}
464
465// Insert object into the Core.
466// From ClipBoard or Insert
467
468bool SwWrtShell::InsertOleObject( const svt::EmbeddedObjectRef& xRef, SwFlyFrameFormat **pFlyFrameFormat )
469{
470 //tdf#125100 Ensure that ole object is initially shown as pictogram
471 comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = mxDoc->GetDocShell()->getEmbeddedObjectContainer();
472 bool bSaveUserAllowsLinkUpdate = rEmbeddedObjectContainer.getUserAllowsLinkUpdate();
473 rEmbeddedObjectContainer.setUserAllowsLinkUpdate(true);
474
475 ResetCursorStack();
476 StartAllAction();
477
478 StartUndo(SwUndoId::INSERT);
479
480 //Some differences between StarMath and any other objects:
481 //1. Selections should be deleted. For StarMath the Text should be
482 // passed to the Object
483 //2. If the cursor is at the end of a non empty paragraph a paragraph
484 // break should be inserted. StarMath objects are character bound and
485 // no break should be inserted.
486 //3. If an selection is passed to a StarMath object, this object should
487 // not be activated. false should be returned then.
488 bool bStarMath = true;
489 bool bActivate = true;
490
491 // set parent to get correct VisArea(in case of object needing parent printer)
492 uno::Reference < container::XChild > xChild( xRef.GetObject(), uno::UNO_QUERY );
493 if ( xChild.is() )
494 xChild->setParent( mxDoc->GetDocShell()->GetModel() );
495
496 SvGlobalName aCLSID( xRef->getClassID() );
497 bStarMath = ( SotExchange::IsMath( aCLSID ) != 0 );
498 if( IsSelection() )
499 {
500 if( bStarMath )
501 {
502 OUString aMathData;
503 GetSelectedText( aMathData, ParaBreakType::ToOnlyCR );
504
505 if( !aMathData.isEmpty() && svt::EmbeddedObjectRef::TryRunningState( xRef.GetObject() ) )
506 {
507 uno::Reference < beans::XPropertySet > xSet( xRef->getComponent(), uno::UNO_QUERY );
508 if ( xSet.is() )
509 {
510 try
511 {
512 xSet->setPropertyValue("Formula", uno::makeAny( aMathData ) );
513 bActivate = false;
514 }
515 catch (const uno::Exception&)
516 {
517 }
518 }
519 }
520 }
521 DelRight();
522 }
523
524 if ( !bStarMath )
525 SwFEShell::SplitNode( false, false );
526
527 EnterSelFrameMode();
528
529 const SvGlobalName* pName = nullptr;
530 SvGlobalName aObjClsId;
531 if (xRef.is())
532 {
533 aObjClsId = SvGlobalName(xRef.GetObject()->getClassID());
534 pName = &aObjClsId;
535 }
536 SwFlyFrameAttrMgr aFrameMgr( true, this, Frmmgr_Type::OLE, pName );
537 aFrameMgr.SetHeightSizeType(SwFrameSize::Fixed);
538
539 SwRect aBound;
540 CalcBoundRect( aBound, aFrameMgr.GetAnchor() );
541
542 //The Size should be suggested by the OLE server
543 MapMode aMapMode( MapUnit::MapTwip );
544 Size aSz = xRef.GetSize( &aMapMode );
545
546 //Object size can be limited
547 if ( aSz.Width() > aBound.Width() )
548 {
549 //Always limit proportional.
550 aSz.setHeight( aSz.Height() * aBound.Width() / aSz.Width() );
551 aSz.setWidth( aBound.Width() );
552 }
553 aFrameMgr.SetSize( aSz );
554 SwFlyFrameFormat *pFormat = SwFEShell::InsertObject( xRef, &aFrameMgr.GetAttrSet() );
555
556 // --> #i972#
557 if ( bStarMath && mxDoc->getIDocumentSettingAccess().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT ) )
558 AlignFormulaToBaseline( xRef.GetObject() );
559
560 if (pFlyFrameFormat)
561 *pFlyFrameFormat = pFormat;
562
563 if ( SotExchange::IsChart( aCLSID ) )
564 {
565 uno::Reference< embed::XEmbeddedObject > xEmbeddedObj = xRef.GetObject();
566 if ( xEmbeddedObj.is() )
567 {
568 bool bDisableDataTableDialog = false;
569 svt::EmbeddedObjectRef::TryRunningState( xEmbeddedObj );
570 uno::Reference< beans::XPropertySet > xProps( xEmbeddedObj->getComponent(), uno::UNO_QUERY );
571 if ( xProps.is() &&
572 ( xProps->getPropertyValue("DisableDataTableDialog") >>= bDisableDataTableDialog ) &&
573 bDisableDataTableDialog )
574 {
575 xProps->setPropertyValue("DisableDataTableDialog",
576 uno::makeAny( false ) );
577 xProps->setPropertyValue("DisableComplexChartTypes",
578 uno::makeAny( false ) );
579 uno::Reference< util::XModifiable > xModifiable( xProps, uno::UNO_QUERY );
580 if ( xModifiable.is() )
581 {
582 xModifiable->setModified( true );
583 }
584 }
585 }
586 }
587
588 EndAllAction();
589 GetView().AutoCaption(OLE_CAP, &aCLSID);
590
591 SwRewriter aRewriter;
592
593 if ( bStarMath )
594 aRewriter.AddRule(UndoArg1, SwResId(STR_MATH_FORMULAreinterpret_cast<char const *>("STR_MATH_FORMULA" "\004"
u8"formula")
));
595 else if ( SotExchange::IsChart( aCLSID ) )
596 aRewriter.AddRule(UndoArg1, SwResId(STR_CHARTreinterpret_cast<char const *>("STR_CHART" "\004" u8"chart"
)
));
597 else
598 aRewriter.AddRule(UndoArg1, SwResId(STR_OLEreinterpret_cast<char const *>("STR_OLE" "\004" u8"OLE-object"
)
));
599
600 EndUndo(SwUndoId::INSERT, &aRewriter);
601
602 rEmbeddedObjectContainer.setUserAllowsLinkUpdate(bSaveUserAllowsLinkUpdate);
603
604 return bActivate;
605}
606
607// The current selected OLE object will be loaded with the
608// verb into the server.
609
610void SwWrtShell::LaunchOLEObj( long nVerb )
611{
612 if ( GetCntType() != CNT_OLE0x0010 ||
613 GetView().GetViewFrame()->GetFrame().IsInPlace() )
614 return;
615
616 svt::EmbeddedObjectRef& xRef = GetOLEObject();
617 OSL_ENSURE( xRef.is(), "OLE not found" )do { if (true && (!(xRef.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/wrtsh/wrtsh1.cxx"
":" "617" ": "), "%s", "OLE not found"); } } while (false)
;
618
619 // LOK: we don't want to handle any other embedded objects than
620 // charts, there are too many problems with eg. embedded spreadsheets
621 // (like it creates a separate view for the calc sheet)
622 if (comphelper::LibreOfficeKit::isActive() && !SotExchange::IsChart(xRef->getClassID()))
623 return;
624
625 SfxInPlaceClient* pCli = GetView().FindIPClient( xRef.GetObject(), &GetView().GetEditWin() );
626 if ( !pCli )
627 pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xRef );
628
629 static_cast<SwOleClient*>(pCli)->SetInDoVerb( true );
630
631 CalcAndSetScale( xRef );
632 pCli->DoVerb( nVerb );
633
634 static_cast<SwOleClient*>(pCli)->SetInDoVerb( false );
635 CalcAndSetScale( xRef );
636}
637
638void SwWrtShell::MoveObjectIfActive( svt::EmbeddedObjectRef& xObj, const Point& rOffset )
639{
640 try
641 {
642 sal_Int32 nState = xObj->getCurrentState();
643 if ( nState == css::embed::EmbedStates::INPLACE_ACTIVE
644 || nState == css::embed::EmbedStates::UI_ACTIVE )
645 {
646 SfxInPlaceClient* pCli =
647 GetView().FindIPClient( xObj.GetObject(), &(GetView().GetEditWin()) );
648 if ( pCli )
649 {
650 tools::Rectangle aArea = pCli->GetObjArea();
651 aArea += rOffset;
652 pCli->SetObjArea( aArea );
653 }
654 }
655 }
656 catch (const uno::Exception&)
657 {
658 }
659}
660
661void SwWrtShell::CalcAndSetScale( svt::EmbeddedObjectRef& xObj,
662 const SwRect *pFlyPrtRect,
663 const SwRect *pFlyFrameRect,
664 const bool bNoTextFramePrtAreaChanged )
665{
666 // Setting the scale of the client. This arises from the difference
667 // between the VisArea of the object and the ObjArea.
668 OSL_ENSURE( xObj.is(), "ObjectRef not valid" )do { if (true && (!(xObj.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/wrtsh/wrtsh1.cxx"
":" "668" ": "), "%s", "ObjectRef not valid"); } } while (false
)
;
669
670 sal_Int64 nAspect = xObj.GetViewAspect();
671 if ( nAspect == embed::Aspects::MSOLE_ICON )
672 return; // the replacement image is completely controlled by container in this case
673
674 sal_Int64 nMisc = 0;
675 bool bLinkingChart = false;
676
677 try
678 {
679 nMisc = xObj->getStatus( nAspect );
680
681 // This can surely only be a non-active object, if desired they
682 // get the new size set as VisArea (StarChart).
683 if( embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE & nMisc )
684 {
685 // TODO/MBA: testing
686 SwRect aRect( pFlyPrtRect ? *pFlyPrtRect
687 : GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ));
688 if( !aRect.IsEmpty() )
689 {
690 // TODO/LEAN: getMapUnit can switch object to running state
691 // xObj.TryRunningState();
692
693 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
694
695 // TODO/LATER: needs complete VisArea?!
696 Size aSize( OutputDevice::LogicToLogic(aRect.SVRect(), MapMode(MapUnit::MapTwip), MapMode(aUnit)).GetSize() );
697 awt::Size aSz;
698 aSz.Width = aSize.Width();
699 aSz.Height = aSize.Height();
700
701 // Action 'setVisualAreaSize' doesn't have to turn on the
702 // modified state of the document, either.
703 bool bModified = false;
704 uno::Reference<util::XModifiable> xModifiable(xObj->getComponent(), uno::UNO_QUERY);
705 if (xModifiable.is())
706 bModified = xModifiable->isModified();
707 xObj->setVisualAreaSize( nAspect, aSz );
708 xModifiable.set(xObj->getComponent(), uno::UNO_QUERY);
709 if (xModifiable.is() && xModifiable->isModified() && !bModified)
710 xModifiable->setModified(bModified);
711
712 // #i48419# - action 'UpdateReplacement' doesn't
713 // have to change the modified state of the document.
714 // This is only a workaround for the defect, that this action
715 // modifies a document after load, because unnecessarily the
716 // replacement graphic is updated, in spite of the fact that
717 // nothing has been changed.
718 // If the replacement graphic changes by this action, the document
719 // will be already modified via other mechanisms.
720 {
721 bool bResetEnableSetModified(false);
722 if ( GetDoc()->GetDocShell()->IsEnableSetModified() )
723 {
724 GetDoc()->GetDocShell()->EnableSetModified( false );
725 bResetEnableSetModified = true;
726 }
727
728 //#i79576# don't destroy chart replacement images on load
729 //#i79578# don't request a new replacement image for charts to often
730 //a chart sends a modified call to the framework if it was changed
731 //thus the replacement update is already handled elsewhere
732 if ( !SotExchange::IsChart( xObj->getClassID() ) )
733 xObj.UpdateReplacement();
734
735 if ( bResetEnableSetModified )
736 {
737 GetDoc()->GetDocShell()->EnableSetModified();
738 }
739 }
740 }
741
742 // TODO/LATER: this is only a workaround,
743 uno::Reference< chart2::XChartDocument > xChartDocument( xObj->getComponent(), uno::UNO_QUERY );
744 bLinkingChart = ( xChartDocument.is() && !xChartDocument->hasInternalDataProvider() );
745 }
746 }
747 catch (const uno::Exception&)
748 {
749 // TODO/LATER: handle the error
750 return;
751 }
752
753 SfxInPlaceClient* pCli = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin() );
754 if ( !pCli )
755 {
756 if ( (embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY & nMisc)
757 || bLinkingChart
758 // --> OD #i117189# - refine condition for non-resizable objects
759 // non-resizable objects need to be set the size back by this method
760 || ( bNoTextFramePrtAreaChanged && nMisc & embed::EmbedMisc::EMBED_NEVERRESIZE ) )
761 {
762 pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
763 }
764 else
765 return;
766 }
767
768 // TODO/LEAN: getMapUnit can switch object to running state
769 // xObj.TryRunningState();
770
771 awt::Size aSize;
772 try
773 {
774 aSize = xObj->getVisualAreaSize( nAspect );
775 }
776 catch (const embed::NoVisualAreaSizeException&)
777 {
778 OSL_FAIL("Can't get visual area size!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/wrtsh/wrtsh1.cxx"
":" "778" ": "), "%s", "Can't get visual area size!"); } } while
(false)
;
779 // the scaling will not be done
780 }
781 catch (const uno::Exception&)
782 {
783 // TODO/LATER: handle the error
784 OSL_FAIL("Can't get visual area size!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/wrtsh/wrtsh1.cxx"
":" "784" ": "), "%s", "Can't get visual area size!"); } } while
(false)
;
785 return;
786 }
787
788 Size _aVisArea( aSize.Width, aSize.Height );
789
790 Fraction aScaleWidth( 1, 1 );
791 Fraction aScaleHeight( 1, 1 );
792
793 bool bUseObjectSize = false;
794
795 // As long as there comes no reasonable size from the object,
796 // nothing can be scaled.
797 if( _aVisArea.Width() && _aVisArea.Height() )
798 {
799 const MapMode aTmp( MapUnit::MapTwip );
800 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
801 _aVisArea = OutputDevice::LogicToLogic(_aVisArea, MapMode(aUnit), aTmp);
802 Size aObjArea;
803 if ( pFlyPrtRect )
804 aObjArea = pFlyPrtRect->SSize();
805 else
806 aObjArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ).SSize();
807
808 // differ the aObjArea and _aVisArea by 1 Pixel then set new VisArea
809 long nX, nY;
810 SwSelPaintRects::Get1PixelInLogic( *this, &nX, &nY );
811 if( !( _aVisArea.Width() - nX <= aObjArea.Width() &&
812 _aVisArea.Width() + nX >= aObjArea.Width() &&
813 _aVisArea.Height()- nY <= aObjArea.Height()&&
814 _aVisArea.Height()+ nY >= aObjArea.Height() ))
815 {
816 if ( nMisc & embed::EmbedMisc::EMBED_NEVERRESIZE )
817 {
818 // the object must not be scaled,
819 // the size stored in object must be used for restoring
820 bUseObjectSize = true;
821 }
822 else
823 {
824 aScaleWidth = Fraction( aObjArea.Width(), _aVisArea.Width() );
825 aScaleHeight = Fraction( aObjArea.Height(), _aVisArea.Height());
826 }
827 }
828 }
829
830 // Now is the favorable time to set the ObjArea.
831 // The Scaling must be considered.
832 SwRect aArea;
833 if ( pFlyPrtRect )
834 {
835 aArea = *pFlyPrtRect;
836 aArea += pFlyFrameRect->Pos();
837 }
838 else
839 {
840 aArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() );
841 aArea.Pos() += GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, xObj.GetObject() ).Pos();
842 }
843
844 if ( bUseObjectSize )
845 {
846 // --> this moves non-resizable object so that when adding borders the baseline remains the same
847 const SwFlyFrameFormat *pFlyFrameFormat = dynamic_cast< const SwFlyFrameFormat * >( GetFlyFrameFormat() );
848 OSL_ENSURE( pFlyFrameFormat, "Could not find fly frame." )do { if (true && (!(pFlyFrameFormat))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/wrtsh/wrtsh1.cxx"
":" "848" ": "), "%s", "Could not find fly frame."); } } while
(false)
;
849 if ( pFlyFrameFormat )
850 {
851 const Point &rPoint = pFlyFrameFormat->GetLastFlyFramePrtRectPos();
852 SwRect aRect( pFlyPrtRect ? *pFlyPrtRect
853 : GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ));
854 aArea += rPoint - aRect.Pos(); // adjust area by diff of printing area position in order to keep baseline alignment correct.
855 }
856 aArea.Width ( _aVisArea.Width() );
857 aArea.Height( _aVisArea.Height() );
858 RequestObjectResize( aArea, xObj.GetObject() );
859 }
860 else
861 {
862 aArea.Width ( long( aArea.Width() / pCli->GetScaleWidth() ) );
863 aArea.Height( long( aArea.Height() / pCli->GetScaleHeight() ) );
864 }
865
866 pCli->SetObjAreaAndScale( aArea.SVRect(), aScaleWidth, aScaleHeight );
867}
868
869void SwWrtShell::ConnectObj( svt::EmbeddedObjectRef& xObj, const SwRect &rPrt,
870 const SwRect &rFrame )
871{
872 SfxInPlaceClient* pCli = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin());
873 if ( !pCli )
874 new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
875 CalcAndSetScale( xObj, &rPrt, &rFrame );
876}
877
878// Insert hard page break;
879// Selections will be overwritten
880void SwWrtShell::InsertPageBreak(const OUString *pPageDesc, const ::std::optional<sal_uInt16>& oPgNum )
881{
882 ResetCursorStack();
883 if( CanInsert() )
884 {
885 SwActContext aActContext(this);
886 StartUndo(SwUndoId::UI_INSERT_PAGE_BREAK);
887
888 if ( !IsCursorInTable() )
889 {
890 if(HasSelection())
891 DelRight();
892 SwFEShell::SplitNode();
893 // delete the numbered attribute of the last line if the last line is empty
894 GetDoc()->ClearLineNumAttrs( *GetCursor()->GetPoint() );
895 }
896
897 const SwPageDesc *pDesc = pPageDesc
898 ? FindPageDescByName( *pPageDesc, true ) : nullptr;
899 if( pDesc )
900 {
901 SwFormatPageDesc aDesc( pDesc );
902 aDesc.SetNumOffset( oPgNum );
903 SetAttrItem( aDesc );
904 }
905 else
906 SetAttrItem( SvxFormatBreakItem(SvxBreak::PageBefore, RES_BREAK) );
907 EndUndo(SwUndoId::UI_INSERT_PAGE_BREAK);
908 }
909 collectUIInformation("BREAK_PAGE", "parameter");
910}
911
912// Insert hard page break;
913// Selections will be overwritten
914
915void SwWrtShell::InsertLineBreak()
916{
917 ResetCursorStack();
918 if( CanInsert() )
919 {
920 if(HasSelection())
921 DelRight();
922
923 const sal_Unicode cIns = 0x0A;
924 SvxAutoCorrect* pACorr = lcl_IsAutoCorr();
925 if( pACorr )
926 AutoCorrect( *pACorr, cIns );
927 else
928 SwWrtShell::Insert( OUString( cIns ) );
929 }
930}
931
932// Insert hard column break;
933// Selections will be overwritten
934
935void SwWrtShell::InsertColumnBreak()
936{
937 SwActContext aActContext(this);
938 ResetCursorStack();
939 if( !CanInsert() )
940 return;
941
942 StartUndo(SwUndoId::UI_INSERT_COLUMN_BREAK);
943
944 if ( !IsCursorInTable() )
945 {
946 if(HasSelection())
947 DelRight();
948 SwFEShell::SplitNode( false, false );
949 }
950 SetAttrItem(SvxFormatBreakItem(SvxBreak::ColumnBefore, RES_BREAK));
951
952 EndUndo(SwUndoId::UI_INSERT_COLUMN_BREAK);
953}
954
955// Insert footnote
956// rStr - optional footnote mark
957
958void SwWrtShell::InsertFootnote(const OUString &rStr, bool bEndNote, bool bEdit )
959{
960 ResetCursorStack();
961 if( !CanInsert() )
962 return;
963
964 if(HasSelection())
965 {
966 //collapse cursor to the end
967 if(!IsCursorPtAtEnd())
968 SwapPam();
969 ClearMark();
970 }
971 SwPosition aPos = *GetCursor()->GetPoint();
972 SwFormatFootnote aFootNote( bEndNote );
973 if(!rStr.isEmpty())
974 aFootNote.SetNumStr( rStr );
975
976 SetAttrItem(aFootNote);
977
978 if( bEdit )
979 {
980 // For editing the footnote text.
981 Left(CRSR_SKIP_CHARS, false, 1, false );
982 GotoFootnoteText();
983 }
984 m_aNavigationMgr.addEntry(aPos);
985}
986
987// SplitNode; also, because
988// - of deleting selected content;
989// - of reset of the Cursorstack if necessary.
990
991void SwWrtShell::SplitNode( bool bAutoFormat )
992{
993 ResetCursorStack();
994 if( !CanInsert() )
995 return;
996
997 SwActContext aActContext(this);
998
999 m_rView.GetEditWin().FlushInBuffer();
1000 bool bHasSel = HasSelection();
1001 if( bHasSel )
1002 {
1003 StartUndo( SwUndoId::INSERT );
1004 DelRight();
1005 }
1006
1007 SwFEShell::SplitNode( bAutoFormat );
1008 if( bHasSel )
1009 EndUndo( SwUndoId::INSERT );
1010}
1011
1012// Turn on numbering
1013// Parameter: Optional specification of a name for the named list;
1014// this indicates a position if it is possible to convert them
1015// into a number and less than nMaxRules.
1016
1017// To test the CharFormats at the numbering
1018// external void SetNumChrFormat( SwWrtShell*, SwNumRules& );
1019
1020// -> #i40041#
1021// Preconditions (as far as OD has figured out):
1022// - <SwEditShell::HasNumber()> is false, if <bNum> is true
1023// - <SwEditShell::HasBullet()> is false, if <bNum> is false
1024// Behavior of method is determined by the current situation at the current
1025// cursor position in the document.
1026void SwWrtShell::NumOrBulletOn(bool bNum)
1027{
1028 // determine numbering rule found at current cursor position in the document.
1029 const SwNumRule* pCurRule = GetNumRuleAtCurrCursorPos();
1030
1031 StartUndo(SwUndoId::NUMORNONUM);
1032
1033 const SwNumRule * pNumRule = pCurRule;
1034
1035 // - activate outline rule respectively turning on outline rule for
1036 // current text node. But, only for turning on a numbering (<bNum> == true).
1037 // - overwrite found numbering rule at current cursor position, if
1038 // no numbering rule can be retrieved from the paragraph style.
1039 bool bContinueFoundNumRule( false );
1040 bool bActivateOutlineRule( false );
1041 int nActivateOutlineLvl( MAXLEVEL ); // only relevant, if <bActivateOutlineRule> == true
1042 SwTextFormatColl * pColl = GetCurTextFormatColl();
1043 if ( pColl )
1044 {
1045 // retrieve numbering rule at paragraph
1046 // style, which is found at current cursor position in the document.
1047 SwNumRule* pCollRule = mxDoc->FindNumRulePtr(pColl->GetNumRule().GetValue());
1048 // #125993# - The outline numbering rule isn't allowed
1049 // to be derived from a parent paragraph style to a derived one.
1050 // Thus check, if the found outline numbering rule is directly
1051 // set at the paragraph style <pColl>. If not, set <pCollRule> to NULL
1052 if ( pCollRule && pCollRule == GetDoc()->GetOutlineNumRule() )
1053 {
1054 const SwNumRule* pDirectCollRule =
1055 mxDoc->FindNumRulePtr(pColl->GetNumRule( false ).GetValue());
1056 if ( !pDirectCollRule )
1057 {
1058 pCollRule = nullptr;
1059 }
1060 }
1061
1062 if ( !pCollRule )
1063 {
1064 pNumRule = pCollRule;
1065 }
1066 // no activation or continuation of outline numbering in Writer/Web document
1067 else if ( bNum &&
1068 !dynamic_cast<SwWebDocShell*>(GetDoc()->GetDocShell()) &&
1069 pCollRule == GetDoc()->GetOutlineNumRule() )
1070 {
1071 if ( pNumRule == pCollRule )
1072 {
1073 // check, if text node at current cursor positioned is counted.
1074 // If not, let it been counted. Then it has to be checked,
1075 // of the outline numbering has to be activated or continued.
1076 SwTextNode const*const pTextNode = sw::GetParaPropsNode(
1077 *GetLayout(), GetCursor()->GetPoint()->nNode);
1078 if ( pTextNode && !pTextNode->IsCountedInList() )
1079 {
1080 // check, if numbering of the outline level of the paragraph
1081 // style is active. If not, activate this outline level.
1082 nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
1083 OSL_ENSURE( pColl->IsAssignedToListLevelOfOutlineStyle(),do { if (true && (!(pColl->IsAssignedToListLevelOfOutlineStyle
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/uibase/wrtsh/wrtsh1.cxx"
":" "1084" ": "), "%s", "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level"
); } } while (false)
1084 "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level" )do { if (true && (!(pColl->IsAssignedToListLevelOfOutlineStyle
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/uibase/wrtsh/wrtsh1.cxx"
":" "1084" ": "), "%s", "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level"
); } } while (false)
;
1085 if ( pColl->IsAssignedToListLevelOfOutlineStyle() &&
1086 pCollRule->Get( static_cast<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
1087 == SVX_NUM_NUMBER_NONE )
1088 {
1089 // activate outline numbering
1090 bActivateOutlineRule = true;
1091 }
1092 else
1093 {
1094 // turning on outline numbering at current cursor position
1095 bContinueFoundNumRule = true;
1096 }
1097 }
1098 else
1099 {
1100 // #i101234#
1101 // activate outline numbering, because from the precondition
1102 // it's known, that <SwEdit::HasNumber()> == false
1103 bActivateOutlineRule = true;
1104 nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
1105 }
1106 }
1107 else if ( !pNumRule )
1108 {
1109 // #i101234#
1110 // Check, if corresponding list level of the outline numbering
1111 // has already a numbering format set.
1112 nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
1113 if ( pCollRule->Get( static_cast<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
1114 == SVX_NUM_NUMBER_NONE )
1115 {
1116 // activate outline numbering, because from the precondition
1117 // it's known, that <SwEdit::HasNumber()> == false
1118 bActivateOutlineRule = true;
1119 }
1120 else
1121 {
1122 // turning on outline numbering at current cursor position
1123 bContinueFoundNumRule = true;
1124 }
1125 }
1126 else
1127 {
1128 // check, if numbering of the outline level of the paragraph
1129 // style is active. If not, activate this outline level.
1130 nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
1131 OSL_ENSURE( pColl->IsAssignedToListLevelOfOutlineStyle(),do { if (true && (!(pColl->IsAssignedToListLevelOfOutlineStyle
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/uibase/wrtsh/wrtsh1.cxx"
":" "1132" ": "), "%s", "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level"
); } } while (false)
1132 "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level" )do { if (true && (!(pColl->IsAssignedToListLevelOfOutlineStyle
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/uibase/wrtsh/wrtsh1.cxx"
":" "1132" ": "), "%s", "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level"
); } } while (false)
;
1133 if ( pColl->IsAssignedToListLevelOfOutlineStyle() &&
1134 pCollRule->Get( static_cast<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
1135 == SVX_NUM_NUMBER_NONE )
1136 {
1137 // activate outline numbering
1138 bActivateOutlineRule = true;
1139 }
1140 else
1141 {
1142 // turning on outline numbering at current cursor position
1143 bContinueFoundNumRule = true;
1144 }
1145 }
1146 pNumRule = pCollRule;
1147 }
1148 }
1149
1150 // Only automatic numbering/bullet rules should be changed.
1151 // Note: The outline numbering rule is also an automatic one. It's only
1152 // changed, if it has to be activated.
1153 if ( pNumRule )
1154 {
1155 if ( !pNumRule->IsAutoRule() )
1156 {
1157 pNumRule = nullptr;
1158 }
1159 else if ( pNumRule == GetDoc()->GetOutlineNumRule() &&
1160 !bActivateOutlineRule && !bContinueFoundNumRule )
1161 {
1162 pNumRule = nullptr;
1163 }
1164 }
1165
1166 // Search for a previous numbering/bullet rule to continue it.
1167 OUString sContinuedListId;
1168 if ( !pNumRule )
1169 {
1170 pNumRule = GetDoc()->SearchNumRule( *GetCursor()->GetPoint(),
1171 false, bNum, false, 0,
1172 sContinuedListId, GetLayout() );
1173 bContinueFoundNumRule = pNumRule != nullptr;
1174 }
1175
1176 if (pNumRule)
1177 {
1178 SwNumRule aNumRule(*pNumRule);
1179
1180 // do not change found numbering/bullet rule, if it should only be continued.
1181 if ( !bContinueFoundNumRule )
1182 {
1183 SwTextNode const*const pTextNode = sw::GetParaPropsNode(
1184 *GetLayout(), GetCursor()->GetPoint()->nNode);
1185
1186 if (pTextNode)
1187 {
1188 // use above retrieve outline level, if outline numbering has to be activated.
1189 int nLevel = bActivateOutlineRule
1190 ? nActivateOutlineLvl
1191 : pTextNode->GetActualListLevel();
1192
1193 if (nLevel < 0)
1194 nLevel = 0;
1195
1196 if (nLevel >= MAXLEVEL)
1197 nLevel = MAXLEVEL - 1;
1198
1199 SwNumFormat aFormat(aNumRule.Get(static_cast<sal_uInt16>(nLevel)));
1200
1201 if (bNum)
1202 aFormat.SetNumberingType(SVX_NUM_ARABIC);
1203 else
1204 {
1205 // #i63395# Only apply user defined default bullet font
1206 if ( numfunc::IsDefBulletFontUserDefined() )
1207 {
1208 const vcl::Font* pFnt = &numfunc::GetDefBulletFont();
1209 aFormat.SetBulletFont( pFnt );
1210 }
1211 aFormat.SetBulletChar( numfunc::GetBulletChar(static_cast<sal_uInt8>(nLevel)));
1212 aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
1213 // #i93908# clear suffix for bullet lists
1214 aFormat.SetPrefix(OUString());
1215 aFormat.SetSuffix(OUString());
1216 }
1217 aNumRule.Set(static_cast<sal_uInt16>(nLevel), aFormat);
1218 }
1219 }
1220
1221 // reset indent attribute on applying list style
1222 SetCurNumRule( aNumRule, false, sContinuedListId, true );
1223 }
1224 else
1225 {
1226 // #i95907#
1227 const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
1228 numfunc::GetDefaultPositionAndSpaceMode() );
1229 SwNumRule aNumRule( GetUniqueNumRuleName(), ePosAndSpaceMode );
1230 // Append the character template at the numbering.
1231 SwCharFormat* pChrFormat;
1232 SwDocShell* pDocSh = GetView().GetDocShell();
1233 // #i63395#
1234 // Only apply user defined default bullet font
1235 const vcl::Font* pFnt = numfunc::IsDefBulletFontUserDefined()
1236 ? &numfunc::GetDefBulletFont()
1237 : nullptr;
1238
1239 if (bNum)
1240 {
1241 pChrFormat = GetCharFormatFromPool( RES_POOLCHR_NUM_LEVEL );
1242 }
1243 else
1244 {
1245 pChrFormat = GetCharFormatFromPool( RES_POOLCHR_BULLET_LEVEL );
1246 }
1247
1248 const SwTextNode *const pTextNode = sw::GetParaPropsNode(*GetLayout(),
1249 GetCursor()->GetPoint()->nNode);
1250 const SwTwips nWidthOfTabs = pTextNode
1251 ? pTextNode->GetWidthOfLeadingTabs()
1252 : 0;
1253 GetDoc()->getIDocumentContentOperations().RemoveLeadingWhiteSpace( *GetCursor()->GetPoint() );
1254
1255 const bool bHtml = dynamic_cast<SwWebDocShell*>( pDocSh ) != nullptr;
1256 const bool bRightToLeft = IsInRightToLeftText();
1257 for( sal_uInt8 nLvl = 0; nLvl < MAXLEVEL; ++nLvl )
1258 {
1259 SwNumFormat aFormat( aNumRule.Get( nLvl ) );
1260 aFormat.SetCharFormat( pChrFormat );
1261
1262 if (! bNum)
1263 {
1264 // #i63395#
1265 // Only apply user defined default bullet font
1266 if ( pFnt )
1267 {
1268 aFormat.SetBulletFont( pFnt );
1269 }
1270 aFormat.SetBulletChar( numfunc::GetBulletChar(nLvl) );
1271 aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
1272 // #i93908# clear suffix for bullet lists
1273 aFormat.SetPrefix(OUString());
1274 aFormat.SetSuffix(OUString());
1275 }
1276
1277 // #i95907#
1278 if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1279 {
1280 if(bHtml && nLvl)
1281 {
1282 // 1/2" for HTML
1283 aFormat.SetAbsLSpace(nLvl * 720);
1284 }
1285 else if ( nWidthOfTabs > 0 )
1286 {
1287 aFormat.SetAbsLSpace(nWidthOfTabs + nLvl * 720);
1288 }
1289 }
1290
1291 // #i38904# Default alignment for
1292 // numbering/bullet should be rtl in rtl paragraph:
1293 if ( bRightToLeft )
1294 {
1295 aFormat.SetNumAdjust( SvxAdjust::Right );
1296 }
1297
1298 aNumRule.Set( nLvl, aFormat );
1299 }
1300
1301 // #i95907#
1302 if ( pTextNode &&
1303 ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
1304 {
1305
1306 const SwTwips nTextNodeIndent = pTextNode->GetAdditionalIndentForStartingNewList();
1307 if ( ( nTextNodeIndent + nWidthOfTabs ) != 0 )
1308 {
1309 // #i111172#/fdo#85666
1310 // If text node is already inside a list, assure that the indents
1311 // are the same. Thus, adjust the indent change value by subtracting
1312 // indents of to be applied list style.
1313 SwTwips nIndentChange = nTextNodeIndent + nWidthOfTabs;
1314 if ( pTextNode->GetNumRule() )
1315 {
1316 int nLevel = pTextNode->GetActualListLevel();
1317
1318 if (nLevel < 0)
1319 nLevel = 0;
1320
1321 if (nLevel >= MAXLEVEL)
1322 nLevel = MAXLEVEL - 1;
1323
1324 const SwNumFormat& aFormat( aNumRule.Get( nLevel ) );
1325 if ( aFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
1326 {
1327 nIndentChange -= aFormat.GetIndentAt() + aFormat.GetFirstLineIndent();
1328 }
1329 }
1330 aNumRule.ChangeIndent( nIndentChange );
1331 }
1332 }
1333 // reset indent attribute on applying list style
1334 // start new list
1335 SetCurNumRule( aNumRule, true, OUString(), true );
1336 }
1337
1338 EndUndo(SwUndoId::NUMORNONUM);
1339}
1340// <- #i40041#
1341
1342void SwWrtShell::NumOn()
1343{
1344 NumOrBulletOn(true);
1345}
1346
1347void SwWrtShell::NumOrBulletOff()
1348{
1349 const SwNumRule * pCurNumRule = GetNumRuleAtCurrCursorPos();
1350
1351 if (!pCurNumRule)
1352 return;
1353
1354 if (pCurNumRule->IsOutlineRule())
1355 {
1356 SwNumRule aNumRule(*pCurNumRule);
1357
1358 SwTextNode * pTextNode =
1359 sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->nNode);
1360
1361 if (pTextNode)
1362 {
1363 int nLevel = pTextNode->GetActualListLevel();
1364
1365 if (nLevel < 0)
1366 nLevel = 0;
1367
1368 if (nLevel >= MAXLEVEL)
1369 nLevel = MAXLEVEL - 1;
1370
1371 SwNumFormat aFormat(aNumRule.Get(static_cast<sal_uInt16>(nLevel)));
1372
1373 aFormat.SetNumberingType(SVX_NUM_NUMBER_NONE);
1374 aNumRule.Set(nLevel, aFormat);
1375
1376 // no start or continuation of a list - the outline style is only changed.
1377 SetCurNumRule( aNumRule, false );
1378 }
1379 }
1380 else
1381 {
1382 DelNumRules();
1383 }
1384
1385 // #126346# - Cursor can not be anymore in front of
1386 // a label, because numbering/bullet is switched off.
1387 SetInFrontOfLabel( false );
1388}
1389// <- #i29560#
1390
1391// Request Default-Bulletlist
1392
1393void SwWrtShell::BulletOn()
1394{
1395 NumOrBulletOn(false);
1396}
1397
1398SelectionType SwWrtShell::GetSelectionType() const
1399{
1400 // ContentType cannot be determined within a Start-/EndAction.
1401 // Because there is no invalid value TEXT will be returned.
1402 // The value does not matter, it may be updated in EndAction anyway.
1403
1404 if (ActionPend())
1405 return IsSelFrameMode() ? SelectionType::Frame : SelectionType::Text;
1406
1407 SwView &_rView = const_cast<SwView&>(GetView());
1408 if (_rView.GetPostItMgr() && _rView.GetPostItMgr()->HasActiveSidebarWin() )
1409 return SelectionType::PostIt;
1410
1411 // Inserting a frame is not a DrawMode
1412 SelectionType nCnt;
1413 if ( !_rView.GetEditWin().IsFrameAction() &&
1414 (IsObjSelected() || (_rView.IsDrawMode() && !IsFrameSelected()) ))
1415 {
1416 if (GetDrawView()->IsTextEdit())
1417 nCnt = SelectionType::DrawObjectEditMode;
1418 else
1419 {
1420 if (GetView().IsFormMode()) // Only Form selected
1421 nCnt = SelectionType::DbForm;
1422 else
1423 nCnt = SelectionType::DrawObject; // Any draw object
1424
1425 if (_rView.IsBezierEditMode())
1426 nCnt |= SelectionType::Ornament;
1427 else if( GetDrawView()->GetContext() == SdrViewContext::Media )
1428 nCnt |= SelectionType::Media;
1429
1430 if (svx::checkForSelectedCustomShapes( GetDrawView(), true /* bOnlyExtruded */ ))
1431 {
1432 nCnt |= SelectionType::ExtrudedCustomShape;
1433 }
1434 sal_uInt32 nCheckStatus = 0;
1435 if (svx::checkForSelectedFontWork( GetDrawView(), nCheckStatus ))
1436 {
1437 nCnt |= SelectionType::FontWork;
1438 }
1439 }
1440
1441 return nCnt;
1442 }
1443
1444 nCnt = static_cast<SelectionType>(GetCntType());
1445
1446 if ( IsFrameSelected() )
1447 {
1448 if (_rView.IsDrawMode())
1449 _rView.LeaveDrawCreate(); // clean up (Bug #45639)
1450 if ( !(nCnt & (SelectionType::Graphic | SelectionType::Ole)) )
1451 return SelectionType::Frame;
1452 }
1453
1454 if ( IsCursorInTable() )
1455 nCnt |= SelectionType::Table;
1456
1457 if ( IsTableMode() )
1458 {
1459 nCnt |= SelectionType::Table | SelectionType::TableCell;
1460 SwTable::SearchType eTableSel = GetEnhancedTableSelection();
1461 if ( eTableSel == SwTable::SEARCH_ROW )
1462 nCnt |= SelectionType::TableRow;
1463 else if ( eTableSel == SwTable::SEARCH_COL )
1464 nCnt |= SelectionType::TableCol;
1465 }
1466
1467 // Do not pop up numbering toolbar, if the text node has a numbering of type SVX_NUM_NUMBER_NONE.
1468 const SwNumRule* pNumRule = GetNumRuleAtCurrCursorPos();
1469 if ( pNumRule )
1470 {
1471 const SwTextNode* pTextNd =
1472 sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->nNode);
1473
1474 if ( pTextNd && pTextNd->IsInList() )
1475 {
1476 int nLevel = pTextNd->GetActualListLevel();
1477
1478 if (nLevel < 0)
1479 nLevel = 0;
1480
1481 if (nLevel >= MAXLEVEL)
1482 nLevel = MAXLEVEL - 1;
1483
1484 const SwNumFormat& rFormat = pNumRule->Get(nLevel);
1485 if ( SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType() )
1486 nCnt |= SelectionType::NumberList;
1487 }
1488 }
1489
1490 return nCnt;
1491}
1492
1493// Find the text collection with the name rCollname
1494// Returns: Pointer at the collection or 0, if no
1495// text collection with this name exists, or
1496// this is a default template.
1497
1498SwTextFormatColl *SwWrtShell::GetParaStyle(const OUString &rCollName, GetStyle eCreate )
1499{
1500 SwTextFormatColl* pColl = FindTextFormatCollByName( rCollName );
1501 if( !pColl && GETSTYLE_NOCREATE != eCreate )
1502 {
1503 sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( rCollName, SwGetPoolIdFromName::TxtColl );
1504 if( USHRT_MAX(32767 *2 +1) != nId || GETSTYLE_CREATEANY == eCreate )
1505 pColl = GetTextCollFromPool( nId );
1506 }
1507 return pColl;
1508}
1509
1510// Find the text collection with the name rCollname
1511// Returns: Pointer at the collection or 0, if no
1512// character template with this name exists, or
1513// this is a default template or template is automatic.
1514
1515SwCharFormat *SwWrtShell::GetCharStyle(const OUString &rFormatName, GetStyle eCreate )
1516{
1517 SwCharFormat* pFormat = FindCharFormatByName( rFormatName );
1518 if( !pFormat && GETSTYLE_NOCREATE != eCreate )
1519 {
1520 sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( rFormatName, SwGetPoolIdFromName::ChrFmt );
1521 if( USHRT_MAX(32767 *2 +1) != nId || GETSTYLE_CREATEANY == eCreate )
1522 pFormat = static_cast<SwCharFormat*>(GetFormatFromPool( nId ));
1523 }
1524 return pFormat;
1525}
1526
1527// Find the table format with the name rFormatname
1528// Returns: Pointer at the collection or 0, if no
1529// frame format with this name exists or
1530// this is a default format or the format is automatic.
1531
1532SwFrameFormat *SwWrtShell::GetTableStyle(const OUString &rFormatName)
1533{
1534 for( size_t i = GetTableFrameFormatCount(); i; )
1535 {
1536 SwFrameFormat *pFormat = &GetTableFrameFormat( --i );
1537 if( !pFormat->IsDefault() &&
1538 pFormat->GetName() == rFormatName && IsUsed( *pFormat ) )
1539 return pFormat;
1540 }
1541 return nullptr;
1542}
1543
1544void SwWrtShell::addCurrentPosition() {
1545 SwPaM* pPaM = GetCursor();
1546 m_aNavigationMgr.addEntry(*pPaM->GetPoint());
1547}
1548
1549// Applying templates
1550
1551void SwWrtShell::SetPageStyle(const OUString &rCollName)
1552{
1553 if( !SwCursorShell::HasSelection() && !IsSelFrameMode() && !IsObjSelected() )
1554 {
1555 SwPageDesc* pDesc = FindPageDescByName( rCollName, true );
1556 if( pDesc )
1557 ChgCurPageDesc( *pDesc );
1558 }
1559}
1560
1561// Access templates
1562
1563OUString const & SwWrtShell::GetCurPageStyle() const
1564{
1565 return GetPageDesc(GetCurPageDesc( false/*bCalcFrame*/ )).GetName();
1566}
1567
1568// Change the current template referring to the existing change.
1569
1570void SwWrtShell::QuickUpdateStyle()
1571{
1572 SwTextFormatColl *pColl = GetCurTextFormatColl();
1573
1574 // Default cannot be changed
1575 if(pColl && !pColl->IsDefault())
1576 {
1577 FillByEx(pColl);
1578 // Also apply the template to remove hard attribute assignment.
1579 SetTextFormatColl(pColl);
1580 }
1581}
1582
1583void SwWrtShell::AutoUpdatePara(SwTextFormatColl* pColl, const SfxItemSet& rStyleSet, SwPaM* pPaM )
1584{
1585 SwPaM* pCursor = pPaM ? pPaM : GetCursor( );
1586 SfxItemSet aCoreSet(
1587 GetAttrPool(),
1588 svl::Items<
1589 RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
1590 RES_PARATR_BEGIN, RES_PARATR_END - 1,
1591 RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
1592 SID_ATTR_TABSTOP_DEFAULTS( 10000 + 3 ),SID_ATTR_TABSTOP_OFFSET( 10000 + 5 ),
1593 SID_ATTR_BORDER_INNERTypedWhichId<SvxBoxInfoItem>( 10000 + 23 ), SID_ATTR_BORDER_INNERTypedWhichId<SvxBoxInfoItem>( 10000 + 23 ),
1594 SID_ATTR_PARA_MODEL( 10000 + 65 ), SID_ATTR_PARA_KEEP( 10000 + 66 ),
1595 SID_ATTR_PARA_PAGENUM( 10000 + 457 ), SID_ATTR_PARA_PAGENUM( 10000 + 457 )>{});
1596 GetPaMAttr( pCursor, aCoreSet );
1597 bool bReset = false;
1598 SfxItemIter aParaIter( aCoreSet );
1599 for (auto pParaItem = aParaIter.GetCurItem(); pParaItem; pParaItem = aParaIter.NextItem())
1600 {
1601 if(!IsInvalidItem(pParaItem))
1602 {
1603 sal_uInt16 nWhich = pParaItem->Which();
1604 if(SfxItemState::SET == aCoreSet.GetItemState(nWhich) &&
1605 SfxItemState::SET == rStyleSet.GetItemState(nWhich))
1606 {
1607 aCoreSet.ClearItem(nWhich);
1608 bReset = true;
1609 }
1610 }
1611 }
1612 StartAction();
1613 if(bReset)
1614 {
1615 ResetAttr( std::set<sal_uInt16>(), pCursor );
1616 SetAttrSet(aCoreSet, SetAttrMode::DEFAULT, pCursor);
1617 }
1618 mxDoc->ChgFormat(*pColl, rStyleSet );
1619 EndAction();
1620}
1621
1622void SwWrtShell::AutoUpdateFrame( SwFrameFormat* pFormat, const SfxItemSet& rStyleSet )
1623{
1624 StartAction();
1625
1626 ResetFlyFrameAttr( &rStyleSet );
1627 pFormat->SetFormatAttr( rStyleSet );
1628
1629 EndAction();
1630}
1631
1632void SwWrtShell::AutoCorrect( SvxAutoCorrect& rACorr, sal_Unicode cChar )
1633{
1634 ResetCursorStack();
1635 if(!CanInsert())
1636 return;
1637
1638 bool bStarted = false;
1639 SwRewriter aRewriter;
1640
1641 if(HasSelection())
1642 {
1643 // Only parentheses here, because the regular insert
1644 // is already clipped to the editshell
1645 StartAllAction();
1646
1647 OUString aTmpStr1 = SwResId(STR_START_QUOTEreinterpret_cast<char const *>("STR_START_QUOTE" "\004"
u8"“")
) +
1648 GetSelText() +
1649 SwResId(STR_END_QUOTEreinterpret_cast<char const *>("STR_END_QUOTE" "\004" u8"”"
)
);
1650 OUString aTmpStr3 = SwResId(STR_START_QUOTEreinterpret_cast<char const *>("STR_START_QUOTE" "\004"
u8"“")
) +
1651 OUStringChar(cChar) +
1652 SwResId(STR_END_QUOTEreinterpret_cast<char const *>("STR_END_QUOTE" "\004" u8"”"
)
);
1653 aRewriter.AddRule( UndoArg1, aTmpStr1 );
1654 aRewriter.AddRule( UndoArg2, SwResId(STR_YIELDSreinterpret_cast<char const *>("STR_YIELDS" "\004" u8"→"
)
) );
1655 aRewriter.AddRule( UndoArg3, aTmpStr3 );
1656
1657 StartUndo( SwUndoId::REPLACE, &aRewriter );
1658 bStarted = true;
1659 DelRight();
1660 }
1661 SwEditShell::AutoCorrect( rACorr, IsInsMode(), cChar );
1662
1663 if(bStarted)
1664 {
1665 EndAllAction();
1666 EndUndo( SwUndoId::REPLACE, &aRewriter );
1667 }
1668}
1669
1670// Some kind of controlled copy ctor
1671
1672SwWrtShell::SwWrtShell( SwWrtShell& rSh, vcl::Window *_pWin, SwView &rShell )
1673 : SwFEShell(rSh, _pWin)
1674 , m_rView(rShell)
1675 , m_aNavigationMgr(*this)
1676{
1677 BITFLD_INI_LISTm_bClearMark = m_bIns = true; m_bAddMode = m_bBlockMode = m_bExtMode
= m_bInSelect = m_bLayoutMode = m_bSelWrd = m_bSelLn = m_bRetainSelection
= false; m_bIsInClickToEdit = false;
1678 CurrShell aCurr( this );
1679
1680 SetSfxViewShell( static_cast<SfxViewShell *>(&rShell) );
1681 SetFlyMacroLnk( LINK(this, SwWrtShell, ExecFlyMac)::tools::detail::makeLink( ::tools::detail::castTo<SwWrtShell
*>(this), &SwWrtShell::LinkStubExecFlyMac)
);
1682
1683 // place the cursor on the first field...
1684 IFieldmark *pBM = nullptr;
1685 if ( IsFormProtected() && ( pBM = GetFieldmarkAfter( ) ) !=nullptr ) {
1686 GotoFieldmark(pBM);
1687 }
1688}
1689
1690SwWrtShell::SwWrtShell( SwDoc& rDoc, vcl::Window *_pWin, SwView &rShell,
1691 const SwViewOption *pViewOpt )
1692 : SwFEShell(rDoc, _pWin, pViewOpt)
1693 , m_rView(rShell)
1694 , m_aNavigationMgr(*this)
1695{
1696 BITFLD_INI_LISTm_bClearMark = m_bIns = true; m_bAddMode = m_bBlockMode = m_bExtMode
= m_bInSelect = m_bLayoutMode = m_bSelWrd = m_bSelLn = m_bRetainSelection
= false; m_bIsInClickToEdit = false;
1697 CurrShell aCurr( this );
1698 SetSfxViewShell( static_cast<SfxViewShell *>(&rShell) );
1699 SetFlyMacroLnk( LINK(this, SwWrtShell, ExecFlyMac)::tools::detail::makeLink( ::tools::detail::castTo<SwWrtShell
*>(this), &SwWrtShell::LinkStubExecFlyMac)
);
1700
1701 // place the cursor on the first field...
1702 IFieldmark *pBM = nullptr;
1703 if ( IsFormProtected() && ( pBM = GetFieldmarkAfter( ) ) !=nullptr ) {
1704 GotoFieldmark(pBM);
1705 }
1706}
1707
1708SwWrtShell::~SwWrtShell()
1709{
1710 CurrShell aCurr( this );
1711 while(IsModePushed())
1712 PopMode();
1713 while(PopCursor(false))
1714 ;
1715 SwTransferable::ClearSelection( *this );
1716}
1717
1718bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete)
1719{
1720 bool bRet = SwCursorShell::Pop(eDelete);
1721 if( bRet && IsSelection() )
1722 {
1723 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
1724 m_fnKillSel = &SwWrtShell::ResetSelect;
1725 }
1726 return bRet;
1727}
1728
1729bool SwWrtShell::CanInsert()
1730{
1731 if(IsSelFrameMode())
1732 {
1733 return false;
1734 }
1735
1736 if(IsObjSelected())
1737 {
1738 return false;
1739 }
1740
1741 if(GetView().GetDrawFuncPtr())
1742 {
1743 return false;
1744 }
1745
1746 if(GetView().GetPostItMgr()->GetActiveSidebarWin())
1747 {
1748 return false;
1749 }
1750
1751 return true;
1752}
1753
1754void SwWrtShell::ChgDBData(const SwDBData& aDBData)
1755{
1756 SwEditShell::ChgDBData(aDBData);
1757 //notify the db-beamer if available
1758 GetView().NotifyDBChanged();
1759}
1760
1761OUString SwWrtShell::GetSelDescr() const
1762{
1763 OUString aResult;
1764
1765 SelectionType nSelType = GetSelectionType();
1766 switch (nSelType)
1767 {
1768 case SelectionType::Graphic:
1769 aResult = SwResId(STR_GRAPHICreinterpret_cast<char const *>("STR_GRAPHIC" "\004" u8"image"
)
);
1770
1771 break;
1772 case SelectionType::Frame:
1773 {
1774 const SwFrameFormat * pFrameFormat = GetSelectedFrameFormat();
1775
1776 if (pFrameFormat)
1777 aResult = pFrameFormat->GetDescription();
1778 }
1779 break;
1780 case SelectionType::DrawObject:
1781 {
1782 aResult = SwResId(STR_DRAWING_OBJECTSreinterpret_cast<char const *>("STR_DRAWING_OBJECTS" "\004"
u8"drawing object(s)")
);
1783 }
1784 break;
1785 default:
1786 if (mxDoc)
1787 aResult = GetCursorDescr();
1788 }
1789
1790 return aResult;
1791}
1792
1793void SwWrtShell::ApplyViewOptions( const SwViewOption &rOpt )
1794{
1795 SwFEShell::ApplyViewOptions( rOpt );
1796 //#i115062# invalidate meta character slot
1797 GetView().GetViewFrame()->GetBindings().Invalidate( FN_VIEW_META_CHARS((20000 + 200) + 24) );
1798}
1799
1800void SwWrtShell::SetReadonlyOption(bool bSet)
1801{
1802 GetView().GetEditWin().GetFrameControlsManager().SetReadonlyControls( bSet );
1803 SwViewShell::SetReadonlyOption( bSet );
1804}
1805
1806// Switch on/off header or footer of a page style - if an empty name is
1807// given all styles are changed
1808
1809void SwWrtShell::ChangeHeaderOrFooter(
1810 const OUString& rStyleName, bool bHeader, bool bOn, bool bShowWarning)
1811{
1812 SdrView *const pSdrView = GetDrawView();
1813 if (pSdrView && pSdrView->IsTextEdit())
1814 { // tdf#107474 deleting header may delete active drawing object
1815 pSdrView->SdrEndTextEdit(true);
1816 }
1817 addCurrentPosition();
1818 StartAllAction();
1819 StartUndo( SwUndoId::HEADER_FOOTER ); // #i7983#
1820 bool bExecute = true;
1821 bool bCursorSet = false;
1822 for( size_t nFrom = 0, nTo = GetPageDescCnt();
1823 nFrom < nTo; ++nFrom )
1824 {
1825 SwPageDesc aDesc( GetPageDesc( nFrom ));
1826 OUString sTmp(aDesc.GetName());
1827 if( rStyleName.isEmpty() || rStyleName == sTmp )
1828 {
1829 bool bChgd = false;
1830
1831 if( bShowWarning && !bOn && GetActiveView() && GetActiveView() == &GetView() &&
1832 ( (bHeader && aDesc.GetMaster().GetHeader().IsActive()) ||
1833 (!bHeader && aDesc.GetMaster().GetFooter().IsActive()) ) )
1834 {
1835 bShowWarning = false;
1836 //Actions have to be closed while the dialog is showing
1837 EndAllAction();
1838
1839 weld::Window* pParent = GetView().GetFrameWeld();
1840 short nResult;
1841 if (bHeader) {
1842 nResult = DeleteHeaderDialog(pParent).run();
1843 } else {
1844 nResult = DeleteFooterDialog(pParent).run();
1845 }
1846
1847 bExecute = nResult == RET_YES;
1848 StartAllAction();
1849 if (nResult == RET_YES)
1850 ToggleHeaderFooterEdit();
1851 }
1852 if( bExecute )
1853 {
1854 bChgd = true;
1855 SwFrameFormat &rMaster = aDesc.GetMaster();
1856 if(bHeader)
1857 rMaster.SetFormatAttr( SwFormatHeader( bOn ));
1858 else
1859 rMaster.SetFormatAttr( SwFormatFooter( bOn ));
1860 if( bOn )
1861 {
1862 SvxULSpaceItem aUL(bHeader ? 0 : MM50283, bHeader ? MM50283 : 0, RES_UL_SPACE );
1863 SwFrameFormat* pFormat = bHeader ?
1864 const_cast<SwFrameFormat*>(rMaster.GetHeader().GetHeaderFormat()) :
1865 const_cast<SwFrameFormat*>(rMaster.GetFooter().GetFooterFormat());
1866 pFormat->SetFormatAttr( aUL );
1867 }
1868 }
1869 if( bChgd )
1870 {
1871 ChgPageDesc( nFrom, aDesc );
1872
1873 if( !bCursorSet && bOn )
1874 {
1875 if ( !IsHeaderFooterEdit() )
1876 ToggleHeaderFooterEdit();
1877 bCursorSet = SetCursorInHdFt(
1878 rStyleName.isEmpty() ? SIZE_MAX(18446744073709551615UL) : nFrom,
1879 bHeader );
1880 }
1881 }
1882 }
1883 }
1884 EndUndo( SwUndoId::HEADER_FOOTER ); // #i7983#
1885 EndAllAction();
1886}
1887
1888void SwWrtShell::SetShowHeaderFooterSeparator( FrameControlType eControl, bool bShow )
1889{
1890 SwViewShell::SetShowHeaderFooterSeparator( eControl, bShow );
1891 if ( !bShow )
1892 GetView().GetEditWin().GetFrameControlsManager().HideControls( eControl );
1893}
1894
1895void SwWrtShell::InsertPostIt(SwFieldMgr& rFieldMgr, const SfxRequest& rReq)
1896{
1897 SwPostItField* pPostIt = dynamic_cast<SwPostItField*>(rFieldMgr.GetCurField());
1898 bool bNew = !(pPostIt && pPostIt->GetTyp()->Which() == SwFieldIds::Postit);
1899 if (bNew || GetView().GetPostItMgr()->IsAnswer())
1900 {
1901 const SvxPostItAuthorItem* pAuthorItem = rReq.GetArg<SvxPostItAuthorItem>(SID_ATTR_POSTIT_AUTHORTypedWhichId<SvxPostItAuthorItem>( 10000 + 44 ));
1902 OUString sAuthor;
1903 if ( pAuthorItem )
1904 sAuthor = pAuthorItem->GetValue();
1905 else
1906 {
1907 std::size_t nAuthor = SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->GetRedlineAuthor();
1908 sAuthor = SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->GetRedlineAuthor(nAuthor);
1909 }
1910
1911 const SvxPostItTextItem* pTextItem = rReq.GetArg<SvxPostItTextItem>(SID_ATTR_POSTIT_TEXTTypedWhichId<SvxPostItTextItem>( 10000 + 46 ));
1912 OUString sText;
1913 if ( pTextItem )
1914 sText = pTextItem->GetValue();
1915
1916 // If we have a text already registered for answer, use that
1917 if (GetView().GetPostItMgr()->IsAnswer() && !GetView().GetPostItMgr()->GetAnswerText().isEmpty())
1918 {
1919 sText = GetView().GetPostItMgr()->GetAnswerText();
1920 GetView().GetPostItMgr()->RegisterAnswerText(OUString());
1921 }
1922
1923 if ( HasSelection() && !IsTableMode() )
1924 {
1925 KillPams();
1926 }
1927
1928 // #i120513# Inserting a comment into an autocompletion crashes
1929 // --> suggestion has to be removed before
1930 GetView().GetEditWin().StopQuickHelp();
1931
1932 SwInsertField_Data aData(SwFieldTypesEnum::Postit, 0, sAuthor, sText, 0);
1933
1934 if (IsSelFrameMode())
1935 {
1936 SwFlyFrame* pFly = GetSelectedFlyFrame();
1937
1938 // Remember the anchor of the selected object before deletion.
1939 std::unique_ptr<SwPosition> pAnchor;
1940 if (pFly)
1941 {
1942 SwFrameFormat* pFormat = pFly->GetFormat();
1943 if (pFormat)
1944 {
1945 RndStdIds eAnchorId = pFormat->GetAnchor().GetAnchorId();
1946 if ((eAnchorId == RndStdIds::FLY_AS_CHAR || eAnchorId == RndStdIds::FLY_AT_CHAR) && pFormat->GetAnchor().GetContentAnchor())
1947 {
1948 pAnchor.reset(new SwPosition(*pFormat->GetAnchor().GetContentAnchor()));
1949 }
1950 }
1951 }
1952
1953 // A frame is selected, end frame selection.
1954 EnterStdMode();
1955 GetView().AttrChangedNotify(nullptr);
1956
1957 // Set up text selection, so the anchor of the frame will be the anchor of the
1958 // comment.
1959 if (pFly)
1960 {
1961 *GetCurrentShellCursor().GetPoint() = *pAnchor;
1962 SwFrameFormat* pFormat = pFly->GetFormat();
1963 if (pFormat && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR)
1964 {
1965 Right(CRSR_SKIP_CELLS, /*bSelect=*/true, 1, /*bBasicCall=*/false, /*bVisual=*/true);
1966 }
1967 else if (pFormat && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_CHAR)
1968 {
1969 aData.m_pAnnotationRange.reset(new SwPaM(*GetCurrentShellCursor().Start(),
1970 *GetCurrentShellCursor().End()));
1971 }
1972 }
1973 }
1974
1975 rFieldMgr.InsertField( aData );
1976
1977 Push();
1978 SwCursorShell::Left(1, CRSR_SKIP_CHARS);
1979 pPostIt = static_cast<SwPostItField*>(rFieldMgr.GetCurField());
1980 Pop(SwCursorShell::PopMode::DeleteCurrent); // Restore cursor position
1981 }
1982
1983 // Client has disabled annotations rendering, no need to
1984 // focus the postit field
1985 if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
1986 return;
1987
1988 if (pPostIt)
1989 {
1990 SwFieldType* pType = GetDoc()->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Postit, OUString(), false);
1991 if(auto pFormat = pType->FindFormatForField(pPostIt))
1992 pFormat->Broadcast( SwFormatFieldHint( nullptr, SwFormatFieldHintWhich::FOCUS, &GetView() ) );
1993 }
1994}
1995bool SwWrtShell::IsOutlineContentFolded(const size_t nPos)
1996{
1997 const SwNodes& rNodes = GetDoc()->GetNodes();
1998 const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
1999
2000 assert(nPos < rOutlineNodes.size())(static_cast <bool> (nPos < rOutlineNodes.size()) ? void
(0) : __assert_fail ("nPos < rOutlineNodes.size()", "/home/maarten/src/libreoffice/core/sw/source/uibase/wrtsh/wrtsh1.cxx"
, 2000, __extension__ __PRETTY_FUNCTION__))
;
2001
2002 SwNode* pOutlineNode = rOutlineNodes[nPos];
2003 if (pOutlineNode->IsEndNode())
2004 return false;
2005
2006 bool bOutlineContentVisibleAttr = false;
2007 if (pOutlineNode->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr))
2008 return !bOutlineContentVisibleAttr;
2009
2010 return false;
2011}
2012
2013void SwWrtShell::ToggleOutlineContentVisibility(SwNode* pNd, bool bForceFold)
2014{
2015 SwOutlineNodes::size_type nPos;
2016 if (GetNodes().GetOutLineNds().Seek_Entry(pNd, &nPos))
2017 ToggleOutlineContentVisibility(nPos, bForceFold);
2018}
2019
2020void SwWrtShell::ToggleOutlineContentVisibility(size_t nPos, bool bForceFold)
2021{
2022 const SwNodes& rNodes = GetNodes();
2023 const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
2024
2025 assert(nPos < rOutlineNodes.size())(static_cast <bool> (nPos < rOutlineNodes.size()) ? void
(0) : __assert_fail ("nPos < rOutlineNodes.size()", "/home/maarten/src/libreoffice/core/sw/source/uibase/wrtsh/wrtsh1.cxx"
, 2025, __extension__ __PRETTY_FUNCTION__))
;
2026
2027 SwNode* pSttNd = rOutlineNodes[nPos];
2028 if (pSttNd->IsEndNode())
2029 return;
2030
2031 SwNode* pEndNd = &rNodes.GetEndOfContent();
2032 if (rOutlineNodes.size() > nPos + 1)
2033 pEndNd = rOutlineNodes[nPos + 1];
2034
2035 if (pSttNd->GetTableBox() || pSttNd->GetIndex() < rNodes.GetEndOfExtras().GetIndex())
2036 {
2037 // limit folding to within table box
2038 if (pSttNd->EndOfSectionIndex() < pEndNd->GetIndex() )
2039 pEndNd = pSttNd->EndOfSectionNode();
2040 }
2041 // if pSttNd isn't in table but pEndNd is, skip over all outline nodes in table
2042 else if (pEndNd->GetTableBox())
2043 {
2044 pEndNd = &rNodes.GetEndOfContent();
2045 for (size_t nOutlinePos = nPos + 2; nOutlinePos < rOutlineNodes.size(); nOutlinePos++)
2046 {
2047 if (!(rOutlineNodes[nOutlinePos]->GetTableBox()))
2048 {
2049 pEndNd = rOutlineNodes[nOutlinePos];
2050 break;
2051 }
2052 }
2053 }
2054
2055 if (IsOutlineContentFolded(nPos) && !bForceFold)
2056 {
2057 // unfold
2058 SwNodeIndex aIdx(*pSttNd, +1);
2059 MakeFrames(GetDoc(), aIdx, *pEndNd);
2060
2061 pSttNd->GetTextNode()->SetAttrOutlineContentVisible(true);
2062
2063 if (GetViewOptions()->IsShowOutlineContentVisibilityButton())
2064 {
2065 // remove fold button if focus is not on outline frame control window
2066 SwContentFrame* pFrame = pSttNd->GetTextNode()->getLayoutFrame(nullptr);
2067 if (pFrame && !pFrame->IsInDtor())
2068 {
2069 SwFrameControlPtr pOutlineFrameControl = GetView().GetEditWin().GetFrameControlsManager().GetControl(FrameControlType::Outline, pFrame);
2070 if (pOutlineFrameControl && pOutlineFrameControl->GetWindow() && !pOutlineFrameControl->GetWindow()->HasFocus())
2071 GetView().GetEditWin().GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, pFrame);
2072 }
2073
2074 // fold revealed outline nodes that have collapsed content
2075 while (aIdx != *pEndNd)
2076 {
2077 SwNode* pTmpNd = &aIdx.GetNode();
2078 if (pTmpNd->IsTextNode() && pTmpNd->GetTextNode()->IsOutline())
2079 {
2080 SwTextNode* pTmpTextNd = pTmpNd->GetTextNode();
2081 bool bOutlineContentVisibleAttr = true;
2082 if (pTmpTextNd->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr) &&
2083 !bOutlineContentVisibleAttr)
2084 {
2085 SwOutlineNodes::size_type iPos;
2086 if (rOutlineNodes.Seek_Entry(pTmpTextNd, &iPos))
2087 {
2088 if (pTmpTextNd->getLayoutFrame(nullptr))
2089 ToggleOutlineContentVisibility(iPos, true);
2090 }
2091 }
2092 }
2093 aIdx++;
2094 }
2095 }
2096 }
2097 else
2098 {
2099 // fold
2100 for (SwNodeIndex aIdx(*pSttNd, +1); &aIdx.GetNode() != pEndNd; aIdx++)
2101 {
2102 SwNode* pNd = &aIdx.GetNode();
2103 if (pNd->IsContentNode())
2104 pNd->GetContentNode()->DelFrames(nullptr);
2105 else if (pNd->IsTableNode())
2106 pNd->GetTableNode()->DelFrames(nullptr);
2107 }
2108 pSttNd->GetTextNode()->SetAttrOutlineContentVisible(false);
2109 }
2110 GetView().GetEditWin().Invalidate(InvalidateFlags::Update);
2111 GetDoc()->GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged));
2112}
2113
2114/* 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();
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;
26
Calling 'Reference::get'
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)
8
Calling implicit copy constructor for 'VclPtr<SfxAbstractInsertObjectDialog>'
9
Calling copy constructor for 'Reference<SfxAbstractInsertObjectDialog>'
12
Returning from copy constructor for 'Reference<SfxAbstractInsertObjectDialog>'
13
Returning from copy constructor for 'VclPtr<SfxAbstractInsertObjectDialog>'
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)
10
Assuming field 'm_pBody' is non-null
11
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
16.1
Field 'm_pBody' is non-null
16.1
Field 'm_pBody' is non-null
16.1
Field 'm_pBody' is non-null
16.1
Field 'm_pBody' is non-null
)
17
Taking true branch
113 m_pBody->release();
18
Calling 'VclReferenceBase::release'
22
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;
27
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)
19
Assuming the condition is true
20
Taking true branch
40 delete this;
21
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