calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / wizards / source / scriptforge / SF_Services.xba
blobb72298ea3046c81e222532b69da79fd219884766
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;documentevent&quot;, &quot;formevent&quot;
130 sLibrary = &quot;SFDocuments&quot;
131 Case &quot;dialog&quot;, &quot;dialogevent&quot; : sLibrary = &quot;SFDialogs&quot;
132 Case &quot;database&quot;, &quot;datasheet&quot; : sLibrary = &quot;SFDatabases&quot;
133 Case &quot;unittest&quot; : sLibrary = &quot;SFUnitTests&quot;
134 Case &quot;menu&quot;, &quot;popupmenu&quot; : sLibrary = &quot;SFWidgets&quot;
135 Case Else
136 End Select
137 Else
138 sLibrary = vSplit(0)
139 sService = vSplit(1)
140 End If
142 With _SF_.ServicesList
144 &apos; Load the set of services from the library, if not yet done
145 If Not .Exists(sLibrary) Then
146 If Not SF_Services._LoadLibraryServices(sLibrary) Then GoTo CatchNotLoaded
147 End If
149 &apos; Find and return the requested service
150 vServicesList = .Item(sLibrary)
151 If Not vServicesList.Exists(sService) Then GoTo CatchNotFound
152 vServiceItem = vServicesList.Item(sService)
153 Select Case vServiceItem.ServiceType
154 Case 1 &apos; Basic module
155 vScriptService = vServiceItem.ServiceReference
156 Case 2 &apos; Method to call
157 If sLibrary = &quot;ScriptForge&quot; Then &apos; Direct call
158 Select Case UCase(sService)
159 Case &quot;DICTIONARY&quot; : vScriptService = SF_Services._NewDictionary()
160 Case &quot;L10N&quot; : vScriptService = SF_Services._NewL10N(pvArgs)
161 Case &quot;TIMER&quot; : vScriptService = SF_Services._NewTimer(pvArgs)
162 Case Else
163 End Select
164 Else &apos; Call via script provider
165 Set vService = SF_Session._GetScript(&quot;Basic&quot;, SF_Session.SCRIPTISAPPLICATION, vServiceItem.ServiceMethod)
166 vScriptService = vService.Invoke(Array(pvArgs()), Array(), Array())
167 End If
168 Case Else
169 End Select
171 End With
173 Finally:
174 CreateScriptService = vScriptService
175 SF_Utils._ExitFunction(cstThisSub)
176 Exit Function
177 Catch:
178 GoTo Finally
179 CatchNotFound:
180 SF_Exception.RaiseFatal(UNKNOWNSERVICEERROR, &quot;Service&quot;, Service, sLibrary, sService)
181 GoTo Finally
182 CatchNotLoaded:
183 SF_Exception.RaiseFatal(SERVICESNOTLOADEDERROR, &quot;Service&quot;, Service, sLibrary)
184 GoTo Finally
185 End Function &apos; ScriptForge.SF_Services.CreateScriptService
187 REM -----------------------------------------------------------------------------
188 Public Function RegisterEventManager(Optional ByVal ServiceName As Variant _
189 , Optional ByRef ServiceReference As Variant _
190 ) As Boolean
191 &apos;&apos;&apos; Register into ScriptForge a new event entry for the library
192 &apos;&apos;&apos; from which this method is called
193 &apos;&apos;&apos; MUST BE CALLED ONLY from a specific RegisterScriptServices() method
194 &apos;&apos;&apos; Usually the method should be called only once by library
195 &apos;&apos;&apos; Args:
196 &apos;&apos;&apos; ServiceName: the name of the service as a string. It the service exists
197 &apos;&apos;&apos; already for the library the method overwrites the existing entry
198 &apos;&apos;&apos; ServiceReference: the function which will identify the source of the triggered event
199 &apos;&apos;&apos; something like: &quot;libraryname.modulename.function&quot;
200 &apos;&apos;&apos; Returns:
201 &apos;&apos;&apos; True if successful
202 &apos;&apos;&apos; Example:
203 &apos;&apos;&apos; &apos; Code snippet stored in a module contained in the SFDocuments library
204 &apos;&apos;&apos; Sub RegisterScriptServices()
205 &apos;&apos;&apos; &apos; Register the events manager of the library
206 &apos;&apos;&apos; RegisterEventManager(&quot;DocumentEvent&quot;, &quot;SFDocuments.SF_Register._EventManager&quot;)
207 &apos;&apos;&apos; End Sub
208 &apos;&apos;&apos; &apos; Code snippet stored in a user script
209 &apos;&apos;&apos; Sub Trigger(poEvent As Object) &apos; Triggered by a DOCUMENTEVENT event
210 &apos;&apos;&apos; Dim myDoc As Object
211 &apos;&apos;&apos; &apos; To get the document concerned by the event:
212 &apos;&apos;&apos; Set myDoc = CreateScriptService(&quot;SFDocuments.DocumentEvent&quot;, poEvent)
213 &apos;&apos;&apos; End Sub
215 Dim bRegister As Boolean &apos; Return value
216 Const cstThisSub = &quot;SF_Services.RegisterEventManager&quot;
217 Const cstSubArgs = &quot;ServiceName, ServiceReference&quot;
219 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
220 bRegister = False
222 Check:
223 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
224 If Not SF_Utils._Validate(ServiceName, &quot;ServiceName&quot;, V_STRING) Then GoTo Finally
225 If Not SF_Utils._Validate(ServiceReference, &quot;ServiceReference&quot;,V_STRING) Then GoTo Finally
226 End If
228 Try:
229 bRegister = _AddToServicesArray(ServiceName, ServiceReference, True)
231 Finally:
232 RegisterEventManager = bRegister
233 SF_Utils._ExitFunction(cstThisSub)
234 Exit Function
235 Catch:
236 GoTo Finally
237 End Function &apos; ScriptForge.SF_Services.RegisterEventManager
239 REM -----------------------------------------------------------------------------
240 Public Function RegisterService(Optional ByVal ServiceName As Variant _
241 , Optional ByRef ServiceReference As Variant _
242 ) As Boolean
243 &apos;&apos;&apos; Register into ScriptForge a new service entry for the library
244 &apos;&apos;&apos; from which this method is called
245 &apos;&apos;&apos; MUST BE CALLED ONLY from a specific RegisterScriptServices() method
246 &apos;&apos;&apos; Args:
247 &apos;&apos;&apos; ServiceName: the name of the service as a string. It the service exists
248 &apos;&apos;&apos; already for the library the method overwrites the existing entry
249 &apos;&apos;&apos; ServiceReference: either
250 &apos;&apos;&apos; - the Basic module that implements the methods of the service
251 &apos;&apos;&apos; something like: GlobalScope.Library.Module
252 &apos;&apos;&apos; - an instance of the class implementing the methods and properties of the service
253 &apos;&apos;&apos; something like: &quot;libraryname.modulename.function&quot;
254 &apos;&apos;&apos; Returns:
255 &apos;&apos;&apos; True if successful
257 Dim bRegister As Boolean &apos; Return value
258 Const cstThisSub = &quot;SF_Services.RegisterService&quot;
259 Const cstSubArgs = &quot;ServiceName, ServiceReference&quot;
261 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
262 bRegister = False
264 Check:
265 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
266 If Not SF_Utils._Validate(ServiceName, &quot;ServiceName&quot;, V_STRING) Then GoTo Finally
267 If Not SF_Utils._Validate(ServiceReference, &quot;ServiceReference&quot;, Array(V_STRING, V_OBJECT)) Then GoTo Finally
268 End If
270 Try:
271 bRegister = _AddToServicesArray(ServiceName, ServiceReference, False)
273 Finally:
274 RegisterService = bRegister
275 SF_Utils._ExitFunction(cstThisSub)
276 Exit Function
277 Catch:
278 GoTo Finally
279 End Function &apos; ScriptForge.SF_Services.RegisterService
281 REM -----------------------------------------------------------------------------
282 Public Sub RegisterScriptServices() As Variant
283 &apos;&apos;&apos; Register into ScriptForge the list of the services implemented by the current library
284 &apos;&apos;&apos; Each library pertaining to the framework must implement its own version of this method
285 &apos;&apos;&apos; This method may be stored in any standard (i.e. not class-) module
286 &apos;&apos;&apos;
287 &apos;&apos;&apos; Each individual service is registered by calling the RegisterService() method
288 &apos;&apos;&apos;
289 &apos;&apos;&apos; The current version is given as an example
290 &apos;&apos;&apos;
291 With GlobalScope.ScriptForge.SF_Services
292 .RegisterService(&quot;Array&quot;, GlobalScope.ScriptForge.SF_Array) &apos; Reference to the Basic module
293 .RegisterService(&quot;Dictionary&quot;, &quot;ScriptForge.SF_Services._NewDictionary&quot;) &apos; Reference to the function initializing the service
294 .RegisterService(&quot;Exception&quot;, GlobalScope.ScriptForge.SF_Exception)
295 .RegisterService(&quot;FileSystem&quot;, GlobalScope.ScriptForge.SF_FileSystem)
296 .RegisterService(&quot;L10N&quot;, &quot;ScriptForge.SF_Services._NewL10N&quot;)
297 .RegisterService(&quot;Platform&quot;, GlobalScope.ScriptForge.SF_Platform)
298 .RegisterService(&quot;Region&quot;, GlobalScope.ScriptForge.SF_Region)
299 .RegisterService(&quot;Session&quot;, GlobalScope.ScriptForge.SF_Session)
300 .RegisterService(&quot;String&quot;, GlobalScope.ScriptForge.SF_String)
301 .RegisterService(&quot;Timer&quot;, &quot;ScriptForge.SF_Services._NewTimer&quot;)
302 .RegisterService(&quot;UI&quot;, GlobalScope.ScriptForge.SF_UI)
303 &apos;TODO
304 End With
306 End Sub &apos; ScriptForge.SF_Services.RegisterScriptServices
308 REM =========================================================== PRIVATE FUNCTIONS
310 REM -----------------------------------------------------------------------------
311 Private Function _AddToServicesArray(ByVal psServiceName As String _
312 , ByRef pvServiceReference As Variant _
313 , ByVal pbEvent As Boolean _
314 ) As Boolean
315 &apos;&apos;&apos; Add the arguments as an additional row in vServicesArray (Public variable)
316 &apos;&apos;&apos; Called from RegisterService and RegisterEvent methods
318 Dim bRegister As Boolean &apos; Return value
319 Dim lMax As Long &apos; Number of rows in vServicesArray
321 bRegister = False
323 Check:
324 &apos; Ignore when method is not called from RegisterScriptServices()
325 If IsEmpty(vServicesArray) Or IsNull(vServicesArray) Or Not IsArray(vServicesArray) Then GoTo Finally
327 Try:
328 lMax = UBound(vServicesArray, 1) + 1
329 If lMax &lt;= 0 Then
330 ReDim vServicesArray(0 To 0, 0 To 2)
331 Else
332 ReDim Preserve vServicesArray(0 To lMax, 0 To 2)
333 End If
334 vServicesArray(lMax, 0) = psServiceName
335 vServicesArray(lMax, 1) = pvServiceReference
336 vServicesArray(lMax, 2) = pbEvent
337 bRegister = True
339 Finally:
340 _AddToServicesArray = bRegister
341 Exit Function
342 End Function &apos; ScriptForge.SF_Services._AddToServicesArray
344 REM -----------------------------------------------------------------------------
345 Private Function _FindModuleFromMethod(ByVal psLibrary As String _
346 , ByVal psMethod As String _
347 ) As String
348 &apos;&apos;&apos; Find in the given library the name of the module containing
349 &apos;&apos;&apos; the method given as 2nd argument (usually RegisterScriptServices)
350 &apos;&apos;&apos; Args:
351 &apos;&apos;&apos; psLibrary: the name of the Basic library
352 &apos;&apos;&apos; psMethod: the method to locate
353 &apos;&apos;&apos; Returns:
354 &apos;&apos;&apos; The name of the module or a zero-length string if not found
356 Dim vCategories As Variant &apos; &quot;user&quot; or &quot;share&quot; library categories
357 Dim sCategory As String
358 Dim vLanguages As Variant &apos; &quot;Basic&quot;, &quot;Python&quot;, ... programming languages
359 Dim sLanguage As String
360 Dim vLibraries As Variant &apos; Library names
361 Dim sLibrary As String
362 Dim vModules As Variant &apos; Module names
363 Dim sModule As String &apos; Return value
364 Dim vMethods As Variant &apos; Method/properties/subs/functions
365 Dim sMethod As String
366 Dim oRoot As Object &apos; com.sun.star.script.browse.BrowseNodeFactory
367 Dim i As Integer, j As Integer, k As Integer, l As Integer, m As Integer
369 _FindModuleFromMethod = &quot;&quot;
370 Set oRoot = SF_Utils._GetUNOService(&quot;BrowseNodeFactory&quot;).createView(com.sun.star.script.browse.BrowseNodeFactoryViewTypes.MACROORGANIZER)
372 &apos; Exploration is done via tree nodes
373 If Not IsNull(oRoot) Then
374 If oRoot.hasChildNodes() Then
375 vCategories = oRoot.getChildNodes()
376 For i = 0 To UBound(vCategories)
377 sCategory = vCategories(i).getName()
378 &apos; Consider &quot;My macros &amp; Dialogs&quot; and &quot;LibreOffice Macros &amp; Dialogs&quot; only
379 If sCategory = &quot;user&quot; Or sCategory = &quot;share&quot; Then
380 If vCategories(i).hasChildNodes() Then
381 vLanguages = vCategories(i).getChildNodes()
382 For j = 0 To UBound(vLanguages)
383 sLanguage = vLanguages(j).getName()
384 &apos; Consider Basic libraries only
385 If sLanguage = &quot;Basic&quot; Then
386 If vLanguages(j).hasChildNodes() Then
387 vLibraries = vLanguages(j).getChildNodes()
388 For k = 0 To UBound(vLibraries)
389 sLibrary = vLibraries(k).getName()
390 &apos; Consider the given library only
391 If sLibrary = psLibrary Then
392 If vLibraries(k).hasChildNodes() Then
393 vModules = vLibraries(k).getChildNodes()
394 For l = 0 To UBound(vModules)
395 sModule = vModules(l).getName()
396 &apos; Check if the module contains the targeted method
397 If vModules(l).hasChildNodes() Then
398 vMethods = vModules(l).getChildNodes()
399 For m = 0 To UBound(vMethods)
400 sMethod = vMethods(m).getName()
401 If sMethod = psMethod Then
402 _FindModuleFromMethod = sModule
403 Exit Function
404 End If
405 Next m
406 End If
407 Next l
408 End If
409 End If
410 Next k
411 End If
412 End If
413 Next j
414 End If
415 End If
416 Next i
417 End If
418 End If
420 End Function &apos; ScriptForge.SF_Services._FindModuleFromMethod
422 REM -----------------------------------------------------------------------------
423 Private Function _LoadLibraryServices(ByVal psLibrary As String) As Boolean
424 &apos;&apos;&apos; Execute psLibrary.RegisterScriptServices() and load its services into the persistent storage
425 &apos;&apos;&apos; Args:
426 &apos;&apos;&apos; psLibrary: the name of the Basic library
427 &apos;&apos;&apos; Library will be loaded if not yet done
428 &apos;&apos;&apos; Returns:
429 &apos;&apos;&apos; True if success
430 &apos;&apos;&apos; The list of services is loaded directly into the persistent storage
433 Dim vServicesList As Variant &apos; Dictionary of services
434 Dim vService As Variant &apos; Single service entry in dictionary
435 Dim vServiceItem As Variant &apos; Single service in vServicesArray
436 Dim sModule As String &apos; Name of module containing the RegisterScriptServices method
437 Dim i As Long
438 Const cstRegister = &quot;RegisterScriptServices&quot;
440 Try:
441 _LoadLibraryServices = False
443 vServicesArray = Array()
445 If psLibrary = &quot;ScriptForge&quot; Then
446 &apos; Direct call
447 ScriptForge.SF_Services.RegisterScriptServices()
448 Else
449 &apos; Register services via script provider
450 If GlobalScope.BasicLibraries.hasByName(psLibrary) Then
451 If Not GlobalScope.BasicLibraries.isLibraryLoaded(psLibrary) Then
452 GlobalScope.BasicLibraries.LoadLibrary(psLibrary)
453 End If
454 Else
455 GoTo Finally
456 End If
457 sModule = SF_Services._FindModuleFromMethod(psLibrary, cstRegister)
458 If Len(sModule) = 0 Then GoTo Finally
459 SF_Session.ExecuteBasicScript(, psLibrary &amp; &quot;.&quot; &amp; sModule &amp; &quot;.&quot; &amp; cstRegister)
460 End If
462 &apos; Store in persistent storage
463 &apos; - Create list of services for the current library
464 Set vServicesList = SF_Services._NewDictionary()
465 For i = 0 To UBound(vServicesArray, 1)
466 Set vService = New _Service
467 With vService
468 .ServiceName = vServicesArray(i, 0)
469 vServiceItem = vServicesArray(i, 1)
470 If VarType(vServiceItem) = V_STRING Then
471 .ServiceType = 2
472 .ServiceMethod = vServiceItem
473 Set .ServiceReference = Nothing
474 Else &apos; OBJECT
475 .ServiceType = 1
476 .ServiceMethod = &quot;&quot;
477 Set .ServiceReference = vServiceItem
478 End If
479 .EventManager = vServicesArray(i, 2)
480 End With
481 vServicesList.Add(vServicesArray(i, 0), vService)
482 Next i
483 &apos; - Add the new dictionary to the persistent dictionary
484 _SF_.ServicesList.Add(psLibrary, vServicesList)
485 _LoadLibraryServices = True
486 vServicesArray = Empty
488 Finally:
489 Exit Function
490 End Function &apos; ScriptForge.SF_Services._LoadLibraryServices
492 REM -----------------------------------------------------------------------------
493 Public Function _NewDictionary() As Variant
494 &apos;&apos;&apos; Create a new instance of the SF_Dictionary class
495 &apos;&apos;&apos; Returns: the instance or Nothing
497 Dim oDict As Variant
499 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
501 Check:
503 Try:
504 Set oDict = New SF_Dictionary
505 Set oDict.[Me] = oDict
507 Finally:
508 Set _NewDictionary = oDict
509 Exit Function
510 Catch:
511 Set oDict = Nothing
512 GoTo Finally
513 End Function &apos; ScriptForge.SF_Services._NewDictionary
515 REM -----------------------------------------------------------------------------
516 Public Function _NewL10N(Optional ByVal pvArgs As Variant) As Variant
517 &apos;&apos;&apos; Create a new instance of the SF_L10N class
518 &apos; Args:
519 &apos;&apos;&apos; FolderName: the folder containing the PO files in SF_FileSystem.FileNaming notation
520 &apos;&apos;&apos; Locale: locale of user session (default) or any other valid la{nguage]-CO[UNTRY] combination
521 &apos;&apos;&apos; The country part is optional. Valid are f.i. &quot;fr&quot;, &quot;fr-CH&quot;, &quot;en-US&quot;
522 &apos;&apos;&apos; Encoding: The character set that should be used
523 &apos;&apos;&apos; Use one of the Names listed in https://www.iana.org/assignments/character-sets/character-sets.xhtml
524 &apos;&apos;&apos; Note that LibreOffice probably does not implement all existing sets
525 &apos;&apos;&apos; Default = UTF-8
526 &apos;&apos;&apos; Locale2: fallback Locale to select if Locale po file does not exist (typically &quot;en-US&quot;)
527 &apos;&apos;&apos; Encoding2: Encoding of the 2nd Locale file
528 &apos;&apos;&apos; Returns: the instance or Nothing
529 &apos;&apos;&apos; Exceptions:
530 &apos;&apos;&apos; UNKNOWNFILEERROR The PO file does not exist
532 Dim oL10N As Variant &apos; Return value
533 Dim sFolderName As String &apos; Folder containing the PO files
534 Dim sLocale As String &apos; Passed argument or that of the user session
535 Dim sLocale2 As String &apos; Alias for Locale2
536 Dim oLocale As Variant &apos; com.sun.star.lang.Locale
537 Dim sPOFile As String &apos; PO file must exist
538 Dim sEncoding As String &apos; Alias for Encoding
539 Dim sEncoding2 As String &apos; Alias for Encoding2
541 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
543 Check:
544 If IsMissing(pvArgs) Then pvArgs = Array()
545 sPOFile = &quot;&quot;
546 sEncoding = &quot;&quot;
547 If UBound(pvArgs) &gt;= 0 Then
548 If Not SF_Utils._ValidateFile(pvArgs(0), &quot;Folder (Arg0)&quot;, , True) Then GoTo Catch
549 sFolderName = pvArgs(0)
550 sLocale = &quot;&quot;
551 If UBound(pvArgs) &gt;= 1 Then
552 If Not SF_Utils._Validate(pvArgs(1), &quot;Locale (Arg1)&quot;, V_STRING) Then GoTo Catch
553 sLocale = pvArgs(1)
554 End If
555 If Len(sLocale) = 0 Then &apos; Called from Python, the Locale argument may be the zero-length string
556 Set oLocale = SF_Utils._GetUNOService(&quot;OfficeLocale&quot;)
557 sLocale = oLocale.Language &amp; &quot;-&quot; &amp; oLocale.Country
558 End If
559 If UBound(pvArgs) &gt;= 2 Then
560 If IsMissing(pvArgs(2)) Or IsEmpty(pvArgs(2)) Then pvArgs(2) = &quot;UTF-8&quot;
561 If Not SF_Utils._Validate(pvArgs(2), &quot;Encoding (Arg2)&quot;, V_STRING) Then GoTo Catch
562 sEncoding = pvArgs(2)
563 Else
564 sEncoding = &quot;UTF-8&quot;
565 End If
566 sLocale2 = &quot;&quot;
567 If UBound(pvArgs) &gt;= 3 Then
568 If Not SF_Utils._Validate(pvArgs(3), &quot;Locale2 (Arg3)&quot;, V_STRING) Then GoTo Catch
569 sLocale2 = pvArgs(3)
570 End If
571 If UBound(pvArgs) &gt;= 4 Then
572 If Not SF_Utils._Validate(pvArgs(4), &quot;Encoding2 (Arg4)&quot;, V_STRING) Then GoTo Catch
573 sEncoding2 = pvArgs(4)
574 Else
575 sEncoding2 = &quot;UTF-8&quot;
576 End If
577 If Len(sFolderName) &gt; 0 Then
578 sPOFile = SF_FileSystem.BuildPath(sFolderName, sLocale &amp; &quot;.po&quot;)
579 If Not SF_FileSystem.FileExists(sPOFile) Then
580 If Len(sLocale2) = 0 Then GoTo CatchNotExists &apos; No fallback =&gt; error
581 &apos; Try the fallback
582 sPOFile = SF_FileSystem.BuildPath(sFolderName, sLocale2 &amp; &quot;.po&quot;)
583 If Not SF_FileSystem.FileExists(sPOFile) Then GoTo CatchNotExists
584 sEncoding = sEncoding2
585 End If
586 End If
587 End If
589 Try:
590 Set oL10N = New SF_L10N
591 Set oL10N.[Me] = oL10N
592 oL10N._Initialize(sPOFile, sEncoding)
594 Finally:
595 Set _NewL10N = oL10N
596 Exit Function
597 Catch:
598 Set oL10N = Nothing
599 GoTo Finally
600 CatchNotExists:
601 SF_Exception.RaiseFatal(UNKNOWNFILEERROR, &quot;FileName&quot;, sPOFile)
602 GoTo Finally
603 End Function &apos; ScriptForge.SF_Services._NewL10N
605 REM -----------------------------------------------------------------------------
606 Public Function _NewTimer(Optional ByVal pvArgs As Variant) As Variant
607 &apos;&apos;&apos; Create a new instance of the SF_Timer class
608 &apos;&apos;&apos; Args:
609 &apos;&apos;&apos; [0] : If True, start the timer immediately
610 &apos;&apos;&apos; Returns: the instance or Nothing
612 Dim oTimer As Variant &apos; Return value
613 Dim bStart As Boolean &apos; Automatic start ?
615 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
617 Check:
618 If IsMissing(pvArgs) Then pvArgs = Array()
619 If UBound(pvArgs) &lt; 0 Then
620 bStart = False
621 Else
622 If Not SF_Utils._Validate(pvArgs(0), &quot;Start (Arg0)&quot;, V_BOOLEAN) Then GoTo Catch
623 bStart = pvArgs(0)
624 End If
625 Try:
626 Set oTimer = New SF_Timer
627 Set oTimer.[Me] = oTimer
628 If bStart Then oTimer.Start()
630 Finally:
631 Set _NewTimer = oTimer
632 Exit Function
633 Catch:
634 Set oTimer = Nothing
635 GoTo Finally
636 End Function &apos; ScriptForge.SF_Services._NewTimer
638 REM ============================================== END OF SCRIPTFORGE.SF_SERVICES
639 </script:module>