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 baside2.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 -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 EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/basctl/inc -I /home/maarten/src/libreoffice/core/basctl/sdi -I /home/maarten/src/libreoffice/core/basctl/source/inc -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/SdiTarget/basctl/sdi -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/basctl/source/basicide/baside2.cxx

/home/maarten/src/libreoffice/core/basctl/source/basicide/baside2.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 "baside2.hxx"
21#include <baside3.hxx>
22#include <basobj.hxx>
23#include <basidesh.hxx>
24#include "brkdlg.hxx"
25#include <iderdll.hxx>
26#include <iderid.hxx>
27#include "moduldlg.hxx"
28#include <docsignature.hxx>
29#include <officecfg/Office/BasicIDE.hxx>
30
31#include <helpids.h>
32#include <strings.hrc>
33
34#include <basic/basmgr.hxx>
35#include <basic/basrdll.hxx>
36#include <basic/sbmeth.hxx>
37#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
38#include <com/sun/star/script/ModuleType.hpp>
39#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
40#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
41#include <com/sun/star/ui/dialogs/FilePicker.hpp>
42#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
43#include <comphelper/SetFlagContextHelper.hxx>
44#include <comphelper/string.hxx>
45#include <svl/srchdefs.hxx>
46#include <sfx2/bindings.hxx>
47#include <sfx2/docfile.hxx>
48#include <sfx2/request.hxx>
49#include <sfx2/viewfrm.hxx>
50#include <sot/exchange.hxx>
51#include <svl/eitem.hxx>
52#include <svl/srchitem.hxx>
53#include <svl/stritem.hxx>
54#include <svl/visitem.hxx>
55#include <svl/whiter.hxx>
56#include <svx/svxids.hrc>
57#include <tools/debug.hxx>
58#include <vcl/waitobj.hxx>
59#include <vcl/errinf.hxx>
60#include <vcl/event.hxx>
61#include <vcl/print.hxx>
62#include <vcl/svapp.hxx>
63#include <vcl/textview.hxx>
64#include <vcl/weld.hxx>
65#include <vcl/xtextedt.hxx>
66#include <toolkit/helper/vclunohelper.hxx>
67#include <cassert>
68#include <osl/diagnose.h>
69#include <officecfg/Office/Common.hxx>
70
71namespace basctl
72{
73
74namespace
75{
76
77namespace Print
78{
79 long const nLeftMargin = 1700;
80 long const nRightMargin = 900;
81 long const nTopMargin = 2000;
82 long const nBottomMargin = 1000;
83 long const nBorder = 300;
84}
85
86short const ValidWindow = 0x1234;
87
88// What (who) are OW and MTF? Compare to baside3.cxx where an
89// identically named variable, used in the same way, has the value
90// "*.*" on Windows, "*" otherwise. Is that what should be done here,
91// too?
92
93#if defined(OW) || defined(MTF)
94char const FilterMask_All[] = "*";
95#else
96char const FilterMask_All[] = "*.*";
97#endif
98
99} // end anonymous namespace
100
101using namespace ::com::sun::star;
102using namespace ::com::sun::star::uno;
103using namespace ::com::sun::star::ui::dialogs;
104using namespace utl;
105using namespace comphelper;
106
107namespace
108{
109
110void lcl_PrintHeader( Printer* pPrinter, sal_uInt16 nPages, sal_uInt16 nCurPage, const OUString& rTitle, bool bOutput )
111{
112 Size const aSz = pPrinter->GetOutputSize();
113
114 const Color aOldLineColor( pPrinter->GetLineColor() );
115 const Color aOldFillColor( pPrinter->GetFillColor() );
116 const vcl::Font aOldFont( pPrinter->GetFont() );
117
118 pPrinter->SetLineColor( COL_BLACK );
119 pPrinter->SetFillColor();
120
121 vcl::Font aFont( aOldFont );
122 aFont.SetWeight( WEIGHT_BOLD );
123 aFont.SetAlignment( ALIGN_BOTTOM );
124 pPrinter->SetFont( aFont );
125
126 long nFontHeight = pPrinter->GetTextHeight();
127
128 // 1st Border => line, 2+3 Border = free space
129 long nYTop = Print::nTopMargin - 3*Print::nBorder - nFontHeight;
130
131 long nXLeft = Print::nLeftMargin - Print::nBorder;
132 long nXRight = aSz.Width() - Print::nRightMargin + Print::nBorder;
133
134 if( bOutput )
135 pPrinter->DrawRect(tools::Rectangle(
136 Point(nXLeft, nYTop),
137 Size(nXRight - nXLeft, aSz.Height() - nYTop - Print::nBottomMargin + Print::nBorder)
138 ));
139
140
141 long nY = Print::nTopMargin - 2*Print::nBorder;
142 Point aPos(Print::nLeftMargin, nY);
143 if( bOutput )
144 pPrinter->DrawText( aPos, rTitle );
145 if ( nPages != 1 )
146 {
147 aFont.SetWeight( WEIGHT_NORMAL );
148 pPrinter->SetFont( aFont );
149 aPos.AdjustX(pPrinter->GetTextWidth( rTitle ) );
150
151 if( bOutput )
152 {
153 OUString aPageStr = " [" + IDEResId(RID_STR_PAGEreinterpret_cast<char const *>("RID_STR_PAGE" "\004" u8"Page"
)
) + " " + OUString::number( nCurPage ) + "]";
154 pPrinter->DrawText( aPos, aPageStr );
155 }
156 }
157
158 nY = Print::nTopMargin - Print::nBorder;
159
160 if( bOutput )
161 pPrinter->DrawLine( Point( nXLeft, nY ), Point( nXRight, nY ) );
162
163 pPrinter->SetFont( aOldFont );
164 pPrinter->SetFillColor( aOldFillColor );
165 pPrinter->SetLineColor( aOldLineColor );
166}
167
168void lcl_ConvertTabsToSpaces( OUString& rLine )
169{
170 if ( rLine.isEmpty() )
171 return;
172
173 OUStringBuffer aResult( rLine );
174 sal_Int32 nPos = 0;
175 sal_Int32 nMax = aResult.getLength();
176 while ( nPos < nMax )
177 {
178 if ( aResult[nPos] == '\t' )
179 {
180 // not 4 Blanks, but at 4 TabPos:
181 OUStringBuffer aBlanker;
182 string::padToLength(aBlanker, ( 4 - ( nPos % 4 ) ), ' ');
183 aResult.remove( nPos, 1 );
184 aResult.insert( nPos, aBlanker.makeStringAndClear() );
185 nMax = aResult.getLength();
186 }
187 ++nPos;
188 }
189 rLine = aResult.makeStringAndClear();
190}
191
192} // namespace
193
194ModulWindow::ModulWindow (ModulWindowLayout* pParent, ScriptDocument const& rDocument,
195 const OUString& aLibName, const OUString& aName, OUString const & aModule)
196 : BaseWindow(pParent, rDocument, aLibName, aName)
197 , m_rLayout(*pParent)
198 , m_nValid(ValidWindow)
199 , m_aXEditorWindow(VclPtr<ComplexEditorWindow>::Create(this))
200 , m_aModule(aModule)
201{
202 m_aXEditorWindow->Show();
203 SetBackground();
204}
205
206SbModuleRef const & ModulWindow::XModule()
207{
208 // ModuleWindows can now be created as a result of the
209 // modules getting created via the api. This is a result of an
210 // elementInserted event from the BasicLibrary container.
211 // However the SbModule is also created from a different listener to
212 // the same event ( in basmgr ) Therefore it is possible when we look
213 // for m_xModule it may not yet be available, here we keep trying to access
214 // the module until such time as it exists
215
216 if ( !m_xModule.is() )
217 {
218 BasicManager* pBasMgr = GetDocument().getBasicManager();
219 if ( pBasMgr )
220 {
221 StarBASIC* pBasic = pBasMgr->GetLib( GetLibName() );
222 if ( pBasic )
223 {
224 m_xBasic = pBasic;
225 m_xModule = pBasic->FindModule( GetName() );
226 }
227 }
228 }
229 return m_xModule;
230}
231
232ModulWindow::~ModulWindow()
233{
234 disposeOnce();
235}
236
237void ModulWindow::dispose()
238{
239 m_nValid = 0;
240 StarBASIC::Stop();
241 m_aXEditorWindow.disposeAndClear();
242 BaseWindow::dispose();
243}
244
245
246void ModulWindow::GetFocus()
247{
248 if (m_nValid != ValidWindow)
249 return;
250 m_aXEditorWindow->GetEdtWindow().GrabFocus();
251 // don't call basic calls because focus is somewhere else...
252}
253
254void ModulWindow::DoInit()
255{
256 if (GetVScrollBar())
257 GetVScrollBar()->Hide();
258 GetHScrollBar()->Show();
259 GetEditorWindow().InitScrollBars();
260}
261
262void ModulWindow::Paint(vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle&)
263{
264}
265
266void ModulWindow::Resize()
267{
268 m_aXEditorWindow->SetPosSizePixel( Point( 0, 0 ), GetOutputSizePixel() );
269}
270
271void ModulWindow::CheckCompileBasic()
272{
273 if ( !XModule().is() )
274 return;
275
276 // never compile while running!
277 bool const bRunning = StarBASIC::IsRunning();
278 bool const bModified = ( !m_xModule->IsCompiled() ||
279 ( GetEditEngine() && GetEditEngine()->IsModified() ) );
280
281 if ( bRunning || !bModified )
282 return;
283
284 bool bDone = false;
285
286 GetShell()->GetViewFrame()->GetWindow().EnterWait();
287
288 AssertValidEditEngine();
289 GetEditorWindow().SetSourceInBasic();
290
291 bool bWasModified = GetBasic()->IsModified();
292
293 {
294 // tdf#106529: only use strict compilation mode when compiling from the IDE
295 css::uno::ContextLayer layer(comphelper::NewFlagContext("BasicStrict"));
296 bDone = m_xModule->Compile();
297 }
298 if ( !bWasModified )
299 GetBasic()->SetModified(false);
300
301 if ( bDone )
302 {
303 GetBreakPoints().SetBreakPointsInBasic( m_xModule.get() );
304 }
305
306 GetShell()->GetViewFrame()->GetWindow().LeaveWait();
307
308 m_aStatus.bError = !bDone;
309 m_aStatus.bIsRunning = false;
310}
311
312void ModulWindow::BasicExecute()
313{
314 // #116444# check security settings before macro execution
315 ScriptDocument aDocument( GetDocument() );
316 bool bMacrosDisabled = officecfg::Office::Common::Security::Scripting::DisableMacrosExecution::get();
317 if (bMacrosDisabled || (aDocument.isDocument() && !aDocument.allowMacros()))
318 {
319 std::unique_ptr<weld::MessageDialog> xBox(
320 Application::CreateMessageDialog(GetFrameWeld(), VclMessageType::Warning,
321 VclButtonsType::Ok, IDEResId(RID_STR_CANNOTRUNMACROreinterpret_cast<char const *>("RID_STR_CANNOTRUNMACRO"
"\004" u8"For security reasons, you cannot run this macro.\n\nFor more information, check the security settings."
)
)));
322 xBox->run();
323 return;
324 }
325
326 CheckCompileBasic();
327
328 if ( !XModule().is() || !m_xModule->IsCompiled() || m_aStatus.bError )
329 return;
330
331 if ( GetBreakPoints().size() )
332 m_aStatus.nBasicFlags = m_aStatus.nBasicFlags | BasicDebugFlags::Break;
333
334 if ( !m_aStatus.bIsRunning )
335 {
336 DBG_ASSERT( m_xModule.is(), "No Module!" )do { if (true && (!(m_xModule.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/basctl/source/basicide/baside2.cxx"
":" "336" ": "), "%s", "No Module!"); } } while (false)
;
337 AddStatus( BASWIN_RUNNINGBASIC );
338 sal_uInt16 nStart, nEnd;
339 TextSelection aSel = GetEditView()->GetSelection();
340 // Init cursor to top
341 const sal_uInt32 nCurMethodStart = aSel.GetStart().GetPara() + 1;
342 SbMethod* pMethod = nullptr;
343 // first Macro, else blind "Main" (ExtSearch?)
344 for ( sal_uInt32 nMacro = 0; nMacro < m_xModule->GetMethods()->Count32(); nMacro++ )
345 {
346 SbMethod* pM = static_cast<SbMethod*>(m_xModule->GetMethods()->Get32( nMacro ));
347 assert(pM && "Method?")(static_cast <bool> (pM && "Method?") ? void (0
) : __assert_fail ("pM && \"Method?\"", "/home/maarten/src/libreoffice/core/basctl/source/basicide/baside2.cxx"
, 347, __extension__ __PRETTY_FUNCTION__))
;
348 pM->GetLineRange( nStart, nEnd );
349 if ( nCurMethodStart >= nStart && nCurMethodStart <= nEnd )
350 {
351 // matched a method to the cursor position
352 pMethod = pM;
353 break;
354 }
355 }
356 if ( !pMethod )
357 {
358 // If not in a method then prompt the user
359 ChooseMacro(GetFrameWeld(), uno::Reference<frame::XModel>());
360 return;
361 }
362 pMethod->SetDebugFlags(m_aStatus.nBasicFlags);
363 BasicDLL::SetDebugMode(true);
364 RunMethod(pMethod);
365 BasicDLL::SetDebugMode(false);
366 // if cancelled during Interactive=false
367 BasicDLL::EnableBreak(true);
368 ClearStatus( BASWIN_RUNNINGBASIC );
369 }
370 else
371 m_aStatus.bIsRunning = false; // cancel of Reschedule()
372}
373
374void ModulWindow::CompileBasic()
375{
376 CheckCompileBasic();
377
378 XModule().is() && m_xModule->IsCompiled();
379}
380
381void ModulWindow::BasicRun()
382{
383 m_aStatus.nBasicFlags = BasicDebugFlags::NONE;
384 BasicExecute();
385}
386
387void ModulWindow::BasicStepOver()
388{
389 m_aStatus.nBasicFlags = BasicDebugFlags::StepInto | BasicDebugFlags::StepOver;
390 BasicExecute();
391}
392
393
394void ModulWindow::BasicStepInto()
395{
396 m_aStatus.nBasicFlags = BasicDebugFlags::StepInto;
397 BasicExecute();
398}
399
400void ModulWindow::BasicStepOut()
401{
402 m_aStatus.nBasicFlags = BasicDebugFlags::StepOut;
403 BasicExecute();
404}
405
406
407void ModulWindow::BasicStop()
408{
409 StarBASIC::Stop();
410 m_aStatus.bIsRunning = false;
411}
412
413void ModulWindow::LoadBasic()
414{
415 Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
416 Reference < XFilePicker3 > xFP = FilePicker::createWithMode(xContext, TemplateDescription::FILEOPEN_SIMPLE);
417
418 if ( !m_sCurPath.isEmpty() )
419 xFP->setDisplayDirectory ( m_sCurPath );
420
421 xFP->appendFilter( "BASIC" , "*.bas" );
422 xFP->appendFilter( IDEResId(RID_STR_FILTER_ALLFILESreinterpret_cast<char const *>("RID_STR_FILTER_ALLFILES"
"\004" u8"<All>")
), FilterMask_All );
423 xFP->setCurrentFilter( "BASIC" );
424
425 if( xFP->execute() != RET_OK )
426 return;
427
428 Sequence< OUString > aPaths = xFP->getSelectedFiles();
429 m_sCurPath = aPaths[0];
430 SfxMedium aMedium( m_sCurPath, StreamMode::READ | StreamMode::SHARE_DENYWRITE | StreamMode::NOCREATE );
431 SvStream* pStream = aMedium.GetInStream();
432 if ( pStream )
433 {
434 AssertValidEditEngine();
435 sal_uInt32 nLines = CalcLineCount( *pStream );
436 // nLines*4: ReadText/Formatting/Highlighting/Formatting
437 GetEditorWindow().CreateProgress( IDEResId(RID_STR_GENERATESOURCEreinterpret_cast<char const *>("RID_STR_GENERATESOURCE"
"\004" u8"Generating source")
), nLines*4 );
438 GetEditEngine()->SetUpdateMode( false );
439 GetEditView()->Read( *pStream );
440 GetEditEngine()->SetUpdateMode( true );
441 GetEditorWindow().PaintImmediately();
442 GetEditorWindow().ForceSyntaxTimeout();
443 GetEditorWindow().DestroyProgress();
444 ErrCode nError = aMedium.GetError();
445 if ( nError )
446 ErrorHandler::HandleError( nError );
447 }
448 else
449 {
450 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetFrameWeld(),
451 VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_COULDNTREADreinterpret_cast<char const *>("RID_STR_COULDNTREAD" "\004"
u8"The file could not be read")
)));
452 xBox->run();
453 }
454}
455
456
457void ModulWindow::SaveBasicSource()
458{
459 Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
460 Reference < XFilePicker3 > xFP = FilePicker::createWithMode(xContext, TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD);
461
462 Reference< XFilePickerControlAccess > xFPControl(xFP, UNO_QUERY);
463 xFPControl->enableControl(ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, false);
464 Any aValue;
465 aValue <<= true;
466 xFPControl->setValue(ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0, aValue);
467
468 if ( !m_sCurPath.isEmpty() )
469 xFP->setDisplayDirectory ( m_sCurPath );
470
471 xFP->appendFilter( "BASIC", "*.bas" );
472 xFP->appendFilter( IDEResId(RID_STR_FILTER_ALLFILESreinterpret_cast<char const *>("RID_STR_FILTER_ALLFILES"
"\004" u8"<All>")
), FilterMask_All );
473 xFP->setCurrentFilter( "BASIC" );
474
475 if( xFP->execute() != RET_OK )
476 return;
477
478 Sequence< OUString > aPaths = xFP->getSelectedFiles();
479 m_sCurPath = aPaths[0];
480 SfxMedium aMedium( m_sCurPath, StreamMode::WRITE | StreamMode::SHARE_DENYWRITE | StreamMode::TRUNC );
481 SvStream* pStream = aMedium.GetOutStream();
482 if ( pStream )
483 {
484 EnterWait();
485 AssertValidEditEngine();
486 GetEditEngine()->Write( *pStream );
487 aMedium.Commit();
488 LeaveWait();
489 ErrCode nError = aMedium.GetError();
490 if ( nError )
491 ErrorHandler::HandleError( nError );
492 }
493 else
494 {
495 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(GetFrameWeld(),
496 VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_COULDNTWRITEreinterpret_cast<char const *>("RID_STR_COULDNTWRITE" "\004"
u8"The file could not be saved")
)));
497 xErrorBox->run();
498 }
499}
500
501void ModulWindow::ImportDialog()
502{
503 const ScriptDocument& rDocument = GetDocument();
504 OUString aLibName = GetLibName();
505 implImportDialog(GetFrameWeld(), m_sCurPath, rDocument, aLibName);
506}
507
508void ModulWindow::ToggleBreakPoint( sal_uInt16 nLine )
509{
510 DBG_ASSERT( XModule().is(), "No Module!" )do { if (true && (!(XModule().is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/basctl/source/basicide/baside2.cxx"
":" "510" ": "), "%s", "No Module!"); } } while (false)
;
511
512 if ( !XModule().is() )
513 return;
514
515 CheckCompileBasic();
516 if ( m_aStatus.bError )
517 {
518 return;
519 }
520
521 BreakPoint* pBrk = GetBreakPoints().FindBreakPoint( nLine );
522 if ( pBrk ) // remove
523 {
524 m_xModule->ClearBP( nLine );
525 GetBreakPoints().remove( pBrk );
526 }
527 else // create one
528 {
529 if ( m_xModule->SetBP( nLine ))
530 {
531 GetBreakPoints().InsertSorted( BreakPoint( nLine ) );
532 if ( StarBASIC::IsRunning() )
533 {
534 for ( sal_uInt32 nMethod = 0; nMethod < m_xModule->GetMethods()->Count32(); nMethod++ )
535 {
536 SbMethod* pMethod = static_cast<SbMethod*>(m_xModule->GetMethods()->Get32( nMethod ));
537 assert(pMethod && "Method not found! (NULL)")(static_cast <bool> (pMethod && "Method not found! (NULL)"
) ? void (0) : __assert_fail ("pMethod && \"Method not found! (NULL)\""
, "/home/maarten/src/libreoffice/core/basctl/source/basicide/baside2.cxx"
, 537, __extension__ __PRETTY_FUNCTION__))
;
538 pMethod->SetDebugFlags( pMethod->GetDebugFlags() | BasicDebugFlags::Break );
539 }
540 }
541 }
542 }
543}
544
545void ModulWindow::UpdateBreakPoint( const BreakPoint& rBrk )
546{
547 DBG_ASSERT( XModule().is(), "No Module!" )do { if (true && (!(XModule().is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/basctl/source/basicide/baside2.cxx"
":" "547" ": "), "%s", "No Module!"); } } while (false)
;
548
549 if ( XModule().is() )
550 {
551 CheckCompileBasic();
552
553 if ( rBrk.bEnabled )
554 m_xModule->SetBP( rBrk.nLine );
555 else
556 m_xModule->ClearBP( rBrk.nLine );
557 }
558}
559
560
561void ModulWindow::BasicToggleBreakPoint()
562{
563 AssertValidEditEngine();
564
565 TextSelection aSel = GetEditView()->GetSelection();
566 aSel.GetStart().GetPara()++; // Basic lines start at 1!
567 aSel.GetEnd().GetPara()++;
568
569 for ( sal_uInt32 nLine = aSel.GetStart().GetPara(); nLine <= aSel.GetEnd().GetPara(); ++nLine )
570 {
571 ToggleBreakPoint( nLine );
572 }
573
574 m_aXEditorWindow->GetBrkWindow().Invalidate();
575}
576
577
578void ModulWindow::BasicToggleBreakPointEnabled()
579{
580 AssertValidEditEngine();
581
582 TextView* pView = GetEditView();
583 if ( !pView )
584 return;
585
586 TextSelection aSel = pView->GetSelection();
587 BreakPointList& rList = GetBreakPoints();
588
589 for ( sal_uInt32 nLine = ++aSel.GetStart().GetPara(), nEnd = ++aSel.GetEnd().GetPara(); nLine <= nEnd; ++nLine )
590 {
591 BreakPoint* pBrk = rList.FindBreakPoint( nLine );
592 if ( pBrk )
593 {
594 pBrk->bEnabled = !pBrk->bEnabled;
595 UpdateBreakPoint( *pBrk );
596 }
597 }
598
599 GetBreakPointWindow().Invalidate();
600}
601
602void ModulWindow::ManageBreakPoints()
603{
604 BreakPointWindow& rBrkWin = GetBreakPointWindow();
605 BreakPointDialog aBrkDlg(rBrkWin.GetFrameWeld(), GetBreakPoints());
606 aBrkDlg.run();
607 rBrkWin.Invalidate();
608}
609
610void ModulWindow::BasicErrorHdl( StarBASIC const * pBasic )
611{
612 GetShell()->GetViewFrame()->ToTop();
613
614 // Return value: BOOL
615 // FALSE: cancel
616 // TRUE: go on...
617 sal_uInt16 nErrorLine = StarBASIC::GetLine() - 1;
618 sal_uInt16 nErrCol1 = StarBASIC::GetCol1();
619 sal_uInt16 nErrCol2 = StarBASIC::GetCol2();
620 if ( nErrCol2 != 0xFFFF )
621 nErrCol2++;
622
623 AssertValidEditEngine();
624 GetEditView()->SetSelection( TextSelection( TextPaM( nErrorLine, nErrCol1 ), TextPaM( nErrorLine, nErrCol2 ) ) );
625
626 // if other basic, the IDE should try to display the correct module
627 bool const bMarkError = pBasic == GetBasic();
628 if ( bMarkError )
629 m_aXEditorWindow->GetBrkWindow().SetMarkerPos(nErrorLine, true);
630
631 // #i47002#
632 Reference< awt::XWindow > xWindow = VCLUnoHelper::GetInterface( this );
633
634 // tdf#118572 make a currently running dialog, regardless of what its modal
635 // to, insensitive to user input until after this error dialog goes away.
636 TopLevelWindowLocker aBusy;
637 aBusy.incBusy(nullptr);
638
639 ErrorHandler::HandleError(StarBASIC::GetErrorCode(), GetFrameWeld());
640
641 aBusy.decBusy();
642
643 // #i47002#
644 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
645 if ( !pWindow )
646 return;
647
648 if ( bMarkError )
649 m_aXEditorWindow->GetBrkWindow().SetNoMarker();
650 return;
651}
652
653BasicDebugFlags ModulWindow::BasicBreakHdl()
654{
655 // Return value: sal_uInt16 => see SB-Debug-Flags
656 sal_uInt16 nErrorLine = StarBASIC::GetLine();
657
658
659 BreakPoint* pBrk = GetBreakPoints().FindBreakPoint( nErrorLine );
660 if ( pBrk )
661 {
662 pBrk->nHitCount++;
663 if ( pBrk->nHitCount <= pBrk->nStopAfter && GetBasic()->IsBreak() )
664 return m_aStatus.nBasicFlags; // go on...
665 }
666
667 nErrorLine--; // EditEngine starts at 0, Basic at 1
668
669 AssertValidEditEngine();
670 GetEditView()->SetSelection( TextSelection( TextPaM( nErrorLine, 0 ), TextPaM( nErrorLine, 0 ) ) );
671 m_aXEditorWindow->GetBrkWindow().SetMarkerPos( nErrorLine );
672
673 m_rLayout.UpdateDebug(false);
674
675 m_aStatus.bIsInReschedule = true;
676 m_aStatus.bIsRunning = true;
677
678 AddStatus( BASWIN_INRESCHEDULE );
679
680 InvalidateDebuggerSlots();
681
682 while( m_aStatus.bIsRunning )
683 Application::Yield();
684
685 m_aStatus.bIsInReschedule = false;
686 m_aXEditorWindow->GetBrkWindow().SetNoMarker();
687
688 ClearStatus( BASWIN_INRESCHEDULE );
689
690 return m_aStatus.nBasicFlags;
691}
692
693void ModulWindow::BasicAddWatch()
694{
695 AssertValidEditEngine();
696 bool bAdd = true;
697 if ( !GetEditView()->HasSelection() )
698 {
699 // tdf#57307 - expand selection to include connector punctuations
700 TextSelection aSel;
701 OUString aWord = GetEditEngine()->GetWord( GetEditView()->GetSelection().GetEnd(), &aSel.GetStart(), &aSel.GetEnd() );
702 if ( !aWord.isEmpty() )
703 GetEditView()->SetSelection( aSel );
704 else
705 bAdd = false;
706 }
707 if ( bAdd )
708 {
709 TextSelection aSel = GetEditView()->GetSelection();
710 if ( aSel.GetStart().GetPara() == aSel.GetEnd().GetPara() ) // single line selection
711 m_rLayout.BasicAddWatch(GetEditView()->GetSelected());
712 }
713}
714
715
716void ModulWindow::EditMacro( const OUString& rMacroName )
717{
718 DBG_ASSERT( XModule().is(), "No Module!" )do { if (true && (!(XModule().is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/basctl/source/basicide/baside2.cxx"
":" "718" ": "), "%s", "No Module!"); } } while (false)
;
719
720 if ( !XModule().is() )
721 return;
722
723 CheckCompileBasic();
724
725 if ( m_aStatus.bError )
726 return;
727
728 sal_uInt16 nStart, nEnd;
729 SbMethod* pMethod = static_cast<SbMethod*>(m_xModule->Find( rMacroName, SbxClassType::Method ));
730 if ( !pMethod )
731 return;
732
733 pMethod->GetLineRange( nStart, nEnd );
734 if ( nStart )
735 {
736 nStart--;
737 nEnd--;
738 }
739 TextSelection aSel( TextPaM( nStart, 0 ), TextPaM( nStart, 0 ) );
740 AssertValidEditEngine();
741 TextView * pView = GetEditView();
742 // scroll if applicable so that first line is at the top
743 long nVisHeight = GetOutputSizePixel().Height();
744 if ( pView->GetTextEngine()->GetTextHeight() > nVisHeight )
745 {
746 long nMaxY = pView->GetTextEngine()->GetTextHeight() - nVisHeight;
747 long nOldStartY = pView->GetStartDocPos().Y();
748 long nNewStartY = static_cast<long>(nStart) * pView->GetTextEngine()->GetCharHeight();
749 nNewStartY = std::min( nNewStartY, nMaxY );
750 pView->Scroll( 0, -(nNewStartY-nOldStartY) );
751 pView->ShowCursor( false );
752 GetEditVScrollBar().SetThumbPos( pView->GetStartDocPos().Y() );
753 }
754 pView->SetSelection( aSel );
755 pView->ShowCursor();
756 pView->GetWindow()->GrabFocus();
757}
758
759void ModulWindow::StoreData()
760{
761 // StoreData is called when the BasicManager is destroyed or
762 // this window is closed.
763 // => interrupts undesired!
764 GetEditorWindow().SetSourceInBasic();
765}
766
767bool ModulWindow::AllowUndo()
768{
769 return GetEditorWindow().CanModify();
770}
771
772void ModulWindow::UpdateData()
773{
774 DBG_ASSERT( XModule().is(), "No Module!" )do { if (true && (!(XModule().is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/basctl/source/basicide/baside2.cxx"
":" "774" ": "), "%s", "No Module!"); } } while (false)
;
775 // UpdateData is called when the source has changed from outside
776 // => interrupts undesired!
777
778 if ( !XModule().is() )
779 return;
780
781 SetModule( m_xModule->GetSource32() );
782
783 if ( GetEditView() )
784 {
785 TextSelection aSel = GetEditView()->GetSelection();
786 setTextEngineText(*GetEditEngine(), m_xModule->GetSource32());
787 GetEditView()->SetSelection( aSel );
788 GetEditEngine()->SetModified( false );
789 MarkDocumentModified( GetDocument() );
790 }
791}
792
793sal_Int32 ModulWindow::countPages( Printer* pPrinter )
794{
795 return FormatAndPrint( pPrinter, -1 );
796}
797
798void ModulWindow::printPage( sal_Int32 nPage, Printer* pPrinter )
799{
800 FormatAndPrint( pPrinter, nPage );
801}
802
803/* implementation note: this is totally inefficient for the XRenderable interface
804 usage since the whole "document" will be format for every page. Should this ever
805 become a problem we should
806 - format only once for every new printer
807 - keep an index list for each page which is the starting paragraph
808*/
809sal_Int32 ModulWindow::FormatAndPrint( Printer* pPrinter, sal_Int32 nPrintPage )
810{
811 AssertValidEditEngine();
812
813 MapMode eOldMapMode( pPrinter->GetMapMode() );
814 vcl::Font aOldFont( pPrinter->GetFont() );
815
816 vcl::Font aFont( GetEditEngine()->GetFont() );
817 aFont.SetAlignment( ALIGN_BOTTOM );
818 aFont.SetTransparent( true );
819 aFont.SetFontSize( Size( 0, 360 ) );
820 pPrinter->SetFont( aFont );
821 pPrinter->SetMapMode(MapMode(MapUnit::Map100thMM));
822
823 OUString aTitle( CreateQualifiedName() );
824
825 sal_Int32 nLineHeight = pPrinter->GetTextHeight();
826 if(nLineHeight == 0)
827 {
828 nLineHeight = 1;
829 }
830
831 Size aPaperSz = pPrinter->GetOutputSize();
832 aPaperSz.AdjustWidth( -(Print::nLeftMargin + Print::nRightMargin) );
833 aPaperSz.AdjustHeight( -(Print::nTopMargin + Print::nBottomMargin) );
834
835 // nLinepPage is not correct if there's a line break
836 sal_Int32 nLinespPage = aPaperSz.Height()/nLineHeight;
837 long nXTextWidth = pPrinter->approximate_digit_width();
838
839 sal_Int32 nCharspLine = aPaperSz.Width() / std::max<long>(nXTextWidth, 1);
840 const sal_uInt32 nParas = GetEditEngine()->GetParagraphCount();
841
842 sal_Int32 nPages = nParas/nLinespPage+1;
843 sal_Int32 nCurPage = 1;
844
845 lcl_PrintHeader( pPrinter, nPages, nCurPage, aTitle, nPrintPage == 0 );
846 Point aPos( Print::nLeftMargin, Print::nTopMargin );
847 for ( sal_uInt32 nPara = 0; nPara < nParas; ++nPara )
848 {
849 OUString aLine( GetEditEngine()->GetText( nPara ) );
850 lcl_ConvertTabsToSpaces( aLine );
851 sal_Int32 nLines = aLine.getLength()/nCharspLine+1;
852 for (sal_Int32 nLine = 0; nLine < nLines; ++nLine)
853 {
854 sal_Int32 nBeginIndex = nLine*nCharspLine;
855 sal_Int32 nCopyCount = std::min<sal_Int32>(nCharspLine, aLine.getLength()-nBeginIndex);
856 OUString aTmpLine = aLine.copy(nBeginIndex, nCopyCount);
857 aPos.AdjustY(nLineHeight );
858 if ( aPos.Y() > ( aPaperSz.Height() + Print::nTopMargin ) )
859 {
860 nCurPage++;
861 lcl_PrintHeader( pPrinter, nPages, nCurPage, aTitle, nCurPage-1 == nPrintPage );
862 aPos = Point(Print::nLeftMargin, Print::nTopMargin + nLineHeight);
863 }
864 if( nCurPage-1 == nPrintPage )
865 pPrinter->DrawText( aPos, aTmpLine );
866 }
867 aPos.AdjustY(10 ); // nParaSpace
868 }
869
870 pPrinter->SetFont( aOldFont );
871 pPrinter->SetMapMode( eOldMapMode );
872
873 return nCurPage;
874}
875
876void ModulWindow::ExecuteCommand (SfxRequest& rReq)
877{
878 AssertValidEditEngine();
879 switch (rReq.GetSlot())
880 {
881 case SID_DELETE(5000 + 713):
882 {
883 if (!IsReadOnly())
884 {
885 KeyEvent aFakeDelete(0, KEY_DELETE);
886 (void)GetEditView()->KeyInput(aFakeDelete);
887 }
888 break;
889 }
890 case SID_SELECTALL(5000 + 723):
891 {
892 TextSelection aSel( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL((sal_uInt32) 0xFFFFFFFF), TEXT_INDEX_ALL((sal_Int32) 0x7FFFFFFF) ) );
893 TextView * pView = GetEditView();
894 pView->SetSelection( aSel );
895 pView->GetWindow()->GrabFocus();
896 break;
897 }
898 case SID_BASICRUN(5000 + 955):
899 {
900 BasicRun();
901 }
902 break;
903 case SID_BASICCOMPILE(5000 + 954):
904 {
905 CompileBasic();
906 }
907 break;
908 case SID_BASICSTEPOVER(5000 + 957):
909 {
910 BasicStepOver();
911 }
912 break;
913 case SID_BASICSTEPINTO(5000 + 956):
914 {
915 BasicStepInto();
916 }
917 break;
918 case SID_BASICSTEPOUT(5000 + 963):
919 {
920 BasicStepOut();
921 }
922 break;
923 case SID_BASICLOAD(5000 + 951):
924 {
925 LoadBasic();
926 }
927 break;
928 case SID_BASICSAVEAS(5000 + 953):
929 {
930 SaveBasicSource();
931 }
932 break;
933 case SID_IMPORT_DIALOG(5000 + 966):
934 {
935 ImportDialog();
936 }
937 break;
938 case SID_BASICIDE_MATCHGROUP( (30000 + 768) + 14 ):
939 {
940 GetEditView()->MatchGroup();
941 }
942 break;
943 case SID_BASICIDE_TOGGLEBRKPNT( (30000 + 768) + 0 ):
944 {
945 BasicToggleBreakPoint();
946 }
947 break;
948 case SID_BASICIDE_MANAGEBRKPNTS( (30000 + 768) + 42 ):
949 {
950 ManageBreakPoints();
951 }
952 break;
953 case SID_BASICIDE_TOGGLEBRKPNTENABLED( (30000 + 768) + 43 ):
954 {
955 BasicToggleBreakPointEnabled();
956 }
957 break;
958 case SID_BASICIDE_ADDWATCH( (30000 + 768) + 1 ):
959 {
960 BasicAddWatch();
961 }
962 break;
963 case SID_BASICIDE_REMOVEWATCH( (30000 + 768) + 7 ):
964 {
965 m_rLayout.BasicRemoveWatch();
966 }
967 break;
968 case SID_CUT(5000 + 710):
969 {
970 if ( !IsReadOnly() )
971 {
972 GetEditView()->Cut();
973 if (SfxBindings* pBindings = GetBindingsPtr())
974 pBindings->Invalidate( SID_DOC_MODIFIED(5000 + 584) );
975 }
976 }
977 break;
978 case SID_COPY(5000 + 711):
979 {
980 GetEditView()->Copy();
981 }
982 break;
983 case SID_PASTE(5000 + 712):
984 {
985 if ( !IsReadOnly() )
986 {
987 GetEditView()->Paste();
988 if (SfxBindings* pBindings = GetBindingsPtr())
989 pBindings->Invalidate( SID_DOC_MODIFIED(5000 + 584) );
990 }
991 }
992 break;
993 case SID_BASICIDE_BRKPNTSCHANGED( (30000 + 768) + 36 ):
994 {
995 GetBreakPointWindow().Invalidate();
996 }
997 break;
998 case SID_SHOWLINES(5000 + 1725):
999 {
1000 const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(rReq.GetSlot());
1001 bool bLineNumbers = pItem && pItem->GetValue();
1002 m_aXEditorWindow->SetLineNumberDisplay(bLineNumbers);
1003
1004 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
1005 officecfg::Office::BasicIDE::EditorSettings::LineNumbering::set(bLineNumbers, batch);
1006 batch->commit();
1007 }
1008 break;
1009 case SID_BASICIDE_DELETECURRENT( (30000 + 768) + 22 ):
1010 {
1011 if (QueryDelModule(m_aName, GetFrameWeld()))
1012 {
1013 // tdf#134551 don't delete the window if last module is removed until this block
1014 // is complete
1015 VclPtr<ModulWindow> xKeepRef(this);
1016 if (m_aDocument.removeModule(m_aLibName, m_aName))
1017 MarkDocumentModified(m_aDocument);
1018 }
1019 }
1020 break;
1021 case FID_SEARCH_OFF((10000 + 500) + 1):
1022 GrabFocus();
1023 break;
1024 case SID_GOTOLINE(5000 + 1724):
1025 {
1026 GotoLineDialog aGotoDlg(GetFrameWeld());
1027 if (aGotoDlg.run() == RET_OK)
1028 {
1029 if (sal_Int32 const nLine = aGotoDlg.GetLineNumber())
1030 {
1031 TextSelection const aSel(TextPaM(nLine - 1, 0), TextPaM(nLine - 1, 0));
1032 GetEditView()->SetSelection(aSel);
1033 }
1034 }
1035 break;
1036 }
1037 }
1038}
1039
1040void ModulWindow::ExecuteGlobal (SfxRequest& rReq)
1041{
1042 switch (rReq.GetSlot())
1043 {
1044 case SID_SIGNATURE(5000 + 1643):
1045 {
1046 DocumentSignature aSignature(m_aDocument);
1047 if (aSignature.supportsSignatures())
1048 {
1049 aSignature.signScriptingContent(rReq.GetFrameWeld());
1050 if (SfxBindings* pBindings = GetBindingsPtr())
1051 pBindings->Invalidate(SID_SIGNATURE(5000 + 1643));
1052 }
1053 }
1054 break;
1055 }
1056}
1057
1058void ModulWindow::GetState( SfxItemSet &rSet )
1059{
1060 SfxWhichIter aIter(rSet);
1061 for ( sal_uInt16 nWh = aIter.FirstWhich(); nWh != 0; nWh = aIter.NextWhich() )
1062 {
1063 switch ( nWh )
1064 {
1065 case SID_CUT(5000 + 710):
1066 {
1067 if ( !GetEditView() || !GetEditView()->HasSelection() )
1068 rSet.DisableItem( nWh );
1069
1070 if ( IsReadOnly() )
1071 rSet.DisableItem( nWh );
1072 }
1073 break;
1074 case SID_COPY(5000 + 711):
1075 {
1076 if ( !GetEditView() || !GetEditView()->HasSelection() )
1077 rSet.DisableItem( nWh );
1078 }
1079 break;
1080 case SID_PASTE(5000 + 712):
1081 {
1082 if ( !IsPasteAllowed() )
1083 rSet.DisableItem( nWh );
1084
1085 if ( IsReadOnly() )
1086 rSet.DisableItem( nWh );
1087 }
1088 break;
1089 case SID_BASICIDE_STAT_POS( (30000 + 768) + 38 ):
1090 {
1091 TextView* pView = GetEditView();
1092 if ( pView )
1093 {
1094 TextSelection aSel = pView->GetSelection();
1095 OUString aPos = IDEResId( RID_STR_LINEreinterpret_cast<char const *>("RID_STR_LINE" "\004" u8"Ln"
)
) +
1096 " " +
1097 OUString::number(aSel.GetEnd().GetPara()+1) +
1098 ", " +
1099 IDEResId( RID_STR_COLUMNreinterpret_cast<char const *>("RID_STR_COLUMN" "\004" u8"Col"
)
) +
1100 " " +
1101 OUString::number(aSel.GetEnd().GetIndex()+1);
1102 SfxStringItem aItem( SID_BASICIDE_STAT_POS( (30000 + 768) + 38 ), aPos );
1103 rSet.Put( aItem );
1104 }
1105 }
1106 break;
1107 case SID_BASICIDE_STAT_TITLE( (30000 + 768) + 40 ):
1108 {
1109 // search for current procedure name (Sub or Function)
1110 TextView* pView = GetEditView();
1111 if ( pView )
1112 {
1113 OUString sProcName;
1114
1115 TextSelection aSel = pView->GetSelection();
1116
1117 sal_uInt32 i = aSel.GetStart().GetPara();
1118 do
1119 {
1120 OUString aCurrLine = GetEditEngine()->GetText( i );
1121 OUString sProcType;
1122 if (GetEditorWindow().GetProcedureName(aCurrLine, sProcType, sProcName))
1123 break;
1124 } while (i--);
1125
1126 OUString aTitle = CreateQualifiedName();
1127 if (!sProcName.isEmpty())
1128 aTitle += "." + sProcName;
1129
1130 SfxStringItem aTitleItem( SID_BASICIDE_STAT_TITLE( (30000 + 768) + 40 ), aTitle );
1131 rSet.Put( aTitleItem );
1132 }
1133 }
1134 break;
1135 case SID_ATTR_INSERTTypedWhichId<SfxBoolItem>( 10000 + 221 ):
1136 {
1137 TextView* pView = GetEditView();
1138 if ( pView )
1139 {
1140 SfxBoolItem aItem( SID_ATTR_INSERTTypedWhichId<SfxBoolItem>( 10000 + 221 ), pView->IsInsertMode() );
1141 rSet.Put( aItem );
1142 }
1143 }
1144 break;
1145 case SID_SHOWLINES(5000 + 1725):
1146 {
1147 bool bLineNumbers = ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
1148 rSet.Put(SfxBoolItem(nWh, bLineNumbers));
1149 break;
1150 }
1151 case SID_SELECTALL(5000 + 723):
1152 {
1153 if ( !GetEditView() )
1154 rSet.DisableItem( nWh );
1155 }
1156 break;
1157 }
1158 }
1159}
1160
1161void ModulWindow::DoScroll( ScrollBar* pCurScrollBar )
1162{
1163 if ( ( pCurScrollBar == GetHScrollBar() ) && GetEditView() )
1164 {
1165 // don't scroll with the value but rather use the Thumb-Pos for the VisArea:
1166 long nDiff = GetEditView()->GetStartDocPos().X() - pCurScrollBar->GetThumbPos();
1167 GetEditView()->Scroll( nDiff, 0 );
1168 GetEditView()->ShowCursor( false );
1169 pCurScrollBar->SetThumbPos( GetEditView()->GetStartDocPos().X() );
1170
1171 }
1172}
1173
1174bool ModulWindow::IsModified()
1175{
1176 return GetEditEngine() && GetEditEngine()->IsModified();
1177}
1178
1179OUString ModulWindow::GetSbModuleName()
1180{
1181 OUString aModuleName;
1182 if ( XModule().is() )
1183 aModuleName = m_xModule->GetName();
1184 return aModuleName;
1185}
1186
1187OUString ModulWindow::GetTitle()
1188{
1189 return GetSbModuleName();
1190}
1191
1192void ModulWindow::ShowCursor( bool bOn )
1193{
1194 if ( GetEditEngine() )
1195 {
1196 TextView* pView = GetEditEngine()->GetActiveView();
1197 if ( pView )
1198 {
1199 if ( bOn )
1200 pView->ShowCursor();
1201 else
1202 pView->HideCursor();
1203 }
1204 }
1205}
1206
1207void ModulWindow::AssertValidEditEngine()
1208{
1209 if ( !GetEditEngine() )
1210 GetEditorWindow().CreateEditEngine();
1211}
1212
1213void ModulWindow::Activating ()
1214{
1215 bool bLineNumbers = ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
1216 m_aXEditorWindow->SetLineNumberDisplay(bLineNumbers);
1217 Show();
1218}
1219
1220void ModulWindow::Deactivating()
1221{
1222 Hide();
1223}
1224
1225sal_uInt16 ModulWindow::StartSearchAndReplace( const SvxSearchItem& rSearchItem, bool bFromStart )
1226{
1227 if (IsSuspended())
1228 return 0;
1229
1230 // one could also relinquish syntaxhighlighting/formatting instead of the stupid replace-everything...
1231 AssertValidEditEngine();
1232 TextView* pView = GetEditView();
1233 TextSelection aSel;
1234 if ( bFromStart )
1235 {
1236 aSel = pView->GetSelection();
1237 if ( !rSearchItem.GetBackward() )
1238 pView->SetSelection( TextSelection() );
1239 else
1240 pView->SetSelection( TextSelection( TextPaM( TEXT_PARA_ALL((sal_uInt32) 0xFFFFFFFF), TEXT_INDEX_ALL((sal_Int32) 0x7FFFFFFF) ), TextPaM( TEXT_PARA_ALL((sal_uInt32) 0xFFFFFFFF), TEXT_INDEX_ALL((sal_Int32) 0x7FFFFFFF) ) ) );
1241 }
1242
1243 bool const bForward = !rSearchItem.GetBackward();
1244 sal_uInt16 nFound = 0;
1245 if ( ( rSearchItem.GetCommand() == SvxSearchCmd::FIND ) ||
1246 ( rSearchItem.GetCommand() == SvxSearchCmd::FIND_ALL ) )
1247 {
1248 nFound = pView->Search( rSearchItem.GetSearchOptions() , bForward ) ? 1 : 0;
1249 }
1250 else if ( ( rSearchItem.GetCommand() == SvxSearchCmd::REPLACE ) ||
1251 ( rSearchItem.GetCommand() == SvxSearchCmd::REPLACE_ALL ) )
1252 {
1253 if ( !IsReadOnly() )
1254 {
1255 bool const bAll = rSearchItem.GetCommand() == SvxSearchCmd::REPLACE_ALL;
1256 nFound = pView->Replace( rSearchItem.GetSearchOptions() , bAll , bForward );
1257 }
1258 }
1259
1260 if ( bFromStart && !nFound )
1261 pView->SetSelection( aSel );
1262
1263 return nFound;
1264}
1265
1266SfxUndoManager* ModulWindow::GetUndoManager()
1267{
1268 if ( GetEditEngine() )
1269 return &GetEditEngine()->GetUndoManager();
1270 return nullptr;
1271}
1272
1273SearchOptionFlags ModulWindow::GetSearchOptions()
1274{
1275 SearchOptionFlags nOptions = SearchOptionFlags::SEARCH |
1276 SearchOptionFlags::WHOLE_WORDS |
1277 SearchOptionFlags::BACKWARDS |
1278 SearchOptionFlags::REG_EXP |
1279 SearchOptionFlags::EXACT |
1280 SearchOptionFlags::SELECTION |
1281 SearchOptionFlags::SIMILARITY;
1282
1283 if ( !IsReadOnly() )
1284 {
1285 nOptions |= SearchOptionFlags::REPLACE;
1286 nOptions |= SearchOptionFlags::REPLACE_ALL;
1287 }
1288
1289 return nOptions;
1290}
1291
1292void ModulWindow::BasicStarted()
1293{
1294 if ( !XModule().is() )
1295 return;
1296
1297 m_aStatus.bIsRunning = true;
1298 BreakPointList& rList = GetBreakPoints();
1299 if ( rList.size() )
1300 {
1301 rList.ResetHitCount();
1302 rList.SetBreakPointsInBasic( m_xModule.get() );
1303 for ( sal_uInt32 nMethod = 0; nMethod < m_xModule->GetMethods()->Count32(); nMethod++ )
1304 {
1305 SbMethod* pMethod = static_cast<SbMethod*>(m_xModule->GetMethods()->Get32( nMethod ));
1306 assert(pMethod && "Method not found! (NULL)")(static_cast <bool> (pMethod && "Method not found! (NULL)"
) ? void (0) : __assert_fail ("pMethod && \"Method not found! (NULL)\""
, "/home/maarten/src/libreoffice/core/basctl/source/basicide/baside2.cxx"
, 1306, __extension__ __PRETTY_FUNCTION__))
;
1307 pMethod->SetDebugFlags( pMethod->GetDebugFlags() | BasicDebugFlags::Break );
1308 }
1309 }
1310}
1311
1312void ModulWindow::BasicStopped()
1313{
1314 m_aStatus.bIsRunning = false;
1315 GetBreakPointWindow().SetNoMarker();
1316}
1317
1318EntryDescriptor ModulWindow::CreateEntryDescriptor()
1319{
1320 ScriptDocument aDocument( GetDocument() );
1321 OUString aLibName( GetLibName() );
1322 LibraryLocation eLocation = aDocument.getLibraryLocation( aLibName );
1323 OUString aModName( GetName() );
1324 OUString aLibSubName;
1325 if( m_xBasic.is() && aDocument.isInVBAMode() && XModule().is() )
1326 {
1327 switch( m_xModule->GetModuleType() )
1328 {
1329 case script::ModuleType::DOCUMENT:
1330 {
1331 aLibSubName = IDEResId( RID_STR_DOCUMENT_OBJECTSreinterpret_cast<char const *>("RID_STR_DOCUMENT_OBJECTS"
"\004" u8"Document Objects")
);
1332 uno::Reference< container::XNameContainer > xLib = aDocument.getOrCreateLibrary( E_SCRIPTS, aLibName );
1333 if( xLib.is() )
1334 {
1335 OUString sObjName;
1336 ModuleInfoHelper::getObjectName( xLib, aModName, sObjName );
1337 if( !sObjName.isEmpty() )
1338 {
1339 aModName += " (" + sObjName + ")";
1340 }
1341 }
1342 break;
1343 }
1344 case script::ModuleType::FORM:
1345 aLibSubName = IDEResId( RID_STR_USERFORMSreinterpret_cast<char const *>("RID_STR_USERFORMS" "\004"
u8"Forms")
);
1346 break;
1347 case script::ModuleType::NORMAL:
1348 aLibSubName = IDEResId( RID_STR_NORMAL_MODULESreinterpret_cast<char const *>("RID_STR_NORMAL_MODULES"
"\004" u8"Modules")
);
1349 break;
1350 case script::ModuleType::CLASS:
1351 aLibSubName = IDEResId( RID_STR_CLASS_MODULESreinterpret_cast<char const *>("RID_STR_CLASS_MODULES" "\004"
u8"Class Modules")
);
1352 break;
1353 }
1354 }
1355 return EntryDescriptor( aDocument, eLocation, aLibName, aLibSubName, aModName, OBJ_TYPE_MODULE );
1356}
1357
1358void ModulWindow::SetReadOnly (bool b)
1359{
1360 if ( GetEditView() )
1361 GetEditView()->SetReadOnly( b );
1362}
1363
1364bool ModulWindow::IsReadOnly()
1365{
1366 return GetEditView() && GetEditView()->IsReadOnly();
1367}
1368
1369bool ModulWindow::IsPasteAllowed()
1370{
1371 bool bPaste = false;
1372
1373 // get clipboard
1374 Reference< datatransfer::clipboard::XClipboard > xClipboard = GetClipboard();
1375 if ( xClipboard.is() )
1376 {
1377
1378 Reference< datatransfer::XTransferable > xTransf;
1379 {
1380 SolarMutexReleaser aReleaser;
1381 // get clipboard content
1382 xTransf = xClipboard->getContents();
1383 }
1384 if ( xTransf.is() )
1385 {
1386 datatransfer::DataFlavor aFlavor;
1387 SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor );
1388 if ( xTransf->isDataFlavorSupported( aFlavor ) )
1389 bPaste = true;
1390 }
1391 }
1392
1393 return bPaste;
1394}
1395
1396void ModulWindow::OnNewDocument ()
1397{
1398 bool bLineNumbers = ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
1399 m_aXEditorWindow->SetLineNumberDisplay(bLineNumbers);
1400}
1401
1402char const* ModulWindow::GetHid () const
1403{
1404 return HID_BASICIDE_MODULWINDOW"BASCTL_HID_BASICIDE_MODULWINDOW";
1405}
1406ItemType ModulWindow::GetType () const
1407{
1408 return TYPE_MODULE;
1409}
1410
1411bool ModulWindow::HasActiveEditor () const
1412{
1413 return !IsSuspended();
1414}
1415
1416
1417void ModulWindow::UpdateModule ()
1418{
1419 OUString const aModule = getTextEngineText(*GetEditEngine());
1420
1421 // update module in basic
1422 assert(m_xModule.is())(static_cast <bool> (m_xModule.is()) ? void (0) : __assert_fail
("m_xModule.is()", "/home/maarten/src/libreoffice/core/basctl/source/basicide/baside2.cxx"
, 1422, __extension__ __PRETTY_FUNCTION__))
;
1423
1424 // update module in module window
1425 SetModule(aModule);
1426
1427 // update module in library
1428 OSL_VERIFY(m_aDocument.updateModule(m_aLibName, m_aName, aModule))do { if (!(m_aDocument.updateModule(m_aLibName, m_aName, aModule
))) do { if (true && (!(0))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basctl/source/basicide/baside2.cxx"
":" "1428" ": "), "OSL_ASSERT: %s", "0"); } } while (false);
} while (0)
;
1429
1430 GetEditEngine()->SetModified(false);
1431 MarkDocumentModified(m_aDocument);
1432}
1433
1434ModulWindowLayout::ModulWindowLayout (vcl::Window* pParent, ObjectCatalog& rObjectCatalog_) :
1435 Layout(pParent),
1436 pChild(nullptr),
1437 aWatchWindow(VclPtr<WatchWindow>::Create(this)),
1438 aStackWindow(VclPtr<StackWindow>::Create(this)),
1439 rObjectCatalog(rObjectCatalog_)
1440{ }
1441
1442ModulWindowLayout::~ModulWindowLayout()
1443{
1444 disposeOnce();
1445}
1446
1447void ModulWindowLayout::dispose()
1448{
1449 aWatchWindow.disposeAndClear();
1450 aStackWindow.disposeAndClear();
1
Calling 'VclPtr::disposeAndClear'
1451 pChild.clear();
1452 Layout::dispose();
1453}
1454
1455void ModulWindowLayout::UpdateDebug (bool bBasicStopped)
1456{
1457 aWatchWindow->UpdateWatches(bBasicStopped);
1458 aStackWindow->UpdateCalls();
1459}
1460
1461void ModulWindowLayout::Paint (vcl::RenderContext& rRenderContext, tools::Rectangle const&)
1462{
1463 rRenderContext.DrawText(Point(), IDEResId(RID_STR_NOMODULEreinterpret_cast<char const *>("RID_STR_NOMODULE" "\004"
u8"< No Module >")
));
1464}
1465
1466void ModulWindowLayout::Activating (BaseWindow& rChild)
1467{
1468 assert(dynamic_cast<ModulWindow*>(&rChild))(static_cast <bool> (dynamic_cast<ModulWindow*>(&
rChild)) ? void (0) : __assert_fail ("dynamic_cast<ModulWindow*>(&rChild)"
, "/home/maarten/src/libreoffice/core/basctl/source/basicide/baside2.cxx"
, 1468, __extension__ __PRETTY_FUNCTION__))
;
1469 pChild = &static_cast<ModulWindow&>(rChild);
1470 aWatchWindow->Show();
1471 aStackWindow->Show();
1472 rObjectCatalog.Show();
1473 rObjectCatalog.SetLayoutWindow(this);
1474 rObjectCatalog.UpdateEntries();
1475 Layout::Activating(rChild);
1476 aSyntaxColors.SetActiveEditor(&pChild->GetEditorWindow());
1477}
1478
1479void ModulWindowLayout::Deactivating ()
1480{
1481 aSyntaxColors.SetActiveEditor(nullptr);
1482 Layout::Deactivating();
1483 aWatchWindow->Hide();
1484 aStackWindow->Hide();
1485 rObjectCatalog.Hide();
1486 pChild = nullptr;
1487}
1488
1489void ModulWindowLayout::GetState (SfxItemSet &rSet, unsigned nWhich)
1490{
1491 switch (nWhich)
1492 {
1493 case SID_SHOW_PROPERTYBROWSER( 10000 + 943 ):
1494 rSet.Put(SfxVisibilityItem(nWhich, false));
1495 break;
1496
1497 case SID_BASICIDE_CHOOSEMACRO( (30000 + 768) + 2 ):
1498 rSet.Put(SfxVisibilityItem(nWhich, true));
1499 break;
1500 }
1501}
1502
1503void ModulWindowLayout::BasicAddWatch (OUString const& rWatchStr)
1504{
1505 aWatchWindow->AddWatch(rWatchStr);
1506}
1507
1508void ModulWindowLayout::BasicRemoveWatch ()
1509{
1510 aWatchWindow->RemoveSelectedWatch();
1511}
1512
1513void ModulWindowLayout::OnFirstSize (long const nWidth, long const nHeight)
1514{
1515 AddToLeft(&rObjectCatalog, Size(nWidth * 0.20, nHeight * 0.75));
1516 AddToBottom(aWatchWindow.get(), Size(nWidth * 0.67, nHeight * 0.25));
1517 AddToBottom(aStackWindow.get(), Size(nWidth * 0.33, nHeight * 0.25));
1518}
1519
1520ModulWindowLayout::SyntaxColors::SyntaxColors () :
1521 pEditor(nullptr)
1522{
1523 aConfig.AddListener(this);
1524
1525 NewConfig(true);
1526}
1527
1528ModulWindowLayout::SyntaxColors::~SyntaxColors ()
1529{
1530 aConfig.RemoveListener(this);
1531}
1532
1533// virtual
1534void ModulWindowLayout::SyntaxColors::ConfigurationChanged (utl::ConfigurationBroadcaster*, ConfigurationHints)
1535{
1536 NewConfig(false);
1537}
1538
1539// when a new configuration has to be set
1540void ModulWindowLayout::SyntaxColors::NewConfig (bool bFirst)
1541{
1542 static struct
1543 {
1544 TokenType eTokenType;
1545 svtools::ColorConfigEntry eEntry;
1546 }
1547 const vIds[] =
1548 {
1549 { TokenType::Unknown, svtools::FONTCOLOR },
1550 { TokenType::Identifier, svtools::BASICIDENTIFIER },
1551 { TokenType::Whitespace, svtools::FONTCOLOR },
1552 { TokenType::Number, svtools::BASICNUMBER },
1553 { TokenType::String, svtools::BASICSTRING },
1554 { TokenType::EOL, svtools::FONTCOLOR },
1555 { TokenType::Comment, svtools::BASICCOMMENT },
1556 { TokenType::Error, svtools::BASICERROR },
1557 { TokenType::Operator, svtools::BASICOPERATOR },
1558 { TokenType::Keywords, svtools::BASICKEYWORD },
1559 };
1560
1561 Color aDocColor = aConfig.GetColorValue(svtools::DOCCOLOR).nColor;
1562 if (bFirst || aDocColor != m_aBackgroundColor)
1563 {
1564 m_aBackgroundColor = aDocColor;
1565 if (!bFirst && pEditor)
1566 {
1567 pEditor->SetBackground(Wallpaper(m_aBackgroundColor));
1568 pEditor->Invalidate();
1569 }
1570 }
1571
1572 Color aFontColor = aConfig.GetColorValue(svtools::FONTCOLOR).nColor;
1573 if (bFirst || aFontColor != m_aFontColor)
1574 {
1575 m_aFontColor = aFontColor;
1576 if (!bFirst && pEditor)
1577 pEditor->ChangeFontColor(m_aFontColor);
1578 }
1579
1580 bool bChanged = false;
1581 for (unsigned i = 0; i != SAL_N_ELEMENTS(vIds)(sizeof(sal_n_array_size(vIds))); ++i)
1582 {
1583 Color const aColor = aConfig.GetColorValue(vIds[i].eEntry).nColor;
1584 Color& rMyColor = aColors[vIds[i].eTokenType];
1585 if (bFirst || aColor != rMyColor)
1586 {
1587 rMyColor = aColor;
1588 bChanged = true;
1589 }
1590 }
1591 if (bChanged && !bFirst && pEditor)
1592 pEditor->UpdateSyntaxHighlighting();
1593}
1594
1595} // namespace basctl
1596
1597/* 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;
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);
2
Calling copy constructor for 'Reference<basctl::StackWindow>'
5
Returning from copy constructor for 'Reference<basctl::StackWindow>'
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
6
Calling 'Reference::clear'
13
Returning; memory was released
205 if (aTmp.get()) {
14
Calling 'Reference::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)
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)
3
Assuming field 'm_pBody' is non-null
4
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)
113 m_pBody->release();
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
6.1
Field 'm_pBody' is non-null
6.1
Field 'm_pBody' is non-null
6.1
Field 'm_pBody' is non-null
6.1
Field 'm_pBody' is non-null
)
7
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
8
Calling 'VclReferenceBase::release'
12
Returning; memory was released
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;
15
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)
9
Assuming the condition is true
10
Taking true branch
40 delete this;
11
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