📄 ted2.asm
字号:
RIGHT_AGAIN:
PUSH CX
;-----------------------
; (JEG)
INC SI
CMP SI,LAST_CHAR ;at end of file?
DEC SI
JAE DO_MOVE
CMP WORD PTR [SI],CRLF ;at end of line?
;-----------------------
JE DONT_MOVE ;if at end, stop moving
DO_MOVE:
CALL RIGHT ;move right one character
DONT_MOVE:
POP CX
MOV AL,SAVE_COLUMN
XOR AH,AH
CMP AX,CX ;is cursor still in margin?
JL IN_MARGIN ;if yes, keep moving
MOV DX,CURS_POSN ;get cursor column again
XOR DH,DH
CMP DX,BP ;at saved cursor position?
JE RIGHT_DONE ;if yes, we're done
JA RIGHT_TOO_FAR ;did we go too far?
IN_MARGIN:
LOOP RIGHT_AGAIN
RIGHT_DONE:
MOV CX,BP
MOV SAVE_COLUMN,CL ;get back saved cursor position
NO_CHANGE:
RET
;-----------------------
RIGHT_TOO_FAR:
CALL LEFT ;move back left one place
MOV CX,BP
MOV SAVE_COLUMN,CL ;get back saved cursor position
RET
SHIFT_RIGHT ENDP
;=======================================================================
; This routine finds the beginning of the previous line.
;-----------------------------------------------------------------------
FIND_PREVIOUS PROC NEAR
; ASSUME DS:FILE_SEG
PUSH CURSOR ;save the cursor location
CALL FIND_CR ;find the start of this line
MOV CURSOR,SI ;save the new cursor
CALL FIND_START ;find the start of this line
POP CURSOR ;get back starting cursor
RET
FIND_PREVIOUS ENDP
;=======================================================================
; This routine searches for the previous carriage return.
; Search starts at DS:SI.
;-----------------------------------------------------------------------
FIND_CR PROC NEAR
; ASSUME DS:FILE_SEG
PUSH CX
MOV AL,LF ;look for a line feed character
MOV DI,SI
MOV CX,SI
JCXZ AT_BEGINNING
DEC DI
STD ;search backwards
LF_PREV:
REPNE SCASB ;scan for the character
;-----------------------
; from TEDPLUS
JCXZ LF_END
CMP BYTE PTR [DI],CR
JNE LF_PREV
DEC DI
LF_END:
;-----------------------
CLD ;restore the direction flag
INC DI
MOV SI,DI
AT_BEGINNING:
POP CX
RET
FIND_CR ENDP
;=======================================================================
; This routine skips past the CR and LF at SI. SI returns new offset.
;-----------------------------------------------------------------------
SKIP_CR_LF PROC NEAR
; ASSUME CS:FILE_SEG
CMP SI,LAST_CHAR ;at last char in file?
JAE NO_SKIP ;if yes, don't skip anything
CMP BYTE PTR [SI],CR ;is first character a CR?
JNE NO_SKIP
INC SI ;look at next character
CMP SI,LAST_CHAR ;is it at the end of file?
JAE NO_SKIP ;if yes, don't skip anymore
CMP BYTE PTR [SI],LF ;is next character a line feed?
JNE NO_SKIP ;skip any line feeds also
INC SI
NO_SKIP:
RET
SKIP_CR_LF ENDP
;=======================================================================
; This routine computes the location of the start of current line.
; Returns SI pointing to the first character of the current line.
;-----------------------------------------------------------------------
FIND_START PROC NEAR
; ASSUME DS:FILE_SEG
MOV SI,CURSOR ;get the current cursor
OR SI,SI ;at start of file?
JZ AT_START ;if yse, we're done
CALL FIND_CR ;find the CR
CALL SKIP_CR_LF
AT_START:
RET
FIND_START ENDP
;=======================================================================
; This routine finds the offset of the start of the next line. The search
; is started at location of ES:SI. On return, CF=1 if no CR was found.
;-----------------------------------------------------------------------
FIND_NEXT PROC NEAR
; ASSUME DS:FILE_SEG
PUSH CX
CALL FIND_EOL ;find the end of this line
JC AT_NEXT ;if at end of file, return
CALL SKIP_CR_LF ;skip past CR and LF
CLC ;indicate end of line found
AT_NEXT:
POP CX
RET
FIND_NEXT ENDP
;=======================================================================
; This routine searches for the next carriage return in the file.
; The search starts at the offset in register SI.
;-----------------------------------------------------------------------
FIND_EOL PROC NEAR
; ASSUME DS:FILE_SEG
MOV AL,CR ;look for a carriage return
CR_SCAN:
MOV CX,LAST_CHAR ;last letter in the file
SUB CX,SI ;count for the search
MOV DI,SI
JCXZ AT_END ;if nothing to search, return
REPNE SCASB ;scan for the character
MOV SI,DI ;return the location of the CR
JCXZ AT_END ;if not found, return
;-----------------------
; from TEDPLUS
CMP BYTE PTR [SI],LF
JNE CR_SCAN
;-----------------------
DEC SI ;back up one, to CR character
CLC ;indicate the CR was found
RET
AT_END:
STC ;indicate CR was not found
RET
FIND_EOL ENDP
;=======================================================================
; This routine positions the screen with the cursor at the row
; selected in register DH. On entry, SI holds the cursor offset.
;-----------------------------------------------------------------------
LOCATE PROC NEAR
; ASSUME DS:FILE_SEG
MOV CL,DH
XOR CH,CH
MOV CURSOR,SI
XOR DX,DX ;start at top of screen
OR SI,SI ;at start of buffer?
JZ LOCATE_FIRST
CALL FIND_START ;get start of this row
XOR DX,DX ;start at top of screen
OR SI,SI ;is cursor at top of file?
JZ LOCATE_FIRST
JCXZ LOCATE_FIRST ;if location to top row were done
FIND_TOP:
PUSH SI
PUSH CX
CALL FIND_CR ;find previous row
POP CX
POP AX
CMP WORD PTR [SI],CRLF
JNE LOCATE_FIRST
CMP SI,AX ;did it change?
JE LOCATE_DONE ;if not, quit moving
INC DH ;cursor moves to next row
LOOP FIND_TOP
LOCATE_DONE:
PUSH CURSOR
MOV CURSOR,SI
CALL FIND_START ;find start at top of screen
POP CURSOR
LOCATE_FIRST:
MOV TOP_OF_SCREEN,SI
MOV CURS_POSN,DX
CALL CURSOR_COL
MOV SAVE_COLUMN,DL
RET
LOCATE ENDP
;=======================================================================
; This routine computes the correct column for the cursor. No inputs.
; On exit, CURS_POSN is set and DX has row/column.
;-----------------------------------------------------------------------
CURSOR_COL PROC NEAR
; ASSUME DS:FILE_SEG
MOV SI,CURSOR ;get cursor offset
CALL FIND_START ;find start of this line
MOV CX,CURSOR ;cursor location in file
SUB CX,SI
MOV DX,CURS_POSN ;get current row
XOR DL,DL ;start at column zero
MOV MARGIN_COUNT,DL ;count past the left margin
JCXZ COL_DONE
CURSOR_LOOP:
LODSB ;get the next character
INC SI
CMP SI,LAST_CHAR
DEC SI
JAE NOT_EOL ;is <CR> without <LF>, at end of file
CMP WORD PTR [SI-1],CRLF ;(JEG)
JE COL_DONE ;if at end, we're done
NOT_EOL:
CMP AL,TAB ;is it a tab?
JNE NOT_A_TAB
MOV BL,MARGIN_COUNT
OR BL,00000111B
MOV MARGIN_COUNT,BL
CMP BL,LEFT_MARGIN ;inside visible window yet?
JB NOT_A_TAB ;if not, don't advance cursor
OR DL,00000111B ;move to multiple of eight
NOT_A_TAB:
MOV BL,MARGIN_COUNT
INC BL
MOV MARGIN_COUNT,BL
CMP BL,LEFT_MARGIN
JBE OUT_OF_WINDOW
INC DL ;we're at next column now
OUT_OF_WINDOW:
LOOP CURSOR_LOOP
COL_DONE:
CMP DL,COLUMNSB ;past end of display?
JB COLUMN_OK ;if not, we're OK
MOV DL,COLUMNSB
DEC DL ;leave cursor at last column
COLUMN_OK:
MOV CURS_POSN,DX ;store at last column
RET
CURSOR_COL ENDP
;=======================================================================
; MARK, CUT, PASTE, PRINT services
;=======================================================================
; This routine toggles the mark state and resets the paste buffer pointers.
;-----------------------------------------------------------------------
MARK PROC NEAR
XOR AX,AX
NOT CS:MARK_MODE ;toggle the mode flag
CMP CS:MARK_MODE,AL ;turning mode ON?
JNE MARK_ON
OR CS:DIRTY_BITS,1 ;need to redraw the screen
MOV CS:MARK_START,0FFFFH
JMP SHORT MARK_RET
;-----------------------
MARK_ON:
MOV AX,CS:CURSOR ;get the cursor offset
MOV CS:MARK_START,AX ;start of marked range
MARK_RET:
MOV CS:MARK_END,AX ;end of marked range
MOV CS:MARK_HOME,AX ;center of marked range
RET
MARK ENDP
;=======================================================================
; This routine removes the marked text and places it in the paste buffer.
;-----------------------------------------------------------------------
CUT PROC NEAR
CMP CS:INSERT_MODE,1 ;in insert mode? (0=ovr,1=ins,2 or 3=RO)
JA NO_MARK ;jump if read-only file
CMP CS:MARK_MODE,0 ;is the mark mode on?
JE NO_MARK ;if not, then do nothing
MOV CX,CS:MARK_END ;get end of mark region
MOV SI,CS:MARK_START ;get start of mark region
SUB CX,SI ;number of bytes selected
MOV PASTE_SIZE,CX
XOR DI,DI ;point to paste buffer
PUSH CX
PUSH ES
MOV ES,CS:PASTE_SEG ;set the paste buffer segment to ES
REP MOVSB ;deleted text to buffer, DS:SI to ES:DI
POP ES
POP AX
MOV CX,CS:LAST_CHAR
SUB CS:LAST_CHAR,AX ;shorten the file this much
MOV DI,CS:MARK_START
MOV SI,CS:MARK_END
SUB CX,SI
JCXZ NO_DELETE
REP MOVSB ;shorten the file, DS:SI to ES:DI
NO_DELETE:
MOV DX,CS:CURS_POSN
MOV SI,CS:MARK_START
CALL LOCATE ;adjust the screen position
CALL MARK ;this turns off select
;-----------------------
; see if we made a CR-LF pair by cutting the character(s) from
; between a Ctrl-M and a Ctrl-J. If so, open a new line.
;-----------------------
CALL C_IF_NEW_CRLF
NO_MARK:
RET
CUT ENDP
;=======================================================================
; This routine copies the paste buffer into the file at the cursor location.
;-----------------------------------------------------------------------
PASTE PROC NEAR
MOV AX,PASTE_SIZE ;number of characters in buffer
OR AX,AX ;any there?
JZ NO_PASTE ;if not, nothing to paste
MOV SI,CURSOR ;get cursor location
PUSH AX
PUSH SI
CALL OPEN_SPACE ;make room for new characters
POP DI
POP CX
JC NO_PASTE ;if no room, just exit
XOR SI,SI ;point to start of paste buffer
PUSH DS
MOV DS,PASTE_SEG ;segment of paste buffer
REP MOVSB ;copy in the new characters
POP DS
OR DIRTY_BITS,1 ;redraw the screen
CALL C_IF_NEW_CRLF
NO_PASTE:
RET
PASTE ENDP
;=======================================================================
; This routine prints an ASCII Form-Feed character.
;-----------------------------------------------------------------------
PRINT_FF PROC NEAR
CALL MARK ;toggle MARK "on"
PUSH DS
PUSH CS
POP DS
MOV CX,1 ;one character to print
MOV SI,OFFSET FF ;offset of last byte in paste buffer
CALL DO_FF_CHAR
POP DS
RET
FF DB 12 ;the ASCII Form-Feed character
PRINT_FF ENDP
;-----------------------------------------------------------------------
; This routine prints the marked text. If printer fails, it is cancelled.
;-----------------------------------------------------------------------
PRINT PROC NEAR
CMP MARK_MODE,0 ;is mark mode on?
JE PRINT_RET ;if not, nothing to print
MOV CX,MARK_END ;end of marked region
MOV SI,MARK_START ;start of marked region
SUB CX,SI ;number of bytes selected
JCXZ PRINT_DONE ;if nothing to print, return
DO_FF_CHAR:
XOR DX,DX ;select printer 0
MOV AH,2
INT 17H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -