;-----------------------------
;Input.asm - by James Vahn
; Gets a line of input from the keyboard
cseg segment
assume cs:cseg,ds:cseg
org 100h
Begin:
mov ax,3 ;Clear the screen
int 10h
mov dx,offset hello ;Brag. ;-)
mov ah,9
int 21h
Demo: mov ah,1 ;Turn INSert mode on.
mov cx,0D0Ah
int 10h
mov bx,offset msg ;Point to default string.
mov cx,10 ;Ten characters maximum
mov dx,0500h ;Line 5, column 0
call input
cmp ax,4800h ;Cursor up.
je up
cmp ax,5000h ;Cursor down.
je dn
mov bx,cx ;$ terminate ASCIIZ.
mov [msg+bx],'$'
mov dx,offset crlf ;Print it to the screen.
mov ah,9
int 21h
int 20h ;Did it work??? 8-)
up: mov dx,offset info1 ;Print cursor up message.
mov ah,9
int 21h
jmp Demo
dn: mov dx,offset info2 ;Print cursor down message.
mov ah,9
int 21h
jmp Demo
crlf db 13,10
msg db 'test',0,0,0,0,0,0,0 ;Succesful input returned here.
info1 db 13,10,'up $'
info2 db 13,10,'down$'
hello db 'Supporting left, right, up, down, backspace, insert, delete and ESC.'
db 13,10,'Up & down update the buffer, ESC aborts, Enter completes.'
db 13,10,'If the first key in the overstrike mode (small cursor), non-editing keys'
db 13,10,'will clear the line.$'
;*************************************
ASCIIZ db 80 dup (255) ;Buffer, max 256(?) bytes.
IpSto dw 0 ;Counter storage.
Home dw 0 ;Cursor home
Char dw 0 ;Character entered.
InTmp db 0 ;Number of chars entered.
Input PROC NEAR
;This gets gets data from the keyboard, printing to the screen with
;DL,DH holding the desired cursor location. CX holds the maximum
;character count and BX points to the default buffer. DS=ES=CS
;CX returns the actual character count, the string is returned in the
;default buffer and AX is returns the character.
;
;Input.Asm by James Vahn 1994
push bx ;Save offset into buffer.
stc ;Set carry to print default.
pushf ;Save the flags.
mov si,bx ;Point SI to the default string.
mov IpSto,cx ;Save 'max' counter.
mov di,offset ASCIIZ ;Point DI to temp buffer.
push di ;Save it.
inc cx ;Add 1 to the counter.
mov al,0 ;A null byte.
rep stosb ;Clear the ASCIIZ buffer.
mov InTmp,al ;Clear the counter.
pop di ;Get our pointer back.
mov ah,0Fh ;Get current page into
int 10h ; BX for these BIOS calls.
mov Home,dx ;Save cursor starting point.
mov ah,2 ;Position the cursor to
int 10h ; location in DL,DH.
cld ;Loops increment DI,SI.
ip1: popf ;Check if there is a default
pushf ; string to print.
jnc ip5 ;No default string.
mov InTmp,0 ;No chars from keyboard yet.
lodsb ;Get character from default.
cmp al,0 ;Is it a terminater?
jne ip6 ;Nope.
popf ;Pull flags and clear the
clc ; carry so we won't print
pushf ; any more of the default.
ip5: mov ah,0 ;Get input from user
int 16h ; via BIOS 16/0.
mov Char,ax
ip6: cmp ax,4B00h ;Left cursor.
jne ip10
jmp Lft
ip10: cmp ax,4D00h ;Right cursor.
jne ip9
jmp Rt
ip9: cmp ax,5300h ;DEL button.
jne ip11
jmp DEL
ip11: cmp ax,5200h ;Toggle INS mode.
jne ip12
jmp INSrt
ip12: cmp ax,4700h ;Home key.
jne ip13
jmp HomeKey
ip13: cmp ax,4F00h ;End key.
jne ip14
jmp EndKey
ip14: cmp al,27 ;Escape key pressed,
jne ip15 ; abort the entry and set
stc ; the carry. Exit.
jmp ip2
ip15: cmp al,13 ;Entry complete, user
jne ip16 ; pressed ENTER.
jmp ip2
ip16: cmp ax,4800h ;Cursor up. Done.
jne ip17
jmp ip2
ip17: cmp ax,5000h ;Cursor down. Done.
jne ip18
jmp ip2
ip18: cmp al,8 ;Was it a backspace?
jne ip19
jmp InBS ;Execute backspace routine.
ip19: ;Chain more key tests here.
ip3: cmp al,' ' ;Nothing less than a space.
jnl ip35
jmp ip1
ip35: cmp al,'~' ;Nothing more than a tilde.
jng ip36
jmp ip1
ip36: mov dx,IpSto ;Test for max # of chars
add dx,offset ASCIIZ ; by comparing DI to the
inc di ; 'max' in IpSto.
cmp di,dx
jle ip4 ;Not yet, continue.
dec di ;Decrease ASCIIZ pointer
mov ax,0E07h ; and BEEP, telling user
int 10h ; the line limit has been
jmp ip1 ; reached.
ip4:
push ax ;Save the character.
cmp InTmp,0 ;Test for first character.
jne btOkay ;Nope, skip this line clear.
mov ah,3 ;Get cursor size via
int 10h ; BIOS 10/3.
test cl,4 ;Test cursor size..
jz btOkay ;If large, then jump. If
mov dx,Home ; small and this is the
mov ah,2 ; first character, then
int 10h ; clear the line.
mov ah,0Ah ;Erase the screen line with
mov al,' ' ; the number of spaces in
mov cx,IpSto ; IpSto via BIOS 10/0A.
int 10h
mov dx,Home ;Move the cursor home
mov ah,2 ; via BIOS 10/2.
int 10h
mov di,offset ASCIIZ ;Reset the pointer to
mov word ptr[di],0 ; ASCIIZ and zero it.
inc di ;Setup the pointer to continue.
btOkay: pop ax ;Restore the character.
call pushrt ;Push all chars right.
dec di ;Move the pointer back one.
stosb ;Store character in buffer
inc InTmp ;Increment number of chars.
mov ah,0Ah ;Send the single character
mov cx,1 ; to the screen via
int 10h ; BIOS 10/0A.
mov ah,3 ;Get current cursor position
int 10h ; via BIOS 10/3.
inc dl ;Advance cursor position
mov ah,2 ; via BIOS 10/2.
int 10h
jmp ip1 ;Go get more input.
ip2: pop bp ;Clear stack.
mov ah,1 ;Restore cursor size
mov cx,0607h ; via BIOS 10/1.
int 10h
pop di ;Pointer to default buffer.
mov si,offset ASCIIZ ;Finish and return.
mov cx,0 ;Zero CX, maintain carry.
jc ESCout ;If carry set, then abort.
ip7: lodsb ;Load AL from ASCIIZ, move to
stosb ; default buffer and increment
inc cx ; CX until zero found.
cmp al,0 ; CX holds character count.
jne ip7
mov ax,Char ;AX holds the character.
ret ;End of Input, return.
ESCout: mov si,di ;SI is default buffer.
ESC1: lodsb ;Load AL from buffer, increment
inc cx ; CX until zero found.
cmp al,0 ; CX holds character count.
jne ESC1
mov ax,Char ;AX hold the character.
ret ;Abort Input, return.
;---------------------------------------------------
;Destructive backspace routine. Character #8.
InBS: cmp di,offset ASCIIZ ;Test for start of line.
je InBS2 ;Yes, ignore backspace.
push di ;Save current destination.
mov si,di ;Copy destination to source
dec di ; and subtract one.
mov ah,3 ;Read cursor position.
int 10h
dec dl ;Backup cursor one place
push dx ; and save new location.
mov ah,2 ;Set new position via
int 10h ; BIOS 10/2.
call DrLft ;Drag string to the left.
pop dx ;Put cursor at new location
mov ah,2 ; via BIOS 10/2.
int 10h
pop di ;Get original destination
dec di ; to ASCIIZ and decrement.
InBS2:inc InTmp ;Increment keystroke counter.
jmp ip1 ;Backspace completed.
;---------------------------------------------------
;DEL key routine. Character #5300.
DEL: cmp di,offset ASCIIZ - 1 ;Test for start of line.
je DEL2 ;Yes, ignore backspace.
push di ;Save current destination.
mov si,di ;Copy destination to source
inc si ; and increase source.
mov ah,3 ;Read cursor position
int 10h ; and save location.
push dx
call DrLft ;Drag string to the left.
pop dx ;Put cursor at original
mov ah,2 ; location via BIOS 10/2.
int 10h
pop di ;Get original buffer position.
DEL2: inc InTmp ;Increment keystroke counter.
jmp ip1 ;Delete completed.
;---------------------------------------------------
;Left cursor routine. Character #4B00
Lft: cmp di,offset ASCIIZ ;Test for start of line.
je lft1 ;Yes, ignore.
mov ah,3 ;Read cursor position
int 10h ; via BIOS 10/3.
dec dl ;Move cursor back one place
mov ah,2 ; via BIOS 10/2.
int 10h
dec di
lft1: inc InTmp ;Increment keystroke counter.
jmp ip1 ;Completed.
;---------------------------------------------------
;Right cursor routine. Character #4D00
Rt: mov dx,IpSto ;Test for max # of chars
add dx,offset ASCIIZ ; by comparing DI to the
cmp di,dx ; 'max' in IpSto.
je rt1
cmp byte ptr[di],0 ;Don't move beyond data
je rt1 ; in buffer.
mov ah,3 ;Read cursor position
int 10h ; via BIOS 10/3.
inc di
inc dl ;Move cursor foward one place
mov ah,2 ; via BIOS 10/2.
int 10h
rt1: inc InTmp ;Increment keystroke counter.
jmp ip1 ;Completed.
;---------------------------------------------------
;Routine to drag string left.
DrLft: lodsb ;Load AL from ASCIIZ and
stosb ; move it back one place.
cmp al,0 ;If it was a zero, exit
je DrLft2 ; this loop and finish.
mov ah,0Ah ;Print it to the screen
mov cx,1 ; via BIOS 10/0A.
int 10h
inc dl ;Advance the cursor one place
mov ah,2 ; for the next character
int 10h ; via BIOS 10/2.
jmp DrLft ;Do the entire line.
DrLft2: mov al,' ' ;Erase last character under
mov ah,0Ah ; cursor by printing a space
mov cx,1 ; via BIOS 10/1.
int 10h
inc InTmp ;Increment keystroke counter.
ret
;---------------------------------------------------
;Routine to toggle INSert mode.
INSrt: mov ah,3 ;Read cursor size
int 10h ; via BIOS 10/3 and
xor cl,4 ; toggle bit 4.
mov ah,1 ;Set new cursor size
int 10h ; via BIOS 10/1 and
jmp ip1 ; jump to entry.
;---------------------------------------------------
; Routine to shift right, inserting text if required.
PushRt:
push ax ;Save our input byte.
push di ;Save the buffer pointer.
push si ;Save another buffer pointer.
mov ah,3 ;Get cursor location
int 10h ; via BIOS 10/3 and
push dx ; save it.
dec di ;Point to last character
mov si,di ; and setup SI.
sub cx,cx ;Zero CX.
pr1: lodsb ;Get a character from the
inc cx ; buffer and increment CX.
cmp al,0 ;Is this the end?
jne pr1 ;Nope, get another.
push dx ;Save the cursor locations.
push cx ;Save the # of chars to move.
push si ;Save buffer pointer.
pr6: mov ah,3 ;Get cursor size via
int 10h ; BIOS 10/3 and test bit 4
and cl,4 ; to see if in insert mode.
je pr8 ;Yes, shift all characters.
pop si ;No, restore registers and
pop cx ; prepare to return to caller.
pop dx
jmp pr4
pr8: mov si,offset ASCIIZ ;Point to start of buffer.
sub cx,cx ;Zero CX.
pr5: lodsb ;Get a byte from the buffer.
inc cx ;Increment our counter.
cmp al,0 ;Is it a zero?
jne pr5 ;Nope, try more.
mov dx,IpSto ;Test for max # of chars.
cmp cx,dx ;Compare.
jle pr7 ;Not yet, continue.
mov ax,0E07h ;BEEP, telling user the
int 10h ; line limit has been reached.
pop si ; Restore registers
pop cx ; and cleanup stack.
pop dx
pop dx
pop si
pop di
dec di
pop ax
pop bp ;Dummy to clean stack.
jmp ip1 ;Re-enter input.
pr7: pop si ;Point to buffer.
pop cx ;Restore # of chars to move.
pop dx ;Restore cursor location.
mov di,si ;DI points one place right.
dec si ;Back SI one place.
std ;Decrement direction counter.
rep movsb ;Move string right.
cld ;Reset direction counter.
inc si ;Point SI at previous data
pr3: ; in the new location.
lodsb ;Get a byte from SI into AL.
cmp al,0 ;Is it a zero?
je pr4 ;Yes, end of string.
mov ah,0Ah ;Print it to the screen
mov cx,1 ; via BIOS 10/0A.
int 10h
inc dl ;Advance the cursor one place
mov ah,2 ; for the next character
int 10h ; via BIOS 10/2.
jmp pr3 ;Get another byte to print.
pr4:
pop dx ;Restore cursor location
mov ah,2 ; back to original via
int 10h ; BIOS 10/2.
pop si ;Restore buffer pointer.
pop di ;Restore another buffer pointer.
pop ax ;Restore our character.
ret ;Return to caller.
;---------------------------------------------------
; Routine to move to home posistion.
HomeKey:
mov dx,Home ;Move cursor to start
mov ah,2 ; of the line via
int 10h ; BIOS 10/2.
mov di,offset ASCIIZ ;Set pointer to start of buffer.
inc InTmp ;Increment keystroke counter.
jmp ip1 ;Re-enter loop.
;---------------------------------------------------
; Routine to move to end posistion.
EndKey:
mov si,offset ASCIIZ ;Point to start of buffer.
sub cx,cx ;Zero CX.
ek1: lodsb ;Get a byte from the buffer.
inc cx ;Increment our counter.
cmp al,0 ;Is it a zero?
jne ek1 ;Nope, try more.
dec si ;Found end, decrease SI
mov di,si ; and move it to DI, our
mov dx,si ; current pointer.
sub dx,offset ASCIIZ ;Calculate cursor location
add dx,Home ; and move it there via
mov ah,2 ; BIOS 10/2.
int 10h
inc InTmp ;Increment keystroke counter.
jmp ip1
Input endp
cseg ends
end Begin