Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-12 - 43,50547/pltlib/sprout/sprout.pag
There is 1 other file named sprout.pag in the archive. Click here to see a list.
TITLE	SPROUT	--  Spooling PRocessor for OUTput - Version 4
SUBTTL	D.A. Lewine - L.S. Samberg/PJT/DPM/NT/CTK 1-Mar-83

	CSM01$==^D400	;Plotter has 3 pens, ON-LINE indicator, 400 SPI
	CSM02$==-1	;Compressed plot files
	CSM03$==-1	;Red and Black in banner
	CSM04$==-1	;Do CSM accounting (minutes and inches used)
	CSM05$==-1	;Add SLEEP time to $DSCHD macro for TTY response wait
	CSM06$==^D1200	;Support the TAB Products Card Terminal at 1200 baud
	CSM07$==-1	;Change some QUEUE defaults
	CSM08$==^D2400	;PTC-6 Plotter Terminal Controller at 2400 baud
IF2,<IFN CSM02$,<PRINTX	[CSM02$ uses TOLP.REL]>>
IF2,<IFN CSM06$,<PRINTX	[CSM06$ uses TABCDP.REL]>>
IF2,<IFN CSM08$,<PRINTX	[CSM08$ uses PTC6.REL]>>

REPEAT	0,<	;To completely remove the CSM changes, make this a REPEAT 1
	CSM01$==0	;Normal XY-10 plotter
	CSM02$==0	;Plot files are 1 byte per increment (very big)
	CSM03$==0	;Do not exercise the black and red pens
	CSM04$==0	;Account disk reads instead of forms type
	CSM05$==0	;No TTY I/O, therefore no sleep requests
	CSM06$==0	;Card punch is on I/O bus or front-end 11
	CSM07$==0	;Use whatever QUEUE says
	CSM08$==0	;Plotter is not connected to a TTY line
	DEFINE	CSMEDT($EDIT,$PART),<>	;Dummy macro
	CSMED$==0	;No additional edits
>  ;End of REPEAT 0
;
;
;
;       COPYRIGHT (c) 1975,1976,1977,1978,1979,1980,1981,1982 BY
;           DIGITAL EQUIPMENT CORPORATION, MAYNARD, MA.
;
;     THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY  BE  USED
;     AND COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE
;     AND WITH THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE.   THIS
;     SOFTWARE  OR ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR
;     OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON.  NO  TITLE  TO
;     AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
;
;     THE INFORMATION  IN  THIS  SOFTWARE  IS  SUBJECT  TO  CHANGE
;     WITHOUT  NOTICE  AND SHOULD NOT BE CONSTRUED AS A COMMITMENT
;     BY DIGITAL EQUIPMENT CORPORATION.
;
;     DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY
;     OF  ITS  SOFTWARE  ON  EQUIPMENT  WHICH  IS  NOT SUPPLIED BY
;     DIGITAL.


		PAGE
	SALL		;Also searches UUOSYM and ACTSYM.UNV
	SEARCH	GLXMAC			;SEARCH GLXLIB SYMBOLS
	SEARCH	QSRMAC			;GET QUASAR SYMBOLS
	SEARCH	ORNMAC			;GET OPERATOR SYMBOLS
	PROLOGUE(SPROUT)		;DO STANDARD PROLOG
IFNDEF CSMEDT,<	SEARCH	CSMEDT	>	;CSM edit macro
	.XCREF	S1,S2,T1,T2,T3,T4,C,J,P	;[CSM] Save some trees


;VERSION INFORMATION
	SPOVER==4			;MAJOR VERSION NUMBER
	SPOMIN==0			;MINOR VERSION NUMBER
	SPOEDT==2533			;EDIT LEVEL
	SPOWHO==2			;Who last patched (JMS @ CSM)

	%SPO==<BYTE (3)SPOWHO(9)SPOVER(6)SPOMIN(18)SPOEDT>+CSMED$

;STORE VERSION NUMBER IN JOBVER
	LOC	137
.JBVER:: EXP	%SPO			;SPROUT VERSION

	RELOC	0

COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1971,1984.
SUBTTL	Table of Contents

;                  Table of Contents for SPROUT
;
;
;			   Section			      Page
;
;    1. Table of Contents  . . . . . . . . . . . . . . . . . .   1
;    2. Revision History . . . . . . . . . . . . . . . . . . .   2
;    3. CSM Revision History . . . . . . . . . . . . . . . . .   2
;    4. Constants  (Conditional and Unconditional) . . . . . .   4
;    5. MACROS . . . . . . . . . . . . . . . . . . . . . . . .   5
;    6. Special Forms Handling Parameters  . . . . . . . . . .   6
;    7. Flag Definitions . . . . . . . . . . . . . . . . . . .   7
;    8. Job Parameter Area . . . . . . . . . . . . . . . . . .   8
;    9. Random Impure Storage  . . . . . . . . . . . . . . . .  11
;   10. Resident JOB DaTABase  . . . . . . . . . . . . . . . .  12
;   11. Non-zero daTABase  . . . . . . . . . . . . . . . . . .  13
;   12. $TEXT Utilities  . . . . . . . . . . . . . . . . . . .  14
;   13. Program Initialization . . . . . . . . . . . . . . . .  15
;   14. Idle Loop  . . . . . . . . . . . . . . . . . . . . . .  16
;   15. Deschedule Process . . . . . . . . . . . . . . . . . .  17
;   16. CHKTIM - Routine to see if it's time to schedule a s .  17
;   17. Do the Job . . . . . . . . . . . . . . . . . . . . . .  18
;   18. Process a File . . . . . . . . . . . . . . . . . . . .  19
;   19. End of Job . . . . . . . . . . . . . . . . . . . . . .  20
;   20. FILDIS . . . . . . . . . . . . . . . . . . . . . . . .  21
;   21. CHKQUE . . . . . . . . . . . . . . . . . . . . . . . .  22
;   22. CHKOBJ . . . . . . . . . . . . . . . . . . . . . . . .  23
;   23. FNDOBJ . . . . . . . . . . . . . . . . . . . . . . . .  24
;   24. GETBLK . . . . . . . . . . . . . . . . . . . . . . . .  25
;   25. NEXTJOB Message from QUASAR  . . . . . . . . . . . . .  26
;   26. User CANCEL Request  . . . . . . . . . . . . . . . . .  27
;   27. UPDATE Routine to send status update . . . . . . . . .  28
;   28. CHKPNT Routine to send checkpoint message  . . . . . .  29
;   29. SETUP/SHUTDOWN Message . . . . . . . . . . . . . . . .  30
;   30. Response to setup message  . . . . . . . . . . . . . .  31
;   31. Operator CANCEL command  . . . . . . . . . . . . . . .  32
;   32. Operator STOP command  . . . . . . . . . . . . . . . .  33
;   33. Operator CONTINUE command  . . . . . . . . . . . . . .  33
;   34. Operator RESPONSE command  . . . . . . . . . . . . . .  33
;   35. Operator REQUEUE command . . . . . . . . . . . . . . .  34
;   36. CLRMSG and SNDQSR routines . . . . . . . . . . . . . .  35
;   37. FRMLEX - Forms limit exceeded routine  . . . . . . . .  36
;   38. Accounting routines  . . . . . . . . . . . . . . . . .  37
;   39. FORMS - Setup Forms for a job  . . . . . . . . . . . .  40
;   40. Forms switch Subroutines . . . . . . . . . . . . . . .  44
;   41. Plotter only switches  . . . . . . . . . . . . . . . .  45
;   42. I/O Subroutines for SPFORM.INI . . . . . . . . . . . .  46
;   43. INPOPN - Routine to open the input file  . . . . . . .  48
;   44. INPBUF - Read a buffer from the input file . . . . . .  49
;   45. INPBYT - Read a byte from the input file . . . . . . .  49
;   46. INPERR - Handle an input failure . . . . . . . . . . .  49
;   47. INPFEF - Force end-of-file on next input . . . . . . .  49
;   48. INPREW - Rewind the input file . . . . . . . . . . . .  49
;   49. OUTGET - OPEN the output device  . . . . . . . . . . .  49
;   50. OUTBYT - Deposit a byte in the output buffer . . . . .  53
;   51. OUTOUT - Routine to output a buffer  . . . . . . . . .  53
;   52. DEVERR - Handle Output Device Errors . . . . . . . . .  55
;   53. OUTREL - Release output device . . . . . . . . . . . .  56
;   54. OUTWON - Wait for on-line  . . . . . . . . . . . . . .  57
;   55. OUTFLS Routine to flush output buffers . . . . . . . .  58
;   56. TTY I/O
;        56.1   Input character from TTY, no wait  . . . . . .  59
;        56.2   Input character, wait up to 30 seconds . . . .  60
;   57. Card punch service
;        57.1   Dispatch table . . . . . . . . . . . . . . . .  61
;        57.2   Checkpoint text generation . . . . . . . . . .  62
;        57.3   File processing  . . . . . . . . . . . . . . .  63
;        57.4   File headers . . . . . . . . . . . . . . . . .  69
;        57.5   File trailers  . . . . . . . . . . . . . . . .  70
;        57.6   Banners  . . . . . . . . . . . . . . . . . . .  71
;        57.7   Word punching  . . . . . . . . . . . . . . . .  72
;        57.8   Letters  . . . . . . . . . . . . . . . . . . .  73
;        57.9   Byte output  . . . . . . . . . . . . . . . . .  74
;   58. Plotter service
;        58.1   Dispatch table . . . . . . . . . . . . . . . .  75
;        58.2   Checkpoint text generation . . . . . . . . . .  76
;        58.3   File processing  . . . . . . . . . . . . . . .  77
;        58.4   Expand CSM's compressed plot format  . . . . .  79
;        58.5   READ36, OPRTXT, PAUSEP, TITLE for TOLP . . . .  81
;        58.6   NEWPEN for 3-pen plotter . . . . . . . . . . .  82
;        58.7   DEVOUT output errors . . . . . . . . . . . . .  83
;        58.8   Banners  . . . . . . . . . . . . . . . . . . .  84
;        58.9   File headers . . . . . . . . . . . . . . . . .  85
;        58.10  File trailers  . . . . . . . . . . . . . . . .  86
;        58.11  Job trailers . . . . . . . . . . . . . . . . .  87
;        58.12  Solid lines  . . . . . . . . . . . . . . . . .  88
;        58.13  Dashed lines . . . . . . . . . . . . . . . . .  89
;        58.14  Job information plotting . . . . . . . . . . .  90
;        58.15  Alignment and testing  . . . . . . . . . . . .  91
;        58.16  Pen calibration  . . . . . . . . . . . . . . .  92
;        58.17  Compute character size . . . . . . . . . . . .  93
;        58.18  Letters  . . . . . . . . . . . . . . . . . . .  94
;        58.19  Line segments  . . . . . . . . . . . . . . . .  95
;        58.20  PTC-6 interface  . . . . . . . . . . . . . . .  97
;        58.21  Rotation and XY20 translation  . . . . . . . .  98
;        58.22  Pen movement generation  . . . . . . . . . . .  99
;        58.23  Character set  . . . . . . . . . . . . . . . . 101
;   59. Paper tape punch service
;        59.1   Dispatch table . . . . . . . . . . . . . . . . 106
;        59.2   Checkpoint text generation . . . . . . . . . . 107
;        59.3   File processing  . . . . . . . . . . . . . . . 108
;        59.4   Banners  . . . . . . . . . . . . . . . . . . . 113
;        59.5   File headers . . . . . . . . . . . . . . . . . 114
;        59.6   File trailers  . . . . . . . . . . . . . . . . 115
;        59.7   Trailers . . . . . . . . . . . . . . . . . . . 116
;        59.8   Blank folds  . . . . . . . . . . . . . . . . . 117
;        59.9   Letters  . . . . . . . . . . . . . . . . . . . 118
;        59.10  Byte output  . . . . . . . . . . . . . . . . . 119
;   60. Character Bit Array for 5 X 7 Character Matrix . . . . 120
;   61. Common Utilities . . . . . . . . . . . . . . . . . . . 122
;   62. Interrupt Module . . . . . . . . . . . . . . . . . . . 124
;   63. IPCF and DEVICE Interrupt service for TOPS10 . . . . . 128
;   64. IPCF and DEVICE interrupt service for TOPS20 . . . . . 129
SUBTTL	Revision History

Comment\

2000	First GALAXY-10 Field-Test release, June, 1975.
2100	Make this version 2, August, 1976.

First field-test release of GALAXY release 2, Jan 1977

2400	MAKE THIS VERSION 4, APRIL 1977.
	(NOTE: RELEASE 3 OF GALAXY WAS TOPS20 ONLY AND DID NOT INCLUDE SPROUT)
	INSERT CHANGES FOR NEW FP/FD.
2401	START CONVERTING TO USE GLXLIB INSTEAD OF CSP??? AND SBS???.
2402	FIX UP AC CONVENTIONS TO BE COMPATIBLE WITH GLXLIB.
2403	MAKE SPROUT INTO A SINGLE SEGMENT AND DO A CODE CLEANUP.
2404	START MERGING IN GLXFIL USAGE FOR THE INPUT FILE.
2405	MORE OF 2404 AND START REPLACING LUUOS WITH $TEXTS.
2406	MAKE MORE USE OF $TEXT.
2407	MANY MINOR BUG FIXES AND CHANGES.
2410	SOME MAJOR CODE CLEANUP.
2411	START MAJOR RE-WORK OF SPROUT TO MAKE MORE USE OF GLXLIB AND TO
	TALK WITH THE NEW OPERATOR INTERFACE.
2412	CHANGE IMAGE MODE ON THE CDP TO IGNORE EACH 81ST BYTE READ
	FROM DISK SO THAT IT IS COMPATIBLE WITH SPRINT AND PIP.
2413	DONT ENFORCE LIMITS ON PTP AND PLT SINCE THE LIMITS ARE DIRECTLY
	DERIVABLE FROM THE FILE-SIZE.
2414	DO SOME CODE CLEANUP.
2415	Code Cleanup and add plotter and card letter routines
2416	Added Forms processing for SPFORM.INI File
2417	Added MSGFLG and Changed interrupt and Scheduling code
	to set/check msgflg for IPCF messages
2420	Added code to check length of message for DEP6BP and DEPBP
2421	Removed msgflg (twas a bad idea)
2422	Fixed OUTOUT and DEVERR for TOPS10
2423	Fixed ACTION operator message processing
2424	Fixed Offline device interrupt code
2425	Updated to new library and message formats
2426	Added preliminary accounting parameters
	Added two pass scheduling algorithm to allow mulitple
	devices to operate in parallel on TOPS20
2427	Fixed bug in INPOPN regarding access checks
	Moved impure interrupt stuff to impure storage
	Added call to I%HOST to get local node name
2430	Changed all message processing to use ac M
	Changed scheduling loop to WAIT instead of SLEEP
	when no jobs are scheduable
2431	Added correct mulitple stream runtime accounting code
2432	Put IB.PRG back into IB
2433	add Mount Bypass
2434	Add WTOR kill code  (AWC)
2435	Fix a $TEXT bug - IQN Stopcode (AWC)
2436	Put in Null routines for TOPS10 accounting
2437	Fix Plotter Banner Header and Trailer code
2440	Add plotter limit check code

2441	MAKE 8 BIT PAPER TAPE OUTPUT BYTE SIZE
2442	Add usage accounting for TOPS-10 (DPM)
2443	Use new feature IB.DET to detach from FRCLIN (DPM)
2444	Delete IB.DET (GLXLIB defaults to detach)
2445	Change reference of symbol z to ZZ [QAR 10-04715]
2446	Add missing (S2) in DVINTR rouine [QAR 10-4903]

2447	Close SPFORM.INI before returning from FRMSWI [QAR 10-4855]
2450	Call OUTOUT after outputing trailers (SPR 20-14682)
	Make # chars per fanfold 85 not 90 (SPR 20-14680)
	Fix spelling error & FRMFD length error (SPR 20-14911)
2451	Get the correct owners name based on type of system.

2452	Fix OUTOUT so we don't loose output done interrupts

2453	Adjust J$XPOS and J$YPOS before clipping output per limits

2454	Always call file trailer routine during file processing

2455	Add support for /DISP:RENAME

2456	Account for X plotter usage

2457	Compute minimum character size (YMAX-YMIN)/90

2460	Have SPROUT generate own checkpoints

2461	Make cryptic error messages more explicit.

2462	Position pen at EOF before printing error message. General
	cleanup of job/file headers and trailers.

2463	Add missing entries in PLT dispatch table for /TAPE:BINARY.

2464	Add accounting support for the plotter.

2465	Don't do things like JRST .+3

2466	Remove edit 2456. Plotter usage is accounted for in minites, not
	amount of paper.

2467	Clear up /BANNER/HEADER/TRAILER problems with plotter. Edit 2457
	made the switch arguments nearly useless. Don't allow arguments
	for the plotter.

2470	SPFORM.INI switch arguments were sometimes stored in half-words,
	and later full-word multiplies were done. That produces strange
	results in banners, headers and trailers.

2471	Remove /GUIDE, /ORIGIN and /SIZE switches from SPFORM.INI since
	they didn't work and it was unclear how they should work. Replace
	the "+" guide marks with a line across the paper. Always ram the
	pen into the stops prior to starting a new job instead of setting
	the origin where ever the operator left the pen.

2472	Remove SPFORM.INI switch defaulting since it could never work
	correctly for all switches all the time (some switches take
	multiple arguments).

2473	Remove TOPS-20 fork code since it never worked & will never be made to.

2474	Fix limit clipping so plots don't overwrite banners and trailers.

2475	If we get an I/O error on the plotter, complain but continue the
	job, since plotters aren't supposed to get output errors.

2476	Always clear PSF%DO (device off-line bit) when the operator issues
	a continue command. This can't hurt anything and will be a win while
	driving a PTP. The PTP gives only off-line interrupts, but no on-line
	interrupts.

2477	Add PTP accounting and fix up checkpoint messages a bit.

2500	Insure plotter trailers won't clip.

2501	Fix PTP banners, header and trailers so characters don't get mangled.

2502	Process /BANNER, /HEADER and /TRAILER switches for all devices like
	it is done for PLTs. Also, add NOTE:foo to CDP and PTP banners since
	they tell me it's documented that way.

2503	Fix problem with J$XLIM growing with every plot done.

2504	Use symbol FTFACT from GALGEN dialogue and remove references to FTOACT.

2505	Fix up CDP headers and trailers.

2506	Do both a status update and a checkpoint prior to asking about
	limit exceeded action.

2507	Don't call EOF routines twice. Remove extra call at FILE.2+ a few.

2510	Clean up /NOTE switch processing a bit.

2511	Fix bug in PTPBYT that caused S1 and S2 to get trashed.

2512	Default /SPU value to 1 if not set in SPFORM.INI

2513	Make sure T1 is set up before calling BLKFLD to punch blank folds
	off paper tape.

2514	Correct the calculation of the number of minutes of plotting time.

2515	Fix compiler errors on TOPS20 by putting TOPS10 refs under conditional

2516	Store sixbit device name on TOPS-20 so accounting doesn't get
	screwed up. Also accumulate the number of feet plotted. Clean up
	other assorted accounting bugs.

2517	Clean up TOPS-20 card banners, headers and trailers.

2520	Zap output buffer after doing SOUT.

2521	Clarify $WTOR responses as 'ABORT' or 'PROCEED' only.

2522	Fix UP-DOWN RIGHT-LEFT confusion. QAR 10-06785

2523	Add file name info to Cannot Access File message QAR 10-06759

2524	Correct checking for a null /NOTE switch.
	Terminate job banner text properly.
	Terminate note text with a NUL when processing job banners.
	Requeue reason text may never gets to the error buffer. Fix it.

2525	Fix logic bug in SPFORM.INI parsing.

2526	Fix some bad error messages.
	GCO: 1298

2527	Remove two extraneous intructions at the end of routine P$CHKS.
	GCO: 1319

2530	Fix a bug that would not allow plots to be output if
	/HEADER was not specified.
	GCO: 1320

2531	Several very trivial fixes which don't really deserve seperate
	edit numbers.
	1) Put OUTSOK under TOPS-20 conditional since it's only needed for
		that system.
	2) Remove some extraneous symbols: J$FMSP, FOB. Put
		FILNAM under TOPS20 conditional.
	3) Fix OUTOUT on the -10 to not save S1/S2 if it is called from
		itself.
	GCO: 1341

2532	Fix a bug that keeps the last buffer from being output
	to the plotter. It may be an obscure monitor bug that has
	to be worked around.

;BEGIN CODE MEINTENANCE

2533	Fix bug in FILDIS. The /DELETE switch was improperly processed,
	when the job was ABORTED by OPR, the file was deleted.
	SPR 20-17944/CTK 1-MAR-83

End of revision history
\
PAGE
SUBTTL	CSM Revision History
				;
; Edit	  Date	   Who	Description
;======	=========  ===	===========
				;
;CSM01$	14-Nov-80  JMS	Plotter has 3 pens and an ON-LINE indicator.  Add
;			routines to change pens and proper positioning after
;			the plot.  Make sure the plotter is on-line at OUTOUT.
	CSMEDT	01	;Show value of CSM01$
	INCS=<CSM01$>	;400 increments per inch = 620 octal
IFN CSM01$,<ND	CKPTIM,^D60>	;Checkpoint every minute.
				;
;CSM02$	14-Nov-80  JMS	Use the compressed plot file format as defined
;			in PLOT.REL (from CSM's FORLIB).  Instead of one
;			byte per increment, most halfwords in the file
;			contains 9-bits of delta-X and 9 of delta-Y.
;			Use TOLP.REL to translate the disk file back
;			into calls to subroutine PLOT.
	CSMEDT	02	;Show value of CSM02$
IFN CSM02$,<IFE CSM01$,<PRINTX ?Must have CSM01$ on for CSM02$>>
				;
;CSM03$	14-Nov-80  JMS	Change the plot banner to exercise the red and
;			black pens.  Plot error message even if no
;			/TRAILER and set blue pen at P$EOF.
	CSMEDT	03	;Show value of CSM03$
				;
;CSM04$	25-Mar-81  JMS	Put the forms name in place of DISK-WRITES,
;			amount of paper in PAGES-PRINTED, cards, feet,
;			or plot time in DISK-READS.
	CSMEDT	04	;Show value of CSM04$
				;
;CSM05$	 8-Jan-81  JMS	Add a sleep request to $DSCHD.  RH of flags is
;			number of seconds to wait.  This is needed for
;			non-blocking TTY I/O routines.
	CSMEDT	05	;Show value of CSM05$
				;
;CSM06$	 8-Jan-81  JMS	Add support for the TAB Products Card Terminal.
;			It is a Reader/Punch that acts like a TTY.
	CSMEDT	06	;Show baud rate (^D1200=^O2260)
IFN CSM06$,<IFE CSM05$,<PRINTX ?Must have CSM05$ on for CSM06$>>
				;
;CSM07$	 8-Mar-83  JMS	Remove DSPMOD so that cards are punched in ASCII,
;			paper tape is punched in ASCII, and plots are
;			done in 18-bit BINARY mode unless explicitly
;			requested otherwise.  This is so that output
;			from SOS or SED is not punched in image-binary.
;			Remove "BEGIN:", "JOB", "jobnam", "USER:" from
;			card punch banner, ignore QUEUE's default of
;			/NOHEADER and always punch file header on cards.
	CSMEDT	07	;Show value of CSM07$
				;
;CSM08$	28-Jun-83  JMS	Add support for the Houston Instruments PTC-6
;			Plotter Terminal Controller on a TTY line.
	CSMEDT	08	;Show value of CSM08$
IFN CSM08$,<	EXTERN	PTCINI,PTCMOV,PTCOUT,PTCFIN
IFE CSM05$,<PRINTX ?Must have CSM05$ on for CSM08$>>
				;

CSMED$==10	;Increment this to change .JBVER

;End of CSM Revision History
SUBTTL	Constants  (Conditional and Unconditional)

;ACCUMULATORS
	M==12				;MESSAGE ADDRESS
	S==13				;STATUS FLAGS
	J==14				;BASE ADDRESS OF CONTEXT DATA
	C==15				;I/O CHARACTER
	E==16				;POINTER TO CURRENT FP

;SYSTEM DEPENDENT PARAMETERS

	DEFINE	FACT,<IFN FTFACT>
	SYSPRM	PTPBSZ,^D36,^D8		;OUTPUT BYTESIZE FOR PTP

;RANDOM CONSTANTS
	ND	PDSIZE,100		;SIZE OF PUSHDOWN LIST
	ND	FACTSW,-1		;-1 TO INCLUDE ACCOUNTING
	ND	NSTRMS,5		;NUMBER OF STREAMS
	ND	ACCTSW,1		;TURN ACCOUNTING ON/OFF
	ND	TXT$LN,^D50		;LENGTH OF JOB TEXT BUFFER
	ND	ERR$LN,^D20		;LENGTH OF JOB ERROR TEXT BUFFER
	ND	NBFRS,2			;NUMBER OF BUFFERS TO CREATE
	ND	NJBPGS,3		;NUMBER OF JOB PAGES TO CREATE

	ND	CKPTIM,^D120		;# of seconds between chkpnts
	XP	MSBSIZ,50		;SIZE OF A MESSAGE BLOCK

;CHECKPOINT BLOCK OFFSETS
	XP	CKFIL,0			;NUMBER OF FILES COMPLETED
	XP	CKCOP,1			;NUMBER OF COPIES COMPLETED
	XP	CKPAG,2			;NUMBER OF UNITS OF LAST COPY
	XP	CKTPP,3			;NUMBER OF TOTAL UNITS processed
	XP	CKFLG,4			;CHECKPOINT FLAGS
	  XP	CKFREQ,1B0		;REQUED BY OPERATOR
	  XP	CKFCHK,1B1		;JOB WAS CHECKPOINTED


;DEVICE DISPATCH TABLE OFFSETS
	XP	DHEAD,0			;ADDRESS OF FILE HEADER ROUTINE
	XP	DTAIL,1			;ADDRESS OF FILE TRAILER (EOF) ROUTINE
	XP	DNAME,2			;DEVICE GENERIC NAME IN 6BIT
	XP	DBYTE,3			;OUTPUT BYTE SIZE
	XP	DPROC,4			;ADDRESS OF FILE processing ROUTINE
	XP	DBANN,5			;ADDRESS OF JOB BANNER ROUTINE
	XP	DEOJ,6			;ADDRESS OF JOB TRAILER (EOJ) ROUTINE
	XP	DLETR,7			;ADDRESS OF CHARACTER processing ROUTINE
	XP	DERR,10			;ADDRESS OF ERROR HANDLER
	XP	DACCT,11		;ADDRESS OF END ACCOUTING ROUTINE
	XP	DCHKP,12		;ADDRESS OF CHECKPOINT TEXT ROUTINE

	CONT.	(Constants)		;FORCE NEW LISTING PAGE

; Card punch constants
;
	XP	CPC,^D80		;CHARACTERS PER CARD


; Plotter constants
;
COMMENT ~
  From the OPERATOR's point of view, the supply spool on the plotter is
above the pen holder, and the takeup spool is below the pen holder.
Therefore, to move the pen in the +Y direction, the pen holder moves to
the left.  To move the pen in the +X direction, the pen stays still and
the paper is moved down (towards the takeup spool).  The following
definitions are based on this point of view.
;End of COMMENT ~

	XP	PNUP,40			;RAISE PEN
	XP	PNDN,20			;LOWER PEN
	XP	PEN2,14			;SELECT PEN 2
	XP	PEN3,03			;SELECT PEN 3
	XP	CNGP,17			;CHANGE PENS
	XP	XYU,10			;-X   move the paper up
	XP	XYD,4			;+X   move the paper down
	XP	XYL,2			;+Y   move pen holder left
	XP	XYR,1			;-Y   move pen holder right
	PLUSX== XYD		;[CSM]	;Move in positive X direction   0
	PLUSY== XYL		;[CSM]	;Move in positive Y direction  90
	MINUSX==XYU		;[CSM]	;Move in negative X direction 180
	MINUSY==XYR		;[CSM]	;Move in negative Y direction 270
	XP	XYUL,XYL!XYU		;-X+Y MOVE UP+LEFT
	XP	XYDL,XYL!XYD		;+X+Y MOVE DOWN+LEFT
	XP	XYUR,XYR!XYU		;-X-Y MOVE UP+RIGHT
	XP	XYDR,XYR!XYD		;+X-Y MOVE DOWN+RIGHT

	CSMEDT	01,0	;3-pen plotter, definitions
IFE CSM01$,<XP	PLTPEN,^D9>		;# TICS FOR PLOT PEN UP/DOWN
IFN CSM01$,<XP	PLTPEN,^D<1800*30/1000>	;30 millisec compared to 1800 per second

	XP	PLTMOV,1		;# TICS FOR PEN MOVEMENT
	XP	CHRPLN,^D90		;# CHARACTERS PER LINE MAXIMUM


; Paper tape punch constants
;
	XP	CHPFLD,^D85		;CHARACTERS PER FOLD OF PTP
	XP	FRMPFT,^D120		;FRAMES PER FOOT OF TAPE
SUBTTL	MACROS

DEFINE LP(SYM,VAL,FLAG),<;;Flag="Z" marks a variable to be zeroed per job
	IF1,<
		XLIST
		IFNDEF J...X,<J...X==1000>
		IFDEF SYM,<PRINTX  ?PARAM SYM USED TWICE>
		SYM==J...X
		J...X==J...X+VAL
		IFNDEF ...BP,<...BP==1B0>
		IFNDEF ...WP,<...WP==0>
		REPEAT VAL,<
		IFIDN <FLAG><Z>,<LPZ(\...WP,...BP)>
			...BP==...BP_<-1>
			IFE ...BP,<
				...BP==1B0
				...WP==...WP+1
			>  ;;END IFE ...BP
		>  ;;END REPEAT VAL
	IFL 2000-J...X,<PRINTX ?PARAMETER AREA LONGER THAN A PAGE>
		LIST
		SALL
	>  ;END IF1

	IF2,<
	.XCREF
	J...X==SYM
	.CREF
	SYM==J...X>;;END IF2>;;END DEFINE LP
;[CSM] Removed 2 CRLFs so that MACRO will show value in listing

DEFINE LPZ(A,B),<
	IFNDEF ...Z'A,<...Z'A==B>
	IFDEF ...Z'A,<...Z'A==...Z'A!B>
>  ;END DEFINE LPZ
SUBTTL	Special Forms Handling Parameters

;Format of SYS:SPFORM.INI

;  DEV FORM/SWITCH	This line applies to all devices of this type
;  DEV FORM:ALL/SWITCH	This line applies to all devices of this type
;  DEV FORM:LOC/SWITCH	This line applies to devices at the central site
;  DEV FORM:REM/SWITCH	This line applies to devices on remote nodes

;	"DEV" can be one of PLT, CDP, or PTP
;	"FORM" is the name of the forms type, 6 characters or less

;Note:  SPROUT will use the first entry which meets the location
;	specification for its device.  Therefore, if ALL is used with
;	LOC or REM, ALL should be after the LOC or the REM.


;Switches legal for all devices

;	/BANNER		Output the job header
;	/HEADER		Output file headers
;	/TRAILER	Output the job trailer
;	/NOTE:AA	Type NOTE to the OPR when forms are mounted


;Switches legal for plotters only

;	/SPU:NN		Steps per unit (a factor of all XX and YY)
;	/SPS:NN		Steps per second (for calculating run time)
;	/MAXIMUM:XX:YY	Maximum pen position
;	/MINIMUM:XX:YY	Minimum pen position after file header


;In the above and below explanations:

;	NN	is a decimal number
;	AA	is a string of 1 to 50 characters, terminated by next "/"
;	XX	is a limit for the X axis
;	YY	is a limit for the Y axis


;Typical SPFORM.INI forms specification

;	CDP NORMAL/BANNER/HEADER -
;		  /NOTE:Load NORMAL Cards in Card Punch
;
;	PLT NORMAL/BANNER/HEADER/TRAILER/SPS:900
;		  /SPU:1/MINIMUM:0:0/MAXIMUM:0:5900-
;		  /NOTE:Set Plotter Controls to 200 Steps per inch
;
;	PTP NORMAL/BANNER/HEADER/TRAILER
;	PTP BLACK /BANNER/HEADER/TRAILER/NOTE:Black oiled paper tape

PAGE
COMMENT |	CSM interpretation of plotter parameters

						;
Example for a drum plotter:
						;
PLT NORMAL /SPS:1800/SPU:4/MINIMUM:0:0/MAXIMUM:0:1100 -
	   /BANNER/HEADER/TRAILER
						;
PLT		= This line applies to the plotter (not CDP or PTP).
NORMAL		= The forms name.
/SPS:1800	= Do accounting based on speed of 1800 steps per second.
/SPU:4		= This plotter uses 400 steps per inch, the following
                  numbers are in 1/100ths of an inch.
/MINIMUM:0:0	= Pen cannot go to left or below the starting point.
/MAXIMUM::1100	= There is no maximum limit in the +X direction, +Y movement
		  is limited to 11.00 inches.  The height of characters used
		  in the /BANNER/HEADER/TRAILER is 11.00/90 = 0.12 inches.
-		= Hypen indicates a continued line.
/BANNER		= Plot "* Start job XXX" 0.12 inches high, plot user's name
		  and PPN 0.36 inches high, and a line across the paper.
/HEADER		= Plot file name 0.12 inches high and a dashed line.
/TRAILER	= Plot a dashed line and the summary 0.12 inches high.
/NOTE		= No note is specified, so that "OPR>START PLOT 0" will
		  not require a "RESPOND 'PROCEED' WHEN READY".
						;
End of COMMENT |

DEFINE SWITCHES,<
	FF	BANNER
	FF	TRAILER
	FF	HEADER
	FF	NOTE
	FF	SPS
	FF	SPU
	FF	MINIMUM
	FF	MAXIMUM
>


;GENERATE TABLE OF SWITCH NAMES
DEFINE FF(A),<	<<SIXBIT /A/>&777777B17>+S$'A	>;;All on 1 line to look nice

	XALL		;[CSM] Show definition in the listing
FFNAMS:	SWITCHES
	F$NSW==.-FFNAMS			;NUMBER OF SWITCHES
	SALL		;[CSM] Normal macro expansions
SUBTTL	Job Parameter Area

	LP	J$$BEG,0		;BEGINNING OF PARAMETER AREA

;REQUEST PARAMETERS
	LP	J$RFLN,1		;NUMBER OF FILES IN REQUEST
	LP	J$RLIM,1,Z		;JOB LIMIT IN PAGES
	LP	J$RTIM,1		;START TIME OF JOB
	LP	J$RNFP,1,Z		;NUMBER OF FILES processed
	LP	J$RNCP,1,Z		;NUMBER OF COPIES OF CURRENT FILE
	LP	J$RNPP,1,Z		;NUMBER OF PAGES IN CURRNET FILE
	LP	J$RACS,20		;CONTEXT ACS
	LP	J$RPDL,PDSIZE		;CONTEXT PUSHDOWN LIST

;DEV PARAMETERS
	LP	J$LBUF,1		;ADDRESS OF DEV BUFFER
	LP	J$LBRH,1		;BUFFER RING HEADER
	LP	J$LBPT,1		;BUFFER BYTE POINTER
	LP	J$LBCT,1		;BUFFER BYTE COUNT
	LP	J$TBCT,1		;TOTAL BYTE COUNT FOR DEVICE
	LP	J$LIOA,1		;-1 IF WE ARE IN A SOUT OR OUT
	LP	J$LREM,1		;-1 IF WE ARE A REMOTE DEVICE
	LP	J$LSER,1		;ADDRESS OF DEVICE SERVICE DISPATCH


TOPS10 <
	LP	J$LJFN,1		;DEV I/O CHANNEL (OR JFN)
	LP	J$LDEV,1		;DEVICE NAME (SIXBIT)
	LP	J$LIOS,2		;DEVICE STATUS
	LP	J$LIOE,1		;-1 IF DEVICE ERROR
> ;END TOPS10 CONDITIONAL

TOPS20 <
	LP	J$LJFN,1		;JFN FOR THE DEV
	LP	J$LDEV,2		;DEVICE NAME STRING
	LP	J$LIOS,2		;DEVICE STATUS
	LP	J$LIOE,1		;-1 IF DEVICE ERROR
	LP	J$LIBP,1		;INITIAL BYTE POINTER
	LP	J$LIBC,1		;INITIAL BYTE COUNT FOR BUFFERS
>  ;END TOPS20 CONDITIONAL

;CURRENT FORMS PARAMETERS
	LP	J$FIFN,1		;TEMPORARY IFN FOR FORM FILE
	LP	J$FORM,1		;CURRENT FORMS TYPE
	LP	J$FPFM,1		;PREVIOUS FORMS TYPE
	LP	J$FPLT,1		;-1 = Plotter-only switches are legal

;STORAGE FOR CURRENT FORMS SWITCHS

DEFINE	FF(X) <LP	J$F'X,1>

	LP	J$FCUR,0		;ORIGIN OF CURRENT SWITCH VALUES
	SWITCHES			;ONE ENTRY PER SWITCH


;MISCELLANY
	LP	J$XFOB,FOB.SZ		;A FILE OPEN BLOCK
	LP	J$XTBF,TXT$LN,Z		;$TEXT BUFFER FOR OUTPUT DEVICE
	LP	J$XERR,ERR$LN,Z		;$TEXT BUFFER FOR ERROR MESSAGES

;CARD PUNCH VARIABLES
	LP	J$XCD1,1		;1 SCRATCH LOCATION FOR CDP OUTPUT
	LP	J$CMSK,1		;SPECIAL MASK FOR BLOCK CARD LETTERS
	LP	J$XCHB,40		;CHECKSUM BLOCK

	CSMEDT	05,1	;TTY I/O and SLEEP, part 1 just before PLOTTER VARIABLES
IFN CSM05$,<	;Flags and variables
	LP	J$TTY,1			;'CDP' in LH, UDX in RH
	LP	J$WUDT,1		;UDT when to wakeup
	LP	J$NACK,1		;Count of Negative ACKs
>  ;End of IFN CSM05$
;PLOTTER VARIABLES

;[CSM]	LP	J$PAUS,1		;PAUSE FOR EVERY FORM
	LP	J$XPOS,1		;CURRENT PLOTTER X COORDINATE
	LP	J$XORG,1		;ORIGINAL X MINIMUM
	LP	J$XLIM,1,Z		;HIGHEST XSTEP SEEN THIS PLOT
	LP	J$XMIN,1		;X MINIMUM POINT IN FORM
	LP	J$XMAX,1		;X MAXIMUM POINT IN FORM
	LP	J$YPOS,1		;CURRENT PLOTTER Y COORDINATE
	LP	J$YLIM,1		;HIGHEST YSTEP SEEN THIS PLOT
	LP	J$YMIN,1		;MINIMUM Y POINT IN FORM
	LP	J$YMAX,1		;MAXIMUM ALLOWABLE Y COORDINATE
	LP	J$ROTA,1		;GRID ROTATION (0-3)
	LP	J$PPOS,1		;PEN POSITION (UP 0  DOWN -1)
	LP	J$CSIZ,1		;CHARACTER SIZE
	LP	J$XBAS,1		;CHARACTER X BASE
	LP	J$YBAS,1		;CHARACTER Y BASE
	LP	J$FUDG,1		;CHARACTER WIDTH FUDG
	LP	J$SPTR,1		;POINTER TO CHARACTER SEGMENT BYTES
	LP	J$STEP,1		;STEP FUNCTION DETERMINES MOVEMENT

	CSMEDT	01,1	;3-Pen plotter, part 1 in "PLOTTER VARIABLES"
IFN CSM01$,<	;Flags and variables for plotter
	LP	J$PENN,1		;Pen number, from 1 to 3
	LP	J$XLOW,1		;Lowest XSTEP seen while pen was down
>  ;End of IFN CSM01$


; Paper tape punch variables
;
	LP	J$TFRM,1,Z		;FRAMES OF TAPE PUNCHED

;ACCOUNTING BLOCK

	LP	J$PTPM,1		;PLOTTER TICS PER MINUTE
	LP	J$PTIC,1,Z		;ACCOUNTING FOR PLOTTER
	LP	J$APRT,1,Z		;NUMBER OF PAGES processed
	LP	J$ADRD,1,Z		;DISK BLOCKS READ.
	LP	J$APRI,1,Z		;JOBS PRIORITY
	LP	J$ARTM,1,Z		;JOBS RUN TIME (CPU)
	LP	J$ASEQ,1,Z		;JOBS SEQUENCE NUMBER
	LP	J$AFXC,1,Z		;TOTAL FILES processed (FILES*COPIES)
	LP	J$ADSP,1,Z		;DISPOSITION (SIXBIT)
	LP	J$AQUE,1,Z		;QUEUE NAME (SIXBIT)
;DISK FILE PARAMETERS

	LP	J$DIFN,1		;THE IFN
	LP	J$DFDA,1		;THE FD ADDRESS
	LP	J$DBPT,1		;BUFFER BYTE POINTER
	LP	J$DBCT,1		;BUFFER BYTE COUNT
	LP	J$DBSZ,1		;INPUT BYTE SIZE
	LP	J$DMOD,1		;I/O MODE OF DISK FILE
	LP	J$DSPN,1		;SPOOLED FILE NAME IF ANY
	LP	J$DSPX,1		;SPOOLED FILE EXTENSION


	LP	J$$END,1		;END OF PARAMETER AREA
		J$$LEN==J$$END		;LENGTH OF PARAMETER AREA
	INTERN	J$$END		;[CSM]	;For .ASSIGNing data areas


;NOW GENERATE A BIT TABLE OF WHICH WORDS IN THE JOB DATA PAGE TO ZERO
;	ON A NEW JOB

ZTABLE:					;PUT TABLE HERE

DEFINE ZTAB(A),<
	IFNDEF ...Z'A,<...Z'A==0>
	EXP	...Z'A
>  ;END DEFINE ZTAB

	ZZ==0
REPEAT <^D512+^D35>/^D36,<
	XLIST
	ZTAB(\ZZ)
	ZZ==ZZ+1
	LIST
>  ;END REPEAT
SUBTTL	Resident JOB DaTABase

STREAM:	BLOCK	1			;(LH) -1 WHILE IN STREAM CONTEXT
					;      0 WHILE IN SCHED CONTEXT
					;(RH) CURRENT STREAM NUMBER

JOBPAG:	BLOCK	NSTRMS			;ADDRESS OF A THREE PAGE BLOCK
					; ONE FOR REQUEST, ONE FOR JOB PARAMS, ONE FOR BUFFER

JOBOBA:	BLOCK	NSTRMS			;TABLE OF OBJECT BLOCK ADDRESSES

JOBSTW:	BLOCK	NSTRMS			;JOB STATUS WORD

JOBACT:	BLOCK	NSTRMS			;-1 IF STREAM IS ACTIVE, 0 OTHERWISE

JOBOBJ:	BLOCK	3*NSTRMS		;LIST OF SETUP OBJECTS

JOBWAC:	BLOCK	NSTRMS			;WTOR ACK CODE (TIME SETUP WAS RECIEVED)

JOBCHK:	BLOCK	NSTRMS			;Stream checkpoint indicator
					;Contains the time for the next chkpnt
					;  or 0 if one is requested

	CSMEDT	05,2	;TTY I/O and SLEEP, part 2 before "LOWEND=="
IFN CSM05$,<
SLEEPT:	BLOCK	1			;Time to sleep
>  ;End of IFN CSM05$

	LOWEND==.-1

TOPS10 <

VECTOR:	BLOCK	0			;BEGINNING OF INTERRUPT VECTOR
VECIPC:	BLOCK	4			;IPCF INTERRUPT BLOCK
VECDEV:	BLOCK	4*NSTRMS		;DEVICE INTERRUPT BLK
	ENDVEC==.-1			;END OF INTERRUPT VECTOR

>  ;END TOPS10 CONDITIONAL

TOPS20 <

LEV1PC:	BLOCK	1			;LVL 1 INTERRUPT PC STORED HERE
LEV2PC:	BLOCK	1			;LVL 2 INTERRUPT PC STORED HERE
LEV3PC:	BLOCK	1			;LVL 3 INTERRUPT PC STORED HERE

> ;END TOPS20 CONDITIONAL

;SCHEDULER FLAGS
	PSF%OB==1B1			;OUTPUT BLOCKED
	PSF%DO==1B2			;DEVICE IS OFF-LINE
	PSF%ST==1B3			;STOPPED BY OPERATOR
	PSF%OR==1B4			;OPERATOR RESPONSE WAIT
	PSF%NP==1B5			;GO TO NEXT PROCESS

DEFINE $DSCHD(FLAGS),<
	$CALL	DSCHD
	XLIST
	JUMP	[EXP FLAGS]
	LIST
	SALL
>  ;END DEFINE $DSCHD
SUBTTL	Program Initialization

SPROUT:	JFCL				;NO CCL ENTRY
	RESET				;CLEAR ALL ACTIVE I/O

IFN CSM02$,<	;Check to see where LINK .ASSIGNed the buffers
	SKIPLE	[TOLP..##-1777]		;Make sure data area is only one page
	 OUTSTR	[ASCIZ	/?Data area for TOLP extends past 1777/]
>  ;End of IFN CSM02$
IFN CSM06$,<
	SKIPLE	[TABC..##-1777]		;Make sure data area is only one page
	 OUTSTR	[ASCIZ	/?Data area for TABCDP extends past 1777/]
>  ;End of IFN CSM06$
IFN CSM08$,<
	SKIPLE	[PTC6..##-1777]		;Make sure data area is only one page
	 OUTSTR	[ASCIZ	/?Data area for PTC6 extends past 1777/]
>  ;End of IFN CSM08$

	MOVE	P,[IOWD PDSIZE,PDL]

	MOVEI	S1,IB.SZ		;GET SIZE OF IB
	MOVEI	S2,IB			;GET ADDR OF IB
	$CALL	I%INIT			;START UP THE WORLD
	MOVEI	S1,<LOWEND-LOWBEG>+1	;LOAD LENGTH OF RESIDENT IMPURE DATA
	MOVEI	S2,LOWBEG		;AND ITS ADDRESS
	$CALL	.ZCHNK			;AND ZERO IT OUT
	$CALL	INTINI			;INITIALIZE THE INTERRUPT SYSTEM
IFN ACCTSW,<
	SETOM	ACTFLG			;UNLESS HE DOESN'T WANT IT
	PUSHJ	P,ACTINI		;SET UP ACCOUNTING DATA
>  ;END IFE ACCTSW
TOPS20 <
	HRRZI	S1,.MSIIC		;BYPASS MOUNTS
	MSTR
	 ERJMP	.+1
> ;END TOPS20 CONDITIONAL

	$CALL	I%ION			;TURN ON INTERRUPTS
	MOVEI	T1,HELLO		;GET HELLO MESSAGE
	$CALL	SNDQSR			;SEND IT

TOPS10<	MOVSI	S1,.STSPL		;PULL A SETUUO TO
	SETUUO	S1,			;    CLEAR ANY SPOOLING BITS
	   JFCL				;IGNORE THE ERROR
>
	$CALL	I%HOST			;GET LOCAL HOST STUFF
TOPS10 <MOVEM	T2,CNTSTA>		;SAVE NUMBER AS CENTRAL STATION
TOPS20 <MOVEM	T1,CNTSTA>		;SAVE NAME AS CENTRAL STATION

	JRST	MAIN			;AND GO!
SUBTTL	Idle Loop


MAIN:	MOVE	P,[IOWD PDSIZE,PDL]	;SETUP A NEW PDL
	HRROS	STREAM			;SET SCHEDULER CONTEXT
	$CALL	CHKQUE			;PROCESS MESSAGES

	MOVX	P2,PSF%NP		;GET NEXT PASS FLAG
MAIN.1:	MOVSI	P1,-NSTRMS		;SET UP DISPATCH AC

MAIN.2:	SKIPN	JOBACT(P1)		;IS THIS STREAM ACTIVE?
	JRST	MAIN.3			;NO,,GET THE NEXT STREAM.
	HRROM	P1,STREAM		;YES -- SAVE NUMBER (IN SCHED CONTEXT)
	MOVE	J,JOBPAG(P1)		;GET ADDRESS OF JOB PAGES
	PUSHJ	P,CHKPNT		;CHECKPOINT JOB IF NECESSARY

	CSMEDT	05,2	;TTY I/O and SLEEP, part 2 at MAIN.2:+5
IFN CSM05$,<	;Watch for sleep time
	PUSHJ	P,CHKTIM		;Time to run this stream?
	JUMPF	MAIN.3			;Not yet
>  ;End of IFN CSM05$

	SKIPN	JOBSTW(P1)		;IS THE STREAM BLOCKED?
	JRST	MAIN.4			;NO -- SETUP STREAM CONTEXT
MAIN.3:	ANDCAM	P2,JOBSTW(P1)		;CLEAR NEXT PASS BIT
	AOBJN	P1,MAIN.2		;TRY NEXT STREAM
	TXZE	P2,PSF%NP		;ON SECOND PASS?
	 JRST	MAIN.1			;NOT YET..TRY AGAIN

;HERE IF NO STREAM IS RUNNABLE

IFE CSM05$,< MOVEI  S1,0	>	;SNOOZE FOR INTERRUPT
IFN CSM05$,< MOVE  S1,SLEEPT	>	;Get sleep time in seconds
	$CALL	I%SLP			;GO WAIT
	$CALL	CHKQUE			;PROCESS MESSAGES
IFN CSM05$,< SETZM  SLEEPT	>	;Clear timer request
	JRST	MAIN.1			;AND TRY AGAIN

MAIN.4:	CAME	J,ACTPAG		;SAME STREAM?
	$CALL	ACTRNT			;NO..INIT RUNTIME VALUES
	MOVEM	J,ACTPAG		;SAVE THIS AS ACCOUNTING PAGE
	HRLZI	0,J$RACS+1(J)		;SET UP STREAM CONTEXT BLT
	HRRI	0,1			;START WITH AC 1
	BLT	0,17			;RESTORE THE ACS
	HRRZS	STREAM			;SET STREAM CONTEXT
	POPJ	P,			;AND RESTORE STREAM PC

;NOTE:	Stream is now active and will return via DSCHD (see next page)
SUBTTL	Deschedule Process

;DSCHD is called by the $DSCHD macro to cause the "current" stream to
;	be un-scheduled.  The call is:
;
;	$DSCHD(flags)
;
;which generates:
;
;	PUSHJ   P,DSCHD
;	JUMP    [EXP flags]

DSCHD:	HRROS	STREAM			;SET SCHED CONTEXT
	MOVEM	0,J$RACS(J)		;SAVE AC 0
	MOVEI	0,J$RACS+1(J)		;PLACE TO PUT AC 1
	HRLI	0,1			;SETUP THE BLT POINTER
	BLT	0,J$RACS+17(J)		;SAVE STREAM ACS
	HRRZ	S1,0(P)			;GET ADDRESS OF "JUMP [FLAGS]"

	CSMEDT	05,2	;TTY I/O and SLEEP, part 2 at DSCHD:+6
IFE CSM05$,< MOVE  S1,@0(S1) >		;GET THE FLAGS
IFN CSM05$,<
	HRRZ	T1,@0(S1)		;Get the seconds to sleep
	HLLZ	S1,@0(S1)		;Get the flags
>  ;End of IFN CSM05$

	HRRZ	S2,STREAM		;GET STREAM NUMBER
	IORM	S1,JOBSTW(S2)		;SET THE FLAGS

IFE CSM05$,< JRST  MAIN >		;AND GO LOOP
IFN CSM05$,<	;This code taken from LPTSPL
	JUMPE	T1,MAIN			;Loop if no sleep time

CONT. (SCHEDULER)
	SKIPE	SLEEPT			;Is a sleep time set?
	CAMG	T1,SLEEPT		;And current amount smaller?
	 MOVEM	T1,SLEEPT		;Yes, save shorter interval
	$CALL	I%NOW			;Get the current time
	IMULI	T1,3			;Seconds to UDT ticks
	ADD	T1,S1			;Build wake-up time
	MOVEM	T1,J$WUDT(J)		;Save for CHKTIM
	JRST	MAIN			;Loop

SUBTTL	CHKTIM - Routine to see if it's time to schedule a stream

;CALL:	J/  Pointer to job page
;
;REG:	TRUE if stream can be scheduled now (timewise)
;	FALSE if stream needs to wait

CHKTIM:	$CALL	I%NOW			;Get the current time
	MOVE	S2,S1			;Get the UDT in S2
	MOVE	S1,J$WUDT(J)		;Get the stream wakeup time
	SUB	S1,S2			;Get time left in UDT ticks
	IDIVI	S1,3			;Convert to seconds
	SKIPG	S1			;Any seconds left?
	 JRST	[SETZM	SLEEPT		  ;No, clear old sleep time
		 $RETT		]	  ;Return TRUE
	SKIPE	SLEEPT			;Is a sleep time set?
	CAMG	S1,SLEEPT		;And current amount smaller?
	 MOVEM	S1,SLEEPT		;Yes, save the shorter interval
	$RETF				;Return FALSE

;End of code taken from LPTSPL>  ;End of IFN CSM05$
SUBTTL	SETUP/SHUTDOWN Message

SETUP:	LOAD	S2,SUP.FL(M)		;GET THE FLAGS
	TXNE	S2,SUFSHT		;IS IT A SHUTDOWN?
	JRST	[MOVEI S1,SUP.TY(M)	;GET OBJECT ADDRESS
		 $CALL	FNDOBJ		;FIND IT
		 JRST SHUTDN]		;AND SHUT IT DOWN

	SETZ	T2,			;CLEAR A LOOP REG

SETU.1:	SKIPN	JOBPAG(T2)		;A FREE STREAM?
	JRST	SETU.2			;YES!
	CAIGE	T2,NSTRMS-1		;NO, LOOP THRU THEM ALL?
	AOJA	T2,SETU.1		;NO, KEEP GOING
	$STOP(TMS,Too many setups)

;[CSM] There is a problem if two streams start with 1/3 of a second
SETU.2:	HRRZM	T2,STREAM		;SAVE THE STREAM NUMBER
	$CALL	I%NOW			;USE SETUP TIME AS ACK STAMP
	LSH	S1,3		;[CSM]	;Free up 3 bits
	IOR	S1,T2		;[CSM]	;Make it be unique
	MOVEM	S1,JOBWAC(T2)		;SAVE CODE FOR $WTOR
	MOVEI	S1,NJBPGS		;NUMBER OF PAGES NEEDED
	$CALL	M%AQNP			;GET THEM
	PG2ADR	S1			;CONVERT TO AN ADDRESS
	MOVEM	S1,JOBPAG(T2)		;AND SAVE IT
	MOVE	J,S1			;PUT IT IN J
	MOVEM	J,J$RACS+J(J)		;SAVE J AWAY
	MOVEI	S1,2000(J)		;DEV BUFFER ADDRESS
	MOVEM	S1,J$LBUF(J)		;STORE IT
	MOVE	S2,T2			;COPY OVER THE STREAM NUMBER
	IMULI	T2,OBJ.SZ		;GET OFFSET OF OBJECT BLOCK
	ADDI	T2,JOBOBJ		;ADD IN THE BASE
	MOVEM	T2,JOBOBA(S2)		;STORE OBJECT ADDRESS
	MOVE	S2,T2			;GET DESTINATION OF BLT INTO S2
	HRLI	S2,SUP.TY(M)		;MAKE A BLT POINTER
	BLT	S2,OBJ.SZ-1(T2)		;BLT THE OBJECT BLOCK
	$CALL	OUTGET			;GET THE OUTPUT DEVICE
	$CALL	RSETUP			;SEND RESPONSE TO SETUP
	HRRZ	S2,STREAM		;GET OUR STREAM NUMBER
	$WTO	(^T/@SETMSG(S1)/,,@JOBOBA(S2)) ;TELL THE OPERATOR
	CAIN	S1,%RSUOK		;ALL IS OK?
	$RETT				;YES, RETURN
	JRST	SHUTDN			;NO, SHUT IT DOWN

SETMSG:	[ASCIZ /Started/]
	[ASCIZ /Not available right now/]
	[ASCIZ /Does not exist/]

ACTBEG:	SKIPN	ACTFLG			;ACCOUNTING?
	 $RETT				;NO..JUST RETURN
	LOAD	S1,.EQSEQ(J),EQ.SEQ	;GET SEQUENCE NUMBER
	STORE	S1,J$ASEQ(J)		;STORE IT
	LOAD	S1,.EQSEQ(J),EQ.PRI	;GET EXTERNAL PRIORITY
	STORE	S1,J$APRI(J)		;STORE IT
	MOVE	S1,J$LSER(J)		;GET DISPATCH ADDRESS
	MOVE	S1,DNAME(S1)		;GET DEVICE (QUEUE) NAME
	MOVEM	S1,J$AQUE(J)		;SAVE FOR ACT END
	SETZM	J$PTIC(J)		;CLEAR PLOTTER ACCOUNTING
	$RETT				;RETURN

ACTEND:	SKIPN	ACTFLG			;ARE WE DOING ACCT?
	$RETT				;NO,,RETURN NOW.
	LOAD	S1,.EQSEQ(J),EQ.IAS	;GET THE INVALID ACCT STRING BIT
	JUMPN	S1,.RETT		;IF LIT,,THEN JUST RETURN
	MOVE	S1,J$LSER(J)		;GET DISPATCH ADDRESS
	PUSHJ	P,DACCT(S1)		;DO FINAL ACCOUNTING
	MOVX	S2,'NORMAL'		;ASSUME NORMAL DISPOSITION
	TXNE	S,RQB			;REQUED?
	MOVX	S2,'REQUED'		;YES
	TXNE	S,ABORT			;ABORTED?
	MOVX	S2,'CANCEL'
	MOVEM	S2,J$ADSP(J)		;STORE DISPOSITION
	$CALL	ACTRNT			;DO FINAL RUNTIME ACCOUTING
	SETZM	ACTPAG			;CLEAR THE PAGE ADDRESS

TOPS10<	MOVE	S1,[.NDRNN,,S2]		;GET CONVERT TO NAME FCT CODE
	MOVEI	S2,2			;A BLOCK LENGTH OF 2
	MOVE	T1,.EQROB+.ROBND(J)	;GET THE NODE NUMBER

CONT. (ACTEND)
FACT<	HRLZM	T1,FACTBL+3 >		;STORE NODE NUMBER NOW

	NODE.	S1,			;CONVERT IT
	 SKIPA				;SKIP ON AN ERROR
	MOVEM	S1,.EQROB+.ROBND(J)	;SAVE THE NODE NAME
	MOVX	S1,<ACTLEN,,ACTLST>	;SET UP AC
	QUEUE.	S1,			;MAKE A USAGE ENTRY
	 PUSHJ	P,ACTE.1		;FAILED,,TELL OPR

FACT<	MOVE	S1,L.LIN		;GET LINE NUMBER
	LDB	S2,[POINT 7,L.TTY,6]	;GET TERMINAL DESIGNATOR
	CAIN	S2,"C"			;ON THE CTY
	MOVEI	S1,7777			;YES, CTY DESIGNATOR
	CAIN	S2,"D"			;DETACHED
	MOVEI	S1,7776			;YES, FLAG THAT INSTEAD OF LINE NUMBER
	LSH	S1,6			;PUT IN BITS 18-29
	HRL	S1,L.JOB		;INSERT JOB NUMBER
	IOR	S1,[251000,,13]		;ADD FACT TYPE AND NUMBER OF WORDS
	MOVEM	S1,FACTBL+0		;STORE IN BLOCK
	MOVE	S1,.EQOID(J)		;GET PPN
	MOVEM	S1,FACTBL+1		;STORE
	SETZM	FACTBL+2		;DAEMON FILLS IN THE DATE/TIME
	MOVE	S1,[%CNSER]		;CPU SERIAL NUMBER
	GETTAB	S1,			;ASK FOR IT
	  SETZ	S1,			;USE 0 IF CAN'T FIND IT
	HLLZ	S2,J$AQUE(J)		;GET QUEUE NAME
	TLZ	S2,77			;CLEAR JUNK
	IOR	S1,S2			;INSERT QUEUE NAME
	IORM	S1,FACTBL+3		;NODE NUMBER ALREADY STORED FROM ABOVE
	MOVE	S1,J$ARTM(J)		;RUN TIME IN MILLISECONDS
	MOVEM	S1,FACTBL+4		;STORE
	SETZM	FACTBL+5		;*** CORE TIME INTERGRAL
	MOVE	S1,J$ADRD(J)		;DISK READS
	MOVEM	S1,FACTBL+6		;STORE

	CSMEDT	04,1	;CSM accounting, part 1 after QUEUE. uuo
IFE CSM04$,< SETZM FACTBL+7 >		;No disk writes
IFN CSM04$,<
	MOVE	S1,J$FORM(J)		;Get the forms type
	MOVEM	S1,FACTBL+7		;Instead of disk writes
>  ;End of CSM04$

CONT. (ACTEND)

	MOVE	S1,J$LDEV(J)		;DEVICE NAME
	MOVEM	S1,FACTBL+10		;STORE
	MOVE	S1,J$ASEQ(J)		;SEQUENCE NUMBER
	MOVEM	S1,FACTBL+11		;STORE
	MOVE	S1,J$APRT(J)		;Number of cards, feet, minutes
	MOVEM	S1,FACTBL+12		;Store as pages printed
	MOVE	S1,[14,,FACTBL-1]	;DAEMON ARGUMENT
	DAEMON	S1,			;MAKE THE FACT ENTRY
	  JRST	ACTE.1			;REPORT THE FAILURE
> ;END FACT ACCOUNTING
> ;END TOPS10 ACCOUNTING

TOPS20<	MOVX	S1,.USENT		;WRITE AN ENTRY
	MOVEI	S2,ACTLST		;POINT TO THE LIST
	USAGE				;DO THE JSYS
	  ERJMP	ACTE.1			;ON AN ERROR,,TELL THE OPERATOR
>					;END OF TOPS-20 CONDITIONAL

	$RETT				;RETURN WHEN DONE

ACTE.1:	MOVE	S1,STREAM		;GET THIS STREAM NUMBER
	$WTO	(System Accounting Failure,<^R/.EQJBB(J)/>,@JOBOBA(S1))
	$RETT				;RETURN

ACTRNT:	SKIPN	ACTFLG			;Accounting turned on?
	$RETT				;No - return
	SETO	S1,			;-1 Means us
	MOVX	S2,JI.RTM		;Function code
	$CALL	I%JINF			;Get our runtime
	ADDM	S2,ACTRNN		;Store accumulated time
	MOVNS	S2			;Negate actual runtime
	EXCH	S2,ACTRNN		;INIT FOR NEXT PASS
	SKIPE	S1,ACTPAG		;GET LAST PROCESSES PAGE ADDRESS
	ADDM	S2,J$ARTM(S1)		;ACCUMULATE TOTAL
	$RETT				;RETURN
	SUBTTL	FORMS - Setup Forms for a job

FORMS:	GETLIM	S1,.EQLIM(J),FORM	;GET THE FORMS TYPE
	CAMN	S1,J$FORM(J)		;EXACTLY THE SAME?
	$RETT				;YES, JUST RETURN
	MOVE	S2,[POINT 7,J$XTBF(J)]	;GET POINTER TO WTOR BUFFER.
	MOVEM	S2,TEXTBP		;AND SAVE IT FOR DEPBP.
	MOVEI	S2,TXT$LN*5		;GET MAXIMUM BYTE COUNT
	MOVEM	S2,TEXTBC
	SKIPN	S2,J$FORM(J)		;GET FORMS TYPE
	MOVX	S2,FRMNOR		;USE NORMAL IF NULL
	XOR	S1,S2			;GET COMMON PART
	AND	S1,[EXP FRMSK1]		;AND IT WITH THE IMPORTANT PART
	GETLIM	S2,.EQLIM(J),FORM	;GET FORMS TYPE
	EXCH	S2,J$FORM(J)		;SAVE IT
	MOVEM	S2,J$FPFM(J)		;SAVE OLD ONES
	SKIPE	S1			;NO NEED TO CHANGE FORMS.
	$TEXT	(DEPBP,<Please load forms type '^W/J$FORM(J)/'>)

FORM.1:	HRLZI	S1,J$FCUR(J)		;GET START OF SWITCH STORAGE
	HRRI	S1,J$FCUR+1(J)		;MAKE BLT POINTER
	SETZM	J$FCUR(J)		;CLEAR THE FIRST WORD
	BLT	S1,J$FCUR+F$NSW-1(J)	;CLEAR THE BLOCK

FORM.2:	$CALL	FRMINI			;READ THE SPFORM.INI FILE.
	MOVE	S1,TEXTBP		;GET THE WTOR BYTE POINTER.
	CAMN	S1,[POINT 7,J$XTBF(J)]	;IS THERE A MESSAGE FOR THE OPERATOR?
	$RETT				;NO,,RETURN.

IFN CSM02$,< FORM.3:	>	;PUSHJ to here to wait for 'PROCEED' in OPRTXT

	$TEXT	(DEPBP,<Type 'RESPOND ^7/[.CHLAB]/number^7/[.CHRAB]/ PROCEED' when ready^0>)
	HRRZ	S1,STREAM		;GET STREAM NUMBER
	$WTOR  (,<^T/J$XTBF(J)/>,@JOBOBA(S1),JOBWAC(S1)) ;SEND THE WTOR.
	$DSCHD	(PSF%OR)		;WAIT FOR OPERATOR RESPONSE.
	$RETT				;RETURN...
SUBTTL	Plotter only switches

S$SPS:	SKIPN	J$FPLT(J)		;IS DEVICE A PLOTTER?
	$RETF				;NO
	PUSHJ	P,FH$DEC		;GET STEPS PER SECOND
	MOVEM	T1,J$FSPS(J)		;STORE IT
	$RETT				;RETURN

S$SPU:	SKIPN	J$FPLT(J)		;IS DEVICE A PLOTTER?
	$RETF				;NO -- ERROR RETURN
	$CALL	FH$DEC			;GET STEPS PER UNIT
	MOVEM	T1,J$FSPU(J)		;AND SAVE IT
	$RETT

S$MINI:	SKIPN	J$FPLT(J)		;IS DEVICE A PLOTTER?
	$RETF				;NO -- INVALID SWITCH
	SETZM	J$XORG(J)		;DEFAULT TO ZERO
	SETZM	J$YMIN(J)		;DITTO
	$CALL	FH$DEC			;GET DECIMAL INTEGER
	MOVEM	T1,J$XORG(J)		;STORE X MINIMUM
	CAIE	C,":"			;IS Y ARGUMENT SPECIFIED?
	$RETT				;NO -- RETURN
	$CALL	FH$DEC			;GET DECIMAL INTEGER
	MOVEM	T1,J$YMIN(J)		;STORE Y MINIMUM
	$RETT				;AND RETURN

S$MAXI:	SKIPN	J$FPLT(J)		;IS DEVICE A PLOTTER?
	$RETF				;NO -- INVALID SWITCH
	MOVX	T1,.INFIN		;GET A LARGE NUMBER
	MOVEM	T1,J$XMAX(J)		;DEFAULT
	MOVEM	T1,J$YMAX(J)		;DITTO
	$CALL	FH$DEC			;GET DECIMAL INTEGER
	SKIPE	T1		;[CSM]	;If not zero,
	MOVEM	T1,J$XMAX(J)		;STORE X MAXIMUM
	CAIE	C,":"			;IS Y ARGUMENT SPECIFIED?
	$RETT				;NO -- RETURN
	$CALL	FH$DEC			;GET DECIMAL INTEGER
	SKIPE	T1		;[CSM]	;If not zero,
	MOVEM	T1,J$YMAX(J)		;STORE Y MAXIMUM
	$RETT				;AND RETURN
;ROUTINE TO SEARCH FOR EOL IN SPFORM.INI

FH$EOL:	$CALL	FH$CHR			;GET A CHARACTER
	JUMPF	.RETF			;FAIL IF EOF
	CAIE	C,.CHLFD		;EOL?
	JRST	FH$EOL			;NO, LOOP
	$RETT				;YES, RETURN!


;ROUTINE TO PICK UP A DECIMAL NUMBER

FH$DEC:	SETZ	T1,			;PLACE TO ACCUMULATE RESULT
FH$DE1:	$CALL	FH$CHR			;GET A CHARACTER
	JUMPF	.RETF			;EOF, RETURN
	CAIL	C,"0"			;CHECK THE RANGE
	CAILE	C,"9"			;0-9
	  POPJ	P,			;RETURN
	IMULI	T1,^D10		;[CSM]	;Shift one decimal place
	ADDI	T1,-"0"(C)		;ADD IN A DIGIT
	JRST	FH$DE1			;AND LOOP AROUND
SUBTTL	OUTGET - OPEN the output device

;THIS ROUTINE OPENS THE SPECIFIED OUTPUT DEVICE, AND SETS UP A BUFFER RING

TOPS10 <
OUTGET:	HRRZ	S1,STREAM		;GET THE STREAM NUMBER
	MOVE	S1,JOBOBA(S1)		;GET OBJECT BLOCK ADDRESS
	MOVE	S1,OBJ.TY(S1)		;GET OBJECT TYPE
	SETZ	S2,			;AND CLEAR AN AC
	CAXN	S1,.OTPTP		;IS IT A PAPERTAPE PUNCH?
	MOVEI	S2,T$DISP		;YES!
	CAXN	S1,.OTCDP		;NO, HOW ABOUT A CARD PUNCH?
	MOVEI	S2,C$DISP		;WIN!
	CAXN	S1,.OTPLT		;TRY FOR A PLOTTER
	MOVEI	S2,P$DISP		;AND GET THE PLOTTER DISPATCH
	JUMPE	S2,OUTDDE		;DONT KNOW ABOUT IT
	MOVEM	S2,J$LSER(J)		;SAVE IT
	MOVEI	S1,J$LDEV(J)		;ADDRESS OF WHERE TO PUT DEVNAM
	HRLI	S1,(POINT 6,0)		;MAKE IT A BYTE POINTER
	MOVEM	S1,TEXTBP		;SAVE IT
	MOVEI	S1,6			;MAXIMUM CHARACTER COUNT
	MOVEM	S1,TEXTBC
	HRRZ	S1,STREAM		;GET THE STREAM NUMBER
	MOVE	S1,JOBOBA(S1)		;GET OBJECT BLOCK ADDRESS
	$TEXT(DEP6BP,<^W3/DNAME(S2)/^O2R0/OBJ.ND(S1)/^O1/OBJ.UN(S1)/^A>)
	MOVE	T1,J$LDEV(J)		;GET THE DEVICE NAME
	DEVNAM	T1,			;GET ITS PHYSICAL NAME
	  JRST	OUTDDE			;LOSE?
	MOVEM	T1,J$LDEV(J)		;AND SAVE IT
	MOVX	T1,.IOIMG+UU.PHS+UU.AIO	;IMAGE+PHONLY+NBIO

	CSMEDT	05,3	;TTY I/O and SLEEP, part 3 after DEVNAM in OUTGET
IFN CSM05$,<	;Check for devices connected to TTY lines
	HLRZ	T2,J$LDEV(J)		;Get first part of physical name
	CAIE	T2,'TTY'		;Is it a terminal?
	 JRST	CSM05Z			;No
	MOVE	S2,J$LSER(J)		;Get service routine
	MOVE	S1,DNAME(S2)		;Get 'PLT' or 'CDP'
	MOVEM	S1,J$TTY(J)		;Put in LH
	MOVE	T2,J$LDEV(J)		;Get device again
	IONDX.	T2,			;Get UDX
	  SETZB	T2,J$TTY(J)		;Should never happen
	HRRM	T2,J$TTY(J)		;Store TTY UDX in RH

CONT.	(OUTGET)		;FORCE NEW LISTING PAGE

;Disable free CRLFs every 80 characters and SET TTY NO GAG

	MOVX	T1,.TONFC+.TOSET	;Change setting to
	MOVEI	T3,1			; no free CRLFs
	MOVE	S1,[3,,T1]
	TRMOP.	S1,			;SET TTY NO CRLF
	  JFCL

;*BUG*;	MOVX	T1,.IOPIM+UU.PHS	;Packed image mode (no echo)
	MOVX	T1,.IOIMG+UU.PHS+IO.SUP	;Image mode, no echo
	HLRZ	S1,J$TTY(J)		;Get device type
	CAIN	S1,'PLT'		;Output to plotter?
	 MOVX	T1,.IOASC+UU.PHS+IO.SUP	;ASCII mode, no echo
CSM05Z:	>  ;End of IFN CSM05$

	MOVE	T2,J$LDEV(J)		;OUTPUT DEVICE NAME
	MOVSI	T3,J$LBRH(J)		;BUFFER HEADER
	MOVE	S1,STREAM		;GET OUR STREAM NUMBER
	MOVEM	S1,J$LJFN(J)		;SAVE AS THE STREAM NUMBER
	LSH	S1,^D23			;PUT IN THE RIGHT PLACE
	IOR	S1,[OPEN T1]		;MAKE IT AN INSTRUCTION
	XCT	S1			;AND EXECUTE IT
	   JRST	OUTDNA			;LOSE GIVE ERROR
	MOVE	S1,J$LSER(J)		;GET DEVICE DISPATCH ADDRESS
	MOVE	S1,DBYTE(S1)		;GET OUTPUT BYTE SIZE

IFN CSM05$,<	;Cannot use 6 bits to PTC-6
	HLRZ	S2,J$TTY(J)		;Nonzero if TTY as output device
	CAIN	S2,'PLT'		;Going to the plotter?
	 MOVEI	S1,7			;Yes, use normal ASCII mode

;SET TTY NO GAG after it has been inited

	MOVX	T1,.TOSND+.TOSET	;Change setting to
	HRRZ	T2,J$TTY(J)
	MOVEI	T3,0			; no SENDs allowed
	MOVE	S2,[3,,T1]
	SKIPE	T2			;Don't TRMOP. if not a TTY
	 TRMOP.	S2,			;SET TTY GAG
	  JFCL
>  ;End of IFN CSM05$

	STORE	S1,J$LBRH+1(J),BP.SIZ	;STORE IT
	MOVX	S1,PSF%OB!PSF%DO	;GET OUTPUT-BLOCKED AND DEVICE OFFLINE
	HRRZ	S2,STREAM		;AND STREAM NUMBER
	ANDCAM	S1,JOBSTW(S2)		;AND CLEAR THE CONDITIONS
	MOVE	T1,J$LJFN(J)		;LOAD CHANNEL NUMBER
	WHERE	T1,			;GET OUR STATION NUMBER
	  SETZ	T1,
	TLZ	T1,-1			;CLEAR STATION FLAGS
	CAME	T1,CNTSTA		;IS THIS CENTRAL STATION?
	SETOM	J$LREM(J)		;NO -- SET REMOTE
	MOVEI	S1,T1			;LOAD ADDRESS OF ARGBLOCK FOR DEVSIZ
	MOVX	T1,.IOIMG		;GET IMAGE MODE
	MOVE	T2,J$LJFN(J)		;GET THE CHANNEL
	DEVSIZ	S1,			;DO THE DEVSIZ
	  JRST	OUTDNA			;LOSE
	MOVEI	T1,PAGSIZ		;LOAD PAGE SIZE
	IDIVI	T1,(S1)			;GET NUMBER OF BUFFER TO CREATE
	MOVE	S1,J$LBUF(J)		;GET ADDRESS OF BUFFER PAGE
	EXCH	S1,.JBFF		;SWAP WITH JOBFF
	MOVE	S2,J$LJFN(J)		;GET CHANEL NUMBER
	LSH	S2,^D23			;POSITION IT
	IOR	S2,[OUTBUF 0(T1)]	;BUILD THE OUTBUF
	XCT	S2			;AND DO IT
	MOVEM	S1,.JBFF		;RESTORE JOBFF
	$CALL	INTCNL			;CONNECT TO INTERRUPTS
	MOVX	S1,%RSUOK		;LOAD OK CODE
	$RETT				;AND RETURN
>  ;END TOPS10 CONDITIONAL
SUBTTL	OUTOUT - Routine to output a buffer


TOPS10 <
OUTOUT:	$SAVE	<S1,S2>			;SAVE SOME ACS

	CSMEDT	01,2	;3-Pen plotter, part 2 at OUTOUT:+1 <TOPS10>
IFN CSM01$,<	;The plotter does not interrupt for off-line or on-line
	SKIPE	J$FPLT(J)		;Is this going to the plotter?
	 PUSHJ	P,PLTCHK		;Yes, check if it is on-line
>  ;End of CSM01$

OUTO.1:	MOVE	S1,STREAM		;Get our stream number
	MOVX	S2,PSF%OB		;Assume we are blocked
	IORM	S2,JOBSTW(S1)		; waiting for output done
	MOVE	S1,J$LJFN(J)		;GET THE CHANNEL NUMBER
	LSH	S1,^D23			;POSITION IT
	TLO	S1,(OUT 0,0)		;MAKE IT AN OUTPUT UUO
	XCT	S1			;AND DO IT
	 JRST	[MOVE	S1,STREAM	;We won!  Clear blocked bit
		 ANDCAM	S2,JOBSTW(S1)	; so we are runnable
		 $RETT]
OUTERR:	PUSHJ 	P,OUTSTS		;READ DEVICE STATUS
	JUMPT	[$DSCHD (0)		;ASSUME OUTPUT BLOCKED
		 JRST OUTO.1]		;RETRY OUTPUT
	$CALL	DEVERR			;PROCESS DEVICE ERROR
	JUMPT	OUTO.1			;RETRY OUTPUT IF CORRECTED
	JRST	MAIN			;STREAM IS SHUTDOWN


OUTWAT:	$CALL	OUTOUT			;OUTPUT THE BUFFER
OUTW.1:	$CALL	OUTSTS			;GET THE STATUS
	TXNN	S1,IO.ACT		;DONE?
	$RETT				;YES, RETURN
	$DSCHD	(0)			;FORCE A SCHEDULING RUN
	JRST	OUTW.1			;TRY AGAIN

CONT. (OUTOUT)

IFN CSM01$,<	;After OUTWAT: inside TOPS10<>
;Ask the monitor to do a CONI to check if PLT is on-line

	OPDEF	STSPL.	[CALLI	-4]	;CSM UUO to do <CONI PLT,T1>
	PLT.ON==1B30			;The plotter power is on

PLTCHK:	CSMEDT	08,1	;PTC-6 Plotter Controller, part 1 inside CSM01$
IFN CSM08$,<
	SKIPE	J$TTY(J)		;Output going to a TTY?
	 POPJ	P,			;Yes, cannot determine on-line status
>  ;End of IFN CSM08$
	STSPL.	S1,			;Get current status of plotter
	TXNE	S1,PLT.ON		;Is the POWER-ON bit set?
	 JRST	PLTONL			;Yes, plotter is on-line now
	AOS	S1,J$NACK(J)		;Increment NACK count
	IDIVI	S1,^D30			;Set S2 modulo 30
	JUMPN	S2,PLTCH1		;Complain every 30 seconds
	HRRZ	S1,STREAM		;Get stream number
	SETOM	JOBCHK(S1)		;Request checkpoint
	$WTO	(Off-line,,@JOBOBA(S1))
PLTCH1:	CSMEDT	05,4	;TTY I/O and SLEEP, part 4 after PLTCHK:
IFN CSM05$,< $DSCHD  (1) >		;De-schedule for 1 second
IFE CSM05$,< MOVEI   S1,1		;Wait 1 second
	     SLEEP   S1, >		; before continuing
	JRST	PLTCHK			;Check if it is on-line now

PLTONL:	SETOM	J$NACK(J)		;Plotter is on-line now
	$RETT				;OK to do the OUT UUO
>  ;End of IFN CSM01$
>  ;END TOPS10 CONDITIONAL

	CONT.	(OUTOUT)
TOPS20 <
OUTOUT:	$SAVE	<T1,T2,T3,T4>		;PRESERVE TEMPORARIES
	MOVE	S1,J$LJFN(J)		;GET DEV JFN
	MOVE	S2,J$LIBP(J)		;GET POINTER TO BUFFER
	SKIPGE	T1,J$LBCT(J)		;GET REMAINING BYTE COUNT
	SETZ	T1,			;MUST BE .GE. 0
	SUB	T1,J$LIBC(J)		;GET NEG. BYTE COUNT
	JUMPE	T1,OUTO.2		;DONE -- RESET BUFFER HEADER
OUTO.1:	HRRZ	T2,STREAM		;GET STREAM
	SETOM	J$LIOA(J)		;SET I/O ACT
	SKIPE	JOBSTW(T2)		;BLOCKED?
	 JRST	OUTINT			;YES -- POSTPONE SOUT
	SOUTR				;DUMP THE BUFFER
	  ERJMP	OUTERR			;PROCESS ERROR
OUTO.2:	SETZM	J$LIOA(J)		;CLEAR I/O ACT
	MOVE	S1,J$LIBC(J)		;GET INITIAL BYTE COUNT
	MOVEM	S1,J$LBCT(J)		;RESET BUFFER COUNT
	MOVE	S1,J$LIBP(J)		;GET INITIAL BYTE POINTER
	MOVEM	S1,J$LBPT(J)		;RESET BUFFER POINTER
	HRRZ	T1,J$LIBP(J)		;GET START ADDRESS OF BUFFER
	HRLZ	T2,T1			;COPY IT
	HRRI	T2,1(T1)		;MAKE A BLT POINTER
	SETZM	(T1)			;CLEAR THE FIRST WORD
	BLT	T2,PAGSIZ-1(T1)		;CLEAR THE BUFFER
	$DSCHD	(PSF%NP)		;PICK UP AGAIN AFTER SCHEDULE
	$RETT				;AND FINALLY RETURN

OUTERR:	SETOM	J$LIOE(J)		;SET ERROR FLAG
OUTINT:	SETZM	J$LIOA(J)		;CLEAR IO ACTIVE
	MOVEM	S2,J$LBPT(J)		;SAVE THE CURRENT POINTER
	MOVEM	T1,J$LBCT(J)		;SAVE NUMBER OF CHARACTERS LEFT
	SKIPE	JOBSTW(J)		;DEVICE OFF-LINE?
	$CALL	OUTWON			;POSSIBLY.  GO CHECK
	SKIPE	J$LIOE(J)		;ERROR?
	$CALL	OUTSTS			;READ DEVICE STATUS
	SKIPT				;ERROR?
	$CALL	DEVERR			;YES -- PROCESS IT
	JUMPF	MAIN			;STREAM HAS BEEN SHUTDOWN
	MOVE	S1,J$LJFN(J)		;RESTORE DEVICE JFN
	MOVE	S2,J$LBPT(J)		;RESTORE POINTER
	MOVE	T1,J$LBCT(J)		;RESTORE COUNT
	JRST	OUTO.1			;RESTART SOUT

>  ;END TOPS20 CONDITIONAL
SUBTTL	TTY I/O -- Input character from TTY, no wait

	CSMEDT	05,5	;TTY I/O and SLEEP, part 5 between OUTFLS and C$DISP
IFN CSM05$,<	INTERN	TIWAIT,TTYIN,TRMERR	;Entry points for TABCDP.MAC

;Routine to input a single character from terminal into S1.
;Uses T1 and T2.

TTYIN::	MOVX	T1,.TOSIP		;Skip if input in progress
	HRRZ	T2,J$TTY(J)		;Get UDX
	MOVE	S1,[2,,T1]		;Point to args
	TRMOP.	S1,			;Check if input
	  JRST	TTYIN1			;Nothing there
	MOVX	T1,.TOISC		;Input single character
	MOVE	S1,[2,,T1]		;Point to args
	TRMOP.	S1,			;Get the char
	  PUSHJ	P,TRMERR		;Should never happen
	$RETT				;Got char in S1

TTYIN1:	MOVEI	S1,0			;Signify failure
	$RETF

TRMERR::$STOP	(TUF,TRMOP. UUO Failure)
SUBTTL	TTY I/O -- Input character, wait up to 30 seconds

;Routine to wait up to 30 seconds for a character to come in.
;Returns TRUE if char in S1, FALSE and zero in S1 if timed out

TIWAIT::PUSHJ	P,TTYIN			;Check for input
	JUMPT	TIWAI2			;Clear NACK counter if got input

;There is a good possibility that the response will come in within 1 second

	MOVX	S1,HB.RTC+^D1000	;Wait 1 second, wake on char ready
	HIBER	S1,
	  JFCL
	PUSHJ	P,TTYIN			;Anything now?
	JUMPT	TIWAI2			;Return if so
	AOS	J$NACK(J)		;No, waited 1 second already

TIWAT1:	$DSCHD	(1)			;De-schedule this stream for 1 second

	PUSHJ	P,TTYIN			;Input now?
	JUMPT	TIWAI2			;Yes, continue
	AOSG	S1,J$NACK(J)		;No, count failure
	 JRST	TIWAT1			;Keep waiting if negative or zero
	IDIVI	S1,^D30			;Set S2 modulo 30
	JUMPN	S2,TIWAT1		;If less than 30 seconds, wait again
	HRRZ	S1,STREAM		;Get stream number
	$WTO	(<No response from ^W/J$LDEV(J)/ after ^D/J$NACK(J)/ seconds>,,@JOBOBA(S1))
	MOVEI	S1,0			;Signify no response
	$RETF

TIWAI2:	SETZM	J$NACK(J)		;Terminal is responding
	POPJ	P,			;TF has been set to TRUE already

>  ;End of IFN CSM05$
SUBTTL	Card punch service -- Dispatch table


C$DISP:	JRST	C$HEAD			;(0) FILE HEADER
	JRST	C$EOF			;(1) FILE TRAILER
	SIXBIT	/CDP/			;(2) GENERIC DEVICE NAME
	EXP	^D12			;(3) OUTPUT BYTE SIZE
	JRST	C$PROC			;(4) PROCESS A FILE
	JRST	C$BANN			;(5) JOB BANNER
	JRST	C$TRAI			;(6) JOB TRAILER
	JRST	C$LETR			;(7) LETTER DEVICE
	JRST	.RETF			;(10) ERROR PROCESSOR

	CSMEDT	04,2	;CSM accounting, part 2 at C$DISP:+11
IFE CSM04$,< JRST  .RETT >		;(11) ACCOUNTING
IFN CSM04$,< JRST  CSMACT >		;(11) Accounting

	JRST	C$CHKP			;(12) CHECKPOINT TEXT GENERATION

IFN CSM04$,<
CSMACT:	MOVE	S1,J$APRT(J)		;Get cards punched or feet punched
	MOVEM	S1,J$ADRD(J)		;Save instead of disk reads
	$RETT
>  ;End of IFN CSM04$
SUBTTL	Card punch service -- File processing


C$PROC:	LOAD	S1,.FPINF(E),FP.FPF	;GET PAPER FORMAT
	CAILE	S1,CDROUL		;WITHIN RANGE?
	JRST	BADMOD			;NO, LOSE
	JUMPN	S1,@C$ROUT-1(S1)	;YES, DISPATCH IF NON-ZERO

	CSMEDT	07,1	;QUEUE defaults, part 1 at C$PROC:+4
IFE CSM07$,<
	MOVEI	S1,C$MTAB		;GET ADDRESS OF MODE TABLE
	MOVEI	S2,C$ROUT		;GET ADDRESS OF ROUTINE TABLE
	PJRST	DSPMOD			;AND DISPATCH BASED ON MODE
>  ;End of CSM07$
IFN CSM07$,<JRST CDASC>			;Default to ASCII mode

;TABLE OF processing ROUTINES
C$ROUT:	EXP	CDASC			;ASCII
	EXP	CD026			;026
	EXP	CDBIN			;CHECKSUMMED BINARY
	EXP	CDASC			;ASCII
	EXP	CDIMA			;IMAGE AND IMAGE BINARY

	CDROUL==.-C$ROUT		;LENGTH OF ROUTINE TABLE

;MODE TABLE
C$MTAB:	BYTE (3) 1,1,0,0,0,0,0,0,5,0,0,5,3,0,3,3
SUBTTL	Card punch service -- File headers


C$HEAD:	SKIPN	J$FHEA(J)		;HEADER ALLOWED?
	$RETT				;NO -- RETURN

	CSMEDT	07,2	;QUEUE defaults, part 2 at C$HEAD:+2
IFE CSM07$,<	;Ignore QUEUE's default of /NOHEADER, always punch it
	LOAD	S1,.FPINF(E),FP.NFH	;GET NO FILE HEADER BIT
	JUMPN	S1,.RETT		;RETURN IF NOT WANTED
>  ;End of IFN CSM07$

	MOVEI	C,4001			;SPECIAL MASK FOR FILE CARDS
	MOVEM	C,J$CMSK(J)		;SAVE FOR C$LETR
	MOVE	S1,J$DFDA(J)		;POINT TO FD
	SKIPN	S2,J$DSPN(J)		;SPOOL NAME?

TOPS10<	MOVE	S2,.FDNAM(S1) >		;NO -- USE FILE NAME

TOPS20<
	MOVX	S1,GJ%SHT!GJ%OFG	;PARSE ONLY, SHORT JFN
	MOVE	S2,J$DFDA(J)		;GET FD ADDRESS
	HRROI	S2,.FDSTG(S2)		;POINT TO START OF FILESPEC
	GTJFN				;GET A JFN
	  ERJMP	.POPJ			;ASSUME A SPOOLED FILE
	MOVE	S2,[POINT 7,FILNAM]	;POINT TO FILENAME STORAGE
	EXCH	S1,S2			;S1:= POINTER, S2:= JFN
	MOVE	T1,[FILNAM,,FILNAM+1]	;SET UP BLT
	SETZM	FILNAM			;CLEAR THE FIRST WORD
	BLT	FILNAM+7		;CLEAR THE ENTIRE BLOCK
	MOVX	T1,1B8			;WANT FILENAME ONLY
	JFNS				;GET IT
	HRROI	S1,FILNAM		;POINT TO THE FILENAME
	$CALL	S%SIXB			;CONVERT TO SIXBIT
>

	MOVEI	S1,[ITEXT<^W6/S2/>]	;POINT TO NAME
	PJRST	C$WORD			;PUNCH CARD AND RETURN
SUBTTL	Card punch service -- File trailers


C$EOF:	MOVEI	S1,^D80			;PUNCH EOF CARD
	MOVEI	C,7417			;TOP FOUR AND BOTTOM FOUR ROWS
	PUSHJ	P,CDPREP		;PUNCH EOF CARDS
;[CSM]	PJRST	OUTOUT			;FORCE OUTPUT
	PJRST	OUTCD1		;[CSM]	;FORCE OUTPUT
SUBTTL	Card punch service -- Banners


C$BANN:	CSMEDT	06,1	;TTY CDP, part 1 at C$BANN:
IFN CSM06$,<	;Set terminal to PUNCH+PRINT mode if /FORMS:NORMAL
	MOVEI	S1,J$FORM(J)		;Get forms name
	CAMN	S1,['NORMAL']		;Normal forms?
	 MOVEI	S1,0			;Yes, turn on print mode
	SKIPE	S2,J$TTY(J)		;Punch really a terminal?
	 PUSHJ	P,TABINI##		;Yes, set it up
>  ;End of IFN CSM06$

	SKIPN	J$FBAN(J)		;BANNER cards wanted?
	$RETT				;RETURN IF ZERO
	MOVEI	C,4003			;MASK FOR JOB CARDS
	MOVEM	C,J$CMSK(J)		;SAVE FOR C$LETR

	CSMEDT	07,3	;QUEUE defaults, part 3 at C$BANN:+4
IFE CSM07$,<	;"BEGIN: JOB jobnam USER:" wastes 4 cards.
	MOVEI	S1,[ITEXT<BEGIN:>]
	PJRST	CTRA.1			;FALL INTO COMMON CODE
>  ;End of IFE CSM07$
IFN CSM07$,<	;Punch just NAME, PPN, and NOTE (if any)
	PJRST	CTRA.2			;Punch user name
>  ;End of IFN CSM07$

IFE CSM06$,<
C$TRAI:	SKIPN	J$FTRA(J)		;Check TRAILER wanted flag
	$RETT				;RETURN IF ZERO
>  ;End of IFE CSM06$
IFN CSM06$,<	;Call TABFIN after all is done
C$TRAI:	SKIPE	J$FTRA(J)		;Trailer cards wanted?
	 $CALL	CTRA.0			;Yes
	SKIPE	J$TTY(J)		;Output to a TTY?
	 PUSHJ	P,TABFIN##		;Yes, finish up
	$RETT
CTRA.0:	>  ;End of IFN CSM06$

	MOVEI	C,4003			;MASK FOR JOB CARDS
	MOVEM	C,J$CMSK(J)		;SAVE FOR C$LETR
	MOVEI	S1,[ITEXT<END:  >]
CTRA.1:	$CALL	C$WORD
	MOVEI	S1,[ITEXT<^W6/.EQJOB(J)/>]
	$CALL	C$WORD
	MOVEI	S1,[ITEXT <REQ-ID >]
	PUSHJ	P,C$WORD
	MOVEI	S1,[ITEXT<#^D5R0/.EQJBB+JIB.ID(J)/>] ;REQUEST ID
	$CALL	C$WORD
	MOVEI	S1,[ITEXT<USER: >]
	$CALL	C$WORD
	$CALL	SETTBF			;POINT TO TEXT BUFFER

	CONT.	(C$BANN)
IFN CSM07$,< CTRA.2: >			;Here to skip over garbage
TOPS10	<				;TOPS-10 ONLY
	MOVEI	S1,[ITEXT <^W6/.EQJBB+JIB.NM(J)/>] ;USER NAME (WORD 1)
	PUSHJ	P,C$WORD		;PUNCH IT
	MOVEI	S1,[ITEXT <^W6/.EQJBB+JIB.NM+1(J)/>] ;USER NAME (WORD 2)
	PUSHJ	P,C$WORD		;PUNCH IT
	MOVEI	S1,[ITEXT <^O6R /.EQOID(J),LHMASK/>] ;PROJECT NUMBER
	PUSHJ	P,C$WORD		;PUNCH IT
	MOVEI	S1,[ITEXT <^O6L /.EQOID(J),RHMASK/>] ;PROGRAMMER NUMBER
	PUSHJ	P,C$WORD		;PUNCH IT
>					;END TOPS-10 CONDITIONAL

TOPS20	<
	MOVE	TF,[POINT 6,FILNAM]	;GET BYTE POINTER
	MOVEM	TF,TEXTBP		;STORE THE BYTE POINTER
	MOVEI	TF,TXT$LN*^D12		;GET BYTE COUNT
	MOVEM	TF,TEXTBC		;AND SAVE IT
	SETZM	FILNAM+0		;CLEAR A WORD
	SETZM	FILNAM+1		;CLEAR ANOTHER WORD
	$TEXT	(DEP6BP,<^T/.EQOWN(J)/^A>) ;ALLOW UP TO 12 CHARACTER NAMES
	MOVEI	S1,[ITEXT <^W6/FILNAM+0/>] ;WORD 1
	PUSHJ	P,C$WORD		;OUTPUT IT
	MOVEI	S1,[ITEXT <^W6/FILNAM+1/>] ;WORD 2
	SKIPE	FILNAM+1		;IS THERE A SECOND WORD?
	PUSHJ	P,C$WORD		;OUTPUT IT
	PUSHJ	P,SETTBF		;RESET BYTE POINTER AND COUNT
>

	GETLIM	T1,.EQLIM(J),NOT1	;GET /NOTE VALUE (WORD 1)
	GETLIM	T2,.EQLIM(J),NOT2	;GET /NOTE VALUE (WORD 2)
	SKIPN	T1			;RETURN IF BOTH
	JUMPE	T2,.RETT		; WORDS ARE ZERO
	MOVEI	S1,[ITEXT<NOTE: >]
	PUSHJ	P,C$WORD		;PUNCH IT
	GETLIM	T1,.EQLIM(J),NOT1	;GET /NOTE VALUE (WORD 1)
	MOVEI	S1,[ITEXT<^W6/T1/>]
	PUSHJ	P,C$WORD		;PUNCH IT
	GETLIM	T1,.EQLIM(J),NOT2	;GET /NOTE VALUE (WORD 2)
	JUMPE	T1,.RETT		;RETURN IF NO SECOND WORD
	MOVEI	S1,[ITEXT<^W6/T1/>]
	PJRST	C$WORD			;PUNCH LAST CARD AND RETURN
SUBTTL	Card punch service -- Word punching


;C$WORD
;Call	S1/ Address of Itext to punch as 6 Character word on card
;  Also J$CMSK Specifies Extra Rows to punch with Characters


C$WORD:	$CALL	SETTBF			;SET POINTERS TO TEXT BUFFER
	$TEXT(DEPBP,<^I/(S1)/^0>)	;STORE STRING IN BUFFER
	MOVEI	S1,0			;GET A NULL
	DPB	S1,[POINT 7,J$XTBF+1(J),13] ;TRUNCATE TO SIX CHARACTERS
	MOVEI	C,3776			;FIRST COLUMN WITH ROUNDED CORNERS
	PUSHJ	P,CDPBYT
	MOVEI	C,7777			;SECOND COLUMN FULLY LACED
	PUSHJ	P,CDPBYT
	MOVEI	S1,3			;NEXT 3 COLUMNS WITH SPECIAL MASK
	MOVE	C,J$CMSK(J)
	PUSHJ	P,CDPREP
	$CALL	STRING			;COLUMNS 6-77 FOR CHARACTERS
	MOVE	C,J$CMSK(J)		;COLUMN 78 SPECIAL MASK
	PUSHJ	P,CDPBYT
	MOVEI	C,7777			;COLUMN 79 FULLY LACED
	PUSHJ	P,CDPBYT
	MOVEI	C,3776			;COLUMN 80 ROUNDED CORNERS
	PUSHJ	P,CDPBYT
;[CSM]	PJRST	OUTOUT			;PUNCH CARD AND RETURN
	PJRST	OUTCD1		;[CSM]	;PUNCH CARD AND RETURN
SUBTTL	Card punch service -- Byte output


; AC 'C' contains the byte to output
;
CDPBYT:	CSMEDT	06,2	;TTY CDP, part 2 at CDPBYT
IFE CSM06$,< PJRST  OUTBYT >
IFN CSM06$,<	;Special output for TAB Products Cardpunch Terminal
	SKIPN	J$TTY(J)		;Output to a TTY?
	 PJRST	OUTBYT			;No
	$SAVE	<S1,S2>			;Yes, preserve ACs used
	MOVE	S1,C			;Copy to expected AC
	PJRST	TABBYT##		;Store byte in other buffer
>  ;End of IFN CSM06$


; Force card out
;
OUTCDP:	AOS	S1,J$APRT(J)		;COUNT ANOTHER ONE
	CAMLE	S1,J$RLIM(J)		;OVER LIMIT?
	PUSHJ	P,FRMLEX		;HANDLE LIMIT EXCEEDED

OUTCD1:					;Output without counting
IFN CSM06$,<	;Special output for TAB Products Cardpunch Terminal
	SKIPE	J$TTY(J)		;Output to a TTY?
	 PJRST	TABPUN##		;Yes, output the card
>  ;End of IFN CSM06$
	PJRST	OUTOUT			;FORCE CARD OUT


; Repeat the byte in AC 'C'
; Call:	MOVE	S1,repeat count
;	MOVE	C,byte to output
;	PUSHJ	P,CDPREP
;
CDPREP:	PUSH	P,P1			;SAVE P1
	MOVE	P1,S1			;GET COUNT
;[CSM]	PUSHJ	P,PTPBYT		;OUTPUT A BYTE
	PUSHJ	P,CDPBYT	;[CSM]	;Use the right output routine
	SOJG	P1,.-1			;AND LOOP
	POP	P,P1			;RESTORE P1
	POPJ	P,			;RETURN
SUBTTL	Plotter service -- Dispatch table

P$DISP:	JRST	P$HEAD			;(0) FILE HEADER
	JRST	P$EOF			;(1) FILE TRAILER
	SIXBIT	/PLT/			;(2) GENERIC DEVICE NAME
	EXP	^D6			;(3) OUTPUT BYTE SIZE
	JRST	P$PROC			;(4) PROCESS A FILE
	JRST	P$BANN			;(5) JOB BANNER
	JRST	P$TRAI			;(6) JOB TRAILER
	JRST	P$LETR			;(7) LETTER PROCESSER
	JRST	P$DERR			;(10) DEVICE ERROR PROCESSOR

	CSMEDT	04,3	;CSM accounting, part 3 at P$DISP:+11
IFE CSM04$,<JRST .RETT>			;(11) ACCOUNTING
IFN CSM04$,<JRST PLTACT>		;(11) Plotter accounting

	JRST	P$CHKP			;(12) CHECKPOINT TEXT GENERATION


IFN CSM04$,<	;Account for both elapsed time and paper used
PLTACT:	MOVE	S1,J$XLIM(J)		;Get total X increments
	ADDI	S1,INCS/2		;Round up
	IDIVI	S1,INCS			;Convert to inches
	EXCH	S1,J$APRT(J)		;Store amount of paper used
	MOVEM	S1,J$ADRD(J)		;Store minutes in place of disk reads
	$RETT
>  ;End of IFN CSM04$
SUBTTL	Plotter service -- Checkpoint text generation


P$CHKP:	$SAVE	<P1,P2,P3>		;SAVE SOME ACS
	MOVE	P1,J$PTIC(J)		;GET # TICS FOR JOB
	IDIV	P1,J$PTPM(J)		;P1:= MINUTES, P2:= FRACTION
	IMULI	P2,^D10			;[CSM] One decimal place
	IDIV	P2,J$PTPM(J)		;P2:= DECIMAL FRACTION OF A MINUTE
	MOVE	P3,J$RLIM(J)		;GET LIMIT
	CAMN	P3,[.INFIN]		;+INFINITY?
	JRST	P$CHK1			;YES
	CAMG	P1,J$RLIM(J)		;OPERATOR ALLOW LIMIT TO EXCEED?
	$TEXT	(DEPBP,<plotted ^D/P1/.^D/P2/ of ^D/J$RLIM(J)/ minutes^0>)
	CAMLE	P1,J$RLIM(J)		;OPERATOR ALLOW LIMIT TO EXCEED?
P$CHK1:	$TEXT	(DEPBP,<plotted ^D/P1/.^D/P2/ minutes (limit exceeded)^0>)
	POPJ	P,			;RETURN
SUBTTL	Plotter service -- File processing


P$PROC:	LOAD	S1,.FPINF(E),FP.FPF	;GET PAPER FORMAT
	CAILE	S1,PLROUL		;WITHIN RANGE?
	JRST	BADMOD			;NO, LOSE
	JUMPN	S1,@P$ROUT-1(S1)	;YES, DISPATCH IF NON-ZERO

	CSMEDT	07,4	;QUEUE defaults, part 4 at P$PROC:+4
IFE CSM07$,<	;This code removed because all plots must be BINARY halfwords
	MOVEI	S1,P$MTAB		;GET ADDRESS OF MODE TABLE
	MOVEI	S2,P$ROUT		;GET ADDRESS OF ROUTINE TABLE
	PJRST	DSPMOD			;AND DISPATCH BASED ON MODE
>  ;End of IFE CSM07$
IFN CSM07$,< JRST  PLTHLF >		;Default always to halfword format


P$ROUT:	EXP	PLTSIX			;/PLOT:IMAGE	(6 BIT)
	EXP	PLTSVN			;/PLOT:ASCII	(7 BIT)

	CSMEDT	02,1	;Halfword format, part 1 at P$ROUT:+3
IFE CSM02$,<EXP	PLTSIX>			;/PLOT:BINARY	(6 BIT)
IFN CSM02$,<EXP	PLTHLF>			;/PLOT:BINARY	(18 bit)
	PLROUL==.-P$ROUT		;LENGTH OF ROUTINE TABLE


;MODE TABLE
P$MTAB:	BYTE (3) 2,2,0,0,0,0,0,0,1,0,0,1,1,1,1,1
SUBTTL	Plotter service -- Expand CSM's compressed plot format

	CSMEDT	02,2	;Halfword format, part 2 after PLTLP0:
IFN CSM02$,<				;Read halfwords from disk
COMMENT ~ Do not use many semicolons, it confuses FILCOM's /C switch

	!=======================================================!
	!                                                       !
	!                PLOTTER MODE  --  18 BIT               !
	!                                                       !
	! In 18 bit mode, each word read from disk is divided   !
	! into halfwords, which are interpreted by subroutine   !
	! TOLP.  Most halfwords have 9 bits of delta-X and      !
	! 9 bits of delta-Y, special opcodes raise and lower    !
	! the pen.  See TOLP.MAC for a full description.        !
	!                                                       !
	!=======================================================!
	!   Delta Y   !   Delta X   !   Delta Y   !   Delta X   !
	!=======================================================!

Call TOLP. with
 S1/ Addr of input routine, which returns data in S1, -1 on EOF
 S2/ 0 to suppress header/trailer, 1 for header, 2 for trailer, 3 for both
 T1/ Current X position (should be same as J$XMIN)
 T2/ Current Y position (should be same as J$YMIN)

On return, ACs 7-16 have been preserved
 TF/ Garbage
 S1/ Garbage
 S2/ Addr of error message, or 0 if no error
 T1-T4/ Garbage

~ ;End of COMMENT

	EXTERN	TOLP.			;Routine to reverse PLOT
	INTERN	PLOT			;Routine to move the pen
	INTERN	NEWPEN,OPRTXT,PAUSEP,TITLE ;Other routines called by TOLP

	ND	INCS,^D400		;Steps per inch (620 octal)
SUBTTL	Plotter service -- READ36, OPRTXT, PAUSEP, TITLE for TOLP

;Routine to read a word from the input file, returns -1 for EOF, -2 if ABORT

READ36:	MOVE	S1,J$PTIC(J)		;Get tics plotted
	IDIV	S1,J$PTPM(J)		;Convert to minutes
	CAMLE	S1,J$RLIM(J)		;Still in range?
	 PUSHJ	P,FRMLEX		;No, complain
	PUSHJ	P,INPBYT		;Get a word
	MOVE	T1,C			;Copy to expected AC
	JUMPT	.POPJ			;Use it if OK
	MOVNI	T1,1			;-1 for EOF
	TXNE	S,RQB+ABORT		;Unless OPR caused EOF
	 MOVNI	T1,2			;-2 for ABORT
	POPJ	P,			;Continue back in TOLP


;Routine to send a message to the OPR.
;Called with byte count in S1, addr of ASCIZ message in S2.

OPRTXT:	PUSHJ	P,PLTOUT		;Dump buffers
	HRRZ	S1,STREAM		;Get the stream number
	$WTO	(OPRTXT message,<^T/0(S2)/>,@JOBOBA(S1)) ;Tell OPR
	POPJ	P,


;Routine to pause the plotter.
;Zero in S1 means to wait for human intervention, nonzero causes graphic
;terminals to pause that many seconds before automatically resuming.

PAUSEP:	PUSHJ	P,PLTOUT		;Dump the buffers
	JUMPN	S1,.POPJ		;Nonzero valid for graphics terminals
	PUSHJ	P,SETTBF		;Set up WTO buffer
	PJRST	FORM.3			;Wait for a "PROCEED" response


;Routine to plot text.
;  T1/ Height in increments
;  T2/ Addr of text
;  T3/ Angle in degrees, 0 to 359
;  T4/ Byte count for text

TITLE:	POPJ	P,			;Not implemented

PLTOUT:
IFE CSM08$,< PJRST  OUTOUT >
IFN CSM08$,<
	SKIPE	J$TTY(J)		;Output to a TTY?
	 PJRST	OUTOUT			;No
	PUSHJ	P,PTCOUT##		;Yes, get ready to output last buffer
	SETZM	J$PPOS(J)		;PTCOUT always raises the pen
	PJRST	OUTRSP			;Output string and wait for response
>  ;End of IFN CSM08$
>  ;End of IFN CSM02$
SUBTTL	Plotter service -- NEWPEN for 3-pen plotter

	CSMEDT	01,3	;3-Pen plotter, part 3 before P$DERR
IFN CSM01$,<
PEN.1:	MOVEI	S1,1			;Set to blue pen
	JRST	NEWPEN

PEN.2:	MOVEI	S1,2			;Set to black pen
	JRST	NEWPEN

PEN.3:	MOVEI	S1,3			;Set to red pen and fall into NEWPEN
	JRST	NEWPEN

	ND PENSEP,INCS*4/4		;Pen separation is 1 inch or 3/4 inch

CHGPEN:	BYTE (6) CNGP,PNDN,0		;Codes to change to pen #1
	BYTE (6) CNGP,PEN2,PNDN,0	;			#2
	BYTE (6) CNGP,PEN3,PNDN,0	;			#3


;Routine to change pens.  Called with pen number in S1, trashes it and S2.

NEWPEN:	$SAVE	<P1,P2>			;Save preserved ACs
;Make sure pen number in S1 is between 1 and 3 inclusive
	SUBI	S1,1			;Change to number from 0 to 2
	IDIVI	S1,3			;Set S2 modulo 3
	AOS	P2,S2			;Copy new pen number (from 1 to 3)

	CSMEDT	08,2	;PTC-6 Plotter Controller, part 2 in NEWPEN
IFN CSM08$,<	;Special codes for PTC-6
	SKIPE	J$TTY(J)		;Using a terminal line?
	 JRST	[PUSHJ	P,PTCPEN##	  ;Yes, tell it (pen number in S2)
		 JRST	NEWPN2	]	  ;Then move the pen holder
>  ;End of IFN CSM08$
	MOVEI	P1,CHGPEN-1(S2)		;Get addr of data
	HRLI	P1,(POINT 6,)		;Make into byte pointer
	PUSHJ	P,PENUP			;Raise any and all pens

;Output the codes to select new pen (even if it was previously selected)

NEWPN1:	ILDB	C,P1			;Get a byte
	PUSHJ	P,PLTBTX		;Send to plotter (even if no-op)
	JUMPN	C,NEWPN1		;Loop till no-op is sent


;When pen #1 is positioned at Y=5.0, then pen #2 is at Y=4.0 and pen #3
;is at Y=3.0.  Therefore, when changing from pen #1 to pen #2 (or 2 to 3),
;the pen holder must be moved 1.0 inches in the +Y direction, without
;affecting J$YPOS and in spite of J$YMAX and J$YMIN.

NEWPN2:	MOVE	P1,P2			;Copy new pen number
	SUB	P1,J$PENN(J)		;Find change (+1 if from pen 1 to pen 2)
	JUMPE	P1,.POPJ		;All done if same as previous pen
	EXCH	P2,J$PENN(J)		;Set new, get old
	JUMPE	P2,.POPJ		;All done if called from P$CPEN

	IMULI	P1,PENSEP		;Distance between pens
	SKIPL	P1			;If going plus,
	 ADDM	P1,J$YMAX(J)		; allow blue pen to move off the paper
	SKIPG	P1			;If going minus,
	 ADDM	P1,J$YMIN(J)		; allow red pen to move off the paper

	MOVE	T1,J$XPOS(J)		;No change in X
	MOVE	T2,P1			;Delta Y
	ADD	T2,J$YPOS(J)		;New Y position
	MOVEI	T3,PN.UP		;Raise the pen
	PUSHJ	P,PLOT			;Move the pen holder into position

	MOVNS	P1			;Cancel the offset
	SKIPG	P1			;If used to be positive,
	 ADDM	P1,J$YMAX(J)		; reset max limit
	SKIPL	P1			;If used to be negative,
	 ADDM	P1,J$YMIN(J)		; reset min limit
	ADDM	P1,J$YPOS(J)		;New pen is where previous one was
	POPJ	P,

;Routine to output bytes to plotter, passing nulls and CNGP codes correctly.
;Note: When changing pens, the first PNDN code does NOT lower the pen.

PLTBTX:	MOVEI	S1,PLTMOV		;Load # tics for movement
	CAIN	C,PNDN			;Pen down code?
	 MOVEI	S1,PLTPEN		;Load # tics for pen up/down
	ADDM	S1,J$PTIC(J)		;Add in for accounting
	PJRST	OUTBYT			;Bypass J$ROTA check
>  ;End of IFN CSM01$
SUBTTL	Plotter service -- Banners

	CSMEDT	03,1	;Banner changes, part 1 at P$BANN:
;*; IFN CSM03$,<ND NAMSIZ,1>
	ND NAMSIZ,3	;User's name will be 3 times larger than other text

P$BANN:	CSMEDT	08,3	;PTC-6 Plotter Controller, part 3 at P$BANN
IFN CSM08$,<
	SKIPE	J$TTY(J)		;PTC-6 controller?
	 PUSHJ	P,[MOVEI T1,PLTPEN	  ;Yes, positive to use CR handshake
		   PUSHJ P,PTCINI##	  ;Initialize terminal
		   PJRST OUTRSP	]	  ;Output string to TTY
>  ;End of IFN CSM08$

	PUSHJ	P,P$CPEN		;RE-CALIBRATE THE PEN
	SKIPN	J$FBANN(J)		;BANNER WANTED?
	POPJ	P,			;NO - JUST RETURN
	PUSH	P,J$PTIC(J)		;DON'T CHARGE FOR PLOTTER OVERHEAD
	MOVEI	S1,[ASCIZ |Start|]	;GET LINE IDENTIFIER
	PUSHJ	P,PLTJOB		;PLOT JOB INFORMATION

BANN.1:	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE

IFN NAMSIZ-1,<	;Start a separate line
	ADD	T1,J$XPOS(J)		;POINT TO NEXT LINE
	MOVE	T2,J$YMIN(J)		;GET MINIMUM Y POSITION
>  ;End of IFN NAMSIZ-1
IFE NAMSIZ-1,<	;Put LIMIT on same line as user name
	MOVE	T2,T1			;Copy character size
	ADD	T2,J$YPOS(J)		;Space over a bit in plus-Y direction
	MOVE	T1,J$XPOS(J)		;Current X position
>  ;End of IFN NAMSIZ-1

	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;MOVE THE PEN
	PUSHJ	P,SETTBF		;SET UP TEXT BUFFER
	$TEXT	(DEPBP,<  Limit: ^D/J$RLIM(J)/, Forms: ^W/J$FORM(J)/^A>)

BANN.2:	GETLIM	T1,.EQLIM(J),NOT1	;GET /NOTE VALUE (WORD 1)
	GETLIM	T2,.EQLIM(J),NOT2	;GET /NOTE VALUE (WORD 2)
	SKIPN	T1			;CHECK WORD 1
	SKIPE	T2			;CHECK WORD 2
	$TEXT	(DEPBP,<, Note: ^W6/T1/^W/T2/^A>) ;YES
	MOVEI	S1,.CHNUL		;GET A <NUL>
	PUSHJ	P,DEPBP			;STORE IT
	PUSHJ	P,STRING		;PLOT STRING
	POP	P,J$PTIC(J)		;RESTORE # PLOTTER TICS
	POPJ	P,			;RETURN
SUBTTL	Plotter service -- File headers


P$HEAD:	PUSH	P,J$PTIC(J)		;DON'T CHARGE FOR PLOTTER OVERHEAD
	PUSHJ	P,P$DASH		;SEPARATE FROM BANNER OR LAST FILE
	SKIPN	J$FHEA(J)		;HEADER ALLOWED?
	PJRST	P$HEA1			;NO..POSITION TO ORIGIN
	LOAD	S1,.FPINF(E),FP.NFH	;GET NO FILE HEADER BIT
	JUMPN	S1,P$HEA1		;SKIP IF NOT WANTED
	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
	$CALL	SETTBF			;SETUP TO PRINT STIRNG
	MOVE	S1,J$DIFN(J)		;GET FILE IFN
	MOVEI	S2,FI.CRE		;GET CREATION DATE TIME
	$CALL	F%INFO
	MOVEI	S2,[ITEXT (<>)]		;ASSUME NOT /DISPOSE:RENAME
	SKIPE	J$DSPN(J)		;WAS IT /DISPOSE:RENAME?
	MOVEI	S2,[ITEXT (< (^W/J$DSPN(J)/.^W/J$DSPX(J)/)>)] ;YES

	CSMEDT	02,3	;Halfword format, part 3 at P$HEA1:-2
IFE CSM02$,< $TEXT (DEPBP,<* File: ^F/@J$DFDA(J)/^I/(S2)/ created:^H/S1/ *^0>) >
IFN CSM02$,< $TEXT (DEPBP,<* File: ^F/@J$DFDA(J)/^I/(S2)/ *^0>) >
			;CSM internal headers have creation date/time
	PUSHJ	P,STRING		;PLOT TEXT

P$HEA1:	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
	ADD	T1,J$XPOS(J)		;OFFSET BY CURRENT POSITION
	MOVE	T2,J$YMIN(J)		;GET MINIMUM Y POSITION
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;POSITION PEN
	MOVE	T1,J$XPOS(J)		;GET CURRENT X POSITION
	MOVEM	T1,J$XMIN(J)		;UPDATE NEW MINIMUM
IFN CSM01$,<	;Allow plots to butt up against each other
	ADDI	T1,INCS/2		;Set lowest seen to 1/2 inch margins
	MOVEM	T1,J$XLOW(J)		;(not fully implemented yet)
>  ;End of IFN CSM01$
	POP	P,J$PTIC(J)		;RESTORE # PLOTTER TICS
	POPJ	P,			;RETURN
SUBTTL	Plotter service -- File trailers


P$EOF:	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
	ADD	T1,J$XLIM(J)		;POSITION BEYOND THE HIGHEST X STEP
	MOVE	T2,J$YMIN(J)		;GO BACK TO THE MARGIN
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;POSITION PEN

	CSMEDT	08,4	;PTC-6 Plotter Controller, part 4 at end of P$EOF
IFN CSM08$,<	;Call PTCOUT instead of OUTOUT
	SKIPE	J$TTY(J)		;PTC-6 controller?
	 JRST	[PUSHJ P,PTCOUT##	  ;Yes, raise pen
		 PJRST OUTRSP	]	  ;Wait for response
>  ;End of IFN CSM08$

	PJRST	OUTOUT			;DUMP WHAT WE HAVE
SUBTTL	Plotter service -- Job trailers


P$TRAI:	CSMEDT	03,3	;Banner changes, part 3 at P$TRAI:
IFE CSM03$,<	;This test prevents error messages from coming out
	PUSHJ	P,P$DASH		;SEPARATE FROM LAST FILE
	PUSH	P,J$PTIC(J)		;DON'T CHARGE FOR PLOTTER OVERHEAD
	SKIPN	J$FTRA(J)		;TRAILER ALLOWED?
	  JRST	P$TRA3			;NO
>  ;End of IFE CSM03$
IFN CSM03$,<	;Output dashed line only if text will be plotted
	PUSH	P,J$PTIC(J)		;Don't charge for plotter overhead
	SKIPN	J$FTRA(J)		;Plot the trailer?
	SKIPE	J$XERR(J)		; or an error message?
	 PUSHJ	P,P$DASH		;Yes, separate text from plot
>  ;End of IFN CSM03$

	SKIPN	J$XERR(J)		;ANY ERROR TEXT?
	JRST	P$TRA0			;NO - ONWARD
	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
	IMULI	T1,2		;[CSM]	;Make room for characters
	ADD	T1,J$XPOS(J)		;POINT TO NEXT LINE
	MOVE	T2,J$YMIN(J)		;GET MINIMUM Y POSITION
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;POSITION PEN
	PUSHJ	P,SETTBF		;SET UP TEXT BUFFER
	$TEXT	(DEPBP,<^T/J$XERR(J)/^0>) ;INCLUDE ERROR TEXT
	PUSHJ	P,STRING		;PLOT ERROR TEXT

P$TRA0:
IFN CSM03$,<	;Check for /TRAILER after plotting error message
	SKIPN	J$FTRA(J)		;Trailer wanted?
	 JRST	P$TRA3			;No, skip job line and summary
>  ;End of IFN CSM03$

	MOVEI	S1,[ASCIZ |End|]	;GET LINE IDENTIFIER
	PUSHJ	P,PLTJOB		;PLOT JOB LINE
CONT.	(P$TRAI)


P$TRA1:	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE

IFN NAMSIZ-1,<	;Start a separate line
	ADD	T1,J$XPOS(J)		;POINT TO NEXT LINE
	MOVE	T2,J$YMIN(J)		;GET MINIMUM Y POSITION
>  ;End of IFN NAMSIZ-1
IFE NAMSIZ-1,<	;Put SUMMARY on same line as user name
	MOVE	T2,T1			;Copy character size
	ADD	T2,J$YPOS(J)		;Space over a bit in plus-Y direction
	MOVE	T1,J$XPOS(J)		;Current X position
>  ;End of IFN NAMSIZ-1

	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;POSITION PEN
	PUSHJ	P,SETTBF		;SET UP TEXT BUFFER
	LOAD	T1,.EQSPC(J),EQ.NUM	;GET NUMBER OF FILES
	MOVEI	T2,[ITEXT (<file>)]	;ASSUME 1 FILE
	CAIE	T1,1			;WAS IT
	MOVEI	T2,[ITEXT (<files>)]	;NO
	$TEXT	(DEPBP,<  Summary: ^D/T1/ ^I/(T2)/^A>)
P$TRA2:	MOVE	T1,(P)			;GET # TICS FOR JOB
	IDIV	T1,J$PTPM(J)		;T1:= MINUTES, T2:= FRACTION
	IMULI	T2,^D10			;[CSM] 1 decimal place (=6 seconds)
	IDIV	T2,J$PTPM(J)		;T2:= DECIMAL FRACTION OF A MINUTE
	$TEXT	(DEPBP,< plotted in ^D/T1/.^D/T2/ minutes^0>)
	PUSHJ	P,STRING		;PLOT TEXT

P$TRA3:	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
	IMULI	T1,2			;LEAVE THIS MUCH SPACE
	ADD	T1,J$XPOS(J)		;OFFSET BY CURRENT POSITION
	PUSHJ	P,P$LINE		;PLOT SEPARATOR
	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
	IMULI	T1,2			;POINT TO NEXT LINE
	ADD	T1,J$XPOS(J)		;OFFSET BY CURRENT POSITION
	MOVE	T2,J$YMIN(J)		;GET MINIMUM Y POSITION
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;POSITION PEN
	POP	P,J$PTIC(J)		;RESTORE # PLOTTER TICS
	MOVE	T1,J$PTIC(J)		;GET # TICS
	IDIV	T1,J$PTPM(J)		;GET MINUTES OF PLOTTER TIME
	MOVEM	T1,J$APRT(J)		;STORE IT

	CSMEDT	08,5	;PTC-6 Plotter Controller, part 5 at end of P$TRAI
IFN CSM08$,<
	SKIPE	J$TTY(J)		;PTC-6 controller?
	 PUSHJ	P,[PUSHJ P,PTCOUT##	  ;Yes, raise pen
		   PUSHJ P,OUTRSP	  ;Wait for response
		   PUSHJ P,PTCFIN##	  ;Finish up and deselect
		   PJRST OUTSTG	]	  ;Output string to TTY
>  ;End of IFN CSM08$

	POPJ	P,			;RETURN
SUBTTL	Plotter service -- Solid lines


; This routine does the following:
;	1. Position to the next line
;	2. Plot a solid line
;	3. Position to the next line
;
P$LINE:	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
	ADD	T1,J$XPOS(J)		;POINT TO NEXT LINE

	CSMEDT	03,4	;Banner changes, part 4 at P$LINE:+2
IFE CSM03$,<	;Going from MIN to MAX when pen is near MAX wastes time
	MOVE	T2,J$YMIN(J)		;GET MINIMUM Y POSITION
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;POSITION PEN
	MOVE	T1,J$XPOS(J)		;Use current X position
	MOVE	T2,J$YMAX(J)		;GET MAXIMUM Y VALUE
>  ;End of IFE CSM03$
IFN CSM03$,<	;Go to MAX, then to MIN and end there
	MOVE	T2,J$YMAX(J)		;Go to closer end point
	CAIL	T2,INCS*6		;More than 6 inches?
	 MOVEI	T2,INCS*6		;Yes, don't waste inc
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;Position pen
	MOVE	T1,J$XPOS(J)		;Use current X position
	MOVE	T2,J$YMIN(J)		;Go to "HOME" position
>  ;End of IFE CSM03$
	MOVEI	T3,PN.DWN		;Pen down
	PUSHJ	P,PLOT			;PLOT A LINE

LINE.1:	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
	IMULI	T1,2			;LEAVE SOME SPACE
	ADD	T1,J$XPOS(J)		;POSITION TO NEXT LINE
	MOVE	T2,J$YMIN(J)		;GET MINIMUM Y VALUE
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;POSITION PEN AT START OF NEXT LINE
	PUSHJ	P,OUTOUT		;DUMP BUFFERS
	POPJ	P,			;RETURN
SUBTTL	Plotter service -- Dashed lines


; This routine works like P$LINE, but line is drawn with dashes.
; The length of each dash is the same as the height of the characters

P$DASH:	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
	ADD	T1,J$XPOS(J)		;POINT TO NEXT LINE

	CSMEDT	03,5	;Banner changes, part 5 at P$DASH:+3
IFE CSM03$,< MOVE  T2,J$YMIN(J) >	;GET MINIMUM Y POSITION
IFN CSM03$,<
	MOVE	T2,J$YMAX(J)		;Get maximum Y position
	CAIL	T2,INCS*6		;More than 6 inches?
	 MOVEI	T2,INCS*6		;Yes, don't waste time and ink
>  ;End of IFN CSM03$
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;POSITION PEN

DASH.1:	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
IFE CSM03$,<
	ADD	T1,J$YPOS(J)		;ADD TO Y POSITION
	CAML	T1,J$YMAX(J)		;GONE TOO FAR?
>  ;End of IFE CSM03$
IFN CSM03$,<
	MOVNS	T1			;Make negative
	ADD	T1,J$YPOS(J)		;Decrement Y position
	CAMG	T1,J$YMIN(J)		;Gone too far?
>  ;End of IFN CSM03$
	JRST	LINE.1			;YES - FINISH UP
	MOVE	T2,T1			;PUT IN PROPER PLACE
	MOVE	T1,J$XPOS(J)		;GET X POSITION
	MOVEI	T3,PN.DWN		;Pen down
	PUSHJ	P,PLOT			;PLOT A LINE

DASH.2:	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
IFE CSM03$,<
	ADD	T1,J$YPOS(J)		;ADD TO Y POSITION
	CAML	T1,J$YMAX(J)		;GONE TOO FAR?
>  ;End of IFE CSM03$
IFN CSM03$,<
	MOVNS	T1			;Make negative
	ADD	T1,J$YPOS(J)		;Decrement Y position
	CAMG	T1,J$YMIN(J)		;Gone too far?
>  ;End of IFN CSM03$
	JRST	LINE.1			;YES - FINISH UP
	MOVE	T2,T1			;PUT IN PROPER PLACE
	MOVE	T1,J$XPOS(J)		;GET X POSITION
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;PLOT A LINE
	JRST	DASH.1			;GO BACK AND DO IT AGAIN
SUBTTL	Plotter service -- Job information plotting


; Here to job information for banner and trailer lines
; Call:	MOVEI	S1,[ASCIZ |Start|]	;OR [ASCIZ |End|]
;	PUSHJ	P,PLTJOB
;
PLTJOB:	PUSH	P,S1			;SAVE TEXT POINTER
	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
	IMULI	T1,2			;MOVE OUT A BIT
	ADD	T1,J$XPOS(J)		;OFFSET BY CURRENT POSITION
	MOVE	T2,J$YMIN(J)		;GET MINIMUM Y POSITION
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;POSITION PEN
	PUSHJ	P,SETTBF		;SET UP TEXT BUFFER

	CSMEDT	03,6	;Banner changes, part 6 at PLTJOB:+8
IFN CSM03$,< PUSHJ P,PEN.3 >		;Do "*START*" in red

	MOVE	T1,.EQJBB+JIB.JN(J)	;GET JOB NAME
	MOVE	T2,.EQJBB+JIB.ID(J)	;GET REQUEST ID
	POP	P,T3			;RESTORE TEXT POINTER
	$TEXT	(DEPBP,<* ^T/(T3)/ Job ^W/T1/ req #^D/T2/ ^H/[-1]/ ^T/(T3)/ *^0>)
	PUSHJ	P,STRING		;PLOT STRING

	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
	IMULI	T1,NAMSIZ+1	;[CSM]	;Size of name plus blank space
	ADD	T1,J$XPOS(J)		;OFFSET BY CURRENT POSITION
	MOVE	T2,J$YMIN(J)		;GET MINIMUM Y POSITION
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;MOVE THE PEN
	PUSHJ	P,SETTBF		;SET UP POINTERS TO THE BUFFER
	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
	IMULI	T1,NAMSIZ	;[CSM]	;The name is bigger than other text
	MOVEM	T1,J$CSIZ(J)		;STORE IT

IFN CSM03$,< PUSHJ P,PEN.2 >		;Do user's name in black

CONT.	(PLTJOB)
	;PLOT THE USERS NAME

TOPS10<	DMOVE	T3,.EQOWN(J)		;Name and PPN, 28 chars max
	$TEXT	(DEPBP,< ^W6/T3/^W/T4/ ^P/.EQOID(J)/^0>)   >

TOPS20<	$TEXT	(DEPBP,< ^T/.EQOWN(J)/^0>) 		   >

	PUSHJ	P,STRING		;PLOT THE STRING
	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
	ADD	T1,J$XPOS(J)		;POINT TO NEXT LINE
	MOVE	T2,J$YMIN(J)		;GET MINIMUM Y POSITION
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;POSITION PEN

IFN CSM03$,< PUSHJ P,PEN.1 >		;Next dividing line will be blue

	POPJ	P,			;RETURN
SUBTTL	Plotter service -- Alignment and testing

REPEAT 0,<

; Routine to test character plots
;
P$TEST:	$SAVE	<P1>			;SAVE P1
	PUSHJ	P,SETTBF		;SET UP TEXT BUFFER
	PUSHJ	P,P$CPEN		;CALIBRATE THE PEN
	MOVEI	C,.CHNUL		;START WITH <NUL>

TEST.1:	PUSH	P,C			;SAVE CHARACTER
	MOVEI	S1,.CHNUL	;[CSM]	;Terminate previous string
	PUSHJ	P,DEPBP		;[CSM]	; (in case of /NOTE: in SPFORM.INI)
	PUSHJ	P,STRING		;OUTPUT TEXT
	PUSHJ	P,P$CHKS		;COMPUTE CHARACTER SIZE
	IMULI	T1,2			;WANT DOUBLE HEIGHT CHARACTERS
	MOVEM	T1,J$CSIZ(J)		;REMEMBER IT
	ADD	T1,J$XPOS(J)		;OFFSET BY CURRENT POSITION
	MOVE	T2,J$YMIN(J)		;GET MINIMUM Y POSITION
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;POSITION PEN
	PUSHJ	P,SETTBF		;SET UP TEXT BUFFER
	POP	P,C			;RESTORE CHARACTER
	CAIN	C,200			;DONE ALL CHARACTERS?
	PJRST	OUTOUT			;PLOT TEXT AND RETURN
	MOVEI	P1,40			;SET UP COUNTER

TEST.2:	SKIPN	S1,C			;GET CHARACTER
	MOVEI	S1," "			;STRING SUBROUTINE CAN'T HANDLE <NUL>
	PUSHJ	P,DEPBP			;PUT CARACTER
	ADDI	C,1			;ADVANCE TO NEXT CHARACTER
	SOJLE	P1,TEST.1		;DONE WITH THIS LINE?
	JRST	TEST.2			;NO
>
SUBTTL	Plotter service -- Pen calibration

;This is the only place that J$XPOS is reset.  It is called from P$BANN.

P$CPEN:	MOVE	T1,J$YMAX(J)		;GET THE MAXIMUM Y VALUE WE KNOW ABOUT

	CSMEDT	01,4	;3-pen plotter, part 4 at end of P$CPEN
IFN CSM01$,<	;Assume pen is positioned close to the origin
	CAIL	T1,INCS*4		;More than 4 inches?
	 MOVEI	T1,INCS*4		;Yes, don't waste time ramming the pen
>  ;End of IFN CSM01$

	MOVEM	T1,J$YPOS(J)		;FAKE OUT THE LOW LEVEL OUTPUT ROUTINE
	PUSH	P,J$YMIN(J)		;SAVE MINIMUM Y POSITION
	SETZM	J$YMIN(J)		;CLEAR SO WE CAN GO BELOW IT
	MOVE	T1,J$XPOS(J)		;Use current X position
	MOVEI	T2,0			;RAM THE PEN INTO THE AXIS
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;POSITION PEN
	SETZM	J$XMIN(J)		;ZERO X MINIMUM
	SETZM	J$YMIN(J)		;ZERO Y MINIMUM
	SETZM	J$XPOS(J)		;ZERO X POSITION
	SETZM	J$YPOS(J)		;ZERO Y POSITION
	MOVE	T1,J$XORG(J)		;GET ORIGINAL X MINIMUM
	MOVE	T2,(P)			;GET MINIMUM Y VALUE
	MOVEI	T3,PN.UP		;Pen up
	PUSHJ	P,PLOT			;PUT PEN THERE
	MOVE	T1,J$XORG(J)		;GET ORIGINAL X MINIMUM
	MOVEM	T1,J$XMIN(J)		;STORE IT
	POP	P,J$YMIN(J)		;RESTORE MINIMUM Y POSITION

IFN CSM01$,<	;RECAL has positioned pen #1 at YMIN
	SETZM	J$PENN(J)		;Flag that pen holder was reset
	MOVEI	S1,1			;Select pen number 1
	PUSHJ	P,NEWPEN		;Tell the plotter which pen to use
>  ;End of IFN CSM01$

	POPJ	P,			;RETURN
SUBTTL	Plotter service -- Compute character size


P$CHKS:	MOVE	T1,J$YMAX(J)		;CALCULATE SIZE
	SUB	T1,J$YMIN(J)		; OF PLOTTING AREA
	IDIVI	T1,CHRPLN		;MAXIMUM NUMBER OF CHARACTERS PER LINE

	CSMEDT	01,5	;3-Pen plotter, part 5 at P$CHKS:+3
IFN CSM01$,<	;Don't plot giant letters on 36 inch wide paper
	CAIL	T1,INCS/6		;Bigger than 1/6 inch?
	 MOVEI	T1,INCS/6		;Yes, reduce size
>  ;End of IFN CSM01$

	MOVEM	T1,J$CSIZ(J)		;STORE CHARACTER SIZE
	POPJ	P,			;RETURN
SUBTTL	Plotter service -- Line segments


;Call	T1/ X Coordinate to move to
;	T2/ Y Coordinate to move to
;	T3/ Pen code as follows
	PN.SAM==1	;No Change in Pen
	PN.DWN==2	;Pen Down before Plotting
	PN.UP== 3	;Pen Up before moving
;
PLOT:	$SAVE	<T1,T2,T3,T4>		;PRESERVE TEMPORARIES

	CSMEDT	08,6	;PTC-6 Plotter Controller, part 6 at PLOT:+1
IFN CSM08$,<	;Delay testing of T3 if output to a terminal
	SKIPN	J$TTY(J)		;Is the plotter really a TTY?
>  ;End of IFN CSM08$

	CAIG	T3,PN.SAM		;CHANGE REQUESTED?
	JRST	PLT.1			;NO..PROCEED
	SUBI	T3,PN.UP		;Yes, get -1  or 0
	CAMN	T3,J$PPOS(J)		;PEN IN POSITION?
	JRST	PLT.1			;YES -- PROCEED
	MOVEI	C,PNUP			;GET PEN UP CODE
	SKIPGE	T3			;WANT IT LOWERED?
	MOVEI	C,PNDN			;YES..GET THE CODE
	$CALL	PLTBYT			;MOVE THE PEN
PLT.1:	SUB	T1,J$XPOS(J)		;COMPUTE DELTA X
	SUB	T2,J$YPOS(J)		;COMPUTE DELTA Y

IFN CSM08$,<	;Call external routine if PTC-6
	SKIPE	J$TTY(J)		;TTY?       (T1, T2, and T3 set up)
	 JRST	PTCMV			;Yes, calculate character string
>  ;End of IFN CSM08$

	MOVEI	T3,XYD			;ASSUME DOWN MOVEMENT
	SKIPG	T1			;IS THAT CORRECT?
	MOVEI	T3,XYU			;NO..ASSUME UP
	MOVEI	T4,XYL			;ASSUME LEFTWARD MOVEMENT
	SKIPG	T2			;IS THAT CORRECT?
	MOVEI	T4,XYR			;NO..THEN ASSUME RIGHT
	MOVMS	T1			;MAKE DELTA X POSITIVE
	MOVMS	T2			;MAKE DELTA Y POSITIVE
	CAML	T1,T2			;IS SMALLEST DELTA IN T2?
	JRST	PLT.2			;YES -- PROCEED
	EXCH	T1,T2			;NO -- MAKE IT SO
	EXCH	T3,T4			;EXCHANGE MOVEMENT CODES
PLT.2:	JUMPE	T1,PLT.8		;DONE IF NO MOVEMENT REQUESTED
	JUMPE	T2,PLT.6		;PLOT ONLY ONE DIRECTION

SUBTTL	Plotter service -- PTC-6 interface

IFN CSM08$,<	;T1 & T2 have delta movement, T3 has 2 or 3
PTCMV:	ADDM	T1,J$XPOS(J)		;Update position
	ADDM	T2,J$YPOS(J)
	MOVE	S1,J$XPOS(J)		;Get new X position
	CAIL	T3,3			;Pen up?
	 JRST	PTCMV1			;No, skip next tests
	CAMLE	S1,J$XLIM(J)		;Highest seen so far?
	 MOVEM	S1,J$XLIM(J)		;Yes
	CAMGE	S1,J$XLOW(J)		;Closest to the origin?
	 MOVEM	S1,J$XLOW(J)		;Yes

;T1, T2, and T3 are set up with delta-X, delta-Y, and pen up/down code

PTCMV1:	PUSHJ	P,PTCMOV##		;Translate move, fall into OUTRSP

			PAGE
;Routine to output the string pointed to by T1 and wait for response.
;S1 has accumulated increments for the last 4 buffers, to be used to
;predict how long it will take for the PTC-6 to respond.

OUTRSP:	JUMPE	T1,.POPJ		;Don't wait if no string
	IMULI	S1,PLTMOV		;Number of ticks to move
	LSH	S1,-2			;S1 has count for 4 buffers
	ADDM	S1,J$PTIC(J)		;Predict elapsed time
	IMULI	S1,^D60*4		;Cancel LSH, use seconds not minutes
	IDIV	S1,J$PTPM(J)		;Number of seconds required
	ADDI	S1,^D<512*10/CSM08$>	;512 chars take 2 seconds at 2400 baud
	MOVNM	S1,J$NACK(J)		;Negative to delay the complaints

OUTRS1:	PUSHJ	P,OUTSTG		;Send the string

OUTRS2:	PUSHJ	P,TIWAIT		;Get response, waiting up to 30 seconds
	JUMPT	OUTRS3			;Got it
	TXNE	S,RQB+ABORT		;REQUEUE or ABORT?
	 $RETF				;Yes, give up
	PUSHJ	P,PTCOUT##		;Send string to raise pen
	SETZM	J$PPOS(J)		;(just to get controller to respond)
	JRST	OUTRS1			;Loop until response or REQUEUE

OUTRS3:	CAIE	S1,.CHCRT		;CR at end?
	 JRST	OUTRS2			;No, skip over "0", "C"
	PJRST	TTYIN			;Yes, snarf up the LF (if it's there)


;Routine to output the string pointed to by T1.
;The Monitor will put the job in "TO" Terminal Output wait if there are more
;than 400 characters in the TTY chunks.

	TOMAX=^D248			;Avoid output wait for TTY

OUTSTG:	JUMPE	T1,.POPJ		;Return if nothing to do
	HRLI	T1,(POINT 7,)		;Make into ASCII byte pointer
OUTST1:	MOVEI	S1,0			;Clear byte count

OUTST2:	ILDB	C,T1			;Get a character
	JUMPE	C,OUTOUT		;Stop on null, output buffer, return
	PUSHJ	P,OUTBYT		;Send it
	CAIG	S1,TOMAX		;Almost enough to cause 'TO' wait?
	 AOJA	S1,OUTST2		;Loop till end of ASCIZ
	PUSHJ	P,OUTOUT		;Dump partial buffer
	$DSCHD	(TOMAX*^D10/CSM08$)	;Wait 1 second at 2400 baud
	JRST	OUTST1			;(gives checkpoint routine a chance)
>  ;End of IFN CSM08$
SUBTTL	Plotter service -- Rotation and XY20 translation



;Plotter Translation Table Entry Description
;	0                         17    20   23 24   27 28   31 32   35
;	================================================================
;	!       XY20 CODE           !  !ROT = 3!ROT = 2!ROT = 1!ROT = 0!
;	================================================================
;
ROTAB:	EXP 0						; 0 NO MOVEMENT
	BYTE (18) 106 (2) 0 (4) XYU ,XYL ,XYD ,XYR 	; 1 Minus X
	BYTE (18) 102 (2) 0 (4) XYD ,XYR ,XYU ,XYL 	; 2 Plus X
	BYTE (18) 114 (2) 0 (4) PEN3,PEN3,PEN3,PEN3	; 3 SELECT PEN3
	BYTE (18) 104 (2) 0 (4) XYR ,XYU ,XYL ,XYD 	; 4 Plus Y
	BYTE (18) 105 (2) 0 (4) XYDL,XYUL,XYUR,XYDR	; 5 Plus Y & Minus X
;[CSM]	BYTE (18) 103 (2) 0 (4) XYDR,XYDL,XYUL,XYUR	;MOVE UP+RIGHT
	BYTE (18) 103 (2) 0 (4) XYDR,XYUR,XYUL,XYDL;[CSM] 6 Plus Y & Plus X
	EXP -1						; 7 ILLEGAL
	BYTE (18) 100 (2) 0 (4) XYL ,XYD ,XYR ,XYU 	;10 Minus Y
;[CSM]	BYTE (18) 107 (2) 0 (4) XYUL,XYUR,XYDR,XYDL	;MOVE DOWN+LEFT
	BYTE (18) 107 (2) 0 (4) XYUL,XYDL,XYDR,XYUR;[CSM]11 Minus Y & Minus X
	BYTE (18) 101 (2) 0 (4) XYUR,XYDR,XYDL,XYUL	;12 Minus Y & Plus X
	EXP -1						;13 ILLEGAL
	BYTE (18) 113 (2) 0 (4) PEN2,PEN2,PEN2,PEN2	;14 SELECT PEN 2
	EXP -1						;15 ILLEGAL
	EXP -1						;16 ILLEGAL
	BYTE (18) 112 (2) 0 (4) CNGP,CNGP,CNGP,CNGP	;17 CHANGE PENS

ROPTR:	POINT	4,ROTAB(C),35		;POINTER TO ZERO ROTATION
	POINT	4,ROTAB(C),31		; ROTATION = 1
	POINT	4,ROTAB(C),27		; ROTATION = 2
	POINT	4,ROTAB(C),23		; ROTATION = 3
SUBTTL	Plotter service -- Pen movement generation


;Call	C/ Character to plot
;
;Will adjust values in J$XPOS and J$YPOS based on pen movement
;Also checks range on J$XMIN-J$XMAX and J$YMIN-J$YMAX
;Saves highest pen movement in J$XLIM and J$YLIM
;
PLTBYT:	$SAVE	<S1,S2>		;[CSM]	;Preserve ACs
	TRZE	C,PNUP			;TEST AND CLEAR PEN UP CODE
	$CALL	PENUP			;RAISE PEN
	TRZE	C,PNDN			;TEST AND CLEAR PEN DOWN CODE
	$CALL	PENDN			;LOWER PEN

PLTXYD:	TRNN	C,XYD			;GOING DOWN?
	JRST	PLTXYU			;NO
	TRNE	C,XYU		;[CSM]	;Going +X and -X at the same time?
	 JRST	PLTB.8		;[CSM]	;Yes, this is a change-pen code
	AOS	S1,J$XPOS(J)		;+1
	CAMG	S1,J$XMAX(J)		;BEYOND X MAXIMUM?
	CAMG	S1,J$XMIN(J)		;WITHIN X BOUNDS?
	TRZ	C,XYD!XYU		;STOP MOVING

PLTXYU:	TRNN	C,XYU			;GOING UP?
	JRST	PLTXYL			;NO
	SOS	S1,J$XPOS(J)		;-1
	CAMGE	S1,J$XMAX(J)		;BEYOND X MAXIMUM?
	CAMGE	S1,J$XMIN(J)		;WITHIN X BOUNDS?
	TRZ	C,XYD!XYU		;STOP MOVING

PLTXYL:	TRNN	C,XYL			;GOING LEFT?
	JRST	PLTXYR			;NO
	TRNE	C,XYR		;[CSM]	;Going +Y and -Y at the same time?
	 JRST	PLTB.8		;[CSM]	;Yes, this is a change-pen code
	AOS	S2,J$YPOS(J)		;+1
	CAMG	S2,J$YMAX(J)		;BEYOND Y MAXIMUM?
	CAMG	S2,J$YMIN(J)		;WITHIN Y BOUNDS?
	TRZ	C,XYR!XYL		;STOP MOVING

PLTXYR:	TRNN	C,XYR			;GOING RIGHT?
	JRST	PLTB.6			;NO
	SOS	S2,J$YPOS(J)		;-1
	CAMGE	S2,J$YMAX(J)		;BEYOND Y MAXIMUM?
	CAMGE	S2,J$YMIN(J)		;WITHIN Y BOUNDS?
	TRZ	C,XYR!XYL		;STOP MOVING

	CONT.	(PLTBYT)
PLTB.6:	SKIPN	J$PPOS(J)		;IS PEN DOWN?
	PJRST	PLTB.8			;NO..DON'T RECORD MAX POSITIONS
	MOVE	S1,J$XPOS(J)	;[CSM]	;In case of no AOS or SOS was done
	CAMLE	S1,J$XMAX(J)		;CLIPPED?
	JRST	PLTB.7			;YES -- DON'T ADJUST LIMIT
	CAMLE	S1,J$XLIM(J)		;HIGHEST POINT SO FAR?
	MOVEM	S1,J$XLIM(J)		;YES -- SAVE IT

	CSMEDT	01,6	;3-pen plotter, part 6 at PLTB.6:+5
IFN CSM01$,<	;Remember X minimum for positioning trailer after X maximum
	CAMGE	S1,J$XLOW(J)		;Smaller than the previous XLOW?
	 MOVEM	S1,J$XLOW(J)		;Yes, user went near -X boundry
					;therefore put dashed line close to plot
>  ;End of IFN CSM01$

PLTB.7:	CAMLE	S2,J$YMAX(J)		;CLIPPED?
	JRST	PLTB.8			;YES -- DON'T ADJUST LIMIT
	CAMLE	S2,J$YLIM(J)		;HIGHEST POINT SO FAR?
	MOVEM	S2,J$YLIM(J)		;YES -- SAVE IT

PLTB.8:	JUMPE	C,.RETT			;RETURN IF NOTHING TO PLOT
	MOVEI	S1,PLTMOV		;LOAD # TICS FOR MOVEMENT
	ADDM	S1,J$PTIC(J)		;ADD TO TOTAL SO FAR
;	MOVE	S1,[LDB	C,ROPTR]	;GET ROTATE INSTRUCTION
;	ADD	S1,J$ROTA(J)		;OFFSET BY GRID ROTATION
;	XCT	S1			;ROTATE
	PJRST	OUTBYT			;OUTPUT THE BYTE
	CHRBAS==6
	CHRWID==6

	FIN==<CHRBAS>B31!<CHRWID>B35
PLTTAB:				;Characters used at Stanford (SUAI)

C%000:	Z				;NULL IS ILLEGAL
C%001:	XX <200,542,702,142,604,FIN>			;Down arrow
	.XCREF				;[CSM] Don't CREF the rest
C%002:	XX <144,563,603,622,621,600,560,541,542,563,603,624,FIN> ;Alpha
C%003:	XX <561,701,702,663,642,241,643,624,603,601,FIN>;Beta
C%004:	XX <602,544,FIN>				;Up angle bracket
C%005:	XX <220,624,564,FIN>				;Negation
C%006:	XX <243,641,620,560,541,543,200,602,FIN>	;Epsilon
C%007:	XX <141,641,240,644,243,543,FIN>		;Pi
C%010:	XX <602,240,544,FIN>				;Lambda
C%011:	XX <240,661,604,564,543,562,602,644,FIN>	;Gamma
C%012:	XX <242,641,620,560,541,543,564,624,643,642,702,704,FIN> ;Linefeed
C%013:	XX <160,541,562,662,703,664,FIN>		;Integral
C%014:	XX <240,644,302,562,160,564,FIN>		;Plus or Minus
C%015:	XX <200,560,541,543,564,624,643,641,620,600,604,242,542,FIN> ;CR
C%016:	XX <202,561,600,620,641,622,602,563,604,624,643,622,FIN> ;Infinity
C%017:	XX <204,623,621,600,560,541,543,564,644,702,701,FIN>	;Delta
C%020:	XX <244,641,620,560,541,544,FIN>		;Subset
C%021:	XX <240,643,624,564,543,540,FIN>		;Element of
C%022:	XX <160,640,661,663,644,564,FIN>		;Intersection
C%023:	XX <260,600,561,563,604,664,FIN>		;Union
C%024:	XX <300,600,542,604,704,240,644,FIN>		;All elements
C%025:	XX <544,704,700,221,624,206>			;There exists
C%026:	XX <100,640,600,561,562,603,643,603,564,FIN>	;Mu (micro)
C%027:	XX <143,564,603,164,560,221,640,661,240,644,FIN>;Double arrow
C%030:	XX <541,561,600,620,641,643,624,604,563,543,544,FIN> ;Omega
C%031:	XX <220,624,262,624,562,FIN>			;Left arrow
C%032:	XX <142,600,642,604,542,FIN>	;Formerly C%175	;Diamond box [CSM]
C%033:	XX <602,642,704,244,640,200,604,FIN>		;Not equal
C%034:	XX <160,563,303,620,623,FIN>			;Less or equal
C%035:	XX <300,623,620,160,563,FIN>			;Greater or equal
C%036:	XX <160,564,224,620,260,664,FIN>		;Identically
C%037:	XX <200,542,604,FIN>				;Down angle bracket

C%140:	XX <341,703,FIN>
C%141:	XX <163,542,541,560,620,641,643,563,544,FIN>
C%142:	XX <300,540,543,564,624,643,640,FIN>
C%143:	XX <224,643,641,620,560,541,543,564,FIN>
C%144:	XX <304,544,541,560,620,641,644,FIN>
C%145:	XX <143,541,560,620,641,643,624,604,600,FIN>
C%146:	XX <141,661,702,703,664,220,622,FIN>
C%147:	XX <144,541,560,620,641,643,624,524,503,501,FIN>
C%150:	XX <700,220,641,643,624,544,FIN>
C%151:	XX <141,543,542,642,641,262,702,662,FIN>
C%152:	XX <121,502,503,524,644,643,FIN>
C%153:	XX <700,243,601,600,602,544,FIN>
C%154:	XX <141,543,542,702,701,FIN>
C%155:	XX <640,620,641,622,542,622,643,624,544,FIN>
C%156:	XX <640,200,642,643,624,544,FIN>
C%157:	XX <160,620,641,643,624,564,543,541,560,FIN>
C%160:	XX <100,640,643,624,564,543,540,FIN>
C%161:	XX <144,541,560,620,641,644,504,FIN>
C%162:	XX <640,200,642,643,624,FIN>
C%163:	XX <543,564,603,601,620,641,644,FIN>
C%164:	XX <301,561,542,543,564,240,642,FIN>
C%165:	XX <240,560,541,542,604,644,544,FIN>
C%166:	XX <240,600,542,604,644,FIN>
C%167:	XX <240,560,541,562,642,562,543,564,644,FIN>
C%170:	XX <644,240,544,FIN>
C%171:	XX <240,560,541,544,244,524,503,501,FIN>
C%172:	XX <240,644,540,544,201,603,FIN> ;z Lowercase Z
C%173:	XX <144,543,562,602,621,620,621,642,662,703,704,FIN> ;{
C%174:	XX <102,702,FIN>		;| Vertical bar
  ;[CSM] Put close brace and tilde where they belong in the ASCII code
C%175:	XX <541,562,602,623,624,623,642,662,701,700,FIN> ;} 175, not C%176
C%176:	XX <160,601,543,564,FIN>	;~ Tilde, formerly C%032
	.CREF			;[CSM]	;OK to CREF now
C%177:	XX <260,564,FIN>		;\ Backslash, duplicate of C%134
SUBTTL	Paper tape punch service -- Dispatch table


T$DISP:	JRST	T$HEAD			;(0) FILE HEADER
	JRST	T$EOF			;(1) FILE TRAILER
	SIXBIT	/PTP/			;(2) GENERIC DEVICE NAME
	EXP	PTPBSZ			;(3) OUTPUT BYTE SIZE
	JRST	T$PROC			;(4) PROCESS A FILE
	JRST	T$BANN			;(5) JOB BANNER
	JRST	T$TRAI			;(6) JOB TRAILER
	JRST	T$LETR			;(7) LETTER ProcessER
	JRST	.RETF			;(10) ERROR PROCCESSOR

	CSMEDT	04,4	;CSM accounting, part 4 at T$DISP:+11
IFE CSM04$,< JRST   .RETT >		;(11) ACCOUNTING
IFN CSM04$,< JRST   CSMACT >		;(11) ACCOUNTING

	JRST	T$CHKP			;(12) CHECKPOINT TEXT GENERATION
SUBTTL	Paper tape punch service -- File processing


T$PROC:	LOAD	S1,.FPINF(E),FP.FFF	;GET FILE FORMAT
	CAIN	S1,.FPF11		;/FILE:ELEVEN?
	JRST	PTELF			;YES, DO IT
	LOAD	S1,.FPINF(E),FP.FPF	;GET PAPER FORMAT
	CAILE	S1,PTROUL		;WITHIN RANGE?
	JRST	BADMOD			;NO, LOSE
	JUMPN	S1,@T$ROUT-1(S1)	;YES, DISPATCH IF NON-ZERO

	CSMEDT	07,5	;QUEUE defaults, part 5 at T$PROC:+6
IFE CSM07$,<	;This code will punch SOS files in BINARY mode
	MOVEI	S1,T$MTAB		;GET ADDRESS OF MODE TABLE
	MOVEI	S2,T$ROUT		;GET ADDRESS OF ROUTINE TABLE
	PJRST	DSPMOD			;AND DISPATCH BASED ON MODE
>  ;End of IFE CSM07$
IFN CSM07$,< JRST  PTASC >		;Default always to ASCII

T$ROUT:	EXP	PTASC			;ASCII
	EXP	PTIMA			;IMAGE
	EXP	PTIBI			;IBIN
	EXP	PTBIN			;BINARY

	PTROUL==.-T$ROUT		;LENGTH OF ROUTINE TABLE

;MODE TABLE
T$MTAB:	BYTE (3) 1,1,0,0,0,0,0,0,2,0,0,3,4,4,4,4
SUBTTL	Paper tape punch service -- Byte output


; AC 'C' contains the byte to output
;
PTPBYT:	$SAVE	<S1,S2>		;[CSM]	;Preserve ACs
	PUSHJ	P,OUTBYT		;OUTPUT THE BYTE
	AOS	S1,J$TFRM(J)		;COUNT THE FRAME
	IDIVI	S1,FRMPFT		;COMPUTE FEET OF TAPE USED
	MOVEM	S1,J$APRT(J)		;STORE FOR ACCOUNTING PURPOSES
	CAMLE	S1,J$RLIM(J)		;EXCEEDED LIMIT?
	PUSHJ	P,FRMLEX		;YES - ASK THE OPERATOR'S ADVICE
	POPJ	P,		;[CSM]	;ACs automatically retored on return


; Repeat the byte in AC 'C'
; Call:	MOVE	S1,repeat count
;	MOVE	C,byte to output
;	PUSHJ	P,PTPREP
;
PTPREP:	$SAVE	<P1>		;[CSM]	;Save P1
	MOVE	P1,S1			;GET COUNT
	PUSHJ	P,PTPBYT		;OUTPUT A BYTE
	SOJG	P1,.-1			;AND LOOP
	POPJ	P,			;RETURN
SUBTTL	Common Utilities

;PUTERR	Routine to Move error Messages into J$XERR Buffer

; Call:	MOVE	S1,address if ITEXT block
;	PUSHJ	P,PUTERR
;
PUTERR:	$CALL	SETEBF			;POINT $TEXT TO ERROR BUFFER
	$TEXT	(DEPBP,<? ^I/0(S1)/^0>)	;YES -- MOVE TO BUFFER
	$RETT


;HERE TO PRINT THE STRING IN J$XTBF(J) ON THE DEVICE
STRING:	$SAVE	<P1,P2>			;SAVE P1 AND P2
	MOVE	P1,[POINT 7,J$XTBF(J)]	;LOAD A BYTE POINTER
	MOVE	P2,J$LSER(J)		;AND ADDRESS OF DISPATCH TABLE

STRI.1:	ILDB	S1,P1			;GET A BYTE
	JUMPE	S1,.RETT		;END OF STRING
	PUSHJ	P,DLETR(P2)		;PRINT THE LETTER
	JRST	STRI.1			;AND LOOP


;HERE TO SETUP A BYTE POINTER TO THE J$XTBF(J) BUFFER
SETTBF:	MOVEI	TF,J$XTBF(J)		;GET THE ADDRESS OF TEXT BUFFER
	HRLI	TF,(POINT 7,0)		;MAKE A POINTER
	MOVEM	TF,TEXTBP		;STORE THE BYTE POINTER
	MOVEI	TF,TXT$LN*5		;GET BYTE COUNT
	MOVEM	TF,TEXTBC		;AND SAVE IT
	SETZM	J$XTBF(J)		;ZAP FIRST WORD
	$RETT				;AND RETURN

SETEBF:	MOVEI	TF,J$XERR(J)		;GET THE ADDRESS OF ERROR BUFFER
	HRLI	TF,(POINT 7,0)		;MAKE A POINTER
	MOVEM	TF,TEXTBP		;STORE THE BYTE POINTER
	MOVEI	TF,ERR$LN*5		;GET BYTE COUNT
	MOVEM	TF,TEXTBC		;AND SAVE IT
	SETZM	J$XERR(J)		;ZAP FIRST WORD
	$RETT				;AND RETURN

		PAGE
	CSMEDT	07,6	;QUEUE defaults, part 6 before DSPMOD:
IFE CSM07$,<
;HERE TO DISPATCH TO A processing ROUTINE BASED ON FILE MODE.
;	S1 CONTAINS THE MODE-TABLE ADDRESS AND S2 CONTAINS THE ROUTINE-
;	TABLE ADDRESS.
DSPMOD:	$SAVE	<T1,T2,T3,T4>		;SAVE SOME ACS
	MOVE	T1,J$DMOD(J)		;GET THE MODE
	IMULI	T1,3			;3 BITS/MODE
	DMOVE	T2,0(S1)		;GET THE MODE TABLE
	LSHC	T2,(T1)			;GET THE CORRECT BYTE ON TOP
	LDB	T2,[POINT 3,T2,2]	;AND PICK IT UP
	JUMPE	T2,BADMOD		;LOSE BIG
	ADD	S2,T2			;ELSE ADD IT IN
	JRST	@-1(S2)			;AND DISPATCH
>  ;End of IFE CSM07$

BADMOD:	MOVEI	S1,[ITEXT (<Illegal file mode ^O/T2/>)]
	PJRST	PUTERR			;AND FORCE IT OUT
LITS:	XLIST	;[CSM] Literals
	LIT	;[CSM]
	LIST	;[CSM]

SPOEND::END	SPROUT