;	PCIO.A	--	Screen and keyboard interface routines for the PC


		dseg
;	In this implementation, all special and function keys are translated
;	to the following values.

;/* control key translations */
up_char		equ	30
down_char	equ	31
left_char	equ	29
right_char	equ	28
bol_char	equ	200
eol_char	equ	201
pageup_char	equ	202
pagedown_char	equ	203
bof_char	equ	204
eof_char	equ	205
Ins_char	equ	206
Del_char	equ	207
NextWord_char	equ	208
PrevWord_char	equ	209

M1		equ	210
M2		equ	211
M3		equ	212
M4		equ	213
M5		equ	214
M6		equ	215
M7		equ	216
M8		equ	217
M9		equ	218
M10		equ	219
;	the table that is used to make the translation

convert:
		db	72, up_char
		db	80, down_char
		db	75, left_char
		db	77, right_char
		db	71, bol_char
		db	79, eol_char
		db	73, pageup_char
		db	81, pagedown_char
		db	77H, bof_char
		db	75H, eof_char
		db	82, Ins_char
		db	83, Del_char
		db	115, PrevWord_char
		db	116, NextWord_char
		db	59, M1
		db	60, M2
		db	61, M3
		db	62, M4
		db	63, M5
		db	64, M6
		db	65, M7
		db	66, M8
		db	67, M9
		db	68, M10
		db	0, 255 ; illegal character

;	equates for bios interface.

;	the interrupt and codes for the screen interface interrupt.

video		equ	10h		;interrupt for dealing with screen

mode		equ	0		;code for setting new screen mode
curtype		equ	1		;code for setting new cursor type
setcur		equ	2		;code for addressing cursor
readcur		equ	3		;code for reading cursor location
readlp		equ	4		;code for reading light pen position
setpage		equ	5		;code to select active page
scrollup	equ	6		;code to scroll screen up
scrolldn	equ	7		;code to scroll screen nown
readch		equ	8		;code to read a character from screen
writeach	equ	9		;code to write char and attributes
writech		equ	10		;code to write character only
setpal		equ	11		;code to set new setpal or border
wdot		equ	12		;code to write a dot
rdot		equ	13		;code to read a dot
wtty		equ	14		;code to write as if teletype
state		equ	15		;code to find current screen status



;	the interrupt and codes for the keyboard interface.

keyboard	equ	16h		;interrupt 16 to deal with keyboard

cicode		equ	0		;code for reading a character
cstscode	equ	1		;code for keyboard status




;	caution: must change column number if 40 column mode

crt_cols	equ	80

;	variables available to a C88 program

		public	scr_cols_, scr_rows_, scr_scrollup_, scr_scrolldown_	
		public	scr_mode_,scr_page_,scr_attr_,scr_window_top_

scr_cols_:	dw	crt_cols	;current number of columns

;	note- make 25 for ms-dos and 24 for cp/m as cp/m steals the bottom
;	line.
scr_rows_:	dw	25		;current number of rows
scr_mode_	db	0		;current screen mode
scr_page_	db	0		;current page
scr_attr_	db	7		;current attributes for screen
					;7 is white letters on black
scr_window_top_	db	2		;first line to scroll

;	variables needed by SEE. Not used here.
scr_scrollup_:	db	0		;zero if scrollup leaves top line alone
scr_scrolldown_:db	0		;zero if scroll down supported



		cseg

;	SCR_SETUP_	scr_setup must be called before any use of any
;			other routine unless the starting mode is 80X25
;			character mode (3,4 or 7). Must be called for monocrome
;			(mode 7) for scr_curson to set a proper cursor.

;			Usage:	scr_setup();

		public	scr_setup_
scr_setup_:	push	bp
		mov	ah,state		;get current state
		int	video
		mov	scr_mode_,al		;current mode
		mov	cl,ah			;make cols a word
		mov	ch,0
		mov	scr_cols_,cx		;40 or 80 columns
		mov	scr_page_,bh
		mov	scr_attr_,7		;set to white chars on black
		cmp	al,4			;see if a character mode
		jc	got_attr
		cmp	al,7			;7 is for graphics mode
		jz	got_attr
		mov	scr_attr_,0		;attribute is zero in graphics
got_attr:	mov	ah,0			;return int containing mode
		pop	bp
		ret


;	SCR_TERM_		do any required termination.

;				Usage:  scr_term();

	public	scr_term_
scr_term_:
	ret





;	SCR_SETMODE_		set a new screen mode

;				Usage:	scr_setmode(new mode);

		public	scr_setmode_
scr_setmode_:	push	bp
		mov	bp,sp
		mov	al,[bp+4]	; new mode value
		mov	ah,mode
		int	video		; set new mode
		call	scr_setup_	;remember new values
		pop	bp
		ret


;	SCR_ROWCOL_		sets cursor at any location.

;				Usage:	scr_rowcol(new row, new column);

		public	scr_rowcol_
scr_rowcol_:				; move cursor to x,y
		push	bp		; save from bios
		mov	bp,sp
		mov	dx,[bp+6]	; column
		mov	ax,[bp+4]	; row
		mov	dh,al
		mov	bh,scr_page_	; force page zero
		mov	ah,setcur	; set cursor location
		int	video		; call bios
		pop	bp
		ret


;	SCR_CLR_		clear entire screen

;				Usage:	scr_clr();

		public	scr_clr_
scr_clr_:				; clear screen


		push	bp		;save from video call
		mov	al,0		;ask for a clear window
		xor	cx,cx		;start at 0,0
		mov	dh,byte scr_rows_;last line
		dec	dh
		mov	dl,byte scr_cols_	;clear entire width
		dec	dl		;last column is width-1
		mov	bh,scr_attr_	;attributes for new blanks
		mov	ah,scrollup	;ask for a scrollup to clear
		int	video		;do the clear
		pop	bp
		ret



;	SCR_CLRL_		clear rest of line.

;				Usage:		scr_clrl();

		public	scr_clrl_		
scr_clrl_:				; clear rest of line
		push	bp
		mov	bh,scr_page_
		mov	ah,readcur	;see where we are
		int	video
		mov	cl,byte scr_cols_	;calc how many chars left in line
		sub	cl,dl		;number left
		mov	ch,0		;number of blanks needed
		mov	al,' '		;write blanks
		mov	bl,scr_attr_	;normal attributes
		mov	bh,scr_page_	;page number
		mov	ah,writeach	;write the blanks
		int	video
		pop	bp
		ret


;	SCR_CLS_		clear rest of screen.

;				Usage:	scr_cls();

		public	scr_cls_
scr_cls_:					; clear rest of screen
		push	bp
		call	scr_clrl_	;clear rest of line
		mov	ah,readcur	;see where we are
		mov	bh,scr_page_
		int	video
		mov	al,0		;ask for a clear window
		mov	ch,dh		;current row
		inc	ch		;+1
		cmp	ch,byte scr_rows_;see if in last line
		jz	cleared		;all done
		mov	cl,0		;first column
		mov	dh,byte scr_rows_;24 is the last line
		dec	dh
		mov	dl,byte scr_cols_	;clear entire width
		dec	dl		;last column is width-1
		mov	bh,scr_attr_	;attributes for new blanks
		mov	ah,scrollup	;ask for a scrollup to clear
		int	video		;do the clear
cleared:	pop	bp

		ret



;	SCR_SCUP_		scroll text up leaving top lines alone.

;				Usage:	scr_scup();

		public	scr_scup_
scr_scup_:			; scroll last line, screen from line
				; scr_windor_top to end
		mov	ax,scr_cols_	;need last column of screen
		dec	ax
		push	ax
		mov	ax,scr_rows_	;scroll through last line
		dec	ax
		push	ax
		xor	ax,ax		;from column 0
		push	ax
		mov	al,scr_window_top_;leave top line alone
		push	ax
		mov	al,1
		push	ax		;scroll by 1
		call	scr_scrup_	;do the scroll
		add	sp,10		;clear arge
		ret

;	SCR_SCRUP_		Scroll the screen up. The window is scrolled
;				up nline lines. A zero nline will clear the
;				window. Top left of the screen in 0,0.

;			Usage: scr_scrup(nline,fromrow,fromcol,torow,tocol);

		public	scr_scrup_
scr_scrup_:	push	bp
		mov	bp,sp
		mov	al,[bp+4]	;number of lines
		mov	ch,[bp+6]	;starting row
		mov	cl,[bp+8]	;starting column
		mov	dh,[bp+10]	;ending row
		mov	dl,[bp+12]	;ending column
		mov	bh,scr_attr_	;current attribute
		mov	ah,scrollup
		int	video		;do the scroll
		pop	bp
		ret


;	SCR_SCDN_		scroll all but the top lines down one.

;				Usage:	scr_scdn();

		public	scr_scdn_
scr_scdn_:
		mov	ax,scr_cols_	;need last column of screen
		dec	ax
		push	ax
		mov	ax,scr_rows_	;scroll through last line
		dec	ax
		push	ax
		xor	ax,ax		;from column 0
		push	ax
		mov	al,scr_window_top_;leave top lines alone
		push	ax
		mov	al,1
		push	ax		;scroll by 1
		call	scr_scrdn_	;do the scroll
		add	sp,10		;clear arge
		ret

;	SCR_SCRDN_		scroll the screen down. the window is scrolled
;				down nline lines. A zero nline will clear the
;				window. Top left of the screen in 0,0.

;			Usage: scr_scrdn(nline,fromrow,fromcol,torow,tocol);

		public	scr_scrdn_
scr_scrdn_:	push	bp
		mov	bp,sp
		mov	al,[bp+4]	;number of lines
		mov	ch,[bp+6]	;starting row
		mov	cl,[bp+8]	;starting column
		mov	dh,[bp+10]	;ending row
		mov	dl,[bp+12]	;ending column
		mov	bh,scr_attr_	;current attribute
		mov	ah,scrolldn
		int	video		;do the scroll
		pop	bp
		ret


;	SCR_CO_			write a character to the screen. this
;				routine increments the cursor position
;				after writing. normal C88 puts and printf
;				statements can also be used to write to the
;				screen.

;				Usage:	scr_co_(character);

		public	scr_co_
scr_co_:					; standard console output
		push	bp
		mov	bp,sp
		mov	al,[bp+4]	;character to write
		mov	bh,scr_page_
		mov	ah,wtty		;use tty write routine
		int	video
		pop	bp
		ret


;	SCR_CI_			keyboard input. function and soft keys are
;				translated. see equates for values.

;				Usage:	character = scr_ci();

		public	scr_ci_
scr_ci_:				;return the next character
					; translate if necessary
		push	bp
		mov	ah,cicode	;ask for a keyboard character
		int	keyboard
		cmp	al,0
		jne	not_special
		mov	bx, offset convert	; convert special key
ci_loop:
		cmp	byte[bx],0
		jz	got_it
		cmp	ah, byte[bx]
		je	got_it
		add	bx,2
		jmp	ci_loop
got_it:		inc	bx
		mov	al,[bx]
		mov	ah,0
		pop	bp
		ret
not_special:	mov	ah,0
		pop	bp
		ret


;	SCR_CSTS_		return character if any available. otherwise
;				return zero.

;				Usage:	character = scr_csts();

		public	scr_csts_
scr_csts_:				;return coded character if any available
		push	bp
		mov	ah,cstscode
		int	keyboard
		mov	ax,0
		jz	csts_over
		call	scr_ci_		;get the coded character
csts_over:	pop	bp
		ret


;	SCR_SET_CURSOR_		does nothing. needed by SEE.


		public	scr_set_cursor_
scr_set_cursor_:			; set the visible cursor to the
					; current position
		ret



;	SCR_SINP_		screen input (read character from the screen).

;				Usage:	character = scr_sinp();

		public	scr_sinp_
scr_sinp_:
		push	bp		;save the registers
		mov	bh,scr_page_
		mov	ah,readch	;code to read a character
		int	video		;al is letter, ah=attributes
		or	al,al		;zero returned instead of blank in
					;graphics mode
		jnz	ret_ch
		mov	al,' '
ret_ch:		mov	ah,0		;kill the attributes
		pop	bp
		ret





;	SCR_CURSOFF_		turn cursor off.

;				Usage:	scr_cursoff();

		public	scr_cursoff_
scr_cursoff_:
		push	bp		;save registers
		cmp	scr_mode_,4	;see if graphics
		jc	text_coff
		cmp	scr_mode_,7
		jnz	no_cur
text_coff:
		mov	cx,0f00h	;should turn cursor off
new_cur:	mov	ah,curtype	;set a new cursor type
		int	video
no_cur:		pop	bp
		ret





;	SCR_CURSON_		turn cursor back on.

;				Usage:	scr_curson();

		public	scr_curson_
scr_curson_:
		push	bp
		mov	cx,0c0dh	;assume monocrome
		cmp	scr_mode_,7	;true is mono
		jz	new_cur		;set it
		mov	cx,0607h	;assume color card in text mode
		cmp	scr_mode_,4	;color text is 0 to 3
		jc	new_cur
		pop	bp		;do nothing if in graphics mode
		ret



;	SCR_MARK  --  mark the current character on the screen.
;		      Used to delimit block areas in SEE. Just write
;		      an X or something if reverse video is not available.
;		      Usage:   scr_mark(current character);

	public	scr_mark_
scr_mark_:					; mark the passed char,
						; cursor does not advance
		push	bp
		mov	al,219			;just write a block character
		mov	bl,scr_attr_		;normal attributes
		mov	cx,1			; one character
		mov	bh,scr_page_		;page number
		mov	ah,writeach		;write char and attr
		int	video			;write character and attributes
		pop	bp
		ret


;	the following routine is not used by either SEE or D88.


;	SCR_APUTS_		write a string and attributes to the screen.
;				the cursor is moved normally

;				Usage:  acr_aputs("Print This",attribute);
;				attribute is BRGBIRGB
;					     | | | |
;					     | | | color for letter. 7 is white
;					     | | intensity for letter
;					     | color for background. 0 is black
;					     blinking

		public scr_aputs_
scr_aputs_:
		push	bp
		mov	bp,sp
		mov	ah,readcur	;see where we are
		mov	bh,scr_page_
		int	video		;dx is cursor location, bh is page
		mov	si,[bp+4]	;string pointer
		mov	cx,1		;number of characters to write
		mov	bl,[bp+6]	;attribute
naputs:		cld
		lodsb			;next character to write
		or	al,al		;zero at end
		jz	eaputs
		cmp	al,10		;look for LF
		jnz	normal_ap
ap_scroll:	mov	bp,sp		;reset pointer to next char
		mov	[bp+4],si
		mov	al,13		;use tty output to scroll screen
		mov	ah,wtty
		int	video		;write cr,lf
		mov	ah,wtty
		mov	al,10
		int	video
		pop	bp
		jmp	scr_aputs_	;start over
normal_ap:
		mov	bh,scr_page_	;page number
		mov	ah,writeach	;write char and attr
		int	video		;write character and attributes
		inc	dl		;next column
		cmp	dl,crt_cols	;see if wrapping around
		jc	set_loc
		mov	dl,0		;at start of column
		inc	dh		;at next row
		cmp	dh,byte scr_rows_;see if need a scroll
		jc	set_loc
		jmp	ap_scroll	;do a scroll up
set_loc:	mov	ah,setcur	;move the cursor
		int	video
		jmp	naputs
eaputs:		pop	bp
		ret

