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