	.TITLE RUNOFF
	.IDENT	/BL6.2/
;
;
; AUTHOR: L. WADE 1-JUN-72
;
; MODIFIED BY:
;
;	E. POLLACK U. OF W. 19-DEC-73
;
;	D. N. CUTLER 27-JUL-75
;
;
;	BONNER LAB MODIFACATIONS
;		ADDED OPTIONAL ESCAPE SEQUENCE HANDLING
;		Substitution flags, Layout, Most DSR commands
;		Table driven parsing, Rewrote most sections!!!!
;
;				J. CLEMENT 	November 1982
;
; THIS PROGRAM WAS TRANSLATED FROM THE PDP-10 VERSION OF RUNOFF
; AUTHORED BY B. CLEMENTS.

;	NOTES ON REGISTER USAGE
;		R0 IS COMPLETELY VOLATILE
;		R1-R3	SUBROUTINE PARAMETER PASSING
;			R1	IS CURRENT CHARACTER
;			R2	IS SPACE/LINE COUNT
;			R3	IS USED AS BUFFER HEADER ADDRESS
;		R4	SUBROUTINE ADDRESS FOR COMMAND EXECUTION
;				J. CLEMENT	AUG 82
;
;	LOCAL MACROS
;
;
;	Initial switch setting tables
;
	.psect	DSPTCH,OVR,GBL,RO,D
	.PSECT	$CONST,LCL,RO,D,CON
RMTAB:	.BYTE	'I,'V,'X,'L,'C,'D,'M,' 	; Roman numeral table
.even
INI$SW::.WORD	CRSW!HYPSW!FFDSW; Initial value for $SWTCH
IUL::	.ifdf	rt11
	.rad50	/L/
	.iff
	.WORD	'L		; Initial underline switch
	.endc
	.PSECT	$VARS,LCL,RW,D,CON
SPSAV::	.WORD	0		; Saves initial stack pointer
;
;	UP/DOWN escape sequences
;
UPTAB::	.BYTE	ESC,ES.NUL	; Multiple escape processing
UPMOV::	.BLKB	CH.HD1+1	; Move text up 1/2 space
DNTAB::	.BYTE	ESC,ES.NUL	; Multiple escape processing
DNMOV::	.BLKB	CH.HD1+1	; Move text down 1/2 space
VARESC::.BLKB	2*CH.HD1+1	; Holds variable spacing string
$OUTSW::.BLKB	1		; Zero if output enabled
	.EVEN
$SWTCH::.BLKW	1		; Input switch
;
;	General input switches and variables
;
STSIZE=6			; Number of status words saved
VARBEG::			; This marks first variable
USTAT::	.BLKW	STSIZE		; User status block
HDSTAT::.BLKW	STSIZE		; header status block
CHSTAT::.BLKW	STSIZE		; chapter status block
APSTAT::.BLKW	STSIZE		; Appendix status block
LVSTAT::.BLKW	STSIZE		; level status block
ULSWT::	.BLKW	1		; Underline stat
RIGSHI::.BLKW	1		; Right shift for text
$IFSTK::.BLKB	1		; Number of nested ifs
$IFUSW::.BLKB	1		; If unconditional switch
$HDSTS::.BLKB	1		; Auto header status (0=enabled)
$DEBSW::.BLKB	1		; Debug switch	
$HDRSW::.BLKB	1		; DISABLE PAGE HEADER (0=NO)
$PAGNG::.blkb	1		; Non zero if no paging
$FIRPG::.BLKB	1		; Non zero if first page of document
$PAGPD::.BLKB	1		; Page pending
$PAGBR::.BLKB	1		; 0=AT TOP OF PAGE
$ULMSW::.BLKB	1		; UNDERLINE MODE (-1=Line,0=BS,1=simulate)
$FOTPD::.BLKB	1		; FOOTNOTE PENDING (0=NO)
$PFOOT::.BLKB	1		; Permanent footnote in progress
$ULOSW::.BLKB	1		; UNDERLINE OUTPUT? (0=NO)
$ULCH::.BYTE	'_		; UNDERLINE CHARACTER
$SEPR::	.BYTE	'-		; separator character
CSMOR::.BLKB	1		; Non zero if more input files pending
EOFSW::.BLKB	1		; NON ZERO IS END OF FILE
$GCEND::.BLKB	1		; Non zero for immediate input stop
$AUTTL::.BLKB	1		; Autotitle active (0=yes)
$AUSTL::.BLKB	1		; Autosubtitle (0=NO)
$LAYOU:	.BLKB	1		; Layout value
NXLAY::	.BLKB	1		; Next layout parameter
PRLAY::	.BLKB	1		; Permanent layout parameter
CHLAY::	.BLKB	1		; Chapter layout parameter
$ELIPS::.BLKB	1		; Non zero enables ellipses
$TABLF::.BLKB	1		; 0=Left justify tabs , Non=Right justify
$TOCBE::.BLKB	1		; Non zero if TOC Begun
$SEQSW::.BLKB	1		; Separated equation mode on (0=no)
$NOSPC::.BLKB	1		; If non zero converts spaces to NXS
$HSPSW::.BLKB	1		; If zero enables half spacing
$KEEPL::.BLKB	1		; Keep blank filled lines
$KEEPT::.BLKB	1		; Keep leading tabs
RETSW::	.BLKB	1		; Non zero return from GCIN on #=|sp tab
$VARSP::.BLKB	1		; Non zero if variable spacing active
$UNLRS::.BLKB	1		; Non zero if must reset underline buffer
$NUMSW::.BLKB	1		; NUMBER PAGES (0=yes)
$ODPAG::.BLKB	1		; Produce odd numbered pages
$SETPG::.BLKB	1		; Page has been set
$SBPSW::.BLKB	1		; SUBPAGE MODE ACTIVE (0=NO)
HYPOP::	.BLKB	1		; Hyphenation option
$COLMN::.BLKB	1		; Number of columns
$COLCT::.BLKB	1		; Column count
	.EVEN
$COLMR::.BLKW	1		; Column margin
HYPLO::	.BLKW	1		; Chars in front of autohyphenation
HYPHI::	.BLKW	1		; Chars in back
HYPSZ::	.BLKW	1		; -Minimum size word for hyphenation
;
;	SWITCH PARAMS
;
LOWPAG::.BLKW	1		; Lowest page number to print
HGHPAG::.BLKW	1		; Highest page number to print
LOWCHP::.BLKW	1		; lowest chapter to print
HGHCHP::.BLKW	1		; highest chapter to print
LOWAPN::.BLKW	1		; lowest appendix to print
HGHAPN::.BLKW	1		; highest appendix to print
CHPMG::	.BLKB	CH.HD1+1	; Chapter header text
CHPM2::	.BLKB	CH.HD2+1	; Appendix trailing text
APNMG::	.BLKB	CH.HD1+1	; Appendix header text
APNM2::	.BLKB	CH.HD2+1	; Appendix trailing text
PAGHD::	.BLKB	CH.HD1+1	; Page number text prototype
PAGH2::	.BLKB	CH.HD2+1	; Second page header prototype
TTLHD1::.BLKB	CH.HD1+1	; Title headers
TTLHD2::.BLKB	CH.HD2+1	; Title headers
STLHD1::.BLKB	CH.HD1+1	; Subtitle headers
STLHD2::.BLKB	CH.HD2+1	; Subtitle headers
LVHD1A::.BLKB	CH.HD1+1	; Header level 1
LVHD1B::.BLKB	CH.HD2+1	; Header level 1
LVHD2A::.BLKB	CH.HD1+1	; Header level 2
LVHD2B::.BLKB	CH.HD2+1	; Header level 2
LVHD3A::.BLKB	CH.HD1+1	; Header level 3
LVHD3B::.BLKB	CH.HD2+1	; Header level 3
LVHD4A::.BLKB	CH.HD1+1	; Header level 4
LVHD4B::.BLKB	CH.HD2+1	; Header level 4
LVHD5A::.BLKB	CH.HD1+1	; Header level 5
LVHD5B::.BLKB	CH.HD2+1	; Header level 5
LVHD6A::.BLKB	CH.HD1+1	; Header level 6
LVHD6B::.BLKB	CH.HD2+1	; Header level 6
	.EVEN
LPPG::	.BLKW	1		; Hardware lines per page
;
; SWITCH FLAGS (WORD)
;
TJFSW:	.BLKW	1		; TEMPORARY JUSTIFY FLAG (0=NO)
;
;	FLAG WORDS
;
;	BYTE 0=	The character to test (flag character)
;	BYTE 1= 0	Flag enabled
;		200	Disabled by NO FLAG command
;		100	Disabled for literal
;
;		Enable bit saved for SAVE command
;
FLGBEG:
$AFLSW::.WORD	'_		; FLAG ACCEPT (-=NO)
$BRFSW::.WORD	'|+100000	; break flag switch
$CFLSW::.WORD	'<+100000	; FLAG CAPITALIZE ENABLE (-=NO)
$EFLSW::.WORD	100000		; ESCAPE FLAG	
$EQFSW::.WORD	0		; Equation flag switch
$HFLSW::.WORD	'=+100000	; FLAG HYPHENATE (-=NO)
$IFLSW::.WORD	'>+100000	; INDEX FLAG ENABLE (-=NO)
$LFLSW::.WORD	'\		; LOWERCASE SWITCH (-=NO)
$PFLSW::.WORD	100000		; Period flag
$OFLSW::.WORD	'%+100000	; OVERSTRIKE FLAG ENABLE (-=NO)
$QFLSW::.WORD	'#		; QUOTED SPACE SWITCH (-=NO)
$SBFSW::.WORD	'$+100000	; substitute flag switch
$SFLSW::.WORD	'^		; UPPERCASE SHIFT SWITCH (-=NO)
$SIFSW::.WORD	'>+100000	; Subindex flag enable
$SPFSW::.WORD	0		; Special flag switch
$TBFSW::.WORD	0		; Tab flag
$UFLSW::.WORD	'&		; UNDERLINE SWITCH (-=NO)
nflags==<.-$AFLSW>/2		; Number of flags
$NFLSW::.WORD	'.		; CONTROL FLAG	
;
;
;	ALL VARIABLES BETWEEN SAVBEG/SAVEND ARE SAVED DURING FOOTNOTING
;
SAVBEG==.
;	DISABLE SWITCHES (0=ENABLED) (200=DISABLED) (100=OFF)(1=OFF FOREVER)
;
;		Switch table saved by SSTAT (only .DIS bits)
;
SWITS:
$AUBRK::.BLKB	1		; Autobreak disabled (0=yes)
$AUHYP::.BLKB	1		; Autohyphenation disabled (0=enabled)
$AUTSW::.BLKB	1		; Autoparagraph active (0=NO,-=autopar,+=table)
$CBRSW::.BLKB	1		; CHANGE BAR SWITCH
$CONT::	.BLKB	1
$ESCSW::.BLKB	1		; ESCAPE SEQUENCES DISABLED
$EQUSW::.BLKB	1		; Equation mode on ? (0=yes)
$HYPSW::.BLKB	1		; Non zero disable hyphenation
$INXSW::.BLKB	1		; INDEXING ENABLED
$OVRSW::.BLKB	1		; OVERSTRIKING DISABLED
$PERSW::.BLKB	1		; Double spaces after punctuation (0=NO)
$SUBSW::.BLKB	1		; substitute disabled flag
$TABSW::.BLKB	1		; NON ZERO DISABLES TABS
$TOCSW::.BLKB	1		; Zero if TOC enabled
$UNLSW::.BLKB	1		; UNDERLINING OFF
NSWITS=.-SWITS			; Number of switches
;
;	Not saved in status
;
$UNLLN::.BLKB	1		; Counts underlines pending
$TABPD::.BLKB	1		; Right justified tab pending
$CENSW::.BLKB	1		; NON ZERO = CENTER TEXT
$RIGSW::.BLKB	1		; Non zero = right justify text
HYPCT:	.BLKB	1		; Counts hyphenated lines	
	.EVEN
HYPSV::	.BLKW	1		; Potential savings by hyphenation
;		(Set by VARSET)
CASE::	.BLKB	1		; -=LOWER CASE ONLY, +=UPPER CASE ONLY	; ***
ULOCK::	.BLKB	1		; Saves permanent case lock
TTLCAS::.BLKW	1		; Title case
STLCAS::.BLKW	1		; Subtitle case
;
;	The following 3 variables are saved by permanent footnotes
;
PFSBEG::
F.1::	.BLKW	1		; Flag word
NSPNG::	.BLKW	1		; SPACING BETWEEN LINES
LMARG::	.BLKW	1		; CURRENT LEFT MARGIN
RMARG::	.BLKW	1		; CURRENT RIGHT MARGIN
PFSEND:				; End of permanent footnote save
PFSIZ==PFSEND-PFSBEG		; Number of bytes to save
CMARG::	.BLKW	1		; MARGIN FOR CENTERING TEXT
;
;	Variables saved by VARSAV and set by VARSET
;
LCH::	.BLKB	1		; LAST CHAR
LSCH::	.BLKB	1		; Last char before space (break)
	.even
BRCNT::	.BLKW	1		; number of breaks this line
CASSAV::.BLKW	1		; SAVE CASE AT LAST SPACE
ESCCNT::.BLKW	1		; COUNTS ESCAPE SEQUENCES
LESMSK::.BLKW	1		; Last escape stack
LINBK::	.BLKW	1		; Line break count (+ no break)
LSPCH::	.BLKW	1		; Number of spacing chars before last space
LTAB::	.BLKW	1		; Address of last tab output count
LUNLSW::.BLKW	1		; Underline switch at last space
OVRCT::	.BLKW	1		; COUNTS BACKSPACE ABORTS
SPCH::	.BLKW	1		; Number of spacing characters
SPCNSV::.BLKW	1		; Same before last space
SPCNT::	.BLKW	1		; Expandable space count
;
;	Saved by VARSAV
;
HYPSP::	.BLKW	1		; Spacing chars at last hyphen
PHSP::	.BLKW	1		; Permanent horizontal spacing
LPHSP::	.BLKW	1		; Last permanent horizontal spacing
LSTSP::	.BLKW	1		; Address of char before last space in output
INDCT::	.BLKW	1		; CURRENT INDENTATION
EBSIZ1::.BLKW	1		; Change bar initital indentation
EBSIZ2::.BLKW	1		; Change bar second indentation
ESMSK::	.BLKW	1		; Address of current location in escape stack
CURVS::	.BLKW	1		; Current vertical spacing
MAXVS::	.BLKW	1		; Max vertical spacing
MINVS::	.BLKW	1		; Min vertical spacing
SAVEND=.
SAVSZ==SAVEND-SAVBEG		; SIZE OF FOOTNOTE SAVE BUFFER
; 
; 	MISC SWITCHES
; 
TESMSK::.BLKW	1		; Temporary escape mask
$PAGSW::.BLKW	1		; OUTPUT 'PAGE' SWITCH (0=YES)
$CHPSW::.BLKW	1		; output chapter (0 = yes)
; 
;	INPUT ADDRESS POINTERS
; 
ERSTR::	.BLKW	1		; SAVES ADDRESS OF STRING
LNINS::	.BLKW	1		; ADDRESS OF LAST CHAR IN LINE
LSPIN::	.BLKW	8.		; ADDRESSES OF LAST INPUT SPACE
LSSTK::	.BLKW	1		; last input stack value
;
;	Page format variables
;
$NTITL::.BLKW	1		; non zero prevents title in header
TMARG::	.BLKW	1		; CURRENT TOP MARGIN
HSPAC::	.BLKW	1		; CURRENT HEADER SPACING
PRMRG::	.BLKW	1		; PERMANENT RIGHT MARGIN
PLMRG::	.BLKW	1		; PERMANENT LEFT MARGIN
PTMRG::	.BLKW	1		; PERMANENT TOP MARGIN
PSPNG::	.BLKW	1		; Permanent spacing
PHSPOU::.BLKW	1		; Permanent output horizontal spacing
EQSPC::	.BLKW	1		; Equation spacing
$EOPSP::.BLKW	1		; Current End of page spacing
NXEPSP::.BLKW	1		; Next End of page spacing
PREPSP::.BLKW	1		; Permanent End of page spacing
CHEPSP::.BLKW	1		; Chapter End of page spacing
APNDSP::.BLKW	1		; appendix display format
CHPDSP::.BLKB	1		; chapter display format
	.blkb	LEVSIZ+1	; Level display formats
	.even
PAGDSP::.BLKW	1		; page number display format
SUBDSP::.BLKW	1		; subpage display format (letter)
PAGNX::	.BLKW	1		; next page number
SUBNX::	.BLKW	1		; next subpage
APNNX::	.BLKW	1		; next appendix number
CHPNX::	.BLKW	1		; next chapter number
PAGENO::.BLKW	1		; CURRENT PAGE NUMBER
SUBPGE::.BLKW	1		; current subpage number
APNDN::	.BLKW	1		; Current appendix number(must be before CHPTN)
CHPTN::	.BLKB	1		; Current chapter number
	.BLKB	LEVSIZ+1	; Number of header levels + 1
CHSK1::	.BLKB	1		; Skip count 1
CHSK2::	.BLKB	1		; Skip count 2
CHSK3::	.BLKB	1		; Skip count 3
CHSP1::	.BLKB	1		; Spacing count 1
CHSP2::	.BLKB	1		; Spacing count 2
CHSP3::	.BLKB	1		; Spacing count 3
LEVEL::	.BYTE	1		; Current level number
LINLV::	.BYTE	3		; Lowest level with text-title run on
CAPLV::	.BYTE	1		; Highest all caps level
MIXLV::	.BYTE	6		; Highest level with first letter in caps
NONLV::	.BYTE	7		; Level - lowest without header number
CENLV::	.BYTE	7		; Level - lowest centered title
BEGLV::	.BYTE	2		; Level begin spacing
ENDLV::	.BYTE	1		; Level end spacing
TPGLV::	.BYTE	8.		; Level test page
SPCLV::	.BYTE	2		; Spaces between number and title
UNILV::	.BLKB	1		; Unitary level number
STLLV::	.BLKB	1		; Autosubtitle level number
OUTLV::	.BLKB	1		; Levels enabled (0-6)
TOCLV::	.BLKB	1		; Levels enabled for TOC
LIDLV::	.BLKB	1		; Left level indent
RIDLV::	.BLKB	1		; Level indentation
TIDLV::	.BLKB	LEVSIZ		; Title indentation
	.even
PARIND::.BLKW	1		; Paragraph indentation
PARSP::	.BLKW	1		; Paragraph spacing count
PARPT::	.BLKW	1		; Paragraph page test count
PARTT2::.BLKW	1		; Paragraph post test count
PARDFO:	.BLKW	1		; Paragraph deferred output
PARDFT:	.BLKW	1		; Paragraph deferred top spacing
PARDFB:	.BLKW	1		; Paragraph deferred bottom spacing
PARDFH:	.BLKW	1		; Paragraph deferred hyphenation
;	LINEC1&2 count lines as output, 3 when formatted
LINEC1::.BLKW	1		; Number of lines left to bottom active page
LINEC2::.BLKW	1		; Number of lines left (physical page)
LINEC3::.BLKW	1		; Number of free lines (counts saved data)
FOTLN::	.BLKW	1		; Number of lines permanent footnote
LN3SAV::.BLKW	1		; Saves old LINEC3 during text deferred
TXDHED::.BLKW	1		; Saves current text deferred header
PFOTHD::.BLKW	1		; Permanent footnote header
CMADR::	.BLKW	5		; Next expected command addresses
LITSV::	.BLKW	1		; SAVED FLAGS MASK ON LITERAL PROCESSING
LSTKP::	.BLKW	1		; CURRENT LIST STACK POINTER
LSTK::	.BLKB	<LISSIZ>*LS.SIZ	; LIST STACK (5 lists by SIZ saved bytes)
TKPEND::.BLKB	LS.SIZ		; End of list stack
	.even
NOTLM::	.BLKW	1		; NOTE SAVED LEFT MARGIN
NOTRM::	.BLKW	1		; NOTE SAVED RIGHT MARGIN
NOTSV::	.BLKW	1		; SAVED FLAG WORD ON NOTE PROCESSING
EXSTAT::.BLKB	1		; I/O status
EXLINE:	.BLKB	1		; Post line count
EXSP1::	.BLKB	1		; REAL SPACES/EXPANDABLE SPACE
EXSP2::	.BLKB	1		; COUNT TO NEXT EXTRA SPACE
EXSP3::	.BLKB	1		; -1=EXTRA SPACES TO LEFT  0=TO RIGHT
EXSP4:	.BLKB	1		; Permanent EXSP3
EXMSP::	.BLKB	1		; Extra micro spaces
	.even
CPOS::	.BLKW	1		; CURRENT CHAR POSITION (set by VARSET)
EQBOT::	.BLKW	1		; Vertical size of equation denominator
EQTOP::	.BLKW	1		; Vertical size of equation numerator
EQSTK::	.BLKW	62.		; Equation stack
EQSEN::				; End of equation stack

FOTSV::	.BLKB	SAVSZ		; FOOTNOTE SAVE PARAM TABLE
PFTSV::	.blkb	PFSIZ		; Permanent footnote save table
	.EVEN

ESCTAB::.BLKB	18.		; Saves locked escape sequences
	.even

NLPG::	.BLKW	1		; MAX LINES THIS PAGE
PNLPG::	.BLKW	1		; Permanent max lines/page
VAREND::.BLKW	1		; end of variables
NBASE:	.BLKW	1		; Base of numeric conversion 
	.psect	TEXT,RO,D,LCL,CON
ONPGTX: .ASCIZ	/ file: /
ONLNTX: .ASCIZ	/On input line /
JUSRM1:	.ASCIZ	/RNO -- Can't justify line/
EQERTX: .ASCIZ	/RNO -- Missing right braces (}) in equation/
TXDERR:	.ASCIZ	/RNO -- Deferred page overflow/
	.even
	.PSECT	$CODE,RO,I,LCL,CON
;
;	INPUT LINE
;
LINUC::	CALL	SHFUC		; Get input in Uppercase
LIN::	CALL	OUTAD		; GET OUTPUT BUFFER ADDRESS
	CALL	LINBEG		; Begin line if necessary
	CALL	GCIN		; Get input text
	CMPNEB	R1,#LF,5$	; NOT LINE FEED
	RETURN
5$:	TSTNE	BRCNT,7$	; NO SPACES TO ALLOW HYPHENATION
	JMP	70$		; Output
7$:	CMPEQB	LCH,#SPC,60$	; Last char space?
	TST	LINBK		; Line <= max length?
	BGE	70$		; yes, keep it intact
	TSTNEB	$HYPSW,60$	; No hyphenation ?
	CMPB	HYPCT,#2	; Check previous hyphenation count
	BGE	60$		; Prevent 3 in a row
;	Inhibit hyphenation at bottom of page
	MOV	LINEC3,R2	; Check if at bottom of page
	SUB	NSPNG,R2	; Number of lines to test
	SUB	EQBOT,R2
	SUB	EQTOP,R2
	BLT	12$		; Past the bottom ?
	SUB	NSPNG,R2
	SUB	PARDFH,R2	; Add deferred lines
	BLT	60$		; Current line at bottom of current ?
12$:				; Allow hyphenation
;	**********************************************************
	.ifDF	H$$PHN		; Autohyphenation ????
	TSTNEB	$AUHYP,50$	; No autohyphenation ?
	MOV	LNINS,R1	; Char count at last char on line
	SUB	LSPCH,R1	; Subtract char at last break
	MOV	R1,LNINS	; Number of chars from end of lin
	CMP	R1,HYPSV	; Check if too few chars
	BLT	60$		; Too few for hyphenation
	MOV	LSTSP,R1	; Address of last space
	CALL	FNDBF		; SET POINTER TO IT
	MOV	#TTBUF,R2	; GET TEMPORARY BUFFER
	CLRB	(R2)+		; Chock beginning
	MOV	#49.,R4		; Maximum number of chars
14$:	CALL	GBYT		; GET CHARACTER
	BCS	17$		; DONE
	BITEQB	#140,R1,14$	; Non printable char?
	BIC	#^C<177>,R1	; clear extra bits
	CMPEQB	GCTABL(R1),#GC.LC,270$ ; lowercase ?
	CMPEQB	GCTABL(R1),#GC.UC,260$ ; uppercase ?
	BITEQB	CHTABL(R1),#CH.PNC,60$ ; Not legal punctuation ?
	BR	270$		; Save punctuation
260$:	ADD	#40,R1		; make it lowercase
270$:	MOVB	R1,(R2)+	; SAVE CHAR
	SOB	R4,14$		; CONTINUE TILL DONE
17$:	CLRB	(R2)+		; NULL FOR END OF STRING
	MOV	#TTBUF+1,R0	; BUFFER WITH HYPHENATION INFO
	CALL	HYPHEN		; TRY TO HYPHENATE THE WORD
	BEQ	60$		; No hyphenation ?
	MOV	#TTBUF+1,R0
	ADD	LNINS,R0	; POINTS TO END OF WORD
30$:	TSTB	-(R0)		; HYPHENATION?
	BMI	40$		; YES
	BNE	30$		; Not done ?
	BR	60$		; NO HYPHENATION
40$:	SUB	#TTBUF+1,R0	; Now is number of chars to transfer
	BLE	60$		; No hyphenation set up ?	
	BR	55$
	.endc			;
;	***********************************************
50$:	TSTEQ	HYPSP,60$	; No hyphenation
	CLR	R0		; No movement
55$:	MOV	R0,HYPSP	; NUMBER OF CHAR TO TRANSFER
	CALL	BKUP		; BACKUP TO LAST SPACE
	MOV	LINBK,-(SP)	; Save chars left in line
	MOV	HYPSP,LINBK	; Number of char left on line
	BLE	56$		; No transfer ?	
	DECB	$GCEND		; Immediate return on LINBK=0
	CALL	GCSPC		; AT BEGINNING INSERT SPACE
56$:	MOV	(SP)+,LINBK	; Restore
	CLR	HYPSP		; Clear hyphenation count
	CLRB	$GCEND		; Regular return restored
	MOV	#'-,R1		; INSERT HYPHEN
	CALL	PUBYT		; OUTPUT IT
	INC	SPCH		; ONE MORE CHAR
	INCB	HYPCT		; Count this hyphenation
	BR	70$		; hyphenation done
60$:	CALL	BKUP		; BACKUP TO CORRECT LOCATION
	CLRB	HYPCT		; Reset hyphenation count
70$:	CALL	OUTLIN		; OUTPUT LINE,JUSTIFIED IF FLAGS
LINFIL:	BITEQ	#FILLF,F.1,110$	; No fill ?
90$:	CALL	CCIN		; Get a char
	CMPEQB	R1,#SPC,90$	; Space ?
	CMPEQB	R1,#CR,90$	; Carriage return
	TSTNEB	$KEEPT,95$	; Keep leading tabs ?
	CMPEQB	R1,#TAB,90$	; Is char tab ?
95$:	CMPNEB	R1,#LF,100$	; Not line feed
	RETURN			; Kill input line
100$:	CALL	BKSPI		; Backspace 1
110$:	CALL	LINBEG		; BEGIN A NEW LINE
	JMP	LIN		; START NEXT LINE

BKSPI::	MOV	BUFAD,R0	; current input header
	TSTEQ	BF.FUL(R0),10$	; at beginning?
	DEC	BF.FUL(R0)	; Decrement index
	DEC	BF.ADD(R0)	; Previous address
	INC	BF.CNT(R0)	; Increment count
10$:	RETURN
;
;	ROUTINE TO BACKUP OVER LAST SPACE (INPUT + OUTPUT)
;
BKUP::	CALL	LSINRS		; Restore input stack
	CALL	OUTAD		; OUTPUT BUFFER ADDRESS
BKOUT::	TSTEQ	BF.HED(R3),10$	; No header ??
	MOV	LSTSP,R1	; LAST SPACE ADDRESS
	CALL	RSTBF		; GO BACK TO PREVIOUS POINT IN BUFFER
	MOV	SPCH,R1		; Current spacing char
	SUB	LSPCH,R1	; - previous = excess
	ADD	R1,LINBK	; Restore remainder count
	SUB	R1,BF.SPC(R3)	; And buffer char count
	MOV	LSPCH,SPCH	; RESTORE CHAR COUNT
	MOV	LESMSK,ESMSK	; Restore escape stack
	MOVB	LUNLSW,$UNLSW	; Restore underline switch
	MOV	CASSAV,CASE	; RESTORE PREVIOUS CASE
	MOV	SPCNSV,SPCNT	; Restore previous space count
	MOVB	LSCH,LCH	; RESTORE LAST CHAR BEFORE SPACE
	MOV	LPHSP,PHSP	; Restore character spacing
	DEC	BRCNT		; One fewer break
10$:	RETURN
;
;	The .NO SPACE COMMAND
;
NOSPC::	CMPNEB	LCH,#SPC,10$	; Last char space ?
	CALL	OUTAD
	BITNE	#FILLF,F.1,BKOUT	; Fill on ?
10$:	RETURN
;
; ENDCM--END OF COMMAND
;
ENDCM:	CALL	$FRCND		; FORCE TO LOGICAL END OF LINE
	CMPEQ	$NFLSW,R1,LGO	; COMMAND FLAG NEXT CHARACTER?
	CMPEQ	#SEMI,R1,LGO	; MORE TEXT ON LINE?
	CMPEQ	R1,#CR,COMNT	; END OF LINE	
	CMPEQ	R1,#LF,LGO	; FINAL END OF LINE
	CALL	CCIN		; Advance pointer for extra char.
	MOV	#27.,R0		; Error message
	CALL	ILMSG
KILCM::	CALL	CCIN		; FORCE TO LOGICAL END OF LINE
	CMPEQ	$NFLSW,R1,10$	; COMMAND FLAG NEXT CHARACTER?
	CMPEQ	#SEMI,R1,LGO	; MORE TEXT ON LINE?
	CMPEQ	R1,#CR,COMNT	; END OF LINE	
	CMPEQ	R1,#LF,LGO	; FINAL END OF LINE
	BR	KILCM
10$:	CALL	BKSPI		; Backspace over this char
	BR	LGO		; Process next command
;
; END OF LINE PROCESSING
;
COMNT::				; Process comment lime
LCR::	CALL	CCIN		; Get next char
	CMPNEB	R1,#LF,COMNT	; Continue till end of line

;
;	READ AND PROCESS NEXT LINE
;
LGO::	MOV	SPSAV,SP	; RELOAD STACK POINTER
	CALL	CCIN		; READ INITIAL CHARACTER ON LINE
	MOV	BUFADD,R0	; INPUT BUFFER
	MOV	BF.ADD(R0),ERSTR ; SAVE FOR ERROR OUTPUT
	TSTEQB	EOFSW,20$	; NOT END OF FILE?
	TSTNEB	CSMOR,15$	; Another input file pending ?
	CALL	OUTNJ		; End current line
	BIC	#FOTF,F.1	; Kill any footnotes
	CALL	OUTNJ		; End current line
	CALL	TXDMP		; Dump out all text
10$:	MOVB	#-1,$HDRSW	; SET NO HEADER
	CLR	TMARG		; No top margin
	CALL	PAGEC		; FORCE A PAGE
15$:	JMP	ENDFIL		; END OF FILE
20$:	CMPEQB	R1,#LF,LGO	; FORMFEED ON INPUT?
	CMPEQ	$NFLSW,R1,COMAN	; LEADING PERIOD?
	BITNE	#IFFLG,F.1,COMNT; If flag on ??
	BITNE	#LITFG,F.1,TEXT	; PROCESSING LITERAL?
	BITEQ	#FILLF,F.1,60$	; NOT FILLING FROM INPUT FILE?
	TSTEQB	$AUTSW,TEXT	; AUTOPARAGRAPH NOT ACTIVE?
	CMPEQ	#CR,R1,40$	; NULL LINE?
	CMPEQ	#TAB,R1,30$	; LEADING TAB?
	CMPEQ	#SPC,R1,30$	; Leading space ?
	TSTB	$AUTSW		; Check type
	BGT	55$		; Autotable ?
	BR	TEXT		; Normal line
30$:	CALL	CCIN		; READ NEXT CHARACTER
35$:	CMPEQ	#SPC,R1,30$	; SPACE?
	CMPEQ	#TAB,R1,30$	; TAB?
	CMPNE	#CR,R1,50$	; NOT CARRIAGE RETURN?
40$:	CALL	CCIN		; BYPASS LINE FEED
	CALL	CCIN		; READ NEXT CHARACTER
	CMPEQ	$NFLSW,R1,COMAN	; LEADING PERIOD?
	MOV	BUFADD,R0	; INPUT BUFFER HEADER
	MOV	BF.ADD(R0),ERSTR ; SAVE FOR ERROR OUTPUT
	BR	35$		; Now kill spaces
50$:	TSTB	$AUTSW		; Check type
	BGT	TEXT		; Autotable ?
55$:	CALL	OUTNJ		; BREAK CURRENT LINE
	CALL	PARTP		; PERFORM PARAGRAPH BREAK
	CALL	LINBEG		; RESET LINE PARAMETERS
	BR	TEXT		; PROCESS TEXT
60$:	TSTNEB	$KEEPL,TEXT	; Keep blank lines ?
	CMPEQ	#CR,R1,COMNT	; NULL LINE?
TEXT::	CALL	BKSPI		; BACKSPACE THE INPUT
	CALL	LSINSV		; Save address of last space
TEXTF:: CALL	LINFIL		; Start input
	CALL	OUTAD		; GET OUTPUT BUFFER
	TSTNEB	$CENSW,10$	; Centered text?
	TSTNEB	$RIGSW,10$	; Right justified text?
	BITNE	#FILLF,F.1,LGO	; Filling from input file?
10$:	CALL	OUTNBJ		; Output either not just, cent, or right just.
	BR	LGO		; End of input line
COMAN:	CALL	CMN		; PARSE COMMAND
	MOV	#ENDCM,-(SP)	; ASSUME NONBREAK COMMAND
	MOV	(R3),-(SP)	; SET ADDRESS OF COMMAND ROUTINE
	MOVB	(R2),-(SP)	; GET FLAG BYTE
	BITEQB	#BRKF,(SP),100$	; NOT BREAK COMMAND?
	CALL	OUTNJ		; BREAK CURRENT LINE
100$:	MOV	#RCNO,R4	; SET ADDRESS OF NUMBER CONVERSION ROUTINE
	BITEQB	#RELF,(SP)+,120$ ;ABSOLUTE CONVERSION REQUIRED?
	MOV	#RCNR,R4	; SET ADDRESS OF RELATIVE CONVERSION ROUTINE
120$:	JMP	@(SP)+		; DISPATCH TO COMMAND ROUTINE

;
;	ERROR OUTPUT
;	HLTER - Fatal internal error
;	ILINP - Fatal error (r0 = error number) no return to caller
;	ILCMA - Error during 2'nd pass (r0 = error number) no return
;	ILCMB - Error during either pass (r0 = error number) no return
;	ILCMC - Error second pass (R0 = message address ) with return to caller
;
HLTER::	MOV	#9.,R0		; Error message
ILINP::	CALL	ERMSG		; Output error message
	CALL	ONLIN		; Output line number
	.ifdf	$PASS
	BICB	#SW.DIS,$OUTSW
	.endc
	JMP	RUNOFF		; And begin again
ILCMB::	MOV	#KILCM,(SP)	; Finish up by finding next command
	BR	ILCMM
ILCM::	MOV	#4,R0		; Illegal command message
ILCMA::	MOV	#KILCM,(SP)	; Finish up by finding next command
	BR	ILMSG		; After printing line and page number
ILTXT:	MOV	#COMNT,(SP)	; FINISH UP SECTION
ILMSG:	.ifdf	$PASS
	BITNEB	#SW.DIS,$OUTSW,ERRRET	; First pass ?
	.endc
ILCMM:	CALL	ERMSG		; Output error message unconditional
;
;	Here we generate traceback through the substitutions
;
ONLIN::	MOVB	SUBSTK,R4	; Get substitute stack
20$:	TSTEQB	R4,70$		; No substitutions
	MOV	BUFADD(R4),R2	; Now have substitute header
	SUB	#2,R4		; Next subs.
	CALL	GETTBF		; Get temporary buffer into R3
	MOV	BF.FUL(R3),-(SP); Current index
	MOV	BF.SPC(R3),R1	; Start of substitution
	CALL	FNDBF
	MOV	#TTBUF,R2	; Temporary output buffer
30$:	CALL	GBYT		; Get 1 byte
	BITEQ	#170,R1,40$	; Valid char ?
	CMP	BF.FUL(R3),(SP)	; Check if at end
	BHI	60$		; Done ?
	MOVB	R1,(R2)+	; Move it
	BR	30$		; Continue till whole label trans.
40$:	MOVB	#':,(R2)+	; And colon
	TSTNE	R1,60$		; Not zero terminator
50$:	CALL	GBYT		; And next substitute
	BLOS	60$		; Done ?
	CMP	BF.FUL(R3),(SP)	; Check if at end
	BHI	60$		; Done ?
	MOVB	R1,(R2)+	; Save char
	CMP	R2,#TTBUF+79.	; Too much ?
	BLO	50$		; No ?
60$:	TST	(SP)+		; Pop saved address
	MOV	#TTBUF,R1	; Address to output
	SUB	R1,R2
	CALL	TTOUT		; Output traceback
	BR	20$
;
;	Print input line
;
70$:	MOV	BUFADD,R3	; GET CURRENT BUFF ADDRESS
	MOV	ERSTR,R1	; POINTS TO BUFFER
	BEQ	81$
	MOV	BF.ADD(R3),R2	; CURRENT CHAR ADDRESS
	SUB	R1,R2		; NUMBER OF BYTES
	BLT	81$
	INC	R2
	CMP	R2,#79.		; OK?
	BLE	80$		; YES
	MOV	#79.,R2		; YES		
80$:	CALL	TTOUT		; PRINT OFFENDING LINE
81$:	CALL	TTINOU		; Type whole line for ident.
;
;	Tracback through the input files
;
ONPAG:	BISB	#20,$UNLSW	; No underlining
	MOV	TRCBUF,-(SP)	; Traceback begin
1$:	TSTEQ	@(SP),30$	; No traceback ?
	MOV	#TTBF,R3	; BUFFER FOR OUTPUT
	CALL	CLRBF		; CLEAR BUFFER
	MOV	#ONLNTX,R0	; On line text string
	CALL	PSTRZB		; MOVE IT TO BUFFER
	MOV	(SP),R4		; Get line
	MOV	(R4)+,R0	; Input Line number
	CALL	DECTY		; Convert to number
	MOV	#ONPGTX,R0	; ON PAGE STRING
	CALL	PSTRZB		; Into buffer
10$:	MOVB	(R4)+,R1	; Get byte
	BEQ	20$		; Done
	CALL	PBYT
	BR	10$
20$:	MOV	#TTBUF,R1	; BUFFER ADDRESS
	MOV	BF.FUL(R3),R2	; SIZE OF STRING
	CALL	TTOUT		; OUTPUT IT
30$:	SUB	#TRCLN,(SP)	; Next string ?
	CMP	(SP),#TRCBUF	; At end ?
	BHI	1$		; No
	BICB	#20,$UNLSW	; underlining
	TST	(SP)+
ERRRET:	RETURN
ILCMC::	.ifdf	$PASS
	BITNEB	#SW.DIS,$OUTSW,ERRRET	; First pass ?
	.endc
	CALL	EROUT		; Output message
	BR	ONLIN		; INDICATE WHAT PAGE


;
;	Put converted page number into buffer
;
PUTPAG:: CLR	-(SP)		; stop for conversion routine
	MOVB	#'-,$SEPR	; specify separator character
	TSTNEB	$CHPSW,20$	; no chapter print?
	MOV	APNDN,R1	; GET CURRENT APPENDIX LEVEL
	BEQ	10$		; IF EQ NONE
	BIS	APNDSP,R1	; set display format
	MOV	R1,-(SP)	; Save for conversion
	BR	20$		; 
10$:	MOVB	CHPTN,R1	; GET CURRENT CHAPTER NUMBER
	BIC	#^C<377>,R1	; Clear extra
	BEQ	20$		; IF EQ NONE
	BIS	CHPDSP,R1	; set display format
	MOV	R1,-(SP)	; Save for conversion
20$:	MOV	PAGENO,R1
	BIS	PAGDSP,R1	; set display format
	MOV	R1,-(SP)	; Save for conversion
	TSTEQB	$SBPSW,40$	; NO SUBPAGE?	
	MOV	SUBPGE,R1	; SUB PAGE NUMBER
	BEQ	40$		; none
	BIS	SUBDSP,R1	; set format
	MOV	R1,-(SP)	; Save for conversion
40$:	CALL	PAGCV		; convert numbers
	RETURN			; 

;
;	CONVERTS PAGENUMBERS on stack terminated by null
;		R3 = buffer header to recieve the final string
;		Format	NUMBER
;			+100000 = Letters (upper case)
;			+120000 = Letters (lower case)
;			+140000	= Roman numeral (upper case)
;			+160000 = Roman (lower case)
;			+010000 = (upper  case first letter)
;	Roman numerals go from 0-2047
;
;		- sign appears after letters, before numbers.
;		ex.  10-5  A-10  10A  A-10B
;	R2-R5	are preserved
;
PAGCV::	MOV	(SP),R0		; save stack
	MOV	SP,R1		; To find base entry
	CLR	(R1)+		; clear old return address
	MOV	R2,-(SP)	; Save R2
	MOV	R4,-(SP)	; And R4
	MOV	R0,-(SP)	; And return address
1$:	TST	(R1)+		; base entry?
	BNE	1$		; not yet
;		now reverse stack between R1,R2
	MOV	SP,R2		; current stack pointer
2$:	MOV	(R2),R0		; save lower entry
	MOV	-(R1),(R2)+	; move upper to lower
	MOV	R0,(R1)		; move lower to upper
	CMP	R2,R1		; not done?
	BLO	2$		; yes
	TST	(SP)+		; unstack extra entry
3$:	MOV	(SP)+,R0	; number?
	BNE	10$		; YES
5$:	MOV	(SP)+,R2	; Restore
	MOV	(SP)+,R4	; Restore
	RETURN
10$:	MOV	R0,R4		; save status
	BIC	#170000,R0	; Clear extra bits
	BITNE	#100000,R4,20$	; Is it letter or Roman ?
	CALL	DECTY		; convert number
	BR	50$		; next!
20$:	BITNE	#40000,R4,70$	; Roman?
	CLR	-(SP)
30$:	DEC	R0		; yes, decrement it
	.if df	$EIS
	MOV	R0,R1		; Dividend
	CLR	R0
	DIV	#26.,R0		; Divide (R0=quotient)
	.iff
	MOV	#26.,R1		; Number to divide by
	CALL	$DIV		; get rhand digit
	.endc
	ADD	#'A,R1		; convert to letter
	MOV	R1,-(SP)	; save it
	TSTNE	R0,30$		; more?
	BR	110$		; no, put into buffer
50$:	MOV	(SP)+,R2	; end?
	BEQ	5$		; yes
	BGT	60$		; Number?
	BITNE	#40000,R2,60$	; Roman numeral?
	TST	R4		; last one letter?
	BGT	65$		; no
60$:	MOVB	$SEPR,R1	; output a separator
	CALL	PUBYT
	INC	BF.SPC(R3)	; Count spacing chars
65$:	MOV	R2,R0		; save char
	BR	10$
70$:	CLR	-(SP)		; end of stack table
	MOV	#RMTAB,R2
	BR	85$
80$:	ADD	#2,R2		; Next numeral
85$:	TSTEQ	R0,110$		; done yet?
	.if df	$EIS
	MOV	R0,R1		; Dividend
	CLR	R0
	DIV	#10.,R0		; Divide (R0=quotient)
	.iff
	MOV	#10.,R1		; Divide by 10
	CALL	$DIV		; Divide R0 by R1
	.endc
	TSTEQ	R1,80$		; none this letter?
	CMPEQ	R1,#4,100$	; reversed letters?
	BLT	90$		; Less than 4 ?
	SUB	#5,R1		; Now is less 5
	BEQ	88$
	CMPNE	R1,#4,86$	; reversed letters?
	MOVB	2(R2),-(SP)	; ex. IX
	BR	101$
86$:	MOVB	(R2),-(SP)	; save letters
87$:	SOB	R1,86$		; till done
88$:	MOVB	1(R2),-(SP)	; Save 5 char
	BR	80$
90$:	MOVB	(R2),-(SP)	; save letters
	SOB	R1,90$		; till done
	BR	80$
100$:	MOVB	1(R2),-(SP)	; output next higher letter
101$:	MOVB	(R2),-(SP)	; and current one ex. 4 = IV
	BR	80$
110$:	MOVB	(SP)+,R1	; unstack numerals
	BEQ	50$		; done?
	BITEQ	#20000,R4,120$	; NOT (lower case)?
	BITNE	#10000,R4,120$	; Not (lower case first char)?
	ADD	#40,R1		; make it lower
120$:	CALL	PUBYT		; save in buffer
	INC	BF.SPC(R3)	; Count spacing chars
	BIC	#10000,R4	; set lower? after first byte
	BR	110$
;
;	CONVERTS R0 TO NUMERIC STRING
;		R3=BUFFER HEADER TO PUT STRING
;	R2-R5	are preserved
;
DECTY::	CLR	-(SP)		; SET INDICATOR
10$:	.if df	$EIS
	MOV	R0,R1		; Dividend
	CLR	R0
	DIV	#10.,R0		; Divide (R0=quotient)
	.iff
	MOV	#10.,R1		; SET DIVISOR
	CALL	$DIV		; DIVIDE
	.endc
	ADD	#60,R1
	MOV	R1,-(SP)	; SAVE RH DIGIT	
	TSTNE	R0,10$		; CONTINUE IF NON ZERO
20$:	MOVB	(SP)+,R1	; 1 DIGIT	
	BEQ	30$		; DONE		
	CALL	PUBYT		; PUT INTO BUFFER
	INC	BF.SPC(R3)	; Count spacing chars
	BR	20$		; CONTINUE TILL DONE
30$:	RETURN			; 		
;
;	BEGINS A LINE OR CONTINUES LINE AFTER COMMANDS BY SETTING FLAGS
;		R3 is set to point to output buffer
;		All other registers are destroyed
;
;	LINFAK - Fake begin if line not in existance
;
LINFAK::CALL	OUTAD
	TSTNE	BF.HED(R3),LINBEG; Line already begun ?
	CALL	ENDBF		; Go to end of buffer
	MOV	#BFHED-2,R2	; NUMBER OF TIMES THRU
	CALL	CBYT		; Spacing before
	MOV	#HD.LIN,R1	; Set it up as line
	CALL	PBYT
	CLR	R1
10$:	CALL	PBYT
	SOB	R2,10$
	CALL	VARSET
	BR	LSINSV
	RETURN	
LINBEG::CALL	OUTAD		; GET OUTPUT ADDRESS
	MOV	BF.HED(R3),R1	; HEADER BYTE
	BEQ	20$		; New line ??
	CALL	FNDBF		; get the location
	CALL	GBYT		; get status byte
	TSTNEB	$CBRSW,10$	; NO CHANGE BAR NEEDED?
	BISB	#HD.BAR,R1	; SET CHANGE BAR BIT
10$:	MOVB	R1,@BF.ADD(R3); New status
	JMP	ENDBF		; go to end of buffer
20$:	CALL	VARSET
	CALL	ENDBF
	MOV	BF.FUL(R3),R1	; Start of header
	INC	R1		; Points to header
	MOV	R1,BF.HED(R3)	; LAST HEADER ADDRESS
	MOV	#BFHED-3,R2	; NUMBER OF TIMES THRU
	CALL	CBYT		; Spacing before
	TSTNEB	$CBRSW,30$	; NO CHANGE BAR NEEDED?
	BISB	#HD.BAR,R1	; SET CHANGE BAR BIT
30$:	TSTEQB	$VARSP,40$	; No variable spacing
	BISB	#HD.VAR,R1
40$:	CALL	PBYT		; Status
	MOVB	NSPNG,R1	; Line spacing after
	CALL	PBYT
	CLR	R1		; NULL FOR HEADER
50$:	CALL	PBYT		; DEPOSIT PART OF HEADER
	SOB	R2,50$		; TILL DONE
	MOV	ESMSK,R4	; Escape sequences locked on
	BEQ	60$		; None ?
	CALL	ESCBEG		; Begin them
60$:	MOV	BF.FUL(R3),LSTSP;SET LAST SPACING CHARACTER BACK HERE
	CLR	BF.SPC(R3)
;
;	Save current input stack
;
LSINSV::MOVB	SUBSTK,R1	; input stack
	MOV	R1,LSSTK	; save old value
10$:	MOV	BUFADD(R1),R0	; INPUT BUFFER
	MOV	BF.FUL(R0),LSPIN(R1) ; LAST SPACE ON INPUT
	SUB	#2,R1		; next member
	BGE	10$		; save more
	RETURN
;
;	Set up variables at beginning of line
;
VARSET::MOV	RMARG,R2	; COMPUTE REAL WIDTH OF LINE
	SUB	LMARG,R2	; AS DIFFERENCE OF MARGINS
	SUB	INDCT,R2	; MINUS INDENTING
	MOV	R2,LINBK	; STORE IN LINE-BREAK COUNT
	MOVB	ULOCK,CASE	; Restore permanent case
	MOV	CASE,CASSAV	; SAVE CASE
	CLR	BRCNT		; no breaks yet this line
	CLR	SPCNT		; INITIAL COUNTS OF SPACING
	CLR	SPCNSV
	CLR	SPCH		; AND NON-SPACING CHARS
	CLR	LSPCH
	CLR	ESCCNT		; NO ESCAPES PENDING
	CLR	OVRCT		; NO BACKSPACE ABORTION
	CLR	LCH		; CLEAR LAST CHARACTERs
	CLR	LTAB		; Address of last tab char
	CLRB	$TABPD		; Set no tab pending
	MOV	ESMSK,LESMSK	; Current end of escape stack
	MOVB	$UNLSW,LUNLSW	; Save underline switch
	MOV	#1,CPOS		; CARRIAGE POSITION IS FAR LEFT
	RETURN
;
;	Restore last input stack
;
LSINRS::MOV	R3,-(SP)	; Save regs
	MOV	R4,-(SP)
	MOVB	LSSTK,R4	; stack at last space
	MOVB	R4,SUBSTK	; restore previous substitute stack
	MOV	BUFADD(R4),BUFAD; restore current buffer pointer
10$:	MOV	BUFADD(R4),R3	; CURRENT BUFFER ADDRESS
	MOV	LSPIN(R4),R1	; LAST SPACE ADDRESS
	CALL	FNDBF		; GO BACK TO PREVIOUS POINT IN BUFFER
	SUB	#2,R4		; more in stack?
	BGE	10$		; yes
	MOV	(SP)+,R4	; Restore
	MOV	(SP)+,R3	; Restore
	RETURN
;
;	RESET UNDERLINE BUFFER
;		R0,R1 are destroyed
;
ULBSET::MOV	#UBUFF,R0	; UNDERLIN BUFFER
	MOV	#ULNSZ,R1	; SIZE OF BUFFER
	MOV	#SPC,R2		; Char to transfer
10$:	MOVB	R2,(R0)+	; PUT SPACE INTO IT
	SOB	R1,10$		; TILL FULL
20$:	CLR	ULNMAX
	CLRB	$UNLRS
	MOV	#1,CPOS
	RETURN			; 

;
; INPUTS:
;
;	R3=BASE VALUE TO BE AUGMENTED.
;
; OUTPUTS:
;	If input skip return is taken ( to (SP)+4 )
;	non-skip return if none found ( to (SP) )
;	C set if number prefaced by + or -
;	C clear if no sign
;	N,Z are determined by number
;	V undefined
;
; RCNO--ABSOLUTE DECIMAL INPUT ROUTINE
;	R3=signed decimal number
;	R3=0 if no input
;
;
; RCNR--RELATIVE DECIMAL CONVERSION ROUTINE
;	R3=R3 + input if input prefaced by + or -
;	R3 unchanged If no input
;
RCNO::	CLR	R3		; CLEAR ANSWER AC
RCNR::	CALL	FNDPAR		; skip spaces
	BCS	50$		; null param
	MOV	R3,-(SP)	; Save Old R3
	MOV	R2,-(SP)	; Save
	MOV	R4,-(SP)
	MOV	R5,-(SP)
	CLR	R3		; Now start with clean slate
	CLR	R5		; Count number of chars converted
	CLR	R4		; AND SIGN FLAG
	CMPNE	#'+,R1,10$	; NOT PLUS SIGN?
	INC	R4		; SET PLUS SIGN PRESENT
10$:	CMPNE	R1,#'-,20$	; NOT MINUS SIGN?
	COM	R4		; SET NEGATE FLAG
20$:	TSTEQ	R4,22$		; SIGN NOT SPECIFIED?
21$:	CALL	CCIN		; READ ANOTHER CHARACTER
22$:	CMPNEB	GCTABL(R1),#GC.DIG,23$ ; NOT A DIGIT?
	INC	R5
	ASL	R3		; MULTIPLY BY 10.
	MOV	R3,-(SP)	; 
	ASL	R3		; 
	ASL	R3		; 
	ADD	(SP)+,R3	; 
	SUB	#60,R1		; SUBTRACT OUT CHARACTER BIAS
	ADD	R1,R3		; ADD IN DIGIT
	BR	21$		; AND LOOP FOR MORE.
23$:	TSTNE	R5,24$		; Number?
	CALL	BKSPI		; back over param
	BR	40$		; And signal no input
24$:	CALL	NEXPAR		; SKIP TO NEXT PARAM
	ADD	#4,8.(SP)	; SET SKIP RETURN
	TST	R4		; check sign
	BEQ	30$		; No sign ?
	BGT	27$		; Plus sign ?
	NEG	R3		; NEGATE NUMBER
27$:	ADD	R3,6(SP)	; Relative value
	SEC			; Note signed number
	BR	40$
30$:	MOV	R3,6(SP)	; Absolute value
	CLC
40$:	MOV	(SP)+,R5
	MOV	(SP)+,R4
	MOV	(SP)+,R2
	MOV	(SP)+,R3	; Get current value
50$:	RETURN			; 
;
;	Routine to skip to next param
;
FNDPAR:	CALL	SKPSP		; SKip over tabs/spaces
	BCS	50$		; No params
	CMPNEB	R1,#'%,40$	; No indirect params ?
	MOVB	SUBSTK,R0	; Check stack level
	BEQ	40$		; At lowest level ?
	MOV	(SP)+,R1	; And return address
	MOV	SUBSTK,-(SP)	; Save status
	MOV	BUFAD,-(SP)	; Save
	MOV	#10$,-(SP)	; Return address
	MOV	R1,-(SP)	; Co routine
	SUB	#2,R0		; Next stack entry
	MOVB	R0,SUBSTK	; Save it
	MOV	BUFADD(R0),BUFAD; INPUT BUFFER
	BR	FNDPAR		; Now skip spaces
10$:	JMP	20$
	ADD	#4,+4(SP)	; Null param ??
20$:	MOV	(SP)+,BUFAD	; Restore
	MOV	(SP)+,SUBSTK	; status
	TST	R3
	RETURN
40$:	CLC
50$:	RETURN
SKPSP::	CALL	CCIN		; READ CHARACTER FROM COMMAND LINE
	CMPEQ	R1,#CR,10$	; LEADING CARRIAGE RETURN?
	CMPEQ	$NFLSW,R1,10$	; LEADING CONTROL CHARACTER?
	CMPEQ	#SEMI,R1,10$	; LEADING CHARACTER SEMICOLON?
	CMPEQ	R1,#CMA,20$	; LEADING COMMA?
	CMPEQ	R1,#SPC,SKPSP	; SPACES AND TABS?
	CMPEQ	R1,#TAB,SKPSP	; LEADING TAB?
	CLC			; done, no null params
	RETURN
10$:	CALL	BKSPI		; BACKUP TO SAVE CHAR.
20$:	SEC			; null param
	RETURN
;
;	SKIP OVER SPACE,BLANKS, AND 1 COMMA ONLY
;
NEXPAR:	CMPEQ	R1,#CMA,30$	; COMMA?	
	CMPEQ	R1,#SPC,10$	; SPACE?	
	CMPNE	R1,#TAB,20$	; TAB? (DISCARD ALL TABS + SPACES)
10$:	CALL	CCIN		; NEXT CHAR	
	BR	NEXPAR		; AND WHAT IS IT?
20$:	CALL	BKSPI		; NEXT CHAR FOR NEXT TIME AROUND
30$:	RETURN			; 

;
;	routine to get up to 3 char alphameric string
;	String is in right justified RAD50 format
;		C = SET IF No param
;			R3 is unchanged if null param
;		R3 = Result + Carry clear
;
;
;
ALPGT2::MOV	#26.,NBASE	; Base
	BR	ALPP
ALPGT::	MOV	#50,NBASE
ALPP:	CALL	FNDPAR		; skip leading spaces
	BCS	50$		; null param?
	CLR	-(SP)		; initial number
20$:	CMP	(SP),#3100	; Done ?
	BHIS	40$		; Found 3 letters ?
	CMPB	GCTABL(R1),#GC.LC ; letter?
	BGT	40$		; no
	BNE	30$		; upper case?
	SUB	#40,R1		; convert to upper
30$:	SUB	#'@,R1		; convert letter to number
	MOV	(SP),R0		; previous sum
	MOV	R1,(SP)		; save current char
	.if df	$EIS
	MUL	NBASE,R0	; Mult R1 by R0
	.iff
	MOV	NBASE,R1	; multiplier
	CALL	$MUL		; mult R1 by R0
	.endc
	ADD	R1,(SP)		; new total
	CALL	CCIN		; next
	BR	20$
40$:	CALL	NEXPAR		; set up for next param
	MOV	(SP)+,R3	; get result
	BEQ	50$		; No Input ?
	CLC
	RETURN			; null param
50$:	SEC			; no
	RETURN
;
;
;	SUBROUTINE TO PARSE INPUT FOR LITERAL
;		R2=ADDRESS OF LITERAL	R1=LENGTH OF LITERAL
;		CARRY CLEAR IF SUCCESS	SET IF NONE FOUND
;		Literal is in TTBUF maximum of 80 bytes!
;		Literal is terminated by zero byte
;
GETLIT:: CALL	FNDPAR		; GET next	
	BCS	50$		; BAD, NO FILE SPEC
	CMPEQ	R1,#'',10$	; START OF LITERAL
	CMPNE	R1,#'",40$	; NOT START OFF LITERAL?
10$:	MOVB	R1,-(SP)	; Save initial char
	MOV	#TTBUF,R2	; Buffer for literal
	CALL	LSINSV		; Save this spot
20$:	CALL	CCIN		; NEXT CHAR	
	BCS	50$		; NO MORE	
	CMP	R2,#TTBUF+80.	; Check if at end of buffer
	BLO	25$		; No ?
	MOV	#51.,R0		; Literal too long
	JMP	ILCMA		; Yes kill this command
25$:	CMPNEB	R1,#TAB,26$	; Not tab ?
	MOVB	#SPC,R1		; Make it space
26$:	MOVB	R1,(R2)+	; Now save char
	CMPEQB	R1,(SP),30$	; END OF LITERAL?
	CMPNE	R1,#CR,20$	; not end of buffer?
	CALL	BKSPI		; backspace over carriage return
30$:	CALL	CCIN		; Get next char
	CMPEQB	R1,(SP),20$	; 2'nd delimiter ???
	CLRB	-(R2)		; Now chock end of literal
	MOV	R2,(SP)		; Save end of buffer
	CALL	NEXPAR		; SKIP TO NEXT PARAM
	MOV	(SP)+,R1	; LAST CHAR IN LIT +1 ADDRESS
	MOV	#TTBUF,R2	; Buffer for literal
	SUB	R2,R1		; NUMBER OF BYTES
	CLC			; OK!		
	RETURN
40$:	CALL	BKSPI		; BACKUP 1 CHAR
50$:	SEC			; NOT OK	
	RETURN
;

;
;	$FRCND-FORCE TO LOGICAL END OF COMMAND
;
$FRCND::CALL	CCIN		; READ CHARACTER FROM FILE
	CMPEQ	#SPC,R1,$FRCND	; SPACE?
	CMPEQ	#TAB,R1,$FRCND	; TAB?
	CMPEQ	#SEMI,R1,10$	; SEMICOLON?
	CALL	BKSPI		; BACKSPACE 1 CHAR
10$:	RETURN			; 
;
;	Line output routine. two entry points
;		OUTLIN - No break
;		OUTNJ  - Output with break
;
OUTLIN::BITNE	#FOTF!TEXF,F.1,10$	; Footnote or Text ?
	TSTNEB	$PAGNG,10$	; No paging ?
	MOV	PARDFT,R1	; Get deferred count
	BEQ	10$		; None ??
	ADD	EQTOP,R1
	ADD	EQBOT,R1
	CMP	R1,LINEC3	; Check if deferred text
	BLE	10$		; Not yet
	BIS	#PARF,F.1	; Set deferred lines
10$:	MOVB	#-1,TJFSW	; SET JUSTIFY FLAG
	COMB	EXSP4
	TSTNEB	$CENSW,OUTNJ0	; CENTERED/NOT JUSTIFIED?
	TSTNEB	$RIGSW,OUTNJ0	; Not justify if right justified
	BITNE	#JUSTF,F.1,OUTJ2 ;JUSTIFYING?
	BR	OUTNBJ
OUTNJ::	BIS	#BRKF,F.1	; Set for break
OUTNBJ:	CLRB	HYPCT		; Clear hyphenation count
OUTNJ0:	CLRB	TJFSW		; CLEAR JUSTIFY FLAG
	CLRB	EXSP4		; CLEAR LEFT RIGHT SPACING
OUTJ2:	CLRB	EXSP2
	CLRB	EXSP1
	MOVB	#-1,EXMSP
	CLR	HYPSP		; Reset hyphenation spacing
	CALL	OUTAD		; GET BUFF ADDRESS
	TSTNE	BF.HED(R3),10$	; Line exists ??
	JMP	OUTNJ3		; Do not process output line
10$:	TSTEQ	@EQSTK,40$	; Is equation not being formatted ?
	MOV	#EQERTX,R0	; Error message for equation
	CALL	ILCMC
	MOV	#EQSTK+2,EQSTK	; Reset equation stack
	MOV	#SW.EDS,R0	; Equation disable bits
	BICB	R0,$TABSW	; ALLOW tabs
	BICB	R0,$NOSPC	; expandable spaces
	BICB	R0,$UFLSW+1	; underlining
	BICB	R0,$BRFSW+1	; break flags
	BICB	R0,$AUBRK	; autobreak
	BICB	R0,$HYPSW	; hyphenation
40$:	MOV	ESMSK,R4	; Escapes locked on
	BEQ	50$		; None ?
	CALL	ESCEND		; End the escape sequence
50$:	TSTEQB	TJFSW,OUTNJ1	; NOT JUSTIFYING LINE?
	CLRB	TJFSW		; IN CASE	
	MOV	RMARG,R0	; YES. COMPUTE WHERE TO EXPAND THEM
	SUB	LMARG,R0	; SIZE OF LINE
	SUB	INDCT,R0	; ..
	SUB	SPCH,R0		; SUBTRACT NUMBER OF SPACING CHARS
	BEQ	OUTNJ1		; No justifacation needed ?
	MOV	SPCNT,R1	; NOW FIND HOW MANY MULT SPACES EACH SPACE IS
	BNE	60$		; Spaces present to allow justif. ?
	MOV	#JUSRM1,R0	; Can't justify line message
	CALL	ILCMC		; Output error message
	BR	OUTNJ1		; 
60$:	ADD	R1,R0		; ADD NUMBER OF SPACES
	.if df	$EIS
	MOV	R1,-(SP)	; Save divisor
	MOV	R0,R1		; Dividend
	CLR	R0
	DIV	(SP)+,R0	; Divide (R0=quotient)
	.iff
	CALL	$DIV		; Divide tot spac/SPCNT = R0/R1
	.endc
	MOVB	R0,EXSP1	; MULTIPLIER FOR ALL SPACES
	TSTEQB	$VARSP,70$	; No variable spacing ?
	MOVB	VARESC,R0	; Number of steps per space
	BLE	70$		; Bad value ?
	.if df	$EIS
	MUL	R1,R0		; Mult R1 by R0
	.iff
	CALL	$MUL		; mult R1 by R0
	.endc
	.if df	$EIS
	CLR	R0
	DIV	SPCNT,R0	; Divide SPCNT into R0,R1
	.iff
	MOV	R1,R0		; Into R0
	MOV	SPCNT,R1	; Get number of spaces again
	CALL	$DIV		; DIVIDE
	.endc
	MOVB	R0,EXMSP	; Number of extra micro spaces
70$:	TSTNEB	EXSP4,80$	; EXTRAS TO LEFT?
	NEG	R1		; RIGHT. GET SPACES BEFORE EXTRAS
	ADD	SPCNT,R1	; ..
80$:	MOVB	R1,EXSP2	; STORE FOR LATER
OUTNJ1:	CALL	OUTAD		; GET BUFF ADDRESS
	MOV	BF.HED(R3),R1	; GET LIN HEADER
	DEC	R1		; Points to first byte
	CALL	FNDBF		; Set to point to it
	CALL	GBYT		; Get the line count
	ADD	EQTOP,R1	; Add on top of equation
	TSTNEB	$PAGNG,10$	; No paging ?
	TSTB	$PFOOT		; Permanent footnote in progress ?
	Blt	5$		; YES ?
	SUB	R1,LINEC3	; Account for extra lines
5$:	ADD	R1,BF.VSP(R3)	; And vertical spacing this buffer
10$:	MOVB	R1,@BF.ADD(R3)	; And save it
	CLR	EQTOP		; No more pre spacing
	CALL	GBYT		; Get status byte
	BISB	#HD.LIN,R1	; Set it as output line
	TSTNE	SPCH,12$	; Spacing chars ?
	BICB	#HD.BAR,R1	; No change bar
12$:	MOVB	R1,@BF.ADD(R3)	; Output line
	MOVB	R1,EXSTAT	; Save status
	CALL	GBYT		; Get post line count
	ADD	EQBOT,R1	; Get bottom spacing
	TSTNEB	$PAGNG,20$	; No paging ?
	TSTB	$PFOOT		; Permanent footnote in progress ?
	BLT	15$		; YES ?
	SUB	R1,LINEC3	; Account for extra lines
15$:	ADD	R1,BF.VSP(R3)	; Account for vertical spacing
20$:	MOVB	R1,@BF.ADD(R3)	; Save lines
	CLR	EQBOT		; Clear bottom
	MOV	LMARG,R2	; GET LEFT MARGIN
	TSTEQB	$RIGSW,50$	; Not right justify?
	BICB	#SW.TDS,$RIGSW	; Reset temporary right justify
	MOV	RMARG,R2	; right margin
	SUB	SPCH,R2		; Now have indentation for right justify
	SUB	INDCT,R2	; Subtract indentation
	TSTNEB	$RIGSW,55$	; Still right justify ?
	BR	54$
50$:	ADD	INDCT,R2	; GET INDENTING IN CASE OF PARAGRAPH
54$:	CLR	INDCT		; (ONCE ONLY)			
55$:	TSTEQB	$CENSW,60$	; NO CENTERING?
	BICB	#SW.TDS,$CENSW	; CLEAR TEMPORARY CENTERING
	MOV	CMARG,R2	; CENTERING MARGIN
	MOV	SPCH,R0		; NUMBER OF CHAR IN LINE
	ASR	R0		; DIVIDE BY 2
	SUB	R0,R2		; NOW IS CHARS TO CENTER
60$:	ADD	EBSIZ2,R2	; ADD ON CHANGE BAR SIZE
	BITEQB	#HD.BAR,EXSTAT,70$	; CHANGE BAR PENDING?
	DEC	R2		; 1 CHAR IS OUT SO STOP ITS SPACE
70$:	MOV	RIGSHI,R1	; Right shift
	ADD	EBSIZ1,R1	; Plus bar spacing #1
	CALL	PBYT		; Output for initial spacing
	MOV	R2,R1		; Spacing after bar
	BGT	80$		; Margin ok?
	CLR	R1		; No, make it 0
80$:	CALL	PBYT		; in buffer
	MOVB	EXSP1,R1
	CALL	PBYT		; in buffer
	MOVB	EXSP2,R1
	CALL	PBYT		; in buffer
	MOVB	EXSP4,R1	; SAVED EXPANSIONS
	CALL	PBYT		; in buffer
	MOVB	EXMSP,R1	; Saved micro expansion
	CALL	PBYT
	CALL	ENDBF		; go back to end of buffer
	CALL	CBYT		; Null at end of line
	CLR	BF.HED(R3)	; No line available
OUTNJ3:	TSTNEB	$PAGNG,20$	; No paging ??
	BITNE	#FOTF!TEXF,F.1,10$	; Text or footnote flags on ?
	BITEQ	#BRKF,F.1,1$	; No break this line ??
	TST	LINEC3		; Check room this page
	BGE	8$		; Room for all deferred ?
1$:	BITEQ	#PARF,F.1,10$	; No deferred ?
	MOV	PARDFT,R0	; Get paragraph line deferral
	MOV	PARDFB,R1	; Get bottom deferred
	BITEQ	#BRKF,F.1,7$	; No break this line ??
	CMPEQ	R0,R1,2$	; Same as bottom ?
	CMP	R0,BF.VSP(R3)	; Deferr all ?
	BGT	3$		; Yes
2$:	MOV	R1,R0		; Deferred lines at bottom
	ADD	LINEC3,R0	; Subtract off number past endpage
3$:	MOV	R0,PARDFO	; Deferred lines
	BR	9$
7$:	ADD	LINEC3,R1	; Add to lines to test
	BLE	8$		; Enough lines ?
	RETURN			; No continue
8$:	CLR	PARDFO
9$:	BIC	#PARF,F.1	; No more deferred
	TSTEQB	$FOTPD,12$	; No footnote pending
	ADD	FOTBF+BF.VSP,PARDFO ; Make room for it
12$:	CALL	OUTL0		; Do the output
	CLR	PARDFO
	BITEQ	#BRKF,F.1,10$	; Line not broken ?
	CLR	PARDFB		; Yes, reset paragraph deferred
	CLR	PARDFT		; 
	CLR	PARDFH
10$:	BIC	#BRKF,F.1	; No break flag
	CALL	TESTL
	BITNE	#FOTF!TXDEF,F.1,40$	; Footnote or deferred text?
	BITEQ	#TEXF!PARF,F.1,20$	; No text saved ??
	TSTNEB	$PAGBR,40$	; not at top of page ??
20$:	BIC	#BRKF!TEXF!PARF,F.1	; Reset text flag
	JMP	OUTL0		; NO OUTPUT THE LINE
40$:	RETURN			; 
;
;	DO ACTUAL OUTPUT TO PRINTER OF TEXT STRING
;
OUTL0::	CLRB	EXLINE
	CALL	OUTAD		; GET HEADER ADDRESS
	CALL	BEGBF		; SET TO TOP OF BUFFER
OUTL1:	MOVB	EXLINE,R2	; Get skip count
	CALL	$SKIP0		; Skip R2 lines
	CLRB	EXLINE		; Clear skip
	CALL	GBYT		; Get skip count
	BCC	5$		; Not done
	JMP	OUTL2		; Done
5$:	BIC	#^C<377>,R1	; Strip off extra byte
	MOV	R1,R2		; Now is skip count
	CALL	GBYT		; Get status
	BITEQB	#HD.TXD,R1,10$	; Not end of text deferred buffer ?
	JMP	TXDOU2
10$:	MOVB	R1,EXSTAT	; Save status
	BGE	15$		; Normal line ??
	TSTNEB	$PAGNG,12$	; No paging ?
	BITEQB	#HD.FIG,R1,11$	; Mandatory skip ?
	TSTNEB	$PAGBR,11$	; Page not already broken?
	ADD	R2,LINEC3	; Compensate for missing skip
	SUB	R2,BF.VSP(R3)
	BR	OUTL1
11$:	TSTEQB	$PAGBR,12$	; Page already broken?
	CMP	R2,LINEC1	; Enough space left ??
	BLE	12$		; No ?
	SUB	R2,BF.VSP(R3)	; Adjust vertical spacing
	MOV	LINEC1,R2	; MAKE IT MAX
	ADD	R2,BF.VSP(R3)	; Adjust vertical spacing
12$:	CALL	$SKIP0
	BR	OUTL1
15$:	BITNEB	#HD.LIN,R1,16$	; Output line ?
	TSTNE	BF.HED(R3),13$	; Header exists ?
	JMP	HLTER		; No, this is fatal error
13$:	JMP	TXDOU3
16$:	CALL	GBYT		; Get post line count
	BIC	#^C<377>,R1	; Strip off extra byte
	MOVB	R1,EXLINE	; Save it
	TSTNEB	$PAGNG,20$	; No paging ?
	ADD	R2,R1		; Total lines this one
	ADD	PARDFO,R1	; Add deferred lines
	CMP	R1,LINEC1	; Check if too big
	BLE	20$		; Is it OK ?
	CLRB	EXLINE
	MOV	BF.FUL(R3),R1	; Get current address
	DEC	R1
	BR	TXDOU4		; And save line
20$:	CALL	$SKIP0		; Skip R2 lines
	CALL	GBYT		; Get initial spacing
	BIC	#^C<377>,R1	; Strip off extra byte
	MOV	R1,R2		;
	CALL	NSPAC		; Output n spaces
	BITEQB	EXSTAT,#HD.BAR,30$	; NO BAR?
	MOVB	#'|,R1		; NOPE
	CALL	FOUT		; Output change bar
	INC	CPOS		; Increment position counter
30$:	CALL	GBYT		; Spaces after bar
	BIC	#^C<377>,R1	; Strip off extra byte
	MOV	R1,R2		; MARGIN
	BIC	#177400,R2	; Clear extra bits
	CALL	NSPAC		; OUTPUT SPACES
	CALL	GBYT		; Get spacing control parameters
	MOVB	R1,EXSP1
	CALL	GBYT
	MOVB	R1,EXSP2
	CALL	GBYT
	MOVB	R1,EXSP3
	CALL	GBYT
	MOVB	R1,EXMSP
	CALL	CCOUT		; Output + format text
	BCS	40$		; End of buffer ?
	CALL	UNLOUT		; Output underlines
	JMP	OUTL1
40$:	CALL	UNLOUT		; Output underlines
	MOVB	EXLINE,R2	; Get skip count
	CALL	$SKIP0		; Skip R2 lines
;
;	END OF LINE, AND FOOTNOTE PROCESSING
;
OUTL2:	CLRB	EXLINE		; Clear skip
	CLRB	EXSTAT		; Clear status
	CLRB	EXSP1		; Clear spacing controls
	CLRB	EXSP2
	CLRB	EXSP3
	MOVB	#-1,EXMSP
	BITEQ	#FOTF,F.1,20$	; No footnote in progress?
	CLRB	$FOTPD		; CLEAR PENDING
	MOV	PFOTHD,R1	; Permanent footnote header
	BEQ	20$		; Zero ?
	MOV	FOTLN,BF.VSP(R3); Permanent footnote size
	JMP	RSTBF		; Return to previous header
20$:	JMP	CLRBF		; CLEAR THE BUFFER
;
;	Reshuffle buffer containing output lines
;
TXDOU2:	TSTEQB	$PAGBR,5$	; At top of page ?
	MOV	R2,BF.VSP(R3)	; New vertical spacing
	BEQ	5$
	CMP	R2,LINEC3	; Compare with available space
	BGT	TXDOU3		; Too big ?
5$:	SUB	R2,LINEC3	; Subtract from LINEC3
	JMP	OUTL1		; And do more
TXDOU3:	MOV	BF.FUL(R3),R1	; Get current index
TXDOU4:	SUB	#2,R1		; Backspace 2
	BNE	1$		; Not at beginning ?
	JMP	ENDBF		; Go to end of buffer
1$:	CALL	FNDBF		; Move over to it
	MOV	BF.HED(R3),R0	; Get current header value
	BEQ	10$		; None ?
	SUB	R1,R0		; Subtrac off offset
	MOV	R0,BF.HED(R3)	; New header
10$:	MOV	R3,R2		; Save address
	CALL	GETTBF		; Get temporary header
	CALL	BEGBF		; Start at beginning of buffer
	BITEQ	#FOTF,F.1,20$	; No footnote ?
	MOV	PFOTHD,R1	; Permanent footnote header
	BEQ	20$		; None ?
	ADD	FOTLN,BF.VSP(R2); Add on permanent lines to header
	TSTEQ	BF.HED(R3),15$	; No header ?
	ADD	R1,BF.HED(R3)	; Add on permanent header
15$:	CALL	FNDBF
20$:	CALL	GBYT2		; Get a byte
	BCS	30$		; Done ?
	CALL	PBYT		; Save it
	BR	20$
30$:	MOV	BF.FUL(R3),R1	; Reset buffer to end here
	MOV	R2,R3		; Switch to primary buffer
	JMP	RSTBF
;
;	Output underlines from buffer
;
UNLOUT:	MOV	R3,-(SP)	; SAVE R3
	TSTEQB	$ULMSW,50$	; Mode backspace or none
	TSTEQ	ULNMAX,40$	; NO UNDERLINES IN BUFFER?
	TSTB	$ULMSW		; Now test mode
	BLT	10$		; Line ?
	TSTNEB	$PAGNG,5$	; No paging
	SUB	#LINSP,LINEC3	; ACCOUNT FOR EXTRA LINE
5$:	CALL	CRLF		; SPACE TO NEXT LINE
	BR	20$		; 
10$:	MOV	#CR,R1		; OUTPUT A CARRIAGE RETURN
	BITEQB	#CRSW,$SWTCH,15$; No CRLF output?
	CALL	FOUT		; 
15$:	CALL	OUTPUT		; Start a new line
20$:	MOVB	#-1,$UNLRS	; Set up reset underline
	MOV	#UBUFF,R3	; GET UNDERLINE BUFFER
	MOV	ULNMAX,R2	; MAX CHAR
30$:	MOVB	(R3)+,R1	; GET UNDERLINE CHAR
	BGT	36$		; Not microspace ?
	BIC	#177600,R1	; Strip extra bits
	MOV	R1,-(SP)	; Save counter
31$:	MOV	#VARESC+1,R4	; Microspace escape seq.
	DEC	(SP)		; ANother time through ?
	BGE	32$		; Yes ?
	TST	(SP)+		; Pop stacke
	BR	37$
32$:	MOVB	(R4)+,R1	; Get char
	BEQ	31$		; Done yet ?
	CALL	FOUT		; Output it
	BR	32$
36$:	CALL	FOUT
37$:	SOB	R2,30$		; TILL DONE
40$:	TSTEQB	$UNLRS,50$	; No changes in underline buffer ?
	CALL	ULBSET		; RESET UNDERLINE BUFFER POINTER
50$:	MOV	#1,CPOS
	CLRB	$ULOSW		; No underlining yet
	MOV	(SP)+,R3	; RESTORE R3
	RETURN
;
;	OUTPUT deferred text
;
TXDOUT::BITNE	#TXDEF!FOTF,F.1,10$ ; Currently in deferred or footn. mode ?
	TSTEQ	BF.VSP+TXDBF,10$; No data in buffer ?
	MOV	F.1,-(SP)
	BIS	#TXDEF!TEXF,F.1	; Set up for deferred text
	CALL	OUTL0		; Output it
	MOV	(SP)+,F.1	; Restore
10$:	RETURN
;
;	END text deferred
;
TXDEND::BITEQ	#TXDEF,F.1,10$	; Not text deferred ?
	CALL	OUTAD		; Get address
	MOV	TXDHED,R1	; Get header
	CALL	FNDBF		; Get it
	MOV	BF.VSP(R3),R1	; Spacing
	CALL	PBYT		; Save it
	CALL	ENDBF
	MOV	#-1,BF.VSP(R3)	; Set up line size
	MOV	LN3SAV,LINEC3	; Restore saved size
	BIC	#TXDEF!TEXF,F.1	; No deferred text now
10$:	BR	TXDOUT		; Try to output text
;
;	Dump all text
;
TXDMP::	BITNE	#TXDEF,F.1,1$	; No text deferred ?
	BIC	#TEXF,F.1	; No text now
1$:	CALL	OUTNJ		; Dump current text
	CALL	TXDEND
	CALL	TXDOUT		; And any deferred
10$:	TSTEQ	BF.VSP+TXDBF,20$; No deferred text ?
	CALL	BPAGE		; Output 1 page
	CALL	OUTNJ		; Flush any normal text
	BR	10$
20$:	RETURN	
;
;	Subroutine to skip N text lines
;		R1=skip count
;	SKIPL	is unconditional skip
;	SKPLIF	is conditional on if not at top of page
;
SKPLIF::CALL	MULSP		; Adjust spacing by the line spacing
	MOV	R1,R2		; Now is correct spacing
	BR	SKPNIF
SKIPL::	CALL	MULSP		; Adjust spacing by the line spacing
	MOV	R1,R2		; Now is correct spacing
	BR	SKIPN
;
;	SUBROUTINE TO SKIP N LINES ON OUTPUT FILE
;	R2 = NUMBER OF LINES TO SKIP
;	bit 15	clear this is mandatory skip
;		set no skip at top of page
;	SKPNIF	Skips if not at top of page
;
SKPNIF::TSTEQB	$PAGBR,SKRET	; At top of page ?
	BIS	#100000,R2	; Set optional bit
SKIPN::	MOV	R2,R0		; Skip in R0
	CALL	OUTAD		; GET BUFFER ADDRESS
	TSTEQ	BF.HED(R3),1$	; No header ??
	JMP	HLTER		; Yes, generate error message
1$:	TSTNEB	$PAGNG,$SKIP0	; No paging ??
	BIC	#^C<377>,R0	; Strip extra bits
	BEQ	SKRET		; YES DO NOT SKIP
	TSTB	$PFOOT		; Permanent footnote
	BLT	40$		; in progress ?
10$:	CMP	R0,LINEC3	; LINE COUNT
	BLT	30$		; Skip count not too many ?
	MOV	LINEC3,R0	; Skip to bottom
	BLE	SKRET		; Bad skip?
20$:	DECB	$PAGPD		; New page pending
30$:	SUB	R0,LINEC3	; Now line count
40$:	ADD	R0,BF.VSP(R3)	; Add to vertical spacing this buffer
	BIC	#377,R2		; Clear extra bits
	ADD	R0,R2		; And subs R0
	BITEQ	#FOTF!TEXF!PARF,F.1,$SKIP0 ; No footnote or deferred text?
	CALL	ENDBF		; get the location
	MOVB	R2,R1		; Skip count
	CALL	PBYT		; Save it
	MOV	#HD.SKP,R1	; Make this skip
	TST	R2		; Check if mandatory skip
	BGE	50$		; Mandatory ?
	BISB	#HD.FIG,R1	; Set it as optional
50$:	CALL	PBYT		; Save skip header
SKRET:	RETURN
$SKIP:	BIC	#^C<377>,R2	; Strip extra bits
	BNE	10$		; Any skip ??
	RETURN
10$:	TSTNEB	$PAGNG,$SKIP1	; No paging
	SUB	R2,LINEC3	; ADD LINES TO TOTAL
	BR	$SKIP1
$SKIP0:	BIC	#^C<377>,R2	; Strip extra bits
	BNE	10$		; Any skip ??
	RETURN
10$:	TSTNEB	$PAGNG,$SKIP1	; No paging ?
	SUB	R2,BF.VSP(R3)	; Number of lines this buffer
$SKIP1:	MOVB	#-1,$PAGBR	; NOT AT TOP OF PAGE
;
;	Perform half line skips
;		R2=half line count
;
	BITEQ	#1,R2,30$	; No half lines required ?
	MOV	R2,-(SP)	; save half line spacing
	TSTNEB	$PAGNG,5$	; No paging
	DEC	LINEC1		; Account for half lines
	DEC	LINEC2
5$:	MOV	#DNMOV,R2	; Get buffer to transfer
10$:	MOVB	(R2)+,R1	; Get char
	BEQ	20$		; Done ?
	CALL	FOUT
	BR	10$
20$:	CALL	OUTPUT		; Start a new line
	MOV	(SP)+,R2	; RESTORE NUMBER OF LINES
30$:	BIC	#1,R2		; Clear half bit
	BLE	70$		; No more to output
60$:	CALL	CRLF		; SPACE TO NEXT LINE
	SUB	#LINSP,R2	; Lines left
	BGT	60$		; Not done ?
70$:	RETURN			; 
;
; ROUTINE TO OUTPUT SPACES TO FILE
;
NSPAC::	DEC	R2		; ANY MORE SPACES TO OUTPUT?
	BLT	SKRET		; IF LT NO
	CALL	CCSPC		; OUTPUT A SPACE
	BR	NSPAC		; 
;
;	End of line output routine
;
CRLF:	BITEQB	#CRSW,$SWTCH,10$	; No CRLF output?
	MOVB	#CR,R1		; Get carriage return
	CALL	FOUT		; Output it
	MOVB	#LF,R1		; And line feed
	CALL	FOUT
10$:	TSTNEB	$PAGNG,20$	; No paging ?
	SUB	#LINSP,LINEC1	; Counts active lines
	SUB	#LINSP,LINEC2	; And total lines
20$:	JMP	OUTPUT		; And end line

;
;	SUBROUTINE PUTS CURRENT CHAR ADDRESS INTO R3
;
OUTAD::	BITNE	#FOTF!TXDEF,F.1,10$ ; Deferred or footnote ?
	MOV	#TX2BF,R3	; NORMAL SECONDARY BUFFER
	RETURN			; 		
10$:	BITEQ	#FOTF,F.1,20$	; NOT FOOTNOTE BUFFER?
	MOV	#FOTBF,R3	; GET FOOTNOTE BUFFER ADDRESS
	RETURN			; 
20$:	MOV	#TXDBF,R3	; Text deferred buffer
	RETURN

;
;	ROUTINE TO SPACE TO TOP OF FORM
;
FORM:	CLRB	$PAGPD		; No longer page pending
;
;	Output FF or adjust to correct page height
;
	TSTNEB	$FIRPG,40$	; First page?
	BITEQ	#FFDSW,$SWTCH,10$ ;SPACING WITH LINE FEEDS?
	MOV	#FF,R1		; OUTPUT A FORMFEED
	CALL	FOUT				
	CALL	OUTPUT		; Start a new line
	BR	40$		; ADJUST COUNTS	
;
;	Go to end of page by adding lines
;
10$:	MOV	LPPG,R1		; Number of lines/page
	BLE	40$		; Too small ?
	MOV	LINEC2,R2	; Number of lines to skip
15$:	BGT	20$		; Skip correct ?
	BEQ	40$		; none ?
	ADD	R1,R2		; Add on lines/page
	BR	15$
20$:	CALL	$SKIP1		; Skip over lines
;
;	Now at end of page
;
40$:	TSTNEB	$OUTSW,50$	; No output ??
	CALL	OPRWAT		; WAIT FOR OPERATOR TO POSITION FORMS	
;
;	Setup current page number
;
50$:	CALL	ULBSET		; Reset underline buffer in case
	MOVB	$SBPSW,R0	; Get subpage status
	BEQ	80$
	BITEQ	#SW.DIS,R0,70$	; No subpage requested ?
	BISB	#SW.TDS,$SBPSW	; Set keep bit
	TSTEQB	$SETPG,60$	; Page reset ?
	MOV	PAGNX,R0	; Keep page requested
	MOV	R0,PAGENO	; Current page number
	INC	R0
	MOV	R0,PAGNX	; Next page
60$:	MOVB	SUBNX,SUBPGE	; set to current subpage
	INCB	SUBNX		; yes increment it
	BNE	90$		; Non zero?
	INCB	SUBNX		; No, make it 1
	BR	90$
70$:	MOVB	#1,SUBNX	; Next subpage number
	CLRB	$SBPSW		; No subpage
	CLRB	SUBPGE		; No subpage
80$:	MOV	PAGNX,R0	; now current page number
	MOV	R0,PAGENO
	INC	R0		; increment next page number
	MOV	R0,PAGNX	; Save new page number
;
;	Test if this page output
;
90$:	TSTNE	PAGENO,100$	; Page number ok ?
	INC	PAGENO		; No make it 1
100$:	CLRB	$SETPG
	BISB	#SW.TDS,$OUTSW	; Set for no output
	CMP	PAGENO,LOWPAG	; ONLY PRINT IN THE SELECTED PAGE
	BLO	150$		; RANGE
	CMPB	CHPTN,LOWCHP	; chapter # too small?
	BLO	150$		; yes
	CMPB	APNDN,LOWAPN	; appendix too small?
	BLO	150$		; yes
	BITNEB	#SW.DIS,$OUTSW,150$; First pass of 2 ?
	CMP	PAGENO,HGHPAG	; page number too big?
	BHI	110$		; yes
	CMPB	CHPTN,HGHCHP	; too big?
	BHI	110$		; yes
	CMPB	APNDN,HGHAPN	; appendix too big?
	BLOS	120$		; No ?
110$:	JMP	ENDFIL		; Terminate file
120$:	BITNE	#1,PAGENO,130$	; Current page number odd ?
	BITNE	#EVESW,$SWTCH,150$; Even pages off ?
	BR	140$
130$:	BITNE	#ODDSW,$SWTCH,150$; Odd pages off ?
140$:	BICB	#SW.TDS,$OUTSW	; Set output on
;
;	Set up params next page
;
150$:	MOVB	NXLAY,$LAYOU	; Current layout is now Next layout
	MOVB	PRLAY,NXLAY	; Next is permanent layout
	MOV	NXEPSP,$EOPSP	; Next end-of-page spacing
	MOV	PREPSP,NXEPSP	; Permanent eop spacing
	MOV	NLPG,LINEC1	; Active lines this page
	SUB	$EOPSP,LINEC1	; Subtract off bottom lines
	MOV	LINEC1,LINEC3	; Potential lines per page
	TSTEQB	$FOTPD,160$	; Footnote not pending ?
	SUB	FOTBF+BF.VSP,LINEC3	; Subtract off header size
160$:	MOV	LPPG,LINEC2	; Number of actual lines remaining this page
	RETURN

;
;	Routine to convert vetical spacing to appropriate number
;
CVSP::	TSTEQB	$HSPSW,10$	; Half spacing ?
	ASL	R3		; Convert to half space count
10$:	RETURN
;
;	Find actual adjusted lines
;		R1=# of text lines
;		R0,R1=hi,low order result
;
MULSP::	MOV	NSPNG,R0	; Get line spacing
	.if df	$EIS
	MUL	R1,R0		; Mult R1 by R0
	.iff
	CALL	$MUL		; mult R1 by R0
	.endc
	RETURN
;
;	Test if room for lines of text
;
TESTT::	CALL	MULSP		; Convert to actual spacing
	BR	TESTP
; 
;	Test if enough room for 1 more line, and if not break page
;
TESTL:	CLR	R1		; Check if no more room
;
;	R1 = number of lines requested, check if break page?
;
TESTP::	TSTNEB	$PAGNG,10$
	TSTB	$PFOOT		; Permanent footnote in progress?
	BLT	10$		; Yes ?
	CMP	R1,LINEC3	; COMPARE TO LENGTH 
	BLE	10$		; Enough lines ?
	MOV	R1,-(SP)	; Save R1
	CALL	BPAGE
	MOV	(SP)+,R1	; Restore
	TSTEQB	$PAGBR,20$	; Currently at top of page ?
	BR	TESTP		; START A NEW PAGE
10$:	SEC			; NO PAGE BROKEN
	RETURN			; 
20$:	CLC			; Page broken
	RETURN
;
; SUBPAGE command
;
TPAGE::	BISB	#SW.DIS,$SBPSW	; Set subpage flag
	BR	BPAGE
;
;	Reset to page # 0 and begin new page
;
PAGRST:: TSTNEB	$CHPSW,PAGEC	; Not chapter oriented?
	MOV	#1,PAGNX	; Next page number is 1
;
;	END SUBPAGE command
;
PAGEC::	BICB	#SW.DIS,$SBPSW	; CLEAR SUBPAGE FLAG
	BR	BPAGE
;
;	PAGE command (new page only if not already at top-of-page)
;
CPAGE::	TSTNEB	$PAGBR,BPAGE	; Page not already broken?
	CLC			; Signify page broken
;
; BREAK COMMAND
;
BREAK::	RETURN

;
;	Start new page routine
;
BPAGE::	MOV	F.1,-(SP)	; Save
1$:	MOV	(SP),F.1	; Get flags
	BITEQ	#TXDEF,F.1,5$	; No text deferred ?
	MOV	#TXDERR,R0	; Error message 
	CALL	EROUT		; Text deferred is illegal here
	CALL	TXDEND		; End the deferred buffer
5$:	TSTNEB	$FIRPG,30$	; First page of document ??
	BITEQ	#FOTF,F.1,10$	; No footnote in progress?
	CALL	OUTL0		; Do footnote output
	MOVB	#-1,$FOTPD	; Reset pending in case it is reset
	BR	30$
10$:	TSTEQB	$FOTPD,30$	; NO FOOTNOTE PENDING?
	MOV	LINEC3,R2	; LINES LEFT
	BLE	20$		; NONE
	CALL	$SKIP		; SKIP THEM
20$:	BIS	#FOTF,F.1	; SET FLAG
	CALL	OUTL0		; OUTPUT IT
	BIC	#FOTF,F.1	; Now set no footnote
30$:	CALL	BPAG2		; Actually output page header
	BICB	#SW.TDS,$HDRSW	; Reset temporary header disable
	CLRB	$FIRPG		; Indicates not first page of document
	CLRB	$ULOSW		; No underlining
	CLRB	$PAGBR		; INDICATES AT TOP OF PAGE
	TSTNEB	$SBPSW,100$	; Currently in subpage ?
	CALL	TXDOUT		; Check for deferred text output
100$:	SUB	TX2BF+BF.VSP,LINEC3	; Subtract off saved lines
	BGE	120$		; Is it OK ?
	BITEQ	#TEXF,F.1,120$	; No text ?
	TSTNEB	$PAGBR,1$	; text on page ?
120$:	BIC	#PARF,(SP)	; No paragraph deferred
	CLR	PARDFO
	BITNE	#FOTF,(SP),130$	; Footnote in progress ?
	CALL	OUTL0		; Dump rest of paragraph
130$:	MOV	(SP)+,F.1	; Get flags
	CLC			; page break indicated
	RETURN
;
;	Output page header
;
BPAG2:	CALL	VARSAV		; Save all necessary variables
	CALL	STKSAV		; Save input stack
	MOV	#<$NFLSW-$AFLSW>/2,R1	; Number of flags
	MOV	#$AFLSW,R0	; Address of table
5$:	BIC	#FL.LIT!FL.ALL,(R0)+; Clear literal/all flags disable
	SOB	R1,5$		; For all flags
	BIC	#FOTF!TEXF!TXDEF!PARF,F.1	; Remove inconvenient flags
	ADD	$EOPSP,LINEC1	; restore bottom lines
	MOVB	#SUBLEV*4,SUBSTK+1	; Set up for extra levels of nesting
	MOV	#HDSTAT,R2	; Header status buffer
	CALL	RSTAT		; Get header status
	MOV	#1,PHSP		; Set permanent horiz spacing
	CLR	INDCT		; Clear indentation
	MOV	PRMRG,RMARG	; Use permanent margins
	MOV	PLMRG,LMARG	; Use permanent margins
	BIS	#FILLF,F.1	; Set fill
	BIC	#JUSTF,F.1	; No justify
	BISB	#SW.TDS,$UNLSW	; Set underlining off
	CLRB	$ULOSW		; No underlining of headers!
	TSTNEB	$FIRPG,30$	; First page?
	BITEQB	#LAY.NB,$LAYOU,30$	; Not number at bottom of page?
	MOV	LINEC1,R2	; Lines remaining this page
	SUB	#LINSP,R2	; Compensate for number to print
	BLE	10$		; None?
	CALL	$SKIP		; Skip em
10$:	CALL	HDMRG		; Set up left margin
	CALL	HDPAG		; Get page to output
	MOV	#LINSP,R2	; Skip 1 line
	CALL	$SKIP		; To end number at bottom of page
30$:	CALL	FORM		; OUTPUT FORMFEEDS OR LINEFEEDS
	MOV	TMARG,R2	; LINES TO SKIP	
	BLE	40$		; NONE
	CALL	$SKIP		; SKIP N LINES
40$:	TSTNEB	$HDRSW,90$	; NO HEADERS TO BE PRINTED?
	CALL	HDMRG		; Set up left margin
	TSTNEB	$NTITL,50$	; no title?
	MOV	#TTLBF,R3	; HEADER BUFFER
	CALL	CENTIT		; Center title if necessary
50$:	BITNEB	#LAY.NB,$LAYOU,60$ ; Page number at bottom?
	CALL	HDPAG		; Get page number
60$:	MOV	#LINSP,R2	; LINES TO SKIP
	CALL	$SKIP		; DO IT
	TSTNEB	$NTITL,70$	; no title?
	MOV	#STLBF,R3	; OUTPUT THE SUBTITLE, IF ANY
	CALL	HDMRG		; Set up margins
	CALL	CENTIT		; Center the subtitle?
70$:	MOV	HSPAC,R2	; LINES TO SKIP
	BGT	80$
	MOV	#LINSP,R2	; Only 1 skip
80$:	CALL	$SKIP		; DO IT
90$:	RETURN
;
;	Get margin and space over to it
;
HDMRG:	CLR	ESMSK		; No escape seq yet.
	CALL	VARSET
	MOV	EBSIZ1,R2	; SPACE FOR CHANGE BAR OFFSET
	ADD	EBSIZ2,R2
	ADD	RIGSHI,R2	; ADD ON RIGHT SHIFT
	ADD	PLMRG,R2	; Add on Permanent left margin
	CALL	NSPAC		; SPACE TO MARGIN	
	RETURN			;
;
;	Subroutine to form title/subtitle for output
;
CENTIT:	CALL	BEGBF		; Start at beginning of buffer
	MOV	CASE,-(SP)	; Save case
	CLR	-(SP)		; Offset to account for
	CMPNE	R3,#TTLBF,1$	; Not title buffer
	BIS	TTLCAS,CASE	; Set up case
	BITNEB	#LAY.NB,$LAYOU,2$ ; Page number at bottom?
	MOV	#10.,(SP)	; Make room for it
	SUB	(SP),LINBK	; For page number
1$:	BIS	STLCAS,CASE	; Set subtitle case
2$:	MOV	R3,R2		; Set up to get data as input
	MOV	#TTBF,R3	; Will be output buffer
	CALL	CLRBF
	CALL	TMPINB		; Set up temporary input
	BISB	#SW.HDR,$IFLSW+1; Prevent indexing
	BISB	#SW.HDR,$TABSW	; Prevent tabs
	BISB	#SW.DIS,$CONT	; Prevent continuation
	CALL	GCIN		; Get input
	BICB	#SW.HDR,$TABSW	; Allow tabs
	BICB	#SW.HDR,$IFLSW+1; Allow indexing
	TST	LINBK		; Check chars count left
	CALL	POPINS
	ADD	(SP)+,LINBK	; For page number
	MOV	(SP)+,CASE	; Restore
	MOV	LINBK,R2	; get remaining char count
	BLE	HDPRN		; None to do
	BITNEB	#LAY.CT,$LAYOU,10$	; Center title?
	BITNEB	#LAY.RT,$LAYOU,20$	; Right title
	BITEQB	#LAY.OT,$LAYOU,HDPRN	; No odd even layout
	BITEQB	#1,PAGENO,HDPRN	; Not odd page number?
	BR	20$		; Shift to right justify
10$:	ASR	R2
20$:	CALL	NSPAC		; Space over to margin
HDPRN:	MOV	ESMSK,R4	; Get escape mask
	CALL	ESCEND		; Terminate escapes
	CLR	ESMSK		; No escape seq
	MOV	#1,PHSP		; Reset permanent spacing
	BISB	#SW.TDS,$UNLSW	; Set underlining off
	CALL	PSTRPA
	JMP	UNLOUT
HDPAG:	TSTNEB	$NUMSW,60$	; NO PAGE NUMBER?
	MOV	#TTBF,R3	; GET TEMPORARY BUFFER
	CALL	CLRBF		; CLEAR IT
	TSTNEB	$PAGSW,50$	; OUTPUT 'PAGE'?
	MOV	#PAGHD,R2	; PAGE HEADER
	CALL	HDOUT		; MOVE IT TO BUFFER
50$:	CLR	BF.SPC(R3)	; Reset space count
	CALL	PUTPAG		; PUT PAGE INTO BUFFER ALSO
	SUB	BF.SPC(R3),LINBK; And subtract from remaining
	MOV	#PAGH2,R2	; And second header
	CALL	HDOUT		; Put it also
	MOV	LINBK,R2	; Number of chars left
	BLE	HDPRN		; None ?
	BITNEB	#LAY.CP,$LAYOU,51$	; Centered page number?
	BITNEB	#LAY.LP,$LAYOU,HDPRN	; left page ?
	BITEQB	#LAY.OP,$LAYOU,55$	; No odd even layout
	BITEQB	#1,PAGENO,HDPRN		; Not odd page number?
	BR	55$
51$:	ASR	R2			; Center it
55$:	CALL	NSPAC		; SPACE TO PAGE NUMBER
	BR	HDPRN		; OUTPUT STRING IN BUFFER
60$:	RETURN
;
;	Output headers
;
HDOUT::	TSTEQB	(R2),20$	; No header to output
	CALL	TMPIN		; Set up temporary input buffer
	BISB	#SW.HDR,$IFLSW+1; Prevent indexing
	BISB	#SW.HDR,$TABSW	; Prevent tabs
	MOV	F.1,-(SP)	; Save
	BIC	#FILLF,F.1	; No fill from literal
	CALL	GCIN		; Get input
	MOV	(SP)+,F.1
	BICB	#SW.HDR,$TABSW	; Allow tabs
	BICB	#SW.HDR,$IFLSW+1; Allow indexing
	CALL	POPINS		; Pop the stack
20$:	RETURN
;
;	SSTAT	saves status (flags,switches,caps mode etc.)
;	RSTAT	restores status
;		R2=address of STSIZE word block to contain status
;		R0,R1	destroyed
;	SSTATS	save status on stack
;		R0-R2	destroyed
SSTATS::MOV	(SP),R0		; Return address
	SUB	#STSIZE*2,SP	; Set up stack
	MOV	R0,(SP)		; Set up return
	MOV	SP,R2		; Where to save status
	TST	(R2)+		; Beginning of table
	CALL	SSTAT		; Store status
	CALL	@(sp)+		; Come back later
	MOV	SP,R2		; Restore status
	CALL	RSTAT
	MOV	R2,SP		; Restore stack
	RETURN
SSTAT::	MOV	R3,-(SP)	; Save regs
	MOV	#switS,R1	; swit address
	MOV	#NswitS,R3	; Size of table
	MOV	R3,(R2)+	; start of status
	CLR	(R2)		; Set up this entry
	MOV	#1,R0
10$:	BITB	#SW.DIS,(R1)+	; Check swit
	BEQ	20$		; No bit ?
	BIS	R0,(R2)		; Set bit in mask
20$:	ASL	R0		; Next mask
	SOB	R3,10$	
	TST	(R2)+		; Next entry in table
	MOV	#$AFLSW,R1	; Flags address
	MOV	#16.,R3		; Size of table
	CLR	(R2)		; Set up this entry
	MOV	#1,R0
50$:	BITEQ	#FL.ALL,(R1)+,60$	; No bit set ?
	BIS	R0,(R2)		; Set bit in mask
60$:	ASL	R0		; Next mask
	SOB	R3,50$	
	TST	(R2)+		; Next entry in table
	MOV	#NFLAGS-16.,R3	; Number of flags to do
	CLR	(R2)		; Set up this entry
	MOV	#1,R0
70$:	BITEQ	#FL.ALL,(R1)+,80$	; No bit set ?
	BIS	R0,(R2)		; Set bit in mask
80$:	ASL	R0		; Next mask
	SOB	R3,70$	
	TST	(R2)+		; Next entry in table
	MOV	F.1,(R2)+	; Save status
	MOV	CASE,(R2)+	; And case
	MOV	(SP)+,R3
	RETURN
RSTAT::	MOV	R3,-(SP)	; Save regs
	MOV	#switS,R1	; swit address
	MOV	#NswitS,R3	; Size of table
	CMPNE	R3,(R2)+,50$	; Not correct status
	MOV	(r2)+,R0
10$:	ASR	R0		; Get bit
	BCC	20$		; No bit ?
	BISB	#SW.DIS,(R1)+	; Set status bit
	BR	25$
20$:	BICB	#SW.DIS,(R1)+
25$:	SOB	R3,10$	
	MOV	#$AFLSW,R1	; swit address
	MOV	#16.,R3		; First 16 flags
	MOV	(r2)+,R0
30$:	ASR	R0		; Get bit
	BCC	40$		; No bit ?
	BIS	#FL.ALL,(R1)+	; Set status bit
	BR	45$
40$:	BIC	#FL.ALL,(R1)+
45$:	SOB	R3,30$	
	MOV	#Nflags-16.,R3	; Size of table
	MOV	(r2)+,R0
46$:	ASR	R0		; Get bit
	BCC	47$		; No bit ?
	BIS	#FL.ALL,(R1)+	; Set status bit
	BR	48$
47$:	BIC	#FL.ALL,(R1)+
48$:	SOB	R3,46$	
	MOV	(R2)+,F.1	; restore status
	MOV	(R2)+,CASE	; And case
50$:	MOV	(SP)+,R3	; Restore
	RETURN
;
;	This saves all necessary variables
;		R0,R1,R2 are destroyed
;
VARSAV::MOV	#FLGBEG,R0	; Variables to save
	MOV	#<SAVEND-FLGBEG>/2,R1	; Number of variables
	MOV	(SP)+,R2	; Return address
10$:	MOV	(R0)+,-(SP)	; Save the variables
	SOB	R1,10$		; Till done
	MOV	R0,-(SP)
	MOV	R2,-(SP)
	CALL	@(SP)+		; Back to main prog
	MOV	(SP)+,R0	; Variables to save
	MOV	#<SAVEND-FLGBEG>/2,R1	; Number of variables
20$:	MOV	(SP)+,-(R0)	; Save the variables
	SOB	R1,20$		; Till done
	RETURN	
;
;	Save input stack
;
STKSAV:	MOV	(SP)+,R0	; Return address
	MOV	SUBSTK,-(SP)	; Save status
	MOV	BUFAD,-(SP)	; Save
	MOV	R0,-(SP)	; Return address
	CALL	@(SP)+		; Back to main prog
	MOV	(SP)+,BUFAD	; Restore
	MOV	(SP)+,SUBSTK	; status
	RETURN
;
;	Do paragraphing
;
PARTP::	MOV	PARSP,R1	; Paragraph line spacing
	CALL	SKPLIF		; Skip if not at top of page
	MOV	PARIND,INDCT	; SET INDENTATION
PART0::	MOV	PARPT,R1	; Get test page count
PART1::	CALL	MULSP		; Get total lines
	MOV	R1,R5		; Top count saved
	MOV	PARTT2,R1	; Deferred lines
	CALL	MULSP		; Calculate deferred line spacing
	MOV	R1,R4		; Save it
PARTS::	BITNE	#FOTF!TEXF,F.1,10$	; No allowed during footnote or text
	TSTNEB	$PAGNG,10$	; Not allowed during no paging
	MOV	R4,R1		; Post count
	CMP	R1,NSPNG	; Is it trivial
	BLE	5$		; Yes ?
	MOV	R1,PARDFB	; Save line spacing
	MOV	R1,PARDFT	; Save line spacing
	SUB	NSPNG,R1	; Subtract 1 line
	MOV	R1,PARDFH	; Save line spacing
	CMP	R5,NSPNG	; Top trivial ?
	BLE	5$		; Yes
	ADD	R5,R4		; Top + bottom
	CMP	R4,LINEC3	; Enough room ?
	BLE	5$		; Yes ?
	MOV	R4,PARDFT	; Set separate top
	MOV	LINEC3,R1	; Number of lines left
	SUB	R5,R1
	MOV	R1,PARDFH	; Set hyphenation inhibit
5$:	MOV	R5,R1		; Get final value
	TSTEQB	$PAGBR,10$	; Already at top of page?
	JMP	TESTP		; TEST AND OUTPUT PAGE IF NECESSARY
10$:	RETURN			;
;
; START OF RUNOFF
;
START:	CALL	$START		; Set up to receive commands 
RUNOFF::MOV	SPSAV,SP	; Reset stack
	CALL	INITL		; INITIALIZE VARIABLES
	JMP	RESTRT		; Continue
	.END	START
