PROCEDURE	<RNCMD - Runoff command processing>,010009
;+
; Copyright (c) 1976
; Digital Equipment Corporation, Maynard, Mass.
;
; This software is furnished under  a license for use only  on  a
; Single computer system and may be  copied only with  the inclu-
; Sion of  the  above  copyright notice.  This software,  or  any
; other copies thereof, may not be  provided  or  otherwise  made
; available to any other person except  for  use  on  such system
; and to  one who agrees  to  these license  terms.  Title to and
; ownership of the software shall at all times remain in DEC.
;
; The information in this software  is  subject to change without
; notice and should not be construed  as  a commitment by Digital
; Equipment Corporation.
;
; DEC assumes no responsibility for the use or reliability of its
; software on equipment which is not supplied by DEC.
;
; Abstract:	This module contains the action routines for most of
;		the Runoff commands.
;
; 	R4 = Address of number conversion routine.
;	R5 = Address of flag word F.1.
;
; Written: 01-Jun-72, -0.0.0-, L. Wade
;
; Modified: 12-Jan-80, -1.0.0-, Henry R. Tumblin
;	Produced Duke supported version
;
; Verified: 12-Jan-80, -1.0.0-, Henry R. Tumblin
;
; Modified: 26-May-80, -1.0.1-, Jon Berntsen
	.IF	DF	A$$RAP
;
; Modified: 26-Aug-80, -1.0.2-, John D. Leonard for .SETSS
;	Fixed Old Figure Command to blank at top of page.
;
; Modified: 30-Sep-80, -1.0.3-, John D. Leonard
;	Fixed BLANK command - was defaulting to skipping two lines.
;
; Modified: 02-Sep-80, -1.0.4-, John D. Leonard
;	Commands to accept spacing count in 1/8 line increments
;
; Modified: 07-Oct-80, -1.0.5-, John D. Leonard
;	Modified .NPL command,
;	Added .NNPL (no number page lower),
;	Added .TM (Top Margin),
;	Added .OP (Over print),
;	Added .OPJ (Over print right justified)
;	Added .OB (Over Bar)
;	Added .EQ (EQuation mode)
;	Added .EEQ (End EQuation mode)
;
; MODIFIED: 05-NOV-80, -1.0.6-, JOHN D. LEONARD
;	ADDED .SETS (SET STRING) COMMAND
;
; Modified: 22-Dec-80, -1.0.7-, John D. Leonard
;	Put test page into footnote command so an attempt to footnote at
;	at bottom of page with insufficient page length forces footnote to
;	next page.
;
; Modified: 06-Jan-81, -1.0.8-, John D. Leonard
;	Changed .CENTER command parameters for clarification. Now specify
;	.CENTER lm,rm; text to center between the given left/right margins.
;	Straightened out minor problems with .RM and added checking to
;	.LM and .RM against permanent settings.
;	Removed the second parameter to the .PS command, so only the page length
;	can be specified. .PRM and .PLM should be used for margin setting.
;	Too confusing.
;	Added 2nd parameter to .FN command to allow specification of footnote
;	terminator character.
;	Removed multiplication of footnote space by spacing.
;	Changed PAGE command so that it calls BPAGE. Problem with page pending
;	mechanism and footnotes. If a .NF command or other mode command followed
;	a .PG, it would change the setting before footnotes were printed.
;	Relative setting in .PS command does not properly modify NLPG to
;	account for the relative setting.
;	This problem only occurs when the page size is changed and the page
;	has footnotes. Footnote checking modifies NLPG !
;
; Modified: 03-Nov-81, -1.0.9-, John D. Leonard
;	Changed .PARAGRAPH and .LIST spacing arguments to 1/8 line format.
;	Also on autoparagraph command.
	.ENDC
;-

	.SBTTL	Runoff definitions(external)

	.GLOBL	ALLOC		; Memory allocator
	.GLOBL	BPAGE		; Break current page
	.GLOBL	CAS		;
	.GLOBL	CBNSP		;
	.GLOBL	CCIN		; Get character from buffer
	.GLOBL	CMADR		; Command address
	.GLOBL	DATEBF		; Date buffer
	.GLOBL	DATECT		; Count of characters in date buffer
	.GLOBL	DATTBF		; TOC date buffer
	.GLOBL	DATTCT		; TOC count of characters in date buffer
	.GLOBL	EBSIZ		; Change bars offset
	.GLOBL	ELCMD		;
	.GLOBL	EOF		; End-of-File character
	.GLOBL	FILLF		;
	.GLOBL	FOOTC		;
	.GLOBL	FOOTLH		; Footnote list head
	.GLOBL	FOOTP1		; Footnote header area
	.GLOBL	GCIN		; Get character from input file
	.GLOBL	GCSCH		; Saved character buffer
	.GLOBL	ILCM		; Common error point for illegal command
	.GLOBL	ILMRG		; Initial left margin
	.GLOBL	INDCT		; Indentation count
	.GLOBL	INLPG		; Initial lines/page
	.GLOBL	IPARIN		;
	.GLOBL	IPARPT		;
	.GLOBL	JUSTF		;
	.GLOBL	LF		; Line feed
	.GLOBL	LIBUF		; Line input buffer header
	.GLOBL	LINEC		;
	.GLOBL	LITCM		;
	.GLOBL	LITFG		;
	.GLOBL	LITSV		;
	.GLOBL	LMARG		; Current left margin
	.GLOBL	METBEG		;
	.GLOBL	METEND		;
	.GLOBL	NEWFIL		;
	.GLOBL	NLPG		; Number of lines per page
	.GLOBL	NSPAC		; Output spaces to output file
	.GLOBL	NSPCH		;
	.GLOBL	NSPNG		;
	.GLOBL	NTABS		;
	.GLOBL	PAGENO		;
	.GLOBL	PARIND		; Paragraph indentation count
	.GLOBL	PARPT		;
	.GLOBL	PARSP		; Paragraph spacing
	.GLOBL	PJUSTF		;
	.GLOBL	PLMARG		; Permanent left margin
	.GLOBL	PNLPG		; Permanent number of lines/page
	.GLOBL	PRMARG		;
	.GLOBL	PRMRG		;
	.GLOBL	PSHFIL		;
	.GLOBL	PSTRPA		; Insert ASCIZ string in buffer
	.GLOBL	RIGSHI		; Right Shift value


	.SBTTL	Runoff definitions(external), continued

	.GLOBL	RMARG		; Current right margin
	.GLOBL	SEMI		; Semicolon
	.GLOBL	SKIPN		; Skip N lines to the output file
	.GLOBL	SKIPS		; Skip lines according to spacing
	.GLOBL	SPC		; Blank
	.GLOBL	SPCNG		;
	.GLOBL	SPECF		;
	.GLOBL	STTLBF		; Subtitle buffer header
	.GLOBL	TAB		; Tab
	.GLOBL	TABTAB		;
	.GLOBL	TABTL		;
	.GLOBL	TPNLPG		; TOC permanent lines/page
	.GLOBL	TTLBUF		; Title buffer header
	.GLOBL	ULBSET		;
	.GLOBL	UPCSW		;
	.GLOBL	WCAS		;
	.GLOBL	WCI		; Write character in buffer
	.GLOBL	WCIFTN		; Write character in footnote buffer
	.GLOBL	WLNIN1		;
	.GLOBL	$AUTSW		; Autoparagraph switch
	.GLOBL	$CBON		; Change bars on switch
	.GLOBL	$CFLSW		;
	.GLOBL	$DATE		; Date switch
	.GLOBL	$DATET		; TOC date switch
	.GLOBL	$FRCND		; Force to logical end of command
	.GLOBL	$HDRSW		; Header switch
	.GLOBL	$HFLSW		;
	.GLOBL	$HPHSW		; Hyphenation switch
	.GLOBL	$INSW		; Input file switches
	.GLOBL	$NUMLW		; Number pages low switch
	.GLOBL	$NUMSW		;
	.GLOBL	$PERSW		;
	.IF	NDF	A$$RAP
	.GLOBL	$PGPSW		;
	.ENDC


	.SBTTL	Runoff definitions(internal)

	.GLOBL	AUTOP		; Autoparagraph
	.GLOBL	BGBAR		; Begin Change bars
	.GLOBL	BREAK		; Break command
	.GLOBL	CENTER		; Center command
	.GLOBL	CHANG		; Change metacharacter.
	.GLOBL	CPAGE		; Page command
	.GLOBL	PAGEC
	.GLOBL	DATE		; Date command
	.GLOBL	DSAFL		; Disable all flags
	.GLOBL	DSCBR		; Disable change bars
	.GLOBL	DSCFL		; Disable flags capitalize
	.GLOBL	DSHFL		; Disable flags hyphenate
	.GLOBL	ELTRL		; End literal command
	.GLOBL	ENBAR		; End change bars
	.GLOBL	ENCBR		; Enable change bars
	.IF	DF	A$$RAP
	.GLOBL	EQON		; Enable Equation mode
	.GLOBL	EQOFF		; Disable Equation mode
	.ENDC
	.GLOBL	FIGUR		; Figure command
	.GLOBL	FILLN		; Fill command
	.GLOBL	FILOF		; Nofill command
	.GLOBL	FOOTN		; Footnote command
	.GLOBL	FTITL		; First title command
	.GLOBL	HYPHN		; Enable hyphenation
	.GLOBL	INDENT		; Indent command
	.GLOBL	INDIRC		; Include command
	.GLOBL	JUSOF		; Justify command
	.GLOBL	JUSTN		; Nojustify command
	.GLOBL	LINSKP		; Blank command
	.GLOBL	LITRL		; Literal command
	.GLOBL	LITSV		;
	.GLOBL	LMARG		;
	.GLOBL	LSTTP		;
	.GLOBL	LWCAS		; LC command
	.GLOBL	NAUTO		; Disable autoparagraph
	.GLOBL	NHYPH		; Disable hyphenation
	.GLOBL	NPERS		;
	.GLOBL	NUMLW		;
	.IF	DF	A$$RAP
	.GLOBL	NUMLWO		; Disable Number Page Lower
	.ENDC
	.GLOBL	NUMOF		; Nonumber command
	.GLOBL	NUMON		; Number command
	.IF	DF	A$$RAP
	.GLOBL	OVERP		; Overprint line
	.GLOBL	OVERPJ		; Overprint line right justified
	.GLOBL	OVERB		; Overprint overbar
	.ENDC
	.GLOBL	PARAG		; Paragraph command
	.GLOBL	PARTP		;
	.GLOBL	PERSP		;
	.GLOBL	SELM		; PLM command
	.GLOBL	SERM		; PRM command
	.GLOBL	SETBF		;
	.GLOBL	SETLM		; LM command
	.GLOBL	SETPG		;
	.GLOBL	SETRM		; RM command
	.GLOBL	SETSTL		; Subtitle command
	.GLOBL	SETTAB		; Tabstop command
	.GLOBL	SETTL		; Title command
	.IF	DF	A$$RAP
	.GLOBL	SETTM		; Set Top Margin
	.ENDC
	.GLOBL	SHFUC		; Shift to upper case
	.GLOBL	SKIPL		; Skip command
	.GLOBL	SSP		; Spacing command
	.IF	DF	A$$RAP
	.GLOBL	SUBSTD		; Set string delimited
	.GLOBL	SUBST		; Set string
	.GLOBL	SETSS		; Set sub/supperscript vertical increment
	.ENDC
	.GLOBL	STAND		; Standard command
	.GLOBL	SWPFIL		; Swap output files
	.GLOBL	TESTP		; Test page command
	.GLOBL	TSTPG		;
	.GLOBL	UPCAS		; UC command


	.SBTTL	ENCBR -- ENABLE CHANGE BARS

	CODE	RNCMD

	.sbttl	Enable/Disable change bar commands(Also on and off)

ENCBR::	CLR	$CBON		; Clear on
	MOV	#CBNSP,EBSIZ	; Number of chars to move to right
	RETURN			;

	.SBTTL	DSCBR -- Disable change bars

DSCBR::	CLR	EBSIZ		; Set offset back to zero
	CLR	$CBON		; Turn off change bar
	RETURN

	.sbttl	BGBAR -- Begin change bars

BGBAR::	MOV	#CBBIT,$CBON	; Turn on change bars
	RETURN

	.sbttl	ENBAR -- End change bars

ENBAR::	MOV	#CBFBT,$CBON	; Turn off change bars
	RETURN


	.SBTTL	AUTOP -- Enable AUTOPARAGRAPH

AUTOP::	MOV	SP,$AUTSW	; set autoparagraph mode
	CALL	(R4)		; optional identing argument
	  MOV	PARIND,R3	; no.  use old value
	CMP	R3,RMARG	; reasonable value?
	BLE	20$		; LE - then ok
10$:	JMP	ILCM		; Else illegal command

20$:	MOV	R3,INDCT	; set paragraph indent
	MOV	R3,PARIND	; store para indent value
	.if	df	A$$RAP
	MOV	SP,$MFAC	; Set for 1/8 line type argument
	.iftf
	CALL	(R4)		; get paragraph spacing
	MOV	PARSP,R3	; default to normal spacing
	.ift
	CLR	$MFAC		; Clear the condition
	.endc
	CMP	R3,#<5*DIVPL>	; legal value?
	BHI	10$		; if HI no

	MOV	R3,PARSP	; set new paragraph spacing
	CALL	(R4)		; get test page count
	MOV	#IPARPT,R3	; default page test number
	CMP	R3,PNLPG	; value within reason?
	BHI	10$		; if HI no
	MOV	R3,PARPT	; set new paragraph page test count

	RETURN			;

	.SBTTL	NAUTO -- Disable AUTOPARAGRAPH

NAUTO::	CLR	$AUTSW		; clear autoparagraph mode
	RETURN			;

	.SBTTL	 DSAFL -- DISABLE ALL FLAGS

DSAFL::	CLR	$CFLSW		; clear flags capitalize
	CLR	$HFLSW		; clear flags hyphenate
	RETURN			;


	.SBTTL	ENCFL -- Enable Flags Capitalize

	.ENABL	LSB
ENCFL::	MOV	SP,$CFLSW	; set word capitalize enable
10$:	CLR	WCAS		; clear case conversion value
	RETURN			;

	.SBTTL	DSCFL -- Disable Flags Capitalize

DSCFL::	CLR	$CFLSW		; clear word capitalize enable
	BR	10$		;
	.DSABL	LSB

	.sbttl	ENHFL -- Enable Flags Hyphenate

ENHFL::	MOV	SP,$HFLSW	; set hyphenate enable
	RETURN			;

	.sbttl	DSHFL -- Disable Flags Hyphenate

DSHFL::	CLR	$HFLSW		; clear hyphenate enable
	RETURN			;

	.sbttl	HYPHN -- Enable Hyphenation

HYPHN::	MOV	SP,$HPHSW	; set hyphenation active
	RETURN			;

	.sbttl	NHYPN -- Disable hyphenation

NHYPH::	CLR	$HPHSW		; clear hyphenation active
	RETURN			;

	.SBTTL	INDENT -- INDENT COMMAND

INDENT::CALL	(R4)		; read signed decimal number
	  MOV	PARIND,R3	; none.  use current value
	CMP	R3,RMARG	; legitimate value?
	BLE	10$
	JMP	ILCM		; no.  complain
10$:	MOV	R3,INDCT	; yes.  store argument

	.sbttl	BREAK -- BREAK COMMAND

BREAK::	RETURN			; Return, flags will do the rest


	.SBTTL	LWRCAS -- Set mode to lower case

	.ENABL	LSB
LWCAS::	MOV	#40,R1		; set for lower case
	BITEQ	#UPCSW,$INSW,10$ ; don't force all upper case?

	.SBTTL	UPCAS -- Set mode to upper case

UPCAS::	CLR	R1		; set for upper case
10$:	MOV	R1,CAS		; store
	RETURN			;
	.DSABL	LSB

	.sbttl	PAGE NUMBER SELECTION COMMANDS

	.sbttl	NUMON -- Turn on and set page numbering

NUMON::	CALL	(R4)		; number pages.  any particular number?
	  MOV	PAGENO,R3	; no.  leave same as before
	MOV	R3,PAGENO	; store page number
	MOV	SP,$NUMSW	; turn on flag to cause numbering
	RETURN			;

	.sbttl	NUMOF -- Turn off page numbering

NUMOF::	CLR	$NUMSW		; turn off numbering.
	RETURN			;

	.sbttl	NUMLW -- NUMBER PAGES LOW

NUMLW::
	.IF	NDF	A$$RAP
	CLR	PAGENO		; clear page number
	.ENDC
	CALL	(R4)		; get page number if any
	  MOV	PAGENO,R3	; set default
	MOV	R3,PAGENO	; set new page number
	.IF	NDF	A$$RAP
	MOV	#1,$NUMLW	; set flag
	.IFF
	TSTNE	$NUMLW,10$	; If already on don't reset page length
	MOV	#NLFTR,$NUMLW	; Set to # of lines in footer
	SUB	$NUMLW,NLPG	; Adjust # of lines per page
10$:				;
	.ENDC
	RETURN
	.IF	DF	A$$RAP

	.SBTTL	NUMLWO - Turn off number pages low

NUMLWO::
	ADD	$NUMLW,NLPG	; Increase length of page
	CLR	$NUMLW		; Clear flag
	RETURN
	.ENDC

	.sbttl	CPAGE -- PAGE COMMAND

CPAGE::	MOV	LINEC,R2	; Get current line count on page
	SUB	#DIVPL,R2	; minus the header size
	CMP	$HDRSW,R2	; In header area ?
	BGE	20$		; GE - then ignore doing page
10$:
	.IF	NDF	A$$RAP
	MOV	SP,$PGPSW	; set page pending flag
	.IFF
	CALL	PAGEC		; do the page
	.ENDC
20$:	RETURN			;

	.sbttl	MARGIN SELECTION COMMANDS

	.sbttl	SETRM -- Set right margin

	.ENABL	LSB
SETRM::	MOV	RMARG,R3	; get current right margin
	CALL	(R4)		; get relative argument
	  MOV	PRMRG,R3	; if none, initialize
	CMP	R3,LMARG	; must be right of left margin
	BLE	110$		; report error
	CMP	R3,PRMARG	; Must be less than or equal to permanent margin
	BLE	10$		; OK
	MOV	PRMARG,R3	; Set it to current right margin then
10$:	MOV	R3,RMARG	; and set the margin
	RETURN			;

	.sbttl	SETLM -- Set left margin

SETLM::	MOV	LMARG,R3	; get current left margin
	CALL	(R4)		; get relative argument
	  .IF	NDF	A$$RAP
	  MOV	#ILMRG,R3	; if none, initialize
	  .IFF
	  MOV	ILMRG,R3	; if none , initialize
	  .ENDC
	CMP	R3,RMARG	; must be less than right margin?
	BGE	110$		; if GE no
	CMP	R3,PLMARG	; Must be greater than or equal to permanent left
	BGE	20$		; OK
	MOV	PLMARG,R3	; else set to permanent left margin
20$:
	MOV	R3,LMARG	; OK, save as left margin
	RETURN			;

	.sbttl	PERMANENT MARGIN SELECTION COMMANDS

	.sbttl	SERM -- Set permanent right margin

SERM::	MOV	PRMARG,R3	; get current right margin
	CALL	(R4)		; get relative argument
	  MOV	PRMRG,R3	; if none, initialize
	CMP	R3,LMARG	; must be right of left margin
	BGT	120$		; if GT ok
110$:	JMP	ILCM		; illegal command
120$:	MOV	R3,PRMARG	; set permanent right margin
	.IF	DF	A$$RAP
	MOV	R3,RMARG	; Set right margin
	MOV	R3,PRMRG	; ?
	.ENDC
	RETURN

	.sbttl	SELM -- Set permanent left margin

SELM::	MOV	PLMARG,R3	; get current left margin
	CALL	(R4)		; get relative argument
	  .IF	NDF	A$$RAP
	  MOV	#ILMRG,R3	; if none, initialize
	  .IFF
	  MOV	ILMRG,R3	; If none, initialize
	  .ENDC
	CMP	R3,RMARG	; must be less than right margin?
	BGE	110$		; if GE no
	MOV	R3,LMARG	; ok save as left margin
	MOV	R3,PLMARG	; save as permanent left margin
	RETURN			;
	.IF	DF	A$$RAP

 	.sbttl	SETTM -- SET Top margin command

SETTM::
	CALL	(R4)		; Get argument
	  MOV	#ITMRG,R3	; Default to initial setting if no arg.
	MOV	R3,TMARG	;	save it in Top Margin
	RETURN
	.ENDC

	.DSABL	LSB
	.ENABL	LSB
	.sbttl	STAND -- STANDARD COMMAND

STAND::	MOV	#SPCNG,NSPNG	; set standard spacing
	.IF	NDF	A$$RAP
	MOV	#ILMRG,	LMARG	; initialize left margin
	.IFF
	MOV	ILMRG,LMARG	; iniialize left margin
	.ENDC
	MOV	#IPARIN,PARIND	; set initial paragraph indent
	MOV	#INLPG,R3	; set initial page length parameter
	BIS	#FILLF!JUSTF!PJUSTF,(R5) ; set to fill and justify
	CALL	15$		; finish in common code
	CALL	SERM		; Set permanent right margin
	RETURN


	.sbttl	SETPG -- PAGE SIZE COMMAND

SETPG::	MOV	PNLPG,R3	; get current page length
	.IF	DF	A$$RAP
	MOV	SP,$MFAC	; Return in # of 1/8 increments
	.ENDC
	CALL	(R4)		; get relative argument
	MOV	PNLPG,R3	; default to current length
	.IF	DF	A$$RAP
	CLR	$MFAC		; Clear the switch
	.ENDC
	CMP	PNLPG,R3	; identical ?
	BEQ	17$		; EQ - then don't bother setting it
	CMP	R3,#<6*DIVPL>	; long enough to be reasonable for heading
	BGT	15$		; if LE error
10$:	JMP	ILCM		; Report error
15$:	.IF	NDF	R$$OCK
	ASL	R3		; multiply by two
	.ENDC	; R$$OCK
	SUB	PNLPG,R3	; Find difference from old setting
	ADD	R3,NLPG		; add to length of this page
	ADD	R3,PNLPG	; and permanent page length
	.IF	NDF	A$$RAP
	ASR	R3
	.IFF
	ASH	#DIV8,R3	; divide page length by 8 and save
	.ENDC
	ADD	R3,TPNLPG	; divide page length by 2 and save
17$:	.IF	NDF	A$$RAP
	CALL	SETRM		; set right margin
	MOV	R3,PRMRG	; set new permanent margin
20$:	MOV	R3,RMARG
	MOV	R3,PRMARG	; set new permanent right margin
	.ENDC
	RETURN			;

	.sbttl	PARAG -- PARAGRAPH COMMAND

PARAG::	CALL	(R4)		; optional indenting argument
	  MOV	PARIND,R3	; no.  use old value
	CMP	R3,RMARG	; reasonable value?
	BGT	10$		; if GT no
	MOV	R3,INDCT	; set paragraph indent
	MOV	R3,PARIND	; store para indent value
	.if	df	A$$RAP
	MOV	SP,$MFAC	; Set for 1/8 line argument
	.iftf
	CALL	(R4)		; get paragraph spacing
	MOV	PARSP,R3	; default to normal spacing
	.ift
	CLR	$MFAC		; Reset 1/8 line indicator
	.endc
	CMP	R3,#<5*DIVPL>	; legal value, max 5 lines
	BHI	10$		; if HI no
	MOV	R3,PARSP	; set new paragraph spacing
	CALL	(R4)		; get test page count  "spaces"
	MOV	#IPARPT,R3	; default page test number
	CMP	R3,PNLPG	; value within reason?
	BHI	10$		; if HI no
	MOV	R3,PARPT	; set new paragraph page test count
PARTP::	MOV	PARPT,R3	; get page test count
	.if	ndf	A$$RAP
	ADD	PARSP,R3	; add # of lines between para.
	.iftf
	MOV	NSPNG,R0	;
	.IF NDF	R$$EIS		; If no EIS, use $MUL
	MOV	R3,R1		; Get into R1 for $MUL
	CALL	$MUL		; get total number of half lines
	.IFF			; If EIS, just use MUL
	MUL	R3,R0		; Get total number of line divisions
	.ENDC	;R$$EIS
	MOV	R1,R3		;
	.iff
	ADD	PARSP,R3	; Plus spacing between paragraphs
	.endc
	CALL	TESTP		; test if room on page
30$:	MOV	PARSP,R1	; get current paragraph spacing
LSTTP::	BEQ	40$		; if EQ no spacing
	.if	ndf	A$$RAP
	MOV	NSPNG,R0	; get lines per line
	.IF NDF	R$$EIS		; If no EIS, use $MUL
	CALL	$MUL		; calculate actual number of lines to skip
	.IFF			; If EIS, use MUL
	MUL	R1,R0		; Calculate actual number of lines to skip
	.ENDC	;R$$EIS
	.endc
	CMP	$HDRSW,LINEC	; already in heading area?
	BGE	40$		; if GE yes
	MOV	R1,R2		; set line skip count
	CALL	SKIPN		; skip lines
40$:	RETURN			;
	.DSABL	LSB

	.sbttl	TSTPG -- TEST PAGE COMMAND

;	TSTPG	-- Entry point for TEST PAGE command
;	TESTP0	__ Internal routine - testpage with R3 multiplied by spacing
;	TESTP	-- Internal routine - testpage with R3 number of 1/8 lines to test
	
	.ENABL	LSB
TSTPG::	CALL	(R4)		; get argument of test
	  JMP	ILCM		; must be one
	CMP	R3,PNLPG	; value within reason?
	BHI	10$		; if HI no
TESTP0::MOV	NSPNG,R0
	.IF NDF	R$$EIS		; If no EIS, use $MUL
	MOV	R3,R1		; Get into R1 for $MUL
	CALL	$MUL
	.IFF			; If EIS, use MUL
	MUL	R3,R0
	.ENDC	;R$$EIS
	MOV	R1,R3
TESTP::	ADD	LINEC,R3	; add on current line position
	CMP	R3,NLPG		; compare to length w/o footnotes
	BLE	20$
	JMP	BPAGE		; test shows near end. break page.

	.sbttl	SSP -- SPACING COMMAND

SSP::
	.IF	DF	A$$RAP
	MOV	SP,$MFAC	; Get spacing in 1/8 line increments
	.ENDC
	CALL	(R4)		; get argument of spacing command
10$:	  JMP	ILCM		; must be one
	.IF	DF	A$$RAP
	CLR	$MFAC		; Clear the flag
	.ENDC
	CMP	R3,#<5*DIVPL>	; must be in range 1 to 5 lines
	BHI	10$
	.IF	NDF	A$$RAP
	CMP	R3,#1.
	BHI	15$		; illegal value?
	.IFF
	TST	R3		; Greater or equal to zero is ok
	BGE	15$		; .sp 0 is overprint mode
	.ENDC
	MOV	#DIVPL,R3
15$:	.IF	NDF	R$$OCK
	ASL	R3		; Make in terms of half lines
	.ENDC	; R$$OCK

	MOV	R3,NSPNG	; ok.  store as normal spacing
20$:	RETURN			;
	.DSABL	LSB
	.IF	DF	A$$RAP

	.sbttl	SETSS - SET SUB/SUPERSCRIPT MOVEMENT

	.ENABL	LSB
SETSS::
	MOV	SP,$MFAC	; indicate increments of 1/8 line
	CALL	(R4)		; get argument in # of 1/8 line movements
	  MOV	#0,R3		; no arg, default to 4/8 (Half line)
	CLR	$MFAC		; Clear the flag
	CMP	R3,#3.		; must be in range 1/8 to 3/8
	BHI	10$
	CMP	R3,#0.
	BHI	15$
10$:	CLR	R3
15$:	MOV	R3,SSINC	; okay, store as new sub/super vertical inc.
	RETURN
	.DSABL	LSB
	.ENDC



	.sbttl	Title/subtitle commands
	.sbttl	SETSTL -- SUBTITLE COMMAND

	.ENABL	LSB
SETSTL::MOV	#STTLBF,R5	; set for subtitle buffer
	CLRB	$LINE2		; Clear alternate subtitle
	BR	10$		;

	.sbttl	FTITL -- FIRST TITLE COMMAND

FTITL::	CLRB	$HDSSW		; enable header on first page

	.sbttl	SETTL -- TITLE COMMAND

SETTL::	MOV	#TTLBUF,R5	; set for title buffer
	CALL	SHFUC		; shift to upper case for title
	CLRB	$LINE1		; Reset alternate title line
10$:	MOV	BF.ADR(R5),BF.PTR(R5) ; initialize descriptor
	CLR	BF.LEN(R5)	; Reset length
SETBF::	CALL	$FRCND		; force to logical end of command
20$:	CALL	GCIN		; read a character from title or subtitle
	CMPEQ	#CR,R1,30$	; carriage return?
	MOV	R5,R4		; point to buffer pointer
	CALL	WCI		; write character in buffer
	BR	20$		;
30$:	CALL	ULBSET		; reset underline buffer
	.IF	DF	A$$RAP
	CALL	OBBSET		; reset obverbar buffer
	.ENDC
	RETURN

;	Set up alternate title/subtitle lines
;
; Format:
;
;	.LINE n; text
;
;	n is 1 or 2 and specifies the title or subtitle line
;	text is the text to replace the title or subtitle.
;

STPGTP:: CALL	(R4)		; Get line #
2$:	  JMP ILCM		; Invalid if not specified
	CLRB	$HDSSW		; Enable header on first page
	CMP	R3,#2		; Can only be 1 or 2
	BHI	2$		; HI - then error
	BLO	40$		; LO - then check lower bound
	MOV	#STTLBF,R5	; Point to buffer to use
	COMB	$LINE2		; Indicate to use this
	BR	10$		; And get line of text

40$:	CMP	R3,#1		; Is it within range ?
	BNE	2$		; NE - then error
	COMB	$LINE1		; Indicate to use this
	MOV	#TTLBUF,R5	; Point to the buffer
	BR	10$		; And go get the buffer

	.DSABL	LSB


	.sbttl	LINE SKIPPING COMMANDS

	.sbttl	SKIPL -- Skip command

	.ENABL	LSB
	.IF	NDF	A$$RAP
SKIPL::	MOV	NSPNG,-(SP)	; skip command.  n current lines
	.IFF
SKIPL::	CALL	(R4)		; skip command. n current lines
	  MOV	#1,R3		; Default to 1 line
	MOV	NSPNG,R0	; To multilpy by line spacing
	.ENDC
	BR	10$

	.SBTTL	LINSKP -- Blank command

	.IF	NDF	A$$RAP
LINSKP::MOV	#DIVPL,-(SP)	; blank command.  n real lines
10$:	CALL	(R4)		; get optional argument
	  MOV	#1,R3		; if none, assume 1 (A$$RAP 1.0.3)
	MOV	(SP)+,R0	; retrieve number of line to skip
	.IFF
LINSKP::MOV	SP,$MFAC	; Can be in 1/8 line increments
	CALL	(R4)		; Get optional argument
	  MOV	#DIVPL,R3	; Default to 1 line
	CLR	$MFAC		; Clear flag
	MOV	#1,R0		; No multiplycation necessary
10$:
	.ENDC
	TST	R3		; Check if arg is negative
	BMI	15$		; if neg, don't make top check
	CMP	LINEC,$HDRSW	; at top of page?
	BLE	30$		; if LE yes
15$:
	.IF NDF	R$$EIS		; If no EIS, use $MUL
	MOV	R3,R1		; Get into R1 for $MUL
	CALL	$MUL		; multiply
	.IFF			; Otherwise, use MUL
	MUL	R3,R0		; Multiply
	.ENDC	;R$$EIS
	TST	R1		; Check if result is +
	BPL	17$		; And continue if normal
	MOV	R1,R2		; Get number of lines from end of page
	ADD	NLPG,R2		; R2 now has line number we want to get to
	CMP	R2,LINEC	; But check if we have already passed it
	BGT	16$		; if GT, then ok
	MOV	#DIVPL,R2		; else just skip one line
	BR	20$
16$:	SUB	LINEC,R2	; Generate number of lines to skip
	BR	20$
17$:	MOV	R1,R2		; check if room on page
	ADD	LINEC,R1	; add current line
	CMP	R1,NLPG		; room for another?
	BLE	20$
	JMP	BPAGE		; no. make a new page
20$:	CALL	SKIPN		; yes.  space out c(r2) lines
30$:	RETURN			;
	.DSABL	LSB

	.sbttl	FIGUR -- FIGURE COMMAND

FIGUR::	CALL	$FRCND		; force to end of command
	.IF	DF	A$$RAP
	MOV	SP,$MFAC	; Can be 1/8 line increments
	.ENDC
	CALL	(R4)		; get argument
	.IF	NDF	A$$RAP
	  MOV	#1,R3		; if none, assume one line
	ASL	R3		; double it
	.IFF
	  MOV	#DIVPL,R3	; If none, assume one line
	CLR	$MFAC		; Clear factor flag
	.ENDC
	CMP	R3,PNLPG	; check for rational argument
	BLOS	10$		; if LOS okay
	JMP	ILCM		; error
10$:	MOV	R3,R2		; Get # of lines to skip
	.IF	DF	A$$RAP
	ADD	LINEC,R3	; Add current line count
	CMP	R3,NLPG		; Room for figure on this page ?
	BLE	15$		; Yes, skip the lines.
	MOV	R2,-(SP)	; Save skip count
	CALL	BPAGE		; No, break the page, then skip lines
	MOV	(SP)+,R2	; Restore R2 skip count.
15$:
	.ENDC
	JMP	SKIPN		; space that out

	.sbttl	FIGURE -- FIGURE COMMAND (SKIPS NEXT WHOLE PAGE)

FIGURE::CALL	$FRCND		; force to end of command
	CALL	(R4)		; get argument
	  MOV	#1,R3		; if none, assume one page
	INC	SPFIG		; increment number of figures to skip
	RETURN


	.sbttl	LITRL -- LITERAL COMMAND

LITRL::	MOV	(R5),LITSV	; save current flags word
	BIS	#LITFG!SPECF,(R5) ; set literal flag
	MOV	CMADR,LITCM	; save current expected command address
	MOV	ELCMD,CMADR	; set address of expected command
	BR	FILOF		; turn off fill and justify

	.sbttl	ELTRL -- END LITERAL COMMAND

ELTRL::	MOV	LITSV,(R5)	; restore previous flags word
	MOV	LITCM,CMADR	; restore previous expected command address
	RETURN			;

	.sbttl	FILL AND JUSTIFY COMMANDS

	.sbttl	JUSTN -- Enable justifying

JUSTN::	BIS	#JUSTF+PJUSTF,(R5) ; turn on justifying
	RETURN			;

	.sbttl	JUSOF -- Disable justifying

JUSOF::	BIC	#PJUSTF+JUSTF,(R5) ; turn off justify bits
	RETURN			;

	.sbttl	FILLN -- Enable filling

FILLN::	BIS	#FILLF+JUSTF,(R5) ; turn on filling, copy pjustf to justf
	BITNE	#PJUSTF,(R5),10$ ; copy permanent flag
	BIC	#JUSTF,(R5)	; to current one.
10$:	RETURN			;

	.sbttl FILOF -- Disable filling

FILOF::	BIC	#FILLF+JUSTF,(R5) ; turn off filling and justifying
	RETURN			;
	.IF	DF	A$$RAP

	.sbttl	EQON -- Enter equation mode

EQON::
	MOV	SP,$EQMFL	; Indicate in equation mode
	MOV	(R5),EQFLSV	; Save flags and turn off fill/justify
	BIC	#FILLF+JUSTF,(R5)
	CLR	R3		; for relative argument
	MOV	SP,$MFAC	; 1/8 line count if desired
	CALL	(R4)		; Get test page count
	  MOV	EQTPC,R3	; Default test page count
	CLR	$MFAC		; Clear the switch
	MOV	R3,-(SP)	; Save it
	MOV	LMARG,EQLMSV	; Save left margin
	MOV	LMARG,R3	; Get current left margin
	CALL	(R4)		; Get relative argument
	  MOV	LMARG,R3	; Default to current left margin if none
	MOV	R3,-(SP)	; Save left margin
	CLR	R3		; For relative argument
	MOV	SP,$MFAC	; 1/8 lines
	CALL	(R4)		; Get skip count
	  MOV	EQSKP,R3	; Old skip count is default
	MOV	R3,-(SP)	; Save it
	CLR	R3		;
	CALL	(R4)		; Get new spacing count if any
	  MOV	EQSPC,R3	; Use old one if no argument
	CLR	$MFAC		; Clear the switch
	MOV	NSPNG,EQSPSV	; Save current spacing
	MOV	R3,NSPNG	; And set to equation mode spacing
	MOV	(SP)+,R2	; Retreive skip count
	BLE	10$		; If 0 or less - don't do it
	CMP	LINEC,$HDRSW	; In header area at top of page ?
	BLE	10$		; Yes don't skip
	CALL	SKIPN		;
10$:	MOV	2(SP),R3	; Test page
	BLE	20$		; don't test page
	CALL	TESTP		;
20$:	MOV	(SP)+,LMARG	; Set new left margin for equation
	TST	(SP)+		; pop off test page count
	RETURN			; return

	.sbttl	EQOFF -- exit equation mode

EQOFF::
	CLR	$EQMFL		; Clear equation mode indicator
	MOV	EQFLSV,(R5)	; Restore fill/justify flags ect.
	MOV	EQLMSV,LMARG	; Restore left margin
	MOV	EQSPSV,NSPNG	; Restore spacing count
	MOV	SP,$MFAC	; 1/8 line divisions
	CLR	R3		; For relative arg
	CALL	(R4)		; Skip count ?
	  MOV	EQSKP,R3	; If none use old as default
	CLR	$MFAC		; Clear 1/8 division indicator
	MOV	NSPNG,R2	; Add difference between original spacing and
	SUB	EQSPC,R2	; EQ spacing so white space before and after
	BGT	5$		; equation are equal. This doesn' work right if
	CLR	R2		; EQ spacing is greater than original spacing.
5$:	ADD	R3,R2		; Add diff to # of lines to skip (blank).
	BLE	10$		;
	CALL	SKIPN		; skip the lines
10$:	
	CALL	DELTMP		; Delete any temporary symbols created when
				; in .EQ/.EEQ mode.
	RETURN			;
	.ENDC

	.sbttl	SETTAB -- TAB STOP SELECTION COMMAND

SETTAB::CLR	NTABS		; clear number of tabs
	MOV	LMARG,R3	; start 1st tab at lm
				; others relative to prev. tab
SETT1:	CALL	(R4)		; get another stop if any
	NOP			;
	RETURN			;
	INC	NTABS		; point to next item
	MOV	NTABS,R0
	MOVB	R3,TABTAB-1(R0)	; store this tabstop
	CMP	R0,#TABTL-1	; check table size
	BLO	SETT1		; ok.
	JMP	ILCM		; too many tabs

	.IF	DF	A$$RAP

	.SBTTL	OVERP -- Overprint this line

OVERP::	BIS	#OVPFL,$OVPSW	; Indicate over print
	CALL	(R4)		; get argument (indentation)
	  MOV	#0,R3		; No indent if arg absent
	BR	OVERP1		; Common code , more or less

	.sbttl	OVERPJ -- Overprint right justified

OVERPJ::BIS	#OVPJFL,$OVPSW	; Indicate RJ overprint
	CALL	(R4)		; Get arg for right justify
	  MOV	PRMARG,R3	; Default is perm right margin
OVERP1:	MOV	NSPNG,-(SP)	; save spacing
	CLR	NSPNG		; skip 0 lines
	CALL	OUTNJ		; break line with 0 skip
	BR	OVERP2		; Justifies to RM or given column

	.sbttl	OVERB -- Over Bar command

OVERB::	BIS	#OVBFL,$OVPSW	; Indicate Over Bar command
	MOV	SP,$MFAC	; arg in 1/8 lines
	CALL	(R4)		; how high is the overbar ?
10$:	  MOV	#DIVPL,R3	; Default to one line
	CLR	$MFAC		; Clear the switch
	CMP	R3,#DIVPL	; Must be within one line
	BGT	10$		; Set to one line if out of range
	MOV	R3,-(SP)	; Save count
	MOV	#CR,R1		; Back up one line
	CALL	FOUT		;
	MOV	#ESC,R1		; Use a negative line feed
	CALL	FOUT		;
	MOV	#LF,R1		;
	CALL	FOUT		;
	MOV	#DIVPL,R2	; Space down to desired overbar line
	SUB	R3,R2		; 	and skip the lines in
	CALL	SKIPDI		; 1/8 line increments
	CLR	R3		; Right margin used in CENTER below
	BR	OVERP2		;
	.ENDC

	.SBTTL	CENTER -- CENTER COMMAND
;

CENTER::
	.if	ndf	A$$RAP
	MOV	PRMARG,R3	; Get right margin
	CALL	(R4)		; Get relative argument
	  MOV	PRMARG,R3	; Default is right margin
	.IFF
	CALL	(R4)		; get left margin spec
	  MOV	LMARG,R3	; default to left margin if none given
	TST	R3		; Must be non-neg - no relative args
	BGE	5$		; Ok
4$:	JMP	ILCM		; Not ok
5$:	MOV	R3,-(SP)	; Save till we get right margin
	CALL	(R4)		; get relative argument
	  MOV	PRMARG,R3	; default is permanent right margin
	MOV	(SP)+,R0	; Retreive left margin spec
	CMP	R0,R3		; Left margin must be less than or equal to right
	BGT	4$		; It's not - report error !
	CMP	R3,PRMARG	; Right must be less than permanent margin
	BGT	4$		; It's not - report error !
	SUB	LMARG,R0	; Set up right margin spec so it works with
	ADD	R0,R3		; Left margin offsetting below -
OVERP2:
	.ENDC
	MOV	R3,-(SP)	; store
	CALL	$FRCND		; force to logical end of command
	CMPNE	#CR,R1,CENT1	; not end of line?
10$:	CALL	GCIN		; discard rest of this command
	CMPNE	R1,#LF,10$	; not line feed?
CENT1:	CALL	GCIN		; read line to be centered
	CMPEQ	R1,#CR,CENT2	; carriage return?
	CALL	WLNIN1		; put in line input buffer
	BR	CENT1		; loop for more
CENT2:	MOV	(SP)+,R2	; compute spacing before line
	.IF	DF	A$$RAP
	BITNE	#OVPFL,$OVPSW,50$	; Skip Justify if overprint
	BITNE	#OVBFL,$OVPSW,25$	; Go output the overbars
	.ENDC
	SUB	LIBUF+BF.LEN,R2	; Less length of line
	SUB	LMARG,R2	; minus left margin
	ADD	NSPCH,R2	; including underlines, etc
	.IF	DF	A$$RAP
	BITNE	#OVPJFL,$OVPSW,50$	; Don't center
	.ENDC
	ASR	R2		; take half
	.IF	DF	A$$RAP
25$:
	.ENDC
	ADD	LMARG,R2	; add in left margin
	ADD	RIGSHI,R2	; Add on right shift space
	ADD	EBSIZ,R2	; Add on change bar area
	CALL	NSPAC		; output spaces
	MOV	#LIBUF+BF.ADR,R4 ; then output line buffer to file
	CALL	PSTRPA		; ..
	MOV	LIBUF+BF.ADR,LIBUF+BF.PTR ; Reset buffer
	CLR	LIBUF+BF.LEN	;   ...
	.IF	DF	A$$RAP
	BITNE	#OVBFL,$OVPSW,40$	; If overbar space back to original pos.
	.ENDC
	CALL	SKIPS		; skip one line
	.IF	DF	A$$RAP
	BR	60$		; return
40$:	MOV	(SP)+,R2	; Retreive # of lines to restore position
	CALL	SKIPDI		; and skip down
	BR	55$		; return

50$:	MOV	(SP)+,NSPNG	; restore spacing
	MOV	R2,INDCT	; Right justify with indentation count
55$:	MOV	#CR,R1		; do a carriage return
	CALL	FOUT		;
	CLR	$OVPSW		; Clear flags
60$:				;
	.ENDC
	RETURN			; Return to caller

	.SBTTL	FOOTN -- FOOTNOTE COMMAND

FOOTN::	CALL	(R4)		; how many lines to reserve?
5$:	  JMP	ILCM		; must have spec
	MOV	R3,R1		; Place in R1
	.IF	NDF	A$$RAP
	ASL	R1		; And double it
	.IFF
	ASH	#MUL8,R1	; Mul by 8 for check
	.ENDC
	CMP	R1,PNLPG	; value within reason?
	BHI	5$		; if HI no
	.IF	NDF	A$$RAP
	MOV	NSPNG,R0	; reserve n times spacing
	.IF NDF	R$$EIS		; If no EIS, use $MUL
	MOV	R3,R1		; Get into R1 for $MUL
	CALL	$MUL		; multiply
	.IFF			; Otherwise, use MUL
	MUL	R3,R0		; Multiply
	.ENDC	;R$$EIS
	.ENDC
	.IF	DF	A$$RAP
	MOV	LINEC,R2	; See if room for this footnote
	ADD	FOOTC,R2	; Plus footnotes already declared
	ADD	R1,R2		; Plus this footnote
	ADD	NSPNG,R2	; Plus current line to output
	ADD	NSPNG,R2	; Plus a normal spacing count
	CMP	R2,NLPG		; Less than page length ?
	BLO	6$		; yes
	SAVE	R0,R1,R2,R3,R4,R5
	CALL	SAVLIB		; Save LIBUF contents till after page break
	UNSAVE	R0,R1,R2,R3,R4,R5
6$:
	.ENDC
	ADD	R1,FOOTC	; add to reserved footnote lines

;	Allocate space in free list

	MOV	#80.,R0		; Set length
	.IF NDF	R$$EIS		; If no EIS available, use $MUL
	MOV	R3,R1		; Get # of lines
	CALL	$MUL		; Get buffer size to allocate
	.IFF			; Otherwise, use MUL
	MUL	R3,R0		; Get buffer size to allocate
	.ENDC	;R$$EIS
	ADD	#FN.SIZ,R1	; Add in additional overhead
	MOV	R1,R3		; Save buffer size -> R3
	CALL	ALLOC		; Allocate buffer space

;	Add item to footnote list

1$:	MOV	FOOTLH,R2	; Point to list head
	BEQ	3$		; EQ - then init back pointer
2$:	MOV	R2,R0		;
	MOV	FN.FWD(R0),R2	; Get next link
	BNE	2$		; NE - then check next link
	MOV	R1,FN.FWD(R0)	; Set foward pointer from last element
	MOV	R0,FN.BCK(R1)	; Set back pointer
	CLR	FN.FWD(R1)	; Set up foward pointer
	BR	4$

;	Create the first list entry

3$:	MOV	R1,FOOTLH	; Save list head
	CLR	FN.FWD(R1)	; Clear foward pointer
	CLR	FN.BCK(R1)	; Clear back pointer

;	Build buffer header

4$:	MOV	R1,R2		; Save pointer
	ADD	#FN.SIZ,R2	; Point beyond list header
	MOV	R3,-(SP)	; Save length of buffer
	SUB	#FN.SIZ,(SP)	; Get length remaining
	MOV	#FOOTP1,R3	; Point to buffer header
	MOV	R2,BF.ADR(R3)	; Set footnote pointers
	MOV	R2,BF.ADR+4(R1)	; Point to start
	MOV	R2,BF.PTR(R3)	; Point to next avail. slot
	MOV	R2,BF.PTR+4(R1)	;  ...
	MOV	R2,BF.END(R3)	; Set up pointer to
	ADD	(SP)+,BF.END(R3) ; Point to end
	MOV	BF.END(R3),BF.END+4(R1) ; ...
	CLR	BF.LEN+4(R1)	; And reset length
	CLR	BF.LEN(R3)	;  ...

	CALL	$FRCND		; force to logical end of line
	CLRB	GCSCH		; clear terminal character
	.IF	DF	A$$RAP
	MOV	#'!,FNCHAR	; Set default footnote terminator
	CMPEQ	#CR,R1,7$	; At end if cr found - else set to terminator
	MOV	R1,FNCHAR	;
7$:
	.ENDC
	CMPNE	#CR,R1,40$	; not end of line?
10$:	CALL	CCIN		; skip rest of command line
	CMPNE	R1,#LF,10$	; not line feed?
	BR	40$		;
20$:	CALL	CCIN		; read a character
30$:	MOV	#FOOTP1,R4	; Point to footnote header
	CALL	WCI		; Write character in buffer
	BCS	60$		; CS - then buffer overflowed
	CMPNE	R1,#LF,20$	; not end of line?
40$:	CALL	CCIN		; see what character after line feed is
	CMPEQ	R1,#EOF,50$	; end of file?
	.IF	NDF	A$$RAP
	CMPNE	#'!,R1,30$	; not end of footnote?
	.IFF
	CMPNE	FNCHAR,R1,30$	; not end of footnote?
	.ENDC
45$:	MOV	#EOF,R1		; set end of footnote
50$:	MOV	#FOOTP1,R4	; Point to footnote header
	CALL	WCI		; Write character in buffer
	BCS	60$		; CS - then buffer overflowed
	MOV	FOOTLH,R2	; Get list head
55$:	MOV	R2,R0		; Get last pointer
	MOV	FN.FWD(R0),R2	; Search for list end
	BNE	55$		; Loop till found
	MOV	FOOTP1+BF.LEN,BF.LEN+4(R0) ; Update length
	MOV	FOOTLH,R0	; Get pointer again
	MOV	BF.ADR+4(R0),FOOTP1+BF.ADR  ; Restore head of list
	MOV	BF.PTR+4(R0),FOOTP1+BF.PTR  ;  ...
	MOV	BF.END+4(R0),FOOTP1+BF.END  ;  ...
	MOV	BF.LEN+4(R0),FOOTP1+BF.LEN  ;  ...
	RETURN			; Return to caller

;	Footnote buffer has overflowed, tell user about it
;	and flush rest of footnote.

60$:	DIAG	FTNOVF		; Say it overflowed

62$:	CALL	CCIN		; Read a character
	CMP	R1,#EOF		; End of file ?
	BEQ	65$		; EQ - then terminate footnote
	.IF	NDF	A$$RAP
	CMP	R1,#'!		; End of footnote ?
	BNE	62$		; NE - then continue reading
	.IFF
	CMPNE	R1,FNCHAR,62$	; Not end of footnote - continue reading
	.ENDC
65$:	MOV	#FOOTP1,R4	; Point to footnote buffer
	SUB	#4,BF.PTR(R4)	; Point back a character
	SUB	#4,BF.LEN(R4)	;  ...
	MOV	#CR,R1		; Output a CR-LF
	CALL	WCI		;  ...
	MOV	#LF,R1		;  ...
	CALL	WCI		;  ...
	BR	45$		; And resume


	.sbttl	PERIOD SPACING COMMANDS
	.SBTTL	PERSP -- Enable period spacing

PERSP::	MOV	SP,$PERSW	; enable two spaces after punctuation
	RETURN			;

	.sbttl	NPERS -- Disable period spacing

NPERS::	CLR	$PERSW		; disable two spaces after punctuation
	RETURN			;

	.sbttl	SHFUC -- COROUTINE TO SHIFT TO UPPER CASE TEMPORARILY

SHFUC::	MOV	(SP),-(SP)	; copy return address
	MOV	CAS,2(SP)	; save current case
	CLR	CAS		; set for upper case
	CALL	@(SP)+		; call the caller back
	MOV	(SP)+,CAS	; restore previous case
	RETURN			;

	.sbttl	DATE -- DATE COMMAND

DATE::	CALL	$FRCND		; force to logical end of command
	CMPNE	#CR,R1,DATE1	; not end of line?
10$:	CALL	GCIN		; discard reset of this command
	CMPNE	R1,#LF,10$	; not a line feed?
DATE1:	MOV	#DATEBF,R0	; get address of buffer
20$:	CALL	GCIN		; read character
	CMPEQ	R1,#CR,DATE2	; is it carriage return
	CMPEQ	R0,#DATEBF+16.,DATE3	; too many characters
	MOVB	R1,(R0)+	; store character
	BR	20$		; get rest
DATE2:	MOV	R0,R2
	SUB	#DATEBF,R0	; get number of characters
	MOV	R0,DATECT	; store number of characters
40$:	CMP	R0,#16.
	BGE	30$
	MOVB	#' ,(R2)+
	INC	R0
	BR	40$
30$:	MOV	#1,$DATE	; save have date
	RETURN

DATE3:	CALL	GCIN		; get character
	CMPNE	R1,#CR,DATE3	; c/r?
	BR	DATE2		; yes return
	.DSABL	LSB


	.sbttl	DATET -- TABLE OF CONTENTS DATE COMMAND

DATET::	CALL	$FRCND		; force to logical end of command
	CMPNE	#CR,R1,DATE1T	; not end of line?
10$:	CALL	GCIN		; discard reset of this command
	CMPNE	R1,#LF,10$	; not a line feed?
DATE1T:	MOV	#DATTBF,R0	; get address of buffer
20$:	CALL	GCIN		; read character
	CMPEQ	R1,#CR,DATE2T	; is it carriage return
	CMPEQ	R0,#DATTBF+16.,DATE3T	; too many characters
	MOVB	R1,(R0)+	; store character
	BR	20$		; get rest
DATE2T:	MOV	R0,R2
	SUB	#DATTBF,R0	; get number of characters
	MOV	R0,DATTCT	; store number of characters
40$:	CMP	R0,#16.
	BGE	30$
	MOVB	#' ,(R2)+
	INC	R0
	BR	40$
30$:	MOV	#1,$DATET	; save have date
	RETURN
DATE3T:	CALL	GCIN		; get character
	CMPNE	R1,#CR,DATE3T	; c/r?
	BR	DATE2T		; yes return


	.sbttl	INDIRC -- INDIRECT FILE PROCESSING

INDIRC::
	MOV	R1,-(SP)	; save R1
	MOV	#80.,R1		; allocate 80. byte buffer.
	CALL	ALLOC		; allocate it.
	MOV	R1,R0		; point to buffer.
	MOV	(SP)+,R1	; recover R1
	MOV	R0,-(SP)	; save beginning of buffer.
	MOV	#80.,-(SP)	; (SP)->end of buffer
	ADD	R0,(SP)		;
10$:	BITB	#CHASP,CHATBL(R1) ; Is it a spacing character?
	BNE	20$		; NE - yes
	CMPEQ	#CR,R1,35$	; stop at end of line
	CMPEQ	#'!,R1,30$	; or at start of comment
	MOVB	R1,(R0)+	; save the character
	CMPEQ	R0,(SP),30$	; stop if buffer is full
20$:	CALL	GCIN		; get the next character
	BR	10$		; check next character
30$:	CALL	GCIN		; flush the rest of the line
	CMPNE	#CR,R1,30$	;
35$:	TST	(SP)+		; clear the stack
	MOV	R0,R1		; length of name => R1
	MOV	(SP)+,R0	; R0-> name
	SUB	R0,R1		;
	BLE	40$		; ignore if no file name
	CALL	PSHFIL		; save current file info
	BCS	40$		; ignore if too deep
	CALL	NEWFIL		; open the new file
40$:	MOV	R0,R1		; file name buffer into R1
	CALL	FREE		; free it
	MOVB	#CR,GCSCH	; force end of line on helpless thing
	RETURN			; and done.

	.SBTTL	SETN - SET NUMERIC VALUE
;
SETN::
	MOV	R4,-(SP)	; Save R4 while we use CCIN.
5$:	CALL	CCIN		; Try to read a character
	BITB	#CHASP,CHATBL(R1) ; Is it a spacing character?
	BNE	5$		; Yes - loop until nonspacing char.
	MOV	#<SYMLEN-1>,-(SP)	; Save the maximum length of name.
	MOV	#BUFR,R2	; Point to the buffer area.
	BITB	#CHALC!CHAUC,CHATBL(R1) ; Legal character?
	BEQ	99$		; no, error.
	BICB	#40,R1		; Raise to upper case just in case.
	MOVB	R1,(R2)+	; Get first part of name.
10$:	CALL	CCIN		; Get a character.
	BITB	#CHALC!CHAUC!CHANU,CHATBL(R1) ; Is it legal for an ident?
	BEQ	20$		; EQ - no
	DEC	(SP)		; Any more characters left?
	.IF	NDF	A$$RAP
	BMI	10$		; No - just ignore trailing characters
	.IFF
	BMI	99$		; Report error if too many characters for ident
	.ENDC
	BITB	#CHALC,CHATBL(R1) ; Is it lower case?
	BEQ	15$		; No - don't try to raise it to upper
	BICB	#40,R1		; Yes - raise to upper case.
15$:	MOVB	R1,(R2)+	; Yes - output it.
	BR	10$		; And get the rest of the symbol.
20$:	TST	(SP)+		; Discard symbol length.
	CLRB	(R2)+		; Pad the symbol with <NUL>
30$:	BITB	#CHASP,CHATBL(R1) ; Is the character space?
	BEQ	40$		; No - just skip.
	CALL	CCIN		; Yes - get next character.
	BR	30$		; And loop.
40$:	CMPB	R1,#'=		; Is it an = sign?
	BNE	99$		; No -- error.
	MOV	(SP)+,R4	; Recover R4
	CALL	(R4)		; Call the appropriate routine.
	  JMP	99$		; Illegal if nothing there.
	MOV	R3,R0		; Get the value into R0
	MOV	#BUFR,R1	; Point to the buffer from R1
	CALL	SETINT		; Set an integer value
	RETURN			; And return to the caller.
99$:	JMP	ILCM		; Illegal command
	DATA	RNCMDD
BUFR:	.BLKB	8.		; Room for symbol buffer.
	CODE	RNCMD
	.IF	DF	A$$RAP

	.SBTTL	SUBD - SET STRING VALUE TO BE SUBSTITUTED, DELIMITED SEARCH

SUBSTD::
	MOV	#DLTSYM,SYMMSK	; Indicate delimited search
	BR	SUBCOM		; Go to common code

	.SBTTL	SUB - SET STRING VALUE TO BE SUBSTITUTED
;
SUBST::
	CLR	SYMMSK		; Indicate not delimited search
SUBCOM:				; Common code
	TSTEQ	$EQMFL,5$	; In equation mode ?
	BIS	#TMPSYM,SYMMSK	; Yes ,indicate delete symbol when .EEQ reached
5$:
	MOV	R4,-(SP)	; Save R4 while we use CCIN.
6$:	CALL	CCIN		; Try to read a character
	BITB	#CHASP,CHATBL(R1) ; Is it a spacing character?
	BNE	6$		; Yes - loop until nonspacing char.
	MOV	#<SYMLEN-1>,-(SP)	; Save the maximum length of name.
	MOV	#BUFR,R2	; Point to the buffer area.
	CMPEQB	R1,#'=,900$	; If first character is '=', error
	MOVB	R1,(R2)+	; Get first part of name.
10$:	CALL	CCIN		; Get a character.
	BITNEB	#CHASP,CHATBL(R1),20$	; Exit loop if spacing character
	CMPEQB	R1,#'=,20$		; Exit loop if '=' found
	DEC	(SP)		; Any more characters left?
	BMI	900$		; Error if too many characters for ident
	MOVB	R1,(R2)+	; Yes - output it.
	BR	10$		; And get the rest of the symbol.
20$:	TST	(SP)+		; Discard symbol length.
	CLRB	(R2)+		; Pad the symbol with <NUL>
30$:	BITB	#CHASP,CHATBL(R1) ; Is the character space?
	BEQ	40$		; No - just skip.
	CALL	CCIN		; Yes - get next character.
	BR	30$		; And loop.
40$:	CMPB	R1,#'=		; Is it an = sign?
	BNE	900$		; No -- error.
;
;	Scan for string - first character is a delimiter - scan will
;	proceed until like delimiter is found or end of line (<cr>).
;
200$:	CALL	CCIN		; search for delimiter
	BITNEB	#CHASP,CHATBL(R1),200$	; loop if spacing character
;
;	Non spacing character - must be punctuation for valid delimiter
;
	CMP	#SPC,R1		; Must be greater than 'space'
	BGE	900$		; it's not - error
	BITNEB	#CHALC!CHAUC!CHANU,CHATBL(R1),900$	; error if not punctuation
	MOV	R1,-(SP)	; save the delimiting character
	MOV	#BUFR2,R2	; Move string into BUFR2
210$:
	CALL	CCIN		; Get next character
	CMPEQ	R1,(SP),300$	; Match on delimiter
	CMP	#SPC,R1		; If greater than 'space' it's ok
	BLE	230$		; Move to output buffer
	BITEQB	#CHAEC,CHATBL(R1),230$	; Not end-of-command character, continue
	MOV	R1,GCSCH	; Store break character
	BR	310$		; Enter symbol in table
230$:
	CMP	R2,#BUF2ND	; At end of temp buffer ?
	BGE	900$		; Yes string too long
	CMPEQB	#'|,R1,240$	; Command/text separartor - insert <cr><lf>
	MOVB	R1,(R2)+	; No - move character to temp buffer and
	BR	210$		; get the next character in string
240$:	MOVB	#CR,(R2)+	; Carriage return followed by
	MOV	#LF,R1		; Line feed - loop to check enough room
	BR	230$		;
;
300$:
310$:
	TST	(SP)+		; Clear delimiter
	MOV	(SP)+,R4	; Restore R4
	MOV	#BUFR2,R0	; Address of string variable
	SUB	R0,R2		; # of characters in string
	MOV	#BUFR,R1	; Address of string variable name
	CALL	SETCHA		; Enter into symbol table
	RETURN			; Return to caller
900$:	JMP	ILCM		; Illegal command
	DATA	RNCMDD
BUFR2:	.BLKB	40.		; Room for string buffer.
BUF2ND:				; End of buffer
	CODE	RNCMD
	.ENDC

;	Change metacharacter command
;
;	This command allows the user to change any
;	metacharacter to any other metacharacter, with
;	some exceptions.  Unfortunately, RNO does not
;	perform properly when ; or . are renamed, and
;	the execution could become difficult to understand
;	if it renamed to an already existing metacharacter,
;	so these cases are prevented.
;
CHANG:	CALL	$FRCND		; Get next item in command.
	CALL	GCIN		; Get first character of mnemonic
	CMP	R1,#140		; Lower case character
	BLT	1$		; Upper case
	SUB	#40,R1		; Make upper case
1$:	MOV	R1,R0		; Save the character
	CALL	GCIN		; Get second character of mnemonic
	CMP	R1,#140		; Make upper case if necessary
	BLT	2$
	SUB	#40,R1
2$:	SWAB	R1		; Put the two characters together
	BIS	R1,R0		; Cram the two characters together.
	MOV	METNUM,R3	; Get number of mnemonics
	MOV	#METNUM,R2	; Get location of last mnemonic
10$:	CMP	R0,-(R2)	; Compare  mnemonic
	BEQ	20$		; Found a match leave
	SOB	R3,10$
	DIAG	BADMET		; Say not found.
	RETURN			; And return.
20$:	DEC	R3		; Make into a 0-origin offset.
	ROL	R3		; Make into word address
	MOV	R3,-(SP)	; Save this location
	CLRB	GCSCH		; Force skipping previous char.
	CALL	$FRCND		; Get next item in command.
	BITB	#CHAEC,CHATBL(R1) ; Is it an end-of-command character?
	BNE	40$		; NE - yes, we can't alter those!
	CLR	R3		; Get beginning of metacharacters.
	MOV	METNUM,R2	; Get count of metacharacters.
30$:	CMP	R1,METBEG(R3)	; Found a match?
	BNE	35$		; No - this one's OK
	CMP	R3,(SP)		; Are we changing a metacharacter
				; to itself?
	BNE	40$		; J if not - duplicate metacharacter.
35$:	ADD	#2,R3		; Get to next matacharacter.
	SOB	R2,30$		; And loop over all metacharacters.
	MOV	(SP)+,R3	; Recover R3
	MOV	R1,METBEG(R3)	; Change to new metacharacter.
	RETURN			; And return.
40$:	MOV	(SP)+,R3	; Recover R3
	DIAG	DUPMET		; Duplicate metacharacter
	RETURN			; And return.
50$:	DIAG	ILLMET		; Can't change this metacharacter.
	RETURN

	.SBTTL	SWPFIL -- Swap output file

;+
;	This command enables the user to swap the output
;	from the .LST file to the .TOC file and back again.
;	This allows title pages to be output to the TOC
;	with little overhead.
;-

SWPFIL:: CALL	$FRCND		; Force to end of command
10$:	CALL	CCIN		; Get next char.
	CMPB	R1,#'a		; Is it lower case ?
	BLO	20$		; Maybe
	CMPB	R1,#'z		; Check upper range
	BHI	20$		; HI - then it's not lower case
	SUB	#40,R1		; Convert to upper case
20$:	CMPB	R1,#'T		; Change to TOC ?
	BEQ	30$		; EQ - yes
	CALL	FORM		; Break page
	CALL	OUTPUT		; Flush the buffer
	CLRB	$SWPFL		; Reset flag
	MOV	SAVLCT,LINEC	; Restore current line count
	BR	40$		; And go to next command

30$:	TSTB	TOCSPC		; Is a TOC file active ?
	BNE	32$		; NE - yes
	DIAG	NOTOC		; Else say so
	CLRB	$SWPFL		; Reset flag
	BR	40$		; And go flush remainder of command

32$:	MOV	LINEC,SAVLCT	; Save line count
 	CALL	OUTPUT		; Flush buffer
	CALL	TOTPUT		; Do TOC also
	COMB	$SWPFL		; Say to switch to .TOC file

40$:	CALL	CCIN		; Get another character
	CMPB	R1,#CR		; Carriage return ?
	BEQ	50$		; EQ - then return
	CMPB	R1,#';		; Semi-colon ?
	BEQ	40$		; EQ - then return
	CMPB	R1,#'.		; Another command ?
	BNE	40$		; NE - then get next character
50$:	MOVB	R1,GCSCH	; Save break character
	RETURN			; And return

	DATA	RNCMDA
SAVLCT:	.BLKW	1		; Saved line count

	CODE	RNCMD

	.sbttl	PRNTLN -- Print message to user.

;+
;	This command allows the user to pass a message
;	back to the user when processing a file. (i.e. current
;	version of document, special switches, etc.)
;-

PRNTLN:: CALL	$FRCND		; Force to end of command
	MOV	#MSGBF,R4	; Point to the buffer
	MOV	BF.ADR(R4),BF.PTR(R4) ; Reset secondary buffer
	CLR	BF.LEN(R4)	; ...
10$:	CALL	CCIN		; Read a character
	CMPB	R1,#CR		; Carriage return ?
	BEQ	20$		; Yes, then go output the message
	CALL	WCI		; Insert character into output buffer
	BR	10$		; Loop till thru
20$:	DIAG	USRMSG		; Output user message
	MOV	BF.ADR(R4),BF.PTR(R4) ; Clear title buffer
	CLR	BF.LEN(R4)	;  ...
	RETURN			; Return

	.END
