home *** CD-ROM | disk | FTP | other *** search
- Page 80,132
- title DC.asm Directory Control /copy/del/move/view program
-
- ;compile options:
- ;SMALL equ -1 ;routines optimized for size rather than speed
- ;SAG equ -1 ;Steve Grandi's mods for UNIX '-' switchchar
- ;BLANK_BIT equ 4 ;view option - see below
-
- COMMENT |
- Revision history:
-
- DC version 1.1 - August, 1991 (Gerhard Karnik - garyk@cbnewsk.att.com)
- Original DOS screen is restored upon exit from program (up to 132x50)
- ALT 1 now calls up vpic (by default)
- ALT 2 now calls up vplay (by default)
- Marked-file-bytes display now works if more than 10 meg bytes
-
- DC version 1.07 - June, 1990 (Gerhard Karnik - garyk@cbnewsk.att.com)
- Support for screen sizes other than 80x25
-
- DC version 1.06f - September 2, 1989
- Fix VIEW bug in number of lines displayed
- New patch location for default sort
- Reverse logic of snow check patch point
- Fix get_mem bug when less than 64k to grab
- complements Russell Nelson:
- Sensing the EGA and disengaging snow control if one is present,
- Changing the menu if they hold down the Alt or Ctrl key.
- Other additions:
- RMDIR and MKDIR
-
- DC version 1.05 - October 24, 1988
- Fix minor bug in return from shell
- Add Ins/Del as duplicates to Grey +/- keys
- Put Menu changes
- Fix Backspace bug
- Fix Sort msg clear problem introduced in 1.04
- Restore Ctrl-Break status in DOS Shell
-
- DC version 1.04d - May 29, 1988
- Work on display speed/ cursor overrun problem
- Rename a few subroutines (for clarity?)
-
- DC version 1.04a - May 12, 1988
- Changed memory management for DOS shell
- Add Steve Grandi's modifications
- add Alt-F2 as "shell to DOS" command
- (If SWITCH != '/', make all output strings use '/' as path delimiter)
- (eliminate CR as view mode exit character)
-
- DC version 1.03(f) - May 9, 1988
- Save and restore original text attribute
- Simplify clutter of clear window subroutines
- Add customizable option switchchar for UNIX hacks
- Fix bug occurring in copy of 0 byte size files
- Fix error that occurs when rename is applied to destination dir
- Fix writing to prn once more
- Add Refresh to original order sort
- Minor fixes and revisions to save a few bytes
- Add rename for directories
- More work on error recovery - write protected target
-
- DC version 1.02 - March 22, 1988
- Add escape/return to error handler
- Fix minor bug in view/ascii and wrap of 80 char + cr,lf
- Added Alt-F1 "Protected Copy" function.
- Tweaked file view function to save 4 bytes.
- Now highlights last sub-dir viewed when returning to parent dir
-
- DC version 1.01 - March 7, 1988
- Modified method of handling directory changes
- F9 (change work dir) now relative to displayed work dir
- Allow specifying both source and dest paths on entry
-
- Earlier versions COD1 through COD9: Dec '87 to Mar. '88
- Combined DR and CO,
- Re-worked file read/write sequence to minimize disk swaps
- Expanded file copy buffer to available memory
- Added ability to change directories
- Expanded display of bytes free to include both source and target disks
- Added "spedometer" display of bytes in marked files
- Added "View" options to :
- Toggle word wrap,
- Horizontal scroll
- Blanking or full suppression of non-ASCII
-
-
- Features that could be added:
-
- List options: search/scan for text
- display current horizontal scroll position
- improve provisions for re-synch in mode toggles
- Fix bug when shelling to DOS when >80 columns
-
-
- | ;end comments
-
-
- ;program equates:
- nul equ 00h
- tab equ 09h
- cr equ 0dh
- lf equ 0ah
- space equ 20h
-
- ;macro to calculate position in display memory; AX,BX,DX destroyed
- CROW MACRO COL,ROW,ADDR
- mov bx,SCREEN_COLS
- shl bx,1
- mov ax,ROW
- mul bx
- mov bx,COL
- shl bx,1
- add ax,bx
- mov ADDR,ax
- ENDM
-
- DOSINT EQU 21h
- COPY_MARK EQU 26
-
- ALT_SHIFT EQU 08H
- CTRL_SHIFT EQU 04H
- HOT_SHIFT EQU ALT_SHIFT+CTRL_SHIFT
-
- ROW1 EQU 2
-
- WHERE_LOC EQU 14 ;col to display current location in view
- WHERE_LEN EQU 08 ;col's allocated
-
- ; locations of data within DTA after FIND_FIRST
- F_ATTR EQU 21
- F_TIME EQU 22
- F_DATE EQU 24
- F_SIZE EQU 26
- F_NAME EQU 30
-
- DIR_RECORD STRUC
- D_MRK DB ?
- D_NAME DB 8 DUP (?)
- DB ?
- D_EXT DB 3 DUP (?)
- DB ?
- D_SIZE DB 8 DUP (?)
- DB ?,?
- D_DATE DB 8 DUP (?)
- DB ?,?
- D_TIME DB 6 DUP (?)
- D_HID DB ?
- D_SYS DB ?
- D_RO DB ?
- D_ARC DB ?
- DIR_RECORD ENDS
-
- FIELD_SIZE EQU 1 + D_ARC - D_MRK
- BAR_LEN EQU D_HID - D_NAME
- ;
- SUBTTL Segment data defines
- page
- ROM_BIOS_DATA SEGMENT AT 40h ; Low Memory "BIOS" Parameters
- ;
- org 10h ; Location of EQUIP_FLAG
- EQUIP_FLAG dw ? ; Contains video settings
- ; in bits 4 and 5
- org 17h ; Location of KB_FLAG
- KB_FLAG db ? ; Contains Alt (bit 3) &
- ; Right Shift (bit 0) States
- org 49h ; Location of CRT_MODE
- CRT_MODE db ?
- org 4ah ; Location of DOS_COLS
- DOS_COLS db ?
- org 84h ; Location of DOS_ROWS
- DOS_ROWS db ?
- ;
- org 63h
- ADDR_6845 dw ?
- CRT_MODE_SET db ?
- ROM_BIOS_DATA ends
- ;
- DUMMY_SEG SEGMENT AT 1000H
- ORG 00H
- PAGES DW 7F0h DUP (?) ;table of screen page sizes
- FILE_BUFF DB ?
-
- ORG 0FFE8H
- END_BUFF DW 0 ;dummy place holder
- READ_SIZE EQU ((END_BUFF - FILE_BUFF)/2) AND 0F800h
-
- FILE_PTR DW ?
- DW ?
- RETRN_PTR DW ?
- DW ?
- FILE_END DW ?
- LAST_PAGE DW ?
- THIS_SCREEN DW ?
- LAST_COL DW ?
- ROW DB ?
- DUMMY_SEG ENDS
- ;
- _TEXT SEGMENT WORD PUBLIC 'CODE'
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- ;
-
- ORG 2
- PSP_TOP_MEM LABEL WORD ;last paragraph of available mem
- ORG 6
- PSP_TOP_SEG LABEL WORD
- ORG 2Ch
- PSP_ENV_SEG LABEL WORD
-
- ORG 5CH
- PSP_FCB DB ?
-
- ORG 80H
- CMD_LINE LABEL BYTE
- DTA LABEL BYTE
-
- SUBTTL Data area
- page
- ORG 100H
- START: JMP MAIN
- ;
-
- ;0=black 1=blue 2=green 3=cyan
- ;4=red 5=magenta 6=brown 7=light gray
- ;8=gray 9=light blue A=light green B=light cyan
- ;C=light red D=light mag. E=yellow F=intense white
-
- C_NORMAL DB 7 ;dir text attribute
- C_INTENSE DB 0Bh ;path name attribute
- C_MENU_ATT DB 1BH ;menu text attribute
- C_BORDER DB 1FH ;menu border attribute
- C_INVERSE DB 70H + 4 ;high-lighted dir entry
-
- SWITCH DB '/'
- STATUS_REG DW 0ffh ;non-zero enables snow check
- DIRALLOC DW 0800h ;minimum memory for file dir
-
- NORMAL DB 07H
- INTENSE DB 0FH
- MENU_ATT DB 07H
- BORDER DB 0FH
- INVERSE DB 70H
- COLORS EQU $ - OFFSET NORMAL
- BAR_ATTRIBUTE DB 70H
- ORIG_ATT DB ? ;original screen attribute
-
- DISPLAY_BIT EQU 80H
- WRAP_BIT EQU 1
- ASCII_BIT EQU 2
-
- BLANK_BIT EQU 4 ;comment out this line to eliminate this option
- HEX_BIT EQU 8
-
- STAR_MASK DB 0FFH
- VIEW_FLAGS DB WRAP_BIT
- OPTIONS DB ' WA'
- ifdef BLANK_BIT
- DB 'B'
- endif
- DB 'H'
- OPTIONS_LEN EQU $ - OPTIONS
-
- PATCH_43LINE DB 0
-
- N_SEGS DB ?
- SEG_COUNT DB ?
- MEM_BUF_SEG DW 0F000H
-
- VERIFY_STAT DB 0
- BREAK_STAT DB 0
- SORT_OPT DB "NESDO"
- SORT_OPT_CNT EQU $ - SORT_OPT
- EVEN
- SORT_TABLE DW 1200h ;name
- DW 309h ;extension
- DW 800h + 13 ;size
- DW 29 ;date
- DW -1 ;no sort
- SORT_TABLE_END EQU $ - 2
- SORT_OFFSET DW 0 ;start of field on which to sort
- SORT_LEN DB 12
-
- FUNCTION DB 0 ;flag byte to identify function request
- COPY_BIT EQU 1 ;read/write file
- DELETE_BIT EQU 2 ;delete file (may follow a move)
- MOVE_BIT EQU 4 ;across dir move via rename
- RENAME_BIT EQU 8 ;simple rename
- PROTECT_BIT EQU 10H ;check if file already exists on dest
- DIR_OK_BIT EQU 20H ;allow function on directory
- UPD_CNT_BIT EQU 80H ;force update of bytes free display
-
- CURSOR_TYPE DW ?
- VIDEO_SEG DW 0B000H
-
- CURRENT_MENU DW ? ;normal or alt menu
- SEARCH_ATTRIB DW 17H ;what attrib files to display
- CUR_OFFSET DW ? ;ptr to first entry on displayed page
- CUR_FILE DW ? ;GET_NAME returned ptr to dir record
- END_OFFSET DW ?
- DIR_DISP_END DW ?
- LINE DW ?
- COUNT DW ?
- MARK_CNT DW ?
- SEARCH_COUNT DW ?
- FILE_CNT DW ?
- FILENAME_END DW ?
- READ_HANDLE DW ?
- WRITE_HANDLE DW ?
- SOURCE_ATTRIB DW ?
- TARGET_ATTRIB DW ?
- SIZE_LOW DW ?
- SIZE_HIGH DW ?
- SOURCE_TIME DW ?
- SOURCE_DATE DW ?
- FILE_NAME DW ?
- WORK_BYTES_FREE DW ?
- DW ?
- WORK_CLUSTER DW ?
- DEST_BYTES_FREE DW ?
- DW ?
- DEST_CLUSTER DW ?
- TARG_BYTES_FREE DW ?
- DW ?
- TARG_CLUSTER DW ?
- MARK_BYTES DW ?
- DW ?
- TEMP DW ? ;for temporary storage
-
- ;------DOS SHELL VARIABLES------
- STK_SEG DW ? ;original SS contents for CALL_DOS
- STK_PTR DW ? ;original SP contents for CALL_DOS
- ENV_SEG DW ? ;segment containing environment block
- COM_VAR DB 'COMSPEC=',0 ;environment variable to match
- ;Parameter block for CALL_DOS
- DOS_PROG DB 0,CR ;DOS command to execute for DOS_SHELL
- DOS_PROG1 DB 'vpic /a', 0, 32 dup(20h) ;DOS_SHELL1 cmd
- DOS_PROG2 DB 'vplay' , 0, 34 dup(20h) ;DOS_SHELL2 cmd
- DOS_LINE DB 75,'/c ',70 dup(20h),CR ;DOS_SHELL1&2 command tail
- PAR_BLK DW 0 ;Use parent's environment
- DW ? ;Point to command tail
- OFFDOSLINE DW ? ;Segment of command tail (filled later)
- DW 4 DUP (0FFh) ;FCB pointers (dummies!)
-
- DISPATCH_KEY label byte ;table of scan codes
- DB 01H,4AH,4EH,1CH ;esc, -, +, cr
- DB 3BH,3CH,3DH,3EH,3FH ;F1, F2, F3, F4, F5
- DB 40H,41H,42H,43H,44H ;F6, F7, F8, F9, F10
- DB 68H,69H,6AH,6BH ;Alt-F1, Alt-F2, Alt-F3, Alt-F4
- DB 71h ;Alt-F10
- DB 52h,53h ;Ins, Del
- DB 78h,79h ;Alt-1, Alt-2
- SORT_KEYS label byte ;must match SORT_OPT table
- DB 31H,12H,1FH,20H,18H ;N, E, S, D, O
- DB 2EH,2FH,32H,13H,10H ;C, V, M, R, Q
-
- VIEW_KEYS label byte
- DB 47H,48H,49H,4FH ;home, up, pgup, end
- DB 50H,51H,76H,84H ;down, pgdn, ^pgdn, ^pgup
- DB 37H,1EH,30H,11H,23H ;*, A, B, W, H
- DISPATCH_CNT EQU $ - DISPATCH_KEY
- DB 4BH,4DH ;left, right
- VIEW_CNT EQU $ - VIEW_KEYS
-
- even
- DISPATCH_TABLE label word
- DW EXIT, UNMARK, MARK, VIEW
- DW COPY, DELETE, MOVE, RENAME, CLEAR_MARK
- DW MARK_BLANK, SWAP_MARK, SWAP_DIR, CD_WORK, CD_DEST
- DW PCOPY, DOS_SHELL, MKDIR, RMDIR
- DW TOGGLE_ROWS
- DW MARK, UNMARK
- DW DOS_SHELL1, DOS_SHELL2
- DW RE_SORT, RE_SORT, RE_SORT, RE_SORT, RE_SORT
- DW COPY, VIEW, MOVE, REFRESH, QUIT
- DW HOME_BAR, UP_ARROW, PG_UP, END_BAR
- DW DN_ARROW, PG_DN, BOTTOM_BAR, TOP_BAR
- DW STAR, ASCII, BLANK, WRAP, HEXDUMP
- DISPATCH_END EQU $ - 2
-
- ;data added for view function
- VIEW_TABLE label word
- DW HOME_FILE, UP_LINE, UP_PG, END_FILE
- DW DN_LINE, DN_PG, END_FILE, HOME_FILE
- DW STAR, V_ASCII, BLANK, VWRAP, VHEX
- DW LEFT, RIGHT
- VIEW_TABLE_END EQU $ - 2
-
- ;error messages
- NOT_ENOUGH DB "Requires 64K free RAM$"
- TOO_MANY DB "Too many files$"
- NO_COMSPEC DB "No COMSPEC variable in environment$"
-
- ;main menu
- ;Graphics border characters:
- GB_TL EQU 201 ;Top left
- GB_TH EQU 205 ;Top horizontal
- GB_TR EQU 187 ;Top right
- GB_L_TEE EQU 199 ;Left Tee
- GB_R_TEE EQU 182 ;Right Tee
- GB_MH EQU 196 ;Middle line horizontal
- GB_BL EQU 200 ;Bottom left
- GB_BR EQU 188 ;Bottom right
- GB_BH EQU 205 ;Bottom Horizontal;
- GB_V EQU 186 ;Vertical border
-
- LOGO DB " Directory Control "
- MENU_WIDTH EQU $ - OFFSET LOGO
- DB " Version 1.1 "
- LOGO_ROWS EQU ($ - OFFSET LOGO)/MENU_WIDTH
-
- MENU1 LABEL BYTE
- DB " F1 Copy "
- DB " F2 Delete "
- DB " F3 Move "
- DB " F4 Rename "
- DB " F5 Clear marks "
- DB " F6 Mark remainder"
- DB " F7 Swap Mrk/Unmrk"
- DB " F8 Swap Dir/Dest."
- DB " F9 Change Dir "
- DB " F10 Change Dest. "
- DB " (ALT for more cmds)"
- DB " ─┘ View / ChDir "
- DB " +/- Mark/Unmark "
- DB "Esc or Alt-Q to Exit"
- MENU1_ROWS EQU ($ - OFFSET MENU1)/MENU_WIDTH
- MENU_ROWS EQU 3 + LOGO_ROWS + MENU1_ROWS
-
- BEG_DOS EQU (2+MENU_ROWS) * 100h
- BEG_WINDOW EQU 44 + (2+MENU_ROWS) * 100h
-
- ;Menu to display with alt key pressed
- CTRL_MENU LABEL BYTE
- ALT_MENU LABEL BYTE
- DB " F1 Prot.- Copy "
- DB " F2 DOS Shell "
- DB " F3 MkDir (Destin) "
- DB " F4 RmDir (Source) "
- DB " F10 Toggle 43 Rows "
- DB " "
- DB " 1 Execute CMD 1 "
- DB " 2 Execute CMD 2 "
- DB " "
- DB " Sort Options: "
- DB " N,E,D,S or O "
- DB " "
- DB " "
- DB " View Options: *WABH"
-
- comment | ignore this for now
- ;This is a proposed alternate menu
- CTRL_MENU LABEL BYTE
- DB " F1 Prot.- Copy "
- DB " F2 DOS Shell "
- DB " F4 Remove Directory"
- DB " F9 MkDir (Source) "
- DB " F10 MkDir (Dest.) "
- DB " "
- DB " Sort Options: "
- DB " N,E,D,S or O "
- DB " "
- DB " "
- DB "Esc or Alt-Q to Exit"
- |
- ;string constants and screen locations
-
- ENTRY_CUR EQU 47 + (4 + MENU_ROWS) * 100h
-
- INVALID DB "Error: Invalid drive or directory",0
- LOAD_SORT_MSG DB "Loading and "
- SORT_MSG DB "Sorting directory.",0
- LOAD_MSG DB "Loading directory.",0
-
- DIRECTORY DB "Directory of ",0
-
- FILES DB 3 DUP(space)
- DB " File(s) with "
- W_FREE DB 8 DUP (space)
- DB " bytes free",0
-
- DEST_MSG DB "Default destination ",0
-
- DEST_FREE DB "Destination disk has "
- D_FREE DB 8 DUP(space)
- DB " bytes free",0
-
- BYTES_MRKD_MSG DB 8 DUP(space)
- DB " Bytes in"
- FILES_MRKD_MSG DB 4 DUP(space)
- DB " "
- MARKED_MSG DB "Marked files",0
-
-
- DELETE_MSG DB " will be deleted.",0
- DB "Do you wish to delete? Y/N",0
- DISK_MSG DB "Error reading drive "
- ERROR_DISK DB " ",0
- DB "(R)etry, (Q)uit or Escape?",0
- PCOPY_MSG DB "P-"
- COPY_MSG DB "Copy ",0
- MOVE_MSG DB "Move ",0
- RENAME_MSG DB "Rename ",0
- CD_MSG DB "Change directory",0
- CHDEST_MSG DB "Change default destination",0
- TO_MSG DB " to...",0
- MKDIR_MSG DB "Create directory",0
- STAR_DOT_STAR DB "*.*",0
- DIRECTORIES DB "<DIR>"
-
- ;Screen size dependant variables
-
- ROW_LEN DW ?
- BAR_START DW ?
- SCREEN_ROWS DW 0
- SCREEN_COLS DW 0
- DIR_ROWS DW 0
- DIR_ROW_END DW ?
- VIEW_ROWS DB ?
- LAST_ROW DW 0
-
- MENU_STRT DW ?
-
- PROMPT_LOC DW ?
- PROMPT_LOC2 DW ?
-
- LOAD_SORT_LOC DW ?
- SORT_LOC DW ?
- LOAD_LOC DW ?
- DIRECT_LOC DW ?
- FILES_LOC DW ?
- DEST_LOC DW ?
- D_FREE_LOC DW ?
-
- MARKED_LOC DW ?
- MARKED_WIN DW ?
-
- END_WINDOW DW ? ;79 + 24 * 100h for C80 screen
-
- ENTRY_ROWS DB ? ;This set of variables are used to
- VID_ADAPT DB 'C' ;restore DOS screen upon exit
- ENTRY_VID_MODE DB ?
-
- ;DOS video information at the time this program is first run
-
- DOS_SCREEN_LINES DB ?
- DOS_SCREEN_COLS DB ?
- DOS_VIDMODE DB ?
- DOS_CURSOR_ROW DB ?
- DOS_CURSOR_COL DB ?
- DOS_SCREEN_BUF DW 132*51 DUP (00h)
-
- SUBTTL Main program loop
- page
- ; CODE AREA
- ;----------------------------------------------------------------------------;
- ; Some housekeeping first. Since we will be changing the default drive ;
- ; and directory to the requested drive and directory, we need to save the ;
- ; current defaults, so they can be restored. Install critical error trap. ;
- ;----------------------------------------------------------------------------;
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- MAIN PROC NEAR
-
- MOV AX,3300H ;Get Control Break status.
- INT DOSINT
- MOV BREAK_STAT,DL ;and save it
-
- MOV AX,3301H ;Turn Control Break off.
- MOV DL,0
- INT DOSINT
-
- MOV AH,54H ;Get current verify flag.
- INT DOSINT ; and save.
- MOV VERIFY_STAT,AL ;(use /V switch to set verify on)
-
- MOV DX,OFFSET DISK_ERROR ;Install critical error trap.
- MOV AX,2524H
- INT DOSINT
-
- CLD ;String moves forward.
- CALL UPD_DEST ;save dir info about dest
- MOV SI,OFFSET DEST_PATH ;Point to storage.
- MOV DI,OFFSET INITIAL_PATH ; make copy of starting point
- MOV CX,68 ;length of path
- REP MOVSB
-
- call SET_SCREEN_VARS ;Set screen size dependant variables
-
- ;---------------------------------------------------------------------;
- ; More housekeeping. We will be writing directly to the screen buffer ;
- ; so we need the display card address and the status register. ;
- ;---------------------------------------------------------------------;
-
- MOV AX,ROM_BIOS_DATA ;Point to the ROM BIOS data area
- MOV DS,AX ; and get base address of active
- ASSUME DS:ROM_BIOS_DATA
- MOV AX,ADDR_6845 ; display card.
- mov bl,CRT_MODE ;Current video mode
- mov cl,DOS_ROWS ;Physical display rows - 1
- PUSH CS ;Done there, so restore data segment.
- POP DS
- mov ENTRY_VID_MODE,bl ;store video mode (usually 3 for text)
- mov ENTRY_ROWS,cl ;rows will be restored on exit
- ASSUME DS:_TEXT
- CMP AX,3B4H ;Base address of MONO card is 3B4h.
- JZ _M1 ;If that's what we got, it's MONO
- ADD AX,6 ;Add six to get status register
-
- _M0: PUSH AX
- MOV VIDEO_SEG,0B800H ; else COLOR so add 800h.
- MOV SI,OFFSET C_NORMAL
- MOV DI,OFFSET NORMAL
- MOV CX,COLORS
- REP MOVSB
- MOV AL,INVERSE
- STOSB
- MOV AX,1200h ;test for EGA/VGA
- MOV BX,10h
- MOV CX,-1
- INT 10H
- POP AX ;get back status reg address
- CMP CX,-1 ;If it changes, we have EGA/VGA.
- je _M05
- mov VID_ADAPT,'E'
- jmp _M1 ;disable snow check
- _M05: CMP BYTE PTR STATUS_REG,0H ;patch point
- JNZ _M2 ;if not 0, enable snow check
-
- _M1: XOR AX,AX ;STATUS_REG=zero disables snow check
- _M2: MOV STATUS_REG,AX ;Store status register.
-
- XOR BH,BH ;Get current attribute
- MOV AH,8 ; of display page zero.
- INT 10H
- MOV ORIG_ATT,AH ;Store it.
- MOV AH,3 ;Retrieve cursor type.
- INT 10H
- MOV CURSOR_TYPE,CX
-
- MOV AX,PSP_TOP_MEM ;get top of available mem
- MOV BX,CS ;get our segment
- SUB AX,BX ;memory available
- CMP AX,DIRALLOC ;we need min mem for dir functions
- JNC _M5 ;got this much
-
- _M3: MOV DX,OFFSET NOT_ENOUGH
- _M4: JMP ERROR_EXIT ;If not available, exit.
-
- _M5: AND AX,0FFFH ;how much left after rounding by 64K?
- DEC AX ; minus some malloc overhead
- DEC AX
- CMP AX,DIRALLOC ;if less than min allowed,
- JAE _M6
- MOV AX,1000H ;use a whole 64K
-
- _M6: MOV BX,AX ;save number of paragraphs
- MOV CL,4 ;x16 to find top byte
- SHL AX,CL ;of this seg and then
- MOV SP,AX ;set up a local stack
- XOR AX,AX
- PUSH AX ;push return address
- PUSH CS
-
- MOV AH,4AH ;modify mem block pointed to by es
- INT DOSINT ;requesting bx paragraphs
- JC _M3
-
- MOV OFFDOSLINE,CS ;put segment in parm block address
- CALL GET_COMSPEC ;get file spec for COMMAND.COM
- MOV DX,OFFSET NO_COMSPEC ;take error exit
- JC _M4
-
- cmp byte ptr PATCH_43LINE,0
- je _M65
- call TOGGLE_OK ;Can we change to 43/50 lines?
- jc _M65 ; no
- xor bl,bl
- call SET_LINES ;set 43/50 lines
- call SET_SCREEN_VARS ;set screen size dependant variables
-
- _M65: call SAVE_DOS_SCREEN
-
- ;----------------------------------------;
- ; Parse the command line for parameters. ;
- ;----------------------------------------;
- MOV DI,OFFSET CMD_LINE ;Point to command line
- XOR CX,CX
- MOV CL,[DI]
- INC CX
- INC DI
- PUSH DI
- PUSH CX
-
- _M7: MOV AL,SWITCH
- REPNZ SCASB
- JNZ _M12
- MOV AL,[DI]
- MOV WORD PTR [DI-1],2020h
- PUSH DI
- PUSH CX
-
- cmp al,'4'
- jnz _M8
- mov al,[di+1]
- cmp al,'3'
- jnz _M8
- mov byte ptr [DI+1],20h
- call TOGGLE_OK ;Can we change to 43/50 lines?
- jc _M8 ; no
- xor bl,bl
- call SET_LINES ;set 43/50 lines
- call SET_SCREEN_VARS ;set screen size dependant variables
-
- _M8: AND AL,5FH ;upper case
-
- ; CMP AL,"H" ;If "H", remove hidden files.
- ; JNZ _M85
- ; MOV SEARCH_ATTRIB,1 + 4 + 10
-
- _M85: CMP AL,"V"
- JNZ _M9
- MOV AX,2E01H ;set verify on
- INT DOSINT
-
- _M9: CMP AL,"F" ;fast option - no snow check
- JNZ _M10
- MOV STATUS_REG,0 ;zero flags video status register.
-
- _M10: MOV DI,OFFSET SORT_OPT
- CALL SET_SORT ;scan for sort options
- _M11: POP CX
- POP DI
- LOOP _M7
-
- _M12: POP CX
- POP DI
- CALL GET_PARAM
- JZ _M15 ;was there a parameter?
- MOV BX,SI ;save start of source
- CALL GET_PARAM
- JZ _M14 ;was there a 2nd parameter?
- MOV DI,OFFSET DEST_PATH ;save it at dest_path
- CMP BYTE PTR [SI+1],':' ;check for drive spec
- JZ _M13 ;one found
- INC DI ;no drive, use default
- INC DI ;by stepping over in dest
- _M13: LODSB ;get a byte
- STOSB ;put a byte
- OR AL,AL ;check for end and loop
- JNZ _M13
-
- _M14: MOV SI,BX
- CALL CHANGE_PATH ;Change drive and directory.
- _M15: CALL READ_DIR ;get dir info from disk
-
- ;-----------------------------------------;
- ; We are ready for business now. We will ;
- ; loop here, waiting for user keystrokes. ;
- ; Performs CALL [DI] to execute function
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : everything
- ;-----------------------------------------;
- GET_KEY PROC NEAR
- CALL REFRESH_DIR_DISP
- CMP FUNCTION,0
- JE _G_K1
- MOV AX,DEST_CLUSTER
- MOV TARG_CLUSTER,AX
- CALL DISP_COUNT_MSG ;display files and space available
- MOV FUNCTION,0 ;Restore function flags.
- MOV CURRENT_MENU,0 ;force menu display
-
- _G_K1: MOV AH,2 ;Get shift state.
- INT 16H
- MOV SI,OFFSET ALT_MENU ;display alt menu.
- TEST AL,ALT_SHIFT ;Is the alt key depressed?
- JNZ _G_K2 ;If no, check function request.
- MOV SI,OFFSET CTRL_MENU ;display ctrl menu.
- TEST AL,CTRL_SHIFT ;Is the ctrl key depressed?
- JNZ _G_K2 ;If no, check function request.
- MOV SI,OFFSET MENU1 ;display this menu.
- _G_K2:
- MOV BL,MENU1_ROWS
- CMP CURRENT_MENU,SI ;Are we already displaying it?
- JE _G_K3
- MOV CURRENT_MENU,SI ;no - display it.
- MOV DI,MENU_STRT ;And to screen position.
-
- mov ax,ROW_LEN ;ADD DI,(LOGO_ROWS + 2)*ROW_LEN
- mov dl,byte ptr LOGO_ROWS
- inc dl
- inc dl
- mul dx
- add di,ax
-
- CALL PUT_MENU_LINES
-
- _G_K3: CALL CK_KEY ;Did we get a key yet?
- JZ _G_K1 ;no, check again
-
- _G_K4: CALL READ_KEY ;Get a keystroke.
- MOV BX,AX ;Save returned key.
- CMP AH,1 ;Is it Esc or below?
- JBE _G_K5 ;If yes, function.
- CMP AH,36H ;Is it right shift or above?
- JAE _G_K5 ;If yes, function.
- CMP AH,1CH ;Is it CR?
- JZ _G_K5 ;If yes, function.
-
- cmp ah,2bh
- je _G_K5
-
- MOV AH,2 ;Get shift state.
- INT 16H
- TEST AL,HOT_SHIFT ;Is a hot key depressed?
- JNZ _G_K5 ;If no, check function request.
- CALL SEARCH ;Else, search for first letter.
- JMP GET_KEY
- _G_K5:
- MOV DI,OFFSET DISPATCH_KEY
- MOV CX,DISPATCH_CNT ;Valid commands.
- MOV AL,BH
- MOV BX,OFFSET DISPATCH_END
- CALL LOOKUP
- JNZ _G_K1 ;If no match, get another.
- CALL [BX] ;Else do subroutine.
- JMP GET_KEY ;Update screen; get next command.
-
- ;-----------------------------------------------------------------------;
- ; This is the exit routine. Restore the defaults the way we found them. ;
- ;-----------------------------------------------------------------------;
-
- ERROR_EXIT:
- MOV AH,9 ;print string$
- INT DOSINT
- MOV AL,1 ;Error code of one.
- JMP SHORT TERMINATE
-
- EXIT: MOV AL,ORIG_ATT
- CALL CLR_SCR ;Clear screen.
- XOR DX,DX
- CALL SET_CURSOR
- XOR AL,AL ;Error code of zero.
- TERMINATE:
- MOV SI,OFFSET INITIAL_PATH ;Restore drive.
-
- _T1: PUSH AX ;save error code
- call RESTORE_SCREEN ;Restore original screen row if needed.
-
- call RESTORE_DOS_SCREEN
- CALL CHANGE_PATH
- MOV AL,VERIFY_STAT ;Restore verify state.
- MOV AH,2EH ;set verify dos call
- INT DOSINT
- MOV AX,3301H ;Restore Control Break.
- MOV DL,BREAK_STAT
- INT DOSINT
-
- POP AX ;get back error code
- MOV AH,4CH
- INT DOSINT ;and go home
-
- QUIT: MOV AL,ORIG_ATT
- CALL CLR_SCR ;Clear screen.
- XOR DX,DX
- CALL SET_CURSOR
- XOR AL,AL ;Error code of zero.
- MOV SI,OFFSET WORK_PATH ; and default directory.
- JMP SHORT _T1
-
- GET_KEY ENDP
- MAIN ENDP
-
-
- ;-----------------------------------------------;
- ; This subroutine parses the user command line entry
- ; On entry : DI points to start of string, CX holds count
- ; Returns : SI=0 if nothing found, else SI points to start
- ; Modifies : adds null to end of space delimited string
- ;----------------------------------------;
- GET_PARAM PROC NEAR
- XOR SI,SI
- MOV AL,space
- JCXZ _G_P5
- _G_P1: SCASB ;scan off leading blanks
- JB _G_P2 ;skip control, too
- LOOP _G_P1
- JMP SHORT _G_P5
-
- _G_P2: DEC DI
- MOV SI,DI ;save source
-
- _G_P3: SCASB ;search for delimiter
- JAE _G_P4
- LOOP _G_P3
-
- _G_P4: DEC DI
- MOV BYTE PTR [DI],0
- _G_P5: OR SI,SI
- RET
- GET_PARAM ENDP
-
- ;-----------------------------------------------------------;
- ; This subroutine gets the file spec for COMMAND.COM from the
- ; environment's COMSPEC variable
- ; On entry : Nothing
- ; Returns : Carry set if COMSPEC not found
- ; PGM_NAME contains file spec
- ; Modifies : SI,DI
- ;-----------------------------------------------------------;
- GET_COMSPEC PROC NEAR
- MOV AX,PSP_ENV_SEG ;get environment segment from PSP
- MOV ENV_SEG,AX
- MOV ES,AX
- ASSUME CS:_TEXT,DS:_TEXT,ES:nothing
-
-
- ;-----------------------------------------------------------;
- ; This section searches the environment block for a string
- ; On entry : ES points to environment block
- ; DS:DI points to "NAME=" to match
- ; Returns : carry set if string not found
- ; ES:DI points to parameter if found
- ; Modifies : SI,DI,BX
- ;-----------------------------------------------------------;
- XOR DI,DI ;initialize offset to environment block
-
- _G_C1: MOV BX,OFFSET COM_VAR ;initialize pointer to pattern
- CMP BYTE PTR ES:[DI],0 ;End of environment block?
- JNE _G_C2 ;no
-
- STC ;indicate error
- JMP SHORT _G_C6
-
- _G_C2: MOV AL,[BX] ;get character from pattern
- OR AL,AL ;end of pattern? (turns off carry)
- JZ _G_C4 ;yes means match successful
-
- CMP AL,ES:[DI] ;compare to char in environment block
- JNE _G_C3 ;jump if match failed
- INC BX
- INC DI
- JMP _G_C2 ;loop
-
- _G_C3: XOR AL,AL ;scan forward for zero byte in env block
- MOV CX,-1
- CLD
- REPNZ SCASB
- JMP _G_C1 ;go compare next string
-
- _G_C4: ;success, return ES:DI = string
- MOV SI,OFFSET PGM_NAME ;set DS:SI to point to location for copy
- _G_C5: MOV AL,ES:[DI] ;transfer null-terminated string
- MOV [SI],AL
- INC SI
- INC DI
- OR AL,AL ;found a null?
- JNZ _G_C5
-
- _G_C6: PUSH CS
- POP ES
- RET
- GET_COMSPEC ENDP
-
- SUBTTL READ_DIR : (re)Display directory
- page
- ;----------------------------------------------------------------------
- ; This procedure reads in the directory information, sorts it, and then
- ;enters the main command input program loop.
- ;On Entry: (1) The current default drive and directory will be displayed
- ; and then saved as WORK_PATH
- ; (2) The default drive and directory will then be reset back to
- ; the destination drive and directory that must already be
- ; saved in DEST_PATH.
- ; (3) The ASCIIZ strings WORK_PATH and DEST_PATH, are
- ; formatted and saved for display purposes.
- ; (4) SOURCE and TARGET strings are also created/saved
- ; During the main program loop the default dir is DEST_PATH
- ;----------------------------------------------------------------------
- READ_DIR PROC NEAR
- MOV AL,NORMAL
- CALL CLR_SCR
- MOV SI,OFFSET LOAD_SORT_MSG ;Display sorting message.
- MOV DI,LOAD_SORT_LOC
- CMP SORT_LEN,-1 ;Unless not sorted.
- JNZ _R_D1
- MOV SI,OFFSET LOAD_MSG ;Then display loading message.
- MOV DI,LOAD_LOC
-
- _R_D1: CALL PUT_STRING
- MOV DI,OFFSET DIR_BUFF ;Put space character
- MOV CX,SP ; in directory listing
- SUB CX,100H ; leave stack space
- SUB CX,DI ; initialize this much space
- MOV AL,space ; with space char in buffer.
- REP STOSB
-
- XOR AX,AX ;initialize variables
- MOV COUNT,AX ;clear file counter
- MOV FILE_CNT,AX ;
- push ax
- MOV ax,BAR_START
- MOV LINE,ax
- pop ax
- MOV CUR_OFFSET,OFFSET DIR_BUFF
-
- ;------------------------------------------------------------------;
- ; Read all the directory filenames and store as records in buffer. ;
- ;------------------------------------------------------------------;
- MOV DX,OFFSET STAR_DOT_STAR
- MOV CX,SEARCH_ATTRIB
- CALL FIND_FIRST ;Find first matching file.
- MOV DI,OFFSET DIR_BUFF + 1 ;Point to buffer.
- JC _R_D3 ;If empty directory, go on
-
- MOV BP,SP ;Reserve space for stack.
- SUB BP,200H
- CALL STORE_ENTRY ;Convert to directory format.
-
- _R_D2: MOV AH,4FH ;Find next matching.
- INT DOSINT
- JC _R_D3 ;If carry, no more names.
- CALL STORE_ENTRY
- CMP DI,BP ;Are we encroaching the stack?
- JBE _R_D2 ;If no, find next.
- MOV DX,OFFSET TOO_MANY ;Else, exit with message.
- JMP ERROR_EXIT
- ;-----------------------------------;
- ; Store buffer end address and page ;
- ; end then sort the filenames. ;
- ;-----------------------------------;
-
- _R_D3: DEC DI
- MOV END_OFFSET,DI ;Store ending offset.
- MOV BX,COUNT ;Retrieve file count.
- MOV AX,DIR_ROW_END
- cmp bx,DIR_ROWS ;Enough to fill one page?
- JAE _R_D4 ;If yes, use default setting.
- MOV AX,ROW_LEN ;Calculate last record.
- mul bx
- ADD AX,BAR_START ;Add bar offset.
-
- _R_D4: MOV DIR_DISP_END,AX
- CMP SORT_LEN,-1 ;Should we sort or leave original?
- JZ _R_D5 ;If it was "/O", don't sort.
- CALL SORT
-
- ;---------------------------------------------------------------;
- ; Ready to get "working" directory and display it and the menu. ;
- ;---------------------------------------------------------------;
-
- _R_D5: MOV DI,OFFSET WORK_PATH ;Point to storage.
- PUSH DI ;and start of string
- CALL GET_PATH ;Get and save directory, space free.
- POP SI ;get back working disk
- MOV DI,OFFSET SOURCE ;Make a carbon copy of directory.
- _R_D6: MOVSB
- CMP BYTE PTR [SI],0
- JNZ _R_D6
-
- MOV AL,"\" ;Add "\" to end of path
-
- IFDEF SAG
- CMP SWITCH,"/" ; Do we really want "/"?
- JE _R_D6A: ; No
- MOV AL,"/" ; Yes
- _R_D6A:
- ENDIF
-
- CMP [DI-1],AL ; if not root directory.
- JZ _R_D7
- STOSB
-
- _R_D7: MOV FILE_NAME,DI ;Store end of path to tack
- ; on filename later on.
- ;
- ;restore current d:\path for default moves and copies
- _R_D8: MOV SI,OFFSET DEST_PATH
- CALL SET_DEST ;Display drive, directory, menu.
- RET
- READ_DIR ENDP
-
- ;--------------------------------------------------;
- ; This long subroutine stores the filename in DIR ;
- ; format. That is, filename, bytes, date and time. ;
- ;--------------------------------------------------;
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- STORE_ENTRY PROC NEAR
- MOV SI,OFFSET DTA+F_NAME ;Point to filename.
- MOV CX,12 ;Store 12 bytes of filename.
- CMP BYTE PTR [SI],"." ;Is it a dot directory?
- JNZ _ST_E2 ;If no, it's a file.
- CMP BYTE PTR [SI+1],"." ;Is it a double dot directory?
- JNZ _ST_E1 ;If no, single dot so skip.
- INC COUNT ;Else, increment total count.
- LODSB ;Store dots and go to file size.
- STOSB
- STOSB
- ADD DI,10
- JMP SHORT _ST_E6
-
- _ST_E1: RET
-
- _ST_E2: INC COUNT ;Increment total count.
- _ST_E3: LODSB ;Get a byte.
- CMP AL,0 ;End of filename?
- JZ _ST_E5 ;If yes, finish with spaces.
- CMP AL,"." ;Is it the period?
- JNZ _ST_E4 ;If no, store.
- SUB CX,3 ;Else store 3 spaces.
- MOV AL,space
- REP STOSB
- ADD CX,3
- JMP SHORT _ST_E3 ;Get next byte.
-
- _ST_E4: STOSB ;Store byte.
- LOOP _ST_E3 ;Get next byte.
- _ST_E5: MOV AL,space ;Pad balance with spaces.
- REP STOSB
-
- ;process file size column
- _ST_E6: PUSH DI ;Save pointer.
- TEST BYTE PTR DTA+F_ATTR,10H ;Is it a directory?
- JZ _ST_E7 ;If no, store size.
- MOV SI,OFFSET DIRECTORIES ;Else, store "<DIR>".
- INC DI
- MOV CX,5
- REP MOVSB
- JMP SHORT _ST_E8
-
- _ST_E7: INC FILE_CNT ;Increment file count.
- ADD DI,8 ;Move to end of bytes field.
- MOV DX,WORD PTR DTA+F_SIZE+2 ;Retrieve high and low words
- MOV AX,WORD PTR DTA+F_SIZE ; of bytes.
- CALL TRANSLATE ;Convert to decimal.
-
- _ST_E8: POP DI ;Retrieve pointer.
- ADD DI,11 ;Move to date field.
- MOV DX,WORD PTR DTA+F_DATE ;Retrieve date.
- MOV AX,DX
- MOV CL,5 ;Shift to lowest bits.
- ROR AX,CL
- AND AX,0FH ;Mask off all but month.
- MOV CL,0FFH ;Flag as no leading zeros.
- MOV CH,"-" ;Delimiting character.
- CALL STORE_DIGITS ;Store it.
-
- ;process date column
- MOV AX,DX ;Retrieve date.
- AND AX,1FH ;Mask off all but day.
- MOV CL,0 ;Flag include leading zeros.
- MOV CH,"-"
- CALL STORE_DIGITS ;Store it.
- MOV AX,DX ;Retrieve date for last time.
- MOV CL,9
- ROR AX,CL
- AND AX,7FH ;Mask off all butyear.
- ADD AX,80 ;Adjust to ASCII.
- CMP AX,100 ;Past year 2000?
- JB _ST_E9 ;If no, display. Else, adjust for
- SUB AX,100 ; next century. (Planning ahead!)
-
- _ST_E9: MOV CL,0 ;Display leading zeros.
- MOV CH,space
- CALL STORE_DIGITS ;Store it.
-
- ;process time column
- INC DI ;Move to time field.
- MOV DX,WORD PTR DTA+F_TIME ;Retrieve time.
- MOV AX,DX
- MOV CL,11 ;Shift to hours bits.
- ROR AX,CL
- AND AX,1FH ;Mask off all but hours.
- PUSH AX
- CMP AX,12 ;Past noon?
- JBE _ST_E10
- SUB AX,12 ;If yes, adjust.
-
- _ST_E10:
- CMP AX,0 ;Midnight?
- JNZ _ST_E11
- MOV AX,12 ;If yes, adjust.
-
- _ST_E11:
- MOV CL,0FFH ;Suppress leading zeros.
- MOV CH,":"
- CALL STORE_DIGITS ;Store it.
-
- MOV AX,DX ;Retrieve time.
- MOV CL,5 ;Shift to minutes bits.
- ROR AX,CL
- AND AX,3FH ;Mask off all but minutes.
- MOV CL,0
- POP DX ;Retrieve hours.
- MOV CH,"p" ;Assume PM.
- CMP DX,12 ;Is it PM?
- JAE _ST_E12
- MOV CH,"a" ;If no, AM.
-
- _ST_E12:
- CALL STORE_DIGITS ;Store it.
- MOV AH,BYTE PTR DTA+F_ATTR ;Get attribute byte.
- MOV AL,"H" ;Assume it's hidden.
- TEST AH,2 ;Is it?
- JNZ _ST_E13 ;If yes, store "H".
- MOV AL,space ;Else, store a space.
-
- _ST_E13:
- STOSB
- MOV AL,"S" ;Assume it's system.
- TEST AH,4 ;Is it?
- JNZ _ST_E14 ;If yes, store "S".
- MOV AL,space ;Else, store a space.
-
- _ST_E14:
- STOSB
- MOV AL,"R" ;Assume it's read-only.
- TEST AH,1 ;Is it?
- JNZ _ST_E15 ;If yes, store "R".
- MOV AL,space ;Else, store a space.
-
- _ST_E15:
- STOSB
- MOV AL,"A" ;Assume it's archive.
- TEST AH,20H ;is it?
- JNZ _ST_E16 ;If yes, store "A".
- MOV AL,space ;Else store a space.
-
- _ST_E16:
- STOSB
- INC DI ;Bump pointer past mark field.
- RET
- STORE_ENTRY ENDP
-
-
- SUBTTL Main Command subroutines
- page
- ;**************************;
- ; MAIN COMMAND SUBROUTINES ;
- ;**************************;
-
- ;---------------------------------------------------------------;
- ; This subroutine toggles the number of rows on the screen. ;
- ; Toggles from 25 rows to 43 (EGA) or 50 (VGA/400 scan lines) ;
- ; and back. Will only do something if and EGA/VGA is being ;
- ; used and it is in Video Mode 3 or 7. ;
- ;---------------------------------------------------------------;
- TOGGLE_ROWS PROC NEAR
- call TOGGLE_OK
- jc _TOG2
-
- mov bl,byte ptr SCREEN_ROWS
- sub bl,25 ;switch to 25 rows if BL!=25; otherwise 43/50
- call SET_LINES
-
- call SET_SCREEN_VARS ;set screen size dependant variables
- call PUT_MENU_PATHS ;restore menu
-
- mov bx,COUNT ;Retrieve file count.
- mov ax,DIR_ROW_END
- cmp bx,DIR_ROWS ;Enough to fill one page?
- jae _TOG1 ;If yes, use default setting.
- mov ax,ROW_LEN ;Calculate last record.
- mul bx
- add ax,BAR_START ;Add bar offset.
- _TOG1: mov DIR_DISP_END,ax ;This value MUST be set when changing rows
-
- call HOME_BAR ;Re-synch display by homing the cursor
-
- _TOG2: ret
- TOGGLE_ROWS ENDP
-
-
- ;---------------------------------------------------------------;
- ; This subroutine restores the screen size before quiting the ;
- ; program ;
- ;---------------------------------------------------------------;
- RESTORE_SCREEN PROC NEAR
- call TOGGLE_OK
- jc _RS
-
- mov bl,byte ptr SCREEN_ROWS
- dec bl
- cmp bl,ENTRY_ROWS
- je _RS
-
- sub bl,24 ;switch to 25 rows if BL!=24; otherwise 43/50
- call SET_LINES
-
- _RS: ret
- RESTORE_SCREEN ENDP
-
-
- ;---------------------------------------------------------------;
- ; This subroutine sets 43/50 or 25 rows on the screen. ;
- ; Called by RESTORE_SCREEN, TOGGLE_ROWS, and MAIN. ;
- ; ;
- ; Entry : BL=0 for 43/50 lines, otherwise 25 lines ;
- ; Returns : nothing ;
- ; Modifies : everything ;
- ;---------------------------------------------------------------;
- SET_LINES PROC NEAR
- mov ax,3
- int 10h ;set video mode 3
-
- or bl,bl ;set 25 rows?
- jne _SETL ; yes
-
- mov ax,1112h ;now set 43/50 rows
- int 10h ;load 8x8 ROM character set (BL already = 0)
- _SETL: ret
- SET_LINES ENDP
-
-
- ;---------------------------------------------------------------;
- ; This routine checks if it is OK to change the number of rows. ;
- ; Called by RESTORE_SCREEN and TOGGLE_ROWS. ;
- ; ;
- ; Returns : nothing ;
- ; Modifies : everything ;
- ;---------------------------------------------------------------;
- TOGGLE_OK PROC NEAR
- cmp VID_ADAPT,'E' ;Do we have an EGA/VGA?
- jne _TOK1 ;if not, do nothing
- cmp ENTRY_VID_MODE,2 ;Only change the number of rows while in
- je _TOK2 ; 'safe' video text modes -> 2, 3 or 7
- cmp ENTRY_VID_MODE,3 ; otherwise don't even try.
- je _TOK2
- cmp ENTRY_VID_MODE,7
- je _TOK2
- _TOK1: stc ;set carry to indicate do not set rows
- _TOK2: ret
- TOGGLE_OK ENDP
-
-
- ;---------------------------------------------------------------;
- ; This subroutine copies files that do not already exist on destination
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : everything
- ;---------------------------------------------------------------;
- PCOPY PROC NEAR
- MOV SI,OFFSET PCOPY_MSG ;display copy message
- OR FUNCTION,COPY_BIT+PROTECT_BIT ;Else, indicate copy.
- JMP SHORT _CPY1
-
- ;---------------------------------------------------------------;
- ; This subroutine copies either the highlighted or marked file. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : everything
- ;---------------------------------------------------------------;
- COPY PROC NEAR
- MOV SI,OFFSET COPY_MSG ;display copy message
- OR FUNCTION,COPY_BIT ;Else, indicate copy.
- _CPY1: CALL SETUP_DEST ;Count marks, ask for destination.
- JC _CPY_RET ; error exit.
- CALL EXEC_MARKED ;Execute the command.
-
- _CPY_RET:
- RET
- COPY ENDP
- PCOPY ENDP
-
-
- ;----------------------------------------------------------------;
- ; This subroutine deletes either the highlighted or marked file. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : everything
- ;----------------------------------------------------------------;
- DELETE PROC NEAR
- OR FUNCTION,DELETE_BIT+DIR_OK_BIT ;Indicate deletion.
- CALL COUNT_MARKS ;Get count of marked files.
- JNZ _DEL1 ;If marked, display number marked.
- CALL GET_NAME ;Else get highlighted.
- JBE _DEL_ERR ;Exit if it's hidden/disallowed
- MOV SI,FILE_NAME ;Else display filename.
- JMP SHORT _DEL2
-
- _DEL1: MOV SI,OFFSET MARKED_MSG
-
- _DEL2: MOV DI,PROMPT_LOC
- CALL PUT_STRING
- MOV SI,OFFSET DELETE_MSG ;Display "will be deleted".
- CALL PUT_STRING
- MOV DI,PROMPT_LOC2 ;Display warning message.
- CALL PUT_STRING
- CALL CLEAR_OLD
-
- _DEL3: CALL READ_KEY ;Get a keystroke.
- CMP AH,31H ;Is it "N"?
- JZ _DEL_RET ;If yes, exit delete.
- CMP AH,1 ;Is it Esc?
- JZ _DEL_RET ;If yes, exit delete.
- CMP AH,15H ;Is it "Y"?
- JZ _DEL4 ;If yes, delete
- CALL BEEP ;Else, beep.
- JMP _DEL3 ;And get another keystroke.
-
- ;_DEL4: OR FUNCTION,DELETE_BIT ;Indicate deletion.
- _DEL4:
- CALL EXEC_MARKED ;Execute the command.
- JMP SHORT _DEL_RET
-
- _DEL_ERR:
- CALL BEEP ;Beep if error.
- _DEL_RET:
- RET
- DELETE ENDP
-
- ;--------------------------------------------------------------;
- ; This subroutine moves either the highlighted or marked file. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : everything
- ;--------------------------------------------------------------;
- MOVE PROC NEAR
- MOV SI,OFFSET MOVE_MSG ;Display move message.
- CALL SETUP_DEST ;Count marks, ask for destination.
- JC _MV_RET ; error exit
-
- MOV AX,WORD PTR ENTRY ;Check if across drives move.
- CMP AH,":" ;Is there a drive specified?
- JZ _MV_2 ;Use specified drive if there
- MOV AL,DEST_PATH ;Otherwise use default
-
- _MV_2: AND AL,5FH ;Capitalize.
- CMP AL,SOURCE ;Is it the same as source?
- MOV AL,MOVE_BIT+PROTECT_BIT ; Meanwhile, force a check to see
- ;if target file already exists before
- ;executing a rename or copy operation
- JZ _MV_3 ;If src disk=targ disk, just rename.
- OR AL,COPY_BIT+DELETE_BIT ;Else, indicate both copy/delete.
-
- _MV_3: MOV FUNCTION,AL ;indicate desired function
- CALL EXEC_MARKED ;Execute the command.
- _MV_RET:
- RET
- MOVE ENDP
-
-
- ;--------------------------------------------------------------;
- ; This subroutine renames either the highlighted or marked file. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : everything
- ;--------------------------------------------------------------;
- RENAME PROC NEAR
- OR FUNCTION,RENAME_BIT+DIR_OK_BIT ;flag desired function
- MOV SI,OFFSET RENAME_MSG ;Display rename message.
- CALL SETUP_DEST ;Count marks, ask for destination.
- JC _REN_RET ; abort
-
- _REN1: MOV SI,OFFSET WORK_PATH
- CALL CHANGE_PATH ;change back to work disk
- _REN2: CALL EXEC_MARKED ;Execute the command.
- ;there is a subtle problem in restoring the dest path that occurs
- ;when the rename operation has renamed the detination such that
- ;DEST_PATH no longer exists as a legitimate path
- MOV DI,OFFSET DEST_PATH ;get destination path
- PUSH DI ;save it for now
- MOV SI,OFFSET SOURCE ;check with what we just changed
-
- _REN3: LODSB ;get a byte
- SCASB ;check it against dest
- JNZ _REN4 ;dest was not renamed
- OR AL,AL ;are we done
- JNZ _REN3 ;no, there's more
-
- _REN4: POP SI
- JNZ _REN5
- MOV SI,OFFSET ENTRY ;use new name instead
- _REN5: CALL SET_DEST ;go restore dest
- _REN_RET:
- RET
- RENAME ENDP
-
-
- ;----------------------------------------------------------------;
- ; This subroutine removes the highlighted directory (<DIR>) if empty
- ; NOTE - NO WARNING PROMPT IS GIVEN
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : everything
- ;----------------------------------------------------------------;
- RMDIR PROC NEAR
- CALL GET_NAME ;Else get highlighted.
- JA _RMD_ERR ;Exit if it's not a directory
-
- _RMD4: OR FUNCTION,DELETE_BIT+DIR_OK_BIT ;Indicate deletion.
- CALL EXEC_MARKED ;Execute the command.
- JMP SHORT _RMD_RET
-
- _RMD_ERR:
- CALL BEEP ;Beep if error.
- _RMD_RET:
- RET
- RMDIR ENDP
-
-
- ;----------------------------------------------------------------;
- ; This subroutine creates a new directory on destination (MKDIR)
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : everything
- ;----------------------------------------------------------------;
- MKDIR PROC NEAR
- MOV SI,OFFSET MKDIR_MSG ;Display prompt
- MOV DI,PROMPT_LOC ;at usual place
- CALL JUST_ASK
- JC _MKD_RET ;escape out
- MOV DX,OFFSET ENTRY ;point to user entry
- MOV AH,39h ;MKDIR fn call
- INT DOSINT
- JNC _MKD_RET
- CALL CD_ERROR
- _MKD_RET:
- MOV FUNCTION,UPD_CNT_BIT ;force msg clear
- RET
- MKDIR ENDP
-
-
- ;-----------------------------------;
- ; This subroutine clears all marks. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : SI
- ;-----------------------------------;
- CLEAR_MARK PROC NEAR
- MOV SI,OFFSET DIR_BUFF ;Point to start of listing.
- _CLM1: MOV BYTE PTR [SI],space ;Write space over mark.
- ADD SI,FIELD_SIZE ;Next record.
- CMP SI,END_OFFSET ;End of listing?
- JB _CLM1 ;If no, continue until done.
- CALL COUNT_MARKS
- RET
- CLEAR_MARK ENDP
-
-
- ;----------------------------------------------------------------------;
- ; This subroutine marks all files that aren't marked with an asterisk. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : SI
- ;----------------------------------------------------------------------;
- MARK_BLANK PROC NEAR
- MOV SI,OFFSET DIR_BUFF ;Point to start of listing.
- _M_B1:
- CMP BYTE PTR [SI].D_SIZE,"<" ;Is it a directory?
- JZ _M_B2 ;If yes, skip.
- CMP BYTE PTR [SI].D_HID,"H" ;Is it a hidden file?
- JZ _M_B2 ;If yes, skip.
- CMP BYTE PTR [SI],space ;Is it a space?
- JNZ _M_B2 ;If no, skip.
- MOV BYTE PTR [SI],COPY_MARK ;Else mark.
- _M_B2:
- ADD SI,FIELD_SIZE ;Next record.
- CMP SI,END_OFFSET ;Continue until done.
- JB _M_B1
- CALL COUNT_MARKS
- RET
- MARK_BLANK ENDP
-
- ;-------------------------------------------------------;
- ; This subroutine swaps marked/unmarked ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : SI
- ;-------------------------------------------------------;
- SWAP_MARK PROC NEAR
- MOV SI,OFFSET DIR_BUFF ;Point to start of listing.
-
- _S_M1: CMP BYTE PTR [SI],COPY_MARK ;Is it marked ?
- JZ _S_M2 ;If yes, unmark it.
- CMP BYTE PTR [SI].D_SIZE,"<" ;Is it a directory?
- JZ _S_M3 ;If yes, skip.
- CMP BYTE PTR [SI].D_HID,"H" ;Is it a hidden file?
- JZ _S_M3 ;If yes, skip.
- MOV BYTE PTR [SI],COPY_MARK ;Else mark.
- JMP SHORT _S_M3
-
- _S_M2: MOV BYTE PTR [SI],space
- _S_M3: ADD SI,FIELD_SIZE ;Next record.
- CMP SI,END_OFFSET ;Continue until done.
- JB _S_M1
- CALL COUNT_MARKS
- RET
- SWAP_MARK ENDP
-
- ;--------------------------------------------------------;
- ; This subroutine marks or unmarks the highlighted file. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : assume everything
- ;--------------------------------------------------------;
- MARK PROC NEAR
- CALL PUT_AMARK
- CALL DN_ARROW ;And move down a row.
- RET
- MARK ENDP
-
- UNMARK PROC NEAR
- MOV DL,space ;Space character.
- CALL PUT_MARK
- CALL DN_ARROW ;And move down a row.
- RET
- UNMARK ENDP
-
- PUT_AMARK PROC NEAR
- MOV DL,COPY_MARK
- PUT_MARK PROC NEAR
- CALL GET_NAME ;Get filename.
- JBE PTM_RET ;If directory or hidden, skip.
- MOV [SI],DL ;Else store the character.
- PUSH SI
- CALL COUNT_MARKS
- POP SI
- PTM_RET: RET
- PUT_MARK ENDP
- PUT_AMARK ENDP
- ;-----------------------------------------------------------------------;
- ; This subroutine searches for a filename with a specific first letter. ;
- ; On entry : BL contains character to search for
- ; Returns : nothing
- ; Modifies : assume everything
- ;-----------------------------------------------------------------------;
- SEARCH PROC NEAR
- CMP BL,"a" ;Capitalize if lower case.
- JB _SRCH1
- CMP BL,"z"
- JA _SRCH1
- AND BL,5FH
-
- _SRCH1: CALL GET_NAME ;Get current position.
- XOR DX,DX ;Zero out file counter.
- MOV DI,SI ;Store current position in DI.
- INC DI ;point to filename
- MOV SI,OFFSET DIR_BUFF + 1 ;Point to top of listing.
- CMP BYTE PTR [DI],BL ;Are we currently at a match?
- JNZ _SRCH3 ;If no, start from top.
-
- _SRCH2: INC DX ;Increment count.
- ADD SI,FIELD_SIZE ;Increment record.
- CMP SI,DI ;New record?
- JBE _SRCH2 ;If no, find it.
-
- _SRCH3: CMP BYTE PTR [SI],BL ;Got a match?
- JZ _SRCH4 ;If yes, process.
-
- ADD SI,FIELD_SIZE ;Else, point to next record.
- INC DX
- CMP BYTE PTR [SI],space ;End of listing?
- JNZ _SRCH3 ;If no, keep searching.
- CALL BEEP ;No matches, so beep.
- STC
- RET
-
- _SRCH4: MOV CX,COUNT ;Retrieve file count.
- SUB CX,DX ;Subtract search count.
- MOV SEARCH_COUNT,CX ;And store.
- MOV CL,NORMAL ;Turn off bar for now.
- MOV BAR_ATTRIBUTE,CL
- CALL END_BAR ;First move to end.
- JMP SHORT _SRCH6
-
- _SRCH5: CALL UP_ARROW ;Move up to matching filename.
-
- _SRCH6: DEC SEARCH_COUNT
- JNZ _SRCH5
- MOV CL,INVERSE ;Turn bar back on and display.
- MOV BAR_ATTRIBUTE,CL
- XOR BP,BP
- CALL SCROLL_BAR
- CLC
- RET
- SEARCH ENDP
-
- ;--------------------------------------------------------------------------;
- ; Command to restore to the working directory and then re-read from disk
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : everything
- ;--------------------------------------------------------------------------;
- REFRESH PROC NEAR
- MOV SI,OFFSET WORK_PATH
- CALL NEW_WORK_DIR
- RET
- REFRESH ENDP
-
- ;------------------------------------------------------------------------;
- ; This subroutine changes the sorting option
- ; On entry : AL contains a scan code
- ; Returns : nothing
- ; Modifies : assume everything
- ;------------------------------------------------------------------------;
-
- RE_SORT PROC NEAR
- MOV DI,OFFSET SORT_KEYS
- CALL SET_SORT ;returns al=sort_offset
- CMP AH,-1 ;ah=sort_len=-1 if orig order
- JZ REFRESH ;re-load unsorted dir
-
- MOV DI,SORT_LOC
- MOV SI,OFFSET SORT_MSG
- CALL PUT_STRING
-
- ;------------------------------------------;
- ; This subroutine does the actual sorting. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : assume everything
- ;------------------------------------------;
- SORT PROC NEAR
- CMP COUNT,1 ;Can't sort less than 2 files.
- JBE _SRT_RET
- MOV DX,END_OFFSET ;End of filenames in DX.
- SUB DX,FIELD_SIZE
- XOR CX,CX ;clear CH
- MOV BL,SORT_LEN
- CMP BL,-1 ;no sort if field length is -1
- JZ _SRT_RET
-
- _SRT1: XOR BH,BH ;BH used as sort flag
- MOV BP,OFFSET DIR_BUFF + 1 ;Point to start of buffer.
-
- _SRT2: MOV SI,BP ;Source and destination.
- MOV AL,[SI+13] ;special test to put <DIR>'s
- CMP AL,[SI+13+FIELD_SIZE] ;at start of list
- JB _SRT4 ;dir field is different, swap
- JA _SRT6
- ADD SI,SORT_OFFSET
- MOV DI,SI
- ADD DI,FIELD_SIZE
- OR BL,BL ;Is it special case of date?
- JZ _SRT7 ;If yes, go do it
- MOV CL,BL
-
- _SRT3: REPZ CMPSB ;Compare filenames.
- JBE _SRT6 ;If already in order, skip.
-
- _SRT4: MOV SI,BP ;Else, recover pointers.
- DEC SI
- MOV DI,SI
- ADD DI,FIELD_SIZE
- MOV CL,FIELD_SIZE / 2 ;Exchange the records.
-
- _SRT5: MOV AX,[DI] ;swap fields through AX
- MOVSW
- MOV [SI-2],AX
- LOOP _SRT5
- INC BH ;Flag that exchange was made.
-
- _SRT6: ADD BP,FIELD_SIZE ;Point to next record.
- CMP BP,DX ;End of top?
- JB _SRT2 ;If no, bubble sort next.
- SUB DX,FIELD_SIZE ;Else, move top down one record.
- OR BH,BH ;Was there exchange made?
- JNZ _SRT1 ;If yes, another pass.
-
- _SRT_RET:
- MOV FUNCTION,UPD_CNT_BIT ;clear msg, restore counter
- RET
-
- _SRT7: MOV CL,2 ; treat special case of date
- REPZ CMPSB ;Compare year first.
- JA _SRT4 ;If above, swap.
- JNZ _SRT6
- SUB SI,8 ;Else, adjust and do month/day.
- SUB DI,8
- MOV CL,5
- REPZ CMPSB
- JA _SRT4 ;If above, swap.
- JNZ _SRT6
- ADD SI,10 ;Else, adjust and do meridian.
- ADD DI,10
- CMPSB
- JA _SRT4 ;If above, swap.
- JNZ _SRT6
- SUB SI,6 ;Else, adjust and do time.
- SUB DI,6
- MOV CL,5
- CMP WORD PTR [SI],3231H ;Is it special case "12:"?
- JZ _SRT8 ;If yes, see if same.
- CMP WORD PTR [DI],3231H ;Is destination "12:"?
- JNZ _SRT3 ;If no, normal compare.
- JMP _SRT4 ;Else, swap.
- _SRT8: CMPSW ;Are both "12:"?
- JNZ _SRT6 ;If no, next record.
- MOV CL,3 ;Else compare minutes.
- JMP SHORT _SRT3
-
- SORT ENDP
- RE_SORT ENDP
-
-
- ;--------------------------------------------------------------------------;
- ; These six subroutines control the bar and page of the directory listing. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : all
- ;--------------------------------------------------------------------------;
- UP_ARROW PROC NEAR
- MOV BP,ROW_LEN ;Move bar up one line.
- NEG BP
- JMP SHORT BAR_MOVE
-
- DN_ARROW PROC NEAR
- MOV BP,ROW_LEN ;Move bar down one line.
-
- BAR_MOVE PROC NEAR
- CALL SCROLL_BAR
- RET
- BAR_MOVE ENDP
- DN_ARROW ENDP
- UP_ARROW ENDP
-
-
- PG_DN PROC NEAR
- mov ax,DIR_ROWS ;Move down 20 lines.
- dec ax
- mov bl,FIELD_SIZE
- mul bl
- mov bp,ax ;BP = FIELD_SIZE * (DIR_ROWS - 1)
-
- MOVE_PAGE PROC NEAR
- CALL SCROLL
- JMP SHORT TOP_BAR ;Move bar to top.
-
- HOME_BAR PROC NEAR
- MOV CUR_OFFSET,OFFSET DIR_BUFF;Move listing to beginning.
-
- TOP_BAR PROC NEAR
- MOV SI,BAR_START ;And move bar to top.
- CALL MOVE_BAR
- RET
- TOP_BAR ENDP
- HOME_BAR ENDP
- MOVE_PAGE ENDP
- PG_DN ENDP
-
-
- PG_UP PROC NEAR
- mov ax,DIR_ROWS ;Move up 20 lines.
- dec ax
- mov bl,FIELD_SIZE
- mul bl
- neg ax
- mov bp,ax ;BP = FIELD_SIZE * (DIR_ROWS - 1)
-
- CALL SCROLL
- JMP SHORT BOTTOM_BAR
-
- END_BAR PROC NEAR
- MOV BX,END_OFFSET ;Move listing to last page.
-
- mov ax,FIELD_SIZE
- mul byte ptr DIR_ROWS
- sub bx,ax
-
- CMP BX,OFFSET DIR_BUFF
- JBE BOTTOM_BAR
- MOV CUR_OFFSET,BX
-
- BOTTOM_BAR PROC NEAR
- MOV SI,DIR_DISP_END ;And move bar to bottom.
- SUB SI,ROW_LEN
- CALL MOVE_BAR
- RET
- BOTTOM_BAR ENDP
- END_BAR ENDP
- PG_UP ENDP
-
- ;----------------------------------------------------;
- ; This subroutine does the actual moving of the bar. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : AX, CX, DX, DI
- ;----------------------------------------------------;
- MOVE_BAR PROC NEAR
- MOV AL,NORMAL ;Remove old bar.
- CALL BAR
- MOV LINE,SI ;And move bar to new line.
- MOV AL,BAR_ATTRIBUTE
-
- BAR PROC NEAR
- MOV DI,LINE ;Retrieve line.
- MOV CX,BAR_LEN ;Bar length 39.
- _BR_1: CALL PUT_CHAR ;Write the attribute.
- LOOP _BR_1
- RET
- BAR ENDP
- MOVE_BAR ENDP
-
- ;-------------------------------------;
- ; This subroutine scrolls the screen. ;
- ; On entry : BP indicates direction and number of lines to scroll
- ; Returns : nothing
- ; Modifies : BX, SI
- ;-------------------------------------;
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- SCROLL PROC NEAR
- MOV SI,CUR_OFFSET ;Get current offset.
- ADD SI,BP ;Add requested direction.
- CMP SI,OFFSET DIR_BUFF ;If above start check upper limit.
- JAE _SC1
- MOV CUR_OFFSET,OFFSET DIR_BUFF;Else, make it start.
- JMP SHORT _SC_RET ;And update screen.
-
- _SC1: MOV BX,END_OFFSET ;See if beyond end of dir listing.
-
- mov ax,FIELD_SIZE
- mul byte ptr DIR_ROWS
- add ax,OFFSET DIR_BUFF
- cmp bx,ax
-
- JA _SC2
- MOV CUR_OFFSET,OFFSET DIR_BUFF
- JMP SHORT _SC_RET
-
- _SC2: mov ax,FIELD_SIZE
- mul byte ptr DIR_ROWS
- sub bx,ax
-
- CMP SI,BX
- JBE _SC3
- MOV SI,BX
-
- _SC3: MOV CUR_OFFSET,SI ;Update current offset.
- _SC_RET:
- RET
- SCROLL ENDP
-
- ;--------------------------------------------------
- ; This subroutine scrolls the bar if between start
- ; and end of page. Otherwise the page is scrolled.
- ; On entry : BP indicates signed number of lines to scroll
- ; Returns : nothing
- ; Modifies : AX, CX, DX, SI, DI
- ;--------------------------------------------------
- SCROLL_BAR PROC NEAR
- MOV SI,LINE ;Get current line.
- ADD SI,BP ;Add requested line.
- MOV BP,FIELD_SIZE ;Assume below beginning.
- NEG BP
- CMP SI,BAR_START ;Is it?
- JB _SCR1 ;If yes, scroll page instead.
- MOV BP,FIELD_SIZE ;Do the same for end of page.
- CMP SI,DIR_DISP_END
- JAE _SCR1
- CALL MOVE_BAR
- JMP SHORT _SCR2
- _SCR1: CALL SCROLL
- _SCR2: RET
- SCROLL_BAR ENDP
-
- ;-------------------------------------------------------;
- ; This subroutine toggles the string filter function. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : nothing
- ;-------------------------------------------------------;
- ASSUME DS:NOTHING,ES:NOTHING
- ASCII PROC NEAR
- XOR VIEW_FLAGS,ASCII_BIT ;Toggle flag.
- RET
- ASCII ENDP
-
- ;-----------------------------------------------------;
- ; This subroutine toggles the non-ascii blanking filter on and off.;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : nothing
- ;-----------------------------------------------------;
- ASSUME DS:NOTHING,ES:NOTHING
- BLANK PROC NEAR
- ifdef BLANK_BIT
- XOR VIEW_FLAGS,BLANK_BIT ;Toggle flag.
- Endif
- RET
- BLANK ENDP
-
- ;--------------------------------------------------------;
- ; This subroutine toggles the WordStar filter on and off.;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : AX
- ;--------------------------------------------------------;
- ASSUME DS:NOTHING,ES:NOTHING
- STAR PROC NEAR
- XOR STAR_MASK,80H ;Toggle flag.
- MOV AL,' '
- JS _ST1
- MOV AL,'*'
- _ST1: MOV OPTIONS,AL
- RET
- STAR ENDP
-
- ;-------------------------------------------------------;
- ; This subroutine toggles the Word wrap function. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : nothing
- ;-------------------------------------------------------;
- ASSUME DS:NOTHING,ES:NOTHING
- WRAP PROC NEAR
- XOR VIEW_FLAGS,WRAP_BIT ;Toggle flag.
- RET
- WRAP ENDP
-
-
- ;-------------------------------------------------------;
- ; This subroutine toggles the Hex Dump function. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : nothing
- ;-------------------------------------------------------;
- ASSUME DS:NOTHING,ES:NOTHING
- HEXDUMP PROC NEAR
- XOR VIEW_FLAGS,HEX_BIT ;Toggle flag.
- RET
- HEXDUMP ENDP
-
-
- ;-------------------------------------------------------;
- ; This subroutine spawns a DOS command interpretor. ;
- ; On entry : no known parameters ;
- ; Returns : nothing ;
- ; Modifies : everything ;
- ;-------------------------------------------------------;
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- DOS_SHELL PROC NEAR
-
- MOV AL,NORMAL
- CALL CLR_SCR
- CALL CURSOR_ON
-
- MOV SI,OFFSET WORK_PATH ;CD to appropriate directory
- CALL CHANGE_PATH
-
- MOV AX,3301H ;Restore Control Break.
- MOV DL,BREAK_STAT
- INT DOSINT
-
- MOV STK_SEG,SS ;save stack
- MOV STK_PTR,SP
- MOV PAR_BLK+2, offset DOS_PROG
- MOV DX,OFFSET PGM_NAME ;exec command.com
- MOV BX,OFFSET PAR_BLK
- MOV AX,4B00H
- INT DOSINT
-
- ;program will go away for awhile and return here on "exit"
-
- PUSH CS
- PUSH CS
- POP DS
- POP ES
- CLI ;no interrupts while fooling with stack
- MOV SS,STK_SEG ;restore stack
- MOV SP,STK_PTR
- STI ;interrupts OK now
- JNC @F ;jump if DOS exec successful
- CALL BEEP ;beep to signal error
-
- @@: MOV AX,3301H ;Turn Control Break off again.
- MOV DL,0
- INT DOSINT
-
- call TOGGLE_OK ;restore screen rows
- jc @F
- mov bl,byte ptr SCREEN_ROWS
- cmp bl,40
- jl @F
- xor bl,bl
- @@: call SET_LINES
-
- MOV DX,80H ;reset DTA area for find first
- MOV AH,1AH
- INT DOSINT
- CALL REFRESH ;Redisplay directory
- RET
- DOS_SHELL ENDP
-
- ;-------------------------------------------------------;
- ; This subroutine spawns a DOS command interpretor ;
- ; and executes the program DOS_LINE1 ;
- ; ;
- ;-------------------------------------------------------;
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
-
- DOS_SHELL1 PROC NEAR
-
- mov si,offset DOS_PROG1 ;command name
- jmp CUSTOM_SHELL
-
- DOS_SHELL2 PROC NEAR
-
- mov si,offset DOS_PROG2 ;command name
-
- CUSTOM_SHELL:
-
- MOV AX,3301H ;Restore Control Break.
- MOV DL,BREAK_STAT
- INT DOSINT
-
- MOV STK_SEG,SS ;save stack
- MOV STK_PTR,SP
-
- mov dh,byte ptr SCREEN_ROWS ;move cursor to bottom of screen
- dec dh
- xor dl,dl
- call SET_CURSOR
-
- mov di,offset DOS_LINE+4 ;clear out DOS_LINE
- mov al,0
- mov cx,70
- @@: stosb
- loop @B
-
- mov di,offset DOS_LINE+4 ;copy command name
- mov cx,40
- @@: lodsb
- cmp al,0
- jz @F
- stosb
- loop @B
-
- @@: mov al,20h ;add space after command
- stosb
-
- push di
- call GET_NAME ;returns highlighted file in si
- pop di
- mov si,OFFSET SOURCE ; point to it
-
- @@: mov cx,60 ;add path+filename
- lodsb
- cmp al,0
- jz @F
- stosb
- loop @B
-
- @@: MOV PAR_BLK+2, offset DOS_LINE
- MOV DX,OFFSET PGM_NAME ;exec command.com
- MOV BX,OFFSET PAR_BLK
- MOV AX,4B00H
- INT DOSINT
-
- ;program will go away for awhile and return here on "exit"
-
- PUSH CS
- PUSH CS
- POP DS
- POP ES
- CLI ;no interrupts while fooling with stack
- MOV SS,STK_SEG ;restore stack
- MOV SP,STK_PTR
- STI ;interrupts OK now
- JNC @F ;jump if DOS exec successful
- CALL BEEP ;beep to signal error
-
- @@:
- ASSUME DS:_TEXT,ES:_TEXT
- MOV AX,3301H ;Turn Control Break off again.
- MOV DL,0
- INT DOSINT
-
- call TOGGLE_OK ;restore screen rows
- jc _CD22
- mov bl,byte ptr SCREEN_ROWS
- cmp bl,40
- jl @F
- xor bl,bl
- @@: call SET_LINES
-
- _CD22: MOV DX,80H ;reset DTA area for find first
- MOV AH,1AH
- INT DOSINT
- CALL PUT_MENU_PATHS
- RET
-
- DOS_SHELL2 ENDP
- DOS_SHELL1 ENDP
-
-
- SUBTTL View file command and subroutines
- page
- ;------------------------------------------------------------;
- ; This subroutine displays the highlighted file for viewing. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : everything
- ;
- ;"global" variables used in the regular segment are
- ;
- ;temporary variables in the extended buffer segment "DUMMY_SEG":
- ; PAGES is an array of byte sizes of previously formatted pages
- ; LAST_PAGE is the buffer pointer value (SI)
- ; for the top of the current page
- ; ROW = # of rows into LAST_PAGE for current display
- ;------------------------------------------------------------;
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- VIEW PROC NEAR
-
- CALL GET_NAME ;Get the file name.
- MOV SI,OFFSET SOURCE ; point to it
- JNC _VW1 ;view file, not directory
- JMP VIEW_DIR
-
- _VW1: CALL GET_MEM
- JNC _VW2
- RET
-
- _VW2: MOV DX,SI ;Open the file
- MOV AX,3D00H
- INT DOSINT
- MOV READ_HANDLE,AX ;Save filehandle.
- MOV AL,NORMAL
- CALL CLR_SCR ;Clear screen.
- MOV AL,INVERSE ;reverse video attribute
- XOR CX,CX ;setup status line
- CALL CLR_EOL
-
- XOR DI,DI ;start at top of screen
- MOV SI,CUR_FILE ;get ptr to record
- INC SI ;inc to filename
- MOV CX,WHERE_LOC ;bytes to write
- CALL PUT_CX_CHARS ;write filename
- ADD DI,2 * WHERE_LEN ;skip over file ptr field
- MOV AL,'/' ;add a "/"
- CALL PUT_CHAR
- MOV CX,BAR_LEN - WHERE_LOC ;remainder of status line
- CALL PUT_CX_CHARS ;display it
-
- MOV DS,MEM_BUF_SEG
- ASSUME DS:DUMMY_SEG
-
- CALL FIRST_READ
-
- mov ax,SCREEN_COLS
- mov LAST_COL,ax
-
- MOV BP,OFFSET PAGES ;Initialize page pointer.
- MOV ROW,0 ;And row pointer.
-
- _VW3: CALL POSITION
-
- MOV CX,SCREEN_ROWS ;Now display one screen
- dec cx
-
- PUSH AX
- MOV AH,1
- INT 16h ;test keyboard
- POP AX
- JNZ _VW4 ;if another key struck, skip display
-
- MOV DI,ROW_LEN ;start down one line
- OR VIEW_FLAGS,DISPLAY_BIT ;Display.
- _VW4: CALL LINES ;format (and display?) CX lines
-
-
- ;process keyboard command entry
- _VW6: MOV AH,0 ;Retrieve keystroke via BIOS.
- INT 16H
- CMP AH,1 ;Is it Esc?
- JZ _VW_RET ;If yes, exit view.
- IFNDEF SAG
- CMP AH,1CH ;Is it carriage return?
- JZ _VW_RET ;If yes, exit view.
- ENDIF
- MOV DI,OFFSET VIEW_KEYS ;get key dispatch
- MOV AL,AH
- MOV CX,VIEW_CNT ;number of valid commands.
- MOV BX,OFFSET VIEW_TABLE_END
- CALL LOOKUP ;VIEW_KEYS
- JNZ _VW6 ;If no, match, get next stroke.
-
- CALL CS:[BX] ;Do subroutine.
- JC _VW6 ;Carry indicates no screen update.
- JMP _VW3 ;Else, update and get next command.
-
- _VW_RET:
- PUSH CS
- POP DS
-
- ASSUME DS:_TEXT,ES:_TEXT
- CALL RELEASE_MEM
- MOV BX,READ_HANDLE ;Close the file.
- MOV AH,3EH
- INT DOSINT
- CALL PUT_MENU_PATHS ;Restore menu.
- RET
- VIEW ENDP
-
- ;----------------------------------------------------------------------;
- ; These six subroutines control the page and starting row of the view. ;
- ; Screen is updated unless carry flag is set upon return
- ;----------------------------------------------------------------------;
- ; This subroutine moves back one line in the file
- ; On entry : parameters as discussed above
- ; Modifies : ROW
- ;--------------------------------------------------------;
- ASSUME DS:DUMMY_SEG,ES:_TEXT
- UP_LINE PROC NEAR
- CMP ROW,0 ;Are we at row zero?
- JNZ _U_L1 ;If no, decrement one row.
- CMP BP,OFFSET PAGES ;Else, are we at first page?
- STC
- JZ _U_L_RET ;If yes, no change.
- CALL UP_PG ;Else, move up one page.
- mov al,VIEW_ROWS ;And move starting row to bottom
- mov ROW,al
-
- _U_L1: DEC ROW ;Decrement row.
-
- MOV AX,0701h ;bios scroll display down 1 line
- CALL SCROLL_WIN
- CALL POSITION
- MOV CX,1 ;Now display one line
- MOV DI,ROW_LEN ;first line
- OR VIEW_FLAGS,DISPLAY_BIT ;Display.
- CALL LINES
- STC ; no update.
- _U_L_RET:
- RET
- UP_LINE ENDP
-
- ;--------------------------------------------------------;
- ; This subroutine moves forward one line in the file
- ; On entry : parameters as discussed above
- ; Modifies : ROW
- ;--------------------------------------------------------;
- DN_LINE PROC NEAR
- CALL CK_FILE_END ;Are we at end of file?
- JNC _D_L1 ;If no, check row.
- RET ;Else, return.
- _D_L1: mov al,byte ptr VIEW_ROWS
- dec al
- CMP ROW,al ;Are we at last row?
- JB _D_L2 ;If no, increment row.
- CALL DN_PG ;Else, page down.
- MOV ROW,-1 ;And move row to top.
-
- _D_L2: INC ROW
- MOV AX,0601h ;bios scroll display up 1 line
- CALL SCROLL_WIN
-
- CALL POSITION
- MOV CX,SCREEN_ROWS ;skip over scrolled display
- dec cx
- dec cx
- CALL LINES
- MOV CX,1 ;Now display last line
-
- push ax
- mov ax,SCREEN_ROWS ;MOV DI,ROW_LEN*(SCREEN_ROWS-1)
- dec ax
- mul ROW_LEN
- mov di,ax
- pop ax
-
- OR VIEW_FLAGS,DISPLAY_BIT ;Display.
- CALL LINES
- STC
- RET
- DN_LINE ENDP
-
-
- ;-------------------------------------------------------------------;
- ; Scroll View window AH = 6 for up, 7 for down
- ; Uses BH = screen attribute to use
- ; CH, CL = row, col of upper left
- ; DH, DL = row, col of lower right
- ; Modifies : AX, BH, CX, DX, saves BP
- ;-------------------------------------------------------------------;
- SCROLL_WIN PROC NEAR
- PUSH BP
- MOV BH,NORMAL ;use normal attribute
- MOV CX,0100h ;top left
- mov dh,byte ptr SCREEN_ROWS
- dec dh ;bottom row
- mov dl,byte ptr SCREEN_COLS
- dec dl ;right col
- INT 10h ;video bios call
- POP BP
- RET
- SCROLL_WIN ENDP
-
-
- ;--------------------------------------------------------;
- ; This subroutine moves back one full screen in the file
- ; On entry : parameters as discussed above
- ; Modifies : ROW, LAST_PAGE
- ;--------------------------------------------------------;
- UP_PG PROC NEAR
- CMP BP,OFFSET PAGES ;Are we already at first page?
- JNZ _U_P2 ;If no, decrement page.
- CMP ROW,0 ;Are we at first row?
- STC
- JZ _U_P_RET ;If yes, no update.
- MOV ROW,0 ;Else move to first row.
- JMP SHORT _U_P4
-
- _U_P1: CALL BACKWARD ;read in previous 1/2 buff
-
- _U_P2: MOV SI,LAST_PAGE ;Get current page.
- SUB SI,DS:[BP] ;Subtract difference to prev page.
- JC _U_P1 ;have we already passed zero?
- CMP SI,OFFSET FILE_BUFF ;Beyond top of buffer?
- JC _U_P1 ;If no, page up.
-
- _U_P3: DEC BP
- DEC BP ;Decrement page pointer.
- MOV LAST_PAGE,SI ;Store new starting position.
-
- _U_P4: CLC
- _U_P_RET:
- RET
- UP_PG ENDP
-
- ;--------------------------------------------------------;
- ; This subroutine moves foward one full screen in the file
- ; On entry : parameters as discussed above
- ; Modifies : ROW, LAST_PAGE
- ;--------------------------------------------------------;
- DN_PG PROC NEAR
- CMP BP,OFFSET FILE_BUFF-2 ;Out of room for page storage?
- JAE _D_P1 ;If yes, skip.
- MOV SI,LAST_PAGE ;Else, retrieve current page.
- AND VIEW_FLAGS,NOT DISPLAY_BIT ;No display.
- MOV CL,VIEW_ROWS ;Move up 24 lines.
- XOR AH,AH ;clear eol flag
- CALL LINES
- CALL CK_FILE_END ;End of file?
- JC _D_P1 ;If yes, no update.
- MOV DX,LAST_PAGE ;Else, save current offset.
- MOV LAST_PAGE,SI ;Store new offset.
- MOV AX,SI
- SUB AX,DX ;Get difference between pages.
- INC BP ;Increment page storage.
- INC BP
- MOV DS:[BP],AX ;And store.
- CLC
- RET
-
- _D_P1: STC
- RET
- DN_PG ENDP
-
-
- ;--------------------------------------------------------;
- ; This subroutine moves the display pointer
- ; back to the beginning of the file
- ; On entry : FILE_PTR + SI points to current location in file
- ; Modifies : ROW, LAST_PAGE
- ;--------------------------------------------------------;
- HOME_FILE PROC NEAR
- CMP FILE_PTR+2,-1 ;check if start of file is in buffer
- JNZ _H_F1 ;nope
- MOV AX,FILE_PTR ;yes, then ptr to start of file
- NEG AX ; will be = 0 - FILE_PTR
- MOV LAST_PAGE,AX ;save it
- JMP SHORT _H_F_RET
-
- _H_F1: XOR DX,DX ;reset DOS file ptr to start of file
- XOR CX,CX
- MOV BX,READ_HANDLE
- MOV AX,4200H ;reset file ptr to start of file
- INT DOSINT
- CALL FIRST_READ ;go read it
-
- _H_F_RET:
- MOV ROW,0 ;re-zero counters
- MOV BP,OFFSET PAGES
-
- mov ax,SCREEN_COLS
- mov LAST_COL,ax
-
- CLC
- RET
- HOME_FILE ENDP
-
-
- ;--------------------------------------------------------;
- ; This subroutine moves the display pointer to the end of the file
- ; by successively paging through the buffer
- ;--------------------------------------------------------;
- END_FILE PROC NEAR
- CALL DN_PG ;Page down until end of file.
- JNC END_FILE
- CLC
- RET
- END_FILE ENDP
-
- ;--------------------------------------------------------;
- ; This subroutine moves an unwrapped display 16 cols to the left
- ; On entry : VIEW_FLAGS indicates if wrap is in effect
- ; Returns : modified LAST_COL
- ; Modifies : AX
- ;--------------------------------------------------------;
- LEFT PROC NEAR
- TEST VIEW_FLAGS,WRAP_BIT
- JNZ _LFT_RET
- MOV AX,LAST_COL
- CMP AX,SCREEN_COLS
- STC
- JZ _LFT_RET
- SUB AX,16
- MOV LAST_COL,AX
- _LFT_RET:
- RET
- LEFT ENDP
-
- ;--------------------------------------------------------;
- ; This subroutine moves an unwrapped display 16 cols to the right
- ; On entry : VIEW_FLAGS indicates if wrap is in effect
- ; Returns : modified LAST_COL
- ; Modifies : AX
- ;--------------------------------------------------------;
- RIGHT PROC NEAR
- TEST VIEW_FLAGS,WRAP_BIT
- JNZ _RGT_RET
- ADD LAST_COL,16
- _RGT_RET:
- RET
- RIGHT ENDP
-
- ;--------------------------------------------------------;
- ; The following 3 subroutines toggle the VHEX, ASCII and WRAP flags
- ; when in view mode and then re-start the display at the beginning.
- ;--------------------------------------------------------;
- ASSUME DS:DUMMY_SEG
- VHEX PROC NEAR
- CALL HEXDUMP
- JMP SHORT _VSF_1
-
- V_ASCII PROC NEAR
- CALL ASCII
- JMP SHORT _VSF_1
-
- VWRAP PROC NEAR
- CALL WRAP
- _VSF_1: MOV SI,THIS_SCREEN
- CALL GET_FPTR
- MOV RETRN_PTR,AX
- MOV RETRN_PTR+2,DX
- CALL HOME_FILE
- MOV SI,LAST_PAGE
- CALL TEST_FPTR
- JAE _VSF_RET
- _VSF_2: CALL DN_PG
- CALL TEST_FPTR
- JB _VSF_2
- JE _VSF_RET
-
- CALL UP_PG
- _VSF_3: INC ROW
- CALL POSITION ;format and count BH rows
- _VSF_4: CALL TEST_FPTR
- JB _VSF_3
- JE _VSF_RET
- DEC ROW
- _VSF_RET: CLC ;call for screen update
- RET
- VWRAP ENDP
- V_ASCII ENDP
- VHEX ENDP
-
- ;----------------------------------------------------------------;
- ; This subroutine checks to see if end of file has been reached. ;
- ;----------------------------------------------------------------;
- CK_FILE_END PROC NEAR
- CMP SI,FILE_END
- JB _CK_F1
- CMP FILE_END,OFFSET FILE_BUFF+(READ_SIZE * 2)
- JC _CK_F2
-
- _CK_F1: CLC
- _CK_F2: RET
- CK_FILE_END ENDP
-
- ;----------------------------------------------------------------;
- ; This subroutine "parses" CX lines of text starting at ROW
- ; On entry : BP points to a page size entry in PAGES
- ; Modifies : AX, BX, CX, DX, SI, DI
- ;----------------------------------------------------------------;
- ASSUME DS:DUMMY_SEG, ES:_TEXT
- POSITION PROC NEAR
- MOV SI,LAST_PAGE ;Get top of current page.
- XOR AH,AH ;clear word-wrap/cr flag register
- XOR CH,CH
- MOV CL,ROW ;Get row offset into page.
- JCXZ _PO1 ;skip if it is row zero
- AND VIEW_FLAGS,NOT DISPLAY_BIT ; skip display.
- CALL LINES ;format and count BH rows
-
- _PO1: PUSH AX ;save AH cr/wrap flag
- MOV THIS_SCREEN,SI ;save current location
- CALL PUT_WHERE
- POP AX
- RET
- POSITION ENDP
-
-
-
- ;----------------------------------------------------------------;
- ; This subroutine formats the text into lines. A line is marked ;
- ; by a line feed, a lone carriage return or,
- ; if word wrap is in effect, by reaching the last column (80).
- ; On entry : DS:SI points to beginning of text to display
- ; BP points to a page size entry in PAGES
- ; CX contains the number of rows to display
- ; ES:DI points to position in display buffer
- ; Modifies : AX, BX, CX, DX, SI, DI
- ; AH is used as a flag register for testing end of line cases
- ; BL is used as a register copy of VIEW_FLAGS
- ; BH is used as a register copy of STAR_MASK
- ;----------------------------------------------------------------;
- ASSUME DS:DUMMY_SEG,ES:_TEXT
- LINES PROC NEAR
- PUSH ES ;save seg register
-
- MOV DX,STATUS_REG ;Retrieve status register.
- MOV BL,VIEW_FLAGS
- MOV BH,STAR_MASK
-
- MOV ES,VIDEO_SEG ;Point to screen segment.
- ASSUME ES:nothing
-
- _LN0: PUSH CX
- _LN1: MOV CX,LAST_COL ;80 columns.
-
- _LN2: CMP SI,FILE_END ;If end of file, pad with spaces.
- JB _LN3
- CALL FORWARD ;read next block of file
- JNC _LN3
- jmp _LN15
-
- _LN3: test bl,HEX_BIT ;HEXDUMP mode?
- jz _LN35 ;no
- jmp LINES_HEX ;hexdump of 1 complete line
-
- _LN35: LODS FILE_BUFF ;Get a byte.
- AND AL,BH ;Strip high bit for WordStar?
- CMP AL,cr ;Carriage return?
- JA _LN8 ; printable char?
- JNZ _LN4 ;no, go check for tab or lf
- OR AH,2 ;set flag to mark cr
- JMP _LN2 ;get next char
-
- _LN4: CMP AL,lf ; linefeed?
- JNZ _LN8 ; no, go display char
- TEST AH,1 ;are we following a word wrap?
- MOV AH,0 ;clear flags
- JNZ _LN2 ;if just wrapped, ignore lf
- _LN5: TEST BL,ASCII_BIT ;stripping non-ascii ?
- JZ _LN7 ;no
- _LN6: push ax
- mov ax,SCREEN_COLS
- sub ax,4 ;have we had more than five displayed?
- mov TEMP,ax
- pop ax
- cmp cx,TEMP
- jae _LN65 ;go point back to start of line
- jmp _LN7
-
- _LN65: add TEMP,4 ;TEMP = SCREEN_COLS
- sub TEMP,cx ;TEMP = # of characters written so far
- shl TEMP,1 ;double to account for attribute
- sub di,TEMP ;bring DI back to start of line
- jmp _LN1
-
- _LN7: CALL PAD_TO_EOL ;If yes, pad balance of line.
- JMP SHORT _LN15
-
- _LN8: CMP AH,2 ;was there a CR without a lf or a wrap?
- MOV AH,0 ;clear flag
- JNZ _LN9 ;no CR, go display this char
- DEC SI ;back up one character
- JMP _LN5 ;pad to EOL
-
- _LN9: JCXZ _LN2 ;bypass if 80 chars already written
- CMP AL,tab ;is it a tab?
- JNZ _LN10 ;no
- MOV AL,space ;expand to spaces
- TEST BL,ASCII_BIT ;stripping non-ascii ?
- JNZ _LN12 ;yes - just display 1 space
- CALL DO_TAB ;write out spaces
- JCXZ _LN14 ;all done ?
- JMP _LN2 ;still more
-
- _LN10: CMP CX,SCREEN_COLS ;horizontal scroll in effect?
- JA _LN13 ;yes - skip chars at left edge
-
- IFDEF BLANK_BIT
- TEST BL,ASCII_BIT+BLANK_BIT ;stripping non-ascii ?
- JZ _LN12 ;no - go display char
- CMP AL,space ;control character?
- JGE _LN12 ;no - go display char
- TEST BL,ASCII_BIT ;stripping non-ascii ?
- JNZ _LN6 ;yes, go write EOL
- MOV AL,space ;blank non-ascii char
- ELSE
- TEST BL,ASCII_BIT ;stripping non-ascii ?
- JZ _LN12 ;no - go display char
- CMP AL,space ;control character?
- JL _LN6 ;yes, go write EOL
- ENDIF
-
- _LN12: TEST BL,DISPLAY_BIT ;display ?
- JZ _LN13 ;return - just counting lines
-
- CALL PUT_BYTE
- INC DI ;Bump pointer past attribute.
-
- _LN13: LOOP GetNextByte ;Get next byte.
-
- _LN14: TEST BL,WRAP_BIT ;is word wrap on?
- JZ GetNextByte ;no - keep looking for end of line
-
- MOV AH,1 ;set word-wrap flag
-
- _LN15: POP CX ;get back line counter
- DEC CX ;this line done- dec line counter
- JZ _LN17 ;all done
-
- JMP _LN0
-
- _LN17: POP ES ;restore segment register
- RET
- LINES ENDP
-
- PAD_TO_EOL PROC NEAR
- CMP CX,SCREEN_COLS ;horizontal scroll?
- JBE PAD_SPACES ;yes, we only need 80 spaces
- MOV CX,SCREEN_COLS
-
- PAD_SPACES PROC NEAR
- MOV AX,space ;clear flag, display space
- JCXZ _PSP_RET
- MOV DX,STATUS_REG ;Retrieve status register.
- TEST BL,DISPLAY_BIT ;Are we to write it to screen?
- JZ _PSP_RET ;If no, return.
-
- _PSP_1: CALL PUT_BYTE
- INC DI ;Bump pointer past attribute.
- LOOP _PSP_1
-
- _PSP_RET:
- RET
-
- GetNextByte:
- jmp _LN2
-
- PAD_SPACES ENDP
- PAD_TO_EOL ENDP
-
-
- ;----------------------------------------------------------------;
- ; This set of subroutines formats the text into lines for the ;
- ; Hexdump mode. ;
- ; On entry : DS:SI points to beginning of text to display ;
- ; ES:DI points to position in display buffer ;
- ; Modifies : AX, CX, SI, DI ;
- ; BL is used as a register copy of VIEW_FLAGS ;
- ;----------------------------------------------------------------;
-
- HEX_BUF DB 16 DUP(?) ;temporary storage of line to display
- SAVECX DW ? ;temporary storage of CX
-
- ASSUME DS:DUMMY_SEG,ES:nothing
- LINES_HEX:
-
- test BL,DISPLAY_BIT ;display ?
- jnz _HEX00 ; yes
- add si,16 ;just counting lines
- jmp _LN15 ;end of line
-
- _HEX00: push bp ;save variable
- mov bp, OFFSET HEX_BUF ;BP points to temporary table
- mov TEMP,dx ;save dx
-
- call DISP_HEX_OFFSET ;display file offset for this line
-
- mov cx,16 ;16 characters per line
-
- _HEX0: cmp si,FILE_END
- jb _HEX1
- mov SAVECX,cx ;save CX
- mov cx,SCREEN_COLS ;if FORWARD fails, space out 80 chars
- call FORWARD
- mov cx,SAVECX
- jc _HEX3 ;EOF, display what we have (<16 chars)
-
- _HEX1: lods FILE_BUFF ;Get a byte.
- mov cs:[bp],al ;store in table
- inc bp
- loop _HEX0 ;loop 16 times
- mov SAVECX,0 ;means display 16 chars from table
- jmp _HEX4
-
- _HEX3: mov dx,SCREEN_COLS ;fixup DI for EOF case
- shl dx,1
- sub di,dx
- mov SAVECX,cx ;cx is < 16 meaning display 16-cx chars
-
- _HEX4: mov bp, OFFSET HEX_BUF ;BP -> table
- mov cx,16 ;loop counter
- mov al,' ' ;space character for PRINT_CHAR routine
-
- _HEX5: mov dh,cs:[bp] ;get byte in table
- cmp cx,SAVECX ;EOF case?
- jg _HEX6 ; no
- call PRINT_CHAR ;print 2 spaces instead of HEX digits
- call PRINT_CHAR
- jmp short _HEX7
- _HEX6: call HEX8OUT ;print 2 hex digits
- _HEX7: call PRINT_CHAR ;print a space
- inc bp
- loop _HEX5
-
- mov cx,2
- call PAD_SPACES ;print 2 spaces
-
- mov bp, OFFSET HEX_BUF ;BP -> table
- mov cx,16 ;loop counter
- _HEX8: mov al,cs:[bp]
-
- cmp cx,SAVECX ;EOF case?
- jg _HEX9 ; no
- MOV AL,' ' ;print a space instead
- call PRINT_CHAR
- jmp short _HEX10
- _HEX9:
- IFDEF BLANK_BIT
- TEST BL,BLANK_BIT ;stripping non-ascii ?
- JZ _HEX10 ;no - go display char
- CMP AL,space ;control character?
- JGE _HEX10 ;no - go display char
- MOV AL,'.' ;blank non-ascii char
- ENDIF
-
- _HEX10: call PRINT_CHAR ;print IBM ASCII of character
- inc bp
- loop _HEX8
-
- mov cx,2
- call PAD_SPACES ;print 2 spaces
-
- mov dx,TEMP ;restore variables
- pop bp
-
- mov cx,SCREEN_COLS ;if >80 screen, fill-out with spaces
- sub cx,80
- jbe _HEX11
- call PAD_SPACES
- _HEX11: jmp _LN15 ;end of line
-
-
- ;Routine to display the file offset of the current line
- DISP_HEX_OFFSET PROC NEAR
- call GET_FPTR ;get absolute file pointer in DX:AX
-
- call HEX8OUT ;print high word
- xchg dl,dh
- call HEX8OUT
-
- push ax ;save low word of file offset
-
- mov al,' '
- call PRINT_CHAR
-
- pop dx ;restore low word of file offset
-
- call HEX8OUT ;print low word
- xchg dl,dh
- call HEX8OUT
-
- mov al,':'
- call PRINT_CHAR
- mov al,' '
- call PRINT_CHAR
- DISP_HEX_OFFSET ENDP
-
-
- ;print the character in AL
- PRINT_CHAR PROC NEAR
- push dx ;save register
- mov dx,TEMP ;CGA Register or 0 for EGA/VGA
- call PUT_BYTE
- pop dx
- inc di ;Bump pointer past attribute.
- ret
- PRINT_CHAR ENDP
-
-
- ;Routine for converting value in DH into ASCII Hexadecimal and printing it.
- HEX8OUT PROC NEAR
- push cx ;preserve registers
- push ax
- mov cx,2 ;loop counter
-
- H8O1: push cx
- mov cl,4
- rol dh,cl ;do high nibble first
-
- mov al,dh
- and al,0fh
- daa ;add 6 if 0ah - 0fh
- add al,0f0h ;sets carry if 0ah - 0fh
- adc al,40h ;make ASCII
- call PRINT_CHAR
-
- pop cx
- loop H8O1
-
- pop ax
- pop cx
- ret
- HEX8OUT ENDP
-
-
- ;--------------------------------------------------------;
- ; This subroutine expands tabs in VIEW
- ; On entry : CX = columns remaining to display
- ; Returns : updated CX
- ; Modifies : AX, CX
- ;--------------------------------------------------------;
- ASSUME DS:DUMMY_SEG,ES:nothing
- DO_TAB PROC NEAR
- JCXZ _D_T2
-
- mov ax,SCREEN_COLS
- and ax,7 ;ax = SCREEN_COLS % 8
- add ax,cx ; (makes cx evenly divisible by 8)
-
- DEC AX ;Adjust column counter.
- AND AX,7 ;Get bottom three bits.
- INC AX ;Adjust.
- CMP CX,SCREEN_COLS
- JA _D_T1
- PUSH CX
- PUSH AX
- XCHG AX,CX
- CALL PAD_SPACES ;Move to next tab position.
- POP AX
- POP CX
- _D_T1: SUB CX,AX ;Adjust counter.
- _D_T2: RET
- DO_TAB ENDP
-
-
- ;-------------------------------------------------------------------;
- ; This subroutine reads the next 1/2 buff
- ; Saves :AX, BX, CX, DX, DI unless end of file encountered
- ;--------------------------------------------------------;
- ASSUME DS:DUMMY_SEG,ES:nothing
- FORWARD PROC NEAR
- CMP FILE_END,OFFSET FILE_BUFF+ (READ_SIZE * 2)
- JNB _FWD1
- CALL PAD_TO_EOL
- STC
- RET
-
- _FWD1: PUSH ES
- PUSH DI ;read next block of file
- PUSH DX ; save pointers
- PUSH CX
- PUSH BX
- PUSH AX
- PUSH CS
- POP ES
- ASSUME DS:DUMMY_SEG,ES:_TEXT
-
- SUB LAST_PAGE,READ_SIZE ;Adjust current page offset.
- XOR CX,CX ;Move file pointer
- MOV DX,READ_SIZE ; forward 1/2 buffer
- CALL MOVE_POINTER
- CALL NEXT_READ
- CLC
- POP AX
- POP BX ;Restore pointers.
- POP CX
- POP DX
- POP DI
- POP ES
- RET
- FORWARD ENDP
-
-
- ;--------------------------------------------------------;
- ; This subroutine starts the first buffer read of a file
- ;--------------------------------------------------------;
- FIRST_READ PROC NEAR
- MOV LAST_PAGE,OFFSET FILE_BUFF+READ_SIZE
-
- ;--------------------------------------------------------;
- ; This subroutine moves the second half of the buffer to the
- ; the first half and then reads in a half buffer of info into the
- ; second half
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : everything
- ;--------------------------------------------------------;
- NEXT_READ PROC NEAR
- MOV SI,OFFSET FILE_BUFF+READ_SIZE
- MOV DI,OFFSET FILE_BUFF ;Move second half of buffer
- CALL MOVE_BUFFER ; to first half and read 1/2 buffer
- MOV CX,-1 ;Move file pointer back.
- NEG DX
- CALL MOVE_POINTER
- SUB AX,OFFSET FILE_BUFF + READ_SIZE
- CALL SAVE_FPTR
- RET
- NEXT_READ ENDP
- FIRST_READ ENDP
-
- ;--------------------------------------------------------;
- ; This subroutine goes back and reads the previous 1/2 buff
- ;--------------------------------------------------------;
- BACKWARD PROC NEAR
- ADD LAST_PAGE,READ_SIZE ;Adjust current page offset.
- MOV CX,-1 ;Move pointer back full buffer
- MOV DX,- (READ_SIZE * 2)
- CALL MOVE_POINTER
- SUB AX,OFFSET FILE_BUFF
- MOV SI,OFFSET FILE_BUFF+READ_SIZE; buffer to second
- CALL SAVE_FPTR
- MOV DI,SI
- MOV SI,OFFSET FILE_BUFF ;Move first half of
- CALL MOVE_BUFFER
- RET
- BACKWARD ENDP
-
- ;--------------------------------------------------------;
- ; This subroutine moves 1/2 buffer from [SI] to [DI]
- ; and then reads in a half buffer into the original [SI] position
- ; On entry : SI, DI pointers
- ; Returns : DX = bytes read
- ; Modifies : everything
- ;--------------------------------------------------------;
- ASSUME DS:DUMMY_SEG,ES:_TEXT
- MOVE_BUFFER PROC NEAR
- MOV DX,SI ;Save pointer.
- MOV CX,READ_SIZE / 2 ;Move (1/4 buffer) words=1/2 buffer
- PUSH ES
- MOV ES,MEM_BUF_SEG
-
- ASSUME ES:DUMMY_SEG
- REP MOVSW
- MOV BX,READ_HANDLE
- MOV CX,READ_SIZE ;Read 1/2 buffer.
- MOV AH,3FH ;Read file into DS:DX
- INT DOSINT ;return AX= # bytes read
- POP ES
-
- ASSUME DS:DUMMY_SEG,ES:_TEXT
- MOV SI,DX ;get back pointer
- MOV DX,AX ;save number of bytes read
- ADD AX,OFFSET FILE_BUFF + READ_SIZE
- MOV FILE_END,AX ;Store end of buffer offset.
- RET
- MOVE_BUFFER ENDP
-
- ;--------------------------------------------------------;
- ; This subroutine call DOS function to do a relative move of the file pointer
- ; On entry : no known parameters
- ; Returns : DX:AX = new pointer location
- ; Modifies : everything
- ;--------------------------------------------------------;
- ASSUME DS:DUMMY_SEG,ES:_TEXT
- MOVE_POINTER PROC NEAR
- MOV BX,READ_HANDLE
- MOV AX,4201H ;Move file pointer.
- INT DOSINT
- RET
- MOVE_POINTER ENDP
-
-
- ;--------------------------------------------------------;
- ; This subroutine saves the current absolute file pointer location
- ; in a form such that SI + FILE_PTR = absolute location in file of
- ; the first byte displayed on the screen
- ; On entry : DX:AX = (DOS pointer) - OFFSET FILE_BUFF of last read
- ; Returns : nothing
- ; Modifies : DX
- ;--------------------------------------------------------;
- ASSUME DS:DUMMY_SEG,ES:_TEXT
- SAVE_FPTR PROC NEAR
- JNC _SFP1
- DEC DX
- _SFP1: MOV FILE_PTR,AX ;save pointer low word
- MOV FILE_PTR+2,DX ;and high
- ; RET ;let this run on and display pointer
- SAVE_FPTR ENDP
-
-
- ;-------------------------------------------------------------------;
- ; Display on VIEW status line the current position in file
- ; On entry : SI contains current position in buffer
- ; Returns : nothing
- ; Modifies : AX, BX, CX, DX, DI
- ; Preserves: DS, SI, BP
- ;-------------------------------------------------------------------;
- PUT_WHERE PROC NEAR
- ASSUME DS:DUMMY_SEG,ES:_TEXT
- PUSH SI
- PUSH DS
- MOV AX,FILE_PTR
- MOV DX,FILE_PTR+2
- PUSH CS
- POP DS
- ASSUME DS:_TEXT
- ADD AX,SI
- JNC _P_W1
- INC DX
- _P_W1: MOV DI,OFFSET CMD_LINE
- PUSH DI
- MOV CX,WHERE_LEN
- CALL FORMAT
- POP SI
- MOV CX,WHERE_LEN
- MOV DI,2 * WHERE_LOC
- CALL PUT_CX_CHARS
- MOV SI,OFFSET OPTIONS
-
- push ax
- mov ax,SCREEN_COLS ;MOV DI,2 * (78 - OPTIONS_LEN)
- dec ax
- dec ax
- sub ax,OPTIONS_LEN
- shl ax,1
- mov di,ax
- pop ax
-
- MOV CX,OPTIONS_LEN
- MOV BL,VIEW_FLAGS ;get option flags
- ROL BL,1 ;star option always displayed
- _P_W2: LODSB ;get option mneumonic
- RCR BL,1 ;rotate through carry
- JC _P_W3 ;is option set?
- OR AL,20H ;no - display lower case
- _P_W3: CALL PUT_CHAR ;display it
- LOOP _P_W2 ;do some more
- POP DS
- POP SI
- RET
- PUT_WHERE ENDP
-
- ;--------------------------------------------------------;
- ; This subroutine gets the current absolute file pointer
- ; location of the first byte displayed on the screen
- ; Returns : DX:AX = FILE_PTR + SI
- ;--------------------------------------------------------;
- ASSUME DS:DUMMY_SEG,ES:_TEXT
- GET_FPTR PROC NEAR
- _GFP1: MOV AX,FILE_PTR ;get pointer low word
- MOV DX,FILE_PTR+2 ;and high
- ADD AX,SI
- JNC _GFP_RET
- INC DX
- _GFP_RET: RET ;let this run on and display pointer
- GET_FPTR ENDP
-
-
- TEST_FPTR PROC NEAR
- CALL GET_FPTR
- CMP DX,RETRN_PTR+2
- JNE _TF_RET
- CMP AX,RETRN_PTR
- _TF_RET: RET
- TEST_FPTR ENDP
-
- ;----------------------------------------------------------------------;
- ; This subroutine displays the highlighted file for viewing. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : everything
- ;----------------------------------------------------------------------;
- ASSUME DS:_TEXT,ES:_TEXT
- VIEW_DIR PROC NEAR
- PUSH SI ;save pointer
- MOV DI,OFFSET TMP_BUFF ;point to storage
- MOV SI,DI ;and save a copy
- MOV AL,space ;use spaces
- MOV CX,8 ;to clear TMP_BUFF
- REP STOSB
- MOV DI,FILE_NAME ;get dir/filename pointed to
- MOV AX,[DI]
- CMP AX,'..' ;is it parent?
- JNZ _V_D2 ;no - go ahead
-
- DEC DI ;save currently displayed dir name
- DEC DI
- PUSH DI
- MOV CX,DI
- SUB CX,OFFSET SOURCE -1
- MOV AL,'\'
-
- IFDEF SAG
- CMP SWITCH,"/" ;do we really want "/" instead?
- JE _V_D1 ;no
- MOV AL,'/' ;yes
- _V_D1:
- ENDIF
- STD
- REPNZ SCASB ;find beginning
- INC DI
- CLD
- POP CX
- SUB CX,DI
- XCHG SI,DI ;now DI points to TMP_BUFF
- INC SI
- REP MOVSB ;save current dir
-
- _V_D2: POP SI ;get back pointer to cur dir
- CALL NEW_WORK_DIR ; and change directory
-
- _V_D3: CALL GET_NAME ;get SI pointer to current name
- INC SI ;point to first char
- MOV CX,8 ;limit search to filename field
- MOV DI,OFFSET TMP_BUFF
- PUSH DI
- REPZ CMPSB ;string compare
- POP DI
- JZ _V_D_RET ;found it - all done
- MOV BL,[DI] ;check first char of dir name
- CMP BL,space ;is there anything but spaces?
- JZ _V_D_RET ;no, so all done
- CALL SEARCH
- JNC _V_D3 ;carry if SEARCH failed
- _V_D_RET:
- RET
- VIEW_DIR ENDP
-
- SUBTTL Subroutines for changing working or destination directories
- page
-
- ;-----------------------------------------
- ; Change the current drive and default directory.
- ; On entry : DS:SI = ASCIIZ path name including optional drive
- ; Returns : AX = error codes if carry set
- ;-----------------------------------------
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- CHANGE_PATH PROC NEAR
- CMP BYTE PTR [SI],0 ;is there anything at all
- JZ _C_D_DX
- CMP WORD PTR [SI+1],':' ;is there only a drive change?
- JZ _C_D_D2 ;yes
-
- _C_D_D1:
- MOV DX,SI ; DS:DX =ASCIIZ path name, may include drive
- MOV AH,3BH ; Change the default directory.
- INT DOSINT
- JC CD_ERROR ;error encountered, bypass drive change
-
- _C_D_D2:
- MOV DX,[SI]
- CMP DH,':' ;is there a drive specification?
- JNZ _C_D_D3 ;no - go exit
-
- AND DL,1FH
- DEC DL ;convert drive letter to 0,1..
- MOV AH,0EH ; Change default drive to DL, 0=A, 1=B
- INT DOSINT ;returns number of drives in AL
- MOV AH,19H ;get default drive into AL, 0=A, 1=B
- INT DOSINT ;to test and
- CMP AL,DL ;see if it worked
- JNZ CD_ERROR ;failed drive change
- _C_D_D3:
- CLC
- _C_D_DX:
- RET
- CHANGE_PATH ENDP
-
- ;--------------------------------------------------------;
- ; display "invalid directory" error message
- ; On entry : no known parameters
- ; Returns : carry flag set
- ; Modifies : AX, CX, DX at least
- ;--------------------------------------------------------;
- CD_ERROR PROC NEAR
- MOV SI,OFFSET INVALID ;error message.
- MOV AH,INTENSE ;get display attribute
- OR AH,80H ;make it blink
- MOV DI,PROMPT_LOC
- CALL PUT_STRATT
- CALL DELAY
- STC
- RET
- CD_ERROR ENDP
-
- ;---------------------------------------------------------;
- ; This subroutine gets the current directory, precedes it with
- ; a \, and saves it at [DI]
- ; On entry : DI points to destination
- ; Returns : nothing
- ; Modifies : AX, DX, DI, SI
- ;---------------------------------------------------------;
- GET_PATH PROC NEAR
- MOV AH,19H ;get default drive into AL, 0=A, 1=B
- INT DOSINT
- ADD AL,"A" ;Convert to ASCII.
- PUSH AX
- STOSB
- MOV AX,"\:" ;Add colon and slash.
- STOSW
- MOV SI,DI ;now pointing to work_dir
- XOR DL,DL
- MOV AH,47H ;Retrieve default directory.
- INT DOSINT
-
- IFDEF SAG
- CMP SWITCH,'/' ;Should we translate \ to / ?
- JE _G_D4 ;NO
- PUSH DI ;save on stack
- DEC DI ;point to first slash after volume
- _G_D1: CMP BYTE PTR [DI],0 ;End of String?
- JE _G_D3 ;yes
- CMP BYTE PTR [DI],'\' ;backsash?
- JNE _G_D2 ;no
- MOV BYTE PTR [DI],'/' ;turn it into a /
- _G_D2: INC DI ;loop
- JMP SHORT _G_D1
- _G_D3: POP DI
- _G_D4:
- ENDIF
-
- POP AX
- CALL DISK_FREE ; get disk free space
- RET
- GET_PATH ENDP
-
- ;-----------------------------------------------------------;
- ; Subroutine prompts for user entry for changing directories
- ; and then parses whatever the user enters
- ; On entry : SI points to a prompt message
- ; Returns : SI pointing to new dir, AX=':' if only drive specified
- ; carry flag set if not successful
- ; Modifies : assume everything
- ;-----------------------------------------------------------;
- ASK4PATH PROC NEAR
- MOV DI,PROMPT_LOC
- CALL PUT_STRING
- CALL TO_DEST ;Ask user for destination.
- JC _A4P_RET ;If Esc pressed, exit.
- XOR AL,AL
- STOSB ;end string with null
- MOV SI,OFFSET ENTRY ;get first 2nd and 3rd bytes
- MOV AX,[SI+1]
- CMP AX,':' ;is this the end?
- CLC
- JNZ _A4P_RET ;If no, we're done
- MOV WORD PTR [SI+2],'.' ;add a '.',0 to string to fool dos
- _A4P_RET:
- RET
- ASK4PATH ENDP
-
- ;---------------------------------------------------------------;
- ; Subroutine to prompt for and then change the working directory
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : assume everything
- ;--------------------------------------------------------;
- CD_WORK PROC NEAR
- MOV SI,OFFSET CD_MSG ;Display prompt
- CALL ASK4PATH
- JC _CD_W_RET
- MOV BL,WORK_PATH ;get old work drive:
- MOV AX,[SI] ;check for drive spec
- CMP AH,':'
- JNZ _CD_W1 ;no drive, change to old work
- AND AL,5FH ;capitalize drive request
- CMP AL,BL ;is new drive=old work drive?
- JNZ NEW_WORK_DIR ;no - just get new path
- ;drive has not changed, but
- CMP AL,DEST_PATH ;is drive same as current dest?
- JNE NEW_WORK_DIR ;no, different drives
- ;make sure we start from old work dir:
- _CD_W1: PUSH SI ;save the new path for work-dir
- MOV SI,OFFSET WORK_PATH ;get back last work path and disk
- CALL CHANGE_PATH ;restore old cur-dir on old work disk
- POP SI ;get back new path and set new work dir
-
- ;---------------------------------------------------;
- ; routine to display a new working directory
- ; On entry : SI points to new dir
- ; Returns : nothing
- ; Modifies : assume everything
- ;---------------------------------------------------;
- NEW_WORK_DIR PROC NEAR
- CALL CHANGE_PATH ;And change drive.
- CALL READ_DIR ; read dir and restart program
- _CD_W_RET:
- RET
- NEW_WORK_DIR ENDP
- CD_WORK ENDP
-
- ;--------------------------------------------------------;
- ; Subroutine to prompt for and then change the default destination directory
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : assume everything
- ;--------------------------------------------------------;
- CD_DEST PROC NEAR
- MOV SI,OFFSET CHDEST_MSG ;Display prompt
- CALL ASK4PATH
- JC _CD_D_RET ;escape out
-
- MOV AX,[SI]
- CMP AH,':'
- JNZ _CD_D1
- ;if old destination drive = work drive, and this is a drive change
- ;then we must restore work_path on work_drive to keep things straight
- MOV AH,DEST_PATH
- CMP AH,AL ;is there a drive change?
- JZ _CD_D1 ;no, go on with dir change
- CMP AH,WORK_PATH ;was work a dir on orig dest drive?
- JNZ _CD_D1 ;no, go on
- MOV DX,OFFSET WORK_PATH ;restore work dir on work drive
- MOV AH,3BH ; Change the default directory.
- INT DOSINT ; DS:DX =ASCIIZ path name, may include drive
-
- _CD_D1:
- SET_DEST PROC NEAR
- CALL CHANGE_PATH ;And change drive.
- CALL UPD_DEST ;update stored info
- MOV AX,DEST_CLUSTER
- MOV TARG_CLUSTER,AX
- CALL COUNT_MARKS
- CALL PUT_MENU_PATHS
- _CD_D_RET:
- RET
- SET_DEST ENDP
- CD_DEST ENDP
-
-
- ;--------------------------------------------------------;
- ; Subroutine to update stored info about the current destination dir
- ; On entry : DOS must be logged on to destination drive and dir
- ; Returns : nothing
- ; Modifies : everything
- ;--------------------------------------------------------;
-
- UPD_DEST PROC NEAR
- MOV DI,OFFSET DEST_PATH ;Point to storage.
- CALL GET_PATH ;use DOS to store current dir at [DI]
- MOV AL,DEST_PATH
- MOV TARG_DISK,AL ;set default target=destination disk
- RET
- UPD_DEST ENDP
-
- ;--------------------------------------------------------;
- ; This subroutine swaps the default destination and
- ; working directories
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : AX, CX, SI, DI
- ;--------------------------------------------------------;
- ASSUME CS:_TEXT, DS:_TEXT, ES:_TEXT
- SWAP_DIR PROC NEAR
- MOV SI,OFFSET WORK_PATH
- MOV DI,OFFSET DEST_PATH
- CLD
- MOV CX,70
- REP MOVSB
- CALL READ_DIR
- RET
- SWAP_DIR ENDP
-
-
- ;----------------------------------------------------;
- ; This subroutine checks whether function is to be applied to
- ; several marked files or just one file. User is then prompted for
- ; a destination path which is read from the keyboard.
- ; On entry : SI points to a prompt message for requesting a destination
- ; Returns : Carry set if current file is directory
- ; Modifies : CX, SI
- ;----------------------------------------------------;
- SETUP_DEST PROC NEAR
- PUSH SI
- CALL COUNT_MARKS
- JNZ _CMC1 ;If any marked, exit
- CALL GET_NAME ;Else get highlighted.
-
- _CMC1: POP SI
- JNC ASK4DEST ;is it an ok name(not dir)?
- CALL BEEP ;no - signal error
- RET ;and return - else continue
-
- ;---------------------------------------------;
- ; This subroutine prompts the user for the ;
- ; destination of highlighted or marked files. ;
- ; On entry : SI points to prompt to be displayed
- ; Returns : nothing
- ; Modifies : AX, CX, SI, DI
- ;---------------------------------------------;
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- ASK4DEST PROC NEAR
- MOV DI,PROMPT_LOC
- CALL PUT_STRING
- PUSH DI
- CALL GET_NAME ;Get filename.
- POP DI
- MOV SI,FILE_NAME
- CMP MARK_CNT,0 ;were there any marked files?
- JZ _A4D1 ;If yes, instead of filename
- MOV SI,OFFSET MARKED_MSG ; display "marked"
-
- _A4D1: CALL PUT_STRING
-
- TO_DEST PROC NEAR
- MOV SI,OFFSET TO_MSG ;Display "to..."
- JUST_ASK PROC NEAR
- CALL PUT_STRING
- CALL CLEAR_OLD ;Remove last user entry.
- ;and set up cursor
- _T_D1: CALL READ_KEY ;Get a keystroke.
- XOR BH,BH ;set video page 0 for tty out
- CMP AL,27 ;Is it Esc?
- JZ _T_D3 ;If yes, abort.
- CMP AL,13 ;Is it carriage return?
- JZ _T_D4 ;If yes, execute.
- CMP AL,8 ;Is it backspace?
- JNZ _T_D2 ;If yes, backspace.
-
- CMP DI,OFFSET ENTRY ;At beginning of field?
- JZ _T_D1 ;If yes, skip.
- DEC DI ;Else, decrement pointer.
- MOV BYTE PTR [DI],0
- MOV AX,0E08H ;use BIOS TTY
- PUSH AX
- INT 10H ;to backspace
- MOV AX,0E00H + space ;blank out char
- INT 10H
- POP AX ;backspace again
- INT 10H
- JMP SHORT _T_D1
-
- _T_D2: CMP AL,space ;Is it above space?
- JBE _T_D1 ;If no, ignore.
- CMP DI,OFFSET ENTRY + 32 ;Else, is 32 char entry field full?
- JZ _T_D1 ;If yes, ignore.
- STOSB ;Else, store the character.
- MOV AH,0EH ;display using BIOS write tty
- INT 10H ;which also updates cursor
- JMP SHORT _T_D1
-
- _T_D3: CALL DISP_COUNT_MSG
- STC
- RET
-
- _T_D4: CLC
- RET
- JUST_ASK ENDP
- TO_DEST ENDP
- ASK4DEST ENDP
- SETUP_DEST ENDP
-
-
- SUBTTL Major support subroutines
- page
- ;***************************;
- ; MAJOR SUPPORT SUBROUTINES ;
- ;***************************;
-
- ;---------------------------------------------------------------------;
- ; Set screen size dependant variables ;
- ;---------------------------------------------------------------------;
-
- SET_SCREEN_VARS PROC NEAR
- mov ax,ROM_BIOS_DATA ;Point to the ROM BIOS data area
- mov ds,ax ; and get base address of active
- ASSUME DS:ROM_BIOS_DATA
-
- mov bl,DOS_ROWS ;Physical display rows - 1
- mov bh,DOS_COLS ;Physical display columns
-
- mov ax,cs
- mov ds,ax ;back to normal data segment
- ASSUME DS:_TEXT
-
- inc bl
- mov byte ptr SCREEN_ROWS,bl
- mov byte ptr SCREEN_COLS,bh
- dec bl
- dec bl
- mov VIEW_ROWS,bl ;SCREEN_ROWS-2 =rows in view display
- dec bl
- dec bl
- mov byte ptr DIR_ROWS,bl ;SCREEN_ROWS-4
- add bl,ROW1
- mov byte ptr LAST_ROW,bl ;ROW1+DIR_ROWS
-
- CROW 0, 1, ROW_LEN
- CROW 1, ROW1, BAR_START
- inc BAR_START
- CROW 0, DIR_ROWS, DIR_ROW_END
-
- mov ax,BAR_START
- add DIR_ROW_END,ax ;DIR_ROW_END=BAR_START+0 CROW DIR_ROWS
-
- CROW 49, 2, MENU_STRT
- CROW 47, (3+MENU_ROWS), PROMPT_LOC
- CROW 47, (4+MENU_ROWS), PROMPT_LOC2
- CROW (40-20/2), 12, LOAD_SORT_LOC
-
- mov ax,PROMPT_LOC
- add ax,8
- mov SORT_LOC,ax
-
- CROW (40-20/2), 12, LOAD_LOC
- CROW 8, 0, DIRECT_LOC
- CROW 6, LAST_ROW, FILES_LOC
- CROW 1, 1, DEST_LOC
-
- mov dx,SCREEN_ROWS
- dec dx
- CROW 2, dx, D_FREE_LOC
-
- mov dx,SCREEN_ROWS
- dec dx
- CROW 46, dx, MARKED_LOC
-
- mov byte ptr MARKED_WIN, 45
- mov ax,SCREEN_ROWS
- dec ax
- mov byte ptr MARKED_WIN+1,al
-
- mov byte ptr END_WINDOW+1,al
- mov ax,SCREEN_COLS
- dec ax
- mov byte ptr END_WINDOW,al
- ret
- SET_SCREEN_VARS ENDP
-
-
- ;---------------------------------------------------------------------;
- ; Save DOS screen on entry to program ;
- ;---------------------------------------------------------------------;
-
- SAVE_DOS_SCREEN PROC NEAR
- ASSUME DS:_TEXT
-
- mov al,byte ptr SCREEN_ROWS
- mov DOS_SCREEN_LINES,al
- mov al,byte ptr SCREEN_COLS
- mov DOS_SCREEN_COLS,al
-
- mov ah,0fh
- int 10h ;get video mode into AL
- mov DOS_VIDMODE,al
- cmp al,3
- jne NO_SAVE
-
- mov ah,0fh ;get dos cursor location
- int 10h ;Get Current Video State
- mov al,bh ;get video page on screen
- mov bh,al
- mov ah,3
- int 10h ;Read Cursor Position and Size
- mov DOS_CURSOR_ROW,dh
- mov DOS_CURSOR_COL,dl
-
- ; Save DOS screen into DOS_SCREEN_BUF
-
- push es ;save registers
- push ds
- push si
- push di
-
- mov ax,cs
- mov es,ax
-
- MOV DS,CS:VIDEO_SEG ;Point to screen segment.
-
- mov di,offset CS:DOS_SCREEN_BUF ;get buffer address
- mov si,0 ;SI = starting address on screen
- cld ;all memory moves are forward direction
-
- mov al,CS:DOS_SCREEN_LINES
- mul CS:DOS_SCREEN_COLS
- mov cx,ax
-
- NextCol:
- lodsw ;get the source character and attribute
- stosw ;and put it in its new home
- dec cx ;show that we just did a column
- jnz NextCol ;continue until done with this row
-
- pop di ;restore registers
- pop si
- pop ds
- pop es
-
- NO_SAVE:
- ret
- SAVE_DOS_SCREEN ENDP
-
-
- ;---------------------------------------------------------------------;
- ; Restore DOS screen on entry to program ;
- ;---------------------------------------------------------------------;
-
- RESTORE_DOS_SCREEN PROC NEAR
- ASSUME DS:_TEXT
-
- ; Restore DOS screen from DOS_SCREEN_BUF
-
- push es ;save registers
- push ds
- push si
- push di
-
- mov ax,cs
- mov es,ax
-
- MOV DS,CS:VIDEO_SEG ;Point to screen segment.
-
- mov di,offset CS:DOS_SCREEN_BUF ;get buffer address
- mov si,0 ;SI = starting address on screen
- cld ;all memory moves are forward direction
-
- xchg si,di ;source is now memory not screen
- push ds
- push es
- pop ds ;ES=old DS
- pop es ;DS=old ES
-
- mov al,CS:DOS_SCREEN_LINES
- mul CS:DOS_SCREEN_COLS
- mov cx,ax
-
- NextCol2:
- lodsw ;get the source character and attribute
- stosw ;and put it in its new home
- dec cx ;show that we just did a column
- jnz NextCol2 ;continue until done with this row
-
- pop di ;restore registers
- pop si
- pop ds
- pop es
-
- ; Restore DOS Cursor
-
- mov dh,DOS_CURSOR_ROW ;row
- mov dl,DOS_CURSOR_COL ;column
- mov bh,0 ;page
- mov ah,2 ;locate cursor function
- int 10h
-
- ret
-
- RESTORE_DOS_SCREEN ENDP
-
-
- ;------------------------------------------------------------------------;
- ; This subroutine either copies moves or deletes
- ; a highlighted or marked file.
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : assume everything. SI points to filename field
- ;------------------------------------------------------------------------;
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- EXEC_MARKED PROC NEAR
- CALL CURSOR_OFF ;Turn cursor off.
- TEST FUNCTION,COPY_BIT ;if a copy is involved
- JZ _XM_2
- CALL GET_BYTES_FREE ;get space available on target
- JNC _XM_1
- JMP CD_ERROR
-
- _XM_1: CALL GET_MEM
- JNC _XM_2
- JMP _XM_RET
-
- _XM_2: CALL COUNT_MARKS ;update bytes marked
- JNZ _XM_3 ;If any marked files, go find them.
- CALL PUT_AMARK ;and mark it
- MOV BYTE PTR [SI],space ;but don't let it show
- JMP SHORT _XM_5 ;And execute it one time.
-
- _XM_3: CALL HOME_BAR ;Home the highlight bar.
-
- _XM_4: CALL REFRESH_DIR_DISP ;Update the screen.
- CALL GET_NAME ;Get the highlighted filename.
- CMP BYTE PTR [SI],COPY_MARK ;Is it marked?
- JZ _XM_5 ;If yes, execute command.
- CALL DN_ARROW ;Else, move down a row.
- JMP SHORT _XM_4 ;And check it for a mark.
-
- _XM_5: CALL GET_NAME ;test current file for hidden
- JNZ _XM_6
- INC MARK_CNT ;fool marked file counters
- JMP _XM_15 ;If yes, skip.
-
- _XM_6: CALL GET_FSIZE ;get file size
- MOV SIZE_LOW,AX ;to be sure it is stored
- MOV SIZE_HIGH,DX ;for future use
- CALL DISP_COUNT ;update counter displays
- TEST FUNCTION,PROTECT_BIT+RENAME_BIT ;Is it a move or rename?
- JZ _XM_11 ;no, bypass "file exists" test
-
- ;check if target filename already exists.
- CALL PARSE_ENTRY ;Else, parse user entry.
- MOV DX,BP ;BP points to filename entry
- TEST FUNCTION,RENAME_BIT ;simple rename ?
- JNZ _XM_7 ; yes, just use new filename
- MOV DX,OFFSET TARGET ;move rename-Point to target.
- _XM_7: PUSH DX ;save target
- MOV CX,7 ;Does the file exist?
- CALL FIND_FIRST
- POP DI ;get back target
- JC _XM_8
- JMP _XM_15 ; skip since file already exists
- _XM_8: TEST FUNCTION,COPY_BIT ;Is it across drives?
- JNZ _XM_12 ;Is yes copy/delete.
- ;file rename and/or move
- MOV DX,OFFSET SOURCE
- PUSH DI ;save target again
- MOV AH,56H ;Else, rename it.
- INT DOSINT
- POP DX ;get back target
- JNC _XM_9
- JMP _XM_15 ;Next one if failed.
- _XM_9: TEST FUNCTION,MOVE_BIT ;is this a move?
- JNZ _XM_14 ;yes, remove it from list.
- MOV CX,17H ;else assume rename
- CALL FIND_FIRST ;find target
- MOV DI,CUR_FILE ;Point to last entry.
- CMP BYTE PTR [DI],COPY_MARK ;was it marked?
- JNZ _XM_10 ;If yes,
- MOV BYTE PTR [DI],"*" ; mark as done
- _XM_10: PUSH DI
- INC DI
- CALL STORE_ENTRY ;save new filename
- POP DI
- DEC COUNT ;correct total count since not new
- CMP BYTE PTR [DI].D_SIZE,'<';directory?
- JZ _XM_16 ;yes
- DEC FILE_CNT ;else correct file count
- JMP SHORT _XM_16 ;next one
-
- _XM_11: TEST FUNCTION,COPY_BIT ;Is it a copy request?
- JZ _XM_13 ;If no, check delete.
- CALL PARSE_ENTRY ;Else parse user entry.
-
- _XM_12: CALL READ_WRITE ;Copy the file.
- JC _XM_15 ;If failed, skip rest.
- MOV SI,CUR_FILE ;Else, mark with asterisk
- MOV BYTE PTR [SI],"*"
-
- _XM_13: TEST FUNCTION,DELETE_BIT ;Is it a delete request?
- JZ _XM_16 ;If no, skip.
- MOV DX,OFFSET SOURCE ;Else, delete the file.
- MOV DI,CUR_FILE ;Point to last entry.
- CMP BYTE PTR [DI].D_SIZE,'<';directory?
- JNZ _XM_13A ;no
- MOV AH,3AH ;remove directory
- INT DOSINT ;will fail if not empty
- JC _XM_15
- JMP _XM_14A
- _XM_13A:
- MOV AH,41H
- INT DOSINT
- JC _XM_15
- MOV AX,SIZE_LOW ;decrement marked bytes
- MOV DX,SIZE_HIGH
- MOV CX,WORK_CLUSTER
- CALL ROUND_UP
- ADD AX,WORK_BYTES_FREE
- ADC DX,WORK_BYTES_FREE+2
- MOV BL,WORK_PATH
- CALL UPD_FREE_COUNT
- ; CMP CL,DEST_PATH ;is dest = work
- ; JNZ _XM_14
- ; ADD DEST_BYTES_FREE,AX ;update dest disk values too
- ; ADC DEST_BYTES_FREE+2,DX ;
-
- _XM_14: DEC FILE_CNT
- _XM_14A:
- CALL REMOVE_FILE ;If successful, remove from list.
- JMP SHORT _XM_16
-
- _XM_15: CALL BEEP
- CALL DN_ARROW ;Go to next line.
- JMP SHORT _XM_17
- ;MARK_CNT is used as a loop counter indicating files left to be processed
- ;Note that when there is a failure MARK_CNT no longer equals the
- ; count of marked files
- ;
- _XM_16: MOV AX,SIZE_LOW ;decrement marked bytes
- MOV DX,SIZE_HIGH
- MOV CX,TARG_CLUSTER
- CALL ROUND_UP
- SUB MARK_BYTES,AX
- SBB MARK_BYTES+2,DX
- _XM_17: DEC MARK_CNT ;update marked file counters
- CALL CK_KEY ; Was a key struck while busy
- JNZ _XM_18 ; at our copy, move or delete task?
- CMP MARK_CNT,0 ;If yes, abort, else all done?
- JLE _XM_X ;If no, continue until done.
- JMP _XM_4
-
- _XM_18: CALL READ_KEY ;Clear the keyboard buffer,
- CALL CK_KEY ; user entry and prompt.
- JNZ _XM_18
-
- _XM_X: TEST FUNCTION,COPY_BIT ;if a copy is involved
- JZ _XM_RET
- CALL RELEASE_MEM
- _XM_RET:
- RET
- EXEC_MARKED ENDP
-
-
- ;----------------------------------------------------;
- ; This section does the reading and writing to disk. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : assume everything
- ; sets SI=source file handle, DI=target file handle
- ;----------------------------------------------------;
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- READ_WRITE PROC NEAR
- CMP N_SEGS,1
- JNC _R_W1
- JMP _R_W_ERR3
-
- _R_W1: XOR DI,DI ;set flag for dest handle
- ;get some information on the target filespec, if it exists
- MOV DX,OFFSET TARGET ;Point to target filename.
- MOV CX,7
- CALL FIND_FIRST ;Get dir info
- JC _R_W4
- MOV SI,OFFSET DTA+F_ATTR
- MOV AL,[SI]
- TEST AL,1 ;is it read only?
- JNZ _R_W2 ;go signal error
-
- XOR AH,AH ;save target attribute
- PUSH DI ;save dest handle/flag
- MOV DI,OFFSET TMP_BUFF ;point to some spare room
- MOV CX,22
- REP MOVSB ;save target info
- POP DI ;get back dest flag
- MOV CX,AX ;Get back attribute
- XOR CX,1 ;Flip read-only attribute.
- MOV DX,OFFSET TARGET ;Point to target filename.
- CALL CHMOD ;change attribute
- JNC _R_W3 ;no error, proceed
- ;error returned when attempting CHMOD
- ;check to see if the error occured because target was a device, eg PRN
- MOV AX,3D01H ;open file for write
- INT DOSINT
- JC _R_W2 ;failed
- XOR BX,BX
- MOV BL,AL ;get file handle from AL
- MOV AX,4400H ;get device info
- INT DOSINT
- CALL CLOSE_FILE
- AND DX,80H ;is this a device?
- JNZ _R_W4 ;yes, ok to proceed
- _R_W2: JMP _R_W_ERR3 ;file failed CHMOD - signal error
-
- _R_W3: MOV DI,-1 ;indicate that we have tweaked target
- ;get some info about the source file
- _R_W4: MOV DX,OFFSET SOURCE ;Point to source filespec.
- MOV CX,7
- CALL FIND_FIRST ;Get source
- JC _R_W8
- MOV SI,OFFSET DTA+F_ATTR
- LODSB
- XOR AH,AH
- MOV SOURCE_ATTRIB,AX ; attribute
-
- CMP DI,-1 ;dir target exist?
- JNZ _R_W6 ;no - bypass 'same file' test
- TEST AL,1 ;is source read-only?
- MOV AL,space ;assume no
- JZ _R_W5 ;and skip
- MOV AL,'R' ;else expect 'R' mark
- _R_W5: MOV BX,CUR_FILE ;get pointer to buffer entry
- CMP AL,[BX].D_RO ;and check with what we have now
- JNZ _R_W8 ;oops - source and target are identical
-
- _R_W6: LODSW ;finish saving source info
- MOV SOURCE_TIME,AX ; time
- LODSW
- MOV SOURCE_DATE,AX ; date
- LODSW ;get low size into AX
- MOV SIZE_LOW,AX ; and save
- LODSW ; and high size word
- MOV SIZE_HIGH,AX ;and save
-
- ;files different:
- XOR AX,AX ;start with nothing
- XOR DX,DX
- CMP DI,-1 ;did filespec exist on target?
- JNZ _R_W7 ;no, we won't be deleting it
- MOV AX,WORD PTR TMP_BUFF+F_SIZE-F_ATTR ;get old size
- MOV DX,WORD PTR TMP_BUFF+F_SIZE+2-F_ATTR
- MOV CX,TARG_CLUSTER ;target cluster size
- CALL ROUND_UP ;round up
- _R_W7: ADD AX,TARG_BYTES_FREE ;add space already available on target
- ADC DX,TARG_BYTES_FREE+2 ;to space that will be freed up
- ;by deleting old target file
-
- PUSH DX ;save result
- PUSH AX
- MOV AX,SIZE_LOW ;get source size.
- MOV DX,SIZE_HIGH
- MOV CX,TARG_CLUSTER ;target cluster size
- CALL ROUND_UP ;round up
- POP BX
- POP CX
- SUB BX,AX
- SBB CX,DX
- JNB _R_W9 ;>0 enough space, go ahead
- _R_W8: CALL RESET_TARG_AT ;negative, not enough room.
- JMP _R_W_ERR3 ;set failed flag and exit
-
- _R_W9: MOV DX,OFFSET SOURCE ;Point to source filespec.
- XOR AL,AL ;Open file for reading.
- CALL OPEN_FILE
- JC _R_W8 ;flip target attr and exit
-
- ; read in from source
- _R_W10: MOV SI,AX ;Save the handle.
-
- _R_W11: MOV BX,SI ;Retrieve read handle.
-
- MOV SEG_COUNT,0 ;zero buffer counter
- MOV AX,MEM_BUF_SEG ;Point to 1st 64K buffer segment
- MOV DS,AX
- ASSUME DS:DUMMY_SEG
-
- _R_W12: XOR DX,DX
- MOV CX,0FFFFH ;Read up to 64K at a time.
- MOV AH,3FH
- INT DOSINT
- MOV DX,DS ;save current buffer seg
- PUSH CS
- POP DS ;restore DS
- ASSUME DS:_TEXT
- JNC _R_W13
- JMP _R_W_ERR ;if error, close files
-
- _R_W13: MOV BP,AX ;Save bytes read.
- CMP AX,CX ;if less than full buffer read,
- JNZ _R_W14 ; go close file
- MOV AL,SEG_COUNT ;get buffer counter
- INC AL ;add 1 to count done
- CMP AL,N_SEGS ;are we at buffer limits?
- JZ _R_W15 ;yes, go write some
- MOV SEG_COUNT,AL ;one more
- ADD DX,1000H ;next 64k seg
- MOV DS,DX ;set up DS
- JMP _R_W12 ;go read more
-
- _R_W14: CALL CLOSE_FILE ;Close file
- XOR SI,SI ;mark file closed
- JC _R_W_ERR ;If there was an error, exit.
-
- _R_W15: OR DI,DI ;has target been opened?
- JG _R_W16
- CALL RESET_TARG_AT ;check/ restore target attr
- MOV DX,OFFSET TARGET ;Point to target filespec.
- XOR CX,CX ;Create and truncate target file
- MOV AH,3CH ; to zero.
- INT DOSINT
- JC _R_W_ERR
- MOV DI,AX ;Save handle.
-
- _R_W16: MOV DX,MEM_BUF_SEG ;Get pointer to buffer segment
-
- _R_W17:
- MOV CX,0FFFFH
- CMP SEG_COUNT,0
- JNZ _R_W18
- MOV CX,BP ;get back # bytes read earlier
-
- _R_W18:
- JCXZ _R_W20 ;If nothing to do, go close
- PUSH CX ;save bytes to write
- MOV DS,DX ;set up buffer segment
- ASSUME DS:DUMMY_SEG
-
- XOR DX,DX
- MOV BX,DI ;Retrieve write handle.
- MOV AH,40H
- INT DOSINT ;Write the buffer to disk.
- POP AX ;get back bytes to write
- MOV DX,DS ;save current buffer ptr
- PUSH CS
- POP DS
- ASSUME DS:_TEXT
-
- JC _R_W_ERR ;abort if error in write
- CMP AX,CX ;Did we write same number as read?
- JNZ _R_W_ERR ;If we didn't, exit.
- DEC SEG_COUNT ;count off one buffer full
- JS _R_W19 ;done with this buffer read if <0
- ADD DX,1000H ;next 64k chunk
- JMP _R_W17
-
- _R_W19:
- OR SI,SI ;is source still open?
- JZ _R_W20
- JMP _R_W11 ;If yes, there must be more.
-
- _R_W20: MOV BX,DI
- MOV CX,SOURCE_TIME ;Else, make time/date same
- MOV DX,SOURCE_DATE ; as source.
- MOV AX,5701H
- INT DOSINT
-
- _R_W21: MOV BX,DI
- CALL CLOSE_FILE
- JMP SHORT _R_W_RET
-
- _R_W_ERR:
- OR SI,SI ;check is file open?
- JZ _R_W_ERR1 ;bypass if zero
- MOV BX,SI ;get read handle
- CALL CLOSE_FILE ;Close file
-
- _R_W_ERR1:
- OR DI,DI ;check is file open?
- JG _R_W_ERR2 ;file is open
- JZ _R_W_ERR3 ;0 means all done
- CALL RESET_TARG_AT ;must be -1
- JMP SHORT _R_W_ERR3
- _R_W_ERR2:
- MOV BX,DI
- CALL CLOSE_FILE
- _R_W_ERR3:
- STC
- _R_W_RET:
- PUSHF
- CALL GET_BYTES_FREE ;get space available on target
- POPF
- RET
- READ_WRITE ENDP
-
-
- ;reset attribute on target
- RESET_TARG_AT PROC NEAR
- CMP DI,-1
- JNZ _R_T_RET
- MOV DX,OFFSET TARGET ;Point to target filename.
- MOV CL,TMP_BUFF ;get original attribute
- XOR CH,CH ;clear high byte
- CALL CHMOD ;change attribute
- MOV DI,0 ;clear handle as a flag
- _R_T_RET:
- RET
- RESET_TARG_AT ENDP
-
- ;--------------------------------------------------------------------------;
- ; This subroutine gets the highlighted file and converts it to DOS format. ;
- ; On entry : CUR_OFFSET points to a filname entry
- ; DIR_OK_BIT is set in FUNCTION if function is allowed
- ; on <DIR> entries.
- ; Returns : SI points to current file
- ; Carry flag is set if function is prohibited on this entry
- ; Zero flag set if entry is hidden but otherwise allowed
- ; updates : CUR_FILE, fills in SOURCE
- ; Modifies : AX, CX, SI, DI
- ;--------------------------------------------------------------------------;
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- GET_NAME PROC NEAR
- MOV SI,CUR_OFFSET ;Get top of page.
- MOV AX,LINE ;Get location of bar.
- SUB AX,BAR_START ;Adjust.
- push dx
- xor dx,dx
- mov cx,ROW_LEN
- div cx
- mov cx,FIELD_SIZE
- mul cx
- pop dx
- ADD SI,AX ;Add to current offset.
- MOV CUR_FILE,SI ;And save pointer.
- PUSH SI
- INC SI ;Bump past mark field.
- MOV DI,FILE_NAME ;Store the first eight characters.
- MOV CX,8 ;in SOURCE
- CALL STORE_BYTES
- INC SI
- CMP BYTE PTR [SI],space ;End of name?
- JZ _G_N_RET ;If yes, done here.
- MOV AL,"." ;Else, add dot.
- STOSB
- MOV CX,3 ;Three possible characters
- CALL STORE_BYTES ; as extension.
-
- _G_N_RET:
- MOV BYTE PTR [DI],0 ;Convert to ASCIIZ.
- POP SI ;get back record ptr
- CMP BYTE PTR [SI].D_NAME,space ;Is it an empty entry?
- JZ _G_N_ERROR ;If yes, indicate so.
-
- TEST FUNCTION,DIR_OK_BIT ;are dir's allowed for this fn?
- JNZ _G_N_OK ;yes, dir's will be ok
-
- CMP BYTE PTR [SI].D_SIZE,"<" ;Is it a directory?
- JZ _G_N_ERROR ;If yes, indicate so.
-
- _G_N_OK:
- CMP BYTE PTR [SI].D_HID,"H" ;Is it hidden?
- CLC
- RET
-
- _G_N_ERROR:
- STC
- RET
- GET_NAME ENDP
-
-
- ;-----------------------------------------------;
- ; This subroutine parses the user TARGET entry. ;
- ; On entry : no known parameters
- ; Returns : nothing
- ; Modifies : everything
- ;----------------------------------------;
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- PARSE_ENTRY PROC NEAR
- MOV BP,OFFSET TARGET ;Point to target storage.
- MOV DI,BP
- MOV SI,OFFSET ENTRY ;Point to user entry.
- CMP BYTE PTR [SI],0 ;Anything entered?
- JNZ _P_E1 ;If yes, continue.
- JMP _P_E17 ;Else, store source name.
-
- _P_E1: LODSB ;Move user entry into target
- STOSB ; workspace.
- CMP AL,0
- JNZ _P_E1
- STD ;Reverse string operation.
- DEC DI ;Adjust pointer back one.
- MOV SI,DI ;Make it the source pointer.
- MOV FILENAME_END,DI ;And store.
-
- _P_E2: CMP SI,OFFSET TARGET - 1 ;Are we at start of name?
- JZ _P_E4 ;If yes, done here.
- LODSB
- CMP AL,"\" ;Else, is it a path delimiter?
- JZ _P_E3 ;If yes, mark start of filename.
- CMP AL,"/" ;Alternative path delimiter?
- JZ _P_E3 ;If yes, mark start of filename.
- CMP AL,":" ;Colon is also a path delimiter.
- JNZ _P_E2
-
- _P_E3: INC SI ;Adjust pointer to end of path.
- _P_E4: INC SI
- MOV BP,SI ;And store.
- CLD ;String back to forward.
- MOV DI,OFFSET PSP_FCB ;Use file control block for
- MOV AX,2900H ; workspace.
- INT DOSINT ;Parse the entry for globals.
- CMP AL,1 ;Any wild cards?
- JNZ _P_E15 ;If no, check if it's a directory.
-
- MOV SI,OFFSET PSP_FCB + 1 ;Else, point to first character.
- MOV DI,BP ;Point to target storage.
- MOV BX,FILE_NAME ;Point to source.
- MOV CX,8 ;Eight characters.
-
- _P_E5: LODSB
- CMP AL,space ;End of name?
- JZ _P_E8 ;If yes, do extension.
- CMP AL,"?" ;Wild card?
- JNZ _P_E6 ;If no, store target character.
- MOV AL,[BX] ;Else, replace with source char.
- CMP AL,"." ;Unless end of name.
- JZ _P_E8
- CMP AL,0
- JZ _P_E8
-
- _P_E6: STOSB ;Store the character.
- CMP BYTE PTR [BX],"." ;Are we at end of source name?
- JZ _P_E7 ;If yes, don't move pointer.
- INC BX ;Else, point to next source char.
-
- _P_E7: LOOP _P_E5
-
- _P_E8: MOV AL,"." ;Filename delimiter.
- STOSB ;Store it.
-
- _P_E9: CMP [BX],AL ;Was there a dot in source?
- JZ _P_E10 ;If yes do extension.
- CMP BYTE PTR [BX],0 ;End of source name?
- JZ _P_E11 ;If yes, do extension.
- INC BX ;Else, go to end of name.
- JMP SHORT _P_E9
-
- _P_E10: INC BX ;Bump pointer past dot.
- _P_E11: MOV SI,OFFSET PSP_FCB + 9 ;Point to extension of parsed.
- MOV CX,3 ;Three characters.
-
- _P_E12: LODSB
- CMP AL,space ;End of parsed?
- JZ _P_E14 ;If yes, done here.
- CMP AL,"?" ;Wild card?
- JNZ _P_E13 ;If no, store user character.
- MOV AL,[BX] ;Else, store source character.
-
- _P_E13: STOSB
- INC BX
- LOOP _P_E12 ;Do all three extension chars.
-
- _P_E14: XOR AL,AL ;Make it an ASCIIZ.
- STOSB
- JMP SHORT _P_E_RET ;Done here.
-
- _P_E15: MOV DI,BP ;Any characters after path
- CMP BP,FILENAME_END ; delimiter?
- JZ _P_E17 ;If no, tack on source name.
- MOV DX,OFFSET ENTRY ;Else, see if it's a directory.
- MOV CX,10H
- CALL FIND_FIRST
- JC _P_E_RET ;If not found, done here.
- CMP DTA+F_ATTR,CL ;If not directory, done here.
- JNZ _P_E_RET
- MOV DI,FILENAME_END ;Else, tack on source filename.
- MOV AL,"\"
-
- IFDEF SAG
- CMP SWITCH,"/" ;do we really want "/"?
- JE _P_E16 ;no
- MOV AL,"/" ;yes
- _P_E16:
- ENDIF
-
- STOSB
- _P_E17: MOV SI,FILE_NAME ;Source filename.
- MOV CX,14
- REP MOVSB
-
- _P_E_RET: RET
- PARSE_ENTRY ENDP
-
-
- ;------------------------------------------------------------------;
- ; This subroutine removes the filename from the directory listing. ;
- ;------------------------------------------------------------------;
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- REMOVE_FILE PROC NEAR
- MOV DI,CUR_FILE ;Point to filename.
- MOV SI,DI ;Move all the records
- ADD SI,FIELD_SIZE ; that follow up one.
-
- _R_F1: MOV CX,FIELD_SIZE
- REP MOVSB
- CMP DI,END_OFFSET
- JB _R_F1
- SUB DI,FIELD_SIZE
- MOV END_OFFSET,DI ;Store new end.
- XOR BP,BP
- CALL SCROLL ;Update the screen.
- DEC COUNT
- JZ _R_F_RET ;If empty, exit.
-
- _R_F2: mov al,byte ptr DIR_ROWS ;Full page?
- cmp byte ptr COUNT,al
-
- JAE _R_F_RET ;If yes, skip.
- mov ax,ROW_LEN ;Else, adjust page end.
- SUB DIR_DISP_END,ax
-
- MOV SI,DIR_DISP_END
- SUB SI,ROW_LEN
- CMP SI,LINE ;Is bar below directory listing?
- JA _R_F_RET ;If no, skip.
- CALL MOVE_BAR ;Else, move bar up one line.
- _R_F_RET:
- RET
- REMOVE_FILE ENDP
-
- SUBTTL Miscellaneous small support subroutines
- page
- ;***************************;
- ; OTHER SUPPORT SUBROUTINES ;
- ;***************************;
-
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- ;-----------------------------------------------------------;
- ; This subroutine moves and turns the cursor on and removes ;
- ; the last user entry in preparation for new input. ;
- ; On entry : DX points to location for prompt
- ; Returns : DI pointing to ENTRY buffer for user input
- ;-----------------------------------------------------------;
- CLEAR_OLD PROC NEAR
- MOV DX,ENTRY_CUR
- CALL SET_CURSOR ;Move cursor.
- MOV DI,OFFSET ENTRY ;Write nulls over old entry.
- PUSH DI
- XOR AX,AX
- MOV CX,18
- REP STOSW
- POP DI ;return pointer for entry.
- RET
- CLEAR_OLD ENDP
-
-
- ;----------------------------------------------------;
- ; This subroutine counts the number of marked files. ;
- ; On entry : no known parameters
- ; Returns : CX = MARK_CNT, Z flag set if CX=0
- ; Modifies : CX, SI
- ;----------------------------------------------------;
- COUNT_MARKS PROC NEAR
- OR FUNCTION,UPD_CNT_BIT
- XOR CX,CX ;Zero out counter.
- MOV MARK_BYTES,CX
- MOV MARK_BYTES+2,CX
- MOV SI,OFFSET DIR_BUFF ;Point to start of listing.
-
- _C_M1: CMP BYTE PTR [SI],COPY_MARK ;Is it marked?
- JNZ _C_M2 ;In no, skip.
- INC CX ;Else, increment counter.
- PUSH CX
- CALL GET_FSIZE
- MOV CX,TARG_CLUSTER
- CALL ROUND_UP
- ADD MARK_BYTES,AX
- ADC MARK_BYTES+2,DX
- POP CX
-
- _C_M2: ADD SI,FIELD_SIZE ;Next record.
- CMP SI,END_OFFSET ;Continue until done.
- JB _C_M1
- MOV MARK_CNT,CX ;Store the count of marked files.
- OR CX,CX
- RET
- COUNT_MARKS ENDP
-
- ;-------------------------------------------------------------;
- ; This subroutine waits until a keystroke is pressed and then ;
- ; clears the message. Keystroke is disgarded.
- ;-------------------------------------------------------------;
- DELAY PROC NEAR
- CALL READ_KEY
-
- ;----------------------------------------------;
- ; This subroutine displays the count of files. ;
- ; On entry : WORK_BYTES_FREE, DEST_BYTES_FREE, MARK_BYTES, etc
- ; Returns : upated display
- ; Modifies : everything
- ;----------------------------------------------;
- DISP_COUNT_MSG PROC NEAR
- CALL CLR_MSG
- DISP_COUNT PROC NEAR
- MOV DI,OFFSET FILES ;message string storage
- MOV SI,DI ;save it
- MOV AX,FILE_CNT
- XOR DX,DX
- MOV CX,LENGTH FILES
- CALL FORMAT
-
- MOV DI,FILES_LOC ;Row 24; column 6.
- MOV AH,INTENSE
- CALL PUT_STRATT
-
- MOV DI,D_FREE_LOC
- MOV SI,OFFSET DEST_FREE ;Display free bytes on dest
- MOV AH,INTENSE
- CALL PUT_STRATT
- ;----------------------------------------------------;
- ; This subroutine displays the byte count and number of marked files. ;
- ; On entry : MARK_BYTES and MARK_CNT contain numbers
- ; Returns : nothing
- ; Modifies : everything
- ;----------------------------------------------------;
-
- DISP_MARKED PROC NEAR
- CMP MARK_CNT,0
- JZ _D_MR1
- MOV AX,MARK_BYTES
- MOV DX,MARK_BYTES+2
- MOV CX,LENGTH BYTES_MRKD_MSG
- MOV DI,OFFSET BYTES_MRKD_MSG
- MOV SI,DI
- CALL FORMAT
- MOV AX,MARK_CNT
- XOR DX,DX
- MOV CX,LENGTH FILES_MRKD_MSG
- MOV DI,OFFSET FILES_MRKD_MSG
- CALL FORMAT
- MOV DI,MARKED_LOC
- CALL PUT_STRING
- JMP SHORT _D_MR_RET
-
- _D_MR1: MOV AL,NORMAL
- MOV CX,MARKED_WIN
- CALL CLR_EOL
-
- _D_MR_RET: RET
- DISP_MARKED ENDP
- DISP_COUNT ENDP
- DISP_COUNT_MSG ENDP
- DELAY ENDP
- ;----------------------------------------------------;
- ; Subr. to convert ascii file size into binary
- ; On entry : SI points to mark field of a marked file
- ; Returns : DX:AX = file size, rounded up to TARG_CLUSTER size
- ; Modifies : AX, BX, DX, BP, saves SI
- ;----------------------------------------------------;
-
- ;we shall assume SI points to filename
- GET_FSIZE PROC NEAR
- PUSH SI
- XOR AX,AX
- XOR DX,DX
- ADD SI,D_SIZE
- CMP BYTE PTR [SI],'<'
- JZ _GFS_RET
- MOV CX,8
- MOV BX,10
- JMP SHORT _GFS3
-
- _GFS1: XCHG AX,DX ;get high word, save low
- MUL BL ;times 10
- MOV BP,AX ;save result
- MOV AX,DX ;get back low word
- MUL BX ;times 10
- ADD DX,BP ;add in previous high word result
- _GFS3: MOV BP,AX ;save low
- XOR AH,AH ;clear byte
- LODSB ;get next digit
- SUB AL,'0' ;convert to hex byte
- JC _GFS4 ;skip spaces
- ADD AX,BP ;add in old result
- JNC _GFS5
- INC DX ;add 1 if carry in low word
- JMP SHORT _GFS5
-
- _GFS4: XOR AX,AX ;clear reg if space
- _GFS5: LOOP _GFS1
- _GFS_RET:
- POP SI
- RET
- GET_FSIZE ENDP
-
- ;----------------------------------------------------;
- ; This subroutine performs a table lookup
- ; On entry : AL contains a byte
- ; DI points to a lookup table of length CX
- ; BX points to last entry of a result table
- ; Returns : BX points to the matching entry in the result table
- ; NZ implies no match found
- ; Modifies : BX, CX, DI
- ;----------------------------------------------------;
- LOOKUP PROC NEAR
- REPNZ SCASB ;scan table
- PUSHF ;save flags
- JNZ _LK_RET ;not found
- SHL CX,1 ;multiply by two bytes per word
- SUB BX,CX ;this many bytes from end
- _LK_RET: POPF ;restore flags
- RET
- LOOKUP ENDP
-
- ;----------------------------------------------------;
- ; This subroutine performs a table lookup for a sort option
- ; Sorts are done on a field starting at SORT_OFFSET with a
- ; field length of SORT_LEN
- ; On entry : AL contains a byte to check
- ; DI points to a lookup table of length SORT_OPT_CNT
- ; Modifies : AX, BX, CX, DI
- ;----------------------------------------------------;
- SET_SORT PROC NEAR
- MOV CX,SORT_OPT_CNT
- MOV BX,OFFSET SORT_TABLE_END
- CALL LOOKUP
- JNZ _S_S_RET
- MOV AX,[BX]
- MOV BYTE PTR SORT_OFFSET,AL
- MOV BYTE PTR SORT_LEN,AH
- _S_S_RET:
- RET
- SET_SORT ENDP
-
- ;--------------------------------------------------------;
- ; This procedure does a string move, skipping over spaces
- ; On entry : SI, DI set up for move
- ; Returns : nothing
- ; Modifies : AL, CX, SI, DI
- ;---------------------------------------------------------;
- STORE_BYTES PROC NEAR
- LODSB ;Get a character.
- CMP AL,space ;If it's space, skip.
- JZ _S_B1
- STOSB
- _S_B1: LOOP STORE_BYTES
- RET
- STORE_BYTES ENDP
-
- ;---------------------------------------------------
- ; These subroutines converts a hex number to decimal.
- ; FORMAT clears field first
- ;---------------------------------------------------
- ; On entry : DX:AX=number to convert
- ; CX = length of field to be cleared first
- ; DI= start of destination field
- ; Returns : DI points to beginning of converted string
- ; Modifies : AX, BX, CX, DX, DI
- ;---------------------------------------------------;
- ASSUME DS:NOTHING,ES:NOTHING
- FORMAT PROC NEAR
- PUSH AX
- MOV AL,space
- DEC CX
- REPNZ STOSB
- POP AX
-
- ;---------------------------------------------------;
- ; On entry : DX:AX=number to convert,
- ; DI= end of destination
- ;---------------------------------------------------;
- TRANSLATE PROC NEAR
- XCHG AX,DX
- MOV BX,10 ;Convert to decimal.
- STD ;Reverse direction.
-
- _TR1: MOV CX,DX ;cx = low 16 bits of number to convert
- XOR DX,DX
- DIV BX
- XCHG AX,CX ;cx = !!!!!!!!!!!!!!
- DIV BX
- XCHG AX,DX
- ADD AL,"0" ;Convert to ASCII.
- STOSB ;Store the remainder.
- MOV AX,CX
- OR CX,DX
- JNZ _TR1
- CLD ;Back to forward direction.
- RET
- TRANSLATE ENDP
- FORMAT ENDP
-
-
- ;------------------------------------------;
- ; This subroutine rounds a number up
- ; On entry : DX:AX = number to convert
- ; CX = number base
- ; Returns : DX:AX with CX unchanged
- ;------------------------------------------;
- ROUND_UP PROC NEAR
- DIV CX ;divide by base
- OR DX,DX ;check for remainder
- JZ _R_U1 ;nothing extra?
- INC AX ;add one for remainder
- _R_U1: MUL CX ;and go back to original units
- RET
- ROUND_UP ENDP
-
- ;-------------------------------------------------;
- ; This routine formats a byte to ASCII decimal
- ; and stores it at ES:DI, followed by delimiter CL
- ; On entry : AX = number (<100) to convert
- ; CH = trailing delimiter char
- ; CL not 0 to supress leading zero
- ; Returns : nothing
- ; Modifies : assume everything
- ;-------------------------------------------------;
- STORE_DIGITS PROC NEAR
- MOV BL,10
- DIV BL ;Divide by ten.
- ADD AX,"00" ;Convert to ASCII.
- OR CL,CL ;Are we to display leading zero?
- JZ _ST_D1 ;If yes, store as is.
- CMP AL,"0" ;Is it a leading zero?
- JNZ _ST_D1 ;If no, store it.
- MOV AL,space ;Else, store a space.
-
- _ST_D1: STOSW
- MOV AL,CH ;Store delimiter character also.
- STOSB
- RET
- STORE_DIGITS ENDP
-
- SUBTTL Screen display subroutines
- page
- ;----------------------------------------------------------------------------;
- ; This subroutine displays the current directory, menu, and number of files. ;
- ;----------------------------------------------------------------------------;
-
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- PUT_MENU_PATHS PROC NEAR
- MOV AL,NORMAL
- CALL CLR_SCR ;Clear the screen.
-
- MOV DI,MENU_STRT ;And to screen position.
- MOV AL,GB_TL ;top left
- MOV BX,GB_TR + GB_TH*100h ;middle and right characters
- CALL PUT_MENU_BORDER
- MOV SI,OFFSET LOGO ;Point to menu position.
- MOV BL,LOGO_ROWS
- CALL PUT_MENU_LINES
- MOV AL,GB_L_TEE ;mid- left
- MOV BX,GB_R_TEE + GB_MH*100h ;middle and right characters
- CALL PUT_MENU_BORDER
-
- MOV SI,OFFSET MENU1
- MOV BL,MENU1_ROWS
- CALL PUT_MENU_LINES
-
- MOV AL,GB_BL ;bottom left
- MOV BX,GB_BR + GB_BH*100h ;middle and right characters
- CALL PUT_MENU_BORDER
-
- MOV AH,INTENSE
- MOV DI,DIRECT_LOC
- MOV SI,OFFSET DIRECTORY ;Display "Directory of".
- CALL PUT_STRATT
- MOV SI,OFFSET WORK_PATH ;Display working directory.
- CALL PUT_STRATT
-
- MOV DI,DEST_LOC
- MOV SI,OFFSET DEST_MSG ;Display destination msg
- CALL PUT_STRATT
- MOV SI,OFFSET DEST_PATH ;Display dest directory.
- CALL PUT_STRATT
-
- MOV AL,INVERSE
- CALL BAR ;Put up cursor bar.
- MOV FUNCTION,UPD_CNT_BIT ;force update of count displays
- RET
- PUT_MENU_PATHS ENDP
-
- ;------------------------------------------------------------;
- ; This subroutine is used to display a border line on menu
- ; On entry : AL = left border edge char to display
- ; AH = display attribute to use
- ; BH = char to repeat in middle
- ; BL = right border edge character
- ; DI = where to put char in display
- ; Returns : DI points to location of start of next line
- ; Modifies : DI, uses and preserves ES
- ;------------------------------------------------------------;
- PUT_MENU_BORDER PROC NEAR
- MOV AH,BORDER
- CALL PUT_CHARATT
- MOV AL,BH
-
- MOV CX,MENU_WIDTH
- _PMB1: CALL PUT_CHARATT
- LOOP _PMB1
-
- MOV AL,BL
- CALL PUT_CHARATT
-
- mov ax,MENU_WIDTH ;ADD DI,ROW_LEN-2*(MENU_WIDTH+2) ;Next line.
- inc ax
- inc ax
- shl ax,1
- mov bx,ROW_LEN
- sub bx,ax
- add di,bx
-
- RET
- PUT_MENU_BORDER ENDP
-
- ;------------------------------------------------------------;
- ; This subroutine is used to display a set of menu lines
- ; On entry : BL = number of lines to display
- ; SI points to lines to display after border
- ; DI = where to put chars in display
- ; Returns : DI points to location of start of next line
- ; Modifies : DI, uses and preserves ES
- ;------------------------------------------------------------;
- PUT_MENU_LINES PROC NEAR
- MOV AH,BORDER
- MOV AL,GB_V
- CALL PUT_CHARATT
-
- MOV AH,MENU_ATT
- MOV CX,MENU_WIDTH
- _PML1: LODSB
- CALL PUT_CHARATT
- LOOP _PML1
-
- MOV AH,BORDER
- MOV AL,GB_V
- CALL PUT_CHARATT
-
- push ax ;ADD DI,ROW_LEN-2*(MENU_WIDTH+2) ;Next line.
- push bx
- mov ax,MENU_WIDTH
- inc ax
- inc ax
- shl ax,1
- mov bx,ROW_LEN
- sub bx,ax
- add di,bx
- pop bx
- pop ax
-
- DEC BL
- JNZ PUT_MENU_LINES
- RET
- PUT_MENU_LINES ENDP
-
- ;-------------------------------------------------;
- ; This subroutine displays the directory listing. ;
- ;-------------------------------------------------;
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT
- REFRESH_DIR_DISP PROC NEAR
- MOV SI,CUR_OFFSET ;Retrieve starting offset.
- CROW 0,ROW1,DI ;Point to row two of screen.
- MOV BH,byte ptr DIR_ROWS ;21 lines to write.
- _R_DD1: MOV CX,FIELD_SIZE ;44 characters per line.
- CALL PUT_CX_CHARS ;Write them.
-
- mov ax,ROW_LEN
- sub ax,FIELD_SIZE * 2
- add di,ax ;Bump pointer to next line.
-
- DEC BH ;Do all 21 lines.
- JNZ _R_DD1
- RET
- REFRESH_DIR_DISP ENDP
-
- ;------------------------------------------------------------;
- ; This subroutine displays a character by writing directly ;
- ; to the screen buffer. To avoid screen noise (snow) on the ;
- ; color card, the horizontal retrace has to be monitored. ;
- ; On entry : AL = char to display
- ; DI = where to put char in display
- ; Returns : DI points to next location
- ; Modifies : DI, uses and preserves ES
- ;------------------------------------------------------------;
- ASSUME DS:NOTHING,ES:NOTHING
- PUT_CHAR PROC NEAR
- PUSH ES ;save seg register
- PUSH DX
- MOV ES,VIDEO_SEG ;Point to screen segment.
- MOV DX,STATUS_REG ;Retrieve status register.
- CALL PUT_BYTE
- INC DI ;Bump pointer past attribute.
- POP DX
- POP ES ;restore segment register
- RET ;Return
- PUT_CHAR ENDP
-
- ;------------------------------------------------------------;
- ; This subroutine displays a character and attribute
- ; On entry : AL = char to display
- ; AH = display attribute to use
- ; DI = where to put char in display
- ; Returns : DI points to next location
- ; Modifies : DI, uses and preserves ES
- ;------------------------------------------------------------;
- PUT_CHARATT PROC NEAR
- PUSH ES ;save seg register
- PUSH DX
- PUSH AX
- MOV ES,VIDEO_SEG ;Point to screen segment.
- MOV DX,STATUS_REG ;Retrieve status register.
- CALL PUT_BYTE ;put char
- MOV AL,AH
- CALL PUT_BYTE ;put attribute
- POP AX
- POP DX
- POP ES ;restore segment register
- RET ;Return
- PUT_CHARATT ENDP
-
-
- PUT_BYTE PROC NEAR
- OR DX,DX ;zero if mono or ega
- JZ _P_B3 ;don't wait if mono
-
- PUSH AX
- _P_B1: IN AL,DX ;Get status.
- TEST AL,8 ;Is vertical in retrace?
- JNZ _P_B2A ;If yes, lets go
- TEST AL,1 ;Is it low?
- JNZ _P_B1 ;If not, wait until it is.
-
- _P_B2: IN AL,DX ;Get status.
- TEST AL,1 ;Is it high?
- JZ _P_B2 ;If no, wait until it is.
- _P_B2A: POP AX
-
- _P_B3: STOSB ; to write to screen buffer.
- RET
- PUT_BYTE ENDP
-
-
- ;---------------------------------------------------------------;
- ; This subroutine writes null terminated string to Videoseg [DI]
- ; On entry : DS:SI points to string of length CX
- ; DI points to a location in the video memory
- ; Returns : nothing
- ; Modifies : AX, SI, DI, uses but preserves ES
- ;---------------------------------------------------------------;
- PUT_STRING PROC NEAR
- LODSB
- OR AL,AL
- JZ _PST_RET
- CALL PUT_CHAR
- JMP PUT_STRING
- _PST_RET:
- RET ;Return
- PUT_STRING ENDP
-
- PUT_STRATT PROC NEAR ;attribute in AH
- LODSB
- OR AL,AL
- JZ _PSA_RET
- CALL PUT_CHARATT
- JMP PUT_STRATT
- _PSA_RET:
- RET ;Return
- PUT_STRATT ENDP
-
- ;---------------------------------------------------------------;
- ; This subroutine writes a string to Videoseg [DI]
- ; Writes up to first null character or CX characters.
- ; On entry : DS:SI points to string with max length CX
- ; DI points to a location in the video memory
- ; Returns : nothing
- ; Modifies : AX, CX, SI, DI, uses but preserves ES
- ;---------------------------------------------------------------;
- ifdef SMALL
- PUT_CX_CHARS PROC NEAR ;use current attribute
-
- PUSH ES ;save seg register
- PUSH DX
- MOV ES,VIDEO_SEG ;Point to screen segment.
- MOV DX,STATUS_REG ;Retrieve status register.
-
- _PCXC1: LODSB ;get character
- CALL PUT_BYTE
- INC DI ;Bump pointer past attribute.
- LOOP _PCXC1
-
- POP DX
- POP ES ;restore segment register
- RET
- PUT_CX_CHARS ENDP
-
- else
-
- ; Faster but bulkier display of CX chars:
- PUT_CX_CHARS PROC NEAR ;use current attribute
-
- PUSH ES ;save seg register
- PUSH DX
- MOV ES,VIDEO_SEG ;Point to screen segment.
- MOV DX,STATUS_REG ;Retrieve status register.
- OR DX,DX
- JZ _PCXC3
-
- _PCXC1: IN AL,DX ;Get status.
- TEST AL,8 ;Is vertical in retrace?
- JNZ _PCXC3 ;If yes, lets go
- TEST AL,1 ;Is it low?
- JNZ _PCXC1 ;If not, wait until it is.
-
- _PCXC2: IN AL,DX ;Get status.
- TEST AL,1 ;Is it high?
- JZ _PCXC2 ;If no, wait until it is.
- MOVSB
- INC DI
- LOOP _PCXC1
- JMP SHORT _PCXC_RET
-
- _PCXC3: MOVSB
- INC DI
- LOOP _PCXC3
-
- _PCXC_RET:
- POP DX
- POP ES ;restore segment register
- RET
- PUT_CX_CHARS ENDP
- endif
-
- ; ********************************
- ; * BIOS SCREEN WRITING ROUTINES
- ; ********************************
- ;-----------------------------------------------------------------------;
- ; These subroutines clear either the messages or the entire screen. ;
- ;-----------------------------------------------------------------------;
- ASSUME DS:_TEXT,ES:_TEXT
-
- CLR_MSG PROC NEAR
- MOV AL,NORMAL
- MOV CX,BEG_WINDOW ;Row 24; column 43.
- JMP SHORT CLR_EOS
-
- CLR_EOL PROC NEAR
- MOV DH,CH
- mov dl,byte ptr SCREEN_COLS
- dec dl
- JMP SHORT CLR_WINDOW
-
- CLR_SCR PROC NEAR
- XOR CX,CX
-
- CLR_EOS PROC NEAR
- MOV DX,END_WINDOW ;Row 25; column 79.
-
- CALL CURSOR_OFF
-
- ;-------------------------------------------------------------------;
- ; Clear arbitray window to attribute specified in AL
- ; On entry : AL = screen attribute to use
- ; CH, CL = row, col of upper left
- ; DH, DL = row, col of lower right
- ; Modifies : AX, saves BX, BP
- ;-------------------------------------------------------------------;
- CLR_WINDOW PROC NEAR
- PUSH BP
- PUSH BX
- MOV BH,AL
- MOV AX,600H
- INT 10H
- POP BX
- POP BP
- RET
- CLR_WINDOW ENDP
- CLR_EOS ENDP
- CLR_SCR ENDP
- CLR_EOL ENDP
- CLR_MSG ENDP
-
- ;CLR_DOS_WIN PROC NEAR
- ; MOV AL,ORIG_ATT
- ; MOV CX,BEG_DOS
- ; CALL CLR_EOS
- ; MOV DX,BEG_DOS - 100h
- ; CALL SET_CURSOR
- ; RET
- ;CLR_DOS_WIN ENDP
-
-
-
-
-
- SUBTTL Bios Interface (non-screen)
- page
- ;******************************************
- ; OTHER BIOS ROUTINES
- ;******************************************
- ;------------------
- ; Set cursor off
- ;------------------
- CURSOR_OFF PROC NEAR
- PUSH CX
- MOV CX,2000H
- JMP SHORT _CU1
-
- ;------------------------------
- ; Set cursor on
- ;------------------------------
- CURSOR_ON PROC NEAR
- PUSH CX
- MOV CX,CURSOR_TYPE
- ;------------------------------
- ; Set cursor size
- ; On entry : CH = start line
- ; CL = stop line
- ;------------------------------
- _CU1: PUSH AX
- MOV AH,1
- INT 10H
- POP AX
- POP CX
- RET
- CURSOR_ON ENDP
- CURSOR_OFF ENDP
-
- ;---------------------------------------------------------;
- ; Move the cursor,
- ; On entry : DH, DL = cursor position, (0,0)= upper left
- ;---------------------------------------------------------;
- SET_CURSOR PROC NEAR
- PUSH SI
- XOR BH,BH ;Page zero.
- MOV AH,2 ;Set cursor.
- INT 10H
- CALL CURSOR_ON
- POP SI
- RET
- SET_CURSOR ENDP
-
- ;-------------------------------------------------------------------;
- ; Beep via DOS.
- ;-------------------------------------------------------------------;
- BEEP PROC NEAR
- MOV DL,7
- MOV AH,2
- INT DOSINT
- RET
- BEEP ENDP
-
- ;-------------------------------------------------------------------;
- ; Retrieve keystroke via BIOS.
- ; Returns : ascii value in AL,
- ; : scan code in AH
- ;-------------------------------------------------------------------;
- READ_KEY PROC NEAR
- MOV AH,0
- INT 16H
- RET
- READ_KEY ENDP
-
- ;-------------------------------------------------------------------;
- ; Check for keystroke via BIOS.
- ; returns Z Flag set if no char
- ; character in AX if NZ
- ;-------------------------------------------------------------------;
- CK_KEY PROC NEAR
- MOV AH,1
- INT 16H
- RET
- CK_KEY ENDP
-
- SUBTTL Dos interface subroutines
- page
- ;******************************************
- ; DOS FUNCTION CALLS
- ;******************************************
- ASSUME DS:_TEXT,ES:_TEXT
- ;-------------------------------;
- ; This subroutine opens a file. ;
- ; On entry : AL = open mode
- ; DS:DX =ASCIIZ path name
- ; Returns : AX = error codes if carry set
- ;-------------------------------;
- OPEN_FILE PROC NEAR
- MOV AH,3DH
- INT DOSINT
- RET
- OPEN_FILE ENDP
-
- ;-------------------------------;
- ; This subroutine closes a file. ;
- ; On entry : BX = file handle
- ; Returns : AX = error codes if carry set
- ;-------------------------------;
- CLOSE_FILE PROC NEAR
- MOV AH,3EH
- INT DOSINT
- RET
- CLOSE_FILE ENDP
-
- ;------------------------------------------------;
- ; This subroutine finds the first matching file. ;
- ; On entry : CX = attribute used in searching
- ; DS:DX =ASCIIZ drive, path and filename
- ; Returns : AX = error codes if carry set
- ;------------------------------------------------;
- FIND_FIRST PROC NEAR
- MOV AH,4EH
- INT DOSINT
- RET
- FIND_FIRST ENDP
-
- ;--------------------------------------------------------------;
- ; These two subroutines retrieve or change a file's attribute. ;
- ; On entry : DS:DX =ASCIIZ pathname
- ; CX = attribute
- ; Returns : AX = error codes if carry set
- ;--------------------------------------------------------------;
- CHMOD PROC NEAR
- MOV AX,4301H
- INT DOSINT
- RET
- CHMOD ENDP
-
- GETMOD PROC NEAR
- MOV AX,4300H
- INT DOSINT
- RET
- GETMOD ENDP
-
- ;------------------------------------------------------------------;
- ; This subroutine gets the disk space available on the target drive
- ; On entry : DX points to [d:]filename
- ; Returns : available space in DX:AX
- ; Modifies : AX, BX, CX, DX, SI
- ;------------------------------------------------------------------;
- ASSUME DS:_TEXT,ES:_TEXT
- GET_BYTES_FREE PROC NEAR
- MOV SI,OFFSET ENTRY ;Retrieve pointer to target file.
- MOV AX,[SI] ;get two bytes
- AND AL,5FH ;Capitalize.
- CMP AH,":" ;Is there a drive request?
- JZ _G_B_1 ;If no, get default drive.
- MOV AL,DEST_PATH ;Assume default drive.
-
- _G_B_1: MOV TARG_DISK,AL ;save it
- ;let run on to DISK_FREE
- ;----------------------------------------------;
- ; This subroutine retrieves available clusters ;
- ; and converts it to hexidecimal bytes free. ;
- ; On entry : AL specifies a drive letter in ASCII
- ; Returns : DX:AX = bytes free on disk
- ; BX = clusters free
- ; CX = bytes per cluster
- ; Modifies : AX, BX, CX, DX
- ;----------------------------------------------;
- ASSUME DS:_TEXT,ES:_TEXT
- DISK_FREE PROC NEAR
- PUSH AX
- AND AL,1FH ;ignore case
- MOV DL,AL
- MOV AH,36H ;Disk free space.
- INT DOSINT
- INC AX ;-1 if not drive not valid
- JNZ _D_F0 ;ok
- STC ;bad drive - set carry
- POP AX
- RET ;return failure
-
- _D_F0: DEC AX ;restore correct ax
- XOR DX,DX
- MUL CX ;sectors per cluster times bytes per sector.
- MOV CX,AX ;save cluster size for other calculations
- MUL BX ;bytes per cluster times clusters
- POP BX
-
-
- CMP BL,TARG_DISK ;save it
- JNZ UPD_FREE_COUNT
- MOV TARG_BYTES_FREE,AX
- MOV TARG_BYTES_FREE+2,DX
- MOV TARG_CLUSTER,CX
-
- UPD_FREE_COUNT PROC NEAR
- CMP BL,DEST_PATH ;test if TARG=DEST
- JNZ _D_F1
- MOV DEST_BYTES_FREE,AX ;update dest disk values too
- MOV DEST_BYTES_FREE+2,DX ;
- MOV DEST_CLUSTER,CX
-
- PUSH DX
- PUSH CX
- PUSH BX
- PUSH AX
- MOV DI,OFFSET D_FREE ;Point to storage.
- MOV CX,LENGTH D_FREE
- CALL FORMAT ;Convert hex to decimal and store.
- POP AX
- POP BX
- POP CX
- POP DX
-
- _D_F1: CMP BL,WORK_PATH ;test if TARG=WORK
- JNZ _D_F2
- MOV WORK_BYTES_FREE,AX ;update work disk values too
- MOV WORK_BYTES_FREE+2,DX ;
- MOV WORK_CLUSTER,CX
-
- MOV DI,OFFSET W_FREE ;Point to storage.
- MOV CX,LENGTH W_FREE
- CALL FORMAT ;Convert hex to decimal and store.
-
- _D_F2: CLC
- _D_F_RET:
- RET
-
- UPD_FREE_COUNT ENDP
- DISK_FREE ENDP
- GET_BYTES_FREE ENDP
-
- ;------------------------------------------------------------------;
- ; This subroutine requests a block of free memory
- ; Returns : Allocated memory at AX:0
- ; Memory allocated in BX
- ; Modifies : everything except SI?
- ;------------------------------------------------------------------;
- ASSUME DS:_TEXT,ES:_TEXT
- GET_MEM PROC NEAR
- MOV BX,0A000H ;Request the world (640k)
- _G_M1: PUSH SI ;save pointer
- MOV AH,48H ;ax returns pointer to block
- INT DOSINT ;bx returns paragraphs allocated
- POP SI
- JNC _G_M2 ;success
- CMP AL,8 ;check for a nasty error
- JNZ _G_M_ER ; not just insufficient memory
- AND BX,0F000h ;round available mem to N 64k segs
- JNZ _G_M1 ;try again if not zero
- _G_M_ER:
- MOV N_SEGS,0 ;reset segs available
- STC
- RET ;uh-oh, not just error 8
-
- _G_M2: MOV MEM_BUF_SEG,AX ;save start of file buf
- MOV CL,4 ;x16 to find top byte
- SHR BH,CL ;of this seg and then
- JZ _G_M_ER ;no memory
- MOV N_SEGS,BH ;save it
- CLC
- _G_M_X: RET
-
- GET_MEM ENDP
-
- ;------------------------------------------------------------------;
- ; This subroutine releases memory allocated by GET_MEM
- ; On entry : MEM_BUF_SEG conatins segment pointer of allocated memory
- ;------------------------------------------------------------------;
- RELEASE_MEM PROC NEAR
- CMP N_SEGS,0
- JZ _R_MEM_RET
- PUSH ES
- MOV ES,MEM_BUF_SEG
- MOV AH,49H ;free allocated block
- INT DOSINT
- POP ES
- MOV N_SEGS,0 ;reset segs available
- _R_MEM_RET:
- RET
- RELEASE_MEM ENDP
-
- ;-------------------------------------------;
- ; This is the new Critical Error interrupt. ;
- ; all registers are saved
- ;-------------------------------------------;
- DISK_ERROR proc far
- ASSUME CS:_TEXT
- STI ;Interrupts back on.
- PUSHF ;Save all registers.
- PUSH ES
- PUSH DS
- PUSH BP
- PUSH DI
- PUSH SI
- PUSH DX
- PUSH CX
- PUSH BX
- PUSH AX
-
- MOV BX,CS
- MOV DS,BX ;Point to our data segment.
- MOV ES,BX
-
- assume cs:_TEXT, ds:_TEXT, es:_TEXT
- ADD AL,"A" ;convert failed drive to char
- MOV ERROR_DISK,AL
- CALL CLR_MSG ;Clear current message.
- MOV SI,OFFSET DISK_MSG ;Display disk error message.
- MOV DI,PROMPT_LOC
- CALL PUT_STRING
- MOV DI,PROMPT_LOC2 ;Display rest of error message.
- CALL PUT_STRING
-
- _D_ER_1:
- CALL READ_KEY ;Get a response to message.
- MOV AL,1 ;assume a retry
- CMP AH,13H ;Was it scan code for "R"?
- JZ _D_ER_2 ;If yes retry.
- INC AL
- INC AL ;ret al=3 to fail
- CMP AH,1 ;Is it Esc?
- JZ _D_ER_2 ;If yes, exit delete.
- CMP AH,10H ;Was it "Q"?
- JNZ _D_ER_1 ;If no, wait until correct response
- JMP TERMINATE ;Else, exit to DOS.
-
- _D_ER_2:
- PUSH AX ;save return option
- CALL DISP_COUNT_MSG ;Clear disk error message.
- POP BX ;get back option
- POP AX ;Restore registers.
- MOV AL,BL ;put return option in AL
- POP BX ;restore remaining registers
- POP CX
- POP DX
- POP SI
- POP DI
- POP BP
- POP DS
- POP ES
- POPF
- IRET
- DISK_ERROR ENDP
-
- even
- PGM_NAME DB 0 ;program name for CALL_DOS
- INITIAL_PATH EQU PGM_NAME+80
- WORK_PATH EQU INITIAL_PATH+70
- DEST_PATH EQU WORK_PATH+70
- SOURCE EQU DEST_PATH+70
- TARGET EQU SOURCE+70+13
- TARG_DISK EQU TARGET+70+13
- ENTRY EQU TARG_DISK+2
- TMP_BUFF EQU ENTRY+36
- DIR_BUFF EQU TMP_BUFF+22
-
- _TEXT ENDS
- END START
-
-