xref: /aoo42x/main/basctl/source/basicide/basobj3.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basctl.hxx"
30 
31 #include <ide_pch.hxx>
32 
33 #include <vector>
34 #include <algorithm>
35 #include <basic/sbx.hxx>
36 #include <unotools/moduleoptions.hxx>
37 
38 #include <iderdll.hxx>
39 #include <iderdll2.hxx>
40 #include <basobj.hxx>
41 #include <basidesh.hxx>
42 #include <objdlg.hxx>
43 #include <bastypes.hxx>
44 #include <basdoc.hxx>
45 #include <basidesh.hrc>
46 
47 #include <baside2.hxx>
48 #include <baside3.hxx>
49 #include <basicmod.hxx>
50 #include <localizationmgr.hxx>
51 #include "dlged.hxx"
52 #include <dlgeddef.hxx>
53 #include <comphelper/processfactory.hxx>
54 #ifndef _COM_SUN_STAR_SCRIPT_XLIBRYARYCONTAINER_HPP_
55 #include <com/sun/star/script/XLibraryContainer.hpp>
56 #endif
57 #include <com/sun/star/script/XLibraryContainerPassword.hpp>
58 #include <com/sun/star/container/XNameContainer.hpp>
59 #include <xmlscript/xmldlg_imexp.hxx>
60 #include <rtl/uri.hxx>
61 #include <osl/process.h>
62 #include <osl/file.hxx>
63 
64 using namespace comphelper;
65 using namespace ::com::sun::star;
66 using namespace ::com::sun::star::uno;
67 using namespace ::com::sun::star::container;
68 
69 
70 //----------------------------------------------------------------------------
71 
72 extern "C" {
73     SAL_DLLPUBLIC_EXPORT long basicide_handle_basic_error( void* pPtr )
74 	{
75         return BasicIDE::HandleBasicError( (StarBASIC*)pPtr );
76     }
77 }
78 
79 namespace BasicIDE
80 {
81 //----------------------------------------------------------------------------
82 
83 SbMethod* CreateMacro( SbModule* pModule, const String& rMacroName )
84 {
85     BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
86     SfxViewFrame* pViewFrame = pIDEShell ? pIDEShell->GetViewFrame() : NULL;
87 	SfxDispatcher* pDispatcher = pViewFrame ? pViewFrame->GetDispatcher() : NULL;
88 
89     if( pDispatcher )
90 	{
91 		pDispatcher->Execute( SID_BASICIDE_STOREALLMODULESOURCES );
92 	}
93 
94 	if ( pModule->GetMethods()->Find( rMacroName, SbxCLASS_METHOD ) )
95 		return 0;
96 
97 	String aMacroName( rMacroName );
98 	if ( aMacroName.Len() == 0 )
99 	{
100 		if ( !pModule->GetMethods()->Count() )
101 			aMacroName = String( RTL_CONSTASCII_USTRINGPARAM( "Main" ) );
102 		else
103 		{
104 			sal_Bool bValid = sal_False;
105 			String aStdMacroText( RTL_CONSTASCII_USTRINGPARAM( "Macro" ) );
106 			//String aStdMacroText( IDEResId( RID_STR_STDMACRONAME ) );
107 			sal_uInt16 nMacro = 1;
108 			while ( !bValid )
109 			{
110 				aMacroName = aStdMacroText;
111 				aMacroName += String::CreateFromInt32( nMacro );
112 				// Pruefen, ob vorhanden...
113 				bValid = pModule->GetMethods()->Find( aMacroName, SbxCLASS_METHOD ) ? sal_False : sal_True;
114 				nMacro++;
115 			}
116 		}
117 	}
118 
119     ::rtl::OUString aOUSource( pModule->GetSource32() );
120 
121 	// Nicht zu viele Leerzeilen erzeugen...
122     sal_Int32 nSourceLen = aOUSource.getLength();
123 	if ( nSourceLen > 2 )
124 	{
125         const sal_Unicode* pStr = aOUSource.getStr();
126 		if ( pStr[ nSourceLen - 1 ]  != LINE_SEP )
127 			aOUSource += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n\n" ) );
128 		else if ( pStr[ nSourceLen - 2 ] != LINE_SEP )
129 			aOUSource += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ) );
130 		else if ( pStr[ nSourceLen - 3 ] == LINE_SEP )
131 			aOUSource = aOUSource.copy( 0, nSourceLen-1 );
132 	}
133 
134 	::rtl::OUString aSubStr;
135 	aSubStr = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Sub " ) );
136 	aSubStr += aMacroName;
137 	aSubStr += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n\nEnd Sub" ) );
138 
139 	aOUSource += aSubStr;
140 
141     // update module in library
142     ScriptDocument aDocument( ScriptDocument::NoDocument );
143     SbxObject* pParent = pModule->GetParent();
144 	StarBASIC* pBasic = PTR_CAST(StarBASIC,pParent);
145     DBG_ASSERT(pBasic, "BasicIDE::CreateMacro: No Basic found!");
146     if ( pBasic )
147 	{
148 		BasicManager* pBasMgr = BasicIDE::FindBasicManager( pBasic );
149 		DBG_ASSERT(pBasMgr, "BasicIDE::CreateMacro: No BasicManager found!");
150 		if ( pBasMgr )
151 		{
152             aDocument = ScriptDocument::getDocumentForBasicManager( pBasMgr );
153             OSL_ENSURE( aDocument.isValid(), "BasicIDE::CreateMacro: no document for the given BasicManager!" );
154             if ( aDocument.isValid() )
155             {
156         	    String aLibName = pBasic->GetName();
157 	            String aModName = pModule->GetName();
158                 OSL_VERIFY( aDocument.updateModule( aLibName, aModName, aOUSource ) );
159             }
160         }
161     }
162 
163     SbMethod* pMethod = (SbMethod*)pModule->GetMethods()->Find( aMacroName, SbxCLASS_METHOD );
164 
165     if( pDispatcher )
166 	{
167 		pDispatcher->Execute( SID_BASICIDE_UPDATEALLMODULESOURCES );
168 	}
169 
170     if ( aDocument.isAlive() )
171         BasicIDE::MarkDocumentModified( aDocument );
172 
173     return pMethod;
174 }
175 
176 //----------------------------------------------------------------------------
177 
178 bool RenameDialog( Window* pErrorParent, const ScriptDocument& rDocument, const String& rLibName, const String& rOldName, const String& rNewName )
179 	throw(ElementExistException, NoSuchElementException)
180 {
181     if ( !rDocument.hasDialog( rLibName, rOldName ) )
182     {
183         OSL_ENSURE( false, "BasicIDE::RenameDialog: old module name is invalid!" );
184         return false;
185     }
186 
187     if ( rDocument.hasDialog( rLibName, rNewName ) )
188     {
189         ErrorBox aError( pErrorParent, WB_OK | WB_DEF_OK, String( IDEResId( RID_STR_SBXNAMEALLREADYUSED2 ) ) );
190         aError.Execute();
191         return false;
192     }
193 
194 	// #i74440
195 	if ( rNewName.Len() == 0 )
196     {
197         ErrorBox aError( pErrorParent, WB_OK | WB_DEF_OK, String( IDEResId( RID_STR_BADSBXNAME ) ) );
198         aError.Execute();
199 		return false;
200     }
201 
202     BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
203     IDEBaseWindow* pWin = pIDEShell ? pIDEShell->FindWindow( rDocument, rLibName, rOldName, BASICIDE_TYPE_DIALOG, sal_False ) : NULL;
204     Reference< XNameContainer > xExistingDialog;
205     if ( pWin )
206         xExistingDialog = ((DialogWindow*)pWin)->GetEditor()->GetDialog();
207 
208     if ( xExistingDialog.is() )
209         LocalizationMgr::renameStringResourceIDs( rDocument, rLibName, rNewName, xExistingDialog );
210 
211     if ( !rDocument.renameDialog( rLibName, rOldName, rNewName, xExistingDialog ) )
212         return false;
213 
214 	if ( pWin )
215 	{
216 		// set new name in window
217 		pWin->SetName( rNewName );
218 
219 		// update property browser
220 		((DialogWindow*)pWin)->UpdateBrowser();
221 
222 		// update tabwriter
223 		sal_uInt16 nId = (sal_uInt16)(pIDEShell->GetIDEWindowTable()).GetKey( pWin );
224 		DBG_ASSERT( nId, "No entry in Tabbar!" );
225 		if ( nId )
226 		{
227 			BasicIDETabBar*	pTabBar = (BasicIDETabBar*)pIDEShell->GetTabBar();
228 			pTabBar->SetPageText( nId, rNewName );
229 			pTabBar->Sort();
230 			pTabBar->MakeVisible( pTabBar->GetCurPageId() );
231 		}
232 	}
233     return true;
234 }
235 
236 //----------------------------------------------------------------------------
237 
238 bool RemoveDialog( const ScriptDocument& rDocument, const String& rLibName, const String& rDlgName )
239 {
240     BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
241     if ( pIDEShell )
242 	{
243 		DialogWindow* pDlgWin = pIDEShell->FindDlgWin( rDocument, rLibName, rDlgName, sal_False );
244 		if( pDlgWin )
245 		{
246 			Reference< container::XNameContainer > xDialogModel = pDlgWin->GetDialog();
247 			LocalizationMgr::removeResourceForDialog( rDocument, rLibName, rDlgName, xDialogModel );
248 		}
249 	}
250 
251     return rDocument.removeDialog( rLibName, rDlgName );
252 }
253 
254 //----------------------------------------------------------------------------
255 
256 StarBASIC* FindBasic( const SbxVariable* pVar )
257 {
258 	const SbxVariable* pSbx = pVar;
259 	while ( pSbx && !pSbx->ISA( StarBASIC ) )
260 		pSbx = pSbx->GetParent();
261 
262 	DBG_ASSERT( !pSbx || pSbx->ISA( StarBASIC ), "Find Basic: Kein Basic!" );
263 	return (StarBASIC*)pSbx;
264 }
265 
266 //----------------------------------------------------------------------------
267 
268 BasicManager* FindBasicManager( StarBASIC* pLib )
269 {
270     ScriptDocuments aDocuments( ScriptDocument::getAllScriptDocuments( ScriptDocument::AllWithApplication ) );
271     for (   ScriptDocuments::const_iterator doc = aDocuments.begin();
272             doc != aDocuments.end();
273             ++doc
274         )
275     {
276         BasicManager* pBasicMgr = doc->getBasicManager();
277         OSL_ENSURE( pBasicMgr, "BasicIDE::FindBasicManager: no basic manager for the document!" );
278         if ( !pBasicMgr )
279             continue;
280 
281         Sequence< ::rtl::OUString > aLibNames( doc->getLibraryNames() );
282         sal_Int32 nLibCount = aLibNames.getLength();
283 	    const ::rtl::OUString* pLibNames = aLibNames.getConstArray();
284 
285         for ( sal_Int32 i = 0 ; i < nLibCount ; i++ )
286 	    {
287             StarBASIC* pL = pBasicMgr->GetLib( pLibNames[ i ] );
288 			if ( pL == pLib )
289 				return pBasicMgr;
290         }
291 	}
292 	return NULL;
293 }
294 
295 //----------------------------------------------------------------------------
296 
297 void MarkDocumentModified( const ScriptDocument& rDocument )
298 {
299 	// Muss ja nicht aus einem Document kommen...
300     if ( rDocument.isApplication() )
301     {
302         BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
303         if ( pIDEShell )
304             pIDEShell->SetAppBasicModified();
305     }
306     else
307     {
308         rDocument.setDocumentModified();
309     }
310 
311     SfxBindings* pBindings = BasicIDE::GetBindingsPtr();
312     if ( pBindings )
313     {
314         pBindings->Invalidate( SID_SIGNATURE );
315         pBindings->Invalidate( SID_SAVEDOC );
316         pBindings->Update( SID_SAVEDOC );
317     }
318 
319 	// Objectcatalog updaten...
320 	BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
321 	ObjectCatalog* pObjCatalog = pIDEShell ? pIDEShell->GetObjectCatalog() : 0;
322 	if ( pObjCatalog )
323 		pObjCatalog->UpdateEntries();
324 }
325 
326 //----------------------------------------------------------------------------
327 
328 void RunMethod( SbMethod* pMethod )
329 {
330 	SbxValues aRes;
331 	aRes.eType = SbxVOID;
332 	pMethod->Get( aRes );
333 }
334 
335 //----------------------------------------------------------------------------
336 
337 void StopBasic()
338 {
339 	StarBASIC::Stop();
340 	BasicIDEShell* pShell = IDE_DLL()->GetShell();
341 	if ( pShell )
342 	{
343 		IDEWindowTable& rWindows = pShell->GetIDEWindowTable();
344 		IDEBaseWindow* pWin = rWindows.First();
345 		while ( pWin )
346 		{
347 			// BasicStopped von Hand rufen, da das Stop-Notify ggf. sonst nicht
348 			// durchkommen kann.
349 			pWin->BasicStopped();
350 			pWin = rWindows.Next();
351 		}
352 	}
353 	BasicIDE::BasicStopped();
354 }
355 
356 //----------------------------------------------------------------------------
357 
358 void BasicStopped( sal_Bool* pbAppWindowDisabled,
359 		sal_Bool* pbDispatcherLocked, sal_uInt16* pnWaitCount,
360 		SfxUInt16Item** ppSWActionCount, SfxUInt16Item** ppSWLockViewCount )
361 {
362 	// Nach einem Error oder dem expliziten abbrechen des Basics muessen
363 	// ggf. einige Locks entfernt werden...
364 
365 	if ( pbAppWindowDisabled )
366 		*pbAppWindowDisabled = sal_False;
367 	if ( pbDispatcherLocked )
368 		*pbDispatcherLocked = sal_False;
369 	if ( pnWaitCount )
370 		*pnWaitCount = 0;
371 	if ( ppSWActionCount )
372 		*ppSWActionCount = 0;
373 	if ( ppSWLockViewCount )
374 		*ppSWLockViewCount = 0;
375 
376 	// AppWait ?
377 	sal_uInt16 nWait = 0;
378 	BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
379 	if( pIDEShell )
380 	{
381 		while ( pIDEShell->GetViewFrame()->GetWindow().IsWait() )
382 		{
383 			pIDEShell->GetViewFrame()->GetWindow().LeaveWait();
384 			nWait++;
385 		}
386 		if ( pnWaitCount )
387 			*pnWaitCount = nWait;
388 	}
389 
390     /*
391     // Interactive = sal_False ?
392 	if ( SFX_APP()->IsDispatcherLocked() )
393 	{
394 		SFX_APP()->LockDispatcher( sal_False );
395 		if ( pbDispatcherLocked )
396 			*pbDispatcherLocked = sal_True;
397     } */
398 
399 	Window* pDefParent = Application::GetDefDialogParent();
400 	if ( pDefParent && !pDefParent->IsEnabled() )
401 	{
402 		pDefParent->Enable( sal_True );
403 		if ( pbAppWindowDisabled )
404 			*pbAppWindowDisabled = sal_True;
405 	}
406 
407 }
408 
409 //----------------------------------------------------------------------------
410 
411 void InvalidateDebuggerSlots()
412 {
413     SfxBindings* pBindings = BasicIDE::GetBindingsPtr();
414     if ( pBindings )
415     {
416         pBindings->Invalidate( SID_BASICSTOP );
417         pBindings->Update( SID_BASICSTOP );
418         pBindings->Invalidate( SID_BASICRUN );
419         pBindings->Update( SID_BASICRUN );
420         pBindings->Invalidate( SID_BASICCOMPILE );
421         pBindings->Update( SID_BASICCOMPILE );
422         pBindings->Invalidate( SID_BASICSTEPOVER );
423         pBindings->Update( SID_BASICSTEPOVER );
424         pBindings->Invalidate( SID_BASICSTEPINTO );
425         pBindings->Update( SID_BASICSTEPINTO );
426         pBindings->Invalidate( SID_BASICSTEPOUT );
427         pBindings->Update( SID_BASICSTEPOUT );
428         pBindings->Invalidate( SID_BASICIDE_TOGGLEBRKPNT );
429         pBindings->Update( SID_BASICIDE_TOGGLEBRKPNT );
430         pBindings->Invalidate( SID_BASICIDE_STAT_POS );
431         pBindings->Update( SID_BASICIDE_STAT_POS );
432     }
433 }
434 
435 //----------------------------------------------------------------------------
436 
437 long HandleBasicError( StarBASIC* pBasic )
438 {
439 	BasicIDEDLL::Init();
440     BasicIDE::BasicStopped();
441 
442     // no error output during macro choosing
443     if ( IDE_DLL()->GetExtraData()->ChoosingMacro() )
444 		return 1;
445 	if ( IDE_DLL()->GetExtraData()->ShellInCriticalSection() )
446 		return 2;
447 
448 	long nRet = 0;
449 	BasicIDEShell* pIDEShell = 0;
450 	if ( SvtModuleOptions().IsBasicIDE() )
451 	{
452 		BasicManager* pBasMgr = BasicIDE::FindBasicManager( pBasic );
453 		if ( pBasMgr )
454 		{
455             sal_Bool bProtected = sal_False;
456             ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) );
457             OSL_ENSURE( aDocument.isValid(), "BasicIDE::HandleBasicError: no document for the given BasicManager!" );
458             if ( aDocument.isValid() )
459             {
460                 ::rtl::OUString aOULibName( pBasic->GetName() );
461                 Reference< script::XLibraryContainer > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ) );
462                 if ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) )
463                 {
464                     Reference< script::XLibraryContainerPassword > xPasswd( xModLibContainer, UNO_QUERY );
465                     if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( aOULibName ) && !xPasswd->isLibraryPasswordVerified( aOULibName ) )
466                     {
467                         bProtected = sal_True;
468                     }
469                 }
470             }
471 
472             if ( !bProtected )
473             {
474 				pIDEShell = IDE_DLL()->GetShell();
475 				if ( !pIDEShell )
476 				{
477                     SfxAllItemSet aArgs( SFX_APP()->GetPool() );
478                     SfxRequest aRequest( SID_BASICIDE_APPEAR, SFX_CALLMODE_SYNCHRON, aArgs );
479                     SFX_APP()->ExecuteSlot( aRequest );
480 					pIDEShell = IDE_DLL()->GetShell();
481 				}
482             }
483         }
484 	}
485 
486 	if ( pIDEShell )
487 		nRet = pIDEShell->CallBasicErrorHdl( pBasic );
488 	else
489         ErrorHandler::HandleError( StarBASIC::GetErrorCode() );
490 
491 	return nRet;
492 }
493 
494 //----------------------------------------------------------------------------
495 
496 SfxBindings* GetBindingsPtr()
497 {
498     SfxBindings* pBindings = NULL;
499 
500     SfxViewFrame* pFrame = NULL;
501     BasicIDEDLL* pIDEDLL = IDE_DLL();
502     if ( pIDEDLL && pIDEDLL->GetShell() )
503     {
504         pFrame = pIDEDLL->GetShell()->GetViewFrame();
505     }
506     else
507     {
508         SfxViewFrame* pView = SfxViewFrame::GetFirst();
509         while ( pView )
510         {
511             SfxObjectShell* pObjShell = pView->GetObjectShell();
512             if ( pObjShell && pObjShell->ISA( BasicDocShell ) )
513             {
514                 pFrame = pView;
515                 break;
516             }
517             pView = SfxViewFrame::GetNext( *pView );
518         }
519     }
520     if ( pFrame != NULL )
521         pBindings = &pFrame->GetBindings();
522 
523     return pBindings;
524 }
525 
526 } //namespace BasicIDE
527 
528 //----------------------------------------------------------------------------
529