home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
turbopas
/
toadln5.arc
/
TOADLN5.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-08-24
|
14KB
|
448 lines
;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
; [bp-7] = insert flag
; - adding insert key toggle (default insert On)
sub sp,5 ;space for 2 integers, 1 boolean
push DS ;save DS
call InitScr ;init screen vars
;
lds si,[bp+4] ;DS:SI = string vector (>S[bp])
mov ax,DS
mov ES,ax ;ES:DI also string vector
mov byte [bp-7],$FF ;assume insert mode
call PadStr ;pad, display, home cursor
;
;Clear keyboard buffer
ClrKbd:
mov ah,1 ;report if char is ready
int $16 ;BIOS
jz KeyIn ;kbd buff is empty
xor ah,ah ; Svc 0, read next kbd char
int $16 ; 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,$1C0D ; 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,$FFFF ;force char ptr to end
call AbsCur ;cursor to screen end
call ShowStr ;update length, display
mov ax,$0E0D ;CR
int $10
mov al,$0A ;LF
int $10
jmp Done ;finished
;
;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
;
GetKey:
;Processes the keyboard char, acts as required.
xor ah,ah ;svc 0, read next kbd char
int $16 ;BIOS
;^U clears the string and screen line.
cmp ax,$1615 ;Is it a ^U?
jne LftArrTst ;nope
mov byte [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,$4B00 ;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,$4D00 ;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,$5300 ;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,$0E08 ;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 [di],$B0 ;"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 BSShow ;nope, at end or beyond
;
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 [di],$B0 ;clear last char
pop di ;restore current psn
pop si ;restore str start
BSShow:
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,$5000 ;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,$4F00 ;End key?
jne UpArrTst ;nope
End1:
mov di,$FFFF ; max out next char ptr
ret
;
UpArrTst:
;Up Arrow key goes straight up 1 line,
;OR to first str char.
cmp ax,$4800 ;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,$4700 ;home key?
jne InsTst ;nope
DoHome:
xor di,di ; back to start
ret
;
InsTst:
;Insert key toggles insert/overwrite mode
cmp ax,$5200 ;Insert key?
jne CrTst ;nope
not byte [bp-7] ;reverse all the bits
xor ax,ax ;no cursor updating
ret
;
CrTst:
;Return or ^Z terminate input, exit procedure.
cmp ax,$1C0D ;Is it a CR?
je GetKeyX ;yep, done
cmp ax,$2C1A ; how about ^Z
jne FunTst ; nope
mov ax,$1C0D ; 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.
;v1.5
; If insert mode, we must first move the string right 1
; from current char (losing chars beyond 255th).
;
PrChr:
cmp byte [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 it
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,$0E ;write char TTY
int $10 ;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,$B0 ;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 $10 ;BIOS CX = current cursor size
;
push cx ;save cursor size
mov ch,$20 ;turn cursor off
mov ah,1 ;set cursor size
int $10 ;BIOS
mov dx,[bp-4] ;home cursor to str start
mov ah,2 ;position cursor
int $10 ;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,$0E ;BIOS display char TTY
cld ;insure forward
SL1:
lodsb ;next string char
int $10 ;display it
loop SL1 ;do them all
pop si ;restore str start
;
pop cx ;old cursor size
;
mov ah,1 ;set cursor size
int $10 ;BIOS
pop dx ;old cursor psn
mov ah,2 ;set cursor psn
int $10 ;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 $10 ;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 $B0 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,$B0 ;graphics char ends it
repe scasb ;scan until we run out of $B0's
cld
;CX points to the non-$B0 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,$0F ;get current video mode
int $10 ;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 $10 ;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,$0E0A ; display LF via BIOS
int $10 ; BIOS
sub di,si ; subtract width
dec dh ; back up 1 row
jmp short CL1
CDone:
mov ah,2 ;svc 2, position cursor
int $10 ;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 $10 ;BIOS
mov bl,ah
;BL = screen attribute (protect it!)
ret
;
Done:
pop DS ;restore DS
;let Turbo do the rest