%TITLE          "Atari 8bit Direcotry Lister - CHiPS bv 1997"
;**********************************************************************
;**                                                                  **
;**  Program   : Xdir                                                **
;**  Purpose   : Atari 8bit Directory Lister                         **
;**                                                                  **
;**  Author    : B.F. Schreurs                                       **
;**              Computer High Performance Software (CHiPS) bv       **
;**  Date      : September 2nd, 1997                                 **
;**                                                                  **
;**  Calls     : XFILES                                              **
;**              DC_DRV                                              **
;**                                                                  **
;**  Language  : Turbo Assembler                                     **
;**                                                                  **
;**********************************************************************
        IDEAL
        JUMPS

;----------------------------------------------------------------------
;--  Equates                                                         --
;----------------------------------------------------------------------
include ".\equ\sysdep.equ"
include ".\equ\video.equ"
include ".\equ\equipmnt.equ"
include ".\equ\keyboard.equ"
include ".\equ\dos.equ"
include ".\equ\attrib.equ"

MAX_ENTRIES_IN_FILE_TABLE   EQU   2000  ; Maximum nr of Entries for File table
FILE_NAME_LENGTH            EQU     12  ; Filename      +
                                        ; "."           +
                                        ; Extension
MAX_SUB_DIRECTORIES         EQU    30   ; Remember a max of 30 subdirs
SUB_DIRECTORY_ENTRY_LENGTH  EQU    15   ; Dirname       +
                                        ; "."           +
                                        ; Extension     +
                                        ; Xdir_Window   +
                                        ; Xdir_Window_File
FILE_SIZE_LENGTH            EQU    14
FILE_ENTRY_LENGTH           EQU    17   ; Filename      +
                                        ; "."           +
                                        ; Extension     +
                                        ; FileAttribute +
                                        ; FileSize
XDISK_SECTORS_SINGLE         EQU    720
XDISK_SECTORS_MEDIUM         EQU   1040
XDISK_SECTORS_ENHANCED       EQU   1120
XDISK_SECTORS_DOUBLE         EQU   1440

XFILE_SIZE_LENGTH           EQU    04
XDIR_START_ROW              EQU    01
XDIR_START_COL              EQU    00
XDIR_END_ROW                EQU    25
XDIR_END_COL                EQU    79
XDIR_FILE_START_ROW         EQU    02
XDIR_FILE_START_COL         EQU    10
XDIR_FILE_END_ROW           EQU    02
XDIR_FILE_END_COL           EQU    21
XDIR_ENTRY_START_ROW        EQU    05
XDIR_ENTRY_START_COL        EQU    01
XDIR_ENTRY_END_ROW          EQU    24
XDIR_ENTRY_END_COL          EQU    26
XDIR_8BIT_VTOC_START_ROW    EQU    02
XDIR_8BIT_VTOC_START_COL    EQU    30
XDIR_8BIT_VTOC_END_ROW      EQU    24
XDIR_8BIT_VTOC_END_COL      EQU    79
XDIR_PATH_LENGTH            EQU    21
MAX_ROW                     EQU    25
MAX_COL                     EQU    80
COMMENT_ROW                 EQU    "#"

XDIR_STATUS_FILE            EQU     1   ; File  Mode
XDIR_STATUS_DRIVE           EQU     2   ; Drive Mode
XDIR_STATUS_ENTRY           EQU     3   ; Entry Mode

ATR_HEADER_SIZE             EQU     16
ATR_HEADER_SIZE_COMPARE     EQU      8
EIGHTBIT_VTOC_OFFSET        EQU  0B400h
EIGHTBIT_VTOC_FILES         EQU     64
VTOC_FILES_COLUMN_ENTRIES   EQU     22
XFILE_ENTRY_SIZE            EQU     16
EIGHTBIT_FILE_ENTRY_SIZE    EQU     16
EIGHTBIT_SECTOR_SIZE        EQU    128
EIGHTBIT_VTOC_SIZE          EQU   1024
DISK_BLOCK_SIZE             EQU   1024

; Xdir      Characters              ....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
;                           Column: 12345678901234567890123456789012345678901234567890123456789012345678901234567890
AC_01                       EQU   <"ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍ[Directory Lister]ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»">
AC_02                       EQU   <"ºFileName: MYFILE.DAT      º                                                   º">
AC_03                       EQU   <"ºABCD                      º                                                   º">
AC_04                       EQU   <"ºPath:\DATA\*.DAT          º                                                   º">
AC_05                       EQU   <"º[..]           [Directory]º                                                   º">
AC_06                       EQU   <"ºSHAREDIR       [Directory]º                                                   º">
AC_07                       EQU   <"ºMYDIR          [Directory]º                                                   º">
AC_08                       EQU   <"ºYOURFILE.DAT         9,321º                                                   º">
AC_09                       EQU   <"ºMYFILE  .DAT           122º                                                   º">
AC_10                       EQU   <"º                          º                                                   º">
AC_11                       EQU   <"º                          º                    Xdir - v5.00                   º">
AC_12                       EQU   <"º                          º                                                   º">
AC_13                       EQU   <"º                          º                  by B.F. Schreurs                 º">
AC_14                       EQU   <"º                          º                 Public Domain 1996                º">
AC_15                       EQU   <"º                          º               Email: stack@xs4all.nl              º">
AC_16                       EQU   <"º                          º                                                   º">
AC_17                       EQU   <"º                          º                                                   º">
AC_18                       EQU   <"º                          º                                                   º">
AC_19                       EQU   <"º                          º                                                   º">
AC_20                       EQU   <"º                          º                                                   º">
AC_21                       EQU   <"º                          º                                                   º">
AC_22                       EQU   <"º                          º                                                   º">
AC_23                       EQU   <"º                          º                                                   º">
AC_24                       EQU   <"º                          º                                                   º">
AC_25                       EQU   <"ÈÍÍÍ[Press F1 for HELP!]ÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ¼">

; Xdir HELP Characters               ...+....1....+....2....+...
;                           Column:  234567890123456789012345678
BC_02                       EQU    <"       FILEMASK           ">
BC_03                       EQU    <"TAB  : to tab to Drives   ">
BC_04                       EQU    <"ENTER: to process Mask    ">
BC_05                       EQU    <"HOME : go to begin of Mask">
BC_06                       EQU    <"END  : go to end of Mask  ">
BC_07                       EQU    <"CURSOR KEYS to navigate   ">
BC_08                       EQU    <"       DRIVES             ">
BC_09                       EQU    <"TAB  : to tab to Dir/Files">
BC_10                       EQU    <"       Entries or FileMask">
BC_11                       EQU    <"ENTER: to select the Drive">
BC_12                       EQU    <"HOME : go to first Drive  ">
BC_13                       EQU    <"END  : go to last Drive   ">
BC_14                       EQU    <"CURSOR KEYS to navigate   ">
BC_15                       EQU    <"       FILES/DIRS         ">
BC_16                       EQU    <"TAB  : to tab to FileMask ">
BC_17                       EQU    <"ENTER: Select/Extract File">
BC_18                       EQU    <"HOME : First occurrence   ">
BC_19                       EQU    <"END  : Last  occurrence   ">
BC_20                       EQU    <"PG UP: Previous Dir/Files ">
BC_21                       EQU    <"PG DN: Next     Dir/Files ">
BC_22                       EQU    <"CURSOR KEYS to navigate   ">
BC_23                       EQU    <"       EXIT PROGRAM       ">
BC_24                       EQU    <"ESC  : ESCape to exit     ">
BC_25                       EQU    <"ÍÍÍÍÍÍPress any keyÍÍÍÍÍÍÍ">

; Xdir Disk Characters              3....+....4....+....5....+....6....+....7....+....
;                           Column: 01234567890123456789012345678901234567890123456789
CC_02                       EQU   <"                      Atari                       ">
CC_03                       EQU   <"00000001.DAT 000³00000023.DAT 000³00000045.DAT 000">
CC_04                       EQU   <"00000002.DAT 000³00000024.DAT 000³00000046.DAT 000">
CC_05                       EQU   <"00000003.DAT 000³00000025.DAT 000³00000047.DAT 000">
CC_06                       EQU   <"00000004.DAT 000³00000026.DAT 000³00000048.DAT 000">
CC_07                       EQU   <"00000005.DAT 000³00000027.DAT 000³00000049.DAT 000">
CC_08                       EQU   <"00000006.DAT 000³00000028.DAT 000³00000050.DAT 000">
CC_09                       EQU   <"00000007.DAT 000³00000029.DAT 000³00000051.DAT 000">
CC_10                       EQU   <"00000008.DAT 000³00000030.DAT 000³00000052.DAT 000">
CC_11                       EQU   <"00000009.DAT 000³00000031.DAT 000³00000053.DAT 000">
CC_12                       EQU   <"00000010.DAT 000³00000032.DAT 000³00000054.DAT 000">
CC_13                       EQU   <"00000011.DAT 000³00000033.DAT 000³00000055.DAT 000">
CC_14                       EQU   <"00000012.DAT 000³00000034.DAT 000³00000056.DAT 000">
CC_15                       EQU   <"00000013.DAT 000³00000035.DAT 000³00000057.DAT 000">
CC_16                       EQU   <"00000014.DAT 000³00000036.DAT 000³00000058.DAT 000">
CC_17                       EQU   <"00000015.DAT 000³00000037.DAT 000³00000059.DAT 000">
CC_18                       EQU   <"00000016.DAT 000³00000038.DAT 000³00000060.DAT 000">
CC_19                       EQU   <"00000017.DAT 000³00000039.DAT 000³00000061.DAT 000">
CC_20                       EQU   <"00000018.DAT 000³00000040.DAT 000³00000062.DAT 000">
CC_21                       EQU   <"00000019.DAT 000³00000041.DAT 000³00000063.DAT 000">
CC_22                       EQU   <"00000020.DAT 000³00000042.DAT 000³00000064.DAT 000">
CC_23                       EQU   <"00000021.DAT 000³00000043.DAT 000³                ">
CC_24                       EQU   <"00000022.DAT 000³00000044.DAT 000³Free Sectors 000">

; Xdir Disk Characters              3....+....4....+....5....+....6....+....7....+....
;                           Column: 01234567890123456789012345678901234567890123456789
DC_02                       EQU   <"                                                  ">
DC_03                       EQU   <"                                                  ">
DC_04                       EQU   <"                                                  ">
DC_05                       EQU   <"                                                  ">
DC_06                       EQU   <"                                                  ">
DC_07                       EQU   <"                                                  ">
DC_08                       EQU   <"                                                  ">
DC_09                       EQU   <"                                                  ">
DC_10                       EQU   <"                                                  ">
DC_11                       EQU   <"                   Xdir - v5.00                   ">
DC_12                       EQU   <"                                                  ">
DC_13                       EQU   <"                 by B.F. Schreurs                 ">
DC_14                       EQU   <"                Public Domain 1996                ">
DC_15                       EQU   <"              Email: stack@xs4all.nl              ">
DC_16                       EQU   <"                                                  ">
DC_17                       EQU   <"                                                  ">
DC_18                       EQU   <"                                                  ">
DC_19                       EQU   <"                                                  ">
DC_20                       EQU   <"                                                  ">
DC_21                       EQU   <"                                                  ">
DC_22                       EQU   <"                                                  ">
DC_23                       EQU   <"                                                  ">
DC_24                       EQU   <"                                                  ">

; Xdir      Attributes Symbolics    ....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
;                           Column: 12345678901234567890123456789012345678901234567890123456789012345678901234567890
AS_01                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc">
AS_02                       EQU   <"cCCCCCCCCC            CCCCCcc                                                  c">
AS_03                       EQU   <"cbbbbbbbbbbbbbbbbbbbbbbbbbbcc                                                  c">
AS_04                       EQU   <"cCCCCCccccccccccccccccccccccc                                                  c">
AS_05                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_06                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_07                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_08                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_09                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_10                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_11                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_12                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_13                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_14                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_15                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_16                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_17                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_18                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_19                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_20                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_21                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_22                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_23                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_24                       EQU   <"cuuuuuuuuuuuuuuuuuuuuuuuuuucc                                                  c">
AS_25                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc">

; Screen B  Attributes Symbolics    ....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
;                           Column: 12345678901234567890123456789012345678901234567890123456789012345678901234567890
BS_02                       EQU    <"cccccccccccccccccccccccccc">
BS_03                       EQU    <"RRRRRRRRRRRRRRRRRRRRRRRRRR">
BS_04                       EQU    <"cccccccccccccccccccccccccc">
BS_05                       EQU    <"cccccccccccccccccccccccccc">
BS_06                       EQU    <"cccccccccccccccccccccccccc">
BS_07                       EQU    <"cccccccccccccccccccccccccc">
BS_08                       EQU    <"cccccccccccccccccccccccccc">
BS_09                       EQU    <"RRRRRRRRRRRRRRRRRRRRRRRRRR">
BS_10                       EQU    <"cccccccccccccccccccccccccc">
BS_11                       EQU    <"cccccccccccccccccccccccccc">
BS_12                       EQU    <"cccccccccccccccccccccccccc">
BS_13                       EQU    <"cccccccccccccccccccccccccc">
BS_14                       EQU    <"cccccccccccccccccccccccccc">
BS_15                       EQU    <"cccccccccccccccccccccccccc">
BS_16                       EQU    <"RRRRRRRRRRRRRRRRRRRRRRRRRR">
BS_17                       EQU    <"cccccccccccccccccccccccccc">
BS_18                       EQU    <"cccccccccccccccccccccccccc">
BS_19                       EQU    <"cccccccccccccccccccccccccc">
BS_20                       EQU    <"cccccccccccccccccccccccccc">
BS_21                       EQU    <"cccccccccccccccccccccccccc">
BS_22                       EQU    <"cccccccccccccccccccccccccc">
BS_23                       EQU    <"RRRRRRRRRRRRRRRRRRRRRRRRRR">
BS_24                       EQU    <"cccccccccccccccccccccccccc">
BS_25                       EQU    <"cccccccccccccccccccccccccc">

; Screen D  Attributes Symbolics    ....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
;                           Column: 12345678901234567890123456789012345678901234567890123456789012345678901234567890
DS_02                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_03                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_04                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_05                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_06                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_07                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_08                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_09                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_10                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_11                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_12                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_13                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_14                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_15                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_16                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_17                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_18                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_19                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_20                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_21                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_22                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_23                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">
DS_24                       EQU   <"cccccccccccccccccccccccccccccccccccccccccccccccccc">



;**********************************************************************
SEGMENT SSeg Para Stack 'STACK'
;**********************************************************************

        db        64 dup (0)            ; Stack

ENDS    SSeg



;**********************************************************************
SEGMENT DSeg Word Public 'DATA'
;**********************************************************************

;----------------------------------------------------------------------
;--  Structures                                                      --
;----------------------------------------------------------------------
include ".\str\dta.str"
include ".\str\xdisk.str"
include ".\str\position.str"
include ".\str\charactr.str"

Struc   File_Entry
  File_Name             DB  12  dup (0) ; Filename
  File_Attribute        DB   1  dup (0) ; See File Attribute description
  File_Size_Low_Low     DB   1  dup (0)
  File_Size_Low_High    DB   1  dup (0)
  File_Size_High_Low    DB   1  dup (0)
  File_Size_High_High   DB   1  dup (0)
ends                                    ; File_Entry



;----------------------------------------------------------------------
;--  Working Storage                                                 --
;----------------------------------------------------------------------
GLOBAL Disk_Parameters:XDisk_Parameters
GLOBAL Drive_Map:Byte:MAX_DRIVES
GLOBAL Return_Code:Byte:1

Disk_Parameters         XDisk_Parameters <>
Return_Code             DB      0

Path_Spec               DB  "C:\*.*"
                        DB  256 dup (SPACE)
                        DB    1 dup (0)  

DOS_Find_Files_Or_Dirs  DW    1 dup (DOS_FIND_DIRECTORIES)
XDIR_Status             DB    1 dup (XDIR_STATUS_ENTRY)

Msg_Error               DB    26 dup (SPACE)
Msg_No_Files_Found      DB    "No Files Found            "
Msg_Drive_Not_Ready     DB    "Drive Not Ready           "

Disk_Media_Type         DW    00007h            ; Set to 1.44 MB
Media_ID_Buffer         DB   25 dup (?)

File_Table_Length        = ( FILE_ENTRY_LENGTH * MAX_ENTRIES_IN_FILE_TABLE )
File_Table              DB  File_Table_Length dup (0)
                        DB    1 dup (0)         ; End of File Table
File_Table_Entry        File_Entry <>
Temp_Entry              File_Entry <>
Files_In_File_Table     DW    0

Max_Files_In_Xdir_Table   = ( XDIR_ENTRY_END_ROW - XDIR_ENTRY_START_ROW + 1 )
Xdir_Table_Entry_Length   = ( XDIR_ENTRY_END_COL - XDIR_ENTRY_START_COL + 1 )

Xdir_Config_File_Spec   DB  "C:\XDIR.CFG    "   ; Xdir's configuration file
                        DB    1 dup (0)
Xdir_Config_Parameter   DB  256 dup (SPACE)
                        DB    1 dup (0)
Default_Drive           DB  "Z:"                ; Drive will be replaced
Default_Path            DB  "\*.*         "
Oversized_Path          DB  "\.."               ; When path does not fit
File_Spec               DB   12 dup (SPACE)     ; File selected
Original_Path           DB  256 dup (SPACE)
                        DB    1 dup (0)
Search_Spec_Drive       DB  "   "               ; Path Specification
Search_Spec_Dir         DB  253 dup (SPACE)
                        DB    1 dup (0)
Path_File_Spec          DB  256 dup (SPACE)
                        DB    1 dup (0)
XFile_No_Entry          DB   16 dup (SPACE)

File_File_Text          DB    "FileName"
File_Mask_Text          DB    "FileMask"
File_Mask               DB    "\*.*         "
                        DB    1 dup (SPACE)     ; Used when scanned for space
                                                ; and Mask completely entered
Old_File_Mask           DB   13 dup (?)
File_Mask_Key_Valid     DB  KEY_ALPHABETIC_UPPERCASE
                        DB  KEY_ALPHABETIC_LOWERCASE
                        DB  KEY_NUMERIC
                        DB  KEY_VALID_DOS
                        DB  KEY_VALID_MASK
                        DB  KEY_DELETE
                        DB  KEY_BACKSPACE
                        DB  NULL
File_Mask_To_Uppercase  DB  KEY_ALPHABETIC_LOWERCASE
                        DB  NULL
File_Dot_Used           DB    1 dup (FALSE)     ; Is the "." already used?
File_Valid              DB    1 dup (FALSE)     ; Is the Filename a valid one?
File_Exist              DB    1 dup (FALSE)     ; Does the file already exist?

Current_Sub_Directory   DB    0                 ; In which subdirectory are we
Sub_Directory_Indicator DB  ".."
Sub_Directories_Length   = ( SUB_DIRECTORY_ENTRY_LENGTH * MAX_SUB_DIRECTORIES )
Sub_Directories         DB  Sub_Directories_Length dup (SPACE)

Old_Dta_Seg             DW    ?                 ; Old Dta Segment Address
Old_Dta_Ofs             DW    ?                 ; Old Dta Segment Offset
Own_Dta                 Dta <>

Disk_Handler            DW      0
Disk_I_O_Buffer         DB  DISK_BLOCK_SIZE dup (0)

ATR_Header_Single       DB   96h,02h,80h,16h,80h,00h,00h,00h
ATR_Header_Medium       DB   96h,02h,80h,20h,80h,00h,00h,00h
ATR_Header_Enhanced     DB   96h,02h,00h,23h,80h,00h,00h,00h
ATR_Header_Double       DB   96h,02h,00h,2Dh,80h,00h,00h,00h

Directory_Above         DB  "[..]        "
Directory               DB  "   [Directory]"
File_Size_Init          DB  "   000,000,000"
File_Size_Text          DB  "   000,000,000"
XFile_Size_Init         DB  "0000"
XFile_Size_Text         DB  "0000"
XFile_Deleted           DB    1 dup (LOGIC_NO)
XFile_Locked            DB    1 dup (LOGIC_NO)
XFile_Extended          DB    1 dup (LOGIC_NO)
XFile_Inverse           DB    1 dup (LOGIC_NO)
XDisk_Done              DB    1 dup (LOGIC_NO)
XDisk_Sectors_Free      DW  XDISK_SECTORS_SINGLE

Save_Cursor_Position    Position <000h, 000h>
Temp_Cursor_Position    Position <000h, 000h>
Cursor_Position         Position <000h, 000h>

Screen_Rows              = XDIR_END_ROW - XDIR_START_ROW + 1
Screen_Cols              = XDIR_END_COL - XDIR_START_COL + 1
Screen_Cols_Help         = XDIR_ENTRY_END_COL - XDIR_ENTRY_START_COL + 1
XFile_Rows               = XDIR_8BIT_VTOC_END_ROW - XDIR_8BIT_VTOC_START_ROW + 1
XFile_Cols               = XDIR_8BIT_VTOC_END_COL - XDIR_8BIT_VTOC_START_COL + 1
Offset_Drive_Map_Attr    = Screen_Cols * 2 + 1
Screen_Size              = Screen_Rows * Screen_Cols
Help_Screen_Size         = ( Screen_Rows - 1 ) * ( Screen_Cols - 2 ) 
Help_Msg_Size            =                       ( Screen_Cols - 2 ) 
XFiles_Screen_Size       = XFile_Rows * XFile_Cols

; Characters
AC_Xdir                 DB      AC_01
AC_Xdir_FileName        DB             AC_02
AC_Xdir_Drive_Map       DB                    AC_03
AC_Xdir_Path_Spec       DB                           AC_04
AC_Xdir_Entries         DB                                  AC_05
                        DB      AC_06, AC_07, AC_08, AC_09, AC_10
                        DB      AC_11, AC_12, AC_13, AC_14, AC_15
                        DB      AC_16, AC_17, AC_18, AC_19, AC_20
                        DB      AC_21, AC_22, AC_23, AC_24
AC_Xdir_Msg_Help        DB                                  AC_25

BC_Xdir                 DB             BC_02, BC_03, BC_04, BC_05
                        DB      BC_06, BC_07, BC_08, BC_09, BC_10
                        DB      BC_11, BC_12, BC_13, BC_14, BC_15
                        DB      BC_16, BC_17, BC_18, BC_19, BC_20
                        DB      BC_21, BC_22, BC_23, BC_24, BC_25

CC_Xdir                 DB             CC_02
CC_Xdir_Files           DB                    CC_03, CC_04, CC_05
                        DB      CC_06, CC_07, CC_08, CC_09, CC_10
                        DB      CC_11, CC_12, CC_13, CC_14, CC_15
                        DB      CC_16, CC_17, CC_18, CC_19, CC_20
                        DB      CC_21, CC_22, CC_23, CC_24

DC_Xdir                 DB             DC_02, DC_03, DC_04, DC_05
                        DB      DC_06, DC_07, DC_08, DC_09, DC_10
                        DB      DC_11, DC_12, DC_13, DC_14, DC_15
                        DB      DC_16, DC_17, DC_18, DC_19, DC_20
                        DB      DC_21, DC_22, DC_23, DC_24

; Symbols
AS_Attr                 DB      AS_01, AS_02, AS_03, AS_04, AS_05
                        DB      AS_06, AS_07, AS_08, AS_09, AS_10
                        DB      AS_11, AS_12, AS_13, AS_14, AS_15
                        DB      AS_16, AS_17, AS_18, AS_19, AS_20
                        DB      AS_21, AS_22, AS_23, AS_24, AS_25

BS_Attr                 DB             BS_02, BS_03, BS_04, BS_05
                        DB      BS_06, BS_07, BS_08, BS_09, BS_10
                        DB      BS_11, BS_12, BS_13, BS_14, BS_15
                        DB      BS_16, BS_17, BS_18, BS_19, BS_20
                        DB      BS_21, BS_22, BS_23, BS_24, BS_25

DS_Attr                 DB             DS_02, DS_03, DS_04, DS_05
                        DB      DS_06, DS_07, DS_08, DS_09, DS_10
                        DB      DS_11, DS_12, DS_13, DS_14, DS_15
                        DB      DS_16, DS_17, DS_18, DS_19, DS_20
                        DB      DS_21, DS_22, DS_23, DS_24

; Attributes
AA_Attr                 DB  Screen_Size        dup (ATTRIB_BLACK)
BA_Attr                 DB  Help_Screen_Size   dup (ATTRIB_RED_WHITE)
DA_Attr                 DB  XFiles_Screen_Size dup (ATTRIB_CYAN_YELLOW)

; Video
Video_RAM_Below_Xdir    DW  Screen_Size dup (0)
Video_Mode_Base         DW  VIDEO_MODE_COLOR_BASE
Video_Mode_Offset       DW      0

Xdir_Mode_Offset         = ( ( XDIR_START_ROW - 1 ) * 80 + XDIR_START_COL ) * 2
Xdir_File_Offset         = ( ( XDIR_8BIT_VTOC_START_ROW - 1 ) * 80 + ( XDIR_8BIT_VTOC_START_COL - 1 ) )
Xdir_FileName           DB     12 dup (?)
Xdir_Drive              DB      ?       ; Drive Nr in Drive Table
Max_Xdir_Drive          DB      ?       ; Max Nr of drives in Drive Table
Old_Xdir_Drive          DB      ?       ; Remember old situation
Xdir_Window             DW      1       ; Current top file in Xdir
                                        ;       corresponding to File_Table
Max_Xdir_Window         = ( MAX_ENTRIES_IN_FILE_TABLE - Max_Files_In_Xdir_Table + 1 )
Xdir_Window_File        DB      1       ; Limited to Max_Files_In_Xdir_Table

;----------------------------------------------------------------------
;--  Pointers                                                        --
;----------------------------------------------------------------------
File_Table_Ptr          DD  File_Table
File_Table_Entry_Ptr    DD  File_Table_Entry
Temp_Entry_Ptr          DD  Temp_Entry
File_Size_Init_Ptr      DD  File_Size_Init
File_Size_Text_Ptr      DD  File_Size_Text
File_Spec_Ptr           DD  File_Spec
Default_Drive_Path_Ptr  DD  Default_Drive
Default_Path_Ptr        DD  Default_Path
Search_Spec_Drive_Ptr   DD  Search_Spec_Drive
Search_Spec_Dir_Ptr     DD  Search_Spec_Dir
Path_Spec_Ptr           DD  Path_Spec
File_Mask_Ptr           DD  File_Mask
Old_File_Mask_Ptr       DD  Old_File_Mask
Sub_Directories_Ptr     DD  Sub_Directories
Dta_Ptr                 DW  ?
AC_Xdir_Ptr             DD  AC_Xdir
AC_Xdir_FileText_Ptr    DD  AC_Xdir_FileName  +  1
AC_Xdir_FileName_Ptr    DD  AC_Xdir_FileName  + 10
AC_Xdir_Path_Spec_Ptr   DD  AC_Xdir_Path_Spec +  6
AC_Xdir_Entries_Ptr     DD  AC_Xdir_Entries   +  1
BC_Xdir_Ptr             DD  BC_Xdir
AS_Attr_Ptr             DD  AS_Attr
AA_Attr_Ptr             DD  AA_Attr
BA_Attr_Ptr             DD  BA_Attr
AA_Attr_FileName_Ptr    DD  AA_Attr + ( AC_Xdir_FileName   - AC_Xdir ) + 10
AA_Attr_Drive_Map_Ptr   DD  AA_Attr + ( AC_Xdir_Drive_Map  - AC_Xdir ) +  1
AA_Attr_Entries_Ptr     DD  AA_Attr + ( AC_Xdir_Entries    - AC_Xdir ) +  1
Xdir_FileName_Ptr       DD  Xdir_FileName
Video_RAM_Below_Xdir_Ptr DD  Video_RAM_Below_Xdir

;----------------------------------------------------------------------
;--  External Variables                                              --
;----------------------------------------------------------------------


ENDS    DSeg

;**********************************************************************
SEGMENT CSeg Word Public 'CODE'
;**********************************************************************
;----------------------------------------------------------------------
;--  External Variables                                              --
;----------------------------------------------------------------------
        EXTRN   DC_DRV:proc                 ; Determine Current Drives
        EXTRN   XFILES:proc                 ; Extract Files



;**********************************************************************
Main:   
;**********************************************************************
        ASSUME  cs:CSeg
        ASSUME  ds:DSeg
        mov     ax, DSeg                    ; Initialize DS to address
        mov     ds, ax                      ; of data segment

        call    Save_And_Surpress_Cursor
        call    Determine_Video_Mode
        call    Save_Video_RAM_Below_Xdir
        call    Translate_Symbolic_Attributes
        call    Read_XDir_Config_File
        call    Parameter_Processing
        call    Determine_Available_Drives
        call    Determine_Sub_Directories
        call    Retrieve_Directory

        call    Show_And_Process_Xdir

        call    Restore_Video_RAM_Below_Xdir
        call    Restore_Saved_Cursor
        call    Set_Return_Code
        call    Exit_Program



;**********************************************************************
PROC    Save_And_Surpress_Cursor
;**********************************************************************
        call    Get_Cursor_Position         ; Save current cursor position
        mov     dh, [Offset Cursor_Position.Row]
        mov     dl, [Offset Cursor_Position.Col]
        mov     [Offset Save_Cursor_Position.Row], dh
        mov     [Offset Save_Cursor_Position.Col], dl

        mov     [Cursor_Position.Row], OFF_SCREEN
        mov     [Cursor_Position.Col], OFF_SCREEN
        call    Set_Cursor_Position

        ret

ENDP    Save_And_Surpress_Cursor



;**********************************************************************
PROC    Determine_Video_Mode
;**********************************************************************
        mov     ah, VIDEO_GET_MODE
        int     VIDEO_SERVICE               ; Get Video Mode
        cmp     al, VIDEO_MODE_MONO         ; Monochrome Mode?
        jne     @@10                        ; No
                                            ; Yes, so
        mov     [Video_Mode_Base], VIDEO_MODE_MONO_BASE

@@10:
        ret

ENDP    Determine_Video_Mode



;**********************************************************************
PROC    Save_Video_RAM_Below_Xdir
;**********************************************************************
        push    es di ds si

        mov     bx, Screen_Rows             ; Nr of Rows
        les     di, [Video_RAM_Below_Xdir_Ptr]   ; Our save area
        mov     si, [Video_Mode_Offset]     ; Videomap Offset
        add     si, Xdir_Mode_Offset        ; Where our box will come
        mov     ds, [Video_Mode_Base]       ; Videomap Base

@@10:
        mov     cx, Screen_Cols
        rep     movsw
        add     si, ( MAX_COL - Screen_Cols ) * 2
        dec     bx
        jnz     @@10

        pop     si ds di es
        ret

ENDP    Save_Video_RAM_Below_Xdir



;**********************************************************************
PROC    Translate_Symbolic_Attributes
;**********************************************************************
        mov     cx, Screen_Size             ; Nr of symbolic attribs to check
        mov     si, offset AA_Attr
        push    ds si
        pop     di es
        mov     si, offset AS_Attr
        xor     ax, ax                      ; Reset ax
        xor     bx, bx                      ; Reset bx
        call    Translate_Symbolic_Attr

        mov     cx, Help_Screen_Size        ; Nr of symbolic attribs to check
        mov     si, offset BA_Attr
        push    ds si
        pop     di es
        mov     si, offset BS_Attr
        xor     ax, ax                      ; Reset ax
        xor     bx, bx                      ; Reset bx
        call    Translate_Symbolic_Attr

        mov     cx, XFiles_Screen_Size      ; Nr of symbolic attribs to check
        mov     si, offset DA_Attr
        push    ds si
        pop     di es
        mov     si, offset DS_Attr
        xor     ax, ax                      ; Reset ax
        xor     bx, bx                      ; Reset bx
        call    Translate_Symbolic_Attr

        ret

ENDP    Translate_Symbolic_Attributes

;**********************************************************************
PROC    Translate_Symbolic_Attr
;**********************************************************************
@@10:
        mov     bl, [byte ds:si]            ; Load attribute from table

        mov     al, ATTRIB_BLACK_WHITE      ; Assume color of attribute
        cmp     bx, "W"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_BLACK_BLINK      ; Assume color of attribute
        cmp     bx, "F"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_BLUE             ; Assume color of attribute
        cmp     bx, "b"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_BLUE_WHITE       ; Assume color of attribute
        cmp     bx, "B"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_BLUE_YELLOW      ; Assume color of attribute
        cmp     bx, "u"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_GREEN_WHITE      ; Assume color of attribute
        cmp     bx, "G"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_GREEN_YELLOW     ; Assume color of attribute
        cmp     bx, "g"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_CYAN_WHITE       ; Assume color of attribute
        cmp     bx, "C"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_CYAN_YELLOW      ; Assume color of attribute
        cmp     bx, "c"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_RED              ; Assume color of attribute
        cmp     bx, "r"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_RED_WHITE        ; Assume color of attribute
        cmp     bx, "R"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_RED_YELLOW       ; Assume color of attribute
        cmp     bx, "d"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_MAGENTA          ; Assume color of attribute
        cmp     bx, "m"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_MAGENTA_WHITE    ; Assume color of attribute
        cmp     bx, "M"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_MAGENTA_YELLOW   ; Assume color of attribute
        cmp     bx, "t"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_BROWN            ; Assume color of attribute
        cmp     bx, "o"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_BROWN_WHITE      ; Assume color of attribute
        cmp     bx, "O"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_BROWN_YELLOW     ; Assume color of attribute
        cmp     bx, "n"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_INVERSE          ; Assume color of attribute
        cmp     bx, "I"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_INVERSE_YELLOW   ; Assume color of attribute
        cmp     bx, "Y"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_OVERLAY          ; Assume overlay attribute
        cmp     bx, "x"                     ; Overlay symbol?
        jz      @@20                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_ERROR            ; Assume color of attribute
        cmp     bx, "E"                     ; Symbol confirms assumption?
        jz      @@20                        ; Yes
                                            ; No, so...
        cmp     bx, "q"                     ; Leave symbol untouched?
        jz      @@30                        ; Yes
                                            ; No, so...
        mov     al, ATTRIB_BLACK            ; Assume Standard Attribute

@@20:
        mov     [byte es:di], al            ; Tranlate Attribute

@@30:
        inc     si
        inc     di
        dec     cx
        jnz     @@10
        ret

ENDP    Translate_Symbolic_Attr



;**********************************************************************
PROC    Set_Cursor_Position
;**********************************************************************
        mov     dh, [offset Cursor_Position.Row]
        mov     dl, [offset Cursor_Position.Col]
        mov     ah, VIDEO_SET_CURSOR
        int     VIDEO_SERVICE               ; Set Cursor
        ret

ENDP    Set_Cursor_Position



;**********************************************************************
PROC    Get_Cursor_Position
;**********************************************************************
        mov     ah, VIDEO_GET_CURSOR
        int     VIDEO_SERVICE               ; Get Cursor
        mov     [offset Cursor_Position.Row], dh
        mov     [offset Cursor_Position.Col], dl
        ret

ENDP    Get_Cursor_Position



;**********************************************************************
PROC    Read_XDir_Config_File
;**********************************************************************
; Open file
        mov     dx, offset Xdir_Config_File_Spec
        mov     ah, DOS_OPEN_FILE
        mov     al, DOS_FILE_READ_ONLY
        int     DOS_SERVICE
        jc      @@99                        ; Open ERROR!

        mov     [Disk_Handler], ax          ; Load handle

; Retrieve Search File Mask
        call    Get_Parameter_From_Config_File
        mov     si, offset File_Mask        ; File Mask Area
        inc     si
        push    ds si
        pop     di es
        mov     si, offset Xdir_Config_Parameter
        mov     cx, FILE_NAME_LENGTH
        rep     movsb                       ; Copy Passed Mask to File Mask

; Retrieve Default Source Path
        call    Get_Parameter_From_Config_File
        mov     si, offset Search_Spec_Drive    ; File Mask Area
        push    ds si
        pop     di es
        mov     si, offset Xdir_Config_Parameter
        mov     cx, PATH_LENGTH
        rep     movsb                       ; Copy Passed Mask to File Mask

; Retrieve Destination Path (XFILES)
        call    Get_Parameter_From_Config_File
        mov     si, offset Disk_Parameters.XFiles_Path
        push    ds si
        pop     di es
        mov     si, offset Xdir_Config_Parameter
        mov     cx, PATH_LENGTH
        rep     movsb                       ; Copy Passed Mask to File Mask

; Retrieve Specification If Deleted Files Should Be Extracted
        mov     [Disk_Parameters.XFilesD_Extract], LOGIC_NO
        call    Get_Parameter_From_Config_File
        mov     si, offset Xdir_Config_Parameter
        cmp     [byte ds:si], "N"           ; Check if No is specified
        je      @@90                        ; No is specified
                                            ; Extract Deleted Files too!
; Retrieve Destination Path Deleted Files (XFILESD)
        mov     [Disk_Parameters.XFilesD_Extract], LOGIC_YES
        call    Get_Parameter_From_Config_File
        mov     si, offset Disk_Parameters.XfilesD_Path
        push    ds si
        pop     di es
        mov     si, offset Xdir_Config_Parameter
        mov     cx, PATH_LENGTH
        rep     movsb                       ; Copy Passed Mask to File Mask

@@90:
; Close config file
        mov     bx, [Disk_Handler]
        mov     ah, DOS_CLOSE_FILE
        int     DOS_SERVICE

@@99:
        ret

ENDP    Read_XDir_Config_File



;**********************************************************************
PROC    Get_Parameter_From_Config_File
;**********************************************************************
; Clear parameter
        mov     si, offset Xdir_Config_Parameter
        push    ds si
        pop     di es
        push    es di
        mov     cx, PATH_LENGTH
        xor     ax, ax                      ; Reset ax
        mov     al, SPACE
        rep     stosb                       ; Clear parameter
        pop     di es
        mov     si, offset Disk_I_O_Buffer

@@10:
; Scan character of the retrieved byte from the config file
        mov     ah, DOS_READ_FROM_HANDLE
        mov     bx, [Disk_Handler]
        mov     cx, 1                       ; Process 1 byte at a time
        mov     dx, offset Disk_I_O_Buffer
        int     DOS_SERVICE                 ; Read byte from config file
        jc      @@99                        ; Stop on error
        or      ax, ax                      ; End of file?
        jz      @@99                        ; Yes
                                            ; No, so
        cmp     [byte ds:si], LF            ; End of line of previous scan?
        je      @@10                        ; Yes
                                            ; No, so
        cmp     [byte ds:si], CR            ; Empty "line" in config file?
        je      @@20                        ; Yes
                                            ; No, so
        cmp     [byte ds:si], SPACE         ; Empty "line" in config file?
        je      @@20                        ; Yes
                                            ; No, so
        cmp     [byte ds:si], COMMENT_ROW   ; Comment "line" in config file?
        jne     @@30                        ; No
                                            ; Yes, so
@@20:
; Scan for end of line character
        mov     ah, DOS_READ_FROM_HANDLE
        mov     bx, [Disk_Handler]
        mov     cx, 1                       ; Process 1 byte at a time
        mov     dx, offset Disk_I_O_Buffer
        int     DOS_SERVICE                 ; Read byte from config file
        jc      @@99                        ; Stop on error
        or      ax, ax                      ; End of file?
        jz      @@99                        ; Yes
                                            ; No, so
        cmp     [byte ds:si], LF            ; End of line reached?
        jne     @@20                        ; No,
                                            ; Yes, so
        jmp     @@10                        ; Scan next line of config file

@@30:
; Process the config parameter
        movsb                               ; Copy byte from I/O Buffer

        mov     ah, DOS_READ_FROM_HANDLE
        mov     bx, [Disk_Handler]
        mov     cx, 1                       ; Process 1 byte at a time
        mov     dx, offset Disk_I_O_Buffer
        int     DOS_SERVICE                 ; Read byte from config file
        jc      @@99                        ; Stop on error
        or      ax, ax                      ; End of file?
        jz      @@99                        ; Yes
                                            ; No, so
        mov     si, dx
        cmp     [byte ds:si], CR            ; End of line reached?
        jne     @@30                        ; No,
                                            ; Yes, so
@@99:
        ret

ENDP    Get_Parameter_From_Config_File



;**********************************************************************
PROC    Parameter_Processing
;**********************************************************************
; Check Search Path from config file, if specified, we use it
        mov     si, offset Search_Spec_Drive
        cmp     [byte ds:si], BACKSLASH     ; Use current directory
        je      @@10                        ; Yes
                                            ; No, so
        les     di, [Search_Spec_Drive_Ptr] ; Offset search path
        mov     cx, PATH_LENGTH             ; Search length
        dec     cx                          ; Because of null terminator
        add     di, cx                      ; Go to end of path
        std                                 ; Search direction is down
        xor     ax, ax                      ; Reset ax
        mov     al, BACKSLASH               ; Search for the "\" character
        repne   scasb                       ; Search uses es:di
        cld                                 ; Cancel the std setting
        inc     di                          ; Pointer adjustment after search
        jmp     @@20

@@10:
; Get default drive
        xor     ax, ax                      ; Reset ax
        mov     ah, DOS_GET_DEFAULT_DRIVE   ; Get Default Drive
        int     DOS_SERVICE 
        add     al, 041h                    ; Because of 0-based stuff

; Process Drive
        mov     [byte ds:si], al            ; Process Drive letter
        mov     [byte ds:si + 1], ":"
        mov     [byte ds:si + 2], "\"

; Get current directory
        xor     ax, ax                      ; Reset ax
        mov     ah, DOS_GET_CURRENT_DIRECTORY
        mov     si, offset Search_Spec_Dir
        xor     dx, dx                      ; Reset dx
        mov     dl, DOS_DEFAULT_DRIVE
        int     DOS_SERVICE

; Attach File Mask
        les     di, [Search_Spec_Drive_Ptr] ; Offset search path
        mov     cx, PATH_LENGTH             ; Search length
        dec     cx                          ; Because of null terminator
        add     di, cx                      ; Go to end of path
        std                                 ; Search direction is down
        xor     ax, ax                      ; Reset ax
        mov     al, NULL                    ; Search for the 000h character
        repne   scasb                       ; Search uses es:di
        cld                                 ; Cancel the std setting
        cmp     [byte ds:di], BACKSLASH     ; Is this the "\" character?
        je      @@20                        ; Yes
                                            ; No, so
        inc     di                          ; Pointer adjustment after search

@@20:
        mov     si, offset Default_Path     ; File Mask Area
        mov     cx, FILE_NAME_LENGTH + 1
        rep     movsb                       ; Copy Passed Mask to File Mask

@@99:
        ret

ENDP    Parameter_Processing



;**********************************************************************
PROC    Determine_Available_Drives
;**********************************************************************
        call    DC_DRV                      ; Determine available drives

        mov     si, offset AC_Xdir_Drive_Map + 1
        push    ds si
        pop     di es
        mov     si, offset Drive_Map
        mov     cx, MAX_DRIVES
        rep     movsb

        mov     cx, MAX_DRIVES              ; 26 Drives maximum
        std                                 ; Search direction is down
        mov     ax, SPACE                   ; Search until not space
        repe    scasb                       ; Search uses ed:di register pair
        cld                                 ; Search direction is up
        mov     [Max_Xdir_Drive], cl

@@30:
; Highlight current drive in Drive Map
        mov     [Xdir_Drive], 0             ; Current Drive Nr determination

        mov     dl, [byte Search_Spec_Drive] ; Get Current Drive
        mov     si, offset AC_Xdir_Drive_Map + 1
        push    ds si
        pop     di es
        mov     si, offset AA_Attr          ; Attr Area
        add     si, Offset_Drive_Map_Attr   ; Attr Drive Map Area

@@40:
        cmp     [byte es:di], SPACE         ; Are we at the end of the Map?
        je      @@60                        ; Yes
                                            ; No, so
        inc     [Xdir_Drive]                 ; Assume this drive to be the one
        cmp     [byte es:di], dl            ; Current Drive located?
        je      @@50                        ; Yes
                                            ; No, so
        inc     di                          ; Move to next drive
        inc     si                          ; Move to next attribute
        jmp     @@40                        ; Check next drive

; Highlight drive
@@50:
        mov     [byte ds:si], ATTRIB_BLUE_YELLOW
        jmp     @@99

; Specified Drive doesn't exist, set last drive in drive map to default drive
@@60:
        dec     di                          ; Get last drive
        dec     si                          ; Go to that drive's attribute
        mov     [byte ds:si], ATTRIB_BLUE_YELLOW
        mov     dl, [byte es:di]            ; Retrieve last drive

        les     di, [Search_Spec_Drive_Ptr] ; Change path
        xor     ax, ax                      ; Reset ax
        mov     al, SPACE                   ; Fill character
        mov     cx, PATH_LENGTH             ; Path size
        rep     stosb                       ; Initialize path

        les     di, [Search_Spec_Drive_Ptr] ; Change search path
        lds     si, [Default_Drive_Path_Ptr]
        mov     cx, FILE_NAME_LENGTH + 2    ; Which is Z:\*.*
        rep     movsb                       ; Search path changed

; Adjust File Mask too
        les     di, [File_Mask_Ptr]         ; File_Mask
        lds     si, [Default_Path_Ptr]      ; Use default path directory
        mov     cx, FILE_NAME_LENGTH        ; Copy length
        rep     movsb                       ; File Mask changed
        
@@99:
        mov     [byte Search_Spec_Drive], dl  ; Set Current Drive
        ret

ENDP    Determine_Available_Drives


;**********************************************************************
PROC    Determine_Sub_Directories
;**********************************************************************
; Search for "\"
        mov     [Current_Sub_Directory], 0  ; Init counter
        mov     [Xdir_Window], 1             ; Init Window
        mov     [Xdir_Window_File], 1        ; Init Window File
        les     di, [Sub_Directories_Ptr]   ; Remember the sub directories

        push    es di

        call    Set_Up_Path_For_Search

        mov     si, offset Default_Path     ; Use the Default Path
        mov     cx, FILE_NAME_LENGTH        ; Copy length
        rep     movsb                       ; Copy

        les     di, [Path_Spec_Ptr]         ; Passed search path
        xor     ax, ax                      ; Reset ax
        mov     al, BACKSLASH               ; Search for the "\" character
        mov     cx, PATH_LENGTH             ; Search length

; Search first and other "\"
@@10:
        repne   scasb                       ; Search equal "\" uses es:di
        cmp     [byte es:di], "*"           ; Are we at the File Mask already?
        je      @@99                        ; Yes
                                            ; No, so
        push    es di                       ; Save es:di for move to ds:si
        mov     dx, cx                      ; Determine length of Sub Dir
        repne   scasb                       ; Find next "\"
        inc     cx                          ; Adjust cx after search
        sub     dx, cx                      ; Size to copy determined
        pop     si ds                       ; Move saved es:di to ds:si
        pop     di es                       ; Replacing es:di with Sub Dir Ptr
        push    cx                          ; Save remaining scan length
        mov     cx, dx                      ; Size to copy
        mov     dx, SUB_DIRECTORY_ENTRY_LENGTH - 3  ; To move to box part
        sub     dx, cx                      ; Remaining space to add
        rep     movsb                       ; Save Sub Directory
        pop     cx                          ; Restore scan length
        add     di, dx                      ; Add remaining space
                                            ;     to get to box part
        mov     [word es:di], 1             ; Xdir Window is 1
        inc     di                          ; Move to
        inc     di                          ;      Xdir_Window_File
        mov     [byte es:di], 1             ; Xdir Window File is 1
        inc     di                          ; Move to next entry
        inc     [Current_Sub_Directory]     ; Increment counter
        cmp     [Current_Sub_Directory], MAX_SUB_DIRECTORIES    ; Table full?
        je      @@99                        ; Yes
                                            ; No, so
        push    es di ds si                 ; Move ds:si
        pop     di es                       ;   to es:di
        jmp     @@10                        ; Scan on

@@99:
        pop     di es                       ; Clean stack

        ret

ENDP    Determine_Sub_Directories



;**********************************************************************
PROC    Show_And_Process_Xdir
;**********************************************************************
@@10:
        call    Transfer_Directory_To_Xdir
        call    Set_Up_XFile_Window
        call    Show_Xdir

@@15:
        call    Process_Xdir

        cmp     ah, NULL                    ; Special key pressed?
        jne     @@20                        ; No
                                            ; Yes, so
        cmp     al, KEY_ESC                 ; ESCape key pressed?
        je      @@99                        ; Yes
                                            ; No, so
        cmp     al, KEY_ARROW_UP            ; Arrow Up key pressed?
        je      @@30                        ; Yes
                                            ; No, so
        cmp     al, KEY_ARROW_RIGHT         ; Arrow Right key pressed?
        je      @@32                        ; Yes
                                            ; No, so
        cmp     al, KEY_ARROW_DOWN          ; Arrow Down key pressed?
        je      @@34                        ; Yes
                                            ; No, so
        cmp     al, KEY_ARROW_LEFT          ; Arrow Left key pressed?
        je      @@36                        ; Yes
                                            ; No, so
        cmp     al, KEY_PAGE_UP             ; Page Up key pressed?
        je      @@38                        ; Yes
                                            ; No, so
        cmp     al, KEY_PAGE_DOWN           ; Page Down key pressed?
        je      @@40                        ; Yes
                                            ; No, so
        cmp     al, KEY_HOME                ; Home key pressed?
        je      @@42                        ; Yes
                                            ; No, so
        cmp     al, KEY_END                 ; End key pressed?
        je      @@44                        ; Yes
                                            ; No, so
        cmp     al, KEY_BACKSPACE           ; BACKSPACE key pressed?
        je      @@46                        ; Yes
                                            ; No, so
        cmp     al, KEY_DELETE              ; DELETE key pressed?
        je      @@48                        ; Yes
                                            ; No, so
        cmp     al, KEY_TAB                 ; TAB key pressed?
        je      @@50                        ; Yes
                                            ; No, so
        cmp     al, KEY_HELP                ; HELP key pressed?
        je      @@60                        ; Yes
                                            ; No, so
        cmp     al, KEY_ENTER               ; ENTER key pressed?
        je      @@90                        ; Yes
                                            ; No, so
        jmp     @@15                        ; Wait until valid key pressed

@@20:
        cmp     [XDIR_Status], XDIR_STATUS_FILE   ; File Mode?
        jne     @@15                        ; No, wait until valid key pressed
                                            ; Yes, so
; File Mode, check validity of key press
        mov     si, offset File_Mask_Key_Valid

@@25:
        cmp     [byte ds:si], NULL          ; End of valid table reached?
        je      @@15                        ; Yes
                                            ; No, so
        cmp     [byte ds:si], al            ; Key press valid?
        je      @@70                        ; Yes
                                            ; No, so
        inc     si                          ; Move to next valid key
        jmp     @@25                        ; Check key

; Special keys are processed below
@@30:
        call    Process_Xdir_Key_ARROW_UP
        jmp     @@10

@@32:
        call    Process_Xdir_Key_ARROW_RIGHT
        jmp     @@10

@@34:
        call    Process_Xdir_Key_ARROW_DOWN
        jmp     @@10

@@36:
        call    Process_Xdir_Key_ARROW_LEFT
        jmp     @@10

@@38:
        call    Process_Xdir_Key_PAGE_UP
        jmp     @@10

@@40:
        call    Process_Xdir_Key_PAGE_DOWN
        jmp     @@10

@@42:
        call    Process_Xdir_Key_HOME
        jmp     @@10

@@44:
        call    Process_Xdir_Key_END
        jmp     @@10

@@46:
        call    Process_Xdir_Key_BACKSPACE
        jmp     @@10

@@48:
        call    Process_Xdir_Key_DELETE
        jmp     @@10

@@50:
        call    Process_Xdir_Key_TAB
        jmp     @@10

@@60:
        call    Process_Xdir_Key_HELP
        jmp     @@10

@@70:
        call    Process_Xdir_Key_FILE
        jmp     @@10

@@90:
        call    Process_Xdir_Key_ENTER
        jmp     @@10

@@99:
        ret

ENDP    Show_And_Process_Xdir



;**********************************************************************
PROC    Retrieve_Directory
;**********************************************************************
; Save Current Dta
        mov     ah, DOS_GET_DTA             ; Get Disk Transfer Area address
        int     DOS_SERVICE 
        mov     [Old_Dta_Seg], es           ; Save old Dta Segment Address
        mov     [Old_Dta_Ofs], bx           ; Save old Dta Segment Offset

; Specify Own Dta
        mov     dx, offset Own_Dta          ; Address of Own Dta
        mov     [Dta_Ptr], dx               ; Store the Dta address
        mov     ah, DOS_SET_DTA
        int     DOS_SERVICE 

; Init file table
        mov     si, offset File_Table
        push    ds si
        pop     di es
        xor     ax, ax                      ; Reset table
        mov     cx, File_Table_Length       ; Nr of Bytes in File_Table
        rep     stosb

; Reset Error Message
        mov     si, offset Msg_Error
        push    ds si
        pop     di es
        mov     al, SPACE                   ;    with spaces
        mov     cx, BOX_MSG_LENGTH
        rep     stosb

; Reset "Selected" FileName
        les     di, [Xdir_FileName_Ptr]      ; Reset FileName
        mov     al, SPACE                   ;    with spaces
        mov     cx, FILE_NAME_LENGTH
        rep     stosb

; Search for files, search mask is file mask
        call    Set_Up_Path_For_Search

        mov     si, offset File_Mask        ; Use the file mask
        mov     cx, FILE_NAME_LENGTH + 1    ; Copy length
        rep     movsb                       ; Copy

@@05:
; The directory search is split up in 2 parts
; First the files are retrieved using the File Mask
; Then ALL Directories are retrieved because they are always shown!!!

; Reset pointer to our own file table
        mov     si, offset File_Table
        push    ds si
        pop     di es
        mov     [Files_In_File_Table], 0
        xor     cx,cx                       ; Reset cx

; Search for Files First
        mov     [DOS_Find_Files_Or_Dirs], DOS_FIND_FILES
        lds     dx, [Path_Spec_Ptr]         ; Use specified search path

; Attention, code below is used for Search for Directories and
;                                   Search for Files with specified File Mask!
@@10:
        mov     cx, [DOS_Find_Files_Or_Dirs]    ; Is one or the other
        xor     ax, ax                      ; Reset ax
        mov     ah, DOS_FIND_FIRST_FILE     ; Find First File
        jmp     @@20

; Retrieve file entries
@@15:
        mov     cx, [DOS_Find_Files_Or_Dirs]    ; Is one or the other
        xor     ax, ax                      ; Reset ax
        mov     ah, DOS_FIND_NEXT_FILE      ; Find Next File

; Read VTOC
@@20:
        int     DOS_SERVICE                 ; Find First/Next Entry
        jc      @@50                        ; No more Entries?

; Move Entry To Entry Table?
        mov     si, offset Own_Dta.File_Name
                                            ; Load address of filename
        cmp     [byte ds:si], DOT           ; Is this a ". " Entry?
        jne     @@22                        ; No
                                            ; Yes, so
        jmp     @@15                        ; Retrieve next Entry

; Novell network drives don't seem to have "." and ".." entries in subdirs
; To make this program universal, and support Novell drives too,
; whenever we are in a subdirectory, we add the [..] directory ourselves
@@22:
        call    Add_Sub_Directory_Marker

; Check Entry for being a file or directory entry
; Directories are always shown!
@@25:
        mov     si, offset Own_Dta.File_Attribute
                                            ; Load address of attribute
        xor     ax, ax                      ; Reset ax
        mov     al, [byte ds:si]            ; Load attribute
        and     al, ATTRIB_FILE_DIRECTORY
        cmp     al, ATTRIB_FILE_DIRECTORY   ; Entry is a directory?
        je      @@30                        ; Yes
                                            ; No, so
; Entry is a file
        mov     [byte ds:si], ATTRIB_FILE_FILE
        cmp     [DOS_Find_Files_Or_Dirs], DOS_FIND_FILES        ; File Mode?
        je      @@35                        ; Yes
                                            ; No, so
        jmp     @@15                        ; Check next entry

; Entry is a directory
@@30:
        cmp     [DOS_Find_Files_Or_Dirs], DOS_FIND_DIRECTORIES  ; Dir Mode?
        jne     @@15                        ; No
                                            ; Yes, so
; Process Entry
@@35:
        push    di                          ; Save di
        mov     di, offset Own_Dta.File_Name
                                            ; Load address of filename
        inc     [Files_In_File_Table]       ; Increase file counter
        mov     al, NULL                    ; Search for Null terminator
        mov     cx, FILE_NAME_LENGTH + 1    ; Search size equal file length + 1
        repne   scasb                       ; Search equal NULL, uses es:di
        mov     ax, cx                      ; ax is used to adjust File Table
        mov     cx, FILE_NAME_LENGTH + 1    ; Determine
        sub     cx, ax                      ;   Copy Length
        dec     cx                          ; Adjust Copy Length
        pop     di                          ; Restore di
        mov     si, offset Own_Dta.File_Name
                                            ; Now copy File to File Table
        rep     movsb                       ; Copy string now ds:si to es:di

        add     di, ax                      ; Move to file attribute
        mov     si, offset Own_Dta.File_Attribute
        movsb                               ; Copy file attribute to table
        mov     si, offset Own_Dta.File_Size
        mov     cx, 4                       ; Size is 4 bytes
        rep     movsb                       ; Copy file size to table
        xor     cx, cx                      ; Reset cx
        mov     [byte es:di], cl            ; Set end of Table;

@@40:
        cmp     [Files_In_File_Table], MAX_ENTRIES_IN_FILE_TABLE
                                            ; Max nr of Entries reached?
        jne     @@15                        ; No
                                            ; Yes, so
@@50:
        cmp     ax, DOS_PATH_NOT_FOUND      ; Specified path exists?
        je      @@55                        ; No
                                            ; Yes, so
        cmp     cx, DOS_FIND_DIRECTORIES    ; Have we done the directories?
        jne     @@60                        ; No,
                                            ; Yes, so
        jmp     @@70

@@55:
; Use root
        mov     [DOS_Find_Files_Or_Dirs], DOS_FIND_FILES

; Specify new search path
        les     di, [Search_Spec_Dir_Ptr]
        xor     ax, ax                      ; Reset ax
        mov     al, SPACE                   ; Fill directory with Spaces
        mov     cx, PATH_LENGTH - 2         ; Nr of Bytes in Directory path
        rep     stosb

; Change Search Path
        les     di, [Search_Spec_Dir_Ptr]
        mov     si, offset Default_Path     ; Default Path is \*.*
        mov     cx, FILE_NAME_LENGTH        ; Fill with \*.*
        rep     movsb                       ; Search Mask changed

; Change File Mask too
        les     di, [File_Mask_Ptr]
        mov     si, offset Default_Path     ; Default Path is \*.*
        mov     cx, FILE_NAME_LENGTH        ; Fill with \*.*
        rep     movsb                       ; Search Mask changed

        call    Set_Up_Path_For_Search

; Set Sub Directories Counter to zero and initialize table
        mov     [Current_Sub_Directory], 0  ; Reset Sub Directories counter
        les     di, [Sub_Directories_Ptr]
        xor     ax, ax                      ; Reset ax
        mov     al, SPACE                   ; Fill directory with Spaces
        mov     cx, Sub_Directories_Length  ; Nr of Bytes in Sub Dir Table
        rep     stosb

        jmp     @@05                        ; Read dir with default root
        
@@60:
        mov     [DOS_Find_Files_Or_Dirs], DOS_FIND_DIRECTORIES

        push    es di

; Search for directories, search mask is *.*
        call    Set_Up_Path_For_Search

        mov     si, offset Default_Path     ; Use the *.*
        mov     cx, FILE_NAME_LENGTH        ; Copy length
        rep     movsb                       ; Copy

        lds     dx, [Path_Spec_Ptr]         ; Use Path Spec

        pop     di es

        jmp     @@10                        ; Search for Directories now!

@@70:
; Novell network drives don't seem to have "." and ".." files in subdirectories
; So, if we are in a subdirectory, we add the [..] directory ourselves always
        call    Add_Sub_Directory_Marker

@@75:
        mov     es, [Old_Dta_Seg]           ; Restore old Dta Address
        mov     dx, [Old_Dta_Ofs]
        mov     ah, DOS_SET_DTA
        int     DOS_SERVICE 

@@80:
        cmp     [Files_In_File_Table], 0    ; Files found?
        je      @@90                        ; No
                                            ; Yes, so
        cmp     [Files_In_File_Table], 1    ; Do we need to sort?
        je      @@89                        ; No
                                            ; Yes, so
; Bubble Sort Files/Directories in alphabetic order
        mov     cx, [Files_In_File_Table]
        dec     cx

@@81:
        push    cx
        mov     si, offset File_Table
        push    ds si
        pop     di es
        add     di, FILE_ENTRY_LENGTH
        xor     bx, bx                      ; Reset bx
        mov     dx, cx

@@82:
        inc     bx
        cmp     bx, dx
        jg      @@84

        mov     cx, FILE_NAME_LENGTH        ; Compare Size
        push    ds si es di                 ; Save offsets
        rep     cmpsb                       ; Entry first > Entry next?
        pop     di es si ds                 ; Restore offsets
        jle     @@83                        ; No
                                            ; Yes, so
; Swap Entries
        push    ds si es di                 ; Save offsets
        les     di, [Temp_Entry_Ptr]        ; Our Temp field
        mov     cx, FILE_ENTRY_LENGTH
        rep     movsb                       ; Array[B] copied to Temp
        pop     si ds di es
        push    es di ds si
        mov     cx, FILE_ENTRY_LENGTH
        rep     movsb                       ; Array[B+1] copied to Array[B]
        lds     si, [Temp_Entry_Ptr]        ; Our Temp field
        mov     cx, FILE_ENTRY_LENGTH
        rep     movsb                       ; Temp copied to Array[B+1]
        pop     di es si ds

@@83:
        add     di, FILE_ENTRY_LENGTH
        add     si, FILE_ENTRY_LENGTH
        jmp     @@82

@@84:
        pop     cx
        loop    @@81

; Bubble Sort in Directories/File order
        mov     cx, [Files_In_File_Table]
        dec     cx

@@85:
        push    cx
        mov     si, offset File_Table
        push    ds si
        pop     di es
        add     di, FILE_ENTRY_LENGTH
        xor     bx, bx                      ; Reset bx
        mov     dx, cx

@@86:
        inc     bx
        cmp     bx, dx
        jg      @@88

        mov     cx, 1                       ; Compare Size 1 byte
        push    ds si es di                 ; Save offsets
        add     si, FILE_NAME_LENGTH        ; Position to correct offset
        add     di, FILE_NAME_LENGTH        ; Position to correct offset
        rep     cmpsb                       ; Entry first > Entry next?
        pop     di es si ds                 ; Restore offsets
        jle     @@87                        ; No
                                            ; Yes, so
; Swap Entries
        push    ds si es di                 ; Save offsets
        les     di, [Temp_Entry_Ptr]        ; Our Temp field
        mov     cx, FILE_ENTRY_LENGTH
        rep     movsb                       ; Array[B] copied to Temp
        pop     si ds di es
        push    es di ds si
        mov     cx, FILE_ENTRY_LENGTH
        rep     movsb                       ; Array[B+1] copied to Array[B]
        lds     si, [Temp_Entry_Ptr]        ; Our Temp field
        mov     cx, FILE_ENTRY_LENGTH
        rep     movsb                       ; Temp copied to Array[B+1]
        pop     di es si ds

@@87:
        add     di, FILE_ENTRY_LENGTH
        add     si, FILE_ENTRY_LENGTH
        jmp     @@86

@@88:
        pop     cx
        loop    @@85

; Highlight selected entry in box
@@89:
        call    Select_Xdir_Window_File
        jmp     @@95

@@90:
        mov     si, offset Msg_Error
        push    ds si
        pop     di es
        mov     si, offset Msg_No_Files_Found
        mov     cx, BOX_MSG_LENGTH
        rep     movsb

; Show Path
@@95:
        les     di, [AC_Xdir_Path_Spec_Ptr]  ; Initialize path first
        mov     al, SPACE
        mov     cx, XDIR_PATH_LENGTH
        rep     stosb
        
        call    Set_Up_Path_For_Search

        mov     si, offset File_Mask        ; Use the file mask
        mov     cx, FILE_NAME_LENGTH        ; Copy length
        rep     movsb                       ; Copy

        les     di, [Path_Spec_Ptr]
        add     di, 2
        mov     cx, 254                     ; Search length
        mov     dx, cx                      ; Remember value
        or      ax, ax                      ; Reset ax
        mov     al, SPACE                   ; Search for space
        repne   scasb                       ; Search equal " " uses es:di
        sub     dx, cx                      ; Determine length of path
        dec     dx                          ; Search adjustment
        cmp     dx, XDIR_PATH_LENGTH         ; Complete path fits on screen?
        jle     @@98                        ; Yes
                                            ; No, so
        dec     di                          ; Pointer adjustment after search
        sub     di, XDIR_PATH_LENGTH - 3     ; What fits after \..
        mov     al, BACKSLASH               ; Search for the "\" character
        mov     cx, XDIR_PATH_LENGTH - 3     ; Search length
        repne   scasb                       ; Search equal "\" uses es:di
        dec     di                          ; Pointer adjustment after search

        push    es di ds si es di           ; Save pointers

        les     di, [AC_Xdir_Path_Spec_Ptr]
        mov     si, offset Oversized_Path   ; Oversized path is \..
        mov     cx, 3
        rep     movsb

        pop     si ds
        mov     cx, XDIR_PATH_LENGTH - 3    ; Path is already \..
        rep     movsb                       ; Path is now \..\SUBDIR\*.*

        pop     si ds di es
        jmp     @@99

@@98:
        les     di, [AC_Xdir_Path_Spec_Ptr]
        mov     si, offset Path_Spec + 2
        mov     cx, XDIR_PATH_LENGTH
        rep     movsb

@@99:
        ret

ENDP    Retrieve_Directory



;**********************************************************************
PROC    Add_Sub_Directory_Marker
;**********************************************************************
        cmp     [Files_In_File_Table], 0    ; [..] already checked?
        jne     @@99                        ; Yes
                                            ; No, so
        cmp     [Current_Sub_Directory], 0  ; Are we in a subdirectory?
        je      @@99                        ; No
                                            ; Yes, so
        inc     [Files_In_File_Table]       ; Increase file counter
                                            ; Now copy File to File Table
        mov     si, offset Sub_Directory_Indicator
                                            ; Load address of filename
        mov     cx, 2
        rep     movsb                       ; Copy string now ds:si to es:di
        add     di, 10                      ; Move to file attribute
        mov     [byte es:di], ATTRIB_FILE_DIRECTORY
        inc     di                          ; Move to File Size
        xor     ax, ax                      ; Reset table with 000h
        mov     cx, 4                       ; Size is 4 bytes
        rep     stosb                       ; Copy file size to table
        mov     [byte es:di], cl            ; Set end of Table;

@@99:
        ret

ENDP    Add_Sub_Directory_Marker



;**********************************************************************
PROC    Set_Up_Path_For_Search
;**********************************************************************
        les     di, [Path_Spec_Ptr]         ; Path used for directory search
        mov     si, offset Search_Spec_Drive
        mov     cx, PATH_LENGTH             ; Copy length
        rep     movsb                       ; Copy path to search path

        mov     cx, PATH_LENGTH             ; Search length
        std                                 ; Search direction is down
        or      ax, ax                      ; Reset ax
        mov     al, BACKSLASH               ; Search for the "\" character
        repne   scasb                       ; Search equal "\" uses es:di
        cld                                 ; Cancel the std setting
        inc     di                          ; Pointer adjustment after search

        ret

ENDP    Set_Up_Path_For_Search



;**********************************************************************
PROC    Transfer_Directory_To_Xdir
;**********************************************************************
        xor     dx, dx                      ; Reset dx
        xor     cx, cx                      ; Reset cx
        xor     bx, bx                      ; Reset bx
        xor     ax, ax                      ; Reset ax

; First clear box area
        les     di, [AC_Xdir_Entries_Ptr]
        mov     bl, Max_Files_In_Xdir_Table
        mov     al, SPACE

@@02:
        mov     cx, Xdir_Table_Entry_Length
        rep     stosb
        mov     cx, Screen_Cols - Xdir_Table_Entry_Length
        add     di, cx                      ; Move to next entry
        dec     bx
        jnz     @@02

; Are there any files to move?
        cmp     [Files_In_File_Table], 0    ; Files found?
        jne     @@04                        ; Yes
                                            ; No, so
        les     di, [AC_Xdir_Entries_Ptr]
        mov     si, offset Msg_Error
        mov     cx, BOX_MSG_LENGTH              ; Size of message
        rep     movsb                       ; Fill it
        jmp     @@99

@@04:
; Move files from File Table to box Table
        mov     si, offset File_Table
        les     di, [AC_Xdir_Entries_Ptr]
        mov     cx, [Xdir_Window]            ; Is 1 when directory was just read
        dec     cx                          ; Because offset starts from 0
        xor     ax, ax                      ; Reset ax
        mov     al, FILE_ENTRY_LENGTH
        mul     cx                          ; Calculate correct entry
        add     si, ax                      ; Correct emtry reached
        mov     bl, Max_Files_In_Xdir_Table

; Check if Entry exist, and if Entry indicates an "above" directory
@@10:
        push    ds si es di                 ; Copy entry to entry structure
        les     di, [File_Table_Entry_Ptr]
        mov     cx, FILE_ENTRY_LENGTH
        rep     movsb
        pop     di es si ds                 ; Copy complete

        mov     dx, Screen_Cols             ; How big is 1 box line

        cmp     [File_Table_Entry.File_Name], NULL  ; Is there a file to copy?
        je      @@80                        ; No
                                            ; Yes, so
        cmp     [File_Table_Entry.File_Name], DOT   ; Is this the ".." File?
        jne     @@20                        ; No
                                            ; Yes, so
@@15:
        push    si

        mov     cx, FILE_NAME_LENGTH
        sub     dx, cx
        mov     si, offset Directory_Above  ; Filename is [..]
        rep     movsb

        pop     si
        add     si, FILE_NAME_LENGTH
        jmp     @@40

; Copy Entry Name
@@20:
        mov     cx, FILE_NAME_LENGTH
        sub     dx, cx
        xor     ax, ax                      ; Reset ax

@@21:
        cmp     [byte ds:si], DOT           ; Extension reached?
        je      @@22                        ; Yes
                                            ; No, so
        movsb                               ; Move character
        dec     cx                          ; More characters?
        jnz     @@21                        ; Yes
                                            ; No, so
        jmp     @@30                        ; Go to File/Directory check

; Life after the DOT
@@22:
        cmp     cl, 4                       ; Location of DOT reached?
        je      @@24                        ; Yes
                                            ; No, so
        mov     [byte es:di], SPACE         ; Fill it up with space
        inc     di                          ; Move up to next character
        inc     ax                          ; Used to adjust si in the end
        dec     cx                          ; Decrement character counter
        jmp     @@22                        ; Compare again

@@24:
        movsb                               ; Move character
        dec     cx                          ; More characters?
        jnz     @@24                        ; Yes
                                            ; No, so
        add     si, ax                      ; Adjust si

; Check if entry is a directory or file
@@30:
        mov     al, [File_Table_Entry.File_Attribute]
        and     al, ATTRIB_FILE_DIRECTORY
        cmp     al, ATTRIB_FILE_DIRECTORY   ; Entry is a directory?
        jne     @@50                        ; No
                                            ; Yes, so
; Entry is a directory
@@40:
        push    si

        mov     cx, FILE_SIZE_LENGTH
        sub     dx, cx
        mov     si, offset Directory
        rep     movsb

        pop     si
        jmp     @@80

; Calculate File Length
@@50:
        call    Calculate_File_Length

        push    si

        mov     cx, FILE_SIZE_LENGTH
        sub     dx, cx
        mov     si, offset File_Size_Text
        rep     movsb

        pop     si

; Check remaining entries
@@80:
        dec     bx                          ; More entries in box available?
        jz      @@99                        ; No
                                            ; Yes, so
; Move to next entry in the Tables
@@90:
        add     si, 5                       ; Go to next file
        add     di, dx                      ; Go to next entry
        jmp     @@10                        ; Process next file

@@99:
        ret

ENDP    Transfer_Directory_To_Xdir



;**********************************************************************
PROC    Calculate_File_Length
;**********************************************************************
        push    ds si es di bx dx

; Init value text
        mov     cx, FILE_SIZE_LENGTH
        lds     si, [File_Size_Init_Ptr]
        les     di, [File_Size_Text_Ptr]
        rep     movsb
        dec     di                          ; Move to end of Text string

        xor     bx, bx                      ; Reset bx
        mov     bx, 10000                   ; Split value
        mov     dh, [File_Table_Entry.File_Size_High_High]
        mov     dl, [File_Table_Entry.File_Size_High_Low]
        mov     ah, [File_Table_Entry.File_Size_Low_High]
        mov     al, [File_Table_Entry.File_Size_Low_Low]
        div     bx
        mov     cx, ax                      ; Save value above 10000
        mov     ax, dx                      ; First convert value below 10000
        mov     bx, 10                      ; Extract digits

; Convert hexadecimal size to textual digits
@@10:
        call    Extract_Digit               ; Convert value below 10000
        call    Extract_Digit
        call    Extract_Digit
        call    Extract_Digit
        mov     ax, cx                      ; Now convert value above 10000
        call    Extract_Digit               ; Convert value above 10000
        call    Extract_Digit
        call    Extract_Digit
        call    Extract_Digit
        call    Extract_Digit

; Surpress leading zeroes
        mov     bx, 10                      ; Value contains 11 characters
                                            ;       but we don't surpress
                                            ;       the last zero
@@20:                
        inc     di                          ; Move to digital character
        cmp     [byte es:di], DECIMAL_SEPERATOR ; Character is decimal?
        jne     @@30                        ; No
                                            ; Yes, so
        mov     [byte es:di], SPACE         ; Replace decimal by space
        jmp     @@40                        ; Process next character

@@30:
        cmp     [byte es:di], ZERO          ; Character is leading zero?
        jne     @@99                        ; No
                                            ; Yes, so
        mov     [byte es:di], SPACE         ; Replace leading zero by space

@@40:
        dec     bx                          ; More characters to check?
        jnz     @@20                        ; Yes
                                            ; No, so
; Return
@@99:        
        pop     dx bx di es si ds

        ret

ENDP    Calculate_File_Length



;**********************************************************************
PROC    Extract_Digit
;**********************************************************************
        xor     dx, dx                      ; Reset result
        div     bx                          ; Extract digit
        add     dx, 030h                    ; Turn digit into character
        cmp     [byte es:di], DECIMAL_SEPERATOR ; Character is decimal?
        jne     @@10                        ; No
                                            ; Yes, so
        dec     di                          ; Move to previous character

@@10:
        mov     [byte es:di], dl            ; Move character to text
        dec     di                          ; Move to previous character
        ret

ENDP    Extract_Digit



;**********************************************************************
PROC    Set_Up_XFile_Window
;**********************************************************************
        mov     si, offset AC_Xdir          ; Our main box
        add     si, Xdir_File_Offset        ; Our 8bit vtoc box
        push    ds si
        pop     di es

; Assume showing "author" information here
        mov     bx, XFile_Rows              ; Nr of Rows
        mov     si, offset DC_Xdir          ; Our author box area

@@01:
        mov     cx, XFile_Cols

@@02:
        movsb                               ; Move char from ds:si to es:di
        dec     cx
        jnz     @@02
        add     di, ( MAX_COL - XFile_Cols )
        dec     bx
        jnz     @@01

; Adjust Attrbibutes
        mov     si, offset AA_Attr          ; Our main box
        add     si, Xdir_File_Offset        ; Our 8bit vtoc box
        push    ds si
        pop     di es

; Assume showing "author" information attributes here
        mov     bx, XFile_Rows              ; Nr of Rows
        mov     si, offset DA_Attr          ; Our author box area

@@11:
        mov     cx, XFile_Cols

@@12:
        movsb                               ; Move char from ds:si to es:di
        dec     cx
        jnz     @@12
        add     di, ( MAX_COL - XFile_Cols )
        dec     bx
        jnz     @@11

; Check "selected" file, if any
        cmp     [Files_In_File_Table], 0    ; Files present?
        je      @@99                        ; No
                                            ; Yes, so
        xor     ax, ax                      ; Reset ax
        mov     cx, [Xdir_Window]            ; Is 1 when directory was just read
        mov     al, [Xdir_Window_File]       ; Get selected entry
        dec     ax                          ;       within File Table
        add     ax, cx                      ; Xdir_Window_File + Xdir Window
        dec     ax                          ; Get correct entry in File Table
        mov     cx, FILE_ENTRY_LENGTH       ; Multiply by size of Entry
        mul     cx

        push    ds si es di                 ; Copy entry to entry structure
        mov     si, Offset File_Table
        add     si, ax
        les     di, [File_Table_Entry_Ptr]
        mov     cx, FILE_ENTRY_LENGTH
        rep     movsb
        pop     di es si ds                 ; Copy complete

        xor     ax, ax                      ; Reset ax
        mov     al, [File_Table_Entry.File_Attribute]
        and     al, ATTRIB_FILE_DIRECTORY
        cmp     al, ATTRIB_FILE_DIRECTORY   ; Entry is a directory?
        je      @@99                        ; Yes
                                            ; No, so
; File "selected"

; Check for valid 8bit image disk here

; Check file size
; File Size Single   -> 0001:6800 for .XFD and 0001:6810 for .ATR
; File Size Medium   -> 0002:0800 for .XFD and 0002:0810 for .ATR
; File Size Enhanced -> 0002:3000 for .XFD and 0002:3010 for .ATR
; File Size Double   -> 0002:D000 for .XFD and 0002:D010 for .ATR
@@30:
        mov     al, [File_Table_Entry.File_Size_High_High]
        cmp     al, 000h                ; 00xx:xxxx?
        jne     @@99                    ; No
                                        ; Yes
        mov     al, [File_Table_Entry.File_Size_Low_Low]
        cmp     al, 000h                ; xxxx:xx00?
        je      @@31                    ; Yes
                                        ; No, so
        cmp     al, 010h                ; xxxx:xx10?
        jne     @@99                    ; No, incorrect disk size
                                        ; Yes
; Check Single
@@31:
        mov     [word XDisk_Sectors_Free], XDISK_SECTORS_SINGLE
        mov     al, [File_Table_Entry.File_Size_Low_High]
        cmp     al, 068h                ; xxxx:68xx?
        jne     @@32                    ; No
                                        ; Yes, so
        mov     al, [File_Table_Entry.File_Size_High_Low]
        cmp     al, 001h                ; xx01:xxxx?
        je      @@40                    ; Yes
                                        ; No, so
; Check Medium
@@32:
        mov     [word XDisk_Sectors_Free], XDISK_SECTORS_MEDIUM
        mov     al, [File_Table_Entry.File_Size_Low_High]
        cmp     al, 008h                ; xxxx:08xx?
        jne     @@33                    ; No
                                        ; Yes, so
        mov     al, [File_Table_Entry.File_Size_High_Low]
        cmp     al, 002h                ; xx02:xxxx?
        je      @@40                    ; Yes
                                        ; No, so
; Check Enhanced
@@33:
        mov     [word XDisk_Sectors_Free], XDISK_SECTORS_ENHANCED
        mov     al, [File_Table_Entry.File_Size_Low_High]
        cmp     al, 030h                ; xxxx:30xx?
        jne     @@34                    ; No
                                        ; Yes, so
        mov     al, [File_Table_Entry.File_Size_High_Low]
        cmp     al, 002h                ; xx02:xxxx?
        je      @@40                    ; Yes
                                        ; No, so
; Check Double
@@34:
        mov     [word XDisk_Sectors_Free], XDISK_SECTORS_DOUBLE
        mov     al, [File_Table_Entry.File_Size_Low_High]
        cmp     al, 0D0h                ; xxxx:D0xx?
        jne     @@99                    ; No
                                        ; Yes, so
        mov     al, [File_Table_Entry.File_Size_High_Low]
        cmp     al, 002h                ; xx02:xxxx?
        jne     @@99                    ; No
                                        ; Yes, so
@@40:
; Open file
        mov     si, offset Path_File_Spec
        push    ds si
        pop     di es
        mov     si, offset Search_Spec_Drive
        mov     cx, PATH_LENGTH
        rep     movsb

; Search for last "\"
        mov     si, offset Path_File_Spec
        push    ds si
        pop     di es
        mov     cx, PATH_LENGTH             ; Search length
        add     di, cx                      ; Go to end of Path
        std                                 ; Search direction is down
        or      ax, ax                      ; Reset ax
        mov     al, BACKSLASH               ; Search for the "\" character
        repne   scasb                       ; Search equal "\" uses es:di
        cld                                 ; Cancel the std setting
        inc     di                          ; Pointer adjustment after search
        inc     di                          ; Move next to the "\"

; Append Filename from entry
        mov     si, offset File_Table_Entry.File_Name
        mov     cx, FILE_NAME_LENGTH
        rep     movsb

; Open file
        mov     [Disk_Parameters.ATR], LOGIC_NO

        mov     dx, offset Path_File_Spec
        mov     ah, DOS_OPEN_FILE
        mov     al, DOS_FILE_READ_ONLY
        int     DOS_SERVICE
        jc      @@99                    ; Open ERROR!

        mov     [Disk_Handler], ax      ; Load handle

        mov     al, [File_Table_Entry.File_Size_Low_Low]
        cmp     al, 000h                ; xxxx:xx00?
        je      @@50                    ; Yes, .XFD file
                                        ; No, so
; Read file header
        mov     [Disk_Parameters.ATR], LOGIC_YES

        mov     ah, DOS_READ_FROM_HANDLE
        mov     bx, [Disk_Handler]
        mov     cx, ATR_HEADER_SIZE     ; Header size
        mov     dx, offset Disk_I_O_Buffer
        int     DOS_SERVICE             ; Read header
        jc      @@80                    ; Stop on error
        or      ax, ax                  ; End of file?
        jz      @@80                    ; Yes
                                        ; No, so
; Check file header single
        mov     si, offset ATR_Header_Single
        push    ds si
        pop     di es
        mov     si, offset Disk_I_O_Buffer
        mov     cx, ATR_HEADER_SIZE_COMPARE
        rep     cmpsb                   ; Header is .ATR Single?
        je      @@50                    ; Yes
                                        ; No, so
; Check file header medium
        mov     si, offset ATR_Header_Medium
        push    ds si
        pop     di es
        mov     si, offset Disk_I_O_Buffer
        mov     cx, ATR_HEADER_SIZE_COMPARE
        rep     cmpsb                   ; Header is .ATR Medium?
        je      @@50                    ; Yes
                                        ; No, so
; Check file header enhanced
        mov     si, offset ATR_Header_Enhanced
        push    ds si
        pop     di es
        mov     si, offset Disk_I_O_Buffer
        mov     cx, ATR_HEADER_SIZE_COMPARE
        rep     cmpsb                   ; Header is .ATR Enhanced?
        je      @@50                    ; Yes,
                                        ; No, so
; Check file header double
        mov     si, offset ATR_Header_Double
        push    ds si
        pop     di es
        mov     si, offset Disk_I_O_Buffer
        mov     cx, ATR_HEADER_SIZE_COMPARE
        rep     cmpsb                   ; Header is .ATR Double?
        je      @@50                    ; Yes
                                        ; No, so

        mov     [Disk_Parameters.ATR], LOGIC_NO
        jmp     @@80

@@50:
; Move to 8bit vtoc location (offset B400h, 8 sectors wide)
        mov     ah, DOS_MOVE_FILE_POINTER
        mov     al, DOS_MOVE_FILE_POINTER_CURR
        mov     bx, [Disk_Handler]
        xor     cx, cx                  ; Reset Offset cx:dx
        mov     dx, EIGHTBIT_VTOC_OFFSET
        int     DOS_SERVICE             ; Position in dx:ax

; Read 8bit vtoc
        mov     ah, DOS_READ_FROM_HANDLE
        mov     bx, [Disk_Handler]
        mov     cx, EIGHTBIT_VTOC_SIZE  ; Sector size
        mov     dx, offset Disk_I_O_Buffer
        int     DOS_SERVICE             ; Read header
        jc      @@80                    ; Stop on error
        or      ax, ax                  ; End of file?
        jz      @@80                    ; Yes

; Move 8bit vtoc files to screen area
        mov     bx, Screen_Cols
        mov     cx, EIGHTBIT_VTOC_FILES ; Maximum nr of 8bit vtoc files
        mov     si, offset CC_Xdir_Files
        push    ds si
        pop     di es
        mov     [XDisk_Done], LOGIC_NO
        mov     si, offset Disk_I_O_Buffer

@@55:
        mov     dx, VTOC_FILES_COLUMN_ENTRIES

@@56:
        push    cx dx ds si es di

        mov     [XFile_Deleted], LOGIC_NO
        mov     [XFile_Locked], LOGIC_NO
        mov     [XFile_Extended], LOGIC_NO
        mov     [XFile_Inverse], LOGIC_NO

        cmp     [XDisk_Done], LOGIC_YES ; All entries already processed?
        je      @@58                    ; Yes
                                        ; No, so
        cmp     [byte ds:si], NULL      ; Entry present?
        jne     @@60                    ; Yes
                                        ; No, so
@@58:
        mov     [XDisk_Done], LOGIC_YES
        mov     si, offset XFile_No_Entry   ; Initialize XFile entry
        mov     cx, XFILE_ENTRY_SIZE
        rep     movsb
        jmp     @@77

@@60:
        push    bx ds si es di

; Check File Status
        xor     ax, ax                  ; Reset ax
        mov     al, [byte ds:si]        ; Load File Status
        and     al, 080h                ; Check Delete Status
        cmp     al, 080h                ; File Deleted?
        jne     @@63                    ; No
                                        ; Yes , so
        mov     [XFile_Deleted], LOGIC_YES

@@63:
        mov     al, [byte ds:si]        ; Load File Status
        and     al, 020h                ; Check Lock Status
        cmp     al, 020h                ; File Locked?
        jne     @@64                    ; No
                                        ; Yes , so
        mov     [XFile_Locked], LOGIC_YES

@@64:
        mov     al, [byte ds:si]        ; Load File Status
        and     al, 001h                ; Check Extended Status
        cmp     al, 001h                ; File Extended?
        jne     @@65                    ; No
                                        ; Yes , so
        mov     [XFile_Extended], LOGIC_YES

@@65:
        add     si, 1                   ; Begin of filesize
        mov     ah, [byte ds:si + 1]
        mov     al, [byte ds:si]

        cmp     [XFile_Deleted], LOGIC_YES
        je      @@66                    ; Yes
                                        ; No, so
        sub     [XDisk_Sectors_Free], ax

@@66:
; Init value text
        mov     cx, XFILE_SIZE_LENGTH
        mov     si, offset XFile_Size_Text
        push    ds si
        pop     di es
        mov     si, offset XFile_Size_Init
        rep     movsb
        dec     di                          ; Move to end of Text string
        mov     bx, 10                      ; Extract digits

; Convert hexadecimal size to textual digits
        call    Extract_Digit               ; Convert value below 10000
        call    Extract_Digit
        call    Extract_Digit
        call    Extract_Digit

; Surpress leading zeroes
        mov     bx, 4

@@67:                
        inc     di                          ; Move to digital character
        cmp     [byte es:di], ZERO          ; Character is leading zero?
        jne     @@68                        ; No
                                            ; Yes, so
        mov     [byte es:di], SPACE         ; Replace leading zero by space
        dec     bx                          ; More characters to check?
        jnz     @@67                        ; Yes
                                            ; No, so
        mov     [XFile_Inverse], LOGIC_YES  ; When all characters are zero,
                                            ; we have a "comment" entry

@@68:
        pop     di es si ds bx

        push    es di

; Move XFilename
        add     si, 5                   ; Begin of filename, i.e. MYFILE  TXT
        mov     cx, 8                   ; Size of filename
        rep     movsb                   ; Move "MYFILE" part
        mov     [byte es:di], DOT       ; Insert a "."
        inc     di                      ; Move to extender part
        mov     cx, 3                   ; Size of extender
        rep     movsb                   ; Move "TXT" part

; Move XSize
        mov     si, offset XFile_Size_Text
        mov     cx, 4
        rep     movsb                   ; Move "  43" File Size part

        pop     di es

; Check if we have to inverse some stuff
        cmp     [XFile_Deleted], LOGIC_YES
        je      @@71                    ; Yes
                                        ; No, so
        mov     cx, 12                  ; Size of the filename

@@69:
        mov     al, [byte es:di]        ; load character
        and     al, 080h                ; Check high bit
        cmp     al, NULL                ; High bit set?
        je      @@70                    ; No
                                        ; Yes, so
        and     [byte es:di], 07Fh      ; Reset high bit
        
@@70:
        inc     di
        dec     cx
        jnz     @@69
        jmp     @@72

@@71:
; If file deleted, mark it red
        cmp     [XFile_Deleted], LOGIC_YES
        jne     @@72                    ; No
                                        ; Yes, so
        mov     si, offset AA_Attr
        add     si, Xdir_File_Offset    ; Our 8bit vtoc box
        add     si, bx
        push    ds si
        pop     di es
        mov     cx, XFILE_ENTRY_SIZE
        xor     ax, ax                      ; Reset ax
        mov     al, ATTRIB_RED_YELLOW
        rep     stosb                       ; Mark it
        jmp     @@77

@@72:
; If file locked, mark it green
        cmp     [XFile_Locked], LOGIC_YES
        jne     @@74                    ; No
                                        ; Yes, so
        mov     si, offset AA_Attr
        add     si, Xdir_File_Offset    ; Our 8bit vtoc box
        add     si, bx
        push    ds si
        pop     di es
        mov     cx, XFILE_ENTRY_SIZE
        xor     ax, ax                      ; Reset ax
        mov     al, ATTRIB_GREEN_YELLOW
        rep     stosb                       ; Mark it

@@74:
; If comment, mark it magenta
        cmp     [XFile_Inverse], LOGIC_YES
        jne     @@75                    ; No
                                        ; Yes, so
        mov     si, offset AA_Attr
        add     si, Xdir_File_Offset    ; Our 8bit vtoc box
        add     si, bx
        push    ds si
        pop     di es
        mov     cx, XFILE_ENTRY_SIZE
        xor     ax, ax                      ; Reset ax
        mov     al, ATTRIB_MAGENTA_YELLOW
        rep     stosb                       ; Mark it

@@75:
; If file extended, mark sector size cyan blue
        cmp     [XFile_Extended], LOGIC_YES
        jne     @@77                    ; No
                                        ; Yes, so
        mov     si, offset AA_Attr
        add     si, Xdir_File_Offset    ; Our 8bit vtoc box
        add     si, bx
        add     si, 12                  ; Size of Filename
        push    ds si
        pop     di es
        mov     cx, 4                   ; Sector size
        xor     ax, ax                  ; Reset ax
        mov     al, ATTRIB_CYAN_BLUE
        cmp     [XFile_Locked], LOGIC_YES
        jne     @@76                    ; No
                                        ; Yes, so
        mov     al, ATTRIB_GREEN_BLUE

@@76:
        rep     stosb                   ; Mark it

@@77:
        pop     di es si ds dx cx

        add     si, EIGHTBIT_FILE_ENTRY_SIZE    ; Move to next vtoc entry
        dec     cx                      ; Complete vtoc scanned?
        jz      @@79                    ; Yes
                                        ; No, so
        dec     dx                      ; Move over to next screen column?
        jz      @@78                    ; Yes
                                        ; No, so
        add     di, ( XFile_Cols )
        add     bx, ( Screen_Cols )
        jmp     @@56                    ; Process next entry

@@78:
        sub     di, ( ( ( VTOC_FILES_COLUMN_ENTRIES - 1 ) *  XFile_Cols ) - XFILE_ENTRY_SIZE - 1 )
        sub     bx, ( ( ( VTOC_FILES_COLUMN_ENTRIES - 1 ) * Screen_Cols ) - XFILE_ENTRY_SIZE - 1 )
        jmp     @@55

@@79:
; Close file
        mov     bx, [Disk_Handler]
        mov     ah, DOS_CLOSE_FILE
        int     DOS_SERVICE
        jmp     @@81

@@80:
; Close file
        mov     bx, [Disk_Handler]
        mov     ah, DOS_CLOSE_FILE
        int     DOS_SERVICE
        jmp     @@99

@@81:
; Set up # of Free Sectors in Text Format
        push    ds si es di

        mov     ax, [XDisk_Sectors_Free]

; Init value text
        mov     cx, XFILE_SIZE_LENGTH
        mov     si, offset XFile_Size_Text
        push    ds si
        pop     di es
        mov     si, offset XFile_Size_Init
        rep     movsb
        dec     di                          ; Move to end of Text string
        mov     bx, 10                      ; Extract digits

; Convert hexadecimal size to textual digits
        call    Extract_Digit               ; Convert value below 10000
        call    Extract_Digit
        call    Extract_Digit
        call    Extract_Digit

; Surpress leading zeroes
        mov     bx, 3                       ; Value contains 4 characters
                                            ;       but we don't surpress
                                            ;       the last zero
@@82:                
        inc     di                          ; Move to digital character
        cmp     [byte es:di], ZERO          ; Character is leading zero?
        jne     @@83                        ; No
                                            ; Yes, so
        mov     [byte es:di], SPACE         ; Replace leading zero by space
        dec     bx                          ; More characters to check?
        jnz     @@82                        ; Yes
                                            ; No, so
@@83:
; Show # Free Sectors
        pop     di es si ds
        add     di, ( ( XFile_Cols * 2 ) + XFILE_ENTRY_SIZE - 4 )
        mov     si, offset XFile_Size_Text
        mov     cx, 4
        rep     movsb                   ; Move "  43" File Size part

; Valid disk image
        mov     si, offset AC_Xdir          ; Our main box
        add     si, Xdir_File_Offset        ; Our 8bit vtoc box
        push    ds si
        pop     di es

        mov     si, offset CC_Xdir          ; Our 8bit vtoc info
        mov     bx, XFile_Rows              ; Nr of Rows

@@85:
        mov     cx, XFile_Cols

@@90:
        movsb                               ; Move char from ds:si to es:di
        dec     cx
        jnz     @@90
        add     di, ( MAX_COL - XFile_Cols )
        dec     bx
        jnz     @@85

@@99:
        ret

ENDP    Set_Up_XFile_Window



;**********************************************************************
PROC    Show_Xdir
;**********************************************************************
        mov     es, [Video_Mode_Base]       ; Videomap Base
        mov     di, [Video_Mode_Offset]     ; Videomap Offset
        add     di, Xdir_Mode_Offset        ; Where our box will come

        mov     si, offset AC_Xdir          ; Our box Area
        mov     ax, offset AA_Attr          ; Our Attributes Area
        mov     bx, Screen_Rows             ; Nr of Rows

@@10:
        mov     cx, Screen_Cols

@@20:
        movsb                               ; Move char from ds:si to es:di
        push    si
        mov     si, ax
        movsb                               ; Move attr from ds:si to es:di
        mov     ax, si
        pop     si
        dec     cx
        jnz     @@20
        add     di, ( MAX_COL - Screen_Cols ) * 2
        dec     bx
        jnz     @@10
        ret

ENDP    Show_Xdir



;**********************************************************************
PROC    Process_Xdir
;**********************************************************************
@@00:
        xor     ax, ax                      ; Reset ax
        mov     ah, KEYBOARD_KBD_STATUS     ; Check buffer
        int     KEYBOARD_SERVICE
                                            ; Key waiting?
        jz      @@00                        ; No
                                            ; Yes, so
        mov     ah, KEYBOARD_READ_CHAR      ; Retrieve Key press
        int     KEYBOARD_SERVICE
        or      al, al                      ; Special Key pressed?
        jnz     @@10                        ; No
                                            ; Yes, so
        xchg    ah, al                      ; ah<-0, al<-scan code
        add     al, 32                      ; Adjust scan code to >= 32
        jmp     @@20

@@10:
        xor     ah, ah                      ; Assume Special Key
        cmp     al, 32                      ; Special Key pressed?
        jb      @@20                        ; Yes
                                            ; No, so
        inc     ah                          ; It's an ASCII key

@@20:
        or      ah, ah                      ; Set or clear zf result flag

@@99:
        ret

ENDP    Process_Xdir



;**********************************************************************
PROC    Process_Xdir_Key_ENTER
;**********************************************************************
        cmp     [XDIR_Status], XDIR_STATUS_DRIVE      ; Were we in Drive Mode?
        je      @@40                                ; Yes
                                                    ; No, so
        cmp     [XDIR_Status], XDIR_STATUS_ENTRY      ; Were we in Entry Mode?
        je      @@65                                ; Yes
                                                    ; No, so
; File Mode
@@10:
        mov     si, offset File_File_Text   ; Make Text FileName
        les     di, [AC_Xdir_FileText_Ptr]   ; Text is FileName or FileMask
        mov     cx, 8                       ; Copy length
        rep     movsb

        lds     si, [AC_Xdir_FileName_Ptr]   ; Save New Mask
        les     di, [File_Mask_Ptr]
        inc     di                          ; Skip the "\"
        mov     cx, FILE_NAME_LENGTH
        rep     movsb                       ; New Mask copied

        mov     si, offset File_Mask        ; Save "old" File Mask
        les     di, [Old_File_Mask_Ptr]
        mov     cx, FILE_NAME_LENGTH + 1    ; We also copy the "\"
        rep     movsb                       ; "old" File Mask saved

; Update directory information
        mov     [Xdir_Window], 1             ; Init Window
        mov     [Xdir_Window_File], 1        ; Init Window File
        call    Retrieve_Directory

        cmp     [Files_In_File_Table], 0    ; Files found?
        je      @@99                        ; No
                                            ; Yes, so
; Check for direct selection
; Search through current file entries for a perfect match
        call    Transfer_Directory_To_Xdir
        call    Deselect_Xdir_Window_File
        call    Show_Xdir

; Restore Entered value first
        mov     si, offset File_Mask + 1    ; To skip the "\"
        les     di, [AC_Xdir_FileName_Ptr]   ; Name/Mask location
        mov     cx, FILE_NAME_LENGTH        ; Copy/Initialize length
        rep     movsb                       ; Copy FileMask

; Switch to Entry Mode
        mov     cl, [Xdir_Drive]             ; Get drive number
        mov     [Old_Xdir_Drive], cl         ; Remember "old" drive

        call    Deselect_Xdir_File
        call    Select_Xdir_Window_File
 
        mov     [Cursor_Position.Row], OFF_SCREEN
        mov     [Cursor_Position.Col], OFF_SCREEN
        call    Set_Cursor_Position
 
        mov     [XDIR_Status], XDIR_STATUS_ENTRY  ; Switch to Entry Mode
        jmp     @@99

; Drive Mode
@@40:
; Check if the drive was changed
        mov     cl, [Old_Xdir_Drive]         ; Get "old" drive number
        cmp     [Xdir_Drive], cl             ; Drive changed?
        je      @@50                        ; No
                                            ; Yes, so
        mov     si, offset Msg_Error
        mov     [byte ds:si], SPACE         ; Assume no error occurs

; Change to requested drive, and go to root of the drive
        mov     si, offset AC_Xdir_Drive_Map ; Our Drive Area
        xor     cx, cx                      ; Reset cx
        mov     cl, [Xdir_Drive]             ; Get drive number
        add     si, cx                      ; Go to selected drive

        xor     bx, bx                      ; Reset dx
        mov     bl, [byte ds:si]            ; Copy selected drive to path
        sub     bl, 64                      ; Turn drive into DOS drive
        mov     ch, 008h                    ; Device category
        mov     cl, 066h                    ; Minor code
        mov     dx, offset Media_ID_Buffer
        mov     ah, DOS_SENSE_MEDIA_TYPE
        mov     al, 00Dh                    ; Subfunction Code
        int     DOS_SERVICE                 ; Check Drive Presence
        cmp     ax, DOS_DRIVE_NOT_READY     ; Drive ready?
        jne     @@45                        ; Yes
                                            ; No, so
; Init file table
        mov     si, offset File_Table
        push    ds si
        pop     di es
        xor     ax, ax                      ; Reset table with 000h
        mov     cx, File_Table_Length       ; Nr of Bytes in File_Table
        rep     stosb

; Reset Number of Files in File Table, and clear box entries
        mov     [Files_In_File_Table], 0
        call    Transfer_Directory_To_Xdir

; Set Error Message
        mov     si, offset Msg_Error
        push    ds si
        pop     di es
        mov     si, offset Msg_Drive_Not_Ready
        mov     cx, BOX_MSG_LENGTH
        rep     movsb

; Continue
        mov     cl, [Xdir_Drive]             ; Get drive number
        mov     [Old_Xdir_Drive], cl         ; Remember "old" drive
        jmp     @@99

@@45:
        les     di, [Search_Spec_Drive_Ptr] ; Change path
        xor     ax, ax                      ; Reset ax
        mov     al, SPACE                   ; Fill character
        mov     cx, PATH_LENGTH             ; Path size
        rep     stosb                       ; Initialize path

        les     di, [Search_Spec_Drive_Ptr] ; Change search path
        lds     si, [Default_Drive_Path_Ptr]    ; Use default path
        mov     cx, FILE_NAME_LENGTH + 2    ; Which is Z:\*.*
        rep     movsb                       ; Search path changed

        les     di, [Search_Spec_Drive_Ptr] ; Change search drive
        mov     si, offset AC_Xdir_Drive_Map ; Our Drive Area
        xor     cx, cx                      ; Reset cx
        mov     cl, [Xdir_Drive]             ; Get drive number
        add     si, cx                      ; Go to selected drive
        movsb                               ; Copy selected drive to path

        mov     [Current_Sub_Directory], 0  ; Reset Sub Directories counter
        les     di, [Sub_Directories_Ptr]
        xor     ax, ax                      ; Reset ax
        mov     al, SPACE                   ; Fill directory with Spaces
        mov     cx, Sub_Directories_Length  ; Nr of Bytes in Sub Dir Table
        rep     stosb

        mov     [Xdir_Window], 1             ; Init Window
        mov     [Xdir_Window_File], 1        ; Init Window File
        call    Retrieve_Directory

@@50:
        mov     si, offset Msg_Error
        cmp     [byte ds:si], SPACE         ; Error occurred?
        jne     @@60                        ; Yes
                                            ; No, so
        mov     [XDIR_Status], XDIR_STATUS_ENTRY  ; Switch to Entry Mode
        Call    Deselect_Xdir_Drive
        Call    Select_Xdir_Window_File
        jmp     @@99

@@60:
        mov     cl, [Xdir_Drive]             ; Get drive number
        mov     [Old_Xdir_Drive], cl         ; Remember "old" drive
        jmp     @@99

; Entry Mode
@@65:
        xor     ax, ax                      ; Reset ax
        mov     cx, [Xdir_Window]            ; Is 1 when directory was just read
        mov     al, [Xdir_Window_File]       ; Get selected entry
        dec     ax                          ;       within File Table
        add     ax, cx                      ; Xdir_Window_File + Xdir Window
        dec     ax                          ; Get correct entry in File Table
        mov     cx, FILE_ENTRY_LENGTH       ; Multiply by size of Entry
        mul     cx

        push    ds si es di                 ; Copy entry to entry structure
        mov     si, Offset File_Table
        add     si, ax
        les     di, [File_Table_Entry_Ptr]
        mov     cx, FILE_ENTRY_LENGTH
        rep     movsb
        pop     di es si ds                 ; Copy complete

        xor     ax, ax                      ; Reset ax
        mov     al, [File_Table_Entry.File_Attribute]
        and     al, ATTRIB_FILE_DIRECTORY
        cmp     al, ATTRIB_FILE_DIRECTORY   ; Entry is a directory?
        je      @@72                        ; Yes
                                            ; No, so

@@70:
; Entry is a disk image
        mov     si, offset Disk_Parameters.Path
        push    ds si
        pop     di es
        push    ds si
        mov     si, offset Search_Spec_Drive
        mov     cx, PATH_LENGTH             ; Length of path
        rep     movsb                       ; Selected path copied
        pop     di es
        mov     cx, PATH_LENGTH             ; Search length
        add     di, cx                      ; Go to end of pth
        std                                 ; Search direction is down
        xor     ax, ax                      ; Reset ax
        mov     al, BACKSLASH               ; Search for the "\" character
        repne   scasb                       ; Search equal "\" uses es:di
        cld                                 ; Cancel the std setting
        inc     di                          ; Pointer adjustment after search
        inc     di                          ; Place Filename after the "\"
        mov     si, offset File_Table_Entry.File_Name   ; Directory location
        mov     cx, FILE_NAME_LENGTH
        rep     movsb

        call    XFILES

        jmp     @@99

@@72:
; Entry is a directory
        call    Deselect_Xdir_Window_File

        mov     bx, PATH_LENGTH             ; Path length
        mov     si, offset File_Table_Entry.File_Name   ; Directory location
        les     di, [Search_Spec_Drive_Ptr]
        mov     cx, PATH_LENGTH             ; Search length
        add     di, cx                      ; Go to end of Path
        or      ax, ax                      ; Reset ax
        mov     al, BACKSLASH               ; Search for the "\" character
        std                                 ; Search direction is down
        repne   scasb                       ; Search equal "\" uses es:di
        cld                                 ; Cancel the std setting
        cmp     [byte ds:si], "."           ; Back to previous directory?
        jne     @@76                        ; No
                                            ; Yes, so
; Back to previous directory
        std                                 ; Search direction is down
        repne   scasb                       ; Search equal "\" uses es:di
        cld                                 ; Cancel the std setting
        inc     di                          ; Pointer adjustment after search
        sub     bx, cx                      ; bx used to blank rest of path
        dec     bx
        cmp     [Current_Sub_Directory], MAX_SUB_DIRECTORIES    ; Above Table?
        jnle    @@74                        ; Yes
                                            ; No, so
        push    es di

        les     di, [Sub_Directories_Ptr]   ; Our Sub Directories Table
        mov     cx, SUB_DIRECTORY_ENTRY_LENGTH  ; Length of entry
        xor     ax, ax                      ; Reset ax
        mov     al, [Current_Sub_Directory] ; Where are we in the table?
        mul     cx                          ; Copy nr of entries * entry length
        add     di, ax                      ; Go to correct entry in Table
        sub     di, 3                       ; To move to Window Part
        mov     ax, [word es:di]            ; Get Xdir Window
        mov     [Xdir_Window], ax           ; Set Xdir Window
        mov     al, [byte es:di + 2]        ; Get Xdir Window File
        mov     [Xdir_Window_File], al      ; Set Xdir Window File

        pop     di es
        dec     [Current_Sub_Directory]     ; Adjust Nr of Sub Dirs
        jmp     @@90                        ; Append search mask

@@74:
        dec     [Current_Sub_Directory]     ; Adjust Nr of Sub Dirs
        mov     [Xdir_Window], 1             ; In the previous directory we go
        mov     [Xdir_Window_File], 1        ;    to the first entry (for now)
        jmp     @@90                        ; Append search mask

; Go to selected Sub Directory
@@76:
        inc     di                          ; Pointer adjustment after search
        inc     di                          ; Point after the "\"
        sub     bx, cx                      ; bx used to blank rest of path
        sub     bx, 2
        mov     cx, FILE_NAME_LENGTH        ; Directory length
        push    es di
        rep     movsb                       ; Copy Directory
        cmp     [Current_Sub_Directory], MAX_SUB_DIRECTORIES    ; Table full?
        je      @@78                        ; Yes
                                            ; No, so
        pop     si ds
        push    ds si

        les     di, [Sub_Directories_Ptr]   ; Our Sub Directories Table
        mov     cx, SUB_DIRECTORY_ENTRY_LENGTH  ; Length of entry
        xor     ax, ax                      ; Reset ax
        mov     al, [Current_Sub_Directory] ; Where are we in the table?
        mul     cx                          ; Copy nr of entries * entry length
        add     di, ax                      ; Go to next entry in Sub Dir Table
        mov     cx, SUB_DIRECTORY_ENTRY_LENGTH - 3  ; To move to Window part
        rep     movsb                       ; Save Sub Directory
        mov     cx, [Xdir_Window]           ; Get  Xdir Window
        mov     [word es:di], cx            ; Save Xdir Window
        inc     di                          ; Move to
        inc     di                          ;      Xdir_Window_File
        xor     cx, cx                      ; Reset cx
        mov     cl, [Xdir_Window_File]      ; Get  Xdir Window File
        mov     [byte es:di], cl            ; Save Xdir Window File
        inc     [Current_Sub_Directory]     ; Increment counter

@@78:
        pop     di es
        mov     [Xdir_Window], 1             ; In the new directory we go
        mov     [Xdir_Window_File], 1        ;    to the first entry

@@80:
        cmp     [byte es:di], SPACE         ; Can we append the mask yet?
        je      @@90                        ; Yes
                                            ; No, so
        cmp     [byte es:di], NULL          ; Can we append the mask yet?
        je      @@90                        ; Yes
                                            ; No, so
        inc     di
        dec     bx
        jmp     @@80

; Append File mask after directory
@@90:
        mov     si, offset File_Mask        ; Append the File Mask now
        mov     cx, FILE_NAME_LENGTH + 1    ; Directory length + "\" character
        sub     bx, cx
        rep     movsb                       ; Append now

; Fill rest of path with spaces
        mov     cx, bx                      ; Fill remainder of path
        mov     al, SPACE                   ;   with spaces
        rep     stosb

; Retrieve new directory information
        call    Retrieve_Directory

@@99:
        ret

ENDP    Process_Xdir_Key_ENTER



;**********************************************************************
PROC    Process_Xdir_Key_TAB
;**********************************************************************
        cmp     [XDIR_Status], XDIR_STATUS_DRIVE      ; Were we in Drive Mode?
        je      @@40                                ; Yes
                                                    ; No, so
        cmp     [XDIR_Status], XDIR_STATUS_ENTRY      ; Were we in Entry Mode?
        je      @@70                                ; Yes
                                                    ; No, so
; We were in File Mode
@@10:
        call    Deselect_Xdir_File

        mov     [Cursor_Position.Row], OFF_SCREEN
        mov     [Cursor_Position.Col], OFF_SCREEN
        call    Set_Cursor_Position

        push    ds si es di

        mov     si, offset File_File_Text   ; Make Text FileName
        les     di, [AC_Xdir_FileText_Ptr]   ; Text is FileName or FileMask
        mov     cx, 8                       ; Copy length
        rep     movsb

        mov     si, offset Xdir_FileName     ; Restore FileName
        les     di, [AC_Xdir_FileName_Ptr]
        mov     cx, FILE_NAME_LENGTH
        rep     movsb                       ; FileName restored

        pop     di es si ds

        mov     cl, [Xdir_Drive]             ; Get drive number
        mov     [Old_Xdir_Drive], cl         ; Remember "old" drive
        mov     [XDIR_Status], XDIR_STATUS_DRIVE      ; Switch to Drive Mode
        call    Select_Xdir_Drive

        jmp     @@99

; We were in Drive Mode
@@40:
        mov     si, offset Msg_Error
        cmp     [byte ds:si], SPACE         ; Did we have an Error Message?
        je      @@50                        ; No
                                            ; Yes, so
        mov     si, offset Msg_No_Files_Found
        push    ds si
        pop     di es
        mov     si, offset Msg_Error
        mov     cx, BOX_MSG_LENGTH
        rep     cmpsb                       ; Severe error?
        jne     @@99                        ; Yes
                                            ; No, so
        mov     [Cursor_Position.Row], XDIR_FILE_START_ROW - 1
        mov     [Cursor_Position.Col], XDIR_FILE_START_COL
        call    Set_Cursor_Position
        mov     [XDIR_Status], XDIR_STATUS_FILE   ; Switch to File Mode

        mov     si, offset File_Mask + 1            ; To skip the "\"
        les     di, [AC_Xdir_FileName_Ptr]           ; Copy File Mask
        mov     cx, FILE_NAME_LENGTH
        rep     movsb                               ; File Mask put on screen

        Call    Deselect_Xdir_Drive
        Call    Select_Xdir_File
        jmp     @@99

@@50:
        Call    Deselect_Xdir_Drive

; Restore Old Drive
        mov     cl, [Old_Xdir_Drive]         ; Get "old" drive number
        mov     [Xdir_Drive], cl             ; And Restore it
        call    Select_Xdir_Drive
        mov     [XDIR_Status], XDIR_STATUS_ENTRY  ; Switch to Entry Mode
        Call    Deselect_Xdir_Drive
        Call    Select_Xdir_Window_File
        jmp     @@99

; We were in Entry Mode
@@70:
        call    Deselect_Xdir_Window_File
        mov     [Cursor_Position.Row], XDIR_FILE_START_ROW - 1
        mov     [Cursor_Position.Col], XDIR_FILE_START_COL
        call    Set_Cursor_Position
        mov     [XDIR_Status], XDIR_STATUS_FILE       ; Switch to File Mode

        push    ds si es di

        mov     si, offset File_Mask_Text   ; Make Text FileMask
        les     di, [AC_Xdir_FileText_Ptr]   ; Text is FileName or FileMask
        mov     cx, 8                       ; Copy length
        rep     movsb

        lds     si, [AC_Xdir_FileName_Ptr]   ; Save FileName
        les     di, [Xdir_FileName_Ptr]
        mov     cx, FILE_NAME_LENGTH
        rep     movsb                       ; FileName saved

        mov     si, offset File_Mask        ; Save "old" File Mask
        les     di, [Old_File_Mask_Ptr]
        mov     cx, FILE_NAME_LENGTH + 1    ; We also copy the "\"
        rep     movsb                       ; "old" File Mask saved

        mov     si, offset File_Mask + 1    ; To skip the "\"
        xor     ax, ax                      ; Reset ax
        mov     al, SPACE                   ; Fill character
        les     di, [AC_Xdir_FileName_Ptr]   ; Name/Mask location
        mov     cx, FILE_NAME_LENGTH        ; Copy/Initialize length

        rep     movsb                       ; Copy FileMask

@@90:
        pop     di es si ds

        call    Select_Xdir_File
        jmp     @@99

@@99:
        ret

ENDP    Process_Xdir_Key_TAB



;**********************************************************************
PROC    Process_Xdir_Key_HELP
;**********************************************************************
; Save current cursor location (before Help was executed)
        call    Save_Temp_Cursor

        mov     es, [Video_Mode_Base]       ; Videomap Base
        mov     di, [Video_Mode_Offset]     ; Videomap Offset
        add     di, Xdir_Mode_Offset        ; Where our box is
        add     di, ( MAX_COL + 1 ) * 2     ; Where our HELP screen will come
        mov     ax, offset BA_Attr          ; Our Attributes Area
        mov     bx, Screen_Rows - 1         ; Nr of Rows

        mov     si, offset BC_Xdir          ; Our box Area File Mode

@@10:
        mov     cx, Screen_Cols_Help

@@20:
        movsb                               ; Move char from ds:si to es:di
        push    si
        mov     si, ax
        movsb                               ; Move attr from ds:si to es:di
        mov     ax, si
        pop     si
        dec     cx
        jnz     @@20
        add     di, ( MAX_COL - Screen_Cols_Help ) * 2
        dec     bx
        jnz     @@10

        call    Process_Xdir
        call    Show_Xdir

; Restore previously saved cursor
        call    Restore_Temp_Cursor

        ret

ENDP    Process_Xdir_Key_HELP



;**********************************************************************
PROC    Process_Xdir_Key_FILE
;**********************************************************************
        push    es di

; Convert Key to Uppercase?
        mov     si, offset File_Mask_To_Uppercase

@@10:
        cmp     [byte ds:si], NULL          ; End of check reached?
        je      @@30                        ; Yes
                                            ; No, so
        cmp     [byte ds:si], al            ; Convert Key to Uppercase?
        je      @@20                        ; Yes
                                            ; No, so
        inc     si                          ; Move to next key in table
        jmp     @@10                        ; Check key

@@20:
        sub     al, 020h                    ; Convert to Uppercase

@@30:
        les     di, [AC_Xdir_FileName_Ptr]           ; Position Of Mask
        xor     dx, dx                              ; Reset dx
        mov     dl, [Cursor_Position.Col]           ; Cursor Position
        sub     dx, XDIR_FILE_START_COL
        add     di, dx                              ; Current location reached
        mov     [byte es:di], al                    ; Accept entered character

        cmp     [Cursor_Position.Col], XDIR_FILE_END_COL     ; End reached
        je      @@99                                ; Yes
                                                    ; No, so
        inc     [Cursor_Position.Col]               ; Move up one position
        call    Set_Cursor_Position

@@99:
        pop     di es

        ret

ENDP    Process_Xdir_Key_FILE



;**********************************************************************
PROC    Process_Xdir_Key_ARROW_UP
;**********************************************************************
        cmp     [XDIR_Status], XDIR_STATUS_ENTRY  ; Are we in Entry Mode?
        jne     @@99                            ; No
                                                ; Yes, so
        cmp     [Files_In_File_Table], 0    ; Files found?
        je      @@99                        ; No
                                            ; Yes, so        
        cmp     [Xdir_Window], 1             ; Are we in the first window?
        jne     @@10                        ; No
                                            ; Yes, so
        cmp     [Xdir_Window_File], 1        ; Are we at the first file?
        je      @@99                        ; Yes
                                            ; No, so
@@10:
        cmp     [Xdir_Window_File], 1        ; Are we at the first file?
        je      @@20                        ; Yes
                                            ; No, so
        call    Deselect_Xdir_Window_File
        dec     [Xdir_Window_File]           ; Move to previous entry
        call    Select_Xdir_Window_File
        jmp     @@99

@@20:
        dec     [Xdir_Window]                ; Go to previous Window
        call    Select_Xdir_Window_File

@@99:
        ret

ENDP    Process_Xdir_Key_ARROW_UP



;**********************************************************************
PROC    Process_Xdir_Key_ARROW_RIGHT
;**********************************************************************
        cmp     [XDIR_Status], XDIR_STATUS_DRIVE      ; Are we in Drive Mode?
        je      @@40                                ; Yes
                                                    ; No, so
        cmp     [XDIR_Status], XDIR_STATUS_FILE       ; Are we in File Mode?
        jne     @@99                                ; No
                                                    ; Yes, so
; File Mode
@@10:
        cmp     [Cursor_Position.Col], XDIR_FILE_END_COL     ; End reached?
        je      @@99                                ; Yes
                                                    ; No, so
        les     di, [AC_Xdir_FileName_Ptr]           ; Position Of Mask
        xor     dx, dx                              ; Reset dx
        mov     dl, [Cursor_Position.Col]           ; Cursor Position
        sub     dx, XDIR_FILE_START_COL
        add     di, dx                              ; Current location reached
        cmp     [byte es:di], SPACE                 ; Can we go to the right?
        je      @@99                                ; No
                                                    ; Yes, so
        inc     [Cursor_Position.Col]               ; Move up one position
        call    Set_Cursor_Position
        jmp     @@99

; Drive Mode
@@40:
        xor     ax, ax                      ; Reset ax
        mov     al, [Max_Xdir_Drive]         ; Load last drive number
        cmp     [Xdir_Drive], al             ; Are we at the last drive?
        je      @@99                        ; Yes
                                            ; No, so
        call    Deselect_Xdir_Drive
        inc     [Xdir_Drive]                 ; Move one drive up to the right
        call    Select_Xdir_Drive

@@99:
        ret

ENDP    Process_Xdir_Key_ARROW_RIGHT



;**********************************************************************
PROC    Process_Xdir_Key_ARROW_DOWN
;**********************************************************************
        cmp     [XDIR_Status], XDIR_STATUS_ENTRY  ; Are we in Entry Mode?
        jne     @@99                              ; No
                                                  ; Yes, so
        cmp     [Files_In_File_Table], 0    ; Files found?
        je      @@99                        ; No
                                            ; Yes, so        
        xor     ax, ax                      ; Reset ax
        mov     cx, [Xdir_Window]           ; Is 1 when directory was just read
        mov     al, [Xdir_Window_File]      ; Get selected entry
        dec     ax                          ;       within File Table
        add     cx, ax                      ; Xdir_Window + Xdir_Window_File
        cmp     cx, [Files_In_File_Table]   ; Are we at the last file?
        je      @@99                        ; Yes
                                            ; No, so
        cmp     [Xdir_Window_File], Max_Files_In_Xdir_Table   ; End of box?
        je      @@10                        ; Yes
                                            ; No, so
        call    Deselect_Xdir_Window_File
        inc     [Xdir_Window_File]           ; Move to next entry
        call    Select_Xdir_Window_File
        jmp     @@99

@@10:
        inc     [Xdir_Window]
        call    Select_Xdir_Window_File

@@99:
        ret

ENDP    Process_Xdir_Key_ARROW_DOWN



;**********************************************************************
PROC    Process_Xdir_Key_ARROW_LEFT
;**********************************************************************
        cmp     [XDIR_Status], XDIR_STATUS_DRIVE      ; Are we in Drive Mode?
        je      @@40                                ; Yes
                                                    ; No, so
        cmp     [XDIR_Status], XDIR_STATUS_FILE       ; Are we in File Mode?
        jne     @@99                                ; No
                                                    ; Yes, so
; File Mode
@@10:
        cmp     [Cursor_Position.Col], XDIR_FILE_START_COL   ; At beginning?
        je      @@99                                ; Yes
                                                    ; No, so
        dec     [Cursor_Position.Col]               ; Move down one position
        call    Set_Cursor_Position
        jmp     @@99

; Drive Mode
@@40:
        cmp     [Xdir_Drive], 1              ; Are we at the 1st drive already?
        je      @@99                        ; Yes
                                            ; No, so
        call    Deselect_Xdir_Drive
        dec     [Xdir_Drive]                 ; Move one drive up to the left
        call    Select_Xdir_Drive

@@99:
        ret

ENDP    Process_Xdir_Key_ARROW_LEFT



;**********************************************************************
PROC    Process_Xdir_Key_PAGE_UP
;**********************************************************************
        cmp     [XDIR_Status], XDIR_STATUS_ENTRY  ; Are we in Entry Mode?
        jne     @@99                            ; No
                                                ; Yes, so
        cmp     [Files_In_File_Table], 0    ; Files found?
        je      @@99                        ; No
                                            ; Yes, so        
        cmp     [Xdir_Window], 1             ; Are we in the first window?
        jne     @@10                        ; No
                                            ; Yes, so
        cmp     [Xdir_Window_File], 1        ; Are we at the first file?
        je      @@99                        ; Yes
                                            ; No, so
        call    Deselect_Xdir_Window_File
        jmp     @@90                        ; Go to top of window

; Go back 1 window or to top of first window?
@@10:
        xor     ax, ax                      ; Reset ax
        mov     ax, [Xdir_Window]            ; Get window
        cmp     ax, Max_Files_In_Xdir_Table  ; Go back 1 complete window?
        jg      @@20                        ; Yes
                                            ; No, so
        call    Deselect_Xdir_Window_File
        mov     [Xdir_Window], 1             ; Go to first window
        jmp     @@90

; Go back 1 complete window
@@20:
        call    Deselect_Xdir_Window_File
        sub     [Xdir_Window], Max_Files_In_Xdir_Table
        jmp     @@90

@@90:
        mov     [Xdir_Window_File], 1        ; Move to first file in window
        call    Select_Xdir_Window_File

@@99:
        ret

ENDP    Process_Xdir_Key_PAGE_UP



;**********************************************************************
PROC    Process_Xdir_Key_PAGE_DOWN
;**********************************************************************
        cmp     [XDIR_Status], XDIR_STATUS_ENTRY  ; Are we in Entry Mode?
        jne     @@99                            ; No
                                                ; Yes, so
        cmp     [Files_In_File_Table], 0    ; Files found?
        je      @@99                        ; No
                                            ; Yes, so        
        xor     ax, ax                      ; Reset ax
        mov     cx, [Xdir_Window]            ; Is 1 when directory was just read
        mov     al, [Xdir_Window_File]       ; Get selected entry
        dec     ax                          ;       within File Table
        add     cx, ax                      ; Xdir_Window + Xdir_Window_File
        cmp     cx, [Files_In_File_Table]   ; Are we at the last file?
        je      @@99                        ; Yes
                                            ; No, so
        call    Deselect_Xdir_Window_File
        mov     ax, [Files_In_File_Table]   ; Get number of files in File Table
        sub     ax, Max_Files_In_Xdir_Table  ; So we know if we can skip 1 window
        cmp     [Xdir_Window], ax            ; Can we skip 1 window?
        jg      @@10                        ; No
                                            ; Yes, so
        add     [Xdir_Window], Max_Files_In_Xdir_Table    ; Skip 1 window

@@10:
        mov     ax, [Files_In_File_Table]   ; Get total number of files
        sub     ax, [Xdir_Window]            ; Determine remaining files
        mov     [Xdir_Window_File], Max_Files_In_Xdir_Table   ; Go to End
        cmp     ax, Max_Files_In_Xdir_Table  ; Can we go to the end of box?
        jge     @@90                        ; Yes
                                            ; No, so
        inc     ax                          ; Adjust pointer to correct entry
        mov     [Xdir_Window_File], al       ; Point to last possible entry

@@90:
        call    Select_Xdir_Window_File

@@99:
        ret

ENDP    Process_Xdir_Key_PAGE_DOWN



;**********************************************************************
PROC    Process_Xdir_Key_HOME
;**********************************************************************
        cmp     [XDIR_Status], XDIR_STATUS_DRIVE  ; Are we in Drive Mode?
        je      @@40                            ; Yes
                                                ; No, so
        cmp     [XDIR_Status], XDIR_STATUS_ENTRY  ; Are we in Entry Mode?
        je      @@70                            ; Yes
                                                ; No, so
; File Mode
@@10:
        cmp     [Cursor_Position.Col], XDIR_FILE_START_COL   ; At beginning?
        je      @@99                                ; Yes
                                                    ; No, so
        mov     [Cursor_Position.Col], XDIR_FILE_START_COL
        call    Set_Cursor_Position
        jmp     @@99

; Drive Mode
@@40:
        call    Deselect_Xdir_Drive
        mov     [Xdir_Drive], 1              ; Go to first entry
        call    Select_Xdir_Drive
        jmp     @@99

; Directory Mode
@@70:
        cmp     [Files_In_File_Table], 0    ; Files found?
        je      @@99                        ; No
                                            ; Yes, so        
        cmp     [Xdir_Window], 1             ; Are we in the first window?
        jne     @@80                        ; No
                                            ; Yes, so
        cmp     [Xdir_Window_File], 1        ; Are we at the first entry?
        je      @@99                        ; Yes
                                            ; No, so
        jmp     @@90                        ; Go to first entry

; Go to first window
@@80:
        mov     [Xdir_Window], 1
        cmp     [Xdir_Window_File], 1        ; Are we at the first entry?
        je      @@95                        ; Yes
                                            ; No, so

; Go to first entry
@@90:
        call    Deselect_Xdir_Window_File
        mov     [Xdir_Window_File], 1        ; Go to first entry

@@95:
        call    Select_Xdir_Window_File

@@99:
        ret

ENDP    Process_Xdir_Key_HOME



;**********************************************************************
PROC    Process_Xdir_Key_END
;**********************************************************************
        cmp     [XDIR_Status], XDIR_STATUS_DRIVE  ; Are we in Drive Mode?
        je      @@40                            ; Yes
                                                ; No, so
        cmp     [XDIR_Status], XDIR_STATUS_ENTRY  ; Are we in Entry Mode?
        je      @@70                            ; Yes
                                                ; No, so
; File Mode
@@10:
        cmp     [Cursor_Position.Col], XDIR_FILE_END_COL     ; End reached?
        je      @@99                                ; Yes
                                                    ; No, so
        les     di, [AC_Xdir_FileName_Ptr]           ; Position Of Mask

@@20:
        cmp     [byte es:di], SPACE                 ; Place cursor here?
        je      @@30                                ; Yes
                                                    ; No, so
        inc     [Cursor_Position.Col]               ; Move cursor to right
        cmp     [Cursor_Position.Col], XDIR_FILE_END_COL     ; End reached?
        je      @@30                                ; Yes
                                                    ; No, so
        inc     di                                  ; Next location
        jmp     @@20

@@30:
        call    Set_Cursor_Position
        jmp     @@99

; Drive Mode
@@40:
        call    Deselect_Xdir_Drive
        xor     ax, ax                      ; Reset ax
        mov     al, [Max_Xdir_Drive]
        mov     [Xdir_Drive], al             ; Go to last entry
        call    Select_Xdir_Drive
        jmp     @@99

; Directory Mode
@@70:
        cmp     [Files_In_File_Table], 0    ; Files found?
        je      @@99                        ; No
                                            ; Yes, so        
        xor     ax, ax                      ; Reset ax
        mov     cx, [Xdir_Window]            ; Is 1 when directory was just read
        mov     al, [Xdir_Window_File]       ; Get selected entry
        dec     ax                          ;       within File Table
        add     cx, ax                      ; Xdir_Window + Xdir_Window_File
        cmp     cx, [Files_In_File_Table]   ; Are we at the last file?
        je      @@99                        ; Yes
                                            ; No, so
        call    Deselect_Xdir_Window_File

        cmp     [Files_In_File_Table], Max_Files_In_Xdir_Table   ; All files already on screen?
        jle     @@80                                            ; Yes
                                                                ; No, so
        mov     ax, [Files_In_File_Table]   ; Get number of files in File Table
        sub     ax, Max_Files_In_Xdir_Table  ; Calculate last window
        inc     ax                          ; To get correct window
        mov     [Xdir_Window], ax            ; Point to window

@@80:
        mov     ax, [Files_In_File_Table]   ; Get total number of files
        sub     ax, [Xdir_Window]            ; Determine remaining files
        mov     [Xdir_Window_File], Max_Files_In_Xdir_Table   ; Go to End
        cmp     ax, Max_Files_In_Xdir_Table  ; Can we go to the end of box?
        jge     @@90                        ; Yes
                                            ; No, so
        inc     ax                          ; Adjust pointer to correct entry
        mov     [Xdir_Window_File], al       ; Point to last possible entry

@@90:
        call    Select_Xdir_Window_File

@@99:
        ret

ENDP    Process_Xdir_Key_END



;**********************************************************************
PROC    Process_Xdir_Key_BACKSPACE
;**********************************************************************
        cmp     [XDIR_Status], XDIR_STATUS_FILE       ; Are we in File Mode?
        jne     @@99                                ; No
                                                    ; Yes, so
; File Mode
@@10:
        cmp     [Cursor_Position.Col], XDIR_FILE_START_COL   ; At beginning?
        je      @@99                                ; Yes
                                                    ; No, so
        lds     si, [AC_Xdir_FileName_Ptr]           ; Position Of Mask
        les     di, [AC_Xdir_FileName_Ptr]           ; Position Of Mask
        xor     dx, dx                              ; Reset dx
        mov     dl, [Cursor_Position.Col]           ; Cursor Position
        sub     dx, XDIR_FILE_START_COL
        add     si, dx                              ; Current location reached
        add     di, dx                              ; Current location reached
        dec     di                                  ; New cursor location
        mov     cx, XDIR_FILE_END_COL                ; Determine copy length
        xor     dx, dx                              ; Reset dx
        mov     dl, [Cursor_Position.Col]           ; Cursor Position
        dec     dx                                  ; Because of offset reasons
        sub     cx, dx                              ; Copy length determined
        rep     movsb                               ; Copy String
        les     di, [AC_Xdir_FileName_Ptr]           ; Position Of Mask
        add     di, FILE_NAME_LENGTH - 1            ; Go to last position
        mov     [byte es:di], SPACE                 ; Reset last character
        dec     [Cursor_Position.Col]               ; Move down one position
        call    Set_Cursor_Position

@@99:
        ret

ENDP    Process_Xdir_Key_BACKSPACE



;**********************************************************************
PROC    Process_Xdir_Key_DELETE
;**********************************************************************
        cmp     [XDIR_Status], XDIR_STATUS_FILE       ; Are we in File Mode?
        jne     @@99                                ; No
                                                    ; Yes, so
; File Mode
@@10:
        lds     si, [AC_Xdir_FileName_Ptr]           ; Position Of Mask
        les     di, [AC_Xdir_FileName_Ptr]           ; Position Of Mask
        xor     dx, dx                              ; Reset dx
        mov     dl, [Cursor_Position.Col]           ; Cursor Position
        sub     dx, XDIR_FILE_START_COL
        add     si, dx                              ; Current location reached
        add     di, dx                              ; Current location reached
        cmp     [Cursor_Position.Col], XDIR_FILE_END_COL ; At end?
        je      @@20                                ; Yes
                                                    ; No, so
        inc     si                                  ; Copy stuff right of it
        mov     cx, XDIR_FILE_END_COL                ; Determine copy length
        xor     dx, dx                              ; Reset dx
        mov     dl, [Cursor_Position.Col]           ; Cursor Position
        sub     cx, dx                              ; Copy length determined
        rep     movsb                               ; Copy String
        les     di, [AC_Xdir_FileName_Ptr]           ; Position Of Mask
        add     di, FILE_NAME_LENGTH - 1            ; Go to last position

@@20:
        mov     [byte es:di], SPACE                 ; Reset last character

@@99:
        ret

ENDP    Process_Xdir_Key_DELETE



;**********************************************************************
PROC    Process_File_Valid
;**********************************************************************
; Assume default
        mov     [File_Valid], FALSE
        mov     [File_Dot_Used], FALSE

; Validate Name/Mask
        lds     si, [AC_Xdir_FileName_Ptr]   ; Entered Name/Mask
        mov     cx, FILE_NAME_LENGTH

        cmp     [byte ds:si], DOT           ; FileName starts with dot?
        je      @@99                        ; Yes
                                            ; No, so
        cmp     [byte ds:si], SPACE         ; FileName not specified?
        je      @@99                        ; Yes
                                            ; No, so
@@10:
        cmp     [byte ds:si], SPACE         ; End of String reached?
        je      @@90                        ; Yes
                                            ; No, so
        cmp     [byte ds:si], DOT           ; Dot located?
        jne     @@20                        ; No
                                            ; Yes, so
; Processing dot
        cmp     [File_Dot_Used], TRUE       ; Dot already used?
        je      @@99                        ; Yes
                                            ; No, so
        mov     [File_Dot_Used], TRUE
        xor     bx, bx                      ; Reset bx
        jmp     @@60

@@20:
; Processing character
        cmp     [File_Dot_Used], TRUE       ; Dot already used?
        je      @@30                        ; Yes
                                            ; No, so
        cmp     cx, 4                       ; Every character still valid?
        jle     @@99                        ; No
                                            ; Yes, so
@@30:
        inc     si
        loop    @@10
        jmp     @@90

; Lif after the dot
@@40:
        cmp     [byte ds:si], SPACE         ; End of String reached?
        je      @@90                        ; Yes
                                            ; No, so
        cmp     [byte ds:si], DOT           ; Dot located?
        je      @@99                        ; Yes!
                                            ; No, so
@@50:
; Processing character
        inc     bx                          ; Max. of 3 characters behind dot
        cmp     bx, 3                       ; Max. surpassed?
        jg      @@99                        ; Yes
                                            ; No,so
@@60:
        inc     si
        loop    @@40

; File is ok
@@90:
        mov     [File_Valid], TRUE

@@99:
        ret

ENDP    Process_File_Valid



;**********************************************************************
PROC    Process_File_Exist
;**********************************************************************
; Assume default
        mov     [File_Exist], FALSE

; Determine actual length of file to be compared
        les     di, [AC_Xdir_FileName_Ptr]   ; Entered Name/Mask
        xor     ax, ax                      ; Reset ax
        mov     al, SPACE
        mov     bx, FILE_NAME_LENGTH + 1
        mov     cx, FILE_NAME_LENGTH + 1
        repne   scasb                       ; Search equal SPACE, uses es:di
        inc     cx                          ; Adjust after search
        sub     bx, cx                      ; Compare length determined

        mov     cx, [Files_In_File_Table]
        mov     si, offset File_Table
        push    ds si
        pop     di es

@@12:
        push    cx es di                    ; Save count and offset

; Load File_Table_Entry with file entry from box
        push    es di ds si

        push    es di
        pop     si ds

        les     di, [File_Table_Entry_Ptr]
        mov     cx, FILE_ENTRY_LENGTH
        rep     movsb

        pop     si ds di es

; Check if we process a file
        mov     al, [File_Table_Entry.File_Attribute]
        and     al, ATTRIB_FILE_DIRECTORY
        cmp     al, ATTRIB_FILE_DIRECTORY   ; Entry is a directory?
        je      @@13                        ; Yes
                                            ; No, so
        lds     si, [AC_Xdir_FileName_Ptr]   ; Entered Name/Mask
        mov     cx, bx                      ; Compare length loaded

; Perfect match?
        rep     cmpsb                       ; Perfect match?
        je      @@14                        ; Yes
                                            ; No
@@13:
        pop     di es cx                    ; Restore count and offset
        add     di, FILE_ENTRY_LENGTH       ; Next entry
        loop    @@12
        jmp     @@99                        ; No match

@@14:
        cmp     bx, FILE_NAME_LENGTH        ; Maximum Filename length used
        je      @@15                        ; Yes
                                            ; No, so
        cmp     [byte es:di], NULL          ; Next char File Table Entry is 0?
        jne     @@13                        ; No
                                            ; Yes, so
@@15:
        pop     di es cx

; File exists!
        mov     [File_Exist], TRUE

@@99:
        ret

ENDP    Process_File_Exist



;**********************************************************************
PROC    Select_Xdir_File
;**********************************************************************
        push    es di

        les     di, [AA_Attr_FileName_Ptr]
        mov     cx, FILE_NAME_LENGTH
        mov     al, ATTRIB_GREEN_YELLOW     ; Use "selected" attribute
        rep     stosb

        pop     di es

        ret

ENDP    Select_Xdir_File



;**********************************************************************
PROC    Deselect_Xdir_File
;**********************************************************************
        push    es di

        les     di, [AA_Attr_FileName_Ptr]
        mov     cx, FILE_NAME_LENGTH
        mov     al, ATTRIB_BLACK            ; Use "selected" attribute
        rep     stosb

        pop     di es

        ret

ENDP    Deselect_Xdir_File



;**********************************************************************
PROC    Select_Xdir_Drive
;**********************************************************************
        push    es di

        les     di, [AA_Attr_Drive_Map_Ptr]
        xor     cx, cx                      ; Reset cx
        mov     cl, [Xdir_Drive]             ; Get entry nr within Drive Map
        dec     cx                          ; Because of offset reasons
        add     di, cx                      ; Go to correct Drive

        mov     al, ATTRIB_GREEN_YELLOW     ; Use "selected" attribute
        mov     cx, 1                       ; How many attr to convert?
        rep     stosb

        pop     di es

        ret

ENDP    Select_Xdir_Drive



;**********************************************************************
PROC    Deselect_Xdir_Drive
;**********************************************************************
        push    es di

        les     di, [AA_Attr_Drive_Map_Ptr]
        xor     cx, cx                      ; Reset cx
        mov     cl, [Xdir_Drive]             ; Get entry nr within Drive Map
        dec     cx                          ; Because of offset reasons
        add     di, cx                      ; Go to correct Drive
        mov     al, ATTRIB_BLUE             ; Use "deselect" dim attribute
        cmp     [XDIR_Status], XDIR_STATUS_DRIVE  ; Drive Mode?
        je      @@10                        ; Yes
                                            ; No, so
        mov     al, ATTRIB_BLUE_YELLOW      ; Use "deselect" bright attribute

@@10:
        mov     cx, 1                       ; How many attr to convert?
        rep     stosb

        pop     di es

        ret

ENDP    Deselect_Xdir_Drive



;**********************************************************************
PROC    Select_Xdir_Window_File
;**********************************************************************
        push    ds si es di

        les     di, [AA_Attr_Entries_Ptr]
        xor     ax, ax                      ; Reset ax
        mov     al, Screen_Cols             ; Nr of cols of box
        xor     cx, cx                      ; Reset cx
        mov     cl, [Xdir_Window_File]      ; Get entry nr within box
        jmp     @@20

@@10:
        add     di, ax                      ; Move to next entry

@@20:
        dec     cx                          ; Determine correct entry
        jnz     @@10

@@30:
        mov     al, ATTRIB_GREEN_YELLOW     ; Use "selected" attribute
        mov     cx, Xdir_Table_Entry_Length  ; How many attr to convert?
        rep     stosb

; Clear our "FileName:" location first
        les     di, [AC_Xdir_FileName_Ptr]   ; "FileName:" location
        mov     al, SPACE                   ; Fill with spaces
        mov     cx, FILE_NAME_LENGTH        ; How many spaces?
        rep     stosb

; Get selected File Entry from File Table
        mov     si, offset File_Table
        xor     ax, ax                      ; Reset ax
        mov     cx, [Xdir_Window]            ; Offset
        dec     cx                          ; Because offset starts at 0
        mov     al, [Xdir_Window_File]       ; "Index"
        add     cx, ax                      ;         added
        dec     cx                          ; Because index  starts at 0
        mov     al, FILE_ENTRY_LENGTH
        mul     cx                          ; Correct entry calculated
        add     si, ax                      ; Correct entry reached

; Copy Entry
        push    ds si                       ; Copy entry to entry structure
        les     di, [File_Table_Entry_Ptr]
        mov     cx, FILE_ENTRY_LENGTH
        rep     movsb
        pop     si ds                       ; Copy complete

; Check Entry
        mov     al, [File_Table_Entry.File_Attribute]
        and     al, ATTRIB_FILE_DIRECTORY
        cmp     al, ATTRIB_FILE_DIRECTORY   ; Entry is a directory?
        je      @@99                        ; Yes
                                            ; No, so
; Copy selected file to our "FileName:" location in the box?
        les     di, [AC_Xdir_FileName_Ptr]   ; "FileName:" location
        mov     cx, FILE_NAME_LENGTH        ; Size of Filename
        rep     movsb                       ; Filename copied

; Restore pointers
@@99:
        pop     di es si ds

        ret

ENDP    Select_Xdir_Window_File



;**********************************************************************
PROC    Deselect_Xdir_Window_File
;**********************************************************************
        push    es di

        les     di, [AA_Attr_Entries_Ptr]

        xor     ax, ax                      ; Reset ax
        mov     al, Screen_Cols             ; Nr of cols of box
        xor     cx, cx                      ; Reset cx
        mov     cl, [Xdir_Window_File]      ; Get entry nr within box
        jmp     @@20

@@10:
        add     di, ax                      ; Move to next entry

@@20:
        dec     cx                          ; Determine correct entry
        jnz     @@10

@@30:
        mov     al, ATTRIB_BLUE_YELLOW      ; Use "deselected" attribute
        mov     cx, Xdir_Table_Entry_Length  ; How many attr to convert?
        rep     stosb

        pop     di es

        ret

ENDP    Deselect_Xdir_Window_File



;**********************************************************************
PROC    Save_Temp_Cursor
;**********************************************************************
        call    Get_Cursor_Position         ; Save current cursor position
        mov     dh, [Offset Cursor_Position.Row]
        mov     dl, [Offset Cursor_Position.Col]
        mov     [Offset Temp_Cursor_Position.Row], dh
        mov     [Offset Temp_Cursor_Position.Col], dl

        mov     [Cursor_Position.Row], OFF_SCREEN
        mov     [Cursor_Position.Col], OFF_SCREEN
        call    Set_Cursor_Position

        ret

ENDP    Save_Temp_Cursor



;**********************************************************************
PROC    Restore_Temp_Cursor
;**********************************************************************
        mov     dh, [Offset Temp_Cursor_Position.Row]
        mov     dl, [Offset Temp_Cursor_Position.Col]
        mov     [offset Cursor_Position.Row], dh
        mov     [offset Cursor_Position.Col], dl
        call    Set_Cursor_Position

        ret

ENDP    Restore_Temp_Cursor



;**********************************************************************
PROC    Restore_Video_RAM_Below_Xdir
;**********************************************************************
        mov     es, [Video_Mode_Base]       ; Videomap Base
        mov     di, [Video_Mode_Offset]     ; Videomap Offset
        add     di, Xdir_Mode_Offset        ; Where our box will come

        mov     si, offset Video_RAM_Below_Xdir  ; Our save area
        mov     bx, Screen_Rows             ; Nr of Rows

@@10:
        mov     cx, Screen_Cols
        rep     movsw
        add     di, ( MAX_COL - Screen_Cols ) * 2
        dec     bx
        jnz     @@10
        ret

ENDP    Restore_Video_RAM_Below_Xdir



;**********************************************************************
PROC    Restore_Saved_Cursor
;**********************************************************************
        mov     dh, [Offset Save_Cursor_Position.Row]
        mov     dl, [Offset Save_Cursor_Position.Col]
        mov     [offset Cursor_Position.Row], dh
        mov     [offset Cursor_Position.Col], dl
        call    Set_Cursor_Position

        ret

ENDP    Restore_Saved_Cursor



;**********************************************************************
PROC    Set_Return_Code
;**********************************************************************
        mov     al, NULL
        mov     [Return_Code], al

        ret

ENDP    Set_Return_Code



;**********************************************************************
PROC    Exit_Program
;**********************************************************************
        mov     ah, DOS_TERMINATE_EXE
        mov     al, [Return_Code]           ; Return code value
        int     DOS_SERVICE

ENDP    Exit_Program



ENDS    CSeg                                ; End of Code segment

END     Main                                ; End of Xdir
