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