1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <iderdll.hxx>
21 #include "iderdll2.hxx"
22 #include "macrodlg.hxx"
23 #include "moduldlg.hxx"
24 #include <strings.hrc>
25 #include "baside2.hxx"
27 #include <com/sun/star/document/XScriptInvocationContext.hpp>
29 #include <basic/sbmeth.hxx>
30 #include <framework/documentundoguard.hxx>
31 #include <tools/diagnose_ex.h>
32 #include <unotools/moduleoptions.hxx>
33 #include <vcl/weld.hxx>
38 #include <basic/basmgr.hxx>
42 using namespace ::com::sun::star
;
43 using namespace ::com::sun::star::uno
;
44 using namespace ::com::sun::star::container
;
47 SAL_DLLPUBLIC_EXPORT rtl_uString
* basicide_choose_macro( void* pOnlyInDocument_AsXModel
, void* pDocFrame_AsXFrame
, sal_Bool bChooseOnly
)
49 Reference
< frame::XModel
> aDocument( static_cast< frame::XModel
* >( pOnlyInDocument_AsXModel
) );
50 Reference
< frame::XFrame
> aDocFrame( static_cast< frame::XFrame
* >( pDocFrame_AsXFrame
) );
51 OUString aScriptURL
= basctl::ChooseMacro( aDocument
, aDocFrame
, bChooseOnly
);
52 rtl_uString
* pScriptURL
= aScriptURL
.pData
;
53 rtl_uString_acquire( pScriptURL
);
57 SAL_DLLPUBLIC_EXPORT
void basicide_macro_organizer( sal_Int16 nTabId
)
59 SAL_INFO("basctl.basicide","in basicide_macro_organizer");
60 basctl::Organize( nTabId
);
64 void Organize( sal_Int16 tabId
)
68 EntryDescriptor aDesc
;
69 if (Shell
* pShell
= GetShell())
70 if (BaseWindow
* pCurWin
= pShell
->GetCurWindow())
71 aDesc
= pCurWin
->CreateEntryDescriptor();
73 vcl::Window
* pParent
= Application::GetDefDialogParent();
74 ScopedVclPtrInstance
<OrganizeDialog
>(pParent
, tabId
, aDesc
)->Execute();
77 bool IsValidSbxName( const OUString
& rName
)
79 for ( sal_Int32 nChar
= 0; nChar
< rName
.getLength(); nChar
++ )
81 sal_Unicode c
= rName
[nChar
];
83 ( c
>= 'A' && c
<= 'Z' ) ||
84 ( c
>= 'a' && c
<= 'z' ) ||
85 ( c
>= '0' && c
<= '9' && nChar
) ||
94 static bool StringCompareLessThan( const OUString
& rStr1
, const OUString
& rStr2
)
96 return rStr1
.compareToIgnoreAsciiCase( rStr2
) < 0;
99 Sequence
< OUString
> GetMergedLibraryNames( const Reference
< script::XLibraryContainer
>& xModLibContainer
, const Reference
< script::XLibraryContainer
>& xDlgLibContainer
)
101 // create a sorted list of module library names
102 std::vector
<OUString
> aModLibList
;
103 if ( xModLibContainer
.is() )
105 Sequence
< OUString
> aModLibNames
= xModLibContainer
->getElementNames();
106 sal_Int32 nModLibCount
= aModLibNames
.getLength();
107 const OUString
* pModLibNames
= aModLibNames
.getConstArray();
108 for ( sal_Int32 i
= 0 ; i
< nModLibCount
; i
++ )
109 aModLibList
.push_back( pModLibNames
[ i
] );
110 std::sort( aModLibList
.begin() , aModLibList
.end() , StringCompareLessThan
);
113 // create a sorted list of dialog library names
114 std::vector
<OUString
> aDlgLibList
;
115 if ( xDlgLibContainer
.is() )
117 Sequence
< OUString
> aDlgLibNames
= xDlgLibContainer
->getElementNames();
118 sal_Int32 nDlgLibCount
= aDlgLibNames
.getLength();
119 const OUString
* pDlgLibNames
= aDlgLibNames
.getConstArray();
120 for ( sal_Int32 i
= 0 ; i
< nDlgLibCount
; i
++ )
121 aDlgLibList
.push_back( pDlgLibNames
[ i
] );
122 std::sort( aDlgLibList
.begin() , aDlgLibList
.end() , StringCompareLessThan
);
126 std::vector
<OUString
> aLibList( aModLibList
.size() + aDlgLibList
.size() );
127 std::merge( aModLibList
.begin(), aModLibList
.end(), aDlgLibList
.begin(), aDlgLibList
.end(), aLibList
.begin(), StringCompareLessThan
);
128 std::vector
<OUString
>::iterator aIterEnd
= std::unique( aLibList
.begin(), aLibList
.end() ); // move unique elements to the front
129 aLibList
.erase( aIterEnd
, aLibList
.end() ); // remove duplicates
132 sal_Int32 nLibCount
= aLibList
.size();
133 Sequence
< OUString
> aSeqLibNames( nLibCount
);
134 for ( sal_Int32 i
= 0 ; i
< nLibCount
; i
++ )
135 aSeqLibNames
.getArray()[ i
] = aLibList
[ i
];
141 weld::Widget
* pErrorParent
,
142 const ScriptDocument
& rDocument
,
143 const OUString
& rLibName
,
144 const OUString
& rOldName
,
145 const OUString
& rNewName
148 if ( !rDocument
.hasModule( rLibName
, rOldName
) )
150 SAL_WARN( "basctl.basicide","basctl::RenameModule: old module name is invalid!" );
154 if ( rDocument
.hasModule( rLibName
, rNewName
) )
156 std::unique_ptr
<weld::MessageDialog
> xError(Application::CreateMessageDialog(pErrorParent
,
157 VclMessageType::Warning
, VclButtonsType::Ok
, IDEResId(RID_STR_SBXNAMEALLREADYUSED2
)));
163 if ( rNewName
.isEmpty() )
165 std::unique_ptr
<weld::MessageDialog
> xError(Application::CreateMessageDialog(pErrorParent
,
166 VclMessageType::Warning
, VclButtonsType::Ok
, IDEResId(RID_STR_BADSBXNAME
)));
171 if ( !rDocument
.renameModule( rLibName
, rOldName
, rNewName
) )
174 if (Shell
* pShell
= GetShell())
176 if (VclPtr
<ModulWindow
> pWin
= pShell
->FindBasWin(rDocument
, rLibName
, rNewName
, false, true))
178 // set new name in window
179 pWin
->SetName( rNewName
);
181 // set new module in module window
182 pWin
->SetSbModule( pWin
->GetBasic()->FindModule( rNewName
) );
185 sal_uInt16 nId
= pShell
->GetWindowId( pWin
);
186 SAL_WARN_IF( nId
== 0 , "basctl.basicide", "No entry in Tabbar!");
189 TabBar
& rTabBar
= pShell
->GetTabBar();
190 rTabBar
.SetPageText(nId
, rNewName
);
192 rTabBar
.MakeVisible(rTabBar
.GetCurPageId());
201 struct MacroExecutionData
203 ScriptDocument aDocument
;
207 :aDocument( ScriptDocument::NoDocument
)
216 DECL_STATIC_LINK( MacroExecution
, ExecuteMacroEvent
, void*, void );
219 IMPL_STATIC_LINK( MacroExecution
, ExecuteMacroEvent
, void*, p
, void )
221 MacroExecutionData
* i_pData
= static_cast<MacroExecutionData
*>(p
);
222 ENSURE_OR_RETURN_VOID( i_pData
, "wrong MacroExecutionData" );
223 // take ownership of the data
224 std::unique_ptr
< MacroExecutionData
> pData( i_pData
);
226 SAL_WARN_IF( (pData
->xMethod
->GetParent()->GetFlags() & SbxFlagBits::ExtSearch
) == SbxFlagBits::NONE
, "basctl.basicide","No EXTSEARCH!" );
228 // in case this is a document-local macro, try to protect the document's Undo Manager from
230 std::unique_ptr
< ::framework::DocumentUndoGuard
> pUndoGuard
;
231 if ( pData
->aDocument
.isDocument() )
232 pUndoGuard
.reset( new ::framework::DocumentUndoGuard( pData
->aDocument
.getDocument() ) );
234 RunMethod( pData
->xMethod
.get() );
238 OUString
ChooseMacro( const uno::Reference
< frame::XModel
>& rxLimitToDocument
,
239 const uno::Reference
< frame::XFrame
>& xDocFrame
,
244 GetExtraData()->ChoosingMacro() = true;
247 SbMethod
* pMethod
= nullptr;
249 ScopedVclPtrInstance
< MacroChooser
> pChooser( nullptr, xDocFrame
, true );
250 if ( bChooseOnly
|| !SvtModuleOptions::IsBasicIDE() )
251 pChooser
->SetMode(MacroChooser::ChooseOnly
);
253 if ( !bChooseOnly
&& rxLimitToDocument
.is() )
255 pChooser
->SetMode(MacroChooser::Recording
);
257 short nRetValue
= pChooser
->Execute();
259 GetExtraData()->ChoosingMacro() = false;
267 pMethod
= pChooser
->GetMacro();
268 if ( !pMethod
&& pChooser
->GetMode() == MacroChooser::Recording
)
269 pMethod
= pChooser
->CreateMacro();
274 SbModule
* pModule
= pMethod
->GetModule();
277 SAL_WARN( "basctl.basicide", "basctl::ChooseMacro: No Module found!" );
281 StarBASIC
* pBasic
= dynamic_cast<StarBASIC
*>(pModule
->GetParent());
284 SAL_WARN( "basctl.basicide", "basctl::ChooseMacro: No Basic found!" );
288 BasicManager
* pBasMgr
= FindBasicManager( pBasic
);
291 SAL_WARN( "basctl.basicide", "basctl::ChooseMacro: No BasicManager found!" );
296 OUString aName
= pBasic
->GetName() + "." + pModule
->GetName() + "." + pMethod
->GetName();
300 ScriptDocument
aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr
) );
301 if ( aDocument
.isDocument() )
304 aLocation
= "document" ;
306 if ( rxLimitToDocument
.is() )
308 uno::Reference
< frame::XModel
> xLimitToDocument( rxLimitToDocument
);
310 uno::Reference
< document::XEmbeddedScripts
> xScripts( rxLimitToDocument
, UNO_QUERY
);
311 if ( !xScripts
.is() )
312 { // the document itself does not support embedding scripts
313 uno::Reference
< document::XScriptInvocationContext
> xContext( rxLimitToDocument
, UNO_QUERY
);
315 xScripts
= xContext
->getScriptContainer();
317 { // but it is able to refer to a document which actually does support this
318 xLimitToDocument
.set( xScripts
, UNO_QUERY
);
319 if ( !xLimitToDocument
.is() )
321 SAL_WARN_IF(!xLimitToDocument
.is(), "basctl.basicide", "basctl::ChooseMacro: a script container which is no document!?" );
322 xLimitToDocument
= rxLimitToDocument
;
327 if ( xLimitToDocument
!= aDocument
.getDocument() )
331 std::unique_ptr
<weld::MessageDialog
> xError(Application::CreateMessageDialog(nullptr,
332 VclMessageType::Warning
, VclButtonsType::Ok
, IDEResId(RID_STR_ERRORCHOOSEMACRO
)));
340 aLocation
= "application" ;
346 aScriptURL
= "vnd.sun.star.script:" + aName
+ "?language=Basic&location=" + aLocation
;
349 if ( !rxLimitToDocument
.is() )
351 MacroExecutionData
* pExecData
= new MacroExecutionData
;
352 pExecData
->aDocument
= aDocument
;
353 pExecData
->xMethod
= pMethod
; // keep alive until the event has been processed
354 Application::PostUserEvent( LINK( nullptr, MacroExecution
, ExecuteMacroEvent
), pExecData
);
363 Sequence
< OUString
> GetMethodNames( const ScriptDocument
& rDocument
, const OUString
& rLibName
, const OUString
& rModName
)
365 Sequence
< OUString
> aSeqMethods
;
369 if ( rDocument
.getModule( rLibName
, rModName
, aOUSource
) )
371 BasicManager
* pBasMgr
= rDocument
.getBasicManager();
372 StarBASIC
* pSb
= pBasMgr
? pBasMgr
->GetLib( rLibName
) : nullptr;
373 SbModule
* pMod
= pSb
? pSb
->FindModule( rModName
) : nullptr;
376 // Only reparse modules if ScriptDocument source is out of sync
377 // with basic's Module
378 if ( !pMod
|| pMod
->GetSource() != aOUSource
)
380 xModule
= new SbModule( rModName
);
381 xModule
->SetSource32( aOUSource
);
382 pMod
= xModule
.get();
385 sal_uInt16 nCount
= pMod
->GetMethods()->Count();
386 sal_uInt16 nRealCount
= nCount
;
387 for ( sal_uInt16 i
= 0; i
< nCount
; i
++ )
389 SbMethod
* pMethod
= static_cast<SbMethod
*>(pMod
->GetMethods()->Get( i
));
390 if( pMethod
->IsHidden() )
393 aSeqMethods
.realloc( nRealCount
);
395 sal_uInt16 iTarget
= 0;
396 for ( sal_uInt16 i
= 0 ; i
< nCount
; ++i
)
398 SbMethod
* pMethod
= static_cast<SbMethod
*>(pMod
->GetMethods()->Get( i
));
399 if( pMethod
->IsHidden() )
401 SAL_WARN_IF( !pMethod
, "basctl.basicide","Method not found! (NULL)" );
402 aSeqMethods
.getArray()[ iTarget
++ ] = pMethod
->GetName();
410 ScriptDocument
const& rDocument
,
411 OUString
const& rLibName
,
412 OUString
const& rModName
,
413 OUString
const& rMethName
416 bool bHasMethod
= false;
419 if ( rDocument
.hasModule( rLibName
, rModName
) && rDocument
.getModule( rLibName
, rModName
, aOUSource
) )
421 // Check if we really need to scan the source ( again )
422 BasicManager
* pBasMgr
= rDocument
.getBasicManager();
423 StarBASIC
* pSb
= pBasMgr
? pBasMgr
->GetLib( rLibName
) : nullptr;
424 SbModule
* pMod
= pSb
? pSb
->FindModule( rModName
) : nullptr;
426 // Only reparse modules if ScriptDocument source is out of sync
427 // with basic's Module
428 if ( !pMod
|| pMod
->GetSource() != aOUSource
)
430 xModule
= new SbModule( rModName
);
431 xModule
->SetSource32( aOUSource
);
432 pMod
= xModule
.get();
434 SbxArray
* pMethods
= pMod
->GetMethods().get();
437 SbMethod
* pMethod
= static_cast<SbMethod
*>(pMethods
->Find( rMethName
, SbxClassType::Method
));
438 if ( pMethod
&& !pMethod
->IsHidden() )
446 } // namespace basctl
448 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */