📄 ted2.asm
字号:
REP MOVSB ;put deleted line in buffer
POP ES ;get back file segment
POP AX
MOV CX,LAST_CHAR ;get the file size
SUB LAST_CHAR,AX ;subtract the deleted line
MOV SI,CURSOR ;get new cursor location
MOV DI,SI
ADD SI,AX ;SI points to end of file
SUB CX,SI ;length of remaining file
JCXZ NO_DEL_L
REP MOVSB ;shift remainder of file up
NO_DEL_L:
MOV DIRTY_BITS,3 ;redraw the screen and adjust cursor
RET
DEL_L ENDP
;=======================================================================
; This routine undeletes a line by copying it from the line buffer into
; the file.
;-----------------------------------------------------------------------
UDEL_L PROC NEAR
CMP LINE_FLAG,0 ;is this an end of line only?
JE UDEL_EOL ;if yes, don't home the cursor
CALL HOME ;move cursor to home
UDEL_EOL:
MOV AX,LINE_LENGTH ;length of deleted line
MOV SI,OFFSET LINE_BUFFER
;**insert_str JMP INSERT_STRING ;(follows immediately)
;(CALL/RETurn)
UDEL_L ENDP
;-----------------------------------------------------------------------
; This routine inserts AX characters from CS:SI into the file.
; (This routine follows "UDEL_L")
;-----------------------------------------------------------------------
INSERT_STRING PROC NEAR
; ASSUME DS:FILE_SEG
PUSH SI ;save string buffer
MOV SI,CS:CURSOR ;get cursor offset
PUSH AX ;save length of string
PUSH SI
CALL OPEN_SPACE ;make space to insert string
POP DI ;get back cursor position
POP CX ;get back string length
POP SI ;get back string buffer
JC NO_SPACE ;if no space available, exit
PUSH DS
PUSH CS
POP DS
ASSUME DS:CSEG
REP MOVSB ;copy characters DS:SI to ES:DI
MOV DIRTY_BITS,3 ;redraw the screen and adjust cursor
POP DS
ASSUME DS:NOTHING
CALL C_IF_NEW_CRLF
NO_SPACE:
RET
INSERT_STRING ENDP
;=======================================================================
; VIDEO services
;=======================================================================
; This routine displays a character by writing directly to
; the screen buffer. To avoid screen noise (snow) on the color
; card (CGA), the horizontal retrace has to be monitored.
;-----------------------------------------------------------------------
WRITE_INVERSE PROC NEAR
ASSUME DS:FILE_SEG, ES:FILE_SEG
MOV BH,CS:INVERSE ;attribute for inverse video
JMP SHORT WRITE_SCREEN
;-----------------------------------------------------------------------
WRITE_FIND:
MOV BH,CS:SRCH_CLR ;attribute for find string
; MOV BH,CS:INVERSE ;attribute for find string
JMP SHORT WRITE_SCREEN
;-----------------------------------------------------------------------
WRITE_NORMAL:
MOV BH,CS:NORMAL ;attribute for normal video
WRITE_SCREEN:
MOV BL,AL ;save the character
PUSH ES
LES DX,CS:VIDEO_STATUS_REG ;video status register
;-------------------------------------------------------
; HWAIT is used to "desnow" the display for the CGA.
; If not CGA, the following instruction is modified to a
; JMP SHORT WRITE_IT
;-------------------------------------------------------
HWAIT:
IN AL,DX ;get video status
ROR AL,1 ;look at horizontal retrace
JNC HWAIT ;wait for retrace
WRITE_IT:
MOV AX,BX ;get the character/attributes
STOSW ;write the character
POP ES
RET
WRITE_INVERSE ENDP
;=======================================================================
; This routine moves the cursor to the row/column in DX.
;-----------------------------------------------------------------------
SET_CURSOR PROC NEAR
XOR BH,BH ;we're using page zero
MOV AH,2 ;BIOS set cursor function
INT 10H
RET
SET_CURSOR ENDP
;=======================================================================
; This routine computes the video buffer offset for the row/column in DX.
;-----------------------------------------------------------------------
POSITION PROC NEAR
MOV AX,CS:COLUMNS ;take columns per row
MUL DH ;times row number
XOR DH,DH
ADD AX,DX ;add the column number
SHL AX,1 ;times 2 for offset
MOV DI,AX ;return result in DI
RET
POSITION ENDP
;=======================================================================
; This routine erases from the location in DX to the right edge of the screen.
;-----------------------------------------------------------------------
ERASE_EOL PROC NEAR
ASSUME DS:NOTHING
CALL POSITION ;find screen offset
MOV CX,CS:COLUMNS ;get screen size
SUB CL,DL ;subtract current position
JCXZ NO_CLEAR
ERASE_LOOP:
MOV AL," " ;write blanks to erase
CALL WRITE_NORMAL ;display it
LOOP ERASE_LOOP
NO_CLEAR:
RET
ERASE_EOL ENDP
;=======================================================================
; This routine displays the function key prompt and insert/overstrike mode
; state. It sets DIRTY_BITS := 3 to force redraw of the entire screen
; and locate cursor.
;-----------------------------------------------------------------------
REDO_PROMPT PROC NEAR
ASSUME DS:NOTHING, ES:NOTHING
PUSH DS
PUSH CS
POP DS
ASSUME DS:CSEG
MOV DH,ROWS ;put prompt at last row
INC DH
XOR DL,DL ;and column 0
CALL POSITION ;convert to screen offset
MOV SI,OFFSET PROMPT_STRING
KEY_LOOP:
MOV AL,"F" ;display an "F"
CALL WRITE_NORMAL
LODSB
OR AL,AL ;last key in prompt?
JZ PROMPT_DONE
CALL WRITE_NORMAL
CMP BYTE PTR CS:[SI],"0" ;is it F10?
JNE TEXT_LOOP
LODSB
CALL WRITE_NORMAL
TEXT_LOOP:
LODSB
OR AL,AL ;last letter in word?
JNZ WRITE_CHAR
MOV AL," " ;display a space
CALL WRITE_NORMAL
JMP KEY_LOOP
WRITE_CHAR:
CALL WRITE_INVERSE ;display the letter
JMP TEXT_LOOP ;do the next letter
PROMPT_DONE:
MOV DH,ROWS
INC DH ;get the last row on the screen
MOV DL,PROMPT_LENGTH + 9
CALL ERASE_EOL ;erase to the end of this row
MOV BL,INSERT_MODE
XOR BH,BH
MOV AL,CS:[BX + OFFSET INSERT_CODE]
; MOV AL,"O" ;write an "O" (for "Overstrike")
; CMP INSERT_MODE,1 ;in insert mode?
; JB OVERSTRIKE
; MOV AL,"I" ;write an "I" (for "Insert")
; JE OVERSTRIKE
; MOV AL,"R" ;write an "R" (for "read-only")
OVERSTRIKE:
DEC DI ;backup one character position
DEC DI
CALL WRITE_NORMAL
MOV DIRTY_BITS,3 ;now redraw the entire screen
POP DS
ASSUME DS:NOTHING
RET
REDO_PROMPT ENDP
;=======================================================================
; This routine displays the file buffer on the screen.
; DISPLAY_BOTTOM has been deleted to reduce the program code size.
;-----------------------------------------------------------------------
DISPLAY_SCREEN PROC NEAR
ASSUME DS:FILE_SEG, ES:FILE_SEG
TEST DIRTY_BITS,2 ;see if we should adjust the cursor
JZ DISP_CURS_OK
MOV SI,CURSOR ;get the new cursor offset
MOV DX,CURS_POSN ;also get the current row
CALL LOCATE ;adjust the cursor screen position
DISP_CURS_OK:
MOV DX,CURS_POSN
MOV SAVE_ROW,DH
CALL SET_CURSOR ;position the cursor
TEST DIRTY_BITS,1 ;see if we should update the screen
JNZ DO_UPDATE_SCREEN
TEST DIRTY_BITS,4 ;is the current line dirty?
JZ DISP_DONE ;if not, take jump
CALL DISPLAY_CURRENT ;redraw the current line
JMP SHORT DISP_DONE
DO_UPDATE_SCREEN:
MOV SI,TOP_OF_SCREEN ;point to first char on screen
XOR DH,DH ;start at first row
; JMP SHORT NEXT_ROW
; ;-----------------------
;DISPLAY_BOTTOM: ;this redraws the bottom only
; CALL FIND_START ;find first character on this row
; MOV DX,CURS_POSN ;get current cursor row
NEXT_ROW:
PUSH DX
CALL DISPLAY_LINE ;display a line
POP DX
;-----------------------
; the keyboard is tested here to see if a key is waiting
;-----------------------
MOV AH,1
INT 16H
MOV AL,1 ;for dirty_bits, update not completed
JNZ DISP_NOT_DONE ;jump if there is a key is waiting
INC DH ;move to the next row
CMP DH,ROWS ;at end of screen yet?
JBE NEXT_ROW ;do all the rows
DISP_DONE:
MOV AL,0
DISP_NOT_DONE:
MOV DIRTY_BITS,AL ;screen is completely redone
RET
DISPLAY_SCREEN ENDP
;=======================================================================
; This routine displays a single line to the screen. DH holds the
; row number, SI has the offset into the file buffer. Tabs are expanded.
; Adjustment is made for side shift.
;-----------------------------------------------------------------------
DISPLAY_CURRENT PROC NEAR
; ASSUME DS:FILE_SEG
CALL FIND_START
MOV DX,CS:CURS_POSN
DISPLAY_CURRENT ENDP
;-----------------------
DISPLAY_LINE PROC NEAR ;external entry point
XOR DL,DL ;start at column zero
MOV CS:MARGIN_COUNT,DL
MOV CX,DX ;use CL to count the columns
CALL POSITION ;compute offset into video
NEXT_CHAR:
CMP SI,LAST_CHAR ;at end of file?
JAE LINE_DONE
LODSB ;get next character, DS:SI
CMP AL,TAB ;is this a Tab character?
JE EXPAND_TAB ;if yes, expand to spaces
CMP SI,LAST_CHAR ;at end of file now?
JAE DO_PUT ;jump, can't be CR-LF pair
CMP WORD PTR [SI-1],CRLF ;EOL marker
JE FOUND_CR ;quit when a CR-LF is found
DO_PUT:
CALL PUT_CHAR ;put character onto screen
TAB_DONE:
CMP CL,CS:COLUMNSB ;at right edge of screen?
JB NEXT_CHAR
;-----------------------
; from TEDPLUS
INC SI
CMP SI,LAST_CHAR ;at end of file?
DEC SI
JAE NOT_BEYOND
CMP WORD PTR [SI],CRLF ;at end of line?
;----------------------
JE NOT_BEYOND
DO_DIAMOND:
DEC DI ;backup one character
DEC DI
MOV AL,4 ;show a diamond
CALL WRITE_INVERSE ;in inverse video
NOT_BEYOND:
JMP FIND_NEXT ;find start of next line
;(CALL/RETurn)
;---------------------------------------
EXPAND_TAB:
MOV AL," " ;convert tab to spaces
CALL PUT_CHAR
MOV AL,MARGIN_COUNT
ADD AL,CL ;CL is column count
TEST AL,00000111B ;at even multiples of eight?
JNZ EXPAND_TAB ;if not, keep adding spaces
JMP TAB_DONE
;---------------------------------------
FOUND_CR:
INC SI ;past the CR-LF
LINE_DONE:
MOV DX,CX
JMP ERASE_EOL ;erase the end of the line
;(CALL/RETurn)
;-----------------------
DISPLAY_LINE ENDP
;=======================================================================
; This routine displays a single character to the screen. If the character
; is marked, it is shown in inverse video. Characters outside the current
; margin are not displayed. Characters left of the margin are skipped.
;-----------------------------------------------------------------------
PUT_CHAR PROC NEAR
; ASSUME DS:FILE_SEG
MOV BL,MARGIN_COUNT ;get distance to left margin
CMP BL,LEFT_MARGIN ;are we inside left margin?
JAE IN_WINDOW ;yes, show the character
INC BL
MOV MARGIN_COUNT,BL
RET
;-----------------------
; from TEDPLUS
IN_WINDOW:
CMP SRCH_FLG,0
JE CKM
CMP SI,SRCH_BASE
JBE CKM
CMP SI,SRCH_END
JA CKM
CALL WRITE_FIND
;**inverse CALL WRITE_INVERSE ;found string highlighted, inverse video
JMP SHORT NEXT_COL
CKM:
;-----------------------
CMP SI,MARK_START ;is this character marked?
JBE NOT_MARKED
CMP SI,MARK_END
JA NOT_MARKED
CALL WRITE_INVERSE ;marked characters shown inverse
JMP SHORT NEXT_COL
;-----------------------
NOT_MARKED:
CALL WRITE_NORMAL
NEXT_COL:
INC CL ;increment the column count
RET
PUT_CHAR ENDP
;=======================================================================
; This routine adjusts the cursor position ahead to the saved cursor column.
; On entry DH has the cursor row.
;-----------------------------------------------------------------------
SHIFT_RIGHT PROC NEAR
; ASSUME DS:FILE_SEG
MOV CL,SAVE_COLUMN ;keep the saved cursor offset
XOR CH,CH
MOV BP,CX ;keep the saved cursor position
ADD CL,LEFT_MARGIN ;shift into visible window
ADC CH,0
XOR DL,DL
MOV CURS_POSN,DX ;get cursor row/column
JCXZ NO_CHANGE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -