Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / wizards / source / scriptforge / SF_Services.xba
blobf00ad9e94b21547d441292f5f3c903e363b06142
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
3 <script:module xmlns:script="http://openoffice.org/2000/script" script:name="SF_Services" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
4 REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
5 REM === Full documentation is available on https://help.libreoffice.org/ ===
6 REM =======================================================================================================================
8 Option Compatible
9 Option Explicit
11 &apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
12 &apos;&apos;&apos; SF_Services
13 &apos;&apos;&apos; ===========
14 &apos;&apos;&apos; Singleton class implementing the &quot;ScriptForge.Services&quot; service
15 &apos;&apos;&apos; Implemented as a usual Basic module
16 &apos;&apos;&apos; The ScriptForge framework includes
17 &apos;&apos;&apos; the current ScriptForge library
18 &apos;&apos;&apos; a number of &quot;associated&quot; libraries
19 &apos;&apos;&apos; any user/contributor extension wanting to fit into the framework
20 &apos;&apos;&apos; The methods in this module constitute the kernel of the ScriptForge framework
21 &apos;&apos;&apos; - RegisterScriptServices
22 &apos;&apos;&apos; Register for a library the list of services it implements
23 &apos;&apos;&apos; Each library in the framework must implement its own RegisterScriptServices method
24 &apos;&apos;&apos; This method consists in a series of invocations of next 2 methods
25 &apos;&apos;&apos; - RegisterService
26 &apos;&apos;&apos; Register a single service
27 &apos;&apos;&apos; - RegisterEventManager
28 &apos;&apos;&apos; Register a single event manager
29 &apos;&apos;&apos; - CreateScriptService
30 &apos;&apos;&apos; Called by user scripts to get an object giving access to a service or to the event manager
31 &apos;&apos;&apos;
32 &apos;&apos;&apos; Detailed user documentation:
33 &apos;&apos;&apos; https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_services.html?DbPAR=BASIC
34 &apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
36 REM ================================================================== EXCEPTIONS
38 Const UNKNOWNSERVICEERROR = &quot;UNKNOWNSERVICEERROR&quot; &apos; Service not found within the registered services of the given library
39 Const SERVICESNOTLOADEDERROR = &quot;SERVICESNOTLOADEDERROR&quot; &apos; Failure during the registering of the services of the given library
40 Const UNKNOWNFILEERROR = &quot;UNKNOWNFILEERROR&quot; &apos; Source file does not exist
42 REM ============================================================== PUBLIC MEMBERS
44 &apos; Defines an entry in in the services dictionary
45 Type _Service
46 ServiceName As String
47 ServiceType As Integer
48 &apos; 0 Undefined
49 &apos; 1 Basic module
50 &apos; 2 Method reference as a string
51 ServiceReference As Object
52 ServiceMethod As String
53 EventManager As Boolean &apos; True if registered item is an event manager
54 End Type
56 Private vServicesArray As Variant &apos; List of services registered by a library
58 REM ============================================================== PUBLIC METHODS
60 REM -----------------------------------------------------------------------------
61 Public Function CreateScriptService(Optional ByRef Service As Variant _
62 , ParamArray pvArgs As Variant _
63 ) As Variant
64 &apos;&apos;&apos; Create access to the services of a library for the benefit of a user script
65 &apos;&apos;&apos; A service is to understand either:
66 &apos;&apos;&apos; as a set of methods gathered in a Basic standard module
67 &apos;&apos;&apos; or a set of methods and properties gathered in a Basic class module
68 &apos;&apos;&apos; Args:
69 &apos;&apos;&apos; Service: the name of the service in 2 parts &quot;library.service&quot;
70 &apos;&apos;&apos; The library is a Basic library that must exist in the GlobalScope
71 &apos;&apos;&apos; (default = &quot;ScriptForge&quot;)
72 &apos;&apos;&apos; The service is one of the services registered by the library
73 &apos;&apos;&apos; thru the RegisterScriptServices() routine
74 &apos;&apos;&apos; pvArgs: a set of arguments passed to the constructor of the service
75 &apos;&apos;&apos; This is only possible if the service refers to a Basic class module
76 &apos;&apos;&apos; Returns
77 &apos;&apos;&apos; The object containing either the reference of the Basic module
78 &apos;&apos;&apos; or of the Basic class instance
79 &apos;&apos;&apos; Both are Basic objects
80 &apos;&apos;&apos; Returns Nothing if an error occurred.
81 &apos;&apos;&apos; ==&gt;&gt; NOTE: The error can be within the user script creating the new class instance
82 &apos;&apos;&apos; Exceptions:
83 &apos;&apos;&apos; SERVICESNOTLOADEDERROR RegisterScriptService probable failure
84 &apos;&apos;&apos; UNKNOWNSERVICEERROR Service not found
85 &apos;&apos;&apos; Examples
86 &apos;&apos;&apos; CreateScriptService(&quot;Array&quot;)
87 &apos;&apos;&apos; =&gt; Refers to ScriptForge.Array or SF_Array
88 &apos;&apos;&apos; CreateScriptService(&quot;ScriptForge.Dictionary&quot;)
89 &apos;&apos;&apos; =&gt; Returns a new empty dictionary; &quot;ScriptForge.&quot; is optional
90 &apos;&apos;&apos; CreateScriptService(&quot;SFDocuments.Calc&quot;)
91 &apos;&apos;&apos; =&gt; Refers to the Calc service, implemented in the SFDocuments library
92 &apos;&apos;&apos; CreateScriptService(&quot;Dialog&quot;, dlgName)
93 &apos;&apos;&apos; =&gt; Returns a Dialog instance referring to the dlgName dialog
94 &apos;&apos;&apos; CreateScriptService(&quot;SFDocuments.Event&quot;, oEvent)
95 &apos;&apos;&apos; =&gt; Refers to the Document service instance, implemented in the SFDocuments library, having triggered the event
97 Dim vScriptService As Variant &apos; Return value
98 Dim vServiceItem As Variant &apos; A single service (see _Service type definition)
99 Dim vServicesList As Variant &apos; Output of RegisterScriptServices
100 Dim vSplit As Variant &apos; Array to split argument in
101 Dim sLibrary As String &apos; Library part of the argument
102 Dim sService As String &apos; Service part of the argument
103 Dim vLibrary As Variant &apos; Dictionary of libraries
104 Dim vService As Variant &apos; An individual service object
105 Const cstThisSub = &quot;SF_Services.CreateScriptService&quot;
106 Const cstSubArgs = &quot;Service, arg0[, arg1] ...&quot;
108 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
109 Set vScriptService = Nothing
111 Check:
112 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
113 If Not SF_Utils._Validate(Service, &quot;Service&quot;, V_STRING) Then GoTo Catch
114 If Len(Service) = 0 Then GoTo CatchNotFound
115 End If
117 Try:
118 &apos; Initialize the list of services when CreateScriptService called for the very 1st time
119 If IsEmpty(_SF_.ServicesList) Then _SF_.ServicesList = SF_Services._NewDictionary()
121 &apos; Simple parsing of argument
122 vSplit = Split(Service, &quot;.&quot;)
123 If UBound(vSplit) &gt; 1 Then GoTo CatchNotFound
124 If UBound(vSplit) = 0 Then
125 sLibrary = &quot;ScriptForge&quot; &apos; Yes, the default value !
126 sService = vSplit(0)
127 &apos; Accept other default values for associated libraries
128 Select Case LCase(sService)
129 Case &quot;document&quot;, &quot;calc&quot;, &quot;writer&quot;, &quot;base&quot;, &quot;formdocument&quot;, &quot;documentevent&quot;, &quot;formevent&quot;
130 sLibrary = &quot;SFDocuments&quot;
131 Case &quot;dialog&quot;, &quot;dialogevent&quot;, &quot;newdialog&quot;
132 sLibrary = &quot;SFDialogs&quot;
133 Case &quot;database&quot;, &quot;datasheet&quot; : sLibrary = &quot;SFDatabases&quot;
134 Case &quot;unittest&quot; : sLibrary = &quot;SFUnitTests&quot;
135 Case &quot;menu&quot;, &quot;popupmenu&quot;, &quot;toolbar&quot;, &quot;toolbarbutton&quot;
136 sLibrary = &quot;SFWidgets&quot;
137 Case Else
138 End Select
139 Else
140 sLibrary = vSplit(0)
141 sService = vSplit(1)
142 End If
144 With _SF_.ServicesList
146 &apos; Load the set of services from the library, if not yet done
147 If Not .Exists(sLibrary) Then
148 If Not SF_Services._LoadLibraryServices(sLibrary) Then GoTo CatchNotLoaded
149 End If
151 &apos; Find and return the requested service
152 vServicesList = .Item(sLibrary)
153 If Not vServicesList.Exists(sService) Then GoTo CatchNotFound
154 vServiceItem = vServicesList.Item(sService)
155 Select Case vServiceItem.ServiceType
156 Case 1 &apos; Basic module
157 vScriptService = vServiceItem.ServiceReference
158 Case 2 &apos; Method to call
159 If sLibrary = &quot;ScriptForge&quot; Then &apos; Direct call
160 Select Case UCase(sService)
161 Case &quot;DICTIONARY&quot; : vScriptService = SF_Services._NewDictionary()
162 Case &quot;L10N&quot; : vScriptService = SF_Services._NewL10N(pvArgs)
163 Case &quot;TIMER&quot; : vScriptService = SF_Services._NewTimer(pvArgs)
164 Case Else
165 End Select
166 Else &apos; Call via script provider
167 Set vService = SF_Session._GetScript(&quot;Basic&quot;, SF_Session.SCRIPTISAPPLICATION, vServiceItem.ServiceMethod)
168 vScriptService = vService.Invoke(Array(pvArgs()), Array(), Array())
169 End If
170 Case Else
171 End Select
173 End With
175 Finally:
176 CreateScriptService = vScriptService
177 SF_Utils._ExitFunction(cstThisSub)
178 Exit Function
179 Catch:
180 GoTo Finally
181 CatchNotFound:
182 SF_Exception.RaiseFatal(UNKNOWNSERVICEERROR, &quot;Service&quot;, Service, sLibrary, sService)
183 GoTo Finally
184 CatchNotLoaded:
185 SF_Exception.RaiseFatal(SERVICESNOTLOADEDERROR, &quot;Service&quot;, Service, sLibrary)
186 GoTo Finally
187 End Function &apos; ScriptForge.SF_Services.CreateScriptService
189 REM -----------------------------------------------------------------------------
190 Public Function RegisterEventManager(Optional ByVal ServiceName As Variant _
191 , Optional ByRef ServiceReference As Variant _
192 ) As Boolean
193 &apos;&apos;&apos; Register into ScriptForge a new event entry for the library
194 &apos;&apos;&apos; from which this method is called
195 &apos;&apos;&apos; MUST BE CALLED ONLY from a specific RegisterScriptServices() method
196 &apos;&apos;&apos; Usually the method should be called only once by library
197 &apos;&apos;&apos; Args:
198 &apos;&apos;&apos; ServiceName: the name of the service as a string. It the service exists
199 &apos;&apos;&apos; already for the library the method overwrites the existing entry
200 &apos;&apos;&apos; ServiceReference: the function which will identify the source of the triggered event
201 &apos;&apos;&apos; something like: &quot;libraryname.modulename.function&quot;
202 &apos;&apos;&apos; Returns:
203 &apos;&apos;&apos; True if successful
204 &apos;&apos;&apos; Example:
205 &apos;&apos;&apos; &apos; Code snippet stored in a module contained in the SFDocuments library
206 &apos;&apos;&apos; Sub RegisterScriptServices()
207 &apos;&apos;&apos; &apos; Register the events manager of the library
208 &apos;&apos;&apos; RegisterEventManager(&quot;DocumentEvent&quot;, &quot;SFDocuments.SF_Register._EventManager&quot;)
209 &apos;&apos;&apos; End Sub
210 &apos;&apos;&apos; &apos; Code snippet stored in a user script
211 &apos;&apos;&apos; Sub Trigger(poEvent As Object) &apos; Triggered by a DOCUMENTEVENT event
212 &apos;&apos;&apos; Dim myDoc As Object
213 &apos;&apos;&apos; &apos; To get the document concerned by the event:
214 &apos;&apos;&apos; Set myDoc = CreateScriptService(&quot;SFDocuments.DocumentEvent&quot;, poEvent)
215 &apos;&apos;&apos; End Sub
217 Dim bRegister As Boolean &apos; Return value
218 Const cstThisSub = &quot;SF_Services.RegisterEventManager&quot;
219 Const cstSubArgs = &quot;ServiceName, ServiceReference&quot;
221 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
222 bRegister = False
224 Check:
225 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
226 If Not SF_Utils._Validate(ServiceName, &quot;ServiceName&quot;, V_STRING) Then GoTo Finally
227 If Not SF_Utils._Validate(ServiceReference, &quot;ServiceReference&quot;,V_STRING) Then GoTo Finally
228 End If
230 Try:
231 bRegister = _AddToServicesArray(ServiceName, ServiceReference, True)
233 Finally:
234 RegisterEventManager = bRegister
235 SF_Utils._ExitFunction(cstThisSub)
236 Exit Function
237 Catch:
238 GoTo Finally
239 End Function &apos; ScriptForge.SF_Services.RegisterEventManager
241 REM -----------------------------------------------------------------------------
242 Public Function RegisterService(Optional ByVal ServiceName As Variant _
243 , Optional ByRef ServiceReference As Variant _
244 ) As Boolean
245 &apos;&apos;&apos; Register into ScriptForge a new service entry for the library
246 &apos;&apos;&apos; from which this method is called
247 &apos;&apos;&apos; MUST BE CALLED ONLY from a specific RegisterScriptServices() method
248 &apos;&apos;&apos; Args:
249 &apos;&apos;&apos; ServiceName: the name of the service as a string. It the service exists
250 &apos;&apos;&apos; already for the library the method overwrites the existing entry
251 &apos;&apos;&apos; ServiceReference: either
252 &apos;&apos;&apos; - the Basic module that implements the methods of the service
253 &apos;&apos;&apos; something like: GlobalScope.Library.Module
254 &apos;&apos;&apos; - an instance of the class implementing the methods and properties of the service
255 &apos;&apos;&apos; something like: &quot;libraryname.modulename.function&quot;
256 &apos;&apos;&apos; Returns:
257 &apos;&apos;&apos; True if successful
259 Dim bRegister As Boolean &apos; Return value
260 Const cstThisSub = &quot;SF_Services.RegisterService&quot;
261 Const cstSubArgs = &quot;ServiceName, ServiceReference&quot;
263 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
264 bRegister = False
266 Check:
267 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
268 If Not SF_Utils._Validate(ServiceName, &quot;ServiceName&quot;, V_STRING) Then GoTo Finally
269 If Not SF_Utils._Validate(ServiceReference, &quot;ServiceReference&quot;, Array(V_STRING, V_OBJECT)) Then GoTo Finally
270 End If
272 Try:
273 bRegister = _AddToServicesArray(ServiceName, ServiceReference, False)
275 Finally:
276 RegisterService = bRegister
277 SF_Utils._ExitFunction(cstThisSub)
278 Exit Function
279 Catch:
280 GoTo Finally
281 End Function &apos; ScriptForge.SF_Services.RegisterService
283 REM -----------------------------------------------------------------------------
284 Public Sub RegisterScriptServices() As Variant
285 &apos;&apos;&apos; Register into ScriptForge the list of the services implemented by the current library
286 &apos;&apos;&apos; Each library pertaining to the framework must implement its own version of this method
287 &apos;&apos;&apos; This method may be stored in any standard (i.e. not class-) module
288 &apos;&apos;&apos;
289 &apos;&apos;&apos; Each individual service is registered by calling the RegisterService() method
290 &apos;&apos;&apos;
291 &apos;&apos;&apos; The current version is given as an example
292 &apos;&apos;&apos;
293 With GlobalScope.ScriptForge.SF_Services
294 .RegisterService(&quot;Array&quot;, GlobalScope.ScriptForge.SF_Array) &apos; Reference to the Basic module
295 .RegisterService(&quot;Dictionary&quot;, &quot;ScriptForge.SF_Services._NewDictionary&quot;) &apos; Reference to the function initializing the service
296 .RegisterService(&quot;Exception&quot;, GlobalScope.ScriptForge.SF_Exception)
297 .RegisterService(&quot;FileSystem&quot;, GlobalScope.ScriptForge.SF_FileSystem)
298 .RegisterService(&quot;L10N&quot;, &quot;ScriptForge.SF_Services._NewL10N&quot;)
299 .RegisterService(&quot;Platform&quot;, GlobalScope.ScriptForge.SF_Platform)
300 .RegisterService(&quot;Region&quot;, GlobalScope.ScriptForge.SF_Region)
301 .RegisterService(&quot;Session&quot;, GlobalScope.ScriptForge.SF_Session)
302 .RegisterService(&quot;String&quot;, GlobalScope.ScriptForge.SF_String)
303 .RegisterService(&quot;Timer&quot;, &quot;ScriptForge.SF_Services._NewTimer&quot;)
304 .RegisterService(&quot;UI&quot;, GlobalScope.ScriptForge.SF_UI)
305 &apos;TODO
306 End With
308 End Sub &apos; ScriptForge.SF_Services.RegisterScriptServices
310 REM =========================================================== PRIVATE FUNCTIONS
312 REM -----------------------------------------------------------------------------
313 Private Function _AddToServicesArray(ByVal psServiceName As String _
314 , ByRef pvServiceReference As Variant _
315 , ByVal pbEvent As Boolean _
316 ) As Boolean
317 &apos;&apos;&apos; Add the arguments as an additional row in vServicesArray (Public variable)
318 &apos;&apos;&apos; Called from RegisterService and RegisterEvent methods
320 Dim bRegister As Boolean &apos; Return value
321 Dim lMax As Long &apos; Number of rows in vServicesArray
323 bRegister = False
325 Check:
326 &apos; Ignore when method is not called from RegisterScriptServices()
327 If IsEmpty(vServicesArray) Or IsNull(vServicesArray) Or Not IsArray(vServicesArray) Then GoTo Finally
329 Try:
330 lMax = UBound(vServicesArray, 1) + 1
331 If lMax &lt;= 0 Then
332 ReDim vServicesArray(0 To 0, 0 To 2)
333 Else
334 ReDim Preserve vServicesArray(0 To lMax, 0 To 2)
335 End If
336 vServicesArray(lMax, 0) = psServiceName
337 vServicesArray(lMax, 1) = pvServiceReference
338 vServicesArray(lMax, 2) = pbEvent
339 bRegister = True
341 Finally:
342 _AddToServicesArray = bRegister
343 Exit Function
344 End Function &apos; ScriptForge.SF_Services._AddToServicesArray
346 REM -----------------------------------------------------------------------------
347 Private Function _FindModuleFromMethod(ByVal psLibrary As String _
348 , ByVal psMethod As String _
349 ) As String
350 &apos;&apos;&apos; Find in the given library the name of the module containing
351 &apos;&apos;&apos; the method given as 2nd argument (usually RegisterScriptServices)
352 &apos;&apos;&apos; Args:
353 &apos;&apos;&apos; psLibrary: the name of the Basic library
354 &apos;&apos;&apos; psMethod: the method to locate
355 &apos;&apos;&apos; Returns:
356 &apos;&apos;&apos; The name of the module or a zero-length string if not found
358 Dim vCategories As Variant &apos; &quot;user&quot; or &quot;share&quot; library categories
359 Dim sCategory As String
360 Dim vLanguages As Variant &apos; &quot;Basic&quot;, &quot;Python&quot;, ... programming languages
361 Dim sLanguage As String
362 Dim vLibraries As Variant &apos; Library names
363 Dim sLibrary As String
364 Dim vModules As Variant &apos; Module names
365 Dim sModule As String &apos; Return value
366 Dim vMethods As Variant &apos; Method/properties/subs/functions
367 Dim sMethod As String
368 Dim oRoot As Object &apos; com.sun.star.script.browse.BrowseNodeFactory
369 Dim i As Integer, j As Integer, k As Integer, l As Integer, m As Integer
371 _FindModuleFromMethod = &quot;&quot;
372 Set oRoot = SF_Utils._GetUNOService(&quot;BrowseNodeFactory&quot;).createView(com.sun.star.script.browse.BrowseNodeFactoryViewTypes.MACROORGANIZER)
374 &apos; Exploration is done via tree nodes
375 If Not IsNull(oRoot) Then
376 If oRoot.hasChildNodes() Then
377 vCategories = oRoot.getChildNodes()
378 For i = 0 To UBound(vCategories)
379 sCategory = vCategories(i).getName()
380 &apos; Consider &quot;My macros &amp; Dialogs&quot; and &quot;LibreOffice Macros &amp; Dialogs&quot; only
381 If sCategory = &quot;user&quot; Or sCategory = &quot;share&quot; Then
382 If vCategories(i).hasChildNodes() Then
383 vLanguages = vCategories(i).getChildNodes()
384 For j = 0 To UBound(vLanguages)
385 sLanguage = vLanguages(j).getName()
386 &apos; Consider Basic libraries only
387 If sLanguage = &quot;Basic&quot; Then
388 If vLanguages(j).hasChildNodes() Then
389 vLibraries = vLanguages(j).getChildNodes()
390 For k = 0 To UBound(vLibraries)
391 sLibrary = vLibraries(k).getName()
392 &apos; Consider the given library only
393 If sLibrary = psLibrary Then
394 If vLibraries(k).hasChildNodes() Then
395 vModules = vLibraries(k).getChildNodes()
396 For l = 0 To UBound(vModules)
397 sModule = vModules(l).getName()
398 &apos; Check if the module contains the targeted method
399 If vModules(l).hasChildNodes() Then
400 vMethods = vModules(l).getChildNodes()
401 For m = 0 To UBound(vMethods)
402 sMethod = vMethods(m).getName()
403 If sMethod = psMethod Then
404 _FindModuleFromMethod = sModule
405 Exit Function
406 End If
407 Next m
408 End If
409 Next l
410 End If
411 End If
412 Next k
413 End If
414 End If
415 Next j
416 End If
417 End If
418 Next i
419 End If
420 End If
422 End Function &apos; ScriptForge.SF_Services._FindModuleFromMethod
424 REM -----------------------------------------------------------------------------
425 Private Function _LoadLibraryServices(ByVal psLibrary As String) As Boolean
426 &apos;&apos;&apos; Execute psLibrary.RegisterScriptServices() and load its services into the persistent storage
427 &apos;&apos;&apos; Args:
428 &apos;&apos;&apos; psLibrary: the name of the Basic library
429 &apos;&apos;&apos; Library will be loaded if not yet done
430 &apos;&apos;&apos; Returns:
431 &apos;&apos;&apos; True if success
432 &apos;&apos;&apos; The list of services is loaded directly into the persistent storage
435 Dim vServicesList As Variant &apos; Dictionary of services
436 Dim vService As Variant &apos; Single service entry in dictionary
437 Dim vServiceItem As Variant &apos; Single service in vServicesArray
438 Dim sModule As String &apos; Name of module containing the RegisterScriptServices method
439 Dim i As Long
440 Const cstRegister = &quot;RegisterScriptServices&quot;
442 Try:
443 _LoadLibraryServices = False
445 vServicesArray = Array()
447 If psLibrary = &quot;ScriptForge&quot; Then
448 &apos; Direct call
449 ScriptForge.SF_Services.RegisterScriptServices()
450 Else
451 &apos; Register services via script provider
452 If GlobalScope.BasicLibraries.hasByName(psLibrary) Then
453 If Not GlobalScope.BasicLibraries.isLibraryLoaded(psLibrary) Then
454 GlobalScope.BasicLibraries.LoadLibrary(psLibrary)
455 End If
456 Else
457 GoTo Finally
458 End If
459 sModule = SF_Services._FindModuleFromMethod(psLibrary, cstRegister)
460 If Len(sModule) = 0 Then GoTo Finally
461 SF_Session.ExecuteBasicScript(, psLibrary &amp; &quot;.&quot; &amp; sModule &amp; &quot;.&quot; &amp; cstRegister)
462 End If
464 &apos; Store in persistent storage
465 &apos; - Create list of services for the current library
466 Set vServicesList = SF_Services._NewDictionary()
467 For i = 0 To UBound(vServicesArray, 1)
468 Set vService = New _Service
469 With vService
470 .ServiceName = vServicesArray(i, 0)
471 vServiceItem = vServicesArray(i, 1)
472 If VarType(vServiceItem) = V_STRING Then
473 .ServiceType = 2
474 .ServiceMethod = vServiceItem
475 Set .ServiceReference = Nothing
476 Else &apos; OBJECT
477 .ServiceType = 1
478 .ServiceMethod = &quot;&quot;
479 Set .ServiceReference = vServiceItem
480 End If
481 .EventManager = vServicesArray(i, 2)
482 End With
483 vServicesList.Add(vServicesArray(i, 0), vService)
484 Next i
485 &apos; - Add the new dictionary to the persistent dictionary
486 _SF_.ServicesList.Add(psLibrary, vServicesList)
487 _LoadLibraryServices = True
488 vServicesArray = Empty
490 Finally:
491 Exit Function
492 End Function &apos; ScriptForge.SF_Services._LoadLibraryServices
494 REM -----------------------------------------------------------------------------
495 Public Function _NewDictionary() As Variant
496 &apos;&apos;&apos; Create a new instance of the SF_Dictionary class
497 &apos;&apos;&apos; Returns: the instance or Nothing
499 Dim oDict As Variant
501 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
503 Check:
505 Try:
506 Set oDict = New SF_Dictionary
507 Set oDict.[Me] = oDict
509 Finally:
510 Set _NewDictionary = oDict
511 Exit Function
512 Catch:
513 Set oDict = Nothing
514 GoTo Finally
515 End Function &apos; ScriptForge.SF_Services._NewDictionary
517 REM -----------------------------------------------------------------------------
518 Public Function _NewL10N(Optional ByVal pvArgs As Variant) As Variant
519 &apos;&apos;&apos; Create a new instance of the SF_L10N class
520 &apos; Args:
521 &apos;&apos;&apos; FolderName: the folder containing the PO files in SF_FileSystem.FileNaming notation
522 &apos;&apos;&apos; Locale: locale of user session (default) or any other valid la{nguage]-CO[UNTRY] combination
523 &apos;&apos;&apos; The country part is optional. Valid are f.i. &quot;fr&quot;, &quot;fr-CH&quot;, &quot;en-US&quot;
524 &apos;&apos;&apos; Encoding: The character set that should be used
525 &apos;&apos;&apos; Use one of the Names listed in https://www.iana.org/assignments/character-sets/character-sets.xhtml
526 &apos;&apos;&apos; Note that LibreOffice probably does not implement all existing sets
527 &apos;&apos;&apos; Default = UTF-8
528 &apos;&apos;&apos; Locale2: fallback Locale to select if Locale po file does not exist (typically &quot;en-US&quot;)
529 &apos;&apos;&apos; Encoding2: Encoding of the 2nd Locale file
530 &apos;&apos;&apos; Returns: the instance or Nothing
531 &apos;&apos;&apos; Exceptions:
532 &apos;&apos;&apos; UNKNOWNFILEERROR The PO file does not exist
534 Dim oL10N As Variant &apos; Return value
535 Dim sFolderName As String &apos; Folder containing the PO files
536 Dim sLocale As String &apos; Passed argument or that of the user session
537 Dim sLocale2 As String &apos; Alias for Locale2
538 Dim oLocale As Variant &apos; com.sun.star.lang.Locale
539 Dim sPOFile As String &apos; PO file must exist
540 Dim sEncoding As String &apos; Alias for Encoding
541 Dim sEncoding2 As String &apos; Alias for Encoding2
543 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
545 Check:
546 If IsMissing(pvArgs) Then pvArgs = Array()
547 sPOFile = &quot;&quot;
548 sEncoding = &quot;&quot;
549 If UBound(pvArgs) &gt;= 0 Then
550 If Not SF_Utils._ValidateFile(pvArgs(0), &quot;Folder (Arg0)&quot;, , True) Then GoTo Catch
551 sFolderName = pvArgs(0)
552 sLocale = &quot;&quot;
553 If UBound(pvArgs) &gt;= 1 Then
554 If Not SF_Utils._Validate(pvArgs(1), &quot;Locale (Arg1)&quot;, V_STRING) Then GoTo Catch
555 sLocale = pvArgs(1)
556 End If
557 If Len(sLocale) = 0 Then &apos; Called from Python, the Locale argument may be the zero-length string
558 Set oLocale = SF_Utils._GetUNOService(&quot;OfficeLocale&quot;)
559 sLocale = oLocale.Language &amp; &quot;-&quot; &amp; oLocale.Country
560 End If
561 If UBound(pvArgs) &gt;= 2 Then
562 If IsMissing(pvArgs(2)) Or IsEmpty(pvArgs(2)) Then pvArgs(2) = &quot;UTF-8&quot;
563 If Not SF_Utils._Validate(pvArgs(2), &quot;Encoding (Arg2)&quot;, V_STRING) Then GoTo Catch
564 sEncoding = pvArgs(2)
565 Else
566 sEncoding = &quot;UTF-8&quot;
567 End If
568 sLocale2 = &quot;&quot;
569 If UBound(pvArgs) &gt;= 3 Then
570 If Not SF_Utils._Validate(pvArgs(3), &quot;Locale2 (Arg3)&quot;, V_STRING) Then GoTo Catch
571 sLocale2 = pvArgs(3)
572 End If
573 If UBound(pvArgs) &gt;= 4 Then
574 If Not SF_Utils._Validate(pvArgs(4), &quot;Encoding2 (Arg4)&quot;, V_STRING) Then GoTo Catch
575 sEncoding2 = pvArgs(4)
576 Else
577 sEncoding2 = &quot;UTF-8&quot;
578 End If
579 If Len(sFolderName) &gt; 0 Then
580 sPOFile = SF_FileSystem.BuildPath(sFolderName, sLocale &amp; &quot;.po&quot;)
581 If Not SF_FileSystem.FileExists(sPOFile) Then
582 If Len(sLocale2) = 0 Then GoTo CatchNotExists &apos; No fallback =&gt; error
583 &apos; Try the fallback
584 sPOFile = SF_FileSystem.BuildPath(sFolderName, sLocale2 &amp; &quot;.po&quot;)
585 If Not SF_FileSystem.FileExists(sPOFile) Then GoTo CatchNotExists
586 sEncoding = sEncoding2
587 End If
588 End If
589 End If
591 Try:
592 Set oL10N = New SF_L10N
593 Set oL10N.[Me] = oL10N
594 oL10N._Initialize(sPOFile, sEncoding)
596 Finally:
597 Set _NewL10N = oL10N
598 Exit Function
599 Catch:
600 Set oL10N = Nothing
601 GoTo Finally
602 CatchNotExists:
603 SF_Exception.RaiseFatal(UNKNOWNFILEERROR, &quot;FileName&quot;, sPOFile)
604 GoTo Finally
605 End Function &apos; ScriptForge.SF_Services._NewL10N
607 REM -----------------------------------------------------------------------------
608 Public Function _NewTimer(Optional ByVal pvArgs As Variant) As Variant
609 &apos;&apos;&apos; Create a new instance of the SF_Timer class
610 &apos;&apos;&apos; Args:
611 &apos;&apos;&apos; [0] : If True, start the timer immediately
612 &apos;&apos;&apos; Returns: the instance or Nothing
614 Dim oTimer As Variant &apos; Return value
615 Dim bStart As Boolean &apos; Automatic start ?
617 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
619 Check:
620 If IsMissing(pvArgs) Then pvArgs = Array()
621 If UBound(pvArgs) &lt; 0 Then
622 bStart = False
623 Else
624 If Not SF_Utils._Validate(pvArgs(0), &quot;Start (Arg0)&quot;, V_BOOLEAN) Then GoTo Catch
625 bStart = pvArgs(0)
626 End If
627 Try:
628 Set oTimer = New SF_Timer
629 Set oTimer.[Me] = oTimer
630 If bStart Then oTimer.Start()
632 Finally:
633 Set _NewTimer = oTimer
634 Exit Function
635 Catch:
636 Set oTimer = Nothing
637 GoTo Finally
638 End Function &apos; ScriptForge.SF_Services._NewTimer
640 REM ============================================== END OF SCRIPTFORGE.SF_SERVICES
641 </script:module>