home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / DIR / DC11.ZIP / DC.ASM next >
Encoding:
Assembly Source File  |  1991-10-14  |  152.9 KB  |  5,403 lines

  1. Page 80,132
  2. title DC.asm  Directory Control /copy/del/move/view program
  3.  
  4. ;compile options: 
  5. ;SMALL     equ    -1    ;routines optimized for size rather than speed
  6. ;SAG    equ    -1    ;Steve Grandi's mods for UNIX '-' switchchar
  7. ;BLANK_BIT    equ    4    ;view option - see below
  8.  
  9. COMMENT | 
  10. Revision history:
  11.  
  12. DC version 1.1 - August, 1991   (Gerhard Karnik - garyk@cbnewsk.att.com)
  13.         Original DOS screen is restored upon exit from program (up to 132x50)
  14.         ALT 1 now calls up vpic (by default)
  15.         ALT 2 now calls up vplay (by default)
  16.         Marked-file-bytes display now works if more than 10 meg bytes
  17.  
  18. DC version 1.07 - June, 1990    (Gerhard Karnik - garyk@cbnewsk.att.com)
  19.         Support for screen sizes other than 80x25
  20.  
  21. DC version 1.06f - September 2, 1989
  22.     Fix VIEW bug in number of lines displayed
  23.     New patch location for default sort
  24.     Reverse logic of snow check patch point
  25.     Fix get_mem bug when less than 64k to grab 
  26.    complements Russell Nelson:
  27.     Sensing the EGA and disengaging snow control if one is present,
  28.     Changing the menu if they hold down the Alt or Ctrl key.
  29.    Other additions:
  30.     RMDIR and MKDIR
  31.  
  32. DC version 1.05 - October 24, 1988
  33.         Fix minor bug in return from shell
  34.     Add Ins/Del as duplicates to Grey +/- keys
  35.     Put Menu changes
  36.     Fix Backspace bug
  37.     Fix Sort msg clear problem introduced in 1.04
  38.     Restore Ctrl-Break status in DOS Shell
  39.  
  40. DC version 1.04d  - May 29, 1988
  41.     Work on display speed/ cursor overrun problem
  42.     Rename a few subroutines (for clarity?)
  43.  
  44. DC version 1.04a  - May 12, 1988
  45.     Changed memory management for DOS shell
  46.     Add Steve Grandi's modifications
  47.     add Alt-F2 as "shell to DOS" command
  48.     (If SWITCH != '/', make all output strings use '/' as path delimiter)
  49.     (eliminate CR as view mode exit character)
  50.     
  51. DC version 1.03(f)  - May 9, 1988
  52.     Save and restore original text attribute
  53.     Simplify clutter of clear window subroutines
  54.     Add customizable option switchchar for UNIX hacks
  55.     Fix bug occurring in copy of 0 byte size files
  56.     Fix error that occurs when rename is applied to destination dir
  57.     Fix writing to prn once more
  58.     Add Refresh to original order sort
  59.     Minor fixes and revisions to save a few bytes
  60.     Add rename for directories
  61.     More work on error recovery - write protected target
  62.  
  63. DC version 1.02 - March 22, 1988
  64.     Add escape/return to error handler
  65.     Fix minor bug in view/ascii and wrap of 80 char + cr,lf
  66.     Added Alt-F1 "Protected Copy" function.
  67.     Tweaked file view function to save 4 bytes.
  68.     Now highlights last sub-dir viewed when returning to parent dir
  69.  
  70. DC version 1.01 - March 7, 1988
  71.     Modified method of handling directory changes
  72.     F9 (change work dir) now relative to displayed work dir
  73.     Allow specifying both source and dest paths on entry
  74.  
  75. Earlier versions COD1 through COD9: Dec '87 to Mar. '88
  76.         Combined DR and CO,
  77.     Re-worked file read/write sequence to minimize disk swaps
  78.     Expanded file copy buffer to available memory
  79.     Added ability to change directories
  80.     Expanded display of bytes free to include both source and target disks
  81.     Added "spedometer" display of bytes in marked files
  82.     Added "View" options to :
  83.         Toggle word wrap, 
  84.         Horizontal scroll
  85.         Blanking or full suppression of non-ASCII
  86.  
  87.  
  88. Features that could be added:
  89.  
  90.   List options:   search/scan for text
  91.               display current horizontal scroll position
  92.               improve provisions for re-synch in mode toggles
  93.   Fix bug when shelling to DOS when >80 columns
  94.  
  95.  
  96. |    ;end comments
  97.  
  98.  
  99. ;program equates:
  100. nul    equ    00h
  101. tab    equ    09h
  102. cr    equ    0dh
  103. lf    equ    0ah
  104. space    equ    20h
  105.  
  106. ;macro to calculate position in display memory; AX,BX,DX destroyed
  107. CROW    MACRO   COL,ROW,ADDR
  108.         mov     bx,SCREEN_COLS
  109.         shl     bx,1
  110.         mov     ax,ROW
  111.         mul     bx
  112.         mov     bx,COL
  113.         shl     bx,1
  114.         add     ax,bx
  115.         mov     ADDR,ax
  116.         ENDM
  117.  
  118. DOSINT        EQU    21h
  119. COPY_MARK    EQU    26
  120.  
  121. ALT_SHIFT    EQU    08H
  122. CTRL_SHIFT    EQU    04H
  123. HOT_SHIFT    EQU    ALT_SHIFT+CTRL_SHIFT
  124.  
  125. ROW1        EQU    2
  126.  
  127. WHERE_LOC    EQU    14    ;col to display current location in view
  128. WHERE_LEN    EQU    08    ;col's allocated
  129.  
  130. ;    locations of data within DTA after FIND_FIRST
  131. F_ATTR        EQU    21
  132. F_TIME        EQU    22
  133. F_DATE        EQU    24
  134. F_SIZE        EQU    26
  135. F_NAME        EQU    30
  136.  
  137. DIR_RECORD    STRUC
  138.     D_MRK    DB    ?
  139.     D_NAME    DB    8 DUP (?)
  140.         DB    ?
  141.     D_EXT    DB    3 DUP (?)
  142.         DB    ?
  143.     D_SIZE    DB    8 DUP (?)
  144.         DB    ?,?
  145.     D_DATE    DB    8 DUP (?)
  146.         DB    ?,?
  147.     D_TIME    DB    6 DUP (?)
  148.     D_HID    DB    ?
  149.     D_SYS    DB    ?
  150.     D_RO    DB    ?
  151.     D_ARC    DB    ?
  152. DIR_RECORD    ENDS
  153.  
  154. FIELD_SIZE    EQU    1 + D_ARC - D_MRK
  155. BAR_LEN        EQU    D_HID - D_NAME
  156. ;
  157. SUBTTL Segment data defines
  158. page
  159. ROM_BIOS_DATA    SEGMENT AT 40h        ; Low Memory "BIOS" Parameters
  160. ;
  161.     org    10h            ; Location of EQUIP_FLAG
  162. EQUIP_FLAG    dw    ?        ; Contains video settings
  163.                     ; in bits 4 and 5
  164.     org    17h            ; Location of KB_FLAG
  165. KB_FLAG     db    ?        ; Contains Alt (bit 3) &
  166.                     ; Right Shift (bit 0) States
  167.         org     49h                     ; Location of CRT_MODE
  168. CRT_MODE        db      ?
  169.         org     4ah                     ; Location of DOS_COLS
  170. DOS_COLS        db      ?
  171.         org     84h                     ; Location of DOS_ROWS
  172. DOS_ROWS        db      ?
  173. ;
  174.     org    63h
  175. ADDR_6845    dw    ?
  176. CRT_MODE_SET    db    ?
  177. ROM_BIOS_DATA    ends
  178. ;
  179. DUMMY_SEG    SEGMENT AT 1000H
  180.         ORG 00H
  181. PAGES        DW    7F0h DUP (?)    ;table of screen page sizes 
  182. FILE_BUFF    DB    ?
  183.  
  184.         ORG    0FFE8H
  185. END_BUFF    DW    0    ;dummy place holder
  186. READ_SIZE    EQU    ((END_BUFF - FILE_BUFF)/2) AND 0F800h
  187.  
  188. FILE_PTR    DW    ?
  189.         DW    ?
  190. RETRN_PTR    DW    ?
  191.         DW    ?
  192. FILE_END    DW    ?
  193. LAST_PAGE    DW    ?
  194. THIS_SCREEN    DW    ?
  195. LAST_COL        DW      ?
  196. ROW        DB    ?
  197. DUMMY_SEG    ENDS
  198. ;
  199. _TEXT    SEGMENT    WORD PUBLIC 'CODE'
  200.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  201. ;
  202.  
  203.     ORG    2
  204. PSP_TOP_MEM    LABEL    WORD        ;last paragraph of available mem
  205.     ORG    6
  206. PSP_TOP_SEG    LABEL    WORD
  207.     ORG    2Ch
  208. PSP_ENV_SEG     LABEL   WORD
  209.  
  210.     ORG    5CH
  211. PSP_FCB    DB    ?
  212.  
  213.     ORG    80H
  214. CMD_LINE    LABEL    BYTE
  215. DTA        LABEL    BYTE
  216.  
  217. SUBTTL Data area
  218. page
  219.     ORG    100H
  220. START:  JMP     MAIN
  221. ;
  222.  
  223. ;0=black    1=blue        2=green        3=cyan
  224. ;4=red        5=magenta    6=brown        7=light gray
  225. ;8=gray        9=light blue    A=light green    B=light cyan
  226. ;C=light red    D=light mag.    E=yellow    F=intense white
  227.  
  228. C_NORMAL        DB      7                       ;dir text attribute
  229. C_INTENSE    DB    0Bh            ;path name attribute
  230. C_MENU_ATT    DB    1BH            ;menu text attribute
  231. C_BORDER    DB    1FH            ;menu border attribute
  232. C_INVERSE    DB    70H + 4            ;high-lighted dir entry
  233.  
  234. SWITCH        DB    '/'
  235. STATUS_REG    DW    0ffh            ;non-zero enables snow check 
  236. DIRALLOC    DW    0800h            ;minimum memory for file dir
  237.  
  238. NORMAL        DB    07H
  239. INTENSE        DB    0FH
  240. MENU_ATT    DB    07H
  241. BORDER        DB    0FH
  242. INVERSE        DB    70H
  243. COLORS        EQU    $ - OFFSET NORMAL
  244. BAR_ATTRIBUTE    DB    70H
  245. ORIG_ATT    DB    ?            ;original screen attribute
  246.  
  247. DISPLAY_BIT    EQU    80H
  248. WRAP_BIT    EQU    1
  249. ASCII_BIT    EQU    2
  250.  
  251. BLANK_BIT    EQU    4    ;comment out this line to eliminate this option
  252. HEX_BIT         EQU     8
  253.  
  254. STAR_MASK    DB    0FFH
  255. VIEW_FLAGS    DB    WRAP_BIT
  256. OPTIONS         DB      ' WA'
  257. ifdef BLANK_BIT
  258.         DB    'B'
  259. endif
  260.                 DB      'H'
  261. OPTIONS_LEN     EQU     $ - OPTIONS
  262.  
  263. PATCH_43LINE    DB      0
  264.  
  265. N_SEGS        DB    ?
  266. SEG_COUNT    DB    ?
  267. MEM_BUF_SEG    DW    0F000H
  268.  
  269. VERIFY_STAT    DB    0
  270. BREAK_STAT    DB    0
  271. SORT_OPT    DB    "NESDO"
  272. SORT_OPT_CNT    EQU    $ - SORT_OPT
  273.         EVEN
  274. SORT_TABLE    DW    1200h        ;name
  275.         DW    309h        ;extension
  276.         DW    800h + 13    ;size
  277.         DW    29        ;date
  278.         DW    -1        ;no sort
  279. SORT_TABLE_END    EQU    $ - 2
  280. SORT_OFFSET    DW    0        ;start of field on which to sort
  281. SORT_LEN    DB    12
  282.  
  283. FUNCTION        DB      0               ;flag byte to identify function request
  284. COPY_BIT        EQU     1               ;read/write file
  285. DELETE_BIT      EQU     2               ;delete file (may follow a move)
  286. MOVE_BIT        EQU     4               ;across dir move via rename
  287. RENAME_BIT      EQU     8               ;simple rename
  288. PROTECT_BIT     EQU     10H             ;check if file already exists on dest
  289. DIR_OK_BIT      EQU     20H             ;allow function on directory
  290. UPD_CNT_BIT     EQU     80H             ;force update of bytes free display
  291.  
  292. CURSOR_TYPE    DW    ?
  293. VIDEO_SEG       DW      0B000H
  294.  
  295. CURRENT_MENU    DW    ?        ;normal or alt menu
  296. SEARCH_ATTRIB    DW    17H        ;what attrib files to display
  297. CUR_OFFSET    DW    ?        ;ptr to first entry on displayed page
  298. CUR_FILE    DW    ?        ;GET_NAME returned ptr to dir record
  299. END_OFFSET    DW    ?
  300. DIR_DISP_END    DW    ?
  301. LINE        DW    ?
  302. COUNT        DW    ?
  303. MARK_CNT    DW    ?
  304. SEARCH_COUNT    DW    ?
  305. FILE_CNT    DW    ?
  306. FILENAME_END    DW    ?
  307. READ_HANDLE    DW    ?
  308. WRITE_HANDLE    DW    ?
  309. SOURCE_ATTRIB    DW    ?
  310. TARGET_ATTRIB    DW    ?
  311. SIZE_LOW    DW    ?
  312. SIZE_HIGH    DW    ?
  313. SOURCE_TIME    DW    ?
  314. SOURCE_DATE    DW    ?
  315. FILE_NAME    DW    ?
  316. WORK_BYTES_FREE DW    ?
  317.         DW    ?
  318. WORK_CLUSTER    DW    ?
  319. DEST_BYTES_FREE DW    ?
  320.         DW    ?
  321. DEST_CLUSTER    DW    ?
  322. TARG_BYTES_FREE    DW    ?
  323.         DW    ?
  324. TARG_CLUSTER    DW    ?
  325. MARK_BYTES    DW    ?
  326.         DW    ?
  327. TEMP            DW      ?               ;for temporary storage
  328.  
  329. ;------DOS SHELL VARIABLES------
  330. STK_SEG         DW      ?               ;original SS contents for CALL_DOS
  331. STK_PTR        DW    ?        ;original SP contents for CALL_DOS
  332. ENV_SEG         DW      ?               ;segment containing environment block
  333. COM_VAR        DB    'COMSPEC=',0    ;environment variable to match
  334.                                         ;Parameter block for CALL_DOS
  335. DOS_PROG        DB      0,CR            ;DOS command to execute for DOS_SHELL
  336. DOS_PROG1       DB      'vpic /a', 0, 32 dup(20h)   ;DOS_SHELL1 cmd
  337. DOS_PROG2       DB      'vplay'  , 0, 34 dup(20h)   ;DOS_SHELL2 cmd
  338. DOS_LINE        DB      75,'/c ',70 dup(20h),CR ;DOS_SHELL1&2 command tail
  339. PAR_BLK         DW      0               ;Use parent's environment
  340.                 DW      ?               ;Point to command tail
  341. OFFDOSLINE      DW      ?               ;Segment of command tail (filled later)
  342.                 DW      4 DUP (0FFh)    ;FCB pointers (dummies!)
  343.  
  344. DISPATCH_KEY    label byte              ;table of scan codes
  345.     DB    01H,4AH,4EH,1CH        ;esc, -, +, cr
  346.     DB    3BH,3CH,3DH,3EH,3FH    ;F1, F2, F3, F4, F5
  347.     DB    40H,41H,42H,43H,44H    ;F6, F7, F8, F9, F10
  348.         DB      68H,69H,6AH,6BH         ;Alt-F1, Alt-F2, Alt-F3, Alt-F4
  349.         DB      71h                     ;Alt-F10
  350.     DB    52h,53h            ;Ins, Del
  351.         DB      78h,79h                 ;Alt-1, Alt-2
  352. SORT_KEYS       label byte              ;must match SORT_OPT table
  353.     DB    31H,12H,1FH,20H,18H    ;N, E, S, D, O
  354.         DB      2EH,2FH,32H,13H,10H     ;C, V, M, R, Q
  355.  
  356. VIEW_KEYS label byte
  357.     DB    47H,48H,49H,4FH        ;home, up, pgup, end
  358.     DB    50H,51H,76H,84H        ;down, pgdn, ^pgdn, ^pgup
  359.         DB      37H,1EH,30H,11H,23H     ;*, A, B, W, H
  360. DISPATCH_CNT    EQU $ - DISPATCH_KEY
  361.     DB    4BH,4DH            ;left, right
  362. VIEW_CNT    EQU $ - VIEW_KEYS
  363.  
  364.     even
  365. DISPATCH_TABLE    label word
  366.         DW      EXIT, UNMARK, MARK, VIEW
  367.         DW      COPY, DELETE, MOVE, RENAME, CLEAR_MARK
  368.     DW    MARK_BLANK, SWAP_MARK, SWAP_DIR, CD_WORK, CD_DEST
  369.         DW      PCOPY, DOS_SHELL, MKDIR, RMDIR
  370.         DW      TOGGLE_ROWS
  371.     DW    MARK, UNMARK
  372.         DW      DOS_SHELL1, DOS_SHELL2
  373.         DW      RE_SORT, RE_SORT, RE_SORT, RE_SORT, RE_SORT
  374.         DW      COPY, VIEW, MOVE, REFRESH, QUIT
  375.         DW      HOME_BAR, UP_ARROW, PG_UP, END_BAR
  376.     DW    DN_ARROW, PG_DN, BOTTOM_BAR, TOP_BAR
  377.         DW      STAR, ASCII, BLANK, WRAP, HEXDUMP
  378. DISPATCH_END    EQU $ - 2
  379.  
  380. ;data added for view function
  381. VIEW_TABLE label word
  382.     DW    HOME_FILE, UP_LINE, UP_PG, END_FILE
  383.     DW    DN_LINE, DN_PG, END_FILE, HOME_FILE
  384.         DW      STAR, V_ASCII, BLANK, VWRAP, VHEX
  385.     DW    LEFT, RIGHT
  386. VIEW_TABLE_END    EQU $ - 2
  387.  
  388. ;error messages
  389. NOT_ENOUGH    DB  "Requires 64K free RAM$"
  390. TOO_MANY    DB  "Too many files$"
  391. NO_COMSPEC    DB  "No COMSPEC variable in environment$"
  392.  
  393. ;main menu
  394. ;Graphics border characters:
  395. GB_TL        EQU    201    ;Top left
  396. GB_TH        EQU    205    ;Top horizontal
  397. GB_TR        EQU    187    ;Top right
  398. GB_L_TEE    EQU    199    ;Left Tee
  399. GB_R_TEE    EQU    182    ;Right Tee
  400. GB_MH        EQU    196    ;Middle line horizontal
  401. GB_BL        EQU    200    ;Bottom left
  402. GB_BR        EQU    188    ;Bottom right
  403. GB_BH        EQU    205    ;Bottom Horizontal;
  404. GB_V        EQU    186    ;Vertical border
  405.  
  406. LOGO    DB  "  Directory Control "
  407. MENU_WIDTH    EQU    $ - OFFSET LOGO
  408.         DB  "    Version 1.1     "
  409. LOGO_ROWS    EQU    ($ - OFFSET LOGO)/MENU_WIDTH
  410.  
  411. MENU1  LABEL  BYTE
  412.     DB  " F1   Copy          "
  413.     DB  " F2   Delete        "
  414.     DB  " F3   Move          "
  415.     DB  " F4   Rename        "
  416.     DB  " F5   Clear marks   "
  417.     DB  " F6   Mark remainder"
  418.     DB  " F7   Swap Mrk/Unmrk"
  419.     DB  " F8   Swap Dir/Dest."
  420.     DB  " F9   Change Dir    "
  421.     DB  " F10  Change Dest.  "
  422.         DB  " (ALT for more cmds)"
  423.         DB  " ─┘  View / ChDir  "
  424.     DB  " +/-  Mark/Unmark   "
  425.     DB  "Esc or Alt-Q to Exit"
  426. MENU1_ROWS    EQU    ($ - OFFSET MENU1)/MENU_WIDTH
  427. MENU_ROWS    EQU    3 + LOGO_ROWS + MENU1_ROWS
  428.  
  429. BEG_DOS        EQU         (2+MENU_ROWS) * 100h
  430. BEG_WINDOW    EQU    44 + (2+MENU_ROWS) * 100h
  431.  
  432. ;Menu to display with alt key pressed
  433. CTRL_MENU  LABEL  BYTE
  434. ALT_MENU  LABEL  BYTE
  435.         DB  " F1  Prot.- Copy    "
  436.     DB  " F2  DOS Shell      "
  437.         DB  " F3  MkDir (Destin) "
  438.     DB  " F4  RmDir (Source) "
  439.         DB  " F10 Toggle 43 Rows "
  440.     DB  "                    "
  441.         DB  " 1   Execute CMD 1  "
  442.         DB  " 2   Execute CMD 2  "
  443.         DB  "                    "
  444.         DB  " Sort Options:      "
  445.      DB  "    N,E,D,S or O    "
  446.      DB  "                    "
  447.         DB  "                    "
  448.         DB  " View Options: *WABH"
  449.  
  450. comment |  ignore this for now
  451. ;This is a proposed alternate menu
  452. CTRL_MENU  LABEL  BYTE
  453.     DB  " F1  Prot.- Copy    "
  454.     DB  " F2  DOS Shell      "
  455.     DB  " F4 Remove Directory"
  456.     DB  " F9  MkDir (Source) "
  457.     DB  " F10 MkDir (Dest.)  "
  458.     DB  "                    "
  459.      DB  " Sort Options:      "
  460.      DB  "    N,E,D,S or O    "
  461.      DB  "                    "
  462.     DB  "                    "
  463.     DB  "Esc or Alt-Q to Exit"
  464. |
  465. ;string constants and screen locations
  466.  
  467. ENTRY_CUR    EQU    47 + (4 + MENU_ROWS) * 100h
  468.  
  469. INVALID        DB  "Error: Invalid drive or directory",0
  470. LOAD_SORT_MSG    DB  "Loading and "
  471. SORT_MSG    DB  "Sorting directory.",0
  472. LOAD_MSG    DB  "Loading directory.",0
  473.  
  474. DIRECTORY    DB  "Directory of ",0
  475.  
  476. FILES           DB  3 DUP(space)
  477.         DB  " File(s) with "
  478. W_FREE        DB  8 DUP (space)
  479.         DB  " bytes free",0
  480.  
  481. DEST_MSG    DB  "Default destination ",0
  482.  
  483. DEST_FREE       DB  "Destination disk has "
  484. D_FREE        DB  8 DUP(space)
  485.         DB  " bytes free",0
  486.  
  487. BYTES_MRKD_MSG  DB  8 DUP(space)
  488.                 DB  " Bytes in"
  489. FILES_MRKD_MSG  DB  4 DUP(space)
  490.         DB  " "
  491. MARKED_MSG    DB  "Marked files",0
  492.  
  493.  
  494. DELETE_MSG    DB  " will be deleted.",0
  495.         DB  "Do you wish to delete?  Y/N",0
  496. DISK_MSG    DB  "Error reading drive "
  497. ERROR_DISK    DB  " ",0
  498.         DB  "(R)etry, (Q)uit or Escape?",0
  499. PCOPY_MSG    DB  "P-"
  500. COPY_MSG    DB  "Copy ",0
  501. MOVE_MSG    DB  "Move ",0
  502. RENAME_MSG    DB  "Rename ",0
  503. CD_MSG        DB  "Change directory",0
  504. CHDEST_MSG    DB  "Change default destination",0
  505. TO_MSG        DB  " to...",0
  506. MKDIR_MSG    DB  "Create directory",0
  507. STAR_DOT_STAR    DB  "*.*",0
  508. DIRECTORIES    DB  "<DIR>"
  509.  
  510. ;Screen size dependant variables
  511.  
  512. ROW_LEN         DW  ?
  513. BAR_START       DW  ?
  514. SCREEN_ROWS     DW  0
  515. SCREEN_COLS     DW  0
  516. DIR_ROWS        DW  0
  517. DIR_ROW_END     DW  ?
  518. VIEW_ROWS       DB  ?
  519. LAST_ROW        DW  0
  520.  
  521. MENU_STRT       DW  ?
  522.  
  523. PROMPT_LOC      DW  ?
  524. PROMPT_LOC2     DW  ?
  525.  
  526. LOAD_SORT_LOC   DW  ?
  527. SORT_LOC        DW  ?
  528. LOAD_LOC        DW  ?
  529. DIRECT_LOC      DW  ?
  530. FILES_LOC       DW  ?
  531. DEST_LOC        DW  ?
  532. D_FREE_LOC      DW  ?
  533.  
  534. MARKED_LOC      DW  ?
  535. MARKED_WIN      DW  ?
  536.  
  537. END_WINDOW      DW  ?                   ;79 + 24 * 100h for C80 screen
  538.  
  539. ENTRY_ROWS      DB  ?                   ;This set of variables are used to
  540. VID_ADAPT       DB  'C'                 ;restore DOS screen upon exit
  541. ENTRY_VID_MODE  DB  ?
  542.  
  543. ;DOS video information at the time this program is first run
  544.  
  545. DOS_SCREEN_LINES  DB ?
  546. DOS_SCREEN_COLS   DB ?
  547. DOS_VIDMODE       DB ?
  548. DOS_CURSOR_ROW    DB ?
  549. DOS_CURSOR_COL    DB ?
  550. DOS_SCREEN_BUF    DW 132*51 DUP (00h)
  551.  
  552. SUBTTL Main program loop
  553. page
  554. ;    CODE AREA
  555. ;----------------------------------------------------------------------------;
  556. ; Some housekeeping first. Since we will be changing the default drive       ;
  557. ; and directory to the requested drive and directory, we need to save the    ;
  558. ; current defaults, so they can be restored.  Install critical error trap.   ;
  559. ;----------------------------------------------------------------------------;
  560.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  561. MAIN    PROC    NEAR
  562.  
  563.     MOV    AX,3300H        ;Get Control Break status.
  564.     INT    DOSINT
  565.     MOV    BREAK_STAT,DL        ;and save it
  566.  
  567.     MOV    AX,3301H        ;Turn Control Break off.
  568.     MOV    DL,0
  569.     INT    DOSINT
  570.  
  571.     MOV    AH,54H            ;Get current verify flag.
  572.     INT    DOSINT            ; and save.
  573.     MOV    VERIFY_STAT,AL        ;(use /V switch to set verify on)
  574.  
  575.     MOV    DX,OFFSET DISK_ERROR    ;Install critical error trap.
  576.     MOV    AX,2524H
  577.     INT    DOSINT
  578.  
  579.     CLD                ;String moves forward.
  580.     CALL    UPD_DEST        ;save dir info about dest
  581.     MOV    SI,OFFSET DEST_PATH    ;Point to storage.
  582.     MOV    DI,OFFSET INITIAL_PATH    ; make copy of starting point
  583.     MOV    CX,68            ;length of path
  584.     REP    MOVSB
  585.  
  586.         call    SET_SCREEN_VARS         ;Set screen size dependant variables
  587.  
  588. ;---------------------------------------------------------------------;
  589. ; More housekeeping. We will be writing directly to the screen buffer ;
  590. ; so we need the display card address and the status register.      ;
  591. ;---------------------------------------------------------------------;
  592.  
  593.     MOV    AX,ROM_BIOS_DATA    ;Point to the ROM BIOS data area
  594.     MOV    DS,AX            ; and get base address of active
  595.     ASSUME    DS:ROM_BIOS_DATA    
  596.         MOV     AX,ADDR_6845            ; display card.
  597.         mov     bl,CRT_MODE             ;Current video mode
  598.         mov     cl,DOS_ROWS             ;Physical display rows - 1
  599.         PUSH    CS                      ;Done there, so restore data segment.
  600.     POP    DS
  601.         mov     ENTRY_VID_MODE,bl       ;store video mode (usually 3 for text)
  602.         mov     ENTRY_ROWS,cl           ;rows will be restored on exit
  603.         ASSUME  DS:_TEXT
  604.     CMP    AX,3B4H            ;Base address of MONO card is 3B4h.
  605.     JZ    _M1            ;If that's what we got, it's MONO
  606.         ADD     AX,6                    ;Add six to get status register
  607.  
  608. _M0:    PUSH    AX
  609.     MOV    VIDEO_SEG,0B800H    ; else COLOR so add 800h.
  610.     MOV    SI,OFFSET C_NORMAL
  611.     MOV    DI,OFFSET NORMAL
  612.     MOV    CX,COLORS
  613.     REP    MOVSB
  614.     MOV    AL,INVERSE
  615.     STOSB
  616.         MOV     AX,1200h                ;test for EGA/VGA
  617.     MOV    BX,10h
  618.     MOV    CX,-1
  619.     INT    10H
  620.     POP    AX            ;get back status reg address
  621.         CMP     CX,-1                   ;If it changes, we have EGA/VGA.
  622.         je      _M05
  623.         mov     VID_ADAPT,'E'
  624.         jmp     _M1                     ;disable snow check
  625. _M05:   CMP     BYTE PTR STATUS_REG,0H  ;patch point
  626.     JNZ    _M2            ;if not 0, enable snow check
  627.  
  628. _M1:    XOR    AX,AX            ;STATUS_REG=zero disables snow check
  629. _M2:    MOV    STATUS_REG,AX        ;Store status register.
  630.  
  631.     XOR    BH,BH            ;Get current attribute
  632.     MOV    AH,8            ; of display page zero.
  633.     INT    10H
  634.     MOV    ORIG_ATT,AH        ;Store it.
  635.     MOV    AH,3            ;Retrieve cursor type.
  636.     INT    10H
  637.     MOV    CURSOR_TYPE,CX
  638.  
  639.     MOV    AX,PSP_TOP_MEM        ;get top of available mem
  640.     MOV    BX,CS            ;get our segment
  641.     SUB    AX,BX            ;memory available
  642.     CMP    AX,DIRALLOC        ;we need min mem for dir functions
  643.     JNC    _M5            ;got this much
  644.  
  645. _M3:    MOV    DX,OFFSET NOT_ENOUGH
  646. _M4:    JMP    ERROR_EXIT        ;If not available, exit.
  647.  
  648. _M5:    AND    AX,0FFFH        ;how much left after rounding by 64K?
  649.     DEC    AX            ; minus some malloc overhead
  650.     DEC    AX
  651.     CMP    AX,DIRALLOC        ;if less than min allowed,
  652.     JAE    _M6
  653.     MOV    AX,1000H        ;use a whole 64K
  654.  
  655. _M6:    MOV    BX,AX            ;save number of paragraphs
  656.     MOV    CL,4            ;x16 to find top byte
  657.     SHL    AX,CL            ;of this seg and then
  658.     MOV    SP,AX            ;set up a local stack
  659.     XOR    AX,AX
  660.     PUSH    AX            ;push return address
  661.     PUSH    CS
  662.  
  663.     MOV    AH,4AH            ;modify mem block pointed to by es
  664.     INT    DOSINT            ;requesting bx paragraphs
  665.     JC    _M3
  666.  
  667.     MOV    OFFDOSLINE,CS        ;put segment in parm block address
  668.         CALL    GET_COMSPEC             ;get file spec for COMMAND.COM
  669.     MOV    DX,OFFSET NO_COMSPEC    ;take error exit
  670.         JC      _M4
  671.  
  672.         cmp     byte ptr PATCH_43LINE,0
  673.         je      _M65
  674.         call    TOGGLE_OK               ;Can we change to 43/50 lines?
  675.         jc      _M65                    ; no
  676.         xor     bl,bl
  677.         call    SET_LINES               ;set 43/50 lines
  678.         call    SET_SCREEN_VARS         ;set screen size dependant variables
  679.  
  680. _M65:   call    SAVE_DOS_SCREEN
  681.  
  682. ;----------------------------------------;
  683. ; Parse the command line for parameters. ;
  684. ;----------------------------------------;
  685.         MOV     DI,OFFSET CMD_LINE      ;Point to command line
  686.     XOR    CX,CX
  687.     MOV    CL,[DI]
  688.     INC    CX
  689.     INC    DI
  690.     PUSH    DI
  691.     PUSH    CX
  692.  
  693. _M7:    MOV    AL,SWITCH
  694.     REPNZ    SCASB
  695.     JNZ    _M12
  696.     MOV    AL,[DI]
  697.     MOV    WORD PTR [DI-1],2020h
  698.     PUSH    DI
  699.     PUSH    CX
  700.  
  701.         cmp     al,'4'
  702.         jnz     _M8
  703.         mov     al,[di+1]
  704.         cmp     al,'3'
  705.         jnz     _M8
  706.         mov     byte ptr [DI+1],20h
  707.         call    TOGGLE_OK               ;Can we change to 43/50 lines?
  708.         jc      _M8                     ; no
  709.         xor     bl,bl
  710.         call    SET_LINES               ;set 43/50 lines
  711.         call    SET_SCREEN_VARS         ;set screen size dependant variables
  712.  
  713. _M8:    AND     AL,5FH                  ;upper case
  714.  
  715. ;       CMP     AL,"H"                  ;If "H", remove hidden files.
  716. ;       JNZ     _M85
  717. ;    MOV    SEARCH_ATTRIB,1 + 4 + 10
  718.  
  719. _M85:   CMP     AL,"V"
  720.     JNZ    _M9
  721.     MOV    AX,2E01H        ;set verify on
  722.     INT    DOSINT
  723.  
  724. _M9:    CMP    AL,"F"            ;fast option - no snow check
  725.     JNZ    _M10
  726.     MOV    STATUS_REG,0        ;zero flags video status register.
  727.  
  728. _M10:    MOV    DI,OFFSET SORT_OPT
  729.     CALL    SET_SORT        ;scan for sort options
  730. _M11:    POP    CX
  731.     POP    DI
  732.     LOOP    _M7
  733.  
  734. _M12:    POP    CX
  735.     POP    DI
  736.     CALL    GET_PARAM
  737.     JZ    _M15            ;was there a parameter?
  738.     MOV    BX,SI            ;save start of source
  739.     CALL    GET_PARAM
  740.     JZ    _M14            ;was there a 2nd parameter?
  741.     MOV    DI,OFFSET DEST_PATH    ;save it at dest_path
  742.     CMP    BYTE PTR [SI+1],':'    ;check for drive spec
  743.     JZ    _M13            ;one found
  744.     INC    DI            ;no drive, use default
  745.     INC    DI            ;by stepping over in dest
  746. _M13:    LODSB                ;get a byte
  747.     STOSB                ;put a byte
  748.     OR    AL,AL            ;check for end and loop
  749.     JNZ    _M13
  750.  
  751. _M14:    MOV    SI,BX
  752.     CALL    CHANGE_PATH        ;Change drive and directory.
  753. _M15:    CALL    READ_DIR        ;get dir info from disk
  754.  
  755. ;-----------------------------------------;
  756. ; We are ready for business now. We will  ;
  757. ; loop here, waiting for user keystrokes. ;
  758. ; Performs CALL [DI] to execute function
  759. ; On entry : no known parameters
  760. ; Returns  : nothing
  761. ; Modifies : everything
  762. ;-----------------------------------------;
  763. GET_KEY    PROC    NEAR
  764.         CALL    REFRESH_DIR_DISP
  765.     CMP    FUNCTION,0
  766.     JE    _G_K1
  767.     MOV    AX,DEST_CLUSTER
  768.     MOV    TARG_CLUSTER,AX
  769.     CALL    DISP_COUNT_MSG        ;display files and space available
  770.     MOV    FUNCTION,0        ;Restore function flags.
  771.     MOV    CURRENT_MENU,0        ;force menu display
  772.  
  773. _G_K1:    MOV    AH,2            ;Get shift state.
  774.     INT    16H
  775.     MOV    SI,OFFSET ALT_MENU    ;display alt menu.
  776.     TEST    AL,ALT_SHIFT        ;Is the alt key depressed?
  777.     JNZ    _G_K2            ;If no, check function request.
  778.     MOV    SI,OFFSET CTRL_MENU    ;display ctrl menu.
  779.     TEST    AL,CTRL_SHIFT        ;Is the ctrl key depressed?
  780.     JNZ    _G_K2            ;If no, check function request.
  781.     MOV    SI,OFFSET MENU1        ;display this menu.
  782. _G_K2:
  783.     MOV    BL,MENU1_ROWS
  784.     CMP    CURRENT_MENU,SI        ;Are we already displaying it?
  785.     JE    _G_K3
  786.     MOV    CURRENT_MENU,SI        ;no - display it.
  787.     MOV    DI,MENU_STRT        ;And to screen position.
  788.  
  789.         mov     ax,ROW_LEN              ;ADD DI,(LOGO_ROWS + 2)*ROW_LEN
  790.         mov     dl,byte ptr LOGO_ROWS
  791.         inc     dl
  792.         inc     dl
  793.         mul     dx
  794.         add     di,ax
  795.  
  796.     CALL    PUT_MENU_LINES
  797.  
  798. _G_K3:    CALL    CK_KEY            ;Did we get a key yet?
  799.     JZ    _G_K1            ;no, check again
  800.  
  801. _G_K4:  CALL    READ_KEY                ;Get a keystroke.
  802.     MOV    BX,AX            ;Save returned key.
  803.     CMP    AH,1            ;Is it Esc or below?
  804.     JBE    _G_K5            ;If yes, function.
  805.     CMP    AH,36H            ;Is it right shift or above?
  806.     JAE    _G_K5            ;If yes, function.
  807.     CMP    AH,1CH            ;Is it CR?
  808.     JZ    _G_K5            ;If yes, function.
  809.  
  810.         cmp     ah,2bh
  811.         je      _G_K5
  812.  
  813.     MOV    AH,2            ;Get shift state.
  814.     INT    16H
  815.     TEST    AL,HOT_SHIFT        ;Is a hot key depressed?
  816.     JNZ    _G_K5            ;If no, check function request.
  817.     CALL    SEARCH            ;Else, search for first letter.
  818.     JMP    GET_KEY
  819. _G_K5:
  820.     MOV    DI,OFFSET DISPATCH_KEY
  821.         MOV     CX,DISPATCH_CNT         ;Valid commands.
  822.     MOV    AL,BH
  823.     MOV    BX,OFFSET DISPATCH_END
  824.         CALL    LOOKUP
  825.     JNZ    _G_K1            ;If no match, get another.
  826.     CALL    [BX]            ;Else do subroutine.
  827.     JMP    GET_KEY            ;Update screen; get next command.
  828.  
  829. ;-----------------------------------------------------------------------;
  830. ; This is the exit routine. Restore the defaults the way we found them. ;
  831. ;-----------------------------------------------------------------------;
  832.  
  833. ERROR_EXIT:
  834.     MOV    AH,9            ;print string$
  835.     INT    DOSINT
  836.     MOV    AL,1            ;Error code of one.
  837.     JMP    SHORT TERMINATE
  838.  
  839. EXIT:   MOV     AL,ORIG_ATT
  840.         CALL    CLR_SCR                 ;Clear screen.
  841.         XOR     DX,DX
  842.         CALL    SET_CURSOR
  843.     XOR    AL,AL            ;Error code of zero.
  844. TERMINATE:
  845.     MOV    SI,OFFSET INITIAL_PATH    ;Restore drive.
  846.  
  847. _T1:    PUSH    AX            ;save error code
  848.         call    RESTORE_SCREEN          ;Restore original screen row if needed.
  849.  
  850.         call    RESTORE_DOS_SCREEN
  851.         CALL    CHANGE_PATH
  852.     MOV    AL,VERIFY_STAT        ;Restore verify state.
  853.     MOV    AH,2EH            ;set verify dos call
  854.     INT    DOSINT
  855.     MOV    AX,3301H        ;Restore Control Break.
  856.     MOV    DL,BREAK_STAT
  857.     INT    DOSINT
  858.  
  859.     POP    AX            ;get back error code
  860.     MOV    AH,4CH
  861.     INT    DOSINT            ;and go home
  862.  
  863. QUIT:   MOV     AL,ORIG_ATT
  864.         CALL    CLR_SCR                 ;Clear screen.
  865.         XOR     DX,DX
  866.         CALL    SET_CURSOR
  867.         XOR     AL,AL                   ;Error code of zero.
  868.         MOV     SI,OFFSET WORK_PATH     ; and default directory.
  869.     JMP    SHORT    _T1
  870.  
  871. GET_KEY    ENDP
  872. MAIN    ENDP
  873.  
  874.  
  875. ;-----------------------------------------------;
  876. ; This subroutine parses the user command line entry
  877. ; On entry : DI points to start of string, CX holds count
  878. ; Returns  : SI=0 if nothing found, else SI points to start
  879. ; Modifies : adds null to end of space delimited string
  880. ;----------------------------------------;
  881. GET_PARAM    PROC    NEAR
  882.     XOR    SI,SI
  883.     MOV    AL,space
  884.     JCXZ    _G_P5
  885. _G_P1:    SCASB                ;scan off leading blanks
  886.     JB    _G_P2            ;skip control, too
  887.     LOOP    _G_P1
  888.     JMP    SHORT _G_P5
  889.  
  890. _G_P2:    DEC    DI
  891.     MOV    SI,DI            ;save source
  892.     
  893. _G_P3:    SCASB                ;search for delimiter
  894.     JAE    _G_P4
  895.     LOOP    _G_P3
  896.  
  897. _G_P4:    DEC    DI
  898.     MOV    BYTE PTR [DI],0
  899. _G_P5:    OR    SI,SI
  900.     RET
  901. GET_PARAM    ENDP
  902.  
  903. ;-----------------------------------------------------------;
  904. ; This subroutine gets the file spec for COMMAND.COM from the
  905. ;  environment's COMSPEC variable
  906. ; On entry :    Nothing
  907. ; Returns  :    Carry set if COMSPEC not found
  908. ;        PGM_NAME contains file spec
  909. ; Modifies :    SI,DI
  910. ;-----------------------------------------------------------;
  911. GET_COMSPEC    PROC    NEAR
  912.     MOV    AX,PSP_ENV_SEG            ;get environment segment from PSP
  913.     MOV    ENV_SEG,AX
  914.     MOV    ES,AX
  915.     ASSUME CS:_TEXT,DS:_TEXT,ES:nothing
  916.  
  917.  
  918. ;-----------------------------------------------------------;
  919. ; This section searches the environment block for a string
  920. ; On entry :    ES points to environment block
  921. ;        DS:DI points to "NAME=" to match
  922. ; Returns  :    carry set if string not found
  923. ;        ES:DI points to parameter if found
  924. ; Modifies :    SI,DI,BX
  925. ;-----------------------------------------------------------;
  926.     XOR    DI,DI            ;initialize offset to environment block
  927.  
  928. _G_C1:    MOV    BX,OFFSET COM_VAR    ;initialize pointer to pattern
  929.     CMP    BYTE PTR ES:[DI],0    ;End of environment block?
  930.     JNE    _G_C2            ;no
  931.  
  932.     STC                ;indicate error
  933.     JMP    SHORT _G_C6
  934.  
  935. _G_C2:    MOV    AL,[BX]            ;get character from pattern
  936.     OR    AL,AL            ;end of pattern? (turns off carry)
  937.     JZ    _G_C4            ;yes means match successful
  938.  
  939.     CMP    AL,ES:[DI]        ;compare to char in environment block
  940.     JNE    _G_C3            ;jump if match failed
  941.     INC    BX
  942.     INC    DI
  943.     JMP    _G_C2            ;loop
  944.  
  945. _G_C3:    XOR    AL,AL            ;scan forward for zero byte in env block
  946.     MOV    CX,-1
  947.     CLD
  948.     REPNZ    SCASB
  949.     JMP    _G_C1            ;go compare next string
  950.  
  951. _G_C4:                    ;success, return ES:DI = string
  952.     MOV    SI,OFFSET PGM_NAME    ;set DS:SI to point to location for copy
  953. _G_C5:    MOV    AL,ES:[DI]        ;transfer null-terminated string
  954.     MOV    [SI],AL
  955.     INC    SI
  956.     INC    DI
  957.     OR    AL,AL            ;found a null?
  958.     JNZ    _G_C5
  959.  
  960. _G_C6:    PUSH    CS
  961.     POP    ES
  962.     RET
  963. GET_COMSPEC    ENDP
  964.  
  965. SUBTTL READ_DIR : (re)Display directory
  966. page
  967. ;----------------------------------------------------------------------
  968. ;  This procedure reads in the directory information, sorts it, and then
  969. ;enters the main command input program loop.
  970. ;On Entry: (1)    The current default drive and directory will be displayed
  971. ;        and then saved as WORK_PATH
  972. ;          (2)    The default drive and directory will then be reset back to
  973. ;        the destination drive and directory that must already be 
  974. ;        saved in DEST_PATH.
  975. ;          (3)  The ASCIIZ strings WORK_PATH and DEST_PATH, are
  976. ;        formatted and saved for display purposes.
  977. ;       (4) SOURCE and TARGET strings are also created/saved
  978. ;   During the main program loop the default dir is DEST_PATH
  979. ;----------------------------------------------------------------------
  980. READ_DIR    PROC    NEAR
  981.     MOV    AL,NORMAL
  982.     CALL    CLR_SCR
  983.     MOV    SI,OFFSET LOAD_SORT_MSG    ;Display sorting message.
  984.     MOV    DI,LOAD_SORT_LOC
  985.     CMP    SORT_LEN,-1        ;Unless not sorted.
  986.     JNZ    _R_D1
  987.     MOV    SI,OFFSET LOAD_MSG    ;Then display loading message.
  988.     MOV    DI,LOAD_LOC
  989.  
  990. _R_D1:    CALL    PUT_STRING
  991.     MOV    DI,OFFSET DIR_BUFF    ;Put space character
  992.     MOV    CX,SP            ; in directory listing
  993.     SUB    CX,100H            ;  leave stack space
  994.     SUB    CX,DI            ; initialize this much space
  995.     MOV    AL,space        ; with space char in buffer.
  996.     REP    STOSB
  997.  
  998.     XOR    AX,AX            ;initialize variables
  999.     MOV    COUNT,AX        ;clear file counter
  1000.     MOV    FILE_CNT,AX        ;
  1001.         push    ax
  1002.         MOV     ax,BAR_START
  1003.         MOV     LINE,ax
  1004.         pop     ax
  1005.     MOV    CUR_OFFSET,OFFSET DIR_BUFF
  1006.  
  1007. ;------------------------------------------------------------------;
  1008. ; Read all the directory filenames and store as records in buffer. ;
  1009. ;------------------------------------------------------------------;
  1010.     MOV    DX,OFFSET STAR_DOT_STAR
  1011.     MOV    CX,SEARCH_ATTRIB
  1012.     CALL    FIND_FIRST        ;Find first matching file.
  1013.     MOV    DI,OFFSET DIR_BUFF + 1    ;Point to buffer.
  1014.     JC    _R_D3            ;If empty directory, go on
  1015.  
  1016.     MOV    BP,SP            ;Reserve space for stack.
  1017.     SUB    BP,200H
  1018.     CALL    STORE_ENTRY        ;Convert to directory format.
  1019.  
  1020. _R_D2:    MOV    AH,4FH            ;Find next matching.
  1021.     INT    DOSINT
  1022.     JC    _R_D3            ;If carry, no more names.
  1023.     CALL    STORE_ENTRY
  1024.     CMP    DI,BP            ;Are we encroaching the stack?
  1025.     JBE    _R_D2            ;If no, find next.
  1026.     MOV    DX,OFFSET TOO_MANY    ;Else, exit with message.
  1027.     JMP    ERROR_EXIT
  1028. ;-----------------------------------;
  1029. ; Store buffer end address and page ;
  1030. ; end then sort the filenames.      ;
  1031. ;-----------------------------------;
  1032.  
  1033. _R_D3:    DEC    DI
  1034.     MOV    END_OFFSET,DI        ;Store ending offset.
  1035.     MOV    BX,COUNT        ;Retrieve file count.
  1036.     MOV    AX,DIR_ROW_END
  1037.         cmp     bx,DIR_ROWS             ;Enough to fill one page?
  1038.     JAE    _R_D4            ;If yes, use default setting.
  1039.     MOV    AX,ROW_LEN        ;Calculate last record.
  1040.         mul     bx
  1041.     ADD    AX,BAR_START        ;Add bar offset.
  1042.  
  1043. _R_D4:    MOV    DIR_DISP_END,AX
  1044.     CMP    SORT_LEN,-1        ;Should we sort or leave original?
  1045.     JZ    _R_D5            ;If it was "/O", don't sort.
  1046.     CALL    SORT
  1047.  
  1048. ;---------------------------------------------------------------;
  1049. ; Ready to get "working" directory and display it and the menu. ;
  1050. ;---------------------------------------------------------------;
  1051.  
  1052. _R_D5:    MOV    DI,OFFSET WORK_PATH    ;Point to storage.
  1053.     PUSH    DI            ;and start of string
  1054.     CALL    GET_PATH        ;Get and save directory, space free.
  1055.     POP    SI            ;get back working disk
  1056.     MOV    DI,OFFSET SOURCE    ;Make a carbon copy of directory.
  1057. _R_D6:    MOVSB
  1058.     CMP    BYTE PTR [SI],0
  1059.     JNZ    _R_D6
  1060.  
  1061.     MOV    AL,"\"            ;Add "\" to end of path
  1062.  
  1063. IFDEF SAG
  1064.     CMP    SWITCH,"/"        ; Do we really want "/"?
  1065.     JE    _R_D6A:            ; No
  1066.     MOV    AL,"/"            ; Yes
  1067. _R_D6A:
  1068. ENDIF
  1069.  
  1070.     CMP    [DI-1],AL        ; if not root directory.
  1071.     JZ    _R_D7
  1072.     STOSB
  1073.  
  1074. _R_D7:    MOV    FILE_NAME,DI        ;Store end of path to tack
  1075.                     ; on filename later on.
  1076. ;
  1077. ;restore current d:\path for default moves and copies
  1078. _R_D8:    MOV    SI,OFFSET DEST_PATH
  1079.     CALL    SET_DEST        ;Display drive, directory, menu.
  1080.     RET
  1081. READ_DIR    ENDP
  1082.  
  1083. ;--------------------------------------------------;
  1084. ; This long subroutine stores the filename in DIR  ;
  1085. ; format. That is, filename, bytes, date and time. ;
  1086. ;--------------------------------------------------;
  1087.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  1088. STORE_ENTRY    PROC    NEAR
  1089.     MOV    SI,OFFSET DTA+F_NAME    ;Point to filename.
  1090.     MOV    CX,12            ;Store 12 bytes of filename.
  1091.     CMP    BYTE PTR [SI],"."    ;Is it a dot directory?
  1092.     JNZ    _ST_E2            ;If no, it's a file.
  1093.     CMP    BYTE PTR [SI+1],"."    ;Is it a double dot directory?
  1094.     JNZ    _ST_E1            ;If no, single dot so skip.
  1095.     INC    COUNT            ;Else, increment total count.
  1096.     LODSB                ;Store dots and go to file size.
  1097.     STOSB
  1098.     STOSB
  1099.     ADD    DI,10
  1100.     JMP    SHORT _ST_E6
  1101.  
  1102. _ST_E1:    RET
  1103.  
  1104. _ST_E2:    INC    COUNT            ;Increment total count.
  1105. _ST_E3:    LODSB                ;Get a byte.
  1106.     CMP    AL,0            ;End of filename?
  1107.     JZ    _ST_E5            ;If yes, finish with spaces.
  1108.     CMP    AL,"."            ;Is it the period?
  1109.     JNZ    _ST_E4            ;If no, store.
  1110.     SUB    CX,3            ;Else store 3 spaces.
  1111.     MOV    AL,space
  1112.     REP    STOSB
  1113.     ADD    CX,3
  1114.     JMP    SHORT _ST_E3        ;Get next byte.
  1115.  
  1116. _ST_E4:    STOSB                ;Store byte.
  1117.     LOOP    _ST_E3            ;Get next byte.
  1118. _ST_E5:    MOV    AL,space        ;Pad balance with spaces.
  1119.     REP    STOSB
  1120.  
  1121. ;process file size column
  1122. _ST_E6:    PUSH    DI            ;Save pointer.
  1123.     TEST    BYTE PTR DTA+F_ATTR,10H    ;Is it a directory?
  1124.     JZ    _ST_E7            ;If no, store size.
  1125.     MOV    SI,OFFSET DIRECTORIES    ;Else, store "<DIR>".
  1126.     INC    DI
  1127.     MOV    CX,5
  1128.     REP    MOVSB
  1129.     JMP    SHORT _ST_E8
  1130.  
  1131. _ST_E7:    INC    FILE_CNT        ;Increment file count.
  1132.     ADD    DI,8            ;Move to end of bytes field.
  1133.     MOV    DX,WORD PTR DTA+F_SIZE+2    ;Retrieve high and low words
  1134.     MOV    AX,WORD PTR DTA+F_SIZE        ; of bytes.
  1135.     CALL    TRANSLATE        ;Convert to decimal.
  1136.  
  1137. _ST_E8:    POP    DI            ;Retrieve pointer.
  1138.     ADD    DI,11            ;Move to date field.
  1139.     MOV    DX,WORD PTR DTA+F_DATE    ;Retrieve date.
  1140.     MOV    AX,DX
  1141.     MOV    CL,5            ;Shift to lowest bits.
  1142.     ROR    AX,CL
  1143.     AND    AX,0FH            ;Mask off all but month.
  1144.     MOV    CL,0FFH            ;Flag as no leading zeros.
  1145.     MOV    CH,"-"            ;Delimiting character.
  1146.     CALL    STORE_DIGITS        ;Store it.
  1147.  
  1148. ;process date column
  1149.     MOV    AX,DX            ;Retrieve date.
  1150.     AND    AX,1FH            ;Mask off all but day.
  1151.     MOV    CL,0            ;Flag include leading zeros.
  1152.     MOV    CH,"-"
  1153.     CALL    STORE_DIGITS        ;Store it.
  1154.     MOV    AX,DX            ;Retrieve date for last time.
  1155.     MOV    CL,9
  1156.     ROR    AX,CL
  1157.     AND    AX,7FH            ;Mask off all butyear.
  1158.     ADD    AX,80            ;Adjust to ASCII.
  1159.     CMP    AX,100            ;Past year 2000?
  1160.     JB    _ST_E9            ;If no, display. Else, adjust for
  1161.     SUB    AX,100            ; next century. (Planning ahead!)
  1162.  
  1163. _ST_E9:    MOV    CL,0            ;Display leading zeros.
  1164.     MOV    CH,space
  1165.     CALL    STORE_DIGITS        ;Store it.
  1166.  
  1167. ;process time column
  1168.     INC    DI            ;Move to time field.
  1169.     MOV    DX,WORD PTR DTA+F_TIME    ;Retrieve time.
  1170.     MOV    AX,DX
  1171.     MOV    CL,11            ;Shift to hours bits.
  1172.     ROR    AX,CL
  1173.     AND    AX,1FH            ;Mask off all but hours.
  1174.     PUSH    AX
  1175.     CMP    AX,12            ;Past noon?
  1176.     JBE    _ST_E10
  1177.     SUB    AX,12            ;If yes, adjust.
  1178.  
  1179. _ST_E10:
  1180.     CMP    AX,0            ;Midnight?
  1181.     JNZ    _ST_E11
  1182.     MOV    AX,12            ;If yes, adjust.
  1183.  
  1184. _ST_E11:
  1185.     MOV    CL,0FFH            ;Suppress leading zeros.
  1186.     MOV    CH,":"
  1187.     CALL    STORE_DIGITS        ;Store it.
  1188.  
  1189.     MOV    AX,DX            ;Retrieve time.
  1190.     MOV    CL,5            ;Shift to minutes bits.
  1191.     ROR    AX,CL
  1192.     AND    AX,3FH            ;Mask off all but minutes.
  1193.     MOV    CL,0
  1194.     POP    DX            ;Retrieve hours.
  1195.     MOV    CH,"p"            ;Assume PM.
  1196.     CMP    DX,12            ;Is it PM?
  1197.     JAE    _ST_E12
  1198.     MOV    CH,"a"            ;If no, AM.
  1199.  
  1200. _ST_E12:
  1201.     CALL    STORE_DIGITS        ;Store it.
  1202.     MOV    AH,BYTE PTR DTA+F_ATTR    ;Get attribute byte.
  1203.     MOV    AL,"H"            ;Assume it's hidden.
  1204.     TEST    AH,2            ;Is it?
  1205.     JNZ    _ST_E13            ;If yes, store "H".
  1206.     MOV    AL,space        ;Else, store a space.
  1207.  
  1208. _ST_E13:
  1209.     STOSB
  1210.     MOV    AL,"S"            ;Assume it's system.
  1211.     TEST    AH,4            ;Is it?
  1212.     JNZ    _ST_E14            ;If yes, store "S".
  1213.     MOV    AL,space        ;Else, store a space.
  1214.  
  1215. _ST_E14:
  1216.     STOSB
  1217.     MOV    AL,"R"            ;Assume it's read-only.
  1218.     TEST    AH,1            ;Is it?
  1219.     JNZ    _ST_E15            ;If yes, store "R".
  1220.     MOV    AL,space        ;Else, store a space.
  1221.  
  1222. _ST_E15:
  1223.     STOSB
  1224.     MOV    AL,"A"            ;Assume it's archive.
  1225.     TEST    AH,20H            ;is it?
  1226.     JNZ    _ST_E16            ;If yes, store "A".
  1227.     MOV    AL,space        ;Else store a space.
  1228.  
  1229. _ST_E16:
  1230.     STOSB
  1231.     INC    DI            ;Bump pointer past mark field.
  1232.     RET
  1233. STORE_ENTRY    ENDP
  1234.  
  1235.  
  1236. SUBTTL Main Command subroutines
  1237. page
  1238.         ;**************************;
  1239.         ; MAIN COMMAND SUBROUTINES ;
  1240.         ;**************************;
  1241.  
  1242. ;---------------------------------------------------------------;
  1243. ; This subroutine toggles the number of rows on the screen.     ;
  1244. ; Toggles from 25 rows to 43 (EGA) or 50 (VGA/400 scan lines)   ;
  1245. ; and back.  Will only do something if and EGA/VGA is being     ;
  1246. ; used and it is in Video Mode 3 or 7.                          ;
  1247. ;---------------------------------------------------------------;
  1248. TOGGLE_ROWS     PROC    NEAR
  1249.         call    TOGGLE_OK
  1250.         jc      _TOG2
  1251.  
  1252.         mov     bl,byte ptr SCREEN_ROWS
  1253.         sub     bl,25           ;switch to 25 rows if BL!=25; otherwise 43/50
  1254.         call    SET_LINES
  1255.  
  1256.         call    SET_SCREEN_VARS ;set screen size dependant variables
  1257.         call    PUT_MENU_PATHS  ;restore menu
  1258.  
  1259.         mov     bx,COUNT        ;Retrieve file count.
  1260.         mov     ax,DIR_ROW_END
  1261.         cmp     bx,DIR_ROWS     ;Enough to fill one page?
  1262.         jae     _TOG1           ;If yes, use default setting.
  1263.         mov     ax,ROW_LEN      ;Calculate last record.
  1264.         mul     bx
  1265.         add     ax,BAR_START    ;Add bar offset.
  1266. _TOG1:  mov     DIR_DISP_END,ax ;This value MUST be set when changing rows
  1267.  
  1268.         call    HOME_BAR        ;Re-synch display by homing the cursor
  1269.  
  1270. _TOG2:  ret
  1271. TOGGLE_ROWS     ENDP
  1272.  
  1273.  
  1274. ;---------------------------------------------------------------;
  1275. ; This subroutine restores the screen size before quiting the   ;
  1276. ; program                                                       ;
  1277. ;---------------------------------------------------------------;
  1278. RESTORE_SCREEN  PROC    NEAR
  1279.         call    TOGGLE_OK
  1280.         jc      _RS
  1281.  
  1282.         mov     bl,byte ptr SCREEN_ROWS
  1283.         dec     bl
  1284.         cmp     bl,ENTRY_ROWS
  1285.         je      _RS
  1286.  
  1287.         sub     bl,24           ;switch to 25 rows if BL!=24; otherwise 43/50
  1288.         call    SET_LINES       
  1289.  
  1290. _RS:    ret
  1291. RESTORE_SCREEN  ENDP
  1292.  
  1293.  
  1294. ;---------------------------------------------------------------;
  1295. ; This subroutine sets 43/50 or 25 rows on the screen.          ;
  1296. ; Called by RESTORE_SCREEN, TOGGLE_ROWS, and MAIN.              ;
  1297. ;                                                               ;
  1298. ; Entry    : BL=0 for 43/50 lines, otherwise 25 lines           ;
  1299. ; Returns  : nothing                                            ;
  1300. ; Modifies : everything                                         ;
  1301. ;---------------------------------------------------------------;
  1302. SET_LINES       PROC    NEAR
  1303.         mov     ax,3
  1304.         int     10h             ;set video mode 3
  1305.  
  1306.         or      bl,bl           ;set 25 rows?
  1307.         jne     _SETL           ; yes
  1308.  
  1309.         mov     ax,1112h        ;now set 43/50 rows
  1310.         int     10h             ;load 8x8 ROM character set (BL already = 0)
  1311. _SETL:  ret
  1312. SET_LINES       ENDP
  1313.  
  1314.  
  1315. ;---------------------------------------------------------------;
  1316. ; This routine checks if it is OK to change the number of rows. ;
  1317. ; Called by RESTORE_SCREEN and TOGGLE_ROWS.                     ;
  1318. ;                                                               ;
  1319. ; Returns  : nothing                                            ;
  1320. ; Modifies : everything                                         ;
  1321. ;---------------------------------------------------------------;
  1322. TOGGLE_OK       PROC    NEAR
  1323.         cmp     VID_ADAPT,'E'    ;Do we have an EGA/VGA?
  1324.         jne     _TOK1            ;if not, do nothing
  1325.         cmp     ENTRY_VID_MODE,2 ;Only change the number of rows while in
  1326.         je      _TOK2            ; 'safe' video text modes -> 2, 3 or 7
  1327.         cmp     ENTRY_VID_MODE,3 ; otherwise don't even try.
  1328.         je      _TOK2
  1329.         cmp     ENTRY_VID_MODE,7
  1330.         je      _TOK2
  1331. _TOK1:  stc                     ;set carry to indicate do not set rows
  1332. _TOK2:  ret
  1333. TOGGLE_OK       ENDP
  1334.  
  1335.  
  1336. ;---------------------------------------------------------------;
  1337. ; This subroutine copies files that do not already exist on destination
  1338. ; On entry : no known parameters
  1339. ; Returns  : nothing
  1340. ; Modifies : everything
  1341. ;---------------------------------------------------------------;
  1342. PCOPY    PROC    NEAR
  1343.     MOV    SI,OFFSET PCOPY_MSG    ;display copy message
  1344.     OR    FUNCTION,COPY_BIT+PROTECT_BIT    ;Else, indicate copy.
  1345.     JMP    SHORT _CPY1
  1346.  
  1347. ;---------------------------------------------------------------;
  1348. ; This subroutine copies either the highlighted or marked file. ;
  1349. ; On entry : no known parameters
  1350. ; Returns  : nothing
  1351. ; Modifies : everything
  1352. ;---------------------------------------------------------------;
  1353. COPY    PROC    NEAR
  1354.     MOV    SI,OFFSET COPY_MSG    ;display copy message
  1355.     OR    FUNCTION,COPY_BIT    ;Else, indicate copy.
  1356. _CPY1:    CALL    SETUP_DEST        ;Count marks, ask for destination.
  1357.     JC    _CPY_RET            ; error exit.
  1358.     CALL    EXEC_MARKED        ;Execute the command.
  1359.  
  1360. _CPY_RET:
  1361.     RET
  1362. COPY    ENDP
  1363. PCOPY    ENDP
  1364.  
  1365.  
  1366. ;----------------------------------------------------------------;
  1367. ; This subroutine deletes either the highlighted or marked file. ;
  1368. ; On entry : no known parameters
  1369. ; Returns  : nothing
  1370. ; Modifies : everything
  1371. ;----------------------------------------------------------------;
  1372. DELETE    PROC    NEAR
  1373.     OR    FUNCTION,DELETE_BIT+DIR_OK_BIT    ;Indicate deletion.
  1374.     CALL    COUNT_MARKS        ;Get count of marked files.
  1375.     JNZ    _DEL1            ;If marked, display number marked.
  1376.         CALL    GET_NAME                ;Else get highlighted.
  1377.     JBE    _DEL_ERR        ;Exit if it's hidden/disallowed 
  1378.     MOV    SI,FILE_NAME        ;Else display filename.
  1379.     JMP    SHORT _DEL2
  1380.  
  1381. _DEL1:    MOV    SI,OFFSET MARKED_MSG
  1382.  
  1383. _DEL2:    MOV    DI,PROMPT_LOC
  1384.     CALL    PUT_STRING
  1385.     MOV    SI,OFFSET DELETE_MSG    ;Display "will be deleted".
  1386.     CALL    PUT_STRING
  1387.     MOV    DI,PROMPT_LOC2        ;Display warning message.
  1388.     CALL    PUT_STRING
  1389.     CALL    CLEAR_OLD
  1390.  
  1391. _DEL3:    CALL    READ_KEY        ;Get a keystroke.
  1392.     CMP    AH,31H            ;Is it "N"?
  1393.     JZ    _DEL_RET        ;If yes, exit delete.
  1394.     CMP    AH,1            ;Is it Esc?
  1395.     JZ    _DEL_RET        ;If yes, exit delete.
  1396.     CMP    AH,15H            ;Is it "Y"?
  1397.     JZ    _DEL4            ;If yes, delete
  1398.     CALL    BEEP            ;Else, beep.
  1399.     JMP    _DEL3            ;And get another keystroke.
  1400.  
  1401. ;_DEL4:    OR    FUNCTION,DELETE_BIT    ;Indicate deletion.
  1402. _DEL4:    
  1403.     CALL    EXEC_MARKED        ;Execute the command.
  1404.     JMP    SHORT _DEL_RET
  1405.  
  1406. _DEL_ERR:
  1407.     CALL    BEEP            ;Beep if error.
  1408. _DEL_RET:
  1409.     RET
  1410. DELETE        ENDP
  1411.  
  1412. ;--------------------------------------------------------------;
  1413. ; This subroutine moves either the highlighted or marked file. ;
  1414. ; On entry : no known parameters
  1415. ; Returns  : nothing
  1416. ; Modifies : everything
  1417. ;--------------------------------------------------------------;
  1418. MOVE    PROC    NEAR
  1419.     MOV    SI,OFFSET MOVE_MSG    ;Display move message.
  1420.     CALL    SETUP_DEST        ;Count marks, ask for destination.
  1421.     JC    _MV_RET            ; error exit
  1422.  
  1423.     MOV    AX,WORD PTR ENTRY    ;Check if across drives move.
  1424.     CMP    AH,":"            ;Is there a drive specified?
  1425.     JZ    _MV_2            ;Use specified drive if there
  1426.     MOV    AL,DEST_PATH        ;Otherwise use default
  1427.  
  1428. _MV_2:    AND    AL,5FH            ;Capitalize.
  1429.     CMP    AL,SOURCE        ;Is it the same as source?
  1430.     MOV    AL,MOVE_BIT+PROTECT_BIT ; Meanwhile, force a check to see
  1431.                                     ;if target file already exists before
  1432.                                     ;executing a rename or copy operation
  1433.     JZ    _MV_3            ;If src disk=targ disk, just rename.
  1434.     OR    AL,COPY_BIT+DELETE_BIT    ;Else, indicate both copy/delete.
  1435.  
  1436. _MV_3:    MOV    FUNCTION,AL        ;indicate desired function
  1437.     CALL    EXEC_MARKED        ;Execute the command.
  1438. _MV_RET:
  1439.     RET
  1440. MOVE    ENDP
  1441.  
  1442.  
  1443. ;--------------------------------------------------------------;
  1444. ; This subroutine renames either the highlighted or marked file. ;
  1445. ; On entry : no known parameters
  1446. ; Returns  : nothing
  1447. ; Modifies : everything
  1448. ;--------------------------------------------------------------;
  1449. RENAME    PROC    NEAR
  1450.     OR    FUNCTION,RENAME_BIT+DIR_OK_BIT    ;flag desired function
  1451.     MOV    SI,OFFSET RENAME_MSG    ;Display rename message.
  1452.     CALL    SETUP_DEST        ;Count marks, ask for destination.
  1453.     JC    _REN_RET        ; abort
  1454.  
  1455. _REN1:    MOV    SI,OFFSET WORK_PATH
  1456.     CALL    CHANGE_PATH        ;change back to work disk
  1457. _REN2:    CALL    EXEC_MARKED        ;Execute the command.
  1458. ;there is a subtle problem in restoring the dest path that occurs
  1459. ;when the rename operation has renamed the detination such that
  1460. ;DEST_PATH no longer exists as a legitimate path
  1461.     MOV    DI,OFFSET DEST_PATH    ;get destination path
  1462.     PUSH    DI            ;save it for now
  1463.     MOV    SI,OFFSET SOURCE    ;check with what we just changed
  1464.  
  1465. _REN3:    LODSB                ;get a byte
  1466.     SCASB                ;check it against dest
  1467.     JNZ    _REN4            ;dest was not renamed
  1468.     OR    AL,AL            ;are we done
  1469.     JNZ    _REN3            ;no, there's more
  1470.  
  1471. _REN4:    POP    SI
  1472.     JNZ    _REN5
  1473.     MOV    SI,OFFSET ENTRY        ;use new name instead
  1474. _REN5:    CALL    SET_DEST        ;go restore dest
  1475. _REN_RET:
  1476.     RET
  1477. RENAME    ENDP
  1478.  
  1479.  
  1480. ;----------------------------------------------------------------;
  1481. ; This subroutine removes the highlighted directory (<DIR>) if empty 
  1482. ;  NOTE - NO WARNING PROMPT IS GIVEN
  1483. ; On entry : no known parameters
  1484. ; Returns  : nothing
  1485. ; Modifies : everything
  1486. ;----------------------------------------------------------------;
  1487. RMDIR    PROC    NEAR
  1488.         CALL    GET_NAME                ;Else get highlighted.
  1489.     JA    _RMD_ERR        ;Exit if it's not a directory
  1490.  
  1491. _RMD4:    OR    FUNCTION,DELETE_BIT+DIR_OK_BIT    ;Indicate deletion.
  1492.     CALL    EXEC_MARKED        ;Execute the command.
  1493.     JMP    SHORT _RMD_RET
  1494.  
  1495. _RMD_ERR:
  1496.     CALL    BEEP            ;Beep if error.
  1497. _RMD_RET:
  1498.     RET
  1499. RMDIR        ENDP
  1500.  
  1501.  
  1502. ;----------------------------------------------------------------;
  1503. ; This subroutine creates a new directory on destination (MKDIR)
  1504. ; On entry : no known parameters
  1505. ; Returns  : nothing
  1506. ; Modifies : everything
  1507. ;----------------------------------------------------------------;
  1508. MKDIR    PROC NEAR
  1509.     MOV    SI,OFFSET MKDIR_MSG    ;Display prompt
  1510.     MOV    DI,PROMPT_LOC        ;at usual place
  1511.     CALL    JUST_ASK
  1512.     JC    _MKD_RET        ;escape out
  1513.     MOV    DX,OFFSET ENTRY        ;point to user entry
  1514.     MOV    AH,39h            ;MKDIR fn call
  1515.     INT    DOSINT
  1516.     JNC    _MKD_RET
  1517.     CALL    CD_ERROR
  1518. _MKD_RET:
  1519.     MOV    FUNCTION,UPD_CNT_BIT    ;force msg clear
  1520.     RET
  1521. MKDIR        ENDP
  1522.  
  1523.  
  1524. ;-----------------------------------;
  1525. ; This subroutine clears all marks. ;
  1526. ; On entry : no known parameters
  1527. ; Returns  : nothing
  1528. ; Modifies : SI
  1529. ;-----------------------------------;
  1530. CLEAR_MARK    PROC    NEAR
  1531.     MOV    SI,OFFSET DIR_BUFF    ;Point to start of listing.
  1532. _CLM1:    MOV    BYTE PTR [SI],space    ;Write space over mark.
  1533.     ADD    SI,FIELD_SIZE        ;Next record.
  1534.     CMP    SI,END_OFFSET        ;End of listing?
  1535.     JB    _CLM1            ;If no, continue until done.
  1536.     CALL    COUNT_MARKS
  1537.     RET
  1538. CLEAR_MARK    ENDP
  1539.  
  1540.  
  1541. ;----------------------------------------------------------------------;
  1542. ; This subroutine marks all files that aren't marked with an asterisk. ;
  1543. ; On entry : no known parameters
  1544. ; Returns  : nothing
  1545. ; Modifies : SI
  1546. ;----------------------------------------------------------------------;
  1547. MARK_BLANK    PROC    NEAR
  1548.     MOV    SI,OFFSET DIR_BUFF    ;Point to start of listing.
  1549. _M_B1:
  1550.     CMP    BYTE PTR [SI].D_SIZE,"<"    ;Is it a directory?
  1551.     JZ    _M_B2            ;If yes, skip.
  1552.     CMP    BYTE PTR [SI].D_HID,"H"    ;Is it a hidden file?
  1553.     JZ    _M_B2            ;If yes, skip.
  1554.     CMP    BYTE PTR [SI],space    ;Is it a space?
  1555.     JNZ    _M_B2            ;If no, skip.
  1556.     MOV    BYTE PTR [SI],COPY_MARK    ;Else mark.
  1557. _M_B2:
  1558.     ADD    SI,FIELD_SIZE        ;Next record.
  1559.     CMP    SI,END_OFFSET        ;Continue until done.
  1560.     JB    _M_B1
  1561.     CALL    COUNT_MARKS
  1562.     RET
  1563. MARK_BLANK    ENDP
  1564.  
  1565. ;-------------------------------------------------------;
  1566. ; This subroutine swaps marked/unmarked            ;
  1567. ; On entry : no known parameters
  1568. ; Returns  : nothing
  1569. ; Modifies : SI
  1570. ;-------------------------------------------------------;
  1571. SWAP_MARK    PROC    NEAR
  1572.     MOV    SI,OFFSET DIR_BUFF    ;Point to start of listing.
  1573.  
  1574. _S_M1:    CMP    BYTE PTR [SI],COPY_MARK    ;Is it marked ?
  1575.     JZ    _S_M2            ;If yes, unmark it.
  1576.     CMP    BYTE PTR [SI].D_SIZE,"<"    ;Is it a directory?
  1577.     JZ    _S_M3            ;If yes, skip.
  1578.     CMP    BYTE PTR [SI].D_HID,"H"    ;Is it a hidden file?
  1579.     JZ    _S_M3            ;If yes, skip.
  1580.     MOV    BYTE PTR [SI],COPY_MARK    ;Else mark.
  1581.     JMP    SHORT _S_M3
  1582.  
  1583. _S_M2:    MOV    BYTE PTR [SI],space
  1584. _S_M3:    ADD    SI,FIELD_SIZE        ;Next record.
  1585.     CMP    SI,END_OFFSET        ;Continue until done.
  1586.     JB    _S_M1
  1587.     CALL    COUNT_MARKS
  1588.     RET
  1589. SWAP_MARK    ENDP
  1590.  
  1591. ;--------------------------------------------------------;
  1592. ; This subroutine marks or unmarks the highlighted file. ;
  1593. ; On entry : no known parameters
  1594. ; Returns  : nothing
  1595. ; Modifies : assume everything
  1596. ;--------------------------------------------------------;
  1597. MARK    PROC    NEAR
  1598.     CALL    PUT_AMARK
  1599.     CALL    DN_ARROW        ;And move down a row.
  1600.     RET
  1601. MARK    ENDP
  1602.  
  1603. UNMARK    PROC    NEAR
  1604.     MOV    DL,space        ;Space character.
  1605.     CALL    PUT_MARK
  1606.     CALL    DN_ARROW        ;And move down a row.
  1607.     RET
  1608. UNMARK    ENDP
  1609.  
  1610. PUT_AMARK    PROC    NEAR
  1611.     MOV    DL,COPY_MARK
  1612. PUT_MARK    PROC    NEAR
  1613.     CALL    GET_NAME        ;Get filename.
  1614.     JBE    PTM_RET            ;If directory or hidden, skip.
  1615.     MOV    [SI],DL            ;Else store the character.
  1616.     PUSH    SI
  1617.     CALL    COUNT_MARKS
  1618.     POP    SI
  1619. PTM_RET:    RET
  1620. PUT_MARK    ENDP
  1621. PUT_AMARK    ENDP
  1622. ;-----------------------------------------------------------------------;
  1623. ; This subroutine searches for a filename with a specific first letter. ;
  1624. ; On entry : BL contains character to search for
  1625. ; Returns  : nothing
  1626. ; Modifies : assume everything
  1627. ;-----------------------------------------------------------------------;
  1628. SEARCH    PROC    NEAR
  1629.     CMP    BL,"a"            ;Capitalize if lower case.
  1630.     JB    _SRCH1
  1631.     CMP    BL,"z"
  1632.     JA    _SRCH1
  1633.     AND    BL,5FH
  1634.  
  1635. _SRCH1:    CALL    GET_NAME        ;Get current position.
  1636.     XOR    DX,DX            ;Zero out file counter.
  1637.     MOV    DI,SI            ;Store current position in DI.
  1638.     INC    DI            ;point to filename
  1639.     MOV    SI,OFFSET DIR_BUFF + 1    ;Point to top of listing.
  1640.     CMP    BYTE PTR [DI],BL    ;Are we currently at a match?
  1641.     JNZ    _SRCH3            ;If no, start from top.
  1642.  
  1643. _SRCH2:    INC    DX            ;Increment count.
  1644.     ADD    SI,FIELD_SIZE        ;Increment record.
  1645.     CMP    SI,DI            ;New record?
  1646.     JBE    _SRCH2            ;If no, find it.
  1647.  
  1648. _SRCH3:    CMP    BYTE PTR [SI],BL    ;Got a match?
  1649.     JZ    _SRCH4            ;If yes, process.
  1650.  
  1651.     ADD    SI,FIELD_SIZE        ;Else, point to next record.
  1652.     INC    DX
  1653.     CMP    BYTE PTR [SI],space    ;End of listing?
  1654.     JNZ    _SRCH3            ;If no, keep searching.
  1655.     CALL    BEEP            ;No matches, so beep.
  1656.     STC
  1657.     RET
  1658.  
  1659. _SRCH4:    MOV    CX,COUNT        ;Retrieve file count.
  1660.     SUB    CX,DX            ;Subtract search count.
  1661.     MOV    SEARCH_COUNT,CX        ;And store.
  1662.     MOV    CL,NORMAL        ;Turn off bar for now.
  1663.     MOV    BAR_ATTRIBUTE,CL
  1664.     CALL    END_BAR            ;First move to end.
  1665.     JMP    SHORT _SRCH6
  1666.  
  1667. _SRCH5:    CALL    UP_ARROW        ;Move up to matching filename.
  1668.  
  1669. _SRCH6:    DEC    SEARCH_COUNT
  1670.     JNZ    _SRCH5
  1671.     MOV    CL,INVERSE        ;Turn bar back on and display.
  1672.     MOV    BAR_ATTRIBUTE,CL
  1673.     XOR    BP,BP
  1674.     CALL    SCROLL_BAR
  1675.     CLC
  1676.     RET
  1677. SEARCH    ENDP
  1678.  
  1679. ;--------------------------------------------------------------------------;
  1680. ; Command to restore to the working directory and then re-read from disk
  1681. ; On entry : no known parameters
  1682. ; Returns  : nothing
  1683. ; Modifies : everything
  1684. ;--------------------------------------------------------------------------;
  1685. REFRESH    PROC    NEAR
  1686.     MOV    SI,OFFSET WORK_PATH
  1687.         CALL    NEW_WORK_DIR
  1688.     RET
  1689. REFRESH        ENDP
  1690.  
  1691. ;------------------------------------------------------------------------;
  1692. ; This subroutine changes the sorting option
  1693. ; On entry : AL contains a scan code
  1694. ; Returns  : nothing
  1695. ; Modifies : assume everything
  1696. ;------------------------------------------------------------------------;
  1697.  
  1698. RE_SORT    PROC    NEAR
  1699.     MOV    DI,OFFSET SORT_KEYS
  1700.     CALL    SET_SORT            ;returns al=sort_offset
  1701.     CMP    AH,-1            ;ah=sort_len=-1 if orig order
  1702.     JZ    REFRESH            ;re-load unsorted dir
  1703.  
  1704.     MOV    DI,SORT_LOC
  1705.     MOV    SI,OFFSET SORT_MSG
  1706.     CALL    PUT_STRING
  1707.  
  1708. ;------------------------------------------;
  1709. ; This subroutine does the actual sorting. ;
  1710. ; On entry : no known parameters
  1711. ; Returns  : nothing
  1712. ; Modifies : assume everything
  1713. ;------------------------------------------;
  1714. SORT    PROC    NEAR
  1715.     CMP    COUNT,1            ;Can't sort less than 2 files.
  1716.     JBE    _SRT_RET
  1717.     MOV    DX,END_OFFSET        ;End of filenames in DX.
  1718.     SUB    DX,FIELD_SIZE
  1719.     XOR    CX,CX            ;clear CH
  1720.     MOV    BL,SORT_LEN
  1721.     CMP    BL,-1            ;no sort if field length is -1
  1722.     JZ    _SRT_RET
  1723.  
  1724. _SRT1:    XOR    BH,BH            ;BH used as sort flag
  1725.     MOV    BP,OFFSET DIR_BUFF + 1    ;Point to start of buffer.
  1726.  
  1727. _SRT2:    MOV    SI,BP            ;Source and destination.
  1728.     MOV    AL,[SI+13]        ;special test to put <DIR>'s
  1729.     CMP    AL,[SI+13+FIELD_SIZE]    ;at start of list
  1730.     JB    _SRT4            ;dir field is different, swap
  1731.     JA    _SRT6
  1732.     ADD    SI,SORT_OFFSET
  1733.     MOV    DI,SI
  1734.     ADD    DI,FIELD_SIZE
  1735.     OR    BL,BL            ;Is it special case of date?
  1736.     JZ    _SRT7            ;If yes, go do it
  1737.     MOV    CL,BL
  1738.  
  1739. _SRT3:    REPZ    CMPSB            ;Compare filenames.
  1740.     JBE    _SRT6            ;If already in order, skip.
  1741.  
  1742. _SRT4:    MOV    SI,BP            ;Else, recover pointers.
  1743.     DEC    SI
  1744.     MOV    DI,SI
  1745.     ADD    DI,FIELD_SIZE
  1746.     MOV    CL,FIELD_SIZE / 2    ;Exchange the records.
  1747.  
  1748. _SRT5:    MOV    AX,[DI]            ;swap fields through AX
  1749.     MOVSW
  1750.     MOV    [SI-2],AX
  1751.     LOOP    _SRT5
  1752.     INC    BH            ;Flag that exchange was made.
  1753.  
  1754. _SRT6:    ADD    BP,FIELD_SIZE        ;Point to next record.
  1755.     CMP    BP,DX            ;End of top?
  1756.     JB    _SRT2            ;If no, bubble sort next.
  1757.     SUB    DX,FIELD_SIZE        ;Else, move top down one record.
  1758.     OR    BH,BH            ;Was there exchange made?
  1759.     JNZ    _SRT1            ;If yes, another pass.
  1760.  
  1761. _SRT_RET:
  1762.     MOV    FUNCTION,UPD_CNT_BIT    ;clear msg, restore counter
  1763.     RET
  1764.  
  1765. _SRT7:    MOV    CL,2            ; treat special case of date
  1766.     REPZ    CMPSB                   ;Compare year first.
  1767.     JA    _SRT4            ;If above, swap.
  1768.     JNZ    _SRT6
  1769.     SUB    SI,8            ;Else, adjust and do month/day.
  1770.     SUB    DI,8
  1771.     MOV    CL,5
  1772.     REPZ    CMPSB
  1773.     JA    _SRT4            ;If above, swap.
  1774.     JNZ    _SRT6
  1775.     ADD    SI,10            ;Else, adjust and do meridian.
  1776.     ADD    DI,10
  1777.     CMPSB
  1778.     JA    _SRT4            ;If above, swap.
  1779.     JNZ    _SRT6
  1780.     SUB    SI,6            ;Else, adjust and do time.
  1781.     SUB    DI,6
  1782.     MOV    CL,5
  1783.     CMP    WORD PTR [SI],3231H    ;Is it special case "12:"?
  1784.     JZ    _SRT8            ;If yes, see if same.
  1785.     CMP    WORD PTR [DI],3231H    ;Is destination "12:"?
  1786.     JNZ    _SRT3            ;If no, normal compare.
  1787.     JMP    _SRT4            ;Else, swap.
  1788. _SRT8:    CMPSW                ;Are both "12:"?
  1789.     JNZ    _SRT6            ;If no, next record.
  1790.     MOV    CL,3            ;Else compare minutes.
  1791.     JMP    SHORT _SRT3
  1792.  
  1793. SORT        ENDP
  1794. RE_SORT        ENDP
  1795.  
  1796.  
  1797. ;--------------------------------------------------------------------------;
  1798. ; These six subroutines control the bar and page of the directory listing. ;
  1799. ; On entry : no known parameters
  1800. ; Returns  : nothing
  1801. ; Modifies : all
  1802. ;--------------------------------------------------------------------------;
  1803. UP_ARROW    PROC    NEAR
  1804.         MOV     BP,ROW_LEN                      ;Move bar up one line.
  1805.         NEG     BP
  1806.     JMP    SHORT BAR_MOVE
  1807.  
  1808. DN_ARROW    PROC    NEAR
  1809.     MOV    BP,ROW_LEN            ;Move bar down one line.
  1810.  
  1811. BAR_MOVE    PROC    NEAR
  1812.     CALL    SCROLL_BAR
  1813.     RET
  1814. BAR_MOVE    ENDP
  1815. DN_ARROW    ENDP
  1816. UP_ARROW    ENDP
  1817.  
  1818.  
  1819. PG_DN   PROC    NEAR
  1820.         mov     ax,DIR_ROWS             ;Move down 20 lines.
  1821.         dec     ax
  1822.         mov     bl,FIELD_SIZE
  1823.         mul     bl
  1824.         mov     bp,ax                   ;BP = FIELD_SIZE * (DIR_ROWS - 1)
  1825.  
  1826. MOVE_PAGE    PROC    NEAR
  1827.         CALL    SCROLL
  1828.     JMP    SHORT TOP_BAR        ;Move bar to top.
  1829.  
  1830. HOME_BAR    PROC    NEAR
  1831.     MOV    CUR_OFFSET,OFFSET DIR_BUFF;Move listing to beginning.
  1832.  
  1833. TOP_BAR    PROC    NEAR
  1834.     MOV    SI,BAR_START        ;And move bar to top.
  1835.     CALL    MOVE_BAR
  1836.     RET
  1837. TOP_BAR        ENDP
  1838. HOME_BAR    ENDP
  1839. MOVE_PAGE    ENDP
  1840. PG_DN        ENDP
  1841.  
  1842.  
  1843. PG_UP   PROC    NEAR
  1844.         mov     ax,DIR_ROWS             ;Move up 20 lines.
  1845.         dec     ax
  1846.         mov     bl,FIELD_SIZE
  1847.         mul     bl
  1848.         neg     ax
  1849.         mov     bp,ax                   ;BP = FIELD_SIZE * (DIR_ROWS - 1)
  1850.  
  1851.         CALL    SCROLL
  1852.     JMP    SHORT BOTTOM_BAR
  1853.  
  1854. END_BAR    PROC    NEAR
  1855.     MOV    BX,END_OFFSET        ;Move listing to last page.
  1856.  
  1857.         mov     ax,FIELD_SIZE
  1858.         mul     byte ptr DIR_ROWS
  1859.         sub     bx,ax
  1860.  
  1861.     CMP    BX,OFFSET DIR_BUFF
  1862.     JBE    BOTTOM_BAR
  1863.     MOV    CUR_OFFSET,BX
  1864.  
  1865. BOTTOM_BAR    PROC    NEAR
  1866.     MOV    SI,DIR_DISP_END        ;And move bar to bottom.
  1867.     SUB    SI,ROW_LEN
  1868.     CALL    MOVE_BAR
  1869.     RET
  1870. BOTTOM_BAR    ENDP
  1871. END_BAR    ENDP
  1872. PG_UP    ENDP
  1873.  
  1874. ;----------------------------------------------------;
  1875. ; This subroutine does the actual moving of the bar. ;
  1876. ; On entry : no known parameters
  1877. ; Returns  : nothing
  1878. ; Modifies : AX, CX, DX, DI
  1879. ;----------------------------------------------------;
  1880. MOVE_BAR    PROC    NEAR
  1881.     MOV    AL,NORMAL        ;Remove old bar.
  1882.     CALL    BAR
  1883.     MOV    LINE,SI            ;And move bar to new line.
  1884.     MOV    AL,BAR_ATTRIBUTE
  1885.  
  1886. BAR    PROC    NEAR
  1887.     MOV    DI,LINE            ;Retrieve line.
  1888.     MOV    CX,BAR_LEN        ;Bar length 39.
  1889. _BR_1:  CALL    PUT_CHAR                ;Write the attribute.
  1890.     LOOP    _BR_1
  1891.     RET
  1892. BAR    ENDP
  1893. MOVE_BAR    ENDP
  1894.  
  1895. ;-------------------------------------;
  1896. ; This subroutine scrolls the screen. ;
  1897. ; On entry : BP indicates direction and number of lines to scroll
  1898. ; Returns  : nothing
  1899. ; Modifies : BX, SI
  1900. ;-------------------------------------;
  1901.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  1902. SCROLL    PROC    NEAR
  1903.     MOV    SI,CUR_OFFSET        ;Get current offset.
  1904.     ADD    SI,BP            ;Add requested direction.
  1905.     CMP    SI,OFFSET DIR_BUFF    ;If above start check upper limit.
  1906.     JAE    _SC1
  1907.     MOV    CUR_OFFSET,OFFSET DIR_BUFF;Else, make it start.
  1908.     JMP    SHORT _SC_RET        ;And update screen.
  1909.  
  1910. _SC1:   MOV     BX,END_OFFSET           ;See if beyond end of dir listing.
  1911.  
  1912.         mov     ax,FIELD_SIZE
  1913.         mul     byte ptr DIR_ROWS
  1914.         add     ax,OFFSET DIR_BUFF
  1915.         cmp     bx,ax
  1916.  
  1917.         JA      _SC2
  1918.     MOV    CUR_OFFSET,OFFSET DIR_BUFF
  1919.     JMP    SHORT _SC_RET
  1920.  
  1921. _SC2:   mov     ax,FIELD_SIZE
  1922.         mul     byte ptr DIR_ROWS
  1923.         sub     bx,ax
  1924.  
  1925.         CMP     SI,BX
  1926.     JBE    _SC3
  1927.     MOV    SI,BX
  1928.  
  1929. _SC3:    MOV    CUR_OFFSET,SI        ;Update current offset.
  1930. _SC_RET:
  1931.     RET
  1932. SCROLL    ENDP
  1933.  
  1934. ;--------------------------------------------------
  1935. ; This subroutine scrolls the bar if between start
  1936. ; and end of page. Otherwise the page is scrolled.
  1937. ; On entry : BP indicates signed number of lines to scroll
  1938. ; Returns  : nothing
  1939. ; Modifies : AX, CX, DX, SI, DI
  1940. ;--------------------------------------------------
  1941. SCROLL_BAR    PROC    NEAR
  1942.     MOV    SI,LINE            ;Get current line.
  1943.     ADD    SI,BP            ;Add requested line.
  1944.         MOV     BP,FIELD_SIZE           ;Assume below beginning.
  1945.         NEG     BP
  1946.     CMP    SI,BAR_START        ;Is it?
  1947.     JB    _SCR1            ;If yes, scroll page instead.
  1948.     MOV    BP,FIELD_SIZE        ;Do the same for end of page.
  1949.     CMP    SI,DIR_DISP_END
  1950.     JAE    _SCR1
  1951.     CALL    MOVE_BAR
  1952.     JMP    SHORT _SCR2
  1953. _SCR1:    CALL    SCROLL
  1954. _SCR2:    RET
  1955. SCROLL_BAR    ENDP
  1956.  
  1957. ;-------------------------------------------------------;
  1958. ; This subroutine toggles the string filter function.    ;
  1959. ; On entry : no known parameters
  1960. ; Returns  : nothing
  1961. ; Modifies : nothing
  1962. ;-------------------------------------------------------;
  1963.     ASSUME    DS:NOTHING,ES:NOTHING
  1964. ASCII    PROC    NEAR
  1965.     XOR    VIEW_FLAGS,ASCII_BIT        ;Toggle flag.
  1966.     RET
  1967. ASCII    ENDP
  1968.  
  1969. ;-----------------------------------------------------;
  1970. ; This subroutine toggles the non-ascii blanking filter on and off.;
  1971. ; On entry : no known parameters
  1972. ; Returns  : nothing
  1973. ; Modifies : nothing
  1974. ;-----------------------------------------------------;
  1975.     ASSUME    DS:NOTHING,ES:NOTHING
  1976. BLANK    PROC    NEAR
  1977. ifdef BLANK_BIT
  1978.     XOR    VIEW_FLAGS,BLANK_BIT    ;Toggle flag.
  1979. Endif
  1980.     RET
  1981. BLANK    ENDP
  1982.  
  1983. ;--------------------------------------------------------;
  1984. ; This subroutine toggles the WordStar filter on and off.;
  1985. ; On entry : no known parameters
  1986. ; Returns  : nothing
  1987. ; Modifies : AX
  1988. ;--------------------------------------------------------;
  1989.     ASSUME    DS:NOTHING,ES:NOTHING
  1990. STAR    PROC    NEAR
  1991.     XOR    STAR_MASK,80H    ;Toggle flag.
  1992.     MOV    AL,' '
  1993.     JS    _ST1
  1994.     MOV    AL,'*'
  1995. _ST1:    MOV    OPTIONS,AL
  1996.     RET
  1997. STAR    ENDP
  1998.  
  1999. ;-------------------------------------------------------;
  2000. ; This subroutine toggles the Word wrap function.    ;
  2001. ; On entry : no known parameters
  2002. ; Returns  : nothing
  2003. ; Modifies : nothing
  2004. ;-------------------------------------------------------;
  2005.     ASSUME    DS:NOTHING,ES:NOTHING
  2006. WRAP    PROC    NEAR
  2007.     XOR    VIEW_FLAGS,WRAP_BIT        ;Toggle flag.
  2008.     RET
  2009. WRAP    ENDP
  2010.  
  2011.  
  2012. ;-------------------------------------------------------;
  2013. ; This subroutine toggles the Hex Dump function.        ;
  2014. ; On entry : no known parameters
  2015. ; Returns  : nothing
  2016. ; Modifies : nothing
  2017. ;-------------------------------------------------------;
  2018.     ASSUME    DS:NOTHING,ES:NOTHING
  2019. HEXDUMP PROC    NEAR
  2020.         XOR     VIEW_FLAGS,HEX_BIT              ;Toggle flag.
  2021.     RET
  2022. HEXDUMP ENDP
  2023.  
  2024.  
  2025. ;-------------------------------------------------------;
  2026. ; This subroutine spawns a DOS command interpretor.    ;
  2027. ; On entry : no known parameters                        ;
  2028. ; Returns  : nothing                                    ;
  2029. ; Modifies : everything                                 ;
  2030. ;-------------------------------------------------------;
  2031.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  2032. DOS_SHELL    PROC    NEAR
  2033.  
  2034.         MOV     AL,NORMAL
  2035.         CALL    CLR_SCR
  2036.         CALL    CURSOR_ON
  2037.  
  2038.         MOV     SI,OFFSET WORK_PATH     ;CD to appropriate directory
  2039.     CALL    CHANGE_PATH
  2040.  
  2041.     MOV    AX,3301H        ;Restore Control Break.
  2042.     MOV    DL,BREAK_STAT
  2043.     INT    DOSINT
  2044.  
  2045.     MOV    STK_SEG,SS        ;save stack
  2046.     MOV    STK_PTR,SP
  2047.         MOV     PAR_BLK+2, offset DOS_PROG
  2048.         MOV     DX,OFFSET PGM_NAME      ;exec command.com
  2049.     MOV    BX,OFFSET PAR_BLK
  2050.     MOV    AX,4B00H
  2051.     INT    DOSINT
  2052.  
  2053. ;program will go away for awhile and return here on "exit"
  2054.  
  2055.         PUSH    CS
  2056.         PUSH    CS
  2057.         POP     DS
  2058.         POP     ES
  2059.     CLI                ;no interrupts while fooling with stack
  2060.     MOV    SS,STK_SEG        ;restore stack
  2061.     MOV    SP,STK_PTR
  2062.     STI                ;interrupts OK now
  2063.         JNC     @F                      ;jump if DOS exec successful
  2064.     CALL    BEEP            ;beep to signal error
  2065.  
  2066. @@:     MOV     AX,3301H                ;Turn Control Break off again.
  2067.     MOV    DL,0
  2068.     INT    DOSINT
  2069.  
  2070.         call    TOGGLE_OK               ;restore screen rows
  2071.         jc      @F
  2072.         mov     bl,byte ptr SCREEN_ROWS
  2073.         cmp     bl,40
  2074.         jl      @F
  2075.         xor     bl,bl
  2076. @@:     call    SET_LINES
  2077.  
  2078.     MOV    DX,80H            ;reset DTA area for find first
  2079.     MOV    AH,1AH
  2080.     INT    DOSINT
  2081.     CALL    REFRESH            ;Redisplay directory
  2082.     RET
  2083. DOS_SHELL    ENDP
  2084.  
  2085. ;-------------------------------------------------------;
  2086. ; This subroutine spawns a DOS command interpretor      ;
  2087. ; and executes the program DOS_LINE1                    ;
  2088. ;                                                       ;
  2089. ;-------------------------------------------------------;
  2090.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  2091.  
  2092. DOS_SHELL1      PROC    NEAR
  2093.  
  2094.         mov     si,offset DOS_PROG1     ;command name
  2095.         jmp     CUSTOM_SHELL
  2096.  
  2097. DOS_SHELL2      PROC    NEAR
  2098.  
  2099.         mov     si,offset DOS_PROG2     ;command name
  2100.  
  2101. CUSTOM_SHELL:
  2102.  
  2103.     MOV    AX,3301H        ;Restore Control Break.
  2104.     MOV    DL,BREAK_STAT
  2105.     INT    DOSINT
  2106.  
  2107.     MOV    STK_SEG,SS        ;save stack
  2108.     MOV    STK_PTR,SP
  2109.  
  2110.         mov     dh,byte ptr SCREEN_ROWS ;move cursor to bottom of screen
  2111.         dec     dh
  2112.         xor     dl,dl
  2113.         call    SET_CURSOR
  2114.  
  2115.         mov     di,offset DOS_LINE+4    ;clear out DOS_LINE
  2116.         mov     al,0
  2117.         mov     cx,70
  2118. @@:     stosb
  2119.         loop    @B
  2120.  
  2121.         mov     di,offset DOS_LINE+4    ;copy command name
  2122.         mov     cx,40
  2123. @@:     lodsb
  2124.         cmp     al,0
  2125.         jz      @F
  2126.         stosb
  2127.         loop    @B
  2128.  
  2129. @@:     mov     al,20h                  ;add space after command
  2130.         stosb
  2131.  
  2132.         push    di
  2133.         call    GET_NAME                ;returns highlighted file in si
  2134.         pop     di
  2135.         mov     si,OFFSET SOURCE        ; point to it
  2136.  
  2137. @@:     mov     cx,60                   ;add path+filename
  2138.         lodsb
  2139.         cmp     al,0
  2140.         jz      @F
  2141.         stosb
  2142.         loop    @B
  2143.  
  2144. @@:     MOV     PAR_BLK+2, offset DOS_LINE
  2145.         MOV     DX,OFFSET PGM_NAME      ;exec command.com
  2146.         MOV     BX,OFFSET PAR_BLK
  2147.         MOV     AX,4B00H
  2148.         INT     DOSINT
  2149.  
  2150. ;program will go away for awhile and return here on "exit"
  2151.  
  2152.         PUSH    CS
  2153.         PUSH    CS
  2154.         POP     DS
  2155.         POP     ES
  2156.     CLI                ;no interrupts while fooling with stack
  2157.     MOV    SS,STK_SEG        ;restore stack
  2158.     MOV    SP,STK_PTR
  2159.     STI                ;interrupts OK now
  2160.         JNC     @F                      ;jump if DOS exec successful
  2161.     CALL    BEEP            ;beep to signal error
  2162.  
  2163. @@:
  2164.         ASSUME  DS:_TEXT,ES:_TEXT
  2165.         MOV     AX,3301H                ;Turn Control Break off again.
  2166.     MOV    DL,0
  2167.     INT    DOSINT
  2168.  
  2169.         call    TOGGLE_OK               ;restore screen rows
  2170.         jc      _CD22
  2171.         mov     bl,byte ptr SCREEN_ROWS
  2172.         cmp     bl,40
  2173.         jl      @F
  2174.         xor     bl,bl
  2175. @@:     call    SET_LINES
  2176.  
  2177. _CD22:  MOV     DX,80H                  ;reset DTA area for find first
  2178.     MOV    AH,1AH
  2179.         INT     DOSINT
  2180.         CALL    PUT_MENU_PATHS
  2181.         RET
  2182.  
  2183. DOS_SHELL2      ENDP
  2184. DOS_SHELL1      ENDP
  2185.  
  2186.  
  2187. SUBTTL View file command and subroutines
  2188. page
  2189. ;------------------------------------------------------------;
  2190. ; This subroutine displays the highlighted file for viewing. ;
  2191. ; On entry : no known parameters
  2192. ; Returns  : nothing
  2193. ; Modifies : everything
  2194. ;
  2195. ;"global" variables used in the regular segment are
  2196. ;
  2197. ;temporary variables in the extended buffer segment "DUMMY_SEG":
  2198. ;    PAGES is an array of byte sizes of previously formatted pages
  2199. ;    LAST_PAGE is the buffer pointer value (SI)
  2200. ;          for the top of the current page
  2201. ;    ROW  = # of rows into LAST_PAGE for current display
  2202. ;------------------------------------------------------------;
  2203.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  2204. VIEW    PROC    NEAR
  2205.  
  2206.     CALL    GET_NAME        ;Get the file name.
  2207.     MOV    SI,OFFSET SOURCE    ; point to it
  2208.     JNC    _VW1            ;view file, not directory
  2209.     JMP    VIEW_DIR
  2210.  
  2211. _VW1:    CALL    GET_MEM
  2212.     JNC    _VW2
  2213.     RET
  2214.  
  2215. _VW2:    MOV    DX,SI            ;Open the file
  2216.     MOV    AX,3D00H
  2217.     INT    DOSINT
  2218.     MOV    READ_HANDLE,AX        ;Save filehandle.
  2219.     MOV    AL,NORMAL
  2220.     CALL    CLR_SCR            ;Clear screen.
  2221.     MOV    AL,INVERSE        ;reverse video attribute
  2222.     XOR    CX,CX            ;setup status line
  2223.     CALL    CLR_EOL
  2224.  
  2225.     XOR    DI,DI            ;start at top of screen
  2226.     MOV    SI,CUR_FILE        ;get ptr to record
  2227.     INC    SI            ;inc to filename
  2228.     MOV    CX,WHERE_LOC        ;bytes to write
  2229.     CALL    PUT_CX_CHARS        ;write filename
  2230.     ADD    DI,2 * WHERE_LEN    ;skip over file ptr field
  2231.     MOV    AL,'/'            ;add a "/"
  2232.     CALL    PUT_CHAR
  2233.     MOV    CX,BAR_LEN - WHERE_LOC    ;remainder of status line
  2234.     CALL    PUT_CX_CHARS            ;display it
  2235.  
  2236.     MOV    DS,MEM_BUF_SEG
  2237.     ASSUME    DS:DUMMY_SEG
  2238.  
  2239.         CALL    FIRST_READ
  2240.  
  2241.         mov     ax,SCREEN_COLS
  2242.         mov     LAST_COL,ax
  2243.  
  2244.     MOV    BP,OFFSET PAGES        ;Initialize page pointer.
  2245.     MOV    ROW,0            ;And row pointer.
  2246.  
  2247. _VW3:    CALL    POSITION
  2248.  
  2249.         MOV     CX,SCREEN_ROWS          ;Now display one screen
  2250.         dec     cx
  2251.  
  2252.         PUSH    AX
  2253.     MOV    AH,1
  2254.     INT    16h            ;test keyboard
  2255.         POP     AX
  2256.         JNZ     _VW4                    ;if another key struck, skip display
  2257.  
  2258.         MOV     DI,ROW_LEN              ;start down one line
  2259.     OR    VIEW_FLAGS,DISPLAY_BIT    ;Display.
  2260. _VW4:    CALL    LINES            ;format (and display?) CX lines
  2261.  
  2262.  
  2263. ;process keyboard command entry
  2264. _VW6:    MOV    AH,0            ;Retrieve keystroke via BIOS.
  2265.     INT    16H
  2266.     CMP    AH,1            ;Is it Esc?
  2267.     JZ    _VW_RET            ;If yes, exit view.
  2268. IFNDEF SAG
  2269.     CMP    AH,1CH            ;Is it carriage return?
  2270.     JZ    _VW_RET            ;If yes, exit view.
  2271. ENDIF
  2272.     MOV    DI,OFFSET VIEW_KEYS    ;get key dispatch
  2273.     MOV    AL,AH
  2274.     MOV    CX,VIEW_CNT        ;number of valid commands.
  2275.     MOV    BX,OFFSET VIEW_TABLE_END
  2276.     CALL    LOOKUP            ;VIEW_KEYS
  2277.     JNZ    _VW6            ;If no, match, get next stroke.
  2278.  
  2279.     CALL    CS:[BX]         ;Do subroutine.
  2280.     JC    _VW6            ;Carry indicates no screen update.
  2281.     JMP    _VW3            ;Else, update and get next command.
  2282.  
  2283. _VW_RET:
  2284.     PUSH    CS
  2285.     POP    DS
  2286.  
  2287.     ASSUME    DS:_TEXT,ES:_TEXT
  2288.     CALL    RELEASE_MEM
  2289.     MOV    BX,READ_HANDLE        ;Close the file.
  2290.     MOV    AH,3EH
  2291.     INT    DOSINT
  2292.     CALL    PUT_MENU_PATHS        ;Restore menu.
  2293.     RET
  2294. VIEW    ENDP
  2295.  
  2296. ;----------------------------------------------------------------------;
  2297. ; These six subroutines control the page and starting row of the view. ;
  2298. ; Screen is updated unless carry flag is set upon return
  2299. ;----------------------------------------------------------------------;
  2300. ; This subroutine moves back one line in the file
  2301. ; On entry : parameters as discussed above
  2302. ; Modifies : ROW
  2303. ;--------------------------------------------------------;
  2304.     ASSUME    DS:DUMMY_SEG,ES:_TEXT
  2305. UP_LINE    PROC    NEAR
  2306.     CMP    ROW,0            ;Are we at row zero?
  2307.     JNZ    _U_L1            ;If no, decrement one row.
  2308.     CMP    BP,OFFSET PAGES        ;Else, are we at first page?
  2309.     STC
  2310.     JZ    _U_L_RET        ;If yes, no change.
  2311.     CALL    UP_PG            ;Else, move up one page.
  2312.         mov     al,VIEW_ROWS            ;And move starting row to bottom
  2313.         mov     ROW,al
  2314.  
  2315. _U_L1:    DEC    ROW            ;Decrement row.
  2316.  
  2317.     MOV    AX,0701h        ;bios scroll display down 1 line
  2318.     CALL    SCROLL_WIN
  2319.     CALL    POSITION
  2320.         MOV     CX,1                    ;Now display one line
  2321.     MOV    DI,ROW_LEN        ;first line
  2322.     OR    VIEW_FLAGS,DISPLAY_BIT    ;Display.
  2323.         CALL    LINES
  2324.     STC                ; no update.
  2325. _U_L_RET:
  2326.     RET
  2327. UP_LINE    ENDP
  2328.  
  2329. ;--------------------------------------------------------;
  2330. ; This subroutine moves forward one line in the file
  2331. ; On entry : parameters as discussed above
  2332. ; Modifies : ROW
  2333. ;--------------------------------------------------------;
  2334. DN_LINE    PROC    NEAR
  2335.     CALL    CK_FILE_END        ;Are we at end of file?
  2336.     JNC    _D_L1            ;If no, check row.
  2337.     RET                ;Else, return.
  2338. _D_L1:  mov     al,byte ptr VIEW_ROWS
  2339.         dec     al
  2340.         CMP     ROW,al                  ;Are we at last row?
  2341.     JB    _D_L2            ;If no, increment row.
  2342.     CALL    DN_PG            ;Else, page down.
  2343.     MOV    ROW,-1            ;And move row to top.
  2344.  
  2345. _D_L2:    INC    ROW
  2346.     MOV    AX,0601h        ;bios scroll display up 1 line
  2347.     CALL    SCROLL_WIN
  2348.  
  2349.     CALL    POSITION
  2350.         MOV     CX,SCREEN_ROWS          ;skip over scrolled display
  2351.         dec     cx
  2352.         dec     cx
  2353.         CALL    LINES
  2354.     MOV    CX,1            ;Now display last line
  2355.  
  2356.         push    ax
  2357.         mov     ax,SCREEN_ROWS          ;MOV DI,ROW_LEN*(SCREEN_ROWS-1)
  2358.         dec     ax
  2359.         mul     ROW_LEN
  2360.         mov     di,ax
  2361.         pop     ax
  2362.  
  2363.     OR    VIEW_FLAGS,DISPLAY_BIT          ;Display.
  2364.     CALL    LINES
  2365.     STC
  2366.     RET
  2367. DN_LINE    ENDP
  2368.  
  2369.  
  2370. ;-------------------------------------------------------------------;
  2371. ; Scroll View window AH = 6 for up, 7 for down
  2372. ; Uses        BH     = screen attribute to use
  2373. ;               CH, CL = row, col of upper left
  2374. ;               DH, DL = row, col of lower right
  2375. ; Modifies : AX, BH, CX, DX, saves BP
  2376. ;-------------------------------------------------------------------;
  2377. SCROLL_WIN    PROC    NEAR
  2378.     PUSH    BP
  2379.         MOV     BH,NORMAL               ;use normal attribute
  2380.         MOV     CX,0100h                ;top left
  2381.         mov     dh,byte ptr SCREEN_ROWS
  2382.         dec     dh                      ;bottom row
  2383.         mov     dl,byte ptr SCREEN_COLS
  2384.         dec     dl                      ;right col
  2385.         INT     10h                     ;video bios call
  2386.         POP     BP
  2387.     RET
  2388. SCROLL_WIN      ENDP
  2389.  
  2390.  
  2391. ;--------------------------------------------------------;
  2392. ; This subroutine moves back one full screen in the file
  2393. ; On entry : parameters as discussed above
  2394. ; Modifies : ROW, LAST_PAGE
  2395. ;--------------------------------------------------------;
  2396. UP_PG    PROC    NEAR
  2397.     CMP    BP,OFFSET PAGES        ;Are we already at first page?
  2398.     JNZ    _U_P2            ;If no, decrement page.
  2399.     CMP    ROW,0            ;Are we at first row?
  2400.     STC
  2401.     JZ    _U_P_RET            ;If yes, no update.
  2402.     MOV    ROW,0            ;Else move to first row.
  2403.     JMP    SHORT _U_P4
  2404.  
  2405. _U_P1:  CALL    BACKWARD                ;read in previous 1/2 buff
  2406.  
  2407. _U_P2:    MOV    SI,LAST_PAGE        ;Get current page.
  2408.     SUB    SI,DS:[BP]        ;Subtract difference to prev page.
  2409.     JC    _U_P1            ;have we already passed zero?
  2410.     CMP    SI,OFFSET FILE_BUFF    ;Beyond top of buffer?
  2411.     JC    _U_P1            ;If no, page up.
  2412.  
  2413. _U_P3:    DEC    BP
  2414.     DEC    BP            ;Decrement page pointer.
  2415.     MOV    LAST_PAGE,SI        ;Store new starting position.
  2416.  
  2417. _U_P4:    CLC
  2418. _U_P_RET:
  2419.     RET
  2420. UP_PG    ENDP
  2421.  
  2422. ;--------------------------------------------------------;
  2423. ; This subroutine moves foward one full screen in the file
  2424. ; On entry : parameters as discussed above
  2425. ; Modifies : ROW, LAST_PAGE
  2426. ;--------------------------------------------------------;
  2427. DN_PG    PROC    NEAR
  2428.         CMP     BP,OFFSET FILE_BUFF-2   ;Out of room for page storage?
  2429.     JAE    _D_P1            ;If yes, skip.
  2430.     MOV    SI,LAST_PAGE        ;Else, retrieve current page.
  2431.     AND    VIEW_FLAGS,NOT DISPLAY_BIT    ;No display.
  2432.     MOV    CL,VIEW_ROWS            ;Move up 24 lines.
  2433.     XOR    AH,AH            ;clear eol flag
  2434.     CALL    LINES
  2435.         CALL    CK_FILE_END             ;End of file?
  2436.     JC    _D_P1            ;If yes, no update.
  2437.     MOV    DX,LAST_PAGE        ;Else, save current offset.
  2438.     MOV    LAST_PAGE,SI        ;Store new offset.
  2439.     MOV    AX,SI
  2440.     SUB    AX,DX            ;Get difference between pages.
  2441.     INC    BP            ;Increment page storage.
  2442.     INC    BP
  2443.     MOV    DS:[BP],AX        ;And store.
  2444.     CLC
  2445.     RET
  2446.  
  2447. _D_P1:    STC
  2448.     RET
  2449. DN_PG    ENDP
  2450.  
  2451.  
  2452. ;--------------------------------------------------------;
  2453. ; This subroutine moves the display pointer 
  2454. ; back to the beginning of the file
  2455. ; On entry : FILE_PTR + SI points to current location in file
  2456. ; Modifies : ROW, LAST_PAGE
  2457. ;--------------------------------------------------------;
  2458. HOME_FILE    PROC    NEAR
  2459.     CMP    FILE_PTR+2,-1        ;check if start of file is in buffer
  2460.     JNZ    _H_F1            ;nope
  2461.     MOV    AX,FILE_PTR        ;yes, then ptr to start of file 
  2462.     NEG    AX            ; will be = 0 - FILE_PTR
  2463.     MOV    LAST_PAGE,AX        ;save it
  2464.     JMP    SHORT _H_F_RET
  2465.  
  2466. _H_F1:    XOR    DX,DX            ;reset DOS file ptr to start of file
  2467.     XOR    CX,CX
  2468.     MOV    BX,READ_HANDLE
  2469.     MOV    AX,4200H        ;reset file ptr to start of file
  2470.     INT    DOSINT
  2471.     CALL    FIRST_READ        ;go read it
  2472.  
  2473. _H_F_RET:
  2474.     MOV    ROW,0            ;re-zero counters
  2475.     MOV    BP,OFFSET PAGES
  2476.  
  2477.         mov     ax,SCREEN_COLS
  2478.         mov     LAST_COL,ax
  2479.  
  2480.         CLC
  2481.     RET
  2482. HOME_FILE    ENDP
  2483.  
  2484.  
  2485. ;--------------------------------------------------------;
  2486. ; This subroutine moves the display pointer to the end of the file
  2487. ; by successively paging through the buffer
  2488. ;--------------------------------------------------------;
  2489. END_FILE    PROC    NEAR
  2490.     CALL    DN_PG            ;Page down until end of file.
  2491.     JNC    END_FILE
  2492.     CLC
  2493.     RET
  2494. END_FILE    ENDP
  2495.  
  2496. ;--------------------------------------------------------;
  2497. ; This subroutine moves an unwrapped display 16 cols to the left
  2498. ; On entry : VIEW_FLAGS indicates if wrap is in effect
  2499. ; Returns  : modified LAST_COL
  2500. ; Modifies : AX
  2501. ;--------------------------------------------------------;
  2502. LEFT    PROC    NEAR
  2503.     TEST    VIEW_FLAGS,WRAP_BIT
  2504.     JNZ    _LFT_RET
  2505.     MOV    AX,LAST_COL
  2506.         CMP     AX,SCREEN_COLS
  2507.     STC
  2508.     JZ    _LFT_RET
  2509.     SUB    AX,16
  2510.     MOV    LAST_COL,AX
  2511. _LFT_RET:
  2512.     RET
  2513. LEFT    ENDP
  2514.  
  2515. ;--------------------------------------------------------;
  2516. ; This subroutine moves an unwrapped display 16 cols to the right
  2517. ; On entry : VIEW_FLAGS indicates if wrap is in effect
  2518. ; Returns  : modified LAST_COL
  2519. ; Modifies : AX
  2520. ;--------------------------------------------------------;
  2521. RIGHT    PROC    NEAR
  2522.     TEST    VIEW_FLAGS,WRAP_BIT
  2523.     JNZ    _RGT_RET
  2524.     ADD    LAST_COL,16
  2525. _RGT_RET:
  2526.     RET
  2527. RIGHT    ENDP
  2528.  
  2529. ;--------------------------------------------------------;
  2530. ; The following 3 subroutines toggle the VHEX, ASCII and  WRAP flags
  2531. ; when in view mode and then re-start the display at the beginning.
  2532. ;--------------------------------------------------------;
  2533.     ASSUME    DS:DUMMY_SEG
  2534. VHEX    PROC    NEAR
  2535.         CALL    HEXDUMP
  2536.         JMP     SHORT   _VSF_1
  2537.  
  2538. V_ASCII PROC    NEAR
  2539.     CALL    ASCII
  2540.     JMP    SHORT    _VSF_1
  2541.  
  2542. VWRAP    PROC    NEAR
  2543.     CALL    WRAP
  2544. _VSF_1: MOV    SI,THIS_SCREEN
  2545.     CALL    GET_FPTR
  2546.     MOV    RETRN_PTR,AX
  2547.     MOV    RETRN_PTR+2,DX
  2548.     CALL    HOME_FILE
  2549.         MOV     SI,LAST_PAGE
  2550.     CALL    TEST_FPTR
  2551.     JAE    _VSF_RET
  2552. _VSF_2: CALL    DN_PG
  2553.     CALL    TEST_FPTR
  2554.     JB    _VSF_2
  2555.         JE      _VSF_RET
  2556.  
  2557.         CALL    UP_PG
  2558. _VSF_3: INC    ROW
  2559.     CALL    POSITION        ;format and count BH rows
  2560. _VSF_4: CALL    TEST_FPTR
  2561.     JB    _VSF_3
  2562.     JE    _VSF_RET
  2563.         DEC     ROW
  2564. _VSF_RET:       CLC                     ;call for screen update
  2565.     RET
  2566. VWRAP    ENDP
  2567. V_ASCII    ENDP
  2568. VHEX    ENDP
  2569.  
  2570. ;----------------------------------------------------------------;
  2571. ; This subroutine checks to see if end of file has been reached. ;
  2572. ;----------------------------------------------------------------;
  2573. CK_FILE_END    PROC    NEAR
  2574.     CMP    SI,FILE_END
  2575.     JB    _CK_F1
  2576.     CMP    FILE_END,OFFSET FILE_BUFF+(READ_SIZE * 2)
  2577.     JC    _CK_F2
  2578.  
  2579. _CK_F1:    CLC
  2580. _CK_F2:    RET
  2581. CK_FILE_END    ENDP
  2582.  
  2583. ;----------------------------------------------------------------;
  2584. ; This subroutine "parses" CX lines of text starting at ROW
  2585. ; On entry :    BP points to a page size entry in PAGES
  2586. ; Modifies : AX, BX, CX, DX, SI, DI
  2587. ;----------------------------------------------------------------;
  2588.     ASSUME    DS:DUMMY_SEG, ES:_TEXT
  2589. POSITION      PROC    NEAR
  2590.     MOV    SI,LAST_PAGE        ;Get top of current page.
  2591.     XOR    AH,AH            ;clear word-wrap/cr flag register
  2592.     XOR    CH,CH
  2593.     MOV    CL,ROW            ;Get row offset into page.
  2594.     JCXZ    _PO1            ;skip if it is row zero
  2595.     AND    VIEW_FLAGS,NOT DISPLAY_BIT    ; skip display.
  2596.     CALL    LINES            ;format and count BH rows
  2597.  
  2598. _PO1:    PUSH    AX            ;save AH cr/wrap flag
  2599.     MOV    THIS_SCREEN,SI        ;save current location
  2600.     CALL    PUT_WHERE
  2601.     POP    AX
  2602.     RET
  2603. POSITION      ENDP
  2604.  
  2605.  
  2606.  
  2607. ;----------------------------------------------------------------;
  2608. ; This subroutine formats the text into lines.  A line is marked ;
  2609. ; by a line feed, a lone carriage return or, 
  2610. ; if word wrap is in effect, by reaching the last column (80). 
  2611. ; On entry :    DS:SI points to beginning of text to display
  2612. ;        BP points to a page size entry in PAGES
  2613. ;        CX contains the number of rows to display
  2614. ;        ES:DI points to position in display buffer
  2615. ; Modifies : AX, BX, CX, DX, SI, DI
  2616. ;        AH is used as a flag register for testing end of line cases
  2617. ;        BL is used as a register copy of VIEW_FLAGS
  2618. ;        BH is used as a register copy of STAR_MASK
  2619. ;----------------------------------------------------------------;
  2620.         ASSUME  DS:DUMMY_SEG,ES:_TEXT
  2621. LINES    PROC    NEAR
  2622.     PUSH    ES            ;save seg register
  2623.  
  2624.     MOV    DX,STATUS_REG        ;Retrieve status register.
  2625.     MOV    BL,VIEW_FLAGS
  2626.     MOV    BH,STAR_MASK
  2627.  
  2628.     MOV    ES,VIDEO_SEG        ;Point to screen segment.
  2629.     ASSUME    ES:nothing
  2630.  
  2631. _LN0:    PUSH    CX
  2632. _LN1:   MOV     CX,LAST_COL             ;80 columns.
  2633.  
  2634. _LN2:   CMP     SI,FILE_END             ;If end of file, pad with spaces.
  2635.     JB    _LN3
  2636.     CALL    FORWARD            ;read next block of file
  2637.         JNC     _LN3
  2638.         jmp     _LN15
  2639.  
  2640. _LN3:   test    bl,HEX_BIT              ;HEXDUMP mode?
  2641.         jz      _LN35                   ;no
  2642.         jmp     LINES_HEX               ;hexdump of 1 complete line
  2643.  
  2644. _LN35:  LODS    FILE_BUFF               ;Get a byte.
  2645.     AND    AL,BH            ;Strip high bit for WordStar?
  2646.     CMP    AL,cr            ;Carriage return?
  2647.     JA    _LN8            ; printable char?
  2648.     JNZ    _LN4            ;no, go check for tab or lf
  2649.     OR    AH,2            ;set flag to mark cr
  2650.     JMP    _LN2            ;get next char
  2651.  
  2652. _LN4:    CMP    AL,lf            ; linefeed?
  2653.     JNZ    _LN8            ; no, go display char
  2654.     TEST    AH,1            ;are we following a word wrap?
  2655.     MOV    AH,0            ;clear flags
  2656.     JNZ    _LN2            ;if just wrapped, ignore lf
  2657. _LN5:   TEST    BL,ASCII_BIT            ;stripping non-ascii ?
  2658.     JZ    _LN7            ;no
  2659. _LN6:   push    ax
  2660.         mov     ax,SCREEN_COLS
  2661.         sub     ax,4                    ;have we had more than five displayed?
  2662.         mov     TEMP,ax
  2663.         pop     ax
  2664.         cmp     cx,TEMP
  2665.         jae     _LN65                   ;go point back to start of line
  2666.         jmp     _LN7
  2667.  
  2668. _LN65:  add     TEMP,4                  ;TEMP = SCREEN_COLS
  2669.         sub     TEMP,cx                 ;TEMP = # of characters written so far
  2670.         shl     TEMP,1                  ;double to account for attribute
  2671.         sub     di,TEMP                 ;bring DI back to start of line
  2672.         jmp     _LN1
  2673.  
  2674. _LN7:   CALL    PAD_TO_EOL              ;If yes, pad balance of line.
  2675.     JMP    SHORT _LN15
  2676.  
  2677. _LN8:    CMP    AH,2        ;was there a CR without a lf or a wrap?
  2678.     MOV    AH,0            ;clear flag
  2679.     JNZ    _LN9            ;no CR, go display this char
  2680.     DEC    SI            ;back up one character
  2681.     JMP    _LN5            ;pad to EOL
  2682.  
  2683. _LN9:    JCXZ    _LN2            ;bypass if 80 chars already written
  2684.     CMP    AL,tab            ;is it a tab?
  2685.     JNZ    _LN10            ;no
  2686.     MOV    AL,space        ;expand to spaces
  2687.     TEST    BL,ASCII_BIT        ;stripping non-ascii ?
  2688.     JNZ    _LN12            ;yes - just display 1 space
  2689.     CALL    DO_TAB            ;write out spaces
  2690.     JCXZ    _LN14            ;all done ?
  2691.     JMP    _LN2            ;still more
  2692.  
  2693. _LN10:  CMP     CX,SCREEN_COLS          ;horizontal scroll in effect?
  2694.     JA    _LN13            ;yes - skip chars at left edge
  2695.  
  2696. IFDEF BLANK_BIT
  2697.     TEST    BL,ASCII_BIT+BLANK_BIT        ;stripping non-ascii ?
  2698.     JZ    _LN12            ;no - go display char
  2699.     CMP    AL,space        ;control character?
  2700.     JGE    _LN12            ;no - go display char
  2701.     TEST    BL,ASCII_BIT        ;stripping non-ascii ?
  2702.     JNZ    _LN6            ;yes, go write EOL
  2703.     MOV    AL,space        ;blank non-ascii char
  2704. ELSE
  2705.     TEST    BL,ASCII_BIT        ;stripping non-ascii ?
  2706.     JZ    _LN12            ;no - go display char
  2707.     CMP    AL,space        ;control character?
  2708.     JL    _LN6            ;yes, go write EOL
  2709. ENDIF
  2710.  
  2711. _LN12:    TEST    BL,DISPLAY_BIT        ;display ?
  2712.     JZ    _LN13            ;return - just counting lines
  2713.  
  2714.     CALL    PUT_BYTE
  2715.     INC    DI            ;Bump pointer past attribute.
  2716.  
  2717. _LN13:  LOOP    GetNextByte             ;Get next byte.
  2718.  
  2719. _LN14:    TEST    BL,WRAP_BIT        ;is word wrap on?
  2720.         JZ      GetNextByte             ;no - keep looking for end of line
  2721.  
  2722.     MOV    AH,1            ;set word-wrap flag
  2723.  
  2724. _LN15:    POP    CX            ;get back line counter
  2725.     DEC    CX            ;this line done- dec line counter
  2726.     JZ    _LN17            ;all done
  2727.  
  2728.     JMP    _LN0
  2729.  
  2730. _LN17:    POP    ES            ;restore segment register
  2731.     RET
  2732. LINES        ENDP
  2733.  
  2734. PAD_TO_EOL    PROC    NEAR
  2735.         CMP     CX,SCREEN_COLS          ;horizontal scroll?
  2736.     JBE    PAD_SPACES        ;yes, we only need 80 spaces
  2737.         MOV     CX,SCREEN_COLS
  2738.  
  2739. PAD_SPACES    PROC    NEAR
  2740.     MOV    AX,space        ;clear flag, display space
  2741.     JCXZ    _PSP_RET
  2742.     MOV    DX,STATUS_REG        ;Retrieve status register.
  2743.     TEST    BL,DISPLAY_BIT        ;Are we to write it to screen?
  2744.     JZ    _PSP_RET        ;If no, return.
  2745.  
  2746. _PSP_1:    CALL    PUT_BYTE
  2747.     INC    DI            ;Bump pointer past attribute.
  2748.     LOOP    _PSP_1
  2749.  
  2750. _PSP_RET:
  2751.     RET
  2752.  
  2753. GetNextByte:
  2754.         jmp     _LN2
  2755.  
  2756. PAD_SPACES      ENDP
  2757. PAD_TO_EOL    ENDP
  2758.  
  2759.  
  2760. ;----------------------------------------------------------------;
  2761. ; This set of subroutines formats the text into lines for the    ;
  2762. ; Hexdump mode.                                                  ;
  2763. ; On entry :    DS:SI points to beginning of text to display     ;
  2764. ;               ES:DI points to position in display buffer       ;
  2765. ; Modifies : AX, CX, SI, DI                                      ;
  2766. ;               BL is used as a register copy of VIEW_FLAGS      ;
  2767. ;----------------------------------------------------------------;
  2768.  
  2769. HEX_BUF DB      16 DUP(?)               ;temporary storage of line to display
  2770. SAVECX  DW      ?                       ;temporary storage of CX
  2771.  
  2772.         ASSUME  DS:DUMMY_SEG,ES:nothing
  2773. LINES_HEX:
  2774.  
  2775.         test    BL,DISPLAY_BIT          ;display ?
  2776.         jnz     _HEX00                  ; yes
  2777.         add     si,16                   ;just counting lines
  2778.         jmp     _LN15                   ;end of line
  2779.  
  2780. _HEX00: push    bp                      ;save variable
  2781.         mov     bp, OFFSET HEX_BUF      ;BP points to temporary table
  2782.         mov     TEMP,dx                 ;save dx
  2783.  
  2784.         call    DISP_HEX_OFFSET         ;display file offset for this line
  2785.  
  2786.         mov     cx,16                   ;16 characters per line
  2787.  
  2788. _HEX0:  cmp     si,FILE_END
  2789.         jb      _HEX1
  2790.         mov     SAVECX,cx               ;save CX
  2791.         mov     cx,SCREEN_COLS          ;if FORWARD fails, space out 80 chars
  2792.         call    FORWARD
  2793.         mov     cx,SAVECX
  2794.         jc      _HEX3                   ;EOF, display what we have (<16 chars)
  2795.  
  2796. _HEX1:  lods    FILE_BUFF               ;Get a byte.
  2797.         mov     cs:[bp],al              ;store in table
  2798.         inc     bp
  2799.         loop    _HEX0                   ;loop 16 times
  2800.         mov     SAVECX,0                ;means display 16 chars from table
  2801.         jmp     _HEX4
  2802.  
  2803. _HEX3:  mov     dx,SCREEN_COLS          ;fixup DI for EOF case
  2804.         shl     dx,1
  2805.         sub     di,dx
  2806.         mov     SAVECX,cx               ;cx is < 16 meaning display 16-cx chars
  2807.  
  2808. _HEX4:  mov     bp, OFFSET HEX_BUF      ;BP -> table
  2809.         mov     cx,16                   ;loop counter
  2810.         mov     al,' '                  ;space character for PRINT_CHAR routine
  2811.  
  2812. _HEX5:  mov     dh,cs:[bp]              ;get byte in table
  2813.         cmp     cx,SAVECX               ;EOF case?
  2814.         jg      _HEX6                   ; no
  2815.         call    PRINT_CHAR              ;print 2 spaces instead of HEX digits
  2816.         call    PRINT_CHAR
  2817.         jmp     short _HEX7
  2818. _HEX6:  call    HEX8OUT                 ;print 2 hex digits
  2819. _HEX7:  call    PRINT_CHAR              ;print a space
  2820.         inc     bp
  2821.         loop    _HEX5
  2822.  
  2823.         mov     cx,2
  2824.         call    PAD_SPACES              ;print 2 spaces
  2825.  
  2826.         mov     bp, OFFSET HEX_BUF      ;BP -> table
  2827.         mov     cx,16                   ;loop counter
  2828. _HEX8:  mov     al,cs:[bp]
  2829.  
  2830.         cmp     cx,SAVECX               ;EOF case?
  2831.         jg      _HEX9                   ; no
  2832.         MOV     AL,' '                  ;print a space instead
  2833.         call    PRINT_CHAR
  2834.         jmp     short _HEX10
  2835. _HEX9:
  2836. IFDEF BLANK_BIT
  2837.         TEST    BL,BLANK_BIT            ;stripping non-ascii ?
  2838.         JZ      _HEX10                  ;no - go display char
  2839.     CMP    AL,space        ;control character?
  2840.         JGE     _HEX10                  ;no - go display char
  2841.         MOV     AL,'.'                  ;blank non-ascii char
  2842. ENDIF
  2843.  
  2844. _HEX10: call    PRINT_CHAR              ;print IBM ASCII of character
  2845.         inc     bp
  2846.         loop    _HEX8
  2847.  
  2848.         mov     cx,2
  2849.         call    PAD_SPACES              ;print 2 spaces
  2850.  
  2851.         mov     dx,TEMP                 ;restore variables
  2852.         pop     bp
  2853.  
  2854.         mov     cx,SCREEN_COLS          ;if >80 screen, fill-out with spaces
  2855.         sub     cx,80
  2856.         jbe     _HEX11
  2857.         call    PAD_SPACES
  2858. _HEX11: jmp     _LN15                   ;end of line
  2859.  
  2860.  
  2861. ;Routine to display the file offset of the current line
  2862. DISP_HEX_OFFSET PROC    NEAR
  2863.         call    GET_FPTR                ;get absolute file pointer in DX:AX
  2864.  
  2865.         call    HEX8OUT                 ;print high word
  2866.         xchg    dl,dh
  2867.         call    HEX8OUT
  2868.  
  2869.         push    ax                      ;save low word of file offset
  2870.  
  2871.         mov     al,' '
  2872.         call    PRINT_CHAR
  2873.  
  2874.         pop     dx                      ;restore low word of file offset
  2875.  
  2876.         call    HEX8OUT                 ;print low word
  2877.         xchg    dl,dh
  2878.         call    HEX8OUT
  2879.  
  2880.         mov     al,':'
  2881.         call    PRINT_CHAR
  2882.         mov     al,' '
  2883.         call    PRINT_CHAR
  2884. DISP_HEX_OFFSET ENDP
  2885.  
  2886.  
  2887. ;print the character in AL
  2888. PRINT_CHAR      PROC    NEAR
  2889.         push    dx                      ;save register
  2890.         mov     dx,TEMP                 ;CGA Register or 0 for EGA/VGA
  2891.         call    PUT_BYTE
  2892.         pop     dx
  2893.         inc     di                      ;Bump pointer past attribute.
  2894.         ret
  2895. PRINT_CHAR      ENDP
  2896.  
  2897.  
  2898. ;Routine for converting value in DH into ASCII Hexadecimal and printing it.
  2899. HEX8OUT PROC    NEAR
  2900.         push    cx                      ;preserve registers
  2901.         push    ax
  2902.         mov     cx,2                    ;loop counter
  2903.  
  2904. H8O1:   push    cx
  2905.         mov     cl,4
  2906.         rol     dh,cl                   ;do high nibble first
  2907.  
  2908.         mov     al,dh
  2909.         and     al,0fh
  2910.         daa                             ;add 6 if 0ah - 0fh
  2911.         add     al,0f0h                 ;sets carry if 0ah - 0fh
  2912.         adc     al,40h                  ;make ASCII
  2913.         call    PRINT_CHAR
  2914.  
  2915.         pop     cx
  2916.         loop    H8O1
  2917.  
  2918.         pop     ax
  2919.         pop     cx
  2920.         ret
  2921. HEX8OUT ENDP
  2922.  
  2923.  
  2924. ;--------------------------------------------------------;
  2925. ; This subroutine expands tabs in VIEW
  2926. ; On entry : CX = columns remaining to display
  2927. ; Returns  : updated CX 
  2928. ; Modifies : AX, CX
  2929. ;--------------------------------------------------------;
  2930.     ASSUME    DS:DUMMY_SEG,ES:nothing
  2931. DO_TAB    PROC    NEAR
  2932.     JCXZ    _D_T2
  2933.  
  2934.         mov     ax,SCREEN_COLS
  2935.         and     ax,7                    ;ax = SCREEN_COLS % 8 
  2936.         add     ax,cx                   ; (makes cx evenly divisible by 8)
  2937.  
  2938.         DEC     AX                      ;Adjust column counter.
  2939.         AND     AX,7                    ;Get bottom three bits.
  2940.     INC    AX            ;Adjust.
  2941.         CMP     CX,SCREEN_COLS
  2942.         JA      _D_T1
  2943.     PUSH    CX
  2944.     PUSH    AX
  2945.     XCHG    AX,CX
  2946.     CALL    PAD_SPACES        ;Move to next tab position.
  2947.     POP    AX
  2948.     POP    CX
  2949. _D_T1:    SUB    CX,AX            ;Adjust counter.
  2950. _D_T2:    RET
  2951. DO_TAB    ENDP
  2952.  
  2953.  
  2954. ;-------------------------------------------------------------------;
  2955. ; This subroutine reads the next 1/2 buff
  2956. ; Saves :AX, BX, CX, DX, DI unless end of file encountered
  2957. ;--------------------------------------------------------;
  2958.     ASSUME    DS:DUMMY_SEG,ES:nothing
  2959. FORWARD    PROC    NEAR
  2960.     CMP    FILE_END,OFFSET FILE_BUFF+ (READ_SIZE * 2)
  2961.     JNB    _FWD1
  2962.         CALL    PAD_TO_EOL
  2963.     STC
  2964.     RET
  2965.  
  2966. _FWD1:    PUSH    ES
  2967.     PUSH    DI            ;read next block of file
  2968.     PUSH    DX            ; save pointers
  2969.     PUSH    CX
  2970.     PUSH    BX
  2971.     PUSH    AX
  2972.     PUSH    CS
  2973.     POP    ES
  2974.     ASSUME    DS:DUMMY_SEG,ES:_TEXT
  2975.  
  2976.     SUB    LAST_PAGE,READ_SIZE    ;Adjust current page offset.
  2977.     XOR    CX,CX            ;Move file pointer
  2978.     MOV    DX,READ_SIZE        ; forward 1/2 buffer
  2979.         CALL    MOVE_POINTER
  2980.         CALL    NEXT_READ
  2981.     CLC
  2982.     POP    AX
  2983.     POP    BX            ;Restore pointers.
  2984.     POP    CX
  2985.     POP    DX
  2986.     POP    DI
  2987.     POP    ES
  2988.     RET
  2989. FORWARD        ENDP
  2990.  
  2991.  
  2992. ;--------------------------------------------------------;
  2993. ; This subroutine starts the first buffer read of a file
  2994. ;--------------------------------------------------------;
  2995. FIRST_READ    PROC    NEAR
  2996.     MOV    LAST_PAGE,OFFSET FILE_BUFF+READ_SIZE
  2997.  
  2998. ;--------------------------------------------------------;
  2999. ; This subroutine moves the second half of the buffer to the
  3000. ; the first half and then reads in a half buffer of info into the
  3001. ; second half
  3002. ; On entry : no known parameters
  3003. ; Returns  : nothing
  3004. ; Modifies : everything
  3005. ;--------------------------------------------------------;
  3006. NEXT_READ    PROC    NEAR
  3007.     MOV    SI,OFFSET FILE_BUFF+READ_SIZE
  3008.     MOV    DI,OFFSET FILE_BUFF    ;Move second half of buffer
  3009.         CALL    MOVE_BUFFER             ; to first half and read 1/2 buffer
  3010.     MOV    CX,-1            ;Move file pointer back.
  3011.     NEG    DX
  3012.     CALL    MOVE_POINTER
  3013.     SUB    AX,OFFSET FILE_BUFF + READ_SIZE
  3014.     CALL    SAVE_FPTR
  3015.     RET
  3016. NEXT_READ    ENDP
  3017. FIRST_READ    ENDP
  3018.  
  3019. ;--------------------------------------------------------;
  3020. ; This subroutine goes back and reads the previous 1/2 buff
  3021. ;--------------------------------------------------------;
  3022. BACKWARD    PROC    NEAR
  3023.     ADD    LAST_PAGE,READ_SIZE    ;Adjust current page offset.
  3024.     MOV    CX,-1            ;Move pointer back full buffer
  3025.     MOV    DX,- (READ_SIZE * 2)
  3026.     CALL    MOVE_POINTER
  3027.     SUB    AX,OFFSET FILE_BUFF
  3028.     MOV    SI,OFFSET FILE_BUFF+READ_SIZE; buffer to second
  3029.     CALL    SAVE_FPTR
  3030.     MOV    DI,SI
  3031.     MOV    SI,OFFSET FILE_BUFF    ;Move first half of
  3032.     CALL    MOVE_BUFFER
  3033.     RET
  3034. BACKWARD    ENDP
  3035.  
  3036. ;--------------------------------------------------------;
  3037. ; This subroutine moves 1/2 buffer from [SI] to [DI]
  3038. ; and then reads in a half buffer into the original [SI] position
  3039. ; On entry : SI, DI pointers
  3040. ; Returns  : DX = bytes read
  3041. ; Modifies : everything
  3042. ;--------------------------------------------------------;
  3043.     ASSUME    DS:DUMMY_SEG,ES:_TEXT
  3044. MOVE_BUFFER    PROC    NEAR
  3045.     MOV    DX,SI            ;Save pointer.
  3046.     MOV    CX,READ_SIZE / 2    ;Move (1/4 buffer) words=1/2 buffer
  3047.     PUSH    ES
  3048.     MOV    ES,MEM_BUF_SEG
  3049.  
  3050.     ASSUME    ES:DUMMY_SEG
  3051.     REP    MOVSW
  3052.     MOV    BX,READ_HANDLE
  3053.     MOV    CX,READ_SIZE        ;Read 1/2 buffer.
  3054.     MOV    AH,3FH            ;Read file into DS:DX
  3055.     INT    DOSINT            ;return AX= # bytes read
  3056.     POP    ES
  3057.  
  3058.     ASSUME    DS:DUMMY_SEG,ES:_TEXT
  3059.     MOV    SI,DX            ;get back pointer
  3060.     MOV    DX,AX            ;save number of bytes read
  3061.     ADD    AX,OFFSET FILE_BUFF + READ_SIZE
  3062.     MOV    FILE_END,AX        ;Store end of buffer offset.
  3063.     RET
  3064. MOVE_BUFFER    ENDP
  3065.  
  3066. ;--------------------------------------------------------;
  3067. ; This subroutine call DOS function to do a relative move of the file pointer
  3068. ; On entry : no known parameters
  3069. ; Returns  : DX:AX = new pointer location
  3070. ; Modifies : everything
  3071. ;--------------------------------------------------------;
  3072.     ASSUME    DS:DUMMY_SEG,ES:_TEXT
  3073. MOVE_POINTER    PROC    NEAR
  3074.     MOV    BX,READ_HANDLE
  3075.     MOV    AX,4201H        ;Move file pointer.
  3076.     INT    DOSINT
  3077.     RET
  3078. MOVE_POINTER    ENDP
  3079.  
  3080.  
  3081. ;--------------------------------------------------------;
  3082. ; This subroutine saves the current absolute file pointer location
  3083. ; in a form such that SI + FILE_PTR = absolute location in file of
  3084. ; the first byte displayed on the screen
  3085. ; On entry : DX:AX = (DOS pointer) - OFFSET FILE_BUFF of last read
  3086. ; Returns  : nothing
  3087. ; Modifies : DX
  3088. ;--------------------------------------------------------;
  3089.     ASSUME    DS:DUMMY_SEG,ES:_TEXT
  3090. SAVE_FPTR    PROC    NEAR
  3091.     JNC    _SFP1
  3092.     DEC    DX
  3093. _SFP1:    MOV    FILE_PTR,AX        ;save pointer low word
  3094.     MOV    FILE_PTR+2,DX        ;and high
  3095. ;    RET            ;let this run on and display pointer
  3096. SAVE_FPTR    ENDP
  3097.  
  3098.  
  3099. ;-------------------------------------------------------------------;
  3100. ; Display on VIEW status line the current position in file
  3101. ; On entry : SI contains current position in buffer
  3102. ; Returns  : nothing
  3103. ; Modifies : AX, BX, CX, DX, DI
  3104. ; Preserves: DS, SI, BP 
  3105. ;-------------------------------------------------------------------;
  3106. PUT_WHERE    PROC    NEAR
  3107.     ASSUME    DS:DUMMY_SEG,ES:_TEXT
  3108.     PUSH    SI
  3109.     PUSH    DS
  3110.     MOV    AX,FILE_PTR
  3111.     MOV    DX,FILE_PTR+2
  3112.     PUSH    CS
  3113.     POP    DS
  3114.     ASSUME    DS:_TEXT
  3115.     ADD    AX,SI
  3116.     JNC    _P_W1
  3117.     INC    DX
  3118. _P_W1:    MOV    DI,OFFSET CMD_LINE
  3119.     PUSH    DI
  3120.     MOV    CX,WHERE_LEN
  3121.     CALL    FORMAT
  3122.     POP    SI
  3123.     MOV    CX,WHERE_LEN
  3124.     MOV    DI,2 * WHERE_LOC
  3125.     CALL    PUT_CX_CHARS
  3126.     MOV    SI,OFFSET OPTIONS
  3127.  
  3128.         push    ax
  3129.         mov     ax,SCREEN_COLS          ;MOV DI,2 * (78 - OPTIONS_LEN)
  3130.         dec     ax
  3131.         dec     ax
  3132.         sub     ax,OPTIONS_LEN
  3133.         shl     ax,1
  3134.         mov     di,ax
  3135.         pop     ax
  3136.  
  3137.         MOV     CX,OPTIONS_LEN
  3138.     MOV    BL,VIEW_FLAGS        ;get option flags
  3139.     ROL    BL,1            ;star option always displayed
  3140. _P_W2:    LODSB                ;get option mneumonic
  3141.     RCR    BL,1            ;rotate through carry
  3142.     JC    _P_W3            ;is option set?
  3143.     OR    AL,20H            ;no - display lower case
  3144. _P_W3:    CALL    PUT_CHAR        ;display it
  3145.     LOOP    _P_W2            ;do some more
  3146.     POP    DS
  3147.     POP    SI
  3148.     RET
  3149. PUT_WHERE    ENDP
  3150.  
  3151. ;--------------------------------------------------------;
  3152. ; This subroutine gets the current absolute file pointer
  3153. ; location of the first byte displayed on the screen
  3154. ; Returns  : DX:AX = FILE_PTR + SI
  3155. ;--------------------------------------------------------;
  3156.         ASSUME  DS:DUMMY_SEG,ES:_TEXT
  3157. GET_FPTR       PROC    NEAR
  3158. _GFP1:    MOV    AX,FILE_PTR        ;get pointer low word
  3159.     MOV    DX,FILE_PTR+2        ;and high
  3160.     ADD    AX,SI
  3161.     JNC    _GFP_RET
  3162.     INC    DX
  3163. _GFP_RET:      RET            ;let this run on and display pointer
  3164. GET_FPTR       ENDP
  3165.  
  3166.  
  3167. TEST_FPTR    PROC    NEAR
  3168.     CALL    GET_FPTR
  3169.     CMP    DX,RETRN_PTR+2
  3170.     JNE    _TF_RET
  3171.     CMP    AX,RETRN_PTR
  3172. _TF_RET:    RET
  3173. TEST_FPTR    ENDP
  3174.  
  3175. ;----------------------------------------------------------------------;
  3176. ; This subroutine displays the highlighted file for viewing. ;
  3177. ; On entry : no known parameters
  3178. ; Returns  : nothing
  3179. ; Modifies : everything
  3180. ;----------------------------------------------------------------------;
  3181.     ASSUME    DS:_TEXT,ES:_TEXT
  3182. VIEW_DIR    PROC    NEAR
  3183.     PUSH    SI            ;save pointer
  3184.     MOV    DI,OFFSET TMP_BUFF    ;point to storage
  3185.     MOV    SI,DI            ;and save a copy
  3186.     MOV    AL,space        ;use spaces
  3187.     MOV    CX,8            ;to clear TMP_BUFF
  3188.     REP    STOSB
  3189.     MOV    DI,FILE_NAME        ;get dir/filename pointed to
  3190.     MOV    AX,[DI]
  3191.     CMP    AX,'..'            ;is it parent?
  3192.     JNZ    _V_D2            ;no - go ahead
  3193.  
  3194.     DEC    DI            ;save currently displayed dir name
  3195.     DEC    DI
  3196.     PUSH    DI
  3197.     MOV    CX,DI
  3198.     SUB    CX,OFFSET SOURCE -1
  3199.     MOV    AL,'\'
  3200.  
  3201. IFDEF    SAG
  3202.     CMP    SWITCH,"/"        ;do we really want "/" instead?
  3203.     JE    _V_D1            ;no
  3204.     MOV    AL,'/'            ;yes
  3205. _V_D1:
  3206. ENDIF
  3207.     STD
  3208.     REPNZ    SCASB            ;find beginning
  3209.     INC    DI
  3210.     CLD
  3211.     POP    CX
  3212.     SUB    CX,DI
  3213.     XCHG    SI,DI            ;now DI points to TMP_BUFF
  3214.     INC    SI
  3215.     REP    MOVSB            ;save current dir
  3216.  
  3217. _V_D2:    POP    SI            ;get back pointer to cur dir
  3218.     CALL    NEW_WORK_DIR        ; and change directory
  3219.  
  3220. _V_D3:    CALL    GET_NAME        ;get SI pointer to current name
  3221.     INC    SI            ;point to first char
  3222.     MOV    CX,8            ;limit search to filename field
  3223.     MOV    DI,OFFSET TMP_BUFF
  3224.     PUSH    DI
  3225.     REPZ    CMPSB            ;string compare
  3226.     POP    DI
  3227.     JZ    _V_D_RET        ;found it - all done
  3228.     MOV    BL,[DI]            ;check first char of dir name
  3229.     CMP    BL,space        ;is there anything but spaces?
  3230.     JZ    _V_D_RET        ;no, so all done
  3231.     CALL    SEARCH
  3232.     JNC    _V_D3            ;carry if SEARCH failed
  3233. _V_D_RET:
  3234.     RET
  3235. VIEW_DIR    ENDP
  3236.  
  3237. SUBTTL Subroutines for changing working or destination directories
  3238. page
  3239.  
  3240. ;-----------------------------------------
  3241. ; Change the current drive and default directory.
  3242. ; On entry : DS:SI = ASCIIZ path name including optional drive
  3243. ; Returns  : AX = error codes if carry set
  3244. ;-----------------------------------------
  3245.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  3246. CHANGE_PATH    PROC    NEAR
  3247.     CMP    BYTE PTR [SI],0    ;is there anything at all
  3248.     JZ    _C_D_DX
  3249.     CMP    WORD PTR [SI+1],':'    ;is there only a drive change?
  3250.     JZ    _C_D_D2        ;yes
  3251.  
  3252. _C_D_D1:
  3253.     MOV    DX,SI            ; DS:DX =ASCIIZ path name, may include drive
  3254.     MOV    AH,3BH        ; Change the default directory.
  3255.     INT    DOSINT  
  3256.     JC    CD_ERROR    ;error encountered, bypass drive change
  3257.  
  3258. _C_D_D2:
  3259.     MOV    DX,[SI]
  3260.     CMP    DH,':'        ;is there a drive specification?
  3261.     JNZ    _C_D_D3        ;no - go exit
  3262.  
  3263.     AND    DL,1FH
  3264.     DEC    DL        ;convert drive letter to 0,1..
  3265.     MOV    AH,0EH        ; Change default drive to DL,  0=A, 1=B
  3266.     INT    DOSINT        ;returns number of drives in AL
  3267.     MOV    AH,19H        ;get default drive into AL, 0=A, 1=B
  3268.     INT    DOSINT        ;to test and
  3269.     CMP    AL,DL        ;see if it worked
  3270.     JNZ    CD_ERROR    ;failed drive change
  3271. _C_D_D3:
  3272.     CLC
  3273. _C_D_DX:
  3274.     RET
  3275. CHANGE_PATH    ENDP
  3276.  
  3277. ;--------------------------------------------------------;
  3278. ; display "invalid directory" error message
  3279. ; On entry : no known parameters
  3280. ; Returns  : carry flag set
  3281. ; Modifies : AX, CX, DX at least
  3282. ;--------------------------------------------------------;
  3283. CD_ERROR    PROC    NEAR
  3284.     MOV    SI,OFFSET INVALID    ;error message.
  3285.     MOV    AH,INTENSE        ;get display attribute
  3286.     OR    AH,80H            ;make it blink
  3287.     MOV    DI,PROMPT_LOC
  3288.     CALL    PUT_STRATT
  3289.     CALL    DELAY
  3290.     STC
  3291.     RET
  3292. CD_ERROR    ENDP
  3293.  
  3294. ;---------------------------------------------------------;
  3295. ; This subroutine gets the current directory, precedes it with
  3296. ; a \, and saves it at [DI]
  3297. ; On entry : DI points to destination
  3298. ; Returns  : nothing
  3299. ; Modifies : AX, DX, DI, SI
  3300. ;---------------------------------------------------------;
  3301. GET_PATH    PROC    NEAR
  3302.     MOV    AH,19H        ;get default drive into AL, 0=A, 1=B
  3303.     INT    DOSINT
  3304.     ADD    AL,"A"            ;Convert to ASCII.
  3305.     PUSH    AX
  3306.     STOSB
  3307.     MOV    AX,"\:"            ;Add colon and slash.
  3308.     STOSW
  3309.     MOV    SI,DI            ;now pointing to work_dir
  3310.     XOR    DL,DL
  3311.     MOV    AH,47H            ;Retrieve default directory.
  3312.     INT    DOSINT
  3313.  
  3314. IFDEF    SAG
  3315.     CMP    SWITCH,'/'        ;Should we translate \ to / ?
  3316.     JE    _G_D4            ;NO
  3317.     PUSH    DI            ;save on stack
  3318.     DEC    DI            ;point to first slash after volume
  3319. _G_D1:    CMP    BYTE PTR [DI],0        ;End of String?
  3320.     JE    _G_D3            ;yes
  3321.     CMP    BYTE PTR [DI],'\'    ;backsash?
  3322.     JNE    _G_D2            ;no
  3323.     MOV    BYTE PTR [DI],'/'    ;turn it into a /
  3324. _G_D2:    INC    DI            ;loop
  3325.     JMP    SHORT _G_D1
  3326. _G_D3:    POP    DI
  3327. _G_D4:
  3328. ENDIF
  3329.  
  3330.     POP    AX
  3331.     CALL    DISK_FREE        ; get disk free space
  3332.     RET
  3333. GET_PATH    ENDP
  3334.  
  3335. ;-----------------------------------------------------------;
  3336. ; Subroutine prompts for user entry for changing directories
  3337. ;  and then parses whatever the user enters
  3338. ; On entry :    SI points to a prompt message
  3339. ; Returns  :    SI pointing to new dir, AX=':' if only drive specified
  3340. ;        carry flag set if not successful
  3341. ; Modifies : assume everything
  3342. ;-----------------------------------------------------------;
  3343. ASK4PATH    PROC    NEAR
  3344.     MOV    DI,PROMPT_LOC
  3345.     CALL    PUT_STRING
  3346.     CALL    TO_DEST            ;Ask user for destination.
  3347.     JC    _A4P_RET        ;If Esc pressed, exit.
  3348.     XOR    AL,AL
  3349.     STOSB                ;end string with null
  3350.     MOV    SI,OFFSET ENTRY        ;get first 2nd and 3rd bytes 
  3351.     MOV    AX,[SI+1]
  3352.     CMP    AX,':'            ;is this the end?
  3353.     CLC
  3354.     JNZ    _A4P_RET        ;If no, we're done
  3355.     MOV    WORD PTR [SI+2],'.'    ;add a '.',0 to string to fool dos
  3356. _A4P_RET:
  3357.     RET
  3358. ASK4PATH    ENDP
  3359.  
  3360. ;---------------------------------------------------------------;
  3361. ; Subroutine to prompt for and then change the working directory
  3362. ; On entry : no known parameters
  3363. ; Returns  : nothing
  3364. ; Modifies : assume everything
  3365. ;--------------------------------------------------------;
  3366. CD_WORK    PROC    NEAR
  3367.     MOV    SI,OFFSET CD_MSG    ;Display prompt
  3368.     CALL    ASK4PATH
  3369.     JC    _CD_W_RET
  3370.     MOV    BL,WORK_PATH        ;get old work drive:
  3371.     MOV    AX,[SI]            ;check for drive spec
  3372.     CMP    AH,':'
  3373.     JNZ    _CD_W1            ;no drive, change to old work
  3374.     AND    AL,5FH            ;capitalize drive request
  3375.     CMP    AL,BL            ;is new drive=old work drive?
  3376.     JNZ    NEW_WORK_DIR        ;no - just get new path
  3377.                     ;drive has not changed, but
  3378.     CMP    AL,DEST_PATH        ;is drive same as current dest?
  3379.     JNE    NEW_WORK_DIR        ;no, different drives
  3380.                     ;make sure we start from old work dir:
  3381. _CD_W1:    PUSH    SI            ;save the new path for work-dir
  3382.     MOV    SI,OFFSET WORK_PATH    ;get back last work path and disk
  3383.     CALL    CHANGE_PATH        ;restore old cur-dir on old work disk
  3384.     POP    SI            ;get back new path and set new work dir
  3385.  
  3386. ;---------------------------------------------------;
  3387. ; routine to display a new working directory
  3388. ; On entry : SI points to new dir 
  3389. ; Returns  : nothing
  3390. ; Modifies : assume everything
  3391. ;---------------------------------------------------;
  3392. NEW_WORK_DIR    PROC    NEAR
  3393.         CALL    CHANGE_PATH             ;And change drive.
  3394.         CALL    READ_DIR                ; read dir and restart program
  3395. _CD_W_RET:
  3396.     RET
  3397. NEW_WORK_DIR    ENDP
  3398. CD_WORK    ENDP
  3399.  
  3400. ;--------------------------------------------------------;
  3401. ; Subroutine to prompt for and then change the default destination directory
  3402. ; On entry : no known parameters
  3403. ; Returns  : nothing
  3404. ; Modifies : assume everything
  3405. ;--------------------------------------------------------;
  3406. CD_DEST    PROC    NEAR
  3407.     MOV    SI,OFFSET CHDEST_MSG    ;Display prompt
  3408.     CALL    ASK4PATH
  3409.     JC    _CD_D_RET        ;escape out
  3410.  
  3411.     MOV    AX,[SI]
  3412.     CMP    AH,':'
  3413.     JNZ    _CD_D1
  3414. ;if old destination drive = work drive, and this is a drive change
  3415. ;then we must restore work_path on work_drive to keep things straight
  3416.     MOV    AH,DEST_PATH
  3417.     CMP    AH,AL            ;is there a drive change?
  3418.     JZ    _CD_D1            ;no, go on with dir change
  3419.     CMP    AH,WORK_PATH        ;was work a dir on orig dest drive?
  3420.     JNZ    _CD_D1            ;no, go on
  3421.     MOV    DX,OFFSET WORK_PATH    ;restore work dir on work drive
  3422.     MOV    AH,3BH        ; Change the default directory.
  3423.     INT    DOSINT          ; DS:DX =ASCIIZ path name, may include drive
  3424.  
  3425. _CD_D1:    
  3426. SET_DEST    PROC    NEAR
  3427.     CALL    CHANGE_PATH        ;And change drive.
  3428.     CALL    UPD_DEST        ;update stored info
  3429.     MOV    AX,DEST_CLUSTER
  3430.     MOV    TARG_CLUSTER,AX
  3431.     CALL    COUNT_MARKS
  3432.     CALL    PUT_MENU_PATHS
  3433. _CD_D_RET:
  3434.     RET
  3435. SET_DEST    ENDP
  3436. CD_DEST        ENDP
  3437.  
  3438.  
  3439. ;--------------------------------------------------------;
  3440. ; Subroutine to update stored info about the current destination dir
  3441. ; On entry : DOS must be logged on to destination drive and dir
  3442. ; Returns  : nothing
  3443. ; Modifies : everything
  3444. ;--------------------------------------------------------;
  3445.  
  3446. UPD_DEST    PROC    NEAR
  3447.     MOV    DI,OFFSET DEST_PATH    ;Point to storage.
  3448.     CALL    GET_PATH        ;use DOS to store current dir at [DI]
  3449.     MOV    AL,DEST_PATH
  3450.     MOV    TARG_DISK,AL        ;set default target=destination disk
  3451.     RET
  3452. UPD_DEST    ENDP
  3453.  
  3454. ;--------------------------------------------------------;
  3455. ; This subroutine swaps the default destination and 
  3456. ; working directories
  3457. ; On entry : no known parameters
  3458. ; Returns  : nothing
  3459. ; Modifies : AX, CX, SI, DI
  3460. ;--------------------------------------------------------;
  3461.     ASSUME    CS:_TEXT, DS:_TEXT, ES:_TEXT
  3462. SWAP_DIR    PROC    NEAR
  3463.     MOV    SI,OFFSET WORK_PATH
  3464.     MOV    DI,OFFSET DEST_PATH
  3465.     CLD
  3466.     MOV    CX,70
  3467.     REP    MOVSB
  3468.     CALL    READ_DIR
  3469.     RET
  3470. SWAP_DIR    ENDP
  3471.  
  3472.  
  3473. ;----------------------------------------------------;
  3474. ; This subroutine checks whether function is to be applied to
  3475. ; several marked files or just one file.  User is then prompted for
  3476. ; a destination path which is read from the keyboard.
  3477. ; On entry : SI points to a prompt message for requesting a destination
  3478. ; Returns  : Carry set if current file is directory
  3479. ; Modifies : CX, SI
  3480. ;----------------------------------------------------;
  3481. SETUP_DEST    PROC    NEAR
  3482.     PUSH    SI
  3483.     CALL    COUNT_MARKS
  3484.     JNZ    _CMC1            ;If any marked, exit
  3485.     CALL    GET_NAME        ;Else get highlighted.
  3486.  
  3487. _CMC1:    POP    SI
  3488.     JNC    ASK4DEST        ;is it an ok name(not dir)?
  3489.     CALL    BEEP            ;no - signal error
  3490.     RET                ;and return - else continue
  3491.  
  3492. ;---------------------------------------------;
  3493. ; This subroutine prompts the user for the     ;
  3494. ; destination of highlighted or marked files. ;
  3495. ; On entry : SI points to prompt to be displayed
  3496. ; Returns  : nothing
  3497. ; Modifies : AX, CX, SI, DI
  3498. ;---------------------------------------------;
  3499.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  3500. ASK4DEST    PROC    NEAR
  3501.     MOV    DI,PROMPT_LOC
  3502.     CALL    PUT_STRING
  3503.     PUSH    DI
  3504.     CALL    GET_NAME        ;Get filename.
  3505.     POP    DI
  3506.     MOV    SI,FILE_NAME
  3507.     CMP    MARK_CNT,0        ;were there any marked files?
  3508.     JZ    _A4D1            ;If yes, instead of filename
  3509.     MOV    SI,OFFSET MARKED_MSG    ; display "marked"
  3510.  
  3511. _A4D1:    CALL    PUT_STRING
  3512.  
  3513. TO_DEST    PROC    NEAR
  3514.     MOV    SI,OFFSET TO_MSG    ;Display "to..."
  3515. JUST_ASK    PROC    NEAR
  3516.     CALL    PUT_STRING
  3517.     CALL    CLEAR_OLD        ;Remove last user entry.
  3518.                     ;and set up cursor
  3519. _T_D1:    CALL    READ_KEY        ;Get a keystroke.
  3520.     XOR    BH,BH            ;set video page 0 for tty out
  3521.     CMP    AL,27            ;Is it Esc?
  3522.     JZ    _T_D3            ;If yes, abort.
  3523.     CMP    AL,13            ;Is it carriage return?
  3524.     JZ    _T_D4            ;If yes, execute.
  3525.     CMP    AL,8            ;Is it backspace?
  3526.     JNZ    _T_D2            ;If yes, backspace.
  3527.  
  3528.     CMP    DI,OFFSET ENTRY        ;At beginning of field?
  3529.     JZ    _T_D1            ;If yes, skip.
  3530.     DEC    DI            ;Else, decrement pointer.
  3531.     MOV    BYTE PTR [DI],0
  3532.     MOV    AX,0E08H        ;use BIOS TTY
  3533.     PUSH    AX
  3534.     INT    10H            ;to backspace
  3535.     MOV    AX,0E00H + space    ;blank out char
  3536.     INT    10H
  3537.     POP    AX            ;backspace again
  3538.     INT    10H
  3539.     JMP    SHORT _T_D1
  3540.  
  3541. _T_D2:    CMP    AL,space        ;Is it above space?
  3542.     JBE    _T_D1            ;If no, ignore.
  3543.     CMP    DI,OFFSET ENTRY + 32    ;Else, is 32 char entry field full?
  3544.     JZ    _T_D1            ;If yes, ignore.
  3545.     STOSB                ;Else, store the character.
  3546.     MOV    AH,0EH            ;display using BIOS write tty
  3547.     INT    10H            ;which also updates cursor
  3548.     JMP    SHORT _T_D1
  3549.  
  3550. _T_D3:    CALL    DISP_COUNT_MSG
  3551.     STC
  3552.     RET
  3553.  
  3554. _T_D4:    CLC
  3555.     RET
  3556. JUST_ASK    ENDP
  3557. TO_DEST        ENDP
  3558. ASK4DEST    ENDP
  3559. SETUP_DEST    ENDP
  3560.  
  3561.  
  3562. SUBTTL Major support subroutines
  3563. page
  3564.         ;***************************;
  3565.         ; MAJOR SUPPORT SUBROUTINES ;
  3566.         ;***************************;
  3567.  
  3568. ;---------------------------------------------------------------------;
  3569. ;   Set screen size dependant variables                               ;
  3570. ;---------------------------------------------------------------------;
  3571.  
  3572. SET_SCREEN_VARS PROC    NEAR
  3573.         mov     ax,ROM_BIOS_DATA        ;Point to the ROM BIOS data area
  3574.         mov     ds,ax                   ; and get base address of active
  3575.         ASSUME  DS:ROM_BIOS_DATA
  3576.  
  3577.         mov     bl,DOS_ROWS             ;Physical display rows - 1
  3578.         mov     bh,DOS_COLS             ;Physical display columns
  3579.  
  3580.         mov     ax,cs
  3581.         mov     ds,ax                   ;back to normal data segment
  3582.         ASSUME  DS:_TEXT
  3583.  
  3584.         inc     bl
  3585.         mov     byte ptr SCREEN_ROWS,bl
  3586.         mov     byte ptr SCREEN_COLS,bh
  3587.         dec     bl
  3588.         dec     bl
  3589.         mov     VIEW_ROWS,bl            ;SCREEN_ROWS-2 =rows in view display
  3590.         dec     bl
  3591.         dec     bl
  3592.         mov     byte ptr DIR_ROWS,bl    ;SCREEN_ROWS-4
  3593.         add     bl,ROW1
  3594.         mov     byte ptr LAST_ROW,bl    ;ROW1+DIR_ROWS
  3595.  
  3596.         CROW    0,              1,              ROW_LEN
  3597.         CROW    1,              ROW1,           BAR_START
  3598.         inc     BAR_START
  3599.         CROW    0,              DIR_ROWS,       DIR_ROW_END
  3600.  
  3601.         mov     ax,BAR_START
  3602.         add     DIR_ROW_END,ax          ;DIR_ROW_END=BAR_START+0 CROW DIR_ROWS
  3603.  
  3604.         CROW    49,             2,              MENU_STRT
  3605.         CROW    47,             (3+MENU_ROWS),  PROMPT_LOC
  3606.         CROW    47,             (4+MENU_ROWS),  PROMPT_LOC2
  3607.         CROW    (40-20/2),      12,             LOAD_SORT_LOC
  3608.  
  3609.         mov     ax,PROMPT_LOC
  3610.         add     ax,8
  3611.         mov     SORT_LOC,ax
  3612.  
  3613.         CROW    (40-20/2),      12,             LOAD_LOC
  3614.         CROW    8,              0,              DIRECT_LOC
  3615.         CROW    6,              LAST_ROW,       FILES_LOC
  3616.         CROW    1,              1,              DEST_LOC
  3617.  
  3618.         mov     dx,SCREEN_ROWS
  3619.         dec     dx
  3620.         CROW    2,              dx,             D_FREE_LOC
  3621.  
  3622.         mov     dx,SCREEN_ROWS
  3623.         dec     dx
  3624.         CROW    46,             dx,             MARKED_LOC
  3625.  
  3626.         mov     byte ptr MARKED_WIN, 45
  3627.         mov     ax,SCREEN_ROWS
  3628.         dec     ax
  3629.         mov     byte ptr MARKED_WIN+1,al
  3630.  
  3631.         mov     byte ptr END_WINDOW+1,al
  3632.         mov     ax,SCREEN_COLS
  3633.         dec     ax
  3634.         mov     byte ptr END_WINDOW,al
  3635.         ret
  3636. SET_SCREEN_VARS ENDP
  3637.  
  3638.  
  3639. ;---------------------------------------------------------------------;
  3640. ;   Save DOS screen on entry to program                               ;
  3641. ;---------------------------------------------------------------------;
  3642.  
  3643. SAVE_DOS_SCREEN PROC    NEAR
  3644.         ASSUME  DS:_TEXT
  3645.  
  3646.         mov     al,byte ptr SCREEN_ROWS
  3647.         mov     DOS_SCREEN_LINES,al
  3648.         mov     al,byte ptr SCREEN_COLS
  3649.         mov     DOS_SCREEN_COLS,al
  3650.  
  3651.         mov     ah,0fh
  3652.         int     10h             ;get video mode into AL
  3653.         mov     DOS_VIDMODE,al
  3654.         cmp     al,3
  3655.         jne     NO_SAVE
  3656.  
  3657.         mov     ah,0fh          ;get dos cursor location
  3658.         int     10h             ;Get Current Video State
  3659.         mov     al,bh           ;get video page on screen
  3660.         mov     bh,al
  3661.         mov     ah,3
  3662.         int     10h             ;Read Cursor Position and Size
  3663.         mov     DOS_CURSOR_ROW,dh
  3664.         mov     DOS_CURSOR_COL,dl
  3665.  
  3666. ; Save DOS screen into DOS_SCREEN_BUF
  3667.  
  3668.         push    es              ;save registers
  3669.         push    ds
  3670.         push    si
  3671.         push    di
  3672.  
  3673.         mov     ax,cs
  3674.         mov     es,ax
  3675.  
  3676.         MOV     DS,CS:VIDEO_SEG         ;Point to screen segment.
  3677.  
  3678.         mov     di,offset CS:DOS_SCREEN_BUF  ;get buffer address
  3679.         mov     si,0            ;SI = starting address on screen
  3680.         cld                     ;all memory moves are forward direction
  3681.  
  3682.         mov     al,CS:DOS_SCREEN_LINES
  3683.         mul     CS:DOS_SCREEN_COLS
  3684.         mov     cx,ax
  3685.  
  3686. NextCol:
  3687.         lodsw                   ;get the source character and attribute
  3688.         stosw                   ;and put it in its new home
  3689.         dec     cx              ;show that we just did a column
  3690.         jnz     NextCol         ;continue until done with this row
  3691.  
  3692.         pop     di              ;restore registers
  3693.         pop     si
  3694.         pop     ds
  3695.         pop     es              
  3696.  
  3697. NO_SAVE:
  3698.         ret
  3699. SAVE_DOS_SCREEN ENDP
  3700.  
  3701.  
  3702. ;---------------------------------------------------------------------;
  3703. ;   Restore DOS screen on entry to program                            ;
  3704. ;---------------------------------------------------------------------;
  3705.  
  3706. RESTORE_DOS_SCREEN PROC    NEAR
  3707.         ASSUME  DS:_TEXT
  3708.  
  3709. ; Restore DOS screen from DOS_SCREEN_BUF
  3710.  
  3711.         push    es              ;save registers
  3712.         push    ds
  3713.         push    si
  3714.         push    di
  3715.  
  3716.         mov     ax,cs
  3717.         mov     es,ax
  3718.  
  3719.         MOV     DS,CS:VIDEO_SEG         ;Point to screen segment.
  3720.  
  3721.         mov     di,offset CS:DOS_SCREEN_BUF  ;get buffer address
  3722.         mov     si,0            ;SI = starting address on screen
  3723.         cld                     ;all memory moves are forward direction
  3724.  
  3725.         xchg    si,di           ;source is now memory not screen
  3726.         push    ds
  3727.         push    es
  3728.         pop     ds              ;ES=old DS
  3729.         pop     es              ;DS=old ES
  3730.  
  3731.         mov     al,CS:DOS_SCREEN_LINES
  3732.         mul     CS:DOS_SCREEN_COLS
  3733.         mov     cx,ax
  3734.  
  3735. NextCol2:
  3736.         lodsw                   ;get the source character and attribute
  3737.         stosw                   ;and put it in its new home
  3738.         dec     cx              ;show that we just did a column
  3739.         jnz     NextCol2        ;continue until done with this row
  3740.  
  3741.         pop     di              ;restore registers
  3742.         pop     si
  3743.         pop     ds
  3744.         pop     es              
  3745.  
  3746. ; Restore DOS Cursor
  3747.  
  3748.         mov     dh,DOS_CURSOR_ROW       ;row
  3749.         mov     dl,DOS_CURSOR_COL       ;column
  3750.         mov     bh,0            ;page
  3751.         mov     ah,2            ;locate cursor function
  3752.         int     10h
  3753.  
  3754.         ret
  3755.  
  3756. RESTORE_DOS_SCREEN ENDP
  3757.  
  3758.  
  3759. ;------------------------------------------------------------------------;
  3760. ; This subroutine either copies moves or deletes
  3761. ; a highlighted or marked file.
  3762. ; On entry : no known parameters
  3763. ; Returns  : nothing
  3764. ; Modifies : assume everything. SI points to filename field
  3765. ;------------------------------------------------------------------------;
  3766.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  3767. EXEC_MARKED    PROC    NEAR
  3768.     CALL    CURSOR_OFF        ;Turn cursor off.
  3769.     TEST    FUNCTION,COPY_BIT    ;if a copy is involved
  3770.     JZ    _XM_2
  3771.     CALL    GET_BYTES_FREE        ;get space available on target
  3772.     JNC    _XM_1
  3773.     JMP    CD_ERROR
  3774.  
  3775. _XM_1:    CALL    GET_MEM
  3776.     JNC    _XM_2
  3777.     JMP    _XM_RET
  3778.  
  3779. _XM_2:    CALL    COUNT_MARKS        ;update bytes marked
  3780.     JNZ    _XM_3            ;If any marked files, go find them.
  3781.     CALL    PUT_AMARK        ;and mark it
  3782.     MOV    BYTE PTR [SI],space    ;but don't let it show
  3783.     JMP    SHORT _XM_5        ;And execute it one time.
  3784.  
  3785. _XM_3:    CALL    HOME_BAR        ;Home the highlight bar.
  3786.  
  3787. _XM_4:  CALL    REFRESH_DIR_DISP                ;Update the screen.
  3788.     CALL    GET_NAME        ;Get the highlighted filename.
  3789.     CMP    BYTE PTR [SI],COPY_MARK    ;Is it marked?
  3790.     JZ    _XM_5            ;If yes, execute command.
  3791.     CALL    DN_ARROW        ;Else, move down a row.
  3792.     JMP    SHORT _XM_4        ;And check it for a mark.
  3793.  
  3794. _XM_5:    CALL    GET_NAME        ;test current file for hidden
  3795.     JNZ    _XM_6
  3796.     INC    MARK_CNT        ;fool marked file counters
  3797.     JMP    _XM_15            ;If yes, skip.
  3798.  
  3799. _XM_6:    CALL    GET_FSIZE        ;get file size
  3800.     MOV    SIZE_LOW,AX        ;to be sure it is stored
  3801.     MOV    SIZE_HIGH,DX        ;for future use
  3802.     CALL    DISP_COUNT        ;update counter displays
  3803.     TEST    FUNCTION,PROTECT_BIT+RENAME_BIT    ;Is it a move or rename?
  3804.     JZ    _XM_11            ;no, bypass "file exists" test
  3805.  
  3806. ;check if target filename already exists.
  3807.     CALL    PARSE_ENTRY        ;Else, parse user entry.
  3808.     MOV    DX,BP            ;BP points to filename entry
  3809.     TEST    FUNCTION,RENAME_BIT    ;simple rename ?
  3810.     JNZ    _XM_7            ; yes, just use new filename
  3811.     MOV    DX,OFFSET TARGET    ;move rename-Point to target.
  3812. _XM_7:    PUSH    DX            ;save target
  3813.     MOV    CX,7            ;Does the file exist?
  3814.     CALL    FIND_FIRST
  3815.     POP    DI            ;get back target
  3816.     JC    _XM_8
  3817.     JMP    _XM_15            ; skip since file already exists
  3818. _XM_8:    TEST    FUNCTION,COPY_BIT    ;Is it across drives?
  3819.     JNZ    _XM_12            ;Is yes copy/delete.
  3820. ;file rename and/or move
  3821.     MOV    DX,OFFSET SOURCE
  3822.     PUSH    DI            ;save target again
  3823.     MOV    AH,56H            ;Else, rename it.
  3824.     INT    DOSINT
  3825.     POP    DX            ;get back target
  3826.     JNC    _XM_9
  3827.     JMP    _XM_15            ;Next one if failed.
  3828. _XM_9:    TEST    FUNCTION,MOVE_BIT    ;is this a move?
  3829.     JNZ    _XM_14            ;yes, remove it from list.
  3830.     MOV    CX,17H            ;else assume rename
  3831.     CALL    FIND_FIRST        ;find target
  3832.     MOV    DI,CUR_FILE        ;Point to last entry.
  3833.     CMP    BYTE PTR [DI],COPY_MARK    ;was it marked?
  3834.     JNZ    _XM_10            ;If yes, 
  3835.     MOV    BYTE PTR [DI],"*"    ; mark as done
  3836. _XM_10:    PUSH    DI
  3837.     INC    DI
  3838.     CALL    STORE_ENTRY        ;save new filename
  3839.     POP    DI
  3840.     DEC    COUNT            ;correct total count since not new
  3841.     CMP    BYTE PTR [DI].D_SIZE,'<';directory?
  3842.     JZ    _XM_16            ;yes
  3843.     DEC    FILE_CNT        ;else correct file count
  3844.     JMP    SHORT _XM_16        ;next one
  3845.  
  3846. _XM_11:    TEST    FUNCTION,COPY_BIT    ;Is it a copy request?
  3847.     JZ    _XM_13            ;If no, check delete.
  3848.     CALL    PARSE_ENTRY        ;Else parse user entry.
  3849.  
  3850. _XM_12:    CALL    READ_WRITE        ;Copy the file.
  3851.     JC    _XM_15            ;If failed, skip rest.
  3852.     MOV    SI,CUR_FILE        ;Else, mark with asterisk
  3853.     MOV    BYTE PTR [SI],"*"
  3854.  
  3855. _XM_13:    TEST    FUNCTION,DELETE_BIT    ;Is it a delete request?
  3856.     JZ    _XM_16            ;If no, skip.
  3857.     MOV    DX,OFFSET SOURCE    ;Else, delete the file.
  3858.     MOV    DI,CUR_FILE        ;Point to last entry.
  3859.     CMP    BYTE PTR [DI].D_SIZE,'<';directory?
  3860.     JNZ    _XM_13A            ;no
  3861.     MOV    AH,3AH            ;remove directory
  3862.     INT    DOSINT            ;will fail if not empty
  3863.     JC    _XM_15
  3864.     JMP    _XM_14A
  3865. _XM_13A:
  3866.     MOV    AH,41H
  3867.     INT    DOSINT
  3868.     JC    _XM_15
  3869.     MOV    AX,SIZE_LOW        ;decrement marked bytes
  3870.     MOV    DX,SIZE_HIGH
  3871.     MOV    CX,WORK_CLUSTER
  3872.     CALL    ROUND_UP
  3873.     ADD    AX,WORK_BYTES_FREE
  3874.     ADC    DX,WORK_BYTES_FREE+2
  3875.     MOV    BL,WORK_PATH
  3876.     CALL    UPD_FREE_COUNT
  3877. ;    CMP    CL,DEST_PATH        ;is dest = work 
  3878. ;    JNZ    _XM_14
  3879. ;    ADD    DEST_BYTES_FREE,AX    ;update dest disk values too
  3880. ;    ADC    DEST_BYTES_FREE+2,DX    ;
  3881.  
  3882. _XM_14:    DEC    FILE_CNT
  3883. _XM_14A:
  3884.     CALL    REMOVE_FILE        ;If successful, remove from list.
  3885.     JMP    SHORT _XM_16
  3886.  
  3887. _XM_15:    CALL    BEEP
  3888.     CALL    DN_ARROW        ;Go to next line.
  3889.     JMP    SHORT _XM_17
  3890. ;MARK_CNT is used as a loop counter indicating files left to be processed
  3891. ;Note that when there is a failure MARK_CNT no longer equals the
  3892. ; count of marked files
  3893. ;
  3894. _XM_16: MOV    AX,SIZE_LOW        ;decrement marked bytes
  3895.     MOV    DX,SIZE_HIGH
  3896.     MOV    CX,TARG_CLUSTER
  3897.     CALL    ROUND_UP
  3898.     SUB    MARK_BYTES,AX
  3899.     SBB    MARK_BYTES+2,DX
  3900. _XM_17:    DEC    MARK_CNT        ;update marked file counters
  3901.     CALL    CK_KEY            ; Was a key struck while busy
  3902.     JNZ    _XM_18            ; at our copy, move or delete task?
  3903.     CMP    MARK_CNT,0        ;If yes, abort, else all done?
  3904.     JLE    _XM_X            ;If no, continue until done.
  3905.     JMP    _XM_4
  3906.  
  3907. _XM_18:    CALL    READ_KEY        ;Clear the keyboard buffer,
  3908.     CALL    CK_KEY            ; user entry and prompt.
  3909.     JNZ    _XM_18
  3910.  
  3911. _XM_X:    TEST    FUNCTION,COPY_BIT    ;if a copy is involved
  3912.     JZ    _XM_RET
  3913.     CALL    RELEASE_MEM
  3914. _XM_RET:
  3915.     RET
  3916. EXEC_MARKED    ENDP
  3917.  
  3918.  
  3919. ;----------------------------------------------------;
  3920. ; This section does the reading and writing to disk. ;
  3921. ; On entry : no known parameters
  3922. ; Returns  : nothing
  3923. ; Modifies : assume everything
  3924. ; sets SI=source file handle, DI=target file handle
  3925. ;----------------------------------------------------;
  3926.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  3927. READ_WRITE    PROC    NEAR
  3928.     CMP    N_SEGS,1
  3929.     JNC    _R_W1
  3930.     JMP    _R_W_ERR3
  3931.  
  3932. _R_W1:    XOR    DI,DI            ;set flag for dest handle
  3933. ;get some information on the target filespec, if it exists
  3934.     MOV    DX,OFFSET TARGET    ;Point to target filename.
  3935.     MOV    CX,7
  3936.     CALL    FIND_FIRST        ;Get dir info
  3937.     JC    _R_W4
  3938.     MOV    SI,OFFSET DTA+F_ATTR
  3939.     MOV    AL,[SI]
  3940.     TEST    AL,1            ;is it read only?
  3941.     JNZ    _R_W2            ;go signal error
  3942.  
  3943.     XOR    AH,AH            ;save target attribute
  3944.     PUSH    DI            ;save dest handle/flag
  3945.     MOV    DI,OFFSET TMP_BUFF    ;point to some spare room
  3946.     MOV    CX,22
  3947.     REP    MOVSB            ;save target info
  3948.     POP    DI            ;get back dest flag
  3949.     MOV    CX,AX            ;Get back attribute 
  3950.     XOR    CX,1            ;Flip read-only attribute.
  3951.     MOV    DX,OFFSET TARGET    ;Point to target filename.
  3952.     CALL    CHMOD            ;change attribute
  3953.     JNC    _R_W3            ;no error, proceed
  3954. ;error returned when attempting CHMOD
  3955. ;check to see if the error occured because target was a device, eg PRN
  3956.     MOV    AX,3D01H        ;open file for write
  3957.     INT    DOSINT
  3958.     JC    _R_W2            ;failed
  3959.     XOR    BX,BX
  3960.     MOV    BL,AL            ;get file handle from AL
  3961.     MOV    AX,4400H        ;get device info
  3962.     INT    DOSINT
  3963.     CALL    CLOSE_FILE
  3964.     AND    DX,80H            ;is this a device?
  3965.     JNZ    _R_W4            ;yes, ok to proceed
  3966. _R_W2:    JMP    _R_W_ERR3        ;file failed CHMOD - signal error
  3967.  
  3968. _R_W3:    MOV    DI,-1            ;indicate that we have tweaked target
  3969. ;get some info about the source file
  3970. _R_W4:    MOV    DX,OFFSET SOURCE    ;Point to source filespec.
  3971.     MOV    CX,7
  3972.     CALL    FIND_FIRST        ;Get source
  3973.     JC    _R_W8
  3974.     MOV    SI,OFFSET DTA+F_ATTR
  3975.     LODSB
  3976.     XOR    AH,AH
  3977.     MOV    SOURCE_ATTRIB,AX    ; attribute
  3978.  
  3979.     CMP    DI,-1            ;dir target exist?
  3980.     JNZ    _R_W6            ;no - bypass 'same file' test
  3981.     TEST    AL,1            ;is source read-only?
  3982.     MOV    AL,space        ;assume no
  3983.     JZ    _R_W5            ;and skip
  3984.     MOV    AL,'R'            ;else expect 'R' mark
  3985. _R_W5:    MOV    BX,CUR_FILE        ;get pointer to buffer entry
  3986.     CMP    AL,[BX].D_RO        ;and check with what we have now
  3987.     JNZ    _R_W8            ;oops - source and target are identical
  3988.  
  3989. _R_W6:    LODSW                ;finish saving source info 
  3990.     MOV    SOURCE_TIME,AX        ; time
  3991.     LODSW
  3992.     MOV    SOURCE_DATE,AX        ; date
  3993.     LODSW                ;get low size into AX
  3994.     MOV    SIZE_LOW,AX        ; and save
  3995.     LODSW                ; and high size word
  3996.     MOV    SIZE_HIGH,AX        ;and save
  3997.  
  3998. ;files different:
  3999.     XOR    AX,AX            ;start with nothing
  4000.     XOR    DX,DX
  4001.     CMP    DI,-1            ;did filespec exist on target?
  4002.     JNZ    _R_W7            ;no, we won't be deleting it
  4003.     MOV    AX,WORD PTR TMP_BUFF+F_SIZE-F_ATTR ;get old size
  4004.     MOV    DX,WORD PTR TMP_BUFF+F_SIZE+2-F_ATTR
  4005.     MOV    CX,TARG_CLUSTER        ;target cluster size
  4006.     CALL    ROUND_UP        ;round up
  4007. _R_W7:    ADD    AX,TARG_BYTES_FREE    ;add space already available on target
  4008.     ADC    DX,TARG_BYTES_FREE+2    ;to space that will be freed up
  4009.                     ;by deleting old target file
  4010.  
  4011.     PUSH    DX            ;save result
  4012.     PUSH    AX
  4013.     MOV    AX,SIZE_LOW        ;get source size.
  4014.     MOV    DX,SIZE_HIGH
  4015.     MOV    CX,TARG_CLUSTER        ;target cluster size
  4016.     CALL    ROUND_UP        ;round up
  4017.     POP    BX
  4018.     POP    CX
  4019.     SUB    BX,AX
  4020.     SBB    CX,DX
  4021.     JNB    _R_W9            ;>0 enough space, go ahead
  4022. _R_W8:    CALL    RESET_TARG_AT        ;negative, not enough room.
  4023.     JMP    _R_W_ERR3        ;set failed flag and exit
  4024.  
  4025. _R_W9:    MOV    DX,OFFSET SOURCE    ;Point to source filespec.
  4026.     XOR    AL,AL            ;Open file for reading.
  4027.         CALL    OPEN_FILE
  4028.     JC    _R_W8            ;flip target attr and exit 
  4029.  
  4030. ;    read in from source
  4031. _R_W10:    MOV    SI,AX            ;Save the handle.
  4032.  
  4033. _R_W11:    MOV    BX,SI            ;Retrieve read handle.
  4034.  
  4035.     MOV    SEG_COUNT,0        ;zero buffer counter
  4036.     MOV    AX,MEM_BUF_SEG        ;Point to 1st 64K buffer segment
  4037.     MOV    DS,AX
  4038.     ASSUME    DS:DUMMY_SEG
  4039.  
  4040. _R_W12:    XOR    DX,DX
  4041.     MOV    CX,0FFFFH        ;Read up to 64K at a time.
  4042.     MOV    AH,3FH
  4043.     INT    DOSINT
  4044.     MOV    DX,DS            ;save current buffer seg
  4045.     PUSH    CS
  4046.     POP    DS            ;restore DS
  4047.     ASSUME    DS:_TEXT
  4048.     JNC    _R_W13
  4049.     JMP    _R_W_ERR        ;if error, close files
  4050.  
  4051. _R_W13:    MOV    BP,AX            ;Save bytes read.
  4052.     CMP    AX,CX            ;if less than full buffer read, 
  4053.     JNZ    _R_W14            ; go close file
  4054.     MOV    AL,SEG_COUNT        ;get buffer counter
  4055.     INC    AL            ;add 1 to count done
  4056.     CMP    AL,N_SEGS        ;are we at buffer limits?
  4057.     JZ    _R_W15            ;yes, go write some
  4058.     MOV    SEG_COUNT,AL        ;one more
  4059.     ADD    DX,1000H        ;next 64k seg
  4060.     MOV    DS,DX            ;set up DS
  4061.     JMP    _R_W12            ;go read more
  4062.  
  4063. _R_W14:    CALL    CLOSE_FILE        ;Close file
  4064.     XOR    SI,SI            ;mark file closed
  4065.     JC    _R_W_ERR        ;If there was an error, exit.
  4066.  
  4067. _R_W15:    OR    DI,DI            ;has target been opened?
  4068.     JG    _R_W16
  4069.     CALL    RESET_TARG_AT        ;check/ restore target attr
  4070.     MOV    DX,OFFSET TARGET    ;Point to target filespec.
  4071.     XOR    CX,CX            ;Create and truncate target file
  4072.     MOV    AH,3CH            ; to zero.
  4073.     INT    DOSINT
  4074.     JC    _R_W_ERR
  4075.     MOV    DI,AX            ;Save handle.
  4076.  
  4077. _R_W16:    MOV    DX,MEM_BUF_SEG        ;Get pointer to buffer segment
  4078.  
  4079. _R_W17:
  4080.     MOV    CX,0FFFFH
  4081.     CMP    SEG_COUNT,0
  4082.     JNZ    _R_W18
  4083.     MOV    CX,BP            ;get back # bytes read earlier
  4084.  
  4085. _R_W18:
  4086.     JCXZ    _R_W20            ;If nothing to do, go close
  4087.     PUSH    CX            ;save bytes to write
  4088.     MOV    DS,DX            ;set up buffer segment
  4089.     ASSUME    DS:DUMMY_SEG
  4090.  
  4091.     XOR    DX,DX
  4092.     MOV    BX,DI            ;Retrieve write handle.
  4093.     MOV    AH,40H
  4094.     INT    DOSINT            ;Write the buffer to disk.
  4095.     POP    AX            ;get back bytes to write
  4096.     MOV    DX,DS            ;save current buffer ptr
  4097.     PUSH    CS
  4098.     POP    DS
  4099.     ASSUME    DS:_TEXT
  4100.  
  4101.     JC    _R_W_ERR        ;abort if error in write
  4102.     CMP    AX,CX            ;Did we write same number as read?
  4103.     JNZ    _R_W_ERR        ;If we didn't, exit.
  4104.     DEC    SEG_COUNT        ;count off one buffer full
  4105.     JS    _R_W19            ;done with this buffer read if <0
  4106.     ADD    DX,1000H        ;next 64k chunk
  4107.     JMP    _R_W17
  4108.  
  4109. _R_W19:
  4110.     OR    SI,SI            ;is source still open?
  4111.     JZ    _R_W20
  4112.     JMP    _R_W11            ;If yes, there must be more.
  4113.  
  4114. _R_W20:    MOV    BX,DI
  4115.     MOV    CX,SOURCE_TIME        ;Else, make time/date same
  4116.     MOV    DX,SOURCE_DATE        ; as source.
  4117.     MOV    AX,5701H
  4118.     INT    DOSINT
  4119.  
  4120. _R_W21:    MOV    BX,DI
  4121.     CALL    CLOSE_FILE
  4122.     JMP    SHORT _R_W_RET
  4123.  
  4124. _R_W_ERR:
  4125.     OR    SI,SI            ;check is file open?
  4126.     JZ    _R_W_ERR1        ;bypass if zero
  4127.     MOV    BX,SI            ;get read handle
  4128.     CALL    CLOSE_FILE        ;Close file
  4129.  
  4130. _R_W_ERR1:
  4131.     OR    DI,DI            ;check is file open?
  4132.     JG    _R_W_ERR2        ;file is open
  4133.     JZ    _R_W_ERR3        ;0 means all done
  4134.     CALL    RESET_TARG_AT        ;must be -1
  4135.     JMP    SHORT _R_W_ERR3
  4136. _R_W_ERR2:
  4137.     MOV    BX,DI
  4138.     CALL    CLOSE_FILE
  4139. _R_W_ERR3:
  4140.     STC
  4141. _R_W_RET:
  4142.     PUSHF
  4143.     CALL    GET_BYTES_FREE        ;get space available on target
  4144.     POPF
  4145.     RET
  4146. READ_WRITE      ENDP
  4147.  
  4148.  
  4149. ;reset attribute on target
  4150. RESET_TARG_AT    PROC    NEAR
  4151.     CMP    DI,-1
  4152.     JNZ    _R_T_RET
  4153.     MOV    DX,OFFSET TARGET    ;Point to target filename.
  4154.     MOV    CL,TMP_BUFF        ;get original attribute
  4155.     XOR    CH,CH            ;clear high byte
  4156.     CALL    CHMOD            ;change attribute
  4157.     MOV    DI,0            ;clear handle as a flag
  4158. _R_T_RET:
  4159.     RET
  4160. RESET_TARG_AT    ENDP
  4161.  
  4162. ;--------------------------------------------------------------------------;
  4163. ; This subroutine gets the highlighted file and converts it to DOS format. ;
  4164. ; On entry :    CUR_OFFSET points to a filname entry
  4165. ;            DIR_OK_BIT is set in FUNCTION if function is allowed
  4166. ;         on <DIR> entries.
  4167. ; Returns  :    SI points to current file
  4168. ;        Carry flag is set if function is prohibited on this entry
  4169. ;        Zero flag set if entry is hidden but otherwise allowed
  4170. ; updates  :    CUR_FILE, fills in SOURCE
  4171. ; Modifies :    AX, CX, SI, DI
  4172. ;--------------------------------------------------------------------------;
  4173.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  4174. GET_NAME        PROC    NEAR
  4175.         MOV     SI,CUR_OFFSET           ;Get top of page.
  4176.     MOV    AX,LINE            ;Get location of bar.
  4177.     SUB    AX,BAR_START        ;Adjust.
  4178.         push    dx
  4179.         xor     dx,dx
  4180.         mov     cx,ROW_LEN
  4181.         div     cx
  4182.         mov     cx,FIELD_SIZE
  4183.         mul     cx
  4184.         pop     dx
  4185.     ADD    SI,AX            ;Add to current offset.
  4186.     MOV    CUR_FILE,SI        ;And save pointer.
  4187.     PUSH    SI
  4188.     INC    SI            ;Bump past mark field.
  4189.     MOV    DI,FILE_NAME        ;Store the first eight characters.
  4190.     MOV    CX,8            ;in SOURCE
  4191.         CALL    STORE_BYTES
  4192.     INC    SI
  4193.     CMP    BYTE PTR [SI],space    ;End of name?
  4194.     JZ    _G_N_RET        ;If yes, done here.
  4195.     MOV    AL,"."            ;Else, add dot.
  4196.     STOSB
  4197.     MOV    CX,3            ;Three possible characters
  4198.         CALL    STORE_BYTES             ; as extension.
  4199.  
  4200. _G_N_RET:
  4201.     MOV    BYTE PTR [DI],0        ;Convert to ASCIIZ.
  4202.     POP    SI            ;get back record ptr
  4203.     CMP    BYTE PTR [SI].D_NAME,space    ;Is it an empty entry?
  4204.     JZ    _G_N_ERROR        ;If yes, indicate so.
  4205.  
  4206.     TEST    FUNCTION,DIR_OK_BIT    ;are dir's allowed for this fn?
  4207.     JNZ    _G_N_OK            ;yes, dir's will be ok
  4208.  
  4209.     CMP    BYTE PTR [SI].D_SIZE,"<"    ;Is it a directory?
  4210.     JZ    _G_N_ERROR        ;If yes, indicate so.
  4211.  
  4212. _G_N_OK:
  4213.     CMP    BYTE PTR [SI].D_HID,"H"    ;Is it hidden?
  4214.     CLC
  4215.     RET
  4216.  
  4217. _G_N_ERROR:
  4218.     STC
  4219.     RET
  4220. GET_NAME    ENDP
  4221.  
  4222.  
  4223. ;-----------------------------------------------;
  4224. ; This subroutine parses the user TARGET entry. ;
  4225. ; On entry : no known parameters
  4226. ; Returns  : nothing
  4227. ; Modifies : everything
  4228. ;----------------------------------------;
  4229.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  4230. PARSE_ENTRY    PROC    NEAR
  4231.     MOV    BP,OFFSET TARGET    ;Point to target storage.
  4232.     MOV    DI,BP
  4233.     MOV    SI,OFFSET ENTRY        ;Point to user entry.
  4234.     CMP    BYTE PTR [SI],0        ;Anything entered?
  4235.     JNZ    _P_E1            ;If yes, continue.
  4236.     JMP    _P_E17            ;Else, store source name.
  4237.  
  4238. _P_E1:    LODSB                ;Move user entry into target
  4239.     STOSB                ; workspace.
  4240.     CMP    AL,0
  4241.     JNZ    _P_E1
  4242.     STD                ;Reverse string operation.
  4243.     DEC    DI            ;Adjust pointer back one.
  4244.     MOV    SI,DI            ;Make it the source pointer.
  4245.     MOV    FILENAME_END,DI        ;And store.
  4246.  
  4247. _P_E2:    CMP    SI,OFFSET TARGET - 1    ;Are we at start of name?
  4248.     JZ    _P_E4            ;If yes, done here.
  4249.     LODSB
  4250.     CMP    AL,"\"            ;Else, is it a path delimiter?
  4251.     JZ    _P_E3            ;If yes, mark start of filename.
  4252.     CMP    AL,"/"            ;Alternative path delimiter?
  4253.     JZ    _P_E3            ;If yes, mark start of filename.
  4254.     CMP    AL,":"            ;Colon is also a path delimiter.
  4255.     JNZ    _P_E2
  4256.  
  4257. _P_E3:    INC    SI            ;Adjust pointer to end of path.
  4258. _P_E4:    INC    SI
  4259.     MOV    BP,SI            ;And store.
  4260.     CLD                ;String back to forward.
  4261.     MOV    DI,OFFSET PSP_FCB    ;Use file control block for
  4262.     MOV    AX,2900H        ; workspace.
  4263.     INT    DOSINT            ;Parse the entry for globals.
  4264.     CMP    AL,1            ;Any wild cards?
  4265.     JNZ    _P_E15            ;If no, check if it's a directory.
  4266.  
  4267.     MOV    SI,OFFSET PSP_FCB + 1    ;Else, point to first character.
  4268.     MOV    DI,BP            ;Point to target storage.
  4269.     MOV    BX,FILE_NAME        ;Point to source.
  4270.     MOV    CX,8            ;Eight characters.
  4271.  
  4272. _P_E5:    LODSB
  4273.     CMP    AL,space        ;End of name?
  4274.     JZ    _P_E8            ;If yes, do extension.
  4275.     CMP    AL,"?"            ;Wild card?
  4276.     JNZ    _P_E6            ;If no, store target character.
  4277.     MOV    AL,[BX]            ;Else, replace with source char.
  4278.     CMP    AL,"."            ;Unless end of name.
  4279.     JZ    _P_E8
  4280.     CMP    AL,0
  4281.     JZ    _P_E8
  4282.  
  4283. _P_E6:    STOSB                ;Store the character.
  4284.     CMP    BYTE PTR [BX],"."    ;Are we at end of source name?
  4285.     JZ    _P_E7            ;If yes, don't move pointer.
  4286.     INC    BX            ;Else, point to next source char.
  4287.  
  4288. _P_E7:    LOOP    _P_E5
  4289.  
  4290. _P_E8:    MOV    AL,"."            ;Filename delimiter.
  4291.     STOSB                ;Store it.
  4292.  
  4293. _P_E9:    CMP    [BX],AL            ;Was there a dot in source?
  4294.     JZ    _P_E10            ;If yes do extension.
  4295.     CMP    BYTE PTR [BX],0        ;End of source name?
  4296.     JZ    _P_E11            ;If yes, do extension.
  4297.     INC    BX            ;Else, go to end of name.
  4298.     JMP    SHORT _P_E9
  4299.  
  4300. _P_E10:    INC    BX            ;Bump pointer past dot.
  4301. _P_E11:    MOV    SI,OFFSET PSP_FCB + 9    ;Point to extension of parsed.
  4302.     MOV    CX,3            ;Three characters.
  4303.  
  4304. _P_E12:    LODSB
  4305.     CMP    AL,space        ;End of parsed?
  4306.     JZ    _P_E14            ;If yes, done here.
  4307.     CMP    AL,"?"            ;Wild card?
  4308.     JNZ    _P_E13            ;If no, store user character.
  4309.     MOV    AL,[BX]            ;Else, store source character.
  4310.  
  4311. _P_E13:    STOSB
  4312.     INC    BX
  4313.     LOOP    _P_E12            ;Do all three extension chars.
  4314.  
  4315. _P_E14:    XOR    AL,AL            ;Make it an ASCIIZ.
  4316.     STOSB
  4317.     JMP    SHORT _P_E_RET        ;Done here.
  4318.  
  4319. _P_E15:    MOV    DI,BP            ;Any characters after path
  4320.     CMP    BP,FILENAME_END        ; delimiter?
  4321.     JZ    _P_E17            ;If no, tack on source name.
  4322.     MOV    DX,OFFSET ENTRY        ;Else, see if it's a directory.
  4323.     MOV    CX,10H
  4324.     CALL    FIND_FIRST
  4325.     JC    _P_E_RET        ;If not found, done here.
  4326.     CMP    DTA+F_ATTR,CL        ;If not directory, done here.
  4327.     JNZ    _P_E_RET
  4328.     MOV    DI,FILENAME_END        ;Else, tack on source filename.
  4329.     MOV    AL,"\"
  4330.  
  4331. IFDEF SAG
  4332.     CMP    SWITCH,"/"        ;do we really want "/"?
  4333.     JE    _P_E16            ;no
  4334.     MOV    AL,"/"            ;yes
  4335. _P_E16:
  4336. ENDIF
  4337.  
  4338.     STOSB
  4339. _P_E17:    MOV    SI,FILE_NAME        ;Source filename.
  4340.     MOV    CX,14
  4341.     REP    MOVSB
  4342.  
  4343. _P_E_RET:    RET
  4344. PARSE_ENTRY    ENDP
  4345.  
  4346.  
  4347. ;------------------------------------------------------------------;
  4348. ; This subroutine removes the filename from the directory listing. ;
  4349. ;------------------------------------------------------------------;
  4350.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  4351. REMOVE_FILE    PROC    NEAR
  4352.     MOV    DI,CUR_FILE        ;Point to filename.
  4353.     MOV    SI,DI            ;Move all the records
  4354.     ADD    SI,FIELD_SIZE        ; that follow up one.
  4355.  
  4356. _R_F1:    MOV    CX,FIELD_SIZE
  4357.     REP    MOVSB
  4358.     CMP    DI,END_OFFSET
  4359.     JB    _R_F1
  4360.     SUB    DI,FIELD_SIZE
  4361.     MOV    END_OFFSET,DI        ;Store new end.
  4362.     XOR    BP,BP
  4363.     CALL    SCROLL            ;Update the screen.
  4364.     DEC    COUNT
  4365.     JZ    _R_F_RET        ;If empty, exit.
  4366.  
  4367. _R_F2:  mov     al,byte ptr DIR_ROWS    ;Full page?
  4368.         cmp     byte ptr COUNT,al
  4369.  
  4370.     JAE    _R_F_RET        ;If yes, skip.
  4371.         mov     ax,ROW_LEN              ;Else, adjust page end.
  4372.         SUB     DIR_DISP_END,ax
  4373.  
  4374.     MOV    SI,DIR_DISP_END
  4375.     SUB    SI,ROW_LEN
  4376.     CMP    SI,LINE            ;Is bar below directory listing?
  4377.     JA    _R_F_RET        ;If no, skip.
  4378.     CALL    MOVE_BAR        ;Else, move bar up one line.
  4379. _R_F_RET:
  4380.     RET
  4381. REMOVE_FILE    ENDP
  4382.  
  4383. SUBTTL Miscellaneous small support subroutines
  4384. page
  4385.         ;***************************;
  4386.         ; OTHER SUPPORT SUBROUTINES ;
  4387.         ;***************************;
  4388.  
  4389.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  4390. ;-----------------------------------------------------------;
  4391. ; This subroutine moves and turns the cursor on and removes ;
  4392. ; the last user entry in preparation for new input.         ;
  4393. ; On entry :    DX points to location for prompt
  4394. ; Returns  :    DI pointing to ENTRY buffer for user input
  4395. ;-----------------------------------------------------------;
  4396. CLEAR_OLD    PROC    NEAR
  4397.     MOV    DX,ENTRY_CUR
  4398.     CALL    SET_CURSOR        ;Move cursor.
  4399.     MOV    DI,OFFSET ENTRY        ;Write nulls over old entry.
  4400.     PUSH    DI
  4401.     XOR    AX,AX
  4402.     MOV    CX,18
  4403.     REP    STOSW
  4404.     POP    DI            ;return pointer for entry.
  4405.     RET
  4406. CLEAR_OLD    ENDP
  4407.  
  4408.  
  4409. ;----------------------------------------------------;
  4410. ; This subroutine counts the number of marked files. ;
  4411. ; On entry : no known parameters
  4412. ; Returns  : CX = MARK_CNT, Z flag set if CX=0
  4413. ; Modifies : CX, SI
  4414. ;----------------------------------------------------;
  4415. COUNT_MARKS    PROC    NEAR
  4416.     OR    FUNCTION,UPD_CNT_BIT
  4417.     XOR    CX,CX            ;Zero out counter.
  4418.     MOV    MARK_BYTES,CX
  4419.     MOV    MARK_BYTES+2,CX
  4420.     MOV    SI,OFFSET DIR_BUFF    ;Point to start of listing.
  4421.  
  4422. _C_M1:    CMP    BYTE PTR [SI],COPY_MARK    ;Is it marked?
  4423.     JNZ    _C_M2            ;In no, skip.
  4424.     INC    CX            ;Else, increment counter.
  4425.     PUSH    CX
  4426.     CALL    GET_FSIZE
  4427.     MOV    CX,TARG_CLUSTER
  4428.     CALL    ROUND_UP
  4429.     ADD    MARK_BYTES,AX
  4430.     ADC    MARK_BYTES+2,DX
  4431.     POP    CX
  4432.  
  4433. _C_M2:    ADD    SI,FIELD_SIZE        ;Next record.
  4434.     CMP    SI,END_OFFSET        ;Continue until done.
  4435.     JB    _C_M1
  4436.     MOV    MARK_CNT,CX        ;Store the count of marked files.
  4437.     OR    CX,CX
  4438.     RET
  4439. COUNT_MARKS    ENDP
  4440.  
  4441. ;-------------------------------------------------------------;
  4442. ; This subroutine waits until a keystroke is pressed and then ;
  4443. ; clears the message.  Keystroke is disgarded.
  4444. ;-------------------------------------------------------------;
  4445. DELAY    PROC    NEAR
  4446.     CALL    READ_KEY
  4447.  
  4448. ;----------------------------------------------;
  4449. ; This subroutine displays the count of files. ;
  4450. ; On entry : WORK_BYTES_FREE, DEST_BYTES_FREE, MARK_BYTES, etc
  4451. ; Returns  : upated display
  4452. ; Modifies : everything
  4453. ;----------------------------------------------;
  4454. DISP_COUNT_MSG    PROC    NEAR
  4455.     CALL    CLR_MSG
  4456. DISP_COUNT    PROC    NEAR
  4457.     MOV    DI,OFFSET FILES        ;message string storage
  4458.     MOV    SI,DI            ;save it
  4459.     MOV    AX,FILE_CNT
  4460.     XOR    DX,DX
  4461.     MOV    CX,LENGTH FILES
  4462.     CALL    FORMAT
  4463.  
  4464.         MOV     DI,FILES_LOC            ;Row 24; column 6.
  4465.     MOV    AH,INTENSE
  4466.     CALL    PUT_STRATT
  4467.  
  4468.         MOV     DI,D_FREE_LOC
  4469.     MOV    SI,OFFSET DEST_FREE    ;Display free bytes on dest
  4470.     MOV    AH,INTENSE
  4471.     CALL    PUT_STRATT
  4472. ;----------------------------------------------------;
  4473. ; This subroutine displays the byte count and number of marked files. ;
  4474. ; On entry : MARK_BYTES and MARK_CNT contain numbers
  4475. ; Returns  : nothing
  4476. ; Modifies : everything
  4477. ;----------------------------------------------------;
  4478.  
  4479. DISP_MARKED     PROC    NEAR
  4480.     CMP    MARK_CNT,0
  4481.     JZ    _D_MR1
  4482.         MOV     AX,MARK_BYTES
  4483.     MOV    DX,MARK_BYTES+2
  4484.         MOV     CX,LENGTH BYTES_MRKD_MSG
  4485.     MOV    DI,OFFSET BYTES_MRKD_MSG
  4486.     MOV    SI,DI
  4487.         CALL    FORMAT
  4488.     MOV    AX,MARK_CNT
  4489.     XOR    DX,DX
  4490.     MOV    CX,LENGTH FILES_MRKD_MSG
  4491.     MOV    DI,OFFSET FILES_MRKD_MSG
  4492.     CALL    FORMAT
  4493.     MOV    DI,MARKED_LOC
  4494.     CALL    PUT_STRING
  4495.     JMP    SHORT    _D_MR_RET
  4496.  
  4497. _D_MR1:    MOV    AL,NORMAL
  4498.     MOV    CX,MARKED_WIN
  4499.         CALL    CLR_EOL
  4500.  
  4501. _D_MR_RET:    RET
  4502. DISP_MARKED    ENDP
  4503. DISP_COUNT    ENDP
  4504. DISP_COUNT_MSG    ENDP
  4505. DELAY    ENDP
  4506. ;----------------------------------------------------;
  4507. ; Subr. to convert ascii file size into binary
  4508. ; On entry : SI points to mark field of a marked file
  4509. ; Returns  : DX:AX = file size, rounded up to TARG_CLUSTER size
  4510. ; Modifies : AX, BX, DX, BP, saves SI
  4511. ;----------------------------------------------------;
  4512.  
  4513. ;we shall assume SI points to filename
  4514. GET_FSIZE    PROC    NEAR
  4515.     PUSH    SI
  4516.     XOR    AX,AX
  4517.     XOR    DX,DX
  4518.     ADD    SI,D_SIZE
  4519.     CMP    BYTE PTR [SI],'<'
  4520.     JZ    _GFS_RET
  4521.     MOV    CX,8
  4522.     MOV    BX,10
  4523.     JMP    SHORT _GFS3
  4524.  
  4525. _GFS1:    XCHG    AX,DX        ;get high word, save low
  4526.     MUL    BL        ;times 10
  4527.     MOV    BP,AX        ;save result
  4528.     MOV    AX,DX        ;get back low word
  4529.     MUL    BX        ;times 10
  4530.     ADD    DX,BP        ;add in previous high word result
  4531. _GFS3:    MOV    BP,AX        ;save low
  4532.     XOR    AH,AH        ;clear byte
  4533.     LODSB            ;get next digit
  4534.     SUB    AL,'0'        ;convert to hex byte
  4535.     JC    _GFS4        ;skip spaces
  4536.     ADD    AX,BP        ;add in old result
  4537.     JNC    _GFS5
  4538.     INC    DX        ;add 1 if carry in low word
  4539.     JMP    SHORT _GFS5
  4540.  
  4541. _GFS4:    XOR    AX,AX        ;clear reg if space
  4542. _GFS5:    LOOP    _GFS1
  4543. _GFS_RET:
  4544.     POP    SI
  4545.     RET
  4546. GET_FSIZE    ENDP
  4547.  
  4548. ;----------------------------------------------------;
  4549. ; This subroutine performs a table lookup
  4550. ; On entry :    AL contains a byte
  4551. ;        DI points to a lookup table of length CX
  4552. ;        BX points to last entry of a result table
  4553. ; Returns  :     BX points to the matching entry in the result table
  4554. ;        NZ implies no match found
  4555. ; Modifies : BX, CX,  DI
  4556. ;----------------------------------------------------;
  4557. LOOKUP    PROC    NEAR
  4558.     REPNZ    SCASB        ;scan table
  4559.     PUSHF            ;save flags
  4560.     JNZ    _LK_RET        ;not found
  4561.     SHL    CX,1        ;multiply by two bytes per word
  4562.     SUB    BX,CX        ;this many bytes from end
  4563. _LK_RET:    POPF            ;restore flags
  4564.     RET    
  4565. LOOKUP    ENDP
  4566.  
  4567. ;----------------------------------------------------;
  4568. ; This subroutine performs a table lookup for a sort option
  4569. ; Sorts are done on a field starting at SORT_OFFSET with a
  4570. ; field length of SORT_LEN
  4571. ; On entry :    AL contains a byte to check
  4572. ;        DI points to a lookup table of length SORT_OPT_CNT
  4573. ; Modifies : AX, BX, CX,  DI
  4574. ;----------------------------------------------------;
  4575. SET_SORT    PROC    NEAR
  4576.     MOV    CX,SORT_OPT_CNT
  4577.     MOV    BX,OFFSET SORT_TABLE_END
  4578.     CALL    LOOKUP
  4579.     JNZ    _S_S_RET
  4580.     MOV    AX,[BX]
  4581.     MOV    BYTE PTR SORT_OFFSET,AL
  4582.     MOV    BYTE PTR SORT_LEN,AH
  4583. _S_S_RET:
  4584.     RET
  4585. SET_SORT    ENDP
  4586.  
  4587. ;--------------------------------------------------------;
  4588. ; This procedure does a string move, skipping over spaces
  4589. ; On entry : SI, DI set up for move
  4590. ; Returns  : nothing
  4591. ; Modifies : AL, CX, SI, DI
  4592. ;---------------------------------------------------------;
  4593. STORE_BYTES    PROC    NEAR
  4594.     LODSB                ;Get a character.
  4595.     CMP    AL,space        ;If it's space, skip.
  4596.     JZ    _S_B1
  4597.     STOSB
  4598. _S_B1:    LOOP    STORE_BYTES
  4599.     RET
  4600. STORE_BYTES    ENDP
  4601.  
  4602. ;---------------------------------------------------
  4603. ; These subroutines converts a hex number to decimal.
  4604. ; FORMAT clears field first
  4605. ;---------------------------------------------------
  4606. ; On entry : DX:AX=number to convert 
  4607. ;         CX = length of field to be cleared first
  4608. ;         DI= start of destination field
  4609. ; Returns  : DI points to beginning of converted string
  4610. ; Modifies : AX, BX, CX, DX, DI
  4611. ;---------------------------------------------------;
  4612.     ASSUME    DS:NOTHING,ES:NOTHING
  4613. FORMAT    PROC    NEAR
  4614.     PUSH    AX
  4615.     MOV    AL,space
  4616.     DEC    CX
  4617.     REPNZ    STOSB
  4618.     POP    AX
  4619.  
  4620. ;---------------------------------------------------;
  4621. ; On entry : DX:AX=number to convert, 
  4622. ;         DI= end of destination
  4623. ;---------------------------------------------------;
  4624. TRANSLATE    PROC    NEAR
  4625.     XCHG    AX,DX
  4626.     MOV    BX,10            ;Convert to decimal.
  4627.     STD                ;Reverse direction.
  4628.  
  4629. _TR1:   MOV     CX,DX           ;cx = low 16 bits of number to convert
  4630.         XOR     DX,DX
  4631.     DIV    BX
  4632.         XCHG    AX,CX           ;cx = !!!!!!!!!!!!!!
  4633.     DIV    BX
  4634.     XCHG    AX,DX
  4635.     ADD    AL,"0"            ;Convert to ASCII.
  4636.     STOSB                ;Store the remainder.
  4637.     MOV    AX,CX
  4638.     OR    CX,DX
  4639.     JNZ    _TR1
  4640.     CLD                ;Back to forward direction.
  4641.     RET
  4642. TRANSLATE    ENDP
  4643. FORMAT        ENDP
  4644.  
  4645.  
  4646. ;------------------------------------------;
  4647. ; This subroutine rounds a number up
  4648. ; On entry :    DX:AX = number to convert
  4649. ;        CX = number base
  4650. ; Returns  :    DX:AX with CX unchanged
  4651. ;------------------------------------------;
  4652. ROUND_UP    PROC    NEAR
  4653.     DIV    CX            ;divide by base
  4654.     OR    DX,DX            ;check for remainder
  4655.     JZ    _R_U1            ;nothing extra?
  4656.     INC    AX            ;add one for remainder
  4657. _R_U1:    MUL    CX            ;and go back to original units
  4658.     RET
  4659. ROUND_UP    ENDP
  4660.  
  4661. ;-------------------------------------------------;
  4662. ; This routine formats a byte to ASCII decimal 
  4663. ; and stores it at ES:DI, followed by delimiter CL
  4664. ; On entry :     AX = number (<100) to convert
  4665. ;        CH = trailing delimiter char
  4666. ;        CL not 0 to supress leading zero
  4667. ; Returns  : nothing
  4668. ; Modifies : assume everything
  4669. ;-------------------------------------------------;
  4670. STORE_DIGITS    PROC    NEAR
  4671.     MOV    BL,10
  4672.     DIV    BL            ;Divide by ten.
  4673.     ADD    AX,"00"            ;Convert to ASCII.
  4674.     OR    CL,CL            ;Are we to display leading zero?
  4675.     JZ    _ST_D1            ;If yes, store as is.
  4676.     CMP    AL,"0"            ;Is it a leading zero?
  4677.     JNZ    _ST_D1            ;If no, store it.
  4678.     MOV    AL,space        ;Else, store a space.
  4679.  
  4680. _ST_D1:    STOSW
  4681.     MOV    AL,CH            ;Store delimiter character also.
  4682.     STOSB
  4683.     RET
  4684. STORE_DIGITS    ENDP
  4685.  
  4686. SUBTTL Screen display subroutines
  4687. page
  4688. ;----------------------------------------------------------------------------;
  4689. ; This subroutine displays the current directory, menu, and number of files. ;
  4690. ;----------------------------------------------------------------------------;
  4691.  
  4692.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  4693. PUT_MENU_PATHS  PROC    NEAR
  4694.     MOV    AL,NORMAL
  4695.     CALL    CLR_SCR            ;Clear the screen.
  4696.  
  4697.     MOV    DI,MENU_STRT        ;And to screen position.
  4698.     MOV    AL,GB_TL        ;top left
  4699.     MOV    BX,GB_TR + GB_TH*100h    ;middle and right characters
  4700.     CALL    PUT_MENU_BORDER
  4701.     MOV    SI,OFFSET LOGO        ;Point to menu position.
  4702.     MOV    BL,LOGO_ROWS
  4703.     CALL    PUT_MENU_LINES
  4704.     MOV    AL,GB_L_TEE            ;mid- left
  4705.     MOV    BX,GB_R_TEE + GB_MH*100h    ;middle and right characters
  4706.     CALL    PUT_MENU_BORDER
  4707.  
  4708.     MOV    SI,OFFSET MENU1
  4709.     MOV    BL,MENU1_ROWS
  4710.     CALL    PUT_MENU_LINES
  4711.  
  4712.     MOV    AL,GB_BL        ;bottom left
  4713.     MOV    BX,GB_BR + GB_BH*100h    ;middle and right characters
  4714.     CALL    PUT_MENU_BORDER
  4715.  
  4716.     MOV    AH,INTENSE
  4717.     MOV    DI,DIRECT_LOC
  4718.     MOV    SI,OFFSET DIRECTORY    ;Display "Directory of".
  4719.     CALL    PUT_STRATT
  4720.     MOV    SI,OFFSET WORK_PATH    ;Display working directory.
  4721.     CALL    PUT_STRATT
  4722.  
  4723.     MOV    DI,DEST_LOC
  4724.     MOV    SI,OFFSET DEST_MSG    ;Display destination msg
  4725.     CALL    PUT_STRATT
  4726.     MOV    SI,OFFSET DEST_PATH    ;Display dest directory.
  4727.     CALL    PUT_STRATT
  4728.  
  4729.     MOV    AL,INVERSE
  4730.     CALL    BAR            ;Put up cursor bar.
  4731.     MOV    FUNCTION,UPD_CNT_BIT    ;force update of count displays
  4732.     RET
  4733. PUT_MENU_PATHS    ENDP
  4734.  
  4735. ;------------------------------------------------------------;
  4736. ; This subroutine is used to display a border line on menu
  4737. ; On entry :    AL = left border edge char to display
  4738. ;        AH = display attribute to use
  4739. ;        BH = char to repeat in middle
  4740. ;        BL = right border edge character
  4741. ;        DI = where to put char in display
  4742. ; Returns  :    DI points to location of start of next line
  4743. ; Modifies :    DI, uses and preserves ES
  4744. ;------------------------------------------------------------;
  4745. PUT_MENU_BORDER    PROC    NEAR
  4746.     MOV    AH,BORDER
  4747.     CALL    PUT_CHARATT
  4748.     MOV    AL,BH
  4749.  
  4750.     MOV    CX,MENU_WIDTH
  4751. _PMB1:    CALL    PUT_CHARATT
  4752.     LOOP    _PMB1
  4753.  
  4754.     MOV    AL,BL
  4755.     CALL    PUT_CHARATT
  4756.  
  4757.         mov     ax,MENU_WIDTH   ;ADD DI,ROW_LEN-2*(MENU_WIDTH+2) ;Next line.
  4758.         inc     ax
  4759.         inc     ax
  4760.         shl     ax,1
  4761.         mov     bx,ROW_LEN
  4762.         sub     bx,ax
  4763.         add     di,bx
  4764.  
  4765.     RET
  4766. PUT_MENU_BORDER    ENDP
  4767.  
  4768. ;------------------------------------------------------------;
  4769. ; This subroutine is used to display a set of menu lines
  4770. ; On entry :    BL = number of lines to display
  4771. ;        SI points to lines to display after border
  4772. ;        DI = where to put chars in display
  4773. ; Returns  :    DI points to location of start of next line
  4774. ; Modifies :    DI, uses and preserves ES
  4775. ;------------------------------------------------------------;
  4776. PUT_MENU_LINES    PROC    NEAR
  4777.     MOV    AH,BORDER
  4778.     MOV    AL,GB_V
  4779.     CALL    PUT_CHARATT
  4780.  
  4781.     MOV    AH,MENU_ATT
  4782.     MOV    CX,MENU_WIDTH
  4783. _PML1:    LODSB
  4784.     CALL    PUT_CHARATT
  4785.     LOOP    _PML1
  4786.  
  4787.     MOV    AH,BORDER
  4788.     MOV    AL,GB_V
  4789.     CALL    PUT_CHARATT
  4790.  
  4791.         push    ax              ;ADD DI,ROW_LEN-2*(MENU_WIDTH+2) ;Next line.
  4792.         push    bx
  4793.         mov     ax,MENU_WIDTH
  4794.         inc     ax
  4795.         inc     ax
  4796.         shl     ax,1
  4797.         mov     bx,ROW_LEN
  4798.         sub     bx,ax
  4799.         add     di,bx
  4800.         pop     bx
  4801.         pop     ax
  4802.  
  4803.     DEC    BL
  4804.     JNZ    PUT_MENU_LINES
  4805.     RET
  4806. PUT_MENU_LINES    ENDP
  4807.  
  4808. ;-------------------------------------------------;
  4809. ; This subroutine displays the directory listing. ;
  4810. ;-------------------------------------------------;
  4811.     ASSUME    CS:_TEXT,DS:_TEXT,ES:_TEXT
  4812. REFRESH_DIR_DISP    PROC    NEAR
  4813.         MOV     SI,CUR_OFFSET           ;Retrieve starting offset.
  4814.         CROW    0,ROW1,DI               ;Point to row two of screen.
  4815.         MOV     BH,byte ptr DIR_ROWS    ;21 lines to write.
  4816. _R_DD1:    MOV    CX,FIELD_SIZE        ;44 characters per line.
  4817.         CALL    PUT_CX_CHARS                    ;Write them.
  4818.  
  4819.         mov     ax,ROW_LEN
  4820.         sub     ax,FIELD_SIZE * 2
  4821.         add     di,ax                   ;Bump pointer to next line.
  4822.  
  4823.     DEC    BH            ;Do all 21 lines.
  4824.     JNZ    _R_DD1
  4825.     RET
  4826. REFRESH_DIR_DISP    ENDP
  4827.  
  4828. ;------------------------------------------------------------;
  4829. ; This subroutine displays a character by writing directly   ;
  4830. ; to the screen buffer.  To avoid screen noise (snow) on the ;
  4831. ; color card, the horizontal retrace has to be monitored.    ;
  4832. ; On entry :    AL = char to display
  4833. ;        DI = where to put char in display
  4834. ; Returns  :    DI points to next location
  4835. ; Modifies :    DI, uses and preserves ES
  4836. ;------------------------------------------------------------;
  4837.     ASSUME    DS:NOTHING,ES:NOTHING
  4838. PUT_CHAR    PROC    NEAR
  4839.     PUSH    ES            ;save seg register
  4840.     PUSH    DX
  4841.     MOV    ES,VIDEO_SEG        ;Point to screen segment.
  4842.     MOV    DX,STATUS_REG        ;Retrieve status register.
  4843.         CALL    PUT_BYTE
  4844.     INC    DI            ;Bump pointer past attribute.
  4845.     POP    DX
  4846.     POP    ES            ;restore segment register
  4847.     RET                ;Return
  4848. PUT_CHAR    ENDP
  4849.  
  4850. ;------------------------------------------------------------;
  4851. ; This subroutine displays a character and attribute
  4852. ; On entry :    AL = char to display
  4853. ;        AH = display attribute to use
  4854. ;        DI = where to put char in display
  4855. ; Returns  :    DI points to next location
  4856. ; Modifies :    DI, uses and preserves ES
  4857. ;------------------------------------------------------------;
  4858. PUT_CHARATT    PROC    NEAR
  4859.     PUSH    ES            ;save seg register
  4860.     PUSH    DX
  4861.     PUSH    AX
  4862.     MOV    ES,VIDEO_SEG        ;Point to screen segment.
  4863.     MOV    DX,STATUS_REG        ;Retrieve status register.
  4864.     CALL    PUT_BYTE        ;put char
  4865.     MOV    AL,AH
  4866.     CALL    PUT_BYTE        ;put attribute
  4867.     POP    AX
  4868.     POP    DX
  4869.     POP    ES            ;restore segment register
  4870.     RET                ;Return
  4871. PUT_CHARATT    ENDP
  4872.  
  4873.  
  4874. PUT_BYTE    PROC    NEAR
  4875.     OR    DX,DX            ;zero if mono or ega
  4876.     JZ    _P_B3            ;don't wait if mono
  4877.  
  4878.     PUSH    AX
  4879. _P_B1:    IN    AL,DX            ;Get status.
  4880.     TEST    AL,8            ;Is vertical in retrace?
  4881.     JNZ    _P_B2A            ;If yes, lets go
  4882.     TEST    AL,1            ;Is it low?
  4883.     JNZ    _P_B1            ;If not, wait until it is.
  4884.  
  4885. _P_B2:    IN    AL,DX            ;Get status.
  4886.     TEST    AL,1            ;Is it high?
  4887.     JZ    _P_B2            ;If no, wait until it is.
  4888. _P_B2A:    POP    AX
  4889.  
  4890. _P_B3:  STOSB                           ; to write to screen buffer.
  4891.     RET
  4892. PUT_BYTE    ENDP
  4893.  
  4894.  
  4895. ;---------------------------------------------------------------;
  4896. ; This subroutine writes null terminated string to Videoseg [DI]
  4897. ; On entry :    DS:SI points to string of length CX
  4898. ;        DI points to a location in the video memory
  4899. ; Returns  :     nothing
  4900. ; Modifies :    AX, SI, DI, uses but preserves ES
  4901. ;---------------------------------------------------------------;
  4902. PUT_STRING    PROC    NEAR
  4903.     LODSB
  4904.     OR    AL,AL
  4905.     JZ    _PST_RET
  4906.     CALL    PUT_CHAR
  4907.     JMP    PUT_STRING
  4908. _PST_RET:
  4909.     RET                ;Return
  4910. PUT_STRING    ENDP
  4911.  
  4912. PUT_STRATT    PROC    NEAR        ;attribute in AH
  4913.     LODSB
  4914.     OR    AL,AL
  4915.     JZ    _PSA_RET
  4916.     CALL    PUT_CHARATT
  4917.     JMP    PUT_STRATT
  4918. _PSA_RET:
  4919.     RET                ;Return
  4920. PUT_STRATT    ENDP
  4921.  
  4922. ;---------------------------------------------------------------;
  4923. ; This subroutine writes a string to Videoseg [DI]
  4924. ; Writes up to first null character or CX characters.
  4925. ; On entry :    DS:SI points to string with max length CX
  4926. ;        DI points to a location in the video memory
  4927. ; Returns  :     nothing
  4928. ; Modifies :    AX, CX, SI, DI, uses but preserves ES
  4929. ;---------------------------------------------------------------;
  4930. ifdef SMALL
  4931. PUT_CX_CHARS    PROC    NEAR        ;use current attribute
  4932.  
  4933.     PUSH    ES            ;save seg register
  4934.     PUSH    DX
  4935.     MOV    ES,VIDEO_SEG        ;Point to screen segment.
  4936.     MOV    DX,STATUS_REG        ;Retrieve status register.
  4937.  
  4938. _PCXC1:    LODSB                ;get character
  4939.     CALL    PUT_BYTE
  4940.     INC    DI            ;Bump pointer past attribute.
  4941.     LOOP    _PCXC1
  4942.  
  4943.     POP    DX
  4944.     POP    ES            ;restore segment register
  4945.     RET
  4946. PUT_CX_CHARS    ENDP
  4947.  
  4948. else
  4949.  
  4950. ; Faster but bulkier display of CX chars:
  4951. PUT_CX_CHARS    PROC    NEAR        ;use current attribute
  4952.  
  4953.     PUSH    ES            ;save seg register
  4954.     PUSH    DX
  4955.     MOV    ES,VIDEO_SEG        ;Point to screen segment.
  4956.     MOV    DX,STATUS_REG        ;Retrieve status register.
  4957.     OR    DX,DX
  4958.     JZ    _PCXC3
  4959.     
  4960. _PCXC1:    IN    AL,DX            ;Get status.
  4961.     TEST    AL,8            ;Is vertical in retrace?
  4962.     JNZ    _PCXC3            ;If yes, lets go
  4963.     TEST    AL,1            ;Is it low?
  4964.     JNZ    _PCXC1            ;If not, wait until it is.
  4965.  
  4966. _PCXC2:    IN    AL,DX            ;Get status.
  4967.     TEST    AL,1            ;Is it high?
  4968.     JZ    _PCXC2            ;If no, wait until it is.
  4969.     MOVSB
  4970.     INC    DI
  4971.     LOOP    _PCXC1
  4972.     JMP    SHORT    _PCXC_RET
  4973.  
  4974. _PCXC3:    MOVSB
  4975.     INC    DI
  4976.     LOOP    _PCXC3
  4977.  
  4978. _PCXC_RET:
  4979.     POP    DX
  4980.     POP    ES            ;restore segment register
  4981.     RET
  4982. PUT_CX_CHARS    ENDP
  4983. endif
  4984.  
  4985. ;    ********************************
  4986. ;    *  BIOS SCREEN WRITING ROUTINES
  4987. ;    ********************************
  4988. ;-----------------------------------------------------------------------;
  4989. ; These subroutines clear either the messages or the entire screen. ;
  4990. ;-----------------------------------------------------------------------;
  4991.         ASSUME    DS:_TEXT,ES:_TEXT
  4992.  
  4993. CLR_MSG    PROC    NEAR
  4994.     MOV    AL,NORMAL
  4995.     MOV    CX,BEG_WINDOW        ;Row 24; column 43.
  4996.     JMP    SHORT CLR_EOS
  4997.  
  4998. CLR_EOL    PROC    NEAR
  4999.     MOV    DH,CH
  5000.         mov     dl,byte ptr SCREEN_COLS
  5001.         dec     dl
  5002.     JMP    SHORT    CLR_WINDOW
  5003.  
  5004. CLR_SCR PROC    NEAR
  5005.     XOR    CX,CX
  5006.  
  5007. CLR_EOS    PROC    NEAR
  5008.     MOV    DX,END_WINDOW        ;Row 25; column 79.
  5009.  
  5010.     CALL    CURSOR_OFF
  5011.  
  5012. ;-------------------------------------------------------------------;
  5013. ; Clear arbitray window to attribute specified in AL
  5014. ; On entry :    AL     = screen attribute to use
  5015. ;        CH, CL = row, col of upper left
  5016. ;        DH, DL = row, col of lower right
  5017. ; Modifies : AX, saves BX, BP
  5018. ;-------------------------------------------------------------------;
  5019. CLR_WINDOW      PROC    NEAR
  5020.     PUSH    BP
  5021.     PUSH    BX
  5022.     MOV    BH,AL
  5023.     MOV    AX,600H
  5024.     INT    10H
  5025.     POP    BX
  5026.     POP    BP
  5027.     RET
  5028. CLR_WINDOW    ENDP
  5029. CLR_EOS        ENDP
  5030. CLR_SCR        ENDP
  5031. CLR_EOL        ENDP
  5032. CLR_MSG        ENDP
  5033.  
  5034. ;CLR_DOS_WIN     PROC    NEAR
  5035. ;        MOV     AL,ORIG_ATT
  5036. ;        MOV     CX,BEG_DOS
  5037. ;        CALL    CLR_EOS
  5038. ;        MOV     DX,BEG_DOS - 100h
  5039. ;        CALL    SET_CURSOR
  5040. ;        RET
  5041. ;CLR_DOS_WIN             ENDP
  5042.  
  5043.  
  5044.  
  5045.  
  5046.  
  5047. SUBTTL Bios Interface (non-screen)
  5048. page
  5049. ;******************************************
  5050. ;  OTHER BIOS ROUTINES
  5051. ;******************************************
  5052. ;------------------
  5053. ; Set cursor off
  5054. ;------------------
  5055. CURSOR_OFF    PROC    NEAR
  5056.     PUSH    CX
  5057.     MOV    CX,2000H
  5058.     JMP    SHORT _CU1
  5059.  
  5060. ;------------------------------
  5061. ; Set cursor on
  5062. ;------------------------------
  5063. CURSOR_ON    PROC    NEAR
  5064.     PUSH    CX
  5065.     MOV    CX,CURSOR_TYPE
  5066. ;------------------------------
  5067. ; Set cursor size
  5068. ; On entry :    CH = start line
  5069. ;        CL = stop line
  5070. ;------------------------------
  5071. _CU1:    PUSH    AX
  5072.     MOV    AH,1
  5073.     INT    10H
  5074.     POP    AX
  5075.     POP    CX
  5076.     RET
  5077. CURSOR_ON    ENDP
  5078. CURSOR_OFF    ENDP
  5079.  
  5080. ;---------------------------------------------------------;
  5081. ; Move the cursor, 
  5082. ; On entry : DH, DL = cursor position, (0,0)= upper left
  5083. ;---------------------------------------------------------;
  5084. SET_CURSOR    PROC    NEAR
  5085.     PUSH    SI
  5086.     XOR    BH,BH            ;Page zero.
  5087.     MOV    AH,2            ;Set cursor.
  5088.     INT    10H
  5089.     CALL    CURSOR_ON
  5090.     POP    SI
  5091.     RET
  5092. SET_CURSOR    ENDP
  5093.  
  5094. ;-------------------------------------------------------------------;
  5095. ; Beep via DOS.
  5096. ;-------------------------------------------------------------------;
  5097. BEEP    PROC    NEAR
  5098.     MOV    DL,7
  5099.     MOV    AH,2
  5100.     INT    DOSINT
  5101.     RET
  5102. BEEP    ENDP
  5103.  
  5104. ;-------------------------------------------------------------------;
  5105. ; Retrieve keystroke via BIOS.
  5106. ; Returns : ascii value in AL,
  5107. ;      : scan code in AH
  5108. ;-------------------------------------------------------------------;
  5109. READ_KEY    PROC    NEAR
  5110.     MOV    AH,0
  5111.     INT    16H
  5112.     RET
  5113. READ_KEY    ENDP
  5114.  
  5115. ;-------------------------------------------------------------------;
  5116. ; Check for keystroke via BIOS.
  5117. ; returns Z Flag set if no char
  5118. ;         character in AX if NZ
  5119. ;-------------------------------------------------------------------;
  5120. CK_KEY    PROC    NEAR
  5121.     MOV    AH,1
  5122.     INT    16H
  5123.     RET
  5124. CK_KEY    ENDP
  5125.  
  5126. SUBTTL Dos interface subroutines
  5127. page
  5128. ;******************************************
  5129. ;        DOS FUNCTION CALLS
  5130. ;******************************************
  5131.     ASSUME    DS:_TEXT,ES:_TEXT
  5132. ;-------------------------------;
  5133. ; This subroutine opens a file. ;
  5134. ; On entry : AL = open mode
  5135. ;          DS:DX =ASCIIZ path name
  5136. ; Returns  : AX = error codes if carry set
  5137. ;-------------------------------;
  5138. OPEN_FILE    PROC    NEAR
  5139.     MOV    AH,3DH
  5140.     INT    DOSINT
  5141.     RET
  5142. OPEN_FILE    ENDP
  5143.  
  5144. ;-------------------------------;
  5145. ; This subroutine closes a file. ;
  5146. ; On entry : BX = file handle
  5147. ; Returns  : AX = error codes if carry set
  5148. ;-------------------------------;
  5149. CLOSE_FILE    PROC    NEAR
  5150.     MOV    AH,3EH
  5151.     INT    DOSINT
  5152.     RET
  5153. CLOSE_FILE    ENDP
  5154.  
  5155. ;------------------------------------------------; 
  5156. ; This subroutine finds the first matching file. ;
  5157. ; On entry : CX = attribute used in searching
  5158. ;         DS:DX =ASCIIZ drive, path and filename
  5159. ; Returns  : AX = error codes if carry set
  5160. ;------------------------------------------------;
  5161. FIND_FIRST    PROC    NEAR
  5162.     MOV    AH,4EH
  5163.     INT    DOSINT
  5164.     RET
  5165. FIND_FIRST    ENDP
  5166.  
  5167. ;--------------------------------------------------------------;
  5168. ; These two subroutines retrieve or change a file's attribute. ;
  5169. ; On entry : DS:DX =ASCIIZ pathname
  5170. ;         CX = attribute 
  5171. ; Returns  : AX = error codes if carry set
  5172. ;--------------------------------------------------------------;
  5173. CHMOD    PROC    NEAR
  5174.     MOV    AX,4301H
  5175.     INT    DOSINT
  5176.     RET
  5177. CHMOD    ENDP
  5178.  
  5179. GETMOD    PROC    NEAR
  5180.     MOV    AX,4300H
  5181.     INT    DOSINT
  5182.     RET
  5183. GETMOD    ENDP
  5184.  
  5185. ;------------------------------------------------------------------; 
  5186. ; This subroutine gets the disk space available on the target drive
  5187. ; On entry : DX points to [d:]filename
  5188. ; Returns  : available space in DX:AX
  5189. ; Modifies : AX, BX, CX, DX, SI
  5190. ;------------------------------------------------------------------;
  5191.     ASSUME    DS:_TEXT,ES:_TEXT
  5192. GET_BYTES_FREE    PROC    NEAR
  5193.     MOV    SI,OFFSET ENTRY        ;Retrieve pointer to target file.
  5194.     MOV    AX,[SI]            ;get two bytes
  5195.     AND    AL,5FH            ;Capitalize.
  5196.     CMP    AH,":"            ;Is there a drive request?
  5197.     JZ    _G_B_1            ;If no, get default drive.
  5198.     MOV    AL,DEST_PATH        ;Assume default drive.
  5199.  
  5200. _G_B_1:    MOV    TARG_DISK,AL        ;save it
  5201.     ;let run on to DISK_FREE
  5202. ;----------------------------------------------; 
  5203. ; This subroutine retrieves available clusters ;
  5204. ; and converts it to hexidecimal bytes free.    ;
  5205. ; On entry :    AL specifies a drive letter in ASCII 
  5206. ; Returns  :    DX:AX = bytes free on disk
  5207. ;        BX    = clusters free
  5208. ;        CX    = bytes per cluster
  5209. ; Modifies : AX, BX, CX, DX
  5210. ;----------------------------------------------;
  5211.     ASSUME    DS:_TEXT,ES:_TEXT
  5212. DISK_FREE    PROC    NEAR
  5213.     PUSH    AX
  5214.     AND    AL,1FH            ;ignore case
  5215.     MOV    DL,AL
  5216.     MOV    AH,36H            ;Disk free space.
  5217.     INT    DOSINT
  5218.     INC    AX            ;-1 if not drive not valid
  5219.     JNZ    _D_F0            ;ok
  5220.     STC                ;bad drive - set carry
  5221.     POP    AX
  5222.     RET                ;return failure
  5223.  
  5224. _D_F0:    DEC    AX            ;restore correct ax
  5225.     XOR    DX,DX
  5226.     MUL    CX        ;sectors per cluster times bytes per sector.
  5227.     MOV    CX,AX        ;save cluster size for other calculations
  5228.     MUL    BX        ;bytes per cluster times clusters
  5229.     POP    BX
  5230.  
  5231.  
  5232.     CMP    BL,TARG_DISK        ;save it
  5233.     JNZ    UPD_FREE_COUNT
  5234.     MOV    TARG_BYTES_FREE,AX
  5235.     MOV    TARG_BYTES_FREE+2,DX
  5236.     MOV    TARG_CLUSTER,CX
  5237.  
  5238. UPD_FREE_COUNT    PROC    NEAR
  5239.     CMP    BL,DEST_PATH        ;test if TARG=DEST
  5240.     JNZ    _D_F1
  5241.     MOV    DEST_BYTES_FREE,AX    ;update dest disk values too
  5242.     MOV    DEST_BYTES_FREE+2,DX    ;
  5243.     MOV    DEST_CLUSTER,CX
  5244.  
  5245.     PUSH    DX
  5246.     PUSH    CX
  5247.     PUSH    BX
  5248.     PUSH    AX
  5249.     MOV    DI,OFFSET D_FREE    ;Point to storage.
  5250.     MOV    CX,LENGTH D_FREE
  5251.     CALL    FORMAT        ;Convert hex to decimal and store.
  5252.     POP    AX
  5253.     POP    BX
  5254.     POP    CX
  5255.     POP    DX
  5256.  
  5257. _D_F1:    CMP    BL,WORK_PATH        ;test if TARG=WORK
  5258.     JNZ    _D_F2
  5259.     MOV    WORK_BYTES_FREE,AX    ;update work disk values too
  5260.     MOV    WORK_BYTES_FREE+2,DX    ;
  5261.     MOV    WORK_CLUSTER,CX
  5262.  
  5263.     MOV    DI,OFFSET W_FREE    ;Point to storage.
  5264.     MOV    CX,LENGTH W_FREE
  5265.     CALL    FORMAT        ;Convert hex to decimal and store.
  5266.  
  5267. _D_F2:    CLC
  5268. _D_F_RET:
  5269.     RET
  5270.  
  5271. UPD_FREE_COUNT    ENDP
  5272. DISK_FREE    ENDP
  5273. GET_BYTES_FREE    ENDP
  5274.  
  5275. ;------------------------------------------------------------------; 
  5276. ; This subroutine requests a block of free memory
  5277. ; Returns  :    Allocated memory at AX:0
  5278. ;        Memory allocated in BX
  5279. ; Modifies : everything except SI?
  5280. ;------------------------------------------------------------------;
  5281.     ASSUME    DS:_TEXT,ES:_TEXT
  5282. GET_MEM        PROC    NEAR
  5283.     MOV    BX,0A000H        ;Request the world (640k)
  5284. _G_M1:    PUSH    SI            ;save pointer
  5285.     MOV    AH,48H            ;ax returns pointer to block
  5286.     INT    DOSINT            ;bx returns paragraphs allocated
  5287.     POP    SI
  5288.     JNC    _G_M2            ;success
  5289.     CMP    AL,8            ;check for a nasty error
  5290.     JNZ    _G_M_ER            ; not just insufficient memory 
  5291.     AND    BX,0F000h        ;round available mem to N 64k segs
  5292.     JNZ    _G_M1            ;try again if not zero
  5293. _G_M_ER:
  5294.     MOV    N_SEGS,0        ;reset segs available
  5295.     STC
  5296.     RET                ;uh-oh, not just error 8
  5297.  
  5298. _G_M2:    MOV    MEM_BUF_SEG,AX        ;save start of file buf
  5299.     MOV    CL,4            ;x16 to find top byte
  5300.     SHR    BH,CL            ;of this seg and then
  5301.     JZ    _G_M_ER            ;no memory
  5302.     MOV    N_SEGS,BH        ;save it
  5303.     CLC
  5304. _G_M_X:    RET
  5305.  
  5306. GET_MEM    ENDP
  5307.  
  5308. ;------------------------------------------------------------------; 
  5309. ; This subroutine releases memory allocated by GET_MEM
  5310. ; On entry : MEM_BUF_SEG conatins segment pointer of allocated memory
  5311. ;------------------------------------------------------------------;
  5312. RELEASE_MEM    PROC    NEAR
  5313.     CMP    N_SEGS,0
  5314.     JZ    _R_MEM_RET
  5315.     PUSH    ES
  5316.     MOV    ES,MEM_BUF_SEG
  5317.     MOV    AH,49H            ;free allocated block
  5318.     INT    DOSINT
  5319.     POP    ES
  5320.     MOV    N_SEGS,0        ;reset segs available
  5321. _R_MEM_RET:
  5322.     RET
  5323. RELEASE_MEM    ENDP
  5324.  
  5325. ;-------------------------------------------;
  5326. ; This is the new Critical Error interrupt. ;
  5327. ; all registers are saved
  5328. ;-------------------------------------------;
  5329. DISK_ERROR    proc    far
  5330.     ASSUME    CS:_TEXT
  5331.     STI                ;Interrupts back on.
  5332.     PUSHF                ;Save all registers.
  5333.     PUSH    ES
  5334.     PUSH    DS
  5335.     PUSH    BP
  5336.     PUSH    DI
  5337.     PUSH    SI
  5338.     PUSH    DX
  5339.     PUSH    CX
  5340.     PUSH    BX
  5341.     PUSH    AX
  5342.  
  5343.     MOV    BX,CS
  5344.     MOV    DS,BX            ;Point to our data segment.
  5345.     MOV    ES,BX
  5346.  
  5347.     assume    cs:_TEXT, ds:_TEXT, es:_TEXT
  5348.     ADD    AL,"A"            ;convert failed drive to char
  5349.     MOV    ERROR_DISK,AL
  5350.     CALL    CLR_MSG            ;Clear current message.
  5351.     MOV    SI,OFFSET DISK_MSG    ;Display disk error message.
  5352.     MOV    DI,PROMPT_LOC
  5353.     CALL    PUT_STRING
  5354.     MOV    DI,PROMPT_LOC2        ;Display rest of error message.
  5355.     CALL    PUT_STRING
  5356.  
  5357. _D_ER_1:
  5358.     CALL    READ_KEY        ;Get a response to message.
  5359.     MOV    AL,1            ;assume a retry
  5360.     CMP    AH,13H            ;Was it scan code for "R"?
  5361.     JZ    _D_ER_2            ;If yes retry.
  5362.     INC    AL
  5363.     INC    AL            ;ret al=3 to fail
  5364.     CMP    AH,1            ;Is it Esc?
  5365.     JZ    _D_ER_2            ;If yes, exit delete.
  5366.     CMP    AH,10H            ;Was it "Q"?
  5367.     JNZ    _D_ER_1            ;If no, wait until correct response
  5368.     JMP    TERMINATE        ;Else, exit to DOS.
  5369.  
  5370. _D_ER_2:
  5371.     PUSH    AX            ;save return option
  5372.     CALL    DISP_COUNT_MSG        ;Clear disk error message.
  5373.     POP    BX            ;get back option
  5374.     POP    AX            ;Restore registers.
  5375.     MOV    AL,BL            ;put return option in AL
  5376.     POP    BX            ;restore remaining registers
  5377.     POP    CX
  5378.     POP    DX
  5379.     POP    SI
  5380.     POP    DI
  5381.     POP    BP
  5382.     POP    DS
  5383.     POP    ES
  5384.     POPF
  5385.     IRET
  5386. DISK_ERROR    ENDP
  5387.  
  5388.                 even
  5389. PGM_NAME    DB    0        ;program name for CALL_DOS
  5390. INITIAL_PATH    EQU    PGM_NAME+80
  5391. WORK_PATH    EQU    INITIAL_PATH+70
  5392. DEST_PATH    EQU    WORK_PATH+70
  5393. SOURCE        EQU    DEST_PATH+70
  5394. TARGET        EQU    SOURCE+70+13
  5395. TARG_DISK    EQU    TARGET+70+13
  5396. ENTRY        EQU    TARG_DISK+2
  5397. TMP_BUFF    EQU    ENTRY+36
  5398. DIR_BUFF    EQU    TMP_BUFF+22
  5399.  
  5400. _TEXT ENDS
  5401. END  START
  5402.  
  5403.