12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466 |
- ' Simple Garage (Garage manager program for Stunts)
- ' Copyright (C) 2022 Lucas Pedrosa
- ' This program is free software: you can redistribute it and/or modify
- ' it under the terms of the GNU General Public License as published by
- ' the Free Software Foundation, version 3 of the License.
- ' This program is distributed in the hope that it will be useful,
- ' but WITHOUT ANY WARRANTY; without even the implied warranty of
- ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ' GNU General Public License for more details.
- ' You should have received a copy of the GNU General Public License
- ' along with this program. If not, see <http://www.gnu.org/licenses/>.
- ' COMPILATION:
- ' Simple Garage has been compiled with FreeBasic 1.09.1 and tested
- ' in GNU/Linux Mint, FreeDOS and DOSBox
- ' It should compile well with any newer version and likely, with some
- ' older versions. You can get FreeBasic at:
- ' - http://www.freebasic.net
- ' For GNU/Linux and for DOS, compile with:
- ' - fbc sgar.bas
- ' For Windows, compile with:
- ' - fbc -s gui sgar.bas
- 'Simple Garage program
- 'Version 2 started 2022-08-27
- #define SGVERSION "2.0"
- #define MAXCARSPERGARAGE 100
- #include "file.bi"
- #ifdef __FB_LINUX__
- #define SLASH "/"
- #else
- #define SLASH "\"
- #endif
- Type Car
- id As String
- file(1 To 9) As String
- numfiles As Byte
- carname As String
- version As String
- author As String
- End Type
- Type Group
- gname As String
- cars As String
- End Type
- Type Garage
- dir As String
- name As String
- End Type
- Dim Shared car(0 To 15, 1 To MAXCARSPERGARAGE) As Car, cars(0 To 15) As UByte
- Dim Shared garage(0 To 15) As Garage, garages As UByte
- Dim Shared group(1 To 50) As Group, groups As UByte, locked As String
- Dim Shared progdir As String, cfgfile As String
- Dim Shared release_date As String, copyright_notice As String
- Dim Shared lastcommand(1 To 10) As String
- Sub LoadConfig
- garage(0).dir = "." : garage(1).dir = "garage"
- locked = "coun" : garages = 1
- progdir = ExePath
- If Right(progdir, 1) <> SLASH Then progdir &= SLASH
- cfgfile = progdir & "sgar.cfg"
- If Not FileExists(progdir & "sgar.cfg") Then Exit Sub
-
- Dim f As Integer, s As String
- Dim p As String, v As String, n As Short
-
- f = FreeFile
- Open progdir & "sgar.cfg" For Input As f
- Line Input #f, s
- If LCase(Left(s, 4)) = "cfg=" Then
- cfgfile = Mid(s, 5)
- Close f
- If FileExists(Mid(s, 5)) Then
- Open Mid(s, 5) For Input As f
- Else
- 'Redirection failed. No such configuration file.
- Exit Sub
- End If
- Else
- Seek #f, 1
- cfgfile = progdir & "sgar.cfg"
- End If
-
- garages = 0 : groups = 0
-
- While Not EoF(f)
- Line Input #f, s
- n = InStr(s, "=")
- If n Then
- p = LCase(Trim(Left(s, n - 1)))
- v = Trim(Mid(s, n + 1))
-
- Select Case p
- Case "stunts", "root"
- garage(0).dir = v
- garage(0).name = "Stunts"
- Case "garage"
- garages += 1
- n = InStr(v, ":")
- If n Then
- garage(garages).dir = Mid(v, n + 1)
- garage(garages).name = Left(v, n - 1)
- Else
- garage(garages).dir = v
- garage(garages).name = ""
- End If
- Case "junkyard"
- garages += 1
- garage(garages).dir = v
- garage(garages).name = "junkyard"
- Case "locked"
- locked = LCase(Trim(v))
- Case "group"
- n = InStr(v, ":")
- If n Then
- groups += 1
- group(groups).gname = LCase(Trim(Left(v, n - 1)))
- group(groups).cars = LCase(Trim(Mid(v, n + 1)))
- End If
- End Select
- End If
- WEnd
- Close f
-
- 'This will default to a garage named "garage" under the current path
- 'which may or may not work!
- If garages = 0 Then garages = 1
- End Sub
- Sub SaveConfig
- Dim f As Integer
-
- f = FreeFile
- Open cfgfile For Output As f
- If Err Then Exit Sub 'Wrong file name. Can't create
-
- Print #f, "stunts=" & garage(0).dir
- For i As Short = 1 To garages
- If Len(garage(i).name) Then
- Print #f, "garage=" & garage(i).name & ":" & garage(i).dir
- Else
- Print #f, "garage=" & garage(i).dir
- End If
- Next i
- Print #f, "locked=" & locked
- For i As Short = 1 To groups
- Print #f, "group=" & group(i).gname & ":" & group(i).cars
- Next i
- Close f
- End Sub
- Sub ReadDirs
- Dim As String s, t, id
- Dim code As Byte
-
- For collection As Byte = 0 To garages
- #ifdef __FB_LINUX__
- s = Dir(garage(collection).dir & SLASH & "*")
- #else
- s = Dir(garage(collection).dir & SLASH & "*.*")
- #endif
- While Len(s)
- t = LCase(s) : code = 0
- If Left(t, 3) = "car" AndAlso Right(t, 4) = ".res" AndAlso Len(t) = 11 Then
- 'Res file
- id = Mid(t, 4, 4)
- code = 1
- ElseIf Left(t, 4) = "stda" AndAlso Right(t, 4) = ".vsh" AndAlso Len(t) = 12 Then
- 'Uncompressed stda file
- id = Mid(t, 5, 4)
- code = 3
- ElseIf Left(t, 4) = "stda" AndAlso Right(t, 4) = ".pvs" AndAlso Len(t) = 12 Then
- 'Compressed stda file
- id = Mid(t, 5, 4)
- code = 4
- ElseIf Left(t, 4) = "stdb" AndAlso Right(t, 4) = ".vsh" AndAlso Len(t) = 12 Then
- 'Uncompressed stdb file
- id = Mid(t, 5, 4)
- code = 5
- ElseIf Left(t, 4) = "stdb" AndAlso Right(t, 4) = ".pvs" AndAlso Len(t) = 12 Then
- 'Compressed stdb file
- id = Mid(t, 5, 4)
- code = 6
- ElseIf Left(t, 2) = "st" AndAlso Right(t, 4) = ".3sh" AndAlso Len(t) = 10 Then
- 'Uncompressed shape file
- id = Mid(t, 3, 4)
- code = 7
- ElseIf Left(t, 2) = "st" AndAlso Right(t, 4) = ".p3s" AndAlso Len(t) = 10 Then
- 'Compressed shape file
- id = Mid(t, 3, 4)
- code = 8
- ElseIf Left(t, 3) = "car" AndAlso Right(t, 4) = ".cfg" AndAlso Len(t) = 11 Then
- 'Car configuration file
- id = Mid(t, 4, 4)
- code = 9
- End If
-
- If code Then
- Dim q As Byte = 0
-
- For i As Short = 1 To cars(collection)
- If car(collection, i).id = id Then
- q = -1
- car(collection, i).file(code) = s
- 'Don't include the configuration file in the count
- 'so it's easier to recognise redundant files
- If code <> 9 Then car(collection, i).numfiles += 1
- Exit For
- End If
- Next i
-
- If q = 0 Then
- cars(collection) += 1
- car(collection, cars(collection)).id = id
- car(collection, cars(collection)).numfiles = 1
- For i As Byte = 1 To 9
- car(collection, cars(collection)).file(i) = ""
- Next i
- car(collection, cars(collection)).file(code) = s
- End If
- End If
-
- s = Dir
- WEnd
- Next collection
- End Sub
- Sub ExtractCarInfo (c As Car, path As String)
- If Len(c.file(1)) = 0 Then
- c.carname = "Unknown"
- Else
- Dim f As Integer, s As String, n As Short, l As Long
-
- f = FreeFile
- Open path & SLASH & c.file(1) For Binary Access Read As f
- s = Space(100)
- Get #f, , s
- n = InStr(s, "gnam")
- Get #f, n + 16, l
- l += 39
- s = Space(255)
- Get #f, l, s
- n = InStr(s, Chr(0))
- If n Then s = Left(s, n - 1) Else s = Left(s, 40)
- Close f
-
- c.carname = s
- End If
-
- c.author = "" : c.version = ""
- If Len(c.file(9)) <> 0 Then
- Dim f As Integer, s As String, n As Short
-
- f = FreeFile
- Open path & SLASH & c.file(9) For Input As f
- While Not EoF(f)
- Line Input #f, s
- n = InStr(s, "=")
- If n Then
- Select Case LCase(Trim(Left(s, n - 1)))
- Case "version", "ver"
- c.version = Trim(Mid(s, n + 1))
- Case "author"
- c.author = Trim(Mid(s, n + 1))
- End Select
- End If
- WEnd
- Close f
- End If
- End Sub
- Function Resolve(s As String) As String
- 'Obtain a list of cars from a search string that can
- 'be a car, a list of cars, a group or a filter
- Dim n As Short, t As String, ss As String
- Dim result As String
-
- n = InStr(s, ",")
- If n Then 'It's a list
- Dim temp As String
-
- t = s
- Do
- n = InStr(t, ",")
- If n Then
- ss = Left(t, n - 1)
- t = Mid(t, n + 1)
- Else
- ss = t
- t = ""
- End If
-
- temp = Resolve(ss)
- If Len(temp) Then
- If Len(result) Then result &= ","
- result &= temp
- End If
- Loop Until Len(t) = 0
- ElseIf Left(s, 1) = "#" Then 'It's a group
- For i As Short = 1 To groups
- If LCase(group(i).gname) = LCase(Mid(s, 2)) Then Return group(i).cars
- Next i
- ElseIf Len(s) = 4 AndAlso InStr(s, "*") = 0 AndAlso InStr(s, ",") = 0 Then 'It's a car
- Return LCase(s)
- Else 'It's a filter
- Dim filtype As Byte, q As Byte
-
- If s = "*" Then
- filtype = 0
- ElseIf Left(s, 1) = "*" AndAlso Right(s, 1) = "*" Then
- filtype = 1
- ss = LCase(Mid(s, 2, Len(s) - 2))
- ElseIf Left(s, 1) = "*" Then
- filtype = 2
- ss = LCase(Mid(s, 2))
- ElseIf Right(s, 1) = "*" Then
- filtype = 3
- ss = LCase(Left(s, Len(s) - 1))
- Else
- filtype = 1
- ss = LCase(s)
- End If
-
- For g As Short = 0 To garages
- For i As Short = 1 To cars(g)
- q = 0
- Select Case filtype
- Case 0 : q = -1 'All
- Case 1
- If InStr(LCase(car(g, i).carname), ss) _
- OrElse InStr(LCase(car(g, i).id), ss) Then q = -1
- Case 2
- If Right(LCase(car(g, i).carname), Len(ss)) = ss _
- OrElse Right(LCase(car(g, i).id), Len(ss)) = ss Then q = -1
- Case Else
- If Left(LCase(car(g, i).carname), Len(ss)) = ss _
- OrElse Left(LCase(car(g, i).id), Len(ss)) = ss Then q = -1
- End Select
-
- If q <> 0 AndAlso InStr(result, LCase(car(g, i).id)) = 0 Then 'Add car to the list
- If Len(result) Then result &= ","
- result &= LCase(car(g, i).id)
- End If
- Next i
- Next g
- End If
- 'Get rid of repeated cars
- t = result
- result = ""
- Do
- n = InStr(t, ",")
- If n Then
- ss = Left(t, n - 1)
- t = Mid(t, n + 1)
- Else
- ss = t
- t = ""
- End If
-
- If InStr(result, ss) = 0 Then
- If Len(result) Then result &= ","
- result &= ss
- End If
- Loop Until Len(t) = 0
-
- Return result
- End Function
- Function MoveCar (id As String, orig As UByte, dest As UByte) As Byte
- Dim n As Short, many As Byte
-
- If Left(id, 1) = "#" Then 'It's a referenced group
- many = 1
- ElseIf InStr(id, ",") Then 'It's an ad-hoc group
- many = 2
- Else 'It's an individual car
- many = 0
- End If
-
- If many Then
- 'This is a group. Call repeatedly for each car
- Dim s As String, ercount As Short
- Dim thiscar As String, gn As Short = 0
-
- If many = 1 Then
- For i As Short = 1 To groups
- If group(i).gname = LCase(Mid(id, 2)) Then
- gn = i
- Exit For
- End If
- Next i
-
- If gn = 0 Then Return 1 'Group not found
-
- s = group(gn).cars
- Else
- s = id
- End If
-
- Do
- n = InStr(s, ",")
-
- If n Then
- thiscar = LCase(RTrim(Left(s, n - 1)))
- s = LTrim(Mid(s, n + 1))
- Else
- thiscar = LCase(Trim(s))
- s = ""
- End If
-
- ercount += MoveCar(thiscar, orig, dest)
- Loop Until Len(s) = 0
-
- If ercount Then Return 2 Else Return 0
- End If
-
- 'If car is locked, it cannot be moved
- If InStr(LCase(locked), LCase(id)) Then Return 3
-
-
- 'Find car
- n = 0
- For i As Short = 1 To cars(orig)
- If LCase(car(orig, i).id) = LCase(id) Then
- n = i
- Exit For
- End If
- Next i
-
- If n = 0 Then Return 1 'Car not found
-
- 'Move files
- For i As Short = 1 To 8
- If Len(car(orig, n).file(i)) Then
- FileCopy garage(orig).dir & SLASH & car(orig, n).file(i), garage(dest).dir & SLASH & car(orig, n).file(i)
- Kill garage(orig).dir & SLASH & car(orig, n).file(i)
- End If
- Next i
-
- 'Move car in lists
- cars(dest) += 1
- car(dest, cars(dest)) = car(orig, n)
- For i As Short = n To cars(orig)
- car(orig, i) = car(orig, i + 1)
- Next i
- cars(orig) -= 1
-
- Return 0 'Executed successfully
- End Function
- Sub Init
- LoadConfig
- If garage(0).dir = garage(1).dir Then
- Print
- Print "Error: Stunts and garage directory are the same or undefined!"
- Print " Edit sgar.cfg to set them correctly."
- Print
- End
- End If
-
- Dim f As Integer
-
- f = FreeFile
- Open garage(0).dir & SLASH & "test981" For Output As f : Close f
- If FileExists(garage(0).dir & SLASH & "test981") Then
- Kill garage(0).dir & SLASH & "test981"
- Else
- Print
- Print "Error: Stunts directory not properly configured"
- Print " Edit sgar.cfg to select the right directory for it"
- Print
- End
- End If
- Open garage(1).dir & SLASH & "test981" For Output As f : Close f
- If FileExists(garage(1).dir & SLASH & "test981") Then
- Kill garage(1).dir & SLASH & "test981"
- Else
- MkDir garage(1).dir
- Open garage(1).dir & SLASH & "test981" For Output As f : Close f
- If FileExists(garage(1).dir & SLASH & "test981") Then
- Kill garage(1).dir & SLASH & "test981"
- Print
- Print "Created garage directory at " & garage(1).dir
- Print
- Else
- Print
- Print "Error: The current garage directory is not accessible and could"
- Print " not be created. Please edit sgar.cfg to select a garage"
- Print " directory that can be used"
- Print
- End
- End If
- End If
-
- ReadDirs
- For g As Byte = 0 To garages
- For i As Short = 1 To cars(g)
- ExtractCarInfo car(g, i), garage(g).dir
- Next i
- Next g
- End Sub
- Function GarageNumber(gname As String) As Byte
- If ValInt(gname) >= 1 Then Return ValInt(gname)
-
- For i As Short = 1 To garages
- If LCase(garage(i).name) = LCase(gname) Then Return i
- Next i
- End Function
- Sub Echo (s As String = "", eol As Byte = -1)
- If eol Then
- Print s
- Else
- Print s;
- End If
- End Sub
- Sub RunCommand (s As String)
- Dim As String c, p(1 To 7), t
- Dim n As Short, ps As Byte
-
- n = InStr(s, " ")
- If n Then
- c = LCase(Trim(Left(s, n - 1)))
- t = Trim(Mid(s, n + 1))
- For i As Byte = 1 To 7
- ps += 1
- n = InStr(t, " ")
- If n Then
- p(ps) = RTrim(Left(t, n - 1))
- t = LTrim(Mid(t, n))
- Else
- p(ps) = t
- Exit For
- End If
- Next i
- Else
- c = LCase(Trim(s))
- ps = 0
- End If
-
- Select Case c
- Case ""
- Case "addto"
- Dim thisgroup As Short, st As String, ss As String
-
- If ps <> 2 Then
- Echo "Use: addto <group> <carid>"
- Echo
- Exit Sub
- End If
-
- For i As Short = 1 To groups
- If group(i).gname = LCase(p(1)) Then
- thisgroup = i
- Exit For
- End If
- Next i
-
- st = Resolve(p(2))
-
- Do
- n = InStr(st, ",")
- If n Then
- ss = Left(st, n - 1)
- st = Mid(st, n + 1)
- Else
- ss = st
- st = ""
- End If
-
- If Len(ss) <> 4 Then
- Echo "invalid car id: " & ss
- ElseIf thisgroup = 0 Then
- groups += 1
- group(groups).gname = LCase(p(1))
- group(groups).cars = LCase(ss)
- Echo "Created group " & p(1) & " with car " & ss
- thisgroup = groups
- ElseIf InStr(LCase(group(thisgroup).cars), LCase(ss)) Then
- Echo "Car " & ss & " is already present in group " & p(1)
- Else
- group(thisgroup).cars &= "," & LCase(ss)
- Echo "Added " & ss & " to " & p(1)
- End If
- Loop Until Len(st) = 0
- Echo ""
- SaveConfig
- Case "bring", "retrieve"
- Dim n As Short, t As String, tt As String, c As Short
- Dim g As Short
-
- If ps = 0 OrElse ps > 3 Then
- Echo "Use: retrieve|bring <carID> [[from] <garage>]"
- Echo ""
- Else
- If LCase(p(2)) = "from" Then p(2) = p(3)
- g = 0
- If ps > 1 Then 'Specified garage
- g = GarageNumber(p(2))
- If g > garages Then
- Echo "Only " & garages & " garages available!"
- Echo ""
- Exit Sub
- End If
- End If
-
- t = Resolve(p(1))
- Do
- c = InStr(t, ",")
- If c Then
- tt = Left(t, c - 1)
- t = Mid(t, c + 1)
- Else
- tt = t
- t = ""
- End If
-
- If g Then
- n = MoveCar(tt, g, 0)
- Else
- For i As Short = 1 To garages
- If LCase(garage(i).name) <> "junkyard" Then
- n = MoveCar(tt, i, 0)
- If n = 0 Then Exit For
- End If
- Next i
- End If
- Select Case n
- Case 0 : Echo "Successfully retrieved " & tt
- Case 1 : Echo "Car not found: " & tt
- Case 2 : Echo "Some cars retrieved"
- Case 3 : Echo "Car is locked and cannot be retrieved: " & tt
- Case Else : Echo "Unknown error"
- End Select
- Loop Until Len(t) = 0
- Echo ""
- End If
- Case "car"
- If ps <> 1 Then
- Echo "Use: car <car>"
- Echo ""
- Exit Sub
- End If
-
- p(1) = Resolve(p(1))
- If InStr(p(1), ",") Then
- Echo "Only a single car ID allowed for this command"
- Echo
- Exit Sub
- End If
-
- For g As Byte = 0 To garages
- For i As Short = 1 To cars(g)
- If LCase(car(g, i).id) = LCase(p(1)) Then
- Echo "Car name: " & car(g, i).carname
- If Len(car(g, i).version) Then Echo "Version: " & car(g, i).version
- If Len(car(g, i).author) Then Echo "Author: " & car(g, i).author
- Echo "Car ID: " & UCase(car(g, i).id)
- Echo "Found in: ", 0
- If Len(garage(g).name) Then Echo garage(g).name Else Echo "Garage #" & g
- Echo "Groups: ", 0
- Dim q As Short = 0
- For j As Short = 1 To groups
- If InStr(LCase(group(j).cars), LCase(car(g, i).id)) Then
- If q Then Echo ", ", 0
- q += 1
- Echo group(j).gname, 0
- End If
- Next j
- If q = 0 Then Echo "None" Else Echo
- Echo "Files: " & car(g, i).numfiles
- For j As Byte = 1 To 9
- If Len(car(g, i).file(j)) Then
- Echo " - " & car(g, i).file(j), 0
- Select Case Right(LCase(car(g, i).file(j)), 4)
- Case ".pvs", ".p3s", ".pre" : Echo " (packed)"
- Case Else : Echo " (unpacked)"
- End Select
- End If
- Next j
- Echo
- Exit Sub
- End If
- Next i
- Next g
-
- Echo "Car not found: " & p(1)
- Echo
- Case "cars"
- Dim total As Short
-
- Echo cars(0) & " cars ready for Stunts"
- For i As Short = 1 To garages
- Echo cars(i) & " cars in ", 0
- If Len(garage(i).name) Then Echo garage(i).name Else Echo "garage #" & i
- total += cars(i)
- Next i
- Echo total & " cars parked"
- Echo cars(0) + total & " total cars"
- If Len(locked) Then
- Dim t As String, tn As Short, num As Short
-
- t = locked
- Do
- tn = InStr(t, ",")
- If tn Then
- num += 1
- t = Mid(t, tn + 1)
- Else
- num += 1
- Exit Do
- End If
- Loop
- Echo num & " locked"
- End If
- Echo
- Case "dirs"
- For i As Short = 0 To garages
- If Len(garage(i).name) Then Echo garage(i).name, 0 Else Echo "Garage #" & i, 0
- Echo ": " & garage(i).dir
- Next i
- Echo
- Case "garagedir", "gdir"
- If Len(p(1)) = 0 Then
- Echo "Use: garagedir [<garage>] <directory>"
- Echo
- Exit Sub
- End If
-
- Dim gd As String, gn As Byte
-
- If ps = 1 Then
- gd = p(1)
- gn = 1
- Else
- gd = p(2)
- gn = 0
- End If
-
- If Open(gd & SLASH & "a123.tmp", For Output, As 1) Then
- Echo "Invalid path: " & gd
- Echo
- Else
- Close 1
- Kill gd & SLASH & "a123.tmp"
-
- If gn Then
- garage(1).dir = gd
- Else
- gn = 0
- If ValInt(p(1)) Then
- gn = ValInt(p(1))
- If gn > garages Then gn = 0
- Else
- For i As Short = 1 To garages
- If LCase(garage(i).name) = LCase(p(1)) Then
- gn = i
- Exit For
- End If
- Next i
- End If
-
- If gn Then
- garage(gn).dir = gd
- ElseIf garages < 15 Then
- garages += 1 : gn = garages
- garage(garages).dir = gd
- garage(garages).name = ""
- End If
- End If
-
- SaveConfig
- For i As Short = 0 To garages
- cars(i) = 0
- Next i
- garages = 1
- Init
- Echo "New garage #" & gn & " directory is " & gd
- Echo
- End If
- Case "garagename", "gname"
- If Len(p(1)) = 0 Then
- Echo "Use: garagename <garage> [new_name]"
- Echo
- Exit Sub
- End If
-
- If ps = 1 Then p(2) = ""
- If ValInt(p(1)) > garages Then
- Echo "There's no garage #" & ValInt(p(1)) & ". Only " & garages & " exist!"
- Echo
- Exit Sub
- End If
-
- If ValInt(p(1)) = 0 Then
- For i As Short = 1 To garages
- If LCase(garage(i).name) = LCase(p(1)) Then
- p(1) = Str(i)
- Exit For
- End If
- Next i
- End If
-
- If ValInt(p(1)) Then
- garage(ValInt(p(1))).name = p(2)
- SaveConfig
- If Len(p(2)) Then
- Echo "Garage #" & ValInt(p(1)) & " renamed as " & p(2)
- Else
- Echo "Garage #" & ValInt(p(1)) & " is now nameless"
- End If
- Echo
- Else
- Echo "Invalid garage"
- Echo
- End If
- Case "rmgarage", "rmg"
- If ps = 0 Then
- Echo "Use: rmgarage <garage>"
- Echo
- Exit Sub
- End If
-
- If ValInt(p(1)) = 0 Then
- For i As Short = 1 To garages
- If LCase(garage(i).name) = LCase(p(1)) Then
- p(1) = Str(i)
- Exit For
- End If
- Next i
- End If
-
- If ValInt(p(1)) > garages Then
- Echo "There are only " & garages & " garages!"
- ElseIf ValInt(p(1)) <= 0 Then
- Echo "Invalid garage"
- ElseIf ValInt(p(1)) = 1 AndAlso garages = 1 Then
- Echo "Cannot remove the only garage"
- Else
- For i As Short = ValInt(p(1)) To garages - 1
- garage(i) = garage(i + 1)
- Next i
- garages -= 1
- SaveConfig
- Echo "Removed garage from list"
- Echo "Please note that any cars in the removed garage will remain"
- Echo "in the garage directory!"
- End If
- Echo
- Case "list", "ls", "lp", "lg", "lj", "l"
- Dim As Byte fil(0 To 15) 'Filter flags
- Dim thislist As String, acar As String, comma As Short
- Dim carcount As Short, found As Byte
-
- Select Case Mid(c, 2)
- Case "", "ist"
- If ps = 2 Then
- Dim g As Short
- g = GarageNumber(p(2))
- If g >= 0 AndAlso g <= 15 Then fil(g) = -1
- Else
- For i As Short = 0 To garages
- fil(i) = -1
- Next i
- End If
- Case "s" : fil(0) = -1
- Case "g", "p"
- For i As Short = 1 To garages
- If LCase(garage(i).name) <> "junkyard" Then fil(i) = -1
- Next i
- Case "j"
- Dim g As Byte
- g = GarageNumber("junkyard")
- If g Then
- fil(g) = -1
- Else
- Echo "No junkyard found"
- Echo
- Exit Sub
- End If
- End Select
-
- If p(1) = "" Then p(1) = "*"
- thislist = Resolve(p(1)) : carcount = 0
- Do
- comma = InStr(thislist, ",")
- If comma Then
- acar = Left(thislist, comma - 1)
- thislist = Mid(thislist, comma + 1)
- Else
- acar = thislist
- thislist = ""
- End If
-
- found = 0
- For j As Short = 0 To garages
- If fil(j) Then
- For i As Short = 1 To cars(j)
- If LCase(car(j, i).id) = LCase(acar) Then
- Echo car(j, i).carname & Space(30 - Len(car(j, i).carname)), 0
- Echo UCase(car(j, i).id), 0
- If car(j, i).numfiles <> 4 Then Echo "! ", 0 Else Echo " ", 0
- If j Then
- If Len(garage(j).name) Then
- Echo garage(j).name
- Else
- Echo "Garage", 0
- If garages > 1 Then
- Echo " #" & j
- Else
- Echo
- End If
- End If
- Else
- Echo "Stunts"
- End If
- carcount += 1
- found = -1
- Exit For
- End If
- Next i
- End If
- Next j
- Loop Until Len(thislist) = 0
- If carcount > 1 Then
- Echo carcount & " cars found"
- ElseIf carcount = 1 Then
- Echo "1 car found"
- Else
- Echo "No cars found"
- End If
- Echo
- Case "park"
- Dim n As Short, t As String, tt As String, c As Short
- Dim g As Short
-
- If ps < 1 OrElse ps > 2 Then
- Echo "Use: park <carID> [<garage>]"
- Echo
- Else
- g = 1
- If ps = 2 Then
- g = GarageNumber(p(2))
- If g > garages Then
- Echo "Only " & garages & " garages available"
- Echo
- Exit Sub
- End If
- End If
-
- t = Resolve(p(1))
- Do
- c = InStr(t, ",")
- If c Then
- tt = Left(t, c - 1)
- t = Mid(t, c + 1)
- Else
- tt = t
- t = ""
- End If
-
- n = MoveCar(tt, 0, g)
- Select Case n
- Case 0 : Echo "Successfully parked " & tt
- Case 1 : Echo "Car not found: " & tt
- Case 2 : Echo "Some cars parked"
- Case 3 : Echo "Car is locked and cannot be parked: " & tt
- Case Else : Echo "Unknown error"
- End Select
- Loop Until Len(t) = 0
- Echo
- End If
- Case "stunts"
- If Len(1) = 0 Then
- Echo "Use: stunts <directory>"
- Echo
- ElseIf Open(p(1) & SLASH & "a123.tmp", For Output, As 1) Then
- Echo "Invalid path: " & p(1)
- Echo
- Else
- Close 1
- Kill p(1) & SLASH & "a123.tmp"
- garage(0).dir = p(1)
- SaveConfig
- For g As Byte = 0 To garages
- cars(g) = 0
- Next g
- garages = 1
- Init
- Echo "New Stunts directory is " & p(1)
- Echo
- End If
- Case "groups", "gs"
- Dim i As Short
- For i = 1 To groups
- Echo group(i).gname
- Next i
- Echo
- Echo i - 1 & " group", 0
- If i - 1 = 1 Then Echo Else Echo "s"
- Echo
- Case "group", "g"
- RunCommand "l #" & p(1)
- Case "removefrom", "rf"
- Dim thisgroup As Short, st As String, ss As String, nn As Short
-
- If ps <> 2 Then
- Echo "Use: removefrom/rf <group> <carid>"
- Echo
- Exit Sub
- End If
-
- For i As Short = 1 To groups
- If group(i).gname = LCase(p(1)) Then
- thisgroup = i
- Exit For
- End If
- Next i
-
- If thisgroup = 0 Then
- Echo "Group not found: " & p(1)
- Echo
- Exit Sub
- End If
-
- st = Resolve(p(2))
- Do
- nn = InStr(st, ",")
- If nn Then
- ss = Left(st, nn - 1)
- st = Mid(st, nn + 1)
- Else
- ss = st
- st = ""
- End If
-
- n = InStr(LCase(group(thisgroup).cars), LCase(ss))
- If Len(ss) <> 4 Then
- Echo "invalid car id: " & ss
- ElseIf n = 0 Then
- Echo "Car " & ss & " was not in that group"
- Else
- Dim As String b1, b2, temp
- b1 = LCase(Trim(group(thisgroup).cars))
- Do
- n = InStr(b1, ",")
- If n Then
- temp = RTrim(Left(b1, n - 1))
- b1 = LTrim(Mid(b1, n + 1))
- Else
- temp = RTrim(b1)
- b1 = ""
- End If
-
- If temp <> LCase(ss) Then
- If b2 = "" Then b2 = temp Else b2 &= "," & temp
- End If
- Loop Until Len(b1) = 0
- If Len(b2) Then
- group(thisgroup).cars = b2
- Echo "Removed " & ss & " from group " & p(1)
- Else
- For i As Short = thisgroup To groups - 1
- group(i) = group(i + 1)
- Next i
- groups -= 1
- Echo "Removed group " & p(1)
- Exit Do
- End If
- End If
- Loop Until Len(st) = 0
- Echo
- SaveConfig
- Case "delgroup", "rmgroup"
- If ps <> 1 Then
- Echo "Use: delgroup|rmgroup <group>"
- Echo
- Exit Sub
- End If
-
- If Left(p(1), 1) = "#" Then p(1) = Mid(p(1), 2)
-
- Dim q As Byte = 0
-
- For i As Short = 1 To groups
- If LCase(p(1)) = LCase(group(i).gname) Then
- q = -1
- For j As Short = i To groups - 1
- group(j) = group(j + 1)
- Next j
- groups -= 1
- SaveConfig
- Echo "Removed group " & p(1)
- Echo
- Exit For
- End If
- Next i
-
- If q = 0 Then
- Echo "Group not found: " & p(1)
- Echo
- End If
- Case "groupthese", "gt"
- If ps <> 1 Then
- Echo "Use: groupthese|gs <group>"
- Echo
- Exit Sub
- End If
- If cars(0) = 0 Then
- Echo "No cars to add to group"
- Echo
- Exit Sub
- End If
- For i As Short = 1 To cars(0)
- RunCommand "addto " & p(1) & " " & car(0, i).id
- Next i
- SaveConfig
- Case "only"
- If ps <> 1 Then
- Echo "Use: only <group>"
- Echo
- Exit Sub
- End If
-
- If Left(p(1), 1) = "#" Then p(1) = Mid(p(1), 2)
-
- Dim g As Short = 0
-
- For i As Short = 1 To groups
- If LCase(p(1)) = LCase(group(i).gname) Then
- g = i
- Exit For
- End If
- Next i
-
- If g = 0 Then
- Echo "Group not found: " & p(1)
- Echo
- Exit Sub
- End If
-
- 'Move to garage cars that are not in group
- For i As Short = 1 To cars(0)
- If InStr(LCase(group(g).cars), LCase(car(0, i).id)) = 0 Then
- RunCommand "park " & car(0, i).id
- i -= 1
- End If
- If i = cars(0) Then Exit For
- Next i
-
- 'Move to Stunts cars that are in group
- For i As Short = 1 To cars(1)
- If InStr(LCase(group(g).cars), LCase(car(1, i).id)) Then
- RunCommand "bring " & car(1, i).id
- i -= 1
- End If
- If i = cars(1) Then Exit For
- Next i
- Case "lock"
- If ps <> 1 Then
- Echo "Use: lock <carID>"
- Echo
- Exit Sub
- End If
- p(1) = LCase(Trim(p(1)))
-
- If InStr(p(1), ",") Then
- Echo "Only one car ID allowed for this command"
- Echo
- Exit Sub
- End If
-
- If Len(p(1)) <> 4 Then
- Echo "Invalid car ID: " & UCase(p(1))
- Echo
- Exit Sub
- End If
- If InStr(locked, p(1)) Then
- Echo "Car already locked: " & UCase(p(1))
- Echo
- Exit Sub
- End If
- If Len(locked) Then locked &= ","
- locked &= p(1)
- Echo "Locked " & UCase(p(1))
- Echo
- SaveConfig
- Case "unlock"
- If ps <> 1 Then
- Echo "Use: lock <carID>"
- Echo
- Exit Sub
- End If
- p(1) = LCase(Trim(p(1)))
-
- If InStr(p(1), ",") Then
- Echo "Only one car ID allowed for this command"
- Echo
- Exit Sub
- End If
-
- If Len(p(1)) <> 4 Or InStr(p(1), ",") <> 0 Then
- Echo "Invalid car ID: " & UCase(p(1))
- Echo
- Exit Sub
- End If
- Dim n As Short
- n = InStr(locked, p(1))
- If n = 0 Then
- Echo "Car already unlocked: " & UCase(p(1))
- Echo
- Exit Sub
- End If
- locked = Left(locked, n - 1) & Mid(locked, n + 4)
- n = InStr(locked, ",,")
- If n Then locked = Left(locked, n) & Mid(locked, n + 2)
- If Right(locked, 1) = "," Then locked = Left(locked, Len(locked) - 1)
- If Left(locked, 1) = "," Then locked = Mid(locked, 2)
- Echo "Unlocked car: " & UCase(p(1))
- Echo
- SaveConfig
- Case "locked"
- If Len(locked) Then
- Echo "Locked cars: " & locked
- Else
- Echo "No cars locked"
- End If
- Echo
- Case "version", "ver"
- Echo "Simple Garage v" & SGVERSION & ", released " & release_date & " - by Cas"
- Echo
- Case "resolve"
- Echo Resolve(p(1))
- Echo
- Case "help"
- If LCase(p(1)) = "filters" Then
- Echo "Most commands in which a car o more can be specified,"
- Echo "where you see a parameter like <car(s)> can use any of"
- Echo "the following:"
- Echo
- Echo "- A single car ID, e.g.: pmin"
- Echo "- A group preceeded by a # sign, e.g.: #mycars"
- Echo "- A filter such as: Porsche*"
- Echo "- A comma-separated list of any of the above: jagu,*n,#orig,fgto"
- Echo
- Echo "Comma-separated lists are called ad-hoc groups in contrast"
- Echo "to referenced groups, which are preceeded by a #."
- Echo "Filters can be of either of the forms:"
- Echo
- Echo "*xyz - ending in xyz"
- Echo "xyz* - beginning with xyz"
- Echo "*xyz* - containing xyz"
- Echo "xyz - also containing xyz (as long as length is not 4)"
- Echo
- Echo "Four characters in a row will be assumed to be a car ID"
- Echo
- Exit Sub
- End If
-
- Echo "addto <group> <car(s)> - Add car(s) to group"
- Echo "car <carID> - Display information about a car"
- Echo "cars - Display number of cars in Stunts & garage"
- Echo "delgroup|rmgroup <group> - Delete a group"
- Echo "dirs - Display current directories"
- Echo "exit|quit - Leave Simple Garage"
- Echo "group|g <group> - List cars in group"
- Echo "groups|gs - List groups"
- Echo "groupthese|gt <group> - Add all cars currently in Stunts to group"
- Echo "lg|lp <car(s)> - List cars among the ones in the garage"
- Echo "list|l <car(s)> - List cars among all available"
- Echo "lock <carID> - Lock car"
- Echo "locked - List locked car IDs"
- Echo "ls <car(s)> - List cars among those ready in Stunts"
- Echo "only <group> - Bring all cars in group and park all others"
- Echo "park <car(s)> [garage] - Park car(s) in garage"
- Echo "removefrom|rf <group> <car(s)> - Remove car(s) from group"
- Echo "retrieve|bring <car(s)> [garage] - Bring car(s) back to Stunts"
- Echo "unlock <carID> - Unlock car"
- Echo "version|ver - Display program version"
- Echo
- Echo "Type 'help filters' for more information on car lists"
- Echo
- Case "exit", "quit" : End
- Case Else
- Echo "Uknown command: " & c
- Echo
- End Select
- End Sub
- Sub MyInput (s As String, maxlength As Short)
- Dim akey As String, t As String, cpos As Short = 1
- Dim As Short startx, starty
- Dim update As Byte = -1, lastn As Byte
-
- startx = Pos(0)
- starty = CSRLin
-
- Do
- If update Then
- Locate starty, startx
- Print t & Space(80 - Len(t) - startx);
- Line (8 * (startx - 2 + cpos), 16 * starty - 3)- Step (7, 0)
- update = 0
- End If
-
- akey = InKey
- Sleep 10
-
- Select Case akey
- Case " " To Chr(126)
- If Len(t) < maxlength Then
- t = Left(t, cpos - 1) & akey & Mid(t, cpos)
- cpos += 1
- update = -1
- End If
- Case Chr(8)
- If cpos > 1 Then
- t = Left(t, cpos - 2) & Mid(t, cpos)
- cpos -= 1
- update = -1
- End If
- Case Chr(255, 77)
- If cpos < Len(t) + 1 Then
- cpos += 1
- update = -1
- End If
- Case Chr(255, 75)
- If cpos > 1 Then
- cpos -= 1
- update = -1
- End If
- Case Chr(255, 83)
- If cpos <= Len(t) Then
- t = Left(t, cpos - 1) & Mid(t, cpos + 1)
- update = -1
- End If
- Case Chr(255, 71)
- cpos = 1
- update = -1
- Case Chr(255, 79)
- cpos = Len(t) + 1
- update = -1
- Case Chr(255, 72)
- If lastn < 10 Then
- lastn += 1
- t = lastcommand(lastn)
- cpos = Len(t) + 1
- update = -1
- End If
- Case Chr(255, 80)
- If lastn > 0 Then
- lastn -= 1
- If lastn Then
- t = lastcommand(lastn)
- Else
- t = ""
- End If
- cpos = Len(t) + 1
- update = -1
- End If
- Case Chr(13)
- s = t
- Exit Do
- Case Chr(27)
- t = ""
- cpos = 1
- update = -1
- Case Chr(255) & "k"
- s = "exit"
- Exit Do
- End Select
- Loop
-
- Locate starty, startx : Print t & " "
- End Sub
- release_date = __DATE_ISO__
- copyright_notice = "Copyright (C) 2022 - Lucas Pedrosa" & Chr(10) & _
- "This program is free software distributed under the GPLv3" & Chr(10) & _
- "See license.txt for details"
- If Command = "/?" Or LCase(Command) = "--help" Then
- Print "Simple Garage " & SGVERSION & ", released " & release_date
- Print "Garage manager program for Stunts"
- Print copyright_notice
- Print
- Print "Use: sgar <command>"
- Print "to execute individual commands"
- Print "Or: sgar"
- Print "to access the GUI console"
- Print
- End
- End If
- If Len(Command) Then
- Dim comline As String, n As Short
-
- comline = Command
- Do
- n = InStr(comline, "%")
- If n Then Mid(comline, n, 1) = "*"
- Loop Until n = 0
- Do
- n = InStr(comline, "@")
- If n Then Mid(comline, n, 1) = "#"
- Loop Until n = 0
-
- Init
- RunCommand comline
- End
- End If
- ScreenRes 640, 480
- Width 80, 30
- WindowTitle "Simple Garage " & SGVERSION
- Dim s As String
- Color 15
- Print "Simple Garage " & SGVERSION & ", released " & release_date
- Color 7
- Print copyright_notice
- Print
- Color 15
- Init
- Do
- Color 10 : Print "@>";
- Color 15 : MyInput s, 70
- Color 7 : RunCommand s
- For i As Short = 10 To 2 Step -1
- lastcommand(i) = lastcommand(i - 1)
- Next i
- lastcommand(1) = s
- Loop
|