REM Program: Hex Editor v3.9a, Module 2 of 5, PD 2003.
REM Author: Erik Jon Oredson AS. Csci
REM Release: 05/23/2003.
REM Status: Public Domain.
REM Email: eoredson@yahoo.com
REM Urls: www.simtel.net www.filegate.net
REM  www.winsite.com

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

REM Subroutines:
REM   ReadConfigFile    --  search for and read configure file.
REM   DropDownMenu      --  starts top drop down menu.
REM   OpenDataFiles     --  search for and open data files.
REM   HelpScreen        --  display help screens.
REM   DisplayScreen2    --  display screen border.
REM   DisplayBootUsage  --  display boot usage.
REM   DisplayScreen     --  display main editing screen.
REM   Deconcatenate     --  deconcatenates a file to 64 bytes.

REM Functions:
REM   ReleaseTime       --  releases time slice to windows.
REM   TrimSpaces        --  removes spaces from a string.
REM   Conanicalize      --  trims a filename.
REM   TestFile          --  test for a file could exist.
REM   Directories       --  get a directory from temp data file.
REM   Filenames         --  get a filename from temp data file.
REM   UndoByte          --  get an undo byte from temp data file.
REM   UndoPosition      --  get an undo position from temp data file.
REM   TimeElapsed       --  test time elapsed from initial time.
REM   TimeNow           --  returns seconds past midnight.

REM Mouse routines:
REM   MouseDriver       --  processes mouse activity.
REM   MouseFunction     --  accesses mouse.

' routine to read in custom config file variables.
' searchs current path, environment path, then path statement.
SUB ReadConfigFile (Var$)
 ' declare error trap.
 ON LOCAL ERROR GOTO Error.Routine

 ' search current directory.
 Config.Filename$ = ConfigFile
 IF DIR$(Config.Filename$) <> Nul THEN
    GOTO ReadFile2
 END IF
 ' search environment data file.
 File$ = ENVIRON$("HEXEDIT")
 IF LEN(File$) THEN
    File$ = RTRIM$(File$)
    File$ = LTRIM$(File$)
    IF RIGHT$(File$, 1) <> "\" THEN
       File$ = File$ + "\"
    END IF
    Config.Filename$ = File$ + ConfigFile
    IF DIR$(Config.Filename$) <> Nul THEN
       GOTO ReadFile2
    END IF
 END IF
 ' search path statement.
 Path$ = ENVIRON$("PATH")
 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 RIGHT$(File$, 1) <> "\" THEN
          File$ = File$ + "\"
       END IF
       Config.Filename$ = File$ + ConfigFile
       IF DIR$(Config.Filename$) <> Nul THEN
          GOTO ReadFile2
       END IF
    ELSE
       EXIT DO
    END IF
 LOOP
 EXIT SUB

' read in the data file
ReadFile2:
 ' open filename.
 ErrorTrap = False
 CLOSE #1
 OPEN Config.Filename$ FOR INPUT AS #1
 IF ErrorTrap THEN
    EXIT SUB
 END IF
 ' read input lines.
 DO WHILE NOT EOF(1)
    LINE INPUT #1, FileLine$
    FileLine2$ = FileLine$
    ' remove spaces.
    FileLine$ = TrimSpaces$(FileLine$)
    ' 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
          SELECT CASE UCASE$(Char$)
          ' check config filenames.
          CASE "DUMPFILE"
             DumpFile = Setting$
          CASE "EDITFILE"
             Var$ = Setting2$
          ' check environment replacement variables.
          CASE "HEXSCREEN"
             SELECT CASE UCASE$(Setting$)
             CASE "OFF", "0", "FALSE"
                ScreenRow = True
             CASE "ON", "-1", "TRUE"
                ScreenRow = False
             END SELECT
          CASE "HEXSORT"
             SELECT CASE UCASE$(Setting$)
             CASE "OFF", "0", "FALSE"
                HeapSortOff = True
             CASE "ON", "-1", "TRUE"
                HeapSortOff = False
             END SELECT
          CASE "HEXDISPLAY"
             SELECT CASE UCASE$(Setting$)
             CASE "OFF", "0", "FALSE"
                FileDisplay = True
             CASE "ON", "-1", "TRUE"
                FileDisplay = False
             END SELECT
          CASE "MOUSEDRAGSCROLL"
             MouseTime = CSNG(VAL(Setting$))
          CASE ELSE
             ' check ascii value.
             NewValue = INT(VAL(Setting$))
             IF NewValue >= False AND NewValue <= 255 THEN
                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
TopProgram:
 CLOSE #1
 EXIT SUB

' critical error trap.
Error.Routine:
 IF ScreenDrawn THEN
    CLS
 END IF
 ScreenDrawn = False
 COLOR White
 PRINT "Hex Editor ReadConfigFile " + Version + " " + Release + " critical error trap:"
 COLOR Yellow
 ErrorTrap = ERR
 SELECT CASE ERR
 CASE 5
    PRINT "Syntax error." ' should not happen.
 CASE 9
    PRINT "Subscript out of range."
 CASE 14
    PRINT "Out of string space."
 CASE 24
    PRINT "Device timeout."
 CASE 25
    PRINT "Device fault."
 CASE 27
    PRINT "Out of paper."
 CASE 52
    PRINT "Bad file name or number."
 CASE 53
    PRINT "File not found."
 CASE 54
    PRINT "Bad file mode."
 CASE 55
    PRINT "File already open."
 CASE 57
    PRINT "Device I/O error."
 CASE 58
    PRINT "File already exists."
 CASE 59
    PRINT "Bad record length."
 CASE 61
    PRINT "Disk full."
 CASE 62
    PRINT "Input past eof."
 CASE 63
    PRINT "Bad record length."
 CASE 64
    PRINT "Bad filename."
 CASE 67
    PRINT "Not enough file handles."
 CASE 68
    PRINT "Device unavailable."
 CASE 70
    PRINT "Permission denied."
 CASE 71
    PRINT "Disk not ready."
 CASE 72
    PRINT "Disk-media error."
 CASE 75
    PRINT "Path/File access error."
 CASE 76
    PRINT "Pathname not found."
 CASE 81
    PRINT "Invalid name."
 CASE ELSE
    PRINT "Untrapped error" + STR$(ERR) + "."
 END SELECT
 ' display error prompt.
 COLOR Green
 PRINT "Press R(etry), C(ontinue), Q(uit), A(bort):";
 ' 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"
       PRINT "r"
       RESUME
    CASE "c"
       PRINT "c"
       RESUME NEXT
    CASE "q"
       PRINT "q"
       RESUME TopProgram
    CASE "a"
       PRINT "a"
       EXIT DO
    END SELECT
 LOOP
END SUB

REM Define functions.

' function to release time slice in windows.
FUNCTION ReleaseTime
 ON LOCAL ERROR RESUME NEXT
 IF SupportedCall = False THEN
    InregsX.AX = &H1680
    InregsX.BX = &H0
    CALL InterruptX(&H2F, InregsX, OutregsX)
    IF (OutregsX.AX AND &HFF) = &H80 THEN
       SupportedCall = True
    END IF
 END IF
 ReleaseTime = True
END FUNCTION

' remove spaces from variable.
FUNCTION TrimSpaces$ (Var$)
 ON LOCAL ERROR RESUME NEXT
 Var1$ = Var$
 DO
    Parse = INSTR(Var1$, " ")
    IF Parse THEN
       Var1$ = LEFT$(Var1$, Parse - 1) + MID$(Var1$, Parse + 1)
    ELSE
       EXIT DO
    END IF
 LOOP
 TrimSpaces$ = Var1$
END FUNCTION

' conanicalizes filename.
FUNCTION Conanicalize$ (Var$)
 ON LOCAL ERROR RESUME NEXT
 Var1$ = Var$
 ' strip drive letter.
 Var1$ = UCASE$(Var1$)
 IF MID$(Var1$, 2, 1) = ":" THEN
    Var1$ = MID$(Var1$, 3)
 END IF
 ' strip dos path.
 DO
    Path = INSTR(Var1$, "\")
    IF Path THEN
       Var1$ = MID$(Var1$, Path + 1)
    ELSE
       EXIT DO
    END IF
 LOOP
 ' strip network path.
 DO
    Path = INSTR(Var1$, "/")
    IF Path THEN
       Var1$ = MID$(Var1$, Path + 1)
    ELSE
       EXIT DO
    END IF
 LOOP
 Conanicalize$ = Var1$
END FUNCTION

' test data file exists.
' returns: function=-1 if file exists,
'   or non-existent & can be created.
FUNCTION TestFile(Var$)
 DIM TestASCIIZ AS STRING*261
 TestASCIIZ = Var$ + CHR$(0)
 InregsX.AX = &H4300
 InregsX.DS = VARSEG(TestASCIIZ)
 InregsX.DX = VARPTR(TestASCIIZ)
 CALL InterruptX(&H21, InregsX, OutregsX)
 IF (OutregsX.Flags AND &H1) = &H0 THEN
    TestFile = True
    EXIT FUNCTION
 END IF
 ' check file nonexistent.
 IF (OutregsX.AX) = 2 THEN
    TestFile = True
    EXIT FUNCTION
 END IF
 TestFile = False
END FUNCTION

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.Routine2
 GOSUB StoreArea
TopProgram1:
 GOSUB DrawMenu
 GOSUB DrawCurrentMenuSelection

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

    ' call mouse subroutine.
    CALL MouseDriver

    ' check left mouse button.
    IF Mouse.ButtonX THEN
       Mouse.Row = Mouse.RowX
       Mouse.Column = Mouse.ColumnX
       GOSUB MouseButton1
    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
       SELECT CASE LEN(CharInput$)
       CASE 1
          SELECT CASE ASC(CharInput$)
          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
             IF FileLength THEN
                GOSUB MenuLeft
             END IF
          CASE 77 ' Right
             IF FileLength THEN
                GOSUB MenuRight
             END IF
          END SELECT
       END SELECT
    END IF
    ' release time slice,
    Var = 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 = 5
    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 = 5 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:
 IF Mouse.Present THEN
    CALL MouseFunction(HideMouse, 0)
 END IF
 COLOR White, Black
 GOSUB DisplayCurrentMenuSelection
 COLOR White, Black
 IF Mouse.Present THEN
    CALL MouseFunction(ShowMouse, 0)
 END IF
 RETURN

' adds hilight to current menu selection.
DrawCurrentMenuSelection:
 IF Mouse.Present THEN
    CALL MouseFunction(HideMouse, 0)
 END IF
 COLOR White, Blue
 GOSUB DisplayCurrentMenuSelection
 COLOR White, Black
 IF Mouse.Present THEN
    CALL MouseFunction(ShowMouse, 0)
 END IF
 RETURN

' draws current menu selection.
DisplayCurrentMenuSelection:
 SELECT CASE CurrentMenu
 CASE 1
    SELECT CASE CurrentMenuSelection
    CASE 1
       LOCATE 3, 7, 0
       PRINT "Open new file";
    CASE 2
       LOCATE 4, 7, 0
       PRINT "Close file   ";
    CASE 3
       LOCATE 5, 7, 0
       PRINT "View files   ";
    CASE 4
       LOCATE 6, 7, 0
       PRINT "Toggle window";
    CASE 5
       LOCATE 7, 7, 0
       PRINT "Exit program ";
    END SELECT
 CASE 2
    SELECT CASE CurrentMenuSelection
    CASE 1
       LOCATE 3, 17, 0
       PRINT "ANSI Chart";
    CASE 2
       LOCATE 4, 17, 0
       PRINT "HEX Chart ";
    END SELECT
 CASE 3
    SELECT CASE CurrentMenuSelection
    CASE 1
       LOCATE 3, 27, 0
       PRINT "HEX Screen Dump";
    CASE 2
       LOCATE 4, 27, 0
       PRINT "HEX File Dump  ";
    END SELECT
 CASE 4
    SELECT CASE CurrentMenuSelection
    CASE 1
       LOCATE 3, 37, 0
       PRINT "Append Bytes       ";
    CASE 2
       LOCATE 4, 37, 0
       PRINT "Append ASCII String";
    CASE 3
       LOCATE 5, 37, 0
       PRINT "Redraw Screen      ";
    CASE 4
       LOCATE 6, 37, 0
       PRINT "Undo last byte     ";
    CASE 5
       LOCATE 7, 37, 0
       PRINT "Undo All bytes     ";
    END SELECT
 CASE 5
    SELECT CASE CurrentMenuSelection
    CASE 1
       LOCATE 3, 47, 0
       PRINT "Jump to byte";
    CASE 2
       LOCATE 4, 47, 0
       PRINT "Jump to page";
    END SELECT
 CASE 6
    SELECT CASE CurrentMenuSelection
    CASE 1
       LOCATE 3, 57, 0
       PRINT "HEX Screen Print";
    CASE 2
       LOCATE 4, 57, 0
       PRINT "HEX File Print  ";
    END SELECT
 CASE 7
    SELECT CASE CurrentMenuSelection
    CASE 1
       LOCATE 3, 65, 0
       PRINT "Search string";
    CASE 2
       LOCATE 4, 65, 0
       PRINT "Search bytes ";
    END SELECT
 END SELECT
 RETURN

' draws menu.
DrawMenu:
 CurrentMenuSelection = 1
 GOSUB BoxBorder
 BoxDrawX1 = Xstore1
 BoxDrawX2 = Xstore2
 BoxDrawY1 = Ystore1
 BoxDrawY2 = Ystore2
 SELECT CASE CurrentMenu
 CASE 1
    BoxDrawLength = 15
    GOSUB DrawBox
    COLOR White
    LOCATE 3, 7, 0
    PRINT "Open new file";
    LOCATE 4, 7, 0
    PRINT "Close file   ";
    LOCATE 5, 7, 0
    PRINT "View files   ";
    LOCATE 6, 7, 0
    PRINT "Toggle window";
    LOCATE 7, 7, 0
    PRINT "Exit program ";
 CASE 2
    BoxDrawLength = 12
    GOSUB DrawBox
    COLOR White
    LOCATE 3, 17, 0
    PRINT "ANSI Chart";
    LOCATE 4, 17, 0
    PRINT "HEX Chart ";
 CASE 3
    BoxDrawLength = 17
    GOSUB DrawBox
    COLOR White
    LOCATE 3, 27, 0
    PRINT "HEX Screen Dump";
    LOCATE 4, 27, 0
    PRINT "HEX File Dump  ";
 CASE 4
    BoxDrawLength = 21
    GOSUB DrawBox
    COLOR White
    LOCATE 3, 37, 0
    PRINT "Append Bytes       ";
    LOCATE 4, 37, 0
    PRINT "Append ASCII String";
    LOCATE 5, 37, 0
    PRINT "Redraw Screen      ";
    LOCATE 6, 37, 0
    PRINT "Undo last byte     ";
    LOCATE 7, 37, 0
    PRINT "Undo All bytes     ";
 CASE 5
    BoxDrawLength = 14
    GOSUB DrawBox
    COLOR White
    LOCATE 3, 47, 0
    PRINT "Jump to byte";
    LOCATE 4, 47, 0
    PRINT "Jump to page";
 CASE 6
    BoxDrawLength = 18
    GOSUB DrawBox
    COLOR White
    LOCATE 3, 57, 0
    PRINT "HEX Screen Print";
    LOCATE 4, 57, 0
    PRINT "HEX File Print  ";
 CASE 7
    BoxDrawLength = 15
    GOSUB DrawBox
    COLOR White
    LOCATE 3, 65, 0
    PRINT "Search string";
    LOCATE 4, 65, 0
    PRINT "Search bytes ";
 END SELECT
 RETURN

' stores area under menu.
StoreArea:
 IF CurrentMenu = False THEN
    RETURN
 END IF
 IF Mouse.Present THEN
    CALL MouseFunction(HideMouse, 0)
 END IF
 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.
 COLOR White, Blue
 GOSUB DisplayTab
 IF Mouse.Present THEN
    CALL MouseFunction(ShowMouse, 0)
 END IF
 RETURN

' restores area under menu.
RestoreArea:
 IF CurrentMenu = False THEN
    RETURN
 END IF
 IF Mouse.Present THEN
    CALL MouseFunction(HideMouse, 0)
 END IF
 GOSUB BoxBorder
 RowX1 = 0
 ColumnY1 = 0
 FOR RowX2 = Xstore1 TO Xstore2
    RowX1 = RowX1 + 1
    ColumnY1 = 0
    FOR ColumnY2 = Ystore1 TO Ystore2
       ColumnY1 = ColumnY1 + 1
       LOCATE RowX2, ColumnY2, 1
       ' restore color.
       TempZ = Area2(RowX1, ColumnY1)
       VarB = INT(TempZ / 16)
       VarF = TempZ MOD 16
       COLOR VarF, VarB
       ' restore ascii character.
       PRINT CHR$(Area1(RowX1, ColumnY1));
    NEXT
 NEXT
 ' remove hilight menu tab.
 COLOR White, Black
 GOSUB DisplayTab
 IF Mouse.Present THEN
    CALL MouseFunction(ShowMouse, 0)
 END IF
 RETURN

' returns borders of box.
BoxBorder:
 SELECT CASE CurrentMenu
 CASE 1
    Xstore1 = 2
    Xstore2 = 8
    Ystore1 = 6
    Ystore2 = 20
 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

' redraws menu tab.
DisplayTab:
 SELECT CASE CurrentMenu
 CASE 1 ' File
    LOCATE 1, 6, 0
    PRINT "File";
 CASE 2 ' Charts
    LOCATE 1, 16, 0
    PRINT "Charts";
 CASE 3 ' Dump
    LOCATE 1, 26, 0
    PRINT "Dump";
 CASE 4 ' Edit
    LOCATE 1, 36, 0
    PRINT "Edit";
 CASE 5 ' Jump
    LOCATE 1, 46, 0
    PRINT "Jump";
 CASE 6 ' Print
    LOCATE 1, 56, 0
    PRINT "Print";
 CASE 7 ' Search
    LOCATE 1, 64, 0
    PRINT "Search";
 END SELECT
 COLOR White, Black
 RETURN

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

' process mouse move.
MoveMouse:
 ' select drop down menu.
 IF Mouse.Row = 1 THEN
    NewMenuSelection = 0
    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
       IF Mouse.Present THEN
          CALL MouseFunction(HideMouse, 0)
       END IF
       COLOR White, Blue
       GOSUB DisplayTab
       IF Mouse.Present THEN
          CALL MouseFunction(ShowMouse, 0)
       END IF
    END IF
    RETURN
 END IF
 ' check mouse selection boundaries.
 SELECT CASE CurrentMenu
 CASE 1
    IF Mouse.Row >=3 AND Mouse.Row <= 7 THEN
       IF Mouse.Column >= 7 AND Mouse.Column <= 19 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.
MouseButton1:
 ExitMouse = False
 IF Mouse.Row - 2 = CurrentMenuSelection THEN
    SELECT CASE CurrentMenu
    CASE 1
       IF Mouse.Column >= 7 AND Mouse.Column <= 19 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.Routine2:
 CurrentMenu = False
 IF ScreenDrawn THEN
    CLS
 END IF
 ScreenDrawn = False
 COLOR White
 PRINT "Hex Editor DropDownMenu " + Version + " " + Release + " critical error trap:"
 COLOR Yellow
 ErrorTrap = ERR
 SELECT CASE ERR
 CASE 5
    PRINT "Syntax error." ' should not happen.
 CASE 9
    PRINT "Subscript out of range."
 CASE 14
    PRINT "Out of string space."
 CASE 24
    PRINT "Device timeout."
 CASE 25
    PRINT "Device fault."
 CASE 27
    PRINT "Out of paper."
 CASE 52
    PRINT "Bad file name or number."
 CASE 53
    PRINT "File not found."
 CASE 54
    PRINT "Bad file mode."
 CASE 55
    PRINT "File already open."
 CASE 57
    PRINT "Device I/O error."
 CASE 58
    PRINT "File already exists."
 CASE 59
    PRINT "Bad record length."
 CASE 61
    PRINT "Disk full."
 CASE 62
    PRINT "Input past eof."
 CASE 63
    PRINT "Bad record length."
 CASE 64
    PRINT "Bad filename."
 CASE 67
    PRINT "Not enough file handles."
 CASE 68
    PRINT "Device unavailable."
 CASE 70
    PRINT "Permission denied."
 CASE 71
    PRINT "Disk not ready."
 CASE 72
    PRINT "Disk-media error."
 CASE 75
    PRINT "Path/File access error."
 CASE 76
    PRINT "Pathname not found."
 CASE 81
    PRINT "Invalid name."
 CASE ELSE
    PRINT "Untrapped error" + STR$(ERR) + "."
 END SELECT
 ' display error prompt.
 COLOR Green
 PRINT "Press R(etry), C(ontinue), Q(uit):";
 ' 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"
       PRINT "r"
       RESUME TopProgram1
    CASE "c"
       PRINT "c"
       RESUME TopProgram1
    CASE "q"
       PRINT "q"
       RESUME TopProgram2
    END SELECT
 LOOP
END SUB

' subroutine to check mouse activity.
SUB MouseDriver
 ON LOCAL ERROR RESUME NEXT
 Mouse.Button1 = False
 Mouse.Button2 = False
 Mouse.Button3 = False
 Mouse.Row = False
 Mouse.Column = False
 ' check mouse present
 IF Mouse.Present = False THEN
    EXIT SUB
 END IF
 ' read middle mouse button.
 CALL MouseFunction(Button, 2)
 IF (OutregsX.AX AND 4) = 4 THEN
    IF OutregsX.BX > 0 THEN
       Mouse.Button3 = True
       Mouse.Row = OutregsX.DX / 8 + 1
       Mouse.Column = OutregsX.CX / 8 + 1
       EXIT SUB
    END IF
 END IF
 ' read right mouse button.
 CALL MouseFunction(Button, 1)
 IF (OutregsX.AX AND 2) = 2 THEN
    IF OutregsX.BX > 0 THEN
       Mouse.Button2 = True
       Mouse.Row = OutregsX.DX / 8 + 1
       Mouse.Column = OutregsX.CX / 8 + 1
       EXIT SUB
    END IF
 END IF
 ' read left mouse button.
 Mouse.ButtonX = False
 CALL MouseFunction(Button, 0)
 IF (OutregsX.AX AND 1) = 1 THEN
    IF OutregsX.BX > 0 THEN
       Mouse.ButtonX = True
       Mouse.RowX = OutregsX.DX / 8 + 1
       Mouse.ColumnX = OutregsX.CX / 8 + 1
    END IF
    ' check button press.
    Var2 = OutregsX.CX / 8 + 1
    Var3 = OutregsX.DX / 8 + 1
    ' check button press.
    IF Var3 <> Mouse.Button1.X OR Var2 <> Mouse.Button1.Y THEN
       Mouse.Button1 = 1
       Mouse.Button1.X = Var3
       Mouse.Button1.Y = Var2
       Mouse.Button1.Row = Mouse.Button1.X
       Mouse.Button1.Column = Mouse.Button1.Y
       EXIT SUB
    END IF
    ' check button pressed w/ mouse position
    CALL MouseFunction(Position, 0)
    Var2 = OutregsX.CX / 8 + 1
    Var3 = OutregsX.DX / 8 + 1
    IF Var3 <> Mouse.X OR Var2 <> Mouse.Y THEN
       Mouse.Button1 = 2
       Mouse.X = Var3
       Mouse.Y = Var2
       Mouse.Row = Mouse.X
       Mouse.Column = Mouse.Y
       EXIT SUB
    END IF
    ' check button pressed w/ mouse position
    CALL MouseFunction(Position, 0)
    Var2 = OutregsX.CX / 8 + 1
    Var3 = OutregsX.DX / 8 + 1
    IF Var3 = 2 OR Var3 = 3 THEN
       IF Var2 >= 6 AND Var2 <= 49 THEN
          Mouse.Button1 = 3
          Mouse.X = Var3
          Mouse.Y = Var2
          Mouse.Row = Mouse.X
          Mouse.Column = Mouse.Y
          EXIT SUB
       END IF
    END IF
    ' check button pressed w/ mouse position
    CALL MouseFunction(Position, 0)
    Var2 = OutregsX.CX / 8 + 1
    Var3 = OutregsX.DX / 8 + 1
    IF Var3 = 20 OR Var3 = 21 THEN
       IF Var2 >= 6 AND Var2 <= 49 THEN
          Mouse.Button1 = 4
          Mouse.X = Var3
          Mouse.Y = Var2
          Mouse.Row = Mouse.X
          Mouse.Column = Mouse.Y
          EXIT SUB
       END IF
    END IF
 END IF
 ' read mouse position
 CALL MouseFunction(Position, 0)
 Var2 = OutregsX.CX / 8 + 1
 Var3 = OutregsX.DX / 8 + 1
 IF Var3 <> Mouse.X OR Var2 <> Mouse.Y THEN
    Mouse.X = Var3
    Mouse.Y = Var2
    Mouse.Row = Mouse.X
    Mouse.Column = Mouse.Y
 END IF
END SUB

SUB MouseFunction (Var1, Var2)
 ' subroutine calls mouse bios function.
 ON LOCAL ERROR RESUME NEXT
 REM INT 33H:
 REM   AX=00 - initialize mouse.
 REM   AX=01 - show mouse cursor.
 REM   AX=02 - hide mouse cursor. (re-entrant).
 REM   AX=03 - return position and button status.
 REM   AX=05 - return button press data.
 InregsX.AX = Var1
 InregsX.BX = Var2
 CALL InterruptX(&H33, InregsX, OutregsX)
END SUB

' structure directory structure function.
FUNCTION Directories$ (Var1%)
 ON LOCAL ERROR RESUME NEXT
 IF Windows.Detected THEN
    GET 3, Var1%, WinFileStruc
    Directories$ = WinFileStruc.Name
 ELSE
    GET 3, Var1%, DosFileStruc
    Directories$ = DosFileStruc.Name
 END IF
END FUNCTION

' structure filename structure function.
FUNCTION Filenames$ (Var1%)
 ON LOCAL ERROR RESUME NEXT
 IF Windows.Detected THEN
    GET 2, Var1%, WinFileStruc
    Filenames$ = WinFileStruc.Name
 ELSE
    GET 2, Var1%, DosFileStruc
    Filenames$ = DosFileStruc.Name
 END IF
END FUNCTION

' structure undo structure function.
FUNCTION UndoByte%(Var1%)
 ON LOCAL ERROR RESUME NEXT
 GET 6, Var1%, UndoFile
 UndoByte = UndoFile.UndoByte1(CurrentFile)
END FUNCTION

' structure undo structure function.
FUNCTION UndoPosition#(Var1%)
 ON LOCAL ERROR RESUME NEXT
 GET 6, Var1%, UndoFile
 UndoPosition = UndoFile.UndoPosition1(CurrentFile)
END FUNCTION

' structure undo structure function.
FUNCTION Markers#(Var1%)
 ON LOCAL ERROR RESUME NEXT
 GET 7, Var1%, MarkerFile
 Markers = MarkerFile.Markers1(CurrentFile)
END FUNCTION

Function TimeElapsed(Start.Time!,Wait.Time!)
 Elapsed.Time!=TimeNow!-Start.Time!
 If Elapsed.Time!<SFalse Then
    Elapsed.Time!=Elapsed.Time!+86400!
 Endif
 If Elapsed.Time!>Wait.Time! Then
    TimeElapsed=True
 Else
    TimeElapsed=False
 Endif
End Function

Function TimeNow!
 ' seconds past midnight
 InregsX.AX=&H0000
 Call InterruptX(&H1A,InregsX,OutregsX)
 If OutregsX.CX<False Then
    Var#=OutregsX.CX+65536
 Else
    Var#=OutregsX.CX
 Endif
 Var#=Var#*&H10000
 If OutregsX.DX<False Then
    Var#=Var#+OutregsX.DX+65536
 Else
    Var#=Var#+OutregsX.DX
 Endif
 Var#=Var#/18.2#
 TimeNow!=Csng(Var#)
End Function

' deconcatenates a filename to 32/64 bytes with \..\ characters.
SUB Deconcatenate(Z$,Z%)
 IF INSTR(Z$, "\") = 0 THEN
    EXIT SUB
 END IF
 DO
    IF LEN(Z$) > Z% 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
 LOOP
 DO
    V = INSTR(Z$, "\..\..\")
    IF V > 0 THEN
       Z$ = LEFT$(Z$, V - 1) + "\..\" + MID$(Z$, V + 7)
    ELSE
       EXIT DO
    END IF
 LOOP
 IF LEN(Z$) > Z% THEN
    Z$ = LEFT$(Z$, Z%)
 END IF
END SUB

' initialize files.
'   tests temp environment directories,
'   temp directory, root, then default.
SUB OpenDataFiles(V1$, V2$)
 ON LOCAL ERROR GOTO Error.Routine4
 V$ = ENVIRON$("TMP")
 IF V$ = "" THEN
    V$ = ENVIRON$("TEMP")
 END IF
 IF LEN(V$) THEN
    IF RIGHT$(V$, 1) = "\" THEN
       F1$ = V$ + V1$
    ELSE
       F1$ = V$ + "\" + V1$
    END IF
    F2$ = ""
    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$ = "" 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$ = "" 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$ = "" 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$ = "" THEN
       GOTO OpenDataFilename
    END IF
    IF TestFile(F2$) THEN
       GOTO OpenDataFilename
    END IF
 END IF
 ERROR 76
 END

OpenDataFilename:
 V1$ = F1$
 V2$ = F2$
 EXIT SUB

' simple error routine
Error.Routine4:
 CLS
 COLOR White
 PRINT "Hex Editor " + Version + " " + Release + " fileopen critical error trap:"
 COLOR Yellow
 ErrorTrap = ERR
 SELECT CASE ERR
 CASE 5
    PRINT "Syntax error." ' should not happen.
 CASE 9
    PRINT "Subscript out of range."
 CASE 14
    PRINT "Out of string space."
 CASE 24
    PRINT "Device timeout."
 CASE 25
    PRINT "Device fault."
 CASE 27
    PRINT "Out of paper."
 CASE 52
    PRINT "Bad file name or number."
 CASE 53
    PRINT "File not found."
 CASE 54
    PRINT "Bad file mode."
 CASE 55
    PRINT "File already open."
 CASE 57
    PRINT "Device I/O error."
 CASE 58
    PRINT "File already exists."
 CASE 59
    PRINT "Bad record length."
 CASE 61
    PRINT "Disk full."
 CASE 62
    PRINT "Input past eof."
 CASE 63
    PRINT "Bad record length."
 CASE 64
    PRINT "Bad filename."
 CASE 67
    PRINT "Not enough file handles."
 CASE 68
    PRINT "Device unavailable."
 CASE 70
    PRINT "Permission denied."
 CASE 71
    PRINT "Disk not ready."
 CASE 72
    PRINT "Disk-media error."
 CASE 75
    PRINT "Path/File access error."
 CASE 76
    PRINT "Pathname not found."
 CASE 81
    PRINT "Invalid name."
 CASE ELSE
    PRINT "Untrapped error" + STR$(ERR) + "."
 END SELECT
 ' display error prompt.
 COLOR Green
 PRINT "Check TEMP variables, .CFG file, or DOS file handles, then restart."
 COLOR Plain
 END
END SUB

REM Remaining screen subroutines:

' display help screens.
SUB HelpScreen
 GOSUB DisplayHelpScreen1
 GOSUB DisplayHelpScreen2
 GOSUB DisplayHelpScreen3
 GOSUB DisplayHelpScreen4
 GOSUB DisplayHelpScreen5
 EXIT SUB

' help screen header.
HelpHeader:
 CALL DisplayScreen2
 LOCATE 2, 2
 COLOR White
 PRINT "Help screen: Hex Editor " + Version + " " + Release + " functions:"
 RETURN

' help screen key prompt.
PressKey:
 COLOR White
 PRINT "Press a key:";
 WHILE INKEY$ = Nul: WEND
 RETURN

' help screen 1.
DisplayHelpScreen1:
 GOSUB HelpHeader
 COLOR Red
 LOCATE 3, 2
 PRINT "Function keys:                          Editing keys:"
 COLOR Yellow
 LOCATE 4, 2
 PRINT "Alt-A  Append multiple bytes to file.   Tab    -- Switch windows."
 LOCATE 5, 2
 PRINT "Alt-C  ANSI Chart.                      Enter  -- Change byte value."
 LOCATE 6, 2
 PRINT "Alt-D  HEX Screen Dump.                 Insert -- Change string value."
 LOCATE 7, 2
 PRINT "Alt-E  HEX File Dump.                   Delete -- Change hex string."
 LOCATE 8, 2
 PRINT "Alt-H  HEX Chart.                       Cursor Up/Down/Left/Right."
 LOCATE 9, 2
 PRINT "Alt-J  Jump to byte position.           Page Up/Page Down, Home/End."
 LOCATE 10, 2
 PRINT "Alt-K  Search for ASCII string.         Ctrl-Home/Ctrl-End."
 LOCATE 11, 2
 PRINT "Alt-L  Jump to page position.           Ctrl-Right/Ctrl-Left."
 LOCATE 12, 2
 PRINT "Alt-M  Append ASCII string to file.     Escape/Alt-F = Input Menu."
 COLOR Yellow
 LOCATE 13, 2
 PRINT "Alt-N  Open new file.                   ";
 COLOR Red
 PRINT "Other keys:"
 COLOR Yellow
 LOCATE 14, 2
 PRINT "Alt-P  HEX Screen Print.                (hex value numeral preceded)."
 LOCATE 15, 2
 PRINT "Alt-Q  Help screen.                     (right window unprintable chars"
 LOCATE 16, 2
 PRINT "Alt-R  Redraw screen.                   are represented with a dot)."
 LOCATE 17, 2
 PRINT "Alt-S  Search for multiple bytes.       (ascii values precede with H"
 LOCATE 18, 2
 PRINT "Alt-T  HEX File Print.                  treated as hexcidecimal)."
 LOCATE 19, 2
 PRINT "Alt-U  Undo last byte change.           (<escape> key exits search)."
 LOCATE 20, 2
 PRINT "Alt-X  Exit program."
 LOCATE 21, 2
 PRINT "Alt-Y  Toggle right window."
 LOCATE 22, 2
 PRINT "Alt-Z  Undo All byte changes."
 LOCATE 23, 2
 GOSUB PressKey
 RETURN

' help screen 2.
DisplayHelpScreen2:
 GOSUB HelpHeader
 COLOR Red
 LOCATE 3, 2
 PRINT "Marker keys:"
 COLOR Yellow
 LOCATE 4, 2
 PRINT "1   add marker"
 LOCATE 5, 2
 PRINT "2   add specific marker value"
 LOCATE 6, 2
 PRINT "3   delete marker"
 LOCATE 7, 2
 PRINT "4   delete specific marker"
 LOCATE 8, 2
 PRINT "5   jump previous marker"
 LOCATE 9, 2
 PRINT "6   jump current marker"
 LOCATE 10, 2
 PRINT "7   jump next marker"
 LOCATE 11, 2
 PRINT "8   jump specific marker"
 LOCATE 12, 2
 PRINT "9   list all markers"
 LOCATE 13, 2
 PRINT "0   list specific marker"
 LOCATE 14, 2
 PRINT "-   list markers of value"
 LOCATE 15, 2
 PRINT "+   list range of markers"
 LOCATE 16, 2
 PRINT "=   delete a range"
 LOCATE 17, 2
 PRINT "[   delete all markers"
 LOCATE 18, 2
 PRINT "]   delete markers of value"
 LOCATE 19, 2
 GOSUB PressKey
 RETURN

' help screen 3.
DisplayHelpScreen3:
 GOSUB HelpHeader
 COLOR Red
 LOCATE 3, 2
 PRINT "Information keys:"
 COLOR Yellow
 LOCATE 4, 2
 PRINT "? key displays file length, and undos remaining."
 LOCATE 5, 2
 PRINT "! key displays current page, row, and column."
 LOCATE 6, 2
 PRINT "~ key displays last page and markers used."
 LOCATE 7, 2
 PRINT CHR$(34) + " key displays current path of file being edited."
 LOCATE 8, 2
 PRINT "; key displays the range of the current hilighted area."
 LOCATE 9, 2
 PRINT "{ key displays number of pasted entries stored in the undo file."
 COLOR Red
 LOCATE 10, 2
 PRINT "Display keys:"
 COLOR Yellow
 LOCATE 11, 2
 PRINT "F1 key toggles 64-byte filename display."
 LOCATE 12, 2
 PRINT "F2 key toggles lower screen help key list."
 LOCATE 13, 2
 COLOR Red
 PRINT "Hilight keys:"
 COLOR Yellow
 LOCATE 14, 2
 PRINT "Shift-<key> hilights area, where <key> is:"
 LOCATE 15, 2
 PRINT "<left>/<right>/<up>/<down>/<page up>/<page down>/<home>/<end>"
 LOCATE 16, 2
 COLOR Red
 PRINT "Clipboard controls:"
 COLOR Yellow
 LOCATE 17, 2
 PRINT "Control-C (copy)/Control-V (paste)"
 LOCATE 18,2
 PRINT "Control-X (undo previous paste)/Control-Z (undo all pastes)"
 LOCATE 19, 2
 GOSUB PressKey
 RETURN

' help screen 4.
DisplayHelpScreen4:
 GOSUB HelpHeader
 COLOR Red
 LOCATE 3, 2
 PRINT "Multiple file keys:"
 COLOR Yellow
 LOCATE 4, 2
 PRINT "Alt-N  -  Load new File."
 LOCATE 5, 2
 PRINT "Alt-V  -  View files."
 LOCATE 6, 2
 PRINT "Alt-W  -  Close file."
 LOCATE 7, 2
 PRINT "F6     -  Next file."
 LOCATE 8, 2
 PRINT "F7     -  Previous file."
 LOCATE 9, 2
 PRINT "F8     -  Load new file."
 LOCATE 10, 2
 PRINT "F9     -  Close file."
 LOCATE 11, 2
 PRINT "F10    -  View files."
 LOCATE 12, 2
 PRINT "Alt-1 to Alt-9  -  select specific file."
 COLOR Red
 LOCATE 13, 2
 PRINT "File menu box keys:"
 COLOR Yellow
 LOCATE 14, 2
 PRINT "F1  -  drive change."
 LOCATE 15, 2
 PRINT "F2  -  toggle file sort.
 LOCATE 16, 2
 PRINT "F3  -  move file menu box."
 LOCATE 17, 2
 PRINT "Alt-A to Alt-Z  selects drive letter.
 LOCATE 18, 2
 GOSUB PressKey
 RETURN

' help screen 5.
DisplayHelpScreen5:
 CALL DisplayScreen2
 COLOR White
 LOCATE 2, 2
 PRINT "Hexedit information: ";
 IF Windows.Detected THEN
    PRINT "(Windows loaded);";
 ELSE
    PRINT "(DOS loaded);";
 END IF
 COLOR Yellow
 LOCATE 3, 2
 PRINT "Program: " + Program + " " + Version + " " + Release + "."
 LOCATE 4, 2
 PRINT "Author: " + Author
 LOCATE 5, 2
 PRINT "Release: " + Publish
 LOCATE 6, 2
 PRINT "Status: " + Status
 LOCATE 7, 2
 PRINT "Email: " + Email
 LOCATE 8, 2
 PRINT "Urls: " + Urls
 LOCATE 9, 2
 GOSUB PressKey
 RETURN
END SUB

' display screen border.
SUB DisplayScreen2
 CLS
 COLOR Magenta
 PRINT CHR$(ULcorner); STRING$(76, Hline); CHR$(URcorner)
 FOR Var2 = 2 TO 23
    LOCATE Var2, 1
    PRINT CHR$(Vline);
    LOCATE Var2, 78
    PRINT CHR$(Vline);
 NEXT
 LOCATE 24, 1
 PRINT CHR$(LLcorner); STRING$(76, Hline); CHR$(LRcorner);
 COLOR Plain
END SUB

' display boot usage.
SUB DisplayBootUsage
 COLOR Green
 PRINT "Command Usage:"
 COLOR Yellow
 PRINT "   Hexedit [@]<filename.ext>, [@]<filename.ext>, ..."
 COLOR Green
 PRINT "Where:"
 COLOR Yellow
 PRINT "   <filename.ext> is the file to edit. May include drive/pathname, and"
 PRINT "   supports long filenames in quotes. Filename may be omitted. Multiple"
 PRINT "   files allowed with * and ? characters. Maximum of 9 files available."
 PRINT "   Filename prepended with @ loads filelist from contents of file."
 COLOR Green
 PRINT "Example:"
 COLOR Yellow
 PRINT "   Hexedit " + CHR$(34) + "\dos\page.com" + CHR$(34)
 PRINT "   Or use the file menu box by starting Hexedit without a filename."
 COLOR Green
 PRINT "File Menu Box Usage:"
 COLOR Yellow
 PRINT "   Navigate using cursors, selecting with <enter>, and switch windows"
 PRINT "   with <tab> and Shift-<tab>. Exits to editor or DOS with <escape>."
 COLOR Green
 PRINT "File Editor Usage:"
 COLOR Yellow
 PRINT "   Enter editing functions or cursor movement through the hex values,"
 PRINT "   while changing them with <enter>, <delete> or <insert> as you edit."
 COLOR Green
 PRINT "Author status:"
 COLOR Yellow
 PRINT "   Written by: Erik Jon Oredson AS. Csci"
 PRINT "   Email: eoredson@yahoo.com"
END SUB

' display main program editing screen.
SUB DisplayScreen
CLS
COLOR Magenta
PRINT " "; CHR$(ULcorner);
PRINT STRING$(3,HLine);
COLOR White
PRINT "File";
COLOR Magenta
PRINT STRING$(6,HLine);
COLOR White
PRINT "Charts";
COLOR Magenta
PRINT STRING$(4,HLine);
COLOR White
PRINT "Dump";
COLOR Magenta
PRINT STRING$(6,HLine);
COLOR White
PRINT "Edit";
COLOR Magenta
PRINT STRING$(6,HLine);
COLOR White
PRINT "Jump";
COLOR Magenta
PRINT STRING$(6,HLine);
COLOR White
PRINT "Print";
COLOR Magenta
PRINT STRING$(3,HLine);
COLOR White
PRINT "Search";
COLOR Magenta
PRINT STRING$(8,HLine);
PRINT CHR$(URcorner)
PRINT " "; CHR$(Vline); STRING$(75, 32); CHR$(Vline)
PRINT " "; CHR$(Vline); " ";
COLOR Green
PRINT CHR$(ULcorner); STRING$(46, Hline); CHR$(URcorner); " ";
PRINT CHR$(ULcorner); STRING$(22, Hline); CHR$(URcorner);
COLOR White
PRINT "x";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "0";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline);
COLOR White
PRINT "<";
COLOR Green
PRINT CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "1";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline);
COLOR White
PRINT "|";
COLOR Green
PRINT CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "2";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline); " "; CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "3";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline); " "; CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "4";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline); " "; CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "5";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline); " "; CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "6";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline); " "; CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "7";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline); " "; CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "8";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline); " "; CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "9";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline); " "; CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "A";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline); " "; CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "B";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline); " "; CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "C";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline); " "; CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "D";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline); " "; CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "E";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline); " "; CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR White
PRINT "F";
COLOR Green
PRINT CHR$(Vline); STRING$(46, 32); CHR$(Vline);
COLOR White
PRINT "|";
COLOR Green
PRINT CHR$(Vline); STRING$(22, 32); CHR$(Vline); " ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline); " ";
COLOR Green
PRINT CHR$(LLcorner); STRING$(46, Hline); CHR$(LRcorner);
COLOR White
PRINT ">";
COLOR Green
PRINT CHR$(LLcorner); STRING$(22, Hline); CHR$(LRcorner); " ";
' check to skip info line area.
IF ScreenRow THEN
   GOTO NextRow
END IF
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR Yellow
PRINT " Alt-A Append bytes, Alt-M Append string, Alt-C ANSI Chart, Alt-N New File ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR Yellow
PRINT " Alt-H HEX Chart, Alt-R Redraw, Alt-S Search bytes, Alt-U Undo, Alt-X Exit ";
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(Vline);
COLOR Yellow
PRINT " Alt-J Jump, Alt-K Search string, Alt-D Dump, Alt-P Print, Alt-Z Undo All. ";
' display last row.
NextRow:
COLOR Magenta
PRINT CHR$(Vline)
PRINT " "; CHR$(LLcorner); STRING$(75, Hline); CHR$(LRcorner);
COLOR Plain
END SUB

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