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 throw(ElementExistException, NoSuchElementException)
176 {
177 if ( !rDocument.hasDialog( rLibName, rOldName ) )
178 {
179 OSL_ENSURE( false, "BasicIDE::RenameDialog: old module name is invalid!" );
180 return false;
181 }
182
183 if ( rDocument.hasDialog( rLibName, rNewName ) )
184 {
185 ErrorBox aError( pErrorParent, WB_OK | WB_DEF_OK, String( IDEResId( RID_STR_SBXNAMEALLREADYUSED2 ) ) );
186 aError.Execute();
187 return false;
188 }
189
190 // #i74440
191 if ( rNewName.Len() == 0 )
192 {
193 ErrorBox aError( pErrorParent, WB_OK | WB_DEF_OK, String( IDEResId( RID_STR_BADSBXNAME ) ) );
194 aError.Execute();
195 return false;
196 }
197
198 BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
199 IDEBaseWindow* pWin = pIDEShell ? pIDEShell->FindWindow( rDocument, rLibName, rOldName, BASICIDE_TYPE_DIALOG, sal_False ) : NULL;
200 Reference< XNameContainer > xExistingDialog;
201 if ( pWin )
202 xExistingDialog = ((DialogWindow*)pWin)->GetEditor()->GetDialog();
203
204 if ( xExistingDialog.is() )
205 LocalizationMgr::renameStringResourceIDs( rDocument, rLibName, rNewName, xExistingDialog );
206
207 if ( !rDocument.renameDialog( rLibName, rOldName, rNewName, xExistingDialog ) )
208 return false;
209
210 if ( pWin )
211 {
212 // set new name in window
213 pWin->SetName( rNewName );
214
215 // update property browser
216 ((DialogWindow*)pWin)->UpdateBrowser();
217
218 // update tabwriter
219 sal_uInt16 nId = (sal_uInt16)(pIDEShell->GetIDEWindowTable()).GetKey( pWin );
220 DBG_ASSERT( nId, "No entry in Tabbar!" );
221 if ( nId )
222 {
223 BasicIDETabBar* pTabBar = (BasicIDETabBar*)pIDEShell->GetTabBar();
224 pTabBar->SetPageText( nId, rNewName );
225 pTabBar->Sort();
226 pTabBar->MakeVisible( pTabBar->GetCurPageId() );
227 }
228 }
229 return true;
230 }
231
232 //----------------------------------------------------------------------------
233
RemoveDialog(const ScriptDocument & rDocument,const String & rLibName,const String & rDlgName)234 bool RemoveDialog( const ScriptDocument& rDocument, const String& rLibName, const String& rDlgName )
235 {
236 BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
237 if ( pIDEShell )
238 {
239 DialogWindow* pDlgWin = pIDEShell->FindDlgWin( rDocument, rLibName, rDlgName, sal_False );
240 if( pDlgWin )
241 {
242 Reference< container::XNameContainer > xDialogModel = pDlgWin->GetDialog();
243 LocalizationMgr::removeResourceForDialog( rDocument, rLibName, rDlgName, xDialogModel );
244 }
245 }
246
247 return rDocument.removeDialog( rLibName, rDlgName );
248 }
249
250 //----------------------------------------------------------------------------
251
FindBasic(const SbxVariable * pVar)252 StarBASIC* FindBasic( const SbxVariable* pVar )
253 {
254 const SbxVariable* pSbx = pVar;
255 while ( pSbx && !pSbx->ISA( StarBASIC ) )
256 pSbx = pSbx->GetParent();
257
258 DBG_ASSERT( !pSbx || pSbx->ISA( StarBASIC ), "Find Basic: Kein Basic!" );
259 return (StarBASIC*)pSbx;
260 }
261
262 //----------------------------------------------------------------------------
263
FindBasicManager(StarBASIC * pLib)264 BasicManager* FindBasicManager( StarBASIC* pLib )
265 {
266 ScriptDocuments aDocuments( ScriptDocument::getAllScriptDocuments( ScriptDocument::AllWithApplication ) );
267 for ( ScriptDocuments::const_iterator doc = aDocuments.begin();
268 doc != aDocuments.end();
269 ++doc
270 )
271 {
272 BasicManager* pBasicMgr = doc->getBasicManager();
273 OSL_ENSURE( pBasicMgr, "BasicIDE::FindBasicManager: no basic manager for the document!" );
274 if ( !pBasicMgr )
275 continue;
276
277 Sequence< ::rtl::OUString > aLibNames( doc->getLibraryNames() );
278 sal_Int32 nLibCount = aLibNames.getLength();
279 const ::rtl::OUString* pLibNames = aLibNames.getConstArray();
280
281 for ( sal_Int32 i = 0 ; i < nLibCount ; i++ )
282 {
283 StarBASIC* pL = pBasicMgr->GetLib( pLibNames[ i ] );
284 if ( pL == pLib )
285 return pBasicMgr;
286 }
287 }
288 return NULL;
289 }
290
291 //----------------------------------------------------------------------------
292
MarkDocumentModified(const ScriptDocument & rDocument)293 void MarkDocumentModified( const ScriptDocument& rDocument )
294 {
295 // Muss ja nicht aus einem Document kommen...
296 if ( rDocument.isApplication() )
297 {
298 BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
299 if ( pIDEShell )
300 pIDEShell->SetAppBasicModified();
301 }
302 else
303 {
304 rDocument.setDocumentModified();
305 }
306
307 SfxBindings* pBindings = BasicIDE::GetBindingsPtr();
308 if ( pBindings )
309 {
310 pBindings->Invalidate( SID_SIGNATURE );
311 pBindings->Invalidate( SID_SAVEDOC );
312 pBindings->Update( SID_SAVEDOC );
313 }
314
315 // Objectcatalog updaten...
316 BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
317 ObjectCatalog* pObjCatalog = pIDEShell ? pIDEShell->GetObjectCatalog() : 0;
318 if ( pObjCatalog )
319 pObjCatalog->UpdateEntries();
320 }
321
322 //----------------------------------------------------------------------------
323
RunMethod(SbMethod * pMethod)324 void RunMethod( SbMethod* pMethod )
325 {
326 SbxValues aRes;
327 aRes.eType = SbxVOID;
328 pMethod->Get( aRes );
329 }
330
331 //----------------------------------------------------------------------------
332
StopBasic()333 void StopBasic()
334 {
335 StarBASIC::Stop();
336 BasicIDEShell* pShell = IDE_DLL()->GetShell();
337 if ( pShell )
338 {
339 IDEWindowTable& rWindows = pShell->GetIDEWindowTable();
340 IDEBaseWindow* pWin = rWindows.First();
341 while ( pWin )
342 {
343 // BasicStopped von Hand rufen, da das Stop-Notify ggf. sonst nicht
344 // durchkommen kann.
345 pWin->BasicStopped();
346 pWin = rWindows.Next();
347 }
348 }
349 BasicIDE::BasicStopped();
350 }
351
352 //----------------------------------------------------------------------------
353
BasicStopped(sal_Bool * pbAppWindowDisabled,sal_Bool * pbDispatcherLocked,sal_uInt16 * pnWaitCount,SfxUInt16Item ** ppSWActionCount,SfxUInt16Item ** ppSWLockViewCount)354 void BasicStopped( sal_Bool* pbAppWindowDisabled,
355 sal_Bool* pbDispatcherLocked, sal_uInt16* pnWaitCount,
356 SfxUInt16Item** ppSWActionCount, SfxUInt16Item** ppSWLockViewCount )
357 {
358 // Nach einem Error oder dem expliziten abbrechen des Basics muessen
359 // ggf. einige Locks entfernt werden...
360
361 if ( pbAppWindowDisabled )
362 *pbAppWindowDisabled = sal_False;
363 if ( pbDispatcherLocked )
364 *pbDispatcherLocked = sal_False;
365 if ( pnWaitCount )
366 *pnWaitCount = 0;
367 if ( ppSWActionCount )
368 *ppSWActionCount = 0;
369 if ( ppSWLockViewCount )
370 *ppSWLockViewCount = 0;
371
372 // AppWait ?
373 sal_uInt16 nWait = 0;
374 BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
375 if( pIDEShell )
376 {
377 while ( pIDEShell->GetViewFrame()->GetWindow().IsWait() )
378 {
379 pIDEShell->GetViewFrame()->GetWindow().LeaveWait();
380 nWait++;
381 }
382 if ( pnWaitCount )
383 *pnWaitCount = nWait;
384 }
385
386 /*
387 // Interactive = sal_False ?
388 if ( SFX_APP()->IsDispatcherLocked() )
389 {
390 SFX_APP()->LockDispatcher( sal_False );
391 if ( pbDispatcherLocked )
392 *pbDispatcherLocked = sal_True;
393 } */
394
395 Window* pDefParent = Application::GetDefDialogParent();
396 if ( pDefParent && !pDefParent->IsEnabled() )
397 {
398 pDefParent->Enable( sal_True );
399 if ( pbAppWindowDisabled )
400 *pbAppWindowDisabled = sal_True;
401 }
402
403 }
404
405 //----------------------------------------------------------------------------
406
InvalidateDebuggerSlots()407 void InvalidateDebuggerSlots()
408 {
409 SfxBindings* pBindings = BasicIDE::GetBindingsPtr();
410 if ( pBindings )
411 {
412 pBindings->Invalidate( SID_BASICSTOP );
413 pBindings->Update( SID_BASICSTOP );
414 pBindings->Invalidate( SID_BASICRUN );
415 pBindings->Update( SID_BASICRUN );
416 pBindings->Invalidate( SID_BASICCOMPILE );
417 pBindings->Update( SID_BASICCOMPILE );
418 pBindings->Invalidate( SID_BASICSTEPOVER );
419 pBindings->Update( SID_BASICSTEPOVER );
420 pBindings->Invalidate( SID_BASICSTEPINTO );
421 pBindings->Update( SID_BASICSTEPINTO );
422 pBindings->Invalidate( SID_BASICSTEPOUT );
423 pBindings->Update( SID_BASICSTEPOUT );
424 pBindings->Invalidate( SID_BASICIDE_TOGGLEBRKPNT );
425 pBindings->Update( SID_BASICIDE_TOGGLEBRKPNT );
426 pBindings->Invalidate( SID_BASICIDE_STAT_POS );
427 pBindings->Update( SID_BASICIDE_STAT_POS );
428 }
429 }
430
431 //----------------------------------------------------------------------------
432
HandleBasicError(StarBASIC * pBasic)433 long HandleBasicError( StarBASIC* pBasic )
434 {
435 BasicIDEDLL::Init();
436 BasicIDE::BasicStopped();
437
438 // no error output during macro choosing
439 if ( IDE_DLL()->GetExtraData()->ChoosingMacro() )
440 return 1;
441 if ( IDE_DLL()->GetExtraData()->ShellInCriticalSection() )
442 return 2;
443
444 long nRet = 0;
445 BasicIDEShell* pIDEShell = 0;
446 if ( SvtModuleOptions().IsBasicIDE() )
447 {
448 BasicManager* pBasMgr = BasicIDE::FindBasicManager( pBasic );
449 if ( pBasMgr )
450 {
451 sal_Bool bProtected = sal_False;
452 ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) );
453 OSL_ENSURE( aDocument.isValid(), "BasicIDE::HandleBasicError: no document for the given BasicManager!" );
454 if ( aDocument.isValid() )
455 {
456 ::rtl::OUString aOULibName( pBasic->GetName() );
457 Reference< script::XLibraryContainer > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ) );
458 if ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) )
459 {
460 Reference< script::XLibraryContainerPassword > xPasswd( xModLibContainer, UNO_QUERY );
461 if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( aOULibName ) && !xPasswd->isLibraryPasswordVerified( aOULibName ) )
462 {
463 bProtected = sal_True;
464 }
465 }
466 }
467
468 if ( !bProtected )
469 {
470 pIDEShell = IDE_DLL()->GetShell();
471 if ( !pIDEShell )
472 {
473 SfxAllItemSet aArgs( SFX_APP()->GetPool() );
474 SfxRequest aRequest( SID_BASICIDE_APPEAR, SFX_CALLMODE_SYNCHRON, aArgs );
475 SFX_APP()->ExecuteSlot( aRequest );
476 pIDEShell = IDE_DLL()->GetShell();
477 }
478 }
479 }
480 }
481
482 if ( pIDEShell )
483 nRet = pIDEShell->CallBasicErrorHdl( pBasic );
484 else
485 ErrorHandler::HandleError( StarBASIC::GetErrorCode() );
486
487 return nRet;
488 }
489
490 //----------------------------------------------------------------------------
491
GetBindingsPtr()492 SfxBindings* GetBindingsPtr()
493 {
494 SfxBindings* pBindings = NULL;
495
496 SfxViewFrame* pFrame = NULL;
497 BasicIDEDLL* pIDEDLL = IDE_DLL();
498 if ( pIDEDLL && pIDEDLL->GetShell() )
499 {
500 pFrame = pIDEDLL->GetShell()->GetViewFrame();
501 }
502 else
503 {
504 SfxViewFrame* pView = SfxViewFrame::GetFirst();
505 while ( pView )
506 {
507 SfxObjectShell* pObjShell = pView->GetObjectShell();
508 if ( pObjShell && pObjShell->ISA( BasicDocShell ) )
509 {
510 pFrame = pView;
511 break;
512 }
513 pView = SfxViewFrame::GetNext( *pView );
514 }
515 }
516 if ( pFrame != NULL )
517 pBindings = &pFrame->GetBindings();
518
519 return pBindings;
520 }
521
522 } //namespace BasicIDE
523
524 //----------------------------------------------------------------------------
525