123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
- <script:module xmlns:script="http://openoffice.org/2000/script" script:name="Module" script:language="StarBasic">
- REM =======================================================================================================================
- REM === The Access2Base library is a part of the LibreOffice project. ===
- REM === Full documentation is available on http://www.access2base.com ===
- REM =======================================================================================================================
- Option Compatible
- Option ClassModule
- Option Explicit
- REM -----------------------------------------------------------------------------------------------------------------------
- REM --- CLASS ROOT FIELDS ---
- REM -----------------------------------------------------------------------------------------------------------------------
- Private _Type As String ' Must be MODULE
- Private _This As Object ' Workaround for absence of This builtin function
- Private _Parent As Object
- Private _Name As String
- Private _Library As Object ' com.sun.star.container.XNameAccess
- Private _LibraryName As String
- Private _Storage As String ' GLOBAL or DOCUMENT
- Private _Script As String ' Full script (string with vbLf's)
- Private _Lines As Variant ' Array of script lines
- Private _CountOfLines As Long
- Private _ProcsParsed As Boolean ' To test before use of proc arrays
- Private _ProcNames() As Variant ' All procedure names
- Private _ProcDecPositions() As Variant ' All procedure declarations
- Private _ProcEndPositions() As Variant ' All end procedure statements
- Private _ProcTypes() As Variant ' One of the vbext_pk_* constants
- REM -----------------------------------------------------------------------------------------------------------------------
- REM --- CONSTRUCTORS / DESTRUCTORS ---
- REM -----------------------------------------------------------------------------------------------------------------------
- Private Sub Class_Initialize()
- _Type = OBJMODULE
- Set _This = Nothing
- Set _Parent = Nothing
- _Name = ""
- Set _Library = Nothing
- _LibraryName = ""
- _Storage = ""
- _Script = ""
- _Lines = Array()
- _CountOfLines = 0
- _ProcsParsed = False
- _ProcNames = Array()
- _ProcDecPositions = Array()
- _ProcEndPositions = Array()
- End Sub ' Constructor
- REM -----------------------------------------------------------------------------------------------------------------------
- Private Sub Class_Terminate()
- On Local Error Resume Next
- Call Class_Initialize()
- End Sub ' Destructor
- REM -----------------------------------------------------------------------------------------------------------------------
- Public Sub Dispose()
- Call Class_Terminate()
- End Sub ' Explicit destructor
- REM -----------------------------------------------------------------------------------------------------------------------
- REM --- CLASS GET/LET/SET PROPERTIES ---
- REM -----------------------------------------------------------------------------------------------------------------------
- REM -----------------------------------------------------------------------------------------------------------------------
- Property Get CountOfDeclarationLines() As Long
- CountOfDeclarationLines = _PropertyGet("CountOfDeclarationLines")
- End Property ' CountOfDeclarationLines (get)
- REM -----------------------------------------------------------------------------------------------------------------------
- Property Get CountOfLines() As Long
- CountOfLines = _PropertyGet("CountOfLines")
- End Property ' CountOfLines (get)
- REM -----------------------------------------------------------------------------------------------------------------------
- Property Get Name() As String
- Name = _PropertyGet("Name")
- End Property ' Name (get)
- REM -----------------------------------------------------------------------------------------------------------------------
- Property Get ObjectType() As String
- ObjectType = _PropertyGet("ObjectType")
- End Property ' ObjectType (get)
- REM -----------------------------------------------------------------------------------------------------------------------
- Public Function Lines(Optional ByVal pvLine As Variant, Optional ByVal pvNumLines As Variant) As String
- ' Returns a string containing the contents of a specified line or lines in a standard module or a class module
- Const cstThisSub = "Module.Lines"
- Utils._SetCalledSub(cstThisSub)
- Dim sLines As String, lLine As Long
- sLines = ""
- If IsMissing(pvLine) Or IsMissing(pvNumLines) Then Call _TraceArguments()
- If Not Utils._CheckArgument(pvLine, 1, _AddNumeric()) Then GoTo Exit_Function
- If Not Utils._CheckArgument(pvNumLines, 1, _AddNumeric()) Then GoTo Exit_Function
-
- lLine = pvLine
- Do While lLine < _CountOfLines And lLine < pvLine + pvNumLines
- sLines = sLines & _Lines(lLine - 1) & vbLf
- lLine = lLine + 1
- Loop
- If Len(sLines) > 0 Then sLines = Left(sLines, Len(sLines) - 1)
- Exit_Function:
- Lines = sLines
- Utils._ResetCalledSub(cstThisSub)
- Exit Function
- End Function ' Lines
- REM -----------------------------------------------------------------------------------------------------------------------
- Public Function ProcBodyLine(Optional ByVal pvProc As Variant, Optional ByVal pvProcType As Variant) As Long
- ' Return the number of the line at which the body of a specified procedure begins
- Const cstThisSub = "Module.ProcBodyLine"
- Utils._SetCalledSub(cstThisSub)
- Dim iIndex As Integer
- If IsMissing(pvProc) Or IsMissing(pvProcType) Then Call _TraceArguments()
- If Not Utils._CheckArgument(pvProc, 1, vbString) Then GoTo Exit_Function
- If Not Utils._CheckArgument(pvProcType, 2, _AddNumeric()) Then GoTo Exit_Function
- iIndex = _FindProcIndex(pvProc, pvProcType)
- If iIndex >= 0 Then ProcBodyLine = _LineOfPosition(_ProcDecPositions(iIndex)) Else ProcBodyLine = iIndex
- Exit_Function:
- Utils._ResetCalledSub(cstThisSub)
- Exit Function
- End Function ' ProcBodyline
- REM -----------------------------------------------------------------------------------------------------------------------
- Public Function ProcCountLines(Optional ByVal pvProc As Variant, Optional ByVal pvProcType As Variant) As Long
- ' Return the number of lines in the specified procedure
- Const cstThisSub = "Module.ProcCountLines"
- Utils._SetCalledSub(cstThisSub)
- Dim iIndex As Integer, lStart As Long, lEnd As Long
- If IsMissing(pvProc) Or IsMissing(pvProcType) Then Call _TraceArguments()
- If Not Utils._CheckArgument(pvProc, 1, vbString) Then GoTo Exit_Function
- If Not Utils._CheckArgument(pvProcType, 2, _AddNumeric()) Then GoTo Exit_Function
- iIndex = _FindProcIndex(pvProc, pvProcType)
- lStart = ProcStartLine(pvProc, pvProcType)
- lEnd = _LineOfPosition(_ProcEndPositions(iIndex))
- ProcCountLines = lEnd - lStart + 1
-
- Exit_Function:
- Utils._ResetCalledSub(cstThisSub)
- Exit Function
- End Function ' ProcCountLines
- REM -----------------------------------------------------------------------------------------------------------------------
- Public Function ProcOfLine(Optional ByVal pvLine As Variant, Optional ByRef pvProcType As Variant) As String
- ' Return the name and type of the procedure containing line pvLine
- Const cstThisSub = "Module.ProcOfLine"
- Utils._SetCalledSub(cstThisSub)
- Dim sProcedure As String, iProc As Integer, lLineDec As Long, lLineEnd As Long
- If IsMissing(pvLine) Or IsMissing(pvProcType) Then Call _TraceArguments()
- If Not Utils._CheckArgument(pvLine, 1, _AddNumeric()) Then GoTo Exit_Function
- If Not Utils._CheckArgument(pvProcType, 2, _AddNumeric()) Then GoTo Exit_Function
- If Not _ProcsParsed Then _ParseProcs()
- sProcedure = ""
- For iProc = 0 To UBound(_ProcNames)
- lLineEnd = _LineOfPosition(_ProcEndPositions(iProc))
- If pvLine <= lLineEnd Then
- lLineDec = _LineOfPosition(_ProcDecPositions(iProc))
- If pvLine < lLineDec Then ' Line between 2 procedures
- sProcedure = ""
- Else
- sProcedure = _ProcNames(iProc)
- pvProcType = _ProcTypes(iProc)
- End If
- Exit For
- End If
- Next iProc
- Exit_Function:
- ProcOfLine = sProcedure
- Utils._ResetCalledSub(cstThisSub)
- Exit Function
- End Function ' ProcOfline
- REM -----------------------------------------------------------------------------------------------------------------------
- Public Function ProcStartLine(Optional ByVal pvProc As Variant, Optional ByVal pvProcType As Variant) As Long
- ' Return the number of the line at which the specified procedure begins
- Const cstThisSub = "Module.ProcStartLine"
- Utils._SetCalledSub(cstThisSub)
- Dim lLine As Long, lIndex As Long, sLine As String
- If IsMissing(pvProc) Or IsMissing(pvProcType) Then Call _TraceArguments()
- If Not Utils._CheckArgument(pvProc, 1, vbString) Then GoTo Exit_Function
- If Not Utils._CheckArgument(pvProcType, 2, _AddNumeric()) Then GoTo Exit_Function
- lLine = ProcBodyLine(pvProc, pvProcType)
- ' Search baclIndexward for comment lines
- lIndex = lLine - 1
- Do While lIndex > 0
- sLine = _Trim(_Lines(lIndex - 1))
- If UCase(Left(sLine, 4)) = "REM " Or Left(sLine, 1) = "'" Then
- lLine = lIndex
- Else
- Exit Do
- End If
- lIndex = lIndex - 1
- Loop
- ProcStartLine = lLine
- Exit_Function:
- Utils._ResetCalledSub(cstThisSub)
- Exit Function
- End Function ' ProcStartLine
- REM -----------------------------------------------------------------------------------------------------------------------
- Public Function Properties(ByVal Optional pvIndex As Variant) As Variant
- ' Return
- ' a Collection object if pvIndex absent
- ' a Property object otherwise
- Const cstThisSub = "Module.Properties"
- Utils._SetCalledSub(cstThisSub)
- Dim vProperty As Variant, vPropertiesList() As Variant, sObject As String
- vPropertiesList = _PropertiesList()
- sObject = Utils._PCase(_Type)
- If IsMissing(pvIndex) Then
- vProperty = PropertiesGet._Properties(sObject, _This, vPropertiesList)
- Else
- vProperty = PropertiesGet._Properties(sObject, _This, vPropertiesList, pvIndex)
- vProperty._Value = _PropertyGet(vPropertiesList(pvIndex))
- End If
-
- Exit_Function:
- Set Properties = vProperty
- Utils._ResetCalledSub(cstThisSub)
- Exit Function
- End Function ' Properties
- REM -----------------------------------------------------------------------------------------------------------------------
- Property Get pType() As String
- pType = _PropertyGet("Type")
- End Property ' Type (get)
- REM -----------------------------------------------------------------------------------------------------------------------
- REM --- CLASS METHODS ---
- REM -----------------------------------------------------------------------------------------------------------------------
- REM -----------------------------------------------------------------------------------------------------------------------
- Public Function Find(Optional ByVal pvTarget As Variant _
- , Optional ByRef pvStartLine As Variant _
- , Optional ByRef pvStartColumn As Variant _
- , Optional ByRef pvEndLine As Variant _
- , Optional ByRef pvEndColumn As Variant _
- , Optional ByVal pvWholeWord As Boolean _
- , Optional ByVal pvMatchCase As Boolean _
- , Optional ByVal pvPatternSearch As Boolean _
- ) As Boolean
- ' Finds specified text in the module
- ' xxLine and xxColumn arguments are mainly to return the position of the found string
- ' If they are initialized but nonsense, the function returns False
- Const cstThisSub = "Module.Find"
- Utils._SetCalledSub(cstThisSub)
- If _ErrorHandler() Then On Local Error Goto Error_Function
- Dim bFound As Boolean, lPosition As Long, lStartLine As Long, lStartColumn As Long, lStartPosition As Long
- Dim lEndLine As Long, lEndColumn As Long, lEndPosition As Long
- Dim sMatch As String, vOptions As Variant, sPattern As String
- Dim i As Integer, sSpecChar As String
- Const cstSpecialCharacters = "\[^$.|?*+()"
- bFound = False
- If IsMissing(pvTarget) Or IsMissing(pvStartLine) Or IsMissing(pvStartColumn) Or IsMissing(pvEndLine) Or IsMissing(pvEndColumn) Then Call _TraceArguments()
- If Not Utils._CheckArgument(pvTarget, 1, vbString) Then GoTo Exit_Function
- If Len(pvTarget) = 0 Then GoTo Exit_Function
- If Not IsEmpty(pvStartLine) Then
- If Not Utils._CheckArgument(pvStartLine, 2, _AddNumeric()) Then GoTo Exit_Function
- End If
- If Not IsEmpty(pvStartColumn) Then
- If Not Utils._CheckArgument(pvStartColumn, 3, _AddNumeric()) Then GoTo Exit_Function
- End If
- If Not IsEmpty(pvEndLine) Then
- If Not Utils._CheckArgument(pvEndLine, 4, _AddNumeric()) Then GoTo Exit_Function
- End If
- If Not IsEmpty(pvEndColumn) Then
- If Not Utils._CheckArgument(pvEndColumn, 5, _AddNumeric()) Then GoTo Exit_Function
- End If
- If IsMissing(pvWholeWord) Then pvWholeWord = False
- If Not Utils._CheckArgument(pvWholeWord, 6, vbBoolean) Then GoTo Exit_Function
- If IsMissing(pvMatchCase) Then pvMatchCase = False
- If Not Utils._CheckArgument(pvMatchCase, 7, vbBoolean) Then GoTo Exit_Function
- If IsMissing(pvPatternSearch) Then pvPatternSearch = False
- If Not Utils._CheckArgument(pvPatternSearch, 8, vbBoolean) Then GoTo Exit_Function
- ' Initialize starting values
- If IsEmpty(pvStartLine) Then lStartLine = 1 Else lStartLine = pvStartLine
- If lStartLine <= 0 Or lStartLine > UBound(_Lines) + 1 Then GoTo Exit_Function
- If IsEmpty(pvStartColumn) Then lStartColumn = 1 Else lStartColumn = pvStartColumn
- If lStartColumn <= 0 Then GoTo Exit_Function
- If lStartColumn > 1 And lStartColumn > Len(_Lines(lStartLine + 1)) Then GoTo Exit_Function
- lStartPosition = _PositionOfLine(lStartline) + lStartColumn - 1
- If IsEmpty(pvEndLine) Then lEndLine = UBound(_Lines) + 1 Else lEndLine = pvEndLine
- If lEndLine < lStartLine Or lEndLine > UBound(_Lines) + 1 Then GoTo Exit_Function
- If IsEmpty(pvEndColumn) Then lEndColumn = Len(_Lines(lEndLine - 1)) Else lEndColumn = pvEndColumn
- If lEndColumn < 0 Then GoTo Exit_Function
- If lEndColumn = 0 Then lEndColumn = 1
- If lEndColumn > Len(_Lines(lEndLine - 1)) + 1 Then GoTo Exit_Function
- lEndPosition = _PositionOfLine(lEndline) + lEndColumn - 1
- If pvMatchCase Then
- Set vOptions = _A2B_.SearchOptions
- vOptions.transliterateFlags = 0
- End If
- ' Define pattern to search for
- sPattern = pvTarget
- ' Protect special characters in regular expressions
- For i = 1 To Len(cstSpecialCharacters)
- sSpecChar = Mid(cstSpecialCharacters, i, 1)
- sPattern = Replace(sPattern, sSpecChar, "\" & sSpecChar)
- Next i
- If pvPatternSearch Then sPattern = Replace(Replace(sPattern, "\*", ".*"), "\?", ".")
- If pvWholeWord Then sPattern = "\b" & sPattern & "\b"
- lPosition = lStartPosition
- sMatch = Utils._RegexSearch(_Script, sPattern, lPosition)
- ' Re-establish default options for later searches
- If pvMatchCase Then vOptions.transliterateFlags = com.sun.star.i18n.TransliterationModules.IGNORE_CASE
- ' Found within requested bounds ?
- If sMatch <> "" And lPosition >= lStartPosition And lPosition <= lEndPosition Then
- pvStartLine = _LineOfPosition(lPosition)
- pvStartColumn = lPosition - _PositionOfLine(pvStartLine) + 1
- pvEndLine = _LineOfPosition(lPosition + Len(sMatch) - 1)
- If pvEndLine > pvStartLine Then
- pvEndColumn = lPosition + Len(sMatch) - 1 - _PositionOfLine(pvEndLine)
- Else
- pvEndColumn = pvStartColumn + Len(sMatch) - 1
- End If
- bFound = True
- End If
- Exit_Function:
- Find = bFound
- Utils._ResetCalledSub(cstThisSub)
- Exit Function
- Error_Function:
- TraceError(TRACEABORT, Err, "Module.Find", Erl)
- bFound = False
- GoTo Exit_Function
- End Function ' Find
- REM -----------------------------------------------------------------------------------------------------------------------
- Public Function getProperty(Optional ByVal pvProperty As Variant) As Variant
- ' Return property value of psProperty property name
- Const cstThisSub = "Module.Properties"
- Utils._SetCalledSub(cstThisSub)
- If IsMissing(pvProperty) Then Call _TraceArguments()
- getProperty = _PropertyGet(pvProperty)
- Utils._ResetCalledSub(cstThisSub)
-
- End Function ' getProperty
- REM --------------------------------Mid(a._Script, iCtl, 25)---------------------------------------------------------------------------------------
- Public Function hasProperty(ByVal Optional pvProperty As Variant) As Boolean
- ' Return True if object has a valid property called pvProperty (case-insensitive comparison !)
- Const cstThisSub = "Module.hasProperty"
- Utils._SetCalledSub(cstThisSub)
- If IsMissing(pvProperty) Then hasProperty = PropertiesGet._hasProperty(_Type, _PropertiesList()) Else hasProperty = PropertiesGet._hasProperty(_Type, _PropertiesList(), pvProperty)
- Utils._ResetCalledSub(cstThisSub)
- Exit Function
-
- End Function ' hasProperty
- REM -----------------------------------------------------------------------------------------------------------------------
- REM --- PRIVATE FUNCTIONS ---
- REM -----------------------------------------------------------------------------------------------------------------------
- REM -----------------------------------------------------------------------------------------------------------------------
- Private Function _BeginStatement(ByVal plStart As Long) As Long
- ' Return the position in _Script of the beginning of the current statement as defined by plStart
- Dim sProc As String, iProc As Integer, iType As Integer
- Dim lPosition As Long, lPrevious As Long, sFind As String
- sProc = ProcOfLine(_LineOfPosition(plStart), iType)
- iProc = _FindProcIndex(sProc, iType)
- If iProc < 0 Then lPosition = 1 Else lPosition = _ProcDecPositions(iProc)
- sFind = "Any"
- Do While lPosition < plStart And sFind <> ""
- lPrevious = lPosition
- sFind = _FindPattern("%^\w", lPosition)
- If sFind = "" Then Exit Do
- Loop
- _BeginStatement = lPrevious
- End Function ' _EndStatement
- REM -----------------------------------------------------------------------------------------------------------------------
- Private Function _EndStatement(ByVal plStart As Long) As Long
- ' Return the position in _Script of the end of the current statement as defined by plStart
- ' plStart is assumed not to be in the middle of a comment or a string
- Dim sMatch As String, lPosition As Long
- lPosition = plStart
- sMatch = _FindPattern("%$", lPosition)
- _EndStatement = lPosition
- End Function ' _EndStatement
- REM -----------------------------------------------------------------------------------------------------------------------
- Private Function _FindPattern(ByVal psPattern As Variant, Optional ByRef plStart As Long) As String
- ' Find first occurrence of any of the patterns in |-delimited string psPattern
- ' Special escapes
- ' - for word breaks: "%B" (f.i. for searching "END%BFUNCTION")
- ' - for statement start: "%^" (f.i. for searching "%^END%BFUNCTION"). Necessarily first 2 characters of pattern
- ' - for statement end: "%$". Pattern should not contain anything else
- ' If quoted string searched, pattern should start and end with a double quote
- ' Return "" if none found, otherwise returns the matching string
- ' plStart = start position of _Script to search (starts at 1)
- ' In output plStart contains the first position of the matching string or is left unchanged
- ' To search again the same or another pattern => plStart = plStart + Len(matching string)
- ' Comments and strings are skipped
- ' Common patterns
- Const cstComment = "('|\bREM\b)[^\n]*$"
- Const cstString = """[^""\n]*"""
- Const cstBeginStatement = "(^|:|\bthen\b|\belse\b|\n)[ \t]*"
- Const cstEndStatement = "[ \t]*($|:|\bthen\b|\belse\b|\n)"
- Const cstContinuation = "[ \t]_\n"
- Const cstWordBreak = "\b[ \t]+(_\n[ \t]*)?\b"
- Const cstAlt = "|"
- Dim sRegex As String, lStart As Long, bContinue As Boolean, sMatch As String
- Dim bEndStatement As Boolean, bQuote As Boolean
- If psPattern = "%$" Then
- sRegex = cstEndStatement
- Else
- sRegex = psPattern
- If Left(psPattern, 2) = "%^" Then sRegex = cstBeginStatement & Right(sRegex, Len(sregex) - 2)
- sregex = Replace(sregex, "%B", cstWordBreak)
- End If
- ' Add all to ignore patterns to regex. If pattern = quoted string do not add cstString
- If Len(psPattern) > 2 And Left(psPattern, 1) = """" And Right(psPattern, 1) = """" Then
- bQuote = True
- sRegex = sRegex & cstAlt & cstComment & cstAlt & cstContinuation
- Else
- bQuote = False
- sRegex = sRegex & cstAlt & cstComment & cstAlt & cstString & cstAlt & cstContinuation
- End If
- If IsMissing(plStart) Then plStart = 1
- lStart = plStart
- bContinue = True
- Do While bContinue
- bEndStatement = False
- sMatch = Utils._RegexSearch(_Script, sRegex, lStart)
- Select Case True
- Case sMatch = ""
- bContinue = False
- Case Left(sMatch, 1) = "'"
- bEndStatement = True
- Case Left(sMatch, 1) = """"
- If bQuote Then
- plStart = lStart
- bContinue = False
- End If
- Case Left(smatch, 1) = ":" Or Left(sMatch, 1) = vbLf
- If psPattern = "%$" Then
- bEndStatement = True
- Else
- bContinue = False
- plStart = lStart + 1
- sMatch = Right(sMatch, Len(sMatch) - 1)
- End If
- Case UCase(Left(sMatch, 4)) = "REM " Or UCase(Left(sMatch, 4)) = "REM" & vbTab Or UCase(Left(sMatch, 4)) = "REM" & vbNewLine
- bEndStatement = True
- Case UCase(Left(sMatch, 4)) = "THEN" Or UCase(Left(sMatch, 4)) = "ELSE"
- If psPattern = "%$" Then
- bEndStatement = True
- Else
- bContinue = False
- plStart = lStart + 4
- sMatch = Right(sMatch, Len(sMatch) - 4)
- End If
- Case sMatch = " _" & vbLf
- Case Else ' Found
- plStart = lStart
- bContinue = False
- End Select
- If bEndStatement And psPattern = "%$" Then
- bContinue = False
- plStart = lStart - 1
- sMatch = ""
- End If
- lStart = lStart + Len(sMatch)
- Loop
-
- _FindPattern = sMatch
- End Function ' _FindPattern
- REM -----------------------------------------------------------------------------------------------------------------------
- Private Function _FindProcIndex(ByVal psProc As String, ByVal piType As Integer) As Integer
- ' Return index of entry in _Procnames corresponding with pvProc
- Dim i As Integer, iIndex As Integer
- If Not _ProcsParsed Then _ParseProcs
- iIndex = -1
- For i = 0 To UBound(_ProcNames)
- If UCase(psProc) = UCase(_ProcNames(i)) And piType = _ProcTypes(i) Then
- iIndex = i
- Exit For
- End If
- Next i
- If iIndex < 0 Then TraceError(TRACEFATAL, ERRPROCEDURENOTFOUND, Utils._CalledSub(), 0, , Array(psProc, _Name))
- Exit_Function:
- _FindProcIndex = iIndex
- Exit Function
- End Function ' _FindProcIndex
- REM -----------------------------------------------------------------------------------------------------------------------
- Public Sub _Initialize()
- _Script = Replace(_Script, vbCr, "")
- _Lines = Split(_Script, vbLf)
- _CountOfLines = UBound(_Lines) + 1
- End Sub ' _Initialize
- REM -----------------------------------------------------------------------------------------------------------------------
- Private Function _LineOfPosition(ByVal plPosition) As Long
- ' Return the line number of a position in _Script
- Dim lLine As Long, lLength As Long
- ' Start counting from start or end depending on how close position is
- If plPosition <= Len(_Script) / 2 Then
- lLength = 0
- For lLine = 0 To UBound(_Lines)
- lLength = lLength + Len(_Lines(lLine)) + 1 ' + 1 for line feed
- If lLength >= plPosition Then
- _LineOfPosition = lLine + 1
- Exit Function
- End If
- Next lLine
- Else
- If Right(_Script, 1) = vbLf Then lLength = Len(_Script) + 1 Else lLength = Len(_Script)
- For lLine = UBound(_Lines) To 0 Step -1
- lLength = lLength - Len(_Lines(lLine)) - 1 ' - 1 for line feed
- If lLength <= plPosition Then
- _LineOfPosition = lLine + 1
- Exit Function
- End If
- Next lLine
- End If
- End Function ' _LineOfPosition
- REM -----------------------------------------------------------------------------------------------------------------------
- Private Sub _ParseProcs()
- ' Fills the Proc arrays: name, start and end position
- ' Executed at first request needing this processing
- Dim lPosition As Long, iProc As Integer, sDecProc As String, sEndProc As String, sNameProc As String, sType As String
- Const cstDeclaration = "%^(private%B|public%B)?\b(property%Bget|property%Blet|property%Bset|function|sub)\b"
- Const cstEnd = "%^end%B(property|function|sub)\b"
- Const cstName = "\w*" '"[A-Za-z_][A-Za-z_0-9]*"
- If _ProcsParsed Then Exit Sub ' Do not redo if already done
- _ProcNames = Array()
- _ProcDecPositions = Array()
- _ProcEndPositions = Array()
- _ProcTypes = Array()
-
- lPosition = 1
- iProc = -1
- sDecProc = "???"
- Do While sDecProc <> ""
- ' Identify Function/Sub declaration string
- sDecProc = _FindPattern(cstDeclaration, lPosition)
- If sDecProc <> "" Then
- iProc = iProc + 1
- ReDim Preserve _ProcNames(0 To iProc)
- ReDim Preserve _ProcDecPositions(0 To iProc)
- ReDim Preserve _ProcEndPositions(0 To iProc)
- ReDim Preserve _ProcTypes(0 To iProc)
- _ProcDecPositions(iProc) = lPosition
- lPosition = lPosition + Len(sDecProc)
- ' Identify procedure type
- Select Case True
- Case InStr(UCase(sDecProc), "FUNCTION") > 0 : _ProcTypes(iProc) = vbext_pk_Proc
- Case InStr(UCase(sDecProc), "SUB") > 0 : _ProcTypes(iProc) = vbext_pk_Proc
- Case InStr(UCase(sDecProc), "GET") > 0 : _ProcTypes(iProc) = vbext_pk_Get
- Case InStr(UCase(sDecProc), "LET") > 0 : _ProcTypes(iProc) = vbext_pk_Let
- Case InStr(UCase(sDecProc), "SET") > 0 : _ProcTypes(iProc) = vbext_pk_Set
- End Select
- ' Identify name of Function/Sub
- sNameProc = _FindPattern(cstName, lPosition)
- If sNameProc = "" Then Exit Do ' Should never happen
- _ProcNames(iProc) = sNameProc
- lPosition = lPosition + Len(sNameProc)
- ' Identify End statement
- sEndProc = _FindPattern(cstEnd, lPosition)
- If sEndProc = "" Then Exit Do ' Should never happen
- _ProcEndPositions(iProc) = lPosition
- lPosition = lPosition + Len(sEndProc)
- End If
- Loop
-
- _ProcsParsed = True
-
- End Sub
- REM -----------------------------------------------------------------------------------------------------------------------
- Private Function _PositionOfLine(ByVal plLine) As Long
- ' Return the position of the first character of the given line in _Script
- Dim lLine As Long, lPosition As Long
- ' Start counting from start or end depending on how close line is
- If plLine <= (UBound(_Lines) + 1) / 2 Then
- lPosition = 0
- For lLine = 0 To plLine - 1
- lPosition = lPosition + 1 ' + 1 for line feed
- If lLine < plLine - 1 Then lPosition = lPosition + Len(_Lines(lLine))
- Next lLine
- Else
- lPosition = Len(_Script) + 2 ' Anticipate an ending null-string and a line feed
- For lLine = UBound(_Lines) To plLine - 1 Step -1
- lPosition = lPosition - Len(_Lines(lLine)) - 1 ' - 1 for line feed
- Next lLine
- End If
- _PositionOfLine = lPosition
- End Function ' _LineOfPosition
- REM -----------------------------------------------------------------------------------------------------------------------
- Private Function _PropertiesList() As Variant
- _PropertiesList = Array("CountOfDeclarationLines", "CountOfLines", "Name", "ObjectType", "Type")
- End Function ' _PropertiesList
- REM -----------------------------------------------------------------------------------------------------------------------
- Private Function _PropertyGet(ByVal psProperty As String) As Variant
- ' Return property value of the psProperty property name
- Dim cstThisSub As String
- Const cstDot = "."
- Dim sText As String
- If _ErrorHandler() Then On Local Error Goto Error_Function
- cstThisSub = "Module.get" & psProperty
- Utils._SetCalledSub(cstThisSub)
- _PropertyGet = Null
-
- Select Case UCase(psProperty)
- Case UCase("CountOfDeclarationLines")
- If Not _ProcsParsed Then _ParseProcs()
- If UBound(_ProcNames) >= 0 Then
- _PropertyGet = ProcStartLine(_ProcNames(0), _ProcTypes(0)) - 1
- Else
- _PropertyGet = _CountOfLines
- End If
- Case UCase("CountOfLines")
- _PropertyGet = _CountOfLines
- Case UCase("Name")
- _PropertyGet = _Storage & cstDot & _LibraryName & cstDot & _Name
- Case UCase("ObjectType")
- _PropertyGet = _Type
- Case UCase("Type")
- ' Find option statement before any procedure declaration
- sText = _FindPattern("%^option%Bclassmodule\b|\bfunction\b|\bsub\b|\bproperty\b")
- If UCase(Left(sText, 6)) = "OPTION" Then _PropertyGet = acClassModule Else _PropertyGet = acStandardModule
- Case Else
- Goto Trace_Error
- End Select
-
- Exit_Function:
- Utils._ResetCalledSub(cstThisSub)
- Exit Function
- Trace_Error:
- TraceError(TRACEFATAL, ERRPROPERTY, Utils._CalledSub(), 0, 1, psProperty)
- _PropertyGet = Nothing
- Goto Exit_Function
- Error_Function:
- TraceError(TRACEABORT, Err, "Module._PropertyGet", Erl)
- _PropertyGet = Null
- GoTo Exit_Function
- End Function ' _PropertyGet
- </script:module>
|