pcs/cio.asm

1465 lines
54 KiB
NASM
Raw Normal View History

2023-05-20 05:57:05 -04:00
; =====> CIO.ASM
;***************************************
;* TIPC Scheme Runtime Support *
;* I/O support *
;* *
;* (C) Copyright 1985, 1986 by Texas *
;* Instruments Incorporated. *
;* All rights reserved. *
;* *
;* Date Written: 24 March 1986 *
;* Last Modification: *
;* 14 April 1986 *
;* Change references to pagetabl *
;* to call memory manager for use *
;* with extended/expanded mem. *
;* 9 Sept 1986 - ds *
;* Add EGA support *
;* 21 Nov 1986 - rb *
;* Detect disk full error correctly*
;* 7 Jan 1987 - dbs *
;* Added support for random I/O *
;* 10 Feb 1987 - tc *
;* EOF-DISP modified to reflect *
;* other changes in Page 5 symbols *
;* 16 Mar 1987 - tc *
;* Added Binary I/O, Error handling*
;* for Disk Full *
;* 21 Jan 1988 - rb *
;* binary I/O uses line-length=0; *
;* do EGA cursor with BIOS call; *
;* use dirty bit of port flags *
;* (commented out) *
;* *
;***************************************
page 60,132
include scheme.equ
include sinterp.arg
P_FLAGS equ 6
W_FLAGS equ 26
HANDLE equ 8
CUR_LINE equ 10
CUR_COL equ 12
UL_LINE equ 14
UL_COL equ 16
N_LINES equ 18
N_COLS equ 20
T_ATTR equ 24
BUF_POS equ 28
BUF_END equ 30
BUFR equ 32
CHUNK equ 14
BACKSP equ 08
WRAP equ 1
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
buf_len equ 253
MSDOS equ 21h
DGROUP group data
data segment word public 'DATA'
assume DS:DGROUP
public port_r, port_seg, port_d
public prn_hand
public direct,nlines, ncols, ulline, ulcol
public curcol, row, column, cur_off, char_hgt
bad_set db "[VM INTERNAL ERROR] setadr: bad port",CR,LF,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
ch_rd db "CHAR-READY?",0
rch_er db "READ-CHAR",0
sfp_err db "SET-FILE-POSITION!",0
port_r dw 0 ; port_reg
dw 0
port_seg dw 0 ; port_page segment
port_d dw 0 ; port_disp
prn_hand dw 0 ; printer handle
win_p dw 0 ; window_p
str_p dw 0 ; string_p
handlee dw 0 ; handle
direct dw 0 ; direction
nlines dw 0 ; n_lines
ncols dw 0 ; n_cols
ulline dw 0 ; ul_line
ulcol dw 0 ; ul_col
t_attrib dw 0 ; text attribute
insert_m dw 0 ; insert mode
curcol dw 0 ; cur_col
curline dw 0 ; cur_line
index dw 0 ; index of buffer
sh_ptr dw 0 ; pointer of 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
scan dw ?
endscan dw ?
cur_off dw 0
char_hgt dw 8
extrn vid_mode:word
extrn ega_col:byte
extrn ega_row:byte
data ends
XGROUP group progx
progx segment word public 'progx'
assume CS:XGROUP
extrn zbell:far
extrn zch_rdy:far
extrn sch_err:near
extrn dos_err:near
;
; For the Ega
; This routine first outputs a byte to the sequencer register to point to
; the map mask register, and then uses the map mask register to enable
; all banks for writing.
;
public enable
enable proc far
comment ~
push DX
push AX
mov DX,3c4h ; port addr of sequencer
mov AL,2 ; index to other map mask register
out DX,AL ; set index register
inc DX ; set DX to map mask register
xchg AL,AH
out DX,AL ; enable all banks
pop AX
pop DX
~
ret
enable endp
;****************************************************************************
;* *
;* EGA Cursor Emulator *
;* *
;* Purpose: to simulate a cursor for the IBM EGA modes. *
;* *
;****************************************************************************
public ega_curs
ega_curs proc far
cmp vid_mode,14 ; don't bother unless in EGA mode
jl ega_03
mov CX,cur_off
and CX,7fh ; is bit one on?
jz ega_02 ; cursor not turned off
and cur_off,0feh ; turn off bit one
jmp ega_03
ega_02: cmp t_attrib,00h ; black attribute?
je ega_03 ; forget it
; set up BIOS call
mov AX,09DBh ; reverse-video block
mov BX,8Fh ; attr = xor,white
mov CX,1 ; repetition count = 1
int 10h
comment ~
push ES
mov AX,0a000h
mov ES,AX
mov char_hgt,8
cmp vid_mode,14
je ega_01
mov char_hgt,14
;
; start scan line = row * height
;
ega_01: mov AL,ega_row ; current line number
xor AH,AH
mul char_hgt
mov scan,AX
;
; end scan line = row * height + height - 1
;
add AX,char_hgt
dec AX
mov endscan,AX
show_loop:
mov CX,80
mul CX
mov BX,AX
xor AX,AX
mov AL,ega_col
add BX,AX ; current column
mov AH,18h
call logical
mov DL,0ffh
call clrbyte
inc scan
mov AX,scan
cmp AX,endscan
jl show_loop
mov AH,0
call logical
mov AH,0
call enable
pop ES
~
ega_03: ret
ega_curs endp
comment ~
; signal to the graphics processor that we want to do a logical operation
; (and or xor) with the latched data.
; on entry ah = function selected
logical proc near
push DX
push AX
mov DX,3ceh ; port addr of graphics address reg
mov AL,3 ; data rotate function
out DX,AL
inc DX
xchg AL,AH
out DX,AL
pop AX
pop DX
ret
logical endp
;
;on entry: DL contains bit mask for clearing ES:[BX] points to byte in
; CRT memory
;
clrbyte proc near
mov AH,0fh
call enable ; enable all banks
mov AL,ES:[BX] ; latch data
xor AL,AL ; zero
mov ES:[BX],AL ; clear byte
mov AH,0ffh
call enable
mov AL,ES:[BX] ; ????
mov AL,DL ; bit mask for character
mov ES:[BX],AL ; set the value
ret
clrbyte endp
~
progx ends
PGROUP group prog
prog segment byte public 'PROG'
assume CS:PGROUP
extrn zscroll:near
extrn zputcur:near
extrn zputc:near
extrn getch:near
extrn zcuron:near
extrn zcuroff:near
extrn zread:near
extrn toblock:near
extrn stringrd:near
extrn printstr:near
;********************************************************************
; *
; set_pos will set the file position, determing which chunk *
; of the file to read and then setting the file position to *
; the appropriate place. *
; *
;********************************************************************
set%_arg struc
dw ? ; caller's CS and IP
dw ?
dw ? ; ES
set_prt dw ? ; port #
set_amt dw ? ; chunk #
set_buf dw ? ; new buffer pointer
set%_arg ends
public set_pos
set_pos proc near
push ES
push BP
mov BP,SP
mov AX,1
pushm <AX, [BP].set_prt>
C_call get_port,,Load_ES ; get port address
mov SP,BP
mov BX,tmp_page ; check return status
cmp byte ptr ptype+[BX],PORTTYPE*2 ; check type
je set_010
setferr: lea BX,sfp_err ; address of error message
pushm <[BP].set_buf, [BP].set_amt, [BP].set_prt>
mov AX,3
pushm <AX, BX>
C_call set_src_,,Load_ES ; set_src_err
mov SP,BP
mov AX,-1
jmp set_don
;
set_010: mov BX,tmp_page
LoadPage ES,BX ; get page address of port
mov SI,tmp_disp
mov DX,word ptr ES:[SI+P_FLAGS]
and DX,04h ; port a file or a window?
cmp DX,04h
je setferr
mov DI,[BP].set_amt
mov DX,[DI]
inc DX
mov word ptr ES:[SI+CHUNK],DX ; update chunk #
dec DX
mov CL,8
xor BX,BX
mov BL,DH
xor DH,DH
shl DX,CL ; multiply DX by 256
mov CX,BX
test byte ptr ES:[SI+P_FLAGS],READWRITE+WRITE_ONLY ;test port flags
pushf ;save flags for later
jz set_015 ;if input port jump
or byte ptr ES:[SI+P_FLAGS],DIRTY ;else set dirty bit
mov BX,[BP].set_buf ; get chunk offset
add DX,[BX] ; and add fo file position
set_015:
mov BX,word ptr ES:[SI+HANDLE] ;get file handle
mov AH,42h ;move file pointer to file
mov AL,0 ;start plus offset in dx
int MSDOS
popf ;restore flags
jnz set_020 ;jump if output port
mov CX,256 ;get buffer length
mov BX,word ptr ES:[SI+HANDLE] ;get file handle
mov DX,SI
add DX,32 ;start of port buffer
push DS
push ES
pop DS ;ds:dx => port buffer
mov AH,3fh ;read from a file
int MSDOS ;go do it
pop DS
mov word ptr ES:[SI+BUF_END],AX ;save #bytes read in port
set_020:
mov BX,[BP].set_buf ;address of chunk offset
mov AX,[BX] ;get offset
mov word ptr ES:[SI+BUF_POS],AX ;and save in port
set_don: pop BP
pop ES
ret
set_pos endp
;;;**************************************************************************
;;; Set Port Address
;;;**************************************************************************
set_arg struc
dw ? ; caller's BP
dw ? ; caller's ES
dw ? ; return address
pg dw ? ; adjusted page number
dis dw ?
set_arg ends
public ssetadr ; temporary
ssetadr proc near ; assembly routine for setadr
push ES
push BP
mov BP,SP
push DI
push SI
push BX
mov BX,[BP].pg ; adjusted page number
cmp byte ptr ptype+[BX],PORTTYPE*2 ; check port type
jne set_err
; get port information
lea DI,port_r ; get port register address
mov [DI].C_page,BX
mov SI,[BP].dis
mov [DI].C_disp,SI
mov port_d,SI
LoadPage ES,BX ; get page address
;;; mov ES,word ptr pagetabl+[BX] ; get page address
mov port_seg,ES ; save the page paragraph
mov AX,word ptr ES:[SI+HANDLE] ; handler
mov handlee,AX
mov AX,word ptr ES:[SI+P_FLAGS] ; port flag
mov direct,AX
mov BX,AX
and AX,WINDOW
mov win_p,AX
and BX,STRIO
mov str_p,BX
xor AX,AX ; return status
set_ret: pop BX
pop SI
pop DI
pop BP
pop ES
ret
; Display error message
set_err: lea SI,bad_set ; address of error message
push SI
C_call printf,,Load_ES ; print error message
mov SP,BP
C_call force_de ; force_debug
mov SP,BP
mov AX,1 ; return error status
jmp set_ret
ssetadr endp
;;;**************************************************************************
;;; Input a Single Character
;;;**************************************************************************
take_arg struc
leng dw 256
new_bpos dw 0
take_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 take_BP ; allocate local storage
mov BP,SP
mov [BP].new_bpos,0 ; buf position after refilling buf
mov [BP].leng,256 ; set up buffer length
lea SI,port_r
mov BX,[SI].C_page
LoadPage ES,BX
mov SI,port_d ; get displacement
; Fix for random I/O - read preceeded by a write
test byte ptr ES:[SI+P_FLAGS],READWRITE+WRITE_ONLY
jz take_c00 ;skip if input port
mov BL,byte ptr ES:[SI+P_FLAGS] ;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+P_FLAGS],NOT DIRTY ;clear flag
; this read was preceded by at least one write, so reposition file pointer
; so it rereads the buffer
mov BX,word ptr ES:[SI+HANDLE]
dec word ptr ES:[SI+CHUNK]
mov CX,word ptr ES:[SI+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+BUF_POS] ; after re-reading file, restore
mov [BP].new_bpos,BX ; current buffer position
jmp take_fil ; go re-read the file
take_c00: mov BX,word ptr ES:[SI+BUF_POS]
cmp BX,word ptr ES:[SI+BUF_END]
jge take_c01
jmp take_nxt ; get the next character from buffer
; buffer empty -- fill it up
take_c01:
cmp win_p,0 ; window object?
jne take_c02
jmp take_fil ; no, jump
take_c02: cmp str_p,0 ; read from string?
je take_win ; no, jump
; read character from string
lea BX,[BP].leng
push BX
lea BX,row ; buffer for characters
push BX
lea SI,port_r
pushm <[SI].C_disp,[SI].C_page> ; port object
mov AX,DS
mov ES,AX ; ES segment points to DS
call stringrd
mov SP,BP
test AX,AX ; check return status
jnz take_ser ; error, jump
lea SI,port_r
mov BX,[SI].C_page
LoadPage ES,BX
;;; LoadPage ES,port_seg ; restore port page
;;; mov ES,port_seg ; reset ES segment
mov SI,port_d ; restore SI register
jmp take_10
take_ser: lea BX,rd_st_er ; address of error message
push BX
C_call printf ; display error message
mov SP,BP
jmp take_10
; read from window
take_win: call read_win
mov BX,AX
jmp short take_11
;
take_10: mov BX,[BP].leng
take_11: mov ES:[SI+BUF_END],BX ; save buffer length
test BX,BX ; length zero?
jnz take_20 ; no, jump
mov ES:[SI+BUF_POS],BX
jmp take_30
take_20: cmp win_p,0 ; window object?
je take_22 ; no, copy string
cmp str_p,0 ; string?
je take_25 ; no, jump
; copy characters from buffer to file object
take_22: push SI ; save SI register
mov DI,SI
add DI,BUFR
lea SI,row
mov CX,BX ; length of characters to move
cld ; direction forward
rep movsb
pop SI ; restore SI register
take_25: mov BX,[BP].new_bpos ; BX = buffer position
; Return the next character from the input buffer
take_nxt: xor AH,AH
mov AL,byte ptr ES:[SI+BUFR+BX]
inc BX
mov word ptr ES:[SI+BUF_POS],BX
cmp AL,CTRL_Z ; test for control-Z
jne take_ret ; no, return
test direct,BINARY
jnz take_ret ; no, return
take_30: mov AX,256 ; text file, send EOF
take_ret: add SP,offset take_BP ; release local storage
pop BP
pop ES
ret
; Read from file
public take_fil
take_fil:
cmp word ptr ES:[SI+CHUNK],1 ; operating on first chunk?
jne take_f05 ; no, jump
cmp word ptr ES:[SI+BUF_POS],0 ; Have we filled the buffer yet?
je take_f10 ; yes, jump
take_f05:
inc word ptr ES:[SI+CHUNK] ; bump the chunk number
take_f10:
mov BX,handlee ; file handle
lea CX,[BP].leng ; address of length of bytes to read
lea AX,row ; input buffer
pushm <CX,AX,BX>
call zread
mov SP,BP
test AX,AX ; error status
jz take_50 ; no, jump
; We will not return from call to dos_err
add AX,(IO_ERRORS_START - 1) ; Make Dos I/O error number
mov BX,1
lea CX,port_r
pushm <CX,AX,BX> ; 1 = non-restartable
call dos_err ; invoke scheme error handler
take_50: jmp take_10 ;relative jump not long enough
take_ch endp
;**************************************************************************
; Read a "record" from window
; ES:SI points to the window object
; Return AX = number of characters read
;**************************************************************************
read_arg struc
read_SI dw ?
read_BX dw ?
sav_p dw ?
sav_d dw ?
read_BP dw ? ; caller's BP
dw ? ; caller's return address
read_arg ends
public read_win
read_win proc near
push BP
sub SP,offset read_BP ; allocate for local storage
mov BP,SP
xor BX,BX ; initialization
mov index,BX
mov sh_ptr,BX
mov insert_m,BX
mov BX,word ptr ES:[SI+CUR_LINE] ; get window information
mov curline,BX
mov DX,word ptr ES:[SI+CUR_COL]
mov curcol,DX
mov DX,word ptr ES:[SI+UL_LINE]
mov ulline,DX
mov DX,word ptr ES:[SI+UL_COL]
mov ulcol,DX
mov DX,word ptr ES:[SI+N_LINES]
mov nlines,DX
mov DX,word ptr ES:[SI+N_COLS]
mov ncols,DX
mov DX,word ptr ES:[SI+T_ATTR]
mov t_attrib,DX
call zcuron ; turn on the cursor
read_001: mov BX,curline ; get the current line number
cmp BX,nlines ; check out of lines
jl read_put
pushm <t_attrib,ncols,nlines,ulcol,ulline>
call zscroll ; scroll up one line
mov SP,BP
mov BX,nlines
dec BX ; cur_line = n_lines - 1
mov curline,BX
mov curcol,0 ; cur_col = 0
read_put: mov DX,curcol
add DX,ulcol
add BX,ulline
pushm <DX,BX>
call zputcur ; show the cursor
mov SP,BP
call getch ; character returned in AL
test AL,AL ; extended character?
jz read_ex
jmp read_100
;;; Process extended key sequence
read_ex: call getch ; character returned in AL
cmp AL,LEFT_AR ; left arrow key?
jne read_ra
jmp read_bs ; as backspace
;
read_ra: cmp AL,RIGHT_AR ; right arrow key?
jne read_f3
mov insert_m,0 ; turn off insert mode
mov BX,sh_ptr
cmp BX,sh_len
jl read_030 ; get character from shadow buffer
jmp read_001
read_030: lea DI,sh_bufer
mov AL,byte ptr [DI+BX]
jmp read_one
;
read_f3: cmp AL,F3 ; F3 key?
jne read_f5
mov insert_m,0 ; turn off insert mode
read_041: mov CX,index
cmp CX,buf_len ; index < len?
jl read_043
jmp read_001 ; no room for more chars
read_043: mov BX,sh_ptr
cmp BX,sh_len ; sh_ptr < sh_length?
jl read_045
jmp read_001 ; buffer empty
read_045: lea DI,sh_bufer
mov AL,byte ptr [DI+BX]
call echo_ch ; AL = character
mov SP,BP
jmp read_041
;
read_f5: cmp AL,F5 ; F5 key?
jne read_ins
call ega_curs ; turn off the EGA cursor
mov insert_m,0 ; turn off insert mode
cmp index,0
jne read_051
jmp read_001
read_051: call str_str ; copy characters to shadow buffer
mov BX,index
mov sh_len,BX
mov byte ptr [DI+BX],0 ; end of string
dec BX
mov [BP].read_SI,SI ; save SI register
lea DI,row ; address of row vector
lea SI,column ; address of column vector
read_053: cmp BX,0
jl read_055
cmp byte ptr [DI+BX],0
jl read_055
mov [BP].read_BX,BX ; save BX
mov CX,BLANK
pushm <t_attrib,CX>
xor CH,CH
mov CL,byte ptr [SI+BX]
mov curcol,CX
add CX,ulcol ; ul_col + cur_col
push CX
mov CL,byte ptr [DI+BX]
mov curline,CX
add CX,ulline ; ul_line + cur_line
push CX
call zputc
mov SP,BP
mov BX,[BP].read_BX ; restore BX
dec BX
jmp read_053
read_055: mov SI,[BP].read_SI ; restore SI register
mov index,0
mov sh_ptr,0
jmp read_001
;
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
;
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 ; sh_ptr < sh_len?
jl read_d01
jmp read_001
read_d01: inc sh_ptr ; sh_ptr++
jmp read_001
;
read_EN: cmp AL,ENTER ; enter key?
je read_RT ; as carriage return
jmp read_001
;;; Process ascii character
read_100: cmp AL,BACKSP ; backspace?
jne read_200
read_bs: mov insert_m,0 ; turn off insert mode
call ega_curs ; turn off the EGA cursor
mov BX,index
cmp BX,0
jle read_150
lea DI,row
dec BX
cmp byte ptr [DI+BX],0
jl read_150
mov index,BX
cmp sh_ptr,0
je read_120
dec sh_ptr ; decrement sh_ptr pointer
read_120: lea DI,column
xor CH,CH
mov CL,byte ptr [DI+BX] ; update cur_line and cur_col
mov curcol,CX
lea DI,row
xor DH,DH
mov DL,byte ptr [DI+BX]
mov curline,DX
mov BX,BLANK
add CX,ulcol ; ul_col + cur_col
add DX,ulline ; ul_line + cur_line
pushm <t_attrib,BX,CX,DX>
call zputc
mov SP,BP
jmp read_001
read_150: call zbell
jmp read_001
;
read_200: cmp AL,RETURN ; carriage return?
je read_RT
jmp read_300 ; no, jump
;;; Process return key
read_RT: cmp vid_mode,14
jl read_rt1
call ega_curs ; turn off the ega cursor
or cur_off,1
read_rt1: mov BX,index
mov byte ptr ES:[SI+BUFR+BX],RETURN ; insert carriage return
inc BX
mov byte ptr ES:[SI+BUFR+BX],LF ; insert line feed
inc BX
mov index,BX
mov DX,curline
mov curcol,0 ; cur_col = 0
inc DX ; cur_line++
cmp DX,nlines ; out of lines?
jl read_220
pushm <t_attrib,ncols,nlines,ulcol,ulline>
call zscroll ; scroll up one line
mov SP,BP
mov DX,nlines ; yes, cur_line = n_lines - 1
dec DX
read_220: mov curline,DX ; restore cur_line
call str_str ; copy string into buffer
cmp TRNS_pag,0 ; check transcript file
je read_250
mov BX,direct
and BX,TRANSCRI
jz read_250
; transcript file "on"
lea BX,port_r
mov DX,[BX].C_page
mov [BP].sav_p,DX
mov DX,[BX].C_disp
mov [BP].sav_d,DX
pushm <TRNS_dis,TRNS_pag>
call ssetadr ; set transcript file address
mov SP,BP
mov AX,index
dec AX
push AX
lea BX,sh_bufer
push BX
mov [BP].read_SI,SI ; save SI register
call printstr ; output to transcript file
mov SP,BP
mov SI,[BP].read_SI ; restore SI register
pushm <[BP].sav_d, [BP].sav_p>
call ssetadr ; set current port address
mov SP,BP
lea DI,sh_bufer
read_250: mov BX,index
dec BX
mov byte ptr [DI+BX],0 ; end of string
dec BX
mov sh_len,BX
jmp read_off
;
read_300: cmp AL,LF ; line feed?
jne read_one
jmp read_001 ; ignore line feed key
;
read_one: mov BX,index ; default
cmp BX,buf_len ; index >= len?
jl read_420
call zbell
jmp read_001
read_420: call echo_ch ; AL = character
jmp read_001
;
read_off: call zcuroff ; turn off the cursor
mov BX,curline
mov CX,curcol
mov ES:[SI+CUR_LINE],BX ; save cur_line and cur_col
mov ES:[SI+CUR_COL],CX
mov AX,index ; return length
;
read_ret: add SP,offset read_BP
pop BP
ret
read_win endp
;*****************************************************************************
; Move the string in port object to buffer sh_bufer
;*****************************************************************************
str_str proc near
lea DI,sh_bufer ; address of shadow buffer
; xor BX,BX
; Clear the buffer
;str_01: cmp BX,sh_len
; jge str_10
; mov byte ptr [DI+BX],0
; inc BX
; jmp str_01
; Move the characters
str_10: push SI ; save SI
add SI,BUFR ; address of input buffer
mov CX,index
mov AX,ES
mov BX,DS
mov ES,BX ; ES:DI points to destination string
mov DS,AX ; DS:SI points to source string
rep movsb
mov ES,AX ; reset segment registers
mov DS,BX
pop SI ; restore SI
lea DI,sh_bufer
ret
str_str endp
;*****************************************************************************
; Echo single character
;*****************************************************************************
echo_ch proc near
push BP
mov BP,SP
mov BX,word ptr ES:[SI+T_ATTR] ; get attribute
mov t_attrib,BX
mov BX,index
mov byte ptr ES:[SI+BX+BUFR],AL ; store character
inc BX ; index++
mov index,BX ;
cmp insert_m,0 ; insert mode?
jne echo_10
inc sh_ptr ; sh_ptr++
echo_10: mov DX,curcol
mov CX,curline
cmp DX,ncols ; end of line?
jl echo_20
inc CX ; yes, cur_line++
xor DX,DX ; cur_col = 0
echo_20: lea DI,row
cmp CX,nlines ; out of lines?
jl echo_50
pushm <t_attrib,ncols,nlines,ulcol,ulline>
call zscroll ; scroll up one line
mov SP,BP
mov CX,nlines
dec CX ; cur_line = n_lines - 1
xor DX,DX ; cur_col = 0
; Decrement the contents of row vector
push AX ; save the character
push BX ; save the index
push CX
mov AX,BX ; AX = index
xor BX,BX
echo_30: cmp BX,AX ; j < index?
jge echo_40
; mov CL,byte ptr [DI+BX]
dec byte ptr [DI+BX] ; row[j]--
; mov byte ptr [DI+BX],CL
inc BX ; j++
jmp echo_30
echo_40: pop CX
pop BX ; restore information
pop AX
echo_50: dec BX ; update row and column vectors
mov byte ptr [DI+BX],CL
lea DI,column
mov byte ptr [DI+BX],DL
cmp AL,TAB ; tab key?
jne echo_100
; Process the TAB key
mov AX,DX
mov BX,8
div BL ; AH = cur_col % 8
sub BL,AH
add DX,BX
cmp DX,ncols ; end of line?
jle echo_60
mov DX,ncols
echo_60: mov BX,DX
add BX,ulcol
cmp BX,80 ; out of screen?
jl echo_200
mov BX,79
pushm <BX,CX>
call zputcur
mov SP,BP
jmp echo_200
; Process the non-TAB key
echo_100: mov curline,CX ; save the information
mov curcol,DX
add DX,ulcol
add CX,ulline
pushm <t_attrib,AX,DX,CX>
call zputc
mov SP,BP
mov DX,curcol ; restore the information
mov CX,curline
inc DX
echo_200: mov curline,CX
mov curcol,DX
pop BP
ret
echo_ch endp
;*************************************************************************
; Push a single character back into the input buffer
;*************************************************************************
public pushchar
pushchar proc near
push ES
push BP
mov BP,SP
push SI
push BX
;;; LoadPage ES,port_seg ; Get port page
lea SI,port_r
mov BX,[SI].C_page
LoadPage ES,BX
;;; mov ES,port_seg ; get address of page
mov SI,port_d
mov BX,word ptr ES:[SI+BUF_POS] ; input buffer starting position
cmp BX,0 ; any character available?
jle push_err ; no, error
dec BX
mov word ptr ES:[SI+BUF_POS],BX ; decrement the starting position
push_ret: pop BX
pop SI
pop BP
pop ES
ret
push_err: lea BX,push_er
push BX
C_call printf,,Load_ES ; print error message
mov SP,BP
C_call force_de,,Load_ES ; force_debug()
mov SP,BP
jmp push_ret
pushchar endp
rd_proc proc near
;*************************************************************************
; Support for read-char-ready?
;*************************************************************************
extrn next_SP:near
extrn src_err:near
public rd_ch_rd
public read_cha
rd_ch_rd: lods byte ptr ES:[SI]
save <SI>
add AX,offset reg0 ; compute register address
mov DI,AX
save <DI> ; save DI register
xor CX,CX
push CX
push AX
C_call get_port,,Load_ES ; get port object
mov SP,BP
test AX,AX ; check return status
jz rd_010
jmp rd_err
;
rd_010: restore <DI>
mov [DI].C_page,SPECCHAR*2 ; prepare to return a character
mov SI,tmp_disp
mov BX,tmp_page
LoadPage ES,BX ; get page address
;;; mov ES,word ptr pagetabl+[BX] ; get address of page
mov BX,word ptr ES:[SI+BUF_POS] ; input buffer starting position
cmp BX,word ptr ES:[SI+BUF_END] ; compare with ending position
jge rd_020
xor AH,AH
mov AL,byte ptr ES:[SI+BUFR+BX] ; get the character
rd_T: cmp AL,CTRL_Z ; control-Z?
jne rd_015
mov BX,word ptr ES:[SI+P_FLAGS]
and BX,BINARY ; binary file?
jnz rd_015
rd_eof: mov [DI].C_page,EOF_PAGE*2 ; return eof character
mov [DI].C_disp,EOF_DISP
jmp next_SP
;
rd_015: mov [DI].C_disp,AX ; return the character
jmp next_SP
; no character in input buffer
rd_020: mov AX,word ptr ES:[SI+P_FLAGS]
mov BX,AX
and AX,WINDOW ; window?
jz rd_030
call zch_rdy ; any character?
test AX,AX
jz rd_no
xor AH,AH ; yes
jmp rd_T
; 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: and BX,OPEN ; open?
jz rd_no ; no, return '()
pushm <tmp_disp,tmp_page>
call ssetadr
mov SP,BP
call take_ch ; get one character
mov SP,BP
restore <DI>
cmp AX,256 ; eof?
je rd_eof
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]
save <SI>
add AX,offset reg0 ; compute register address
mov DI,AX
save <DI> ; save DI register
xor CX,CX
push CX
push AX
C_call get_port,,Load_ES ; get port object
mov SP,BP
test AX,AX ; check return status
jz rc_010
jmp rc_err
;
rc_010: restore <DI>
mov [DI].C_page,SPECCHAR*2
mov BX,tmp_page
LoadPage ES,BX ; get page address
;;; mov ES,word ptr pagetabl+[BX] ; get address of page
mov SI,tmp_disp
mov AX,word ptr ES:[SI+P_FLAGS] ; get port flags
mov BX,AX
and AX,WINDOW ; window object?
jz rc_050
and BX,STRIO ; string object?
jnz rc_050
mov CX,word ptr ES:[SI+BUF_POS]
cmp CX,word ptr ES:[SI+BUF_END] ; any character in buffer?
jl rc_050
mov CX,word ptr ES:[SI+CUR_LINE]
add CX,word ptr ES:[SI+UL_LINE]
mov DX,word ptr ES:[SI+CUR_COL]
add DX,word ptr ES:[SI+UL_COL]
push AX
mov AX,word ptr ES:[SI+T_ATTR]
mov t_attrib,AX
pop AX
pushm <DX,CX>
call zputcur ; cursor position
mov SP,BP
call zcuron ; cursor on
mov SP,BP
call getch ; get character
mov [DI].C_disp,AX
mov byte ptr ES:[SI+BUFR],AL ; store in port object
call zcuroff ; cursor off
mov SP,BP
mov BX,1
mov word ptr ES:[SI+BUF_POS],BX
mov word ptr ES:[SI+BUF_END],BX
jmp next_SP
;
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?
je rc_060
jmp rd_015 ; return the character
rc_060: jmp rd_eof
;
rc_err: lea BX,rch_er ; address of error message
jmp src_err ; jump to error handler
rd_proc endp
;;;****************************************************************
;;; Output a single character
;;;****************************************************************
give_arg struc
lenn dw ? ; character string length
lenn2 dw ? ; second copy of length
sav_pg dw ?
sav_ds dw ?
give_SI dw ?
give_DX dw ?
give_CX dw ?
give_BX dw ?
give_BP dw ? ; caller's BP
dw ? ; caller's ES
dw ? ; caller's return address
char dw ? ; the character to be output
give_arg ends
extrn zscroll:near
extrn force_de:near
extrn zputc:near
extrn printf:near
extrn zwrite:near
extrn force_re:near
public givechar
givechar proc near
push ES
push BP
sub SP,offset give_BP
mov BP,SP
mov [BP].give_SI,SI ; save registers
mov [BP].give_DX,DX
mov [BP].give_CX,CX
mov [BP].give_BX,BX
cmp TRNS_pag,0 ; transcript file?
je give_010
mov BX,direct
and BX,TRANSCRI
jz give_010
; transcript file "on"
lea BX,port_r
mov DX,[BX].C_page
mov [BP].sav_pg,DX
mov DX,[BX].C_disp
mov [BP].sav_ds,DX
pushm <TRNS_dis,TRNS_pag>
call ssetadr ; set transcript file
mov SP,BP
push [BP].char
call givechar ; output to transcript file
mov SP,BP
pushm <[BP].sav_ds,[BP].sav_pg>
call ssetadr ; set port address
mov SP,BP
;
give_010: mov CX,[BP].char
cmp win_p,0 ; window?
jne give_015
jmp give_fil ; no, jump
give_015: cmp str_p,0 ; string?
je give_018
jmp give_030 ; yes, return
; Output to window
give_018: cmp CL,RETURN ; carriage return?
jne give_020
mov CL,LF ; yes, change to LF
give_020:
;;; call putc_win ; putc_window
;;;********************************************************************
;;; Output Character to Window
;;;
;;; Description:This routine writes a character to the current cursor
;;; position, then increments the cursor location.
;;; If the current cursor position is now within the bounds
;;; of the window, the character is output in the first
;;; column of the next line, scrolling the window, if
;;; necessary. The current text attributes are used to
;;; write the character.
;;; Note: CX = character
;;;********************************************************************
mov SI,port_d ; get displacement
lea BX,port_r
mov BX,[BX].C_page
LoadPage ES,BX
;;; LoadPage ES,port_seg ; get port page
;;; mov ES,port_seg ; get page segment
mov AX,direct ; get the port flag
and AX,OPEN ; open for write?
jnz putc_002
jmp give_ret
putc_002: mov BX,word ptr ES:[SI+CUR_LINE] ; BX = cur_line
mov AX,word ptr ES:[SI+CUR_COL] ; AX = cur_col
mov DX,word ptr ES:[SI+UL_LINE]
mov ulline,DX
mov DX,word ptr ES:[SI+UL_COL]
mov ulcol,DX
mov DX,word ptr ES:[SI+N_LINES]
mov nlines,DX
mov DX,word ptr ES:[SI+N_COLS]
mov ncols,DX
mov DX,word ptr ES:[SI+T_ATTR]
mov t_attrib,DX
; Check for the character
cmp CL,NULL_CH ; null character?
jne putc_010
jmp give_ret ; do nothing
;
putc_010: cmp CL,BACKSP ; backspace?
jne putc_020
dec AX
cmp AX,0
jl putc_015
jmp putc_120
putc_015: xor AX,AX ; cur_col = 0
jmp putc_120
;
putc_020: cmp CL,BELL_CH ; bell character?
jne putc_030
call zbell ; sound the alarm
mov SP,BP
jmp give_ret
;
putc_030: cmp CL,TAB ; tab character?
jne putc_050
mov CX,AX
mov DX,8 ; DL = 8
div DL ; AH = (cur_col % 8)
sub DL,AH
add CX,DX
mov AX,CX
jmp putc_120
;
;putc_040: cmp CL,RETURN ; carriage return?
; jne putc_050
; xor AX,AX ; cur_col = 0
; jmp putc_100
;
putc_050: cmp CL,LF ; line feed?
jne putc_060
xor AX,AX
inc BX
cmp BX,nlines ; out of lines?
jge putc_055
jmp putc_100
putc_055: pushm <t_attrib,ncols,nlines,ulcol,ulline>
call zscroll ; scroll window up one line
mov SP,BP
mov BX,nlines
dec BX
xor AX,AX
jmp putc_100
; default
putc_060: cmp AX,ncols ; check end of line
jl putc_080
mov DX,word ptr ES:[SI+W_FLAGS]
and DX,WRAP
jz putc_070
inc BX ; wrap
xor AX,AX
jmp putc_080
putc_070: inc AX ; clip
jmp putc_100 ; no display
putc_080: cmp BX,nlines ; check out of lines?
jl putc_090
pushm <t_attrib,ncols,nlines,ulcol,ulline>
call zscroll ; scroll window up one line
mov SP,BP
mov BX,nlines
dec BX ; set up current line number
xor AX,AX ; and current column number
putc_090: mov curcol,AX
mov curline,BX
push t_attrib ; text character attribute
push [BP].char ; character
add AX,ulcol
push AX ; column number to console
add BX,ulline
push BX ; line number to console
call zputc ; write on cursor position
mov SP,BP
mov AX,curcol
mov BX,curline
inc AX ; increment current column
putc_100: mov ES:[SI+CUR_LINE],BX ; save current cursor line number
putc_120: mov ES:[SI+CUR_COL],AX ; save current cursor column number
give_030: jmp give_ret
; Output to file
give_fil: lea BX,[BP].lenn
mov word ptr [BX],1 ; lenn <- 1
mov word ptr [BX+2],1 ; lenn2 <- 1
lea SI,[BP].char
mov AX,handlee
test direct,BINARY ; Binary file?
jnz give_50 ; Yes, jump
cmp CL,LF ; Line feed?
jne give_50 ; no, jump
mov word ptr [SI],RETURN ; output carriage return
pushm <BX, SI, AX>
call zwrite
mov SP,BP
test AX,AX ; check return status
jnz give_er ; error, jump
mov AX,[BP].lenn ; #chars spec'd = #chars written?
cmp AX,[BP].lenn2
jne give_disk
mov AX,handlee
jmp give_80
;
give_50: pushm <BX, SI, AX>
call zwrite
mov SP,BP
test AX,AX
jnz give_er
mov AX,[BP].lenn ; #chars spec'd = #chars written?
cmp AX,[BP].lenn2
cmp AX,[BP].lenn2
jne give_disk
test direct,BINARY ; Binary file?
jnz give_100 ; yes, jump
cmp word ptr [SI],RETURN ; carriage return?
jne give_100 ; no, jump
mov AX,handlee
;;; cmp AX,prn_hand ; printer?
;;; je give_100 ; yes, jump
give_80: lea SI,[BP].char
mov word ptr [SI],LF ; output line feed
lea BX,[BP].lenn
mov word ptr [BX],1
pushm <BX,SI,AX>
call zwrite
mov SP,BP
test AX,AX ; check return status
jnz give_er
mov AX,[BP].lenn ; #chars spec'd = #chars written?
cmp AX,[BP].lenn2
cmp AX,[BP].lenn2
je give_100
give_disk:
mov ax,DISK_FULL_ERROR ; Note disk full error
jmp short give_er1
give_er: add ax,(IO_ERRORS_START - 1) ; make dos i/o error number
give_er1: mov BX,1
lea CX,port_r
pushm <CX,AX,BX> ; 1 = non-restartable
; We will not return from call to dos_err
call dos_err ; invoke scheme error handler
give_100: lea BX,port_r
mov BX,[BX].C_page
LoadPage ES,BX
;;; LoadPage ES,port_seg
;;; mov ES,port_seg
mov BX,word ptr [SI] ; get the character
mov SI,port_d
mov AX,word ptr ES:[SI+CUR_COL]
test direct,BINARY ; Binary file?
jnz give_200
cmp BL,BACKSP ; back space?
jne give_110
dec AX
cmp AX,0
jge give_200
give_rt: xor AX,AX
jmp give_200
give_110: cmp BL,TAB ; tab?
jne give_120
mov CX,AX
mov DX,8
div DL ; AH = (cur_col % 8)
sub DL,AH
add CX,DX
mov AX,CX
jmp give_200
;
give_120: cmp BL,RETURN ; carriage return?
jne give_130 ; no, continue
mov BL,LF ; yes, make it a linefeed
jmp give_rt
;
give_130: cmp BL,LF ; line feed?
jne give_140
jmp give_rt
; default
give_140: cmp AX,word ptr ES:[SI+N_COLS]
jge give_rt
inc AX
;
give_200:
cmp word ptr ES:[SI+N_COLS],0 ; Line length = 0 ?
je give_20a ; Yes, don't maintain column
mov ES:[SI+CUR_COL],AX
give_20a: mov AX,word ptr ES:[SI+BUF_POS]
inc AX
test direct,BINARY ; Binary file?
jnz give_20b ; yes, jump
cmp BX,LF ; CR or LF just output?
jne give_20b ; no, jump
inc AX ; yes bump # bytes written
give_20b:
cmp AX,256 ; Exceed chunk boundary?
jle give_201 ; no, jump
sub AX,256 ; AX = excess above chunk
inc word ptr ES:[SI+CHUNK] ; bump chunk #
give_201: mov word ptr ES:[SI+BUF_POS],AX ; set the buffer position
give_ret: xor AX,AX
add SP,offset give_BP ; release local storage
mov SI,[BP].give_SI ; restore registers
mov DX,[BP].give_DX
mov CX,[BP].give_CX
mov BX,[BP].give_BX
pop BP
pop ES
ret
givechar endp
prog ends
end