﻿B4J=true
Group=Default Group
ModulesStructureVersion=1
Type=Class
Version=9.1
@EndOfDesignText@
#IgnoreWarnings:12
Sub Class_Globals
    Public Lines As List
    Private indent As Int = 0
    Private linePos As Int
    Private strActual As String
    'Private strTemp As String
    Public SubRoutines As Map
    'Private SubStart As Int
    'Private SubEnd As Int
    'Private SubName As String
    'Private SubCode As String
    Private strCode As String
    Private banano As BANano  'ignore
    Public Properties As List
    Public Signatures As List
    Public Events As List
    Private collection As BANanoCollectJS
    Public ClassGlobalsCode As List
    Public InitializeCode As List
    Public CreateViewCode As List
    Public DesignerKeys As Map
    Public Comments As List
    Public IsDirty As Boolean
    Public Transactions As String
    Public ThisCode As StringBuilder
    Private CRLF1 As String = Chr(13) & Chr(10)
End Sub
'prepare the file for saving
Sub RefreshWait As Boolean
    'join the lines for the transaction file
    Lines = banano.Await(RemoveLinesWait("",True))
    Transactions = Join(CRLF1, Lines)
    Return True
End Sub
'insert lines, does not refresh
Sub InsertLines(newLines As List)
    For Each nline As String In newLines
        Lines.Add(nline)
    Next
End Sub
'replace a line, does not refresh
Sub ReplaceLine(pos As Int, newLine As String)
    Lines.Set(pos, newLine)
End Sub
'delete lines, does not refresh
Sub DeleteLines(startPos As Int, numLines As Int)
    Dim endPos As Int = startPos + numLines
    Dim di As Int
    For di = startPos To endPos
        Lines.Set(di, "")
    Next
    Lines = banano.Await(RemoveLinesWait("",True))
End Sub
'add content from a string
Sub AddFromString(strValue As String)
    Lines.Add(strValue)
End Sub
'initialize the source code and prepare it for use
'this removes any line continuation on the
'source code
'<code>
'ch.Initialize
'BANano.Await(ch.ScanWait(sourceCode))
'BANano.Await(ch.BeautifyWait)
'return ch.Transactions
'</code>
Public Sub Initialize()
    IsDirty = False
    Properties.Initialize
    Signatures.Initialize
    Events.Initialize
    ClassGlobalsCode.Initialize
    InitializeCode.Initialize
    CreateViewCode.Initialize
    DesignerKeys.Initialize
    Comments.Initialize
    Lines.Initialize
End Sub
'
'Sub AddEvent(sCode As String) As Boolean
'	If BANanHasEvent(sCode) = False Then
'		Events.Add(sCode)
'		IsDirty = True
'		Return True
'	End If
'	Return False
'End Sub
'
'Sub DeleteEvent(scode As String) As Boolean
'	If HasEvent(scode) = False Then Return True
'	Dim idxPos As Int = Events.IndexOf(scode)
'	Events.RemoveAt(idxPos)
'	IsDirty = True
'	Return Not(HasEvent(scode))
'End Sub
'
'Sub AddPropertyWait(sCode As String) As Boolean
'	If HasPropertyWait(sCode) = False Then
'		Properties.Add(sCode)
'		IsDirty = True
'		'parse the property
'		Return True
'	End If
'	Return False
'End Sub
'
'Sub DeleteProperty(scode As String) As Boolean
'	If HasPropertyWait(scode) = False Then Return True
'	Dim idxPos As Int = Properties.IndexOf(scode)
'	Properties.RemoveAt(idxPos)
'	IsDirty = True
'	Return Not(HasPropertyWait(scode))
'End Sub
'scan the source code
Sub ScanWait(sourceCode As String) As Boolean
    strCode = sourceCode
    If strCode.trim.Length = 0 Then Return False
    Lines = StrParse(CRLF1, strCode)
    indent = 0
    linePos = 0
    strActual = ""
    'strTemp = ""
    'trim all lines in the code
    banano.Await(TrimLinesWait)
    'remove all empty lines
    Lines = banano.Await(RemoveLinesWait("",True))
    'remove all line continuations
    'banano.Await(RemoveLineContinuationWait)
    'we will the collection for most things
    collection.Initialize(Me, Lines)
    'scan all event definitions
    banano.Await(ScanEventsWait)
    'scan for designer properties
    banano.Await(ScanPropertiesWait)
    'scan subroutines
    banano.Await(ScanSubRoutinesWait)
    'scan for class globals
    ClassGlobalsCode = banano.Await(GetSubRoutineCodeWait("Class_Globals"))
    InitializeCode = banano.Await(GetSubRoutineCodeWait("Initialize"))
    CreateViewCode = banano.Await(GetSubRoutineCodeWait("DesignerCreateView"))
    'scan comments
    banano.Await(ScanCommentsWait)
    'join the lines for the transaction file
    Transactions = Join(CRLF1, Lines)
    Return True
End Sub
'see if we can get the lines
Sub GetLinesWait As List
    Return Lines
End Sub
'determine if the create view code has some code line
Sub HasCreateViewWait(sFind As String) As Boolean
    Dim subIdx As Long = CreateViewCode.IndexOf(sFind)
    If subIdx = -1 Then Return False
    Return True
End Sub
'determine if the properties code has some code line
Sub HasPropertyWait(sFind As String) As Boolean
    Dim subIdx As Long = Properties.IndexOf(sFind)
    If subIdx = -1 Then Return False
    Return True
End Sub
'determine if the class globals code has some code line
Sub HasClassGlobalsWait(sFind As String) As Boolean
    Dim subIdx As Long = ClassGlobalsCode.IndexOf(sFind)
    If subIdx = -1 Then Return False
    Return True
End Sub
'Has a signature
Sub HasSignatureWait(sStuff As String) As Boolean
    Dim subIdx As Long = Signatures.IndexOf(sStuff)
    If subIdx = -1 Then Return False
    Return True
End Sub
'Has an event
Sub HasEventWait(sStuff As String) As Boolean
    Dim subIdx As Long = Events.IndexOf(sStuff)
    If subIdx = -1 Then Return False
    Return True
End Sub
'has a subroutine
Sub HasSubRoutineWait(sSubName As String) As Boolean
    Return SubRoutines.ContainsKey(sSubName)
End Sub
'find the position of a particular sub signature.
private Sub SignaturePositionWait(signature As String) As Long
    Dim pos As Object = collection.searchStrict(signature)
    If pos = False Then Return -1
    Return pos
End Sub
'scan the class globals code
private Sub ScanClassGlobalsWait As Boolean
    ClassGlobalsCode = banano.Await(GetSubRoutineCodeWait("Class_Globals"))
    Return True
End Sub
'returns a map with code and signature items
Sub GetSubRoutineWait(sSubName As String) As Map
    Dim m As Map = CreateMap()
    If SubRoutines.ContainsKey(sSubName) Then
        m = SubRoutines.Get(sSubName)
    End If
    Return m
End Sub
'return code of a particular subroutine
Sub GetSubRoutineCodeWait(sSubName As String) As List
    Dim m As List
    m.Initialize
    If SubRoutines.ContainsKey(sSubName) Then
        Dim sb As Map = SubRoutines.Get(sSubName)
        m = sb.Get("code")
    End If
    Return m
End Sub
'scan all comments
private Sub ScanCommentsWait As Boolean
    Comments.Initialize
    For Each strline As String In Lines
        If strline.StartsWith("'") Then
            Comments.Add(strline)
        End If
    Next
    Return True
End Sub
'scan a subroutine code from this position
Sub ScanSubRoutineWait(startPos As Int) As List
    Dim sb As List
    sb.Initialize
    '
    Dim startString As String = collection.getValueAt(startPos)
    sb.add(startString)
    Dim bFound As Boolean = False
    Dim nPos As Int = startPos + 1
    Do Until bFound = True
        Dim nString As String = collection.getValueAt(nPos)
        sb.add(nString)
        If nString = "End Sub" Then
            bFound = True
        End If
        nPos = nPos + 1
    Loop
    Return sb
End Sub
'scan code starting at pos and ending a pos
Sub ScanCodeEndingWait(startPos As Int, endsWith1 As String) As Long
    Dim sb As List
    sb.Initialize
    '
    Dim startString As String = collection.getValueAt(startPos)
    sb.add(startString)
    Dim bFound As Boolean = False
    Dim nPos As Int = startPos + 1
    Do Until bFound = True
        Dim nString As String = collection.getValueAt(nPos)
        sb.add(nString)
        If nString = endsWith1 Then
            bFound = True
        End If
        nPos = nPos + 1
    Loop
    Dim endLoc As Long = startPos + sb.size
    Return endLoc
End Sub
'sort a map by key
private Sub SortMap(m As Map) As Map
    Dim nm As Map
    nm.Initialize
    Dim lst As List
    lst.Initialize
    For Each strkey As String In m.Keys
        lst.Add(strkey)
    Next
    'sort the list keys
    lst.Sort(True)
    For Each strkey As String In lst
        Dim strvalue As Object = m.Get(strkey)
        nm.Put(strkey,strvalue)
    Next
    Return nm
End Sub
'join a list by delimiter
private Sub Join(Delimiter As String, lst As List) As String
    Return MvFromList(lst,Delimiter)
End Sub
'build a multi-value string from a list
private Sub MvFromList(lst As List, Delim As String) As String
    Dim lTot As Int
    Dim lCnt As Int
    Dim lStr As StringBuilder
    lStr.Initialize
    lTot = lst.Size - 1
    For lCnt = 0 To lTot
        lStr.Append(lst.Get(lCnt))
        If lCnt <> lTot Then lStr.Append(Delim)
    Next
    Return lStr.tostring
End Sub
'return the number of lines of code
private Sub Code_CountLines As Long
    Return Lines.Size - 1
End Sub
'private Sub ConfirmCase(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    'Confirm that we are handling 'Next' at the end of a conditional operation
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 4 Then
'        Return False
'    Else if tLen = 4 Then
'        If Left1(Tempstring, 4) = "case" Then Return True
'    Else if tLen > 4 Then
'        If Left1(Tempstring, 5) = "case " Then Return True
'    End If
'    Return False
'End Sub
'return the left part of a string
private Sub Left1(Text As String, xLength As Long) As String
    If xLength>Text.Length Then xLength=Text.Length
    Return Text.SubString2(0, xLength)
End Sub
' return length of a string
private Sub Len1(Text As String) As Long
    Return Text.Length
End Sub
'trim a string
private Sub Trim1(strValue As String) As String
    Return strValue.trim
End Sub
'lowercase a string
private Sub LCase1(Text As String) As String
    Return Text.ToLowerCase
End Sub
'return the position of a string found in a string
private Sub InStr1(Text As String, sFind As String) As Int
    Return Text.tolowercase.IndexOf(sFind.tolowercase) + 1
End Sub
'remove lines containing a string
private Sub RemoveLinesWait(StrSearch As String, ExactMatch As Boolean) As List
    Dim nLines As List
    nLines.Initialize
    Dim totLines As Long
    Dim cntLines As Long
    Dim curLine As String
    totLines = Lines.size - 1
    For cntLines = 0 To totLines
        curLine = Lines.Get(cntLines)
        If ExactMatch = True Then
            If LCase1(StrSearch) = LCase1(curLine) Then
            Else
                nLines.Add(curLine)
            End If
        Else
            If InStr1(LCase1(curLine), LCase1(StrSearch)) > 0 Then
            Else
                nLines.Add(curLine)
            End If
        End If
    Next
    Return nLines
End Sub
'count line continuation
private Sub CountLineContinuation() As Long
    Private totLines As Long
    Private cntLines As Long
    Private curLine As String
    Private LC As Long = 0
    totLines = Lines.Size - 1
    For cntLines = totLines To 0 Step -1
        curLine = Lines.Get(cntLines)
        curLine = curLine.Trim
        If Right1(curLine,1) = "_" Then
            LC = LC + 1
        End If
    Next
    Return LC
End Sub
'trim all lines in this file
private Sub TrimLinesWait As Boolean
    Dim totLines As Long
    Dim cntLines As Long
    Dim curLine As String
    totLines = Lines.Size - 1
    For cntLines = 0 To totLines
        curLine = Lines.get(cntLines)
        curLine = Trim1(curLine)
        Lines.Set(cntLines, curLine)
    Next
    Return True
End Sub
'private Sub ConfirmIf(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    'Confirm that we are handling the 'If' conditional operator
'    If Left1(Tempstring,3) = "if " Then
'        If Right1(Tempstring,4) = "then" Then Return True
'    End If
'    If Left1(Tempstring,4) = "#if " Then
'        If Right1(Tempstring,7) = "release" Then Return True
'        If Right1(Tempstring,5) = "debug" Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmEnd(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    'Confirm that we are handling a routine 'End' operator
'    If Left1(Tempstring, 7) = "#end if" Then Return True
'    If Left1(Tempstring, 11) = "#end region" Then Return True
'    If Left1(Tempstring, 6) = "end if" Then Return True
'    If Left1(Tempstring, 7) = "end sub" Then Return True
'    If Left1(Tempstring, 7) = "end try" Then Return True
'    If Left1(Tempstring, 10) = "end select" Then Return True
'    Return False
'End Sub
'Private Sub ConfirmDo(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    'Confirm that we are handling the start of a 'Do' loop operation
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen = 2 Then
'        If Tempstring = "do" Then Return True
'    else if tLen > 2 Then
'        If Left1(Tempstring, 3) = "do " Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmLoop(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    'Confirm that we are handling the end of a do 'Loop' operation
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 4 Then
'        Return False
'    else if tLen = 4 Then
'        If Left1(Tempstring, 4) = "loop" Then Return True
'    else if tLen > 4 Then
'        If Left1(Tempstring, 5) = "loop " Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmCatch(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    'Confirm that we are handling a 'Catch' point in a Try / End Try operation
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen = 5 Then
'        If Left1(Tempstring, 5) = "catch" Then Return True
'    else if tLen < 5 Then
'        Return False
'    else if tLen > 6 Then
'        If Left1(Tempstring, 6) = "catch " Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmNext(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    'Confirm that we are handling 'Next' at the end of a conditional operation
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 4 Then
'        Return False
'    else if tLen = 4 Then
'        If Left1(Tempstring, 4) = "next" Then Return True
'    else if tLen > 4 Then
'        If Left1(Tempstring, 5) = "next " Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmElse(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    'Confirm that we are handling the 'Else' part of an If End if conditional operation
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 4 Then
'        Return False
'    else if tLen = 4 Then
'        If Left1(Tempstring, 4) = "else" Then Return True
'    else if tLen > 4 Then
'        If Left1(Tempstring, 5) = "else " Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmElse1(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    'Confirm that we are handling the 'Else' part of an If End if conditional operation
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 5 Then
'        Return False
'    else if tLen = 5 Then
'        If Left1(Tempstring, 5) = "#else" Then Return True
'    else if tLen > 5 Then
'        If Left1(Tempstring, 6) = "#else " Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmRegion(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    'Confirm that we are handling the 'Else' part of an If End if conditional operation
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 7 Then
'        Return False
'    else if tLen = 7 Then
'        If Left1(Tempstring, 5) = "#region" Then Return True
'    else if tLen > 7 Then
'        If Left1(Tempstring, 8) = "#region " Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmEndRegion(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    'Confirm that we are handling the 'Else' part of an If End if conditional operation
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 11 Then
'        Return False
'    else if tLen = 11 Then
'        If Left1(Tempstring, 11) = "#end region" Then Return True
'    else if tLen > 11 Then
'        If Left1(Tempstring, 11) = "#end region " Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmSelect(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 7 Then
'        Return False
'    else if tLen >= 7 Then
'        If Left1(Tempstring, 7) = "select " Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmTry(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 3 Then
'        Return False
'    else if tLen = 3 Then
'        If Left1(Tempstring, 3) = "try" Then Return True
'    else if tLen > 3 Then
'        If Left1(Tempstring, 4) = "try " Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmFor(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 3 Then
'        Return False
'    else if tLen = 3 Then
'        If Left1(Tempstring, 3) = "for" Then Return True
'    else if tLen > 3 Then
'        If Left1(Tempstring, 4) = "for " Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmSub(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 3 Then
'        Return False
'    else if tLen = 3 Then
'        If Left1(Tempstring, 3) = "sub" Then Return True
'    else if tLen > 3 Then
'        If Left1(Tempstring, 4) = "sub " Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmPrivateSub(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 10 Then
'        Return False
'    else if tLen = 10 Then
'        If Left1(Tempstring, 11) = "private sub" Then Return True
'    else if tLen > 10 Then
'        If Left1(Tempstring, 12) = "private sub " Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmEndSub(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 7 Then
'        Return False
'    else if tLen = 7 Then
'        If Left1(Tempstring, 7) = "end sub" Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmEndSelect(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 10 Then
'        Return False
'    else if tLen = 10 Then
'        If Left1(Tempstring, 10) = "end select" Then Return True
'    End If
'    Return False
'End Sub
'private Sub ConfirmPublicSub(Tempstring As String) As Boolean
'    Tempstring = Tempstring.Trim.tolowercase
'    Dim tLen As Int = Len1(Tempstring)
'    If tLen < 10 Then
'        Return False
'    else if tLen = 10 Then
'        If Left1(Tempstring, 10) = "public sub" Then Return True
'    else if tLen > 10 Then
'        If Left1(Tempstring, 11) = "public sub " Then Return True
'    End If
'    Return False
'End Sub

'get code between this and that line
private Sub GetBetweenLines(intStart As Int, intEnd As Int) As String
    Dim sb As StringBuilder
    sb.Initialize
    For iStart = intStart To intEnd
        sb.Append(Lines.Get(iStart))
        sb.Append(CRLF1)
    Next
    Return sb.tostring
End Sub
'get a clean sub-routine name
private Sub GetSubName(strDeclaration As String, bIncludeBrackets As Boolean) As String
    Dim fBracket As Int
    Dim sBracket As Int
    Dim sResult As String
    strDeclaration = strDeclaration.trim
    fBracket = InStr1(strDeclaration, "(")
    sBracket = InStrRev(strDeclaration, ")")
    If fBracket > 0 Then
        sResult = Left1(strDeclaration, fBracket - 1)
    Else
        sResult = strDeclaration
    End If
    If bIncludeBrackets = True Then
        sResult = sResult & "()"
    End If
    If sBracket > 0 Then
        sResult = sResult & Mid1(strDeclaration, sBracket + 1)
    End If
    If sResult.tolowercase.StartsWith("sub ") Then
        sResult = Mid1(sResult,5)
        sResult = sResult.trim
    else if sResult.tolowercase.StartsWith("private sub ") Then
        sResult = Mid1(sResult,13)
    else if sResult.tolowercase.StartsWith("public sub ") Then
        sResult = Mid1(sResult,12)
    End If
    sResult = sResult.trim
    sResult = MvField(sResult,1," ")
    Return sResult
End Sub
'convert object to string
Sub CStr(o As Object) As String
	If banano.isnull(o) Or banano.IsUndefined(o) Then o = ""
	If o = "null" Then Return ""
	If o = "undefined" Then Return ""
	Return "" & o
End Sub
'parse a string
private Sub StrParse(delim As String, inputString As String) As List
    Dim nl As List
    nl.Initialize
    inputString = CStr(inputString)
    If banano.IsNull(inputString) Or banano.IsUndefined(inputString) Then inputString = ""
    If inputString = "" Then Return nl
    If inputString.IndexOf(delim) = -1 Then
        nl.Add(inputString)
    Else
        nl = banano.Split(delim,inputString)
    End If
    Return nl
End Sub
'mvfield sub
private Sub MvField(sValue As String, iPosition As Int, Delimiter As String) As String
    If sValue.Length = 0 Then Return ""
    Dim xPos As Int = sValue.IndexOf(Delimiter)
    If xPos = -1 Then Return sValue
    Dim mValues As List = StrParse(Delimiter,sValue)
    Dim tValues As Int
    tValues = mValues.size -1
    Select Case iPosition
    Case -1
        Return mValues.get(tValues)
    Case -2
        Return mValues.get(tValues - 1)
    Case -3
        Dim sb As StringBuilder
        sb.Initialize
        Dim startcnt As Int
        sb.Append(mValues.Get(1))
        For startcnt = 2 To tValues
            sb.Append(Delimiter)
            sb.Append(mValues.get(startcnt))
        Next
        Return sb.tostring
    Case Else
        iPosition = iPosition - 1
        If iPosition <= -1 Then
            Return mValues.get(tValues)
        End If
        If iPosition > tValues Then
            Return ""
        End If
        Return mValues.get(iPosition)
    End Select
End Sub
'string reverse finder
private Sub InStrRev(value As String, search As String) As Long
    Return value.tolowercase.LastIndexOf(search.tolowercase) + 1
End Sub
'private Sub SplitWords(s As String) As String()
'    Return Regex.Split(s, "\W+")
'End Sub
'remove line continuation
private Sub RemoveLineContinuationWait() As Boolean
    Dim tLines As Long
    Dim tCount As Long
    Dim currLine As String
    Dim NextLine As String
    tLines = Lines.Size - 2
    For tCount = 0 To tLines
        currLine = Lines.Get(tCount)
        NextLine = Lines.Get(tCount + 1)
        If Right1(currLine, 1) = "_" Then
            If Len1(currLine) + Len1(NextLine) < 255 Then
                currLine = Left1(currLine, Len1(currLine-1)) & " " & NextLine
                Lines.Set(tCount,currLine)
                Lines.Set(tCount + 1,"")
            End If
        End If
    Next
    Return True
End Sub
'mid
private Sub Mid2(Text As String, Start As Int, xLength As Int) As String
    Return Text.SubString2(Start-1,Start+xLength-1)
End Sub
'mid
private Sub Mid1(Text As String, Start As Int) As String
    Return Text.SubString(Start-1)
End Sub
'right
private Sub Right1(Text As String, xLength As Long) As String
    If xLength>Text.Length Then xLength=Text.Length
    Return Text.SubString(Text.Length-xLength)
End Sub
'parse and create designer property list
private Sub ParsePropertiesWait(propLines As List) As Boolean
    DesignerKeys.Initialize
    For Each dprop As String In propLines
        Dim prop As Map = banano.Await(ParseDesignerKeyCodeWait(dprop))
        Dim skey As String = prop.Get("key")
        DesignerKeys.Put(skey, prop)
    Next
    Return True
End Sub
'keys from designer properties
Sub GetKeyFromDesignerCodeWait(scode As String) As String
    Dim m As Map = banano.Await(ParseDesignerKeyCodeWait(scode))
    Dim skey As String = m.Get("key")
    Return skey
End Sub
'parse designer properties
Sub ParseDesignerKeyCodeWait(sCode As String) As Map
    sCode = sCode.Replace("#DesignerProperty:","")
    sCode = sCode.trim
    Dim propitems As List = StrParse(",", sCode)
    'create a new map for your property
    Dim prop As Map = CreateMap()
    '
    For Each stritem As String In propitems
        stritem = stritem.Trim
        Dim fp As String = MvField(stritem, 1, ":")
        Dim sp As String = MvField(stritem, 2, ":")
        fp = fp.Trim
        fp = fp.tolowercase
        sp = sp.Trim
        prop.Put(fp, sp)
    Next
    Return prop
End Sub
'has a designer key
Sub HasDesignerKeyWait(propKey As String) As Boolean
    Return DesignerKeys.ContainsKey(propKey)
End Sub
'Scan all Events in the source code and assign to events
private Sub ScanEventsWait As Boolean
    Events.Initialize
    For Each strline As String In Lines
        If strline.StartsWith("#Event:") Then
            Events.Add(strline)
        End If
    Next
    Return True
End Sub
'Scan all Events in the source code
private Sub ScanPropertiesWait As Boolean
    Properties.Initialize
    For Each strline As String In Lines
        If strline.StartsWith("#DesignerProperty:") Then
            Properties.Add(strline)
        End If
    Next
    'parse these and create an object array
    banano.Await(ParsePropertiesWait(Properties))
    Return True
End Sub
'scan subroutines
private Sub ScanSubRoutinesWait As Boolean
    Signatures.Initialize
    SubRoutines.Initialize
    'build the signatures first
    For Each strline As String In Lines
        Dim strOriginal As String = strline
        strline = strline.ToLowerCase
        If strline.StartsWith("sub ") Then
            Dim sSubName As String = GetSubName(strOriginal, False)
            Signatures.Add(strOriginal)
            Dim thissub As Map = CreateMap()
            thissub.Put("signature", strOriginal)
            thissub.Put("arguments", Arguements(strOriginal))
            SubRoutines.Put(sSubName, thissub)
            Continue
        End If
        If strline.StartsWith("private sub ") Then
            Dim sSubName As String = GetSubName(strOriginal, False)
            Signatures.Add(strOriginal)
            Dim thissub As Map = CreateMap()
            thissub.Put("signature", strOriginal)
            thissub.Put("arguments", Arguements(strOriginal))
            SubRoutines.Put(sSubName, thissub)
            Continue
        End If
        If strline.StartsWith("public sub ") Then
            Dim sSubName As String = GetSubName(strOriginal, False)
            Signatures.Add(strOriginal)
            Dim thissub As Map = CreateMap()
            thissub.Put("signature", strOriginal)
            thissub.Put("arguments", Arguements(strOriginal))
            SubRoutines.Put(sSubName, thissub)
            Continue
        End If
    Next
    'get the code for each signature
    'loop through each sub and save the code
    For Each sSubName As String In SubRoutines.Keys
        Dim subroutine As Map = SubRoutines.Get(sSubName)
        Dim sig As String = subroutine.get("signature")
        'get start of the source code of the
        Dim gpos As Long = banano.Await(SignaturePositionWait(sig))
        Dim cgcode As List
        cgcode.Initialize
        If gpos = -1 Then
        Else
            'get the source code
            cgcode = banano.Await(ScanSubRoutineWait(gpos))
        End If
        subroutine.Put("code", cgcode)
        SubRoutines.Put(sSubName, subroutine)
    Next
    Return True
End Sub
'gets the variable names from sub signature
private Sub CleanArguements(strArgue As String) As String
    If strArgue.Length = 0 Then
        Return ""
    End If
    Dim lst As List
    lst.Initialize
    Dim spArgue As List = StrParse(",", strArgue)
    For Each strLine As String In spArgue
        strLine = strLine.trim
        Dim proptype As String = MvField(strLine,3," ")
        Dim propname As String = MvField(strLine,1," ")
        proptype = proptype.Trim
        propname = propname.trim
        lst.Add(propname)
    Next
    Return MvFromList(lst,",")
End Sub
'private Sub Translate()
'	Dim y As Int
'	strActual = Lines.Get(linePos)
'	strActual = strActual.trim
'	For y = 0 To indent - 1
'		strActual = TAB & strActual
'	Next
'	strTemp = strActual.Trim.tolowercase
'	'strTemp = Code_CommentStrip(strTemp)
'	If Len1(strTemp) < 2 Then
'		Code_Writer
'		Return
'	End If
'	Select Case Left1(strTemp,2)
'	Case "#r"
'		If ConfirmRegion(strTemp) Then
'			Code_AddTab
'		Else
'			Code_Writer
'		End If
'	Case "#i"
'		If ConfirmIf(strTemp) Then
'			Code_AddTab
'		Else
'			Code_Writer
'		End If
'	Case "if"
'		If ConfirmIf(strTemp) Then
'			Code_AddTab
'		Else
'			Code_Writer
'		End If
'	Case "en"
'		If ConfirmEnd(strTemp) = True Then
'			If ConfirmEndSub(strTemp) = True Then
'				Code_DelTab
'				SubEnd = linePos
'				SubCode = GetBetweenLines(SubStart,SubEnd)
'				SubRoutines.Put(SubName,SubCode)
'				Exit
'			End If
'			If ConfirmEndSelect(strTemp) Then
'				indent = indent - 1
'				If strActual.SubString2(0, 1) = TAB Then
'					strActual = strActual.Substring2(1, strActual.Length)
'				End If
'				Code_DelTab
'				Exit
'			End If
'			Code_DelTab
'		Else
'			Code_Writer
'		End If
'	Case "su"
'		If ConfirmSub(strTemp) = True Then
'			indent = 0
'			Code_AddTab
'			SubStart = linePos
'			SubDeclaration = strActual
'			SubName = GetSubName(strActual,False)
'		Else
'			Code_Writer
'		End If
'	Case "pr"
'		If ConfirmPrivateSub(strTemp) = True Then
'			indent = 0
'			Code_AddTab
'			SubStart = linePos
'			SubDeclaration = strActual
'			SubName = GetSubName(strActual,False)
'		Else
'			Code_Writer
'		End If
'	Case "pu"
'		If ConfirmPublicSub(strTemp) = True Then
'			indent = 0
'			Code_AddTab
'			SubStart = linePos
'			SubDeclaration = strActual
'			SubName = GetSubName(strActual,False)
'		Else
'			Code_Writer
'		End If
'	Case "fo"
'		If ConfirmFor(strTemp) = True Then
'			Code_AddTab
'		Else
'			Code_Writer
'		End If
'	Case "do"
'		If ConfirmDo(strTemp) = True Then
'			Code_AddTab
'		Else
'			Code_Writer
'		End If
'	Case "lo"
'		If ConfirmLoop(strTemp) = True Then
'			Code_DelTab
'		Else
'			Code_Writer
'		End If
'	Case "ne"
'		If ConfirmNext(strTemp) = True Then
'			Code_DelTab
'		Else
'			Code_Writer
'		End If
'	Case "#e"
'		If ConfirmEnd(strTemp) = True Then
'			Code_DelTab
'			Exit
'		End If
'		If ConfirmElse1(strTemp) = True Then
'			Code_DelTab
'			indent = indent + 1
'			Exit
'		End If
'		If ConfirmEndRegion(strTemp) = True Then
'			Code_DelTab
'			Exit
'		End If
'		Code_Writer
'	Case "el"
'		If ConfirmElse(strTemp) = True Then
'			Code_DelTab
'			indent = indent + 1
'		Else
'			Code_Writer
'		End If
'	Case "se"
'		If ConfirmSelect(strTemp) = True Then
'			SelStart = True
'			Code_AddTab
'		Else
'			Code_Writer
'		End If
'	Case "ca"
'		If ConfirmCase(strTemp) = True Then
'			If SelStart Then
'				Code_AddTab
'				SelStart = False
'			Else
'				Code_DelTab
'				indent = indent + 1
'			End If
'			Exit
'		End If
'
'		If ConfirmCatch(strTemp) = True Then
'			Code_DelTab
'			indent = indent + 1
'			Exit
'		End If
'		Code_Writer
'		Exit
'	Case "tr"
'		If ConfirmTry(strTemp) = True Then
'			Code_AddTab
'		Else
'			Code_Writer
'		End If
'	Case Else
'		Code_Writer
'	End Select
'End Sub
'
'code writing
private Sub Code_Writer
    Lines.Set(linePos,strActual)
End Sub
'add a tab to code
private Sub Code_AddTab
    indent = indent + 1
    Code_Writer
End Sub
'code delete tab
private Sub Code_DelTab
    indent = indent - 1
    If strActual.SubString2(0, 1) = TAB Then
        strActual = strActual.Substring2(1, strActual.Length)
    End If
    Code_Writer
End Sub
'get a declaration from sugnature
private Sub GetDeclaration(decl As String) As String
    decl = decl.Replace("Public ","")
    decl = decl.Replace("Private ","")
    decl = decl.Replace("public ","")
    decl = decl.Replace("private ","")
    decl = decl.Replace("sub ","")
    decl = decl.Replace("Sub ","")
    decl = decl.Trim
    Return decl
End Sub
'strip comments
private Sub CommentStrip(Tempstring As String) As String
    Dim iSingQuote As Int
    Dim iQUOTE As Int
    If Tempstring.Contains("'") Then
        iSingQuote = Tempstring.LastIndexOf("'")
        Do While iSingQuote > 0
            iSingQuote = Tempstring.LastIndexOf("'")
            iQUOTE = Tempstring.LastIndexOf(QUOTE)
            If iSingQuote > iQUOTE Then
                Tempstring = Tempstring.SubString2(0, Tempstring.LastIndexOf("'"))
                Tempstring = Tempstring.Trim
            Else
                Exit
            End If
        Loop
        Return Tempstring
    Else
        Return Tempstring
    End If
End Sub
'spacer
private Sub Space(HM As Int) As String
    Dim RS As String = ""
    Do While Len1(RS) < HM
        RS = RS & " "
    Loop
    Return RS
End Sub
'get arguments from a declaration
private Sub Arguements(strDeclaration As String) As String
    Dim fBracket As Long
    Dim sBracket As Long
    Dim line As String
    'first first bracket
    fBracket = InStr1(strDeclaration, "(")
    'find last bracket
    sBracket = InStrRev(strDeclaration, ")")
    If fBracket = -1 Or sBracket = 0 Then Return ""
    Select Case sBracket
    Case fBracket + 1
        Return ""
    Case Else
        line = Mid2(strDeclaration, fBracket + 1, sBracket - fBracket - 1)
        Return line
    End Select
End Sub
'beautify source code
Public Sub BeautifyWait As Boolean
    Dim nIndent As Int
    Dim nLine As Int
    Dim strNewLine As String
    For nLine = 0 To Lines.Size - 1
        strNewLine = Lines.get(nLine)
        If IsBlockEnd(strNewLine) Then nIndent = nIndent - 1
        If nIndent < 0 Then nIndent = 0
        ' Put back new line.
        Dim xLine As String = Space1(nIndent * 4) & strNewLine
        ReplaceLine(nLine, xLine)
        If IsBlockStart(strNewLine) Then nIndent = nIndent + 1
    Next
    Dim b As Boolean = banano.Await( RefreshWait)
    Return b
End Sub
'Description: Return Space made of number of
'Tags: space
Sub Space1(HM As Int) As String
    Dim RS As String = ""
    Do While Len1(RS) < HM
        RS = RS & " "
    Loop
    Return RS
End Sub
'is block start
Sub IsBlockStart(strLine As String) As Boolean
    Dim bOK As Boolean
    Dim nPos As Int
    Dim strTemp As String
    nPos = InStr1(strLine, " ") - 1
    If nPos < 0 Then nPos = Len1(strLine)
    strTemp = Left1(strLine, nPos)
    strTemp = strTemp.tolowercase
    Select Case strTemp
    Case "for", "do", "while", "select", "case", "else", "#else", "try", "#region", "sub", "catch"
        bOK = True
    Case "if", "#if", "else", "#else"
        'find the posiiton of then
        Dim p1 As Int = Len1(strLine)
        p1 = banano.parseInt(p1)
        Dim p2 As Int = InStr1(strLine.tolowercase, " then")
        p2 = banano.parseInt(p2)
        Dim p3 As Int = p2 + 4
        p3 = banano.parseInt(p3)
        bOK = (p1 = p3)
    Case "private", "public"
        If strLine.ToLowerCase.StartsWith("private sub ") Then bOK = True
        If strLine.ToLowerCase.StartsWith("public sub ") Then bOK = True
        '			Dim p1 As Int = Len1(strTemp)
        '			p1 = banano.parseInt(p1)
        '			Dim p2 As Int = InStr2(nPos + 1, strLine, " ")
        '			p2 = banano.parseInt(p2)
        '			nPos = InStr2(p1 + 1, strLine, " ")
        '			nPos = banano.parseInt(nPos)
        '			Select Case Mid2(strLine, nPos + 1, p2 - nPos - 1)
        '				Case "Sub"
        '					bOK = True
        '			End Select
    End Select
    Return bOK
End Sub
'instr
Sub InStr2(iStart As Int, Text As String, sFind As String) As Int
    Return Text.IndexOf2(sFind, iStart) + 1
End Sub
'Description: Replace a string within a string
'Tags: Replace function, string
Sub Replace1(Text As String, sFind As String, sReplaceWith As String) As String
    Return Text.Replace(sFind, sReplaceWith)
End Sub
'Description: Return a string in uppercase
'Tags: upper case, ucase
Sub UCase1(Text As String) As String
    Return Text.ToUpperCase
End Sub
'is block end
Sub IsBlockEnd(strLine As String) As Boolean
    Dim bOK As Boolean
    Dim nPos As Int
    Dim strTemp As String
    nPos = InStr1(strLine, " ") - 1
    If nPos < 0 Then nPos = Len1(strLine)
    nPos = banano.parseInt(nPos)
    '
    strTemp = Left1(strLine, nPos)
    strTemp = strTemp.ToLowerCase
    Select Case strTemp
    Case "next", "loop", "case", "else", "#else", "#end", "catch"
        bOK = True
    Case "end"
        Dim p1 As Int = Len1(strLine)
        p1 = banano.parseInt(p1)
        bOK = (p1 > 3)
    End Select
    Return bOK
End Sub
'remove these sub routines
Sub RemoveSubRoutinesWait(SubsToRemove As List) As Boolean
    For Each sub2find As String In SubsToRemove
        'we need to find the signature for the subroute
        Dim subcode As Map = banano.await(GetSubRoutineWait(sub2find))
        If subcode.ContainsKey("signature") Then
            Dim signame As String = subcode.Get("signature")
            Dim code As List = subcode.Get("code")
            Dim numlines As Long = code.size - 1
            'in which line is the subroutine
            Dim sigPos As Long = Lines.IndexOf(signame)
            Dim endPos As Long = sigPos + numlines
            Dim cgLines As List
            cgLines.Initialize
            Dim codeLine As Int
            For codeLine = sigPos To endPos
                Dim strline As String = Lines.Get(codeLine)
                cgLines.Add(strline)
            Next
            Dim bMatch As Boolean = banano.Await(ListsMatchWait(cgLines, code))
            If bMatch Then
                'what is on line matches what is stored, blank out the lines
                For codeLine = sigPos To endPos
                    Lines.Set(codeLine, "")
                Next
            End If
        End If
    Next
    banano.Await(PostProcessWait)
    Return True
End Sub
'comment this sub routines
Sub CommentSubRoutineWait(SubName As String) As Boolean
    'we need to find the signature for the subroute
    Dim subcode As Map = banano.await(GetSubRoutineWait(SubName))
    If subcode.ContainsKey("signature") Then
        Dim signame As String = subcode.Get("signature")
        Dim code As List = subcode.Get("code")
        Dim numlines As Long = code.size - 1
        'in which line is the subroutine
        Dim sigPos As Long = Lines.IndexOf(signame)
        Dim endPos As Long = sigPos + numlines
        Dim cgLines As List
        cgLines.Initialize
        Dim codeLine As Int
        For codeLine = sigPos To endPos
            Dim strline As String = Lines.Get(codeLine)
            cgLines.Add(strline)
        Next
        Dim bMatch As Boolean = banano.Await(ListsMatchWait(cgLines, code))
        If bMatch Then
            For codeLine = sigPos To endPos
                Dim strline As String = Lines.Get(codeLine)
                strline = $"'${strline}"$
                Lines.Set(codeLine, strline)
            Next
            banano.Await(PostProcessWait)
        End If
    End If
    Return True
End Sub
'comment this sub routines
Sub RemoveSubRoutineWait(SubName As String) As Boolean
    'we need to find the signature for the subroute
    Dim subcode As Map = banano.await(GetSubRoutineWait(SubName))
    If subcode.ContainsKey("signature") Then
        Dim signame As String = subcode.Get("signature")
        Dim code As List = subcode.Get("code")
        Dim numlines As Long = code.size - 1
        'in which line is the subroutine
        Dim sigPos As Long = Lines.IndexOf(signame)
        Dim endPos As Long = sigPos + numlines
        Dim cgLines As List
        cgLines.Initialize
        Dim codeLine As Int
        For codeLine = sigPos To endPos
            Dim strline As String = Lines.Get(codeLine)
            cgLines.Add(strline)
        Next
        Dim bMatch As Boolean = banano.Await(ListsMatchWait(cgLines, code))
        If bMatch Then
            For codeLine = sigPos To endPos
                Lines.Set(codeLine, "")
            Next
            banano.Await(PostProcessWait)
        End If
    End If
    Return True
End Sub
'add line to class globals
Sub AddClassGlobalsWait(sLine As String) As Boolean
    Dim subcode As Map = banano.await(GetSubRoutineWait("Class_Globals"))
    Dim signame As String = subcode.Get("signature")
    Dim code As List = subcode.Get("code")
    Dim numlines As Long = code.size - 1
    'in which line is the subroutine
    Dim sigPos As Long = Lines.IndexOf(signame)
    Dim endPos As Long = sigPos + numlines
    Dim cgLines As List
    cgLines.Initialize
    Dim codeLine As Int
    For codeLine = sigPos To endPos
        Dim strline As String = Lines.Get(codeLine)
        cgLines.Add(strline)
    Next
    Dim bMatch As Boolean = banano.Await(ListsMatchWait(cgLines, code))
    'if we have a match, find if what we want to add exists
    If bMatch Then
        'does this line exist in initialize
        Dim cg2addPos As Int = banano.Await(ListStartWithWait(code, sLine))
        If cg2addPos = -1 Then
            'this line does not exist within the scope
            Dim addPos As Long = endPos
            Lines.InsertAt(addPos, sLine)
            banano.Await(PostProcessWait)
        End If
    End If
    Return True
End Sub
'add a line to initialize
Sub AddInitializeWait(sLine As String) As Boolean
    'we need to find the signature for class globals
    Dim subcode As Map = banano.await(GetSubRoutineWait("Initialize"))
    Dim signame As String = subcode.Get("signature")
    Dim code As List = subcode.Get("code")
    Dim numlines As Long = code.size - 1
    'in which line is the subroutine
    Dim sigPos As Long = Lines.IndexOf(signame)
    Dim endPos As Long = sigPos + numlines
    Dim cgLines As List
    cgLines.Initialize
    Dim codeLine As Int
    For codeLine = sigPos To endPos
        Dim strline As String = Lines.Get(codeLine)
        cgLines.Add(strline)
    Next
    Dim bMatch As Boolean = banano.Await(ListsMatchWait(cgLines, code))
    'if we have a match, find if what we want to add exists
    If bMatch Then
        'does this line exist in initialize
        Dim cg2addPos As Int = banano.Await(ListStartWithWait(code, sLine))
        If cg2addPos = -1 Then
            'this line does not exist within the scope
            Dim addPos As Long = endPos
            Lines.InsertAt(addPos, sLine)
            banano.Await(PostProcessWait)
        End If
    End If
    Return True
End Sub
'remove comments and wait
Sub RemoveCommentsWait As Boolean
    'loop through each key value pair
    Dim tlines As Long = Lines.Size - 1
    Dim clines As Long
    For clines = 0 To tlines
        Dim strline As String = Lines.Get(clines)
        If strline.StartsWith("'") Then
            Lines.Set(clines, "")
        End If
    Next
    banano.Await(PostProcessWait)
    Return True
End Sub
'build a property from a map
Sub BuildPropertyWithList(m As Map) As String
    Dim sb As String = ""
    Dim skey As String = m.Get("key")
    Dim sdisplayname As String = m.Get("displayname")
    Dim sfieldtype As String = m.Get("fieldtype")
    Dim sdefaultvalue As String = m.Get("defaultvalue")
    Dim sdescription As String = m.Get("description")
    Dim slist As String = m.GetDefault("list", "")
    slist = parseNull(slist)
    '
    sb = $"#DesignerProperty: Key: ${skey}, DisplayName: ${sdisplayname}, FieldType: ${sfieldtype}, DefaultValue: ${sdefaultvalue}, Description: ${sdescription}"$
    If slist <> "" Then
        slist = SortChoices(slist)
        sb = $"${sb}, List: ${slist}"$
    End If
    Return sb
End Sub

'parse null
Sub parseNull(v As Object) As String
	If banano.IsNull(v) Or banano.IsUndefined(v) Then
		Return ""
	End If
	v = CStr(v)
	If v = "null" Then Return ""
	If v = "undefined" Then Return ""
	Return v
End Sub

'get the contents of these sub-routes for use later
Sub GetSubroutesWait(exclude As List) As Map
    Dim retmap As Map = CreateMap()
    For Each subName As String In SubRoutines.Keys
        'dont process the ones on
        Dim subPos As Int = exclude.IndexOf(subName)
        If subPos = -1 Then
            'get the code
            Dim subprofile As Map = SubRoutines.Get(subName)
            Dim subcode As String = subprofile.Get("code")
            retmap.Put(subName, subcode)
        End If
    Next
    Return retmap
End Sub
'add comment on line containing text
Sub AddCommentsWait(kvs As Map) As Boolean
    'loop through each key value pair
    For Each strline As String In kvs.Keys
        Dim scomment As String = kvs.Get(strline)
        If scomment.StartsWith("'") = False Then
            scomment = "'" & scomment
        End If
        'find the line on the code
        Dim sigPos As Long = Lines.IndexOf(strline)
        If sigPos = -1 Then Continue
        'get the previous line
        Lines.InsertAt(sigPos, scomment)
    Next
    banano.Await(PostProcessWait)
    Return True
End Sub
'add a designer property line to the file
Sub AddDesignerPropertyAwait(propLine As String, atTop As Boolean) As Boolean
    'does the property exist on the designer code
    Dim pExist As Boolean = banano.Await(HasPropertyWait(propLine))
    'we need to check the actual key
    Dim pKey As String = banano.Await(GetKeyFromDesignerCodeWait(propLine))
    'check the key existence
    Dim kExist As Boolean = banano.Await(HasDesignerKeyWait(pKey))
    'the property exist, the key also does not no need to add it
    If pExist = True Or kExist = True Then Return False
    Select Case atTop
    Case True
        'get the first property
        Dim strfirst As String = Properties.Get(0)
        'get position on file
        Dim firstPos As Long = Lines.IndexOf(strfirst)
        'insert the property to the file
        Lines.InsertAt(firstPos, propLine)
        banano.Await(PostProcessWait)
    Case Else
        'how many properties do we have
        Dim pLength As Int = Properties.Size - 1
        'get the last property
        Dim strLast As String = Properties.Get(pLength)
        'find the position of the last property on the file
        Dim lastPos As Long = Lines.IndexOf(strLast)
        'we will insert on this line
        lastPos = lastPos + 1
        'insert the property to the file
        Lines.InsertAt(lastPos, propLine)
        banano.Await(PostProcessWait)
    End Select
    Return True
End Sub
'post processing
private Sub PostProcessWait As Boolean
    indent = 0
    linePos = 0
    strActual = ""
    'strTemp = ""
    'trim all lines in the code
    banano.Await(TrimLinesWait)
    'remove all empty lines
    Lines = banano.Await(RemoveLinesWait("",True))
    'remove all line continuations
    'banano.Await(RemoveLineContinuationWait)
    'we will the collection for most things
    collection.Initialize(Me, Lines)
    'scan all event definitions
    banano.Await(ScanEventsWait)
    'scan for designer properties
    banano.Await(ScanPropertiesWait)
    'scan subroutines
    banano.Await(ScanSubRoutinesWait)
    'scan for class globals
    ClassGlobalsCode = banano.Await(GetSubRoutineCodeWait("Class_Globals"))
    InitializeCode = banano.Await(GetSubRoutineCodeWait("Initialize"))
    CreateViewCode = banano.Await(GetSubRoutineCodeWait("DesignerCreateView"))
    'scan comments
    banano.Await(ScanCommentsWait)
    'join the lines for the transaction file
    Transactions = Join(CRLF1, Lines)
    Return True
End Sub
'compare 2 lists
private Sub ListsMatchWait(list1 As List, list2 As List) As Boolean
    Dim lmatch As Int = 0
    Dim l1Tot As Long = list1.Size - 1
    Dim l1Cnt As Long
    For l1Cnt = 0 To l1Tot
        Dim l1line As String = list1.Get(l1Cnt)
        Dim l2line As String = list2.Get(l1Cnt)
        If l1line <> l2line Then
            lmatch = lmatch + 1
        End If
    Next
    If lmatch = 0 Then
        Return True
    End If
    Return False
End Sub
'add a line of code after a subroutine name, after line
Sub AddSubRoutineLineAfterWait(subName As String, codeToFind As String, sLine As String) As Boolean
    'we need to find the signature for class globals
    Dim subcode As Map = banano.await(GetSubRoutineWait(subName))
    Dim signame As String = subcode.Get("signature")
    Dim code As List = subcode.Get("code")
    Dim numlines As Long = code.size - 1
    'in which line is the subroutine
    Dim sigPos As Long = Lines.IndexOf(signame)
    Dim endPos As Long = sigPos + numlines
    Dim cgLines As List
    cgLines.Initialize
    Dim codeLine As Int
    For codeLine = sigPos To endPos
        Dim strline As String = Lines.Get(codeLine)
        cgLines.Add(strline)
    Next
    Dim bMatch As Boolean = banano.Await(ListsMatchWait(cgLines, code))
    'if we have a match, find if what we want to add exists
    If bMatch Then
        'does this line exist
        Dim cg2addPos As Int = banano.Await(ListStartWithWait(code, codeToFind))
        If cg2addPos = -1 Then Return False
        'this line does not exist within the scope
        Dim addPos As Long = sigPos + cg2addPos + 1
        Lines.InsertAt(addPos, sLine)
        banano.Await(PostProcessWait)
        Return True
    Else
        Return False
    End If
End Sub
'remove exact lines
Sub RemoveExactLinesWait(delLines As List) As Boolean
    Dim tLines As Int = Lines.size - 1
    Dim cLines As Int
    Dim tranLines As Int = 0
    For cLines = 0 To tLines
        'get the file line
        Dim fLine As String = Lines.Get(cLines)
        'loop through each subroutine
        For Each strline As String In delLines
            If fLine.EqualsIgnoreCase(strline) Then
                Lines.Set(cLines, "")
                tranLines = tranLines + 1
            End If
        Next
    Next
    If tranLines = 0 Then
        Return False
    End If
    banano.Await(PostProcessWait)
    Return True
End Sub
'replace exact lines
Sub ReplaceExactLinesWait(findLine As String, putLine As String) As Boolean
    Dim tLines As Int = Lines.size - 1
    Dim cLines As Int
    Dim tranLines As Int = 0
    For cLines = 0 To tLines
        'get the file line
        Dim fLine As String = Lines.Get(cLines)
        If fLine.EqualsIgnoreCase(findLine) Then
            Lines.Set(cLines, putLine)
            tranLines = tranLines + 1
        End If
    Next
    If tranLines = 0 Then
        Return False
    End If
    banano.Await(PostProcessWait)
    Return True
End Sub
'comment a line
Sub CommentExactLineWait(findLine As String) As Boolean
    Dim tLines As Int = Lines.size - 1
    Dim cLines As Int
    Dim tranLines As Int = 0
    For cLines = 0 To tLines
        'get the file line
        Dim fLine As String = Lines.Get(cLines)
        If fLine.EqualsIgnoreCase(findLine) Then
            Lines.Set(cLines, $"'${findLine}"$)
            tranLines = tranLines + 1
        End If
    Next
    If tranLines = 0 Then
        Return False
    End If
    banano.Await(PostProcessWait)
    Return True
End Sub
'add subroutines copied using subroutine name & code
Sub AddSubroutesWait(SubRoutinesM As Map) As Boolean
    'loop through each subroutine
    For Each subname As String In SubRoutinesM.Keys
        Dim codelines As List = SubRoutinesM.Get(subname)
        'does this sub exist
        Dim SubRoutines1 As Map = SubRoutines
        Dim bExist As Boolean = SubRoutines1.ContainsKey(subname)
        'the sub does not exist, add it
        If bExist = False Then
            For Each CodeLine As String In codelines
                Lines.Add(CodeLine)
            Next
        End If
    Next
    banano.Await(PostProcessWait)
    Return True
End Sub
'add a single sub routine with code
Sub AddSubrouteWait(subName As String, subCode As String) As Boolean
    Dim SubRoutines1 As Map = SubRoutines
    Dim bExist As Boolean = SubRoutines1.ContainsKey(subName)
    'the sub does not exist, add it
    If bExist = False Then
        Dim codeLines As List = StrParse(CRLF1, subCode)
        For Each CodeLine As String In codeLines
            Lines.Add(CodeLine)
        Next
        banano.Await(PostProcessWait)
    End If
    Return True
End Sub
'comment a line at position
Sub CodeLineCommentAt(pos As Int)
    If pos < Lines.Size Then
        Dim cl As String = Lines.Get(pos)
        cl = cl.trim
        If cl.StartsWith("'") Then Return
        cl = $"'${cl}"$
        Lines.Set(pos, cl)
    End If
End Sub
'uncomment a code line
Sub CodeLineUnCommentAt(pos As Int)
    If pos < Lines.Size Then
        Dim cl As String = Lines.Get(pos)
        cl = cl.trim
        If cl.StartsWith("'") Then
            cl = MidS(cl,2)
            Lines.Set(pos, cl)
        End If
    End If
End Sub
'mid
Sub MidS(Text As String, iStart As Int) As String
	Dim x As String = Text.SubString(iStart - 1)
	Return x
End Sub
'find a code line
Sub CodeLineFindWait(sLine As String) As Int
    Dim pos As Int = banano.Await(ListHasMatchWait(Lines, sLine))
    Return pos
End Sub
'find a code line
Sub CodeLineFindStartAtWait(startPos As Int, sLine As String) As Int
    Dim pos As Int = banano.Await(ListHasMatchStartAtWait(Lines, startPos, sLine))
    Return pos
End Sub
'find a code line
Sub CodeLineFindStartAtStartWithWait(startPos As Int, wordSearch As String) As Int
    Dim pos As Int
    Dim posTot As Int= Lines.Size - 1
    Dim ssearch As String = wordSearch.tolowercase
    For pos = startPos To posTot
        Dim lItem As String = Lines.Get(pos)
        lItem = lItem.tolowercase
        If lItem.StartsWith(ssearch) Then
            Return pos
        End If
    Next
    Return -1
End Sub
'do a lowercase match
Sub ListHasMatchWait(lst As List, wordSearch As String) As Int
    Dim posTot As Int= lst.Size - 1
    Dim ssearch As String = wordSearch.tolowercase
    Dim pos As Int
    For pos = 0 To posTot
        Dim lItem As String = lst.Get(pos)
        lItem = lItem.tolowercase
        If lItem.EqualsIgnoreCase(ssearch) Then
            Return pos
        End If
    Next
    Return -1
End Sub
'do a lowercase match
Sub ListHasMatchStartAtWait(lst As List, startPos As Int, wordSearch As String) As Int
    Dim posTot As Int= lst.Size - 1
    Dim ssearch As String = wordSearch.tolowercase
    Dim pos As Int
    For pos = startPos To posTot
        Dim lItem As String = lst.Get(pos)
        lItem = lItem.tolowercase
        If lItem.EqualsIgnoreCase(ssearch) Then
            Return pos
        End If
    Next
    Return -1
End Sub
'do a lowercase match
private Sub ListHasMatchStartEndAtWait(lst As List, startPos As Int, endPos As Int, wordSearch As String) As Int
    Dim ssearch As String = wordSearch.tolowercase
    Dim pos As Int
    For pos = startPos To endPos
        Dim lItem As String = lst.Get(pos)
        lItem = lItem.tolowercase
        If lItem.EqualsIgnoreCase(ssearch) Then
            Return pos
        End If
    Next
    Return -1
End Sub
'get lines between positions
Sub GetCodeBetweenLinesWait(lst As List, startPos As Int, endPos As Int) As List
    Dim pos As Int
    Dim nlines As List
    nlines.Initialize
    For pos = startPos To endPos
        Dim strLine As String = lst.Get(pos)
        nlines.Add(strLine)
    Next
    Return nlines
End Sub
'count matches
private Sub ListHasMatchCountWait(lst As List, wordSearch As String) As Int
    Dim posTot As Int= lst.Size - 1
    Dim ssearch As String = wordSearch.tolowercase
    Dim pos As Int
    Dim pos1 As Int = 0
    For pos = 0 To posTot
        Dim lItem As String = lst.Get(pos)
        If lItem.EqualsIgnoreCase(ssearch) Then
            pos1 = pos1 + 1
        End If
    Next
    Return pos1
End Sub
'
'do a lowercase match of list starts with
private Sub ListStartWithWait(lst As List, wordSearch As String) As Int
    Dim pos As Int
    Dim posTot As Int= lst.Size - 1
    Dim ssearch As String = wordSearch.tolowercase
    For pos = 0 To posTot
        Dim lItem As String = lst.Get(pos)
        lItem = lItem.tolowercase
        If lItem.StartsWith(ssearch) Then
            Return pos
        End If
    Next
    Return -1
End Sub
'check if list contains words
private Sub ListContainsWordsWait(lst As List, wordSearch As String) As Boolean
    Dim ssearch As String = wordSearch.tolowercase
    For Each lItem As String In lst
        lItem = lItem.ToLowerCase
        If lItem.Contains(ssearch) Then
            Return True
        End If
    Next
    Return False
End Sub
Sub AddDesignerCreateViewGetPropWait(sLine As String) As Boolean  'ignore
    'we need to find the signature for the create view code
    Dim subcode As Map = banano.await(GetSubRoutineWait("DesignerCreateView"))
    Dim signame As String = subcode.Get("signature")
    Dim code As List = subcode.Get("code")
    Dim numlines As Long = code.size - 1
    'in which line is the subroutine
    Dim sigPos As Long = Lines.IndexOf(signame)
    Dim endPos As Long = sigPos + numlines
    Dim cgLines As List
    cgLines.Initialize
    Dim codeLine As Int
    For codeLine = sigPos To endPos
        Dim strline As String = Lines.Get(codeLine)
        cgLines.Add(strline)
    Next
    Dim bMatch As Boolean = banano.Await(ListsMatchWait(cgLines, code))
    'if we have a match, find if what we want to add exists
    If bMatch Then
        'what is the 'If Props <> Null Then' position'
        Dim nullPos As Int = banano.Await(ListHasMatchStartAtWait(Lines, sigPos, "If Props <> Null Then"))
        'what is the position of the next 'End If
        Dim endifPos As Int = banano.Await(ListHasMatchStartAtWait(Lines, nullPos, "End If"))
        '
        If nullPos <> -1 And endifPos > nullPos Then
            'get the code lines between If & End If
            Dim codeLines As List = banano.Await(GetCodeBetweenLinesWait(Lines, nullPos, endifPos))
            Dim codeLinesEnd As Int = codeLines.Size - 1
            'search for the read inside If & End If
            Dim readPos As Int = banano.Await(ListHasMatchStartEndAtWait(codeLines, 0, codeLinesEnd, sLine))
            'read prop not found
            If readPos = -1 Then
                Lines.InsertAt(endifPos, sLine)
                banano.Await(PostProcessWait)
                Return True
            End If
        Else
            'If & End If do not exist
            Return False
        End If
    Else
        'code lines dont match, exist
        Return False
    End If
End Sub
'add this text after on condition that the next line contents are not what we are adding
Sub AddDesignerCreateViewAfterWait(sLine As String, sAfter As String) As Boolean
    'we need to find the signature for the create view code
    Dim subcode As Map = banano.await(GetSubRoutineWait("DesignerCreateView"))
    Dim signame As String = subcode.Get("signature")
    Dim code As List = subcode.Get("code")
    Dim numlines As Long = code.size - 1
    'in which line is the subroutine
    Dim sigPos As Long = Lines.IndexOf(signame)
    Dim endPos As Long = sigPos + numlines
    Dim cgLines As List
    cgLines.Initialize
    Dim codeLine As Int
    For codeLine = sigPos To endPos
        Dim strline As String = Lines.Get(codeLine)
        cgLines.Add(strline)
    Next
    Dim bMatch As Boolean = banano.Await(ListsMatchWait(cgLines, code))
    'if we have a match, find if what we want to add exists
    If bMatch Then
        'does the list have the after position: code to find
        Dim afterPos As Int = banano.Await(ListHasMatchStartEndAtWait(Lines, sigPos, endPos, sAfter))
        If afterPos = -1 Then
            Return False
        End If
        'get the right location to add
        Dim nextLine As Int = afterPos + 1
        Dim sNextLine As String = Lines.Get(nextLine)
        If sNextLine.EqualsIgnoreCase(sLine) Then
            Return False
        End If
        Lines.InsertAt(nextLine, sLine)
        banano.Await(PostProcessWait)
        Return True
    Else
        Return False
    End If
End Sub
'add this text after on condition that the next line contents are not what we are adding
Sub AddCodeAfterWait(codeToFind As String, codeToAdd As String) As Boolean
    Dim endPos As Int = Lines.Size - 1
    'does the list have the after position: code to find
    Dim afterPos As Int = banano.Await(ListHasMatchStartEndAtWait(Lines, 0, endPos, codeToFind))
    If afterPos = -1 Then
        Return False
    End If
    'get the right location to add
    Dim nextLine As Int = afterPos + 1
    Dim sNextLine As String = Lines.Get(nextLine)
    If sNextLine.EqualsIgnoreCase(codeToAdd) Then
        Return False
    End If
    Lines.InsertAt(nextLine, codeToAdd)
    banano.Await(PostProcessWait)
    Return True
End Sub
'add on designer
private Sub AddDesignerCreateViewSetPropWait(sLine As String) As Boolean   'ignore
    'we need to find the signature for the create view code
    Dim subcode As Map = banano.await(GetSubRoutineWait("DesignerCreateView"))
    Dim signame As String = subcode.Get("signature")
    Dim Code As List = subcode.Get("code")
    Dim numlines As Long = Code.size - 1
    'in which line is the subroutine
    Dim sigPos As Long = Lines.IndexOf(signame)
    Dim endPos As Long = sigPos + numlines
    Dim cgLines As List
    cgLines.Initialize
    Dim codeLine As Int
    For codeLine = sigPos To endPos
        Dim strline As String = Lines.Get(codeLine)
        cgLines.Add(strline)
    Next
    Dim bMatch As Boolean = banano.Await(ListsMatchWait(cgLines, Code))
    'if we have a match, find if what we want to add exists
    If bMatch Then
        'what is the 'If Props <> Null Then' position'
        Dim nullPos As Int = banano.Await(ListHasMatchStartAtWait(Lines, sigPos, "If Props <> Null Then"))
        'what is the position of the next 'End If
        Dim endifPos As Int = banano.Await(ListHasMatchStartAtWait(Lines, nullPos, "End If"))
        'what is the position of VElement.BindAllEvents
        Dim baPos As Int = banano.Await(ListHasMatchStartAtWait(Lines,endifPos, "VElement.BindAllEvents"))
        'bindall pos
        If nullPos <> -1 Then
            If endifPos > nullPos Then
                If baPos > endifPos Then
                    'get the code lines between End if & .BindAllEvents
                    Dim codelines As List = banano.Await(GetCodeBetweenLinesWait(Lines, endifPos + 1, baPos))
                    Dim codeLinesEnd As Int = codelines.Size - 1
                    'search for the set inside End If & BindAllEvents
                    Dim readPos As Int = banano.Await(ListHasMatchStartEndAtWait(codelines, 0, codeLinesEnd, sLine))
                    'set prop not found
                    If readPos = -1 Then
                        Lines.InsertAt(baPos, sLine)
                        banano.Await(PostProcessWait)
                        Return True
                    End If
                Else
                    Return False
                End If
            Else
                Return False
            End If
        End If
    Else
        'code lines dont match, exist
        Return False
    End If
End Sub
'build the binding name to be used for this
'pass it the variable name and the type of binding e.g show, disabled
Sub BuildBindingInitAssignment(nvarName As String, varType As String) As String
    Dim initCodeLine As String = $"${nvarName} = ${BuildBindingVariable(varType)}"$
    Return initCodeLine
End Sub
'build any binding variable based on type e.g. show, required, disabled etc
private Sub BuildBindingVariable(sType As String) As String
    Dim sq As String = Chr(34)
    Dim showBinding As String = $"~${sq}~{mName}${sType}${sq}~"$
    showBinding = showBinding.Replace("~","$")
    Return showBinding
End Sub
'sort choices in a property list
private Sub SortChoices(oldChoices As String) As String
    Dim oc As List = StrParse("|", oldChoices)
    oc.sort(True)
    Dim nc As String = Join("|", oc)
    Return nc
End Sub
'code writer
Sub Code_Clear
    ThisCode.Initialize
End Sub
'code writer
Sub Code_Add(s As String)
    s = s.Replace("~","$")
    ThisCode.Append(s).Append(CRLF1)
End Sub
'code writer
Sub Code_Comment(s As String)
    ThisCode.Append($"'${s}"$).Append(CRLF1)
End Sub
'code writer
Sub Code_ToString As String
    Return ThisCode.tostring
End Sub