Bump version to 24.04.3.4
[LibreOffice.git] / basctl / source / basicide / basobj3.cxx
blob4672cdd52c2bf8e3cdec1c0e0a57d1f46754de28
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
25 #include <unotools/moduleoptions.hxx>
27 #include <iderdll.hxx>
28 #include "iderdll2.hxx"
29 #include "basdoc.hxx"
30 #include <iderid.hxx>
31 #include <strings.hrc>
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>
48 namespace basctl
51 using namespace comphelper;
52 using namespace ::com::sun::star;
53 using namespace ::com::sun::star::uno;
54 using namespace ::com::sun::star::container;
56 extern "C" {
57 SAL_DLLPUBLIC_EXPORT tools::Long basicide_handle_basic_error( void const * pPtr )
59 return HandleBasicError( static_cast<StarBASIC const *>(pPtr) );
63 SbMethod* CreateMacro( SbModule* pModule, const OUString& rMacroName )
65 SfxDispatcher* pDispatcher = GetDispatcher();
66 if( pDispatcher )
68 pDispatcher->Execute( SID_BASICIDE_STOREALLMODULESOURCES );
71 if ( pModule->FindMethod( rMacroName, SbxClassType::Method ) )
72 return nullptr;
74 OUString aMacroName( rMacroName );
75 if ( aMacroName.isEmpty() )
77 if (!pModule->GetMethods()->Count())
78 aMacroName = "Main" ;
79 else
81 bool bValid = false;
82 sal_Int32 nMacro = 1;
83 while ( !bValid )
85 aMacroName = "Macro" + OUString::number( nMacro );
86 // test whether existing...
87 bValid = pModule->FindMethod( aMacroName, SbxClassType::Method ) == nullptr;
88 nMacro++;
93 OUString aOUSource( pModule->GetSource32() );
95 // don't produce too many empty lines...
96 sal_Int32 nSourceLen = aOUSource.getLength();
97 if ( nSourceLen > 2 )
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 );
108 aOUSource += "Sub " + aMacroName + "\n\nEnd Sub";
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
115 ? ScriptDocument::getDocumentForBasicManager(pBasMgr)
116 : ScriptDocument(ScriptDocument::NoDocument);
118 if (aDocument.isValid())
120 const OUString& aLibName = pBasic->GetName();
121 const OUString& aModName = pModule->GetName();
122 OSL_VERIFY( aDocument.updateModule( aLibName, aModName, aOUSource ) );
125 SbMethod* pMethod = pModule->FindMethod( aMacroName, SbxClassType::Method );
127 if( pDispatcher )
129 pDispatcher->Execute( SID_BASICIDE_UPDATEALLMODULESOURCES );
132 if (aDocument.isAlive())
133 MarkDocumentModified(aDocument);
135 return pMethod;
138 bool RenameDialog (
139 weld::Widget* pErrorParent,
140 ScriptDocument const& rDocument,
141 OUString const& rLibName,
142 OUString const& rOldName,
143 OUString const& rNewName
146 if ( !rDocument.hasDialog( rLibName, rOldName ) )
148 OSL_FAIL( "basctl::RenameDialog: old module name is invalid!" );
149 return false;
152 if ( rDocument.hasDialog( rLibName, rNewName ) )
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;
160 // #i74440
161 if ( rNewName.isEmpty() )
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;
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();
175 if ( xExistingDialog.is() )
176 LocalizationMgr::renameStringResourceIDs( rDocument, rLibName, rNewName, xExistingDialog );
178 if ( !rDocument.renameDialog( rLibName, rOldName, rNewName, xExistingDialog ) )
179 return false;
181 if (!pWin || !pShell)
182 return true;
184 // set new name in window
185 pWin->SetName( rNewName );
187 // update property browser
188 pWin->UpdateBrowser();
190 // update tabwriter
191 sal_uInt16 nId = pShell->GetWindowId( pWin );
192 DBG_ASSERT( nId, "No entry in Tabbar!" );
193 if ( nId )
195 TabBar& rTabBar = pShell->GetTabBar();
196 rTabBar.SetPageText( nId, rNewName );
197 rTabBar.Sort();
198 rTabBar.MakeVisible( rTabBar.GetCurPageId() );
200 return true;
203 bool RemoveDialog( const ScriptDocument& rDocument, const OUString& rLibName, const OUString& rDlgName )
205 if (Shell* pShell = GetShell())
207 if (VclPtr<DialogWindow> pDlgWin = pShell->FindDlgWin(rDocument, rLibName, rDlgName))
209 Reference< container::XNameContainer > xDialogModel = pDlgWin->GetDialog();
210 LocalizationMgr::removeResourceForDialog( rDocument, rLibName, rDlgName, xDialogModel );
214 return rDocument.removeDialog( rLibName, rDlgName );
217 StarBASIC* FindBasic( const SbxVariable* pVar )
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));
225 BasicManager* FindBasicManager( StarBASIC const * pLib )
227 ScriptDocuments aDocuments( ScriptDocument::getAllScriptDocuments( ScriptDocument::AllWithApplication ) );
228 for (auto const& doc : aDocuments)
230 BasicManager* pBasicMgr = doc.getBasicManager();
231 OSL_ENSURE( pBasicMgr, "basctl::FindBasicManager: no basic manager for the document!" );
232 if ( !pBasicMgr )
233 continue;
235 Sequence< OUString > aLibNames( doc.getLibraryNames() );
236 sal_Int32 nLibCount = aLibNames.getLength();
237 const OUString* pLibNames = aLibNames.getConstArray();
239 for ( sal_Int32 i = 0 ; i < nLibCount ; i++ )
241 StarBASIC* pL = pBasicMgr->GetLib( pLibNames[ i ] );
242 if ( pL == pLib )
243 return pBasicMgr;
246 return nullptr;
249 void MarkDocumentModified( const ScriptDocument& rDocument )
251 Shell* pShell = GetShell();
253 // does not have to come from a document...
254 if ( rDocument.isApplication() )
256 if (pShell)
257 pShell->SetAppBasicModified(true);
259 else
261 rDocument.setDocumentModified();
264 // tdf#130161 in all cases call UpdateObjectCatalog
265 if (pShell)
266 pShell->UpdateObjectCatalog();
268 if (SfxBindings* pBindings = GetBindingsPtr())
270 pBindings->Invalidate( SID_SIGNATURE );
271 pBindings->Invalidate( SID_SAVEDOC );
272 pBindings->Update( SID_SAVEDOC );
276 void RunMethod( SbMethod const * pMethod )
278 SbxValues aRes;
279 aRes.eType = SbxVOID;
280 pMethod->Get( aRes );
283 void StopBasic()
285 StarBASIC::Stop();
286 if (Shell* pShell = GetShell())
288 Shell::WindowTable& rWindows = pShell->GetWindowTable();
289 for (auto const& window : rWindows)
291 BaseWindow* pWin = window.second;
292 // call BasicStopped manually because the Stop-Notify
293 // might not get through otherwise
294 pWin->BasicStopped();
297 BasicStopped();
300 void BasicStopped(
301 bool* pbAppWindowDisabled,
302 bool* pbDispatcherLocked,
303 sal_uInt16* pnWaitCount,
304 SfxUInt16Item** ppSWActionCount, SfxUInt16Item** ppSWLockViewCount
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;
320 // AppWait?
321 if (Shell* pShell = GetShell())
323 sal_uInt16 nWait = 0;
324 while ( pShell->GetViewFrame().GetWindow().IsWait() )
326 pShell->GetViewFrame().GetWindow().LeaveWait();
327 nWait++;
329 if ( pnWaitCount )
330 *pnWaitCount = nWait;
333 weld::Window* pDefParent = Application::GetDefDialogParent();
334 if (pDefParent && !pDefParent->get_sensitive())
336 pDefParent->set_sensitive(true);
337 if ( pbAppWindowDisabled )
338 *pbAppWindowDisabled = true;
343 void InvalidateDebuggerSlots()
345 SfxBindings* pBindings = GetBindingsPtr();
346 if (!pBindings)
347 return;
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 );
369 tools::Long HandleBasicError( StarBASIC const * pBasic )
371 EnsureIde();
372 BasicStopped();
374 // no error output during macro choosing
375 if (GetExtraData()->ChoosingMacro())
376 return 1;
377 if (GetExtraData()->ShellInCriticalSection())
378 return 2;
380 tools::Long nRet = 0;
381 Shell* pShell = nullptr;
382 if ( SvtModuleOptions::IsBasicIDE() )
384 BasicManager* pBasMgr = FindBasicManager( pBasic );
385 if ( pBasMgr )
387 bool bProtected = false;
388 ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) );
389 OSL_ENSURE( aDocument.isValid(), "basctl::HandleBasicError: no document for the given BasicManager!" );
390 if ( aDocument.isValid() )
392 const OUString& aOULibName( pBasic->GetName() );
393 Reference< script::XLibraryContainer > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ) );
394 if ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) )
396 Reference< script::XLibraryContainerPassword > xPasswd( xModLibContainer, UNO_QUERY );
397 if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( aOULibName ) && !xPasswd->isLibraryPasswordVerified( aOULibName ) )
399 bProtected = true;
404 if ( !bProtected )
406 pShell = GetShell();
407 if ( !pShell )
409 SfxAllItemSet aArgs( SfxGetpApp()->GetPool() );
410 SfxRequest aRequest( SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs );
411 SfxGetpApp()->ExecuteSlot( aRequest );
412 pShell = GetShell();
418 if ( pShell )
419 nRet = tools::Long(pShell->CallBasicErrorHdl( pBasic ));
420 else
421 ErrorHandler::HandleError( StarBASIC::GetErrorCode() );
423 return nRet;
426 SfxBindings* GetBindingsPtr()
428 SfxBindings* pBindings = nullptr;
430 SfxViewFrame* pFrame = nullptr;
431 if (Shell* pShell = GetShell())
433 pFrame = &pShell->GetViewFrame();
435 else
437 SfxViewFrame* pView = SfxViewFrame::GetFirst();
438 while ( pView )
440 if (dynamic_cast<DocShell*>(pView->GetObjectShell()))
442 pFrame = pView;
443 break;
445 pView = SfxViewFrame::GetNext( *pView );
448 if ( pFrame != nullptr )
449 pBindings = &pFrame->GetBindings();
451 return pBindings;
454 SfxDispatcher* GetDispatcher ()
456 if (Shell* pShell = GetShell())
458 SfxViewFrame& rViewFrame = pShell->GetViewFrame();
459 if (SfxDispatcher* pDispatcher = rViewFrame.GetDispatcher())
460 return pDispatcher;
462 return nullptr;
464 } // namespace basctl
466 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */