home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
directry
/
dirnotes
/
dirnotes.asm
next >
Wrap
Assembly Source File
|
1989-10-15
|
48KB
|
1,061 lines
; Dirnotes.asm
; FORMAT: DIRNOTES [d][path][directory]
; *A 10-15-89 WCL ... Chg'd Home,End key defs to ^Home,^End respectively
; rev 1.10 Added new Home,End,Tab,Sh-Tab,Ins,Del,^T,^Left,^Right KEY DEFS
; Reassembled with TASM 1.0, Linked with TLINK 2.0.
CODE SEGMENT ;*************************;
ASSUME CS:CODE,DS:CODE ;* *;
ORG 100H ;* REMEMBER TO EXE2BIN *;
;* *;
START: JMP BEGINNING ;*************************;
; DATA AREA
; ---------
COPYRIGHT DB 'Copyright 1987 Ziff-Davis Publishing Co. - Rev 1.10',10,13
PROGRAMMER DB 'Michael J. Mefford - Updated 10-15-89 by WCL',1AH
DIRNOTES DB 'DIRN----.DAT',0
STAR_DOT_STAR DB '*.*',0
CURRENT_DISK DB ?
STATUS_REG DW ?
VIDEO_SEG DW 0B000H
NORMAL DB 07H
INVERSE DB 70H
CURSOR_ORG DW ? ;*A CH & CL registers: cursor height
CURS_POS DW ? ; row,col
CUR_OFFSET DW OFFSET BUFFER
END_OFFSET DW ?
PAGE_END DW 403+21*160
COUNT DW 1
LINE DW 403
EOF_FLAG DB 0
UPDATE_FLAG DB 0
INS_FLAG DB 1 ;*A 1 = insert mode
NOT_ENOUGH DB 'Not enough memory$'
INVALID DB 'Invalid directory$'
TOO_MANY DB 'Too many files$'
LOADING DB 'Loading and sorting directory notes.',0
DIRECTORY DB 'Directory of ',0
FILES DB ' Files',0
STATUS_LINE DB 'Press Esc to exit',0
SAVING DB 'Saving ',0
;----------------------------------------------------------------------------;
; 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. If less than 64K, exit. ;
;----------------------------------------------------------------------------;
; CODE AREA
; ---------
BEGINNING: CLD
MOV AH,19H ;Get current drive.
INT 21H
MOV CURRENT_DISK,AL ;And save.
MOV SI,OFFSET CURRENT_DIR ;Get current directory.
CALL GET_DIR
CMP SP,65500 ;Do we have 64K?
MOV DX,OFFSET NOT_ENOUGH
JA PARSE
JMP ERROR_EXIT ;If no, exit.
;-----------------------------------------------------------;
; Parse the command line for parameters and append the ;
; DIRNOTES filename with the characters of directory name. ;
;-----------------------------------------------------------;
PARSE: CMP BYTE PTR DS:[80H],0 ;Any parameters?
JZ APPEND ;If no, skip parse.
MOV SI,81H ;Else, point to first character.
NEXT_PARSE: LODSB
CMP AL,13 ;Carriage return?
JZ APPEND ;If yes, done here.
CMP AL,32 ;Leading space?
JBE NEXT_PARSE ;If yes, get next byte.
PUSH SI ;Save start.
NEXT_PARA: LODSB
CMP AL,13 ;End of parameter?
JZ END_PARA ;If yes, done here.
CMP AL,':' ;Drive request?
JNZ NEXT_PARA ;If no, get next byte.
MOV DL,BYTE PTR [SI-2] ;Else, retrieve request.
AND DL,5FH ;Capitalize.
SUB DL,'A' ;Convert to DOS format.
MOV AH,0EH ;And change drive.
INT 21H
JMP SHORT NEXT_PARA ;Find end of parameter.
END_PARA: MOV BYTE PTR DS:[SI-1],0 ;Convert parameter to ASCIIZ.
POP DX ;Retrieve start.
DEC DX ;Adjust.
MOV AH,3BH ;Change directory.
INT 21H
MOV DX,OFFSET INVALID ;Exit if invalid parameter.
JNC APPEND
JMP ERROR_EXIT
APPEND: MOV SI,80H ;Get default directory.
CALL GET_DIR
CLD
NEXT_END: LODSB ;Find end.
CMP AL,0
JNZ NEXT_END
DEC SI
STD ;Reverse direction.
NEXT_START: AND BYTE PTR [SI],5FH ;Capitalize.
LODSB
CMP AL,'\' ;Look for last path.
JNZ NEXT_START
CLD ;Back to forward direction.
INC SI
INC SI
MOV DI,OFFSET DIRNOTES+5 ;Insert three characters of path
MOV CX,3 ; into filename, DIRN----.DAT
STORE_PATH: CMP BYTE PTR [SI],0
JZ DISPLAY
MOVSB
LOOP STORE_PATH
;---------------------------------------------------------------------;
; More housekeeping. We will be writing directly to the screen buffer ;
; so we need the display card address and the status register. ;
;---------------------------------------------------------------------;
DISPLAY: MOV AX,40H ;Point to the ROM BIOS data area
MOV DS,AX ; and get base address of active
MOV AX,DS:[63H] ; display card.
ADD AX,6 ;Add six to get status register
PUSH CS ;Done there, so restore data segment.
POP DS
MOV STATUS_REG,AX ;Store status register.
CMP AX,3BAH ;Status port of MONO card is 3BAh.
JZ MESSAGE ;If that's what we got, it's MONO
MOV VIDEO_SEG,0B800H ; else COLOR so add 800h.
XOR BH,BH ;Get current attribute
MOV AH,8 ; of display page zero.
INT 10H
MOV NORMAL,AH ;Store it.
XOR AH,1110111B ;Flip color bits.
MOV INVERSE,AH ;Save it.
MESSAGE: CALL CLS
MOV SI,OFFSET LOADING ;Display loading message.
MOV DX,0C15H
CALL DISPLAY_TEXT
MOV DI,OFFSET BUFFER ;Fill buffer with spaces.
MOV CX,30000
MOV AX,2020H
REP STOSW
;------------------------------------------------------------------;
; Read all the directory filenames and store as records in buffer. ;
;------------------------------------------------------------------;
READ_DIR: MOV DX,OFFSET STAR_DOT_STAR
MOV CX,6
MOV AH,4EH ;Find first matching.
INT 21H
JNC STORE_NAME
JMP EXIT ;If empty directory, exit.
STORE_NAME: MOV DI,OFFSET BUFFER ;Set up pointers and store
MOV BP,60000 ; first filename.
CALL BUFFER_NAME
FIND_NEXT: MOV AH,4FH ;Find next matching.
INT 21H
JC STORE_COUNT ;If carry, no more names.
INC COUNT ;Inc count of names.
CALL BUFFER_NAME
CMP DI,BP ;Are we encroaching stack?
JB FIND_NEXT ;If no, find next.
MOV DX,OFFSET TOO_MANY ;Else, exit with message.
JMP ERROR_EXIT
;---------------------------------------------;
; Store buffer end address and page end, ;
; number of files then alphabetize filenames. ;
;---------------------------------------------;
STORE_COUNT: MOV END_OFFSET,DI ;Store ending offset.
MOV BX,COUNT
MOV AX,BX
MOV CL,10 ;Convert to decimal.
STD ;Reverse direction.
MOV DI,OFFSET FILES+2 ;Point to storage.
NEXT_COUNT: DIV CL
XCHG AL,AH
ADD AL,'0' ;Convert to ASCII.
STOSB ;Store the remainder.
XCHG AL,AH
XOR AH,AH
CMP AX,0 ;Are we done?
JNZ NEXT_COUNT
CLD ;Back to forward direction.
CMP BX,20 ;Enough to file one page?
JA SORT ;If yes, use default setting.
MOV AX,160 ;Else, calculate last record.
MUL BL
ADD AX,403 ;Add bar offset.
MOV PAGE_END,AX
CMP BX,1 ;Skip sort if only one filename.
JZ OPEN_FILE
SORT: MOV DX,END_OFFSET ;End of filenames in DX.
SUB DX,81
NEXT_PASS: MOV BP,0
MOV BX,OFFSET BUFFER ;Point to start of buffer.
NEXT_SORT: MOV SI,BX ;Put in source and destination
MOV DI,BX ; registers.
ADD DI,81
MOV CX,12
REPZ CMPSB ;Compare filenames.
JBE END_SORT ;If already in order, skip.
MOV SI,BX ;Else, recover pointers.
MOV DI,BX
ADD DI,81
MOV CX,40 ;Exchange the records.
NEXT_SWAP: MOV AX,[DI]
MOVSW
MOV [SI-2],AX
LOOP NEXT_SWAP
MOV BP,1 ;Flag that exchange was made.
END_SORT: ADD BX,81 ;Point to next record.
CMP BX,DX ;End of top?
JB NEXT_SORT ;If no, bubble sort next.
CMP BP,0 ;Was there exchange made?
JZ OPEN_FILE ;If no, done here.
SUB DX,81 ;Else, move top down one record.
JMP SHORT NEXT_PASS
;-------------------------------;
; Attempt to read old dirnotes. ;
;-------------------------------;
OPEN_FILE: MOV DX,OFFSET DIRNOTES ;Open DIRNOTES
MOV AX,3D00H ; for reading.
INT 21H
JC READY ;If not found, skip to display.
MOV BX,AX
PUSH BX ;Save filehandle.
READ_FILE: POP BX
PUSH BX
MOV DX,60000 ;Point above directory listing.
MOV CX,37*81 ;Read up to 37 records at a time.
MOV AH,3FH
INT 21H
CMP AX,0 ;End of file?
JZ CLOSE_FILE ;If yes, done here.
ADD DX,AX
MOV DI,DX ;Else, point to end and tack
MOV BYTE PTR [DI],1AH ; on Ctrl Z as end signature.
CMP AX,37*81 ;Was it a full read?
JZ COMPARE ;If yes, compare records.
MOV EOF_FLAG,1 ;Else, flag as end of file.
;-------------------------------------------------------;
; Here we will match old DIRNOTES with new directory ;
; listing. Notes for deleted files will not find match. ;
;-------------------------------------------------------;
COMPARE: MOV BP,OFFSET BUFFER ;Point to first record.
NEXT_FILE: MOV BX,60000 ;Point to read buffer.
NEXT_MATCH: MOV SI,BX ;Set up source and destination.
MOV DI,BP
MOV CX,6 ;Filename with extension.
REPZ CMPSW ;Compare all 12 characters.
JNZ END_NOTE ;Skip if no match.
ADD SI,28 ; else point to note.
ADD DI,28
MOV CX,20
REP MOVSW ;Store note.
SUB SI,67
SUB DI,67
MOV CX,13
REPZ CMPSW ;Has size or date changed?
JNZ END_MATCH
MOV BYTE PTR [BP+39],32 ;If yes, remove "U".
JMP SHORT END_MATCH ;Skip rest and go to next record.
END_NOTE: ADD BX,81 ;Point to next record.
CMP BYTE PTR DS:[BX],1AH ;Are we at the end?
JNZ NEXT_MATCH ;If no, compare.
END_MATCH: ADD BP,81 ;Point to next record.
CMP BYTE PTR DS:[BP],32 ;End of directory listing?
JNZ NEXT_FILE ;If no, check for matches.
CMP EOF_FLAG,1 ;Else, end of file?
JNZ READ_FILE ;If no, read more.
CLOSE_FILE: POP BX
MOV AH,3EH ;Close file.
INT 21H
;--------------------------------------------;
; Now, we are ready to initialize the screen ;
;--------------------------------------------;
READY: MOV AX,VIDEO_SEG ;Initialize video segment.
MOV ES,AX
MOV DX,4 ;Row 0; column 3.
MOV SI,OFFSET DIRECTORY ;Display "Directory ".
CALL DISPLAY_TEXT
MOV AH,19H
INT 21H ;Get drive.
ADD AL,'A' ;Convert to ASCII.
CALL WRITE_TEXT ;Display it.
MOV AL,':' ;Add colon.
CALL WRITE_TEXT
MOV SI,80H ;Get directory.
CALL GET_DIR
DEC SI
CALL GET_TEXT ;Write it as well.
MOV DX,180EH ;Row 24; column 13.
MOV SI,OFFSET FILES ;Display file count.
CALL DISPLAY_TEXT
MOV DX,1833H ;Row 24; column 50.
MOV SI,OFFSET STATUS_LINE ;Display "Press Esc to exit".
CALL DISPLAY_TEXT
MOV BL,INVERSE ;Put up cursor bar.
CALL BAR
CALL UPDATE_SCREEN ;Display directory listing.
MOV CURS_POS,229H ;Initialize cursor position.
MOV AH,03 ;*A
MOV BH,0 ;*A
INT 10H ;*A Get original cursor size
MOV CURSOR_ORG,CX ;*A
CALL SET_CUR_SIZE ;*A Set cursor size
;-----------------------------------------;
; We are ready for business now. We will ;
; loop here, waiting for user keystrokes. ;
;-----------------------------------------;
GET_KEY: CALL SET_CURSOR ;Update cursor position.
MOV AH,0 ;Wait for
INT 16H ;keystroke.
ASCII: CMP AL,32 ;Is it space or above?
JB CR ;If no, skip.
CMP BYTE PTR CURS_POS,79 ;End of line? Line: 42-79 physical
JZ GET_KEY ;If yes, skip. 41-78 logical
CMP INS_FLAG, 1 ;Insert mode on? *A
JNZ WRT_ASCII ;Jmp if not *A
CALL PUSHEM_OUT ;Else push out characters *A
WRT_ASCII: CALL STORE_CHAR ;Else, store the ASCII character.
INC BYTE PTR CURS_POS ;Update cursor (points to next loc).
JMP SHORT GET_KEY
CR: CMP AH,1CH ;Is it carriage return?
JNZ BS
MOV BYTE PTR CURS_POS,41 ;Cursor to beginning of line.
JMP SCROLL_DOWN ; and scroll down.
BS: CMP AH,0EH ;Backspace?
JNZ TAB
CMP BYTE PTR CURS_POS,41 ;Are we already at beginning?
JZ GET_KEY ;If yes, skip.
DEC BYTE PTR CURS_POS ;Else, cursor left one.
MOV AL,32 ;And replace with space.
CALL STORE_CHAR
JMP SHORT GET_KEY
TAB: CMP AH,0FH ;Tab? *A
JNZ LEFT_ARROW
CMP AL,00H
JZ SHFT_TAB
CMP BYTE PTR CURS_POS,79 ;Are we already end of line?
JZ GET_KEY
ADD BYTE PTR CURS_POS,5 ;Cursor right.
CMP BYTE PTR CURS_POS,79 ;Are we past end of line?
JBE EXIT_TAB
MOV BYTE PTR CURS_POS,79
EXIT_TAB: JMP SHORT GET_KEY
SHFT_TAB: ;Sh-Tab? *A
CMP BYTE PTR CURS_POS,41 ;Are we already start of line?
JZ GET_KEY
SUB BYTE PTR CURS_POS,5 ;Cursor left.
CMP BYTE PTR CURS_POS,41 ;Are we before start of line?
JAE EXIT_SH_TAB ;Jump if not
MOV BYTE PTR CURS_POS, 41
EXIT_SH_TAB: JMP GET_KEY
LEFT_ARROW: CMP AH,4BH ;Left arrow?
JNZ RIGHT_ARROW
CMP BYTE PTR CURS_POS,41 ;Are we already home position?
JZ LEFT_EXIT
DEC BYTE PTR CURS_POS ;If no, back cursor up one.
LEFT_EXIT: JMP GET_KEY
RIGHT_ARROW: CMP AH,4DH ;Right arrow?
JNZ CTL_LFT_ARR
CMP BYTE PTR CURS_POS,79 ;Are we already end of line?
JZ SKIP_CHK
INC BYTE PTR CURS_POS ;Cursor right one.
SKIP_CHK: JMP GET_KEY
CTL_LFT_ARR: CMP AH,73H ;^Left arrow?
JNZ CTL_RT_ARR
INC BYTE PTR CURS_POS
CHAR_L: CALL LOOPER_LEFT
JAE CHAR_L
NON_CHAR_L: CALL LOOPER_LEFT
JB NON_CHAR_L
CHAR_L2: CALL LOOPER_LEFT
JAE CHAR_L2
INC BYTE PTR CURS_POS
EXIT_CTL_L: JMP GET_KEY
LOOPER_LEFT:
CMP BYTE PTR CURS_POS,41
JZ EXIT_CTL_L
DEC BYTE PTR CURS_POS
CALL GET_CHAR
CMP BL,48
RET
CTL_RT_ARR: CMP AH,74H ;^Right arrow? *A
JNZ UP_ARROW
DEC BYTE PTR CURS_POS
CHAR_R: CALL LOOPER_RT
JAE CHAR_R
MOV BH,BYTE PTR CURS_POS ;Location of last non_char (space)
NON_CHAR_R: CALL LOOPER_RT
JB NON_CHAR_R
CHK_END: CMP BYTE PTR CURS_POS,79
JB EXIT_CTL_R1
DEC BYTE PTR CURS_POS ;Point to last logical char
CALL GET_CHAR
CMP BL,32
JNZ EXIT_CTL_R0
INC BH
MOV BYTE PTR CURS_POS,BH
FIND_CHAR: CALL LOOPIT_LEFT
JZ FIND_CHAR
EXIT_CTL_R0: INC BYTE PTR CURS_POS
EXIT_CTL_R1: JMP GET_KEY
LOOPER_RT: CMP BYTE PTR CURS_POS,79
JZ CHK_END
INC BYTE PTR CURS_POS
CALL GET_CHAR
CMP BL,48
RET
LOOPIT_LEFT:
CMP BYTE PTR CURS_POS,41
JZ EXIT_CTL_R1
DEC BYTE PTR CURS_POS
CALL GET_CHAR
CMP BL,32
RET
UP_ARROW: CMP AH,48H ;Up arrow?
JNZ DN_ARROW
MOV BP,-160 ;If yes, move bar up one line.
MOV DX,0FF00H ;And also the cursor.
CALL SCROLL_BAR
JMP GET_KEY
DN_ARROW: CMP AH,50H ;Down arrow?
JNZ HOME
SCROLL_DOWN: MOV BP,160 ;If yes, move cursor and bar down.
MOV DX,100H
CALL SCROLL_BAR
JMP GET_KEY
HOME: CMP AH,47H ;Home key? *A
JNZ END_KEY
SET_MIN_POS: MOV BYTE PTR CURS_POS, 41
JMP GET_KEY
END_KEY: CMP AH,4FH ;End key? *A
JNZ PG_UP
SET_END_POS: MOV BYTE PTR CURS_POS, 79
LOOP_END_POS: CMP BYTE PTR CURS_POS, 41
JZ EXIT_END_POS
DEC BYTE PTR CURS_POS
CALL GET_CHAR
CMP BL,32
JZ LOOP_END_POS
INC BYTE PTR CURS_POS
EXIT_END_POS: JMP GET_KEY
PG_UP: CMP AH,49H ;Page up?
JNZ PG_DN
MOV BP,-81*21 ;If yes, move up 21 lines.
CALL SCROLL
JMP SHORT BOTTOM_BAR ;And move bar to bottom.
PG_DN: CMP AH,51H ;Page down?
JNZ CTRL_PG_UP
MOV BP,81*21 ;If yes, move down 21 lines.
CALL SCROLL
JMP SHORT TOP_BAR ;And move bar to top.
CTRL_PG_UP: CMP AH,84H ;Ctrl PgUp?
JNZ CTRL_PG_DN
TOP_BAR: MOV SI,403 ;If yes, move bar to top.
MOV CURS_POS,229H
JMP SHORT UPDATE_BAR
CTRL_PG_DN: CMP AH,76H ;Ctrl PgDn?
JNZ CTRL_HOME
BOTTOM_BAR: MOV SI,PAGE_END ;If yes, move bar to bottom.
MOV AX,SI ;Divide page end by 160
SUB SI,160 ; to get cursor row position.
SUB AX,403-160
XOR DX,DX
MOV BX,160
DIV BX
MOV DH,AL
MOV DL,29H
MOV CURS_POS,DX
UPDATE_BAR: CALL MOVE_BAR ;Display updates.
CALL SET_CURSOR
CALL UPDATE_SCREEN
JMP NEXT_KEY
CTRL_HOME: CMP AH,77H ;^Home? *A
JNZ CTRL_END
MOV CUR_OFFSET,OFFSET BUFFER ;If yes, move listing and
JMP SHORT TOP_BAR ; bar to top.
CTRL_END: CMP AH,75H ;^End? *A
JNZ INS_KEY
MOV BX,END_OFFSET ;If yes, move listing and
SUB BX,81*21 ; bar to bottom.
CMP BX,OFFSET BUFFER
JBE BOTTOM_BAR
MOV CUR_OFFSET,BX
JMP SHORT BOTTOM_BAR
INS_KEY: CMP AH,52H ;Insert? *A
JNZ DEL
XOR BYTE PTR INS_FLAG,1
CALL SET_CUR_SIZE
JMP GET_KEY
DEL: CMP AH,53H ;Del? *A
JNZ CTRL_T
CALL DEL_CHAR
JMP GET_KEY
CTRL_T: CMP AH,14H ;Ctrl T? *A
JNZ CTRL_Y
MOV BH,80
SUB BH,BYTE PTR CURS_POS
CALL GET_CHAR
CMP BL,32
JZ DEL_A_SPACE
DEL_A_CHAR: DEC BH
CMP BH,0
JZ EXIT_T
CALL DEL_CHAR
CALL GET_CHAR
CMP BL,32
JNZ DEL_A_CHAR
DEL_A_SPACE: DEC BH
CMP BH,0
JZ EXIT_T
CALL DEL_CHAR
CALL GET_CHAR
CMP BL,32
JZ DEL_A_SPACE
EXIT_T: JMP GET_KEY
CTRL_Y: CMP AH,15H ;Ctrl-Y? *A
JNZ ESC
MOV BYTE PTR CURS_POS,41
MOV BH, 39
EXIT_DEL_CHR: CALL DEL_CHAR
DEC BH
CMP BH,0
JNZ EXIT_DEL_CHR
JMP GET_KEY
ESC: CMP AH,1 ;Esc?
JNZ NEXT_KEY
JMP EXIT ;If yes, exit.
NEXT_KEY: JMP GET_KEY
;*************;
; SUBROUTINES ;
;*************;
;--------------------------------------;
; This subroutine sets the cursor size ;
;--------------------------------------;
SET_CUR_SIZE:
CMP BYTE PTR INS_FLAG,1
JZ INSERT_ON
MOV CX,CURSOR_ORG
JMP DO_TEN
INSERT_ON: MOV CX,080CH
DO_TEN: MOV AH,01H
INT 10H
RET
;-------------------------------------;
; This subroutine scrolls the screen. ;
;-------------------------------------;
SCROLL: MOV SI,CUR_OFFSET ;Get current offset.
ADD SI,BP ;Add requested direction.
JNS CK_LOWER ;If signed and PgUp request
CMP BP,-81*21 ; then below start.
JZ LOWER_LIMIT
CK_LOWER: CMP SI,OFFSET BUFFER ;If above start check upper limit.
JAE UPPER_LIMIT
LOWER_LIMIT: MOV CUR_OFFSET,OFFSET BUFFER ;Else, make it start.
JMP SHORT UPDATE ;And update screen.
UPPER_LIMIT: MOV BX,END_OFFSET ;See if beyond end of
CMP BX,OFFSET BUFFER+21*81 ; directory listing as well.
JA CK_UPPER
MOV CUR_OFFSET,OFFSET BUFFER
JMP SHORT UPDATE
CK_UPPER: SUB BX,21*81
CMP SI,BX
JBE END_SCROLL
MOV SI,BX
END_SCROLL: MOV CUR_OFFSET,SI ;Update current offset.
UPDATE: CALL UPDATE_SCREEN
RET
;--------------------------------------------------;
; This subroutine scrolls the bar if between start ;
; and end of page. Otherwise the page is scrolled. ;
;--------------------------------------------------;
SCROLL_BAR: MOV SI,LINE ;Get current line.
ADD SI,BP ;Add requested line.
MOV BP,-81 ;Assume below beginning.
CMP SI,403 ;Is it?
JB SCROLL_PAGE ;If yes, scroll page instead.
MOV BP,81 ;Do the same for end of page.
CMP SI,PAGE_END
JAE SCROLL_PAGE
ADD CURS_POS,DX ;If in range, update cursor
CALL MOVE_BAR ; and bar position.
RET
SCROLL_PAGE: CALL SCROLL
RET
;----------------------------------------------------;
; This subroutine does the actual moving of the bar. ;
;----------------------------------------------------;
MOVE_BAR: MOV BL,NORMAL ;Remove old bar.
CALL BAR
MOV LINE,SI ;And move bar to new line.
MOV BL,INVERSE
CALL BAR
RET
BAR: MOV DI,LINE ;Retrieve line.
MOV BH,38 ;Bar length 39.
MOV DX,STATUS_REG
NEXT_BAR: MOV CX,1 ;Write one character at a time.
CALL HORZ_RET
DEC BH
JNZ NEXT_BAR
RET
;----------------------------------------------;
; This subroutine stores the ASCII characters. ;
; AL = character to store ;
;----------------------------------------------;
STORE_CHAR:
CALL GET_CHAR_LOC ;*A
MOV [SI],AL ;Store it.
MOV CX,1 ;Write one character
CALL WRITE_SCREEN ;Display by updating screen.
MOV UPDATE_FLAG,1 ;Flag as updated so file will
RET ; be written upon Esc.
;------------------------------------------------;
; This subroutine retrieves the ASCII character. ;
; BL = character to retrieve ;
;------------------------------------------------;
GET_CHAR: CALL GET_CHAR_LOC ;*A
MOV BL,DS:[SI] ;Retrieve it.
RET ;
;------------------------------------------------;
; This subroutine deletes an ASCII character. ; *A
;------------------------------------------------;
DEL_CHAR:
CMP BYTE PTR CURS_POS,79 ; Past last char?
JAE EXIT_DEL_CHAR ; Skip del if so, else
MOV AX, CURS_POS ;
PUSH AX ; Save cursor position
NEXTDEL: INC BYTE PTR CURS_POS ; Point to next position
CMP BYTE PTR CURS_POS,79 ; Is it past the last char?
JB GETIT ; Jump if not
MOV AL,32 ; else fill last char with a space
JMP MOVIT
GETIT: CALL GET_CHAR ; Get char at next location
MOV AL,BL ; mov it into AL
MOVIT: DEC BYTE PTR CURS_POS ; Point to current del char
CALL STORE_CHAR ; Put new char there and show it
INC BYTE PTR CURS_POS ; Point to next del position
CMP BYTE PTR CURS_POS,79 ; Past the last char yet?
JB NEXTDEL ; No, continue processing
POP AX ; Yes, restore old cursor position
MOV CURS_POS,AX
EXIT_DEL_CHAR: RET
;------------------------------------------------;
; This subroutine push out trailing characters ; *A
;------------------------------------------------;
PUSHEM_OUT:
CMP BYTE PTR CURS_POS,78 ; At or past last valid char?
JAE PUSH_RET ; Yes, Can't push any further
PUSH AX ; Save current charcter
MOV AX, CURS_POS ;
PUSH AX ; Save cursor position
MOV BYTE PTR CURS_POS,78 ;
NEXTADD:
POP AX ; Restore cursor postion
DEC BYTE PTR CURS_POS ; Backup one character
CMP BYTE PTR CURS_POS,AL ; Is it prior to start loc?
PUSH AX
JB PUSH_RESTORE ; Jump if not
CALL GET_CHAR ; and get char at that location
MOV AL,BL ; mov it into AL
INC BYTE PTR CURS_POS ; Point to next char
CALL STORE_CHAR ; Put previous char there and show it
DEC BYTE PTR CURS_POS ; Backup one character
JMP NEXTADD
PUSH_RESTORE:
POP AX
MOV CURS_POS,AX
POP AX
PUSH_RET: RET
;----------------------------------------------------------------; *A
; This subroutine causes [SI] to point to the current character ;
; Destroyed: CX,DL ;
;----------------------------------------------------------------;
GET_CHAR_LOC: ;
PUSH AX ;Save AX.
MOV SI,CUR_OFFSET ;Retrieve current starting offset.
MOV AX,CURS_POS ;Retrieve cursor position.
MOV CX,AX ;Save it.
MOV AL,AH
XOR AH,AH ;Isolate row.
DEC AX ;Adjust for offset.
DEC AX
ADD SI,AX ;Add to source.
MOV DL,80 ;Multiply by 80.
MUL DL
ADD SI,AX ;Add to source.
MOV DI,AX ;DI is screen offset.
SHL DI,1 ;Adjust for attribute.
ADD DI,2*160 ;Adjust for starting in row 3.
XOR CH,CH ;Isolate column.
ADD SI,CX ;Add column to offset.
SHL CX,1 ;Double for screen offset.
ADD DI,CX ;Add it. = screen offset
POP AX ;Retrieve AX.
RET
;---------------------------------------------------;
; This subroutine writes the listing to the screen. ;
;---------------------------------------------------;
UPDATE_SCREEN: MOV SI,CUR_OFFSET ;Retrieve starting offset.
MOV DI,2*160 ;Point to row three of screen.
MOV BH,21 ;21 lines to write.
NEXT_WRITE: MOV CX,79 ;79 characters per line.
CALL WRITE_SCREEN ;Write them.
ADD SI,2 ;Bump pointer past cr/lf.
ADD DI,2 ;Bump pointer to next line.
DEC BH ;Do all 21 lines.
JNZ NEXT_WRITE
RET
;------------------------------------------------------------;
; This subroutine displays the directory by writing directly ;
; to the screen buffer. To avoid screen noise (snow) on the ;
; color card, the horizontal retrace has to be monitored. ;
; CX = number of characters to write (79 max) ;
; DI = screen position ;
; Destroyed: BL, AL, DI ;
;------------------------------------------------------------;
WRITE_SCREEN:
MOV DX,STATUS_REG ;Get status register.
NEXT_BYTE: LODSB ;Get a byte.
MOV BL,AL ;Save it in BL.
HORZ_RET: IN AL,DX ;Get status.
TEST AL,1 ;Is it low?
JNZ HORZ_RET ;If not, wait until it
CLI ;No more interrupts.
WAIT: IN AL,DX ;Get status.
TEST AL,1 ;Is it high?
JZ WAIT ;If no, wait until it is.
MOV AL,BL ;Retrieve character; now it's OK
STOSB ; to write to screen buffer.
STI ;Interrupts back on.
INC DI ;Bump pointer past attribute.
LOOP NEXT_BYTE ;Get next byte.
RET ;Return
;------------------------------------;
; This subroutine clears the screen. ;
;------------------------------------;
CLS: MOV BH,NORMAL ;Clear with original attribute.
XOR CX,CX
MOV DX,184FH ;Entire screen.
MOV AX,600H ;Scroll active page.
INT 10H
RET ;Return.
;-----------------------------------------;
; These subroutines display the messages. ;
;-----------------------------------------;
DISPLAY_TEXT: MOV CURS_POS,DX ;Store requested cursor position.
CALL SET_CURSOR ;Move cursor.
GET_TEXT: LODSB
CMP AL,0 ;Zero marks end of string.
JZ END_TEXT
CALL WRITE_TEXT
JMP SHORT GET_TEXT
END_TEXT: RET
WRITE_TEXT: PUSH SI ;BIOS does not save SI.
MOV AH,0EH ;Write teletype
INT 10H
POP SI
RET
;----------------------------------------------------------------------;
; These two subroutines move the cursor and get the current directory. ;
;----------------------------------------------------------------------;
SET_CURSOR: PUSH SI ;Save SI pointer; BIOS doesn't.
MOV DX,CURS_POS ;Get requested cursor position.
XOR BH,BH ;Page zero.
MOV AH,2
INT 10H
POP SI
RET
GET_DIR: MOV BYTE PTR [SI],'\' ;DOS doesn't preface directory
INC SI ; with slash so we must.
XOR DL,DL
MOV AH,47H ;Retrieve default directory.
INT 21H
RET
;--------------------------------------------------;
; This long subroutine stores the filename in DIR ;
; format. That is, filename, bytes, date and time. ;
;--------------------------------------------------;
BUFFER_NAME: MOV SI,158 ;Point to filename.
MOV CX,12 ;Store 12 bytes of filename.
NEXT_STORE: LODSB ;Get a byte.
CMP AL,0 ;End of filename?
JZ END_STORE ;If yes, finish with blanks.
CMP AL,'.' ;Is it the period?
JNZ STORE_BYTE ;If no, store.
SUB CX,3 ;Else store 3 spaces.
MOV AL,32
REP STOSB
ADD CX,3
JMP SHORT NEXT_STORE ;Get next byte.
STORE_BYTE: STOSB ;Store byte.
LOOP NEXT_STORE ;Get next byte.
END_STORE: MOV AL,32 ;Pad balance with spaces.
REP STOSB
FILE_SIZE: PUSH DI ;Save pointer.
ADD DI,8 ;Move to end of bytes field.
MOV DX,DS:[154] ;Retrieve high and low words
MOV AX,DS:[156] ; of bytes.
MOV BX,10 ;Convert to decimal; divide by 10.
STD ;Reverse direction.
NEXT_SIZE: MOV CX,DX ;Low word in CX.
XOR DX,DX ;Zero in high half.
DIV BX ;Convert to decimal.
XCHG AX,CX ;Retrieve low word.
DIV BX
XCHG AX,DX ;Retrieve remainder.
ADD AL,'0' ;Convert to ASCII.
STOSB ;Store it.
MOV AX,CX ;Are we done?
OR CX,DX
JNZ NEXT_SIZE ;If no, divide again.
CLD ;Back to forward direction.
POP DI ;Retrieve pointer.
ADD DI,11 ;Move to date field.
DATE: MOV DX,DS:[152] ;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_WORD ;Store it.
MOV AX,DX ;Retrieve date.
AND AX,1FH ;Mask off all but day.
MOV CL,0 ;Flag include leading zeros.
MOV CH,'-'
CALL STORE_WORD ;Store it.
MOV AX,DX ;Retrieve date for last time.
MOV CL,9
ROR AX,CL
AND AX,7FH ;Mask off all but year.
ADD AX,80 ;Adjust to ASCII.
CMP AX,100 ;Past year 2000?
JB DISPLAY_DATE ;If no, display. Else, adjust for
SUB AX,100 ; next century. (Planning ahead!)
DISPLAY_DATE: MOV CL,0 ;Display leading zeros.
MOV CH,32
CALL STORE_WORD ;Store it.
TIME: INC DI ;Move to time field.
MOV DX,DS:[150] ;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 MERIDIAN
SUB AX,12 ;If yes, adjust.
MERIDIAN: CMP AX,0 ;Midnight?
JNZ NOT_MIDNIGHT
MOV AX,12 ;If yes, adjust.
NOT_MIDNIGHT: MOV CL,0FFH ;Suppress leading zeros.
MOV CH,':'
CALL STORE_WORD ;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 PM
MOV CH,'a' ;If no, AM.
PM: CALL STORE_WORD ;Store it.
MOV BYTE PTR [DI],'U' ;Assume for now updated.
MOV BYTE PTR [DI+40],13 ;Tack on carriage return linefeed.
MOV BYTE PTR [DI+41],10
ADD DI,42 ;Move pointer past note field
RET ; to start of next record.
STORE_WORD: DIV BL ;Divide by ten.
ADD AX,'00' ;Convert to ASCII.
CMP CL,0 ;Are we to display leading zero?
JZ STORE_IT ;If yes, store as is.
CMP AL,'0' ;Is it a leading zero?
JNZ STORE_IT ;If no, store it.
MOV AL,32 ;Else, store a space.
STORE_IT: STOSW
MOV AL,CH ;Store delimiter character also.
STOSB
RET
;-----------------------------------------------------------------;
; This is the exit routines. Check if notes have been updated. ;
; If yes, write the file. Return to original drive and directory. ;
;-----------------------------------------------------------------;
ERROR_EXIT: MOV AH,9 ;Display error message.
INT 21H
CALL RESTORE_PATH ;Restore path.
INT 20H ;Exit.
EXIT: MOV CURS_POS,1700H ;Row 22; column 0.
CALL SET_CURSOR
MOV CX,CURSOR_ORG ;*A
MOV AH,01H ;*A
INT 10H ;*A
CMP BYTE PTR UPDATE_FLAG,1 ;Did we update notes?
JNZ NO_WRITE ;If no, skip write
MOV SI,OFFSET SAVING ;Display "Saving DIRN----.DAT.
CALL GET_TEXT
MOV SI,OFFSET DIRNOTES
CALL GET_TEXT
MOV DX,OFFSET DIRNOTES ; else point to DIRNOTES
MOV CX,20H ; create the file.
MOV AH,3CH
INT 21H
MOV BX,AX ;Filehandle.
MOV DX,OFFSET BUFFER ;Point to the buffer
MOV CX,END_OFFSET
SUB CX,DX ;File size.
MOV AH,40H ;Write it.
INT 21H
NO_WRITE: CALL RESTORE_PATH ;Restore default directory.
MOV CURS_POS,0 ;Home the cursor.
CALL SET_CURSOR
CALL CLS ;Clear the screen.
INT 20H ; and exit.
RESTORE_PATH: MOV DL,CURRENT_DISK ;Reset the drive.
MOV AH,0EH
INT 21H
MOV DX,OFFSET CURRENT_DIR ;Reset the directory.
MOV AH,3BH
INT 21H
RET
;-------------------------------------------------;
; Approximate 700 filename buffer at end of code. ;
;-------------------------------------------------;
CURRENT_DIR:
BUFFER EQU CURRENT_DIR+66
CODE ENDS
END START