Google
 

Trailing-Edge - PDP-10 Archives - steco_19840320_1er_E35 - 10,5676/teco/source/tectrm.mac
There are 3 other files named tectrm.mac in the archive. Click here to see a list.
	SUBTTL	Introduction


; Copyright (c) 1979, 1980 Stevens Institute of Technology, Hoboken, New Jersey
; 07030.

; This software may be used and copied provided that this copyright notice
;is included, and provided that copies of all modifications are sent to:
;
;	TECO Project
;	Computer Center
;	Stevens Institute of Technology
;	Castle Point Station
;	Hoboken, New Jersey    07030
;
;
; The information in this software is subject to change without notice
; and should not be construed as a commitment by Stevens Institute of
; Technology.

  ; Search needed universals

	SEARCH	TECUNV		; TECO universal file

  ; Generate the prologue


	TECVER==200		; Major version number
	TECMIN==1		; Minor version number
	TECEDT==1174		; Edit level
	TECWHO==0		; Last editor


	PROLOGUE(TRM,<TECO Terminal processing>)	; Generate the TITLE and other stuff
	SUBTTL	Table of Contents

;+
;.pag.lit

;		Table of Contents for TECTRM - Terminal processing
;
;
;			   Section			      Page
;   1. Introduction . . . . . . . . . . . . . . . . . . . . .    1
;   2. Table of Contents. . . . . . . . . . . . . . . . . . .    2
;   3. Revision History . . . . . . . . . . . . . . . . . . .    3
;   4. T$INIT - Terminal initialization . . . . . . . . . . .    4
;   5. T$CINI - Per command initialization. . . . . . . . . .    5
;   6. T$SRTN - Set terminal routines up. . . . . . . . . . .    6
;   7. T$SECH - Set terminal to echo characters . . . . . . .    7
;   8. T$CECH - Clear terminal echo . . . . . . . . . . . . .    8
;   9. T$IBUF - Input a character buffered moe. . . . . . . .    9
;  10. T$TCHR - Type a character dependant upon ET value. . .   10
;  11. T$ACHR - Type a character for ^A command . . . . . . .   11
;  12. TYPCHR - Type out for ET = 0 . . . . . . . . . . . . .   12
;  13. TYPLIT - Type out for ET = 1 . . . . . . . . . . . . .   13
;  14. TYPIMG - Type out for ET = 3 . . . . . . . . . . . . .   14
;  15. T$OCHR - Type out routine for messages . . . . . . . .   15
;  16. T$OBUF - Output a character in buffered mode . . . . .   16
;  17. TTYOUT - Output the TTY buffer . . . . . . . . . . . .   17
;  18. Output routines
;       18.1.   .TSTRG. . . . . . . . . . . . . . . . . . . .   18
;       18.2.   .TCRLF - Output a CRLF. . . . . . . . . . . .   19
;  19. $STRING routines
;       19.1.   T$TYPE. . . . . . . . . . . . . . . . . . . .   20
;       19.2.   T$TGCH - Get a character from the string. . .   22
;       19.3.   STRFNC - Function table . . . . . . . . . . .   23
;       19.4.   T$T.T - Type an ASCIZ string. . . . . . . . .   24
;       19.5.   T$T.C - Type an ASCIZ string with special characters  25
;       19.6.   T$T.O - Type an unsigned octal number . . . .   26
;       19.7.   T$T.D - Type a decimal number . . . . . . . .   27
;       19.8.   T$T.F - Type a file spec from an FDB. . . . .   28
;       19.9.   T$T.G - Type a Q-register name. . . . . . . .   29
;       19.10.  T$T.7 - Type an ascii character . . . . . . .   30
;       19.11.  T$T.6 - Type a SIXBIT character . . . . . . .   31
;       19.12.  T$T.P - Type a PPN or path. . . . . . . . . .   32
;       19.13.  T$T.W - Type a SIXBIT word. . . . . . . . . .   33
;       19.14.  T$T.5 - Type an ASCII word. . . . . . . . . .   33
;       19.15.  T$T.M - Type a carriage return. . . . . . . .   34
;       19.16.  T$T.J - Type a line feed. . . . . . . . . . .   34
;       19.17.  T$T.K - Type a vertical tab . . . . . . . . .   34
;       19.18.  T$T.L - type a form feed. . . . . . . . . . .   34
;       19.19.  T$T.V - Type a version number . . . . . . . .   35
;       19.20.  T$T.0 - Insert a null . . . . . . . . . . . .   36
;       19.21.  T$T.I - Set left margin . . . . . . . . . . .   36
;       19.22.  T$T.S - Type another $STRING. . . . . . . . .   37
;       19.23.  T$T.Z - type a switch table . . . . . . . . .   38
;       19.24.  T$T.X - Set output routine. . . . . . . . . .   39
;       19.25.  T$T.INS - Type the following string . . . . .   40
;       19.26.  T$T.EOS - End the current string. . . . . . .   41
;       19.27.  T$T.BEG - Illegal . . . . . . . . . . . . . .   41
;       19.28.  T$T.N - Set no-carriage return. . . . . . . .   41
;       19.29.  T$COLN - Type a colon . . . . . . . . . . . .   42
;       19.30.  T$COMA - Type a comma . . . . . . . . . . . .   42
;       19.31.  T$DOT - Type a period . . . . . . . . . . . .   42
;       19.32.  T$T.A - Type a left angle braket. . . . . . .   43
;       19.33.  T$T.R - Type a right angle bracket. . . . . .   43
;       19.34.  T$T.Q - Type a double quote . . . . . . . . .   43
;       19.35.  T$SPAC - Type a space . . . . . . . . . . . .   44
;       19.36.  T$CHAR - Type the character in CH . . . . . .   45
;  20. Low segment for TECTRM . . . . . . . . . . . . . . . .   46
;  21. End of TECTRM. . . . . . . . . . . . . . . . . . . . .   47

;.end lit.pag
;-
	SUBTTL	Revision History
COMMENT	|

1000	Start of this version

1007	By: Nick Bush		On: 30-July-1980
	1) Make CHKTYI work a little better on slow speed (<=600 baud) 
	   terminals. It will now wait until the output buffer is empty before
	   returning the no input return.
	
	2) Put the cursor in a better position to indicate the location of PT
	   when PT = Z. The only time the cursor will now be over the prompt
	   is when PT = Z and the last line of the buffer is terminated by an
	   end of line character, and is on the last line of the window.
	Modules: TECUNV,TECVID,TECTRM

1017	By: Robert McQueen		On: 12-August-1980
	- The ENQ'd path was wrong sometimes, test backwards.
	- ^Z command caused files to be renamed for EB'd files.
	Modules: TECTRM,TECECM

Start of Version 200A(1126)

1161	By: Nick Bush		On: 13-May-1982
	Add new code to support peek-ahead for immediate (FC table) commands and
	for a new form of the control-T command.
	Add the new form of the control-T command to allow macros to peek at
	input, and to make use of timed input.  Also add the Q-register
	TERMINAL-INPUT-BUFFER to hold the text being peeked at, with the side
	effect of allowing macros to store text into the Q-register, and have
	it be treated as input typed on the terminal.
	Also change the space command to just pass through the arguments unless
	EO is set to 4 or less.
	Modules: TECUNV,TECVID,TECUPD,TECMVM,TECPRS,TECTRM,TECCMD,TECTBL

1174	By: Nick Bush		On: 11-August-1982
	When running terminal in image mode, tack the parity bit on correctly.
	
	Don't smash the Q-reg in the LDB to terminate the command buffer section
	unless absolutely necessary.
	Modules: TECTRM,TECVID
|
	SUBTTL	T$INIT - Terminal initialization

;+
;.HL1 T$INIT
;This routine will do the terminal initialization for TECO.  It will
;find the terminal type from the monitor if possible and set the
;default TECO terminal type from that.
;.literal
;
; Usage:
;	PUSHJ	P,T$INIT	; Do terminal initialization
;	(Return)
;.end literal
;-

	$CODE			; Code

T$INIT:	STORE	T1,TTYFDB,TTYFDB+.FDLEN-1,0 ; Clear the FDB
	STORI.	$FMTRM,T2,FDBMOD,+TTYFDB ; Store the mode
	STORI.	<SIXBIT /TTY/>,T2,FDBDEV,+TTYFDB ; Store the device name
	MOVX	T1,$IOWRI	; To write on this
	MOVEI	T2,TTYFDB	; Get the address
	PUSHJ	P,F$OPEN	; Open the terminal
	 PJRST	F$ERR		; Couldn't?
	MOVE	T3,MYJOB	; Get the job number
	TRMNO.	T3,		; Get the universal index
	  JRST	DEFCRT		; Use the default
	MOVX	T2,.TOTRM	; Get the terminal type
	MOVE	T1,[XWD 2,T2]	; Get the argument pointer
	TRMOP.	T1,		; Get the type
	  JRST	DEFCRT		; Use the default
	JUMPE	T1,DEFCRT	; Use the default
	TXNE	T1,LH.ALF	; Is it really a name?
	 JRST	T$IN.1		; Yes, just go look for it
	HRL	T1,T1		; Move the offset into the correct half
	HRRI	T1,.GTTNM	; Get the terminal name
	GETTAB	T1,		; from the monitor
	  JRST	DEFCRT		; Use the default
T$IN.1:	MOVEM	T1,TRMTYP	; Store the terminal type
	MOVE	T2,[-NUMCRT,,CRTTAB] ; Get the table pointer
	PUSHJ	P,LOKNAM	; Find it
	  JRST	DEFCRT		; Use the default
	MOVEI	T1,-CRTTAB(T2)	; Compute the offset
	SKIPA			; Enter into the common code
DEFCRT:	MOVEI	T1,CRTGEN-CRTDSP	; Get the offset of the "General CRT"
	MOVE	CRT,CRTDSP(T1)	; Get the flags
	MOVEM	CRT,CRTTYP	; Store the flags

	SETZM	ISOFLG		; Assume we don't have image outstr
	MOVX	T1,.TOISO	; Get the image mode outstr function
	MOVEM	T1,TRMOCH+.TOFNC ; Store it
	SETOM	TRMOCH+.TOUDX	; Use this terminal for now
	MOVSI	T1,8		; Get the size of an image mode character
	MOVEM	T1,TRMOCH+.TOAR2 ; Store it
	SETZM	TRMOCH+.TOAR3	; Point to an addressable location
	MOVE	T1,[XWD 4,TRMOCH] ; Get the function pointer
	TRMOP.	T1,		; Do we have the function?
	 JRST	T$CINI		;  No, don't allocate buffers and such
	SETOM	ISOFLG		; Say we have the function
	MOVX	T1,TRMSIZ*4	; Get the maximum number of characters/buffer
	MOVEM	T1,OUTCNT	; Store for later
	MOVX	T1,TRMSIZ	; Get the size of the terminal buffer
	MOVX	T2,.BTGEN	; We want a general block type
	PUSHJ	P,M$ZBLK	; Get the core
	MOVEM	T1,TRMOCH+.TOAR3 ; Store the buffer address
	HRLI	T1,(POINT 8,)	; Make it a byte pointer
	MOVEM	T1,OUTPTR	; Store it
	FALL	T$CINI		; And fall into per command initialization
	SUBTTL	T$CINI - Per command initialization

;+
;.HL1 T$CINI
;This routine will do the per command terminal initialization
;.literal
;
; Usage:
;	PUSHJ	P,T$CINI
;	(Return)
;.end literal
;-

T$CINI:	MOVE	T1,[PUSHJ P,T$ICHW] ; Get the instruction to get a character
	MOVEM	T1,ICHINS	; Store it
	TXZ	S,S.LCTT	; Clear the terminal lower case bit
	SETO	T1,		; Get the line characteristics
	GETLCH	T1		; for this line
	TXNE	T1,GL.LCM	; Is this a lower case terminal
	 TXO	S,S.LCTT	; Yes - Set the terminal lower case bit
	TXO	S,S.SLOG	; Suppress the * in the log file
	SKPCLS	TTYFDB		; Terminal open?
	 JRST	T$CI.0		; Yes, don't need to open it again

; Here if the terminal was closed (An error after EX command)

	MOVX	T1,$IOWRI	; Get the function
	MOVEI	T2,TTYFDB	; Get the FDB address
	PUSHJ	P,F$OPEN	; Open the terminal again
	  PJRST	F$ERR		; Failed, process the error

T$CI.0:	LOAD.	T1,FDBCHN,+TTYFDB ; Get the channel number
	IONDX.	T1,		; And get the UDX
	 STOPCD	CUX,<Can't get terminal UDX>
	HRRZM	T1,TRMUDX	; Save the terminal UDX
	MOVEM	T1,TRMSOP+1	; Save for the SKPINC TRMOP
	MOVEM	T1,TRMOCH+.TOUDX ; Also here for doing image output
	MOVEM	T1,TRMTOC+1	; Also for getting number of chars in output buffer
	HRRZ	T3,T1		; Get the universal I/O index
	MOVX	T1,.TOSOP	; Get the function for skip if output present
	MOVEM	T1,TRMSOP	; Save it
	MOVX	T1,.TOTOC	; Get the other function
	MOVEM	T1,TRMTOC	; Save it
	MOVX	T1,.TOOIC	; Get the image output function
	SKIPN	ISOFLG		; Are we doing image outstrs?
	 MOVEM	 T1,TRMOCH	;  No, save it
	MOVEI	T2,.TOALT	; Check the state of altmode conversion
	MOVE	T1,[XWD 2,T2]	; Get the argument pointer for the TRMOP
	TRMOP.	T1,		; Get the altmode information from TOPS-10
	 LDB	T1,[POINTR (S,S.LCTT)] ; Failed - Use the LC bit
	SKIPE	T1		; Conversion of altmodes wanted ?
	 TXOA	S,S.NALT	; No - Don't convert them
	  TXZ	S,S.NALT	; Yes - Do the conversion
	MOVX	T2,.TOTSP	; Get the terminal transmit speed
	MOVX	T1,<XWD 2,T2>	; Get the arg pointer
	TRMOP.	T1,		; Get the speed from the monitor
	 MOVX	T1,.TS120	; Assume 1200 baud
	MOVEM	T1,TRMSPD	; Save the terminal speed
	MOVX	T2,.TOWID	; Get the width
	MOVE	T1,[XWD 2,T2]	; And set up for the TRMOP.
	TRMOP.	T1,		; Get the width
	 SKIPA	T1,$CRWID(CRT)	; Get the default width
	  SOJ	T1,		; Internal width is one less
	MOVEM	T1,TRMWID	; Store the value
	MOVX	T2,.TOPAG	; Determine if terminal has TTY PAGE set
	MOVE	T1,[XWD 2,T2]	; Get the pointer
	TRMOP.	T1,		; Get the bit
	 SETZ	T1,		; Assume not TTY PAGE
	STOR	T1,S,S.XNXF	; Flag whether we get XON's/XOFF's
	MOVX	T2,.TOPSZ	; Get the terminal page size
	MOVE	T1,[XWD 2,T2]	; Get the TRMOP pointer
	TRMOP.	T1,		; Get the length of the terminal page
	 MOVE	T1,$CRLIN(CRT)	; Don't know it, get the default
	JUMPN	T1,.+2		; Have a length
	 MOVE	T1,$CRLIN(CRT)	; No, get the default
	MOVEM	T1,TRMLEN	; Save the length
	FALL	T$SRTN		; Fall into routine to set up routines
	SUBTTL	T$SRTN - Set terminal routines up

;+
;.HL1 T$SRTN
;This routine will set up the terminal input and output routines.
;It will store the routine addresses in the TY.??? areas in the low
;segment.  All calls to the routines to input and output characters
;will be by the $CALL macro.
;.literal
;
; Usage:
;	PUSHJ	P,T$SRTN
;	(Return)
;.end literal
;-

T$SRTN:	MOVEI	T1,T$IBUF	; Routine to input a byte buffered
	SKPNS			; Skip if not screen mode
	 MOVEI	T1,V$ICHR	; Routine to input a byte video mode
	MOVEM	T1,TY.IBY	; Store in the place to input a byte

	MOVEI	T1,T$OBUF	; Routine to output a byte buffered
	SKPNS			; Skip if not screen mode
	 MOVEI	T1,V$OCHR	; Routine to output a byte video mode
	MOVEM	T1,TY.OBY	; Store in the low segment

	MOVX	T3,IO.FCS!.IOASC ; Get the status
	SKIPE	IMGFLG		; Image mode?
	 MOVX	T3,IO.FCS!.IOPIM ; Yes, get the correct mode
	SKIPN	ECHOFF		; Want echo turned off for some reason?
	 SKPNS			; Screen mode?
	  TXO	T3,IO.SUP	; Yes, suppress echoing
	LOADS.	T2,FDBCHN,+TTYFDB ; Get the channel number
	HRRI	T2,.FOSET	; Get the function
	MOVE	T1,[XWD 2,T2]	; Get the pointer
	FILOP.	T1,		; And set the status
	 STOPCD	FSF,<FILOP. .FOSET function failed>
	POPJ	P,		; Return to the caller
	SUBTTL	T$SECH - Set terminal to echo characters

;+
;.HL1 T$SECH
; This routine will set up to have the terminal echo characters.
;-

T$SECH:	SKIPN	ECHOFF		; Echo off?
	 POPJ	P,		; No, just return
	JMPS	T$SE.1		; If screen mode just set the flag
	$SAVE	<T1,T2,T3>	; Yes, save some room
	SETZ	T2,		; clear room for the FILOP. arg
	MOVX	T3,IO.FCS!.IOASC ; Get the status
	LOADS.	T2,FDBCHN,+TTYFDB ; Get the channel number
	HRRI	T2,.FOSET	; Get the function
	MOVE	T1,[XWD 2,T2]	; Get the pointer
	FILOP.	T1,		; And set the status
	 STOPCD	CSE,<Couldn't set terminal echo on>
T$SE.1:	SETZM	ECHOFF		; Flag echo is on
	POPJ	P,		; Return
	SUBTTL	T$CECH - Clear terminal echo

;+
;.HL1 T$CECH
; This routine will turn the terminal echo off.
;-

T$CECH:	SKIPE	ECHOFF		; Is it already off?
	 POPJ	P,		; Yes, just return
	JMPS	T$CE.1		; If screen mode just set the flag
	$SAVE	<T1,T2,T3>	; Yes, save some room
	MOVX	T3,IO.SUP!IO.FCS!.IOASC ; Get the status
	LOADS.	T2,FDBCHN,+TTYFDB ; Get the channel number
	HRRI	T2,.FOSET	; Get the function
	MOVE	T1,[XWD 2,T2]	; Get the pointer
	FILOP.	T1,		; And set the status
	 STOPCD	CCE,<Couldn't set terminal echo off>
T$CE.1:	SETOM	ECHOFF		; Flag echo is off
	POPJ	P,		; Return
	SUBTTL	T$IBUF - Input a character buffered moe

;+
;.HL1 T$IBUF
;This routine will input a character from the terminal.
;.literal
;
; Usage:
;	PUSHJ	P,T$IBUF
;	(Return)
;
;
; Returns:
;	CH - Containing the characters
;.end literal
;-

T$IBUF:	TXZE	F,F.TYOF	; Need to output the buffer
	 PUSHJ	P,TTYOUT	; Output the buffer
TIBF.2:	PUSHJ	P,T$READ	; Get a character
	TXNE	S,S.LIIN	; Want image of input?
	 PUSHJ	P,LOGC.0	; Yes, log the character

; Here on having gotten a character in CH.  Check the character for
; a Control G.  If it is and we are not in screen mode then we have
; to echo an "^G".

TIBF.3:	CAXE	CH,.CHBEL	; Is this a bell (Control G) ?
	 JRST	ALTCNV		; No - Go check for old altmodes
	MOVEI	CH,"^"		; Echo the bell as ^G
	PUSHJ	P,TYPCHR	; Output the "^"
	MOVEI	CH,"G"		; Get the "G"
	PUSHJ	P,TYPCHR	; Output it too
	MOVX	CH,.CHBEL	; Get the bell back
	POPJ	P,		; Return to the caller


; Here to see if we must do altmode conversions.  First see if the
; flag is set to do the conversion then check to see if the character
; is one that must be converted.

ALTCNV:	TXNE	S,S.NALT	; Old altmode conversions ?
	  POPJ	P,		; No - Just return
	CAXL	CH,.CHALT	; Is this an old altmode ?
	 CAILE	CH,.CHAL2	; .  .  .
	  POPJ	P,		; No - Go return properly
ALTC.1:	MOVEI	CH,.CHESC	; Return an new altmode
	POPJ	P,		; Return

; Here to convert the 175 and 176 to escape (33) if EO = 1

ALTEO:	CAXE	CH,.CHALT	; Old style altmode ?
	 CAIN	CH,.CHAL2	; .  .  .
	  CHKEO	EO21,ALTC.1	; Check for before version 21
	POPJ	P,		; EO > 1 or not 175 or 176
	SUBTTL	T$RBUF - Read any characters already typed into buffer

;+
;.HL1 T$RBUF
; This routine will read any characters which have been typed by the user
;into the peek-ahead buffer.  In video mode, the characters will not have
;been echoed, therefore when the characters are read from the buffer, the
;reader is responsible for echoing.
;.b.lit
;
; Usage:
;	PUSHJ	P,T$RBUF
;	 (return here always)
;
;.end lit
;-

T$RBUF:	$SAVE	<T1,T2>			; Save T1
	XCT	ICHINS			; Get first character
	 POPJ	P,			; Nothing there, just return

TRBU.1:	XMOVEI	T1,TTIBUF+$QRTPT	; Get the address of the buffer
	PUSHJ	P,M$ACHR		; Append the character
	PUSHJ	P,T$ICHS		; Get a character
	 JRST	TRBU.2			; Go clear the pointer
	JRST	TRBU.1			; Store it

TRBU.2:	LOAD.	T1,TPTADR,+$QRTPT+TTIBUF ; Get the address of the buffer
	ZERO.	,BLKPT,(T1)		; Clear the pointer
	POPJ	P,			; ANd return
	SUBTTL	T$ICHW - Input a character and wait if none available

;+
;.hl1 T$ICHW
; This routine will read a character from the terminal, waiting until one
;is available, if necessary.
;.b.lit
;
; Usage:
;	PUSHJ	P,T$ICHW
;	 (non-skip return never)
;	(skip return always)
;
;.end lit
;-

T$ICHW:	PUSHJ	P,SC$FLS		; Flush the screen buffer first
TOPS10,	INCHRW	CH			; Get a character, wait forever
TOPS20,<
	PBIN				; Get a character
	MOVE	CH,T1			; Into correct ac
> ; End of TOPS20

	PJRST	.POPJ1			; Give skip return always
	SUBTTL	T$ICHS - Input a character if available

;+
;.HL1 T$ICHS
; This routine will input a character if there are any available.  If no
;characters are available, it will get the error return.
;.b.lit
;
; Usage:
;	PUSHJ	P,T$ICHS
;	 (No characters available)
;	(Character input into CH)
;
;.end lit
;-

T$ICHS:	PUSHJ	P,SC$FLS		; Flush the screen buffer first
TOPS10,<
	INCHRS	CH			; Get a character (if any)
	 POPJ	P,			; Nothing there
	PJRST	.POPJ1			; Got one, return
> ; End of TOPS10
TOPS20,<
;**** Do something
> ; End of TOPS20
	SUBTTL	T$PEKW - Peek ahead a given number of character

;+
;.hl1 T$PEKW
; This routine will peek ahead n characters and wait for the characters to
;be typed.
;.b.lit
;
; Usage:
;	T1/ Character number to peek at (1=first)
;	PUSHJ	P,T$PEKW
;	(return, CH=character)
;
;.end lit
;-

T$PEKW:	PUSHJ	P,T$CHKI		; Check if the character is there
	 JRST	.-1			; Not there, try reading some
	PUSHJ	P,T$PEEK		; Get the character
	 STOPCD	PCD,<Peek-ahead character disappeared>
	POPJ	P,			; And return
	SUBTTL	T$PEEK - Peek at a character

;+
;.hl1 T$PEEK
; This routine will peek at a character in the type-in buffer.
;.b.lit
;
; Usage:
;	T1/ Character number to peek at (1=first,...)
;	PUSHJ	P,T$PEEK
;	 (return, not enough chars in buffer)
;	(return, character in CH)
;
;.end lit
;-

T$PEEK:	PUSHJ	P,T$CHKI		; Check if we have enough input
	 POPJ	P,			; No, forget it
	LOAD.	T3,TPTADR,+$QRTPT+TTIBUF ; Get the address of the buffer
	SOJ	T1,			; Get the character position
	IDIVI	T1,^D5			; Convert character index to word address
	TDO	T1,BTAB(T2)		; Make into a byte pointer
	ADD	T1,T3			;  .  .  .
	ADDX	T1,.BKTLN		;  .  .  .
	LDB	CH,T1			; Get the character
	PJRST	.POPJ1			; And return
	SUBTTL	T$REDN - Read some characters

;+
;.hl1 T$REDN
; This routine will skip some characters in the input buffer.
;Note that in video mode the characters will not be echoed.
;.b.lit
;
; Usage:
;	T1/ number of characters to skip
;	PUSHJ	P,T$REDN
;	 (return here always)
;
;.end lit
;-

T$REDN:	$SAVE	<P1>			; Save P1
	MOVE	P1,T1			; Copy the amount to skip
	LOAD.	T1,TPTADR,+$QRTPT+TTIBUF ; Get the address of the buffer
	MOVE	T2,P1			; Get the amount to delete
	SETZ	T3,			; Delete from the top
	LOAD.	P1,BLKEND,(T1)		; Get the amount there currently
	ZERO.	,BLKPT,(T1)		; Make sure PT is clear
	SUB	P1,T2			; Get the amount there will be left
	JUMPGE	P1,.+2			; Something left?
	 ADD	T2,P1			; No, delete the whole thing
	PUSHJ	P,M$SRNK		; Delete the characters
	JUMPGE	P1,.POPJ		; Need to delete more?
	MOVM	P1,P1			; Yes, make it positive

TRDN.1:	PUSHJ	P,T$READ		; Get a character
	SOJG	P1,TRDN.1		; And loop for all we need to get
	POPJ	P,			; And return
	SUBTTL	T$READ - Read a character

;+
;.hl1 T$READ
; This routine will read a character from the type-in buffer (or terminal).
;Note that in video mode, the character will not have been echoed.  The
;caller is repsonsible for echoing the character.
;.b.lit
;
; Usage:
;	PUSHJ	P,T$READ
;	(return, character in CH)
;
;.end lit
;-

T$READ:	LOAD.	T1,TPTADR,+TTIBUF+$QRTPT ; Get the address of the type-ahead
	CFXN.	,BLKEND,(T1),0		; Anything in the buffer?
	 JRST	TREA.0			; No, get one from the terminal
	ZERO.	,BLKPT,(T1)		; Clear the pointer
	ADDX	T1,<POINT 7,.BKTLN,6>	; Point to the first character
	LDB	CH,T1			; Get it
	LOAD.	T1,TPTADR,+TTIBUF+$QRTPT ; Get the address of the buffer back
	MOVEI	T2,1			; Delete one character
	SETZ	T3,			; At the start of the buffer
	PJRST	M$SRNK			; Go delete it

TREA.0:	PUSHJ	P,T$ICHW		; No, get a character from the terminal
	 JFCL				; Always has one
	POPJ	P,			; And return
	SUBTTL	T$WAIT - Wait for a character, or until timer expires

;+
;.HL1 T$WAIT
; This routine will wait until a given time arrives, or a character is typed,
;depending upon its arguments.
;.b.lit
;	T1/ Time to wait in milli-seconds (if negative, always wait full time)
;	T2/ Number of characters to wait for
;	PUSHJ	P,T$WAIT
;	 (return, no character available)
;	(return, character(s) avaiable)
;
;.end lit
;-

T$WAIT:	$SAVE	<P1,P2,P3,P4>		; Save some ac's
	DMOVE	P1,T1			; Get a copy of the time
	JUMPL	T1,TWAI.1		; If we don't care if character is here

	SKIPE	T1,P2			; Get the number of characters to check for
	 PUSHJ	P,T$CHKI		; Check if any characters here
	  JRST	TWAI.1			; Go wait if not enough here yet
	PJRST	.POPJ1			; Otherwise, give skip return

TWAI.1:
TOPS10,<
; Get the current system uptime, and determine what the uptime should
;be when the timer is to expire

	MOVX	T1,%CNSUP		; Get the system uptime
	GETTAB	T1,			;  .  .  .
	 SETZ	T1,			; Assume system isn't up
	MOVM	T2,P1			; Get the time to wait in milli-seconds
	MUL	T2,JIFSEC		; Convert to jiffies
	DIVX	T2,^D1000		;  .  .  .
	ADD	T1,T2			; Get the uptime when we wish to continue
	MOVE	P3,T1			; Get the final time
	MOVE	P4,T3			; And the extra milli-seconds after that

; Now enter the loop to check for correct time

TWAI.2:	MOVX	T1,%CNSUP		; Get the current uptime
	GETTAB	T1,			;  .  .  .
	 MOVX	T1,.INFIN		; Assume we have been up forever
	SUBM	P3,T1			; No, get the amount left to wait
	JUMPLE	T1,TWAI.3		; If we hit end time, go check remaining milli-seconds
	MULX	T1,^D1000		; Convert to milli-seconds
	DIV	T1,JIFSEC		;  .  .  .
	CAXLE	T1,^D<68*1000>		; More than the max wait time?
	 MOVX	T1,^D<68*1000>		; Yes, use the max
	JUMPL	P1,.+2			; Wait to wake on TTY input?
	 TXO	T1,HB.RTC		; Yes, flag that
	TXO	T1,HB.RWJ		; Don't allow anyone else to wake us
	HIBER	T1,			; Wait for a while
	 JRST	[IDIVI	T1,^D1000		; Make number of seconds to wait
		SLEEP	T1,			; Do it
		JRST	.+1]			; And continue
	JUMPL	P1,TWAI.2		; If we don't want to wake for input, check time
	SKIPE	T1,P2			; Get the number of characters to check for
	 PUSHJ	P,T$CHKI		; Check if that much input
	  JRST	TWAI.2			; No, wait some more
	PJRST	.POPJ1			; Else, all done

; Here when jiffy portion of timing runs out.  Check for input (maybe), and
;wait the rest of the fractional jiffies (milli-seconds)

TWAI.3:	JUMPN	T1,TWAI.6		; If we are already a jiffy past, skip this
	JUMPL	P1,TWAI.4		; If want to wait without checking input, skip this
	SKIPE	T1,P2			; Otherwise, get the character count
	 PUSHJ	P,T$CHKI		; And check if available
	  JRST	TWAI.4			; Not there yet
	PJRST	.POPJ1			; Got them, return now

; Here to wait the final milli-seconds.

TWAI.4:	MSTIME	P3,			; Get the current time
	ADD	P3,P4			; Plus the amount we want to wait

TWAI.5:	MSTIME	T1,			; Get the current time
	SUBM	P3,T1			; Get the amount left to wait
	JUMPLE	T1,TWAI.6		; All done waiting
	JUMPL	P1,.+2			; Abort on input?
	 TXO	T1,HB.RTC		; Yes, get the flag
	TXO	T1,HB.RWJ		; Otherwise only allow our job
	HIBER	T1,			; Wait a little
	 JFCL				; Old monitor can run us this far?
	JUMPL	P1,TWAI.5		; See if timer expired
	SKIPE	T1,P2			; Get the number of chars we are waiting for
	 PUSHJ	P,T$CHKI		; Check if they are here yet
	  JRST	TWAI.5			; No, check timer
	PJRST	.POPJ1			; Yes, all done

; Here when timer has expired completely.  Just check if the desired
;characters are available

TWAI.6:	JUMPE	P2,.POPJ1		; 0 characters are always available now
	MOVE	T1,P2			; Otherwise get the count
	PJRST	T$CHKI			; And check what we have
> ; End of TOPS10

TOPS20,<
;****** Do something
> ; End of TOPS20
	SUBTTL	T$CHKI - Check for input availability

;+
;.HL1 T$CHKI
; This routine will check if there are a given number of characters of
;terminal input available.
;.b.lit
;
; Usage:
;	T1/ Number of characters to check for
;	PUSHJ	P,T$CHKI
;	 (return, characters not available)
;	(return, characters available)
;
;.end lit
;-

T$CHKI:	LOAD.	T2,TPTADR,+$QRTPT+TTIBUF ; Get the address of the buffer
	CFML.	,BLKEND,(T2),T1		; Have as many chars as we are looking for?
	 PJRST	.POPJ1			; Yes, all done
TCHK.0:	PUSHJ	P,T$RBUF		; No, read into the buffer some more (if anything there)

	LOAD.	T2,TPTADR,+$QRTPT+TTIBUF ; Get the address of the buffer
	CFML.	,BLKEND,(T2),T1		; Have as many chars as we are looking for?
	 AOS	(P)			; Yes, give skip return
	POPJ	P,			; All done
	SUBTTL	T$CTYI - Check for type-ahead

;+
;.hl1 T$CTYI
; This routine will check if there has been any type-ahead at all.
;It is mainly used by the screen update processing to determine is an update
;should be aborted.
;.b.lit
;
; Usage:
;	PUSHJ	P,T$CTYI
;	 (return, no type ahead)
;	(return, characters have been typed)
;
;.end lit
;-

T$CTYI:	SKPINC				; Check if monitor has some characters
	 JRST	TCTY.1			; No, check if any in buffer
	PJRST	.POPJ1			; Yes, return

TCTY.1:	PUSH	P,T1			; Save T1
	LOAD.	T1,TPTADR,+$QRTPT+TTIBUF ; Get the address of the buffer
	CFXE.	,BLKEND,(T1),0		; Anything in the buffer?
	 AOS	-1(P)			; Yes, bump return address
	POP	P,T1			; Restore T1
	POPJ	P,			; And return
	SUBTTL	T$TCHR - Type a character dependant upon ET value

;+
;.hl1 T$TCHR
; This routine will type a character from CH. How the character
;is typed depends upon the ET value. If ET=0 then the character
;will be typed literally if it is between a space and an underscore
;(back arrow), or if it is a control-character between a tab
;and a carriage return. Otherwise, it with either be typed as ^char
;(if is a control-char) or $ (for altmode) or possible as a case flagged character
;(depending on the EU value and the terminals LC bit.)
;-

T$TCHR:	MOVE	T1,ETVAL	; Get the ET value
	JRST	@ETDSP(T1)	; Dispatch to the correct routine

; Dispatch routine depending on the ET value

ETDSP:	EXP	TYPCHR		; ET = 0
	EXP	TYPLIT		; ET = 1
	EXP	TYPIMG		; ET = 2

	SUBTTL	T$ACHR - Type a character for ^A command

;+
;.hl1 T$ACHR
; This routine will type a character respecting the ET value
;but not the EU value.
;-

T$ACHR:	MOVE	T1,ETVAL	; Get the ET value
	JRST	@T$ATBL(T1)	; And do the right thing

T$ATBL:	EXP	T$OCHR		; Type the character without flagging
	EXP	TYPLIT		; Literal typeout
	EXP	TYPIMG		; Image typeout
	SUBTTL	TYPCHR - Type out for ET = 0

;+
;.hl1 TYPCHR
; This routine will type out a character if the ET value is 0.
;It will respect the EU value for case flagging.
;-

TYPCHR:	PUSHJ	P,ALTEO		; Convert altmodes as needed
	TXNE	S,S.LCTT	; Lower case terminal?
	 PJRST	T$OCHR		; Yes, no case flagging needed
	SKIPGE	T1,TYCASF	; No, get the EU value
	 PJRST	T$OCHR		; EU = -1 means no case flagging
	CAXGE	CH,"`"		; Lower case range character?
	 JRST	TYPC.1		; No, check if upper case range
	JUMPN	T1,T$OCHR	; If EU = 1 no lower case flagging

TYPC.0:	PUSH	P,CH		; Must flag character, save it
	MOVX	CH,"'"		; Get the flag character
	PUSHJ	P,@TY.OBY	; Output it
	MOVE	CH,(P)		; Get the character back
	TXZ	CH,"A"^!"a"	; Convert to upper case
	PUSHJ	P,@TY.OBY	; Type it
	POP	P,CH		; Restore the character
	POPJ	P,		; And return

TYPC.1:	CAXGE	CH,"@"		; Upper case range character?
	 PJRST	T$OCHR		; No, go type it
	JUMPE	T1,T$OCHR	; Yes, just type if EU = 0
	JRST	TYPC.0		; Must flag the character

	SUBTTL	TYPLIT - Type out for ET = 1

;+
;.hl1 TYPLIT
; This routine will type out a character if the ET value is 1.
;It will simply put the character into the output buffer.
;-

TYPLIT:	PJRST	@TY.OBY		; Output a byte
	SUBTTL	TYPIMG - Type out for ET = 3

;+
;.hl1 TYPIMG
; This routine will type out a character in image mode.
;The character will be typed with odd parity and also put into the
;log file if the user requested.
;-

TYPIMG:	TXNE	S,S.SLOG	; Want this?
	 TXNN	S,S.LOUT	; Logging output?
	  JRST	.+2		; No, skip this
	PUSHJ	P,LOGCHR	; Yes, put it in the log file

	TXZE	F,F.TYOF	; Need to output the buffer first?
	 PUSHJ	P,TTYOUT	; Yes, force it so things are in the correct order
	SKIPL	CHRFLG(CH)	; Need a parity bit on?
	 TRO	CH,200		; Yes, turn it on

	IONEOU	CH		; Output the character
	TRZ	CH,200		; Make sure character is back correctly
	POPJ	P,		; And return
	SUBTTL	T$OCHR - Type out routine for messages

;+
;.hl1 T$TOCHR
; This routine will type out a character with control-character
;conversion, but no case flagging. It is used for error message
;type out and for re-printing the commands for ^G<space> or ^G., or
;when backspacing makes it necessary to retype the command.
;-

T$OCHR:	CAXE	CH,.CHTAB	; Tab's go literally
	 CAIL	CH," "		; If greater than a space all is okay
	  PJRST	@TY.OBY		; Just go type the character
	CAXL	CH,.CHCNH	; Is this between a backspace
	 CAXLE	CH,.CHCRT	; And a carriage return?
	  JRST	T$OC.1		; No, check for altmode
	CAXE	CH,.CHLFD	; Line feeds
	 CAXN	CH,.CHCRT	; And carriage returns
	  PJRST	@TY.OBY		; Always go literally
	JMPS	T$OC.2		; If screen mode, these all go as ^char
	CAXE	CH,.CHCNH	; Control-H?
	 JRST	@TY.OBY		; Or literally for non-screen
	TXNE	CRT,CR$TTY	; TTY type terminal
	 JRST	T$OC.2		; Yes, go type the ^H
	PJRST	@TY.OBY		; No, type literally


T$OC.1:	CAXE	CH,.CHESC	; Is this an escape?
	 JRST	T$OC.2		; No, must use ^char form
	MOVX	CH,"$"		; Yes, use a dollar sign
	PUSHJ	P,@TY.OBY	; Output it
	MOVX	CH,.CHESC	; And restore the escape
	POPJ	P,		; And return

T$OC.2:	PUSH	P,CH		; Here to type as ^char
	MOVX	CH,"^"		; Get the up-arrow
	PUSHJ	P,@TY.OBY	; Type it
	MOVE	CH,(P)		; Get the character back
	ADDX	CH,"A"-.CHCNA	; Convert to correct character
	PUSHJ	P,@TY.OBY	; Output it
	POP	P,CH		; Get the character back
	CAXE	CH,.CHBEL	; Was it a bell?
	 POPJ	P,		; No, just return
	TXON	S,S.SLOG	; Already suppressing log file?
	 PUSH	P,[[TXZ S,S.SLOG		; No, remember to clear the flag
		POPJ	P,]]		; And return
	PJRST	@TY.OBY		; And output the character
	SUBTTL	T$OBUF - Output a character in buffered mode

;+
;.hl1 T$OBUF
; This routine will output a character into the terminal output
;buffer. It will also send the character to the log file if
;the user has request type out be logged.
;If the character should not go to the log file either S.SLOG should
;be on or T$OB.0 should be called.
;-


T$OBUF:	TXNN	S,S.SLOG	; Log stuff suppressed?
	 TXNN	S,S.LOUT	; Write in log file also?
	  JRST	.+2		; No log wanted
	PUSHJ	P,LOGCHR	; Yes, do it

T$OB.0:	SKPOPN	TTYFDB		; Terminal open?
	JRST	[OUTCHR CH		; No, just output the character
		POPJ	P,]		; And return
T$OB.2:	TXO	F,F.TYOF	; Flag we have to output the buffer
	SOSL	.FDBRH+.BFCTR+TTYFDB ; Count the byte
	 JRST	T$OB.1		; Have room, go write it
	PUSHJ	P,TTYOUT	; No room, write the buffer
	JRST	T$OB.2		; And try again

T$OB.1:	SKIPL	CHRFLG(CH)	; Need parity bit on?
	 TRO	CH,200		; Yes, do so
	IDPB	CH,.FDBRH+.BFPTR+TTYFDB ; Store the character
	TRZ	CH,200		; Clear the parity bit
	CAXLE	CH,.CHLFD	; Is this less than a line feed
	  POPJ	P,		; No,  Return
	FALL	TTYOUT		; Yes, go output the buffer
	SUBTTL	TTYOUT - Output the TTY buffer

;+
;.hl1 TTYOUT
; This routine will force the monitor to type the terminal
;output buffer on the users terminal.
;-

TTYOUT:	$SAVE	<CH,T1>		; Save CH, T1 and T2
	LOAD.	T1,FDBCHN,+TTYFDB ; Get the channel number
	SETZ	CH,		; Clear this
	STOR	T1,CH,FO.CHN	; Store the channel number
	HRRI	CH,.FOOUT	; Get the function
	MOVE	T1,[XWD 1,CH]	; Get the argument pointer
	FILOP.	T1,		; Do it
	  JFCL			; Don't care
	TXZ	F,F.TYOF	; No longer need to output
	POPJ	P,
	SUBTTL	Output routines -- .TCRLF - Output a CRLF

;+
;.HL1 .TCRLF
;This routine will output a carriage return and a line feed.
;-

.TCRLF:	MOVEI	CH,.CHCRT	; Get the first character
	PUSHJ	P,T$OCHR	; Output it
	MOVX	CH,.CHLFD	; Get the second
	PJRST	T$OCHR		; Output it and return
	SUBTTL	$STRING routines -- T$TYPE

;+
;.hl1 $STRING routines
; These routines handle the output of the text string generated by
;the $STRING macro.
;.hl2 T$TYPE
; This is the main entry point for the $STRING routines. There is an alternate
;entry into this routine at T$ERTY if the ac's have already been saved.
;.b
;.literal
; Usage:
;	MOVEI	T1,Address.of.string
;	PUSHJ	P,T$TYPE
;	 (return)
;
;.end literal
;-

T$TYPE:	$SAVE	<TYPEAC,TYPEAC+T1,TYPEAC+T2,TYPEAC+T3,TYPEAC+T4,TYPEAC+P1,
		TYPEAC+P2,TYPEACT+P3,TYPEAC+P4,TYPEAC+A1,TYPEAC+A2,TYPEAC+CH,
		TGCRTN,EOSCRL,COLUMN,LFTMAR,STRTMP,TYPOUT,TLSTCH> ; Save necessary items
	MOVEM	T2,TYPEAC+T2	; Save T2
	MOVE	T2,[XWD T3,TYPEAC+T3] ; Get the pointer to save the ac's
	BLT	T2,TYPEAC+CH	; And save through P4
	PUSHJ	P,T$ERTY	; Type the string
	MOVE	CH,[XWD TYPEAC+T2,T2] ; Get the BLT pointer
	BLT	CH,CH		; And restore the ac's
	POPJ	P,		; And return

T$ERTY:	SETZM	COLUMN		; Put at left margin
	SETZM	LFTMAR		; Clear the left margin
	SETOM	EOSCRL		; Flag we want a CRLF at the end of the string
	SETZM	TYPOUT		; Flag type on terminal
	MOVEI	T2,[OUTCHR	CH	; Get desparation type out routine
		POPJ	P,]		; In case the terminal is open yet
	SKPOPN	TTYFDB		; If terminal is open, all is fine
	 MOVEM	T2,TYPOUT	; No, use the OUTCHR
T$TY.S:	SETZM	TLSTCH		; No last character
	HLRZM	T1,TGCRTN	; Save the get-a-char routine
	TXNE	T1,LH.ALF	; Have a get a thing routine?
	 HRRZM	T1,TYPOUT	; Yes, save the address
	SKIPE	TGCRTN		; Did we get a routine?
	 TDZA	T1,T1		; No, for T1 clear
	HRLI	T1,(POINT 7,)	; Set up the byte pointer
	MOVE	P1,T1		; And copy into P1
T$TY.0:	PUSHJ	P,T$TGCH	; Get a character
	CAXE	CH,$TFBEG	; Is it the prefix character?
	 JRST	T$TY.0		; No, skip until we find it
	PUSHJ	P,T$TGCH	; Get a character
	JUMPE	CH,.-1		; Skip nulls
	CAXLE	CH,$TFMAX	; Small enough?
	 STOPCD	(BSF,<Bad $STRING function>)
	MOVE	T1,STRFNC-$TFBEG(CH) ; Get the table entry
	TXNN	T1,TF$ARG	; Need an arg?
	 JRST	T$TY.5		; No, skip this
	SETZ	P2,		; Clear the word to build the address
	MOVE	T3,[POINT 7,P2,7] ; And set up to build it
	MOVEI	T4,4		; Get the count
T$TY.9:	PUSHJ	P,T$TGCH	; Get a character
	IDPB	CH,T3		; And store it
	SOJG	T4,T$TY.9	; Loop for all the chars
; Calculate the effective address, using the callers ac's if
;necessary.

T$TY.1:	LOAD	T2,P2,IW.IDX	; Get the index field
	JUMPE	T2,T$TY.2	; Have one?
	CAIG	T2,CH		; Is is an ac we have saved?
	 SKIPA	T2,TYPEAC(T2)	; Yes, get the value from the block
	  MOVE	T2,(T2)		; No, just get the value from the AC
T$TY.2:	LOAD	T3,P2,IW.ADR	; Get the address field
	ADD	T2,T3		; Get the total
	TXNN	P2,IW.IND	; Is the indirect bit on?
	 JRST	T$TY.4		; No, go store the address
	TXZ	T2,LH.ALF	; Clear the left half
	CAIG	T2,CH		; Saved ac?
	 MOVEI	T2,TYPEAC(T2)	; Yes, point to the right thing
	MOVE	P2,(T2)		; Get the word
	JRST	T$TY.1		; And go around again

T$TY.4:	TXNE	T1,TF$IMM	; Immediate address type function?
	 JRST	T$TY.5		; Yes, skip this
	CAIG	T2,CH		; Need to relocate to saved ac's?
	 MOVEI	T2,TYPEAC(T2)	; Yes, get the correct address
T$TY.5:	PUSHJ	P,(T1)		; And call the right routine
	 JRST	T$TY.0		; Loop until we get the end of string
	POPJ	P,		; And return
	SUBTTL	$STRING routines -- T$TGCH - Get a character from the string

;+
;.hl2 T$TGCH
; This routine will get a character from the string.
;-

T$TGCH:	SETZ	CH,		; Clear the last character
	EXCH	CH,TLSTCH	; Get it
	JUMPN	CH,.POPJ	; And return it if we have one
	SKIPE	TGCRTN		; Have a routine to call?
	 PJRST	@TGCRTN		; Yes, go do it
	ILDB	CH,P1		; No, just get a character
	POPJ	P,		; And return
	SUBTTL	$STRING routines -- STRFNC - Function table

; This table contains the flags and dispatch addresses for the $STRING
;functions.

STRFNC:
	DEFINE TT(CHAR,FLAGS,STRING),<EXP FLAGS+T$T.'CHAR>
	TXTTYP			; Expand the macro
	SUBTTL	$STRING routines -- T$T.E - Type a DOSTR table

;+
;.hl2 T$T.E
;This routine will type a DOSTR table.  It will call T$T.T to do all the
;hard work.
;-

T$T.E:	$SAVE	<P1>		; Save a register
	MOVE	P1,(T2)		; Copy the pointer to the table
	JRST	T$TE.1		; Enter the loop

T$TE.0:	MOVEI	CH,","		; Get the character to output
	PUSHJ	P,T$CHAR	; Output the character
	MOVEI	CH," "		; And a space
	PUSHJ	P,T$CHAR	;  .  .  .

T$TE.1:	MOVE	T1,@(P1)	; Get the byte pointer to the first string
	PUSHJ	P,T$TA.1	; Output the string
	AOBJN	P1,T$TE.0	; Loop for all entries
	POPJ	P,		; Return to the caller
	SUBTTL	$STRING routines -- T$T.T - Type an ASCIZ string

;+
;.hl2 T$T.T
; This routine will cause the ASCIZ string pointed to by the address
;to be typed out.
;-

T$T.T:	MOVE	T1,T2		; Get the address
	HRLI	T1,(POINT 7,)	; Get the byte pointer into it
	JRST	T$TA.1		; And join common routine

T$T.B:	MOVE	T1,(T2)		; Get the address of the string
T$TA.1:	$SAVE	<P1>		; Save P1
	MOVE	P1,T1		; And get the byte pointer
T$TA.2:	ILDB	CH,P1		; Get the character
	JUMPE	CH,.POPJ	; Just return if it is a null
	PUSHJ	P,T$CHAR	; Otherwise type the character
	JRST	T$TA.2		; And loop for entire string
	SUBTTL	$STRING routines -- T$T.C - Type an ASCIZ string with special characters

;+
;.HL2 T$T.C
; This routine will cause the ASCIZ string pointed to by the address to
;be typed out.  Any special characters will be typed as <xxx> where xxx
;is the name of the special character.
;-

T$T.C:	$SAVE	<P1>		; Save P1
	MOVE	P1,T2		; Get the address
	HRLI	P1,(POINT 7)	; Build the full byte pointer
T$TC.0:	ILDB	CH,P1		; Get the character
	JUMPE	CH,.POPJ	; Give a normal return
	PUSHJ	P,T$FCHR	; Type a funny character
	JRST	T$TC.0		; Loop for the next character
	SUBTTL	$STRING routines -- T$T.O - Type an unsigned octal number

;+
;.hl2 T$T.O
; This routine will type the value pointed to by the address to be typed
;out as an unsigned octal number.
;-

T$T.O:	SKIPL	T1,(T2)		; Get the value
	 JRST	T$TO.0		; Not negative, skip the sign
	MOVEI	CH,"-"		; Get the minus sign
	PUSHJ	P,T$CHAR	; Type the sign
	MOVN	T1,(T2)		; Get the positive value
T$TO.0:	SETZB	T2,T3		; Clear T2 and T3

T$TO.1:	IDIVI	T1,^D8		; Get the digit
	PUSH	P,T2		; Save it
	AOJ	T3,		; And count it
	JUMPN	T1,T$TO.1	; And loop for all the digits
T$TO.2:	POP	P,CH		; Get the digit back
	ADDX	CH,"0"		; Make it an ascii character
	PUSHJ	P,T$CHAR	; And type the character
	SOJG	T3,T$TO.2	; Loop for all the chars
	POPJ	P,		; And return
	SUBTTL	$STRING routines -- T$T.D - Type a decimal number

;+
;.hl2 T$T.D
; This routine will type the value as a decimal number.
;-

T$T.D:	SKIPL	T1,(T2)		; Is the value negative?
	 JRST	T$TD.0		; No, skip this
	MOVEI	CH,"-"		; Get the minus sign
	PUSHJ	P,T$CHAR	; And type it
	MOVN	T1,(T2)		; And get the value as positive
T$TD.0:	IDIVI	T1,^D10		; Get a digit
	PUSH	P,T2		; Save it
	JUMPE	T1,.+2		; Done?
	 PUSHJ	P,T$TD.0	; No, get the next
	POP	P,CH		; Get the digit back
	ADDX	CH,"0"		; Make it ASCII
	PJRST	T$CHAR		; And type the character
	SUBTTL	$STRING routines -- T$T.F - Type a file spec from an FDB

;+
;.hl2 T$T.F
; This routine will type out a complete file spec from an FDB.
;-

T$T.F:	$SAVE	<P1>		; Save some ac's
	MOVE	P1,(T2)		; Get the arg address
	CFXN.	,FDBNOD,(P1),0	; Have a node?
	 JRST	T$TF.1		; No, skip this
	MOVEI	T2,.FDNOD(P1)	; Yes, get the address
	PUSHJ	P,T$T.W		; Type it
	PUSHJ	P,T$COLN	; Type a colon
	PUSHJ	P,T$COLN	; And another

T$TF.1:	CFXN.	,FDBDEV,(P1)	; Have a device
	 JRST	T$TF.2		; No, skip it
	MOVEI	T2,.FDDEV(P1)	; Yes, get the address
	PUSHJ	P,T$T.W		; And type it
	PUSHJ	P,T$COLN	; And type the colon

T$TF.2:	MOVEI	T2,.FDNAM(P1)	; Get the address of the name
	PUSHJ	P,T$T.W		; Type it
	MOVX	T1,FD.HEX	; Check if we have an extension
	TDNN	T1,.FDFLG(P1)	; No, skip it
	 JRST	T$TF.3		;  .  .  .
	PUSHJ	P,T$DOT		; Yes, print a dot
	CFXN.	T1,FDBEXT,(P1),0 ; Have an extension?
	 JRST	T$TF.3		; No, skip this
	LOADS.	T1,FDBEXT,(P1)	; Get the extension
	MOVEM	T1,STRTMP	; Save it in the temp
	MOVEI	T2,STRTMP	; Get the address
	PUSHJ	P,T$T.W		; Type the string
T$TF.3:	MOVX	T1,FD.PTH	; Get the bit to check
	TDNN	T1,.FDFLG(P1)	; Check if we have a path
	 JRST	T$TF.4		; No, skip this
	MOVEI	T1,.FDPPN-.PTPPN(P1) ; Get the address of the path
	MOVEM	T1,STRTMP	; Save it
	MOVEI	T2,STRTMP	; Get the address
	PUSHJ	P,T$T.P		; And type the PPN and path
T$TF.4:	CFXN.	T1,FDBPRO,(P1),0 ; Have a protection to type?
	 JRST	T$TF.5		; No, skip it
	MOVEI	T2,[ASCIZ | /PROTECTION:|] ; Get the text
	PUSHJ	P,T$T.T		; List it
	LOAD.	T3,FDBPRO,(P1)	; Get the protection
	MOVEI	CH,"0"		; See if we need leading zeros
	CAIGE	T3,100		; Will it print three digits?
	 PUSHJ	P,T$CHAR	; No, print the first zero
	MOVEI	CH,"0"		; Get the zero back
	CAIGE	T3,10		; Will it print two digits?
	 PUSHJ	P,T$CHAR	; No, print the second zero
	MOVEM	T3,STRTMP	; Save the value
	MOVEI	T2,STRTMP	; Get the address
	PUSHJ	P,T$T.O		; And type the number

T$TF.5:	CFXN.	T1,FDBVER,(P1),0 ; Have a version number?
	 JRST	T$TF.6		; No, skip it
	MOVEI	T2,[ASCIZ | /VERSION:|] ; Get the text
	PUSHJ	P,T$T.T		; And tell him what this is
	MOVEI	T2,.FDVER(P1)	; Get the version address
	PUSHJ	P,T$T.V		; And list it

T$TF.6:	CFXN.	T1,FDBMOD,(P1),0 ; Have a non-default mode?
	 JRST	T$TF.7		; No, skip this
	MOVEI	T2,[ASCIZ | /MODE:|] ; Get the text
	PUSHJ	P,T$T.T		; And type it
	LOAD.	T1,FDBMOD,(P1)	; Get the mode
	MOVEI	T2,MODKEY(T1)	; Get the address of the sixbit
	PUSHJ	P,T$T.W		; Type the keyword

T$TF.7:	POPJ	P,		; And return
	SUBTTL	$STRING routines -- T$T.G - Type a Q-register name

;+
;.HL2 T$T.G
;This routine will type a Q-register name.  It gets the name
;from the QRG block supplied as the argument.
;-

T$T.G:	MOVE	T2,(T2)		; Get the Q-reg address
	MOVE	T1,$QRFLG(T2)	; Get the flags
	TXNE	T1,QR$PRD!QR$LQR ; Predefined or user long name?
	 JRST	T$T.G0		; Yes, go check which
	MOVE	CH,$QRQRN(T2)	; No, get the name
	JRST	T$CHAR		; Enter the common routine

; Here if the name is not a single character

T$T.G0:	TXNN	T1,QR$LQR	; User defined long name?
	 JRST	[MOVE	T1,$QRQRN(T2)	; No, must be predefined
		PJRST	T$TA.1]		; So go type it
	$SAVE	<P1,P2>		; Save P1
	LOAD.	P1,TPTADR,+$QRQRN(T2) ; Get the address of the STE
	LOAD.	P2,SYMCNT,(P1)	; Get the count of the number of characters
	ADDX	P1,<POINT 7,$SYNAM> ; Make a byte pointer

T$T.G1:	ILDB	CH,P1		; Get the character
	PUSHJ	P,T$CHAR	; Output the character
	SOJG	P2,T$T.G1	; Loop back
	POPJ	P,		; Return
	SUBTTL	$STRING routines -- T$T.7 - Type an ascii character

;+
;.hl2 T$T.7
; This routine will type a single ASCII character from the address given.
;-
T$T.8:	MOVE	CH,(T2)		; Get the character
	PJRST	T$CHAR		; And type it

T$T.7:	MOVE	CH,(T2)		; Get the character
T$FCHR:	MOVSI	T2,-FNYLEN	; Build the byte pointer
T$T7.0:	CAMN	CH,FNYTBL(T2)	; Is this the character
	 JRST	T$T7.1		; Yes - Continue
	AOBJN	T2,T$T7.0	; Loop until we fail or find it
	PJRST	T$CHAR		; Output the character


T$T7.1:	PUSHJ	P,T$T.A		; Output the left angle bracket
	HRRI	T2,FNYTXT(T2)	; Get the address
	PUSHJ	P,T$T.T		; Output the string
	PJRST	T$T.R		; Output the closing bracket

DEFINE	FNYCHR,<
FC	.CHNUL,NULL
FC	.CHBEL,BELL
FC	.CHVTB,VT
FC	.CHTAB,TAB
FC	.CHCRT,CR
FC	.CHFFD,FF
FC	.CHESC,ESC
FC	.CHLFD,LF
> ; End of FNYCHR macro definition

DEFINE	FC(CHAR,TEXT),<EXP	CHAR>

FNYTBL:	FNYCHR			; Expand the characters
 FNYLEN==.-FNYTBL		; Determine the lenght of the table

; Expand the text

DEFINE	FC(CHAR,TEXT),<ASCII |'TEXT'|>
FNYTXT:	FNYCHR			; Expand the text
	SUBTTL	$STRING routines -- T$T.6 - Type a SIXBIT character

;+
;.hl2 T$T.6
; This routine will type a single SIXBIT character from the address given.
;-

T$T.6:	MOVE	CH,(T2)		; Get the character
	ADDX	CH,"A"-'A'	; Convert to ascii
	PJRST	T$CHAR		; And type it
	SUBTTL	$STRING routines -- T$T.P - Type a PPN or path

;+
;.hl2 T$T.P
; This routine will type out a PPN from the address or a complete path
;if the address contains the address of a path block.
;-

T$T.P:	$SAVE	<P1,P2>		; Save P1
	MOVE	P1,(T2)		; Get the arg
	JUMPE	P1,.POPJ	; Just return if null
	TXNN	P1,LH.ALF	; Have an address?
	 SKIPE	.PTPPN(P1)	; Yes, is the ppn in the block zero?
	  JRST	.+2		; Must type it
	   POPJ	P,		; No, just return
	MOVEI	CH,"["		; Get the open bracket
	PUSHJ	P,T$CHAR	; And type it
	SETZ	P2,		; Clear in case no path
	TXNE	P1,LH.ALF	; Have just a PPN
	 JRST	T$TP.1		; Yes, go handle it
	HRLI	P2,<.PTPPN-.PTMAX> ; Get the number of words
	HRRI	P2,.PTPPN(P1)	; And point to the first one
	MOVE	P1,(P2)		; Get the PPN
T$TP.1:	JUMPGE	P1,T$TP.2	; SIXBIT PPN?
	MOVEM	P1,STRTMP	; Yes, save it
	MOVEI	T2,STRTMP	; And get the address
	PUSHJ	P,T$T.W		; And type it
	JRST	T$TP.3		; Go handle the rest

T$TP.2:	HLRZM	P1,STRTMP	; Save the project number
	MOVEI	T2,STRTMP	; Get the address
	PUSHJ	P,T$T.O		; And type it
	PUSHJ	P,T$COMA	; Type a comma
	HRRZM	P1,STRTMP	; Save the programmer number
	MOVEI	T2,STRTMP	; Get the address
	PUSHJ	P,T$T.O		; Type the programmer number

T$TP.3:	AOBJP	P2,T$RBRK	; Type a right bracket if done
	SKIPE	(P2)		; Have an SFD?
	 JRST	T$TP.4		; Yes, go type it
T$RBRK:	MOVEI	CH,"]"		; No, get the character
	PJRST	T$CHAR		; And type the closing bracket


T$TP.4:	PUSHJ	P,T$COMA	; Type a comma
	MOVEI	T2,(P2)		; Get the address
	PUSHJ	P,T$T.W		; And type the word
	JRST	T$TP.3		; Loop for all the SFD's
	SUBTTL	$STRING routines -- T$T.W - Type a SIXBIT word

;+
;.hl2 T$T.W
; This routine will type a single SIXBIT word.
;-

T$T.W:	SKIPN	T3,(T2)		; Get the word
	 POPJ	P,		; Return if nothing to type

T$TW.1:	SETZ	T2,		; Clear T2
	LSHC	T2,6		; Get a character
	MOVEI	CH,"A"-'A'(T2)	; Get the character
	PUSHJ	P,T$CHAR	; Type it
	JUMPN	T3,T$TW.1	; Loop for all of the charas
	POPJ	P,		; And return


	SUBTTL	$STRING routines -- T$T.5 - Type an ASCII word

;+
;.hl2 T$T.5
; This routine will type a single ASCII word.
;-

T$T.5:	MOVE	T3,(T2)		; Get the word
	TXZ	T3,1B35		; Clear the LSN bit
	JUMPE	T3,.POPJ	; Return if nothing to type
T$T5.1:	SETZ	T2,		; Clear T2
	LSHC	T2,7		; Get a character
	MOVE	CH,T2		; Get the character
	PUSHJ	P,T$CHAR	; Type it
	JUMPN	T3,T$T5.1	; Loop for all the chars
	POPJ	P,		; And return
	SUBTTL	$STRING routines -- T$T.M - Type a carriage return


;+
;.hl2 T$T.M
; This routine will type a carriage return (no line feed).
;-

T$T.M:	MOVX	CH,.CHCRT	; Get the character
	PJRST	T$CHAR		; And type it


	SUBTTL	$STRING routines -- T$T.J - Type a line feed

;+
;.hl2 T$T.J
; This routine will type a line feed.
;-

T$T.J:	MOVX	CH,.CHLFD	; Get the character
	PJRST	T$CHAR		; And type it

	SUBTTL	$STRING routines -- T$T.K - Type a vertical tab

;+
;.hl2 T$T.K
; This routine will type a vertical tab.
;-

T$T.K:	MOVX	CH,.CHVTB	; Get the character
	PJRST	T$CHAR		; And type it

	SUBTTL	$STRING routines -- T$T.L - type a form feed

;+
;.hl2 T$T.L
; This routine will type a form feed.
;-

T$T.L:	MOVX	CH,.CHFFD	; et the character
	PJRST	T$CHAR		; And type it
	SUBTTL	$STRING routines -- T$T.V - Type a version number

;+
;.hl2 T$T.V
; This routine will type out a version number in standard form.
;-

T$T.V:	$SAVE	<P1>		; Save this value
	MOVE	P1,(T2)		; Get the word
	LOAD	T1,P1,VR.VER	; Get the major version
	JUMPE	T1,T$TV.1	; Have it?
	MOVEM	T1,STRTMP	; Save it
	MOVEI	T2,STRTMP	; Get the address
	PUSHJ	P,T$T.O		; And type it

T$TV.1:	LOAD	T1,P1,VR.MIN	; Get the minor version
	JUMPE	T1,T$TV.3	; Have it?
	IDIVX	T1,^D26		; Split into two digits
	JUMPE	T1,T$TV.2	; First digit there?
	MOVEI	CH,"A"-1(T1)	; Yes, convert to a letter
	PUSH	P,T2		; Save T2
	PUSHJ	P,T$CHAR	; And type the character
	POP	P,T2		; Get back the second digit

T$TV.2:	MOVEI	CH,"A"-1(T2)	; Get the seond digit
	PUSHJ	P,T$CHAR	; And list it

T$TV.3:	TXNN	P1,VR.EDT	; Have an edit level?
	 JRST	T$TV.4		; No, go handle who field
	MOVEI	CH,"("		; et a left paren
	PUSHJ	P,T$CHAR	; And type it
	LOAD	T1,P1,VR.EDT	; Get the edit
	MOVEM	T1,STRTMP	; Save the number
	MOVEI	T2,STRTMP	; Get the address
	PUSHJ	P,T$T.O		; Type it
	MOVEI	CH,")"		; Get the close paren
	PUSHJ	P,T$CHAR	; Type the lcose paren

T$TV.4:	TXNN	P1,VR.WHO	; Have a who field?
	 POPJ	P,		; No, return
	LOAD	T1,P1,VR.WHO	; Get the field
	MOVNM	T1,STRTMP	; Save in the temp
	MOVEI	T2,STRTMP	; Get the address
	PJRST	T$T.O		; And go type the value
	SUBTTL	$STRING routines -- T$T.0 - Insert a null

;+
;.hl2 T$T.0
; This routine will terminate a string with a null. No descriptors
;after it will be looked at.
;-

T$T.0:	SETZB	CH,EOSCRL	; Clear the character and the crlf flag
	PJRST	T$CHAR		; And go store the null


	SUBTTL	$STRING routines -- T$T.I - Set left margin

;+
;.hl2 T$T.I
; This routine will set the left margin to the given immediate
;value.
;-

T$T.I:	MOVE	T1,TRMWID	; Not a real CRT, get the width
	CAIL	T2,-20(T1)	; Is this too far left?
	 MOVEI	T2,-20(T1)	; Yes, use the max
	MOVEM	T2,LFTMAR	; Save the new left margin
	POPJ	P,		; And return
	SUBTTL	$STRING routines -- T$T.S - Type another $STRING

;+
;.hl2 T$T.S
; This routine will type another $STRING string.
;-

T$T.S:	$SAVE	<P1,LFTMAR,TGCRTN,TLSTCH> ; Save P1 for upper level
	MOVE	T1,T2		; Get the address of the string
	PJRST	T$TY.S		; And call ourself to process the string
	SUBTTL	$STRING routines -- T$T.Z - type a switch table

;+
;.hl2 T$T.Z
; This routine will type out a switch table given an AOBJx pointing to the
;names.
;-

T$T.Z:	$SAVE	<P1,P2>		; Save some working room
	MOVE	P1,(T2)		; Get the AOBJx
	JUMPGE	P1,.POPJ	; Just return if none
	SETO	P2,		; Flag no comma yet

T$TZ.1:	LDB	T2,[POINT 6,(P1),5] ; Get the first character
	CAXN	T2,'.'		; Is it a dot?
	 JRST	T$TZ.3		; Yes, skip it (internal place holder)
	AOJE	P2,T$TZ.2	; Need a comma?
	PUSHJ	P,T$COMA	; Yes, type it
	PUSHJ	P,T$SPAC	; Type a space

T$TZ.2:	MOVEI	T2,(P1)		; Get the address
	PUSHJ	P,T$T.W		; And type the word
T$TZ.3:	AOBJN	P1,T$TZ.1	; And loop for all the entries
	POPJ	P,		; Return
	SUBTTL	$STRING routines -- T$T.X - Set output routine

;+
;.hl2 T$T.X
; This routine will set the output a character routine to the address given.
;The routine will be called with the character to type in CH. It may smash
;only CH.
;-

T$T.X:	MOVEM	T2,TYPOUT	; Store the routine address
	POPJ	P,		; And return
	SUBTTL	$STRING routines -- T$T.INS - Type the following string

;+
;.hl2 T$T.INS
; This routine will type the string which follow after the function code.
;Call with the byte pointer in P1, returns updated P1.
;-

T$T.INS:PUSHJ	P,T$TGCH	; Get the next character
	CAXN	CH,$TFBEG	; Next byte a function
	 JRST	[MOVEM	CH,TLSTCH	; Save the character
		POPJ	P,]		; And return
	JUMPE	CH,T$T.INS	; Ignore nulls
	PUSHJ	P,T$CHAR	; No, type the character
	JRST	T$T.INS		; And loop until end
	SUBTTL	$STRING routines -- T$T.EOS - End the current string

;+
;.hl2 T$T.EOS
; This routine is called on the end of a string.
;-

T$T.EOS:SKIPN	EOSCRL		; Want a CRLF?
	 JRST	.POPJ1		; No, return
	PUSHJ	P,T$T.M		; Yes, type the carriage return
	AOS	(P)		; Force te skip return
	PJRST	T$T.J		; And type the line feed

	SUBTTL	$STRING routines -- T$T.BEG - Illegal

T$T.BEG:STOPCD	(T2I,<Type 2 function is illegal>)


	SUBTTL	$STRING routines -- T$T.N - Set no-carriage return

;+
;.hl2 T$T.N
; This routine will set so no carriage return is given at the end of the
;current string.
;-

T$T.N:	SETZM	EOSCRL		; Clear the flag for the crlf
	POPJ	P,		; And return
	SUBTTL	$STRING routines -- T$COLN - Type a colon

;+
;.hl2 T$COLN
; This routine will type a colon.
;-

T$COLN:	MOVEI	CH,":"		; Get the character
	PJRST	T$CHAR		; And go type the character


	SUBTTL	$STRING routines -- T$COMA - Type a comma

;+
;.hl2 T$COMA
; THis routine will type a comma.
;-

T$COMA:	MOVEI	CH,","		; Get the comma
	PJRST	T$CHAR		; And go type it


	SUBTTL	$STRING routines -- T$DOT - Type a period

;+
;.hl2 T$DOT
; This routine will type a period (dot).
;-

T$DOT:	MOVEI	CH,"."		; Get the character
	PJRST	T$CHAR		; And go type it
	SUBTTL	$STRING routines -- T$T.A - Type a left angle braket
	SUBTTL	$STRING routines -- T$T.R - Type a right angle bracket

;+
;.HL2 T$T.R and T$T.A
; These routines will type a right and left angle bracket.
;-

T$T.R:	SKIPA	CH,[EXP .CHRAB]	; Get a right angle bracket

T$T.A:	MOVX	CH,.CHLAB	; Get a left angle bracket
	PJRST	T$CHAR		; Type the character

	SUBTTL	$STRING routines -- T$T.Q - Type a double quote

;+
;.hl2 T$T.Q
; This routine will type a double quote.
;-

T$T.Q:	MOVX	CH,""""		; Get the character
	PJRST	T$CHAR		; And type it
	SUBTTL	$STRING routines -- T$SPAC - Type a space

;+
;.hl2 T$SPAC
; This routine will type a space.
;-

T$SPAC:	MOVEI	CH," "		; Get the character
	FALL	T$CHAR		; And fall into the routine


	SUBTTL	$STRING routines -- T$CHAR - Type the character in CH

;+
;.HL2 T$CHAR
; This routine will type a character. It will insert CRLF's as necessary
;to avoid wraparound if possible.
;-


T$CHAR:	SKIPE	TYPOUT		; Have a typeout?
	 JRST	@TYPOUT		; Yes, go use it
	$SAVE	<P1,P2>		; Save P1 and P2
	SETZ	P1,		; Clear the character width
	PUSHJ	P,ALTEO		; Convert altmodes
	CAXE	CH,.CHESC	; Is this an escape?
	 CAIL	CH," "		; This a normal character?
	  AOJA	P1,T$CH.9	; Yes, only one wide
	CAXN	CH,.CHTAB	; Is this a tab?
	 JRST	[MOVX	P1,7		; Yes, put at tab stop
		EXCH	P1,COLUMN	; Switch around
		IORM	P1,COLUMN	;  .  .  .
		SUB	P1,COLUMN	; Get the amount to move
		MOVN	P1,P1		; Make it positive
		JRST	T$CH.9]		; And go handle it
	CAXE	CH,.CHCNH	; Is this a backspace?
	 JRST	T$CH.7		; No, check other control chars
	TXNE	CRT,CR$TTY	; Is this a TTY?
	 JRST	T$CH.6		; Yes, make it two wide
	SOJA	P1,T$CH.9	; Otherwise it is minus one

T$CH.7:	CAXL	CH,.CHLFD	; Is this a line feed?
	 CAXLE	CH,.CHFFD	; Or other vertical positioning?
	  JRST	.+2		; No, try carriage return
	   JRST	T$CH.9		; Yes, zero wide
	CAXE	CH,.CHCRT	; Is this a carriage return?
T$CH.6:	 SKIPA	P1,[EXP 2]	; No, use two wide
	  MOVN	P1,COLUMN	; Yes, this puts the column to zero
T$CH.9:	PUSH	P,P1		; Save the width
	EXCH	P1,COLUMN	; Switch the column and width
	CAMG	P1,LFTMAR	; At the left margin?
	 CAIE	CH," "		; Yes, is this a space?
	  JRST	T$CH.8		; Must write the character
	MOVEM	P1,COLUMN	; Yes, reset the column
	POP	P,P1		; Get the value back
	POPJ	P,		; And return, ignoring the leading space

T$CH.8:	MOVE	P2,TRMWID	; Get the width from the monitor
	CAIL	P1,-20(P2)	; Getting near the right margin?
	 CAIE	CH," "		; A space?
	  JRST	T$CH.1		; No, go type the character
	POP	P,(P)		; Yes, get rid of the stacked value
	PUSHJ	P,.TCRLF	; Yes, type a crlf
	SETZM	COLUMN		; Clear the column
T$CH.0:	MOVEI	CH," "		; Get a space
	MOVE	P1,COLUMN	; Get the column number
T$CH.A:	CAML	P1,LFTMAR	; Hit the right place yet?
	 POPJ	P,		; Yes, return
	PUSHJ	P,T$OCHR	; No, type a space
	AOS	P1,COLUMN	; Bump the column
	JRST	T$CH.A		; And loop

T$CH.1:	MOVEM	P1,COLUMN	; Reset the column
	SKIPLE	(P)		; Don't indent for characters zero or negative wide
	CAML	P1,LFTMAR	; Need to indent?
	 JRST	T$CH.4		; No, just type the character
	PUSH	P,CH		; Save the character
	PUSHJ	P,T$CH.0	; Indent the proper amount
	POP	P,CH		; Get the character back

T$CH.4:	POP	P,P1		; Get rid of the character width
	ADDM	P1,COLUMN	; Reset the column
	PJRST	T$OCHR		; And type it
	SUBTTL	Low segment for TECTRM

	$IMPURE			; Do the impure storage
	LOWVER(TRM,3)		; Low segment version number for this module

; Terminal I/O buffers and blocks

TTYFDB:	BLOCK	.FDLEN		; FDB for the terminal
TRMUDX:	BLOCK	1		; UDX for the terminal
TRMSPD:	BLOCK	1		; Terminal speed from monitor
TRMSOP:	BLOCK	2		; TRMOP. block for skip if output present
TRMOCH:	BLOCK	4		; TRMOP. to use for image output
TRMTOC:	BLOCK	2		; TRMOP. block for getting number of chars in output buffer
ISOFLG:	BLOCK	1		; Flag to tell about image outstr status

; Flags

TYCASF:	BLOCK	1		; Type out case flag
				; 0 = Type ' before LC, + = Type ' before UC
				; - = Don't type '

; Terminal processing data

TY.OBY:	BLOCK	1		; Address of the routine to output a byte
TY.IBY:	BLOCK	1		; Address of the routine to input a byte
TY.OST:	BLOCK	1		; Address of the routine to output a string
TY.IST:	BLOCK	1		; Address of the routine to input a string

; Storage for $STRING routines

COLUMN:	BLOCK	1		; Current column for output
EOSCRL:	BLOCK	1		; Flag for CRLF at end of string
LFTMAR:	BLOCK	1		; Column for left margin
TYPEAC:	BLOCK	20		; Block for saving AC's during T$TYPE
				; routine
STRTMP:	BLOCK	1		; Temp for storing things we need the address of
TYPOUT:	BLOCK	1		; Address of routine to call for output
TGCRTN:	BLOCK	1		; Routine to fetch a character
TLSTCH:	BLOCK	1		; Character to be read again

ECHOFF:	BLOCK	1		; Flag whether echo is on or off
TRMWID:	BLOCK	1		; Terminal width from monitor
TRMLEN:	BLOCK	1		; Length of the terminal page
TRMTYP:	BLOCK	1		; Terminal type


; Peek ahead buffer

TTIBUF:	BLOCK	$QRLEN		; TERMINAL-INPUT-BUFFER Q-register
ICHINS:	BLOCK	1		; Instruction to get character from terminal
	SUBTTL	End of TECTRM

	END			; End of TECTRM