xref: /trunk/main/basctl/source/basicide/basobj3.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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