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