1465 lines
54 KiB
NASM
1465 lines
54 KiB
NASM
; =====> 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
|
||
|