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
|
|||
|
|