Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-12 - 43,50547/pltlib/v12/pltiod.mac
There are 2 other files named pltiod.mac in the archive. Click here to see a list.
SUBTTL	ALCOR and DECOR -- Set up disk (or TTY) buffers

;Routine to allocate core for buffers
;Calling sequence:
;	MOVEI	T1,(amount of core needed)
;	PUSHJ	P,ALCOR	
;	 *return*	Address of core returned in T1 or -1 if none
;			Uses T2 and T3

ALCOR:	MOVEI	T2,CORSIZ	;Assume first time here
	SKIPN	CORBUF		;Buffer in use?
	 MOVEM	T2,CORBUF	;First time here, entire buffer is free
	MOVEI	T2,1(T1)	;Get size + 1 (for the overhead word)
	MOVEI	T1,CORBUF	;Start at beginning

;The word pointed to by T1 is positive if the chunk is free, negative if used

ALCOR1:	CAMLE	T2,(T1)		;Will request fit in this chunk?
	 JRST	ALCOR2		;No
	MOVN	T3,T2		;Set to negative of size
	EXCH	T3,(T1)		;Mark this chunk as in use, get old free size
	SUB	T3,T2		;Decrement size of free space
	ADDI	T2,(T1)		;T2 now points past requested chunk
	MOVEM	T3,(T2)		;Store new free size
	ADDI	T1,1		;Point to the chunk (instead of overhead word)
	POPJ	P,		;Return with addr in T1

;Chunk is not big enough if (T1) is positive, chunk is in use if (T1) is
;negative, or CORBUF is full if (T1) is zero.

ALCOR2:	MOVM	T3,(T1)		;Get the overhead word
	JUMPE	T3,ALCOR3	;Have to ask FOROTS if hit end of CORBUF
	ADD	T1,T3		;Point to the next overhead word
	JRST	ALCOR1		;Try again

;Here when CORBUF is full, get memory from FOROTS

ALCOR3:	MOVEI	T1,-1(T2)	;Get the requested size into T1
	SKIPA	T2,[ALCOR.##]	;Addr of routine

DECOR2:	MOVEI	T2,DECOR.##	;Addr of routine
	MOVEM	T1,TEMP		;Store in memory
	MOVEI	L,[-1,,0	  ;1 arg
		INTEGER TEMP	  ;Address of arg
		]+1		;Point to args
	PUSHJ	P,(T2)		;Ask FOROTS to do core management
	MOVE	T1,0		;Result was in AC0
	POPJ	P,		;Return with result in T1
SUBTTL	ALCOR and DECOR -- Release disk (or TTY) buffers

;Routine to deallocate core for buffers
;Calling sequence:
;	MOVEI	T1,(addr returned from ALCOR)
;	PUSHJ	P,DECOR	
;	 *return*	
;			Uses T2 and T3

DECOR:	MOVEI	T1,-1(T1)	;Get addr of overhead word
	CAIL	T1,CORBUF	;Is this an addr in CORBUF?
	CAIL	T1,CORBUF+CORSIZ
	 JRST	DECOR2		;No, must be for FOROTS
	SKIPL	T2,(T1)		;Should have -SIZE
IFE FTDBUG,<POPJ P,>		;Bug, don't make things worse
IFN FTDBUG,<ERRSTR (<Problems in DECOR>)>
	MOVMS	(T1)		;Set -SIZE to +FREE
	MOVEI	T1,CORBUF	;Start with first chunk

;Try to consolidate contiguous free space, pointed to by T1

DECOR1:	MOVM	T2,(T1)		;Get -SIZE or +FREE
	ADDI	T2,(T1)		;Point to size word at start of next chunk
	SKIPN	(T2)		;ZERO at end of CORBUF?
	 POPJ	P,		;Yes, all done
	SKIPL	(T1)		;Is either chunk in use?
	SKIPG	(T2)
	 JRST	[MOVE	T1,T2     ;Yes, point to start of next chunk
		 JRST	DECOR1]	  ;Look for 2 ajacent free chunks
	MOVE	T3,(T2)		;No, get size on 2nd free chunk
	ADDM	T3,(T1)		;Add it into the size of the first chunk
	JRST	DECOR1		;See if next chunk is also free
SUBTTL	OUTDMP, OUTSTG, OUTWRD - Output a string of bytes

;Routine to output a string of bytes to plotter
;Call with byte pointer in T1, byte count in T2 (T2=0 if terminated by 0 byte)

OUTDMP:	PUSHJ	P,OUTSTG	;Output the string
	TXNE	P4,P4.TTY	;Output to a terminal?
	 PUSHJ	P,DUMPBF		;Yes, dump output buffer
	POPJ	P,

OUTSTG:	PUSH	P,T2		;Preserve T2
	MOVEI	T2,0		;ASCIZ string
	PUSHJ	P,OUTWRD	;Send the bytes
T2POPJ:	POP	P,T2		;Restore T2
	POPJ	P,		;Return


OUTWRD:	TLCE	T1,-1		;LH of pointer 0
	TLCN	T1,-1		; or -1?
	 HRLI	T1,(POINT 7,)	;Yes, default to 7-bit bytes
	PUSH	P,T1		;Store pointer

OUTST1:	ILDB	T1,(P)		;Get a byte
	SKIPG	T2		;If T2 started at zero,
	 JUMPE	T1,T1POPJ	; then stop at end of ASCIZ
	PUSHJ	P,OUTBYT	;Send it
	JUMPE	T2,OUTST1	;Always loop if ASCIZ
	SOJG	T2,OUTST1	;Loop if more bytes to output

T1POPJ:	POP	P,T1		;Updated pointer in T1
	POPJ	P,


SUBTTL	RETZER, RETM1, CPOPJ, CPOPJ1, T1POPJ, T2POPJ

RETZER:	TDZA	T1,T1		;Return 0 in T1
RETM1:	 SETO	T1,		;Return -1 in T1
	POPJ	P,

CPOPJ1:	AOS	(P)		;Skip return
CPOPJ:	POPJ	P,		;Return
SUBTTL	Output numbers and bytes

;Output a decimal number.  Uses T1 and T2

OUTDEC:	IDIVI	T1,^D10		;Get a digit
	HRLM	T2,(P)		;Store on stack
	SKIPE	T1		;If not done,
	 PUSHJ	P,OUTDEC	; recurs
	HLRZ	T1,(P)		;Get digit
	ADDI	T1,"0"		;Make printing
	PFALL	OUTBYT		;Output the byte and return

;Output the byte in T1.  Preserves all ACs

OUTBYT:	DMOVEM	T1,OUTBT1	;Preserve byte across call
	TXNN	P4,P4.TT8	;Sending 8-bit bytes to the terminal?
	 JRST	OUTBY1		;No
	MOVEI	T2,(T1)		;(Taken from page 2-114 of
	LSH	T2,-4		; the Processor Reference
	XORI	T2,(T1)		; Manual)
	TRCE	T2,14
	TRNN	T2,14
	 XORI	T1,200
	TRCE	T2,3
	TRNN	T2,3
	 XORI	T1,200		;T1 is 7-bits plus even parity

OUTBY1:	SOSG	BUFR.C(P4)	;Decrement byte count
	 PUSHJ	P,DUMPBF	;Get another output buffer
	IDPB	T1,BUFR.P(P4)	;Store byte in buffer
	AOS	BYTE.C(P4)	;Increment the cumulative byte count
	DMOVE	T1,OUTBT1	;Restore original byte and T2
	POPJ	P,


TOPS20<	PRINTX	%TOPS20 - Many routines in PLTIOD not defined
	PLTIO2:	UNIMP	;List of UNIMPlemented routines
	EXP	CLRIB,INCHR,REOPEN	;Routines to be rewritten
	DUMPBF:	UNIMP	;Dump output buffers
	GETNAM:	UNIMP	;Get file name from caller
	OPNFIL:	UNIMP	;Open the output file
	CLSFIL:	UNIMP	;Close the file
	RELFIL:	UNIMP	;Release JFN
	TTBINM:	UNIMP	;Set terminal to PLOT (binary) mode
	TTASCM:	UNIMP	;Set terminal to text (ASCII) mode
	SPTYPT:	UNIMP	;Set plotter type for 'TTY'
	TTYINI:	UNIMP	;Initialize terminal
	TTYFIN:	UNIMP	;Finish up with the terminal
	TOWAIT:	UNIMP	;Wait so many milliseconds after output buffer is empty
	GETLIM:	UNIMP	;Get SETWIN limits from SYS:PRIV.SYS
	ISACTV:	UNIMP	;Check if JFN is still open
	SETODV:	UNIMP	;Set output device to TTY: or DSK: as appropriate
	POPJ	P,
>  ;End TOPS20

TOPS10<	;This conditional lasts for many pages

;Dump output buffer, get a new one.  Uses T2

DUMPBF:	PUSH	P,T1		;Preserve T1
	MOVE	T2,BUFR.N(P4)	;Channel number
	HRRI	T2,.FOOUT	;Output function
	MOVE	T1,[1,,T2]	;1 word argument
	FILOP.	T1,		;Get a new buffer
	  MOVX	T1,IO.ERR	;Unknown error
	TXNE	T1,IO.ERR	;Any output errors?
	 JRST	[ERRSTR	(<?PLOT - I/O error on output>)
		HALT    .+1]
	POP	P,T1		;No errors
	POPJ	P,
SUBTTL	GETNAM - Decode output file spec

;Routine to decode output device and filename for subroutine PLOTS
;Call:  MOVEI   T2,[ASCII/DEV:FILNAM/]    or     MOVEI T2,0
;	PUSHJ	P,GETNAM	Called only by PLOTS routine
;	 *return*		Sets up D.PLOT and F.PLOT

GETNAM:	MOVSI	T1,'PLT'	;Logical device name for output
	MOVEM	T1,D.PLOT	;Save default output device
	SKIPN	T2		;Was a name supplied?
	 JRST	GETNA3		;No, use name of program
	SKIPE	T1,(T2)		;Is the double-precision variable zero?
	CAMN	T1,BLANKS	; or all blank?
	 JRST	GETNA3		;Yes, forget it
	HRLI	T2,(POINT 7,)	;Make byte pointer
GETNA0:	MOVE	T1,[POINT 6,F.PLOT]
	SETZM	F.PLOT		;Clear accumulated name

GETNA1:	ILDB	T3,T2		;Get a char
	CAIL	T3,140		;Lowercase?
	 SUBI	T3,40		;Yes, convert
	SUBI	T3," "-' '	;Convert to SIXBIT
	CAIL	T3,'0'		;Alphameric?
	CAILE	T3,'Z'
	 JRST	GETNA2		;No
	CAILE	T3,'9'
	CAIL	T3,'A'
	 JRST	[IDPB	T3,T1	  ;Yes, put in F.PLOT
		 TLNE	T2,770000 ;Done 6 chars?
		  JRST	GETNA1	  ;No, loop
		 JRST	GETNA2	] ;Yes, stop
GETNA2:	MOVE	T1,F.PLOT	;Get name
	CAIN	T3,':'		;End of device?
	 JRST	[MOVEM	T1,D.PLOT ;Yes, store it
		 JRST	GETNA0	] ; and go for file name
	JUMPN	T1,GETNA4	;Use file name if nonzero

GETNA3:	HRROI	T1,.GTPRG	;Get the name of this program
	GETTAB	T1,
	 MOVSI	T1,'PLT'	;Can never happen
	MOVEM	T1,F.PLOT	;Store implicit file name

GETNA4:	POPJ	P,		;D.PLOT and F.PLOT are set up
SUBTTL	NEWFIL - Create new file name

;NEWFIL - Sets up a new file for output.  Increments file name if necessary,
;sets up LOOKUP block.
;Call:
;	PUSHJ	P,NEWFIL
;	 *return*


NEWFIL:	SKIPE	T1,FILE.N(P4)	;Has a file name been set up for this plotter?
	 JRST	[PUSHJ	P,INCNAM  ;Yes, increment old name
		 MOVEM	T1,FILE.N(P4)	;Store for next time
		 JRST	NEWFI1]	  ; and use it
	MOVE	T1,F.PLOT	;No, get name from call to PLOTS
	SETO	T2,		;Get full mask

NEWFI0:	TDNE	T1,T2		;Found trailing spaces?
	 JRST	[LSH	T2,-6	  ;No, shift mask
		 JRST	NEWFI0	] ;Try again
	AND	T2,[SIXBIT /000000/]
	IOR	T1,T2		;Expand 'ABC' to 'ABC000', 'GRAPH' to 'GRAPH0'
	PUSHJ	P,INCNAM	;Increment it (so 6th character is '1')
	MOVEM	T1,FILE.N(P4)	;Store to be incremented again for 2nd plot
	MOVE	T1,F.PLOT	;Get original file name and use it for 1st plot

NEWFI1:	MOVEM	T1,ENT+0	;Store file name
	HLLZ	T1,PLTEXT(P4)	;Extension (.PLT, .PIC, or .TEK)
	MOVEM	T1,ENT+1
	SETZM	ENT+2		;Default protection
	SETZM	ENT+3		;Default directory

	MOVE	T1,FILE.D(P4)	;Get output device
	MOVEM	T1,FLP+.FODEV	;Put in FILOP. block
	POPJ	P,

PAGE
;Routine to increment name in T1.  'ABCDEF' will go to 'ABCDE1',
;'ABCDE1' will go to 'ABCDE2', 'ABCDE9' to 'ABCD10', etc.
;Uses T2-T4, returns new name in T1.  Called only by NEWFIL, above

INCNAM:	MOVEI	T2,6		;Start with 6th position
INCNA1:	MOVE	T3,[
		POINT 6,T1,5	  ;1st position
		POINT 6,T1,11	  ;2nd
		POINT 6,T1,17	  ;3rd
		POINT 6,T1,23	  ;4th
		POINT 6,T1,29	  ;5th
		POINT 6,T1,35	  ;6th
		    ]-1(T2)	;Get byte pointer
	LDB	T4,T3		;Get character
	CAIL	T4,'0'		;Digit?
	CAILE	T4,'9'		; ...
	 JRST	[MOVEI	T4,'1'	  ;No
		 DPB	T4,T3	  ;Set byte to 1
		 POPJ	P,	] ;And return
	ADDI	T4,1		;Yes, increment digit
	CAIN	T4,'9'+1	;Incremented 9?
	 MOVEI	T4,'0'		;Yes, reset to 0
	DPB	T4,T3		;Store new char
	CAIN	T4,'0'		;Incremented to 0?
	 SOJG	T2,INCNA1	;Yes, increment next digit also
	POPJ	P,		;Return with name in T1
SUBTTL	Open output file

;SETODV - Routine to set up output device in T1
;If logical device is not the physical or spooled plotter, use it.

SETODV:	MOVE	T1,D.PLOT	;Get specified device
	MOVE	T2,T1		;Copy
	DEVTYP	T2,		;Get device type
	  MOVX	T2,.TYPLT	;Can never fail in 6 or 7 series monitors
	ANDX	T2,TY.DEV	;Only the type
	CAXE	T2,.TYPLT	;Is it PLT: (or logical name for PLT:)?
	 POPJ	P,		;No, use it
	MOVSI	T1,'DSK'	;Yes, use DSK: instead
	TXNE	P4,P4.TTY	;Unless routine is for a graphics terminal
	 MOVSI	T1,'TTY'	; in which case use TTY:
	POPJ	P,

;ISACTV - Routine to see if the I/O channel is still active
;Call:	PUSHJ	P,ISACTV
;	  *not active*
;	 *is active*		Preserves T1

ISACTV:	HLRZ	T2,BUFR.N(P4)	;Get channel number
	DEVNAM	T2,		;Get device associated with it
	SKIPE	T2		;If DEVNAM returned nonzero,
	 AOS	(P)		; then the I/O channel is still OPEN
	POPJ	P,


;OPNFIL - routine to set up FILOP. block, get channel, and open file

TTBINM:			;Set TTY to BINARY mode

OPNFIL:	HLLZ	T1,BUFR.N(P4)	;Get previous channel number
	JUMPN	T1,OPNFI1	;Use it if channel still open
IFE FT701,<PUSHJ  P,ALCHN	;Get a free channel from FOROTS
	   HRLZS  T1	>	;Put in LH
IFN FT701,<MOVX   T1,FO.ASC>	;Set bit to assign extended channel
OPNFI1:	HRRI	T1,.FOCRE	;Code to create new file
	TXO	T1,FO.PRV	;Allow [1,2] to write in [11,10,TEST]
	MOVEM	T1,FLP+.FOFNC	;Channel,,code

	LDB	T1,[POINTR PLTINI(P4),IN.BYT] ;Get the byte size
	LDB	T2,[POINTR PLTINI(P4),IN.MOD] ;Get the I/O mode

;Enter here with byte size in T1, I/O mode in T2, FLP+.FOFNC set up

REOPEN:	MOVEM	T1,BYTSIZ	;Save for after FILOP.
	MOVEM	T2,FLP+.FOIOS	;Store mode

.CREF IN.ACK	;This flag not used yet (for PTC-5 in the future)

	MOVSI	T1,BUFR.H(P4)	;Get addr of 3 word buffer header
	MOVEM	T1,FLP+.FOBRH	;Set for output only
	MOVSI	T1,2		;2 output buffers
	MOVEM	T1,FLP+.FONBF
	MOVEI	T1,ENT		;Address of ENTER block
	MOVEM	T1,FLP+.FOLEB
	PUSHJ	P,NEWFIL	;Set up device and ENTER block

;Reserve space for output buffers

	HRRZ	T1,BUFR.N(P4)	;Get address of current buffers
	JUMPN	T1,OPNFI2	;Use old space if set up
	MOVEI	T1,FLP+.FOIOS	;Point to OPEN block
	DEVSIZ	T1,		;Get size of buffers for this device
	  JRST	RETM1		;No such device, return -1
	HRRZS	T1		;Keep only buffer size
	IMULI	T1,2		;Get size of 2 buffers
	PUSHJ	P,ALCOR		;Reserve space for the buffers

OPNFI2:	HRRM	T1,BUFR.N(P4)	;Remember address for DECOR
	JUMPLE	T1,CPOPJ	;Abort if no core available
	MOVE	T1,.JBFF##	;Get current first-free
	MOVEM	T1,SAVEFF	;Save .JBFF for later

OPNFI3:	HRRZ	T1,BUFR.N(P4)	;Get addr of buffer
	MOVEM	T1,.JBFF##	;Tell monitor where to put buffers
	MOVE	T1,[FLPLEN,,FLP];Point to args
	FILOP.	T1,		;Open file for output
	  JRST	OPNERR		;Could be file already exists
	MOVE	T1,BYTSIZ	;Get byte size
	LSH	T1,^D18+6	;Shift to position
	MOVEM	T1,BUFR.P(P4)	; in byte pointer
	MOVE	T1,FLP+.FOFNC	;Get channel number assigned
	TXZ	T1,FO.PRV	;Clear this bit
	HLLM	T1,BUFR.N(P4)	;Store
	MOVE	T1,SAVEFF	;Get old .JBFF
	MOVEM	T1,.JBFF##	;Reset first-free
	JRST	RETZER		;Return 0 in T1

;Here when FILOP. failed.  Function .FOCRE returns error if file already exists.

OPNERR:	CAIN	T1,ERAEF%	;Already existing file?
	 JRST	[PUSHJ	P,NEWFIL  ;Yes, increment file name
		 JRST	OPNFI3	] ;Try again
	MOVE	T1,SAVEFF	;No, reset first free
	MOVEM	T1,.JBFF##	;...
	SKIPA	T1,FLP+.FOFNC	;Get channel number
				; and fall into RELFIL

RELFIL:	MOVE	T1,BUFR.N(P4)	;Get channel number in left half
	HRRI	T1,.FOREL	;Get code
	MOVEM	T1,FLP+.FOFNC	; to RELEASe channel
	MOVE	T2,[1,,T1]	;Point to args
	FILOP.	T2,		;Release the channel
	  JFCL			;Can never fail
	HRRZ	T1,BUFR.N(P4)	;Get address of PLT buffers
	PUSHJ	P,DECOR		;Deallocate the core
IFGE FT701,<HLRZ  T1,BUFR.N(P4)	;Get channel number
	    CAIG  T1,17		;If 0 through 17,
	     PUSHJ P,DECHN>	;Give it back to FOROTS
	SETZM	BUFR.N(P4)	;No channel and no buffers assigned
	JRST	RETM1		;Return -1 in T1 to signify failure


TTASCM:			;Set TTY to ASCII mode

CLSFIL:	MOVE	T1,BUFR.N(P4)	;Get channel number in left half
	HRRI	T1,.FOCLS	;Get code
	MOVEM	T1,FLP+.FOFNC	; to CLOSE file
	MOVE	T2,[1,,T1]	;Point to args
	FILOP.	T2,		;CLOSE file (keeping channel around)
	  SKIPA			;Should never happen
	POPJ	P,
	  ERRSTR (<% PLOT - Error closing plot>)
	POPJ	P,
SUBTTL	Translate 'TTY' to appropriate plotter type

	ND FTTERM,0	;Defined non-zero if any graphics terminal support

IFE FTTERM,<SPTYPT==RETM1>	;Return -1 in T1 if no graphics terminals
IFN FTTERM,<	;This routine is called only of the plotter type is 'TTY'
SPTYPT:	MOVE	T1,D.PLOT	;Get device name (PLT: or TTY:)
	MOVE	T2,D.PLOT	;Need second copy
	DEVCHR	T1,		;Check for TTY vs PLT vs DSK vs NUL
	TXNN	T1,DV.TTY	;Is it a terminal (or NUL:)?
	 MOVSI	T2,'TTY'	;No, use TTY: instead of PLT: or DSK:
	MOVEM	T2,D.PLOT	;Store in case changed
	IONDX.	T2,		;Get UDX of device
	  SETZ	T2,		;No such device
	TXNN	T2,.UXTRM	;Is logical name TTY: really a terminal?
	 JRST	RETM1		;No, give error return for no such plotter
	MOVX	T1,.TOTRM	;Yes, get terminal type from monitor
	MOVE	T3,[2,,T1]	;Point to args
	TRMOP.	T3,		;Get it
	  MOVEI	T3,0		;If 6.03A, set to default TTY plotter

	MOVSI	T1,-TTYNUM	;Get length of table
SETYPA:	CAME	T3,TTY6NM(T1)	;Does monitor type match (SIXBIT) ?
	 AOBJN	T1,SETYPA	;No match, try next one
	SKIPGE	T1		;Found a match?
	 SKIPA	T1,TTY7NM(T1)	;Yes, get it
	  MOVX	T1,DTTPLT	;Unknown terminal type, set default
	POPJ	P,		;Go back and check this plotter type

		PAGE	;Still in IFN FTTERM
DEFINE X(SIXNAM,ASCNAM),<
	SIXBIT /SIXNAM/	;ASCNAM	>

DEFINE TTYS,<XALL;;List of monitor names and plot names for graphics terminals
IFDEF TEKINI,<
  X TK4006,4006;;Tektronix
  X TK4010,4010
  X TK4025,4025
>  ;End of IFDEF TEKINI
IFDEF RGSINI,<
  X GIGI,GIGI
  X VT125,VT125
  X VT100,REGIS;;Assume VT125 or VK100(GIGI) in VT100 mode
>  ;End of IFDEF RGSINI
SALL>  ;End of DEFINE TTYS

TTY6NM:	TTYS		;List of monitor types in SIXBIT
TTYNUM==.-TTY6NM	;Number of equivalences

DEFINE X(SIXNAM,ASCNAM),<
	ASCII /ASCNAM/	;SIXNAM	>

TTY7NM:	TTYS		;List of plotter types in ASCII

;End of SPTYPT routine	>  ;End of IFN FTTERM
SUBTTL	TTYINI - Set up terminal

IFE FTTERM,<TTYINI: TTYFIN: POPJ P,>
IFN FTTERM,<

;Initialize the terminal for output.  By using .IOBIN (binary mode) output,
;the monitor will pass tabs, formfeeds, and blank lines regardless of terminal
;settings, and will not do auto CRLF.  As long as the job is not in a binary
;input wait, Control-C will stop the program.  By using .IOPIM (packed image)
;for input,;the monitor will not echo the response, and will pass nulls and
;Control-C to subroutine XHAIRS.


TTYINI:	TXZ	P4,P4.TTY!P4.TT8;Should be zero already
	PUSHJ	P,SETUDX	;Set up TRMOP data if output to a TTY
	  POPJ	P,		;Not a terminal
	TXO	P4,P4.TTY	;Output is going to a TTY
	LDB	T1,[POINTR PLTINI(P4),IN.MOD]	;Get I/O mode
	CAILE	T1,.IOASL	;ASCII or ASCII line?
	 TXO	P4,P4.TT8	;No, set 8th bit to parity for binary modes

	MOVE	T1,[INTDAT,,INTBLK] ;Source,,destination
	BLT	T1,INTBLK+3	;Set up 4-word interrupt block
	MOVEI	T1,INTBLK	;Tell monitor
	EXCH	T1,.JBINT##	; to trap Control-C
	CAIE	T1,INTBLK	;Second time around?
	 MOVEM	T1,OLDINT	;No, save old .JBINT in case its important
	MOVEI	T1,0		;Clear send bit (TTY GAG)
	PJRST	P,STOSND	;Set the send bit to zero

INTDAT:	4,,INTNPC		;Length,,new PC on interrupt
	ER.ICC			;Intercept Control-C
	EXP	0,0		;Last 2 words initially zero


TTYFIN:	MOVE	T1,OLDINT	;Get previous .JBINT
	MOVEM	T1,.JBINT##	;Restore it
	MOVEI	T1,1		;Bit to enable sends (TTY NO GAG)
	PFALL	STOSND		;Set .TOSND and return

STOSND:	MOVEM	T1,TRM+2	;Store argument, 0=NOSEND(GAG), 1=SEND(NOGAG)
	MOVEI	T1,.TOSND+.TOSET;Function code
	MOVEM	T1,TRM+0	;Store
	MOVE	T1,[3,,TRM]	;Point to args
	TRMOP.	T1,		;SET TTY (NO) GAG
	  JFCL			;No big deal
	POPJ	P,
;Here on Control-C during normal output (not during XHAIRS)
;Reset the terminal to ASCII mode.

INTNPC:	MOVEM	17,INTS17	;Save all ACs
	MOVEI	17,INTS00
	BLT	17,INTS16
	MOVE	P,[IOWD INTPDS,INTPDL] ;Set up new PDL
	PUSH	P,INTBLK+.EROPC	;Save PC at time of interrupt
	SKIPN	.JBDDT##	;If not debugging,
	 SETZM	INTBLK+.EROPC	;Trap further Control-Cs

	MOVSI	P3,-PLTNUM	;Get size of table
INTNP1:	SKIPL	P4,PLTTAB(P3)	;Is this plotter active?
	 JRST	INTNP2		;No, try next one
	TXNN	P4,P4.TTY	;Is this going to a terminal?
	  JRST	INTNP2		;No
	PUSHJ	P,@PLTFIN(P4)	;Yes, set plotter to ASCII mode
	PUSHJ	P,DUMPBF		;Dump output buffer
INTNP2:	AOBJN	P3,INTNP1	;Loop for all

IFN FT2CC,<	;Try to notify other intercept routine
	MOVE	T1,OLDINT	;Get old value of .JBINT
	MOVEM	T1,.JBINT##	;Restore it
	SETZM	OLDINT		;Be paranoid and clear to prevent recursion
	TRNE	T1,-1		;Anything in RH?
	SKIPN	T2,.ERCLS(T1)	;Yes, any bits set?
	 JRST	INTNP3		;No
	TRNN	T2,ER.ICC	;Does it want to trap Control-C
	 JRST	INTNP3		;No
	POP	P,.EROPC(T1)	;Get PC at time of interrupt
	MOVE	T2,INTBLK+.ERCCL;Get cause of interrupt
	MOVEM	T2,.ERCCL(T1)	;Copy
	HRRZ	T2,.ERNPC(T1)	;Get address of interrupt handler
	HLL	T2,.EROPC(T1)	;Set PC flags
	MOVEM	T2,INTPDL	;Store in memory
	MOVSI	17,INTS00	;Point to saved ACs
	BLT	17,17		;Restore accumulators
	JRSTF	@INTPDL		;Go to other Control-C handler
>  ;End of IFN FT2CC

INTNP3:	ERRSTR	(<PLOT - Aborted graphics due to Control-C>)
	MONRT.			;Exit to monitor
IFE FT2CC,<JRST	INTNP3>		;Cannot continue
IFN FT2CC,<	;Try to resume

	MOVSI	P3,-PLTNUM	;Get size of table
INTNP4:	SKIPGE	P4,PLTTAB(P3)	;Was this plotter active?
	TXNN	P4,P4.TTY	; and going to a TTY?
	 JRST	INTNP5		;No, try next one
	PUSHJ	P,@PLTINI(P4)	;Yes, set plotter to graphics mode
INTNP5:	AOBJN	P3,INTNP4	;Loop for all
	POP	P,INTPDL	;Get old PC and flags
	MOVSI	17,INTS00	;Point to saved ACs
	BLT	17,17		;Restore accumulators
	JRSTF	@INTPDL		;.CONTINUE
>  ;End of IFN FT2CC
SUBTTL	Terminal I/O routines

;Routine to test for TTY as output device and set up TRMOP. data.
;Calling sequence:
;	PUSHJ	P,SETUDX
;	  *error*	;Output device not a TTY
;	 *ok return*	;Output device is a TTY
;			Uses T1

SETUDX:	HLRZ	T1,BUFR.N(P4)	;Get channel number
	IONDX.	T1,		;Get I/O index number
	  MOVEI	T1,0		;Error, not a TTY
	MOVEM	T1,TRM+1	;Save UDX
	TXNE	T1,.UXTRM	;Output to a TTY?
	 AOS	(P)		;Yes, give skip return
	POPJ	P,

;Routine to wait a while after the terminal output buffer is empty.
;  Calling sequence:
;	MOVEI	T1,(milliseconds to wait)
;	PUSHJ	P,TOWAIT
;	 *return*
;			Preserves all ACs

TOWAIT:	PUSH	P,T1		;Save delay time
	PUSHJ	P,SETUDX	;Set TRM if it's a TTY
	  JRST	T1POPJ		;Not, can't wait for DSK

WAIT0:	MOVEI	T1,.TOSOP	;Set up to wait for
	MOVEM	T1,TRM		; the TTY buffer
	MOVE	T1,[2,,TRM]	; going empty
	TRMOP.	T1,		;Skip if Output in Progress
	 JRST	WAIT1		;Output buffer is empty
	MOVEI	T1,^D250	;Wait
	HIBER	T1,		; 1/4
	  JFCL			; second
	JRST	WAIT0		;See if output buffer empty now

WAIT1:	POP	P,T1		;Get delay time
	HIBER	T1,		;Hibernate for a while
	  JFCL			;Can never happen
	POPJ	P,
;Routine to input a character from the terminal

INCHR:	PUSHJ	P,SETUDX	;Set up TRM
	  JRST	RETZER		;Not a TTY, return 0 in T1
	MOVEI	T1,.TOISC	;Code to input single char
	MOVEM	T1,TRM+0	;Store function
	MOVE	T1,[2,,TRM]	;Point to args
	TRMOP.	T1,		;Get a char
	  SETO	T1,		;Only if detached
;*;	IDPB	T1,HEADBP	;Store
	POPJ	P,

;Routine to clear input buffer of typeahead

CLRIB:	PUSHJ	P,SETUDX	;Set up TRM
	  POPJ	P,		;No input buffer to clear
	MOVEI	T1,.TOCIB	;Code to clear input buffer
	MOVEM	T1,TRM+0	;Store function
	MOVE	T1,[2,,TRM]	;Point to args
	TRMOP.	T1,		;Clear typeahead
	  JFCL			;Only if detached
	POPJ	P,

;Routine to read TTY response in binary
;Call:
;	MOVEI	T1,[ASCIZ /Prompt or trigger/]
;	MOVE	T2,[bytecount,,terminator]
;	PUSHJ	P,RDTBIN
;	 *return* 	Returns pointer to response in T1, byte count in T2

;RDTBIN:	POPJ	P,
>  ;End of IFN FTTERM
SUBTTL	I/O routines - Read window limits from SYS:PRIV.SYS

	%0==0		;Temporary I/O channel, will be released before returning
	DFWINS==DFWINS	;Should be about 35.0 inches IFE FTPRIV

GETLIM:	GETPPN	T1,		;Get this guy's PPN
	  JFCL
	MOVEM	T1,MYPPN
	SETZB	X,Y		;In case OPEN fails
	SETZM	P.WIND		;Clear priv bits

IFDEF DSKINI,<	IFN FTPRIV,<	;Read file for limits
	MOVX	T1,UU.PHS!.IODMP;Physical only, dump mode
	MOVSI	T2,'SYS'	;System device
	SETZ	T3,0		;No buffers
	OPEN	%0,T1		;Go get an I/O channel
	 JRST	GETLI9		;??? Use default
	MOVE	T1,['PRIV  ']	;Set up to lookup file 'PRIV.SYS'
	MOVSI	T2,'SYS'	; ..
	SETZB	T3,T4		; ..
	LOOKUP	%0,T1		;Lookup the file 'PRIV.SYS'
	 JRST	GETLI4		;Can't find it - go use the default

GETLI1:	IN	%0,GETLIO	;Go get a block of data
	  TDZA	T3,T3		;Skip and set up pointer to SWBUFR
	 JRST	GETLI4		;EOF and no match, use default

GETLI2:	SKIPE	T1,WINPPN(T3)	;Pick up next PPN
	CAML	T1,MYPPN	;Searched far enough?
	 JRST	GETLI3		;Yes, see if it matches PPN
	ADDI	T3,WINLEN	;Increment the counter
	CAIGE	T3,200-WINLEN	;Skip if finished with this block
	 JRST	GETLI2		;No - go try the next entry then
	JRST	GETLI1		;Go read the next block

GETLI3:	CAME	T1,MYPPN	;Searched past PPN?
	 JRST	GETLI4		;Yes, go use the default
	DMOVE	X,WINX(T3)	;Get max X and Y for this PPN
	DATE	T1,		;The today's date
	MOVE	T2,WINDAT(T3)	;Get the user's privileges and exp-date
	HLRZM	T2,P.WIND	;Save priv bits (all zero for now)
	CAILE	T1,(T2)		;Today less than expiration date?
GETLI4:	 SETZB	X,Y		;No, zeros means use default
	SKIPN	X		;If expired or default,
	 SETZM	P.WIND		; clear window privs
	RELEAS	%0		;Release the I/O channel
>  ;End of IFN FTPRIV	>  ;End of IFDEF DSKINI

GETLI9:	CAMG	X,[DFWINS]	;PRIV.SYS too small or zero?
	 MOVE	X,[DFWINS]	;Yes, use default of 11.0 inches
	CAMG	Y,[DFWINS]
	 MOVE	Y,[DFWINS]
	DMOVEM	X,X.WMAX	;Save max from SYS:PRIV.SYS
	POPJ	P,
SUBTTL	Misc - IFX.X and IFX.Y

IFN FTKA,<	;PUSHJ P,IFX.X is equivalent to FIXR X,X
		;Uses T2 and T3, preserves T1

IFX.X:	TDZA	T3,T3		;Set up to use X
IFX.Y:	 MOVEI	T3,1		;Set up to use Y
	PUSH	P,T1		;Preserve T1
	MOVE	T1,X(T3)	;Get value into the right place
	MOVSI	T2,(DEC 0.5)	;Assume we round positive
	SKIPGE	T1		;Do we?
	 MOVSI	T2,(DEC -0.5)	;No, then use negative rounding factor
	FADR	T1,T2		;Round it.
	PUSHJ	P,IFX.1##	;Go convert the number to an integer
	MOVEM	T1,X(T3)	;Store the value back where is belongs
	POP	P,T1		;Restore T1
	POPJ	P,		;Return
>  ;End of IFN FTKA

SUBTTL	ALCHN and DECHN

IFE FT701,<
;  Subroutine ALCHN - this routine gets an I/O channel for the caller
;  Calling sequence:
;	PUSHJ	P,ALCHN
;	  *no channel*
;	 *good return*

ALCHN:	PRINTX	?ALCHN/DECHN not written
DECHN:	POPJ	P,
>  ;End IFE FT701

>  ;End of TOPS10 from many pages back
SUBTTL	Data area -- Global variables


TOPS10<	IFN FTPRIV,<
GETLIO:	IOWD 200,SWBUFR	;IOWD for reading 1 block, H.ZERO must follow
	0		;Zero marks the end
>  ;End IFN FTPRIV >  ;End TOPS10


;Some handy constants

BLANKS:	ASCII	/     /		;5 spaces
CRLF:	BYTE (7) CR,LF,0


;NOTE:  All Y varibles must immediately follow the X variables for DMOVE X,var.

	$LOSEG
  ;PLOTS variables
PLTTAB:	BLOCK	PLTNUM	;Pointers to defined plotters
E.PLOT:	BLOCK	1	;Counter for window-exceeded errors
T.PLOT:	BLOCK	1	;Default plotter type
C.PLOT:	BLOCK	1	;Count of calls to PLOT (never zeroed)
D.PLOT:	BLOCK	1	;Output device from PLOTS
F.PLOT:	BLOCK	1	;Output file name "   "

  ;PLOT variables
X.CALL:	BLOCK	2	;Last pen position as set by CALL PLOT(X,Y,I) and
Y.CALL=X.CALL+1		; returned by CALL WHERE(X,Y)
P.DOWN:	BLOCK	1	;-1 to drop pen before moving, 0 to raise before moving
X.ORIG:	BLOCK	2	;Offset due to origin shifting,
Y.ORIG=X.ORIG+1		; set by CALL PLOT(X,Y,-3)
S.ORIG:	BLOCK	1	;Negative to change the origin

  ;SETWIN variables
X.WIND:	BLOCK	5	;Universal window, set by call to SETWIN, and
Y.WIND=X.WIND+1		; is limited by X.WMAX and Y.WMAX
X.WMAX=X.WIND+2		;Maximum window size, as defined in SYS:PRIV.SYS
Y.WMAX=X.WIND+3		;(Subroutine GETWIN depends on this particular order)
P.WIND=X.WIND+4		;Privileges (currently zero)

  ;NEWPEN variables
C.NPEN:	BLOCK	1	;New pen color
L.NPEN:	BLOCK	1	;New pen line type (not yet implemented)

  ;ROTATE variables
A.ROTA:	BLOCK	1	;Angle from previous call to ROTATE, in degrees
X.ROTA:	BLOCK	2	;Origin set by ROTATE
Y.ROTA=X.ROTA+1		;Origin set by ROTATE

  ;FACTOR variables
X.FACT:	BLOCK	2	;Scaling factor in X direction
Y.FACT=X.FACT+1		;Scaling factor in Y direction
SUBTTL	Data area -- Temporary variables


SAVE0:	BLOCK	17	;Place to save ACs, 0-16
    SAVET1=SAVE0+T1
    SAVEL= SAVE0+L
MYPPN:	BLOCK	1	;For checking in SETWIN
ANGLE:	BLOCK	1	;Argument for SIN. and COS.
TEMP:	BLOCK	6	;Temporary storage
OUTBT1:	BLOCK	2	;Saves T1 and T2 for OUTBYT
SAVEFF:	BLOCK	1	;Holds old .JBFF while creating buffers
X.NEWP:	BLOCK	2	;New pen position for CHECK
    Y.NEWP==X.NEWP+1	;New pen position for CHECK

FILPTR:	BLOCK	1	;Pointer to file name for PLOTS
BYTSIZ:	BLOCK	1	;Byte size for OPNFIL
	FLPLEN==6	;Length of block
FLP:	BLOCK	FLPLEN	;FILOP. block
ENT:	BLOCK	4	;ENTER block

IFN FTTERM,<
TRM:	BLOCK	3	;TRMOP. block
INTBLK:	BLOCK	4	;Interrupt block (Control-C)
OLDINT:	BLOCK	1	;Previous value of .JBINT
	INTPDS==20	;Size of interrupt PDL
INTPDL:	BLOCK	INTPDS	;Interrupt PDL
INTS00:	BLOCK	20	;Save all ACs on interrupt
    INTS16=INTS00+16
    INTS17=INTS00+17
>  ;End of IFN FTTERM

IFN FTHEAD,<	;Plot headers and trailers
HDRHIT:	BLOCK	1	;Height of header/trailer in inches	(0.10)
NINETY:	BLOCK	1	;Plot it at +90 degrees			(90.0)
ONE:	BLOCK	1	;Number for ISETAB (must be in LOSEG)	 (1)
HEADBF:	BLOCK	^D20	;Space for 100 chars
HEADCT:	BLOCK	1	;Count of chars in HEADBF
HEADBP:	BLOCK	1	;Byte pointer to HEADBF
>  ;End of IFN FTHEAD

	ND BUFSIZ,203*2	;Default size is 2 disk buffers
IFN FTAPLT,<ND CORSIZ,<BUFSIZ+PLTSIZ+2>*2>  ;Enough to handle 2 plotters
	ND CORSIZ,<1+BUFSIZ>+<1+PLTSIZ>	    ;Enough to handle any single plotter
CORBUF:	BLOCK	CORSIZ+1;Used by ALCOR/DECOR
	L.ZERO=.-1	;Guarenteed zero word in the LOSEG

IFN FTPRIV,<
SWBUFR:	BLOCK	200	;Buffer for SETWIN routine (1 block in DUMP mode)
	WINPPN=SWBUFR+0	;PPN
	WINDAT=SWBUFR+1	;Date in 15 bit format
	WINX=  SWBUFR+2	;Max X in floating point
	WINY=  SWBUFR+3	;Max Y in floating point
	WINLEN==4	;Size of each entry
>  ;End of IFN FTPRIV
SUBTTL	Literals and END statement

	$HISEG			;End of DATA, back to CODE section

LITIOD:	LIT
PLTEND=.-1

	END			;End of PLTIOD.MAC