LibreOffice Module basctl (master) 1
basobj3.cxx
Go to the documentation of this file.
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 <vcl/errinf.hxx>
21#include <vcl/svapp.hxx>
22#include <vcl/weld.hxx>
23#include <basic/basmgr.hxx>
24#include <basic/sbmeth.hxx>
26
27#include <iderdll.hxx>
28#include "iderdll2.hxx"
29#include "basdoc.hxx"
30#include <iderid.hxx>
31#include <strings.hrc>
32
33#include <baside3.hxx>
34#include <basidesh.hxx>
35#include <basobj.hxx>
36#include <localizationmgr.hxx>
37#include <dlged.hxx>
38#include <com/sun/star/script/XLibraryContainerPassword.hpp>
39#include <sfx2/app.hxx>
40#include <sfx2/dispatch.hxx>
41#include <sfx2/sfxsids.hrc>
42#include <sfx2/request.hxx>
43#include <sfx2/viewfrm.hxx>
44#include <sal/log.hxx>
45#include <osl/diagnose.h>
46#include <tools/debug.hxx>
47
48namespace basctl
49{
50
51using namespace comphelper;
52using namespace ::com::sun::star;
53using namespace ::com::sun::star::uno;
54using namespace ::com::sun::star::container;
55
56extern "C" {
57 SAL_DLLPUBLIC_EXPORT tools::Long basicide_handle_basic_error( void const * pPtr )
58 {
59 return HandleBasicError( static_cast<StarBASIC const *>(pPtr) );
60 }
61}
62
63SbMethod* CreateMacro( SbModule* pModule, const OUString& rMacroName )
64{
65 SfxDispatcher* pDispatcher = GetDispatcher();
66 if( pDispatcher )
67 {
68 pDispatcher->Execute( SID_BASICIDE_STOREALLMODULESOURCES );
69 }
70
71 if ( pModule->FindMethod( rMacroName, SbxClassType::Method ) )
72 return nullptr;
73
74 OUString aMacroName( rMacroName );
75 if ( aMacroName.isEmpty() )
76 {
77 if (!pModule->GetMethods()->Count())
78 aMacroName = "Main" ;
79 else
80 {
81 bool bValid = false;
82 sal_Int32 nMacro = 1;
83 while ( !bValid )
84 {
85 aMacroName = "Macro" + OUString::number( nMacro );
86 // test whether existing...
87 bValid = pModule->FindMethod( aMacroName, SbxClassType::Method ) == nullptr;
88 nMacro++;
89 }
90 }
91 }
92
93 OUString aOUSource( pModule->GetSource32() );
94
95 // don't produce too many empty lines...
96 sal_Int32 nSourceLen = aOUSource.getLength();
97 if ( nSourceLen > 2 )
98 {
99 const sal_Unicode* pStr = aOUSource.getStr();
100 if ( pStr[ nSourceLen - 1 ] != LINE_SEP )
101 aOUSource += "\n\n" ;
102 else if ( pStr[ nSourceLen - 2 ] != LINE_SEP )
103 aOUSource += "\n" ;
104 else if ( pStr[ nSourceLen - 3 ] == LINE_SEP )
105 aOUSource = aOUSource.copy( 0, nSourceLen-1 );
106 }
107
108 aOUSource += "Sub " + aMacroName + "\n\nEnd Sub";
109
110 // update module in library
111 StarBASIC* pBasic = dynamic_cast<StarBASIC*>(pModule->GetParent());
112 BasicManager* pBasMgr = pBasic ? FindBasicManager(pBasic) : nullptr;
113 SAL_WARN_IF(!pBasMgr, "basctl.basicide", "No BasicManager found!");
114 ScriptDocument aDocument = pBasMgr
117
118 if (aDocument.isValid())
119 {
120 const OUString& aLibName = pBasic->GetName();
121 const OUString& aModName = pModule->GetName();
122 OSL_VERIFY( aDocument.updateModule( aLibName, aModName, aOUSource ) );
123 }
124
125 SbMethod* pMethod = pModule->FindMethod( aMacroName, SbxClassType::Method );
126
127 if( pDispatcher )
128 {
129 pDispatcher->Execute( SID_BASICIDE_UPDATEALLMODULESOURCES );
130 }
131
132 if (aDocument.isAlive())
134
135 return pMethod;
136}
137
139 weld::Widget* pErrorParent,
140 ScriptDocument const& rDocument,
141 OUString const& rLibName,
142 OUString const& rOldName,
143 OUString const& rNewName
144)
145{
146 if ( !rDocument.hasDialog( rLibName, rOldName ) )
147 {
148 OSL_FAIL( "basctl::RenameDialog: old module name is invalid!" );
149 return false;
150 }
151
152 if ( rDocument.hasDialog( rLibName, rNewName ) )
153 {
154 std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(pErrorParent,
155 VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_SBXNAMEALLREADYUSED2)));
156 xError->run();
157 return false;
158 }
159
160 // #i74440
161 if ( rNewName.isEmpty() )
162 {
163 std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(pErrorParent,
164 VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_BADSBXNAME)));
165 xError->run();
166 return false;
167 }
168
169 Shell* pShell = GetShell();
170 VclPtr<DialogWindow> pWin = pShell ? pShell->FindDlgWin(rDocument, rLibName, rOldName) : nullptr;
171 Reference< XNameContainer > xExistingDialog;
172 if ( pWin )
173 xExistingDialog = pWin->GetEditor().GetDialog();
174
175 if ( xExistingDialog.is() )
176 LocalizationMgr::renameStringResourceIDs( rDocument, rLibName, rNewName, xExistingDialog );
177
178 if ( !rDocument.renameDialog( rLibName, rOldName, rNewName, xExistingDialog ) )
179 return false;
180
181 if (!pWin || !pShell)
182 return true;
183
184 // set new name in window
185 pWin->SetName( rNewName );
186
187 // update property browser
188 pWin->UpdateBrowser();
189
190 // update tabwriter
191 sal_uInt16 nId = pShell->GetWindowId( pWin );
192 DBG_ASSERT( nId, "No entry in Tabbar!" );
193 if ( nId )
194 {
195 TabBar& rTabBar = pShell->GetTabBar();
196 rTabBar.SetPageText( nId, rNewName );
197 rTabBar.Sort();
198 rTabBar.MakeVisible( rTabBar.GetCurPageId() );
199 }
200 return true;
201}
202
203bool RemoveDialog( const ScriptDocument& rDocument, const OUString& rLibName, const OUString& rDlgName )
204{
205 if (Shell* pShell = GetShell())
206 {
207 if (VclPtr<DialogWindow> pDlgWin = pShell->FindDlgWin(rDocument, rLibName, rDlgName))
208 {
209 Reference< container::XNameContainer > xDialogModel = pDlgWin->GetDialog();
210 LocalizationMgr::removeResourceForDialog( rDocument, rLibName, rDlgName, xDialogModel );
211 }
212 }
213
214 return rDocument.removeDialog( rLibName, rDlgName );
215}
216
218{
219 SbxVariable const* pSbx = pVar;
220 while (pSbx && !dynamic_cast<StarBASIC const*>(pSbx))
221 pSbx = pSbx->GetParent();
222 return const_cast<StarBASIC*>(static_cast<const StarBASIC*>(pSbx));
223}
224
226{
228 for (auto const& doc : aDocuments)
229 {
230 BasicManager* pBasicMgr = doc.getBasicManager();
231 OSL_ENSURE( pBasicMgr, "basctl::FindBasicManager: no basic manager for the document!" );
232 if ( !pBasicMgr )
233 continue;
234
235 Sequence< OUString > aLibNames( doc.getLibraryNames() );
236 sal_Int32 nLibCount = aLibNames.getLength();
237 const OUString* pLibNames = aLibNames.getConstArray();
238
239 for ( sal_Int32 i = 0 ; i < nLibCount ; i++ )
240 {
241 StarBASIC* pL = pBasicMgr->GetLib( pLibNames[ i ] );
242 if ( pL == pLib )
243 return pBasicMgr;
244 }
245 }
246 return nullptr;
247}
248
249void MarkDocumentModified( const ScriptDocument& rDocument )
250{
251 Shell* pShell = GetShell();
252
253 // does not have to come from a document...
254 if ( rDocument.isApplication() )
255 {
256 if (pShell)
257 pShell->SetAppBasicModified(true);
258 }
259 else
260 {
261 rDocument.setDocumentModified();
262 }
263
264 // tdf#130161 in all cases call UpdateObjectCatalog
265 if (pShell)
266 pShell->UpdateObjectCatalog();
267
268 if (SfxBindings* pBindings = GetBindingsPtr())
269 {
270 pBindings->Invalidate( SID_SIGNATURE );
271 pBindings->Invalidate( SID_SAVEDOC );
272 pBindings->Update( SID_SAVEDOC );
273 }
274}
275
276void RunMethod( SbMethod const * pMethod )
277{
278 SbxValues aRes;
279 aRes.eType = SbxVOID;
280 pMethod->Get( aRes );
281}
282
284{
286 if (Shell* pShell = GetShell())
287 {
288 Shell::WindowTable& rWindows = pShell->GetWindowTable();
289 for (auto const& window : rWindows)
290 {
291 BaseWindow* pWin = window.second;
292 // call BasicStopped manually because the Stop-Notify
293 // might not get through otherwise
294 pWin->BasicStopped();
295 }
296 }
297 BasicStopped();
298}
299
301 bool* pbAppWindowDisabled,
302 bool* pbDispatcherLocked,
303 sal_uInt16* pnWaitCount,
304 SfxUInt16Item** ppSWActionCount, SfxUInt16Item** ppSWLockViewCount
305)
306{
307 // maybe there are some locks to be removed after an error
308 // or an explicit cancelling of the basic...
309 if ( pbAppWindowDisabled )
310 *pbAppWindowDisabled = false;
311 if ( pbDispatcherLocked )
312 *pbDispatcherLocked = false;
313 if ( pnWaitCount )
314 *pnWaitCount = 0;
315 if ( ppSWActionCount )
316 *ppSWActionCount = nullptr;
317 if ( ppSWLockViewCount )
318 *ppSWLockViewCount = nullptr;
319
320 // AppWait?
321 if (Shell* pShell = GetShell())
322 {
323 sal_uInt16 nWait = 0;
324 while ( pShell->GetViewFrame().GetWindow().IsWait() )
325 {
326 pShell->GetViewFrame().GetWindow().LeaveWait();
327 nWait++;
328 }
329 if ( pnWaitCount )
330 *pnWaitCount = nWait;
331 }
332
334 if (pDefParent && !pDefParent->get_sensitive())
335 {
336 pDefParent->set_sensitive(true);
337 if ( pbAppWindowDisabled )
338 *pbAppWindowDisabled = true;
339 }
340
341}
342
344{
345 SfxBindings* pBindings = GetBindingsPtr();
346 if (!pBindings)
347 return;
348
349 pBindings->Invalidate( SID_BASICSTOP );
350 pBindings->Update( SID_BASICSTOP );
351 pBindings->Invalidate( SID_BASICRUN );
352 pBindings->Update( SID_BASICRUN );
353 pBindings->Invalidate( SID_BASICCOMPILE );
354 pBindings->Update( SID_BASICCOMPILE );
355 pBindings->Invalidate( SID_BASICSTEPOVER );
356 pBindings->Update( SID_BASICSTEPOVER );
357 pBindings->Invalidate( SID_BASICSTEPINTO );
358 pBindings->Update( SID_BASICSTEPINTO );
359 pBindings->Invalidate( SID_BASICSTEPOUT );
360 pBindings->Update( SID_BASICSTEPOUT );
361 pBindings->Invalidate( SID_BASICIDE_TOGGLEBRKPNT );
362 pBindings->Update( SID_BASICIDE_TOGGLEBRKPNT );
363 pBindings->Invalidate( SID_BASICIDE_STAT_POS );
364 pBindings->Update( SID_BASICIDE_STAT_POS );
365 pBindings->Invalidate( SID_BASICIDE_STAT_TITLE );
366 pBindings->Update( SID_BASICIDE_STAT_TITLE );
367}
368
370{
371 EnsureIde();
372 BasicStopped();
373
374 // no error output during macro choosing
375 if (GetExtraData()->ChoosingMacro())
376 return 1;
377 if (GetExtraData()->ShellInCriticalSection())
378 return 2;
379
380 tools::Long nRet = 0;
381 Shell* pShell = nullptr;
383 {
384 BasicManager* pBasMgr = FindBasicManager( pBasic );
385 if ( pBasMgr )
386 {
387 bool bProtected = false;
389 OSL_ENSURE( aDocument.isValid(), "basctl::HandleBasicError: no document for the given BasicManager!" );
390 if ( aDocument.isValid() )
391 {
392 const OUString& aOULibName( pBasic->GetName() );
394 if ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) )
395 {
396 Reference< script::XLibraryContainerPassword > xPasswd( xModLibContainer, UNO_QUERY );
397 if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( aOULibName ) && !xPasswd->isLibraryPasswordVerified( aOULibName ) )
398 {
399 bProtected = true;
400 }
401 }
402 }
403
404 if ( !bProtected )
405 {
406 pShell = GetShell();
407 if ( !pShell )
408 {
409 SfxAllItemSet aArgs( SfxGetpApp()->GetPool() );
410 SfxRequest aRequest( SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs );
411 SfxGetpApp()->ExecuteSlot( aRequest );
412 pShell = GetShell();
413 }
414 }
415 }
416 }
417
418 if ( pShell )
419 nRet = tools::Long(pShell->CallBasicErrorHdl( pBasic ));
420 else
422
423 return nRet;
424}
425
427{
428 SfxBindings* pBindings = nullptr;
429
430 SfxViewFrame* pFrame = nullptr;
431 if (Shell* pShell = GetShell())
432 {
433 pFrame = &pShell->GetViewFrame();
434 }
435 else
436 {
438 while ( pView )
439 {
440 if (dynamic_cast<DocShell*>(pView->GetObjectShell()))
441 {
442 pFrame = pView;
443 break;
444 }
445 pView = SfxViewFrame::GetNext( *pView );
446 }
447 }
448 if ( pFrame != nullptr )
449 pBindings = &pFrame->GetBindings();
450
451 return pBindings;
452}
453
455{
456 if (Shell* pShell = GetShell())
457 {
458 SfxViewFrame& rViewFrame = pShell->GetViewFrame();
459 if (SfxDispatcher* pDispatcher = rViewFrame.GetDispatcher())
460 return pDispatcher;
461 }
462 return nullptr;
463}
464} // namespace basctl
465
466/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SfxApplication * SfxGetpApp()
ScriptDocument aDocument
Definition: basobj2.cxx:194
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
static weld::Window * GetDefDialogParent()
StarBASIC * GetLib(sal_uInt16 nLib) const
static DialogMask HandleError(ErrCode nId, weld::Window *pParent=nullptr, DialogMask nMask=DialogMask::MAX)
const SbxArrayRef & GetMethods() const
SbMethod * FindMethod(const OUString &, SbxClassType)
const OUString & GetSource32() const
bool Get(SbxValues &) const
const SbxObject * GetParent() const
const OUString & GetName(SbxNameType=SbxNameType::NONE) const
void Update(sal_uInt16 nId)
void Invalidate(sal_uInt16 nId)
const SfxPoolItem * Execute(sal_uInt16 nSlot, SfxCallMode nCall=SfxCallMode::SLOT, const SfxPoolItem **pArgs=nullptr, sal_uInt16 nModi=0, const SfxPoolItem **pInternalArgs=nullptr)
const SfxPoolItem * ExecuteSlot(SfxRequest &rReq, const SfxInterface *pIF=nullptr)
SfxBindings & GetBindings()
static SAL_WARN_UNUSED_RESULT SfxViewFrame * GetNext(const SfxViewFrame &rPrev, const SfxObjectShell *pDoc=nullptr, bool bOnlyVisible=true)
SfxDispatcher * GetDispatcher()
static SAL_WARN_UNUSED_RESULT SfxViewFrame * GetFirst(const SfxObjectShell *pDoc=nullptr, bool bOnlyVisible=true)
virtual SfxObjectShell * GetObjectShell() override
static void Stop()
static ErrCode const & GetErrorCode()
static bool IsBasicIDE()
virtual void SetPageText(sal_uInt16 nPageId, const OUString &rText)
void MakeVisible(sal_uInt16 nPageId)
sal_uInt16 GetCurPageId() const
virtual void BasicStopped()
Definition: bastypes.cxx:251
static void removeResourceForDialog(const ScriptDocument &rDocument, const OUString &aLibName, std::u16string_view aDlgName, const css::uno::Reference< css::container::XNameContainer > &xDialogModel)
static void renameStringResourceIDs(const ScriptDocument &rDocument, const OUString &aLibName, std::u16string_view aDlgName, const css::uno::Reference< css::container::XNameContainer > &xDialogModel)
encapsulates a document which contains Basic scripts and dialogs
bool renameDialog(const OUString &_rLibName, const OUString &_rOldName, const OUString &_rNewName, const css::uno::Reference< css::container::XNameContainer > &_rxExistingDialogModel) const
renames a dialog
css::uno::Reference< css::script::XLibraryContainer > getLibraryContainer(LibraryContainerType _eType) const
returns the Basic or Dialog library container of the document
@ AllWithApplication
all ScriptDocuments, including the dedicated one which represents the application-wide scripts/dialog...
static ScriptDocuments getAllScriptDocuments(ScriptDocumentList _eListType)
returns the set of ScriptDocument instances, one for each open document which contains Basic/Dialog c...
bool removeDialog(const OUString &_rLibName, const OUString &_rDialogName) const
removes a given dialog from the document
bool updateModule(const OUString &_rLibName, const OUString &_rModName, const OUString &_rModuleCode) const
updates a given module with new code
static ScriptDocument getDocumentForBasicManager(const BasicManager *_pManager)
returns a (newly created) ScriptDocument instance for the document to which a given BasicManager belo...
bool isAlive() const
determines whether the document instance is alive
void setDocumentModified() const
marks the document as modified @precond the instance operates on a real document, not on the applicat...
bool hasDialog(const OUString &_rLibName, const OUString &_rDialogName) const
determines whether a dialog with the given name exists in the given library
bool isApplication() const
determines whether the ScriptDocument instance operates on the whole application, as opposed to a rea...
bool isValid() const
determines whether the document is actually able to contain Basic/Dialog libraries
bool CallBasicErrorHdl(StarBASIC const *pBasic)
Definition: basides1.cxx:1406
void UpdateObjectCatalog()
Definition: basidesh.hxx:220
TabBar & GetTabBar()
Definition: basidesh.hxx:166
sal_uInt16 GetWindowId(BaseWindow const *pWin) const
Definition: basides3.cxx:125
std::map< sal_uInt16, VclPtr< BaseWindow > > WindowTable
Definition: basidesh.hxx:63
void SetAppBasicModified(bool bModified)
Definition: basidesh.hxx:206
VclPtr< DialogWindow > FindDlgWin(const ScriptDocument &rDocument, const OUString &rLibName, const OUString &rName, bool bCreateIfNotExist=false, bool bFindSuspended=false)
Definition: basides3.cxx:114
virtual void set_sensitive(bool sensitive)=0
virtual bool get_sensitive() const=0
#define DBG_ASSERT(sCon, aError)
const char * pLib
#define SAL_WARN_IF(condition, area, stream)
void RunMethod(SbMethod const *pMethod)
Definition: basobj3.cxx:276
SfxBindings * GetBindingsPtr()
Definition: basobj3.cxx:426
tools::Long HandleBasicError(StarBASIC const *pBasic)
Definition: basobj3.cxx:369
void BasicStopped(bool *pbAppWindowDisabled, bool *pbDispatcherLocked, sal_uInt16 *pnWaitCount, SfxUInt16Item **ppSWActionCount, SfxUInt16Item **ppSWLockViewCount)
Definition: basobj3.cxx:300
ExtraData * GetExtraData()
Definition: iderdll.cxx:101
SbMethod * CreateMacro(SbModule *pModule, const OUString &rMacroName)
Definition: basobj3.cxx:63
bool RemoveDialog(const ScriptDocument &rDocument, const OUString &rLibName, const OUString &rDlgName)
Definition: basobj3.cxx:203
Shell * GetShell()
Definition: iderdll.cxx:80
constexpr auto LINE_SEP
Definition: bastypes.hxx:54
void EnsureIde()
Definition: iderdll.cxx:74
SfxDispatcher * GetDispatcher()
Definition: basobj3.cxx:454
void MarkDocumentModified(const ScriptDocument &rDocument)
Definition: basobj3.cxx:249
BasicManager * FindBasicManager(StarBASIC const *pLib)
Definition: basobj3.cxx:225
void StopBasic()
Definition: basobj3.cxx:283
SAL_DLLPUBLIC_EXPORT tools::Long basicide_handle_basic_error(void const *pPtr)
Definition: basobj3.cxx:57
StarBASIC * FindBasic(const SbxVariable *pVar)
Definition: basobj3.cxx:217
void InvalidateDebuggerSlots()
Definition: basobj3.cxx:343
bool RenameDialog(weld::Widget *pErrorParent, ScriptDocument const &rDocument, OUString const &rLibName, OUString const &rOldName, OUString const &rNewName)
renames a dialog
Definition: basobj3.cxx:138
std::vector< ScriptDocument > ScriptDocuments
OUString IDEResId(TranslateId aId)
Definition: iderdll.cxx:108
int i
long Long
sal_Int16 nId
SbxVOID
SbxDataType eType
sal_uInt16 sal_Unicode