	.TITLE	KERLIB - KERMIT - library
	.SBTTL	S Hecht/D Stevens/RCM/NB

;
; Kerlib is the library of routines that are common to KERFIL and KERMIT
;
; Version
;

	.IDENT	/1.0.04/
;
; Directives
;
	.ENABLE	LC			; Enable lower case in .ASCIx
	.NLIST	BEX			; Don't list binary expansions
	.LIBRARY /KERMLB/		; Kermit macro library
	.SBTTL	 Revision History

;++
; 1.0.00	By: Authors		    On: Many days
;		Create this module.
;
; 1.0.01	By: Robert C. McQueen	    On: 15-Feb-1984
;		Some module clean up.
;
; 1.0.02	By: Robert C. McQueen	    On: 5-March-1984
;		Remove ATTACH and DETACH.
;
; 1.0.03	By: Robert C. McQueen	    On: 13-March-1984
;		Remove SMC global location and associated storage.
;
; 1.0.04	By: Robert C. McQueen	    On: 12-April-1984
;		Move SY.GENERIC to KERXFR.
;
; 1.0.05	By: Robert C. McQueen	    On: 16-April-1984
;		Support KERCON being a seperate task.
;--

	.SBTTL	External symbols and RSX directives

; Get the KERMLB definitions

	.MCALL	KERDEF
	KERDEF				; Get the general symbol definitions

; Get the character definitions

	.MCALL	CHRDEF			; Character definition macro
	CHRDEF				; Define the characters (Ctl-xxxx)

; Bliss interface macros

	.MCALL	BLSRTN			; Allow use of BLISS macros from
	.MCALL	BLSCAL			;   library

;
; System routines used in Kerlib
;

	.MCALL	DIR$
	.MCALL	QIO$
	.MCALL	QIOW$
	.MCALL	QIOW$S			; Output for TERM.DUMP
	.MCALL	ALUN$
	.MCALL	EXIT$S
	.MCALL	WTSE$S
	.MCALL	CLEF$S
	.SBTTL	Impure data area

; Set the PSECT to be $OWN$ for the read/write data

	.PSECT	$OWN$,  D  

ALTLOC:	.BLKW	1			; Old output routine address.
					;   used with ALTBUF
NOSCRN::.BLKW	1			; No screen output to be done
	.SBTTL	Data


; Set the PSECT to be $PLIT$ for the read-only data

	.PSECT	$PLIT$,  RO ,  D  

CSITXT::.BYTE	.CHCSI,.CHNUL

M$LFBS:	.BYTE	.CHLFD,.CHBS,.CHSPC,.CHSPC,.CHNUL ; Screen painting

M$LFSP:	.BYTE	.CHLFD,.CHSPC,.CHSPC,.CHCRT,.CHNUL ; Screen painting

M$RVID:	.ASCIZ	<.CHCSI>/7m/		; Turn on reverse video
M$BVID::.ASCIZ	<.CHESC>/[1m/		; Bold video attribute
BVID$L==.-M$BVID
M$NVID::.ASCIZ	<.CHESC>/[0m/		; Reset video attributes
NVID$L==.-M$NVID
M$HOME:	.ASCIZ	<.CHCSI>/H/		; Home cursor sequence
CLRESC:	.ASCIZ	<.CHCSI>/2J/		; Clear screen sequence
CUROFF::.ASCIZ	<.CHCSI>/?25l/		; Turn the cursor off
CURON::	.ASCIZ	<.CHCSI>/?25h/		; Turn the cursor on
	.EVEN

;
; Error routine data
;

ADRERR:: .blkw	1


FATEM1:	.byte	.CHCR,.CHLF
	.asciz	'Please record the following error information: '
	.even
FATEM2:	.asciz	', '
	.even
FATEM3:	.BYTE	.CHCR,.CHLF,.CHLF
	.ASCIZ	'Please press RESUME to return to P/OS Main Menu '
	.EVEN
	.sbttl	Input Output Macro Calls

;
; Input/Output control for Kermit
;
;	Writes data onto the terminal, 
;	 and reads data off the terminal.
;
;	INPUT: Any data to be printed onto screen
;		Move data into buffer at IOBUFF.
;
;	OUTPUT: The data you wanted displayed is put onto the screen.
;		Control stays with the calling routine.
;

ASSIGN::
	alun$	TERLUN,TI,0		; Macro to assign the terminal lun.


READ::	qiow$	io.rvb!tf.esq,TERLUN,ttrefn,,iostat,,<iobuff,400.>
					; Macro to read data from the terminal
					;   into the iobuffer, a status return 
					;   is put into iostat, a wait flag of
					;   5 is set when read is completed,
					;   the 10. specifies that the task
					;   reads data from the terminal.
					; TF.ESQ tells the terminal 
					;   to recognize escape sequences.
READ1::	qiow$	io.ral,terlun,ttrefn,,iostat,,<iobuff,1.>
					; Macro to read a single character
					;   from the terminal (passes all 
					;   characters including ^C)

KILTT::	qiow$	io.kil,TERLUN,ttaefn,,iostat
					; Macro to kill all pending I/O
					;   related to the terminal
	.SBTTL	Module initialization

;++
; The following routine will initialize this module.  It will return to the
; caller after the module has been initialized.
;--

INILIB::MOV	#FALSE,NOSCRN		; Allow TERM.DUMP to output data
	RTS	PC			; Return to the caller
	.SBTTL	Exit routine

;
; Exit routine
;This is called from KERMSG in response to a generic logout command.
;

	.PSECT	$CODE$,  RO 

SY.LOGOUT::
EXIT::	JSR	PC,S$CLEAR		; Clear screen
	EXIT$S
	.sbttl	Convert to ascii routine


;		The contents of Registers:
;			R2:	Brings down the value to be converted.
;			R3:	Holds each number to be converted to ascii.
;			R5:	Brings down the base you want it converted.
;				  from.
;		the old contents of register R3 are destroyed
;		by this subroutine.
;
;
CHGOCT::MOV	#8.,R5
	JMP	ASCCHG
CHGDEC::MOV	#10.,R5
ASCCHG::MOV	R2,R3			; Move the number to be converted.
	BPL	31$			; If it is a positive number branch.
	NEG	R3			; Negate the number so it is positive
	BLSCAL	TT.CHAR,#'-		; Output the minus
31$:	CLR	R2			; Clear R2.
	DIV	R5,R2			; Divide by the base, the remainder
					;   goes into R3, the high order
					;   word in R2.
	ADD	#'0,R3			; Make the remainder an ascii character
	MOV	R3,-(SP)		;   put it into the stack.
	MOV	R2,R3			; Put the rest back into R3.
	BEQ	32$			; Have we reached the end of the num
					;   if yes then branch.
	JSR	PC,31$			; Call the routine again
32$:	BLSCAL	TT.CHAR,(SP)+		; Get the character and output it
	RTS	PC			; Return from subroutine.
	.SBTTL	Clear screen

;
; This routine puts the escape sequence needed to clear the screen
;   into the I/O buffer.
;
;	INPUT:	none
;
;	OUTPUT:	The escape sequence put into the I/O buffer.
;

	.GLOBL	S$CLEAR
S$CLEAR:
CLRSCR::BLSCAL	TT.TEXT,#CLRESC		; Get the clear screen text
;	JMP	S$HOME			; Home the cursor
	.SBTTL	Screen support -- Home the cursor

;++
; This routine will home the cursor.  It will then return to the caller.
;
; Usage:
;	JSR	PC,S$HOME
;	(Return)
;
;--

	.GLOBL	S$HOME

S$HOME:	BLSCAL	TT.TEXT,#M$HOME,+	; Home the cursor
	BLSCAL	TT.OUTPUT,,-		; Force it out
	RTS	PC			; Return to the caller
	.sbttl	Cursor Positioning Routine


;
; This routine moves the cursor to the position specified by R2 and R5
;
;	INPUT:	R5	contains the 'Y' position to move to
;		R2	contains the 'X' position to move to
;
;	OUTPUT:	The code for moving the cursor as specified is placed 
;		in the I/O buffer.
;
;	REGISTERS used:	R2, R3, R5
;		R2	Temporary value location (destroyed)
;		R3	Temporary value location (destroyed)
;		R5	(destroyed)
;

CURABS::
	MOV	R5,YPOS			; Save the 'Y' position
	MOV	R2,XPOS			; Save the 'X' position
	BLSCAL	TT.TEXT,#CSITXT,+	; Output the <Escape>[
	MOV	YPOS,R2			; Convert the ypos to decimal
	JSR	PC,CHGDEC		;   and move it to the buffer
	BLSCAL	TT.CHAR,#.CHSEM,+	; Output the semicolon
	MOV	XPOS,R2			; Convert the xpos to decimal
	JSR	PC,CHGDEC		;   and move it to the buffer
	BLSCAL	TT.CHAR,#'H,-		; Output the character
	RTS	PC			; Return to sender
	.sbttl Error handling global routine

;
; I/O error handling routine
;
;
;	INPUT:	None
;
;	OUTPUT:	The I/O error message is displayed along with giving
;		a fatal error message.  Control is returned to P/OS
;		MAIN MENU when RESUME is pressed.
;

IOERR::	MOV	#IOMSG,ADRERR		; Sets up message to be printed out 
					;  when an I/O attempt fails.
	MOV	#8.,BASE		; Put conversion base into base.
	MOV	IOSTAT,STATUS		; put iostatus into status.
	MOV	IOSTAT+2,STAT1		; Put second iostat word into stat1.
;	jmp	error			; jump to main error routine.

;
; Error handling routine
;

ERROR::	JSR	PC,S$CLEAR		; Clear screen

	BLSCAL	TT.TEXT,ADRERR,+	; Output the error text
	BLSCAL	TT.TEXT,#FATEM1,+	; Output the second part of the error
	MOV	STATUS,R2		; Get the status code
	MOV	BASE,R5			; Set conversion base.
	JSR	PC,ASCCHG		; Convert to ascii and put in buffer

	BLSCAL	TT.TEXT,#FATEM2,+	; Output the next part of the msg
	MOV	STAT1,R2		; Get second word of status
	JSR	PC,CHGOCT		; Convert to ascii and put in buffer

	BLSCAL	TT.TEXT,#FATEM3,+	; And the last part of the message
	BLSCAL	TT.TEXT,#CURON,+	; Turn the cursor back on
	BLSCAL	TT.OUTPUT,,-		; Output the text.
	CALL	WTRES			; Wait for RESUME key
	JMP	EXIT			; Exit KERMIT
	.SBTTL	Support routines -- PAINT - Paint a box

;++
; This routine will paint a box on the screen with a centered title
; on the first line.  It uses the normal BLISS calling sequence.
;
; Usage:
; BLISS:
;	PAINT(Text_address, Text_length, Number_of_lines);
;
; Macro:
;	BLSCAL	PAINT,<#TXTADR,#TXTLEN,#LINES>
;
;--

BLSRTN	PAINT,2,<TXTADR,TXTLEN,LINES>

; The first thing that we must do is to insure that some silly person
; didn't cause wrap around to be turned on, so turn it off.

;**

; Tell KERTT to buffer until buffer is full or we call TT.OUTPUT

	BLSCAL	TT.HOLD,<#TRUE>,+	; Start holding data

; Now clear the screen and home the cursor

	JSR	PC,S$CLEAR		; Clear the screen
					;  and home the cursor

; How put the screen into reverse video, so that spaces paint the block
; boundary

	BLSCAL	TT.TEXT,<#M$RVID>,+	; Call the routine

; Compute the number of spaces before and after the centered text.

	MOV	TXTLEN+..STKO(SP),R2	; Get the length of the title
	ASR	R2			; Divide into two parts
	MOV	#40.,R1			; Get the number of spaces to print
	SUB	R2,R1			;  . . .
	SUB	TXTLEN+..STKO(SP),R2	; Comput number of character after
					;  the center of the screen
	ADD	#41.,R2			; Now number of spaces to print

; At this point we have the following
;	R1 := Number of spaces before centered text
;	R2 := Number of spaces after the centered text
;
; First output the spaces before the centered text

	MOV	#.CHSPC,(SP)		; Store a space
10$:	JSR	PC,TT.CHAR		; Output the spaces
	SOB	R1,10$			; Output the spaces before text

; Now output the centered text.

	BLSCAL	TT.TEXT,<TXTADR+..STKO(SP)>,+ ; Output the text

; Now output the characters after the centered text

	MOV	#.CHSPC,(SP)		; Store a space
20$:	JSR	PC,TT.CHAR		; Output the character
	SOB	R2,20$			; Loop for all of the characters

; At this point we have drawn the top of the box.  We will now go down the
; right hand side of the screen.  To do this we output: <LF><BS><SP><SP>

	MOV	LINES+..STKO(SP),R2	; Get the number of lines to do
	DEC	R2			; Less the line on the top
	MOV	#M$LFBS,(SP)		; Store the argument
30$:	JSR	PC,TT.TEXT		; Call the routine
	SOB	R2,30$			; Loop until done

; Now we have painted the top and the right hand side of the box.  Go back
; to the top of the screen and paint the left hand side of the box.  The
; character sequence to paint the other side is: <LF><SP><SP><CR>

	BLSCAL	TT.TEXT,#M$HOME,+	; Home the cursor
	MOV	LINES+..STKO(SP),R2	; Get the number of lines
	DEC	R2			; Remove one
	MOV	#M$LFSP,(SP)		; Store the argument
40$:	JSR	PC,TT.TEXT		; Output it
	SOB	R2,40$			; Loop until done


; At this point we have painted the top, right and left sides of the box
; all that must be done at this point is to do the bottom of the screen.
; this can be done by just printing 80 spaces.

	MOV	#80.,R2			; Get the number of spaces
	MOV	#.CHSPC,(SP)		; Store the argument

50$:	JSR	PC,TT.CHAR		; Output the characters
	SOB	R2,50$			; Loop for all characters

; Now we must put the cursor back to the top of the screen and turn off
; reverse video.

	BLSCAL	TT.TEXT,<#M$NVID>,+	; Back to normal video
	BLSCAL	TT.TEXT,#M$HOME,+	; Home the cursor
	BLSCAL	TT.HOLD,#FALSE,+	; Can dump whenever it wants now
	BLSCAL	TT.OUTPUT,,-		; Force the output
	RTS	PC			; Return to the caller
	.SBTTL	Bliss interface -- DBG_DUMP - Dump a terminal buffer

;++
; This routine will dump a buffer of characters to the terminal.  It will
; be called with the number of characters and the address of the buffer.  All
; this routine does is to output the buffer.
;
; Usage:
;
; Macro:
;	MOV	#Buffer.address,-(SP)
;	MOV	#Number.of.character,-(SP)
;	JSR	PC,DBG.DUMP
;	(Return - R0 contains the status)
;
; Bliss:
;	Status = DBG_DUMP(Buffer, Number_of_characters);
;
;++

DBG.DUMP::
;***** Fall into TERM_DUMP *****
	.SBTTL	Bliss interface -- TERM_DUMP - Dump a terminal buffer

;++
; This routine will dump a buffer of characters to the terminal.  It will
; be called with the number of characters and the address of the buffer.  All
; this routine does is to output the buffer.
;
; Usage:
;
; Macro:
;	MOV	#Buffer.address,-(SP)
;	MOV	#Number.of.character,-(SP)
;	JSR	PC,TERM.DUMP
;	(Return - R0 contains the status)
;
; Bliss:
;	Status = TERM_DUMP(Buffer, Number_of_characters);
;
;++


BLSRTN	TERM.DUMP,2,<ADDR,LEN>		; Save R1 and compute offsets
	BIT	#TRUE,CONNECT.FLAG	; Terminal connected?
	BNE	99$			; Yes, just exit
	BIT	#TRUE,NOSCRN		; No screen output?
	BNE	99$			; Yes, skip this
	MOV	ADDR(SP),R0		; Get the address of the buffer
	MOV	LEN(SP),R1		; Get the length
	BEQ	99$			; If so then branch
	QIOW$S	#IO.WVB,#TERLUN,#TTWEFN,,#IOSTAT,,<R0,R1>
99$:	MOV	#KNORMAL,R0		; Return normal
	RTS	PC			; Return to the caller
	.SBTTL	Set alternate type out routines -- Set up

;++
; This routine will set the alternate type out routine.  It will first
; make sure that the output has been dumped and then it will set the
; new output routine.
;
; Usage:
;	JSR	PC,ALTBUF		; Call the routine
;
;--

	.GLOBL	ALTBUF

ALTBUF:	BLSCAL	TT.OUTPUT		; Make sure the buffers are output
	BLSCAL	TT.SET.OUTPUT,#ALTOUT	; Set the character output routine
	MOV	R0,ALTLOC		;   to ALTOUT and save old routine
	MOV	#IOBUFF,BUFPOS		; Set the buffer pointer for ALTOUT
	RTS	PC			; Return to sender
	.SBTTL	Set alternate type out routines -- Restore routine

;++
; This routine will restore the old type out routine.  It assumes that
; ALTBUF was called some type before
;
; Usage:
;	JSR	PC,ALTRST
;	(Return)
;--

	.GLOBL	ALTRST

ALTRST:	BLSCAL	TT.SET.OUTPUT,ALTLOC	; Reset output to standard routine
	RTS	PC			; Return
	.SBTTL	Set alternate type out routines -- Output the buffer

;++
; This routine will cause the buffer to be output and clear some of the
; initial characters that are in IOBUFF to be cleared.  Required for the
; menu processing.
;
; Usage:
;	JSR	PC,ALTCLR
;	(Return)
;
;--
	.GLOBL	ALTCLR

ALTCLR:	BLSCAL	TT.OUTPUT		; Dump buffer characters
	MOV	#IOBUFF,R0		; Get the buffer start address
	RTS	PC			; Return to sender
	.SBTTL	Set alternate type out routines -- Dump the buffer

; Alternate output routine.  Simply buffers the characters.

	BLSRTN	ALTOUT,2,<ALTADR,ALTLEN> ; Define routine using macro
	MOV	ALTADR(SP),R0		; Get the new characters address
	MOV	ALTLEN(SP),R1		; Get the length of the buffer
	MOV	R1,IOBLEN		; Store the length
	BEQ	10$			;   Get out of here
5$:	MOVB	(R0)+,@BUFPOS		; Move the characters to the buffer
	INC	BUFPOS			; Increment buffer pointer
	SOB	R1,5$			; Decrement character count and branch
					;   if not done.  
	CLRB	(R0)+			; Clear the last byte
10$:	MOV	#IOBUFF,BUFPOS		; Reset the buffer pointer
	RTS	PC			; Return to sender
	.SBTTL	FNDOFS - Find offset in a table

;++
; This routine will find an offset into a table.  It will return the
; the address in the table or zero if it is not found.
;
; Usage:
;	R0/ Address of the table
;	R1/ Length of the table
;	R2/ Item to find
;	JSR	PC,FNDOFS
;	(Return)
;
; On return:
;	R0/ Address of entry or zero if not found
;--

	.PSECT	$CODE$,	RO

	.GLOBL	FNDOFS

FNDOFS:	CMP	R2,(R0)+		; Is this the entry?
	BEQ	10$			; Branch if it is it
	SOB	R1,FNDOFS		; Loop for all entries
	CLR	R0			; Clear if not found
	RTS	PC			; Return failure

; Now return the corrected offset to the item

10$:	TST	-(R0)			; Back up to the entry
	RTS	PC			; Return to the caller
	.SBTTL	End of KERLIB

	.END
