📄 edit.asm
字号:
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -