﻿Version=6.90
NumberOfForms=0
NumberOfObjects=0
Sub designer
end sub
@EndOfDesignText@
'Simple ini file module, v1.00, Derek Lazenby, 9th June 2010

' Parse files using syntax
' <ini file> ::= { <line> } <eof>
' <line> ::= <empty> | <header> | <definition> | <comment>
' <header> ::= '[' <name> ']'
' <definition> ::= <name> '=' <value>
' <comment> ::= ';' string
' <name> ::= string
' <value> ::= string

' headers and comments must start at the first character of a line

Sub Globals
	'Declare the global variables here.
	Dim cEof, cEmpty, cHeader, cDefinition, cComment, cError As Integer

	' can't pass files as parameters, sigh
	Dim hrFile, hwFile

	' oh for enumeration types
	cEof = 0
	cEmpty = 1
	cHeader = 2
	cDefinition = 3
	cComment = 4
	cError = 5
End Sub

' syntax and semantics
' write a key to a ini file
Public Sub PutString ( ByRef IniFile As String , ByRef Section As String , _
						 ByRef Key As String, ByRef Value As String )

	Dim Line, tmp_INIFile As String, LType, AfterEqPos As Integer
	Dim HeaderFound As Boolean
		 
	' create a new file if needed
	If Not ( FileExist ( IniFile )) Then
		FileOpen ( hwFile, IniFile, cWrite,, cASCII )
		FileWrite ( hwFile, "[" & Section & "]" )
		FileWrite ( hwFile, Key & "=" & Value )
		FileWrite ( hwFile, "" )
		FileClose ( hwFile )
		Return
	End If
	
	' init variables
	HeaderFound = False
	tmp_INIFile = SubString ( INIFile, 0, StrLength ( INIFile ) - 3 ) & "tmp"
	
	' open the file (read) and a new file (write)
	FileOpen ( hrFile, IniFile, cRead,, cASCII )
	FileOpen ( hwFile, tmp_IniFile, cWrite,, cASCII )
	
	' loop until this key written or error
	Do
		' read line and identify line type
		Line = GetLine ( LType, AfterEqPos ) ' returns all 3 values
		
		' process different line types
		Select LType
			Case cEof
				' append key to end of file, with header if needed
				If Not ( HeaderFound ) Then FileWrite ( hwFile, "[" & Section & "]" )
				FileWrite ( hwFile, Key & "=" & Value )
				FileWrite ( hwFile, "" )
				Exit
			Case cError
				' without an exception mechanism handling this would be extremely messy
				' so just quietly copy this line and hope the user uses an editor sometime
				' in Ada, (and later languages) this would be "raise MyException" here and
				' "exception when MyException =>" in the user code as this is not the place
				' To Do anything active as it would get done for each and every call,
				' potentially a big number of error reports.
				' Goto <ErrorLabel> isn't possible as a generic module has no knowledge of
				' the app
				FileWrite ( hwFile, Line )
			Case cHeader
				If HeaderFound Then 
					' new key at end of previous section
					FileWrite ( hwFile, Key &"=" & Value )
					FileWrite ( hwFile, "" )
					FileWrite ( hwFile, Line ) ' this headeer
					FileWrite ( hwFile, FileReadToEnd ( hrFile ))
					Exit
				End If
				
				' copy this header and see if it is the one we want
				FileWrite ( hwFile, Line )
				If "[" & Section & "]" = Line Then HeaderFound = True
			Case cDefinition
				If HeaderFound AND StrIndexOf ( Line, Key, 0 ) = 0 Then
					' update existing key under existing header
					FileWrite ( hwFile, Key &"=" & Value )
					FileWrite ( hwFile, FileReadToEnd ( hrFile ))
					Exit
				Else
					' this was some other key
					FileWrite ( hwFile, Line )
				End If
			Case cEmpty
				If Not ( HeaderFound ) Then ' otherwise do the blank later
					FileWrite ( hwFile, "" )
				End If
			Case cComment
				FileWrite ( hwFile, Line )
		End Select
	Loop While True
	
	FileClose ( hrFile )
	FileClose ( hwFile )
	
	' make new file the real file
	FileCopy ( tmp_INIFile, INIFile )
	
	' done with temp file
	FileDel ( tmp_INIFile )
End Sub

' syntax and semantics
' Read a key from an ini file
Public Sub GetString ( ByRef IniFile As String , ByRef Section As String , _
						 	  ByRef Key As String, _
							  ByRef Default As String _
					  		) As String
	Dim Line, Result As String, LType, AfterEqPos As Integer
	Dim HeaderFound As Boolean
	
	' no file then return default
	If Not ( FileExist ( IniFile )) Then Return Default
	
	' init variables
	HeaderFound = False
	Result = Default ' presume we can't find the key
	
	' open the file (read)
	FileOpen ( hrFile, IniFile, cRead,, cASCII )
	
	' loop until this key read or error
	Do
		' read line and identify line type
		Line = GetLine ( LType, AfterEqPos ) ' returns all 3 values
		
		' process different line types
		Select LType
			Case cEof
				Exit
			Case cError
				' without an exception mechanism handling this would be extremely messy
				' so just quietly ignore this line and hope the user uses an editor sometime
				' also see comment in PutString above
			Case cHeader
				If HeaderFound Then
					' reached next section so key doesn't exist
					Exit
				Else If "[" & Section & "]" = Line Then
					HeaderFound = True
				End If
			Case cDefinition
				If HeaderFound AND StrIndexOf ( Line, Key, 0 ) = 0 Then
					' this is the one
					Result = SubString ( Line, AfterEqPos, StrLength ( Line ) - AfterEqPos )
					Exit
				End If
			Case cEmpty, cComment
		End Select
	Loop While True
	
	FileClose ( hrFile )
	
	Return Result
End Sub

' lexical analyser
' read a line and identify it's type; say where any data starts ( after = )
Private Sub GetLine ( ByRef LType As Integer, _
							 ByRef AfterEqPos As Integer ) As String
	Dim l As String, EqPos As Integer
	
	l = FileRead ( hrFile )
	If l = EOF Then
		LType = cEof ' so we can simply use a select statement above
	Else If l = "" Then
		LType = cEmpty
	Else If StrIndexOf ( l, ";", 0 ) = 0 Then
		LType = cComment
	Else If StrIndexOf ( l, "[", 0 ) = 0 Then
		LType = cHeader
	Else
		EqPos = StrIndexOf ( l, "=", 0 )
		If EqPos <> -1 Then
			LType = cDefinition
			AfterEqPos = EqPos + 1
		Else
			LType = cError
		End If
	End If
	
	Return l
End Sub
	
	