home *** CD-ROM | disk | FTP | other *** search
- ;v1.5
- ; - fixed BS error
- ; - handling/addressing local variables with conventional
- ; .ASM format.
- ; [bp+4] = VAR S doubleword vector
- ; [bp-4] = string starting xy coordinates
- ; [bp-6] = screen width
- ; - adding insert key toggle (default insert On)
-
- ;Codes returned in AX from a svc 0, Int 16H call:
- CTRLU EQU 1615H ;^U
- CTRLZ EQU 2C1AH ;^Z
- DNARR EQU 5000H ;Cursor down
- UPARR EQU 4800H ;Cursor up
- HOMKEY EQU 4700H ;Home key
- ENDKEY EQU 4F00H ;End key
- LFTARR EQU 4B00H ;Cursor left
- RTARR EQU 4D00H ;Cursor right
- INSKEY EQU 5200H ;Insert key
- DELKEY EQU 5300H ;Delete key
- BSKEY EQU 0E08H ;Backspace/Rubout key
- CRKEY EQU 1C0DH ;Return key
- ;
- GRAPH EQU 0B0H ;Selected graphics pad char
- ;
- CSEG Segment Public Para 'CODE'
- ASSUME CS:CSEG, DS:CSEG, ES:CSEG
-
- Toadln proc near ;keep MASM happy
- push bp ;Do like Turbo does
- mov bp,sp
- push bp
- sub sp,5 ;space for 2 integers, 1 boolean
- push DS ;save DS
- call InitScr ;init screen vars
- ;
- lds si,dword ptr [bp+4] ;DS:SI = string vector (>S[bp])
- mov ax,DS
- mov ES,ax ;ES:DI also string vector
- mov byte ptr [bp-7],0FFH ;default= insert mode
- call PadStr ;pad, display, home cursor
- ;
- ;Clear keyboard buffer
- ClrKbd:
- mov ah,1 ;report if char is ready
- int 16H ;BIOS
- jz KeyIn ;kbd buff is empty
- xor ah,ah ; Svc 0, read next kbd char
- int 16H ; BIOS
- jmp short ClrKbd ; Until kbd buff is empty
- ;
- ;Kbd buffer is now empty
- ;Now get/process the user's keyboard input.
- KeyIn:
- call GetKey ;Read, process kbd char
- or ax,ax ;no cursor moving?
- je KeyIn ;right, next key
- cmp ax,CRKEY ; Was it a CR or ^Z?
- je ReturnStr ; yep, done
- ;insure cursor is updated
- call AbsCur ; repsn cursor, update len
- jmp short Keyin ; next key, please
- ;
- ReturnStr:
- mov di,0FFFFH ;force char ptr to end
- call AbsCur ;cursor to screen end
- call ShowStr ;update length, display
- mov ax,0E0DH ;CR
- int 10H
- mov al,0AH ;LF
- int 10H
- pop DS ;restore DS
- mov sp,bp ;do like Turbo does
- pop bp
- ret 4 ;allow for the VAR
- ;
- GetKey:
- ;Processes the keyboard char, acts as required.
- xor ah,ah ;svc 0, read next kbd char
- int 16H ;BIOS
- ;^U clears the string and screen line.
- cmp ax,CTRLU ;Is it a ^U?
- jne LftArrTst ;nope
- mov byte ptr [si],0 ; clear str length
- call PadStr ; clear screen/string
- ret
- ;
- LftArrTst:
- ;Left Arrow key moves left 1 char, stops at 1st char.
- cmp ax,LFTARR ;how about cursor left?
- jne RtArrTst ;nope
- dec di ; back up ptr
- ret
- ;
- RtArrTst:
- ;Right Arrow key moves right 1 char,
- ;stops at last char (+1 if not 255th char)
- cmp ax,RTARR ;right cursor?
- jne DelTst ;nope
- inc di ; bump 1 to right
- ret
- ;
- DelTst:
- ;Delete key rubs out the cursor char,
- ; does NOT move cursor, moves rest of string left.
- cmp ax,DELKEY ;Delete key?
- je DoBS ;yep, skip to common code
- ;
- BSTst:
- ;BS moves left 1 char and deletes THAT char.
- ;No action if we're at first char
- cmp ax,BSKEY ;Is it a BS? (Rubout)
- jne DnArrTst ;nope
- ;
- dec di ;back up next char ptr
- cmp di,si ;did we back up to length byte
- jbe NoBS ;yep, no action
- ;
- DoBS:
- mov byte ptr [di],GRAPH ;"delete" char right here
- call AbsCur ;fix cursor psn,current str psn
- mov ax,di ;new current psn
- sub ax,si ;- start = next char ofs
- cmp ax,cx ;is cursor within string? (not at end)
- jae BS_Show ;nope, at end or beyond
- ;
- ;Move string (from current char pointer to end) left 1 char
- sub cx,ax ;len - cur psn = bytes to move
- push si ;save str start
- push di ;save this new psn
- mov si,di ;new char ptr
- inc si ;move from old char ptr
- cld ;insure fwd
- rep movsb
- mov byte ptr [di],GRAPH ;clear last char
- pop di ;restore current psn
- pop si ;restore str start
- BS_Show:
- call ShowStr
- ret
- NoBS:
- inc di ;restore DI
- xor ax,ax ;flag no cursor move
- ret
- ;
- DnArrTst:
- ;Down Arrow key goes straight down 1 line,
- ;OR to last str char (+1 if not 255th char)
- cmp ax,DNARR ;down cursor?
- jne EndTst ;nope
- add di,[bp-6] ; + scr width = 1 line down
- jc End1 ; went beyond MAXINT
- ret ; done
- ;
- EndTst:
- ;End key goes to last str char (+1 if not 255th char)
- cmp ax,ENDKEY ;End key?
- jne UpArrTst ;nope
- End1:
- mov di,0FFFFH ; max out next char ptr
- ret
- ;
- UpArrTst:
- ;Up Arrow key goes straight up 1 line,
- ;OR to first str char.
- cmp ax,UPARR ;up cursor?
- jne HomTst ;nope
- sub di,[bp-6] ;- scr width = 1 line up
- jb DoHome ;went negative, home
- ret ;done
- ;
- HomTst:
- ;Home key goes to first str char.
- cmp ax,HOMKEY ;home key?
- jne InsTst ;nope
- DoHome:
- xor di,di ; back to start
- ret
- ;
- InsTst:
- ;Insert key toggles insert/overwrite mode
- cmp ax,INSKEY ;Insert key?
- jne CrTst ;nope
- not byte ptr [bp-7] ;reverse all the bits
- xor ax,ax ;no cursor updating
- ret
- ;
- CrTst:
- ;Return or ^Z terminate input, exit procedure.
- cmp ax,CRKEY ;Is it a CR?
- je GetKeyX ;yep, done
- cmp ax,CTRLZ ; how about ^Z
- jne FunTst ; nope
- mov ax,CRKEY ; force to CR
- ret
- ;
- FunTst:
- ;We gobble any other function or cursor keys
- ;so spurious chars won't get in the string.
- xor ah,ah ;clear msb (aux byte)
- or al,al ;is it a special? (cursor/function)
- je GetKeyX ;yep, ignore it (AX=0)
- ;
- ;We assume it's a legal char now, so we display it.
- ;Legals include other control keys.
- PrChr:
- ;If insert mode, we must first move the string right 1
- ;from current char (losing chars beyond 255th).
- ;
- cmp byte ptr [bp-7],0 ;overwrite mode?
- jz PrC ;yep, just stuff it
- ;
- push ax ;save current char
- call FixLen ;CX=current length,AX=rel psn
- sub cx,ax ;length - cur psn = chars to move
- pop ax ;restore char
- jb PrC ;curr char is next char (empty), stuff
- jnz Pr1 ;more than 1 char to move
- ;We're sitting on last real char,
- ;so just 1 to move to right. Do it manually:
- mov ah,[di] ; snarf old char
- push ax ; save
- call PrC ; display,stuff
- call AbsCur ; doublecheck psn, DI, etc.
- pop ax ; get back char
- mov al,ah ; old char into AL
- cmp cl,255 ; length maxed out?
- jb PrC ; nope, stuff it and return
- ret ; gobble last char
- ;
- Pr1: push si ;save str start
- push di ;save this new psn
- inc cx ;adjust chars to move
- add di,cx ;curr char + chars to move
- ;di points to last char in string
- mov si,di ;same place
- dec si ;back up to char before
- std ;insure backward
- rep movsb ;do the move DI-1 to DI
- cld ;be neat: forward again
- pop di ;restore current psn
- pop si ;restore str start
- stosb ;stuff ASCII char, bump DI
- call ShowStr ;display the string (AX=0)
- not ax ;AX <> 0,flag cursor updating
- ret
- ;
- PrC:
- stosb ;stuff ASCII char, bump DI
- mov ah,0EH ;write char TTY
- int 10H ;BIOS
- GetKeyX:
- ret
- ;
- PadStr:
- ;Pads from past last char to 255 chars with graphic char.
- ;Displays str, homes cursor.
- ;Returns CX=str length, DI=str start
- ;
- xor ch,ch ;clear msb
- mov cl,[si] ;get str length
- mov di,si ;current char = str start
- inc di ;bump past len byte
- push si ;str start
- push di ;and next char ptr
- ;
- add di,cx ;add in length (if any)
- not cl ;255-str len
- mov al,GRAPH ;pad with graphic char
- cld ;insure fwd (sigh...)
- rep stosb ;do the pad
- pop di ;restore str start
- pop si ;and next char ptr
- mov dx,[bp-4] ;home cursor to str start
- ;fall thru to ShowStr and return
- ;
- ShowStr:
- ;Display str at starting coordinates,
- ;Clear to EOL (e.g., full 255 chars).
- ;Exit with CX=current str length, DI unchanged,
- ; cursor psn unchanged.
- push dx ;remember current cursor psn
- mov ah,3 ;read cur psn (want cursor size)
- int 10H ;BIOS CX = current cursor size
- ;
- push cx ;save cursor size
- mov ch,20H ;turn cursor off
- mov ah,1 ;set cursor size
- int 10H ;BIOS
- mov dx,[bp-4] ;home cursor to str start
- mov ah,2 ;position cursor
- int 10H ;BIOS
- ;
- ;We display all 255 chars. Str buffer may be padded
- ;with graphic chars (not part of real length),
- ;but we show them to "Clr EOL".
- push si ;str start
- inc si ;bump past length byte
- mov cx,255 ;255 chars
- mov ah,0EH ;BIOS display char TTY
- SL1:
- lodsb ;next string char
- int 10H ;display it
- loop SL1 ;do them all
- pop si ;restore str start
- ;
- pop cx ;old cursor size
- ;
- mov ah,1 ;set cursor size
- int 10H ;BIOS
- pop dx ;old cursor psn
- mov ah,2 ;set cursor psn
- int 10H ;BIOS
- call GetLen ;update CX=len
- mov [si],cl ;and force into len byte
- xor ax,ax ;so we don't call AbsCur
- ret
- ;
- AbsCur:
- ;Absolute cursor movement to next char ptr (DI).
- ;Enter with DI = ptr to next str char.
- ;Test to insure DI doesn't point beyond
- ; 255 chars past start (from FixLen)
- ;Exit with
- ; DX= adjusted xy coords
- ; DI = adjusted current char ptr (from FixLen)
- ; CX = str length (from GetLen)
- ; cursor pointing to next str char
- ;
- mov dx,[bp-4] ;get str's starting cursor psn
- call FixLen ;check str len,char ptr
- ;Returns CX=str len, AX=next char ofs
- or ax,ax ;curr char = start?
- je PsnCur ;yep, go "home" cursor
- ;
- dec ax
- push cx ;save str len
- mov cx,[bp-6] ;get scr width
- add al,dl ;add in starting col
- adc ah,0 ;in case of carry
- AL1:
- cmp ax,cx ;less than 1 line?
- jbe A3 ;yep
- sub ax,cx ;>width, subtract width
- inc dh ;bump row
- jmp short AL1 ;until col < = width
- A3: ;updated DL=col,DH=row
- pop cx ;restore length
- mov dl,al ;update row
- ;
- PsnCur:
- mov ah,2 ;svc 2, position cursor
- int 10H ;BIOS
- ret
- ;
- FixLen:
- ;Insures str len (and CX) are legal,
- ;keeps DI within legal limits (start + 0..254)
- ;Enters with DI = current char ptr (could be beyond str length),
- ;Exits with CX = str len, AX=rel cursor psn within string
- ;
- ;first scan for our terminating GRAPH graphics char
- call GetLen ;returns with CX=len
- jcxz F0 ;no str length, force to start
- ;now insure str ptr is legal (within string)
- mov ax,di ;str ptr
- sub ax,si ;- str start = next char ofs
- ja F1 ;ok, next char > start
- F0:
- xor ax,ax ; next char ofs = 0
- mov di,si ; force next char to start
- inc di ; bump to 1st char
- ret ; done
- ;
- ;at or above 1st char, how about beyond str end?
- F1:
- cmp ax,cx ;< len?
- jbe F2 ;yep
- mov di,si ; start
- mov ax,cx ; get length
- cmp al,255 ; maxed out?
- je F1A ; yep
- inc ax ; no, so bump to next char
- F1A:
- add di,ax ; point to last char
- F2:
- ret
- ;
- GetLen:
- push di ;save next char ptr
- mov di,si ;start
- mov cx,255 ;max possible len
- add di,cx ;point to end
- std ;scan backwards
- mov al,GRAPH ;graphics char ends it
- repe scasb ;scan until we run out of GRAPH's
- cld
- ;CX points to the non-GRAPH char (or 0)
- jz G1 ;didn't find ANY
- inc cx ; adjust from the scasb
- G1:
- pop di ;restore next char ptr
- ret ;with CX=len
- ;
- InitScr:
- ;Get required screen stuff
- mov ah,0FH ;get current video mode
- int 10H ;BIOS
- ;BH = active display page (protect it!)
- mov al,ah ;need width as LSB
- xor ah,ah ;clear msb
- mov [bp-6],ax ;save current scr width
- ;
- ;We need 255 chars of screen space WITHOUT SCROLLING,
- ;or our cursor positioning will be screwed up.
- ;Test now to see if we have enough room.
- ;If not, do our scrolling NOW instead of letting BIOS do it.
- ;
- mov si,ax ;save width in SI
- mov ah,3 ;get current cursor psn in DX
- int 10H ;BIOS
- cmp dh,21 ;row 21 or less?
- jbe NoScroll ;yep, scroll testing
- ;
- mov al,dh ;current row
- mov cx,si ;CL = width multiplier
- mul cl ;AX=row * width
- C1:
- add al,dl ;add in current col
- adc ah,0 ;in case of carry
- mov cx,ax ;remember as abs scr psn
- add ax,255 ;plus full line length
- mov di,ax ;abs scrn psn + string
- CL1:
- cmp di,cx ;less than 1 line?
- jbe CDone ;yep, ok
- mov ax,0E0AH ; display LF via BIOS
- int 10H ; BIOS
- sub di,si ; subtract width
- dec dh ; back up 1 row
- jmp short CL1
- CDone:
- mov ah,2 ;svc 2, position cursor
- int 10H ;BIOS
- NoScroll:
- mov [bp-4],dx ;now save current cursor psn
- ;
- ;Get screen attributes at current cursor psn
- mov ah,8 ;Read char & attrib
- int 10H ;BIOS
- mov bl,ah
- ;BL = screen attribute (protect it!)
- ret
-
- Toadln endp
- CSEG ENDS
- end Toadln