📄 gwlin.asm
字号:
TITLE GWLIN - read and edit line from keyboard
;***
; GWLIN - read and edit line from keyboard
;
; Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
;
;******************************************************************************
;
; * entry point: B$RDLIN
;
; * returns string in b$Buf1
; * byte vector up to length of 255
; * zero-byte terminated
;
; * both ASCII and KANJI versions on switch FK_KANJI
;
;-------------------------------------------------------------------
;
; Data structures used:
;
; * b$INBUF - byte vector of length 256
; * contains ASCII/KANJI values of present state
; of string entered
; * end-of-line (EOL) indication is 0 value
;
; * XBLTAB - word vector of length 8 (KANJI only)
; * entries, if any, defined up to index XBLNXT
; * entry contains b$INBUF location of KANJI character
; where an extra blank had to be inserted on the
; display screen to prevent splitting the KANJI
; character across rows.
;
;------------------------------------------------------------------
;
; Editting functions supported:
;
; * ^B - move cursor back one word
; * ^C - exit program
; * ^E - truncate line at cursor
; * ^F - move cursor forward one word
; * ^H - delete character left of cursor
; * ^I - insert/overwrite to next tab field of length 8
; * ^K - move cursor to beginning of line
; * ^M - (carriage return) return string to program
; * ^N - move cursor to end of line
; * ^R - toggle between insertion and overwriting
; * ^T - toggle function key label display
; * ^U - erase line
; * ^\ - (left cursor) move cursor left once
; * ^] - (right cursor) move cursor right once
; * DEL - delete character over cursor
;==================================================================
; ASCII character definitions
CTL_B=002D ;^B - control B
CTL_C=003D ;^C - control C
CTL_E=005D ;^E - control E
CTL_F=006D ;^F - control F
CTL_G=007D ;^G - control G (BELL)
CTL_H=008D ;^H - control H (backspace)
CTL_I=009D ;^I - control I (TAB)
CTL_J=010D ;^J - control J (line feed)
CTL_K=011D ;^K - control K
CTL_M=013D ;^M - control M (carriage return)
CTL_N=014D ;^N - control N
CTL_R=018D ;^R - control R (insert map)
CTL_T=020D ;^T - control T
CTL_U=021D ;^U - control U (ESC map)
CTL_BS=028D ;^\ - control \ (right arrow map)
CTL_RB=029D ;^] - control ] (left arrow map)
ASC_SP=032D ;ASCII space
ASC_DL=127D ;ASCII DEL (delete map)
; Standard MS Keyboard codes (have FF as high byte)
CNTL=0FFh ; Must be sent in front of control chars
; other definitions
.XLIST
INCLUDE switch.inc
INCLUDE rmacros.inc
USESEG _DATA
USESEG CONST
USESEG _BSS
USESEG CN_TEXT
INCLUDE seg.inc
INCLUDE dc.inc
INCLUDE messages.inc ; MS message
INCLUDE const.inc
.LIST
BUFLEN=255D ;length of b$INBUF
.SALL ;suppress macro expansion
sBegin _DATA
externW b$CRTWIDTH ; width of display screen
externW b$CURSOR ; (1,1)-relative screen cursor
externB b$IOFLAG ; Misc. IO flags. Defined in GWINI.ASM
sEnd _DATA
sBegin CONST
globalB b$EightSpaces,' ',8 ; string of eight spaces (for TAB)
sEnd CONST
sBegin _BSS
externB b$Buf1 ; defined in GWINI.ASM
b$INBUF EQU b$Buf1 ; (use b$Buf1 and b$Buf2)
staticW CSRPTR,,1 ;b$INBUF index to input cursor
staticW EOLPTR,,1 ;b$INBUF index to input end-of-line
staticW UPDPTR,,1 ;b$INBUF index to start of update
staticW CSRLOC,,1 ;display column of cursor
staticW EOLLOC,,1 ;display column of end-of-line
staticB INSFLG,,1 ;0=overwrite mode, 0FFH=insert mode
staticB ENDFLG,,1 ;0=process another char, 0FFH=done
INPLEN=16D ;length of input string for insert
externB b$Buf3 ; defined in GWINI.ASM
INPSTR EQU b$Buf3 ; string of bytes for character insert
sEnd _BSS
sBegin CN_TEXT
assumes CS,CN_TEXT
externNP B$TTYGetChar ; Wait for keyboard character, checking for
; ^BREAK
externNP B$TTYST ;determines if character input pending
externNP B$BREAK
externNP B$TTY_SOUT ;output character in AL to screen
externNP B$STDGET ; input char from keyboard or redir input
externNP B$ERR_RPE ; INPUT PAST END error
externNP B$BREAK_CHK ;check for break character entered
externNP B$SCRN_GPOS ; get screen cursor position
externNP B$SCNLOC ; update cursor position and variables
externNP B$EDTMAP ;OEM mapping for keyboard characters
externNP B$LABELK ;toggle function label display
externNP B$OFFCSR ; off cursor
externNP B$INSCSR ; insert mode cursor
externNP B$OVWCSR ; overwrite mode cursor
externNP B$USRCSR ; user cursor
externNP B$BLEEP ; sound bell on display
; TABLE macro to define entries in CTLTAB
TABLE MACRO FCODE,FADDR
DB FCODE
DW FADDR
ENDM TABLE
; CTLTAB definition for control character processing
CTLTAB:
TABLE CTL_B,BAKWRD ;move cursor backward one word
TABLE CTL_C,BREAK ;exit from BASCOM program
TABLE CTL_E,TRUNC ;truncate input line at cursor
TABLE CTL_F,FORWRD ;move cursor forward one word
TABLE CTL_J,IGNORE ; process LF (follows CR in redirected input)
TABLE CTL_K,BEGIN ;move cursor to line beginning
TABLE CTL_M,ENDLIN ;process CR to end line input
TABLE CTL_N,APPEND ;move cursor to end of input line
TABLE CTL_U,ERASE ;erase entire input line
TABLE CTL_BS,CSRRGT ;move cursor once to the right
TABLE CTL_RB,CSRLFT ;move cursor once to the left
; the above functions set INSFLG=0
CTLINS:
TABLE CTL_H,DELLFT ;delete character left of cursor
TABLE CTL_I,TABCHR ;process TAB printing character
TABLE CTL_R,TOGINS ;toggle insert/overwrite mode
TABLE CTL_T,B$LABELK ;toggle key label display
TABLE ASC_DL,DELCSR ;delete character on cursor
CTLEND: ;end of CTLTAB
page
;***
; B$RDLIN -- Read a line of input.
;
;Purpose:
;
;Entry:
; Caller should hold (and subsequently release) b$Buf1 & b$Buf2
;Exit:
; b$Buf1 (+ b$Buf2) contains the data input.
;Uses:
; None
;Preserves:
; All
;Exceptions:
;
;******************************************************************************
cProc B$RDLIN,<NEAR,PUBLIC>,<AX,BX,CX,DX,ES>
cBegin
; initialization
PUSH DS ; set ES=DS
POP ES
XOR BX,BX ;clear BX for use as zero
MOV CSRPTR,BX ;cursor at start of input line
MOV EOLPTR,BX ;input line starts out null
MOV INSFLG,BL ;start with overwrite mode
MOV ENDFLG,BL ;input line is starting, not ending
MOV b$INBUF,BL ;clear EOL position of b$INBUF
OR b$IOFLAG,(F_EDIT OR IN_INPUT) ; Disable $PRTMAP
; and tell B$TTY_SOUT not to echo to stdout
; until final dump of edited buffer.
CALL FRCLIN ;force new line if cursor stuck
CALL OFFCSR ;turn off cursor
;********************************************************************
; start of main program loop
;********************************************************************
; get next keyboard character
; if PSW.Z=1, then ignore the character
; if PSW.C=0, then character is ASCII in AL
NXTCHR:
; Update the state of the BIOS Insert bit to correspond to
; the current state of our Insert flag. This allows programs
; that depend on this bit (i.e. screen readers for the blind)
; to work properly.
push es
push ax
push bx
xor bx, bx
mov es, bx ;prepare ES for accessing BIOS
cli ;No interrupts while munging Keyboard flags
mov al, es:[417h] ;get current shift states
and al, 7fh ;assume insert mode off
cmp INSFLG, bl ;is insert mode off
je @F ;brif so, assumption correct
or al, 80h ;otherwise, set insert mode on
@@:
mov es:[417h], al ;tell the BIOS of the change
sti ;allow interrupts again.
pop bx ;Restore previous registers
pop ax
pop es
CALL FRCSTR ;force output if no char pending
CALL GETCHR ;get the next character
JNZ NXTCH1 ;jump if input is legal
CALL BADCHR ;process illegal character
JMP SHORT NXTCHR ;and try for the next character
; if one-byte character, process as ASCII printing code
NXTCH1:
JC NXTCH2 ;jump if two-byte character
NXTCH1A:
CALL ASCCHR ;process as ASCII if carry clear
JMP SHORT NXTCHR ;and process the next character
; two-byte character - test for function key code
NXTCH2:
CMP AH,080H ;test if function key code
JNE NXTCH3 ;if not, then jump
CMP AL,080H ;test for 8080H -> 80H byte
JE NXTCH1A ;if so, then just print it
CALL FKYCHR ;process function key
JMP SHORT NXTCHR ;and process the next character
; test for control character code
NXTCH3:
CMP AH,0FFH ;test if control character
JNE NXTCHR ; brif not -- process next char
CMP AL,010H ;test for FF10H -> FEH
JNE NXTCH3A ;if not, then jump
MOV AL,0FEH ;force in mapped character
JMP SHORT NXTCH1A ;jump to print character
NXTCH3A:
CMP AL,0FFH ;test for FFFFH -> FFH
JE NXTCH1A ;if so, then print character
CALL CTLCHR ;process control character in AL
; test if input line is finished - if so, leave module
TEST ENDFLG,0FFH ;test if input line has ended
JNZ RDEXIT ;if so, jump to exit the module
JMP SHORT NXTCHR ;jump to process the next char
RDEXIT:
CALL USRCSR ;turn on user cursor
cEnd ; restore registers and return to caller
page
;********************************************************************
; GETCHR - get keyboard character - remove 3-byte codes
;********************************************************************
; Note that the interpreter does character mapping on ouput only.
; Either B$EDTMAP and $PRTMAP is called when a character is printed
; on the screen, depending on whether in edit mode or not.
; The compiler, not having a full screen editor, only needs B$EDTMAP
; during the INPUT statement. So edit character mapping is done on the
; keyboard input, and print mapping is done on screen output. Since
; characters echoed from here have already been mapped, they must not
; be mapped in B$TTY_SOUT also, so F_EDIT [13] is set to nonzero on entry
; to B$RDLIN and cleared on the only three exits through ENDLIN, BREAK,
; and end of redirected IO.
GETCHR:
; PUSH DX ;save register on the stack
CALL ONCSR ;turn on cursor for input
test b$IOFLAG,RED_INP ; input redirected?
jz noredir
call B$STDGET ; read char from standard input
jnz redir
; End of redirected input seen, flush input buffer and exit
AND b$IOFLAG,NOT (F_EDIT OR IN_INPUT) ; Re-enable $PRTMAP
; Exiting INPUT statement
CALL APPEND ; move cursor to end of line
JMP B$ERR_RPE ; jump to "INPUT PAST END" error
noredir:
MOV DL,1 ;Check for events while waiting
CALL B$TTYGetChar ;get character from keyboard
redir:
cCALL B$EDTMAP ;map to OEM specifications
PUSHF ;save flags on stack
CALL OFFCSR ;turn off cursor
; if 3-byte code (AL=254D), clear AX to ignore character
CMP AL,254D ;is this a 3-byte code?
JNE GETCH1 ;if not, then branch
POPF ;restore flags (and stack)
XOR AX,AX ;clear AX to be ignored
; POP DX ;restore register from stack
RET ;and return to caller
; not 3-byte code, just return AX to caller
GETCH1:
POPF ;restore flags
; POP DX ;restore register from stack
RET ;and return to caller
;********************************************************************
; EDTSTR - edit string in INPSTR into input buffer
;********************************************************************
EDTSTR:
PUSH CX ;save registers on stack
PUSH SI
MOV CX,BX ;get length of INPSTR in bytes
JCXZ EDTST1 ;if null, then just exit
MOV SI,OFFSET DGROUP:INPSTR ;get offset of string
CALL PRTCHR ;insert/overwrite string in b$INBUF
XOR BX,BX ;done - reset INPSTR pointer
EDTST1:
POP SI ;restore registers from stack
POP CX
RET ;return to caller
;********************************************************************
; ONCSR - turn on appropriate cursor
;********************************************************************
ONCSR:
TEST INSFLG,0FFH ;is insert mode active?
JNZ INSCSR ; brif so (returns to caller)
JMP SHORT OVRCSR ; otherwise, turn on overwrite cursor
; and return to caller
;********************************************************************
; OFFCSR - turn off cursor
; INSCSR - turn on insert cursor (half-height)
; OVRCSR - turn on overwrite cursor
; USRCSR - turn on user cursor
;********************************************************************
OFFCSR:
PUSH AX ;save register on stack
MOV AX,OFFSET CS:B$OFFCSR ; turns off cursor
JMP SHORT CHGCSR ;jump to common code
INSCSR:
PUSH AX ;save register on stack
MOV AX,OFFSET CS:B$INSCSR ; displays insert cursor
JMP SHORT CHGCSR ;jump to common code
OVRCSR:
PUSH AX ;save register on stack
MOV AX,OFFSET CS:B$OVWCSR ; displays overwrite cursor
JMP SHORT CHGCSR ;jump to common code
USRCSR:
PUSH AX ;save register on stack
MOV AX,OFFSET CS:B$USRCSR ; displays user cursor
CHGCSR:
PUSH DX ;save register on stack
MOV DL,b$IOFLAG
AND DL,RED_INP OR RED_OUT ; redirected input and output?
CMP DL,RED_INP OR RED_OUT
JZ NO_CURSOR ; brif so -- don't touch cursor
MOV DX,b$CURSOR ; get cursor position
CALL AX ; call appropriate cursor display routine
NO_CURSOR:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -