821 lines
33 KiB
NASM
821 lines
33 KiB
NASM
; =====> PROREAD.ASM
|
||
;*****************************************************************
|
||
;* Lowlevel Read Support *
|
||
;* *
|
||
;* (C) Copyright 1985, 1986 by Texas *
|
||
;* Instruments Incorporated. *
|
||
;* All rights reserved. *
|
||
;* *
|
||
;* Date Written: 24 March 1986 *
|
||
;* Last Modification: *
|
||
;* *
|
||
;* 14 Apr 86 (tc) Change references to pagetabl to call *
|
||
;* memory manager for use with ext/exp memory. *
|
||
;* 9 Sep 86 (ds) EGA support. *
|
||
;* 21 Nov 86 (rb) Detect disk full error correctly. *
|
||
;* 7 Jan 87 (ds) Added support for random I/O. *
|
||
;* 10 Feb 87 (tc) EOF-DISP modified to reflect other changes. *
|
||
;* in Page 5 symbols. *
|
||
;* 16 Mar 87 (tc) Added Binary I/O, Error handling, better *
|
||
;* handling for Disk Full *
|
||
;*****************************************************************
|
||
page 60,132
|
||
include scheme.equ
|
||
include sinterp.arg
|
||
|
||
MSDOS equ 21h
|
||
|
||
BACKSP equ 08
|
||
TAB equ 09
|
||
RETURN equ 0Dh
|
||
LF equ 0Ah
|
||
CTRL_Z equ 1Ah
|
||
LEFT_AR equ 4Bh
|
||
RIGHT_AR equ 4Dh
|
||
F3 equ 3Dh
|
||
F5 equ 3Fh
|
||
INSERT equ 52h
|
||
DELETE equ 53h
|
||
ENTER equ 0Dh
|
||
NULL_CH equ 0
|
||
BELL_CH equ 07
|
||
BLANK equ 0020h
|
||
|
||
SCREEN_WIDTH equ 80
|
||
buf_len equ 253
|
||
|
||
DGROUP group data
|
||
data segment word public 'DATA'
|
||
assume DS:DGROUP
|
||
;from iosuport.asm
|
||
extrn port_r:word, port_pg:word, port_ds:word, port_seg:word
|
||
;from ???
|
||
extrn vid_mode:word
|
||
|
||
|
||
public cur_off, char_hgt
|
||
;
|
||
; Local error messages
|
||
;
|
||
ch_rd db "CHAR-READY?",0
|
||
rch_er db "READ-CHAR",0
|
||
push_er db "[VM INTERNAL ERROR] pushchar: failed",CR,LF,0
|
||
rd_st_er db "[VM INTERNAL ERROR] takechar: source not a string",CR,LF,0
|
||
|
||
|
||
cur_off dw 0
|
||
char_hgt dw 8
|
||
|
||
;
|
||
; The following data is used to capture and restore data entered from
|
||
; the console. All characters entered are saved in a shadow buffer
|
||
; so that they may be recalled via the F3, and F5 keys
|
||
;
|
||
insert_m dw 0 ;insert mode flag
|
||
index dw 0 ;index into port buffer
|
||
sh_ptr dw 0 ;pointer into shadow buffer
|
||
sh_len dw 0 ;length of shadow buffer
|
||
sh_bufer db 256 dup (0) ;shadow buffer for characters
|
||
row dw 256 dup (0) ;row vector
|
||
column dw 256 dup (0) ;column vector
|
||
|
||
data ends
|
||
|
||
|
||
PGROUP group prog
|
||
prog segment byte public 'PROG'
|
||
assume CS:PGROUP
|
||
;from basicio.asm
|
||
extrn zbell:near,zscroll:near,zputcur:near
|
||
extrn zputc:near,zcuron:near,zcuroff:near
|
||
extrn zread:near,stringrd:near,char_rdy:near
|
||
extrn ega_curs:near
|
||
;from ???
|
||
extrn getch:near,ssetadr:near
|
||
;from
|
||
extrn toblock:near
|
||
;from sprint.asm
|
||
extrn printtxt:near
|
||
;from sinterp.asm
|
||
extrn next_SP:near,src_err:near,sch_err:near,dos_err:near
|
||
|
||
;;;**************************************************************************
|
||
;;; Input a Single Character
|
||
;;;**************************************************************************
|
||
|
||
take_buf_len equ 256
|
||
|
||
take_arg struc
|
||
tk_leng dw take_buf_len
|
||
new_bpos dw 0
|
||
tk_bp dw ? ;caller's BP
|
||
dw ? ;caller's ES
|
||
dw ? ;caller's return address
|
||
take_arg ends
|
||
|
||
public take_ch
|
||
take_ch proc near
|
||
push es
|
||
push bp
|
||
sub sp,offset tk_bp ;allocate local storage
|
||
mov bp,sp
|
||
mov [BP].new_bpos,0 ;buf position after refilling buf
|
||
LoadPage es,port_pg
|
||
mov si,port_ds ;es:si => port object
|
||
|
||
; Fix for random I/O - read preceeded by a write
|
||
test byte ptr es:[si].pt_pflgs,READWRITE+WRITE_ONLY
|
||
jz take_c00 ;skip if input port
|
||
mov bl,byte ptr es:[si].pt_pflgs ;get port flags
|
||
and bl,DIRTY+STRIO+OPEN+WINDOW ;isolate appropriate flags
|
||
cmp bl,DIRTY+OPEN ;buffer modified?
|
||
jne take_c00 ; no, jump
|
||
and byte ptr es:[si].pt_pflgs,NOT DIRTY ;clear flag
|
||
; this read was preceeded by at least one write, so reposition file pointer
|
||
; so it rereads the buffer
|
||
mov bx,word ptr es:[si].pt_handl
|
||
dec word ptr es:[si].pt_chunk
|
||
mov cx,word ptr es:[si].pt_chunk
|
||
xor dl,dl
|
||
mov dh,cl
|
||
mov cl,ch
|
||
xor ch,ch
|
||
mov ax,4200h ; reposition file pointer
|
||
int MSDOS
|
||
mov bx,es:[si].pt_bfpos ; after re-reading file, restore
|
||
mov [BP].new_bpos,bx ; current buffer position
|
||
jmp take_fill ; go re-read the file
|
||
take_c00:
|
||
mov bx,es:[si].pt_bfpos
|
||
cmp bx,es:[si].pt_bfend ;have we exceeded port's buffer?
|
||
jge take_fill ; yes, go fill it again
|
||
take_nxt:
|
||
xor ah,ah
|
||
mov al,byte ptr es:[si+pt_buffr+bx] ;get next char from buffer
|
||
inc bx ;bump buffer position pointer
|
||
mov es:[si].pt_bfpos,bx ; and update in port object
|
||
cmp al,CTRL_Z ;control-z?
|
||
jne take_ret ; no, return
|
||
test es:[si].pt_pflgs,BINARY ;binary file?
|
||
jnz take_ret ; no, return
|
||
take_eof: mov AX,256 ;text file, send EOF
|
||
take_ret: add sp,offset tk_bp ; release local storage
|
||
pop bp
|
||
pop es
|
||
ret
|
||
|
||
; buffer empty -- fill it up
|
||
take_fill:
|
||
mov [BP].tk_leng,take_buf_len ;set up buffer length
|
||
test es:[si].pt_pflgs,WINDOW ;window port?
|
||
jz take_fil ; no, jump
|
||
test es:[si].pt_pflgs,STRIO ;string port?
|
||
jnz take_str ; yes, jump
|
||
; read from window
|
||
call read_win ;read from window
|
||
mov BX,AX
|
||
jmp take_11
|
||
; Read from file
|
||
public take_fil
|
||
take_fil:
|
||
cmp word ptr es:[si].pt_chunk,1 ; operating on first chunk?
|
||
jne take_f05 ; no, jump
|
||
cmp word ptr es:[si].pt_bfpos,0 ; Have we filled the buffer yet?
|
||
je take_f10 ; yes, jump
|
||
take_f05:
|
||
inc word ptr es:[si].pt_chunk ; bump the chunk number
|
||
take_f10:
|
||
push bp ;<this is tk_leng>
|
||
lea ax,row
|
||
push ax ;address of input buffer
|
||
push es:[si].pt_handl ;file handle
|
||
call zread ;read from file
|
||
mov sp,bp ;dump args from stack
|
||
test ax,ax ;error?
|
||
jnz take_err ; yes, jump
|
||
jmp take_10
|
||
; read character from string
|
||
take_str:
|
||
mov ax,ds
|
||
mov es,ax ;es = ds
|
||
push bp ;<this is tk_leng>
|
||
lea bx,row
|
||
push bx ;buffer for characters
|
||
push port_ds ;port displacement
|
||
push port_pg ;port page
|
||
call stringrd ;read from string
|
||
mov sp,bp ;dump args off stack
|
||
test ax,ax ;error encountered?
|
||
jz take_05 ; no, jump
|
||
lea bx,rd_st_er ;address of error message
|
||
push bx
|
||
C_call printf ;display error message
|
||
mov sp,bp ;dump args from stack
|
||
take_05:
|
||
LoadPage es,port_pg ;restore port addressability
|
||
mov si,port_ds
|
||
;
|
||
take_10: mov bx,[bp].tk_leng ;bx = length
|
||
take_11: mov es:[si].pt_bfend,bx ;update buffer length
|
||
test bx,bx ;length = zero?
|
||
jnz take_20 ; no, jump
|
||
mov es:[si].pt_bfpos,bx ; yes, position = end
|
||
jmp take_eof ; note eof
|
||
take_20:
|
||
test es:[si].pt_pflgs,WINDOW ;window port?
|
||
jz take_22 ; no, jump
|
||
test es:[si].pt_pflgs,STRIO ;string port?
|
||
jz take_25 ; no, jump
|
||
; copy characters from buffer to file object
|
||
take_22:
|
||
push si ;tempsave si
|
||
mov di,si
|
||
add di,pt_buffr ;es:di => port buffer
|
||
lea si,row ;ds:si => char buffer
|
||
mov cx,bx ;# characters to move
|
||
cld ;direction forward
|
||
rep movsb ;do it
|
||
pop si ;restore si
|
||
take_25:
|
||
mov bx,[bp].new_bpos ;BX = buffer position
|
||
jmp take_nxt
|
||
take_err:
|
||
; We will not return from call to dos_err
|
||
add ax,(IO_ERRORS_START - 1) ;make Dos I/O error number
|
||
mov bx,1 ;non-restartable
|
||
lea cx,port_r ;port object
|
||
pushm <cx,ax,bx> ;invoke scheme error handler
|
||
call dos_err ;control will not return here
|
||
take_ch endp
|
||
|
||
;**************************************************************************
|
||
; Read a "record" from window
|
||
; ES:SI points to the window object
|
||
; Return AX = number of characters read
|
||
;**************************************************************************
|
||
read_arg struc
|
||
dw ? ;caller's bp
|
||
dw ? ;return address
|
||
read_arg ends
|
||
|
||
public read_win
|
||
read_win proc near
|
||
push bp
|
||
mov bp,sp
|
||
mov index,0 ;clear index into port buffer
|
||
mov sh_ptr,0 ;clear index into shadow buffer
|
||
mov insert_m,0 ;clear insert flag
|
||
call zcuron ;turn on the cursor
|
||
mov bx,es:[si].pt_text ;get text attribute for window
|
||
read_001:
|
||
mov bx,es:[si].pt_cline ;bx = current line number
|
||
cmp bx,es:[si].pt_nline ;have we exceeded number of lines?
|
||
jl read_put ; no, jump
|
||
push es:[si].pt_text
|
||
push es:[si].pt_ncols
|
||
push es:[si].pt_nline
|
||
push es:[si].pt_ulcol
|
||
push es:[si].pt_ullin
|
||
call zscroll ;scroll up one line
|
||
mov sp,bp ;dump args off stack
|
||
mov bx,es:[si].pt_nline
|
||
dec bx
|
||
mov es:[si].pt_cline,bx ;current line = #lines - 1
|
||
mov es:[si].pt_ccol,0 ;current column = 0
|
||
read_put:
|
||
mov dx,es:[si].pt_ccol
|
||
add dx,es:[si].pt_ulcol
|
||
add bx,es:[si].pt_ullin
|
||
pushm <dx,bx>
|
||
call zputcur ;show the cursor
|
||
mov sp,bp ;bump args off stack
|
||
|
||
call getch ;get character from console
|
||
test al,al ;extended character?
|
||
jz read_ex
|
||
jmp read_100 ; no, go process ascii character
|
||
;
|
||
; Process extended key sequence
|
||
;
|
||
read_ex:
|
||
call getch ;get extended character from console
|
||
cmp al,LEFT_AR ;left arrow key?
|
||
jne read_ra ; no, jump
|
||
jmp read_bs ; yes, treat as backspace
|
||
; Check for RIGHT ARROW key
|
||
read_ra:
|
||
cmp al,RIGHT_AR ;right arrow key?
|
||
jne read_f3 ; no, jump
|
||
mov insert_m,0 ;turn off insert mode
|
||
mov bx,sh_ptr ;bx => shadow buffer
|
||
cmp bx,sh_len ;if more chars in shadow buffer
|
||
jl read_030 ; then go fetch
|
||
jmp read_001 ; else go read next char from window
|
||
read_030:
|
||
lea di,sh_bufer ;ds:di => shadow buffer
|
||
mov al,byte ptr [di+bx] ;fetch character from buffer
|
||
jmp read_one ;and go echo to screen
|
||
; Check for F3 key
|
||
read_f3:
|
||
cmp AL,F3 ;F3 key?
|
||
jne read_f5 ; no, jump
|
||
mov insert_m,0 ;turn off insert mode
|
||
read_041: mov cx,index
|
||
cmp cx,buf_len ;have we exceeded port buffer?
|
||
jl read_043 ; no, jump
|
||
jmp read_001 ;no room for more chars
|
||
read_043:
|
||
mov bx,sh_ptr ;bx => shadow buffer
|
||
cmp bx,sh_len ;have we exceeded length of buffer?
|
||
jl read_045 ; no, jump
|
||
jmp read_001
|
||
read_045: lea di,sh_bufer ;ds:di => shadow buffer
|
||
mov al,byte ptr [di+bx] ;get character from buffer
|
||
call echo_ch ;echo to screen
|
||
mov sp,bp ;bump args from stack
|
||
jmp read_041 ;go get next character
|
||
; Check for F5 key
|
||
read_f5: cmp AL,F5 ;F5 key?
|
||
jne read_ins ; no, jump
|
||
call ega_curs ;turn off the EGA cursor
|
||
mov insert_m,0 ;disable insert mode
|
||
cmp index,0
|
||
jne read_051
|
||
jmp read_001
|
||
read_051:
|
||
call str_str ;copy from port buf to shadow buf
|
||
mov bx,index ;bx = index into port buffer
|
||
mov sh_len,bx ;update shadow buffer length
|
||
mov byte ptr [di+bx],0 ;note end of string
|
||
dec bx ;bx => last char in shadow buffer
|
||
lea di,row ;di => row vector
|
||
read_053:
|
||
cmp bx,0 ;reached start of shadow buffer?
|
||
jl read_055 ; yes, exit loop
|
||
cmp byte ptr [di+bx],0 ;at top of screen?
|
||
jl read_055 ; yes, exit loop
|
||
mov ax,BLANK ;blank character for write
|
||
lea si,column ;si => column vector
|
||
xor ch,ch
|
||
mov cl,byte ptr [si+bx] ;cl = column for character
|
||
xor dh,dh
|
||
mov dl,byte ptr [di+bx] ;dl = row for character
|
||
mov si,port_ds ;si => port object
|
||
mov es:[si].pt_ccol,cx ;update column
|
||
mov es:[si].pt_cline,dx ; and row
|
||
add cx,es:[si].pt_ulcol ;cx = column within window
|
||
add dx,es:[si].pt_ullin ;dx = row within window
|
||
push bx ;tempsave bx around call
|
||
|
||
push es:[si].pt_text ;text attribute
|
||
push ax ;blank character
|
||
push cx ;column
|
||
push dx ;row
|
||
call zputc ;clear character from window
|
||
add sp,8 ;dump args off stack
|
||
|
||
pop bx ;restore shadow buffer index
|
||
dec bx ;and decrement for next character
|
||
jmp read_053 ;go clear next character
|
||
read_055:
|
||
mov index,0 ;clear index into port buffer
|
||
mov sh_ptr,0 ;clear index into shadow buffer
|
||
jmp read_001 ;go read the next character
|
||
; Check for INSERT key
|
||
read_ins: cmp al,INSERT ;insert key?
|
||
jne read_del
|
||
call ega_curs ;turn off the EGA cursor
|
||
mov insert_m,1 ;turn on insert mode
|
||
jmp read_001
|
||
; Check for DELETE key
|
||
read_del: cmp al,DELETE ;delete key?
|
||
jne read_EN
|
||
mov insert_m,0 ;turn off insert mode
|
||
mov bx,sh_ptr
|
||
cmp bx,sh_len ;ensure still within shadow buffer
|
||
jg read_d02
|
||
read_d01: inc sh_ptr
|
||
read_d02: jmp read_001
|
||
; Check for ENTER key
|
||
read_EN: cmp al,ENTER ;enter key?
|
||
je read_RT ; yes, treat as carriage return
|
||
jmp read_001 ;ignore all other extended keys
|
||
;
|
||
; Process ascii character key
|
||
;
|
||
|
||
; Check for BACKSPACE key
|
||
read_100:
|
||
cmp al,BACKSP ;backspace?
|
||
jne read_200 ; no, try next
|
||
read_bs: mov insert_m,0 ;disable insert mode
|
||
call ega_curs ;disable EGA cursor
|
||
mov bx,index ;bx = port buffer index
|
||
cmp bx,0 ;if already at buffer start
|
||
jle read_150 ; then jump
|
||
dec bx ;decrement port buffer index
|
||
lea di,row ;ds:di => row vector
|
||
cmp byte ptr [di+bx],0 ;if at screen start
|
||
jl read_150 ; then jump
|
||
mov index,bx ;save buffer index
|
||
cmp sh_ptr,0 ;if at start of shadow buffer
|
||
je read_120 ; then jump
|
||
dec sh_ptr ; else backspace one character
|
||
read_120: lea di,column ;ds:di => column vector
|
||
xor ch,ch
|
||
mov cl,byte ptr [di+bx] ;get column of prior character
|
||
mov es:[si].pt_ccol,cx ; and update within port object
|
||
add cx,es:[si].pt_ulcol ;cx = col within window
|
||
xor dh,dh
|
||
lea di,row
|
||
mov dl,byte ptr [di+bx] ;get line of prior character
|
||
mov es:[si].pt_cline,dx ; and update within port object
|
||
add dx,es:[si].pt_ullin ;dx = line within window
|
||
|
||
mov bx,BLANK
|
||
push es:[si].pt_text ;text attribute
|
||
push bx ;blank character
|
||
push cx ;column
|
||
push dx ;line
|
||
call zputc ;blank out char on screen
|
||
mov sp,bp ;dump args off stack
|
||
jmp read_001
|
||
read_150:
|
||
call zbell ;beep
|
||
jmp read_001
|
||
; Check for BACKSPACE key
|
||
read_200: cmp al,RETURN ;carriage return?
|
||
je read_RT ; yes
|
||
jmp read_300 ; no, jump
|
||
; Process return key
|
||
read_RT:
|
||
cmp vid_mode,14 ;if not in ega mode
|
||
jl read_rt1 ; then jump
|
||
call ega_curs ; else turn off the ega cursor
|
||
or cur_off,1 ; and note cursor off
|
||
read_rt1:
|
||
mov bx,index ;bx = port buffer index
|
||
mov byte ptr es:[si+pt_buffr+bx],RETURN ;move CR to buffer
|
||
inc bx
|
||
mov byte ptr es:[si+pt_buffr+BX],LF ;move LF to buffer
|
||
inc bx
|
||
mov index,bx ;update port buffer pointer
|
||
mov es:[si].pt_ccol,0 ;clear current column
|
||
mov dx,es:[si].pt_cline ;get current line
|
||
inc dx ; and increment
|
||
cmp dx,es:[si].pt_nline ;if still on screen
|
||
jl read_220 ; then jump
|
||
push es:[si].pt_text
|
||
push es:[si].pt_ncols
|
||
push es:[si].pt_nline
|
||
push es:[si].pt_ulcol
|
||
push es:[si].pt_ullin
|
||
call zscroll ;scroll up one line
|
||
mov sp,bp ;dump args off stack
|
||
mov dx,es:[si].pt_nline
|
||
dec dx
|
||
read_220: mov es:[si].pt_cline,dx ;update current line
|
||
call str_str ;copy shadow buffer into port buffer
|
||
cmp TRNS_pag,0
|
||
je read_250
|
||
test es:[si].pt_pflgs,TRANSCRI
|
||
jz read_250
|
||
; transcript file "on", write buffer to transcript file
|
||
push si ;save current port disp
|
||
push port_pg ;save current port page number
|
||
|
||
pushm <TRNS_dis,TRNS_pag>
|
||
call ssetadr ;set transcript file address
|
||
add sp,4 ;bump args off stack
|
||
mov ax,index
|
||
dec ax
|
||
push ax ;index into buffer
|
||
lea bx,sh_bufer
|
||
push bx ;buffer address
|
||
call printtxt ;output to transcript file
|
||
add sp,4 ;dump args off stack
|
||
;use port args saved above
|
||
call ssetadr ;restore current port address
|
||
pop bx ;restore port page number
|
||
LoadPage es,bx ;es:si => port object
|
||
pop si ;restore port displacement
|
||
lea di,sh_bufer ;ds:di => shadow buffer
|
||
read_250:
|
||
mov bx,index ;bx = index into port buffer
|
||
dec bx ;decrement
|
||
mov byte ptr [di+bx],0 ;note end of string in shadow buffer
|
||
dec bx
|
||
mov sh_len,bx ;update shadow length
|
||
jmp read_done
|
||
; Check for LINEFEED key
|
||
read_300:
|
||
cmp al,LF ;line feed?
|
||
jne read_one ; no, jump
|
||
jmp read_001 ; yes, ignore
|
||
; Default character encountered
|
||
read_one:
|
||
mov bx,index ;bx = port buffer index
|
||
cmp bx,buf_len ;have we exceeded buffer boundary?
|
||
jl read_420 ; no, jump
|
||
call zbell ; yes, sound beep
|
||
jmp read_001 ; and continue
|
||
read_420:
|
||
call echo_ch ;echo character to display
|
||
jmp read_001 ;go handle next read
|
||
; finished reading from window
|
||
read_done:
|
||
call zcuroff ;turn off the cursor
|
||
mov ax,index ;return length
|
||
pop bp
|
||
ret
|
||
read_win endp
|
||
|
||
;*****************************************************************************
|
||
; Move the string in port object to buffer sh_bufer
|
||
;*****************************************************************************
|
||
str_str proc near
|
||
lea di,sh_bufer ;di=address of shadow buffer
|
||
; Move the characters
|
||
push si ;tempsave si
|
||
add si,pt_buffr ;port buffer address
|
||
mov cx,index ;cx = buffer length
|
||
mov AX,ES
|
||
mov BX,DS
|
||
mov ES,BX ;es:di => shadow buffer
|
||
mov DS,AX ;ds:si => port buffer
|
||
rep movsb ;move 'em out
|
||
mov es,ax ;reset segment registers
|
||
mov ds,bx
|
||
lea di,sh_bufer ;di => shadow buffer
|
||
pop si ;si => port object
|
||
ret
|
||
str_str endp
|
||
;*****************************************************************************
|
||
; Echo single character
|
||
; Entry : al = character to display
|
||
; es:si => current port object
|
||
;*****************************************************************************
|
||
echo_ch proc near
|
||
mov bx,index ;bx = index within port buffer
|
||
mov byte ptr es:[si+bx+pt_buffr],al ;store character
|
||
inc bx ;bump index
|
||
mov index,bx ; and update
|
||
cmp insert_m,0 ;insert mode?
|
||
jne echo_10 ; yes, jump
|
||
inc sh_ptr ;bump shadow buffer index
|
||
echo_10:
|
||
mov cx,es:[si].pt_cline ;cx = current column
|
||
mov dx,es:[si].pt_ccol ;dx = current line
|
||
cmp dx,es:[si].pt_ncols ;reached end of line?
|
||
jl echo_20 ; no, jump
|
||
inc cx ;bump current line
|
||
xor dx,dx ;clear current col
|
||
echo_20:
|
||
lea di,row ;ds:di => row vector
|
||
cmp cx,es:[si].pt_nline ;exceed number lines?
|
||
jl echo_50 ; no, jump
|
||
push es:[si].pt_text ;text attribute
|
||
push es:[si].pt_ncols ;number columns
|
||
push es:[si].pt_nline ;number lines
|
||
push es:[si].pt_ulcol ;upper left col
|
||
push es:[si].pt_ullin ;upper left line
|
||
call zscroll ;scroll up one line
|
||
add sp,10 ;dump args
|
||
mov cx,es:[si].pt_nline
|
||
dec cx ;update current line
|
||
xor dx,dx ;clear current column
|
||
; Decrement the contents of row vector
|
||
push ax ;tempsave character
|
||
push bx ;tempsave buffer index
|
||
mov ax,bx ;ax = port buffer index
|
||
xor bx,bx ;bx = buffer start
|
||
echo_30: cmp bx,ax ;have we reached buffer end
|
||
jge echo_40 ; yes, jump
|
||
dec byte ptr [di+bx] ;decrement row for character
|
||
inc bx ;index for next character
|
||
jmp echo_30 ;loop till done
|
||
echo_40: pop bx ;restore buffer index
|
||
pop ax ;restore character
|
||
;update row/col vector for this character
|
||
echo_50:
|
||
dec bx ;create index into row/col vectors
|
||
mov byte ptr [di+bx],cl ;update row
|
||
lea di,column
|
||
mov byte ptr [di+bx],dl ;update col
|
||
cmp al,TAB ;is character the tab key?
|
||
jne echo_100 ; no, jump
|
||
; Process the TAB key
|
||
mov ax,dx ;ax = current column
|
||
mov bx,8 ;bx = tab spacing
|
||
div bl ;ah = remainder (cur_col % 8)
|
||
sub bl,ah ;bx = 8 - remainder
|
||
add dx,bx ;dx = (new) current column
|
||
cmp dx,es:[si].pt_ncols ;exceeded line length?
|
||
jle echo_60 ; no, jump
|
||
mov dx,es:[si].pt_ncols ; yes, current col = end of line
|
||
echo_60:
|
||
mov es:[si].pt_ccol,dx ;update current col
|
||
mov es:[si].pt_cline,cx ;update current line
|
||
|
||
mov bx,dx ;bx = current column
|
||
add bx,es:[si].pt_ulcol ;bx = column within window
|
||
cmp bx,SCREEN_WIDTH ;off of screen?
|
||
jl echo_ret ; no, jump
|
||
mov bx,(SCREEN_WIDTH - 1) ; yes, current col = last col
|
||
pushm <bx,cx>
|
||
call zputcur ;position cursor
|
||
add sp,4 ;dump args
|
||
jmp echo_ret ;return
|
||
; Process the non-TAB key
|
||
echo_100:
|
||
mov es:[si].pt_cline,cx ;update current line
|
||
add cx,es:[si].pt_ullin ;cx = current lin relative to window
|
||
mov es:[si].pt_ccol,dx ;update current line
|
||
add dx,es:[si].pt_ulcol ;dx = current col relative to window
|
||
|
||
push es:[si].pt_text ;text attribute
|
||
push ax ;character to display
|
||
push dx ;column
|
||
push cx ;line
|
||
call zputc ;display character
|
||
add sp,8 ;dump args
|
||
inc es:[si].pt_ccol ;update port's current column
|
||
echo_ret:
|
||
ret
|
||
echo_ch endp
|
||
;*************************************************************************
|
||
; Push a single character back into the input buffer
|
||
;*************************************************************************
|
||
public pushchar
|
||
pushchar proc near
|
||
push es
|
||
push si
|
||
|
||
LoadPage es,port_pg
|
||
mov si,port_ds ;es:si => port object
|
||
|
||
cmp es:[si].pt_bfpos,0 ;any chars in buffer?
|
||
jle push_err ; no, error
|
||
dec es:[si].pt_bfpos ;position to prio character
|
||
push_ret:
|
||
pop si
|
||
pop es
|
||
ret
|
||
push_err:
|
||
lea bx,push_er ;bx = address of error msg
|
||
push bx ;pass to print routine
|
||
C_call printf,,Load_ES ;print error message
|
||
add sp,2 ;dump args
|
||
C_call force_de,,Load_ES ;envoke debugger
|
||
add sp,2 ;will we ever return here???
|
||
jmp push_ret
|
||
pushchar endp
|
||
|
||
rd_proc proc near
|
||
;*************************************************************************
|
||
; Support for read-char-ready?
|
||
;*************************************************************************
|
||
public rd_ch_rd
|
||
public read_cha
|
||
rd_ch_rd:
|
||
lods byte ptr es:[si] ;get register
|
||
save <si> ;save vm instruction pointer
|
||
add ax,offset reg0 ;compute register address
|
||
mov di,ax
|
||
save <di> ;save register argument for later
|
||
xor cx,cx
|
||
push cx
|
||
push ax
|
||
C_call get_port,,Load_ES ;get port object
|
||
;port returned in tmp_page:tmp_disp
|
||
mov sp,bp ;dump args
|
||
test ax,ax ;check return status
|
||
jz rd_010 ; no errors, continue
|
||
jmp rd_err ; else jump to error handler
|
||
rd_010:
|
||
restore <di> ;restore register argument
|
||
mov [di].C_page,SPECCHAR*2 ;prepare to return a character
|
||
mov si,tmp_disp
|
||
LoadPage es,tmp_page ;get page address
|
||
mov bx,es:[si].pt_bfpos ;bx = buffer index
|
||
cmp bx,es:[si].pt_bfend ;if at buffer end
|
||
jge rd_020 ; then go fill the buffer
|
||
;get character from port object buffer
|
||
xor ah,ah
|
||
mov al,byte ptr es:[si+pt_buffr+bx] ;get the character
|
||
rd_T:
|
||
cmp al,CTRL_Z ;control-z character?
|
||
jne rd_015 ; no, continue
|
||
test es:[si].pt_pflgs,BINARY ;binary file?
|
||
jnz rd_015 ; yes, continue
|
||
jmp rd_eof ; no, return eof char
|
||
rd_015: mov [di].C_disp,ax ;return the character
|
||
jmp next_SP
|
||
; no character in input buffer
|
||
rd_020:
|
||
test es:[si].pt_pflgs,WINDOW ;window port?
|
||
jz rd_030 ; no, jump
|
||
jz rd_030
|
||
call char_rdy ;check for character at console
|
||
test ax,ax ;was one there?
|
||
jz rd_no ; no, jump
|
||
xor ah,ah
|
||
jmp rd_T ;go process
|
||
; no character available -- return '()
|
||
rd_no: xor ax,ax
|
||
mov [DI].C_page,ax
|
||
mov [DI].C_disp,ax
|
||
jmp next_SP
|
||
; not a window
|
||
rd_030:
|
||
test es:[si].pt_pflgs,OPEN ;is the port open?
|
||
jz rd_no ; no, return '()
|
||
pushm <tmp_disp,tmp_page>
|
||
call ssetadr ;set up port address
|
||
mov sp,bp ;dump args
|
||
call take_ch ;get a character
|
||
mov sp,bp ;dump args
|
||
restore <di> ;di => register for return
|
||
cmp ax,256 ;eof?
|
||
jne rd_033 ; no, continue
|
||
jmp rd_eof ; yes, go process it
|
||
rd_033:
|
||
call pushchar ; no, put it back
|
||
mov sp,bp
|
||
jmp rd_015
|
||
|
||
; Wrong port object, display error message
|
||
rd_err: lea BX,ch_rd
|
||
jmp src_err ; link to error handler
|
||
|
||
;;;************************************************************************
|
||
;;; Support for read-char
|
||
;;;************************************************************************
|
||
read_cha:
|
||
lods byte ptr es:[si] ;get register
|
||
save <si> ;save vm instruction pointer
|
||
add ax,offset reg0 ;compute register address
|
||
mov di,ax
|
||
save <di> ;save register argument for later
|
||
xor cx,cx
|
||
push cx
|
||
push ax
|
||
C_call get_port,,Load_ES ;get port object
|
||
;port returned in tmp_page:tmp_disp
|
||
mov sp,bp ;dump args
|
||
test ax,ax ;check return status
|
||
jz rc_010 ; no errors, continue
|
||
jmp rc_err ; else jump to error handler
|
||
rc_010:
|
||
restore <di>
|
||
mov [di].C_page,SPECCHAR*2 ;prepare to return character
|
||
mov si,tmp_disp
|
||
LoadPage es,tmp_page ;es:si => port object
|
||
mov bx,es:[si].pt_pflgs ;get port flags
|
||
test bx,WINDOW ;window port?
|
||
jz rc_050 ; no, jump
|
||
test bx,STRIO ;string port?
|
||
jnz rc_050 ; yes, jump
|
||
;read from window
|
||
mov cx,es:[si].pt_bfpos ;cx = port buffer index
|
||
cmp cx,es:[si].pt_bfend ;any character in buffer?
|
||
jl rc_050 ; no, jump
|
||
mov cx,es:[si].pt_cline
|
||
add cx,es:[si].pt_ullin ;cx = line
|
||
mov dx,es:[si].pt_ccol
|
||
add dx,es:[si].pt_ulcol ;dx = column
|
||
pushm <dx,cx>
|
||
call zputcur ;position cursor
|
||
mov sp,bp ;dump args
|
||
call zcuron ;enable cursor
|
||
call getch ;get character from console
|
||
mov [di].C_disp,ax ;return character in reg
|
||
mov byte ptr es:[si].pt_buffr,al ;store also in port object
|
||
call zcuroff ;disable cursor
|
||
mov bx,1
|
||
mov es:[si].pt_bfpos,bx ;update port position
|
||
mov es:[si].pt_bfend,bx
|
||
jmp next_SP
|
||
;read from port object
|
||
rc_050:
|
||
pushm <tmp_disp,tmp_page>
|
||
call ssetadr ;set port address
|
||
mov sp,bp
|
||
call take_ch ;take one character
|
||
mov sp,bp
|
||
restore <di>
|
||
cmp ax,256 ;eof character?
|
||
je rd_eof ; yes, jump
|
||
jmp rd_015 ; no, return the character
|
||
;
|
||
rd_eof: mov [di].C_page,EOF_PAGE*2 ; no, return eof character
|
||
mov [di].C_disp,EOF_DISP
|
||
jmp next_SP
|
||
;
|
||
rc_err: lea BX,rch_er ; address of error message
|
||
jmp src_err ; jump to error handler
|
||
rd_proc endp
|
||
|
||
prog ends
|
||
end
|
||
|