REM Program: Hex Editor v7.7a, Module 2 of 6, PD 2007.
REM Author: Erik Jon Oredson AS. Csci
REM Release: 10/15/2007.
REM Status: Public Domain.
REM Email: eoredson@gmail.com
REM Urls: www.filegate.net www.simtel.net

' get include file.
REM $INCLUDE: 'hexedit.inc'

REM Subroutines:
REM   CalculatePosition1    --  calculate screen values given file position.
REM   CalculatePosition2    --  calculate screen values given variable.
REM   Colorf            --  specialized color function.
REM   Colorf2           --  specialized color function.
REM   DisplayBootUsage  --  display boot usage.
REM   DisplayScreen     --  display main editing screen.
REM   DisplayScreen2    --  display screen border.
REM   Deconcatenate     --  deconcatenates filename.
REM   DropDownMenu      --  starts top drop down menu.
REM   DisplayTab        --  redraws menu tab.
REM   DisplayCriticalError  --  display error trap message.
REM   ExcludeList       --  gets exluded filelist for menu.
REM   GetDrive          --  reads default drive/directory.
REM   InitializePaste   --  initialize paste file.
REM   InitPasteFiles    --  init paste files for new file.
REM   InitVars          --  inits some startup variables.
REM   Locatef           --  specialized locate function.
REM   MultiFileFunction     --  routine to process multiple files.
REM   OpenDataFiles     --  search for and open data files.
REM   OpenUndoFile      --  open undo/marker file.
REM   OpenPasteFiles    --  open paste files.
REM   Printf            --  specialized print function.
REM   ReadCommandLine   --  reads lowercase command line.
REM   ReadConfigFile    --  search for and read configure file.
REM   StoreServerName   --  stores default server name.

REM Reads lowercase command line.
SUB ReadCommandLine(Var$)
 On Local Error Resume Next
 Var$ = Nul
 InregsX.AX = &H6200
 CALL InterruptX(&H21, InregsX, OutregsX)
 PSPsegment = OutregsX.BX
 PSPoffset = 128
 DEF SEG = PSPsegment
 FOR Count = 1 TO 127
    CommandChar = PEEK(PSPoffset + Count)
    SELECT CASE CommandChar
    CASE 0, 10, 13
       EXIT FOR
    CASE ELSE
       Var$ = Var$ + CHR$(CommandChar)
    END SELECT
 NEXT
 DEF SEG
 Var$ = RTRIM$(Var$)
END SUB

REM Gets default drive/directory.
SUB GetDrive(Drive.Number, Directory$)
 On Local Error Resume Next
 InregsX.AX = &H1900
 CALL InterruptX(&H21, InregsX, OutregsX)
 Drive.Number = OutregsX.AX AND &HFF ' 0=a, 1=b, ..

 ' check windows dos.
 IF Windows.Detected THEN
    ' get current directory.
    InregsX.AX = &H7147
    InregsX.DX = Drive.Number + 1
    InregsX.DS = VARSEG(ASCIIZ3)
    InregsX.SI = VARPTR(ASCIIZ3)
    CALL InterruptX(&H21, InregsX, OutregsX)
 ELSE
    ' get current directory.
    InregsX.AX = &H4700
    InregsX.DX = Drive.Number + 1
    InregsX.DS = VARSEG(ASCIIZ3)
    InregsX.SI = VARPTR(ASCIIZ3)
    CALL InterruptX(&H21, InregsX, OutregsX)
 END IF

 ' store current directory.
 Directory.ASCIIZ = ASCIIZ3
 Directory$ = Directory.ASCIIZ
 Var = Instr(Directory$, Chr$(0))
 If Var Then
    Directory$ = Left$(Directory$, Var - 1)
 Endif
END SUB

REM Store default server name.
SUB StoreServerName
 On Local Error Resume Next

 ' store default server name.
 DefaultNetPath = Nul
 InregsX.AX = &H5E00
 InregsX.DS = VARSEG(ASCIIZ3)
 InregsX.DX = VARPTR(ASCIIZ3)
 CALL InterruptX(&H21, InregsX, OutregsX)

 ' check error flag.
 IF (OutregsX.Flags AND &H1) = &H0 THEN
    ' read CH
    VarS = (OutregsX.CX AND &HFF00) / 256
    IF VarS > 0 THEN ' valid name.
       DefaultNetPath = ASCIIZ3
       Imbedded = INSTR(DefaultNetPath, CHR$(0))
       IF Imbedded THEN
          DefaultNetPath = LEFT$(DefaultNetPath, Imbedded - 1)
       END IF
    END IF
 END IF
END SUB

REM Subroutine to init variables.
SUB InitVars
 On Local Error Resume Next

 ' init a quote symbol.
 Quote = CHR$(34)

 ' init screen colors.
 Black = 0
 Blue = 1
 Cyan = 11
 Green = 10
 Magenta = 13
 Plain = 7
 Red = 12
 White = 15
 Yellow = 14

 ' init ascii characters.
 Hline = 205
 Vline = 186
 ULcorner = 201
 URcorner = 187
 LLcorner = 200
 LRcorner = 188

 ' store video page.
 InregsX.AX=&H0F00
 Call InterruptX(&H10,InregsX,OutregsX)
 Video.Page=OutregsX.BX

 ' store basic dta.
 InregsX.AX = &H2F00
 CALL InterruptX(&H21, InregsX, OutregsX)
 BASIC.DTA.SEG = OutregsX.ES
 BASIC.DTA.OFF = OutregsX.BX

 ' check for DOS or Windows loaded.
 Windows.Detected = True
 InregsX.AX = &H160A
 CALL InterruptX(&H2F, InregsX, OutregsX)
 IF OutregsX.AX > 0 THEN
    InregsX.AX = &H4A33
    CALL InterruptX(&H2F, InregsX, OutregsX)
    IF OutregsX.AX = 0 THEN
       Windows.Detected = 0 ' DOS 7.00/7.10
    END IF
 END IF

 ' store mouse timing.
 MouseTime = 1!

 ' check mouse present.
 Mouse.Present = False
 CALL MouseFunction(CheckMouse, 0)
 IF OutregsX.AX = &HFFFF THEN
    ' set pixels per row/column.
    InregsX.AX = 7
    InregsX.BX = 0
    InregsX.CX = 0
    InregsX.DX = 632
    CALL InterruptX(&H33, InregsX, OutregsX)
    InregsX.AX = 8
    InregsX.BX = 0
    InregsX.CX = 0
    InregsX.DX = 192
    CALL InterruptX(&H33, InregsX, OutregsX)
    Mouse.Present = True
 END IF

 ' init filename variables.
 ConfigFile = "hexedit.cfg"
 DumpFile = "hexedit.dmp"
 ExcludeFile = "hexedit.exd"

 ' restore data.
 RESTORE

 ' read Alt-<key> data.
 REDIM Keys(26) AS INTEGER
 FOR Var = 1 TO 26
    READ Keys(Var)
 NEXT

 ' scancodes for Alt-A to Alt-Z.
 DATA  30, 48, 46, 32, 18, 33, 34, 35, 23, 36 
 DATA  37, 38, 50, 49, 24, 25, 16, 19, 31, 20 
 DATA  22, 47, 17, 45, 21, 44 
END SUB

REM subroutine to send string of characters to screen.
SUB Printf(Var1$)
 On Local Error Resume Next
 InregsX2=InregsX ' store register state.
 VarZ=Video.Page*256+Background.Color*16+Foreground.Color
 For VarX=1 To Len(Var1$)
    VarY=Asc(Mid$(Var1$,VarX,1))
    InregsX.AX=&H0900+VarY
    InregsX.BX=VarZ
    InregsX.CX=1 ' char
    Call InterruptX(&H10,InregsX,OutregsX)
    ' reposition cursor.
    If Pos(0)+1<=80 Then
       Locate Csrlin,Pos(0)+1,0
    Endif
 Next
 InregsX=InregsX2 ' restore register state.
END SUB

REM subroutine stores recent color change.
SUB Colorf(Var)
 On Local Error Resume Next
 Foreground.Color=Var
 Color Var
END SUB

REM subroutine stores recent color change.
SUB Colorf2(Var1,Var2)
 On Local Error Resume Next
 Foreground.Color=Var1
 Background.Color=Var2
 Color Var1,Var2
END SUB

REM subroutine sets cursor position.
SUB LOCATEf(Var1,Var2,Var3)
 On Local Error Resume Next
 ' test end of page.
 If Var1>24 Then
    ' scroll screen.
    InregsX2=InregsX
    InregsX.AX=&H0601
    InregsX.BX=&H0700
    InregsX.CX=&H0000
    InregsX.DX=24*256+&H4F
    Call InterruptX(&H10,InregsX,OutregsX)
    Var1=24
    InregsX=InregsX2
 Endif
 Locate Var1,Var2,Var3
END SUB

REM subroutine to access multiple file structure.
SUB MultiFileFunction(Var)
 On Local Error Resume Next
 Select Case Var
 Case 1 ' Init new file.
    File(CurrentFile).AsciiValue = False
    File(CurrentFile).ASCIIZ = ASCIIZ
    File(CurrentFile).Buffer = CHR$(0)
    File(CurrentFile).CopyPositionEnd = 0
    File(CurrentFile).CopyPositionPivot = 0
    File(CurrentFile).CopyPositionStart = 0
    File(CurrentFile).CurrentMarker = 0!
    File(CurrentFile).CurrentUndo = 0!
    File(CurrentFile).CurrentWindow2 = 0
    File(CurrentFile).Filename = Filename
    File(CurrentFile).FileAttribute = FileAttribute
    File(CurrentFile).FileByte = CHR$(0)
    File(CurrentFile).FileLength = FileLength
    File(CurrentFile).FileLocked = FileLocked
    File(CurrentFile).FilePage = 1
    File(CurrentFile).FilePosition = 1
    File(CurrentFile).Handle = Handle
    File(CurrentFile).MarkerCount = 0!
    File(CurrentFile).NetPath = CurrentNetPath
    File(CurrentFile).PageColumn = 1
    File(CurrentFile).PageRow = 1
    File(CurrentFile).ShortFilename = ShortFilename
 Case 2 ' Store current file.
    File(CurrentFile).AsciiValue = AsciiValue
    File(CurrentFile).ASCIIZ = ASCIIZ
    File(CurrentFile).Buffer = Buffer
    File(CurrentFile).CopyPositionEnd = CopyPositionEnd
    File(CurrentFile).CopyPositionPivot = CopyPositionPivot
    File(CurrentFile).CopyPositionStart = CopyPositionStart
    File(CurrentFile).CurrentMarker = CurrentMarker
    File(CurrentFile).CurrentUndo = CurrentUndo
    File(CurrentFile).CurrentWindow2 = CurrentWindow2
    File(CurrentFile).Filename = Filename
    File(CurrentFile).FileAttribute = FileAttribute
    File(CurrentFile).FileByte = FileByte
    File(CurrentFile).FileLength = FileLength
    File(CurrentFile).FileLocked = FileLocked
    File(CurrentFile).FilePage = FilePage
    File(CurrentFile).FilePosition = FilePosition
    File(CurrentFile).Handle = Handle
    File(CurrentFile).MarkerCount = MarkerCount
    File(CurrentFile).NetPath = CurrentNetPath
    File(CurrentFile).PageColumn = PageColumn
    File(CurrentFile).PageRow = PageRow
    File(CurrentFile).ShortFilename = ShortFilename
 Case 3 ' Restore current file.
    AsciiValue = File(CurrentFile).AsciiValue
    ASCIIZ = File(CurrentFile).ASCIIZ
    Buffer = File(CurrentFile).Buffer
    CopyPositionEnd = 0
    CopyPositionPivot = 0
    CopyPositionStart = 0
    CurrentMarker = File(CurrentFile).CurrentMarker
    CurrentUndo = File(CurrentFile).CurrentUndo
    CurrentWindow2 = File(CurrentFile).CurrentWindow2
    Filename = File(CurrentFile).Filename
    FileAttribute = File(CurrentFile).FileAttribute
    FileByte = File(CurrentFile).FileByte
    FileLength = File(CurrentFile).FileLength
    FileLocked = File(CurrentFile).FileLocked
    FilePage = File(CurrentFile).FilePage
    FilePosition = File(CurrentFile).FilePosition
    Handle = File(CurrentFile).Handle
    MarkerCount = File(CurrentFile).MarkerCount
    CurrentNetPath = File(CurrentFile).NetPath
    PageColumn = File(CurrentFile).PageColumn
    PageRow = File(CurrentFile).PageRow
    ShortFilename = File(CurrentFile).ShortFilename
 End Select
END SUB

REM subroutine to open undo/marker files,
REM   also counts opened hexedit processes.
SUB OpenUndoFile(Var2)
 ON LOCAL ERROR GOTO Error.Routine1
 ' reset process counter.
 Var = False
 Var2 = False
 ' start counter loop.
 DO
    ' make temp filename with counter.
    V1$ = "UNDOBYTE.DA" + MID$(STR$(Var), 2)
    V2$ = Nul
    ' get valid path for file.
    CALL OpenDataFiles(V1$, V2$)
    ' check file open.
    CLOSE #6
    Disk.Ready = False
    ' attempt to open file.
    OPEN V1$ FOR RANDOM AS #6 LEN = LEN(UndoFile)
    ' exit loop if valid file.
    IF Disk.Ready = False THEN
       EXIT DO
    END IF
    ' increment process counter.
    Var = Var + 1
    ' check maximum processes open.
    IF Var > 9 THEN
       Var2 = True
       ErrorTrap = 90
       Exit Sub
    END IF
 LOOP

 ' store process number.
 Process.Number = Var

 ' make temp filename with process number.
 V1$ = "MARKERS1.DA" + MID$(STR$(Process.Number), 2)
 V2$ = Nul
 Var2 = False
 ' get valid path.
 CALL OpenDataFiles(V1$, V2$)
 CLOSE #7
 Disk.Ready = False
 ' attempt to open file.
 OPEN V1$ FOR RANDOM AS #7 LEN = LEN(MarkerFile)
 If Disk.Ready Then
    Var2 = True
 Endif
 EXIT SUB
Error.Routine1:
 Disk.Ready = True
 ErrorTrap = Err
 RESUME NEXT
END SUB

REM subroutine to initialize paste file.
SUB InitializePaste(Var2)
 ON LOCAL ERROR GOTO Error.Routine3
 ' make temp filename with process number.
 V1$ = "COPYFILE.DA" + MID$(STR$(Process.Number), 2)
 V2$ = Nul
 Var2 = False
 ' get valid path.
 CALL OpenDataFiles(V1$, V2$)
 CLOSE #4
 Disk.Ready = False
 ' check file exists.
 IF DIRx$(V1$)<>"" THEN
    KILL V1$ ' delete file.
 END IF
 IF Disk.Ready Then
    Var2 = True
 End if
 EXIT SUB
Error.Routine3:
 Disk.Ready = True
 ErrorTrap = Err
 RESUME NEXT
END SUB

REM subroutine to open paste files.
SUB OpenPasteFiles(Var2)
 ON LOCAL ERROR GOTO Error.Routine4
 ' make filename with process number.
 V1$ = "COPYFILE.DA" + MID$(STR$(Process.Number), 2)
 ' make filename with process number and file number.
 V2$ = "UNDOFIL" + MID$(STR$(Process.Number), 2) + ".DA" + MID$(STR$(CurrentFile), 2)
 ' get valid path.
 Var2 = False
 CALL OpenDataFiles(V1$, V2$)
 CLOSE #4, #5
 Disk.Ready = False
 ' attempt to open file.
 OPEN V1$ FOR RANDOM AS #4 LEN = 1
 IF Disk.Ready THEN
    Var2 = True
    EXIT SUB
 END IF
 Disk.Ready = False
 ' attempt to open file.
 OPEN V2$ FOR RANDOM AS #5 LEN = 1
 IF Disk.Ready THEN
    Var2 = True
 END IF
 EXIT SUB
Error.Routine4:
 Disk.Ready = True
 ErrorTrap = Err
 RESUME NEXT
END SUB

REM subroutine to init paste files for new file.
SUB InitPasteFiles(Var2)
 ON LOCAL ERROR GOTO Error.Routine5
 ' make filename with process number.
 V1$ = "COPYFILE.DA" + MID$(STR$(Process.Number), 2)
 ' make filename with process number and file number.
 V2$ = "UNDOFIL" + MID$(STR$(Process.Number), 2) + ".DA" + MID$(STR$(CurrentFile), 2)
 ' get valid path.
 Var2 = False
 CALL OpenDataFiles(V1$, V2$)
 CLOSE #4, #5
 Disk.Ready = False
 ' attempt to open file.
 OPEN V1$ FOR RANDOM AS #4 LEN = 1
 IF Disk.Ready THEN
    Var2 = True
    EXIT SUB
 END IF
 Disk.Ready = False
 IF DIRx$(V2$)<>"" THEN
    KILL V2$ ' remove temp file.
 END IF
 IF Disk.Ready THEN
    Var2 = True
    EXIT SUB
 END IF
 Disk.Ready = False
 ' attempt to open temp file.
 OPEN V2$ FOR RANDOM AS #5 LEN = 1
 IF Disk.Ready THEN
    Var2 = True
 END IF
 EXIT SUB
Error.Routine5:
 Disk.Ready = True
 ErrorTrap = Err
 RESUME NEXT
END SUB

REM Position calculation routines follow:

' displays cell position in string format type 1.
SUB FormatPosition1
 On Local Error Resume Next
 CALL CalculatePosition2
 IF CurrentWindow2 = False THEN
    PRINTf "(page:" + MID$(STR$(FilePage2 - 1), 2) + ","
 ELSE
    PRINTf "(page:" + RIGHT$("00000000" + HEX$(FilePage2 - 1), 8) + "H,"
 END IF
 PRINTf "row:" + MID$(STR$(PageRow2), 2) + ","
 PRINTf "column:" + MID$(STR$(PageColumn2), 2) + ")"
END SUB

' calculate current screen page number, row, and column, given file position.
SUB CalculatePosition1
 On Local Error Resume Next
 FilePage = INT((FilePosition - 1) / 320) + 1
 PageRow = INT((FilePosition - (FilePage - 1) * 320 - 1) / 20) + 1
 PageColumn = INT((FilePosition - (FilePage - 1) * 320) - (PageRow - 1) * 20)
END SUB

' calculate screen page number, row, and column, given variable.
SUB CalculatePosition2
 On Local Error Resume Next
 IF TempPosition3 = DFalse THEN
    FilePage2 = False
    PageRow2 = False
    PageColumn2 = False
 ELSE
    FilePage2 = INT((TempPosition3 - 1) / 320) + 1
    PageRow2 = INT((TempPosition3 - (FilePage2 - 1) * 320 - 1) / 20) + 1
    PageColumn2 = INT((TempPosition3 - (FilePage2 - 1) * 320) - (PageRow2 - 1) * 20)
 END IF
END SUB

REM Subroutine to get environment variable settings,
REM   and read custom config file variables.

SUB ReadConfigFile (Var$)
 ' declare error trap.
 ON LOCAL ERROR GOTO Error.Routine6

 ' check for ambiguation variable.
 IF ENVIRON$("AMBIGUATE") <> Nul THEN
    AmbiguateSwitch = True
 END IF

 ' check for screen row variable.
 IF ENVIRON$("HEXSCREEN") <> Nul THEN
    ScreenRow = True
 END IF

 ' check for heap sort variable.
 IF ENVIRON$("HEXSORT") <> Nul THEN
    HeapSortOff = True
 END IF

 ' check for file date/time variable.
 IF ENVIRON$("FILESWITCH") <> Nul THEN
    X = INT(VAL(ENVIRON$("FILESWITCH")))
    SELECT CASE X
    CASE 0, 1, 2
       FileSwitch = X
    END SELECT
 END IF

 ' check for file date/time variable.
 IF ENVIRON$("FILESIZE") <> Nul THEN
    X = INT(VAL(ENVIRON$("FILESIZE")))
    SELECT CASE X
    CASE 0, 1, 2
       FileSizeType = X
    END SELECT
 END IF

 ' check for quiet variable.
 IF ENVIRON$("QUIET") <> Nul THEN
    X = INT(VAL(ENVIRON$("QUIET")))
    SELECT CASE X
    CASE -1, 0, 1, 2, 3, 4, 5, 6
       QuietSwitch = X
    END SELECT
 END IF

 ' init alternate characters.
 IF ENVIRON$("HEXCHARS") <> Nul THEN
    Hline = 45
    Vline = 124
    ULcorner = 43
    URcorner = 43
    LLcorner = 43
    LRcorner = 43
 END IF

 ' define screen offsets for file menu box.
 ' allows menu repositioning.
 Xcoor = 5
 Ycoor = 20

 ' check config variable.
 IF ENVIRON$("LOADWIN") <> Nul THEN
    Load.Windows = True
 END IF

 ' check config variable.
 IF ENVIRON$("LOADDOS") <> Nul THEN
    Load.DOS = True
 END IF

 ' check config variable.
 IF ENVIRON$("HEXCONFIG") <> Nul THEN
    EXIT SUB
 END IF

REM Read Hexedit.cfg file,
REM   search current path, environment path, then path statement.

 ' search current path.
 File$ = CURDIR$
 IF RIGHT$(File$, 1) <> "\" THEN
    File$ = File$ + "\"
 END IF
 Config.Filename$ = File$ + ConfigFile
 IF DIRx$(Config.Filename$) <> Nul THEN
    GOSUB ReadFile2
    IF ValidFile THEN
       EXIT SUB
    END IF
 END IF

 ' search environment path.
 File$ = ENVIRON$("HEXEDIT")
 IF LEN(File$) THEN
    File$ = RTRIM$(File$)
    File$ = LTRIM$(File$)
    IF LEFT$(File$, 1) = Chr$(34) Then
       File$ = Mid$(File$, 2)
    END IF
    IF RIGHT$(File$, 1) = Chr$(34) Then
       File$ = Left$(File$, Len(File$) - 1)
    END IF
    IF RIGHT$(File$, 1) <> "\" THEN
       File$ = File$ + "\"
    END IF
    ASCIIZ = File$ + ConfigFile + Chr$(0)
    CALL GetShortFilename(Config.Filename$) ' v7.6a 06/01/2007
    IF LEN(Config.Filename$) THEN
       IF DIRx$(Config.Filename$) <> Nul THEN
          GOSUB ReadFile2
          IF ValidFile THEN
             EXIT SUB
          END IF
       END IF
    END IF
 END IF

 ' search path statement.
 Path$ = ENVIRON$("PATH")
 IF LEN(Path$) THEN
    DO
       ' parse path.
       Parse = INSTR(Path$, ";")
       IF Parse THEN
          File$ = LEFT$(Path$, Parse - 1)
          Path$ = MID$(Path$, Parse + 1)
       ELSE
          File$ = Path$
          Path$ = Nul
       END IF

       ' store filename.
       File$ = RTRIM$(File$)
       File$ = LTRIM$(File$)
       IF LEN(File$) THEN
          IF LEFT$(File$, 1) = Chr$(34) Then
             File$ = Mid$(File$, 2)
          END IF
          IF RIGHT$(File$, 1) = Chr$(34) Then
             File$ = Left$(File$, Len(File$) - 1)
          END IF
          IF RIGHT$(File$, 1) <> "\" THEN
             File$ = File$ + "\"
          END IF
          ASCIIZ = File$ + ConfigFile + Chr$(0)
          CALL GetShortFilename(Config.Filename$) ' v7.6a 06/01/2007
          IF LEN(Config.Filename$) THEN
             IF DIRx$(Config.Filename$) <> Nul THEN
                GOSUB ReadFile2
                IF ValidFile THEN
                   EXIT DO
                END IF
             END IF
          END IF
       END IF
       IF Path$ = NUl THEN
          EXIT DO
       END IF
    LOOP
 END IF
 EXIT SUB

' read in the data file
ReadFile2:
 ' open filename.
 ErrorTrap = False
 ValidFile = False
 CLOSE #1
 OPEN Config.Filename$ FOR INPUT SHARED AS #1
 IF ErrorTrap THEN
    RETURN
 END IF
 ValidFile = True

 ' read input lines.
 DO WHILE NOT EOF(1)
    LINE INPUT #1, FileLine$
    FileLine2$ = FileLine$

    ' remove spaces.
    Var1$ = FileLine$
    DO
       Parse = INSTR(Var1$, " ")
       IF Parse THEN
          Var1$ = LEFT$(Var1$, Parse - 1) + MID$(Var1$, Parse + 1)
       ELSE
          EXIT DO
       END IF
    LOOP
    FileLine$ = Var1$

    ' check for comment.
    IF LEFT$(FileLine$, 1) = ";" THEN
       FileLine$ = Nul
    END IF

    ' check assignment value.
    Parse = INSTR(FileLine$, "=")

    ' parse off left/right sides.
    IF Parse THEN

       ' get left/right side values.
       Char$ = LEFT$(FileLine$, Parse - 1)
       Setting$ = MID$(FileLine$, Parse + 1)

       ' get right side value for filenames
       ' enclosed in quotes containing spaces.
       Parse = INSTR(FileLine2$, "=")
       Setting2$ = MID$(FileLine2$, Parse + 1)
       Setting2$ = RTRIM$(Setting2$)
       Setting2$ = LTRIM$(Setting2$)

       ' check length of values.
       IF LEN(Char$) > 0 AND LEN(Setting$) > 0 THEN
          ' compare values.
          SELECT CASE UCASE$(Char$)
          ' check dump filename.
          CASE "DUMPFILE"
             DumpFile = Setting$
          ' check exclude filename.
          CASE "EXCLUDEFILE"
             ExcludeFile = Setting$
          ' check and concatenate loaded filenames.
          CASE "EDITFILE"
             IF Var$ = Nul THEN
                Var$ = Setting2$
             ELSE
                Var$ = Var$ + CHR$(13) + Setting2$
             END IF
          ' check windows detected override setting.
          CASE "LOADWINDOWS"
             SELECT CASE UCASE$(Setting$)
             CASE "OFF", "0", "FALSE"
                Load.Windows = False
             CASE "ON", "-1", "TRUE"
                Load.Windows = True
             END SELECT
          ' check DOS detected override setting.
          CASE "LOADDOS"
             SELECT CASE UCASE$(Setting$)
             CASE "OFF", "0", "FALSE"
                Load.DOS = False
             CASE "ON", "-1", "TRUE"
                Load.DOS = True
             END SELECT
          ' check environment replacement variables.
          CASE "HEXDISPLAY" ' 64-byte display.
             SELECT CASE UCASE$(Setting$)
             CASE "OFF", "0", "FALSE"
                FileDisplay = True
             CASE "ON", "-1", "TRUE"
                FileDisplay = False
             END SELECT
          CASE "HEXSCREEN" ' help key list.
             SELECT CASE UCASE$(Setting$)
             CASE "OFF", "0", "FALSE"
                ScreenRow = True
             CASE "ON", "-1", "TRUE"
                ScreenRow = False
             END SELECT
          CASE "HEXSORT" ' file\dir sort.
             SELECT CASE UCASE$(Setting$)
             CASE "OFF", "0", "FALSE"
                HeapSortOff = True
             CASE "ON", "-1", "TRUE"
                HeapSortOff = False
             END SELECT
          CASE "AMBIGUATE" ' file menu box ambiguation.
             SELECT CASE UCASE$(Setting$)
             CASE "OFF", "0", "FALSE"
                AmbiguateSwitch = False
             CASE "ON", "-1", "TRUE"
                AmbiguateSwitch = True
             END SELECT
          CASE "QUIET" ' file menu box display.
             SELECT CASE UCASE$(Setting$)
             CASE "OFF", "0", "FALSE"
                QuietSwitch = False
             CASE "ON", "-1", "TRUE"
                QuietSwitch = True
             CASE ELSE
                SELECT CASE INT(VAL(Setting$))
                CASE 1 TO 6
                   QuietSwitch = INT(VAL(Setting$))
                END SELECT
             END SELECT
          CASE "FILESWITCH" ' file menu box date\time display.
             SELECT CASE INT(VAL(Setting$))
             CASE 0, 1, 2
                FileSwitch = INT(VAL(Setting$))
             END SELECT
          CASE "FILESIZE" ' file menu box filesize display.
             SELECT CASE INT(VAL(Setting$))
             CASE 0, 1, 2
                FileSizeType = INT(VAL(Setting$))
             END SELECT
          CASE "MOUSEDRAGSCROLL" ' mouse drag scroll timer.
             MouseTime = CSNG(VAL(Setting$))
          CASE "XCOOR" ' file menu box location.
             NewValue = INT(VAL(Setting$))
             IF NewValue >= 2 THEN
                IF NewValue <= 8 THEN
                   Xcoor = NewValue
                END IF
             END IF
          CASE "YCOOR" ' file menu box location.
             NewValue = INT(VAL(Setting$))
             IF NewValue >= 1 THEN
                IF NewValue <= 39 THEN
                   Ycoor = NewValue
                END IF
             END IF
          ' custom color overrides.
          CASE "BLACK"
             NewValue = INT(VAL(Setting$))
             IF NewValue >= 0 THEN
                IF NewValue <= 15 THEN
                   Black = NewValue
                END IF
             END IF
          CASE "BLUE"
             NewValue = INT(VAL(Setting$))
             IF NewValue >= 0 THEN
                IF NewValue <= 15 THEN
                   Blue = NewValue
                END IF
             END IF
          CASE "CYAN"
             NewValue = INT(VAL(Setting$))
             IF NewValue >= 0 THEN
                IF NewValue <= 15 THEN
                   Cyan = NewValue
                END IF
             END IF
          CASE "GREEN"
             NewValue = INT(VAL(Setting$))
             IF NewValue >= 0 THEN
                IF NewValue <= 15 THEN
                   Green = NewValue
                END IF
             END IF
          CASE "MAGENTA"
             NewValue = INT(VAL(Setting$))
             IF NewValue >= 0 THEN
                IF NewValue <= 15 THEN
                   Magenta = NewValue
                END IF
             END IF
          CASE "PLAIN"
             NewValue = INT(VAL(Setting$))
             IF NewValue >= 0 THEN
                IF NewValue <= 15 THEN
                   Plain = NewValue
                END IF
             END IF
          CASE "RED"
             NewValue = INT(VAL(Setting$))
             IF NewValue >= 0 THEN
                IF NewValue <= 15 THEN
                   Red = NewValue
                END IF
             END IF
          CASE "WHITE"
             NewValue = INT(VAL(Setting$))
             IF NewValue >= 0 THEN
                IF NewValue <= 15 THEN
                   White = NewValue
                END IF
             END IF
          CASE "YELLOW"
             NewValue = INT(VAL(Setting$))
             IF NewValue >= 0 THEN
                IF NewValue <= 15 THEN
                   Yellow = NewValue
                END IF
             END IF
          CASE ELSE
             ' check ascii value.
             NewValue = INT(VAL(Setting$))
             IF NewValue >= False AND NewValue <= 255 THEN
                ' menu box ansi character overrides.
                SELECT CASE UCASE$(Char$)
                CASE "HLINE"
                   Hline = NewValue
                CASE "VLINE"
                   Vline = NewValue
                CASE "ULCORNER"
                   ULcorner = NewValue
                CASE "URCORNER"
                   URcorner = NewValue
                CASE "LLCORNER"
                   LLcorner = NewValue
                CASE "LRCORNER"
                   LRcorner = NewValue
                END SELECT
             END IF
          END SELECT
       END IF
    END IF
 LOOP
 RETURN

TopProgram:
 CLOSE #1
 EXIT SUB

' critical error trap.
Error.Routine6:
 ErrorTrap = ERR
 ' check screen.
 IF ScreenDrawn THEN
    CLS
 END IF
 ScreenDrawn = False
 ' display error message.
 COLORf White
 LOCATEf Csrlin, 1, 0
 PRINTf "Hex Editor ReadConfigFile " + Version + " " + Release + " critical error trap:"
 ' display error.
 COLORf Yellow
 LOCATEf Csrlin+1, 1, 0
 CALL DisplayCriticalError(ErrorTrap)
 ' display error prompt.
 COLORf Green
 LOCATEf Csrlin+1, 1, 0
 PRINTf "Press R(etry), C(ontinue), Q(uit):"
 LOCATEf Csrlin, 44, 1
 ' get keypress.
 DO
    ErrorRespond$ = Nul
    DO
       ErrorRespond$ = INKEY$
       IF LEN(ErrorRespond$) THEN
          EXIT DO
       END IF
    LOOP
    ' parse key.
    SELECT CASE LCASE$(ErrorRespond$)
    CASE "r"
       PRINTf "r"
       LOCATEf Csrlin+1, 1, 0
       RESUME
    CASE "c"
       PRINTf "c"
       LOCATEf Csrlin+1, 1, 0
       RESUME NEXT
    CASE "q"
       PRINTf "q"
       LOCATEf Csrlin+1, 1, 0
       RESUME TopProgram
    END SELECT
    R = ReleaseTime
 LOOP
END SUB

REM Drop down menu subroutine:

REM Returns: variable CurrentMenu equals 1 to 7, or 0 if exit,
REM  variable CurrentMenuSelection is menu selection in CurrentMenu.

SUB DropDownMenu
 ' declare error trap.
 ON LOCAL ERROR GOTO Error.Routine7
 GOSUB StoreArea
TopProgram1:
 GOSUB DrawMenu
 GOSUB DrawCurrentMenuSelection

 ' keyboard/mouse input loop.
 DO
    CharInput$ = Nul

    ' call mouse subroutine.
    CALL MouseDriver

    ' check left mouse button.
    IF Mouse.ButtonX THEN
       Mouse.Row = Mouse.RowX
       Mouse.Column = Mouse.ColumnX
       GOSUB MouseButton1X
    ELSE
       ' check right/middle mouse button.
       IF Mouse.Button2 OR Mouse.Button3 THEN
          GOSUB RestoreArea
          CurrentMenu = False
          EXIT SUB
       ELSE
          ' check mouse position.
          IF Mouse.Row OR Mouse.Column THEN
             GOSUB MoveMouse
          END IF
       END IF
    END IF

    ' store keyboard buffer.
    CharInput$ = INKEY$
    IF LEN(CharInput$) THEN
       CharInput$ = UCASE$(CharInput$)
       SELECT CASE LEN(CharInput$)
       CASE 1
          SELECT CASE ASC(CharInput$)
          CASE 65 TO 90 ' A - Z
             SELECT CASE CurrentMenu
             CASE 1
                VarZ = Instr("OCAVTE", CharInput$)
                IF VarZ THEN
                   GOSUB RestoreArea
                   CurrentMenuSelection = VarZ
                   EXIT SUB
                END IF
             CASE 2
                VarZ = Instr("AH", CharInput$)
                IF VarZ THEN
                   GOSUB RestoreArea
                   CurrentMenuSelection = VarZ
                   EXIT SUB
                END IF
             CASE 3
                VarZ = Instr("SF", CharInput$)
                IF VarZ THEN
                   GOSUB RestoreArea
                   CurrentMenuSelection = VarZ
                   EXIT SUB
                END IF
             CASE 4
                VarZ = Instr("ASRUB", CharInput$)
                IF VarZ THEN
                   GOSUB RestoreArea
                   CurrentMenuSelection = VarZ
                   EXIT SUB
                END IF
             CASE 5
                VarZ = Instr("BP", CharInput$)
                IF VarZ THEN
                   GOSUB RestoreArea
                   CurrentMenuSelection = VarZ
                   EXIT SUB
                END IF
             CASE 6
                VarZ = Instr("SF", CharInput$)
                IF VarZ THEN
                   GOSUB RestoreArea
                   CurrentMenuSelection = VarZ
                   EXIT SUB
                END IF
             CASE 7
                VarZ = Instr("SB", CharInput$)
                IF VarZ THEN
                   GOSUB RestoreArea
                   CurrentMenuSelection = VarZ
                   EXIT SUB
                END IF
             END SELECT
          CASE 13 ' Enter
             GOSUB RestoreArea
             EXIT SUB
          CASE 27 ' Escape
             GOSUB RestoreArea
             CurrentMenu = False
             EXIT SUB
          END SELECT
       CASE 2
          SELECT CASE ASC(RIGHT$(CharInput$, 1))
          CASE 72 ' Up
             GOSUB MenuUp
          CASE 80 ' Down
             GOSUB MenuDown
          CASE 75 ' Left
             GOSUB MenuLeft
          CASE 77 ' Right
             GOSUB MenuRight
          END SELECT
       END SELECT
    END IF
    ' release time slice,
    R = ReleaseTime
 LOOP
 EXIT SUB

' moves one menu left, wrapping.
MenuLeft:
 GOSUB RestoreArea
 IF CurrentMenu = 1 THEN
    CurrentMenu = 7
 ELSE
    CurrentMenu = CurrentMenu - 1
 END IF
 GOSUB StoreArea
 GOSUB DrawMenu
 GOSUB DrawCurrentMenuSelection
 RETURN

' moves one menu right, wrapping.
MenuRight:
 GOSUB RestoreArea
 IF CurrentMenu = 7 THEN
    CurrentMenu = 1
 ELSE
    CurrentMenu = CurrentMenu + 1
 END IF
 GOSUB StoreArea
 GOSUB DrawMenu
 GOSUB DrawCurrentMenuSelection
 RETURN

' moves menu up, wrapping.
' selects CurrentMenuSelection variable.
MenuUp:
 SELECT CASE CurrentMenu
 CASE 1
    GOSUB EraseCurrentMenuSelection
    IF CurrentMenuSelection = 1 THEN
       CurrentMenuSelection = 6
    ELSE
       CurrentMenuSelection = CurrentMenuSelection - 1
    END IF
    GOSUB DrawCurrentMenuSelection
 CASE 2
    GOSUB EraseCurrentMenuSelection
    IF CurrentMenuSelection = 1 THEN
       CurrentMenuSelection = 2
    ELSE
       CurrentMenuSelection = CurrentMenuSelection - 1
    END IF
    GOSUB DrawCurrentMenuSelection
 CASE 3
    GOSUB EraseCurrentMenuSelection
    IF CurrentMenuSelection = 1 THEN
       CurrentMenuSelection = 2
    ELSE
       CurrentMenuSelection = CurrentMenuSelection - 1
    END IF
    GOSUB DrawCurrentMenuSelection
 CASE 4
    GOSUB EraseCurrentMenuSelection
    IF CurrentMenuSelection = 1 THEN
       CurrentMenuSelection = 5
    ELSE
       CurrentMenuSelection = CurrentMenuSelection - 1
    END IF
    GOSUB DrawCurrentMenuSelection
 CASE 5
    GOSUB EraseCurrentMenuSelection
    IF CurrentMenuSelection = 1 THEN
       CurrentMenuSelection = 2
    ELSE
       CurrentMenuSelection = CurrentMenuSelection - 1
    END IF
    GOSUB DrawCurrentMenuSelection
 CASE 6
    GOSUB EraseCurrentMenuSelection
    IF CurrentMenuSelection = 1 THEN
       CurrentMenuSelection = 2
    ELSE
       CurrentMenuSelection = CurrentMenuSelection - 1
    END IF
    GOSUB DrawCurrentMenuSelection
 CASE 7
    GOSUB EraseCurrentMenuSelection
    IF CurrentMenuSelection = 1 THEN
       CurrentMenuSelection = 2
    ELSE
       CurrentMenuSelection = CurrentMenuSelection - 1
    END IF
    GOSUB DrawCurrentMenuSelection
 END SELECT
 RETURN

' moves menu down, wrapping.
' selects CurrentMenuSelection variable.
MenuDown:
 SELECT CASE CurrentMenu
 CASE 1
    GOSUB EraseCurrentMenuSelection
    IF CurrentMenuSelection = 6 THEN
       CurrentMenuSelection = 1
    ELSE
       CurrentMenuSelection = CurrentMenuSelection + 1
    END IF
    GOSUB DrawCurrentMenuSelection
 CASE 2
    GOSUB EraseCurrentMenuSelection
    IF CurrentMenuSelection = 2 THEN
       CurrentMenuSelection = 1
    ELSE
       CurrentMenuSelection = CurrentMenuSelection + 1
    END IF
    GOSUB DrawCurrentMenuSelection
 CASE 3
    GOSUB EraseCurrentMenuSelection
    IF CurrentMenuSelection = 2 THEN
       CurrentMenuSelection = 1
    ELSE
       CurrentMenuSelection = CurrentMenuSelection + 1
    END IF
    GOSUB DrawCurrentMenuSelection
 CASE 4
    GOSUB EraseCurrentMenuSelection
    IF CurrentMenuSelection = 5 THEN
       CurrentMenuSelection = 1
    ELSE
       CurrentMenuSelection = CurrentMenuSelection + 1
    END IF
    GOSUB DrawCurrentMenuSelection
 CASE 5
    GOSUB EraseCurrentMenuSelection
    IF CurrentMenuSelection = 2 THEN
       CurrentMenuSelection = 1
    ELSE
       CurrentMenuSelection = CurrentMenuSelection + 1
    END IF
    GOSUB DrawCurrentMenuSelection
 CASE 6
    GOSUB EraseCurrentMenuSelection
    IF CurrentMenuSelection = 2 THEN
       CurrentMenuSelection = 1
    ELSE
       CurrentMenuSelection = CurrentMenuSelection + 1
    END IF
    GOSUB DrawCurrentMenuSelection
 CASE 7
    GOSUB EraseCurrentMenuSelection
    IF CurrentMenuSelection = 2 THEN
       CurrentMenuSelection = 1
    ELSE
       CurrentMenuSelection = CurrentMenuSelection + 1
    END IF
    GOSUB DrawCurrentMenuSelection
 END SELECT
 RETURN

' removes hilight from current menu selection.
EraseCurrentMenuSelection:
 CALL HMouse
 COLORf2 White, 0
 SelectColor = 0
 GOSUB DisplayCurrentMenuSelection
 COLORf2 White, 0
 CALL SMouse
 RETURN

' adds hilight to current menu selection.
DrawCurrentMenuSelection:
 CALL HMouse
 COLORf2 White, 1
 SelectColor = 1
 GOSUB DisplayCurrentMenuSelection
 COLORf2 White, 0
 CALL SMouse
 RETURN

' draws current menu selection.
DisplayCurrentMenuSelection:
 SELECT CASE CurrentMenu
 CASE 1
    SELECT CASE CurrentMenuSelection
    CASE 1
       LOCATEf 3, 7, 0
       PRINTf "Open New File  "
       Colorf2 Magenta, SelectColor
       Locatef 3, 7, 0
       Printf "O"
    CASE 2
       LOCATEf 4, 7, 0
       PRINTf "Close File     "
       Colorf2 Magenta, SelectColor
       Locatef 4, 7, 0
       Printf "C"
    CASE 3
       LOCATEf 5, 7, 0
       PRINTf "Close All Files"
       Colorf2 Magenta, SelectColor
       Locatef 5, 13, 0
       Printf "A"
    CASE 4
       LOCATEf 6, 7, 0
       PRINTf "View Files     "
       Colorf2 Magenta, SelectColor
       Locatef 6, 7, 0
       Printf "V"
    CASE 5
       LOCATEf 7, 7, 0
       PRINTf "Toggle Window  "
       Colorf2 Magenta, SelectColor
       Locatef 7, 7, 0
       Printf "T"
    CASE 6
       LOCATEf 8, 7, 0
       PRINTf "Exit Program   "
       Colorf2 Magenta, SelectColor
       Locatef 8, 7, 0
       Printf "E"
    END SELECT
 CASE 2
    SELECT CASE CurrentMenuSelection
    CASE 1
       LOCATEf 3, 17, 0
       PRINTf "ANSI Chart"
       Colorf2 Magenta, SelectColor
       Locatef 3, 17, 0
       Printf "A"
    CASE 2
       LOCATEf 4, 17, 0
       PRINTf "HEX Chart "
       Colorf2 Magenta, SelectColor
       Locatef 4, 17, 0
       Printf "H"
    END SELECT
 CASE 3
    SELECT CASE CurrentMenuSelection
    CASE 1
       LOCATEf 3, 27, 0
       PRINTf "HEX Screen Dump"
       Colorf2 Magenta, SelectColor
       Locatef 3, 31, 0
       Printf "S"
    CASE 2
       LOCATEf 4, 27, 0
       PRINTf "HEX File Dump  "
       Colorf2 Magenta, SelectColor
       Locatef 4, 31, 0
       Printf "F"
    END SELECT
 CASE 4
    SELECT CASE CurrentMenuSelection
    CASE 1
       LOCATEf 3, 37, 0
       PRINTf "Append Bytes       "
       Colorf2 Magenta, SelectColor
       Locatef 3, 37, 0
       Printf "A"
    CASE 2
       LOCATEf 4, 37, 0
       PRINTf "Append ASCII String"
       Colorf2 Magenta, SelectColor
       Locatef 4, 50, 0
       Printf "S"
    CASE 3
       LOCATEf 5, 37, 0
       PRINTf "Redraw Screen      "
       Colorf2 Magenta, SelectColor
       Locatef 5, 37, 0
       Printf "R"
    CASE 4
       LOCATEf 6, 37, 0
       PRINTf "Undo Last Byte     "
       Colorf2 Magenta, SelectColor
       Locatef 6, 37, 0
       Printf "U"
    CASE 5
       LOCATEf 7, 37, 0
       PRINTf "Undo All Bytes     "
       Colorf2 Magenta, SelectColor
       Locatef 7, 46, 0
       Printf "B"
    END SELECT
 CASE 5
    SELECT CASE CurrentMenuSelection
    CASE 1
       LOCATEf 3, 47, 0
       PRINTf "Jump To Byte"
       Colorf2 Magenta, SelectColor
       Locatef 3, 55, 0
       Printf "B"
    CASE 2
       LOCATEf 4, 47, 0
       PRINTf "Jump To Page"
       Colorf2 Magenta, SelectColor
       Locatef 4, 55, 0
       Printf "P"
    END SELECT
 CASE 6
    SELECT CASE CurrentMenuSelection
    CASE 1
       LOCATEf 3, 57, 0
       PRINTf "HEX Screen Print"
       Colorf2 Magenta, SelectColor
       Locatef 3, 61, 0
       Printf "S"
    CASE 2
       LOCATEf 4, 57, 0
       PRINTf "HEX File Print  "
       Colorf2 Magenta, SelectColor
       Locatef 4, 61, 0
       Printf "F"
    END SELECT
 CASE 7
    SELECT CASE CurrentMenuSelection
    CASE 1
       LOCATEf 3, 65, 0
       PRINTf "Search String"
       Colorf2 Magenta, SelectColor
       Locatef 3, 72, 0
       Printf "S"
    CASE 2
       LOCATEf 4, 65, 0
       PRINTf "Search Bytes "
       Colorf2 Magenta, SelectColor
       Locatef 4, 72, 0
       Printf "B"
    END SELECT
 END SELECT
 RETURN

' draws menu.
DrawMenu:
 CurrentMenuSelection = 1
 GOSUB BoxBorder
 BoxDrawX1 = Xstore1
 BoxDrawX2 = Xstore2
 BoxDrawY1 = Ystore1
 BoxDrawY2 = Ystore2
 CALL HMouse
 SELECT CASE CurrentMenu
 CASE 1
    BoxDrawLength = 17
    GOSUB DrawBox
    COLORf White
    LOCATEf 3, 7, 0
    PRINTf "Open New File  "
    LOCATEf 4, 7, 0
    PRINTf "Close File     "
    LOCATEf 5, 7, 0
    PRINTf "Close All Files"
    LOCATEf 6, 7, 0
    PRINTf "View Files     "
    LOCATEf 7, 7, 0
    PRINTf "Toggle Window  "
    LOCATEf 8, 7, 0
    PRINTf "Exit Program   "
    Colorf Magenta
    Locatef 3, 7, 0
    Printf "O"
    Locatef 4, 7, 0
    Printf "C"
    Locatef 5, 13, 0
    Printf "A"
    Locatef 6, 7, 0
    Printf "V"
    Locatef 7, 7, 0
    Printf "T"
    Locatef 8, 7, 0
    Printf "E"
 CASE 2
    BoxDrawLength = 12
    GOSUB DrawBox
    COLORf White
    LOCATEf 3, 17, 0
    PRINTf "ANSI Chart"
    LOCATEf 4, 17, 0
    PRINTf "HEX Chart "
    Colorf Magenta
    Locatef 3, 17, 0
    Printf "A"
    Locatef 4, 17, 0
    Printf "H"
 CASE 3
    BoxDrawLength = 17
    GOSUB DrawBox
    COLORf White
    LOCATEf 3, 27, 0
    PRINTf "HEX Screen Dump"
    LOCATEf 4, 27, 0
    PRINTf "HEX File Dump  "
    Colorf Magenta
    Locatef 3, 31, 0
    Printf "S"
    Locatef 4, 31, 0
    Printf "F"
 CASE 4
    BoxDrawLength = 21
    GOSUB DrawBox
    COLORf White
    LOCATEf 3, 37, 0
    PRINTf "Append Bytes       "
    LOCATEf 4, 37, 0
    PRINTf "Append ASCII String"
    LOCATEf 5, 37, 0
    PRINTf "Redraw Screen      "
    LOCATEf 6, 37, 0
    PRINTf "Undo Last Byte     "
    LOCATEf 7, 37, 0
    PRINTf "Undo All Bytes     "
    Colorf Magenta
    Locatef 3, 37, 0
    Printf "A"
    Locatef 4, 50, 0
    Printf "S"
    Locatef 5, 37, 0
    Printf "R"
    Locatef 6, 37, 0
    Printf "U"
    Locatef 7, 46, 0
    Printf "B"
 CASE 5
    BoxDrawLength = 14
    GOSUB DrawBox
    COLORf White
    LOCATEf 3, 47, 0
    PRINTf "Jump To Byte"
    LOCATEf 4, 47, 0
    PRINTf "Jump To Page"
    Colorf Magenta
    Locatef 3, 55, 0
    Printf "B"
    Locatef 4, 55, 0
    Printf "P"
 CASE 6
    BoxDrawLength = 18
    GOSUB DrawBox
    COLORf White
    LOCATEf 3, 57, 0
    PRINTf "HEX Screen Print"
    LOCATEf 4, 57, 0
    PRINTf "HEX File Print  "
    Colorf Magenta
    Locatef 3, 61, 0
    Printf "S"
    Locatef 4, 61, 0
    Printf "F"
 CASE 7
    BoxDrawLength = 15
    GOSUB DrawBox
    COLORf White
    LOCATEf 3, 65, 0
    PRINTf "Search String"
    LOCATEf 4, 65, 0
    PRINTf "Search Bytes "
    Colorf Magenta
    Locatef 3, 72, 0
    Printf "S"
    Locatef 4, 72, 0
    Printf "B"
 END SELECT
 CALL SMouse
 RETURN

' stores area under menu.
StoreArea:
 IF CurrentMenu = False THEN
    RETURN
 END IF
 CALL HMouse
 GOSUB BoxBorder
 RowX1 = 0
 ColumnY1 = 0
 FOR RowX2 = Xstore1 TO Xstore2
    RowX1 = RowX1 + 1
    ColumnY1 = 0
    FOR ColumnY2 = Ystore1 TO Ystore2
       ColumnY1 = ColumnY1 + 1
       ' store ascii character.
       Area1(RowX1, ColumnY1) = SCREEN(RowX2, ColumnY2)
       ' store color. (undocumented: also stores background color).
       Area2(RowX1, ColumnY1) = SCREEN(RowX2, ColumnY2, 1)
    NEXT
 NEXT
 ' hilight menu tab.
 COLORf2 White, 1
 CALL DisplayTab(CurrentMenu)
 CALL SMouse
 RETURN

' restores area under menu.
RestoreArea:
 IF CurrentMenu = False THEN
    RETURN
 END IF
 CALL HMouse
 GOSUB BoxBorder
 RowX1 = 0
 ColumnY1 = 0
 FOR RowX2 = Xstore1 TO Xstore2
    RowX1 = RowX1 + 1
    ColumnY1 = 0
    FOR ColumnY2 = Ystore1 TO Ystore2
       ColumnY1 = ColumnY1 + 1
       LOCATEf RowX2, ColumnY2, 1
       ' restore color.
       TempZ = Area2(RowX1, ColumnY1)
       ' undocumented: also stores background color.
       VarB = INT(TempZ / 16)
       VarF = TempZ MOD 16
       COLORf2 VarF, VarB
       ' restore ascii character.
       PRINTf CHR$(Area1(RowX1, ColumnY1))
    NEXT
 NEXT
 ' remove hilight menu tab.
 COLORf2 White, 0
 CALL DisplayTab(CurrentMenu)
 CALL SMouse
 RETURN

' returns borders of box.
BoxBorder:
 SELECT CASE CurrentMenu
 CASE 1
    Xstore1 = 2
    Xstore2 = 9
    Ystore1 = 6
    Ystore2 = 22
 CASE 2
    Xstore1 = 2
    Xstore2 = 5
    Ystore1 = 16
    Ystore2 = 27
 CASE 3
    Xstore1 = 2
    Xstore2 = 5
    Ystore1 = 26
    Ystore2 = 42
 CASE 4
    Xstore1 = 2
    Xstore2 = 8
    Ystore1 = 36
    Ystore2 = 56
 CASE 5
    Xstore1 = 2
    Xstore2 = 5
    Ystore1 = 46
    Ystore2 = 59
 CASE 6
    Xstore1 = 2
    Xstore2 = 5
    Ystore1 = 56
    Ystore2 = 73
 CASE 7
    Xstore1 = 2
    Xstore2 = 5
    Ystore1 = 64
    Ystore2 = 78
 END SELECT
 RETURN

' draws box from (BoxDrawX1,BoxDrawY1) To (BoxDrawX2,BoxDrawY2),
'  length of box from left to right being BoxDrawLength.
DrawBox:
 COLORf Yellow
 LOCATEf BoxDrawX1, BoxDrawY1, 0
 PRINTf CHR$(ULcorner) + STRING$(BoxDrawLength - 2, Hline) + CHR$(URcorner)
 FOR RowX1 = BoxDrawX1 + 1 TO BoxDrawX2 - 1
    LOCATEf RowX1, BoxDrawY1, 0
    PRINTf CHR$(Vline)
    LOCATEf RowX1, BoxDRawY2, 0
    PRINTf CHR$(Vline)
 NEXT
 LOCATEf BoxDrawX2, BoxDrawY1, 0
 PRINTf CHR$(LLcorner) + STRING$(BoxDrawLength - 2, Hline) + CHR$(LRcorner)
 RETURN

' process mouse move.
MoveMouse:
 ' select drop down menu.
 IF Mouse.Row = 1 THEN
    NewMenuSelection = False
    SELECT CASE Mouse.Column
    CASE 6 TO 9 ' File
       NewMenuSelection = 1
    CASE 16 TO 21 ' Charts
       NewMenuSelection = 2
    CASE 26 TO 29 ' Dump
       NewMenuSelection = 3
    CASE 36 TO 39 ' Edit
       NewMenuSelection = 4
    CASE 46 TO 49 ' Jump
       NewMenuSelection = 5
    CASE 56 TO 60 ' Print
       NewMenuSelection = 6
    CASE 64 TO 69 ' Search
       NewMenuSelection = 7
    END SELECT
    IF NewMenuSelection > False THEN
       IF NewMenuSelection <> CurrentMenu THEN
          IF CurrentMenu > False THEN
             GOSUB RestoreArea
          END IF
          CurrentMenu = NewMenuSelection
          CurrentMenuSelection = 1
          GOSUB StoreArea
          GOSUB DrawMenu
          GOSUB DrawCurrentMenuSelection
       END IF
    END IF
    IF CurrentMenu > False THEN
       CALL HMouse
       COLORf2 White, 1
       CALL DisplayTab(CurrentMenu)
       CALL SMouse
    END IF
    RETURN
 END IF
 ' check mouse selection boundaries.
 SELECT CASE CurrentMenu
 CASE 1
    IF Mouse.Row >=3 AND Mouse.Row <= 8 THEN
       IF Mouse.Column >= 7 AND Mouse.Column <= 21 THEN
          IF Mouse.Row - 2 <> CurrentMenuSelection THEN
             GOSUB EraseCurrentMenuSelection
             CurrentMenuSelection = Mouse.Row - 2
          END IF
          GOSUB DrawCurrentMenuSelection
       END IF
    END IF
 CASE 2
    IF Mouse.Row >=3 AND Mouse.Row <= 4 THEN
       IF Mouse.Column >= 17 AND Mouse.Column <= 26 THEN
          IF Mouse.Row - 2 <> CurrentMenuSelection THEN
             GOSUB EraseCurrentMenuSelection
             CurrentMenuSelection = Mouse.Row - 2
          END IF
          GOSUB DrawCurrentMenuSelection
       END IF
    END IF
 CASE 3
    IF Mouse.Row >=3 AND Mouse.Row <= 4 THEN
       IF Mouse.Column >= 27 AND Mouse.Column <= 41 THEN
          IF Mouse.Row - 2 <> CurrentMenuSelection THEN
             GOSUB EraseCurrentMenuSelection
             CurrentMenuSelection = Mouse.Row - 2
          END IF
          GOSUB DrawCurrentMenuSelection
       END IF
    END IF
 CASE 4
    IF Mouse.Row >=3 AND Mouse.Row <= 7 THEN
       IF Mouse.Column >= 37 AND Mouse.Column <= 55 THEN
          IF Mouse.Row - 2 <> CurrentMenuSelection THEN
             GOSUB EraseCurrentMenuSelection
             CurrentMenuSelection = Mouse.Row - 2
          END IF
          GOSUB DrawCurrentMenuSelection
       END IF
    END IF
 CASE 5
    IF Mouse.Row >=3 AND Mouse.Row <= 5 THEN
       IF Mouse.Column >= 47 AND Mouse.Column <= 58 THEN
          IF Mouse.Row - 2 <> CurrentMenuSelection THEN
             GOSUB EraseCurrentMenuSelection
             CurrentMenuSelection = Mouse.Row - 2
          END IF
          GOSUB DrawCurrentMenuSelection
       END IF
    END IF
 CASE 6
    IF Mouse.Row >=3 AND Mouse.Row <= 5 THEN
       IF Mouse.Column >= 57 AND Mouse.Column <= 72 THEN
          IF Mouse.Row - 2 <> CurrentMenuSelection THEN
             GOSUB EraseCurrentMenuSelection
             CurrentMenuSelection = Mouse.Row - 2
          END IF
          GOSUB DrawCurrentMenuSelection
       END IF
    END IF
 CASE 7
    IF Mouse.Row >=3 AND Mouse.Row <= 5 THEN
       IF Mouse.Column >= 65 AND Mouse.Column <= 77 THEN
          IF Mouse.Row - 2 <> CurrentMenuSelection THEN
             GOSUB EraseCurrentMenuSelection
             CurrentMenuSelection = Mouse.Row - 2
          END IF
          GOSUB DrawCurrentMenuSelection
       END IF
    END IF
 END SELECT
 RETURN

' process left mouse button.
MouseButton1X:
 ExitMouse = False
 IF Mouse.Row - 2 = CurrentMenuSelection THEN
    SELECT CASE CurrentMenu
    CASE 1
       IF Mouse.Column >= 7 AND Mouse.Column <= 21 THEN
          ExitMouse = True
       END IF
    CASE 2
       IF Mouse.Column >= 17 AND Mouse.Column <= 26 THEN
          ExitMouse = True
       END IF
    CASE 3
       IF Mouse.Column >= 27 AND Mouse.Column <= 41 THEN
          ExitMouse = True
       END IF
    CASE 4
       IF Mouse.Column >= 37 AND Mouse.Column <= 55 THEN
          ExitMouse = True
       END IF
    CASE 5
       IF Mouse.Column >= 47 AND Mouse.Column <= 58 THEN
          ExitMouse = True
       END IF
    CASE 6
       IF Mouse.Column >= 57 AND Mouse.Column <= 72 THEN
          ExitMouse = True
       END IF
    CASE 7
       IF Mouse.Column >= 65 AND Mouse.Column <= 77 THEN
          ExitMouse = True
       END IF
    END SELECT
    ' exit subroutine with menu selection.
    IF ExitMouse THEN
       GOSUB RestoreArea
       EXIT SUB
    END IF
 END IF
 RETURN

TopProgram2:
 EXIT SUB

' critical error trap.
Error.Routine7:
 ErrorTrap = ERR
 CurrentMenu = False
 ' check screen.
 IF ScreenDrawn THEN
    CLS
 END IF
 ScreenDrawn = False
 ' display error message.
 COLORf White
 LOCATEf Csrlin, 1, 0
 PRINTf "Hex Editor DropDownMenu " + Version + " " + Release + " critical error trap:"
 ' display error.
 COLORf Yellow
 LOCATEf Csrlin+1, 1, 0
 CALL DisplayCriticalError(ErrorTrap)
 ' display error prompt.
 COLORf Green
 LOCATEf Csrlin+1, 1, 0
 PRINTf "Press R(etry), C(ontinue), Q(uit):"
 LOCATEf Csrlin, 35, 1
 ' get keypress.
 DO
    ErrorRespond$ = Nul
    DO
       ErrorRespond$ = INKEY$
       IF LEN(ErrorRespond$) THEN
          EXIT DO
       END IF
    LOOP
    ' parse key.
    SELECT CASE LCASE$(ErrorRespond$)
    CASE "r"
       PRINTf "r"
       LOCATEf Csrlin+1, 1, 0
       RESUME TopProgram1
    CASE "c"
       PRINTf "c"
       LOCATEf Csrlin+1, 1, 0
       RESUME TopProgram1
    CASE "q"
       PRINTf "q"
       LOCATEf Csrlin+1, 1, 0
       RESUME TopProgram2
    END SELECT
    R = ReleaseTime
 LOOP
END SUB

' inits mouse.
SUB ClearMouse
 On Local Error Resume Next
 ' clear mouse buttons.
 CALL MouseFunction(Button, 0)
 CALL MouseFunction(Button, 1)

 ' store mouse position.
 CALL MouseFunction2(1,1)
 CALL MouseFunction(Position, 0)

 ' reset mouse position.
 Mouse.X = OutregsX.DX / 8 + 1
 Mouse.Y = OutregsX.CX / 8 + 1
END SUB

' Deconcatenates a filename to a specified length
'  with imbedded \..\ character strings.
'
' Input:
'   Y$ - Netpath (full path)
'   Z$ - DosPath (ambiguated)
'   Z% - Length (32-64)
'
' Returns:
'   Z$ - Concatenated path
'     C:\path\..\path\
'   or,
'     For remote or default server:
'       \\server name\share name\path\..\path\
'

SUB Deconcatenate(Y$,Z$,Z%)
 ON LOCAL ERROR GOTO Error.Routine12
 Y$ = UCASE$(Y$)
 Z$ = UCASE$(Z$)
 ' check netpath.
 IF LEN(Y$) THEN
    ' store net path.
    Y1$ = UCASE$(Y$)
    IF RIGHT$(Y1$, 1) <> "\" THEN
       Y1$ = Y1$ + "\"
    END IF

    ' check default net path.
    IF RTRIM$(DefaultNetPath) <> Nul THEN

       ' store default netpath.
       Z1$ = "\\" + UCASE$(RTRIM$(DefaultNetPath)) + "\"

       ' check netpath is in default path.
       IF LEFT$(Y1$, LEN(Z1$)) = Z1$ THEN

          ' ambiguate netpath.
          ASCIIZ3 = ASCIIZ
          ASCIIZ = Y1$ + CHR$(0)
          CALL GetShortFilename(Short.Filename$)
          ASCIIZ = ASCIIZ3

          ' store ambiguated netpath.
          N1$ = Short.Filename$
       END IF
    END IF
    IF N1$ = Nul THEN
       N1$ = Y1$
    END IF
    N1$ = UCASE$(N1$)

    ' truncate drive letter.
    IF MID$(N1$, 2, 1) = ":" THEN
       N1$ = MID$(N1$, 3)
    END IF

    ' truncate netpath from dospath.
    IF LEFT$(Z$, LEN(N1$)) = N1$ THEN
       Z$ = MID$(Z$, LEN(N1$) + 1)
    END IF

    ' get ending position of server name.
    Y2 = INSTR(3, Y1$, "\")

    ' get ending position of share name.
    Y3 = INSTR(Y2 + 1, Y1$, "\")

    ' get server\share name.
    Y1$ = LEFT$(Y1$, Y3)
 END IF

 ' check path
 IF INSTR(Z$, "\") = False THEN
    IF LEN(Y$) THEN
       Z$ = Y1$ + Z$
    END IF
    IF LEN(Z$) > Z% THEN
       Z$ = LEFT$(Z$, Z% - 3) + "..."
    END IF
    EXIT SUB
 END IF

 ' decrement length of netpath
 Z1% = Z%
 IF LEN(Y1$) THEN
    Z1% = Z1% - LEN(Y1$)
    IF Z1% <= 0 THEN
       Z$ = LEFT$(Y1$, Z% - 3) + "..."
       EXIT SUB
    END IF
    Z1% = Z1% + 1
 END IF

 ' deconcatenate path
 IF Y$ <> Nul THEN
    IF LEFT$(Z$, 1) <> "\" THEN
       Z$ = "\" + Z$
    END IF
 END IF
 DO
    IF LEN(Z$) > Z1% THEN
       V1 = INSTR(Z$, "\")
       IF V1 > 0 THEN
          DO
             IF MID$(Z$, V1, 4) = "\..\" THEN
                V1 = INSTR(V1 + 1, Z$, "\")
             ELSE
                EXIT DO
             END IF
          LOOP
          V2 = INSTR(V1 + 1, Z$, "\")
          IF V2 > 0 THEN
             Z$ = LEFT$(Z$, V1) + ".." + MID$(Z$, V2)
          ELSE
             EXIT DO
          END IF
       END IF
    ELSE
       EXIT DO
    END IF
    ' remove redundant paths
    DO
       V = INSTR(Z$, "\..\..\")
       IF V > 0 THEN
          Z$ = LEFT$(Z$, V - 1) + "\..\" + MID$(Z$, V + 7)
       ELSE
          EXIT DO
       END IF
    LOOP
 LOOP

 ' remove redundant paths
 DO
    V = INSTR(Z$, "\..\..\")
    IF V > 0 THEN
       Z$ = LEFT$(Z$, V - 1) + "\..\" + MID$(Z$, V + 7)
    ELSE
       EXIT DO
    END IF
 LOOP

 ' prepend net path
 IF LEN(Y1$) THEN
    IF Z$ = "\" THEN
       Z$ = Y1$
    ELSE
       IF LEFT$(Z$, 2) = "\\" THEN
          N1$ = Z$
       ELSE
          IF LEFT$(Z$, 1) = "\" THEN
             Z$ = Y1$ + MID$(Z$, 2)
          ELSE
             Z$ = Y1$ + Z$
          END IF
       END IF
    END IF
 END IF

 ' truncate to length
 IF LEN(Z$) > Z% THEN
    Z$ = LEFT$(Z$, Z% - 3) + "..."
 END IF
Error.Resume12:
 EXIT SUB
Error.Routine12:
 RESUME Error.Resume12
END SUB

' initialize files.
'   tests temp environment directories,
'   temp directory, root, then default.
SUB OpenDataFiles(V1$, V2$)
 ON LOCAL ERROR GOTO Error.Routine8
 V$ = ENVIRON$("TMP")
 IF V$ = Nul THEN
    V$ = ENVIRON$("TEMP")
 END IF
 IF LEN(V$) THEN
    IF LEFT$(V$, 1) = CHR$(34) THEN
       V$ = MID$(V$, 2)
    END IF
    IF RIGHT$(V$, 1) = CHR$(34) THEN
       V$ = LEFT$(V$, LEN(V$) - 1)
    END IF
    IF RIGHT$(V$, 1) = "\" THEN
       F1$ = V$ + V1$
    ELSE
       F1$ = V$ + "\" + V1$
    END IF
    F2$ = Nul
    IF LEN(V2$) THEN
       IF RIGHT$(V$, 1) = "\" THEN
          F2$ = V$ + V2$
       ELSE
          F2$ = V$ + "\" + V2$
       END IF
    END IF
    IF TestFile(F1$) THEN
       IF F2$ = Nul THEN
          GOTO OpenDataFilename
       END IF
       IF TestFile(F2$) THEN
          GOTO OpenDataFilename
       END IF
    END IF
 END IF
 F1$ = "C:\TEMP\" + V1$
 IF LEN(V2$) THEN
    F2$ = "C:\TEMP\" + V2$
 END IF
 IF TestFile(F1$) THEN
    IF F2$ = Nul THEN
       GOTO OpenDataFilename
    END IF
    IF TestFile(F2$) THEN
       GOTO OpenDataFilename
    END IF
 END IF
 F1$ = "C:\" + V1$
 IF LEN(V2$) THEN
    F2$ = "C:\" + V2$
 END IF
 IF TestFile(F1$) THEN
    IF F2$ = Nul THEN
       GOTO OpenDataFilename
    END IF
    IF TestFile(F2$) THEN
       GOTO OpenDataFilename
    END IF
 END IF
 F1$ = V1$
 IF LEN(V2$) THEN
    F2$ = V2$
 END IF
 IF TestFile(F1$) THEN
    IF F2$ = Nul THEN
       GOTO OpenDataFilename
    END IF
    IF TestFile(F2$) THEN
       GOTO OpenDataFilename
    END IF
 END IF
 ERROR 76
 END

' returns filenames.
OpenDataFilename:
 V1$ = F1$
 V2$ = F2$
 EXIT SUB

' error routine
Error.Routine8:
 ErrorTrap = ERR
 CLS
 COLORf White
 LOCATEf Csrlin, 1, 0
 PRINTf "Hex Editor " + Version + " " + Release + " fileopen critical error trap:"
 COLORf Yellow
 LOCATEf Csrlin+1, 1, 0
 CALL DisplayCriticalError(ErrorTrap)
 ' display error prompt.
 COLORf Green
 LOCATEf Csrlin+1, 1, 0
 PRINTf "Check TEMP variables, .CFG file, or DOS file handles, then restart."
 COLORf Plain
 CALL ResetTrap
 END
END SUB

' initialize directory/filename record.
SUB OpenDataFiles1
 ON LOCAL ERROR GOTO Error.Routine9
 V1$ = "HEXEDIT1.DA" + MID$(STR$(Process.Number), 2)
 V2$ = "HEXEDIT2.DA" + MID$(STR$(Process.Number), 2)
 CALL OpenDataFiles(V1$, V2$)
 CLOSE #2, #3
 IF Windows.Detected THEN
    ' open filename random record structure for windows.
    OPEN V1$ FOR RANDOM AS #2 LEN = LEN(WinFileStruc)
    ' open directory random record structure for windows.
    OPEN V2$ FOR RANDOM AS #3 LEN = LEN(WinFileStruc)
 ELSE
    ' open filename random record structure for windows.
    OPEN V1$ FOR RANDOM AS #2 LEN = LEN(DosFileStruc)
    ' open directory random record structure for windows.
    OPEN V2$ FOR RANDOM AS #3 LEN = LEN(DosFileStruc)
 END IF
 EXIT SUB

' error routine
Error.Routine9:
 ErrorTrap = ERR
 CLS
 COLORf White
 LOCATEf Csrlin, 1, 0
 PRINTf "Hex Editor " + Version + " " + Release + " fileopen critical error trap:"
 COLORf Yellow
 LOCATEf Csrlin+1, 1, 0
 CALL DisplayCriticalError(ErrorTrap)
 ' display error prompt.
 COLORf Green
 LOCATEf Csrlin+1, 1, 0
 PRINTf "Check TEMP variables, .CFG file, or DOS file handles, then restart."
 COLORf Plain
 CALL ResetTrap
 END
END SUB

' redraws menu tab.
SUB DisplayTab(Var)
 On Local Error Resume Next
 SELECT CASE Var
 CASE 1 ' File
    LOCATEf 1, 6, 0
    PRINTf "File"
 CASE 2 ' Charts
    LOCATEf 1, 16, 0
    PRINTf "Charts"
 CASE 3 ' Dump
    LOCATEf 1, 26, 0
    PRINTf "Dump"
 CASE 4 ' Edit
    LOCATEf 1, 36, 0
    PRINTf "Edit"
 CASE 5 ' Jump
    LOCATEf 1, 46, 0
    PRINTf "Jump"
 CASE 6 ' Print
    LOCATEf 1, 56, 0
    PRINTf "Print"
 CASE 7 ' Search
    LOCATEf 1, 64, 0
    PRINTf "Search"
 END SELECT
 COLORf2 White, 0
END SUB

' display error trap message.
SUB DisplayCriticalError(Var)
 On Local Error Resume Next
 SELECT CASE Var
 CASE 5
    PRINTf "Syntax error." ' should not happen.
 CASE 6
    PRINTf "Overflow."
 CASE 9
    PRINTf "Subscript out of range."
 CASE 14
    PRINTf "Out of string space."
 CASE 24
    PRINTf "Device timeout."
 CASE 25
    PRINTf "Device fault."
 CASE 27
    PRINTf "Out of paper."
 CASE 52
    PRINTf "Bad file name or number."
 CASE 53
    PRINTf "File not found."
 CASE 54
    PRINTf "Bad file mode."
 CASE 55
    PRINTf "File already open."
 CASE 57
    PRINTf "Device I/O error."
 CASE 58
    PRINTf "File already exists."
 CASE 59
    PRINTf "Bad record length."
 CASE 61
    PRINTf "Disk full."
 CASE 62
    PRINTf "Input past eof."
 CASE 63
    PRINTf "Bad record length."
 CASE 64
    PRINTf "Bad file name."
 CASE 67
    PRINTf "Not enough file handles."
 CASE 68
    PRINTf "Device unavailable."
 CASE 70
    PRINTf "Permission denied."
 CASE 71
    PRINTf "Disk not ready."
 CASE 72
    PRINTf "Disk-media error."
 CASE 75
    PRINTf "Path/File access error."
 CASE 76
    PRINTf "Pathname not found."
 CASE 81
    PRINTf "Invalid name."
 CASE 90
    PRINTf "Too many processes."
 CASE ELSE
    PRINTf "Untrapped error" + STR$(Var) + "."
 END SELECT
 END SUB

' construct file exclusion list.
SUB ExcludeList(V1,Y$)
 On Local Error Resume Next
 IF V1 = 1 THEN
    LOCATEf Xcoor + 1, Ycoor + 2, 1
    PRINTf SPACE$(38)
    LOCATEf Xcoor + 1, Ycoor + 2, 1
    COLORf2 White, 0
    PRINTf "Enter file spec: "
    Y$ = lineinput$(Xcoor + 1, Ycoor + 19, 21)
 ELSE
    LOCATEf Xcoor + 1, Ycoor + 2, 1
    PRINTf SPACE$(38)
    LOCATEf Xcoor + 1, Ycoor + 2, 1
    COLORf2 White, 0
    PRINTf "Enter dir spec: "
    Y$ = lineinput$(Xcoor + 1, Ycoor + 18, 22)
 END IF
 IF LEN(Y$) THEN
    IF LEFT$(Y$, 1) = "@" THEN
       Filename2$ = UCASE$(MID$(Y$, 2))
       Y$ = Nul
       IF LEN(Filename2$) THEN
          Check.Disk = True
          Disk.Ready = False
          ErrorTrap = False
          CLOSE #1
          ASCIIZ3 = ASCIIZ
          ASCIIZ = Filename2$ + CHR$(0)
          CALL GetShortFilename(Short.Filename$)
          ASCIIZ = ASCIIZ3
          Filename2$ = Short.Filename$
          IF DIRx$(Filename2$) = Nul THEN
             LOCATEf Xcoor + 1, Ycoor + 2, 1
             PRINTf SPACE$(38)
             LOCATEf Xcoor + 1, Ycoor + 2, 1
             COLORf2 White, 0
             PRINTf "Filelist not found. Press <esc>:"
             WHILE INKEY$<>CHR$(27)
               R = ReleaseTime
             WEND
             RETURN
          END IF
          OPEN Filename2$ FOR INPUT AS #1
          Check.Disk = False
          IF Disk.Ready OR ErrorTrap THEN
             LOCATEf Xcoor + 1, Ycoor + 2, 1
             PRINTf SPACE$(38)
             LOCATEf Xcoor + 1, Ycoor + 2, 1
             COLORf2 White, 0
             PRINTf "Filelist not found. Press <esc>:"
             WHILE INKEY$<>CHR$(27)
                R = ReleaseTime
             WEND
             RETURN
          END IF
          DO UNTIL EOF(1)
             LINE INPUT #1, Y1$
             Y1$ = LTRIM$(Y1$)
             Y1$ = RTRIM$(Y1$)
             Y1$ = UCASE$(Y1$)
             IF LEN(Y1$) THEN
                IF LEFT$(Y1$, 1) = Quote THEN
                   Y1$ = MID$(Y1$, 2)
                   IF RIGHT$(Y1$, 1) = Quote THEN
                      Y1$ = LEFT$(Y1$, LEN(Y1$) - 1)
                   END IF
                END IF
                IF LEN(Y1$) THEN
                   IF INSTR(Y1$, " ") = False THEN
                      ' add excluded filename.
                      Y$ = Y$ + Y1$ + " "
                      IF LEN(Y$) > 4096 THEN
                         Y$ = Nul
                         EXIT DO
                      END IF
                   END IF
                END IF
             END IF
          LOOP
          LOCATEf Xcoor + 1, Ycoor + 2, 1
          PRINTf SPACE$(38)
          LOCATEf Xcoor + 1, Ycoor + 2, 1
          COLORf2 White, 0
          IF LEN(Y$) THEN
             PRINTf "Filelist loaded. Press <esc>:"
          ELSE
             PRINTf "Filelist not loaded. Press <esc>:"
          END IF
          WHILE INKEY$<>CHR$(27)
             R = ReleaseTime
          WEND
       END IF
    END IF
 END IF
 Y$ = LTRIM$(Y$)
 Y$ = RTRIM$(Y$)
END SUB

' display screen border.
SUB DisplayScreen2
 On Local Error Resume Next
 CLS
 COLORf Magenta
 PRINTf CHR$(ULcorner) + STRING$(76, Hline) + CHR$(URcorner)
 FOR Var2 = 2 TO 23
    LOCATEf Var2, 1, 0
    PRINTf CHR$(Vline)
    LOCATEf Var2, 78, 0
    PRINTf CHR$(Vline)
 NEXT
 LOCATEf 24, 1, 0
 PRINTf CHR$(LLcorner) + STRING$(76, Hline) + CHR$(LRcorner)
 COLORf Plain
END SUB

' display boot usage.
SUB DisplayBootUsage
 On Local Error Resume Next
 CLS
 COLORf White
 LOCATEf 1, 1, 0
 PRINTf "Hex Editor " + Version + " " + Release + "."
 COLORf Green
 LOCATEf 2, 1, 0
 PRINTf "Command Usage:"
 COLORf Yellow
 LOCATEf 3, 1, 0
 PRINTf "   Hexedit [@]<filename.ext>, [@]<filename.ext>, ..."
 COLORf Green
 LOCATEf 4, 1, 0
 PRINTf "Where:"
 COLORf Yellow
 LOCATEf 5, 1, 0
 PRINTf "   <filename.ext> is the file to edit.  May include drive/pathname, and"
 LOCATEf 6, 1, 0
 PRINTf "   supports long filenames in quotes. Filename may be omitted. Multiple"
 LOCATEf 7, 1, 0
 PRINTf "   files allowed with * and ? characters. Maximum of 9 files available."
 LOCATEf 8, 1, 0
 PRINTf "   Filename prepended with @ loads filelist from contents of text file."
 LOCATEf 9, 1, 0
 PRINTf "   May also contain server and share name if prepended as \\serv1\share\"
 COLORf Green
 LOCATEf 10, 1, 0
 PRINTf "Example:"
 COLORf Yellow
 LOCATEf 11, 1, 0
 PRINTf "   Hexedit " + CHR$(34) + "\dos\page.com" + CHR$(34)
 LOCATEf 12, 1, 0
 PRINTf "   Or use the file menu box by starting Hexedit without a filename."
 COLORf Green
 LOCATEf 13, 1, 0
 PRINTf "File Menu Box Usage:"
 COLORf Yellow
 LOCATEf 14, 1, 0
 PRINTf "   Navigate using cursors, selecting with <enter>, and switch windows"
 LOCATEf 15, 1, 0
 PRINTf "   with <tab> and Shift-<tab>. Exits to editor or DOS with <escape>."
 COLORf Green
 LOCATEf 16, 1, 0
 PRINTf "File Editor Usage:"
 COLORf Yellow
 LOCATEf 17, 1, 0
 PRINTf "   Enter editing functions or cursor movement through the hex values,"
 LOCATEf 18, 1, 0
 PRINTf "   while changing them with <enter>, <delete> or <insert> as you edit."
 COLORf Green
 LOCATEf 19, 1, 0
 PRINTf "Author status:"
 COLORf Yellow
 LOCATEf 20, 1, 0
 PRINTf "   Written by: Erik Jon Oredson, AS. Csci"
 LOCATEf 21, 1, 0
 PRINTf "   Email: eoredson@gmail.com"
 LOCATEf 22, 1, 0
 PRINTf "   Urls: www.filegate.net, www.simtel.net"
END SUB

' display main program editing screen.
SUB DisplayScreen
On Local Error Resume Next
CALL HMouse
CLS
COLORf Magenta
LOCATEf 1, 1, 0
PRINTf " " + CHR$(ULcorner)
PRINTf STRING$(3,HLine)
COLORf White
PRINTf "File"
COLORf Magenta
PRINTf STRING$(6,HLine)
COLORf White
PRINTf "Charts"
COLORf Magenta
PRINTf STRING$(4,HLine)
COLORf White
PRINTf "Dump"
COLORf Magenta
PRINTf STRING$(6,HLine)
COLORf White
PRINTf "Edit"
COLORf Magenta
PRINTf STRING$(6,HLine)
COLORf White
PRINTf "Jump"
COLORf Magenta
PRINTf STRING$(6,HLine)
COLORf White
PRINTf "Print"
COLORf Magenta
PRINTf STRING$(3,HLine)
COLORf White
PRINTf "Search"
COLORf Magenta
PRINTf CHR$(Hline)+Chr$(Hline)
COLORf Yellow
PRINTf Version
COLORf Magenta
PRINTf STRING$(1,HLine)
PRINTf CHR$(URcorner)
LOCATEf 2, 1, 0
PRINTf " " + CHR$(Vline) + STRING$(75, 32) + CHR$(Vline)
LOCATEf 3, 1, 0
PRINTf " " + CHR$(Vline) + " "
COLORf Green
PRINTf CHR$(ULcorner) + STRING$(46, Hline) + CHR$(URcorner) + " "
PRINTf CHR$(ULcorner) + STRING$(22, Hline) + CHR$(URcorner)
COLORf White
PRINTf "x"
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 4, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "0"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline)
COLORf White
PRINTf "<"
COLORf Green
PRINTf CHR$(Vline) + STRING$(22, 32) + CHR$(Vline)
COLORf White
PRINTf "?"
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 5, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "1"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline)
COLORf White
PRINTf "|"
COLORf Green
PRINTf CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 6, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "2"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline) + " " + CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 7, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "3"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline) + " " + CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 8, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "4"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline) + " " + CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 9, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "5"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline) + " " + CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 10, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "6"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline) + " " + CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 11, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "7"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline) + " " + CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 12, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "8"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline) + " " + CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 13, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "9"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline) + " " + CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 14, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "A"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline) + " " + CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 15, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "B"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline) + " " + CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 16, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "C"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline) + " " + CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 17, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "D"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline) + " " + CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 18, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "E"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline) + " " + CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 19, 1, 0
PRINTf " " + CHR$(Vline)
COLORf White
PRINTf "F"
COLORf Green
PRINTf CHR$(Vline) + STRING$(46, 32) + CHR$(Vline)
COLORf White
PRINTf "|"
COLORf Green
PRINTf CHR$(Vline) + STRING$(22, 32) + CHR$(Vline) + " "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 20, 1, 0
PRINTf " " + CHR$(Vline) + " "
COLORf Green
PRINTf CHR$(LLcorner) + STRING$(46, Hline) + CHR$(LRcorner)
COLORf White
PRINTf ">"
COLORf Green
PRINTf CHR$(LLcorner) + STRING$(22, Hline) + CHR$(LRcorner) + " "
COLORf Magenta
PRINTf CHR$(Vline)
' check to skip info line area.
IF ScreenRow THEN
   COLORf Magenta
   LOCATEf 21, 1, 0
   PRINTf " " + CHR$(LLcorner) + STRING$(75, Hline) + CHR$(LRcorner)
   COLORf Plain
   CALL SMouse
   EXIT SUB
END IF
LOCATEf 21, 1, 0
PRINTf " " + CHR$(Vline)
COLORf Yellow
PRINTf " Alt-A Append bytes, Alt-M Append string, Alt-C ANSI Chart, Alt-N New File "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 22, 1, 0
PRINTf " " + CHR$(Vline)
COLORf Yellow
PRINTf " Alt-H HEX Chart, Alt-R Redraw, Alt-S Search bytes, Alt-U Undo, Alt-X Exit "
COLORf Magenta
PRINTf CHR$(Vline)
LOCATEf 23, 1, 0
PRINTf " " + CHR$(Vline)
COLORf Yellow
PRINTf " Alt-J Jump, Alt-K Search string, Alt-D Dump, Alt-P Print, Alt-Z Undo All. "
COLORf Magenta
PRINTf CHR$(Vline)
COLORf Magenta
LOCATEf 24, 1, 0
PRINTf " " + CHR$(LLcorner) + STRING$(75, Hline) + CHR$(LRcorner)
COLORf Plain
CALL SMouse
END SUB

REM End-of-subprogram. Please deliver the cats now.
