⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 edit.asm

📁 random.zip 随机数产生器的汇编源代码 cmdsrc.zip 一个文本编辑器的汇编源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
; EDIT.ASM
; (c) 1989, 1990 Ashok P. Nadkarni
;
; This module contains the line editing functions of CMDEDIT.

	PUBLIC	get_kbd_line
	PUBLIC	auto_recall
	PUBLIC	expand_fnkey

	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	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

@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
	dw	@filename	;^I
	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	@ignore		;^T
	dw	@prev_line	;^U
	dw	@search_forw	;^V
	dw	@del_next_word	;^W
	dw	@del_bol	;^X
	dw	@autorecall	;^Y
	dw	@default_action	;^Z
	dw	@erase_line	;^[ or ESC
	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'

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -