home *** CD-ROM | disk | FTP | other *** search
- ; EDIT.ASM
- ; (c) 1989, 1990 Ashok P. Nadkarni
- ;
- ; This module contains the line editing functions of CMDEDIT.
- ; ^T function (macro disable toggle) added by dfa, December 1990.
- ; Ability to switch ESC to filename completion added by dfa, May 1991.
-
- PUBLIC get_kbd_line
- PUBLIC auto_recall
- PUBLIC expand_fnkey
- PUBLIC ESC_key_function ;Added by dfa
- PUBLIC TAB_key_function ;Added by dfa
-
- INCLUDE common.inc
- INCLUDE ascii.inc
- INCLUDE BIOS.INC
- INCLUDE DOS.INC
- INCLUDE GENERAL.INC
-
-
- CSEG SEGMENT PARA PUBLIC 'CODE'
- CSEG ENDS
-
- DGROUP GROUP CSEG
-
- ASSUME CS:DGROUP, DS:DGROUP, SS:DGROUP, ES:DGROUP
-
- CSEG SEGMENT PARA PUBLIC 'CODE'
-
- EXTRN linebuf:BYTE
- EXTRN lastchar:WORD
- EXTRN caller_cursor:WORD
- EXTRN dot:WORD
- EXTRN edit_mode:BYTE
- EXTRN omode_cursor:WORD
- EXTRN disable_macro:BYTE ;added by dfa
- EXTRN sym_stk:WORD
- EXTRN LINEBUF_END:ABS
-
-
- tempchar db ? ;Temporary storage
- auto_recall db 0 ;By default no auto recall
- auto_recall_on db ? ;1 if auto-recall in effect,
- ; else 0
- continue_recall db ? ;auto-recall state variable
- fnkey_tab db 'S','F',0 ;Used to look for function key
- ; definitions.
- fnkey_exec_char db '@' ;If the last character a fn key
- ; definition is this, the key is
- ; executed immediately
-
- ; Must be IDENTICAL to the string in CMDCONF.C including the
- ; terminating '\0' byte. This must be followed immediately by ctrl_key_defs.
- cmdedit_keymap_id db 'CMDEDIT key map',0
- ; ctrl_key_redefs is used to allow the cmdconf program to remap the control
- ; keys. Each entry corresponds to a control key. It must immediately follow
- ; cmdedit_keymap_id.
- ctrl_key_redefs LABEL WORD
- x = 0
- REPT 32 ;32 control keys
- DW x
- x = x + 1
- ENDM
-
-
- EXTRN disp_line:PROC
- EXTRN hist_back:PROC
- EXTRN hist_fwd:PROC
- EXTRN hist_bck_match:PROC
- EXTRN hist_fwd_match:PROC
- EXTRN remember:PROC
- EXTRN execute_auto_recall:PROC
- EXTRN insert_at_dot:PROC
- EXTRN erase_to_dot:PROC
- EXTRN isalphnum:PROC
- EXTRN set_disp_marks:PROC
- EXTRN bell:PROC
- EXTRN line_to_scr:PROC
- EXTRN isspace:PROC
- EXTRN xlate_lower:PROC
- EXTRN expand_var:PROC
- EXTRN ismacsym:PROC
- EXTRN get_symbol:PROC
-
- ;number of command keys
- NUM_CMD_KEYS EQU (cmd_key_jumps-cmd_key_table)/2
-
- ;+
- ; FUNCTION : get_kbd_line
- ;
- ; Gets a line from the user and stores it in linebuf. The length
- ; of the line is stored in global linelen. The name is a misnomer
- ; because the line is from standard input, not necessarily from
- ; the keyboard.
- ;
- ; Parameters:
- ; None.
- ;
- ; Returns:
- ; Nothing.
- ; Register(s) destroyed:
- ;-
-
- get_kbd_line proc near
- @save si,di
- mov al,auto_recall
- mov auto_recall_on,al ;Indicate if auto-recall is enabled
- mov continue_recall,1 ;Init auto-recall memory
-
- ; Main editing loop
- @get_kbd_line_10:
- mov al,continue_recall
- and auto_recall_on,al ;Indicate if we should keep
- ; auto-recalling
- mov continue_recall,0 ;Reset the flag. It will be set
- ; for the default actions keys.
- call near ptr disp_line ;Show current line
- call near ptr getkey ;get next key from the user
- mov si,ax ;si holds the character
- cmp ax,32 ;Control character ?
- jge @get_kbd_line_15 ;No, then check if fn key
- mov di,si ;DI used to calculate
- add di,di ; offset into table
- mov ax,ctrl_key_redefs[di] ;Mapping of key
- mov si,ax
- cmp ax,32 ;Control char ?
- jge @get_kbd_line_15 ;No, then check if fn key
- mov di,si ;DI used to calculate
- add di,di ; offset into table
- jmp ctrl_key_table[di] ;Branch according to control char
- @get_kbd_line_15: ;Check if function key
- cmp ax,256+59 ;>= F1 ?
- jb @get_kbd_line_20 ;No, then check next table
- cmp ax,256+68 ;<= F10
- jg @get_kbd_line_20 ;Not fn key
- jmp @fn_key ;Handle the function key
- @get_kbd_line_20:
- cmp ax,256+84 ;>= Shift-F1 ?
- jb @get_kbd_line_25 ;No, then check next table
- cmp ax,256+93 ;<= Shift-F10
- jg @get_kbd_line_25 ;
- jmp @sfn_key ;Handle the shifted function key
- @get_kbd_line_25:
- mov cx,NUM_CMD_KEYS ;size and...
- mov bx,offset DGROUP:cmd_key_table ;beginning of jump table
- @get_kbd_line_30: ;Loop begin
- cmp ax,cs:[bx] ;Is this the key ?
- je @get_kbd_line_40 ;Hurrah, found
- inc bx ;point to next key
- inc bx
- loop @get_kbd_line_30 ;If more keys, repeat
- jmp short @default_action ;key not in table
- @get_kbd_line_40: ;Jump to location associated with
- jmp word ptr cs:[bx+(2*NUM_CMD_KEYS)] ;key
-
- @quote: ;Insert next char
- ; without interpreting it
- call near ptr getkey
-
- @default_action: ;Insert the character (in AX)
- call near ptr store_char
- jc @get_kbd_line_10 ;No room for char, keep looping
- mov al,auto_recall_on ;Are we auto-recalling ?
- or al,al
- jz @get_kbd_line_10 ;No
- call near ptr execute_auto_recall
- jc @get_kbd_line_10 ;If carry set, no matching
- ; string in history buffer
- mov continue_recall,1 ;Else indicate auto-recall is
- ; still to go on
- jmp short @get_kbd_line_10
-
-
- @char_left: ;Cursor one char left
- call near ptr char_left ;char_left will return to top
- jmp @get_kbd_line_10
- ; of editing loop
-
- @char_right: ;Cursor one char right
- call near ptr char_right ;char_right will return to top
- jmp @get_kbd_line_10
- ; of editing loop
-
- @word_left: ;Cursor one word left
- call near ptr word_left
- jmp @get_kbd_line_10
-
- @word_right: ;Cursor one word right
- call near ptr word_right
- jmp @get_kbd_line_10
-
- @bol: ;Beginning of line
- call near ptr go_bol
- jmp @get_kbd_line_10
-
-
- @eol: ;End of line
- call near ptr go_eol
- jmp @get_kbd_line_10
-
-
- @prev_line: ;Get previous history line
- mov ax,offset DGROUP:hist_back
- @history_line:
- call ax
- mov ax,lastchar
- mov dot,ax ;Leave cursor at end of line
- @history_search:
- jnc @history_line_done ;Line found
- call near ptr bell ;No line
- @history_line_done:
- jmp @get_kbd_line_10
-
- @next_line: ;Get next history line
- mov ax,offset DGROUP:hist_fwd
- jmp short @history_line
-
- @search_back: ;Search back thru history buffer
- mov ax,offset DGROUP:hist_bck_match
- @search:
- mov di,dot ;Save current dot
- call ax
- mov dot,di ;Restore it
- jmp short @history_search
-
- @search_forw: ;Search forward thru history buffer
- mov ax,offset DGROUP:hist_fwd_match
- jmp short @search
-
- @filename: ;Try to find a matching filename
- call near ptr match_file
- cmp auto_recall_on,1 ;Autorecall ongoing?
- je short @del_eol ;Yes, then delete to end of line
- jmp @get_kbd_line_10
-
- @del_left: ;Delete char before cursor
- mov ax,offset dgroup:char_left
- jmp short @delete
-
- @del_right: ;Delete char at cursor
- mov ax,offset dgroup:char_right
- jmp short @delete
-
-
- @del_prev_word: ;Delete upto word beginning
- mov ax,offset dgroup:word_left
- jmp short @delete
-
- @del_next_word: ;Delete to start of next word
- mov ax,offset dgroup:word_right
- jmp short @delete
-
- @del_bol: ;Delete to beginning of line
- mov ax,offset dgroup:go_bol
- jmp short @delete
-
-
- @toggle_insert:
- mov ax,1
- xor al,edit_mode ;Toggle edit mode
- mov edit_mode,al
- xchg ax,bx
- add bx,bx ;Word offset
- mov cx,omode_cursor[bx] ;cx<-cursor shape
- mov ah,01h ;Set cursor size function
- IF TOGGLE_CURSOR
- int 10h ;BIOS
- ENDIF
- jmp @get_kbd_line_10 ;Repeat editing loop
-
- @abort_and_store: ;Erases current line but remembers
- ; it in the history buffer
- call near ptr remember
- ; Fall through to erase line
- @erase_line:
- call near ptr go_bol ;Move dot to beginning of line
- ; fall thru to delete to end of line
-
- @del_eol: ;Delete to end of line
- mov ax,offset dgroup:go_eol
-
- @delete: ;General purpose delete
- mov si,dot ;Remember the dot
- call ax ;Move dot to new position
- xchg si,ax
- call near ptr erase_to_dot ;Delete characters between ax and dot
- jmp @get_kbd_line_10
-
- @autorecall:
- xor auto_recall,1 ;Toggle auto recall mode
- jmp @get_kbd_line_10
-
- @macro: ;added by dfa
- xor disable_macro,1 ;Toggle macro & symbol expansion disable
- jmp @get_kbd_line_10
-
-
- @vars:
- ; Expand the variables on the line.
- call near ptr expand_var
- jmp @get_kbd_line_10 ;Ignore return status from expand_var
-
-
- @inline_back:
- @inline_forw:
- @ignore:
- jmp @get_kbd_line_10 ;Ignore the character
-
-
- ctrl_key_table LABEL WORD
- dw @ignore ;NUL or ^@
- dw @bol ;^A
- dw @char_left ;^B
- dw @ignore ;^C
- dw @del_right ;^D
- dw @eol ;^E
- dw @char_right ;^F
- dw @abort_and_store ;^G
- dw @del_left ;^H
- TAB_key_function dw @filename ;^I ( label added by dfa )
- dw @vars ;^J might have to be @ignore in order for input
- ; redirection to work properly but try for
- ; var expansion anyway.
- dw @del_eol ;^K
- dw @del_prev_word ;^L
- dw @done_editing ;^M
- dw @next_line ;^N
- dw @del_eol_exec ;^O
- dw @ignore ;^P - don't use, filtered by get key call ?
- dw @quote ;^Q
- dw @search_back ;^R
- dw @ignore ;^S - don't use, does not work properly
- dw @macro ;^T (changed by dfa - was @ignore)
- dw @prev_line ;^U
- dw @search_forw ;^V
- dw @del_next_word ;^W
- dw @del_bol ;^X
- dw @autorecall ;^Y
- dw @default_action ;^Z
- ESC_key_function dw @erase_line ;^[ or ESC (label added by dfa)
- dw @inline_back ;^\
- dw @inline_forw ;^]
- dw @done_wipeout ;^^
- dw @ignore ;^_
-
- cmd_key_table: ;table of command keys
- dw 127 ;DEL
- dw 327 ;HOME
- dw 328 ;UP
- dw 331 ;LEFT
- dw 333 ;RIGHT
- dw 335 ;END
- dw 336 ;DOWN
- dw 338 ;INS
- dw 339 ;KDEL
- dw 371 ;CTLLEFT
- dw 372 ;CTLRIGHT
- cmd_key_jumps:
- dw @del_left ;DEL
- dw @bol ;HOME
- dw @prev_line ;UP
- dw @char_left ;LEFT
- dw @char_right ;RIGHT
- dw @eol ;END
- dw @next_line ;DOWN
- dw @toggle_insert ;INS
- dw @del_right ;KDEL
- dw @word_left ;CTLLEFT
- dw @word_right ;CTLRIGHT
-
-
- @sfn_key:
- ; A shifted function key has been struck.
- ; (Treat same as an unshifted function key).
- @fn_key:
- ; A function key has been struck.
- call near ptr expand_fnkey
- jc @fn_key_20 ;Error or no expansion
- or dx,dx ;Line to be executed
- ; immediately ?
- je short @done_editing_2 ;Yes, all done
- @fn_key_20:
- jmp @get_kbd_line_10 ;else keep editing
-
- @del_eol_exec: ;Deletes characters from the dot
- ; to end of the line and then
- ; executes the line
- mov si,dot ;Remember the dot
- call go_eol
- xchg si,ax
- call near ptr erase_to_dot
- jmp short @done_editing
-
-
- @done_wipeout:
- ; The line is executed. However it is not stored in the history buffer and
- ; is also removed from the screen (this is a little klugy).
- mov ax,offset DGROUP:linebuf
- mov dot,ax
- mov dx,lastchar
- mov lastchar,ax ;Temporarily pretend line
- ; is empty
- xchg ax,dx
- push ax
- call near ptr set_disp_marks
- call disp_line
- pop ax
- mov lastchar,ax ;Restore line length
- jmp short @get_kbd_line_90
-
- @done_editing:
- call near ptr remember ;Store in history buffer
- ; Picks up line from global linebuf
- @done_editing_2:
- call near ptr disp_line ;Necessry for @del_eol_exec,
- ; might as well do for others
- mov ax,lastchar
- mov dot,ax ;Set dot to end of line
- call near ptr line_to_scr ;Set cursor beyond last character
-
- @get_kbd_line_90:
- @DispCh CR ;Do a carraige return because
- ; some applications like EDLIN
- ; only do a LF to go to next line
- ; @DispCh LF ;Go onto next line
- ; all done
- @get_kbd_line_99:
- @restore
- ret
- get_kbd_line endp
-
-
-
- getkey proc near
- @GetKey 0
- mov ah,0
- or al,al
- jne @114 ;not '\0'
- mov ah,0Bh
- int 21h ;check if key available
- or al,al
- jz @113 ;no character available
- @GetKey 0
- mov ah,1
- jmp short @114
- @113:
- xor ax,ax
- @114:
- ret
- getkey endp
-
-
-
- ;+
- ; FUNCTION : expand_fnkey
- ;
- ; Inserts the expansion corresponding to a symbol key into the
- ; linebuffer. If the buffer is too small, only as many characters as
- ; possible are inserted and the function returns an error. The
- ; function also returns an error if the symbols is not defined. The
- ; function also updates the displayed line. The function also checks
- ; if the line is to be executed immediately or not, based on the last
- ; character of the fn key expansion.
- ;
- ; Parameters:
- ; AX = function key character, must be between (256+59)-(256+68)
- ; function keys and (256+84)-(256+93) for shifted functin keys.
- ;
- ; Returns:
- ; CF = 0 if no error, else 1
- ; If CF is 1, then AX is 0 if symbol not found or non-zero
- ; if symbol found but no room in line.
- ; AX = 1 if symbol was present
- ; 0 if symbol was not found.
- ; DX = 0 if the line is to be executed immediately
- ; non-0 otherwise
- ; DX is only valid if CF=0 and AX=1
- ; Register(s) destroyed:
- ; <TBA>
- ;-
- expand_fnkey proc near
- @save si,di
- push bp
- mov bp,sp
- sub sp,LINEBUF_SIZE
- exp_buf equ <byte ptr [bp-LINEBUF_SIZE]>
-
- mov si,offset DGROUP:fnkey_tab ;SI->'SFn'
- mov dx,3 ;DX<-length of string
- mov di,si
- sub ax,256+59
- cmp ax,10 ;Is it a function key
- jnb @expand_fnkey_10 ;No, shifted function key
- inc si ;SI->'Fn'
- dec dx ;length of string is 2
- jmp short @expand_fnkey_15
- @expand_fnkey_10:
- sub ax,84-59
- @expand_fnkey_15:
- cmp ax,9 ;F10 must appear as F0
- jne @expand_fnkey_20
- mov al,'0'-'1'
- @expand_fnkey_20:
- add al,'1'
- mov 2[di],al ;Store in 'SFn' string
- ; OK now try and expand the symbol.
- ; SI->symbol
- mov ax,LINEBUF_SIZE
- xchg ax,dx ;AX<-length of synbol
- ; DX<-length of expansion buffer
- lea di,exp_buf
- call near ptr get_symbol ;Params SI,AX,DI,DX
- jc @expand_fnkey_99 ;No symbol (buffer too
- ; small case not possible).
- ; AX will be 0 for this case.
- ; OK now we have the symbol expansion, so try insert it into the linebuffer.
- ; AX contains length of expansion
- mov si,di ;SI->expansion
- add di,ax
- dec di ;DI->last char of expansion
- xor dx,dx
- mov dl,byte ptr [di]
- sub dl,fnkey_exec_char ;Is this line to be
- ; immediately executed
- jne @expand_fnkey_80 ;No
- dec ax ;The last char of expansion
- ; is a special char. Do not
- ; include it in the insert
- ; string
- @expand_fnkey_80:
- push dx
- call near ptr insert_at_dot ;Params SI,AX
- ; pushf ;Save CF
- ; call disp_line
- ; popf ;Restore CF
- mov ax,1 ;AX<-exit code
- pop dx ;DX is 0 if line is to be
- ; executed immediately
- @expand_fnkey_99:
- mov sp,bp
- pop bp
- @restore
- ret
-
- expand_fnkey endp
-
-
- ;+
- ; FUNCTION : store_char
- ;
- ; Stores the character in AX into the line buffer if max line
- ; length will not be exceeded. Characters may be inserted or
- ; overwrite chars in the buffer depending on the edit mode and whether
- ; auto-recall is on.
- ;
- ; Parameters:
- ; AX = character
- ;
- ; Returns:
- ; CF = 0 if no error, else 1
- ; Register(s) destroyed:
- ; <TBA>
- ;-
- store_char proc near
- @save si
- cmp ax,256 ;char >= 256
- jnb @store_char_90 ;Ignore if so
- cmp edit_mode,0 ;1 if insert mode
- je @store_char_20 ;Jump if overtype mode
- cmp auto_recall_on,1 ;Is auto-recall on ?
- je @store_char_20 ;Yes, behave as if in overtype mode
- mov si,offset dgroup:tempchar ;temporary storage
- mov [si],al ;Store char
- mov ax,1 ;Length of string
- call near ptr insert_at_dot ;Insert the character
- jnc @store_char_99 ;No problemo
- jmp short @store_char_90 ;No room in buffer
- @store_char_20:
- mov si,dot ;Current position in line
- cmp si,LINEBUF_END ;At line end?
- jae @store_char_90
- ; Enough room for a char
- mov [si],al ;Store the char
- mov dx,si ;DX->changed character
- mov ax,si
- inc ax ;AX->char after change
- mov dot,ax ;Store it as new dot position
- cmp si,lastchar ;Was it end of line ?
- jb @store_char_30
- mov lastchar,ax ;Store new end of line
- @store_char_30:
- call near ptr set_disp_marks ;ax,dx parameters
- clc ;Indicate no error
- jmp short @store_char_99
- @store_char_90:
- call near ptr bell
- stc ;Indicate error
- @store_char_99:
- @restore
- ret
- store_char endp
-
-
- ;+
- ; FUNCTION : word_left
- ;
- ; Move one word left.
- ;
- ; Parameters:
- ; Globals linebuf and dot.
- ;
- ; Returns:
- ; CF = 1 if dot was at beginning of the line already
- ; 0 otherwise.
- ; Register(s) destroyed:
- ;-
- word_left proc near
- @word_left_10:
- call near ptr char_left ;Move one char left
- jc @word_left_99 ;Already at beginning of line
- @word_left_12:
- ;Loop to backup over non-alphanum
- call near ptr isalphnum ;AL alphanumeric?
- jnc @word_left_15 ;Yes
- call near ptr char_left ;One char left.
- ;AL<-char at dot
- jnc @word_left_12 ;Not at beginning of line
- @word_left_15: ;Now backup to beginning of word
- ; At this point, dot is always at a alphabetic char or beginning
- ; of the line
- call near ptr char_left
- jc @word_left_98 ;Were already at beginning of line
- call near ptr isalphnum ;Alphanumeric?
- jnc @word_left_15 ;Yes, loop back
- ;Found non-alphanumeric char
- call near ptr char_right ;move over one
- @word_left_98:
- clc ;Clear carry flag
- @word_left_99:
- ret
- word_left endp
-
-
-
- ;+
- ; FUNCTION : word_right
- ;
- ; Move one word right.
- ;
- ; Parameters:
- ; Globals linebuf and dot.
- ;
- ; Returns:
- ; Nothing.
- ; Register(s) destroyed:
- ;-
- word_right proc near
- @word_right_10: ;Loop fwd over alphanumerics
- call near ptr char_right ;One char right
- ;AL<-char at dot
- jc @word_right_99 ;Already at end of line
- call near ptr isalphnum ;Is AL alphanumeric ?
- jnc @word_right_10 ;Yes, loop back
- @word_right_15: ;Now move to beginning of word
- call near ptr char_right
- jc @word_right_99 ;Already at end of line
- call near ptr isalphnum ;Alphanumeric?
- jc @word_right_15 ;Not alphanum char, loop back
- @word_right_99:
- ret
- word_right endp
-
-
-
-
- ;+
- ; FUNCTION : char_left
- ;
- ; Moves the 'dot' one character to the left unless
- ; already at the beginning of the line.
- ;
- ; Parameters:
- ; Global dot is current position in the line.
- ;
- ; Returns:
- ; AL = char at new dot position.
- ; CF = 1 if OLD dot was at beginning of line
- ; 0 otherwise.
- ; Register(s) destroyed:
- ;-
- char_left proc near
- @save si
- mov ax,dot ;Current position in line
- cmp ax,offset dgroup:linebuf
- jne @char_left_5
- stc ;Dot already at beginning of line
- jmp short @char_left_99
- @char_left_5:
- dec ax ;Move dot left
- mov dot,ax
- @char_left_99:
- xchg ax,si
- lodsb ;AL<-char at dot
- @restore
- ret
- char_left endp
-
-
-
-
-
-
-
- ;+
- ; FUNCTION : char_right
- ;
- ; Moves the 'dot' one character to the right unless
- ; already at the end of the line.
- ;
- ; Parameters:
- ; Global dot is current position in the line.
- ;
- ; Returns:
- ; AL = char at new dot position. Undefined if new dot is at
- ; the end of the line.
- ; CF = 1 if OLD dot was already at end of the line.
- ; 0 otherwise.
- ; Register(s) destroyed:
- ;-
- char_right proc near
- @save si
- mov si,dot ;Current position in line
- mov ax,lastchar ;AX->Beyond last char
- dec ax ;AX->last char in line
- cmp ax,si ;Dot at end ?
- jc @char_right_99 ;Already at line end
- inc si ;Move dot right, CF not affected
- mov dot,si
- lodsb ;AL<-char at dot, (undefined if
- ; dot is now at end of line).
- ; CF already clear
- @char_right_99:
- @restore
- ret
- char_right endp
-
-
-
- ;+
- ; FUNCTION : go_bol
- ;
- ; Sets dot to pint to the beginning of the line
- ;
- ; Register(s) destroyed: None.
- ;-
- go_bol proc near
- mov dot,offset dgroup:linebuf
- ret
- go_bol endp
-
-
-
- ;+
- ; FUNCTION : go_eol
- ;
- ; Sets dot to pint to the end of the line
- ;
- ; Register(s) destroyed: AX.
- ;-
- go_eol proc near
- mov ax,lastchar
- mov dot,ax
- ret
- go_eol endp
-
-
-
-
- ;+
- ; FUNCTION : match_file
- ;
- ; match_file tries to expand the filename to the left of the
- ; cursor. If there are several matching files, the longest common
- ; prefix is placed on the line.
- ;
- ; Parameters:
- ; None.
- ;
- ; Returns:
- ; Nothing.
- ; Register(s) destroyed:
- ;-
- match_file proc near
- @save si,di
- push bp
- mov bp,sp
- sub sp,64+44+2+2+2+2+2+2 ;Locals
- pname equ 64 ;Storage for entire filename with path
- ffblk equ pname+44
- ffblk_attr equ ffblk-15h ;Attr byte within ffblk
- ffblk_name equ ffblk-1Eh ;filename within ffblk
- fname equ ffblk+2 ;Points to start of filename in name
- oldDTAseg equ fname+2
- oldDTAoff equ oldDTAseg+2
- lineptr equ oldDTAoff+2 ;Pointer to location in linebuf
- remaining equ lineptr+2 ;Remembers remaining space in path
- breakstate equ remaining+2 ;Remembers break state
-
- mov ax,3300h ;Get current break state
- int 21h ;DL<-current break state
- mov byte ptr [bp-breakstate],dl ;Remember it
- xor dl,dl
- mov ax,3301h ;Disable break check during
- ; disk i/O
- int 21h
- lea di,[bp-pname] ;OK 'cause SS==DS
- mov si,dot ;Current line position
- mov cx,63 ;Max length of path
- @match_file_10:
- cmp si,offset dgroup:linebuf
- je @match_file_51 ;Beginning of line and filename
- dec si
- mov al,[si] ;AL<-next char
- @match_file_25:
- call near ptr isspace
- je @match_file_50 ;Beginning of filename
- @match_file_45: ;Check for next char if
- ; pathname not too long
- loop @match_file_10
- jmp @match_file_99 ;Pathname too long, just exit
- @match_file_50:
- inc si
- @match_file_51:
- ; Copy filename into ASCIIZ buffer
- ; SI->first char of filename in path buffer
- xor dx,dx ;Flags
- mov ax,63
- sub ax,cx ;Length of name
- mov [bp-remaining],cx ;remember num bytes left in
- ; path buffer
- xchg ax,cx ;CX<-length of name
- mov [bp-lineptr],si ;Save start of path name in linebuf
- mov [bp-fname],di ;Remember start of filename in
- ; path buffer as well (assumed)
- or cx,cx ;Too far for jcxz
- jne @match_file_55
- jmp @match_file_99 ;No name, just exit
- @match_file_55:
- lodsb ;AL<-next char
- stosb ;Store it
- cmp al,'.'
- jne @match_file_56
- or dl,1 ;Set flag to remember file type '.'
- jmp short @match_file_65 ;Check out next character
- @match_file_56:
- cmp al,'\' ;Directory separator?
- jne @match_file_59
- @match_file_57:
- mov [bp-fname],di ;Update start of filename in
- ; path buffer
- @match_file_58:
- and dl,0FEh ;Forget file type flag
- jmp short @match_file_65
- @match_file_59:
- cmp al,'/' ;Same thing
- je @match_file_57
- cmp al,':' ;Disk?
- jne @match_file_65
- and dl,0FEh ;Forget file type (shouldn't really
- ; occur)
- mov [bp-fname],di ;Update start of filename in
- ; path buffer
-
- @match_file_65:
- loop @match_file_55
-
- mov cx,[bp-remaining] ;CX<-remaining space
- jcxz @match_file_52 ;Only space for terminator
- mov al,'*'
- stosb ;Attach a '*'
- cmp cl,3 ;Enough space for ".*"
- jb @match_file_52
- and dl,1 ;Saw a file type ?
- jne @match_file_52 ;Yes, go attach terminator
- mov [di],2A2Eh ;Attach a ".*"
- inc di
- inc di
- @match_file_52:
- xor al,al ;AL<-0
- stosb ;Terminating 0
-
- ; name contains the filename
- push es
- @GetDTA ;Get and save old DTA
- mov [bp-oldDTAseg],es
- mov [bp-oldDTAoff],bx
- pop es
- ;
- lea dx,[bp-ffblk]
- @SetDTA dx ;Set DTA to our DTA
-
- lea dx,[bp-pname] ;dx->ASCII name
- @GetFirst dx,16 ;Include subdirs in search
- jnc @match_file_70 ;No error
- call near ptr bell ;No files found
- jmp @match_file_90 ;Restore DTA and exit
-
-
- @match_file_70: ;At least one file found
- mov di,[bp-fname] ;DI->filename portion
- lea si,[bp-ffblk_name] ;Name returned by GetFirst
- @match_file_71: ;Copy the file name
- lodsb
- stosb
- or al,al
- jne @match_file_71
-
- mov al,SPACE ;If file, add a space
- test byte ptr [bp-ffblk_attr],16 ;Subdirectory?
- je @match_file_72 ;No
- mov al,'\' ;If subdir, add a backslash
- @match_file_72:
- mov byte ptr [di-1],al ;Add a space or a '\'
- mov byte ptr [di],0
-
- ; Now hunt for more files. For each file found, keep the longest
- ; prefix in common so far.
-
- @GetNext ;Get the next file name
- jc @match_file_80 ;No more files
-
- mov di,[bp-fname] ;DI->start of file name
- lea si,[bp-ffblk_name] ;Name returned by GetNext
- mov cx,13 ;Max Length of field
- repe cmpsb ;Compare strings
- mov byte ptr [di-1],0 ;Terminating null
- jmp short @match_file_72 ;Try for more files
-
- @match_file_80:
- ; Found one or more files, copy the longest common prefix
- ; into the line buffer
- mov ax,[bp-lineptr] ;AX->start of chars to be deleted
- call near ptr erase_to_dot ;Delete characters between dot
- ; and start of name
- lea si,[bp-pname] ;SI->name to be copied
- mov di,si
- xor al,al
- mov cx,64
- repne scasb ;Hunt for terminating null
- mov ax,63
- sub ax,cx ;AX<-length of string
- ; SI->string, AX is length
- push ax
- call near ptr xlate_lower ;Convert to lowercase
- pop ax
- call near ptr insert_at_dot ;SI->source, AX == length
-
- @match_file_90:
- push ds
- mov ds,[bp-oldDTAseg]
- mov dx,[bp-oldDTAoff]
- @SetDTA dx ;Restore DTA
- pop ds
- @match_file_99:
- ; Restore previous state of break checking
- mov dl,byte ptr [bp-breakstate]
- mov ax,3301h
- int 21h
- mov sp,bp
- pop bp
- @restore
- ret
- match_file endp
-
-
-
- CSEG ENDS
-
- END
-