📄 ted2.asm
字号:
INC DH ;advance cursor to next row
CALL SHIFT_RIGHT ;move cursor to current column
DOWN_RET:
RET
;-----------------------
SCREEN_UP:
CMP SI,LAST_CHAR ;get cursor offset
JE DOWN_RET
CALL FIND_START ;find the start of this line
MOV CURSOR,SI ;this is the new cursor
CALL FIND_NEXT ;find the offset of next line
JC SHIFT_RET ;if no more lines, then return
MOV CURSOR,SI ;this is the new cursor
MOV SI,TOP_OF_SCREEN ;get the start of the top row
CALL FIND_NEXT ;and find the next line
MOV TOP_OF_SCREEN,SI ;store the new top of screen
JMP SHORT SHIFT_RET
;(CALL/RETurn)
DOWN ENDP
;-----------------------------------------------------------------------
; This routine moves the cursor up one row. If the cursor is at the first row,
; the screen is scrolled down.
;-----------------------------------------------------------------------
UP PROC NEAR
MOV UNDO_LENGTH,0
MOV DX,CURS_POSN
MOV SI,CURSOR
OR DH,DH ;at top row already?
JZ SCREEN_DN ;if yes, then scroll down
DEC DH ;move the cursor up one row
CALL FIND_CR ;find the beginning of this row
MOV CURSOR,SI
CALL FIND_START ;find start of this row
MOV CURSOR,SI
CALL SHIFT_RIGHT ;skip over to current column
AT_TOP:
RET
;-----------------------
SCREEN_DN:
MOV SI,TOP_OF_SCREEN
OR SI,SI ;at start of file?
JZ AT_TOP ;if at top, then do nothing
CALL FIND_PREVIOUS ;find the preceding line
MOV TOP_OF_SCREEN,SI ;save new top of screen
MOV SI,CURSOR
CALL FIND_PREVIOUS ;find the preceding line
MOV CURSOR,SI ;this is the new cursor
SHIFT_RET:
OR DIRTY_BITS,1 ;need to redraw the screen
MOV SI,CURSOR
MOV DX,CURS_POSN
JMP SHIFT_RIGHT ;move cursor to current column
;(CALL/RETurn)
UP ENDP
;=======================================================================
; These four routines move the screen one page at a time by calling the
; UP and DOWN procedures.
;-----------------------------------------------------------------------
CTRL_PGDN PROC NEAR ;do PgDn then PgUp
CALL PGDN
JMP SHORT PGUP
;(CALL/RETurn)
CTRL_PGDN ENDP
;-----------------------------------------------------------------------
PGUP PROC NEAR
MOV CS:PAGE_PROC,OFFSET UP
JMP SHORT PAGE_UP_DN
PGUP ENDP
;-----------------------------------------------------------------------
CTRL_PGUP PROC NEAR ;do PgUp then PgDn
CALL PGUP
;** JMP SHORT PGDN
;(CALL/RETurn)
CTRL_PGUP ENDP
;-----------------------------------------------------------------------
PGDN PROC NEAR
MOV CS:PAGE_PROC,OFFSET DOWN
PAGE_UP_DN:
MOV CL,CS:ROWS ;get vertical length of screen
SUB CL,5 ;don't page a full screen
XOR CH,CH ;make it a word
PAGE_LOOP:
PUSH CX
CALL PAGE_PROC ;move the cursor down
POP CX
LOOP PAGE_LOOP ;loop for one page length
RET
PGDN ENDP
;=======================================================================
; This routine toggles the Insert/Overstrike mode.
;-----------------------------------------------------------------------
INSERT PROC NEAR
; ASSUME DS:NOTHING
;**RO mode NOT CS:INSERT_MODE ;toggle the switch
XOR CS:INSERT_MODE,1 ;toggle the "I/O" switch
CALL REDO_PROMPT ;redraw the insert/overstrike status
RET
INSERT ENDP
;=======================================================================
; FILE MANIPULATION services
;=======================================================================
; This routine forces the insertion of the NUL character, 00H, in the file.
;-----------------------------------------------------------------------
NUL_CHAR PROC NEAR
XOR AX,AX
NUL_CHAR ENDP
;-----------------------------------------------------------------------
; This routine adds a character into the file. In insert mode, remaining
; characters are pushed forward. If the scan code for <Enter> is detected,
; a <CR><LF> pair is added as the EOL marker. If the scan code for
; <Backspace> is detected, the character to the left of the cursor is
; deleted (unless the cursor is already at the start of the file).
;-----------------------------------------------------------------------
INSERT_KEY PROC NEAR
ASSUME DS:FILE_SEG
MOV SI,CS:CURSOR
CMP CS:INSERT_MODE,1 ;in insert mode? (0=ovr,1=ins,2 or 3=RO)
JA FILE_FULL ;jump if read-only file
CMP AH,28 ;was this the <Enter> key scan code?
JE NEW_LINE ;if yes, make new line: <CR><LF>.
CMP AH,14 ;was it the <Backspace> key scan code?
JE BACK_SPACE ;if yes, delete character left.
CMP CS:INSERT_MODE,1 ;in insert mode? (0=ovr,1=ins,2 or 3=RO)
JE INSERT_CHAR ;jump if Insert
;-----------------------
; test for overstrike character at end of line or file.
; if EOL or EOF, then insert rather than overstrike.
;-----------------------
CMP SI,CS:LAST_CHAR ;at end of file?
JAE INSERT_CHAR
INC SI
CMP SI,CS:LAST_CHAR ;at end of file?
DEC SI
JAE INSERT_CHAR
CMP WORD PTR [SI],CRLF ;at end of line?
JE INSERT_CHAR
OVERSTRIKE_NOT_AT_CRLF:
MOV DI,SI
PUSH AX ;save new character
XCHG DS:[SI],AL ;switch new character for old one
CALL SAVE_CHAR ;store the old character
POP AX ;get back new character
JMP SHORT ADVANCE
;---------------------------------------
INSERT_CHAR:
PUSH SI
PUSH AX ;save the new character
MOV AX,1
CALL OPEN_SPACE ;make room for it at SI
POP AX ;get back the new character
POP DI
JC FILE_FULL
STOSB ;insert character in file buffer, ES:DI
ADVANCE:
OR CS:DIRTY_BITS,4 ;current line is dirty
;-----------------------
; see if we made a CR-LF pair by adding a Ctrl-M with a Ctrl-J
;-----------------------
CALL C_IF_NEW_CRLF ;see if in middle of new CR-LF
JC FILE_FULL ;jump if new line was done
;------------------------
CMP AL,CR ;was key <Ctrl-M> - CR?
JNE INS_NOT_CR
MOV CS:DIRTY_BITS,1 ;redraw the screen (just in case EOL)
INS_NOT_CR:
;-----------------------
PUSH UNDO_LENGTH
CALL RIGHT ;move cursor to next letter
POP UNDO_LENGTH
FILE_FULL:
RET
CR_AT_EOF:
INC CS:CURSOR
RET
;---------------------------------------
; process the <Enter> key, make new line
;---------------------------------------
NEW_LINE:
PUSH SI
MOV AX,2
CALL OPEN_SPACE ;make space for CR and LF
POP DI ;get back old cursor location
JC FILE_FULL
MOV AX,CRLF ;LF*256+CR
STOSW ;store the CR and LF
JMP SHORT ADVANCE_NEW_LINE ;repaint the screen
;(CALL/RETurn)
INSERT_KEY ENDP
;---------------------------------------
; process the <Backspace> key, delete character left of cursor.
;---------------------------------------
BACK_SPACE PROC NEAR
OR SI,SI ;is cursor at start of file?
JZ FILE_FULL ;if so, no delete right
CALL LEFT ;move left one space (flush UnDo buffer)
;**follows JMP DEL_CHAR ;and delete the character (into buffer)
;(CALL/RETurn)
BACK_SPACE ENDP
;=======================================================================
; This routine deletes the character at the cursor by shifting the remaining
; characters forward. <Del> key
;-----------------------------------------------------------------------
DEL_CHAR PROC NEAR
CMP CS:INSERT_MODE,1 ;in insert mode? (0=ovr,1=ins,2 or 3=RO)
JA NO_DEL ;jump if read-only file
MOV CX,LAST_CHAR
MOV SI,CURSOR
MOV DI,SI
CMP SI,CX ;are we at end of file?
JAE NO_DEL ;if yes, then don't delete
LODSB ;loads char in AL, DS:SI
CALL SAVE_CHAR ;save it for UNDO function
MOV AH,[SI] ;look at the next character also
PUSH AX ;save character we're deleting
DEC LAST_CHAR ;shorten the file by one
SUB CX,SI
REP MOVSB ;move file down one, DS:SI to ES:DI
POP AX ;get back character we deleted
CMP AX,CRLF ;did we delete a CR?
JE COMBINE
OR DIRTY_BITS,4 ;current line is dirty
;-----------------------
; see if we made a CRLF by deleting a character.
; if we are in the middle of a CRLF, move the cursor back one.
;-----------------------
JMP SHORT C_IF_NEW_CRLF
;(CALL/RETurn) - saves a byte
;---------------------------------------
COMBINE: ;deleted an EOL marker, CR-LF
CALL DEL_CHAR ;now delete the line feed (recursive)
MOV DIRTY_BITS,3
MOV DX,CURS_POSN
MOV SAVE_COLUMN,DL ;save the cursor column
NO_DEL:
RET
DEL_CHAR ENDP
;=======================================================================
; see if we made a CR-LF pair with the cursor located on the LF character
; by joining the character (Ctrl-M) with a (Ctrl-J). If so, back up the
; cursor and open a new line and return with carry set. if not, return with
; carry clear.
;-----------------------------------------------------------------------
C_IF_NEW_CRLF PROC NEAR
MOV SI,CS:CURSOR ;present cursor location
OR SI,SI ;is it at start of file
JZ DONE_CRLF
CMP WORD PTR [SI-1],CRLF ;did we make CR-LF?
JNE DONE_CRLF
DEC CS:CURSOR ;move cursor back to point at CR code
C_IF_NEW_CRLF ENDP
;---------------------------------------
; This routine opens a new line.
;---------------------------------------
ADVANCE_NEW_LINE PROC NEAR ;split line on screen for CR-LF
CALL HOME ;cursor to start of line
CALL DOWN ;move down to the new line
MOV DIRTY_BITS,3 ;repaint the screen and cursor
STC ;C=1 if new line was done
RET
DONE_CRLF:
CLC ;C=0 if not new line
RET
ADVANCE_NEW_LINE ENDP
;=======================================================================
; This routine restores any characters which have recently been deleted.
;-----------------------------------------------------------------------
UNDO PROC NEAR
; ASSUME DS:FILE_SEG
XOR AX,AX
XCHG AX,CS:UNDO_LENGTH ;get buffer length
MOV SI,OFFSET UNDO_BUFFER
JMP INSERT_STRING
;(CALL/RETurn)
UNDO ENDP
;=======================================================================
; This routine inserts spaces into the file buffer. On entry, AX
; contains the number of spaces to be inserted. On return, CF=1 if
; there was not enough space in the file buffer.
;-----------------------------------------------------------------------
OPEN_SPACE PROC NEAR
; ASSUME DS:FILE_SEG
MOV CX,LAST_CHAR ;last character in the file
MOV SI,CX
MOV DI,CX
ADD DI,AX ;offset for new end of file
JC NO_ROOM ;if no more room, return error
MOV LAST_CHAR,DI ;save offset of end of file
SUB CX,CURSOR ;number of characters to shift
DEC DI
DEC SI
STD ;string moves goes forward
REP MOVSB ;shift the file upward
CLD
MOV BYTE PTR DIRTY_FILE,0FFH ;file has been altered
CLC
NO_ROOM: ;carry is set if no room in file
RET
OPEN_SPACE ENDP
;=======================================================================
; This routine adds a character to the UNDO buffer.
;-----------------------------------------------------------------------
SAVE_CHAR PROC NEAR
MOV BX,UNDO_LENGTH
OR BH,BH ;is buffer filled?
JNZ NO_SAVE ;buffer overflowed, no insert
INC UNDO_LENGTH
MOV BYTE PTR CS:UNDO_BUFFER[BX],AL
MOV BYTE PTR CS:DIRTY_FILE,0FFH ;file altered
NO_SAVE:
RET
SAVE_CHAR ENDP
;=======================================================================
; This routine deletes from the cursor position to the end of the line.
;-----------------------------------------------------------------------
DEL_EOL PROC NEAR
;-----------------------
; from TEDPLUS, modified by JEG, delete line if at column 1.
;**Shft-F8 MOV CX,CURSOR_POSN
;**Shft-F8 JCXZ DEL_L
;-----------------------
CMP CS:INSERT_MODE,1 ;in insert mode? (0=ovr,1=ins,2 or 3=RO)
JA NO_DEL_L ;jump if read-only file
MOV LINE_FLAG,0
PUSH CURSOR ;save starting cursor location
CALL ENDD ;move to the end of the line
POP SI ;get back starting cursor
MOV CX,CURSOR ;offset of end of line
MOV CURSOR,SI ;restore starting cursor
JMP SHORT DEL_END ;delete characters to end of line
;(CALL/RETurn)
DEL_EOL ENDP
;-----------------------------------------------------------------------
; This routine deletes a line, placing it in the line buffer. <F9>, <Shft-F8>
;-----------------------------------------------------------------------
DEL_L PROC NEAR
CMP CS:INSERT_MODE,1 ;in insert mode? (0=ovr,1=ins,2 or 3=RO)
JA NO_DEL_L ;jump if read-only file
MOV LINE_FLAG,1
CALL FIND_START ;find start of this line
MOV CURSOR,SI ;this will be the new cursor
PUSH SI ;save the cursor position
CALL FIND_NEXT ;find the next line
MOV CX,SI ;CX will hold line length
POP SI ;get back new cursor location
DEL_END:
MOV BYTE PTR DIRTY_FILE,0FFH ;file has been altered
SUB CX,SI ;number of bytes on line
OR CH,CH ;is line too long to fit?
JZ NOT_TOO_LONG
MOV CX,100H ;save only 256 characters
NOT_TOO_LONG:
MOV LINE_LENGTH,CX ;store length of deleted line
JCXZ NO_DEL_L
MOV DI,OFFSET LINE_BUFFER ;buffer for deleted line
PUSH CX
PUSH ES
PUSH CS
POP ES ;line buffer is in CSEG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -