	.TITLE	GCIN
	.IDENT	/V01/
;
;	These are general input/output character interpretation routines
;
	.vars
	.BLKB	1
TBUFF:	.BLKB	SUBMAX+2
	.even
ADDR:	.BLKA	1
;
;	INPUT CHARACTER PARSING TABLES
;		TO ADD MORE FLAGS THESE TABLES MUST BE CHANGED
;		THE FLAG DEFINITIONS COORESPOND TO THE FLAG SWITCHES
;
GC.UC==		0*$WORDL			; Upper case letters
GC.LC==		1*$WORDL			; Lower case letters
GC.AFL==	2*$WORDL			; Accept flag
GC.CFL==	3*$WORDL			; Capitalize flag
GC.UFL==	4*$WORDL			; Underline flag
GC.LFL==	5*$WORDL			; Lowercase flag
GC.SFL==	6*$WORDL			; Uppercase flag
GC.QFL==	7*$WORDL			; Quoted space flag
GC.OFL==	8.*$WORDL			; Overstrike flag
GC.IFL==	9.*$WORDL			; Index flag
GC.HFL==	10.*$WORDL			; Hyphenation flag
GC.EFL==	11.*$WORDL			; Escape flag
GC.SUB==	12.*$WORDL			; substitute flag
GC.BRK==	13.*$WORDL			; break flag
GC.NFL==	14.*$WORDL			; COMMAND FLAG
GC.CR==		15.*$WORDL			; CARRIAGE RETURN
GC.TAB==	16.*$WORDL			; tab input char
GC.LF==		17.*$WORDL			; lin feed input
GC.DIG==	18.*$WORDL			; digit (0-9)
GC.SPC==	19.*$WORDL			; space
GC.MSC==	20.*$WORDL			; MISCELLANEOUS CHARS
GC.SPF==	21.*$WORDL			; Special flag
GC.EQ1==	22.*$WORDL			; Equation flags
GC.EQ2==	23.*$WORDL			; Equation flags
GC.SIX==	24.*$WORDL			; Subindex flag
GC.PFL==	25.*$WORDL			; PEriod flag
GO.UNL==	-1*$WORDL			; underline 1 char
GO.ESC==	-2*$WORDL			; begin escape sequence
GO.QTS==	-3*$WORDL			; quoted space output
GO.BS==		-4*$WORDL			; backspace output
GO.TAB=		-5*$WORDL			; Tab count byte follows
GO.ELP=		-6*$WORDL			; Ellipses count follows this
GC.ILL=		-7*$WORDL			; illegal character
GO.REP=		-8.*$WORDL			; Repeat characters
GO.INX=		-9.*$WORDL			; Index entry
GO.TOC=		-10.*$WORDL			; TOC entry
GO.PAG=		-11.*$WORDL			; Page number
;
;	THE FOLLOWING CORRESPOND TO THE ASCII CHARACTERS
;
GCTABL:: .BYTE	GC.ILL,GC.ILL,GC.ILL,GC.ILL,GC.ILL,GC.ILL	; NUL-ENQ
	.BYTE	GC.ILL,GC.ILL,GO.BS				; ACK-BS
	.BYTE	GC.TAB,GC.LF,GC.ILL,GC.ILL			; TAB,LF,VT,FF
	.BYTE	GC.CR,GC.ILL,GC.ILL,GC.ILL			; CR,SO,SI,DLE
	.BYTE	GC.ILL,GC.ILL,GO.PAG,GO.TOC,GC.ILL		; DC1-nak
	.BYTE	GO.INX,GO.REP,GO.TAB,GO.ELP,GC.ILL		; SYN-SUB
	.BYTE	GO.ESC,GO.UNL,GC.ILL,GC.ILL,GC.ILL		; ESC-US
	.BYTE	GC.SPC						; SPACE
	.BYTE	GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC	;  - &
	.BYTE	GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC	; ' - ,
	.BYTE	GC.MSC,GC.MSC,GC.MSC				; - . /
	.BYTE	GC.DIG,GC.DIG,GC.DIG,GC.DIG,GC.DIG		; 0 - 4
	.BYTE	GC.DIG,GC.DIG,GC.DIG,GC.DIG,GC.DIG		; 5 - 9
	.BYTE	GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC ; : - @
	.BYTE	GC.UC,GC.UC,GC.UC,GC.UC,GC.UC,GC.UC		; UPPER CASE
	.BYTE	GC.UC,GC.UC,GC.UC,GC.UC,GC.UC,GC.UC		; UPPER CASE
	.BYTE	GC.UC,GC.UC,GC.UC,GC.UC,GC.UC,GC.UC		; UPPER CASE
	.BYTE	GC.UC,GC.UC,GC.UC,GC.UC,GC.UC,GC.UC,GC.UC,GC.UC	; UPPER CASE
	.BYTE	GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC,GC.MSC	; [ - `
	.BYTE	GC.LC,GC.LC,GC.LC,GC.LC,GC.LC,GC.LC		; LOWER CASE
	.BYTE	GC.LC,GC.LC,GC.LC,GC.LC,GC.LC,GC.LC		; LOWER CASE
	.BYTE	GC.LC,GC.LC,GC.LC,GC.LC,GC.LC,GC.LC		; LOWER CASE
	.BYTE	GC.LC,GC.LC,GC.LC,GC.LC,GC.LC,GC.LC,GC.LC,GC.LC	; LOWER CASE
	.BYTE	GC.MSC,GC.MSC,GC.MSC,GC.MSC			; { - ~
	.BYTE	GO.QTS						; DEL
;
;	CHARACTER DEFINITION TABLE
;
CH.BRK==	^o1			; Char is followed by break
CH.BRB==	^o2			; Char is preceeded by break
CH.FLC==	^o4			; CHAR MAY BE FLAG CHAR
CH.FLG==	^o10			; CHAR IS CURRENTLY FLAG CHAR
CH.PER==	^o20			; CHAR IS PUNCTUATION
CH.VOW==	^o40			; character is a vowel
CH.PNC==	^o100			; char is punctuation (for routine HYPHEN)
CH.UNL==	^o200			; char is not underlinable
CHTABL:: .BLKB	9.					; Nul-BS
	.BYTE	CH.FLC					; Tab
	.BLKB	22.					; LF-US
	.BYTE	CH.PNC!CH.UNL				; "space"
	.BYTE	CH.FLC!CH.PNC!CH.PER			; !
	.BYTE	CH.FLC!CH.PNC				; "
	.BYTE	CH.FLC					; #
	.BYTE	CH.FLC					; $
	.BYTE	CH.FLC					; %
	.BYTE	CH.FLC					; &
	.BYTE	CH.FLC					; '
	.BYTE	CH.FLC!CH.PNC				; (
	.BYTE	CH.FLC!CH.PNC				; )
	.BYTE	CH.FLC					; *
	.BYTE	CH.FLC					; +
	.BYTE	CH.FLC!CH.PNC				; ,
	.BYTE	CH.FLC					; -
	.BYTE	CH.FLC!CH.PER!CH.PNC			; .
	.BYTE	CH.FLC!CH.PNC				; /
	.BLKB	10.					; 0 - 9
	.BYTE	CH.FLC!CH.PER,CH.FLC!CH.PER		; : ;
	.BYTE	CH.FLC,CH.FLC,CH.FLC			; < = >
	.BYTE	CH.FLC!CH.PER,CH.FLC!CH.PNC		; ? @
	.BYTE	CH.VOW,0,0,0,CH.VOW,0,0,0		; A-H
	.BYTE	CH.VOW,0,0,0,0,0,CH.VOW,0		; I-P
	.BYTE	0,0,0,0,CH.VOW,0,0,0			; Q-X
	.BYTE	CH.VOW,0				; Y-Z
	.BYTE	CH.FLC					; [
	.BYTE	CH.FLC!CH.PNC				; \
	.BYTE	CH.FLC					; ]
	.BYTE	CH.FLC					; ^
	.BYTE	CH.FLC					; _ underscore
	.BYTE	CH.FLC					; `
	.BYTE	CH.VOW,0,0,0,CH.VOW,0,0,0		; A-H
	.BYTE	CH.VOW,0,0,0,0,0,CH.VOW,0		; I-P
	.BYTE	0,0,0,0,CH.VOW,0,0,0			; Q-X
	.BYTE	CH.VOW,0				; Y-Z
	.BYTE	CH.FLC,CH.FLC,CH.FLC,CH.FLC		; { - ~
	.BYTE	CH.PNC					; DEL
;
;	Contains character width
;
CHWADD::.WORDA	0
CHWTAB::.BLKB	128.*FNTSIZ			; Contains character widths
	.even
	.text
ILSBST:	.ASCIZ	/RNO -- Too many nested substitutions/
ILSBND:	.ASCIZ	/RNO -- Undefined substitution/
ILUNES:	.ASCIZ	/RNO -- Undefined escape seq./
EQER1:	.ASCIZ	/RNO -- Missing denominator in equation/
EQER2:	.ASCIZ	/RNO -- Missing right brace (}) in equation/
EQER3:	.ASCIZ	/RNO -- Too many nested fractions/
EQER4:	.ASCIZ	/RNO -- Syntax error in equation/
	.even
	.const
;
;	THE JUMP TABLE TO PARSE CHARS
;
	.code
	.WORDA	HLTER
	.WORDA	GOPAG
	.WORDA	GOTOC
	.WORDA	GOINX
	.WORDA	GOREP
	.WORDA	HLTER
	.WORDA	GOELP
	.WORDA	GOTAB
	.WORDA	GOBS
	.WORDA	GOQTS
	.WORDA	GOESC
	.WORDA	GOUNL
GCJMP:	.WORDA	GCDN
	.WORDA	GCUP
	.WORDA	GCACC
	.WORDA	GCCAP
	.WORDA	GCUNL
	.WORDA	SHFDN
	.WORDA	SHFUP
	.WORDA	GCQTS
	.WORDA	GCOVR
	.WORDA	GCIFL
	.WORDA	GCHYP
	.WORDA	GCESC
	.WORDA	GCSUB
	.WORDA	GCBRK
	.WORDA	GCINR
	.WORDA	GCCR
	.WORDA	GCTAB
	.WORDA	GCLF
	.WORDA	GCINR
	.WORDA	GCSPC
	.WORDA	GCINR
	.WORDA	GCSPF
	.WORDA	GCEQN1
	.WORDA	GCEQN2
	.WORDA	GCSIX
	.WORDA	GCPER
;
;	GET INPUT CHARACTER FROM SOURCE FILE AND INTERPRET IT
;		All registers except for R3 are destroyed
;
	.code
GCIN::	CALL	CCIN		; GET CHARACTER FROM FILE.
GCIN1:	MOVB	(R0),R0		; Get character type
GCIN2:	ADD	#GCJMP,R0	; Dispatch table
	JMP	@(R0)		; DISPATCH ACCORDING TO TABLE
;
;	HERE ARE SPECIAL CHARACTER CASES
;
;	UPPER CASE
GCDN:	TSTB	CASE		; CONVERSION NECESSARY
	BGE	NOCONV		; No ?
GCDN1:	ADD	#^o40,R1	; CONVERT CASE IF NECESSARY
	JMP	GCINR		;
;	LOWER CASE LETTERS
GCUP:	TSTB	CASE		; CONVERSION NECESSARY
	BLE	NOCONV
GCUP1:	SUB	#^o40,R1	; CONVERT TO UPPER CASE
NOCONV:	JMP	GCINR		;
;	CAPITALIZE FLAG
GCCAP:	TSTNEB	$CFLSW+1,NOCONV	; Flag temporarily disabled ?
	MOVB	#1,CASE		; SET WORD CAPITALIZE CONVERSION VALUE
	BR	GCIN		;
;	UNDERLINE FLAG
GCUNL:	TSTEQB	$UFLSW+1,1$	; Flag not disabled ?
	JMP	GCINR		; Temporarily disabled
1$:	BITEQB	#^C<SW.TDS>,$UNLSW,20$	; Permanently disabled ?
10$:	JMP	GCIN		; Permanently disabled ?
20$:	TSTNE	@EQSTK,10$	; Equation in progress ?
	MOV	#ULCHS,R1	; SET TO UNDERLINE CHARACTER
	MOVB	R1,$UNLLN	; Set to mark this line as underlined
	JMP	GCINO		;
;	OVERSTRIKE FLAG
GCOVR:	TSTEQB	$OFLSW+1,1$	; Flag not disabled ?
	JMP	GCINR		; Temporarily disabled
1$:	BISB	#SW.TDS,$AUHYP	; Temporary disable hyphenation
	TSTEQB	$OVRSW,2$	; Overstrike enabled
	JMP	GCIN		; Overstrike disabled ?
2$:	MOV	#BS,R1		; MAKE IT BACK SPACE
	MOV	PHSP,R0		; Horizontal spacing
	BGE	10$		; Not proportional ?
	NEG	R0		; Get width
10$:	ADD	R0,LINBK	; Add to remaining chars
	SUB	R0,SPCH		; Subtract from spacing characters
	JMP	GCINO		;
;	HYPHENATE FLAG
GCHYP:	TSTEQB	$HFLSW+1,1$	; Flag not disabled ?
	JMP	GCINR		; Temporarily disabled
1$:	TSTEQB	RETSW,2$	; No return ?
	JMP	GCLF		; Return ?
2$:	TSTNE	@EQSTK,50$	; Equation being formatted ?
	BISB	#SW.TDS,$AUHYP	; Set temporary no auto hyphenation
	MOV	PHSP,R0
	BGE	10$		; Not proportional ?
	NEG	R0		; Get positive width
10$:	SUB	LINBK,R0	; Check room on page
	BLE	15$		; Room for hyphen ?
12$:	JMP	GCIN		; No room
15$:	CMPEQB	LCH,#SPC,12$	; Last char space ?
	CMPEQB	LCH,#TAB,12$	; or tab ?
	CMPEQB	LCH,#NXS,12$	; or non expandable space ?
	CALL	BRKSV
	INCB	HYPSP		; Hyphenation Enabled this word
50$:	JMP	CONTIN
;	QUOTED SPACE FLAG
GCQTS:	TSTEQB	$QFLSW+1,1$	; Flag not disabled ?
	JMP	GCINR		; Temporarily disabled
1$:	TSTEQB	RETSW,2$	; No return
	JMP	GCLF		; Return ?
2$:	MOVB	ULOCK,CASE	; RESET CASE
GCQTS1:	MOV	#NXS,R1		; SET NON EXPANDABLE SPACE
	BISB	#SW.TDS,$AUHYP	; Set temporary no auto hyphenation
	BR	GCINR1		; AND SAVE IT
GCINR:	BIC	#^o1002,CASE	; Reset temporary upper case conversion
GCINR1:	CALL	PUBYT		; OUTPUT CHAR
	MOV	TESMSK,R4	; Cancel escapes ?
	BEQ	20$		; No ?
	CALL	ESCEND		; Cancel them
20$:	MOVB	LCH,R1
	MOV	R1,R0
	ADD	#CHTABL,R0
	BITEQB	#CH.BRK,(R0),GCINR2	; No AutoBreak ?
	CMPEQB	R1,#SPC,GCINR2	; Space ?
	TSTNEB	$AUBRK,GCINR2	; No auto break ?
	TSTNE	@EQSTK,GCINR2	; Equation being formatted ?
	TST	LINBK		; Past end of line ?
	BLT	GCINR2		; Yes ?
	BISB	#SW.TDS,$AUHYP	; set temporary no hyphenation
	TSTEQB	$TABPD,30$	; No right tabs ?
	CALL	BRKTS		; Set them up
	BR	GCINR2		; done
30$:	CALL	BRKSV		; Set up break here
GCINR2:	TSTEQB	$GCEND,80$	; Immediate end requested?
	DECB	$GCEND		; Decrement hyphenation count
	BLE	GCLF		; Done ?
80$:	JMP	GCIN		; Continue
GCLF:	CLRB	$GCEND
	TSTNEB	@EQSTK,10$	; Equation pending ?
	RETURN
10$:	CALL	BKSPI		; Backspace over LF
	CMPEQB	#2,@EQSTK,20$	; Denominator ?
	ADD	#EQ.NX,EQSTK	; Restack
	CMP	EQSTK,#EQSTK	; Check if too small
	BHI	14$		; Ok ?
	CALL	HLTER	
14$:	MOV	#EQER1,R0	; Missing denominator
	CALL	ILCMC
	JMP	GCIN		; And continue
20$:	MOV	#EQER2,R0	; Missing right brace
	CALL	ILCMC
	JMP	GCEQN2		; Attempt to end equation
GCINO:	CALL	PBYT		; OUTPUT CHAR
	JMP	GCIN		; CONTINUE PARSING INPUT
;	ACCEPT FLAG
GCACC:	TSTEQB	$AFLSW+1,1$	; Flag not disabled ?
	JMP	GCINR		; Temporarily disabled
1$:	CALL	CCIN		; READ CHARACTER NO TRANSLATION
	CMP	R1,#SPC		; Compare with space
	BGT	10$		; Printable ?
	BNE	5$		; Not space ?
	JMP	GCQTS1		; Space ? Make it quoted space
5$:	JMP	GCIN1		; Less than space ?
10$:	BIC	#^o1002,CASE	; Reset temporary upper case conversion
	CALL	PUBYT		; OUTPUT CHAR
	BIS	#^o200,LCH	; Set for quoted char
	MOV	TESMSK,R4	; Cancel escapes ?
	BEQ	20$		; No ?
	CALL	ESCEND		; Cancel them
20$:	BR	GCINR2
;
;	ROUTINE TO READ INPUT FROM FILE AND REMOVE BAD INPUT
;	output:	R0=	Location in GCTABL
;		R1=	CHARACTER READ
;		Carry clear if OK
;		R2-R5	are saved
;
CCIN::	MOV	BUFAD,R1	; input buffer header
	CALL	GBYT1		; get input
	BLOS	20$		; At end of buffer ?
	BIC	#^C<^o177>,R1	; CLEAR EXCESS BITS
	MOV	R1,R0
	ADD	#GCTABL,R0
	TSTB	(R0)		; LEGAL CHARACTER?
	BLT	CCIN		; NO GET ANOTHER
	CLC
	RETURN
20$:	BCS	25$		; Carry set ?
	CALL	BKSPI		; Backup over 0
25$:	TSTEQB	SUBSTK,30$	; End of input line ?
	CALL	POPINS		; Go down one entry
	BR	CCIN		; try again
30$:	CALL	FIN		; NO. READ FROM FILE
	BCC	CCIN		; Successful input ?
	RETURN			; None to get
;
;	Get params from current level of subst only
;	output:	R0=	Location in GCTABL
;		R1=	CHARACTER READ
;		Carry clear if OK
;
CCINP::	MOV	BUFAD,R1
	CALL	GBYT1		; get input
	BCS	30$
	BIC	#^C<^o177>,R1	; CLEAR EXCESS BITS
	BEQ	20$		; At end of buffer ?
	MOV	R1,R0
	ADD	#GCTABL,R0
	TSTB	(R0)		; LEGAL CHARACTER?
	BLT	CCINP		; NO GET ANOTHER
	CLC
	RETURN
20$:	CALL	BKSPI		; Backup over input char
30$:	CLR	R1
	SEC
	RETURN
;
;	routine to parse substitution - SUBSTITUTE FLAG
;
GCSUB:	TSTEQB	$SBFSW+1,1$	; Flag not disabled ?
	JMP	GCINR
1$:	MOV	R3,-(SP)	; save
	MOV	BUFAD,R3	; get buffer header for input
	MOV	BF.FUL(R3),R1	; For traceback
	DEC	R1		; Points to traceback point
	MOV	R1,BF.VSP(R3)	; Save it
	MOV	#TBUFF-1,R2	; temporary buffer
	MOVB	R1,(R2)+	; Save flag
	CLRB	(R2)		; Clear in case no more
	MOV	BF.FUL(R3),-(SP) ; save current location
	MOV	#SUBMAX,R4	; max number of char/label
50$:	CALL	GBYT		; get input
	CMP	R1,#SPC		; non printable?
	BLE	60$		; yes, done
	MOV	R1,R0
	ADD	#GCTABL,R0
	CMPNEB	(R0),#GC.LC,55$	; Not lower case ?
	CMPEQ	R2,#TBUFF,55$		; Not first char ?
	SUB	#^o40,R1		; Make it lower case
55$:	MOVB	R1,(R2)+	; Save char
	SOB	R4,50$		; no, continue
60$:	CLRB	(R2)+		; Chock end of string
	MOV	BF.FUL(R3),BF.HED(R3)	; End of string
	MOV	#TBUFF,R2	; Start of buffer
	CMPNEB	(R2),$SBFSW,65$	; First char not substitute flag ?
	MOVB	#DOLAR,(R2)	; Make first char $
65$:	MOV	(SP)+,R1	; current location
	CALL	FNDBF		; go back to it
	MOV	#TBUFF,R0	; Starting address
	CALL	FNDSB		; Find substitution
	BCC	80$		; Found it ?
	CALL	ILCMC
80$:	MOV	(SP)+,R3	; restore
	JMP	GCIN
;
;	Find substitutions All registers destroyed
;
FNDSB::	MOV	R0,ADDR		; Start of string
	CMPB	SUBSTK,SUBSTK+1	; max stack reached?
	BLO	40$		; no
	MOV	#ILSBST,R0	; Too many nestings error
	BR	20$
10$:	CALL	POPINS		; Back in stack
	MOV	#ILSBND,R0	; Undefined substitution error
20$:	SEC
	return
40$:	CALL	PSHINS		; Set up input stack
	CALL	BEGBF		; Start at beginning
	CALL	GWRD		; First index
	BCS	10$		; None?
50$:	TSTEQ	R1,10$		; None ?
	CALL	FNDBF		; Find next entry
	CALL	GWRD		; get next index
	BCS	10$		; end, no escape found
	MOV	R1,R4		; save
	MOV	ADDR,R2		; temporary buffer
	MOV	BF.FUL(R3),BF.SPC(R3)	; Save index for traceback
60$:	CALL	GBYT		; Get next char in key word table
	BCS	10$		; None?
	BITEQ	R1,#^o140,90$	; End of search ?
70$:	CMPEQB	R1,(R2)+,60$	; match?
	TSTB	@ADDR		; Check first byte
	BGT	80$		; Not command ?
	DEC	R2		; Go back to last char checked
	CMPEQB	R1,#SPC,60$	; Space in table ?
	CMPNEB	-1(R2),#SPC,80$	; Char before last not space ?
	CMPEQB	(R2)+,#SPC,70$	; Current space ?
80$:	MOV	R4,R1		; Next entry index
	BR	50$		; search again
90$:	MOV	BF.FUL(R3),BF.VSP(R3)	; Set traceback
	CLR	BF.HED(R3)	; Set no traceback
	TSTB	@ADDR		; Check for command
	BGT	92$		; Not commad
	MOVB	(R2),R0		; Get terminal char
	BITNEB	#^o100,R0,80$	; Alpha char ?
92$:	BITEQB	R1,#7,95$	; Not a number ?
	MOV	R1,R5
	CLR	-(SP)		; Chock stack
93$:	CALL	GWRD		; get the number
	TSTEQ	R1,94$		; Zero ?
	MOV	R1,-(SP)	; Save number
94$:	SOB	R5,93$
	MOVB	#MINUS,$SEPR	; Page separator
	CALL	ENDBF		; Set to end of buffer
	MOV	BF.FUL(r3),R4	; Save index
	MOV	R4,BF.VSP(R3)	; Set traceback
	CALL	PAGCV		; And convert number
	MOV	BF.FUL(R3),BF.HED(R3)	; Set traceback
	CALL	CBYT		; Chock it
	MOV	R4,R1		; Beginning of string
	CALL	FNDBF		; Set to scratch location
95$:	MOV	R2,R1		; end of string
	SUB	ADDR,R1		; find string length
	MOVB	SUBSTK,R3	; Get subst stack
	ADD	#BUFADD-$WORDL,R3	; Old stack
	MOV	(R3),R3		; Old stack
	ADD	BF.FUL(r3),R1	; Add offset to start of string
	CALL	FNDBF		; Set to end of string
	TSTB	@ADDR
	BLT	110$		; Command ?
	TSTEQB	$SUBSW,110$	; substitution not suppressed?
100$:	JMP	POPINS		; Reset subst
110$:	CLC
	RETURN			; done, continue with normal sequence
;
;	TAB character handled here.  It is expanded.
;
GCTAB:	TSTNEB	$TBFSW+1,1$	; Flag disabled ?
	TSTNE	@EQSTK,1$	; Equation being formatted ?
	TSTNEB	$CENSW,1$	; Centering enabled ?
	TSTNEB	$RIGSW,1$	; Right justify enabled
	TSTEQB	$TABSW,2$	; Tabs allowed ?
1$:	JMP	GCSPC		; NO!
2$:	BISB	#SW.TDS,$AUHYP	; No autohyphenation now
	MOVB	ULOCK,CASE	; RESTORE CASE
	CALL	BRKTS		; Test + execute right tabs
	CLR	R2
	CALL	TABB		; FIND WHERE NEXT TAB STOP IS
	CMP	R2,LINBK	; Compare with remaining dist
	BLE	20$		; It is OK ?
	TST	LINBK		; Currently too long ?
	BLT	10$		; Yes
	CALL	BKSPI		; Backup over tab to save it
	CALL	BRKSV		; No, put break here
10$:	MOVB	#TAB,R1		; Current char
	RETURN
20$:	MOV	#TABBF,R1	; Get status
	CALL	GBYT1		;
	BITNE	#TB.L,R1,30$	; Tab only left
	BITNE	#TB.R!TB.C,R1,25$; Tab right or center
	TSTEQB	$TABLF,30$	; Left justify  tabs ?
	MOV	#TB.R,R1	; Set it to right
25$:	MOV	PHSP,R2		; Only 1 space for right justify
	BGE	26$		; Positive
	NEG	R2		; Make it positive
26$:	MOVB	R1,$TABPD	; Set for right tab
30$:	CMPNEB	LCH,#TAB,35$	; Was last char not tab ?
	TSTEQ	LTAB,35$	; No tab pending
	CALL	ADDTAB		; Add r2 to previous tab
	BR	TABXIT		;
35$:	SUB	R2,LINBK	; Subtrac from remaining space
	ADD	R2,SPCH		; Add to spacing characters
	TSTEQB	BRCNT,36$	; Beginning of line ?
	CALL	BKSPI		; Backup over tab to save it
	CALL	BRKSV		; Save break before tab
	CALL	CCIN
	BR	37$
36$:	CALL	BRKSV		; Set break after tab
37$:	MOVB	#TAB,LCH	; LAST CHAR
	MOVB	#TABO,R1	; Set to output tab
	MOVB	@TABBF+BF.ADD,R4; Ellipses count
	BIC	#^C<TB.CNT>,R4	; Clear count
	BNE	39$		; Ellipses spec ?
	TSTEQB	$ELIPS,40$	; No ellipses?
39$:	TST	PHSP		; Check if proportional
	BLE	40$		; Yes ?
	MOVB	#ELIP,R1	; Yes, set to output ellipses
40$:	CALL	PBYT		; Into buffer
	MOV	BF.FUL(R3),LTAB	; Address of last tab char
	MOV	R2,R1		; Number of spaces
	CALL	PBYT		; Into buffer
	TSTNEB	$ELIPS,45$	; Ellipses ?
	TSTEQ	R4,TABXIT	; No ellipses ?
45$:	TST	PHSP		; Check if proportional
	BLE	TABXIT		; Yes ?
	MOV	R4,R1		; Ellipses count
	CALL	PBYT
	TSTEQ	R4,TABXIT	; Done ?
50$:	MOV	#TABBF,R1
	CALL	GBYT1		; Put ellipses into buffer
	CALL	PBYT
	SOB	R4,50$
TABXIT:	JMP	GCIN		; Next char
;
;	End of line action, space if fill disabled
;
GCCR:	CALL	BRKTS		; Test tab + break
	TSTNEB	$BRKSW,10$	; Break line enabled ?
	TSTNEB	$CENSW,10$	; Centering enabled ?
	TSTNEB	$RIGSW,10$	; Right justify enabled
	BITNE	#FILLF,F.1,GCSPC ; Fill enabled ?
10$:	TST	LINBK		; Past end of line ?
	BGE	TABXIT		; No ?
	TSTNE	@EQSTK,TABXIT	; Equation in progress ?
	RETURN			; Yes !
;
;	Handle spaces in input stream
;
SPCXIT:	JMP	GCIN
GCSPC::	TSTEQB	RETSW,1$	; Not Return ?
	RETURN
1$:	MOVB	ULOCK,CASE	; RESTORE CASE
	TSTEQ	@EQSTK,2$	; Equation being formatted ?
	JMP	25$		; Yes
2$:	TST	LINBK		; Line full ?
	BGE	10$		; NO ?
	RETURN			; Yes, break for full line
10$:	BITEQB	#CH.BRK,CHTABL+SPC,15$	; No AutoBreak ?
	CALL	BRKTS		; Test and set up right tabs
15$:	BITEQ	#FILLF,F.1,30$	; FILL disabled ?
	MOVB	LCH,R1		; GET PREVIOUS CHARACTER WHAT WAS IT?
	BEQ	SPCXIT		; Start of new line ?
	BLT	30$
	CMPEQB	R1,#SPC,SPCXIT	; Space before space ?
	CMPEQB	R1,#TAB,SPCXIT	; Tab before space ?
	CMPEQB	R1,#NXS,SPCXIT	; Non expandable space before space ?
	CMPEQB	R1,#CPER,17$	; Is it following period char?
	TSTEQB	$PERSW,30$	; Automatic punctuation spacing disabled ?
	MOV	R1,R0
	ADD	#CHTABL,R0
	BITEQB	#CH.PER,(R0),30$ ; Not Punctuation before space ?
17$:	CMP	LINBK,#1	; Space left ?
	BLE	30$		; No
20$:	CALL	50$		; Set up for space
	CALL	PUBYT		; Save space
	TSTEQB	$GCEND,25$	; Immediate end ?
	DECB	$GCEND		; Done ?
	BNE	25$		; No ?
	RETURN
25$:	MOV	#NXS,R1		; Next output non expandable space
	BR	40$		;
30$:	CALL	50$		;
40$:	BICB	#SW.TDS,$HYPSW	; Allow hyphenation
	BICB	#SW.TDS,$AUHYP	; Allow auto hyphenation
	CLRB	HYPSP
45$:	JMP	GCINR1		; RETURN CHAR.
;
;	Section to insert spaces
;
50$:	BITEQB	#CH.BRK,CHTABL+SPC,55$	; No AutoBreak ?
	CALL	BRKSV		; Set up for break here
55$:	TSTNEB	$NOSPC,70$	; No expandable spaces allowed ?
	INC	SPCNT		; COUNT THIS SPACE
	MOV	#SPC,R1		; SPACE CHARACTER (EXPANDABLE)
60$:	RETURN			;
70$:	MOV	#NXS,R1		; Make it non expandable
SPCRET:	RETURN
;
;	Period flag here
;
GCPER:	TSTNEB	$PFLSW+1,10$	; Period flag disabled ?
	MOVB	#CPER,LCH	; Last is period flag
	JMP	GCIN
10$:	JMP	GCINR		; Output char
;
;	break flag here
;
GCBRK:	TSTEQB	$BRFSW+1,1$	; Flag not disabled ?
	JMP	GCINR
1$:	TSTNEB	RETSW,SPCRET	; Return ?
	TSTNE	@EQSTK,CONTIN	; Equation being formatted ?
	BISB	#SW.TDS,$AUHYP	; set temporary no hyphenation
	TST	LINBK		; Past end of line
	BGE	10$		; Not yet
	RETURN
10$:	TSTEQB	$TABPD,20$	; No right tabs ?
	CALL	BRKTS		; Set them up
	BR	CONTIN		; done
20$:	CALL	BRKSV		; Set up break here
CONTIN:	TSTNEB	$CONT,20$	; Continue disabled ?
	CALL	CCIN		; Get next char
	CMPNEB	R1,#CR,40$	; Not CR
	CALL	FIN		; Next line
	CALL	LSINSV		; Save input line
20$:	JMP	GCIN		; And next line
40$:	JMP	GCIN1		; next char
;
;	Test and set up right tab
;
BRKTS:	MOVB	$TABPD,R0	; Check pending tabs
	BNE	2$		; tab pending?
1$:	RETURN
2$:	CLRB	$TABPD		; No more tabs pending
	TSTEQ	LTAB,1$		; No tab address ?
	MOV	#-1,R2		; Initial tab
	BITEQ	#TB.C,R0,5$	; No centered tabs ?
	MOV	SPCH,R0		; Get text size
	SUB	LSPCH,R0	; Minus previous size
	DEC	R0		; Account for tab
	ASR	R0		; Divided by 2
	SUB	R0,R2		; Subtract from Offset
5$:	CALL	TABB		; Find next tab stop
	DEC	R2
ADDTAB:	CMP	R2,LINBK	; Compare with remaining line
	BGT	10$		; Too big ?
	ADD	R2,SPCH		; Spacing chars
	SUB	R2,LINBK	; Current length this line
	MOV	LTAB,R1		; Previous address
	CALL	FNDBF
	CALL	GBYT
	ADD	R1,R2		; Add on more
	MOV	LTAB,R1
	CALL	FNDBF
	MOV	R2,R1
	CALL	PBYT	; Increment old tab
	CALL	ENDBF
10$:	RETURN
;
;	Set up break (save current character status)
;
BRKSV::	CLRB	HYPSP
	CALL	LSINSV		; save input addresses
	INC	BRCNT		; count breaks this line
	MOV	PHSP,LPHSP	; Spacing at break
	MOV	CASE,CASSAV	; SAVE CURRENT CASE
	MOV	BF.FUL(R3),LSTSP ; POSITION IN BUFFER
	MOV	ESMSK,LESMSK	; Save current escape mask
	MOVB	$UNLSW,LUNLSW	; And underline status
	MOVB	LCH,LSCH	; SAVE CHAR BEFORE SPACE
	MOV	SPCNT,SPCNSV	; Save old space count
	MOV	SPCH,LSPCH	; Save current spacing char count
	RETURN

;
;	Here we handle Index flag
;
GCIFL:	TSTEQB	$IFLSW+1,10$	; Autoindex flag on ?
	JMP	GCINR		; No, ouput char
10$:	CALL	AINDEX		; Do autoindex
	JMP	GCIN		; Continue
;
;	SUBINDEX FLAG
;
GCSIX:	TSTEQB	$SIFSW+1,10$	; Autoindex flag on ?
	JMP	GCINR		; No, ouput char
10$:	CMPNEB	LCH,#SPC,20$	; Not last space
	MOV	LSTSP,R1	; Abort last space
	CALL	RSTBF		; Terminate buffer here
20$:	CLR	LCH		; Set last to null
	MOVB	#SXCHR,R1	; Get subindex character
	JMP	GCINO		; Save subindex flag
;
;	HERE WE HANDLE SEPARATE ESCAPE SEQUENCES
;
GCESC:	TSTEQB	$EFLSW+1,1$	; Flag not disabled ?
	JMP	GCINR
1$:	MOV	R1,R5		; First character
	MOV	BUFAD,R0	; Get input buffer
	MOV	BF.FUL(R0),BF.VSP(R0)	; Current index saved
	DEC	BF.VSP(R0)	; For error traceback
	CALL	CCIN		; GET NEXT CHAR
GCES1:	CALL	ESCSEQ		; ESCAPE SEQUENCE?
	BCC	10$		; No ?
	MOV	#ILUNES,R0	; Message undefined escape
	CALL	ILCMC		; Output error message
10$:	JMP	GCIN		; NEXT CHAR
;
;	Special Flag character detected
;
GCSPF:	TSTEQB	$SPFSW+1,1$	; Flag not disabled ?
	JMP	GCINR
1$:	MOV	#CIRCUM+^o100000,R5	; Move in shift up operator+ temp flag
	CALL	ESCSEQ		; Execute sequence
	BCC	10$		; Not executed ?
	MOV	#ILUNES,R0	; Message undefined escape
	CALL	ILCMC		; Output error message
10$:	JMP	GCIN		; Continue
;
;	SUBROUTINE TO FIND ESCAPE SEQUENCE FROM TABLE
;
;		R5=0 for begin
;		  =non zero for end seq
;		R4=Escape sequence mask
;		R3	is preserved/ all other registers changed
;
	.enabl	LSB
ESCBEG:: CLR	R5		; Look for begin sequence
	BR	ESCEN1
ESCEND:: MOV	#^o177,R5		; Look for end sequence
ESCEN1:	TSTEQ	R4,7$		; No escapes ?
	TSTNEB	$ESCSW,7$	; Escapes disabled ?
	MOV	R3,-(SP)	; Save current buffer
	MOV	#ESCBF,R3	; Escape buffer
	CALL	BEGBF		; Start at beginning
	MOV	(SP)+,R3	; Restore
2$:	TSTEQ	R4,7$		; Done ?
	CALL	11$		; Do next sequence
	BCC	2$		; Ok ?
7$:	RETURN
11$:	MOV	R3,-(SP)	; Save current buffer
	MOV	#ESCBF,R3	; Escape buffer
12$:	CALL	GBYT		; Get count
	BCC	13$		; Not Done ?
	  MOV	(SP)+,R3	; restore
	  SEC			; NO SEQ FOUND
	  RETURN
13$:	MOV	BF.FUL(R3),-(SP); And current index
	MOV	R1,R2		; Character count
	CALL	GBYT		; Skip first char
	CALL	GBYT		; Skip second char
	CALL	GBYT		; Get status
	MOV	R1,-(SP)	; Save status
	BITNEB	#ES.LCK,R1,4$	; Is this lock status ?
3$:	  TST	(SP)+		; Pop status
	  MOV	R2,R1		; number of bytes to skip
	  ADD	(SP)+,R1	; New index
	  CALL	FNDBF		; skip them
	  BR	12$		; Try again
4$:	CALL	GBYT		; Get lock byte
	BLT	5$		; Unlock ?
	  TSTNEB	R5,3$		; Lock desired ?
	  BIC	#^C<^o17>,R1	; Clear extra bits
	  MOV	#1,R0
	  ASH	R1,R0
	  BITEQ	R0,R4,3$	; Not requested escape ?
	  BIC	R0,R4		; Clear 1 bit
	  BR	31$		; Ok!
5$:	TSTEQB	R5,3$		; Unlock desired ?
	  BIC	#^C<^o17>,R1	; Clear extra bits
	  MOV	#1,R0
	  ASH	R1,R0
	  BITEQ	R0,R4,3$	; Not requested escape ?
	  BIC	R0,R4		; Clear 1 bit
	  BITNE	R0,TESMSK,6$	; Clearing temporary bit?
	  JMP	31$
6$:	  JMP	32$
;
;	R5	= first char
;	R1	= second char
;	R3,R5	are preserved
;	C	= set if sequence not found
;
ESCSEQ:	MOV	R3,-(SP)	; save current buffer
	MOV	#ESCBF,R3	; escape buffer
	MOV	R1,R4		; SAVE CHAR
	CALL	BEGBF		; Start at beginning
10$:	CALL	GBYT		; get beginning of sequence
	BCC	20$		; not end of table?
17$:	MOVB	R4,R1		; GET CHAR BACK
	MOV	(SP)+,R3	; restore
	SEC			; NO SEQ FOUND
	RETURN
20$:	MOV	BF.FUL(R3),-(SP)	; And save current index
	MOV	R1,R2		; number of bytes in sequence
	CALL	GBYT		; get next bytes
	CMPNEB	R5,R1,25$	; MATCH WITH CHAR?
	CALL	GBYT		; get next bytes
	CMPEQB	R4,R1,30$	; MATCH WITH CHAR?
25$:	MOV	R2,R1		; number of bytes to skip
	ADD	(SP)+,R1	; add on current index
	CALL	FNDBF		; skip them
	BCS	17$		; Bad address
	BR	10$
30$:	TSTEQB	$ESCSW,27$	; ESCAPE SEQUENCES not DISABLED?
	JMP	55$		; Disabled
27$:	BISB	#SW.TDS,$AUHYP	; set temporary no hyphenation
	CALL	GBYT		; Get flag byte
	MOV	R1,-(SP)	; Save bit mask
	BITEQ	#ES.LCK,(SP),31$	; Not lock/Unlock ?
	  CALL	GBYT			; Get lock word
	  BLT	21$			; Unlock ?
	  BIC	#^C<^o17>,R1		; Clear extra bits
	  MOV	#1,R0
	  ASH	R1,R0
	  BITEQ	R0,ESMSK,272$		; Not locked on ?
	  JMP	54$			; currently locked on
272$:	  BIS	R0,ESMSK		; Lock it on
	  BITEQ	#^o100000,R5,31$	; Not temporary lock ?
	  BITEQ	#ES.CHR,(SP),31$	; Not Temporary sequence ?
	  BIS	R0,TESMSK		; Set temporary mask
	  BR	31$
21$:	  BIC	#^C<^o17>,R1		; Clear extra bits
	  MOV	#1,R0
	  ASH	R1,R0
	  BITNE	R0,ESMSK,32$		; Not locked off ?
	  JMP	54$			; Currently locked off ?
32$:	  BIC	R0,ESMSK		; Lock it off
	  BIC	R0,TESMSK		; Clear temporary mask also
31$:	BITEQ	#ES.VSP,(SP),33$	; No vertical spacing
	  CALL	GBYT			; Get vertical spacing
	  TSTNEB	$PAGNG,299$	; No paging ?
 	  SUB	R1,LINEC3		; Decrement lines left
;	  ADD	R1,BF.VSP(R3)		; Add to saved spacing	- SPR 015
	  MOV	2*$WORDL(SP),R0		; Location of buffer	- SPR 015
	  ADD	R1,BF.VSP(R0)		; Add on line spacing	- SPR 015
299$:	  ADD	CURVS,R1		; Add on current VS
	  MOV	R1,CURVS		; Save current
	  CMP	R1,MINVS		; Compare with min
	  BGT	311$			; Bigger ?
	  MOV	R1,MINVS		; New min
311$:	  CMP	R1,MAXVS		; Compare with max
	  BLT	312$			; Smaller ?
	  MOV	R1,MAXVS		; New max
312$:;	  ADD	R1,BF.VSP(R3)		; Count deferred text line - SPR 015
33$:	BITEQ	#ES.HSP,(SP),40$	; No Horizontal spacing
	  CALL	GBYT			; Get horizontal spacing
	  BITNE	#ES.PSP,(SP),35$	; Permanent spacing ?
	  MOVB	R4,LCH		; Set last char
	  ADD	R1,SPCH		; Count spacing chars
	  SUB	R1,LINBK	; And remove from available spaces
	  BR	40$
35$:	  BICB	#^o40,$NOSPC	; Set for expandable spaces ok
	  BICB	#^o40,$TABSW	; Enable tabs
	  MOV	R1,PHSP		; Set permanent horiz spacing
;	  BICB	#SW.TD2,$AUHYP	; Temporary hyphenation off
	  TSTNEB	$VARSP,40$	; Variable spacing on ?
	  CMPEQ	R1,#1,40$	; Spacing 1 ?
;	  BISB	#SW.TD2,$AUHYP	; set temporary no hyphenation
	  BISB	#^o40,$NOSPC	; Set no expandable spaces
	  BISB	#^o40,$TABSW	; Set no tabs
40$:	TST	(SP)+		; Pop saved flags
	MOV	(SP)+,R1	; Index for transfer
	ADD	#2,R1		; Points to status now
	SUB	#2,R2		; Number of bytest to transfer
	CALL	FNDBF		; Go back to start of sequence
	MOV	(SP)+,R3	; Output buffer
	MOV	#ESC,R1		; Mark escape sequence in output buffer
	CALL	PUBYT1		; OUTPUT IT
	MOV	R2,R1		; Number of bytes in seq
	CALL	PBYT		; Save it *** Jan 1,1986
50$:	MOV	#ESCBF,R1	; escape buffer
	CALL	GBYT1		; get next bytes
	CALL	PBYT		; OUTPUT CHAR
	SOB	R2,50$
	BR	60$
54$:	TST	(SP)+		; Pop stack
55$:	TST	(SP)+		; Pop stack
	MOV	(SP)+,R3	; Restore buffer address
60$:	CLC			; SUCCESS
	RETURN			;
	.DSABL	LSB
;
;	ROUTINE TO FIND NEXT TABSTOP FOR OUTLIN ROUTINE.
;	INPUT	R2=	Space to include
;	OUTPUT	R2=	DISTANCE TO NEXT STOP
;		R0,R1 are destroyed
;
TABB:	MOV	R3,-(SP)	; Save R3
	MOV	R2,-(SP)	; And R2
	MOV	#TABBF,R3	; Set to search tab buffer
	CALL	BEGBF		; Start at beginning
	MOV	LMARG,R0	; Left margin
	ADD	INDCT,R0	; Plus indentation
	CALL	CVHSP		; Get horiz spacing
	ADD	R1,R2
	ADD	SPCH,R2		; Number of spacing chars
10$:	CALL	GWRD		; Get next tab
	BCC	20$		; Not End of buffer ?
	MOV	LINBK,R2	; Set at end of line
	SUB	(SP),R2		; Plus current amount
	BGT	40$		; At least 1 space?
	MOV	#1,R2		; No make it 1
	BR	40$
20$:	MOV	R1,R0
	CALL	CVHSP		; Horizontal spacing
	CMP	R1,R2		; Compare tab with current position
	BGT	30$		; Larger than current ?
	CALL	GBYT		; Get status
	BIC	#^C<TB.CNT>,R1	; Chars to skip
	BEQ	10$		; None
	ADD	BF.FUL(R3),R1	; Add on current location
	CALL	FNDBF		; Skip em
	BCC	10$		; Is it OK ?
	CALL	HLTER		; FATAL ERROR ****
30$:	SUB	R2,R1		; GET DISTANCE TO TABSTOP
	MOV	R1,R2		; Get into R2
40$:	TST	(SP)+		; Pop old R2
	MOV	(SP)+,R3	; Restore
	RETURN			;
;
;	UPPER CASE FLAG
;
	.ENABL	LSB
SHFUP:	TSTEQB	$SFLSW+1,1$	; Flag not disabled ?
	JMP	GCINR
1$:	CALL	CCIN		; READ A CHARACTER
	MOV	R1,R0
	ADD	#CHTABL,R0
	BITEQB	(R0),#CH.FLG,40$	; Not flag character ?
	CMPNE	R1,$UFLSW,10$	; LOCK ON UNDERLINE?
	BICB	#SW.TDS,$UNLSW	; UNDERLINING POSSIBLY ON
	BR	30$
10$:	CMPNE	R1,$CFLSW,20$	; NOT LOCK UPPER CASE?
	MOV	#^o401,CASE	; SET UPPER CASE + LOCK
	BR	30$		; READ ONOTHER CHAR
20$:	CMPNE	R1,$SFLSW,40$	; NOT UNLOCK ALL?
	CALL	UPCAS		; SET TO UPPER CASE
30$:	JMP	GCIN		; AND GO READ ANOTHER CHARACTER
40$:	MOVB	$SFLSW,R5	; MATCH CHAR
	CALL	ESCSEQ		; SEARCH FOR ESCAPE SEQUENCE
	BCC	30$		; FOUND ONE!
	MOV	R1,R0
	ADD	#GCTABL,R0
	MOVB	(R0),R0		; CHAR TYPE?
	CMPNE	R0,#GC.LC,50$	; NOT LOWER CASE?
	JMP	GCUP1		; LOWER CASE, SHIFT IT.
50$:	CMP	R0,#GC.LC	; ALPHABETIC CHAR?
	BLE	60$		; YES, DO NOT EXECUTE IT
	JMP	GCIN2
60$:	JMP	GCINR
;
;	LOWER CASE FLAG DETECTED
;
SHFDN:	TSTEQB	$LFLSW+1,2$	; Flag not disabled ?
	JMP	GCINR
2$:	CALL	CCIN		; GET ANOTHER CHARACTER
	MOV	R1,R0
	ADD	#CHTABL,R0
	BITEQB	(R0),#CH.FLG,80$	; Not flag character ?
	CMPNE	R1,$UFLSW,70$	; UNLOCK UNDERLINE?
	BISB	#SW.TDS,$UNLSW	; UNDERLINING OFF
	BR	30$		;
70$:	CMPNE	R1,$LFLSW,80$	; NOT LOWERCASE LOCK?
	CALL	LWCAS		; SET LOWER CASE SHIFT
	BR	30$		;
80$:	MOVB	$LFLSW,R5	; MATCH CHAR
	CALL	ESCSEQ		; HANDLE ESCAPE SEQUENCES
	BCS	82$		; No escape seq ?
	BR	30$		; Found esc seq
82$:	MOV	R1,R0
	ADD	#GCTABL,R0
	MOVB	(R0),R0		; CHAR TYPE?
	CMPNE	R0,#GC.UC,50$	; NOT UPPER CASE?
	BITNE	#UPCSW,$SWTCH,60$ ; IS UP SHIFT MANDATED?
	JMP	GCDN1		; SHIFT TO LOWER CASE
	.DSABL	LSB

;
; CASE SELECTION COMMANDS
;

	.ENABL	LSB
LWCAS::	MOV	#-1,R1		; SET FOR CONVERSION TO LOWER CASE
	BR	10$		;
UPCAS::	CLR	R1		; SET FOR NO CASE CONVERSION
10$:	BITEQ	#UPCSW,$SWTCH,20$	; Not Upper case only?
	MOV	#^o401,R1		; FORCE TO UPPER CASE
20$:	MOV	R1,CASE		; SET CASE CONVERSION
	RETURN			;
	.DSABL	LSB
;
; COROUTINE TO SHIFT TO UPPER CASE TEMPORARILY
;

SHFUC::	MOV	(SP),-(SP)	; COPY RETURN ADDRESS
	MOV	CASE,$wordl(SP)	; SAVE CURRENT CASE
	MOV	#^o401,CASE	; UPPER CASE ONLY
	CALL	@(SP)+		; CALL THE CALLER BACK
	MOV	(SP)+,CASE	; RESTORE PREVIOUS CASE
SHXIT:	RETURN			;
;
;	PUT STRING ENDED BY ZERO BYTE TO BUFFER
;		R0=	STRING ADDRESS
;
PSTRZB::MOV	R2,-(SP)	; Save R2
	MOV	R0,R2
10$:	MOVB	(R2)+,R1	; Get char
	BEQ	20$		; If zero done ?
	CALL	PBYT		; PUT IT
	BR	10$		; CONTINUE
20$:	MOV	(SP)+,R2	; Restore
	RETURN

;
; ROUTINES TO OUTPUT A STRING TO THE OUTPUT FILE
;	R3=BUFFER ADDRESS FOR STRING
;		Output terminates at either null or end of input buffer
;		Z or C tell user what form of termination occurred.
;
;		This one starts at top of buffer
PSTRPA::CALL	BEGBF		; SET TO TOP OF BUFFER
	CLR	EXSP1		; No multiple spaces
	CLR	EXSP2		; No multiple spaces
	MOVB	#-1,EXSP3	; No multiple spaces
	CLRB	EXSTAT		; No status
	CLR	EXMSP		; No multiple micro spaces
;
;	This one starts anywhere in buffer
;		R3 is preserved all other registers destroyed
;
CCOUT::	CLRB	$ULOSW		; No underlining at first
CCOUT2:	CALL	GBYT		; Get 1 byte
	BHI	1$		; Not done ?
	RETURN			; Done on zero or carry set
1$:	BGT	10$		; No extra bits
	INCB	$ULOSW		; Set underline
10$:	BIC	#^C<^o177>,R1	; Clear extra bits
	CMPEQB	R1,#SPC,GOSPC	; Is it space ?
	MOV	R1,R0
	ADD	#GCTABL,R0
	MOVB	(R0),R0		; GET CHAR TYPE
	BGE	GOPRN		; PRINTABLE
	ADD	#GCJMP,R0
	JMP	@(R0)		; DISPATCH ACCORDING TO TABLE
;	Handle single underline
GOUNL:	INCB	$ULOSW
	BR	CCOUT2
;	Printable char
GOPRN:	CALL	CCPRN		; Print 1 char
	BR	CCOUT
GOSPC:	MOV	EXMSP,-(SP)	; Micro spaces
	MOV	EXSP1,-(SP)	; YES. HOW MANY MULTIPLE SPACES?
	DEC	EXSP2		; TO EXTRA BLANKS YET?
	BGE	70$		; NO.
	TSTEQB	EXSP3,80$	; EXTRA SPACES TO RIGHT?
	BR	90$		; LEFT. NO MORE EXTRAS, JUST LOOP
70$:	TSTEQB	EXSP3,90$	; NO EXTRA SPACES LEFT OR RIGHT?
80$:	BITEQB	#HD.VAR,EXSTAT,85$	; No micro spacing ?
	INC	$wordl(SP)		; Micro spacing count
	BR	90$
85$:	INC	(SP)		; Extra space to output
90$:	BITEQB	#HD.VAR,EXSTAT,110$	; No micro spacing ?
	MOV	$wordl(SP),R1	; count
	DEC	R1
	BLE	110$		; micro count too small ?
	TSTEQB	$ULMSW,94$	; Underline by BS ?
	  MOV	CPOS,R0		; Current position
	  CMP	R0,#ULNSZ	; check with max
	  BHI	95$		; Too big ?
	  BIS	#^o200,R1	; Now is count for underline buffer
	  MOVB	R1,UBUFF-1(R0)	; Into buffer
	  MOVB	#-1,$UNLRS
	  INC	CPOS		; Next position
	  BR	95$
94$:	TSTEQB	$ULOSW,95$	; No underlining ?
	  MOV	#1,R2		; Number of chars to underline
	  CALL	CCUNL
95$:	MOV	$wordl(SP),R1	; micro spaces
	DEC	R1
	CALL	VAROUT		; Output variable escap seq
110$:	CALL	CCSPC		; OUTPUT SPACES
	  DEC	(SP)		; Decrement counter
	  BGT	110$		; Not done ?
	CMP	(SP)+,(SP)+	; Pop counters
	JMP	CCOUT
GOQTS:	CALL	CCSPC		; Turn quoted space to single space
	JMP	CCOUT
;
;	Put variable escape seq into buffer
; INPUT:
;	R1	= number of micro spaces
;
VAROUT::TST	R1
	BLE	30$		; No count ?
	MOV	R2,-(SP)	; Save
	MOV	R4,-(SP)
	MOV	R5,-(SP)
	MOV	R1,R5		; Total count
1$:	MOV	#VARESC+1,R2	; Address of escape sequence buffer
	MOVB	(R2)+,R4	; Count
	BLE	20$		; None ?
10$:	MOVB	(R2)+,R1	; Data to output
	  CALL	FOUT		; Output it
	  SOB	R4,10$		; Output it
	  SOB	R5,1$
20$:	MOV	(SP)+,R5
	MOV	(SP)+,R4	; Restore
	MOV	(SP)+,R2
30$:	RETURN
;
;	Output escape sequences
;
GOESC:	CALL	GBYT			; Get count
	MOV	R1,R4			; Save it
	DEC	R4			; Decrement count
	CALL	GBYT			; Get flag byte
	MOV	R1,-(SP)		; Save bit mask
	BITEQB	#ES.LCK,(SP),10$	; Not lock/Unlock ?
	  DEC	R4			; Decrement count
	  CALL	GBYT			; Get lock word
10$:	BITEQB	#ES.VSP,(SP),20$	; No vertical spacing
	  DEC	R4			; Decrement count
	  CALL	GBYT			; Get vertical spacing
	  TSTNEB	$PAGNG,20$	; No paging
	  SUB	R1,LINEC1		; Decrement lines left
	  SUB	R1,LINEC2		; Decrement lines left
20$:	BITEQB	#ES.HSP,(SP),80$	; No Horizontal spacing
	  DEC	R4			; Decrement count
	  CALL	GBYT			; Get horizontal spacing
	  BLE	80$			; Too small ?
	  BITNEB	#ES.PSP,(SP),40$	; Permanent spacing ?
	  TSTNEB	$ULOSW,30$		; Underline ?
	  ADD	R1,CPOS			; No
	  BR	80$
30$:	  MOV	R1,R2			; Number of underlines
	  CALL	CCUNL			; Perform underlining
	  BR	80$
40$:	  MOV	R1,PHSPOU		; Set permanent horiz spacing
;
;	Now output escape sequence
;
80$:	TST	(SP)+		; Pop status
	TST	R4		; Check count
	BLE	100$		; Done ?
90$:	CALL	GBYT		; Get escape sequence chars
	CALL	FOUT		; Output char with no interpretation
	SOB	R4,90$		; More ?
100$:	JMP	CCOUT		; End of escape seq buffer ?
;
;	Handle backspaces
;
GOBS:	SUB	PHSPOU,CPOS		; New position
	BGT	10$		; OK ?
	MOV	#1,CPOS		; No, make it 1
10$:	CALL	FOUT		; Output backspace
	JMP	CCOUT
;
;	Handle tabs
;
GOTAB:	CALL	GBYT		; Get next input byte
	MOV	R1,-(SP)	; Save it
10$:	DECB	(SP)		; Done?
	BGE	20$		; Not done yet
	TST	(SP)+		; Pop stack
	JMP	CCOUT
20$:	CALL	CCSPC		; Output a space
	BR	10$		; Check it
;	Handle tabs with ellipses
GOELP:	CALL	GBYT		; Get 1 byte
	CLR	-(SP)		; Clear counter on stack
	MOVB	R1,(SP)		; Save count
	CALL	GBYT		; Get ellipses count
	MOV	#TBUFF,R4	; Temporary buffer
	MOV	R1,R2		; Count
	MOV	R1,R5		; Count
	BEQ	6$		; No ellipse spec ?
5$:	CALL	GBYT		; Get chars
	MOVB	R1,(R4)+	; Till done
	SOB	R5,5$		; Get them all
	BR	7$
6$:	MOVB	#SPC,(R4)+	; set first
	MOVB	#PD,(R4)+	; second
	MOV	#2,R2		; And count
7$:	CLRB	(R4)+		; chock buffer
	DEC	(SP)		; Output 1 char ?
	BLE	15$		; No, done
	CALL	CCSPC		;
	DIV$	R2,CPOS		; Divide CPOS/R2 result = R0
	ADD	#TBUFF-1,R1	; Add on temporary buffer address
	MOV	R1,ADDR
10$:	DEC	(SP)
	BGT	20$		; Spaces to output ?
15$:	BLT	16$		; No output ?
	CALL	CCSPC		; Output 1 space
16$:	TST	(SP)+		; Done so pop stack
	JMP	CCOUT
20$:	INC	ADDR
	MOVB	@ADDR,R1	; Char to print
	BNE	30$		; Char ok ?
	MOV	#TBUFF-1,ADDR	; No, start at beginning
	BR	20$
30$:	CALL	CCPRN		; Output printable char
	BR	10$
;
;	Handle repeated output
;
GOREP:	CALL	GBYT		; Get repeat count
	BNE	5$		; Repeat not zero ?
	  CALL	ENDREP		; SKip it
	  JMP	CCOUT		; And do more
5$:	CLR	-(SP)		; Clear count on stack
	MOVB	R1,(SP)		; Save count
	MOV	BF.FUL(R3),-(SP)	; Save input index
10$:	CALL	CCOUT		; Now output string
	DEC	$wordl(SP)		; Done ?
	BLE	20$		; Yes ?
	  MOV	(SP),R1		; Rewind input buffer
	  CALL	FNDBF		; Back over string
	  BR	10$		; Repeat
20$:	CMP	(SP)+,(SP)+	; Pop stack
	JMP	CCOUT		; And continue
;
;	section to fill in index entries
;
GOINX:	CALL	GWRD		; Get address inside index buffer
	MOV	R1,R4		; backward link
	MOV	R3,-(SP)	; Save
	MOV	#INXBF,R3	; Get index buffer address
	CALL	FNDBF		; get next entry
	BCS	11$		; None ?
	CALL	GWRD		; get link to next
	MOV	R1,R5
10$:	MOV	R5,R1		; next entry
	BEQ	15$		; End of line ?
	CALL	FNDBF		; find it
	BCC	12$		; OK ?
11$:	CALL	HLTER
12$:	CALL	GWRD		; get next foreward link
	BCS	11$		; None ?
	MOV	R1,R2
	CALL	GBYT		; get status byte
	BCS	11$		; None ?
	BITNE	#X.ENT,R1,15$	; No entry ?
	MOV	R5,R4		; R4 has backward link
	MOV	R2,R5		; next foreward link
	BR	10$
15$:	MOV	R4,R1		; Go back to last one
	CALL	FNDBF		; Get the index entry address
	BCS	11$		; None ?
	MOV	BF.MAX(R3),R1	; New entry address
	CALL	PWRD		; Link to end
	CALL	ENDBF		; Now go to end
	MOV	R5,R1		; Save foreward link
	CALL	PWRD
	MOV	#X.PAG,R1	; Set for page number
	TSTNEB	$CHPSW,30$	; no chapter print?
	BITEQ	#NM.MSK,APNDN,20$	; No appendix?
	BIS	#X.AP,R1	; Set appendix status
	BR	30$		; no chapter if appendix
20$:	BITEQ	#NM.MSK,CHPTN,30$	; No chapter?
	BIS	#X.CH,R1
30$:	BITEQ	#NM.MSK,SUBPGE,40$	; No subpage?
	BIS	#X.SPG,R1
40$:	CALL	PBYT		; Save status bits
	TSTNEB	$CHPSW,60$	; no chapter print?
	MOV	APNDN,R1
	BEQ	50$
	BIS	APNDSP,R1	; Set display bits
	BR	55$
50$:	MOV	CHPTN,R1
	BEQ	60$
	BIS	CHPDSP,R1	; Set display bits
55$:	CALL	PWRD		; put chapter
60$:	MOV	PAGENO,R1
	BNE	65$		; Not zero ?
	INC	R1		; Make it 1
65$:	BIS	PAGDSP,R1	; Add on display bits
	CALL	PWRD		; put chapter
70$:	MOV	SUBPGE,R1	; Subpage number
	BEQ	80$
	BIS	SUBDSP,R1	; Display bits
	CALL	PWRD		; put subpage
80$:	MOV	(SP)+,R3	; Restore
	JMP	CCOUT
;
;	Routine to output TOC entries
;
GOTOC: MOV	#TTBUF,R2	; Get temporary buffer
10$:	CALL	GBYT		; Get 1 byte
	MOVB	R1,(R2)+	; Into buffer
	BNE	10$
	MOV	#TTBUF+1,R1	; Address of array
	SUB	R1,R2		; Size of array
	DEC	R2		; Final
	BLE	40$		; None ??
	CALL	OUTTOC		; Output the toc line
	TSTB	TTBUF		; Check type of output
	BLE	40$		; No number requested ??
	MOV	R3,-(SP)	; Save R3
	MOV	#TTBF,R3	; Get temporary buffer
	CALL	CLRBF		; Clear it
	MOV	#TAB,R1		; Tab char.
	CALL	PBYT		; into buffer
	MOV	#TOCM1,R0	; Pre-header
	CALL	PSTRZB		; Ino buffer
	CALL	PUTPAG		; Get page number
	MOV	#TOCM1,R0	; Post-header
	CALL	PSTRZB
	MOV	BF.FUL(R3),R2	; Get size
	MOV	(SP)+,R3	; Restore
	MOV	#TTBUF,R1	; Start of buffer
	CALL	OUTTOC		; And output it
40$:	JMP	CCOUT
;
;	Set up page number
;
GOPAG:	MOV	R3,-(SP)
	CALL	GWRD		; Get page number index
	MOV	R1,R2
	MOV	#SUBF0,R3	; Substitution buffer
	CALL	BEGBF		; Reset to beginning of buffer
	MOV	R2,R1
	CALL	FNDBF		; Get location
	BCS	10$
	CALL	GETPAG		; Get page number
10$:	MOV	(SP)+,R3	; Restore
	JMP	CCOUT		; Return
;
;	Routine to get page number into buffer in symbolic rep.
;
GETPAG::CLR	R1
	TSTNEB	$CHPSW,20$	; No chapter ?
	MOV	APNDN,R1	; Get appendix
	BEQ	10$
	BIS	APNDSP,R1	; And format
	BR	20$
10$:	MOV	CHPTN,R1	; Chapter number
	BEQ	20$		; None ?
	BIS	CHPDSP,R1	; And format
20$:	CALL	PWRD
	MOV	PAGENO,R1	; Get page number
	BNE	25$		; Not zero ?
	INC	R1		; Set it to 1
25$:	BIS	PAGDSP,R1	; Set format
	CALL	PWRD		; Save current page
	CLR	R1		; Incase no subpage
	TSTEQ	$SBPSW,30$	; No subpage ?
	MOV	SUBPGE,R1	; Get subpage
	BIS	SUBDSP,R1	; And format
30$:	CALL	PWRD
	RETURN
;
;	Subroutine to output printable chars
;
CCSPC::	MOV	#SPC,R1		; GET SPACE
CCPRN:	TSTEQB	$ULOSW,NOUNL	; No underlining ?
	MOV	PHSPOU,R2	; Number of underlines
	CALL	CCUNL		; YES, DO IT
	JMP	FOUT		; output character
NOUNL:	ADD	PHSPOU,CPOS	; INCREMENT POSITION COUNTER
	JMP	FOUT		; OUTPUT CHAR
;
;	Do underlining
;	R2	= Number of positions to underline
;
CCUNL:	MOV	R1,-(SP)	; SAVE CHAR
80$:	TSTNEB	$ULMSW,90$	; Underline by line or sim. ?
	  MOV	R2,-(SP)	; Save count
	  ADD	R2,CPOS		; New position
82$:	  MOV	#LPUS,R1	; GET UNDERLINE
	  CALL	FOUT		; OUTPUT IT
	  SUB	PHSPOU,R2	; Remaining count
	  BGT	82$		; More to do ?
	  MOV	(SP)+,R2	; Get count again
84$:	  MOV	#BS,R1		; GET BACKSPACE
	  CALL	FOUT		; OUTPUT IT
	  SUB	PHSPOU,R2	; Remaining count
	  BGT	84$		; More to do ?
	  BR	100$
90$:	MOV	CPOS,R0		; POSITION
	CMP	R0,#ULNSZ	; TOO BIG?
	BHI	95$		; YES
	  MOVB	$ULCH,UBUFF-1(R0) ; PUT IT INTO BUFFER
	  CMP	R0,ULNMAX	; SMALLER DUE TO BS
	  BLOS	100$		; YES, KEEP MAX
	  MOV	R0,ULNMAX	; AND SAVE LAST ADDRESS
95$:	INC	CPOS
	SOB	R2,90$		; Do it for each char
100$:	MOV	(SP)+,R1	; GET SAVED CHAR
	RETURN
;
;	Routine to get character width
;	INPUT:	R1=character
;	OUTPUT:	R0=width
;
GETCHW::MOV	PHSP,R0		; Horizontal spacing
	BGE	10$		; Not proportional ?
	NEG	R0
	MOV	R1,-(SP)
	ADD	#CHWTAB,R1
	MOV	(R1),R1		; Get width
	CMPNE	R0,CHWTAB+40,5$	; Not correct table ?
	MOV	R1,R0
	BR	7$		; Save
5$:	MUL$	R1,R0
	DIV$	CHWTAB+40,R1	; Divide by space
7$:	MOV	(SP)+,R1	; Restore char
10$:	RETURN
;
;	Output byte underlined
;
PUBYT::	MOVB	R1,LCH		; SAVE LAST CHARACTER
	CALL	GETCHW		; Get character width
	ADD	R0,SPCH		; Add to spacing char count
	SUB	R0,LINBK	; Subtract from char count remaining
	BCC	PUBYT1		; Not crossed end of line ?
	MOV	BF.FUL(R3),LNINS; Char count at last character
	TSTNEB	$LINBR,PUBYT1	; Do not automatically break ?
	TSTNEB	@EQSTK,PUBYT1	; Equation in progress ?
	TSTNE	BRCNT,PUBYT1	; Breaks this line?
	CALL	BKSPI		; Backup input
	MOV	#-1,LINBK	; Set false indicator of bad line
	CALL	BRKSV
	CALL	CCIN
	MOVB	LCH,R1		; Get char again
PUBYT1:	TSTNEB	$UNLSW,10$	; No underline this char ?
	TSTNE	@EQSTK,10$	; Equation in progress ?
	MOV	R1,R0
	ADD	#CHTABL,R0
	BITNEB	#CH.UNL,(R0),10$	; Underlining not allowed ?
	BIS	#^o200,R1		; Mark it as underlined
10$:	JMP	PBYT		; OUTPUT CHAR
;
;	This is an equation writing routine
;	It will parse fractions written in the form:
;		{ . . . }/{. . .}
;	and using standard letter quality printer escape sequences
;	generate factions.
;
;
;	The first left brace generates:
;		1. Shift up
;		2. Multiple spaces = 0
;
;	The numerator right brace ( }/{ )
;		1. Shift down
;		2. Multiple BS
;		3. Multiple underscore
;		4. Multiple BS
;		5. Shift down
;
;	Denominator right brace
;		1. Multiple spaces ?
;		2. Shift up
;
;	EQSTK contains the following
;		Word 0	= 0
;		. . . . . . .
;		1+N = Index points to beginning of numerator
;		2+N = Shift up count
;		3+N = Vertical space occupied
;		3+N = Current spacing
;		4+N = Type (1 = Numerator, 2 = Denom.)
;		. . . . . . .
;
EQ.HS=-1*$WORDL			; Offset from type
EQ.VSZ=-2*$WORDL		; Offset to vertical size
EQ.VSP=-3*$WORDL		; Offset from type for horiz spacing param
EQ.AD=-4*$WORDL		; Offset from type for address of output
EQ.NX=-5*$WORDL		; Offset to next stack entry
;
;	Add word to equation stack
;	R0=word to add
;
STACK:	CMP	EQSTK,#EQSEN-$WORDL	; Past end of stack ?
	BHIS	EQERR3			; Yes ?
	ADD	#$WORDL,EQSTK		; Incrment stack pointer
	MOV	R0,@EQSTK		; Save value
	RETURN
EQERR3:	MOV	#EQER3,R0
	CALL	ILCMC		; Output error message
	JMP	GCIN
;
;
;	Routine to alter shifts if necessary
;
SHIFT:	CMP	R1,EQ.VSP(R5)		; Extra shift needed
	BLE	10$			; No extra needed
	MOV	R1,EQ.VSP(R5)
10$:	MOV	EQ.VSP(R5),R1		; New shift count
	CMP	R2,EQ.VSZ(R5)		; Check vertical size
	BLE	20$			; Not larger than saved ?
	MOV	R2,EQ.VSZ(R5)		; Save new one
20$:	MOV	EQ.VSZ(R5),R2		; New vertical size
	RETURN
;
;	Found left brace {
;
;
;	Service equation flags
;
GCEQN1:	TSTNEB	$EQFSW+1,NOEQ		; No equations allowed ?
	MOVB	#LPAREN,R1		; Just in case no flag
	TSTNEB	$EQUSW,NOEQ		; Equation disabled ?
	CALL	PADIT			; Check for subscripts/superscripts
	MOV	BF.FUL(R3),R0		; And current buffer pointer
	CALL	STACK			; EQ.AD
	MOV	#1,R2
	ADD	EQSPC,R2		; Plust extra
	MOV	R2,R0			; Save on stack
	CALL	STACK			; EQ.VSP
	CALL	UP			; Shift up
	CLR	R0			; Vertical size
	CALL	STACK			; EQ.VSZ
	MOV	SPCH,R0			; Save the current spacing chars
	CALL	STACK			; EQ.HS
	MOV	#1,R0			; And now the type
	CALL	STACK			; EQ.TYP
	MOV	#NXS,R4			; Character to store
	CLR	R2			; Number of times
	CALL	REPEAT
	JMP	GCIN			; Continue
NOEQ:	JMP	GCINR			; No char formation
;
;	Found right brace }
;
GCEQN2:	TSTNEB	$EQFSW+1,NOEQ		; No equations allowed ?
	MOVB	#RPAREN,R1		; In case no equation
	TSTNEB	$EQUSW,NOEQ		; Equation disabled ?
	CALL	PADIT			; Check for subscripts/superscripts
	MOV	EQSTK,R5		; Get current stack
	CMPNE	(R5),#1,10$		; End of denominator ?
	JMP	GCEQ3			; Parse End of numerator
10$:	CMPEQ	(R5),#2,11$		; End of denom ?
	CALL	HLTER			; Bad stack
11$:	MOV	EQ.VSP(R5),R2		; Shift back up
	CALL	UP
	MOV	SPCH,R2			; Current spacing
	SUB	EQ.NX+EQ.HS(R5),R2	; - previous spacing
	BGT	12$			; OK ?
	JMP	EQERR4			; Bad ?
12$:	SUB	EQ.HS(R5),R2		; Subtract numerator spacing
	BNE	15$			; Not done ?
	JMP	50$			; Done ?
15$:	BGT	40$			; Denom bigger ?
	NEG	R2
	ADD	R2,SPCH			; Adjust spacing char count
	SUB	R2,LINBK
	MOV	R2,-(SP)		; Save
	ASR	R2			; Divide by 2
	BEQ	20$			; No spaces at end
	MOV	#NXS,R4			; Add on spaces at end
	CALL	REPEAT
20$:	SUB	R2,(SP)			; Now spacing at beginning of line
	MOV	(SP)+,R2		; Get result
	BNE	25$			; Ok ?
	JMP	50$			; None at beginning
25$:	MOV	EQ.AD(R5),R1		; Buffer index for spacing
	CALL	FNDBF
	CALL	SKPREP			; Skip shift down 1.
	CALL	SKPREP			; Skip BS 2.
	CALL	SKPREP			; Skip underline 3.
	CALL	GBYT			; Skip begin of next rep
	MOV	EQ.HS(R5),R1		; Previous spacing
	SUB	R2,R1			; New Backspace count
	CALL	PBYT			; Save the space count
	BR	50$			; Now handle vertical spacing
40$:	MOV	R2,-(SP)		; Save count
	ASR	R2			; Divide by 2
	BEQ	45$			; No count
	MOV	EQ.NX+EQ.AD(R5),R1	; left brace output index
	CALL	FNDBF
	CALL	SKPREP			; Now have spacing count
	CALL	GBYT			; Skip repeat start
	MOV	R2,R1			; Actual number of spaces
	CALL	PBYT
45$:	MOV	EQ.AD(R5),R1		; Get index
	CALL	FNDBF			; Get location
	CALL	SKPREP			; Skip shift param
	CALL	GBYT			; Skip repeat start
	MOV	EQ.HS(R5),R1		; Backspace count
	ADD	R2,R1			; + spaces at beginning
	CALL	PBYT			; And save it
	CALL	SKPREP			; Now have underline repeat
	CALL	GBYT			; Skip repeat start
	ADD	EQ.HS(R5),(SP)		; Total number of char in denom
	MOV	(SP),R1			; Actual underline size
	CALL	PBYT
	CALL	SKPREP			; Next BS
	CALL	GBYT			; Skip repeat start
	MOV	(SP)+,R1		; Number to do
	CALL	PBYT
50$:	MOV	EQ.NX+EQ.AD(R5),R1	; Adjust the vertical spacing
	CALL	FNDBF			; Get vertical spacing repeat
	CALL	GBYT			; Skip repeat spec.
	MOV	EQ.NX+EQ.VSP(R5),R1	; Adjusted vertical spacing
	MOV	R1,R2			; Save
	CALL	PBYT
	MOV	EQ.AD(R5),R1		; Denominator
	CALL	FNDBF
	CALL	GBYT			; Skip repeat spec.
	DEC	R2			;
	MOV	R2,R1			; Back to line vs
	CALL	PBYT
	MOV	#4,R4			; Skip 4 params
60$:	CALL	SKPREP
	SOB	R4,60$
	CALL	GBYT			; Skip repeat start
	MOV	EQ.VSP(R5),R1
	INC	R1			; Plus 1
	CALL	PBYT			; New vertical spacing
	MOV	EQSTK,R0		; Current stack address
	MOV	EQ.VSZ(R0),R1		; Denominator
	ADD	EQ.VSP(R0),R1		; Total denom size
	ADD	#EQ.NX,R0		; Next entry
	MOV	EQ.VSZ(R0),R2		; Numerator size
	ADD	EQ.VSP(R0),R2		; Total numerator size
	ADD	#EQ.NX,R0		; Next entry
	MOV	R0,EQSTK
	TSTNE	(R0),100$		; Equation not ended ?
	TSTEQB	$SEQSW,80$		; No separated equations ?
	BITNE	#FOTF,F.1,80$		; Footnote in progress ?
	DEC	R1			; Size -1/2 line already accounted for
	DEC	R2			; Ditto
	CMP	R1,EQBOT		; Compare with current value
	BLE	65$			; Smaller ?
	MOV	R1,EQBOT		; Save size
65$:	CMP	R2,EQTOP		; Compare with current value
	BLE	80$			; Smaller ?
	MOV	R2,EQTOP		; Save top size
80$:	TSTEQ	BRCNT,90$		; No breaks this line ?
	TST	LINBK			; Past end of line ?
	BLT	100$
90$:	CALL	ENDBF			; Back at end of buffer
	CALL	BRKSV			; Put line break here
100$:	CALL	ENDBF
	JMP	GCIN			; Continue
;
;	Error during text processing
;
EQERR5:	CALL	BKSPI
EQERR4:	TSTEQ	@EQSTK,10$		; No equation in progress ?
	ADD	#EQ.NX,EQSTK		; Restack kill this entry
10$:	MOV	#EQER4,R0
	CALL	ILCMC			; Output error message
	JMP	GCIN			; Next char
;
;	End numerator
;
GCEQSK:	CALL	CCIN
	BCC	1$			; Not end of input
	TST	(SP)+			; REturn to user
	RETURN
1$:	CMPEQB	R1,#SPC,GCEQSK		; Space ?
	CMPEQB	R1,#TAB,GCEQSK		; Tab ?
10$:	RETURN	
GCEQ3:	CALL	GCEQSK			; Skip over end of line
	CMPEQB	R1,#SLASH,GCEQ3		; Slash ?
	CMPNEB	R1,#LBRACE,EQERR5	; Error in parsing ? not left brace ?
	MOV	BF.FUL(R3),R0		; And current buffer pointer
	CALL	STACK			; EQ.AD
	MOV	EQ.VSP(R5),R2		; Previous vertical shift
	DEC	R2			; - 1
	CALL	DOWN			; Now execute a shift down
	MOV	#1,R0
	ADD	EQSPC,R0		; Vertical shift for stack
	CALL	STACK			; EQ.VSP Save shift on stack
	CLR	R0			; Vertical size
	CALL	STACK			; EQ.VSZ
	MOV	SPCH,R0			; Current spacing
	SUB	EQ.HS(R5),R0		; Horizontal movement
	MOV	R0,R2			; Save
	BGT	20$			; Is it positive ?
	JMP	EQERR4			; Bad !
20$:	SUB	R0,SPCH
	ADD	R0,LINBK		; Set back to old spacing char
	CALL	STACK			; EQ.HS Save it for convenience
	MOV	#2,R0			; And now the type
	CALL	STACK			; EQ.TYP
	MOV	#BS,R4			; Repeat backspace
	CALL	REPEAT
	MOV	#UNDSC,R4		; Repeat underline
	CALL	REPEAT
	MOV	#BS,R4			; Back space again
	CALL	REPEAT
	MOV	#2,R2			; Down shift to execute
	CALL	DOWN			; Now shift down
	JMP	GCIN
;
;	Pad the equation with 1/2 lines as necessary
;
PADIT:	MOV	EQSTK,R5		; Get stack location
	TSTEQ	(R5),100$		; First time thru ?
	MOV	MINVS,R2		; Subscripts
	NEG	R2			; Correct sign
	MOV	MAXVS,R1		; Plus Superscripts
	INC	R1			; Account for 1/2 line
	INC	R2			; Ditto
5$:	CMPEQ	(R5),#1,10$		; Numerator ?
	MOV	R2,-(SP)
	MOV	R1,R2			; Reverse order
	MOV	(SP)+,R1
10$:	TSTEQ	(R5),100$		; Done ?
	CALL	SHIFT			; Check if spacing is correct
	CMPEQ	(R5),#1,30$		; Current is numerator ?
	ADD	#EQ.NX,R5		; Next entry
	ADD	R2,R1			; Now is shift up
	MOV	EQ.VSZ(R5),R2		; Get size above numerator
	ADD	EQ.VSP(R5),R2		; Add shift up
	ADD	#EQ.NX,R5		; Next entry
	BR	5$
30$:	ADD	#EQ.NX,R5		; Next entry
	CMPEQ	(R5),#1,40$		; Another numerator?
	ADD	R2,R1			; Add size to shift
	CLR	R2			; Clear shift
	BR	10$
40$:	ADD	R1,R2			; Add shift to spacing
	CLR	R1
	BR	10$
100$:	CLR	MAXVS			; Maximum vertical spacing
	CLR	MINVS			; Minimum vertical spacing
	CLR	CURVS			; And clear current
	RETURN
;
;	Enter repeating char into output
;		R4=Char to repeat
;		R2=Repeat count
;
REPEAT:	MOV	#REPO,R1		; Set for repeat
	CALL	PBYT
	MOV	R2,R1			; Repeat count
	CALL	PBYT
	MOV	R4,R1			; Char to repeat
	CALL	PBYT			; Now output character
	CALL	CBYT
	RETURN
;
;	Put up/down shifts into output
; INPUT:
;	R2	= Number of shifts
; OUTPUT:
;	R2	Destroyed
;
DOWN:	MOV	#DNTAB,-(SP)		; Table
	BR	UP1
UP:	MOV	#UPTAB,-(SP)		; Table
UP1:	MOV	#REPO,R1		; Get repeat char
	CALL	PBYT			; To output
	MOV	R2,R1			; Number of shifts
	CALL	PBYT			; Into buffer
10$:	MOV	(SP)+,R2		; Characters to transfer
	MOV	R4,-(SP)		; Save R4
	MOVB	(R2),R4			; Count
	BLE	20$			; Zero or negative ?
	MOV	#ESC,R1			; Set up for escape
	CALL	PBYT
	INC	R4
15$:	MOVB	(R2)+,R1		; Characters
	CALL	PBYT			; Tranferred to buffer
	SOB	R4,15$			; Till done
20$:	MOV	(SP)+,R4		; Restore
	CALL	CBYT			; Terminate repeat
	RETURN
;
;	Skip over a repeat function
;
SKPREP:	CALL	GBYT			; Get next char in output buffer
	BNE	1$			; Not null ?
	  RETURN			; Done
1$:	CMPNEB	R1,#REPO,2$		; Repeat ?
	  CALL	GBYT			; Skip count
	  BR	ENDREP			; Now end the repeat
2$:	CMPNEB	R1,#ESC,SKPREP		; Not escape ?
	  CALL	ENDESC			; End escape seq
	BR	SKPREP
;
;	Subroutine to find end of repeat function
;
ENDREP:	CALL	GBYT			; Get next char in output buffer
	BNE	1$			; Not null ?
	  RETURN			; Done
1$:	CMPNEB	R1,#REPO,2$		; Repeat ?
	  CALL	GBYT			; Skip count
	  BR	ENDREP
2$:	CMPNEB	R1,#ESC,ENDREP		; Not escape ?
	  CALL	ENDESC			; End escape seq
	BR	ENDREP
;
;	Skip over escape seq
;
ENDESC:	MOV	R2,-(SP)		; Save R2
	CALL	GBYT			; Begin next param
	MOV	R1,R2			; Count
3$:	CALL	GBYT
	SOB	R2,3$			; Skip escape seq.
	MOV	(SP)+,R2		; Restore
	RETURN
	.END
