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=
"Module" script:
language=
"StarBasic">
4 REM =======================================================================================================================
5 REM === The Access2Base library is a part of the LibreOffice project. ===
6 REM === Full documentation is available on http://www.access2base.com ===
7 REM =======================================================================================================================
14 REM -----------------------------------------------------------------------------------------------------------------------
15 REM --- CLASS ROOT FIELDS ---
16 REM -----------------------------------------------------------------------------------------------------------------------
18 Private _Type As String
' Must be MODULE
19 Private _This As Object
' Workaround for absence of This builtin function
20 Private _Parent As Object
21 Private _Name As String
22 Private _Library As Object
' com.sun.star.container.XNameAccess
23 Private _LibraryName As String
24 Private _Storage As String
' GLOBAL or DOCUMENT
25 Private _Script As String
' Full script (string with vbLf
's)
26 Private _Lines As Variant
' Array of script lines
27 Private _CountOfLines As Long
28 Private _ProcsParsed As Boolean
' To test before use of proc arrays
29 Private _ProcNames() As Variant
' All procedure names
30 Private _ProcDecPositions() As Variant
' All procedure declarations
31 Private _ProcEndPositions() As Variant
' All end procedure statements
32 Private _ProcTypes() As Variant
' One of the vbext_pk_* constants
34 REM -----------------------------------------------------------------------------------------------------------------------
35 REM --- CONSTRUCTORS / DESTRUCTORS ---
36 REM -----------------------------------------------------------------------------------------------------------------------
37 Private Sub Class_Initialize()
42 Set _Library = Nothing
43 _LibraryName =
""
44 _Storage =
""
45 _Script =
""
50 _ProcDecPositions = Array()
51 _ProcEndPositions = Array()
52 End Sub
' Constructor
54 REM -----------------------------------------------------------------------------------------------------------------------
55 Private Sub Class_Terminate()
56 On Local Error Resume Next
57 Call Class_Initialize()
58 End Sub
' Destructor
60 REM -----------------------------------------------------------------------------------------------------------------------
62 Call Class_Terminate()
63 End Sub
' Explicit destructor
65 REM -----------------------------------------------------------------------------------------------------------------------
66 REM --- CLASS GET/LET/SET PROPERTIES ---
67 REM -----------------------------------------------------------------------------------------------------------------------
69 REM -----------------------------------------------------------------------------------------------------------------------
70 Property Get CountOfDeclarationLines() As Long
71 CountOfDeclarationLines = _PropertyGet(
"CountOfDeclarationLines
")
72 End Property
' CountOfDeclarationLines (get)
74 REM -----------------------------------------------------------------------------------------------------------------------
75 Property Get CountOfLines() As Long
76 CountOfLines = _PropertyGet(
"CountOfLines
")
77 End Property
' CountOfLines (get)
79 REM -----------------------------------------------------------------------------------------------------------------------
80 Property Get Name() As String
81 Name = _PropertyGet(
"Name
")
82 End Property
' Name (get)
84 REM -----------------------------------------------------------------------------------------------------------------------
85 Property Get ObjectType() As String
86 ObjectType = _PropertyGet(
"ObjectType
")
87 End Property
' ObjectType (get)
89 REM -----------------------------------------------------------------------------------------------------------------------
90 Public Function Lines(Optional ByVal pvLine As Variant, Optional ByVal pvNumLines As Variant) As String
91 ' Returns a string containing the contents of a specified line or lines in a standard module or a class module
93 Const cstThisSub =
"Module.Lines
"
94 Utils._SetCalledSub(cstThisSub)
96 Dim sLines As String, lLine As Long
99 If IsMissing(pvLine) Or IsMissing(pvNumLines) Then Call _TraceArguments()
100 If Not Utils._CheckArgument(pvLine,
1, _AddNumeric()) Then GoTo Exit_Function
101 If Not Utils._CheckArgument(pvNumLines,
1, _AddNumeric()) Then GoTo Exit_Function
104 Do While lLine
< _CountOfLines And lLine
< pvLine + pvNumLines
105 sLines = sLines
& _Lines(lLine -
1)
& vbLf
108 If Len(sLines)
> 0 Then sLines = Left(sLines, Len(sLines) -
1)
112 Utils._ResetCalledSub(cstThisSub)
114 End Function
' Lines
116 REM -----------------------------------------------------------------------------------------------------------------------
117 Public Function ProcBodyLine(Optional ByVal pvProc As Variant, Optional ByVal pvProcType As Variant) As Long
118 ' Return the number of the line at which the body of a specified procedure begins
120 Const cstThisSub =
"Module.ProcBodyLine
"
121 Utils._SetCalledSub(cstThisSub)
123 Dim iIndex As Integer
125 If IsMissing(pvProc) Or IsMissing(pvProcType) Then Call _TraceArguments()
126 If Not Utils._CheckArgument(pvProc,
1, vbString) Then GoTo Exit_Function
127 If Not Utils._CheckArgument(pvProcType,
2, _AddNumeric()) Then GoTo Exit_Function
129 iIndex = _FindProcIndex(pvProc, pvProcType)
130 If iIndex
>=
0 Then ProcBodyLine = _LineOfPosition(_ProcDecPositions(iIndex)) Else ProcBodyLine = iIndex
133 Utils._ResetCalledSub(cstThisSub)
135 End Function
' ProcBodyline
137 REM -----------------------------------------------------------------------------------------------------------------------
138 Public Function ProcCountLines(Optional ByVal pvProc As Variant, Optional ByVal pvProcType As Variant) As Long
139 ' Return the number of lines in the specified procedure
141 Const cstThisSub =
"Module.ProcCountLines
"
142 Utils._SetCalledSub(cstThisSub)
144 Dim iIndex As Integer, lStart As Long, lEnd As Long
146 If IsMissing(pvProc) Or IsMissing(pvProcType) Then Call _TraceArguments()
147 If Not Utils._CheckArgument(pvProc,
1, vbString) Then GoTo Exit_Function
148 If Not Utils._CheckArgument(pvProcType,
2, _AddNumeric()) Then GoTo Exit_Function
150 iIndex = _FindProcIndex(pvProc, pvProcType)
151 lStart = ProcStartLine(pvProc, pvProcType)
152 lEnd = _LineOfPosition(_ProcEndPositions(iIndex))
153 ProcCountLines = lEnd - lStart +
1
156 Utils._ResetCalledSub(cstThisSub)
158 End Function
' ProcCountLines
160 REM -----------------------------------------------------------------------------------------------------------------------
161 Public Function ProcOfLine(Optional ByVal pvLine As Variant, Optional ByRef pvProcType As Variant) As String
162 ' Return the name and type of the procedure containing line pvLine
164 Const cstThisSub =
"Module.ProcOfLine
"
165 Utils._SetCalledSub(cstThisSub)
167 Dim sProcedure As String, iProc As Integer, lLineDec As Long, lLineEnd As Long
169 If IsMissing(pvLine) Or IsMissing(pvProcType) Then Call _TraceArguments()
170 If Not Utils._CheckArgument(pvLine,
1, _AddNumeric()) Then GoTo Exit_Function
171 If Not Utils._CheckArgument(pvProcType,
2, _AddNumeric()) Then GoTo Exit_Function
173 If Not _ProcsParsed Then _ParseProcs()
175 sProcedure =
""
176 For iProc =
0 To UBound(_ProcNames)
177 lLineEnd = _LineOfPosition(_ProcEndPositions(iProc))
178 If pvLine
<= lLineEnd Then
179 lLineDec = _LineOfPosition(_ProcDecPositions(iProc))
180 If pvLine
< lLineDec Then
' Line between
2 procedures
181 sProcedure =
""
183 sProcedure = _ProcNames(iProc)
184 pvProcType = _ProcTypes(iProc)
191 ProcOfLine = sProcedure
192 Utils._ResetCalledSub(cstThisSub)
194 End Function
' ProcOfline
196 REM -----------------------------------------------------------------------------------------------------------------------
197 Public Function ProcStartLine(Optional ByVal pvProc As Variant, Optional ByVal pvProcType As Variant) As Long
198 ' Return the number of the line at which the specified procedure begins
200 Const cstThisSub =
"Module.ProcStartLine
"
201 Utils._SetCalledSub(cstThisSub)
203 Dim lLine As Long, lIndex As Long, sLine As String
205 If IsMissing(pvProc) Or IsMissing(pvProcType) Then Call _TraceArguments()
206 If Not Utils._CheckArgument(pvProc,
1, vbString) Then GoTo Exit_Function
207 If Not Utils._CheckArgument(pvProcType,
2, _AddNumeric()) Then GoTo Exit_Function
209 lLine = ProcBodyLine(pvProc, pvProcType)
210 ' Search baclIndexward for comment lines
212 Do While lIndex
> 0
213 sLine = _Trim(_Lines(lIndex -
1))
214 If UCase(Left(sLine,
4)) =
"REM
" Or Left(sLine,
1) =
"'" Then
222 ProcStartLine = lLine
225 Utils._ResetCalledSub(cstThisSub)
227 End Function
' ProcStartLine
229 REM -----------------------------------------------------------------------------------------------------------------------
230 Public Function Properties(ByVal Optional pvIndex As Variant) As Variant
232 ' a Collection object if pvIndex absent
233 ' a Property object otherwise
235 Const cstThisSub =
"Module.Properties
"
236 Utils._SetCalledSub(cstThisSub)
238 Dim vProperty As Variant, vPropertiesList() As Variant, sObject As String
240 vPropertiesList = _PropertiesList()
241 sObject = Utils._PCase(_Type)
242 If IsMissing(pvIndex) Then
243 vProperty = PropertiesGet._Properties(sObject, _This, vPropertiesList)
245 vProperty = PropertiesGet._Properties(sObject, _This, vPropertiesList, pvIndex)
246 vProperty._Value = _PropertyGet(vPropertiesList(pvIndex))
250 Set Properties = vProperty
251 Utils._ResetCalledSub(cstThisSub)
253 End Function
' Properties
255 REM -----------------------------------------------------------------------------------------------------------------------
256 Property Get pType() As String
257 pType = _PropertyGet(
"Type
")
258 End Property
' Type (get)
260 REM -----------------------------------------------------------------------------------------------------------------------
261 REM --- CLASS METHODS ---
262 REM -----------------------------------------------------------------------------------------------------------------------
264 REM -----------------------------------------------------------------------------------------------------------------------
265 Public Function Find(Optional ByVal pvTarget As Variant _
266 , Optional ByRef pvStartLine As Variant _
267 , Optional ByRef pvStartColumn As Variant _
268 , Optional ByRef pvEndLine As Variant _
269 , Optional ByRef pvEndColumn As Variant _
270 , Optional ByVal pvWholeWord As Boolean _
271 , Optional ByVal pvMatchCase As Boolean _
272 , Optional ByVal pvPatternSearch As Boolean _
274 ' Finds specified text in the module
275 ' xxLine and xxColumn arguments are mainly to return the position of the found string
276 ' If they are initialized but nonsense, the function returns False
278 Const cstThisSub =
"Module.Find
"
279 Utils._SetCalledSub(cstThisSub)
280 If _ErrorHandler() Then On Local Error Goto Error_Function
282 Dim bFound As Boolean, lPosition As Long, lStartLine As Long, lStartColumn As Long, lStartPosition As Long
283 Dim lEndLine As Long, lEndColumn As Long, lEndPosition As Long
284 Dim sMatch As String, vOptions As Variant, sPattern As String
285 Dim i As Integer, sSpecChar As String
287 Const cstSpecialCharacters =
"\[^$.|?*+()
"
291 If IsMissing(pvTarget) Or IsMissing(pvStartLine) Or IsMissing(pvStartColumn) Or IsMissing(pvEndLine) Or IsMissing(pvEndColumn) Then Call _TraceArguments()
292 If Not Utils._CheckArgument(pvTarget,
1, vbString) Then GoTo Exit_Function
293 If Len(pvTarget) =
0 Then GoTo Exit_Function
294 If Not IsEmpty(pvStartLine) Then
295 If Not Utils._CheckArgument(pvStartLine,
2, _AddNumeric()) Then GoTo Exit_Function
297 If Not IsEmpty(pvStartColumn) Then
298 If Not Utils._CheckArgument(pvStartColumn,
3, _AddNumeric()) Then GoTo Exit_Function
300 If Not IsEmpty(pvEndLine) Then
301 If Not Utils._CheckArgument(pvEndLine,
4, _AddNumeric()) Then GoTo Exit_Function
303 If Not IsEmpty(pvEndColumn) Then
304 If Not Utils._CheckArgument(pvEndColumn,
5, _AddNumeric()) Then GoTo Exit_Function
306 If IsMissing(pvWholeWord) Then pvWholeWord = False
307 If Not Utils._CheckArgument(pvWholeWord,
6, vbBoolean) Then GoTo Exit_Function
308 If IsMissing(pvMatchCase) Then pvMatchCase = False
309 If Not Utils._CheckArgument(pvMatchCase,
7, vbBoolean) Then GoTo Exit_Function
310 If IsMissing(pvPatternSearch) Then pvPatternSearch = False
311 If Not Utils._CheckArgument(pvPatternSearch,
8, vbBoolean) Then GoTo Exit_Function
313 ' Initialize starting values
314 If IsEmpty(pvStartLine) Then lStartLine =
1 Else lStartLine = pvStartLine
315 If lStartLine
<=
0 Or lStartLine
> UBound(_Lines) +
1 Then GoTo Exit_Function
316 If IsEmpty(pvStartColumn) Then lStartColumn =
1 Else lStartColumn = pvStartColumn
317 If lStartColumn
<=
0 Then GoTo Exit_Function
318 If lStartColumn
> 1 And lStartColumn
> Len(_Lines(lStartLine +
1)) Then GoTo Exit_Function
319 lStartPosition = _PositionOfLine(lStartline) + lStartColumn -
1
320 If IsEmpty(pvEndLine) Then lEndLine = UBound(_Lines) +
1 Else lEndLine = pvEndLine
321 If lEndLine
< lStartLine Or lEndLine
> UBound(_Lines) +
1 Then GoTo Exit_Function
322 If IsEmpty(pvEndColumn) Then lEndColumn = Len(_Lines(lEndLine -
1)) Else lEndColumn = pvEndColumn
323 If lEndColumn
< 0 Then GoTo Exit_Function
324 If lEndColumn =
0 Then lEndColumn =
1
325 If lEndColumn
> Len(_Lines(lEndLine -
1)) +
1 Then GoTo Exit_Function
326 lEndPosition = _PositionOfLine(lEndline) + lEndColumn -
1
329 Set vOptions = _A2B_.SearchOptions
330 vOptions.transliterateFlags =
0
333 ' Define pattern to search for
335 ' Protect special characters in regular expressions
336 For i =
1 To Len(cstSpecialCharacters)
337 sSpecChar = Mid(cstSpecialCharacters, i,
1)
338 sPattern = Replace(sPattern, sSpecChar,
"\
" & sSpecChar)
340 If pvPatternSearch Then sPattern = Replace(Replace(sPattern,
"\*
",
".*
"),
"\?
",
".
")
341 If pvWholeWord Then sPattern =
"\b
" & sPattern
& "\b
"
343 lPosition = lStartPosition
344 sMatch = Utils._RegexSearch(_Script, sPattern, lPosition)
345 ' Re-establish default options for later searches
346 If pvMatchCase Then vOptions.transliterateFlags = com.sun.star.i18n.TransliterationModules.IGNORE_CASE
348 ' Found within requested bounds ?
349 If sMatch
<> "" And lPosition
>= lStartPosition And lPosition
<= lEndPosition Then
350 pvStartLine = _LineOfPosition(lPosition)
351 pvStartColumn = lPosition - _PositionOfLine(pvStartLine) +
1
352 pvEndLine = _LineOfPosition(lPosition + Len(sMatch) -
1)
353 If pvEndLine
> pvStartLine Then
354 pvEndColumn = lPosition + Len(sMatch) -
1 - _PositionOfLine(pvEndLine)
356 pvEndColumn = pvStartColumn + Len(sMatch) -
1
363 Utils._ResetCalledSub(cstThisSub)
366 TraceError(TRACEABORT, Err,
"Module.Find
", Erl)
369 End Function
' Find
371 REM -----------------------------------------------------------------------------------------------------------------------
372 Public Function getProperty(Optional ByVal pvProperty As Variant) As Variant
373 ' Return property value of psProperty property name
375 Const cstThisSub =
"Module.Properties
"
377 Utils._SetCalledSub(cstThisSub)
378 If IsMissing(pvProperty) Then Call _TraceArguments()
379 getProperty = _PropertyGet(pvProperty)
380 Utils._ResetCalledSub(cstThisSub)
382 End Function
' getProperty
384 REM --------------------------------Mid(a._Script, iCtl,
25)---------------------------------------------------------------------------------------
385 Public Function hasProperty(ByVal Optional pvProperty As Variant) As Boolean
386 ' Return True if object has a valid property called pvProperty (case-insensitive comparison !)
388 Const cstThisSub =
"Module.hasProperty
"
390 Utils._SetCalledSub(cstThisSub)
391 If IsMissing(pvProperty) Then hasProperty = PropertiesGet._hasProperty(_Type, _PropertiesList()) Else hasProperty = PropertiesGet._hasProperty(_Type, _PropertiesList(), pvProperty)
392 Utils._ResetCalledSub(cstThisSub)
395 End Function
' hasProperty
397 REM -----------------------------------------------------------------------------------------------------------------------
398 REM --- PRIVATE FUNCTIONS ---
399 REM -----------------------------------------------------------------------------------------------------------------------
401 REM -----------------------------------------------------------------------------------------------------------------------
402 Private Function _BeginStatement(ByVal plStart As Long) As Long
403 ' Return the position in _Script of the beginning of the current statement as defined by plStart
405 Dim sProc As String, iProc As Integer, iType As Integer
406 Dim lPosition As Long, lPrevious As Long, sFind As String
408 sProc = ProcOfLine(_LineOfPosition(plStart), iType)
409 iProc = _FindProcIndex(sProc, iType)
410 If iProc
< 0 Then lPosition =
1 Else lPosition = _ProcDecPositions(iProc)
412 sFind =
"Any
"
413 Do While lPosition
< plStart And sFind
<> ""
414 lPrevious = lPosition
415 sFind = _FindPattern(
"%^\w
", lPosition)
416 If sFind =
"" Then Exit Do
419 _BeginStatement = lPrevious
421 End Function
' _EndStatement
423 REM -----------------------------------------------------------------------------------------------------------------------
424 Private Function _EndStatement(ByVal plStart As Long) As Long
425 ' Return the position in _Script of the end of the current statement as defined by plStart
426 ' plStart is assumed not to be in the middle of a comment or a string
428 Dim sMatch As String, lPosition As Long
430 sMatch = _FindPattern(
"%$
", lPosition)
431 _EndStatement = lPosition
433 End Function
' _EndStatement
435 REM -----------------------------------------------------------------------------------------------------------------------
436 Private Function _FindPattern(ByVal psPattern As Variant, Optional ByRef plStart As Long) As String
437 ' Find first occurrence of any of the patterns in |-delimited string psPattern
438 ' Special escapes
439 ' - for word breaks:
"%B
" (f.i. for searching
"END%BFUNCTION
")
440 ' - for statement start:
"%^
" (f.i. for searching
"%^END%BFUNCTION
"). Necessarily first
2 characters of pattern
441 ' - for statement end:
"%$
". Pattern should not contain anything else
442 ' If quoted string searched, pattern should start and end with a double quote
443 ' Return
"" if none found, otherwise returns the matching string
444 ' plStart = start position of _Script to search (starts at
1)
445 ' In output plStart contains the first position of the matching string or is left unchanged
446 ' To search again the same or another pattern =
> plStart = plStart + Len(matching string)
447 ' Comments and strings are skipped
449 ' Common patterns
450 Const cstComment =
"(
'|\bREM\b)[^\n]*$
"
451 Const cstString =
"""[^
""\n]*
"""
452 Const cstBeginStatement =
"(^|:|\bthen\b|\belse\b|\n)[ \t]*
"
453 Const cstEndStatement =
"[ \t]*($|:|\bthen\b|\belse\b|\n)
"
454 Const cstContinuation =
"[ \t]_\n
"
455 Const cstWordBreak =
"\b[ \t]+(_\n[ \t]*)?\b
"
456 Const cstAlt =
"|
"
458 Dim sRegex As String, lStart As Long, bContinue As Boolean, sMatch As String
459 Dim bEndStatement As Boolean, bQuote As Boolean
461 If psPattern =
"%$
" Then
462 sRegex = cstEndStatement
465 If Left(psPattern,
2) =
"%^
" Then sRegex = cstBeginStatement
& Right(sRegex, Len(sregex) -
2)
466 sregex = Replace(sregex,
"%B
", cstWordBreak)
468 ' Add all to ignore patterns to regex. If pattern = quoted string do not add cstString
469 If Len(psPattern)
> 2 And Left(psPattern,
1) =
"""" And Right(psPattern,
1) =
"""" Then
471 sRegex = sRegex
& cstAlt
& cstComment
& cstAlt
& cstContinuation
474 sRegex = sRegex
& cstAlt
& cstComment
& cstAlt
& cstString
& cstAlt
& cstContinuation
477 If IsMissing(plStart) Then plStart =
1
482 bEndStatement = False
483 sMatch = Utils._RegexSearch(_Script, sRegex, lStart)
485 Case sMatch =
""
487 Case Left(sMatch,
1) =
"'"
489 Case Left(sMatch,
1) =
""""
494 Case Left(smatch,
1) =
":
" Or Left(sMatch,
1) = vbLf
495 If psPattern =
"%$
" Then
500 sMatch = Right(sMatch, Len(sMatch) -
1)
502 Case UCase(Left(sMatch,
4)) =
"REM
" Or UCase(Left(sMatch,
4)) =
"REM
" & vbTab Or UCase(Left(sMatch,
4)) =
"REM
" & vbNewLine
504 Case UCase(Left(sMatch,
4)) =
"THEN
" Or UCase(Left(sMatch,
4)) =
"ELSE
"
505 If psPattern =
"%$
" Then
510 sMatch = Right(sMatch, Len(sMatch) -
4)
512 Case sMatch =
" _
" & vbLf
513 Case Else
' Found
517 If bEndStatement And psPattern =
"%$
" Then
520 sMatch =
""
522 lStart = lStart + Len(sMatch)
525 _FindPattern = sMatch
527 End Function
' _FindPattern
529 REM -----------------------------------------------------------------------------------------------------------------------
530 Private Function _FindProcIndex(ByVal psProc As String, ByVal piType As Integer) As Integer
531 ' Return index of entry in _Procnames corresponding with pvProc
533 Dim i As Integer, iIndex As Integer
535 If Not _ProcsParsed Then _ParseProcs
538 For i =
0 To UBound(_ProcNames)
539 If UCase(psProc) = UCase(_ProcNames(i)) And piType = _ProcTypes(i) Then
544 If iIndex
< 0 Then TraceError(TRACEFATAL, ERRPROCEDURENOTFOUND, Utils._CalledSub(),
0, , Array(psProc, _Name))
547 _FindProcIndex = iIndex
549 End Function
' _FindProcIndex
551 REM -----------------------------------------------------------------------------------------------------------------------
552 Public Sub _Initialize()
554 _Script = Replace(_Script, vbCr,
"")
555 _Lines = Split(_Script, vbLf)
556 _CountOfLines = UBound(_Lines) +
1
558 End Sub
' _Initialize
560 REM -----------------------------------------------------------------------------------------------------------------------
561 Private Function _LineOfPosition(ByVal plPosition) As Long
562 ' Return the line number of a position in _Script
564 Dim lLine As Long, lLength As Long
565 ' Start counting from start or end depending on how close position is
566 If plPosition
<= Len(_Script) /
2 Then
568 For lLine =
0 To UBound(_Lines)
569 lLength = lLength + Len(_Lines(lLine)) +
1 ' +
1 for line feed
570 If lLength
>= plPosition Then
571 _LineOfPosition = lLine +
1
576 If Right(_Script,
1) = vbLf Then lLength = Len(_Script) +
1 Else lLength = Len(_Script)
577 For lLine = UBound(_Lines) To
0 Step -
1
578 lLength = lLength - Len(_Lines(lLine)) -
1 ' -
1 for line feed
579 If lLength
<= plPosition Then
580 _LineOfPosition = lLine +
1
586 End Function
' _LineOfPosition
588 REM -----------------------------------------------------------------------------------------------------------------------
589 Private Sub _ParseProcs()
590 ' Fills the Proc arrays: name, start and end position
591 ' Executed at first request needing this processing
593 Dim lPosition As Long, iProc As Integer, sDecProc As String, sEndProc As String, sNameProc As String, sType As String
594 Const cstDeclaration =
"%^(private%B|public%B)?\b(property%Bget|property%Blet|property%Bset|function|sub)\b
"
595 Const cstEnd =
"%^end%B(property|function|sub)\b
"
596 Const cstName =
"\w*
" '"[A-Za-z_][A-Za-z_0-
9]*
"
598 If _ProcsParsed Then Exit Sub
' Do not redo if already done
600 _ProcDecPositions = Array()
601 _ProcEndPositions = Array()
606 sDecProc =
"???
"
607 Do While sDecProc
<> ""
608 ' Identify Function/Sub declaration string
609 sDecProc = _FindPattern(cstDeclaration, lPosition)
610 If sDecProc
<> "" Then
612 ReDim Preserve _ProcNames(
0 To iProc)
613 ReDim Preserve _ProcDecPositions(
0 To iProc)
614 ReDim Preserve _ProcEndPositions(
0 To iProc)
615 ReDim Preserve _ProcTypes(
0 To iProc)
616 _ProcDecPositions(iProc) = lPosition
617 lPosition = lPosition + Len(sDecProc)
618 ' Identify procedure type
620 Case InStr(UCase(sDecProc),
"FUNCTION
")
> 0 : _ProcTypes(iProc) = vbext_pk_Proc
621 Case InStr(UCase(sDecProc),
"SUB
")
> 0 : _ProcTypes(iProc) = vbext_pk_Proc
622 Case InStr(UCase(sDecProc),
"GET
")
> 0 : _ProcTypes(iProc) = vbext_pk_Get
623 Case InStr(UCase(sDecProc),
"LET
")
> 0 : _ProcTypes(iProc) = vbext_pk_Let
624 Case InStr(UCase(sDecProc),
"SET
")
> 0 : _ProcTypes(iProc) = vbext_pk_Set
626 ' Identify name of Function/Sub
627 sNameProc = _FindPattern(cstName, lPosition)
628 If sNameProc =
"" Then Exit Do
' Should never happen
629 _ProcNames(iProc) = sNameProc
630 lPosition = lPosition + Len(sNameProc)
631 ' Identify End statement
632 sEndProc = _FindPattern(cstEnd, lPosition)
633 If sEndProc =
"" Then Exit Do
' Should never happen
634 _ProcEndPositions(iProc) = lPosition
635 lPosition = lPosition + Len(sEndProc)
643 REM -----------------------------------------------------------------------------------------------------------------------
644 Private Function _PositionOfLine(ByVal plLine) As Long
645 ' Return the position of the first character of the given line in _Script
647 Dim lLine As Long, lPosition As Long
648 ' Start counting from start or end depending on how close line is
649 If plLine
<= (UBound(_Lines) +
1) /
2 Then
651 For lLine =
0 To plLine -
1
652 lPosition = lPosition +
1 ' +
1 for line feed
653 If lLine
< plLine -
1 Then lPosition = lPosition + Len(_Lines(lLine))
656 lPosition = Len(_Script) +
2 ' Anticipate an ending null-string and a line feed
657 For lLine = UBound(_Lines) To plLine -
1 Step -
1
658 lPosition = lPosition - Len(_Lines(lLine)) -
1 ' -
1 for line feed
662 _PositionOfLine = lPosition
664 End Function
' _LineOfPosition
666 REM -----------------------------------------------------------------------------------------------------------------------
667 Private Function _PropertiesList() As Variant
669 _PropertiesList = Array(
"CountOfDeclarationLines
",
"CountOfLines
",
"Name
",
"ObjectType
",
"Type
")
671 End Function
' _PropertiesList
673 REM -----------------------------------------------------------------------------------------------------------------------
674 Private Function _PropertyGet(ByVal psProperty As String) As Variant
675 ' Return property value of the psProperty property name
677 Dim cstThisSub As String
678 Const cstDot =
".
"
682 If _ErrorHandler() Then On Local Error Goto Error_Function
683 cstThisSub =
"Module.get
" & psProperty
684 Utils._SetCalledSub(cstThisSub)
687 Select Case UCase(psProperty)
688 Case UCase(
"CountOfDeclarationLines
")
689 If Not _ProcsParsed Then _ParseProcs()
690 If UBound(_ProcNames)
>=
0 Then
691 _PropertyGet = ProcStartLine(_ProcNames(
0), _ProcTypes(
0)) -
1
693 _PropertyGet = _CountOfLines
695 Case UCase(
"CountOfLines
")
696 _PropertyGet = _CountOfLines
697 Case UCase(
"Name
")
698 _PropertyGet = _Storage
& cstDot
& _LibraryName
& cstDot
& _Name
699 Case UCase(
"ObjectType
")
701 Case UCase(
"Type
")
702 ' Find option statement before any procedure declaration
703 sText = _FindPattern(
"%^option%Bclassmodule\b|\bfunction\b|\bsub\b|\bproperty\b
")
704 If UCase(Left(sText,
6)) =
"OPTION
" Then _PropertyGet = acClassModule Else _PropertyGet = acStandardModule
710 Utils._ResetCalledSub(cstThisSub)
713 TraceError(TRACEFATAL, ERRPROPERTY, Utils._CalledSub(),
0,
1, psProperty)
714 _PropertyGet = Nothing
717 TraceError(TRACEABORT, Err,
"Module._PropertyGet
", Erl)
720 End Function
' _PropertyGet