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

📄 cmdedit.asm

📁 8086汇编语言编写的文本编辑器源码,功能比较简单
💻 ASM
📖 第 1 页 / 共 4 页
字号:
@get_next_line_99:
	ret
get_next_line endp



;+
; FUNCTION : replace_vars
;
;	Replaces all the variables in the current line with their
;	expansions. If the line is too long, aborts with a truncation
;	error.
;
; Parameters:
;	None.
;
; Returns:
;	Nothing.
; Register(s) destroyed:
;	AX,BX,CX,DX
;-
replace_vars proc near
	call	near ptr expand_var		;CF set if error. AX
;						 contains error code
	jnc	@replace_vars_99
	jmp	near ptr abort_processing	;Abort processing

@replace_vars_99:
	ret
replace_vars endp



;+
; FUNCTION : get_curpos
;
;	Returns the current cursor position.
;
; Parameters:
;	Global	video_page indicates the page.
;
; Returns:
;	DX	= Current cursor position.
;	CX	= Current cursor scan lines.
; Register(s) destroyed: AX,BX
;-
get_curpos proc	near
	@GetCur	video_page
	ret
get_curpos	endp


;+
; FUNCTION : set_disp_marks
;
;	Sets the marks disp_begin and disp_end to indicate the start
;	and end positions in the line that have been changed. The
;	routine is passed two parameters which indicate
;	the potentially new values for disp_begin and disp_end
;	respectively. However the global disp_begin is changed only if
;	the new value is less than the current value. Similarly
;	disp_end is changed only if the new value is greater than the
;	current value.
;
; Parameters:
;	AX	= potential disp_end
;	DX	= potential disp_begin
;
; Returns:
;	Nothing.
;	May set globals disp_begin and disp_end.
;
; Register(s) destroyed: None.
;-
set_disp_marks	proc near
	cmp	ax,disp_end		;New value greater ?
	jb	@set_disp_marks_10	;No
	mov	disp_end,ax		;New disp_end
@set_disp_marks_10:
	cmp	dx,disp_begin		;New value smaller
	jnb	@set_disp_marks_20	;No
	mov	disp_begin,dx		;New disp_begin
@set_disp_marks_20:
	ret
set_disp_marks	endp


;+
; FUNCTION : disp_line
;
;	Displays the current contents of the line buffer. Since the
;	entire line is not redisplayed everytime, all procedures that
;	change the contents of the line buffer have to follow certain
;	rules in order to make sure the display correctly shows the
;	line. The variable disp_begin must be set to the earliest
;	position in the line that has been changed and disp_end to beyond
;	last position in the line that has been changed.;
; Parameters:
;	None.
;
; Returns:
;	Nothing
; Register(s) destroyed:
;-
disp_line proc near
	@save	si,di
	mov	ax,disp_begin		;Lower limit of changed chars
	mov	si,ax
	mov	cx,disp_end		;CX->byte after last char that
;					 has changed
	sub	cx,si			;CX<-num chars to be output
	jcxz	@disp_line_90		;Nothing to be updated
	push	cx			;Save CX across calls
	call	near ptr line_to_scr	;Move cursor to corresponding
;					 position on the screen.
;	OK, now we are ready to begin updating the screen.
	call	near ptr get_curpos	;DX<-current cursor position
	pop	cx			;Restore CX
	mov	di,lastchar		;DI->beyond last char
	cmp	si,di			;Beyond last char?
	je	@disp_line_25		;Go display blanks
@disp_line_10:				;Loop to output chars
	lodsb				;AL<-next char
	@DispCh	al			;Display it
	push	cx			;Save CX
	push	dx			;Save old cursor position
	call	near ptr get_curpos	;DX<-new cursor position
					; BX destroyed
	pop	bx			;BX<-old cursor position
	pop	cx			;Restore CX
	or	dl,dl			;Column 0 ?
	jne	@disp_line_20		;Nope
					;Col 0
	cmp	bh,dh			;Is the row the same
	jne	@disp_line_20
					;yes, screen scrolled
	dec	initial_curpos+1	;Decrement the row for initial
;					 cursor position
@disp_line_20:
	mov	bx,dx			;New cursor position
	cmp	si,di			;Beyond last char?
	loopne	@disp_line_10		;Keep looping until count exhausted or 
;					 beyond last char
@disp_line_25:
;	Now all changed positions have been displayed. If CX is not 0, 
;	then the remaining char positions have to be 
;	replaced with blanks. Note that since we are now overwriting  
;	previously displayed positions, no need to check for line 
;	wraparound or scroll. 

	jcxz	@disp_line_90		;No more chars

	mov	al,' '			;Overwrite with blanks
@disp_line_30:
	@DispCh	al
	loop	@disp_line_30
@disp_line_90:
	mov	ax,dot
	mov	disp_begin,ax		;Initialize for next call
	mov	disp_end,ax
	call	near ptr line_to_scr	;Set cursor at dot

	@restore
	ret
disp_line endp





;+
; FUNCTION : line_to_scr
;
;	Places the cursor at the screen position corresponding to a
;	specific position in the line buffer. The entire line buffer
;	upto that position must have been displayed before.
;
; Parameters:
;	AX	= Pointer into the line buffer
;
; Returns:
;	Nothing.
; Register(s) destroyed: AX, BX, DX
;-
line_to_scr proc near
	sub	ax,offset dgroup:linebuf ;ax<-num chars
	mov	dx,initial_curpos	;Initial cursor position
;					 dh<-row, dl<-column
	xor	bh,bh
	mov	bl,dl			;BX<-original column
	add	ax,bx			;Compensate for initial position.
;					 AX is now the 'virtual column'
	mov	bl,screen_width		;BX<-width of screen
@line_to_scr_10:			;Loop to skip over chars that
;					 do not need to be updated
	cmp	ax,bx			;Num of chars fit on a line?
	jb	@line_to_scr_20		;Yes, exit loop
	sub	ax,bx			;Go to next line
	inc	dh			;Increment the row
	jmp	short @line_to_scr_10
@line_to_scr_20:
; al now contains the column and dh the row where the cursor should
; be placed 
	mov	dl,al			;dx<-screen position
	@SetCurPos ,,video_page		;Set the cursor position
	ret
line_to_scr endp




;+
; FUNCTION : insert_chars
;
;	Inserts a string of chars at the specified position in the
;	linebuffer. If the length would exceed the size of the line buffer,
;	chars are only store until the buffer is full and the carry flag is
;	set. Dot is updated appropriately.
;
; Parameters :
;
;	SI	- ptr to source string
;	DI	- ptr to insert position. This must lie in the line buffer.
;	AX	- length of source string
;
; Returns:
;	CF	= 1 if could not be fitted into linebuf
;		  0 otherwise
;
; Registers destroyed:
;	AX,CX,DX
insert_chars proc near
	@save	si,di
	mov	dx,di			;Save insert position in DX
	mov	di,lastchar		;First empty position
	mov	cx,offset DGROUP:linebuf_suffix
	sub	cx,di			;Subtract current last position
;					 CX<-max chars that will fit
	cmp	cx,ax			;Will all chars fit ?
	jb	@insert_chars_5	;Not all chars will fit
	xchg	ax,cx			;All chars will fit
@insert_chars_5:
;	CX is number of chars to insert
	pushf				;Remember CF
;	Make place for the characters to be inserted by moving current
;	characters up by CX.
	mov	ax,di
	sub	ax,dx			;AX<-num chars to move
	push	si			;Remember source address
	mov	si,di			;SI->first char to be moved
	add	di,cx			;DI -> new value of lastchar
	mov	lastchar,di		;Store it
	xchg	ax,cx			;AX<-num chars to insert
;					 CX<-num chars to move
	std				;Direction is downward
	cmpsb				;Decrement SI,DI
	rep	movsb			;Make place
	cld
	pop	si			;Restore string source
; Before inserting the chars, update the dot if it is affected.
	cmp	dx,dot			;Is the dot at or after the insert
;					 position ?
	jb	@insert_chars_50	;No, jump
	add	dot,ax			;Else update the dot
@insert_chars_50:
	mov	di,dx			;DI->insert position
	xchg	cx,ax			;CX<-num chars to insert
	rep	movsb			;Copy string into linebuffer
	mov	ax,lastchar
	call	near ptr set_disp_marks	;AX,DX are parameters
	popf				;Restore CF

	@restore
	ret
insert_chars endp


;+
; FUNCTION : insert_at_dot
;
;	Inserts a string of characters into the line buffer in the
;	position pointed to by dot. If the length specified in global
;	caller_buflen will be exceeded,chars are only stored until the
;	buffer is full and CF is set.
;
; Parameters:
;	SI	= ptr to source string
;	AL	= length of string
;
; Returns:
;	CF	= 1 if could not be fitted into linebuf
;		  0 otherwise
; Register(s) destroyed:
;	<TBA>
;-
insert_at_dot proc near
	@save	si,di,dx
	xor	ah,ah			;AX<-length of source string
	mov	di,dot			;DI-> insert position
	call	near ptr insert_chars	;Params SI,DI,AX, returns status in CF
	@restore
	ret
insert_at_dot endp




;+
; FUNCTION : remove_chars
;
;	Removes a string of chars at the specified position in the
;	linebuffer. The display markers and the lastchar global are updated
;	accordingly. 
;
; Parameters :
;
;	SI	- ptr to position in linebuf from which to delete
;	AX	- number of chars to delete.
;
; Returns:
;	Nothing.
;
; Registers destroyed:
;	AX,CX,DX
remove_chars proc near
	@save	si,di
	mov	di,ax			;Save delete count

; First update the display markers
	mov	ax,lastchar
	mov	dx,si
	call	near ptr set_disp_marks	;AX,DX params
	mov	ax,lastchar
	sub	ax,si			;Num chars after delete position
	cmp	ax,di			;More than the specified number ?
	jb	@remove_chars_10	;No, so just delete that many bytes
	mov	ax,di
@remove_chars_10:
; AX is number of bytes to delete. See if the dot needs to be updated.
	mov	di,si			;DI->delete position
	add	si,ax			;SI->first char after delete string
	cmp	di,dot
	jnb	@remove_chars_40	;dot before delete pos, so
;					 unaffected
	cmp	si,dot			;Is dot beyond it delete range
	jb	@remove_chars_30	;Yes
; dot is in delete region. Update it to point to first delete position
	mov	dot,di
	jmp	short @remove_chars_40
@remove_chars_30:
; dot is beyond delete position. So subtract delete bytes from it.
	sub	dot,ax

@remove_chars_40:
; Now that the screen markers and dot have been updated, get down to the
; real business at hand. SI points to first char after delete string, DI is
; the delete position. AX is number of bytes to be deleted.
	mov	cx,lastchar
	sub	lastchar,ax		;Update lastchar
	sub	cx,si			;CX<-num bytes to move
	rep	movsb			;Move 'em
; All done

	@restore
	ret
remove_chars endp


;+
; FUNCTION : erase_to_dot
;
;	Deletes all characters from the line buffer between the
;	positions AX and dot. (Either AX or dot may be specify the
;	beginning of range to be deleted). The markers disp_begin and
;	disp_end are set to reflect the changed positions in the line.
;	Global lastchar is also updated.
; Parameters:
;	AX	= One endpoint of the range to be deleted.
;	Global	dot is the other.
; Returns:
;	Nothing.
; Register(s) destroyed:
;-
erase_to_dot proc near
	@save	si
	mov	si,dot
	cmp	ax,si			;Make sure AX is after dot
	jnb	@erase_to_dot_10	;Yes it is
	xchg	si,ax			;Else exchange
@erase_to_dot_10:			;AX is low end, SI high end
	sub	ax,si			;AX is num bytes to delete
	call	near ptr remove_chars	;Delete AX chars starting at [SI]
	@restore
	ret
erase_to_dot endp


;+
; FUNCTION : cmdedit_cmd
;
;	Checks if the line buffer contains a CMDEDIT command and if so
;	executes it.
;
; Parameters:
;	None.
;
; Returns:
;	CF	= 0 if the line was a command
;		  1 otherwise.
; Register(s) destroyed:
;	AX,BX,CX,DX
;-
cmdedit_cmd proc near
	@save	si,di
	mov	si,offset DGROUP:linebuf	;SI->linebuf
	mov	di,lastchar			;DI->end of line in linebuf
; Skip leading whitespace
	mov	cx,di
	sub	cx,si				;CX<-num chars in linebuf
	call	near ptr skip_whitespace	;SI->first non-whitespace char
;						 CX<-num remaining chars
	jcxz	@cmdedit_cmd_99			;No command on line
	mov	di,si				;DI->first char of word
; Skip first word (name of this command)
	call	near ptr skip_nonwhite		;SI->first whitespace after
;							 command name
;						 CX<-num remaining chars
	mov	ax,si
	sub	ax,di				;AX<-num chars in word
	cmp	ax,MAX_CMD_LEN			;Word too long to be command?
	ja	@cmdedit_cmd_98			;Yes, exit
; Now search thru the command table to see if the first word in the line is a
; CMDEDIT command. Currently, DI->start of word, AX = num chars in word
	xor	dx,dx				;DX<-Command number
	mov	si,offset dgroup:cmd_table	;SI->Start of commands

@cmdedit_cmd_10:

⌨️ 快捷键说明

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