293 lines
9.2 KiB
NASM
293 lines
9.2 KiB
NASM
procedure $STD_CON_STRING_INPUT,NEAR ;System call 10
|
|
ASSUME DS:NOTHING,ES:NOTHING
|
|
|
|
; Inputs:
|
|
; DS:DX Point to an input buffer
|
|
; Function:
|
|
; Fill buffer from console input until CR
|
|
; Returns:
|
|
; None
|
|
|
|
MOV AX,SS
|
|
MOV ES,AX
|
|
MOV SI,DX
|
|
XOR CH,CH
|
|
LODSW
|
|
OR AL,AL
|
|
retz ;Buffer is 0 length!!?
|
|
MOV BL,AH ;Init template counter
|
|
MOV BH,CH ;Init template counter
|
|
CMP AL,BL
|
|
JBE NOEDIT ;If length of buffer inconsistent with contents
|
|
CMP BYTE PTR [BX+SI],c_CR
|
|
JZ EDITON ;If CR correctly placed EDIT is OK
|
|
NOEDIT:
|
|
MOV BL,CH ;Reset buffer
|
|
EDITON:
|
|
MOV DL,AL
|
|
DEC DX ;DL is # of bytes we can put in the buffer
|
|
NEWLIN:
|
|
MOV AL,[CARPOS]
|
|
MOV [STARTPOS],AL ;Remember position in raw buffer
|
|
PUSH SI
|
|
MOV DI,OFFSET DOSGROUP:INBUF ;Build the new line here
|
|
MOV [INSMODE],CH ;Insert mode off
|
|
MOV BH,CH ;No chars from template yet
|
|
MOV DH,CH ;No chars to new line yet
|
|
invoke $STD_CON_INPUT_NO_ECHO ;Get first char
|
|
CMP AL,c_LF ;Linefeed
|
|
JNZ GOTCH ;Filter out LF so < works
|
|
entry GETCH
|
|
invoke $STD_CON_INPUT_NO_ECHO
|
|
GOTCH:
|
|
CMP AL,"F"-"@" ;Ignore ^F
|
|
JZ GETCH
|
|
CMP AL,[ESCCHAR]
|
|
JZ ESC
|
|
CMP AL,c_DEL
|
|
JZ BACKSPJ
|
|
CMP AL,c_BS
|
|
JZ BACKSPJ
|
|
CMP AL,c_CR
|
|
JZ ENDLIN
|
|
CMP AL,c_LF
|
|
JZ PHYCRLF
|
|
CMP AL,CANCEL
|
|
JZ KILNEW
|
|
SAVCH:
|
|
CMP DH,DL
|
|
JAE BUFFUL ;No room
|
|
STOSB
|
|
INC DH ;Got a char
|
|
invoke BUFOUT ;Print control chars nicely
|
|
CMP BYTE PTR [INSMODE],0
|
|
JNZ GETCH ;In insert mode, get more chars
|
|
CMP BH,BL
|
|
JAE GETCH ;We are out of chars in template
|
|
INC SI ;Skip to next char in template
|
|
INC BH
|
|
JMP SHORT GETCH
|
|
|
|
BACKSPJ: JMP SHORT BACKSP
|
|
|
|
BUFFUL:
|
|
MOV AL,7 ;Bell
|
|
invoke OUT
|
|
JMP SHORT GETCH
|
|
|
|
ESC:
|
|
transfer OEMFunctionKey
|
|
|
|
ENDLIN:
|
|
STOSB ;Put the CR in the buffer
|
|
invoke OUT ;Echo it
|
|
POP DI ;Get start of buffer
|
|
MOV [DI-1],DH ;Tell user how many bytes
|
|
INC DH ;DH is length including CR
|
|
COPYNEW:
|
|
MOV BP,ES ;XCHG ES,DS
|
|
MOV BX,DS
|
|
MOV ES,BX
|
|
MOV DS,BP
|
|
MOV SI,OFFSET DOSGROUP:INBUF
|
|
MOV CL,DH
|
|
REP MOVSB ;Copy final line to user buffer
|
|
return ;All done
|
|
|
|
;Output a CRLF
|
|
entry CRLF
|
|
MOV AL,c_CR
|
|
invoke OUT
|
|
MOV AL,c_LF
|
|
JMP OUT
|
|
|
|
;Output a CRLF which is not terminate buffer
|
|
PHYCRLF:
|
|
invoke CRLF
|
|
JMP GETCH
|
|
|
|
;Zap the line without zapping the template
|
|
entry KILNEW
|
|
MOV AL,"\"
|
|
invoke OUT ;Print the CANCEL indicator
|
|
POP SI ;Remember start of edit buffer
|
|
PUTNEW:
|
|
invoke CRLF ;Go to next line on screen
|
|
MOV AL,[STARTPOS]
|
|
invoke TAB ;Tab over
|
|
JMP NEWLIN ;Start over again
|
|
|
|
;Back up one char
|
|
entry BACKSP
|
|
OR DH,DH
|
|
JZ OLDBAK ;No chars in line, do nothing to line
|
|
CALL BACKUP ;Do the backup
|
|
MOV AL,ES:[DI] ;Get the deleted char
|
|
CMP AL," "
|
|
JAE OLDBAK ;Was a normal char
|
|
CMP AL,c_HT
|
|
JZ BAKTAB ;Was a tab, fix up users display
|
|
CALL BACKMES ;Was a control char, zap the '^'
|
|
OLDBAK:
|
|
CMP BYTE PTR [INSMODE],0
|
|
JNZ GETCH1 ;In insert mode, get more chars
|
|
OR BH,BH
|
|
JZ GETCH1 ;Not advanced in template, stay where we are
|
|
DEC BH ;Go back in template
|
|
DEC SI
|
|
GETCH1:
|
|
JMP GETCH
|
|
|
|
BAKTAB:
|
|
PUSH DI
|
|
DEC DI ;Back up one char
|
|
STD ;Go backward
|
|
MOV CL,DH ;Number of chars currently in line
|
|
MOV AL," "
|
|
PUSH BX
|
|
MOV BL,7 ;Max
|
|
JCXZ FIGTAB ;At start, do nothing
|
|
FNDPOS:
|
|
SCASB ;Look back
|
|
JNA CHKCNT
|
|
CMP BYTE PTR ES:[DI+1],9
|
|
JZ HAVTAB ;Found a tab
|
|
DEC BL ;Back one char if non tab control char
|
|
CHKCNT:
|
|
LOOP FNDPOS
|
|
FIGTAB:
|
|
SUB BL,[STARTPOS]
|
|
HAVTAB:
|
|
SUB BL,DH
|
|
ADD CL,BL
|
|
AND CL,7 ;CX has correct number to erase
|
|
CLD ;Back to normal
|
|
POP BX
|
|
POP DI
|
|
JZ OLDBAK ;Nothing to erase
|
|
TABBAK:
|
|
invoke BACKMES
|
|
LOOP TABBAK ;Erase correct number of chars
|
|
JMP SHORT OLDBAK
|
|
|
|
BACKUP:
|
|
DEC DH ;Back up in line
|
|
DEC DI
|
|
BACKMES:
|
|
MOV AL,c_BS ;Backspace
|
|
invoke OUT
|
|
MOV AL," " ;Erase
|
|
invoke OUT
|
|
MOV AL,c_BS ;Backspace
|
|
JMP OUT ;Done
|
|
|
|
;User really wants an ESC character in his line
|
|
entry TwoEsc
|
|
MOV AL,[ESCCHAR]
|
|
JMP SAVCH
|
|
|
|
;Copy the rest of the template
|
|
entry COPYLIN
|
|
MOV CL,BL ;Total size of template
|
|
SUB CL,BH ;Minus position in template, is number to move
|
|
JMP SHORT COPYEACH
|
|
|
|
entry CopyStr
|
|
invoke FINDOLD ;Find the char
|
|
JMP SHORT COPYEACH ;Copy up to it
|
|
|
|
;Copy one char from template to line
|
|
entry COPYONE
|
|
MOV CL,1
|
|
;Copy CX chars from template to line
|
|
COPYEACH:
|
|
MOV BYTE PTR [INSMODE],0 ;All copies turn off insert mode
|
|
CMP DH,DL
|
|
JZ GETCH2 ;At end of line, can't do anything
|
|
CMP BH,BL
|
|
JZ GETCH2 ;At end of template, can't do anything
|
|
LODSB
|
|
STOSB
|
|
invoke BUFOUT
|
|
INC BH ;Ahead in template
|
|
INC DH ;Ahead in line
|
|
LOOP COPYEACH
|
|
GETCH2:
|
|
JMP GETCH
|
|
|
|
;Skip one char in template
|
|
entry SKIPONE
|
|
CMP BH,BL
|
|
JZ GETCH2 ;At end of template
|
|
INC BH ;Ahead in template
|
|
INC SI
|
|
JMP GETCH
|
|
|
|
entry SKIPSTR
|
|
invoke FINDOLD ;Find out how far to go
|
|
ADD SI,CX ;Go there
|
|
ADD BH,CL
|
|
JMP GETCH
|
|
|
|
;Get the next user char, and look ahead in template for a match
|
|
;CX indicates how many chars to skip to get there on output
|
|
;NOTE: WARNING: If the operation cannot be done, the return
|
|
; address is popped off and a jump to GETCH is taken.
|
|
; Make sure nothing extra on stack when this routine
|
|
; is called!!! (no PUSHes before calling it).
|
|
FINDOLD:
|
|
invoke $STD_CON_INPUT_NO_ECHO
|
|
CMP AL,[ESCCHAR] ; did he type a function key?
|
|
JNZ FindSetup ; no, set up for scan
|
|
invoke $STD_CON_INPUT_NO_ECHO ; eat next char
|
|
JMP NotFnd ; go try again
|
|
FindSetup:
|
|
MOV CL,BL
|
|
SUB CL,BH ;CX is number of chars to end of template
|
|
JZ NOTFND ;At end of template
|
|
DEC CX ;Cannot point past end, limit search
|
|
JZ NOTFND ;If only one char in template, forget it
|
|
PUSH ES
|
|
PUSH DS
|
|
POP ES
|
|
PUSH DI
|
|
MOV DI,SI ;Template to ES:DI
|
|
INC DI
|
|
REPNE SCASB ;Look
|
|
POP DI
|
|
POP ES
|
|
JNZ NOTFND ;Didn't find the char
|
|
NOT CL ;Turn how far to go into how far we went
|
|
ADD CL,BL ;Add size of template
|
|
SUB CL,BH ;Subtract current pos, result distance to skip
|
|
return
|
|
|
|
NOTFND:
|
|
POP BP ;Chuck return address
|
|
JMP GETCH
|
|
|
|
entry REEDIT
|
|
MOV AL,"@" ;Output re-edit character
|
|
invoke OUT
|
|
POP DI
|
|
PUSH DI
|
|
PUSH ES
|
|
PUSH DS
|
|
invoke COPYNEW ;Copy current line into template
|
|
POP DS
|
|
POP ES
|
|
POP SI
|
|
MOV BL,DH ;Size of line is new size template
|
|
JMP PUTNEW ;Start over again
|
|
|
|
entry EXITINS
|
|
entry ENTERINS
|
|
NOT BYTE PTR [INSMODE]
|
|
JMP GETCH
|
|
|
|
;Put a real live ^Z in the buffer (embedded)
|
|
entry CTRLZ
|
|
MOV AL,"Z"-"@"
|
|
JMP SAVCH
|
|
$STD_CON_STRING_INPUT ENDP
|