REM Program: Hex Editor v3.6a, Module 2 of 4, PD 2003.
REM Author: Erik Jon Oredson AS. Csci
REM Release: 04/01/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'

' Include function for BC 7.1 compiler:
'   Comment out for VB 1.0.
Declare Function FormatD$ (byval a#,b$)
Function Format$(x#,x$)
 Format$ = FormatD$(x#,x$)
End Function

REM Subroutines:
REM   ReadConfigFile    --  search for and read configure file.
REM   DropDownMenu      --  starts top drop down menu.
REM   Menu              --  starts file selection 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 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 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.

REM Note: Mouse function 'Hide' should be used before any menu write,
REM  then mouse function 'Show' after the display is updated,
REM  this allows the mouse cursor in DOS to be hilighted over any
REM  menu selection or display. Mouse 'Hide' is re-entrant, that is,
REM  multiple calls to mouse 'Hide' are counted, then the same number of
REM  mouse 'Show' functions must be called. Should usually locate cursor
REM  after mouseshow.

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
 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

' deconcatenates a filename to 64 bytes with \..\ characters.
SUB Deconcatenate(Z$)
 DO
    IF LEN(Z$) > 64 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$) > 64 THEN
    Z$ = LEFT$(Z$, 64)
 END IF
END SUB

' File input menu box.
SUB Menu (C$, D$, X$, E$)

' returns:
'   C$  -  Drive letter.
'       Normally C without : or \
'   D$  -  Directory.
'       Without leading or trailing \ (can be null)
'   X$  -  Filespec.
'       Normally *.*
'   E$  -  Filename.
'       Can be long filename.

' concatenate:
'   IF D$="" THEN
'      Filename=C$+":\"+E$
'   ELSE
'      Filename=C$+":\"+D$+"\"+E$
'   END IF

' define simple error routine
ON LOCAL ERROR GOTO Error.Routine3

' test windows
GOSUB TestWindows

' open structure files
GOSUB OpenDataFiles

' display menu screen
GOSUB MainMenu

' get current drive/directory
GOSUB InitDrive
GOSUB InitDir

' read all subdirectories
StartMenu:
Current.Dir = 1
Dir.Box.Line = 1
GOSUB ClearDirBox
GOSUB LoadDirSpec
GOSUB DisplayDirSpec
GOSUB DisplayCurrentDir

' display first ten files
IF D$ = "" THEN
   F$ = C$ + ":\*.*"
ELSE
   F$ = C$ + ":\" + D$ + "\" + "*.*"
END IF
GOSUB ClearFileBox
GOSUB LoadFileSpec
GOSUB DisplayFileSpec
GOSUB DisplayCurrentPath

' main input loop
X$ = "*.*"
LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
PRINT SPACE$(12);
LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
PRINT X$;
DO
   LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
   PRINT SPACE$(12);
   LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
   PRINT X$;
   DO
      I$ = ""
      DO
         I$ = INKEY$
         IF LEN(I$) THEN
            EXIT DO
         END IF
      LOOP
      IF I$ = ":" OR I$ = "\" OR I$ = "/" THEN
         I$ = ""
      END IF
      IF LEN(I$) = 2 THEN
         SELECT CASE ASC(RIGHT$(I$, 1))
         ' F1 changes drive letter.
         CASE 59
            I$ = ""
            LOCATE 2 + Xcoor - 1, Ycoor + 2, 1
            PRINT SPACE$(28);
            LOCATE 2 + Xcoor - 1, Ycoor + 2, 1
            COLOR Yellow, Black
            PRINT "Drive letter: ";
            DO
               Z$ = INKEY$
               IF LEN(Z$) = 1 THEN
                  EXIT DO
               END IF
            LOOP
            Z$ = UCASE$(Z$)
            IF Z$ >= "A" AND Z$ <= "Z" THEN
               PRINT Z$;
               ' check drive disk space.
               Check.Disk = True
               Disk.Ready = False
               InregsX.AX = &H3600
               InregsX.DX = ASC(Z$) - 64
               CALL InterruptX(&H21, InregsX, OutregsX)
               Check.Disk = False
               IF Disk.Ready = True THEN
                  GOSUB PromptDisk
               ELSE
                  IF OutregsX.AX = &HFFFF THEN
                     GOSUB PromptDisk
                  ELSE
                     C$ = Z$
                     D$ = ""
                     GOSUB DisplayFilename
                     GOTO StartMenu
                  END IF
               END IF
            END IF
         ' F2 toggles heap sorting.
         CASE 60
            I$ = ""
            HeapSortOff = NOT HeapSortOff
            LOCATE 2 + Xcoor - 1, Ycoor + 2, 1
            PRINT SPACE$(12);
            LOCATE 2 + Xcoor - 1, Ycoor + 2, 1
            COLOR White, Black
            IF HeapSortOff THEN
               PRINT "Sorting Off. Press <esc>:";
            ELSE
               PRINT "Sorting On. Press <esc>:";
            END IF
            WHILE INKEY$<>CHR$(27)
            WEND
            GOSUB DisplayFilename
            COLOR Plain, Black
            PRINT X$;
         END SELECT
         I$ = ""
      END IF
      ' Tab moves to file loop, or
      '   directory loop if there are no files.
      IF I$ = CHR$(9) THEN
         IF Num.Files > 0 THEN
            GOSUB FileInputLoop
         ELSE
            GOSUB DirInputLoop
            IF I$ = CHR$(13) THEN
               I$ = ""
               Current.Dir = 1
               Dir.Box.Line = 1
               GOSUB ClearDirBox
               GOSUB LoadDirSpec
               GOSUB DisplayDirSpec
               GOSUB DisplayCurrentDir
            END IF
            GOSUB DisplayCurrentPath
         END IF
         EXIT DO
      END IF
      IF I$ = CHR$(13) THEN
         I$ = ""
         EXIT DO
      END IF
      IF I$ = CHR$(27) THEN
         EXIT DO
      END IF
      IF I$ = CHR$(8) THEN
         IF LEN(X$) > 0 THEN
            X$ = LEFT$(X$, LEN(X$) - 1)
            LOCATE CSRLIN, POS(0) - 1, 1
            PRINT " ";
            LOCATE CSRLIN, POS(0) - 1, 1
         END IF
      ELSE
         I$ = LTRIM$(I$)
         I$ = RTRIM$(I$)
         I$ = UCASE$(I$)
         IF LEN(X$) < 12 THEN
            PRINT I$;
            X$ = X$ + I$
         END IF
      END IF
   LOOP
   IF I$ = CHR$(27) THEN
      E$ = ""
      EXIT DO
   END IF
   IF I$ = CHR$(13) THEN
      EXIT DO
   END IF
   IF D$ = "" THEN
      F$ = C$ + ":\" + X$
   ELSE
      F$ = C$ + ":\" + D$ + "\" + X$
   END IF
   GOSUB ClearFileBox
   GOSUB LoadFileSpec
   GOSUB DisplayFileSpec
LOOP
COLOR Plain, Black
CLS
EXIT SUB

PromptDisk:
 LOCATE 2 + Xcoor - 1, Ycoor + 2, 1
 PRINT SPACE$(12);
 LOCATE 2 + Xcoor - 1, Ycoor + 2, 1
 COLOR White, Black
 PRINT "Disk not ready. Press <esc>:";
 WHILE INKEY$<>CHR$(27)
 WEND
 GOSUB DisplayFilename
 COLOR Plain, Black
 PRINT X$;
 RETURN

DisplayFilename:
 LOCATE 2 + Xcoor - 1, Ycoor + 2, 1
 PRINT SPACE$(28);
 LOCATE 2 + Xcoor - 1, Ycoor + 2, 1
 COLOR White, Black
 PRINT "Filename: ";
 COLOR Plain, Black
 RETURN

FileInputLoop:
 E$ = Filenames(1)
 E$ = RTRIM$(E$)
 COLOR Plain, Black
 LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
 PRINT SPACE$(12);
 LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
 PRINT LEFT$(E$, 12);
 COLOR Black, Plain
 LOCATE 6 + Xcoor - 1, 4 + Ycoor - 1, 1
 PRINT LEFT$(E$, 12);
 COLOR Plain, Black
 GOSUB DisplayLongName2
 Current.File = 1
 Box.Line = 1
 E$ = RTRIM$(Filenames(1))
 I$ = ""
 DO
    DO
       I$ = INKEY$
       IF LEN(I$) THEN
          EXIT DO
       END IF
    LOOP
    ' shift-tab returns to top
    IF LEN(I$) = 2 THEN
       IF ASC(RIGHT$(I$, 1)) = 15 THEN
          I$ = ""
          RETURN
       END IF
    END IF
    ' Tab moves to directory loop
    IF I$ = CHR$(9) THEN
       GOSUB DirInputLoop
       IF I$ = CHR$(9) THEN
          GOSUB DisplayCurrentPath
          RETURN
       END IF
       IF I$ = CHR$(13) THEN
          I$ = ""
          Current.Dir = 1
          Dir.Box.Line = 1
          GOSUB ClearDirBox
          GOSUB LoadDirSpec
          GOSUB DisplayDirSpec
          GOSUB DisplayCurrentDir
          GOSUB DisplayCurrentPath
          RETURN
       END IF
    END IF
    IF I$ = CHR$(13) THEN
       RETURN
    END IF
    IF I$ = CHR$(27) THEN
       RETURN
    END IF
    IF LEN(I$) = 1 THEN
       SELECT CASE I$
       CASE "A" TO "Z", "a" TO "z", "0" TO "9"
       DO
          IF Current.File + 1 <= Num.Files THEN
             IF Box.Line < 10 THEN
                LOCATE Box.Line + 5 + Xcoor - 1, 4 + Ycoor - 1, 1
                COLOR Plain, Black
                PRINT LEFT$(RTRIM$(Filenames(Current.File)), 12);
                Box.Line = Box.Line + 1
                Current.File = Current.File + 1
                E$ = RTRIM$(Filenames(Current.File))
                COLOR Plain, Black
                LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                PRINT SPACE$(12);
                LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                PRINT LEFT$(E$, 12);
                LOCATE Box.Line + 5 + Xcoor - 1, 4 + Ycoor - 1, 1
                COLOR Black, Plain
                PRINT LEFT$(E$, 12);
                COLOR Plain, Black
                GOSUB DisplayLongName2
             ELSE
                Current.File = Current.File + 1
                E$ = RTRIM$(Filenames(Current.File))
                COLOR Plain, Black
                LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                PRINT SPACE$(12);
                LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                PRINT LEFT$(E$, 12);
                GOSUB ClearFileBox
                COLOR Plain, Black
                FOR V = 1 TO 9
                   LOCATE 15 - V + Xcoor - 1, 4 + Ycoor - 1, 1
                   PRINT LEFT$(RTRIM$(Filenames(Current.File - V)), 12);
                NEXT
                COLOR Black, Plain
                LOCATE 15 + Xcoor - 1, 4 + Ycoor - 1, 1
                PRINT LEFT$(RTRIM$(Filenames(Current.File)), 12);
                GOSUB DisplayLongName2
             END IF
             IF LEFT$(E$, 1) = I$ THEN
                EXIT DO
             END IF
          ELSE
             EXIT DO
          END IF
       LOOP
       END SELECT
       I$ = ""
    END IF
    IF LEN(I$) = 2 THEN
       V = ASC(RIGHT$(I$, 1))
       SELECT CASE V
       CASE 72 ' up
          IF Current.File - 1 > 0 THEN
             IF Box.Line > 1 THEN
                LOCATE Box.Line + 5 + Xcoor - 1, 4 + Ycoor - 1, 1
                COLOR Plain, Black
                PRINT LEFT$(RTRIM$(Filenames(Current.File)), 12);
                Box.Line = Box.Line - 1
                Current.File = Current.File - 1
                E$ = RTRIM$(Filenames(Current.File))
                COLOR Plain, Black
                LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                PRINT SPACE$(12);
                LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                PRINT LEFT$(E$, 12);
                LOCATE Box.Line + 5 + Xcoor - 1, 4 + Ycoor - 1, 1
                COLOR Black, Plain
                PRINT LEFT$(E$, 12);
                COLOR Plain, Black
                GOSUB DisplayLongName2
             ELSE
                Current.File = Current.File - 1
                E$ = RTRIM$(Filenames(Current.File))
                COLOR Plain, Black
                LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                PRINT SPACE$(12);
                LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                PRINT LEFT$(E$, 12);
                GOSUB ClearFileBox
                COLOR Plain, Black
                FOR V = 1 TO 9
                   IF Current.File + V <= Num.Files THEN
                      LOCATE 6 + V + Xcoor - 1, 4 + Ycoor - 1, 1
                      PRINT LEFT$(RTRIM$(Filenames(Current.File + V)), 12);
                   END IF
                NEXT
                COLOR Black, Plain
                LOCATE 6 + Xcoor - 1, 4 + Ycoor - 1, 1
                PRINT LEFT$(RTRIM$(Filenames(Current.File)), 12);
                GOSUB DisplayLongName2
             END IF
          END IF
       CASE 80 ' down
          IF Current.File + 1 <= Num.Files THEN
             IF Box.Line < 10 THEN
                LOCATE Box.Line + 5 + Xcoor - 1, 4 + Ycoor - 1, 1
                COLOR Plain, Black
                PRINT LEFT$(RTRIM$(Filenames(Current.File)), 12);
                Box.Line = Box.Line + 1
                Current.File = Current.File + 1
                E$ = RTRIM$(Filenames(Current.File))
                COLOR Plain, Black
                LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                PRINT SPACE$(12);
                LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                PRINT LEFT$(E$, 12);
                LOCATE Box.Line + 5 + Xcoor - 1, 4 + Ycoor - 1, 1
                COLOR Black, Plain
                PRINT LEFT$(E$, 12);
                COLOR Plain, Black
                GOSUB DisplayLongName2
             ELSE
                Current.File = Current.File + 1
                E$ = RTRIM$(Filenames(Current.File))
                COLOR Plain, Black
                LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                PRINT SPACE$(12);
                LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                PRINT LEFT$(E$, 12);
                GOSUB ClearFileBox
                COLOR Plain, Black
                FOR V = 1 TO 9
                   LOCATE 15 - V + Xcoor - 1, 4 + Ycoor - 1, 1
                   PRINT LEFT$(RTRIM$(Filenames(Current.File - V)), 12);
                NEXT
                COLOR Black, Plain
                LOCATE 15 + Xcoor - 1, 4 + Ycoor - 1, 1
                PRINT LEFT$(RTRIM$(Filenames(Current.File)), 12);
                GOSUB DisplayLongName2
             END IF
          END IF
       CASE 73 ' pgup
          IF Current.File - 10 > 0 THEN
             Box.Line = 1
             Current.File = Current.File - 10
          ELSE
             Box.Line = 1
             Current.File = 1
          END IF
          E$ = RTRIM$(Filenames(Current.File))
          COLOR Plain, Black
          LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
          PRINT SPACE$(12);
          LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
          PRINT LEFT$(E$, 12);
          GOSUB ClearFileBox
          COLOR Plain, Black
          FOR V = 1 TO 9
             IF Current.File + V <= Num.Files THEN
                LOCATE 6 + V + Xcoor - 1, 4 + Ycoor - 1, 1
                PRINT LEFT$(RTRIM$(Filenames(Current.File + V)), 12);
             END IF
          NEXT
          COLOR Black, Plain
          LOCATE 6 + Xcoor - 1, 4 + Ycoor - 1, 1
          PRINT LEFT$(RTRIM$(Filenames(Current.File)), 12);
          GOSUB DisplayLongName2
       CASE 81 ' pgdn
          IF Current.File + 10 <= Num.Files THEN
             Box.Line = 10
             Current.File = Current.File + 10
             E$ = RTRIM$(Filenames(Current.File))
             COLOR Plain, Black
             LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
             PRINT SPACE$(12);
             LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
             PRINT LEFT$(E$, 12);
             GOSUB ClearFileBox
             COLOR Plain, Black
             FOR V = 1 TO 9
                LOCATE 15 - V + Xcoor - 1, 4 + Ycoor - 1, 1
                PRINT LEFT$(RTRIM$(Filenames(Current.File - V)), 12);
             NEXT
             COLOR Black, Plain
             LOCATE 15 + Xcoor - 1, 4 + Ycoor - 1, 1
             PRINT LEFT$(RTRIM$(Filenames(Current.File)), 12);
             GOSUB DisplayLongName2
          ELSE
             IF Current.File + 1 <= Num.Files THEN
                DO UNTIL Current.File = Num.Files
                   IF Box.Line < 10 THEN
                      LOCATE Box.Line + 5 + Xcoor - 1, 4 + Ycoor - 1, 1
                      COLOR Plain, Black
                      PRINT LEFT$(RTRIM$(Filenames(Current.File)), 12);
                      Box.Line = Box.Line + 1
                      Current.File = Current.File + 1
                      E$ = RTRIM$(Filenames(Current.File))
                      COLOR Plain, Black
                      LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                      PRINT SPACE$(12);
                      LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                      PRINT LEFT$(E$, 12);
                      LOCATE Box.Line + 5 + Xcoor - 1, 4 + Ycoor - 1, 1
                      COLOR Black, Plain
                      PRINT LEFT$(E$, 12);
                      COLOR Plain, Black
                      GOSUB DisplayLongName2
                   ELSE
                      Current.File = Current.File + 1
                      E$ = RTRIM$(Filenames(Current.File))
                      COLOR Plain, Black
                      LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                      PRINT SPACE$(12);
                      LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                      PRINT LEFT$(E$, 12);
                      GOSUB ClearFileBox
                      COLOR Plain, Black
                      FOR V = 1 TO 9
                         LOCATE 15 - V + Xcoor - 1, 4 + Ycoor - 1, 1
                         PRINT LEFT$(RTRIM$(Filenames(Current.File - V)), 12);
                      NEXT
                      COLOR Black, Plain
                      LOCATE 15 + Xcoor - 1, 4 + Ycoor - 1, 1
                      PRINT LEFT$(RTRIM$(Filenames(Current.File)), 12);
                      GOSUB DisplayLongName2
                   END IF
                LOOP
             END IF
          END IF
       CASE 71 ' home
          IF Current.File > 1 THEN
             Box.Line = 1
             Current.File = 1
          END IF
          E$ = RTRIM$(Filenames(Current.File))
          COLOR Plain, Black
          LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
          PRINT SPACE$(12);
          LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
          PRINT LEFT$(E$, 12);
          GOSUB ClearFileBox
          COLOR Plain, Black
          FOR V = 1 TO 9
             IF Current.File + V <= Num.Files THEN
                LOCATE 6 + V + Xcoor - 1, 4 + Ycoor - 1, 1
                PRINT LEFT$(RTRIM$(Filenames(Current.File + V)), 12);
             END IF
          NEXT
          COLOR Black, Plain
          LOCATE 6 + Xcoor - 1, 4 + Ycoor - 1, 1
          PRINT LEFT$(RTRIM$(Filenames(Current.File)), 12);
          GOSUB DisplayLongName2
       CASE 79 ' end
          IF Current.File + 1 <= Num.Files THEN
             DO UNTIL Current.File = Num.Files
                IF Box.Line < 10 THEN
                   LOCATE Box.Line + 5 + Xcoor - 1, 4 + Ycoor - 1, 1
                   COLOR Plain, Black
                   PRINT LEFT$(RTRIM$(Filenames(Current.File)), 12);
                   Box.Line = Box.Line + 1
                   Current.File = Current.File + 1
                   E$ = RTRIM$(Filenames(Current.File))
                   COLOR Plain, Black
                   LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                   PRINT SPACE$(12);
                   LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                   PRINT LEFT$(E$, 12);
                   LOCATE Box.Line + 5 + Xcoor - 1, 4 + Ycoor - 1, 1
                   COLOR Black, Plain
                   PRINT LEFT$(E$, 12);
                   COLOR Plain, Black
                   GOSUB DisplayLongName2
                ELSE
                   Current.File = Current.File + 1
                   E$ = RTRIM$(Filenames(Current.File))
                   COLOR Plain, Black
                   LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                   PRINT SPACE$(12);
                   LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
                   PRINT LEFT$(E$, 12);
                   GOSUB ClearFileBox
                   COLOR Plain, Black
                   FOR V = 1 TO 9
                      LOCATE 15 - V + Xcoor - 1, 4 + Ycoor - 1, 1
                      PRINT LEFT$(RTRIM$(Filenames(Current.File - V)), 12);
                   NEXT
                   COLOR Black, Plain
                   LOCATE 15 + Xcoor - 1, 4 + Ycoor - 1, 1
                   PRINT LEFT$(RTRIM$(Filenames(Current.File)), 12);
                   GOSUB DisplayLongName2
                END IF
             LOOP
          END IF
       END SELECT
    END IF
 LOOP
 RETURN

DirInputLoop:
 GOSUB ClearLongName2
 Q$ = RTRIM$(Directories(Current.Dir))
 LOCATE Dir.Box.Line + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
 COLOR Black, Plain
 PRINT LEFT$(Q$, 12);
 COLOR Plain, Black
 GOSUB DisplayLongName1
 I$ = ""
 DO
    DO
       I$ = INKEY$
       IF LEN(I$) THEN
          EXIT DO
       END IF
    LOOP
    ' shift-tab returns to file loop
    IF LEN(I$) = 2 THEN
       IF ASC(RIGHT$(I$, 1)) = 15 THEN
          I$ = ""
          LOCATE Dir.Box.Line + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
          COLOR Plain, Black
          PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
          ' returns if no files.
          IF Num.Files = 0 THEN
             GOSUB ClearLongName2
             RETURN
          END IF
          ' display current filename.
          GOSUB DisplayLongName2
          E$ = Filenames(Current.File)
          E$ = RTRIM$(E$)
          COLOR Plain, Black
          LOCATE Box.Line + 5 + Xcoor - 1, 4 + Ycoor - 1, 1
          PRINT SPACE$(12);
          COLOR Black, Plain
          LOCATE Box.Line + 5 + Xcoor - 1, 4 + Ycoor - 1, 1
          PRINT LEFT$(E$, 12);
          COLOR Plain, Black
          RETURN
       END IF
    END IF
    ' Tab returns to top loop
    IF I$ = CHR$(9) THEN
       LOCATE Dir.Box.Line + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
       COLOR Plain, Black
       PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
       RETURN
    END IF
    IF I$ = CHR$(13) THEN
       ' check the path type
       SELECT CASE Q$
       CASE "." ' self
          ' nul
       CASE ".." ' parent
          IF INSTR(D$, "\") = 0 THEN
             D$ = ""
          ELSE
             FOR V = LEN(D$) TO 1 STEP -1
                IF MID$(D$, V, 1) = "\" THEN
                   D$ = LEFT$(D$, V - 1)
                   EXIT FOR
                END IF
             NEXT
          END IF
       CASE ELSE ' imbedded path
          IF D$ = "" THEN
             D$ = Q$
          ELSE
             D$ = D$ + "\" + Q$
          END IF
       END SELECT
       RETURN
    END IF
    IF I$ = CHR$(27) THEN
       RETURN
    END IF
    IF LEN(I$) = 1 THEN
       SELECT CASE I$
       CASE "A" TO "Z", "a" TO "z", "0" TO "9"
       DO
          IF Current.Dir + 1 <= Num.Dirs THEN
             IF Dir.Box.Line < 10 THEN
                LOCATE Dir.Box.Line + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
                COLOR Plain, Black
                PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                Dir.Box.Line = Dir.Box.Line + 1
                Current.Dir = Current.Dir + 1
                LOCATE Dir.Box.Line + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
                COLOR Black, Plain
                PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                COLOR Plain, Black
             ELSE
                GOSUB ClearDirBox
                Current.Dir = Current.Dir + 1
                COLOR Plain, Black
                FOR V = 1 TO 9
                   LOCATE 15 - V + Xcoor - 1, 21 + Ycoor - 1, 1
                   PRINT LEFT$(RTRIM$(Directories(Current.Dir - V)), 12);
                NEXT
                COLOR Black, Plain
                LOCATE 15 + Xcoor - 1, 21 + Ycoor - 1, 1
                PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                COLOR Plain, Black
             END IF
             Q$ = RTRIM$(Directories(Current.Dir))
             GOSUB DisplayLongName1
             IF LEFT$(Q$, 1) = I$ THEN
                EXIT DO
             END IF
          ELSE
             EXIT DO
          END IF
       LOOP
       END SELECT
       I$ = ""
    END IF
    IF LEN(I$) = 2 THEN
       V = ASC(RIGHT$(I$, 1))
       SELECT CASE V
       CASE 72 ' up
          IF Current.Dir - 1 > 0 THEN
             IF Dir.Box.Line > 1 THEN
                LOCATE Dir.Box.Line + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
                COLOR Plain, Black
                PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                Dir.Box.Line = Dir.Box.Line - 1
                Current.Dir = Current.Dir - 1
                LOCATE Dir.Box.Line + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
                COLOR Black, Plain
                PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                COLOR Plain, Black
             ELSE
                GOSUB ClearDirBox
                Current.Dir = Current.Dir - 1
                COLOR Plain, Black
                FOR V = 1 TO 9
                   IF Current.Dir + V <= Num.Dirs THEN
                      LOCATE 6 + V + Xcoor - 1, 21 + Ycoor - 1, 1
                      PRINT LEFT$(RTRIM$(Directories(Current.Dir + V)), 12);
                   END IF
                NEXT
                COLOR Black, Plain
                LOCATE 6 + Xcoor - 1, 21 + Ycoor - 1, 1
                PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                COLOR Plain, Black
             END IF
             Q$ = RTRIM$(Directories(Current.Dir))
             GOSUB DisplayLongName1
          END IF
       CASE 80 ' down
          IF Current.Dir + 1 <= Num.Dirs THEN
             IF Dir.Box.Line < 10 THEN
                LOCATE Dir.Box.Line + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
                COLOR Plain, Black
                PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                Dir.Box.Line = Dir.Box.Line + 1
                Current.Dir = Current.Dir + 1
                LOCATE Dir.Box.Line + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
                COLOR Black, Plain
                PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                COLOR Plain, Black
             ELSE
                GOSUB ClearDirBox
                Current.Dir = Current.Dir + 1
                COLOR Plain, Black
                FOR V = 1 TO 9
                   LOCATE 15 - V + Xcoor - 1, 21 + Ycoor - 1, 1
                   PRINT LEFT$(RTRIM$(Directories(Current.Dir - V)), 12);
                NEXT
                COLOR Black, Plain
                LOCATE 15 + Xcoor - 1, 21 + Ycoor - 1, 1
                PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                COLOR Plain, Black
             END IF
             Q$ = RTRIM$(Directories(Current.Dir))
             GOSUB DisplayLongName1
          END IF
       CASE 73 ' pgup
          IF Current.Dir - 10 > 0 THEN
             Dir.Box.Line = 1
             Current.Dir = Current.Dir - 10
          ELSE
             Dir.Box.Line = 1
             Current.Dir = 1
          END IF
          GOSUB ClearDirBox
          COLOR Plain, Black
          FOR V = 1 TO 9
             IF Current.Dir + V <= Num.Dirs THEN
                LOCATE 6 + V + Xcoor - 1, 21 + Ycoor - 1, 1
                PRINT LEFT$(RTRIM$(Directories(Current.Dir + V)), 12);
             END IF
          NEXT
          COLOR Black, Plain
          LOCATE 6 + Xcoor - 1, 21 + Ycoor - 1, 1
          PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
          COLOR Plain, Black
          Q$ = RTRIM$(Directories(Current.Dir))
          GOSUB DisplayLongName1
       CASE 81 ' pgdn
          IF Current.Dir + 10 <= Num.Dirs THEN
             GOSUB ClearDirBox
             Dir.Box.Line = 10
             Current.Dir = Current.Dir + 10
             COLOR Plain, Black
             FOR V = 1 TO 9
                LOCATE 15 - V + Xcoor - 1, 21 + Ycoor - 1, 1
                PRINT LEFT$(RTRIM$(Directories(Current.Dir - V)), 12);
             NEXT
             COLOR Black, Plain
             LOCATE 15 + Xcoor - 1, 21 + Ycoor - 1, 1
             PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
             COLOR Plain, Black
             Q$ = RTRIM$(Directories(Current.Dir))
             GOSUB DisplayLongName1
          ELSE
             IF Current.Dir + 1 <= Num.Dirs THEN
                DO UNTIL Current.Dir = Num.Dirs
                   IF Dir.Box.Line < 10 THEN
                      LOCATE Dir.Box.Line + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
                      COLOR Plain, Black
                      PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                      Dir.Box.Line = Dir.Box.Line + 1
                      Current.Dir = Current.Dir + 1
                      LOCATE Dir.Box.Line + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
                      COLOR Black, Plain
                      PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                      COLOR Plain, Black
                   ELSE
                      GOSUB ClearDirBox
                      Current.Dir = Current.Dir + 1
                      COLOR Plain, Black
                      FOR V = 1 TO 9
                         LOCATE 15 - V + Xcoor - 1, 21 + Ycoor - 1, 1
                         PRINT LEFT$(RTRIM$(Directories(Current.Dir - V)), 12);
                      NEXT
                      COLOR Black, Plain
                      LOCATE 15 + Xcoor - 1, 21 + Ycoor - 1, 1
                      PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                      COLOR Plain, Black
                   END IF
                LOOP
                Q$ = RTRIM$(Directories(Current.Dir))
                GOSUB DisplayLongName1
             END IF
          END IF
       CASE 71 ' home
          IF Current.Dir > 1 THEN
             Dir.Box.Line = 1
             Current.Dir = 1
          END IF
          GOSUB ClearDirBox
          COLOR Plain, Black
          FOR V = 1 TO 9
             IF Current.Dir + V <= Num.Dirs THEN
                LOCATE 6 + V + Xcoor - 1, 21 + Ycoor - 1, 1
                PRINT LEFT$(RTRIM$(Directories(Current.Dir + V)), 12);
             END IF
          NEXT
          COLOR Black, Plain
          LOCATE 6 + Xcoor - 1, 21 + Ycoor - 1, 1
          PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
          COLOR Plain, Black
          Q$ = RTRIM$(Directories(Current.Dir))
          GOSUB DisplayLongName1
       CASE 79 ' end
          IF Current.Dir + 1 <= Num.Dirs THEN
             DO UNTIL Current.Dir = Num.Dirs
                IF Dir.Box.Line < 10 THEN
                   LOCATE Dir.Box.Line + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
                   COLOR Plain, Black
                   PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                   Dir.Box.Line = Dir.Box.Line + 1
                   Current.Dir = Current.Dir + 1
                   LOCATE Dir.Box.Line + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
                   COLOR Black, Plain
                   PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                   COLOR Plain, Black
                ELSE
                   GOSUB ClearDirBox
                   Current.Dir = Current.Dir + 1
                   COLOR Plain, Black
                   FOR V = 1 TO 9
                      LOCATE 15 - V + Xcoor - 1, 21 + Ycoor - 1, 1
                      PRINT LEFT$(RTRIM$(Directories(Current.Dir - V)), 12);
                   NEXT
                   COLOR Black, Plain
                   LOCATE 15 + Xcoor - 1, 21 + Ycoor - 1, 1
                   PRINT LEFT$(RTRIM$(Directories(Current.Dir)), 12);
                   COLOR Plain, Black
                END IF
             LOOP
             Q$ = RTRIM$(Directories(Current.Dir))
             GOSUB DisplayLongName1
          END IF
       END SELECT
    END IF
 LOOP
 RETURN

MainMenu:
' define screen offsets,
' allows menu centering.
Xcoor = 5
Ycoor = 20
' draw menu
COLOR , 1
CLS
LOCATE Xcoor, Ycoor
COLOR , 0
COLOR Yellow
PRINT CHR$(ULcorner) + STRING$(33, Hline) + CHR$(URcorner)
LOCATE Xcoor + 1, Ycoor
PRINT CHR$(Vline) + " ";
COLOR White
PRINT "Filename:";
COLOR Yellow
PRINT "                       " + CHR$(Vline)
LOCATE Xcoor + 2, Ycoor
PRINT CHR$(Vline) + "                                 " + CHR$(Vline)
LOCATE Xcoor + 3, Ycoor
PRINT CHR$(Vline) + " ";
COLOR White
PRINT "Files:           Directories:   ";
COLOR Yellow
PRINT CHR$(Vline)
LOCATE Xcoor + 4, Ycoor
PRINT CHR$(Vline);
COLOR Magenta
PRINT " " + CHR$(ULcorner) + STRING$(12, Hline) + CHR$(URcorner);
COLOR White
PRINT "F1=";
COLOR Magenta
PRINT CHR$(ULcorner) + STRING$(12, Hline) + CHR$(URcorner) + " ";
COLOR Yellow
PRINT CHR$(Vline)
COLOR Yellow
LOCATE Xcoor + 5, Ycoor
PRINT CHR$(Vline);
COLOR Magenta
PRINT " " + CHR$(Vline) + SPACE$(12) + CHR$(Vline);
COLOR White
PRINT "<c>";
COLOR Magenta
PRINT CHR$(Vline) + SPACE$(12) + CHR$(Vline) + " ";
COLOR Yellow
PRINT CHR$(Vline)
COLOR Yellow
LOCATE Xcoor + 6, Ycoor
PRINT CHR$(Vline);
COLOR Magenta
PRINT " " + CHR$(Vline) + SPACE$(12) + CHR$(Vline) + "   " + CHR$(Vline) + SPACE$(12) + CHR$(Vline) + " ";
COLOR Yellow
PRINT CHR$(Vline)
COLOR Yellow
LOCATE Xcoor + 7, Ycoor
PRINT CHR$(Vline);
COLOR Magenta
PRINT " " + CHR$(Vline) + SPACE$(12) + CHR$(Vline);
COLOR White
PRINT "F2=";
COLOR Magenta
PRINT CHR$(Vline) + SPACE$(12) + CHR$(Vline) + " ";
COLOR Yellow
PRINT CHR$(Vline)
COLOR Yellow
LOCATE Xcoor + 8, Ycoor
PRINT CHR$(Vline);
COLOR Magenta
PRINT " " + CHR$(Vline) + SPACE$(12) + CHR$(Vline);
COLOR White
PRINT "<s>";
COLOR Magenta
PRINT CHR$(Vline) + SPACE$(12) + CHR$(Vline) + " ";
COLOR Yellow
PRINT CHR$(Vline)
COLOR Yellow
LOCATE Xcoor + 9, Ycoor
PRINT CHR$(Vline);
COLOR Magenta
PRINT " " + CHR$(Vline) + SPACE$(12) + CHR$(Vline) + "   " + CHR$(Vline) + SPACE$(12) + CHR$(Vline) + " ";
COLOR Yellow
PRINT CHR$(Vline)
COLOR Yellow
LOCATE Xcoor + 10, Ycoor
PRINT CHR$(Vline);
COLOR Magenta
PRINT " " + CHR$(Vline) + SPACE$(12) + CHR$(Vline) + "   " + CHR$(Vline) + SPACE$(12) + CHR$(Vline) + " ";
COLOR Yellow
PRINT CHR$(Vline)
COLOR Yellow
LOCATE Xcoor + 11, Ycoor
PRINT CHR$(Vline);
COLOR Magenta
PRINT " " + CHR$(Vline) + SPACE$(12) + CHR$(Vline) + "   " + CHR$(Vline) + SPACE$(12) + CHR$(Vline) + " ";
COLOR Yellow
PRINT CHR$(Vline)
COLOR Yellow
LOCATE Xcoor + 12, Ycoor
PRINT CHR$(Vline);
COLOR Magenta
PRINT " " + CHR$(Vline) + SPACE$(12) + CHR$(Vline) + "   " + CHR$(Vline) + SPACE$(12) + CHR$(Vline) + " ";
COLOR Yellow
PRINT CHR$(Vline)
COLOR Yellow
LOCATE Xcoor + 13, Ycoor
PRINT CHR$(Vline);
COLOR Magenta
PRINT " " + CHR$(Vline) + SPACE$(12) + CHR$(Vline) + "   " + CHR$(Vline) + SPACE$(12) + CHR$(Vline) + " ";
COLOR Yellow
PRINT CHR$(Vline)
COLOR Yellow
LOCATE Xcoor + 14, Ycoor
PRINT CHR$(Vline);
COLOR Magenta
PRINT " " + CHR$(Vline) + SPACE$(12) + CHR$(Vline) + "   " + CHR$(Vline) + SPACE$(12) + CHR$(Vline) + " ";
COLOR Yellow
PRINT CHR$(Vline)
COLOR Yellow
LOCATE Xcoor + 15, Ycoor
PRINT CHR$(Vline);
COLOR Magenta
PRINT " " + CHR$(LLcorner) + STRING$(12, Hline) + CHR$(LRcorner) + "   ";
PRINT CHR$(LLcorner) + STRING$(12, Hline) + CHR$(LRcorner) + " ";
COLOR Yellow
PRINT CHR$(Vline)
LOCATE Xcoor + 16, Ycoor
PRINT CHR$(LLcorner) + STRING$(33, Hline) + CHR$(LRcorner)
IF Xcoor - 1 > 0 THEN
   COLOR Green, Blue
   LOCATE Xcoor - 1, Ycoor
   PRINT "Hexedit v3.6a for Windows/DOS 2003.";
END IF
IF Xcoor + 17 <= 24 THEN
   COLOR Green, Blue
   LOCATE Xcoor + 17, Ycoor
   PRINT "Path:";
END IF
IF Xcoor + 18 <= 24 THEN
   COLOR Green, Blue
   LOCATE Xcoor + 18, Ycoor
   PRINT "File:";
END IF
IF Xcoor + 19 <= 24 THEN
   COLOR Green, Blue
   LOCATE Xcoor + 19, Ycoor
   PRINT "Size:";
END IF
COLOR Plain, Black
RETURN

' display path
DisplayCurrentPath:
 Q$ = D$
 FOR Var = LEN(Q$) TO 1 STEP -1
    IF MID$(Q$, Var, 1) = "\" THEN
       Q$ = MID$(Q$, Var + 1)
       EXIT FOR
    END IF
 NEXT
 IF Q$ = "" THEN
    Q$ = "\"
 END IF
 GOSUB DisplayLongName1
 RETURN

' display long directory
DisplayLongName1:
 COLOR Green, Blue
 IF Xcoor + 17 <= 24 THEN
    Length = 80 - Ycoor - 1
    LOCATE Xcoor + 17, Ycoor
    PRINT SPACE$(Length);
    LOCATE Xcoor + 17, Ycoor
    P$ = "Path: " + Q$
    IF LEN(P$) > Length THEN
       P$ = LEFT$(P$, Length - 3) + "..."
    END IF
    PRINT P$;
 END IF
 COLOR Plain, Black
 RETURN

' display long filename
DisplayLongName2:
 COLOR Green, Blue
 IF Xcoor + 18 <= 24 THEN
    Length = 80 - Ycoor - 1
    LOCATE Xcoor + 18, Ycoor
    PRINT SPACE$(Length);
    LOCATE Xcoor + 18, Ycoor
    P$ = "File: " + E$
    IF LEN(P$) > Length THEN
       P$ = LEFT$(P$, Length - 3) + "..."
    END IF
    PRINT P$;
 END IF
 COLOR Plain, Black
 GOSUB DisplayFilesize
 RETURN

' display filesize
DisplayFilesize:
 GOSUB GetFilesize
 COLOR Green, Blue
 IF Xcoor + 19 <= 24 THEN
    Length = 80 - Ycoor - 1
    LOCATE Xcoor + 19, Ycoor
    PRINT SPACE$(Length);
    LOCATE Xcoor + 19, Ycoor
    P$ = "Size: " + Format$(Filesize, "#,##0;;0")
    PRINT P$;" ";
    GOSUB DisplayFileattr
 END IF
 COLOR Plain, Black
 RETURN

' get filesize
GetFilesize:
 ' reset filesize
 FileSize = False
 ' store dta
 GOSUB SetDTA
 ' store long filename
 IF D$ = "" THEN
    W$ = C$ + ":\" + E$
 ELSE
    W$ = C$ + ":\" + D$ + "\" + E$
 END IF
 ' store asciiz filename
 ASCIIZ3 = W$ + CHR$(0)
 ' check windows/get file info
 IF Windows.Detected THEN
    InregsX.AX = &H714E
    InregsX.CX = &H27
    InregsX.SI = &H1
    InregsX.DS = VARSEG(ASCIIZ3)
    InregsX.DX = VARPTR(ASCIIZ3)
    InregsX.ES = VARSEG(WDTAfile)
    InregsX.DI = VARPTR(WDTAfile)
    CALL InterruptX(&H21, InregsX, OutregsX)
    Wfile.Handle = OutregsX.AX
 ELSE
    InregsX.AX = &H4E00
    InregsX.CX = &H27
    InregsX.DS = VARSEG(ASCIIZ3)
    InregsX.DX = VARPTR(ASCIIZ3)
    CALL InterruptX(&H21, InregsX, OutregsX)
 END IF
 ' check findnext error
 IF (OutregsX.Flags AND &H1) = &H1 THEN
    RETURN
 END IF
 ' store filesize
 IF Windows.Detected THEN
    FileSize = ASC(MID$(WDTAfile.FileSizeHigh, 4, 1))
    FileSize = FileSize * &H100 + ASC(MID$(WDTAfile.FileSizeHigh, 3, 1))
    FileSize = FileSize * &H100 + ASC(MID$(WDTAfile.FileSizeHigh, 2, 1))
    FileSize = FileSize * &H100 + ASC(MID$(WDTAfile.FileSizeHigh, 1, 1))
    FileSize = FileSize * &H100 + ASC(MID$(WDTAfile.FileSizeLow, 4, 1))
    FileSize = FileSize * &H100 + ASC(MID$(WDTAfile.FileSizeLow, 3, 1))
    FileSize = FileSize * &H100 + ASC(MID$(WDTAfile.FileSizeLow, 2, 1))
    FileSize = FileSize * &H100 + ASC(MID$(WDTAfile.FileSizeLow, 1, 1))
 ELSE
    FileSize = ASC(MID$(DTAfile.FileSize, 4, 1))
    FileSize = FileSize * &H100 + ASC(MID$(DTAfile.FileSize, 3, 1))
    FileSize = FileSize * &H100 + ASC(MID$(DTAfile.FileSize, 2, 1))
    FileSize = FileSize * &H100 + ASC(MID$(DTAfile.FileSize, 1, 1))
 END IF
 ' store file attribute
 IF Windows.Detected THEN
    FileAttribute = ASC(WDTAfile.FileBits)
 ELSE
    FileAttribute = ASC(DTAfile.FileBits)
 END IF
 ' check windows dos
 IF Windows.Detected THEN
    ' close long filename search
    InregsX.AX = &H71A1
    InregsX.BX = Wfile.Handle
    CALL InterruptX(&H21, InregsX, OutregsX)
 END IF
 ' restore dta
 GOSUB ResetDTA
 RETURN

' display file attribute
DisplayFileattr:
 P$ = Nul
 IF (FileAttribute AND ReadOnlyBit) = ReadOnlyBit THEN
    P$ = P$ + "o"
 END IF
 IF (FileAttribute AND HiddenBit) = HiddenBit THEN
    P$ = P$ + "h"
 END IF
 IF (FileAttribute AND SystemBit) = SystemBit THEN
    P$ = P$ + "s"
 END IF
 IF (FileAttribute AND ArchiveBit) = ArchiveBit THEN
    P$ = P$ + "a"
 END IF
 IF LEN(P$) THEN
    PRINT "("; P$; ")";
 END IF
 RETURN

' clear long directory area
ClearLongName1:
 COLOR Green, Blue
 IF Xcoor + 17 <= 24 THEN
    Length = 80 - Ycoor - 1
    LOCATE Xcoor + 17, Ycoor
    PRINT SPACE$(Length);
    LOCATE Xcoor + 17, Ycoor
    PRINT "Path: ";
 END IF
 COLOR Plain, Black
 RETURN

' clear long filename area
ClearLongName2:
 COLOR Green, Blue
 IF Xcoor + 18 <= 24 THEN
    Length = 80 - Ycoor - 1
    LOCATE Xcoor + 18, Ycoor
    PRINT SPACE$(Length);
    LOCATE Xcoor + 18, Ycoor
    PRINT "File: ";
 END IF
 ' clear size area
 IF Xcoor + 19 <= 24 THEN
    Length = 80 - Ycoor - 1
    LOCATE Xcoor + 19, Ycoor
    PRINT SPACE$(Length);
    LOCATE Xcoor + 19, Ycoor
    PRINT "Size: ";
 END IF
 COLOR Plain, Black
 RETURN

' check windows dos
TestWindows:
 InregsX.AX = &H160A
 CALL InterruptX(&H2F, InregsX, OutregsX)
 IF OutregsX.AX = False THEN
    Temp = (OutregsX.BX AND &HFF00) / 256
    IF Temp >= 4 THEN
       Windows.Detected = True
    END IF
 END IF
 RETURN

' return current drive.
InitDrive:
 InregsX.AX = &H1900
 CALL InterruptX(&H21, InregsX, OutregsX)
 Drive.Number = OutregsX.AX AND &HFF
 C$ = CHR$(Drive.Number + 65)
 RETURN

' return current directory.
InitDir:
 ' 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
 D$ = LEFT$(ASCIIZ3, INSTR(ASCIIZ3, CHR$(0)) - 1)
 RETURN

' initialize directory/filename record.
OpenDataFiles:
 V1$ = "HEXEDIT1.DAT"
 V2$ = "HEXEDIT2.DAT"
 CALL OpenDataFiles(V1$, V2$)
 CLOSE #2, #3
 ' open data structure files.
 IF Windows.Detected THEN
    OPEN V1$ FOR RANDOM AS #2 LEN = LEN(WinFileStruc)
    OPEN V2$ FOR RANDOM AS #3 LEN = LEN(WinFileStruc)
 ELSE
    OPEN V1$ FOR RANDOM AS #2 LEN = LEN(DosFileStruc)
    OPEN V2$ FOR RANDOM AS #3 LEN = LEN(DosFileStruc)
 END IF
 RETURN

' load current subdirectories.
LoadDirSpec:
 Num.Dirs = 0
 GOSUB SetDTA
 ' find first directory
 IF D$ = "" THEN
    ASCIIZ3 = C$ + ":\*.*" + CHR$(0)
 ELSE
    IF D$ = "\" THEN
       ASCIIZ3 = C$ + ":\*.*" + CHR$(0)
    ELSE
       ASCIIZ3 = C$ + ":\" + D$ + "\*.*" + CHR$(0)
    END IF
 END IF
 IF Windows.Detected THEN
    InregsX.AX = &H714E
    InregsX.CX = &H37
    InregsX.SI = &H1
    InregsX.DS = VARSEG(ASCIIZ3)
    InregsX.DX = VARPTR(ASCIIZ3)
    InregsX.ES = VARSEG(WDTAfile)
    InregsX.DI = VARPTR(WDTAfile)
    CALL InterruptX(&H21, InregsX, OutregsX)
    Wfile.Handle = OutregsX.AX
 ELSE
    InregsX.AX = &H4E00
    InregsX.CX = &H37
    InregsX.DS = VARSEG(ASCIIZ3)
    InregsX.DX = VARPTR(ASCIIZ3)
    CALL InterruptX(&H21, InregsX, OutregsX)
 END IF
 ' store directories
 DO
    ' check for directory
    IF Windows.Detected THEN
       Attribute = ASC(WDTAfile.FileBits)
    ELSE
       Attribute = ASC(DTAfile.FileBits)
    END IF
    IF (Attribute AND &H10) = &H10 THEN
       ' store directory name
       IF Windows.Detected THEN
          E$ = WDTAfile.ASCIIZfull
       ELSE
          E$ = DTAfile.ASCIIZfilename
       END IF
       IF INSTR(E$, CHR$(0)) THEN
          E$ = LEFT$(E$, INSTR(E$, CHR$(0)) - 1)
       END IF
       IF Num.Dirs < 32767 THEN
          Num.Dirs = Num.Dirs + 1
          IF Windows.Detected THEN
             WinFileStruc.Name = E$
             PUT 3, Num.Dirs, WinFileStruc
          ELSE
             DosFileStruc.Name = E$
             PUT 3, Num.Dirs, DosFileStruc
          END IF
       END IF
    END IF
    ' find next directory
    IF Windows.Detected THEN
       ' find next long filename
       InregsX.AX = &H714F
       InregsX.BX = Wfile.Handle
       InregsX.SI = &H1
       InregsX.ES = VARSEG(WDTAfile)
       InregsX.DI = VARPTR(WDTAfile)
       CALL InterruptX(&H21, InregsX, OutregsX)
    ELSE
       ' find next directory
       InregsX.AX = &H4F00
       CALL InterruptX(&H21, InregsX, OutregsX)
    END IF
    ' check findnext error
    IF (OutregsX.Flags AND &H1) = &H1 THEN
       EXIT DO
    END IF
 LOOP
 ' check windows dos
 IF Windows.Detected THEN
    ' close long filename search
    InregsX.AX = &H71A1
    InregsX.BX = Wfile.Handle
    CALL InterruptX(&H21, InregsX, OutregsX)
 END IF
 IF Num.Dirs = 0 THEN
    IF Windows.Detected THEN
       WinFileStruc.Name = "."
       PUT 3, 1, WinFileStruc
    ELSE
       DosFileStruc.Name = "."
       PUT 3, 1, DosFileStruc
    END IF
    Num.Dirs = 1
 END IF
 GOSUB ResetDTA
 IF HeapSortOff THEN
    RETURN
 END IF
 IF Windows.Detected THEN
    GOSUB Win.Heap.Sort2
 ELSE
    GOSUB Dos.Heap.Sort2
 END IF
 RETURN

DisplayDirSpec:
 VarX = 0
 DO
    VarX = VarX + 1
    IF VarX > 10 THEN
       EXIT DO
    END IF
    IF VarX > Num.Dirs THEN
       EXIT DO
    END IF
    LOCATE VarX + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
    E$ = Directories(VarX)
    E$ = RTRIM$(E$)
    PRINT LEFT$(E$, 12);
 LOOP
 RETURN

ClearDirBox:
 FOR VarX = 1 TO 10
    LOCATE VarX + 5 + Xcoor - 1, 21 + Ycoor - 1, 1
    PRINT SPACE$(12);
 NEXT
 RETURN

DisplayCurrentDir:
 ' deconcatenate long path with \..\ characters
 Z$ = C$ + ":\" + D$
 DO
    IF LEN(Z$) > 32 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$) > 32 THEN
    Z$ = LEFT$(Z$, 32)
 END IF
 LOCATE 3 + Xcoor - 1, 3 + Ycoor - 1, 1
 PRINT SPACE$(32);
 LOCATE 3 + Xcoor - 1, 3 + Ycoor - 1, 1
 PRINT Z$;
 RETURN

' load specified files.
LoadFileSpec:
 Num.Files = 0
 GOSUB SetDTA
 ' find first file
 ASCIIZ3 = F$ + CHR$(0)
 IF Windows.Detected THEN
    InregsX.AX = &H714E
    InregsX.CX = &H27
    InregsX.SI = &H1
    InregsX.DS = VARSEG(ASCIIZ3)
    InregsX.DX = VARPTR(ASCIIZ3)
    InregsX.ES = VARSEG(WDTAfile)
    InregsX.DI = VARPTR(WDTAfile)
    CALL InterruptX(&H21, InregsX, OutregsX)
    Wfile.Handle = OutregsX.AX
 ELSE
    InregsX.AX = &H4E00
    InregsX.CX = &H27
    InregsX.DS = VARSEG(ASCIIZ3)
    InregsX.DX = VARPTR(ASCIIZ3)
    CALL InterruptX(&H21, InregsX, OutregsX)
 END IF
 ' store files
 DO
    ' check findnext error
    IF (OutregsX.Flags AND &H1) = &H1 THEN
       EXIT DO
    END IF
    ' check for file
    IF Windows.Detected THEN
       Attribute = ASC(WDTAfile.FileBits)
    ELSE
       Attribute = ASC(DTAfile.FileBits)
    END IF
    IF (Attribute AND &H10) <> &H10 THEN
       ' store directory name
       IF Windows.Detected THEN
          E$ = WDTAfile.ASCIIZfull
       ELSE
          E$ = DTAfile.ASCIIZfilename
       END IF
       IF INSTR(E$, CHR$(0)) THEN
          E$ = LEFT$(E$, INSTR(E$, CHR$(0)) - 1)
       END IF
       IF Num.Files < 32767 THEN
          Num.Files = Num.Files + 1
          IF Windows.Detected THEN
             WinFileStruc.Name = E$
             PUT 2, Num.Files, WinFileStruc
          ELSE
             DosFileStruc.Name = E$
             PUT 2, Num.Files, DosFileStruc
          END IF
       END IF
    END IF
    ' find next file
    IF Windows.Detected THEN
       ' find next long filename
       InregsX.AX = &H714F
       InregsX.BX = Wfile.Handle
       InregsX.SI = &H1
       InregsX.ES = VARSEG(WDTAfile)
       InregsX.DI = VARPTR(WDTAfile)
       CALL InterruptX(&H21, InregsX, OutregsX)
    ELSE
       ' find next directory
       InregsX.AX = &H4F00
       CALL InterruptX(&H21, InregsX, OutregsX)
    END IF
 LOOP
 ' check windows dos
 IF Windows.Detected THEN
    ' close long filename search
    InregsX.AX = &H71A1
    InregsX.BX = Wfile.Handle
    CALL InterruptX(&H21, InregsX, OutregsX)
 END IF
 GOSUB ResetDTA
 LOCATE Xcoor + 3, Ycoor + 9
 PRINT SPACE$(10);
 LOCATE Xcoor + 3, Ycoor + 9
 COLOR White
 PRINT "(" + MID$(STR$(Num.Files), 2) + ")";
 COLOR 7
 IF HeapSortOff THEN
    RETURN
 END IF
 COLOR White
 LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
 PRINT SPACE$(12);
 LOCATE 2 + Xcoor - 1, 13 + Ycoor - 1, 1
 PRINT "Sorting..";
 COLOR 7
 IF Windows.Detected THEN
    GOSUB Win.Heap.Sort1
 ELSE
    GOSUB Dos.Heap.Sort1
 END IF
 RETURN

DisplayFileSpec:
 VarX = 0
 DO
    VarX = VarX + 1
    IF VarX > 10 THEN
       EXIT DO
    END IF
    IF VarX > Num.Files THEN
       EXIT DO
    END IF
    LOCATE VarX + 5 + Xcoor - 1, 4 + Ycoor - 1, 1
    E$ = Filenames(VarX)
    E$ = RTRIM$(E$)
    PRINT LEFT$(E$, 12);
 LOOP
 RETURN

ClearFileBox:
 FOR VarX = 1 TO 10
    LOCATE VarX + 5 + Xcoor - 1, 4 + Ycoor - 1, 1
    PRINT SPACE$(12);
 NEXT
 RETURN

' assign program dta.
SetDTA:
 InregsX.AX = &H1A00
 InregsX.DS = VARSEG(DTAfile)
 InregsX.DX = VARPTR(DTAfile)
 CALL InterruptX(&H21, InregsX, OutregsX)
 RETURN

' restore basic dta.
ResetDTA:
 InregsX.AX = &H1A00
 InregsX.DS = BASIC.DTA.SEG
 InregsX.DX = BASIC.DTA.OFF
 CALL InterruptX(&H21, InregsX, OutregsX)
 RETURN

' sorts windows hexedit1.dat file.
Win.Heap.Sort1:
 IF Num.Files < 2 THEN
    RETURN
 END IF
 Num = Num.Files
 FOR I = 2 TO Num
    J = I
    DO UNTIL J = 1
       P = J \ 2
       I1$ = Filenames(J)
       I2$ = Filenames(P)
       IF I1$ > I2$ THEN
          WinFileStruc.Name = I2$
          PUT 2, J, WinFileStruc
          WinFileStruc.Name = I1$
          PUT 2, P, WinFileStruc
          J = P
       ELSE
          EXIT DO
       END IF
    LOOP
 NEXT
 FOR I = Num TO 2 STEP -1
    I1$ = Filenames(1)
    I2$ = Filenames(I)
    WinFileStruc.Name = I2$
    PUT 2, 1, WinFileStruc
    WinFileStruc.Name = I1$
    PUT 2, I, WinFileStruc
    J = 1
    DO
       IF 2! * CSNG(J) > CSNG(I) - 1! THEN
          EXIT DO
       END IF
       C = 2 * J
       IF C + 1 <= I - 1 THEN
          IF Filenames(C + 1) > Filenames(C) THEN
             C = C + 1
          END IF
       END IF
       I1$ = Filenames(J)
       I2$ = Filenames(C)
       IF I1$ < I2$ THEN
          WinFileStruc.Name = I2$
          PUT 2, J, WinFileStruc
          WinFileStruc.Name = I1$
          PUT 2, C, WinFileStruc
          J = C
       ELSE
          EXIT DO
       END IF
    LOOP
 NEXT
 RETURN

' sorts dos hexedit1.dat file.
Dos.Heap.Sort1:
 IF Num.Files < 2 THEN
    RETURN
 END IF
 Num = Num.Files
 FOR I = 2 TO Num
    J = I
    DO UNTIL J = 1
       P = J \ 2
       I1$ = Filenames(J)
       I2$ = Filenames(P)
       IF I1$ > I2$ THEN
          DosFileStruc.Name = I2$
          PUT 2, J, DosFileStruc
          DosFileStruc.Name = I1$
          PUT 2, P, DosFileStruc
          J = P
       ELSE
          EXIT DO
       END IF
    LOOP
 NEXT
 FOR I = Num TO 2 STEP -1
    I1$ = Filenames(1)
    I2$ = Filenames(I)
    DosFileStruc.Name = I2$
    PUT 2, 1, DosFileStruc
    DosFileStruc.Name = I1$
    PUT 2, I, DosFileStruc
    J = 1
    DO
       IF 2! * CSNG(J) > CSNG(I) - 1! THEN
          EXIT DO
       END IF
       C = 2 * J
       IF C + 1 <= I - 1 THEN
          IF Filenames(C + 1) > Filenames(C) THEN
             C = C + 1
          END IF
       END IF
       I1$ = Filenames(J)
       I2$ = Filenames(C)
       IF I1$ < I2$ THEN
          DosFileStruc.Name = I2$
          PUT 2, J, DosFileStruc
          DosFileStruc.Name = I1$
          PUT 2, C, DosFileStruc
          J = C
       ELSE
          EXIT DO
       END IF
    LOOP
 NEXT
 RETURN

' sorts windows hexedit2.dat file.
Win.Heap.Sort2:
 IF Num.Dirs < 2 THEN
    RETURN
 END IF
 Num = Num.Dirs
 FOR I = 2 TO Num
    J = I
    DO UNTIL J = 1
       P = J \ 2
       I1$ = Directories(J)
       I2$ = Directories(P)
       IF I1$ > I2$ THEN
          WinFileStruc.Name = I2$
          PUT 3, J, WinFileStruc
          WinFileStruc.Name = I1$
          PUT 3, P, WinFileStruc
          J = P
       ELSE
          EXIT DO
       END IF
    LOOP
 NEXT
 FOR I = Num TO 2 STEP -1
    I1$ = Directories(1)
    I2$ = Directories(I)
    WinFileStruc.Name = I2$
    PUT 3, 1, WinFileStruc
    WinFileStruc.Name = I1$
    PUT 3, I, WinFileStruc
    J = 1
    DO
       IF 2! * CSNG(J) > CSNG(I) - 1! THEN
          EXIT DO
       END IF
       C = 2 * J
       IF C + 1 <= I - 1 THEN
          IF Directories(C + 1) > Directories(C) THEN
             C = C + 1
          END IF
       END IF
       I1$ = Directories(J)
       I2$ = Directories(C)
       IF I1$ < I2$ THEN
          WinFileStruc.Name = I2$
          PUT 3, J, WinFileStruc
          WinFileStruc.Name = I1$
          PUT 3, C, WinFileStruc
          J = C
       ELSE
          EXIT DO
       END IF
    LOOP
 NEXT
 RETURN

' sorts dos hexedit2.dat file.
Dos.Heap.Sort2:
 IF Num.Dirs < 2 THEN
    RETURN
 END IF
 Num = Num.Dirs
 FOR I = 2 TO Num
    J = I
    DO UNTIL J = 1
       P = J \ 2
       I1$ = Directories(J)
       I2$ = Directories(P)
       IF I1$ > I2$ THEN
          DosFileStruc.Name = I2$
          PUT 3, J, DosFileStruc
          DosFileStruc.Name = I1$
          PUT 3, P, DosFileStruc
          J = P
       ELSE
          EXIT DO
       END IF
    LOOP
 NEXT
 FOR I = Num TO 2 STEP -1
    I1$ = Directories(1)
    I2$ = Directories(I)
    DosFileStruc.Name = I2$
    PUT 3, 1, DosFileStruc
    DosFileStruc.Name = I1$
    PUT 3, I, DosFileStruc
    J = 1
    DO
       IF 2! * CSNG(J) > CSNG(I) - 1! THEN
          EXIT DO
       END IF
       C = 2 * J
       IF C + 1 <= I - 1 THEN
          IF Directories(C + 1) > Directories(C) THEN
             C = C + 1
          END IF
       END IF
       I1$ = Directories(J)
       I2$ = Directories(C)
       IF I1$ < I2$ THEN
          DosFileStruc.Name = I2$
          PUT 3, J, DosFileStruc
          DosFileStruc.Name = I1$
          PUT 3, C, DosFileStruc
          J = C
       ELSE
          EXIT DO
       END IF
    LOOP
 NEXT
 RETURN

' simple error routine
Error.Routine3:
 IF Check.Disk THEN
    IF ERR = 57 THEN
       Disk.Ready = True
       RESUME NEXT
    END IF
    IF ERR = 71 THEN
       Disk.Ready = True
       RESUME NEXT
    END IF
    IF ERR = 76 THEN
       Disk.Ready = True
       RESUME NEXT
    END IF
 END IF
 CLS
 COLOR White
 PRINT "Hex Editor Menu " + 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 "Check TEMP variables, .CFG file, or DOS file handles, then restart."
 COLOR Plain
 END
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
    IF RIGHT$(V$, 1) = "\" THEN
       F2$ = V$ + V2$
    ELSE
       F2$ = V$ + "\" + V2$
    END IF
    IF TestFile(F1$) THEN
       IF TestFile(F2$) THEN
          GOTO OpenDataFilename
       END IF
    END IF
 END IF
 F1$ = "C:\TEMP\" + V1$
 F2$ = "C:\TEMP\" + V2$
 IF TestFile(F1$) THEN
    IF TestFile(F2$) THEN
       GOTO OpenDataFilename
    END IF
 END IF
 F1$ = "C:\" + V1$
 F2$ = "C:\" + V2$
 IF TestFile(F1$) THEN
    IF TestFile(F2$) THEN
       GOTO OpenDataFilename
    END IF
 END IF
 F1$ = V1$
 F2$ = V2$
 IF TestFile(F1$) THEN
    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."
 LOCATE 13, 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 "Usage:"
 COLOR Yellow
 PRINT "   Hexedit <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."
 COLOR Green
 PRINT "Example:"
 COLOR Yellow
 PRINT "   Hexedit " + CHR$(34) + "\dos\page.com" + CHR$(34)
 COLOR Green
 PRINT "Menu Usage:"
 COLOR Yellow
 PRINT "   Navigate using cursors, selecting with <enter>, and switch windows"
 PRINT "   with <tab>. F1 selects drive letter. F2 toggles sorting."
 PRINT "   Exits with <escape>."
 COLOR Green
 PRINT "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."
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.
