SF_Services.xba 27 KB

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