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

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

REM File menu box routine:

SUB Menu (N$, C$, D$, X$, E$)

REM Call to Menu() Returns:
REM   N$  -  Network path
REM       \\serv1\share
REM       Without trailing slash
REM         Or Nul for no net
REM   C$  -  Drive letter
REM       Normally C without : or \
REM   D$  -  Directory
REM       Without leading or trailing \ (can be null)
REM       Can be long pathname. No trailing spaces.
REM   X$  -  Filespec
REM       Normally *.*
REM   E$  -  Filename.ext
REM       Can be long filename. No trailing spaces.
REM
REM Concatenate upon return:
REM   IF N$ = Nul THEN
REM      IF D$ = Nul THEN
REM         Filename = C$ + ":\" + E$
REM      ELSE
REM         Filename = C$ + ":\" + D$ + "\" + E$
REM      END IF
REM   ELSE
REM      IF D$ = Nul THEN
REM         Filename = N$ + "\" + E$
REM      ELSE
REM         Filename = N$ + "\" + D$ + "\" + E$
REM      END IF
REM   END IF
REM
REM although netpath may be specified as c:\\serv1\share\dir1\filename.ext
REM this box does not fully support mixed drive letter and netpath.
REM
REM
REM During editing,
REM   I$  -  Current keystroke.
REM   F$  -  Fully qualified pathname with filename and drive letter.
REM   Q$  -  Current subdirectory.
REM   D1$ -  Temporary directory storage.
REM   X1$ -  Temporary file entry area path/file.
REM   X2$ -  Temporary filename storage.
REM
REM Mouse variables,
REM   IsMenu =
REM     1  -  Click in file box.
REM     2  -  Click in dir box.
REM     3  -  Click in drive box.
REM     4  -  Click in entry area.
REM     5  -  Click on 'x' to exit.

REM define error routine.
ON LOCAL ERROR GOTO Error.Routine

' reset flags.
Ambiguate = AmbiguateSwitch
FileSort = False
DirSort = False

' open structure files.
CALL OpenDataFiles1

' display menu screen.
CALL FileMainMenu

' get current drive.
Current.Drive = False
GOSUB GetDrives
GOSUB InitDrive

' get current filespec.
GOSUB InitFileSpec

' get current directory spec.
GOSUB InitDirSpec

' read all filenames.
GOSUB ClearFileBox
Z4$ = "Initing files.."
CALL LoadFileSpec(FileY$,F$)
GOSUB DisplayFileSpec
GOSUB DisplayCurrentPath

' read all subdirectories.
GOSUB ClearDirBox
Z3$ = "Initing dirs.."
CALL LoadDirSpec(DirY$,N$,C$,D$)
GOSUB DisplayDirSpec
GOSUB DisplayCurrentDir
GOSUB DisplayCurrentPath

' display first directory.
Current.Dir! = 1!
Dir.Box.Line = 1
GOSUB DisplayInitDir

' display all drives.
GOSUB InitDrives

' display first file.
GOSUB ClearLongName2
IF Num.Files > 0 THEN
   Current.File! = 1!
   Box.Line = 1
   GOSUB InitFiles
END IF

' check mouse.
IF Mouse.Present THEN
   ' position mouse.
   CALL MouseFunction2(1,1)
END IF
CALL SMouse

' reset filename attribute overrides.
RequireReadOnly = False
RequireHidden = False
RequireSystem = False
RequireArchive = False
RequireDirReadOnly = False
RequireDirHidden = False
RequireDirSystem = False
RequireDirArchive = False

REM File entry area variables:
REM   ProcessEditLine - processes X$ edit line when set to True.
REM   Xstart     - hilights file entry area for overstrike when set to True.
REM   Xposition1 - left position in file entry area editing string.
REM   Xposition2 - position of character in file entry area editing string.
REM

REM main input loop..

Xstart = True
Xposition1 = 1
DO
   ' reset filespec.
   IF X$ = Nul THEN
      X$ = "*.*"
      Xposition1 = 1
      Xposition2 = 3
   END IF

   ' display file entry area.
   GOSUB DisplayFileLine

   ' start input loop.
   DO
      ' reset input.
      I$ = Nul

      ' reset edit line.
      ProcessEditLine = False

      ' process input.
      DO
         ' get keypress.
         I$ = INKEY$

         ' process keypress.
         IF LEN(I$) THEN
            IsMenu = False
            EXIT DO
         END IF

         ' call mouse subroutine.
         CALL MouseDriver1

         ' check exit symbol.
         IF IsMenu = 5 THEN
            I$ = CHR$(27)
            EXIT DO
         END IF

         ' check left mouse button.
         IF Mouse.ButtonX THEN
            GOSUB MouseButton1Z
            SELECT CASE IsMenu
            CASE 1 ' file box.
               IF I$ = CHR$(13) THEN
                  E$ = RTRIM$(Filenames(Current.File!))
                  GOTO EndLoop2
               ELSE
                  GOSUB FileBoxKey
               END IF
            CASE 2 ' dir box.
               IF I$ = CHR$(13) THEN
                  GOSUB GetNewPath
                  EXIT DO
               ELSE
                  GOSUB DirBoxKey
               END IF
            CASE 3 ' drive box.
               IF I$ = CHR$(13) THEN
                  X$ = CHR$(Current.Drive + 64) + ":\*.*"
                  ProcessEditLine = True
                  EXIT DO
               ELSE
                  GOSUB DriveBoxKey
               END IF
            END SELECT
         ELSE
            ' check mouse position.
            IF Mouse.Row OR Mouse.Column THEN
               GOSUB MouseOverX1
               GOSUB DisplayFileLine
            END IF
         END IF

         ' release time slice,
         ' (speeds up mouse in windows).
         R = ReleaseTime
      LOOP

      ' ignore backslash
      IF I$ = "/" THEN
         I$ = Nul
      END IF

StartLoop0:

      ' check alt-<key>
      IF LEN(I$) = 2 THEN
         Gosub GetAltKey
         IF VarZ THEN
            ' specify drive letter.
            X$ = CHR$(Var2 + 64) + ":\*.*"
            I$ = Nul
            ProcessEditLine = True
            EXIT DO
         END IF
      END IF

StartLoop1:

      ' check extended key
      IF LEN(I$) = 2 THEN
         SELECT CASE ASC(RIGHT$(I$, 1))
         CASE 71 ' Home
            IF Xposition2 > 0 THEN
               Xstart = False
               Xposition1 = 1
               Xposition2 = 0
               GOSUB DisplayFileLine
            END IF
         CASE 79 ' End
            IF Xposition2 < LEN(X$) THEN
               Xstart = False
               Xposition2 = LEN(X$)
               Xposition1 = Xposition2 - 25
               IF Xposition1 < 1 THEN
                  Xposition1 = 1
               END IF
               GOSUB DisplayFileLine
            END IF
         CASE 83 ' Delete
            IF LEN(X$) > 0 THEN
               Xstart = False
               X$ = LEFT$(X$, Xposition2) + MID$(X$, Xposition2 + 2)
               GOSUB DisplayFileLine
            END IF
         CASE 75 ' Left
            IF LEN(X$) THEN
               IF Xposition2 > 0 THEN
                  Xposition2 = Xposition2 - 1
                  IF Xposition2 - 25 <= Xposition1 THEN
                     Xposition1 = Xposition1 - 1
                     IF Xposition1 < 1 THEN
                        Xposition1 = 1
                     END IF
                     GOSUB DisplayFileLine
                  END IF
               END IF
            END IF
         CASE 77 ' Right
            IF LEN(X$) THEN
               IF Xposition2 < LEN(X$) THEN
                  Xposition2 = Xposition2 + 1
                  IF Xposition2 > Xposition1 + 25 THEN
                     Xposition1 = Xposition1 + 1
                  END IF
                  GOSUB DisplayFileLine
               END IF
            END IF
         CASE 80 ' Down
            I$ = CHR$(9)
            GOTO TabFile
         CASE 59 ' F1  - change drive letter.
            I$ = Nul
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            PRINTf SPACE$(38)
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            COLORf2 Yellow, 0
            PRINTf "Drive letter: "
            DO
               Z$ = INKEY$
               IF LEN(Z$) = 1 THEN
                  Z$ = UCASE$(Z$)
                  IF Z$ >= "A" AND Z$ <= "Z" THEN
                     EXIT DO
                  END IF
               END IF
               R = ReleaseTime
            LOOP
            PRINTf Z$
            X$ = UCASE$(Z$) + ":\*.*"
            I$ = Nul
            ProcessEditLine = True
            EXIT DO
         CASE 60 ' F2  - toggle heap sorting.
            I$ = Nul
            HeapSortOff = NOT HeapSortOff
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            PRINTf SPACE$(38)
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            COLORf2 White, 0
            IF HeapSortOff THEN
               PRINTf "Sorting Off. Press <esc>:"
            ELSE
               PRINTf "Sorting On. Press <esc>:"
            END IF
            WHILE INKEY$<>CHR$(27)
               R = ReleaseTime
            WEND
            GOSUB UpdateDisplay
            EXIT DO
         CASE 61 ' F3 - move file menu box.
            CALL HMouse
            I$ = Nul
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            PRINTf SPACE$(38)
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            COLORf2 White, 0
            PRINTf "Use cursor keys. Press <esc> to quit."
            CALL MoveMenu
            CALL BottomRow
            GOSUB DisplayCurrentPath
            IF Num.Files > 0 THEN
               GOSUB DisplayLongName2
            END IF
            GOSUB DisplayFilename6
            GOSUB DisplayFileLine
            CALL SMouse
         CASE 62 ' F4 - backward 1 drive letter.
            I$ = Nul
            V = ASC(C$)
            IF V > 65 THEN
               V = V - 1
               X$ = CHR$(V) + ":\*.*"
               ProcessEditLine = True
               EXIT DO
            END IF
         CASE 63 ' F5 - forward 1 drive letter.
            I$ = Nul
            V = ASC(C$) - 64
            IF V + 1 <= Last.Drive THEN
               V = V + 1
               X$ = CHR$(V + 64) + ":\*.*"
               ProcessEditLine = True
               EXIT DO
            END IF
         CASE 64 ' F6 - toggle ambiguate.
            I$ = Nul
            Ambiguate = NOT Ambiguate
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            PRINTf SPACE$(38)
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            COLORf2 White, 0
            IF Ambiguate = False THEN
               PRINTf "Ambiguation Off. Press <esc>:"
            ELSE
               PRINTf "Ambiguation On. Press <esc>:"
            END IF
            WHILE INKEY$<>CHR$(27)
               R = ReleaseTime
            WEND
            GOSUB UpdateDisplay
            EXIT DO
         CASE 65 ' F7 - redraw screen
            GOSUB RedrawScreen
            EXIT DO
         CASE 66 ' F8 - attribute override
            I$ = Nul
            CALL OverridePrompt
            GOSUB UpdateDisplay
            EXIT DO
         CASE 67 ' F9 - help screen
            I$ = Nul
            CALL HMouse
            CALL DisplayHelp
            GOSUB RedrawScreen
            CALL SMouse
         CASE 68 ' F10 - exit program
            I$ = CHR$(27)
            EXIT DO
         CASE 133 ' F11 - drop to DOS
            COLORf Plain
            CLS
            PRINTf "Type 'Exit' to return to editor.."
            Var$=Curdir$
            Call ResetTrap
            SHELL
            Chdrive Var$
            Chdir Var$
            Call SetTrap
            GOSUB RedrawScreen
            EXIT DO
         CASE 134 ' F12 - enter filespec
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            PRINTf SPACE$(38)
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            COLORf2 White, 0
            PRINTf "Enter file spec: "
            X$ = lineinput$(Xcoor + 1, Ycoor + 19, 21)
            I$ = Nul
            IF LEN(X$) THEN
               E$ = X$
               IF MID$(E$, 2, 1) = ":" THEN
                  C$ = LEFT$(E$, 1)
                  E$ = MID$(E$, 3)
                  N$ = ""
               END IF
               FOR VarQ = LEN(E$) TO 1 STEP -1
                  IF MID$(E$, VarQ, 1) = "\" THEN
                     D$ = LEFT$(E$, VarQ)
                     E$ = MID$(E$, VarQ + 1)
                     EXIT FOR
                  END IF
               NEXT
               IF RIGHT$(D$, 1) = "\" THEN
                  D$ = LEFT$(D$, LEN(D$) - 1)
               END IF
               IF LEFT$(D$, 1) = "\" THEN
                  D$ = MID$(D$, 2)
               END IF
               X$ = "*.*"
               I$ = CHR$(13)
               EXIT DO
            END IF
            GOSUB DisplayFilename6
            GOSUB DisplayFileLine
            EXIT DO
         CASE 104 ' Alt-F1 - toggle quiet mode.
            I$ = Nul
            SELECT CASE QuietSwitch
            CASE -1
               QuietSwitch = 0
               P$ = "Quiet switch off."
            CASE 0
               QuietSwitch = 1
               P$ = "Quiet switch level 1."
            CASE 1
               QuietSwitch = 2
               P$ = "Quiet switch level 2."
            CASE 2
               QuietSwitch = 3
               P$ = "Quiet switch level 3."
            CASE 3
               QuietSwitch = 4
               P$ = "Quiet switch level 4."
            CASE 4
               QuietSwitch = 5
               P$ = "Quiet switch level 5."
            CASE 5
               QuietSwitch = 6
               P$ = "Quiet switch level 6."
            CASE 6
               QuietSwitch = True
               P$ = "Quiet switch on."
            CASE ELSE
               QuietSwitch = True
               P$ = "Quiet switch on."
            END SELECT
            P$ = P$ + " Press <esc>."
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            PRINTf SPACE$(38)
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            COLORf2 White, 0
            PRINTf P$
            WHILE INKEY$<>CHR$(27)
               R = ReleaseTime
            WEND
            GOSUB UpdateDisplay
            EXIT DO
         CASE 105 ' Alt-F2 - file exclusion entry.
            I$ = Nul
            CALL ExcludeList(1,Y$)
            FileY$ = Y$
            GOSUB RedrawScreen
            EXIT DO
         CASE 106 ' Alt-F3 - dir exclusion entry.
            I$ = Nul
            CALL ExcludeList(2,Y$)
            DirY$ = Y$
            GOSUB RedrawScreen
            EXIT DO
         CASE 107 ' Alt-F4 - toggle file sort ascending/descending.
            I$ = Nul
            FileSort = NOT FileSort
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            PRINTf SPACE$(38)
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            COLORf2 White, 0
            IF FileSort THEN
               PRINTf "File sort descending. Press <esc>:"
            ELSE
               PRINTf "File sort ascending. Press <esc>:"
            END IF
            WHILE INKEY$<>CHR$(27)
               R = ReleaseTime
            WEND
            GOSUB UpdateDisplay
            EXIT DO
         CASE 108 ' Alt-F5 - toggle dir sort ascending/descending.
            I$ = Nul
            DirSort = NOT DirSort
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            PRINTf SPACE$(38)
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            COLORf2 White, 0
            IF DirSort THEN
               PRINTf "Dir sort descending. Press <esc>:"
            ELSE
               PRINTf "Dir sort ascending. Press <esc>:"
            END IF
            WHILE INKEY$<>CHR$(27)
               R = ReleaseTime
            WEND
            GOSUB UpdateDisplay
            EXIT DO
         CASE 109 ' Alt-F6 - toggle file date/time switch.
            I$ = Nul
            SELECT CASE FileSwitch
            CASE 0
               FileSwitch = 1
               P$ = "File switch level 1."
            CASE 1
               FileSwitch = 2
               P$ = "File switch level 2."
            CASE 2
               FileSwitch = 0
               P$ = "File switch level 0."
            CASE ELSE
               FileSwitch = 0
               P$ = "File switch level 0."
            END SELECT
            P$ = P$ + " Press <esc>."
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            PRINTf SPACE$(38)
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            COLORf2 White, 0
            PRINTf P$
            WHILE INKEY$<>CHR$(27)
               R = ReleaseTime
            WEND
            GOSUB UpdateDisplay
            EXIT DO
         CASE 110 ' Alt-F7 - toggle file size switch.
            I$ = Nul
            SELECT CASE FileSizeType
            CASE 0
               FileSizeType = 1
               P$ = "File size switch level 1."
            CASE 1
               FileSizeType = 2
               P$ = "File size switch level 2."
            CASE 2
               FileSizeType = 0
               P$ = "File size switch level 0."
            CASE ELSE
               FileSizeType = 0
               P$ = "File size switch level 0."
            END SELECT
            P$ = P$ + " Press <esc>."
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            PRINTf SPACE$(38)
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            COLORf2 White, 0
            PRINTf P$
            WHILE INKEY$<>CHR$(27)
               R = ReleaseTime
            WEND
            GOSUB UpdateDisplay
            EXIT DO
         CASE 111 ' Alt-F8 - network path.
            I$ = Nul
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            PRINTf SPACE$(38)
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            COLORf2 White, 0
            PRINTf "Net path: "
            Z$ = lineinput(Xcoor+1,Ycoor+12,28)
            X$ = Nul
            IF LEN(Z$) THEN
               IF LEFT$(Z$, 2) = "\\" THEN
                  X$ = Z$
               END IF
            END IF
            GOSUB DisplayFilename6
            GOSUB DisplayFileLine
            IF LEN(X$) THEN
               ProcessEditLine = True
               EXIT DO
            END IF
         CASE 112 ' Alt-F9 - default network path.
            I$ = Nul
            X$ = Nul
            ' store default server name
            IF RTRIM$(DefaultNetPath) <> Nul THEN
               X$ = "\\" + RTRIM$(DefaultNetPath) +"\C\"
               GOSUB DisplayFilename6
               GOSUB DisplayFileLine
               ProcessEditLine = True
               EXIT DO
            END IF
         CASE 113 ' Alt-F10 - load default net w/ drive letter
            I$ = Nul
            X$ = Nul
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            PRINTf SPACE$(38)
            LOCATEf Xcoor + 1, Ycoor + 2, 1
            COLORf2 White, 0
            PRINTf "Drive letter: "
            DO
               Z$ = INKEY$
               IF LEN(Z$) = 1 THEN
                  Z$ = UCASE$(Z$)
                  IF Z$ >= "A" AND Z$ <= "Z" THEN
                     EXIT DO
                  END IF
               END IF
               R = ReleaseTime
            LOOP
            PRINTf Z$
            ' store default server name
            IF RTRIM$(DefaultNetPath) <> Nul THEN
               X$ = "\\" + RTRIM$(DefaultNetPath) +"\" + UCASE$(Z$)+ "\"
               GOSUB DisplayFilename6
               GOSUB DisplayFileLine
               ProcessEditLine = True
               EXIT DO
            END IF
         CASE ELSE
            I$ = Nul ' nul activity
         END SELECT
         I$ = Nul ' nul keystroke
      END IF

REM tab key label.
TabFile:

      ' 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
            ' check function key.
            IF LEN(I$) = 2 THEN
               VarQ = ASC(RIGHT$(I$, 1))
               IF VarQ >= 59 AND VarQ <= 68 THEN
                  GOTO StartLoop1
               END IF
               IF VarQ >= 104 AND VarQ <= 113 THEN
                  GOTO StartLoop1
               END IF
               IF VarQ = 133 OR VarQ = 134 THEN
                  GOTO StartLoop1
               END IF
               Gosub GetAltKey
               IF VarZ THEN
                  GOTO StartLoop0
               END IF
            END IF
            ' tab from drive input loop.
            IF I$ = CHR$(9) THEN
               I$ = Nul
               EXIT DO
            END IF
            ' shift-tab from dir input loop.
            IF I$ = CHR$(0) + CHR$(15) THEN
               I$ = Nul
               EXIT DO
            END IF
            ' click on file entry area.
            IF IsMenu = 4 THEN
               GOSUB DisplayCurrentPath
               IF Num.Files > 0 THEN
                  GOSUB DisplayLongName2
               END IF
               EXIT DO
            END IF
            IF I$ = CHR$(13) THEN
               SELECT CASE IsMenu
               CASE 1 ' file box.
                  E$ = RTRIM$(Filenames(Current.File!))
                  GOTO EndLoop2
               CASE 2 ' dir box.
                  GOSUB GetNewPath
               CASE 3 ' drive box.
                  X$ = CHR$(Current.Drive + 64) + ":\*.*"
                  I$ = Nul
                  ProcessEditLine = True
                  EXIT DO
               CASE 4 ' entry area.
                  GOSUB DisplayCurrentPath
                  IF Num.Files > 0 THEN
                     GOSUB DisplayLongName2
                  END IF
                  EXIT DO
               CASE 5
                  I$ = CHR$(27)
                  EXIT DO
               CASE ELSE
                  E$ = RTRIM$(Filenames(Current.File!))
                  GOTO EndLoop2
               END SELECT
            END IF
         ELSE
            GOSUB DirInputLoop
            ' check function key.
            IF LEN(I$) = 2 THEN
               VarQ = ASC(RIGHT$(I$, 1))
               IF VarQ >= 59 AND VarQ <= 68 THEN
                  GOTO StartLoop1
               END IF
               IF VarQ >= 104 AND VarQ <= 113 THEN
                  GOTO StartLoop1
               END IF
               IF VarQ = 133 OR VarQ = 134 THEN
                  GOTO StartLoop1
               END IF
               Gosub GetAltKey
               IF VarZ THEN
                  GOTO StartLoop0
               END IF
            END IF
            ' tab from drive input loop.
            IF I$ = CHR$(9) THEN
               I$ = Nul
               EXIT DO
            END IF
            ' shift-tab from drive input loop.
            IF I$ = CHR$(0) + CHR$(15) THEN
               I$ = Nul
               EXIT DO
            END IF
            IF IsMenu = 4 THEN
               GOSUB DisplayCurrentPath
               IF Num.Files > 0 THEN
                  GOSUB DisplayLongName2
               END IF
               EXIT DO
            END IF
            IF I$ = CHR$(13) THEN
               SELECT CASE IsMenu
               CASE 1 ' file box.
                  E$ = RTRIM$(Filenames(Current.File!))
                  GOTO EndLoop2
               CASE 2 ' dir box.
                  GOSUB GetNewPath
               CASE 3 ' drive box.
                  X$ = CHR$(Current.Drive + 64) + ":\*.*"
                  I$ = Nul
                  ProcessEditLine = True
                  EXIT DO
               CASE 4 ' entry area.
                  GOSUB DisplayCurrentPath
                  IF Num.Files > 0 THEN
                     GOSUB DisplayLongName2
                  END IF
                  EXIT DO
               CASE 5
                  I$ = CHR$(27)
                  EXIT DO
               CASE ELSE
                  GOSUB GetNewPath
               END SELECT
            END IF
         END IF
      END IF

      ' enter key.
      IF I$ = CHR$(13) THEN
         I$ = Nul
         ProcessEditLine = True
         EXIT DO
      END IF

      ' escape key.
      IF I$ = CHR$(27) THEN
         EXIT DO ' exit box.
      END IF

      ' backspace.
      IF I$ = CHR$(8) THEN
         IF LEN(X$) THEN
            IF Xstart = True AND Xposition2 = 0 THEN
               X$ = Nul
               Xstart = False
               Xposition1 = 1
               Xposition2 = 0
               GOSUB DisplayFileLine
            ELSE
               IF XPosition2 > 0 THEN
                  Xstart = False
                  X$ = LEFT$(X$, Xposition2 - 1) + MID$(X$, Xposition2 + 1)
                  Xposition2 = Xposition2 - 1
                  IF Xposition2 - 25 <= Xposition1 THEN
                     Xposition1 = Xposition1 - 1
                     IF Xposition1 < 1 THEN
                        Xposition1 = 1
                     END IF
                  END IF
                  GOSUB DisplayFileLine
               END IF
            END IF
         END IF
      ELSE
         ' append/insert character into filename area.
         IF LEN(I$) THEN
            ' error check input length.
            IF LEN(X$) >= 32767 THEN
               X$ = Nul
               Xstart = False
               Xposition1 = 1
               Xposition2 = 0
               LOCATEf Xcoor + 1, Ycoor + 2, 1
               PRINTf SPACE$(38)
               LOCATEf Xcoor + 1, Ycoor + 2, 1
               COLORf2 White, 0
               PRINTf "Edit line error. Press <esc>:"
               WHILE INKEY$<>CHR$(27)
                  R = ReleaseTime
               WEND
            ELSE
               IF Xstart THEN
                  X$ = Nul
                  Xstart = False
                  Xposition1 = 1
                  Xposition2 = 0
                  GOSUB DisplayFileLine
               END IF
               X$ = LEFT$(X$, Xposition2) + I$ + MID$(X$, Xposition2 + 1)
               Xposition2 = Xposition2 + 1
               IF Xposition2 > 26 THEN
                  Xposition1 = Xposition1 + 1
               END IF
               GOSUB DisplayFileLine
            END IF
         END IF
      END IF
   LOOP

   ' exit menu box w/o filename.
   IF I$ = CHR$(27) THEN
      E$ = Nul
      EXIT DO
   END IF

   ' exit menu box with filename.
   IF I$ = CHR$(13) THEN
      EXIT DO
   END IF

   REM Process edit line in X$
   REM
   REM Parses
   REM   c:\path\filename.ext
   REM     or
   REM   \\netpath\share\path
   REM
   REM With partial pathname override,
   REM filename ambiguation detection, and
   REM multi-dot imbedded path retracting.

   ' check process flag.
   IF ProcessEditLine THEN

      ' store values.
      D1$ = D$
      X2$ = F$

      ' change netpath. v7.6a 06/10/2007.
      IF LEFT$(X$, 2) = "\\" THEN
         IF RIGHT$(X$, 1) <> "\" THEN
            X$ = X$ + "\"
         END IF
         N$ = X$

         ' display message.
         CALL HMouse
         COLORf White
         LOCATEf Xcoor + 1, Ycoor + 12, 1
         PRINTf SPACE$(26)
         LOCATEf Xcoor + 1, Ycoor + 12, 1
         PRINTf "Checking path.."
         COLORf Plain
         CALL SMouse

         ' store long filename.
         W$ = N$
         IF RIGHT$(W$, 1) = "\" THEN
            W$ = LEFT$(W$, LEN(W$) - 1)
         END IF

         ' store asciiz filename.
         ASCIIZ3 = W$ + CHR$(0)

         ' verify share folder.
         Check.Disk = True
         Disk.Ready = False
         IF Windows.Detected THEN
            ' get file attribute.
            InregsX.AX = &H7143
            InregsX.BX = &H0 ' get attr
            InregsX.DS = VARSEG(ASCIIZ3)
            InregsX.DX = VARPTR(ASCIIZ3)
            CALL InterruptX(&H21, InregsX, OutregsX)
         ELSE
            ' get file attribute.
            InregsX.AX = &H4300
            InregsX.DS = VARSEG(ASCIIZ3)
            InregsX.DX = VARPTR(ASCIIZ3)
            CALL InterruptX(&H21, InregsX, OutregsX)
         END IF
         Check.Disk = False

         ' check carry flag error.
         IF (OutregsX.Flags AND &H1) = &H1 THEN
            ' check file nonexistent.
            IF (OutregsX.AX) <> 2 THEN
               Disk.Ready = True
            END IF
         END IF

         ' check disk not available.
         IF Disk.Ready THEN
            N$ = Nul
            GOSUB PromptNet
            GOSUB InitFileSpec
            Xstart = True
            GOTO EndLoop1
         END IF

         ' store new netpath.
         N$ = LEFT$(N$, LEN(N$) - 1)
         D$ = Nul ' root.
         X$ = "*.*"

         ' parse dospath from netpath
         VX = INSTR(3, N$, "\") + 1
         VX = INSTR(VX + 1, N$, "\")
         IF VX THEN
            D$ = MID$(N$, VX)
            N$ = LEFT$(N$, VX - 1)
         END IF
         New.Net = True
      END IF

      ' change drive.
      IF MID$(X$, 2, 1) = ":" THEN

         ' display message.
         CALL HMouse
         COLORf White
         LOCATEf Xcoor + 1, Ycoor + 12, 1
         PRINTf SPACE$(26)
         LOCATEf Xcoor + 1, Ycoor + 12, 1
         PRINTf "Loading drive.."
         COLORf Plain
         CALL SMouse

         ' check drive.
         Z$ = UCASE$(LEFT$(X$, 1))
         X$ = MID$(X$, 3)

         ' check disk space.
         Check.Disk = True
         Disk.Ready = False
         InregsX.AX = &H3600
         InregsX.DX = ASC(Z$) - 64
         CALL InterruptX(&H21, InregsX, OutregsX)
         Check.Disk = False

         ' check disk not available.
         IF Disk.Ready THEN
            GOSUB PromptDisk
            GOSUB InitFileSpec
            Xstart = True
            GOTO EndLoop1
         END IF
         IF OutregsX.AX = &HFFFF THEN
            GOSUB PromptDisk
            GOSUB InitFileSpec
            Xstart = True
            GOTO EndLoop1
         END IF

         ' store new drive.
         IF C$ <> Z$ OR N$ <> Nul THEN
            N$ = Nul
            C$ = Z$
            New.Drive = ASC(C$) - 64
            IF X$ = Nul THEN
               X$ = "\"
            END IF
            IF RIGHT$(X$, 1) = "\" THEN
               X$ = X$ + "*.*"
            END IF
         END IF
      END IF

      ' parse out path.
      CALL Parse.Path(D$, X$)

      ' parse off directory.
      IF INSTR(X$, "\") THEN
         FOR Var = LEN(X$) TO 1 STEP -1
            IF MID$(X$, Var, 1) = "\" THEN
               EXIT FOR
            END IF
         NEXT

         ' parse filename.
         SELECT CASE Var
         CASE 1 ' check root.
            D$ = Nul
            X$ = MID$(X$, Var + 1)
         CASE LEN(X$) ' check nul filename.
            D$ = LEFT$(X$, Var - 1)
            X$ = Nul
         ' parse directory/filename.
         CASE ELSE
            IF LEFT$(X$, 1) = "\" THEN
               D$ = LEFT$(X$, Var - 1)
            ELSE
               D$ = D$ + "\" + LEFT$(X$, Var - 1)
            END IF
            X$ = MID$(X$, Var + 1)
         END SELECT
      END IF

      ' process directory.
      IF LEFT$(D$, 1) = "\" THEN
         D$ = MID$(D$, 2)
      END IF
      IF RIGHT$(D$, 1) = "\" THEN
         D$ = LEFT$(D$, LEN(D$) - 1)
      END IF
      IF LEFT$(D$, 1) = "\" THEN
         D$ = Nul
      END IF
      IF RIGHT$(D$, 1) = "\" THEN
         D$ = Nul
      END IF
      IF D$ = "\" THEN
         D$ = Nul
      END IF

      ' check directory.
      GOSUB CheckPath
      IF ValidPath = False THEN
         D$ = D1$
         X$ = X1$
         Xposition1 = 1
         Xposition2 = 0
         GOTO EndLoop1
      END IF

      ' store directory.
      D3$ = D$
      X3$ = X$

      ' prevent directory from loading twice.
      LoadedDir = False

      ' check filename.
      IF X$ = STRING$(LEN(X$), ".") THEN
         ' strip multiple dots from path.
         CALL Parse.Path2(D$, X$)
      END IF

      ' construct partial path.
      IF D$ = Nul THEN
         D$ = X$
      ELSE
         IF X$ <> Nul THEN
            D$ = D$ + "\" + X$
         END IF
      END IF

      ' check path.
      GOSUB CheckPath

      ' check path is file.
      IF OutregsX.AX = 32 THEN ' sharing violation.
         ValidPath = False
      END IF

      ' check valid path.
      IF ValidPath = False THEN
         D$ = D3$
         X$ = X3$
      END IF

      ' check valid path.
      IF ValidPath THEN
         ' check directory already loaded.
         IF D$ <> D1$ OR New.Drive > 0 OR New.Net THEN
            ' load current directory.
            Z3$ = "Loading dirs.."
            CALL LoadDirSpec(DirY$,N$,C$,D$)
            New.Drive = True
            New.Net = False
         END IF
         ' reset filename.
         X$ = Nul
         ' set loaded flag.
         LoadedDir = True
         GOSUB DisplayCurrentDir
      END IF

      ' check filename.
      IF X$ = Nul THEN
         GOSUB InitFileSpec
      END IF

      ' check loaded dir.
      IF LoadedDir = False THEN
         ' check filename characters.
         IF INSTR(X$, "?") = False THEN
            IF INSTR(X$, "*") = False THEN
               ' search for directory spec override.
               FOR Var! = 1! TO Num.Dirs
                  S$ = UCASE$(RTRIM$(Directories(Var!)))
                  ' check X$ is directory in current one.
                  IF D$ = Nul THEN
                     ASCIIZ = "\" + S$ + CHR$(0)
                  ELSE
                     ASCIIZ = "\" + D$ + "\" + S$ + CHR$(0)
                  END IF
                  Flag = False
                  ' get conanicalized directory name.
                  If Windows.Detected Then
                     V4 = False
                     GOSUB ShortFilenameX
                     ' check directory name.
                     IF UCASE$(X$) = Short.Filename$ THEN
                        Flag = True
                     END IF
                  Endif
                  ' check directory name.
                  If Flag = False Then
                     IF UCASE$(X$) = S$ THEN
                        Flag = True
                     END IF
                  Endif
                  If Flag Then
                     ' store directory.
                     S$ = RTRIM$(Directories(Var!))
                     IF D$ = Nul THEN
                        D$ = S$
                     ELSE
                        D$ = D$ + "\" + S$
                     END IF
                     ' restore filename override.
                     GOSUB InitFileSpec
                     EXIT FOR
                  END IF
               NEXT
            END IF
         END IF
      END IF

      ' store current filespec.
      IF X$ = "." THEN
         X$ = Nul
      END IF

      ' store and load directories.
      IF LoadedDir = False THEN
         ' check directory already loaded.
         IF D$ <> D1$ OR New.Drive > 0 OR New.Net THEN
            ' load directories.
            GOSUB LoadNewDir
            New.Drive = True
            New.Net=False
         END IF
      ELSE
         ' init directories.
         GOSUB LoadNewDir2
         GOSUB DisplayCurrentDir
      END IF

      ' store filename.
      GOSUB InitDirSpec

      ' store filename.
      X1$ = X$
      Xposition1 = 1
      Xposition2 = 0

      ' compare filespecs.
      IF UCASE$(F$) <> UCASE$(X2$) THEN
         ' store filespec.
         X2$ = F$
         ' load file box.
         GOSUB LoadNewFiles
      END IF

      ' check filename characters.
      IF INSTR(X$, "?") = False THEN
         IF INSTR(X$, "*") = False THEN
            ' search for filename spec override.
            FOR Var! = 1! TO Num.Files
               S$ = UCASE$(RTRIM$(Filenames(Var!)))
               ' check X$ is filename in current directory.
               IF D$ = Nul THEN
                  ASCIIZ = "\" + S$ + CHR$(0)
               ELSE
                  ASCIIZ = "\" + D$ + "\" + S$ + CHR$(0)
               END IF
               Flag = False
               ' get conanicalized filename.
               If Windows.Detected Then
                  V4 = False
                  GOSUB ShortFilenameX
                  ' check filename.
                  If UCASE$(X$) = Short.Filename$ Then
                     Flag = True
                  Endif
               Endif
               ' check filename.
               If Flag = False Then
                  IF UCASE$(X$) = S$ THEN
                     Flag = True
                  Endif
               Endif
               If Flag Then
                  ' select file for editing.
                  E$ = RTRIM$(Filenames(Var!))
                  EXIT DO
               END IF
            NEXT
         END IF
      END IF

      ' construct dir/filename.
      V$ = MakeFilename$(N$, C$, D$, X$)

      ' check filename characters.
      IF INSTR(V$, "?") = False THEN
         IF INSTR(V$, "*") = False THEN
            ' check filename exists or not found.
            IF TestFile(V$) THEN
               ' select file for editing.
               E$ = X$
               EXIT DO
            END IF
         END IF
      END IF

      ' display all drives.
      IF New.Drive = True THEN
         Current.Drive = ASC(C$) - 64
         GOSUB InitDrives
         New.Drive = False
      END IF

      ' restart editing loop.
      Xstart = True
   END IF
EndLoop1:
LOOP

' exit editing loop.
EndLoop2:

' exit file menu box.
CALL HMouse
COLORf2 7, 0
CLS

' return to editor.
EXIT SUB

' reset file menu box.
UpdateDisplay:
 GOSUB DisplayFilename6
 COLORf2 Plain, 0
 ' init dir box.
 GOSUB ClearDirBox
 Z3$ = "Updating dirs.."
 CALL LoadDirSpec(DirY$,N$,C$,D$)
 GOSUB DisplayDirSpec
 Current.Dir! = 1!
 Dir.Box.Line = 1
 GOSUB DisplayCurrentDir
 ' init file box.
 GOSUB ClearFileBox
 Z4$ = "Updating files.."
 CALL LoadFileSpec(FileY$,F$)
 GOSUB DisplayFileSpec
 GOSUB DisplayCurrentPath
 ' display first file.
 GOSUB ClearLongName2
 IF Num.Files > 0 THEN
    Current.File! = 1!
    Box.Line = 1
    GOSUB InitFiles
 END IF
 ' init drive box.
 GOSUB InitDrives
 RETURN

' init filespec.
InitFileSpec:
 ' compare stored filename.
 IF X1$ = Nul THEN
    X$ = "*.*"
    Xposition1 = 1
    Xposition2 = 3
 ELSE
    ' restore filename spec.
    X$ = X1$
    Xposition1 = 1
    Xposition2 = 0
 END IF
 ' check filename.
 IF X$ = "." THEN
    X$ = Nul
 END IF
 RETURN

' init current directory.
InitDirSpec:
 F$ = MakeFilename$(N$, C$, D$, X$)
 RETURN

' inits dir box with new dirspec.
LoadNewDir:
 Current.Dir! = 1!
 Dir.Box.Line = 1
 GOSUB ClearDirBox
 GOSUB CheckPath
 IF ValidPath = False THEN
    D$ = D1$
    X$ = X1$
    Xposition1 = 1
    Xposition2 = 0
 END IF
 Z3$ = "Reloading dirs.."
 CALL LoadDirSpec(DirY$,N$,C$,D$)
 GOSUB DisplayDirSpec
 GOSUB DisplayCurrentDir
 GOSUB DisplayCurrentPath
 GOSUB DisplayDirectory
 RETURN

' inits dir box without new dirspec.
LoadNewDir2:
 Current.Dir! = 1!
 Dir.Box.Line = 1
 GOSUB ClearDirBox
 GOSUB CheckPath
 IF ValidPath = False THEN
    D$ = D1$
    X$ = X1$
    Xposition1 = 1
    Xposition2 = 0
 END IF
 GOSUB DisplayDirSpec
 GOSUB DisplayCurrentDir
 GOSUB DisplayCurrentPath2
 GOSUB DisplayDirectory
 RETURN

' inits file box.
LoadNewFiles:
 GOSUB ClearFileBox
 Z4$ = "Reloading files.."
 CALL LoadFileSpec(FileY$,F$)
 GOSUB DisplayFileSpec
 IF Num.Files > 0 THEN
    Current.File! = 1!
    Box.Line = 1
    GOSUB InitFiles
 ELSE
    GOSUB ClearLongName2
 END IF
 RETURN

' display current filename entry area.
DisplayFileLine:
 CALL HMouse
 LOCATEf Xcoor + 1, Ycoor + 12, 1
 PRINTf SPACE$(26)
 ' check hilighting.
 IF Xstart THEN
    COLORf2 Black, Plain
 END IF
 ' display edit line and position cursor.
 LOCATEf Xcoor + 1, Ycoor + 12, 1
 PRINTf MID$(X$, Xposition1, 26)
 LOCATEf Xcoor + 1, Ycoor + Xposition2 - Xposition1 + 13, 1
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' display invalid disk message.
PromptDisk:
 Z2$ = "Disk not ready. Press <esc>:"
 GOTO NextPrompt
' display invalid netpath message.
PromptNet:
 Z2$ = "Net not ready. Press <esc>:"
NextPrompt:
 CALL HMouse
 LOCATEf Xcoor + 1, Ycoor + 2, 1
 PRINTf SPACE$(38)
 LOCATEf Xcoor + 1, Ycoor + 2, 1
 COLORf2 White, 0
 PRINTf Z2$
 WHILE INKEY$<>CHR$(27)
    R = ReleaseTime
 WEND
 GOSUB DisplayFilename6
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' init filename input loop.
InitFiles:
 E$ = RTRIM$(Filenames(1!))
 CALL HMouse
 COLORf2 Black, Plain
 LOCATEf Xcoor + 5, Ycoor + 3, 1
 PRINTf LEFT$(E$, 12)
 COLORf2 Plain, 0
 GOSUB DisplayLongName2
 CALL SMouse
 RETURN

' filename input loop.
FileInputLoop:
 I$ = Nul
 DO
    IF Current.File! > 0 THEN
       GOSUB DisplayLongName2
       GOSUB ClearFilename
       GOSUB DisplayFilename1
    END IF
    DO
       ' get keystroke.
       I$ = INKEY$
       IF LEN(I$) THEN
          IsMenu = False
          EXIT DO
       END IF

       ' call mouse subroutine.
       CALL MouseDriver1

       ' check file entry area.
       IF IsMenu >= 4 THEN
          RETURN
       END IF

       ' check left mouse button.
       IF Mouse.ButtonX THEN
          GOSUB MouseButton1Z
          SELECT CASE IsMenu
          CASE 1 ' file box.
             IF I$ = CHR$(13) THEN
                EXIT DO
             ELSE
                GOSUB FileBoxKey
             END IF
          CASE 2 ' dir box.
             IF I$ = CHR$(13) THEN
                RETURN
             ELSE
                GOSUB DirBoxKey
             END IF
          CASE 3 ' drive box.
             IF I$ = CHR$(13) THEN
                RETURN
             ELSE
                GOSUB DriveBoxKey
             END IF
          END SELECT
       ELSE
          ' check mouse position.
          IF Mouse.Row OR Mouse.Column THEN
             GOSUB MouseOverX1
          END IF
       END IF

       ' release time slice.
       R = ReleaseTime
    LOOP

    ' check function key.
    IF LEN(I$) = 2 THEN
       VarQ = ASC(RIGHT$(I$, 1))
       IF VarQ >= 59 AND VarQ <= 68 THEN
          RETURN
       END IF
       IF VarQ >= 104 AND VarQ <= 113 THEN
          RETURN
       END IF
       IF VarQ = 133 OR VarQ = 134 THEN
          RETURN
       END IF
       Gosub GetAltKey
       IF VarZ THEN
          RETURN
       END IF
    END IF

    ' up returns shift-tab.
    IF LEN(I$) = 2 THEN
       IF ASC(RIGHT$(I$, 1)) = 72 THEN
          IF Current.File! = 1! THEN
             IF Box.Line = 1 THEN
                I$ = CHR$(0) + CHR$(15)
             END IF
          END IF
       END IF
    END IF

    ' shift-tab returns to top.
    IF LEN(I$) = 2 THEN
       IF ASC(RIGHT$(I$, 1)) = 15 THEN
          RETURN
       END IF
    END IF

    ' right returns tab.
    IF LEN(I$) = 2 THEN
       IF ASC(RIGHT$(I$, 1)) = 77 THEN
          I$ = CHR$(9)
       END IF
    END IF

    ' Tab moves to directory loop.
    IF I$ = CHR$(9) THEN
       GOSUB DirInputLoop
       ' check function key.
       IF LEN(I$) = 2 THEN
          VarQ = ASC(RIGHT$(I$, 1))
          IF VarQ >= 59 AND VarQ <= 68 THEN
             RETURN
          END IF
          IF VarQ >= 104 AND VarQ <= 113 THEN
             RETURN
          END IF
          IF VarQ = 133 OR VarQ = 134 THEN
             RETURN
          END IF
          Gosub GetAltKey
          IF VarZ THEN
             RETURN
          END IF
       END IF
       IF IsMenu >= 4 THEN
          RETURN
       END IF
       IF I$ = CHR$(9) THEN
          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
                GOSUB ClearFilename
                Box.Line = Box.Line + 1
                Current.File! = Current.File! + 1!
                GOSUB DisplayFilename1
                GOSUB DisplayLongName2
             ELSE
                Current.File! = Current.File! + 1!
                GOSUB DisplayFilename2
                GOSUB DisplayFileBox1
                GOSUB DisplayFilename3
                GOSUB DisplayLongName2
             END IF
             IF LEFT$(E$, 1) = I$ THEN
                EXIT DO
             END IF
             IF INKEY$ = CHR$(27) THEN
                EXIT DO
             END IF
          ELSE
             EXIT DO
          END IF
          R = ReleaseTime
       LOOP
       END SELECT
       I$ = Nul
    END IF
    IF LEN(I$) = 2 THEN
       GOSUB FileBoxKey
       IF Num.Files = 0 THEN
          I$ = CHR$(0) + CHR$(15)
          RETURN
       END IF
    END IF
 LOOP
 RETURN

' process key in file box.
FileBoxKey:
 V = ASC(RIGHT$(I$, 1))
 SELECT CASE V
 CASE 83 ' delete (added v7.6a 06/10/2007)
    ' check file.
    IF Num.Files > 0 THEN
       E$ = RTRIM$(Filenames(Current.File!))
       LOCATEf Xcoor + 1, Ycoor + 2, 1
       PRINTf SPACE$(38)
       LOCATEf Xcoor + 1, Ycoor + 2, 1
       COLORf2 White, 0
       PRINTf "Delete current file(y/n)? "
       ZQ$ = lineinput(Xcoor + 1, Ycoor + 27, 1)
       IF UCASE$(ZQ$) = "Y" THEN

          ' delete filename.
          G$ = MakeFilename$(N$, C$, D$, E$)
          ASCIIZ = G$ + CHR$(0)

          ' check windows dos
          IF Windows.Detected THEN
             ' change filename attribute
             InregsX.AX = &H7143
             InregsX.BX = &H1
             InregsX.CX = &H0
             InregsX.DS = VARSEG(ASCIIZ)
             InregsX.DX = VARPTR(ASCIIZ)
             CALL InterruptX(&H21, InregsX, OutregsX)
             ' delete long filename
             InregsX.AX = &H7141
             InregsX.DS = VARSEG(ASCIIZ)
             InregsX.DX = VARPTR(ASCIIZ)
             InregsX.SI = &H0
             InregsX.CX = &H0
             CALL InterruptX(&H21, InregsX, OutregsX)
          ELSE
             ' set file attributes
             InregsX.AX = &H4301
             InregsX.DS = VARSEG(ASCIIZ)
             InregsX.DX = VARPTR(ASCIIZ)
             InregsX.CX = &H0
             CALL InterruptX(&H21, InregsX, OutregsX)
             ' delete filename
             InregsX.AX = &H4100
             InregsX.DS = VARSEG(ASCIIZ)
             InregsX.DX = VARPTR(ASCIIZ)
             InregsX.CX = &H0
             CALL InterruptX(&H21, InregsX, OutregsX)
          END IF

          ' check carry flag error
          IF (OutregsX.Flags AND &H1) = &H1 THEN
             LOCATEf Xcoor + 1, Ycoor + 2, 1
             PRINTf SPACE$(38)
             LOCATEf Xcoor + 1, Ycoor + 2, 1
             COLORf2 White, 0
             PRINTf "Error deleting filename. Press <esc>:"
             WHILE INKEY$<>CHR$(27)
                R = ReleaseTime
             WEND
          ELSE
             ' init file box.
             GOSUB DisplayFilename6
             GOSUB ClearFileBox
             Z4$ = "Updating files.."
             CALL LoadFileSpec(FileY$,F$)
             GOSUB DisplayFileSpec
             GOSUB DisplayCurrentPath
             ' display first file.
             GOSUB ClearLongName2
             IF Num.Files > 0 THEN
                Current.File! = 1!
                Box.Line = 1
                GOSUB InitFiles
             END IF
          END IF
       END IF
       GOSUB DisplayFilename6
       GOSUB DisplayFileLine
       GOSUB DisplayLongName2
    END IF
 CASE 72 ' up
    IF Current.File! - 1 > 0 THEN
       IF Box.Line > 1 THEN
          GOSUB ClearFilename
          Box.Line = Box.Line - 1
          Current.File! = Current.File! - 1!
          GOSUB DisplayFilename1
          GOSUB DisplayLongName2
       ELSE
          Current.File! = Current.File! - 1!
          GOSUB DisplayFilename2
          GOSUB DisplayFileBox2
          GOSUB DisplayFilename4
          GOSUB DisplayLongName2
       END IF
    END IF
 CASE 80 ' down
    IF Current.File! + 1 <= Num.Files THEN
       IF Box.Line < 10 THEN
          GOSUB ClearFilename
          Box.Line = Box.Line + 1
          Current.File! = Current.File! + 1!
          GOSUB DisplayFilename1
          GOSUB DisplayLongName2
       ELSE
          Current.File! = Current.File! + 1!
          GOSUB DisplayFilename2
          GOSUB DisplayFileBox1
          GOSUB DisplayFilename3
          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
    GOSUB DisplayFilename2
    GOSUB DisplayFileBox2
    GOSUB DisplayFilename4
    GOSUB DisplayLongName2
 CASE 81 ' pgdn
    IF Current.File! + 10 <= Num.Files THEN
       Box.Line = 10
       Current.File! = Current.File! + 10!
       GOSUB DisplayFilename2
       GOSUB DisplayFileBox1
       GOSUB DisplayFilename3
       GOSUB DisplayLongName2
    ELSE
       IF Current.File! + 1 <= Num.Files THEN
          DO UNTIL Current.File! = Num.Files
             IF Box.Line < 10 THEN
                GOSUB ClearFilename
                Box.Line = Box.Line + 1
                Current.File! = Current.File! + 1!
                GOSUB DisplayFilename1
                GOSUB DisplayLongName2
             ELSE
                Current.File! = Current.File! + 1!
                GOSUB DisplayFilename2
                GOSUB DisplayFileBox1
                GOSUB DisplayFilename3
                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
    GOSUB DisplayFilename2
    GOSUB DisplayFileBox2
    GOSUB DisplayFilename4
    GOSUB DisplayLongName2
 CASE 79 ' end
    IF Current.File! + 1 <= Num.Files THEN
       DO UNTIL Current.File! = Num.Files
          IF Box.Line < 10 THEN
             GOSUB ClearFilename
             Box.Line = Box.Line + 1
             Current.File! = Current.File! + 1!
             GOSUB DisplayFilename1
             GOSUB DisplayLongName2
          ELSE
             Current.File! = Current.File! + 1!
             GOSUB DisplayFilename2
             GOSUB DisplayFileBox1
             GOSUB DisplayFilename3
             GOSUB DisplayLongName2
          END IF
       LOOP
    END IF
 END SELECT
 RETURN

' clear filename.
ClearFilename:
 CALL HMouse
 COLORf2 Plain, 0
 LOCATEf Box.Line + Xcoor + 4, Ycoor + 3, 1
 PRINTf LEFT$(RTRIM$(Filenames(Current.File!)), 12)
 CALL SMouse
 RETURN

' display filename.
DisplayFilename1:
 E$ = RTRIM$(Filenames(Current.File!))
 CALL HMouse
 COLORf2 Plain, 0
 LOCATEf Xcoor + 1, Ycoor + 12, 1
 PRINTf SPACE$(26)
 LOCATEf Xcoor + 1, Ycoor + 12, 1
 GOSUB TruncateFilename
 PRINTf A$
 COLORf2 Black, Plain
 LOCATEf Box.Line + Xcoor + 4, Ycoor + 3, 1
 PRINTf LEFT$(E$, 12)
 V9 = LEN(RTRIM$(LEFT$(E$, 12)))
 LOCATEf Box.Line + Xcoor + 4, Ycoor + V9 + 3, 1
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' display filename.
DisplayFilename2:
 E$ = RTRIM$(Filenames(Current.File!))
 CALL HMouse
 COLORf2 Plain, 0
 LOCATEf Xcoor + 1, Ycoor + 12, 1
 PRINTf SPACE$(26)
 LOCATEf Xcoor + 1, Ycoor + 12, 1
 GOSUB TruncateFilename
 PRINTf A$
 GOSUB ClearFileBox
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' display filename.
DisplayFilename3:
 E$ = RTRIM$(Filenames(Current.File!))
 CALL HMouse
 COLORf2 Black, Plain
 LOCATEf Xcoor + 14, Ycoor + 3, 1
 PRINTf LEFT$(E$, 12)
 V9 = LEN(RTRIM$(LEFT$(E$, 12)))
 LOCATEf Xcoor + 14, Ycoor + V9 + 3, 1
 CALL SMouse
 RETURN

' display filename.
DisplayFilename4:
 E$ = RTRIM$(Filenames(Current.File!))
 CALL HMouse
 COLORf2 Black, Plain
 LOCATEf Xcoor + 5, Ycoor + 3, 1
 PRINTf LEFT$(E$, 12)
 V9 = LEN(RTRIM$(LEFT$(E$, 12)))
 LOCATEf Xcoor + 5, Ycoor + V9 + 3, 1
 CALL SMouse
 RETURN

' display filename.
DisplayFilename5:
 E$ = RTRIM$(Filenames(Current.File!))
 CALL HMouse
 COLORf2 Black, Plain
 LOCATEf Box.Line + Xcoor + 4, Ycoor + 3, 1
 PRINTf LEFT$(E$, 12)
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' display filename line.
DisplayFilename6:
 CALL HMouse
 LOCATEf Xcoor + 1, Ycoor + 2, 1
 PRINTf SPACE$(38)
 LOCATEf Xcoor + 1, Ycoor + 2, 1
 COLORf2 White, 0
 PRINTf "Filename: "
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' update filename box.
DisplayFileBox1:
 CALL HMouse
 FOR V = 1 TO 9
    LOCATEf Xcoor - V + 14, Ycoor + 3, 1
    PRINTf LEFT$(RTRIM$(Filenames(Current.File! - V)), 12)
 NEXT
 CALL SMouse
 RETURN

' update filename box.
DisplayFileBox2:
 CALL HMouse
 FOR V = 1 TO 9
    IF Current.File! + V <= Num.Files THEN
       LOCATEf Xcoor + V + 5, Ycoor + 3, 1
       PRINTf LEFT$(RTRIM$(Filenames(Current.File! + V)), 12)
    END IF
 NEXT
 CALL SMouse
 RETURN

' display init directory.
DisplayInitDir:
 CALL HMouse
 Q$ = RTRIM$(Directories(Current.Dir!))
 LOCATEf Dir.Box.Line + Xcoor + 4, Ycoor + 19, 1
 COLORf2 Black, Plain
 PRINTf LEFT$(Q$, 12)
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' directory input loop.
DirInputLoop:
 GOSUB DisplayInitDir
 GOSUB DisplayLongName1
 I$ = Nul
 DO
    DO
       ' get keystroke.
       I$ = INKEY$
       IF LEN(I$) THEN
          IsMenu = False
          EXIT DO
       END IF

       ' call mouse subroutine.
       CALL MouseDriver1

       ' check file entry area.
       IF IsMenu >= 4 THEN
          RETURN
       END IF

       ' check left mouse button.
       IF Mouse.ButtonX THEN
          GOSUB MouseButton1Z
          SELECT CASE IsMenu
          CASE 1 ' file box.
             IF I$ = CHR$(13) THEN
                RETURN
             ELSE
                GOSUB FileBoxKey
             END IF
          CASE 2 ' dir box.
             IF I$ = CHR$(13) THEN
                RETURN
             ELSE
                GOSUB DirBoxKey
             END IF
          CASE 3 ' drive box.
             IF I$ = CHR$(13) THEN
                RETURN
             ELSE
                GOSUB DriveBoxKey
             END IF
          END SELECT
       ELSE
          ' check mouse position.
          IF Mouse.Row OR Mouse.Column THEN
             GOSUB MouseOverX1
          END IF
       END IF

       ' release time slice.
       R = ReleaseTime
    LOOP

    ' check function key.
    IF LEN(I$) = 2 THEN
       VarQ = ASC(RIGHT$(I$, 1))
       IF VarQ >= 59 AND VarQ <= 68 THEN
          RETURN
       END IF
       IF VarQ >= 104 AND VarQ <= 113 THEN
          RETURN
       END IF
       IF VarQ = 133 OR VarQ = 134 THEN
          RETURN
       END IF
       Gosub GetAltKey
       IF VarZ THEN
          RETURN
       END IF
    END IF

    ' up returns shift-tab.
    IF LEN(I$) = 2 THEN
       IF ASC(RIGHT$(I$, 1)) = 72 THEN
          IF Current.Dir! = 1! THEN
             IF Dir.Box.Line = 1 THEN
                I$ = CHR$(0) + CHR$(15)
             END IF
          END IF
       END IF
    END IF

    ' left returns shift-tab.
    IF LEN(I$) = 2 THEN
       IF ASC(RIGHT$(I$, 1)) = 75 THEN
          I$ = CHR$(0) + CHR$(15)
       END IF
    END IF

    ' shift-tab returns to file loop.
    IF LEN(I$) = 2 THEN
       IF ASC(RIGHT$(I$, 1)) = 15 THEN
          ' display current filename.
          GOSUB ClearLongName2
          IF Num.Files > 0 THEN
             GOSUB DisplayLongName2
             GOSUB ClearFilename
             GOSUB DisplayFilename1
          END IF
          ' display current directory.
          GOSUB ClearDirectory
          GOSUB DisplayCurrentPath
          RETURN
       END IF
    END IF

    ' right returns tab.
    IF LEN(I$) = 2 THEN
       IF ASC(RIGHT$(I$, 1)) = 77 THEN
          I$ = CHR$(9)
       END IF
    END IF

    ' Tab moves to drive input loop.
    IF I$ = CHR$(9) THEN
       GOSUB DriveInputLoop
       ' check function key.
       IF LEN(I$) = 2 THEN
          VarQ = ASC(RIGHT$(I$, 1))
          IF VarQ >= 59 AND VarQ <= 68 THEN
             RETURN
          END IF
          IF VarQ >= 104 AND VarQ <= 113 THEN
             RETURN
          END IF
          IF VarQ = 133 OR VarQ = 134 THEN
             RETURN
          END IF
          Gosub GetAltKey
          IF VarZ THEN
             RETURN
          END IF
       END IF
       IF IsMenu >= 3 THEN
          GOSUB DisplayCurrentPath
          IF Num.Files > 0 THEN
             GOSUB DisplayLongName2
          END IF
          RETURN
       END IF
       IF I$ = CHR$(9) THEN
          GOSUB DisplayCurrentPath
          IF Num.Files > 0 THEN
             GOSUB DisplayLongName2
          END IF
          RETURN
       END IF
       Q$ = RTRIM$(Directories(Current.Dir!))
       GOSUB DisplayLongName1
    END IF
    IF I$ = CHR$(13) THEN
       IsMenu = 2
       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
                GOSUB ClearDirectory
                Dir.Box.Line = Dir.Box.Line + 1
                Current.Dir! = Current.Dir! + 1!
                GOSUB DisplayDirectory
             ELSE
                GOSUB ClearDirBox
                Current.Dir! = Current.Dir! + 1!
                GOSUB DisplayDirBox1
                GOSUB DisplayDirectory2
             END IF
             Q$ = RTRIM$(Directories(Current.Dir!))
             GOSUB DisplayLongName1
             IF LEFT$(Q$, 1) = I$ THEN
                EXIT DO
             END IF
             IF INKEY$ = CHR$(27) THEN
                EXIT DO
             END IF
          ELSE
             EXIT DO
          END IF
          R = ReleaseTime
       LOOP
       END SELECT
       I$ = Nul
    END IF
    IF LEN(I$) = 2 THEN
       GOSUB DirBoxKey
    END IF
 LOOP
 RETURN

' clear directory.
ClearDirectory:
 CALL HMouse
 LOCATEf Dir.Box.Line + Xcoor + 4, Ycoor + 19, 1
 COLORf2 Plain, 0
 PRINTf LEFT$(RTRIM$(Directories(Current.Dir!)), 12)
 CALL SMouse
 RETURN

' display directory.
DisplayDirectory:
 CALL HMouse
 LOCATEf Dir.Box.Line + Xcoor + 4, Ycoor + 19, 1
 COLORf2 Black, Plain
 PRINTf LEFT$(RTRIM$(Directories(Current.Dir!)), 12)
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' display directory.
DisplayDirectory2:
 CALL HMouse
 COLORf2 Black, Plain
 LOCATEf Xcoor + 14, Ycoor + 19, 1
 PRINTf LEFT$(RTRIM$(Directories(Current.Dir!)), 12)
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' display directory.
DisplayDirectory3:
 CALL HMouse
 COLORf2 Black, Plain
 LOCATEf Xcoor + 5, Ycoor + 19, 1
 PRINTf LEFT$(RTRIM$(Directories(Current.Dir!)), 12)
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' update dir box.
DisplayDirBox1:
 CALL HMouse
 COLORf2 Plain, 0
 FOR V = 1 TO 9
    LOCATEf Xcoor - V + 14, Ycoor + 19, 1
    PRINTf LEFT$(RTRIM$(Directories(Current.Dir! - V)), 12)
 NEXT
 CALL SMouse
 RETURN

' update dir box.
DisplayDirBox2:
 CALL HMouse
 COLORf2 Plain, 0
 FOR V = 1 TO 9
    IF Current.Dir! + V <= Num.Dirs THEN
       LOCATEf Xcoor + V + 5, Ycoor + 19, 1
       PRINTf LEFT$(RTRIM$(Directories(Current.Dir! + V)), 12)
    END IF
 NEXT
 CALL SMouse
 RETURN

' process dir box key.
DirBoxKey:
 V = ASC(RIGHT$(I$, 1))
 SELECT CASE V
 CASE 82 ' insert (added v7.6a 06/10/2007)
    LOCATEf Xcoor + 1, Ycoor + 2, 1
    PRINTf SPACE$(38)
    LOCATEf Xcoor + 1, Ycoor + 2, 1
    COLORf2 White, 0

    ' get new path.
    PRINTf "Dir path: "
    ZQ$ = lineinput(Xcoor + 1, Ycoor + 12, 28)

    ' parse new path.
    IF LEN(ZQ$) THEN

       ' create new directory.
       G$ = MakeFilename$(N$, C$, D$, ZQ$)
       ASCIIZ = G$ + CHR$(0)

       ' check windows dos
       IF Windows.Detected THEN
          ' make directory
          InregsX.AX = &H7139
          InregsX.DS = VARSEG(ASCIIZ)
          InregsX.DX = VARPTR(ASCIIZ)
          CALL InterruptX(&H21, InregsX, OutregsX)
       ELSE
          ' make directory
          InregsX.AX = &H3900
          InregsX.DS = VARSEG(ASCIIZ)
          InregsX.DX = VARPTR(ASCIIZ)
          CALL InterruptX(&H21, InregsX, OutregsX)
       END IF

       ' check carry flag error
       IF (OutregsX.Flags AND &H1) = &H1 THEN
          LOCATEf Xcoor + 1, Ycoor + 2, 1
          PRINTf SPACE$(38)
          LOCATEf Xcoor + 1, Ycoor + 2, 1
          COLORf2 White, 0
          PRINTf "Error creating directory. Press <esc>:"
          WHILE INKEY$<>CHR$(27)
             R = ReleaseTime
          WEND
       ELSE
          ' redisplay dir box.
          GOSUB DisplayFilename6
          GOSUB ClearDirBox
          Z3$ = "Loading dirs.."
          CALL LoadDirSpec(DirY$,N$,C$,D$)
          GOSUB DisplayDirSpec
          GOSUB DisplayCurrentDir
          GOSUB DisplayCurrentPath
          ' display first directory.
          Current.Dir! = 1!
          Dir.Box.Line = 1
          GOSUB DisplayInitDir
       END IF
       GOSUB DisplayFilename6
       GOSUB DisplayFileLine
       GOSUB DisplayInitDir
       GOSUB DisplayLongName1
    END IF
 CASE 83 ' delete (added v7.6a 06/10/2007)
    ' check path.
    Q$ = RTRIM$(Directories(Current.Dir!))
    IF Q$ = "." OR Q$ = ".." THEN
       LOCATEf Xcoor + 1, Ycoor + 2, 1
       PRINTf SPACE$(38)
       LOCATEf Xcoor + 1, Ycoor + 2, 1
       COLORf2 White, 0
       PRINTf "Can't delete directory. Press <esc>:"
       WHILE INKEY$<>CHR$(27)
          R = ReleaseTime
       WEND
    ELSE
       LOCATEf Xcoor + 1, Ycoor + 2, 1
       PRINTf SPACE$(38)
       LOCATEf Xcoor + 1, Ycoor + 2, 1
       COLORf2 White, 0
       PRINTf "Delete current path(y/n)? "
       ZQ$ = lineinput(Xcoor + 1, Ycoor + 27, 1)
       IF UCASE$(ZQ$) = "Y" THEN

          ' delete directory.
          G$ = MakeFilename$(N$, C$, D$, Q$)
          ASCIIZ = G$ + CHR$(0)

          ' check windows dos
          IF Windows.Detected THEN
             ' delete directory
             InregsX.AX = &H713A
             InregsX.DS = VARSEG(ASCIIZ)
             InregsX.DX = VARPTR(ASCIIZ)
             CALL InterruptX(&H21, InregsX, OutregsX)
          ELSE
             ' delete directory
             InregsX.AX = &H3A00
             InregsX.DS = VARSEG(ASCIIZ)
             InregsX.DX = VARPTR(ASCIIZ)
             CALL InterruptX(&H21, InregsX, OutregsX)
          END IF

          ' check carry flag error
          IF (OutregsX.Flags AND &H1) = &H1 THEN
             LOCATEf Xcoor + 1, Ycoor + 2, 1
             PRINTf SPACE$(38)
             LOCATEf Xcoor + 1, Ycoor + 2, 1
             COLORf2 White, 0
             PRINTf "Error deleting directory. Press <esc>:"
             WHILE INKEY$<>CHR$(27)
                R = ReleaseTime
             WEND
          ELSE
             ' redisplay dir box.
             GOSUB DisplayFilename6
             GOSUB ClearDirBox
             Z3$ = "Loading dirs.."
             CALL LoadDirSpec(DirY$,N$,C$,D$)
             GOSUB DisplayDirSpec
             GOSUB DisplayCurrentDir
             GOSUB DisplayCurrentPath
             ' display first directory.
             Current.Dir! = 1!
             Dir.Box.Line = 1
             GOSUB DisplayInitDir
          END IF
       END IF
    END IF
    GOSUB DisplayFilename6
    GOSUB DisplayFileLine
    GOSUB DisplayInitDir
    GOSUB DisplayLongName1
 CASE 72 ' up
    IF Current.Dir! - 1 > 0 THEN
       IF Dir.Box.Line > 1 THEN
          GOSUB ClearDirectory
          Dir.Box.Line = Dir.Box.Line - 1
          Current.Dir! = Current.Dir! - 1!
          GOSUB DisplayDirectory
       ELSE
          GOSUB ClearDirBox
          Current.Dir! = Current.Dir! - 1!
          GOSUB DisplayDirBox2
          GOSUB DisplayDirectory3
       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
          GOSUB ClearDirectory
          Dir.Box.Line = Dir.Box.Line + 1
          Current.Dir! = Current.Dir! + 1!
          GOSUB DisplayDirectory
       ELSE
          GOSUB ClearDirBox
          Current.Dir! = Current.Dir! + 1!
          GOSUB DisplayDirBox1
          GOSUB DisplayDirectory2
       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
    GOSUB DisplayDirBox2
    GOSUB DisplayDirectory3
    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!
       GOSUB DisplayDirBox1
       GOSUB DisplayDirectory2
       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
                GOSUB ClearDirectory
                Dir.Box.Line = Dir.Box.Line + 1
                Current.Dir! = Current.Dir! + 1!
                GOSUB DisplayDirectory
             ELSE
                GOSUB ClearDirBox
                Current.Dir! = Current.Dir! + 1!
                GOSUB DisplayDirBox1
                GOSUB DisplayDirectory2
             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
    GOSUB DisplayDirBox2
    GOSUB DisplayDirectory3
    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
             GOSUB ClearDirectory
             Dir.Box.Line = Dir.Box.Line + 1
             Current.Dir! = Current.Dir! + 1!
             GOSUB DisplayDirectory
          ELSE
             GOSUB ClearDirBox
             Current.Dir! = Current.Dir! + 1!
             GOSUB DisplayDirBox1
             GOSUB DisplayDirectory2
          END IF
       LOOP
       Q$ = RTRIM$(Directories(Current.Dir!))
       GOSUB DisplayLongName1
    END IF
 END SELECT
 RETURN

' drive input loop.
DriveInputLoop:
 I$ = Nul
 DO
    GOSUB DisplayDrive
    DO
       ' get keystroke.
       I$ = INKEY$
       IF LEN(I$) THEN
          IsMenu = False
          EXIT DO
       END IF

       ' call mouse subroutine.
       CALL MouseDriver1

       ' check file entry area.
       IF IsMenu >= 4 THEN
          RETURN
       END IF

       ' check left mouse button.
       IF Mouse.ButtonX THEN
          GOSUB MouseButton1Z
          SELECT CASE IsMenu
          CASE 1 ' file box.
             IF I$ = CHR$(13) THEN
                RETURN
             ELSE
                GOSUB FileBoxKey
             END IF
          CASE 2 ' dir box.
             IF I$ = CHR$(13) THEN
                RETURN
             ELSE
                GOSUB DirBoxKey
             END IF
          CASE 3 ' drive box.
             IF I$ = CHR$(13) THEN
                RETURN
             ELSE
                GOSUB DriveBoxKey
             END IF
          END SELECT
       ELSE
          ' check mouse position.
          IF Mouse.Row OR Mouse.Column THEN
             GOSUB MouseOverX1
             GOSUB DisplayDrive
          END IF
       END IF

       ' release time slice.
       R = ReleaseTime
    LOOP

    ' check function key.
    IF LEN(I$) = 2 THEN
       VarQ = ASC(RIGHT$(I$, 1))
       IF VarQ >= 59 AND VarQ <= 68 THEN
          RETURN
       END IF
       IF VarQ >= 104 AND VarQ <= 113 THEN
          RETURN
       END IF
       IF VarQ = 133 OR VarQ = 134 THEN
          RETURN
       END IF
       Gosub GetAltKey
       IF VarZ THEN
          RETURN
       END IF
    END IF

    ' left returns shift-tab.
    IF LEN(I$) = 2 THEN
       IF ASC(RIGHT$(I$, 1)) = 75 THEN
          I$ = CHR$(0) + CHR$(15)
       END IF
    END IF

    ' shift-tab returns to directory loop.
    IF LEN(I$) = 2 THEN
       IF ASC(RIGHT$(I$, 1)) = 15 THEN
          I$ = Nul
          GOSUB DisplayDirectory
          RETURN
       END IF
    END IF

    ' up returns tab.
    IF LEN(I$) = 2 THEN
       IF ASC(RIGHT$(I$, 1)) = 72 THEN
          IF Current.Drive = 1 THEN
             IF Drive.Box.Line = 1 THEN
                I$ = CHR$(9)
             END IF
          END IF
       END IF
    END IF

    ' right returns tab.
    IF LEN(I$) = 2 THEN
       IF ASC(RIGHT$(I$, 1)) = 77 THEN
          I$ = CHR$(9)
       END IF
    END IF

    ' Tab returns to top loop.
    IF I$ = CHR$(9) THEN
       RETURN
    END IF

    ' select a drive.
    IF I$ = CHR$(13) THEN
       IsMenu = 3
       RETURN
    END IF

    ' exit from drive box.
    IF I$ = CHR$(27) THEN
       RETURN
    END IF

    ' process drive box keystroke.
    IF LEN(I$) = 2 THEN
       GOSUB DriveBoxKey
    END IF
 LOOP
 RETURN

GetAltKey:
 ' get alt keycode.
 Var = ASC(RIGHT$(I$, 1))
 VarZ = False
 ' compare all Alt-n keys
 FOR Var2 = 1 TO 26
    ' check key.
    IF Keys(Var2) = Var THEN
       VarZ = True
       Return
    END IF
 NEXT
 Return

' process drive box key.
DriveBoxKey:
 V = ASC(RIGHT$(I$, 1))
 SELECT CASE V
 CASE 72 ' up
    GOSUB MoveDriveUp
 CASE 80 ' down
    V6 = False
    GOSUB MoveDriveDown
 END SELECT
 RETURN

' move up one drive letter.
MoveDriveUp:
 IF Current.Drive - 1 > 0 THEN
    IF Drive.Box.Line > 1 THEN
       GOSUB ClearDrive
       Drive.Box.Line = Drive.Box.Line - 1
       Current.Drive = Current.Drive - 1
       GOSUB DisplayDrive
    ELSE
       Current.Drive = Current.Drive - 1
       GOSUB ClearDriveBox
       COLORf2 Plain, 0
       FOR V = 1 TO 9
          LOCATEf Xcoor + V + 5, Ycoor + 35, 0
          PRINTf "[" + CHR$(Current.Drive + V + 64) + "]"
       NEXT
       Drive.Box.Line = 1
       GOSUB DisplayDrive
    END IF
 END IF
 RETURN

' move down one drive letter with drive info.
MoveDriveDown:
 IF Current.Drive + 1 <= Last.Drive THEN
    IF Drive.Box.Line < 10 THEN
       GOSUB ClearDrive
       Drive.Box.Line = Drive.Box.Line + 1
       Current.Drive = Current.Drive + 1
       IF V6 = False THEN
          GOSUB DisplayDrive
       ELSE
          GOSUB DisplayDrive2
       END IF
    ELSE
       Current.Drive = Current.Drive + 1
       GOSUB ClearDriveBox
       COLORf2 Plain, 0
       FOR V = 1 TO 9
          LOCATEf Xcoor - V + 14, Ycoor + 35, 1
          PRINTf "[" + CHR$(Current.Drive - V + 64) + "]"
       NEXT
       Drive.Box.Line = 10
       IF V6 = False THEN
          GOSUB DisplayDrive
       ELSE
          GOSUB DisplayDrive2
       END IF
    END IF
 END IF
 RETURN

' display path with dir info.
DisplayCurrentPath:
 GOSUB DisplayCurrentPath3
 GOSUB DisplayLongName1
 RETURN

' display path w/o dir info.
DisplayCurrentPath2:
 GOSUB DisplayCurrentPath3
 GOSUB DisplayLongName3
 RETURN

' format pathname for display.
DisplayCurrentPath3:
 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$ = Nul THEN
    Q$ = "\"
 END IF
 RETURN

' display long directory with dir info.
DisplayLongName1:
 CALL HMouse
 COLORf2 Green, 1
 IF Xcoor + 17 <= 24 THEN
    Length = 80 - Ycoor - 1
    LOCATEf Xcoor + 17, Ycoor, 0
    PRINTf SPACE$(Length)
    LOCATEf Xcoor + 17, Ycoor, 0
    P$ = "Path: " + Q$
    IF LEN(P$) > Length THEN
       P$ = LEFT$(P$, Length - 3) + "..."
    END IF
    PRINTf P$
 END IF
 COLORf2 Plain, 0
 GOSUB DisplayDirInfo
 V = LEN(RTRIM$(Directories(Current.Dir!)))
 IF V > 12 THEN
    V = 12
 END IF
 LOCATEf Dir.Box.Line + Xcoor + 4, Ycoor + V + 19, 1
 CALL SMouse
 RETURN

' display long filename with file info.
DisplayLongName2:
 CALL HMouse
 COLORf2 Green, 1
 IF Xcoor + 18 <= 24 THEN
    Length = 80 - Ycoor - 1
    LOCATEf Xcoor + 18, Ycoor, 0
    PRINTf SPACE$(Length)
    LOCATEf Xcoor + 18, Ycoor, 0
    P$ = "File: " + E$
    IF LEN(P$) > Length THEN
       P$ = LEFT$(P$, Length - 3) + "..."
    END IF
    PRINTf P$
 END IF
 COLORf2 Plain, 0
 GOSUB DisplayFileInfo
 V = LEN(RTRIM$(Filenames(Current.File!)))
 IF V > 12 THEN
    V = 12
 END IF
 LOCATEf Box.Line + Xcoor + 4, Ycoor + V + 3, 1
 CALL SMouse
 RETURN

' display long directory w/o dir info.
DisplayLongName3:
 CALL HMouse
 COLORf2 Green, 1
 IF Xcoor + 17 <= 24 THEN
    Length = 80 - Ycoor - 1
    LOCATEf Xcoor + 17, Ycoor, 0
    PRINTf SPACE$(Length)
    LOCATEf Xcoor + 17, Ycoor, 0
    P$ = "Path: " + Q$
    IF LEN(P$) > Length THEN
       P$ = LEFT$(P$, Length - 3) + "..."
    END IF
    PRINTf P$
 END IF
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' display filename information.
DisplayFileInfo:
 CALL HMouse
 COLORf2 Green, 1
 IF Xcoor + 19 <= 24 THEN
    GOSUB GetFileInfo
    Var# = FileSize
    P$ = "Info: "
    IF Var# = DFalse THEN
       P$ = P$ + "zero"
    ELSE
       CALL FormatX(Value$, Var#, -1)
       P$ = P$ + Value$ + " "
       SELECT CASE FileSizeType
       CASE 1
          P$ = P$ + "KB"
       CASE 2
          P$ = P$ + "MB"
       CASE ELSE
          P$ = P$ + "B"
       END SELECT
       P$ = P$ +"."
    END IF
    SELECT CASE QuietSwitch
    CASE -1, 1, 3, 5
       ' nul
    CASE ELSE
       IF LEN(FileDateTime) THEN
          P$ = P$ + FileDateTime
       END IF
    END SELECT
    SELECT CASE QuietSwitch
    CASE -1, 2, 3, 6
       ' nul
    CASE ELSE
       GOSUB GetAttribute
    END SELECT
    GOSUB DisplayInfo
 END IF
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' display directory information.
DisplayDirInfo:
 CALL HMouse
 COLORf2 Green, 1
 IF Xcoor + 19 <= 24 THEN
    GOSUB GetDirInfo
    P$ = "Info: <dir>"
    SELECT CASE QuietSwitch
    CASE -1, 1, 3, 5
       ' nul
    CASE ELSE
       IF LEN(FileDateTime) THEN
          P$ = P$ + FileDateTime
       END IF
    END SELECT
    SELECT CASE QuietSwitch
    CASE -1, 2, 3, 6
       ' nul
    CASE ELSE
       GOSUB GetAttribute
    END SELECT
    GOSUB DisplayInfo
 END IF
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' display drive attribute.
DisplayDriveInfo:
 CALL HMouse
 COLORf2 Green, 1
 IF Xcoor + 19 <= 24 THEN
    P$ = "Info: " + CHR$(Current.Drive + 64) + ":\"
    CALL GetDriveInfo(DriveAttribute$)
    P$ = P$ + DriveAttribute$
    GOSUB DisplayInfo
 END IF
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' display file info.
DisplayInfo:
 Length = 80 - Ycoor - 1
 LOCATEf Xcoor + 19, Ycoor, 0
 PRINTf SPACE$(Length)
 LOCATEf Xcoor + 19, Ycoor, 0
 IF Ycoor + LEN(P$) >= 80 THEN
    P$ = LEFT$(P$, 80 - Ycoor - 1)
 END IF
 PRINTf P$
 RETURN

' get filesize, date/time, and attribute.
GetFileInfo:
 ' store long filename.
 W$ = MakeFilename$(N$, C$, D$, E$)
 ' set file.
 Var = &H27 ' file bit.
 ' get file info
 GOSUB ReadFileInfo
 RETURN

' get dir date/time, attribute.
GetDirInfo:
 ' store long filename.
 W$ = MakeFilename$(N$, C$, D$, Q$)
 ' set file.
 Var = &H37 ' dir bit.
 ' get file info
 GOSUB ReadFileInfo
 RETURN

' read file info.
ReadFileInfo:
 ' store dta.
 IF Windows.Detected = False THEN
    GOSUB SetDTA
 END IF
 ' store asciiz filename.
 ASCIIZ3 = W$ + CHR$(0)
 ' check windows/get file info.
 IF Windows.Detected THEN
    InregsX.AX = &H714E
    InregsX.CX = Var
    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
    ' get second
    IF FileSwitch = 1 THEN
       InregsX.AX = &H7143
       InregsX.BX = &H08
       InregsX.DS = VARSEG(ASCIIZ3)
       InregsX.DX = VARPTR(ASCIIZ3)
       CALL InterruptX(&H21, InregsX, OutregsX)
       Millisecond = OutregsX.SI
    END IF
 ELSE
    InregsX.AX = &H4E00
    InregsX.CX = Var
    InregsX.DS = VARSEG(ASCIIZ3)
    InregsX.DX = VARPTR(ASCIIZ3)
    CALL InterruptX(&H21, InregsX, OutregsX)
 END IF
 ' check findnext error.
 IF (OutregsX.Flags AND &H1) = &H0 THEN
    CALL GetInfo(-1,V$)
 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.
 IF Windows.Detected = False THEN
    GOSUB ResetDTA
 END IF
 RETURN

' get file/dir attribute.
GetAttribute:
 Call GetInfo(0,A$)
 IF A$ <> Nul THEN
    IF Ycoor + LEN(P$) + LEN(A$) < 80 THEN
       P$ = P$ + A$
    END IF
 END IF
 RETURN

' clear long directory area.
ClearLongName1:
 CALL HMouse
 COLORf2 Green, 1
 IF Xcoor + 17 <= 24 THEN
    Length = 80 - Ycoor - 1
    LOCATEf Xcoor + 17, Ycoor, 0
    PRINTf SPACE$(Length)
    LOCATEf Xcoor + 17, Ycoor, 0
    PRINTf "Path: "
 END IF
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' clear long filename area.
ClearLongName2:
 CALL HMouse
 COLORf2 Green, 1
 IF Xcoor + 18 <= 24 THEN
    Length = 80 - Ycoor - 1
    LOCATEf Xcoor + 18, Ycoor, 0
    PRINTf SPACE$(Length)
    LOCATEf Xcoor + 18, Ycoor, 0
    PRINTf "File: "
 END IF
 ' clear size area.
 IF Xcoor + 19 <= 24 THEN
    Length = 80 - Ycoor - 1
    LOCATEf Xcoor + 19, Ycoor, 0
    PRINTf SPACE$(Length)
    LOCATEf Xcoor + 19, Ycoor, 0
    PRINTf "Info: "
 END IF
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' construct new path.
GetNewPath:
 ' check filespec.
 IF INSTR(X$, "?") = False THEN
    IF INSTR(X$, "*") = False THEN
       X$ = "*.*"
       Xposition1 = 1
       Xposition2 = 3
    END IF
 END IF
 ' check file.
 IF X$ = Nul THEN
    X$ = "*.*"
    Xposition1 = 1
    Xposition2 = 3
 END IF
 ' store new path.
 Q$ = RTRIM$(Directories(Current.Dir!))
 ' store path to be parsed.
 X$ = Q$ + "\" + X$
 RETURN

' truncate filename for display.
TruncateFilename:
 A$ = RTRIM$(E$)
 IF LEN(A$) > 26 THEN
    A$ = LEFT$(A$, 23) + "..."
 END IF
 RETURN

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

' check path.
CheckPath:
 ' reset flag.
 ValidPath = True
 ' read path attributes.
 GOSUB ReadPath
 ' check path.
 IF D$ = Nul THEN
    RETURN
 END IF
 IF D$ = "\" THEN
    RETURN
 END IF
 ' check carry flag error.
 IF (OutregsX.Flags AND &H1) = &H1 THEN
    ValidPath = False
    RETURN
 END IF
 ' check filename is not path.
 IF (OutregsX.CX AND &H10) <> &H10 THEN
    ValidPath = False
 END IF
 RETURN

' read path/file attribute.
ReadPath:
 ' store directory.
 ASCIIZ = MakeFilename2$(N$, C$, D$) + CHR$(0)

 ' conanicalize filename.
 V4 = True
 GOSUB ShortFilenameX
 IF D$ = Nul THEN
    RETURN
 END IF
 IF D$ = "\" THEN
    RETURN
 END IF

 ' store filename.
 ASCIIZ = RTRIM$(Short.Filename$) + CHR$(0)

 ' check windows.
 IF Windows.Detected THEN
    ' get file attribute.
    InregsX.AX = &H7143
    InregsX.BX = &H0
    InregsX.DS = VARSEG(ASCIIZ)
    InregsX.DX = VARPTR(ASCIIZ)
    CALL InterruptX(&H21, InregsX, OutregsX)
 ELSE
    ' get file attribute.
    InregsX.AX = &H4300
    InregsX.DS = VARSEG(ASCIIZ)
    InregsX.DX = VARPTR(ASCIIZ)
    CALL InterruptX(&H21, InregsX, OutregsX)
 END IF
 RETURN

' display directory box.
DisplayDirSpec:
 CALL HMouse
 VarX! = SFalse
 DO
    VarX! = VarX! + 1!
    IF VarX! > 10! THEN
       EXIT DO
    END IF
    IF VarX! > Num.Dirs THEN
       EXIT DO
    END IF
    LOCATEf Cint(VarX!) + Xcoor + 4, Ycoor + 19, 1
    Q$ = Directories(VarX!)
    Q$ = RTRIM$(Q$)
    PRINTf LEFT$(Q$, 12)
 LOOP
 CALL SMouse
 RETURN

' clear directory box.
ClearDirBox:
 CALL HMouse
 FOR VarX = 1 TO 10
    LOCATEf VarX + Xcoor + 4, Ycoor + 19, 1
    PRINTf SPACE$(12)
 NEXT
 CALL SMouse
 RETURN

' display directory.
DisplayCurrentDir:
 ' ambiguate dospath.
 IF RIGHT$(D$, 2) = "\." THEN
    D$ = LEFT$(D$, LEN(D$) - 2)
 END IF
 ASCIIZ = MakeFilename4$(N$, C$, D$) + CHR$(0)
 V4 = True
 GOSUB ShortFilenameX
 IF Short.Filename$ = Nul THEN
    IF N$ = Nul THEN
       Short.Filename$ = C$ + ":\"
    ELSE
       Short.Filename$ = N$
    END IF
 END IF
 Z$ = Short.Filename$
 IF N$ = Nul THEN
    IF MID$(Z$, 2, 1) <> ":" THEN
       Z$ = C$ + ":" + Z$
    END IF
 ELSE
    IF MID$(Z$, 2, 1) = ":" THEN
       Z$ = MID$(Z$, 3)
    END IF
 END IF

 ' get deconcatenated filename.
 N1$ = N$
 CALL Deconcatenate(N$, Z$, 37)
 N$ = N1$

 ' display filename.
 CALL HMouse
 LOCATEf Xcoor + 2, Ycoor + 2, 1
 PRINTf SPACE$(37)
 LOCATEf Xcoor + 2, Ycoor + 2, 1
 PRINTf UCASE$(Z$)
 CALL SMouse
 RETURN

' display filename box.
DisplayFileSpec:
 CALL HMouse
 VarX! = SFalse
 DO
    VarX! = VarX! + 1!
    IF VarX! > 10! THEN
       EXIT DO
    END IF
    IF VarX! > Num.Files THEN
       EXIT DO
    END IF
    LOCATEf Cint(VarX!) + Xcoor + 4, Ycoor + 3, 1
    Q$ = Filenames(VarX!)
    Q$ = RTRIM$(Q$)
    PRINTf LEFT$(Q$, 12)
 LOOP
 CALL SMouse
 RETURN

' clear filename box.
ClearFileBox:
 CALL HMouse
 FOR VarX = 1 TO 10
    LOCATEf VarX + Xcoor + 4, Ycoor + 3, 1
    PRINTf SPACE$(12)
 NEXT
 CALL SMouse
 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

' format filename for display and search purposes.
ShortFilenameX:
 IF D$ = "\" THEN
    Short.Filename$ = "\"
    RETURN
 END IF
 IF D$ = Nul THEN
    Short.Filename$ = "\"
    RETURN
 END IF

 ' store filename.
 If Windows.Detected Then
    ' read ambiguated 8.3 filename.
    CALL GetShortFilename(Short.Filename$)
 Else
    Short.Filename$ = ASCIIZ
    Imbedded = Instr(Short.Filename$, Chr$(0))
    If Imbedded Then
       Short.Filename$ = Left$(Short.Filename$, Imbedded - 1)
    Endif
 Endif
 IF Short.Filename$ = Nul THEN
    RETURN
 END IF

 ' check 8.3 flag.
 IF V4 THEN
    RETURN
 END IF

 ' store 8.3 filename.
 FOR V = LEN(Short.Filename$) TO 1 STEP -1
    IF MID$(Short.Filename$, V, 1) = "\" THEN
       Short.Filename$ = MID$(Short.Filename$, V + 1)
       EXIT FOR
    END IF
 NEXT
 RETURN

' get default drives.
GetDrives:
 ' get current drive.
 InregsX.AX = &H1900
 CALL InterruptX(&H21, InregsX, OutregsX)
 Default.Drive = OutregsX.AX AND &HFF ' 0=a, 1=b,..

 ' get maximum drives.
 InregsX.AX = &H0E00
 InregsX.DX = Default.Drive
 CALL InterruptX(&H21, InregsX, OutregsX)
 Last.Drive = OutregsX.AX AND &HFF ' number of drives

 ' some old DOS functions return 0 - 63.
 IF Last.Drive > 26 THEN
    Last.Drive = 26
 END IF
 RETURN

' clear current drive.
ClearDrive:
 CALL HMouse
 COLORf2 Plain, 0
 LOCATEf Xcoor + Drive.Box.Line + 4, Ycoor + 35, 0
 PRINTf "[" + CHR$(Current.Drive + 64) + "]"
 CALL SMouse
 RETURN

' clear drive box.
ClearDriveBox:
 CALL HMouse
 FOR Var = 1 TO 10
    LOCATEf Xcoor + 4 + Var, Ycoor + 35, 1
    PRINTf "   "
 NEXT
 CALL SMouse
 RETURN

' display current drive with info.
DisplayDrive:
 GOSUB DisplayDriveInfo
 CALL HMouse
 COLORf2 Black, Plain
 LOCATEf Xcoor + Drive.Box.Line + 4, Ycoor + 35, 1
 PRINTf "[" + CHR$(Current.Drive + 64) + "]"
 LOCATEf Xcoor + Drive.Box.Line + 4, Ycoor + 38, 1
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' display current drive w/o info.
DisplayDrive2:
 CALL HMouse
 COLORf2 Black, Plain
 LOCATEf Xcoor + Drive.Box.Line + 4, Ycoor + 35, 1
 PRINTf "[" + CHR$(Current.Drive + 64) + "]"
 LOCATEf Xcoor + Drive.Box.Line + 4, Ycoor + 38, 1
 COLORf2 Plain, 0
 CALL SMouse
 RETURN

' display available drives.
DisplayDrives:
 CALL HMouse
 FOR Var = 1 TO Last.Drive
    IF Var > 10 THEN
       CALL SMouse
       RETURN
    END IF
    LOCATEf Xcoor + 4 + Var, Ycoor + 35, 1
    PRINTf "[" + CHR$(Var + 64) + "]"
 NEXT
 CALL SMouse
 RETURN

' display current drives.
InitDrives:
' init drive letter.
IF Current.Drive = False THEN
   Current.Drive = Drive.Number + 1
END IF
' display drives.
V3 = Current.Drive
IF V3 > Last.Drive THEN
   V3 = Last.Drive
END IF
GOSUB ClearDriveBox
Drive.Box.Line = 1
Current.Drive = 1
GOSUB DisplayDrives
GOSUB DisplayDrive2
' scroll to drive.
DO UNTIL Current.Drive >= V3
   V6 = True
   GOSUB MoveDriveDown
LOOP
GOSUB DisplayDriveInfo
RETURN

' process left mouse button single-click.
MouseButton1Z:
 ' store mouse variables.
 IsMenu = False
 Mouse.Row = Mouse.RowX
 Mouse.Column = Mouse.ColumnX
 ' file box pageup
 IF Mouse.Row = Xcoor + 4 THEN
    IF Mouse.Column = Ycoor + 16 THEN
       I$ = CHR$(0) + CHR$(73)
       IsMenu = 1
       RETURN
    END IF
 END IF
 ' file box up
 IF Mouse.Row = Xcoor + 5 THEN
    IF Mouse.Column = Ycoor + 16 THEN
       I$ = CHR$(0) + CHR$(72)
       IsMenu = 1
       RETURN
    END IF
 END IF
 ' file box down
 IF Mouse.Row = Xcoor + 14 THEN
    IF Mouse.Column = Ycoor + 16 THEN
       I$ = CHR$(0) + CHR$(80)
       IsMenu = 1
       RETURN
    END IF
 END IF
 ' file box pagedown
 IF Mouse.Row = Xcoor + 15 THEN
    IF Mouse.Column = Ycoor + 16 THEN
       I$ = CHR$(0) + CHR$(81)
       IsMenu = 1
       RETURN
    END IF
 END IF
 ' directory box pageup
 IF Mouse.Row = Xcoor + 4 THEN
    IF Mouse.Column = Ycoor + 32 THEN
       I$ = CHR$(0) + CHR$(73)
       IsMenu = 2
       RETURN
    END IF
 END IF
 ' directory box up
 IF Mouse.Row = Xcoor + 5 THEN
    IF Mouse.Column = Ycoor + 32 THEN
       I$ = CHR$(0) + CHR$(72)
       IsMenu = 2
       RETURN
    END IF
 END IF
 ' directory box down
 IF Mouse.Row = Xcoor + 14 THEN
    IF Mouse.Column = Ycoor + 32 THEN
       I$ = CHR$(0) + CHR$(80)
       IsMenu = 2
       RETURN
    END IF
 END IF
 ' directory box pagedown
 IF Mouse.Row = Xcoor + 15 THEN
    IF Mouse.Column = Ycoor + 32 THEN
       I$ = CHR$(0) + CHR$(81)
       IsMenu = 2
       RETURN
    END IF
 END IF
 ' drive box up
 IF Mouse.Row = Xcoor + 5 THEN
    IF Mouse.Column = Ycoor + 39 THEN
       I$ = CHR$(0) + CHR$(72)
       IsMenu = 3
       RETURN
    END IF
 END IF
 ' drive box down
 IF Mouse.Row = Xcoor + 14 THEN
    IF Mouse.Column = Ycoor + 39 THEN
       I$ = CHR$(0) + CHR$(80)
       IsMenu = 3
       RETURN
    END IF
 END IF
 ' check mouse selection boundaries for file box.
 IF Mouse.Row >= Xcoor + 5 AND Mouse.Row <= Xcoor + 14 THEN
    IF Mouse.Column >= Ycoor + 3 AND Mouse.Column <= Ycoor + 14 THEN
       IF Num.Files > 0 THEN
          I$ = Nul
          Valid = False
          V = Mouse.Row - (Xcoor + 4)
          IF V = Box.Line THEN
             Valid = True
          END IF
          IF V > Box.Line THEN
             IF Current.File! + (V - Box.Line) <= Num.Files THEN
                Current.File! = Current.File! + (V - Box.Line)
                Valid = True
             END IF
          END IF
          IF V < Box.Line THEN
             IF Current.File! - (Box.Line - V) > 0 THEN
                Current.File! = Current.File! - (Box.Line - V)
                Valid = True
             END IF
          END IF
          IF Valid THEN
             I$ = CHR$(13)
             IsMenu = 1
          END IF
       END IF
       RETURN
    END IF
 END IF
 ' check mouse selection boundaries for dir box.
 IF Mouse.Row >= Xcoor + 5 AND Mouse.Row <= Xcoor + 14 THEN
    IF Mouse.Column >= Ycoor + 19 AND Mouse.Column <= Ycoor + 31 THEN
       I$ = Nul
       Valid = False
       V = Mouse.Row - (Xcoor + 4)
       IF V = Dir.Box.Line THEN
          Valid = True
       END IF
       IF V > Dir.Box.Line THEN
          IF Current.Dir! + (V - Dir.Box.Line) <= Num.Dirs THEN
             Current.Dir! = Current.Dir! + (V - Dir.Box.Line)
             Valid = True
          END IF
       END IF
       IF V < Dir.Box.Line THEN
          IF Current.Dir! - (Dir.Box.Line - V) > 0 THEN
             Current.Dir! = Current.Dir! - (Dir.Box.Line - V)
             Valid = True
          END IF
       END IF
       IF Valid THEN
          I$ = CHR$(13)
          IsMenu = 2
       END IF
       RETURN
    END IF
 END IF
 ' check mouse selection boundaries for drive box.
 IF Mouse.Row >= Xcoor + 5 AND Mouse.Row <= Xcoor + 14 THEN
    IF Mouse.Column >= Ycoor + 35 AND Mouse.Column <= Ycoor + 37 THEN
       I$ = Nul
       Valid = False
       V = Mouse.Row - (Xcoor + 4)
       IF V = Drive.Box.Line THEN
          Valid = True
       END IF
       IF V > Drive.Box.Line THEN
          IF Current.Drive + (V - Drive.Box.Line) <= Last.Drive THEN
             GOSUB ClearDrive
             Current.Drive = Current.Drive + (V - Drive.Box.Line)
             Drive.Box.Line = Drive.Box.Line + (V - Drive.Box.Line)
             GOSUB DisplayDrive
             Valid = True
          END IF
       END IF
       IF V < Drive.Box.Line THEN
          IF Current.Drive - (Drive.Box.Line - V) > 0 THEN
             GOSUB ClearDrive
             Current.Drive = Current.Drive - (Drive.Box.Line - V)
             Drive.Box.Line = Drive.Box.Line - (Drive.Box.Line - V)
             GOSUB DisplayDrive
             Valid = True
          END IF
       END IF
       IF Valid THEN
          I$ = CHR$(13)
          IsMenu = 3
       END IF
       RETURN
    END IF
 END IF
 ' check mouse selection boundaries for file entry area.
 IF Mouse.Row = Xcoor + 1 THEN
    IF Mouse.Column >= Ycoor + 2 AND Mouse.Column <= Ycoor + 39 THEN
       I$ = Nul
       IsMenu = 4
       RETURN
    END IF
 END IF
 ' check mouse selection boundaries for file box help.
 IF Mouse.Row = Xcoor THEN
    IF Mouse.Column = Ycoor + 39 THEN
       I$ = Nul
       CALL HMouse
       CALL DisplayHelp
       GOSUB RedrawScreen
       CALL SMouse
       RETURN
    END IF
 END IF
 ' check mouse selection boundaries for file box exit.
 IF Mouse.Row = Xcoor THEN
    IF Mouse.Column = Ycoor + 40 THEN
       I$ = Nul
       IsMenu = 5
       RETURN
    END IF
 END IF
 RETURN

' mouseover for file/dir/drive boxes.
MouseOverX1:
 ' check mouse selection boundaries for file box.
 IF Mouse.Row >= Xcoor + 5 AND Mouse.Row <= Xcoor + 14 THEN
    IF Mouse.Column >= Ycoor + 3 AND Mouse.Column <= Ycoor + 14 THEN
       IF Num.Files > 0 THEN
          B1 = Mouse.Row - (Xcoor + 4)
          IF B1 > Box.Line THEN
             B2 = B1 - Box.Line
             IF B2 <= Num.Files THEN
                FOR B3 = 1 TO B2
                   IF Current.File! + 1 <= Num.Files THEN
                      IF Box.Line < 10 THEN
                         GOSUB ClearFilename
                         Box.Line = Box.Line + 1
                         Current.File! = Current.File! + 1!
                         GOSUB DisplayFilename5
                         GOSUB DisplayLongName2
                      END IF
                   END IF
                NEXT
             END IF
          ELSE
             IF B1 < Box.Line THEN
                B2 = Box.Line - B1
                IF B2 > 0 THEN
                   FOR B3 = 1 TO B2
                      IF Current.File! - 1 > 0 THEN
                         IF Box.Line > 1 THEN
                            GOSUB ClearFilename
                            Box.Line = Box.Line - 1
                            Current.File! = Current.File! - 1!
                            GOSUB DisplayFilename5
                            GOSUB DisplayLongName2
                         END IF
                      END IF
                   NEXT
                END IF
             ELSE
                IF B1 = Box.Line THEN
                   GOSUB ClearFilename
                   GOSUB DisplayFilename5
                   GOSUB DisplayLongName2
                END IF
             END IF
          END IF
       END IF
       RETURN
    END IF
 END IF
 ' check mouse selection boundaries for dir box.
 IF Mouse.Row >= Xcoor + 5 AND Mouse.Row <= Xcoor + 14 THEN
    IF Mouse.Column >= Ycoor + 19 AND Mouse.Column <= Ycoor + 31 THEN
       IF Num.Dirs > 0 THEN
          D1 = Mouse.Row - (Xcoor + 4)
          IF D1 > Dir.Box.Line THEN
             D2 = D1 - Dir.Box.Line
             IF D2 > 0 THEN
                IF D2 <= Num.Dirs THEN
                   FOR D3 = 1 TO D2
                      IF Current.Dir! + 1 <= Num.Dirs THEN
                         IF Dir.Box.Line < 10 THEN
                            GOSUB ClearDirectory
                            Dir.Box.Line = Dir.Box.Line + 1
                            Current.Dir! = Current.Dir! + 1!
                            GOSUB DisplayDirectory
                            Q$ = RTRIM$(Directories(Current.Dir!))
                            GOSUB DisplayLongName1
                         END IF
                      END IF
                   NEXT
                END IF
             END IF
          ELSE
             IF D1 < Dir.Box.Line THEN
                D2 = Dir.Box.Line - D1
                IF D2 > 0 THEN
                   IF D2 <= Num.Dirs THEN
                      FOR D3 = 1 TO D2
                         IF Current.Dir! - 1 > 0 THEN
                            IF Dir.Box.Line > 1 THEN
                               GOSUB ClearDirectory
                               Dir.Box.Line = Dir.Box.Line - 1
                               Current.Dir! = Current.Dir! - 1!
                               GOSUB DisplayDirectory
                               Q$ = RTRIM$(Directories(Current.Dir!))
                               GOSUB DisplayLongName1
                            END IF
                         END IF
                      NEXT
                   END IF
                END IF
             ELSE
                IF D1 = Dir.Box.Line THEN
                   GOSUB DisplayDirectory
                   Q$ = RTRIM$(Directories(Current.Dir!))
                   GOSUB DisplayLongName1
                END IF
             END IF
          END IF
       END IF
       RETURN
    END IF
 END IF
 ' check mouse selection boundaries for drive box.
 IF Mouse.Row >= Xcoor + 5 AND Mouse.Row <= Xcoor + 14 THEN
    IF Mouse.Column >= Ycoor + 35 AND Mouse.Column <= Ycoor + 37 THEN
       X0 = Mouse.Row - (Xcoor + 4)
       IF X0 > Drive.Box.Line THEN
          X1 = Current.Drive + (X0 - Drive.Box.Line)
          IF X1 <= Last.Drive THEN
             GOSUB ClearDrive
             Current.Drive = Current.Drive + (X0 - Drive.Box.Line)
             Drive.Box.Line = Drive.Box.Line + (X0 - Drive.Box.Line)
             GOSUB DisplayDrive
          END IF
       ELSE
          IF X0 < Drive.Box.Line THEN
             X1 = Current.Drive - (Drive.Box.Line - X0)
             IF X1 > 0 THEN
                GOSUB ClearDrive
                Current.Drive = Current.Drive - (Drive.Box.Line - X0)
                Drive.Box.Line = Drive.Box.Line - (Drive.Box.Line - X0)
                GOSUB DisplayDrive
             END IF
          ELSE
             IF X0 = Drive.Box.Line THEN
                GOSUB DisplayDrive
             END IF
          END IF
       END IF
    END IF
 END IF
 RETURN

' redraws editing screen.
RedrawScreen:
 COLORf2 White, 1
 CLS
 CALL FileMainMenu
 GOSUB UpdateDisplay
 GOSUB DisplayCurrentPath
 IF Num.Files > 0 THEN
    GOSUB DisplayLongName2
 END IF
 GOSUB DisplayFilename6
 GOSUB DisplayFileLine
 RETURN

' error routine.
Error.Routine:
 ErrorTrap = ERR
 ' verify disk letter.
 IF Check.Disk THEN
    Select Case ErrorTrap
    Case 53, 57, 64, 68, 70, 71, 76
       Disk.Ready = True
       RESUME NEXT
    END Select
 END IF
 ' display error.
 COLORf2 White, 0
 CLS
 LOCATEf Csrlin, 1, 0
 PRINTf "Hex Editor Menu " + Version + " " + Release + " critical error trap:"
 ' display error.
 COLORf Yellow
 LOCATEf Csrlin+1, 1, 0
 CALL DisplayCriticalError(ErrorTrap)
 ' display error and exit.
 COLORf Green
 LOCATEf Csrlin+1, 1, 0
 PRINTf "Check TEMP variables, .CFG file, or DOS file handles, then restart."
 COLORf Plain
 CALL ResetTrap
 END
END SUB

REM End-of-subprogram. Writing code is the easiest thing in the world.
