Google
 

Trailing-Edge - PDP-10 Archives - cuspbinsrc_1of2_bb-x128c-sb - 10,7/decmai/ms/msdspl.mac
There are 7 other files named msdspl.mac in the archive. Click here to see a list.
;This software is furnished under a license and may only be used
;  or copied in accordance with the terms of such license.
;
;Copyright (C) 1979,1980,1981,1982 by Digital Equipment Corporation
;	       1983,1984,1985,1986    Maynard, Massachusetts, USA


	TITLE MSDSPL - Message typeout and display routines for MS

	SEARCH GLXMAC,MSUNV,MACSYM
	PROLOG (MS)

	CPYRYT
	MSINIT

	.DIRECTIVE FLBLST
	SALL

;Define globals

	GLOBS			; Storage
	GLOBRS			; Routines

;Routines defined herein

	INTERNAL TYPBOD, TYPHDR, TYPLIT, TYPMHD

;Routines defined elsewhere

;MSUTL.MAC
	EXTERNAL COUNTS, CRIF, CRLF, MOVST0, MOVSTR, TBOUT, TNOUT, TSOUT, REMAP
	EXTERNAL GTBFL,	WTOP, SETSFL
;Data items defined elsewhere

;MS.MAC
	EXTERNAL LFCNT,MSGFAD,WBOT,MYHDPT,MYHSPT

SUBTTL Type header line for a message (HEADERS command)

TYPHDR:	CALL CRIF		; CRLF if needed
	SKIPG A,OUTIFN		; File or terminal?
	MOVX A,.PRIOU		; No, must be to TTY then
	SETZB C,D
	GTMBL (M,B)  		; Get ptr to message block
	MOVE T,MSGBTS(B)	; Get message's bits
	TXNE T,M%SEEN
	 SKIPA B,[" "]
	 MOVEI B,"N"		; New
	CALL TBOUT
	TXNN T,M%ATTN
	 SKIPA B,[" "]
	 MOVEI B,"F"		; FLAGGED
	CALL TBOUT
	TXNN T,M%RPLY
	 SKIPA B,[" "]
	 MOVEI B,"A"		; Answered
	CALL TBOUT
	TXNN T,M%DELE
	 SKIPA B,[" "]
	 MOVEI B,"D"		; Deleted
	CALL TBOUT
	MOVEI B,1(M)		; Message number
	$TEXT (TYPHD9,<^D4R /B/ ^A>)
	TXNN T,M%VALI		; Message parsed yet?
	CALL PRSMS0		; No, go parse it
	GTMBL (M,B)  		; Get ptr to message block
	SKIPG B,MSGDAT(B)	; Date
	 JRST [	$TEXT (TYPHD9,<      ^A>)	; Fill with spaces if not there
		JRST TYPHD2]
	$TEXT (TYPHD9,<^H6R /B/^A>)
	; ..
	; ..

TYPHD2:	SKIPG A,OUTIFN		; File or TTY
	MOVX A,.PRIOU		;  ..
	MOVEI B," "		; Delimit this column
	CALL TBOUT		;  ..
	GTMBL (M,B)  		; Get ptr to message block
	MOVE A,MSGFRM(B)	; "From" field
	MOVE C,MSGFRN(B)	; Size
	MOVEI B,^D22		; Limited to 22 chars
	CALL TYPFME		; Is this message from me?
	 SKIPA			; No...
	  JRST [$TEXT (TYPHD9,<To: ^A>)	; Yes, use "To:" field instead
		GTMBL (M,C)  		; Get ptr to message block
		MOVE A,MSGTO(C)		;  ..
		MOVE C,MSGTON(C)	;  ..
		SUBI B,4		; Account for "To: " string
		JRST TYPHD1]		;  ..
TYPHD1:	TXNE F,F%PRSN		; Personal name only?
	CALL TYPPRN		; Yes, extract it and point A to it
	CALL TYPHDS		; Type the field
	JUMPE B,TYPHD3		; None more needed
	MOVE C,B		; Make room
	MOVEI B," "
	SKIPG A,OUTIFN		; LPT, file, or terminal?
	MOVX A,.PRIOU		; Terminal
	CALL TBOUT
	SOJG C,.-1		; Fill with spaces
TYPHD3:	SKIPG A,OUTIFN		; File or TTY...
	MOVX A,.PRIOU		;  ..
	MOVEI B,"|"		; Delimit this column with vertical bar
	CALL TBOUT		;  ..
	GTMBL (M,B)  		; Get ptr to message block
	MOVE A,MSGSUB(B)	; Subject field
	SKIPG B,LINEW		; Get tty line width
	MOVEI B,^D72		; If unknown or weird, assume 72
	SUBI B,^D52		; Make rest of line fit
	GTMBL (M,C)  		; Get ptr to message block
	MOVE C,MSGBON(C)	; Get character count of msg
	CAIL C,^D100		; If length>100, need another column
	SUBI B,1		;  ..
	CAIL C,^D1000		; If length>1000, need another
	SUBI B,1		;  ..
	CAIL C,^D10000		;  etc. etc.
	SUBI B,1		; 5 columns ought to do it!
	GTMBL (M,C)  		; Get ptr to message block
	MOVE C,MSGSUN(C)	; Size of subject field
	PUSH P,F
	TXZ F,F%PRSN
	CALL TYPHDS
	POP P,F
	SKIPG A,OUTIFN
	MOVX A,.PRIOU
	SETZB C,D
	HRROI B,[ASCIZ / (/]
	CALL TSOUT
	GTMBL (M,B)  		; Get ptr to message block
	MOVE B,MSGBON(B)	; Length of message
	MOVEI C,^D10		; Base 10
	CALL TNOUT
	 JFCL
	HRROI B,[ASCIZ / chars)
/]
	CALL TSOUT		; Finish off line
	RET
;Here from $TEXT macros above

TYPHD9:	MOVE B,A		; Character
	SKIPG A,OUTIFN		; File
	MOVEI A,.PRIOU		;  or terminal
	CALL TBOUT
	$RET

TYPHD8:	IDPB A,UPDPTR		; Just stuff it
	RET
;TYPFME - Check to see if current message is from me
;Return	+1: no
;	+2: yes

TYPFME:	$SAVE <A,B,C,F>		; Don't clobber temps
	TRVAR <<TMPST,40>,SVNDPT> ; Temporary string space
	GTMBL (M,B)  		; Get ptr to message block
	MOVE V,MSGFRM(B)	; Point to beginning of "from" field
	MOVE W,MSGFRN(B)	; Length of "from" field
	CALL SETSFL
	PUSH P,V
	SUB V,WBOT
	MOVE A,MSGFAD
	IMULI A,5
	ADD V,A
       	CHR2BP			; Form byte pointer
	POP P,V
	MOVEI B,TMPST		; Pointer to temp space
	HRLI B,(POINT 7,)	;  ..
	TXZ F,F%F1!F%F2		; Init flags
TYPFM0:	SOJL W,TYPFM3		; Eat leading LWSP first
        ILDB C,A		;  ..
	CAIE C," "		;  ..
	CAIN C,11		;  ..
	JRST TYPFM0		; LWSP, ignore it
	JRST TYPFM2		; OK, have non-LWSP char to examine now
TYPFM1:	SOJL W,TYPFM3		; Insure that we don't run off end of field
	ILDB C,A		; Next char of "from" field
TYPFM2:	CAIN C,42		; Beginning of quoted string?
	JRST [	SOJL W,TYPFM3		; Yes, ignore - can't be real name
		ILDB C,A		;  ..
		CAIE C,42		; End of quoted string?
		JRST .			; No, eat chars
		JRST TYPFM0]		; Yes, start interpreting chars again
	CAIE C,12		; Stop at LF
	CAIN C,15		;  or CR
	JRST TYPFM3		;  ..
	CAIE C,"("		;  or start of comment
	SKIPN C			;  or null
	JRST TYPFM3		;  ..
	TXNN F,F%F1		; Inside real name yet?
	IFSKP.
	 CAIN C,">"		; If so, check for closure
	 JRST TYPFM3		; Real name closed, quit now
	 CAIE C,"@"		; Node name begin ?
	 JRST TYPFM6		; No - Real name not done yet
	 TXO F,F%F2		; Yes - Flag "got node"
	 TXZ F,F%F1		; And get rid of real name flag
	 MOVEM A,SVNDPT		; Save current pointer for node check
	 JRST TYPFM3		; Tie it off and start node name
	ENDIF.
	CAIN C,"<"		; Start of (trailing) real name?
	JRST [	MOVEI B,TMPST		; Yes, discard personal name
		HRLI B,(POINT 7,)	; Start checking real name
		TXO F,F%F1		; Flag this
		JRST TYPFM0]
TYPFM6:	IDPB C,B		; Character seems OK, stuff it
	JRST TYPFM1

TYPFM3:	SETZ C,			; End of string, insure ASCIZ
	IDPB C,B		;  ..
	MOVEI B,TMPST		; Now scan what we've got to isolate 1st word
	HRLI B,(POINT 7,)
TYPFM4:	ILDB A,B		; For each character,
	CAIN A," "		;  if a space,
	JRST [	SETZ A,			; Space ends 1st word, so
		DPB A,B			;  tie it off ASCIZ-wise
		JRST TYPFM5]		; Now we can do the compare
	JUMPN A,TYPFM4		; Until null found, loop
TYPFM5:	HRROI A,MYDIRS		; Compare extracted name
	HRROI B,TMPST		;  with my name
	$CALL S%SCMP		;  ..
	TXNE F,F%F2		; Got node name to ?
	JUMPE A,TYPFM7		; Yes, go check it
	JUMPE A,RSKP   		; No, A=0 implies match, so skip return
	RET			; No match, nonskip return

TYPFM7:	MOVEI B,TMPST		; Now scan the node name
	HRLI B,(POINT 7,)
	MOVE A,SVNDPT		; Get pointer to node name in message
TYPFM8:	SOJL W,TYPFM9		; Eat leading LWSP first
        ILDB C,A		;  ..
	CAIE C," "		;  ..
	CAIN C,11		;  ..
	JRST TYPFM8		; LWSP, ignore it
	SKIPE C			; Null ?
	CAIN C,">"		; End of address spec ?
	IFNSK.
	 SETZ C,		; Yes
	 IDPB C,B		; Terminate 
	 JRST TYPFM9		; And go check
	ENDIF.
	IDPB C,B		; Not white space, deposit it 
	JRST TYPFM8

TYPFM9:	MOVE A,MYHDPT		; Compare our decnet node name
	HRROI B,TMPST		;  with my name
	$CALL S%SCMP		;  ..
	JUMPE A,RSKP   		; No, A=0 implies match, so skip return
	MOVE A,MYHSPT
	HRROI B,TMPST		;  with my name
	$CALL S%SCMP		;  ..
	JUMPE A,RSKP   		; No, A=0 implies match, so skip return
	RET			; No match, nonskip return


SUBTTL Utility routines for HEADERS command

;Extract personal name from field and point to it (just copy field
; if no personal name present)
; Call:
;	A/ Character pointer to string
;	B/ Width of field (not used, but preserved)
;	C/ Length of string

TYPPRN:	TRVAR <<ARGS,3>,SVFLGS,SPACES>
	DMOVEM A,ARGS		; Save args
	SETZM SPACES		; No spaces yet
	MOVEM F,SVFLGS		;  and flags
	MOVEM C,2+ARGS		;  ..
	MOVEI T,[ASCIZ /
From-the-terminal-of: /]
	GTMBL (M,MX)   		; Get ptr to message block
	CALL FNDHDR		; No, see if local mail crock
	 JRST TYPPR2		; No, do usual
	CALL FNDSB1		; Compute length of this field
	MOVEM V,ARGS		; Fudge ptr to point to this field
	MOVEM W,2+ARGS		; Length of this field
TYPPR2:	MOVE M,MSGNUM(MX)	; Restore M
	MOVE V,ARGS		; Form byte ptr to string
	MOVE C,[POINT 7,STRBUF]	; Where to put extracted name
	SKIPN D,2+ARGS		; Length of field
	JRST TYPPRX		; None there, point to empty field and quit
	TXZ F,F%F1!F%F2		; Not in quoted field or personal name yet
TYPPR0:	CALL GTBFL		; Next char of field
	AOS V
	MOVE B,A
	CAIN B,15		; Ignore return
	JRST [	SOJG D,TYPPR0		; ..
		JRST TYPPRX]		; ..
	CAIN B,12		; Turn LF into space
	JRST [	MOVEI B,40		; ..
		SOJG D,TYPPR0		; ..
		JRST TYPPRX]		; ..
	TXNE F,F%F2		; Inside quoted string?
	JRST [	CAIN B,42		; Yes, is this the close quote?
		TXZ F,F%F2		; Yes, clear quote flag
		JRST TYPPR1]		; Move char literally
	CAIN B,40		; Space?
	JRST [	AOS SPACES		; Yes, count it
		SOJG D,TYPPR0		;  ..
		JRST TYPPRX]
	CAIN B,42		; Start of quoted string?
	JRST [	TXO F,F%F2		; Yes, flag quotedness
		JRST TYPPR1]		; Go move the quote
	TXNE F,F%F1		; Inside name?
	JRST [	CAIN B,")"		; End of comment (personal name)?
		JRST TYPPRX		; Got it -- done
		JRST TYPPR1]		; Still in quotes -- copy this char
	CAIN B,74		; Start of actual address (mach-ID) (brocket)?
	JRST [	CALL GTBFL		; Yes, flush it
		AOS V
		MOVE B,A
		SETZM SPACES		; Flush space counter too
		CAIE B,76		; End of mach-ID (close brocket)?
		JRST [	SOJG D,.		; No, keep eating chars
			JRST TYPPRX]		; Until no more left
		SOJG D,TYPPR0		; End of mach-ID, return to normal
		JRST TYPPRX]		;  processing, or quit if no more chars
	CAIN B,"("		; Start of comment field (personal name)?
	JRST [	MOVE C,[POINT 7,STRBUF]	; Yes, discard stuff copied so far
		SETZM STRBUF		; In case nothing inside parens
		SETZM SPACES		;  ..
		TXO F,F%F1		; Remember inside quotes
		JRST TYPPR0]		; Go copy this stuff
TYPPR1:	SKIPE SPACES		; Do we owe any spaces?
	JRST [	PUSH P,B		; Yes, make one
		MOVEI B,40		;  ..
		IDPB B,C		;  ..
		POP P,B			; Get actual character
		SETZM SPACES		; Reset space counter
		JRST .+1]
	IDPB B,C		; None of the above, move this char
	SOJG D,TYPPR0		; Do for all chars
TYPPRX:	SETZ B,			; Insure ASCIZ
	IDPB B,C		;  ..
	MOVE A,C		; Byte ptr to end of string
	BP2CHR			; Form char ptr to end of string
	MOVE B,V		; Preserve for a bit
	MOVE A,[POINT 7,STRBUF]	; Ptr to beginning of string
	BP2CHR			; Form char ptr
	MOVE A,V		; Return it in A
	SUB B,V			; Compute length of string
	MOVEI C,-1(B)		; Return in C -- account for null
	MOVE B,1+ARGS		; Return original B (width of column)
	MOVE F,SVFLGS		; Restore flags and return
	RET
;Type field
;
; A/ Character address of string
; B/ Width of field
; C/ Size of string
;
;Returns:
;	B/ number of chars left unfilled

TYPHDS:	JUMPE A,R		; Nothing there to type
	MOVE V,A		; Start of field
	JUMPE C,R		; Nothing if zero length
	CAMLE C,B		; Or truncate
	 MOVE C,B
	MOVN C,C
	ADD B,C			; Get number of chars needed to fill
	PUSH P,B
	TXNE F,F%PRSN		; Personal name only?
	JRST TPHDS1		;YES
	CALL SETSFL
	PUSH P,V
	SUB V,WBOT
	MOVE A,MSGFAD
	IMULI A,5
	ADD V,A
TPHDS1:	CHR2BP			; Get byte pointer
	TXNN F,F%PRSN		; Personal name only?
	POP P,V			;NO, RESTORE V
	MOVE B,A
	SKIPG A,OUTIFN		; LPT, file, or terminal
	MOVX A,.PRIOU
	CALL TSOUT
	POP P,B
	RET
;Type message headers
;Call:	A/ pointer to name of single header-item to type, or 0 for all
;	CALL TYPMHD
;Return	+1: message badly-formed (headers not separate) or single
;	    header-item not found
;	+2: OK, header name and contents typed

TYPMHD:	TRVAR <<HDR0,20>,HDR1,SHDR> ; Header-name, temp ptr to its end, ptr to selected header
	MOVEM A,SHDR		; Save pointer to single header-name
	GTMBL (M,B)  		; Get ptr to message block
	MOVX A,M%VALI		; Have we parsed this message yet?
	TDNN A,MSGBTS(B)	;  ..
	CALL PRSMS0		; No, do so then
	GTMBL (M,B)
	SKIPN C,MSGBON(B)	; Is this message empty?
	RET			; If empty, bad format
	CAMN C,MSGHDN(B)	; Are headers distinguished from msg body?
	RET			; No, give failure return then
	SKIPE A,SHDR		; Single header being selected?
	CALLRET TYPSHD		; Type the header-item and return
	TXNE F,F%VBTY		; Verbosely type it?
	JRST TYPMS2		; Yes, no fancy header handling then
	SKIPE E,OHSN		; Any "set only-headers-shown" cmd in effect?
	JRST TYPM0A		; Yes, it takes precedence over supressed hdrs
	GTMBL (M,B)  		; Get ptr to message block
	MOVE V,MSGBOD(B)	; Get start of message body
	CALL REMAP		;MAKE SURE WE ARE OK
	MOVE W,MSGHDN(B)	; Length of message headers
TYPM0B:	MOVE A,MSGFAD
	IMULI A,5
	PUSH P,V
	SUB V,WBOT
	ADD V,A
	CHR2BP
	POP P,V
	MOVEI B,HDR0		; Where to store this headername
	HRLI B,(POINT 7,)	;  ..
	SETZ E,			; Init length of this name
	MOVEI X,^D79		; Fence in case non-RFC733 header
TYPM0C:	ILDB C,A  		; Copy header name to temp space
	SOJL X,[MOVEI A,1(M)
		WARN <Incorrectly formatted header for message %1D
>
		RET]
	ADDI E,1		; Count length of name
	CAIN C,":"		; Go for name of this one
	JRST TYPM0D
	JUMPE C,TYPM0C		; Ignore nulls inserted by cretinous mailers
	IDPB C,B		; Store real chars
	JRST TYPM0C
;Here with header name stored in HDR0, see if suppressed or not

TYPM0D:	MOVEM B,HDR1		; Remember where string ends
	SETZ C,			; Tie string off
	IDPB C,B		;  ..
	PUSH P,W		; Save current length of rest of hdr area
	SETZ W,
	CALL FNDTO1		; Compute length of arg for this hdr item
	GTMBL (M,MX)   		; Get ptr to message block
	MOVE M,MSGNUM(MX)
	POP P,W			; Restore header area byte count
	ADDI X,2		; Account for terminating CRLF
	SKIPN A,CNCLHD		; Point to concealed-headers table
	JRST TYPM0F		; None are concealed, type this one then
	HRROI B,HDR0		; Point to name we're checking on
	$CALL S%TBLK		; Do the lookup
	TXNE B,TL%EXM		; Found?
	JRST TYPM0E		; Yes, don't type it
TYPM0F:	SETZ A,			; Insure ASCIZ
	IDPB A,HDR1		;  ..
	HRRI A,HDR0		; Form ptr to name of this header item
	HRLI A,(POINT 7,)	;  ..
	TXNE F,F%BREF		; Want fancy (brief) address list display?
	CALL ADDRSP		; Yes, see if this is an address field
	 SKIPA			; Not an address field, type it normally
	  JRST [MOVX A,.PRIOU		; Address field - first type its name
		HRROI B,HDR0		; Which we know is here
		SETZ C,			;  ..
		CALL TSOUT		;  ..
		MOVEI B,":"		; Type the colon
		CALL TBOUT		;  ..
		PUSH P,V		; Must preserve this, actually
		ADDI V,(E)		; Reflect that we've typed name
		CALL TYPMSA		; Now type its contents fancily
		POP P,V			; Restore char pointer
		JRST TYPM0E]		;  ..
	PUSH P,V
	SUB V,WBOT
	MOVE A,MSGFAD
	IMULI A,5
	ADD V,A
	CHR2BP			; Not concealed - form BP to it
	POP P,V
	MOVE B,A		; Set up for TSOUT
	MOVX A,.PRIOU		; Type on terminal
	MOVE C,X		; Length of contents
	ADDI C,(E)		;  plus length of name
	MOVN C,C		; Negate count, so embedded nulls have
	SETZ D,			;  no significance to TSOUT
	CALL TSOUT		; Type this one
TYPM0E:	SUBI W,(E)		; Account for length of name
	ADDI V,(E)		;  ..
	SUBI W,(X)		;  and for length of contents
	ADDI V,(X)		;  ..
	CAILE W,2		; Are we down to the extra CRLF?
	JRST TYPM0B		; No, go handle next header-item
	CALL CRLF		; Yes, type the blank line
	RETSKP			;  and return
;Here if doing "set only-headers-to-show"

TYPM0A:	MOVN E,E		; Yes, build AOBJN ptr to table of names
	HRLZ E,E		;  ..
TYPMS0:	MOVE A,OHSPTR(E)	; Get addr of first header name to show
	HRLI A,(POINT 7,)	; Form byte pointer
	CALL TYPSHD		; Type it if present
	 JFCL			; Don't care if not found
	AOBJN E,TYPMS0		; No, must be next header item... go check it
TYPM1B:	CALL CRLF		; Make a blank line
	RETSKP			; Return OK


;Here if doing no special header handling -- type all headers literally

TYPMS2:	GTMBL (M,B)  		; Get ptr to message block
	MOVN C,MSGHDN(B)	; Get negative length of header area
	MOVE V,MSGBOD(B)	;  and start of entire message
	CALL SETSFL
	PUSH P,V
	SUB V,WBOT
	MOVE A,MSGFAD
	IMULI A,5
	ADD V,A
	CHR2BP			; Form byte pointer
	POP P,V
	MOVE B,A		; Set up for TSOUT
	MOVX A,.PRIOU		; Type on terminal
	SETZ D,
	CALL TSOUT
	RETSKP

;Type body of message

TYPBOD:	GTMBL (M,B)  		; Get ptr to message block
	MOVN C,MSGBON(B)	; Length of msg body
	ADD C,MSGHDN(B)		; Minus length of hdrs (already handled)
	MOVE V,MSGBOD(B)	; Beginning of msg body
	ADD V,MSGHDN(B)		; Skip header area
	CALL GTBFL		; MAKE SURE WE ARE IN THE WINDOW
TYPB1:	MOVE D,V    		; CURRENT CHAR POINTER
	SUB D,WTOP		; Get negative count of bytes in window
	SOS D			; Minus one.
	MOVE A,C		; Get negative size of message body
	CAMLE D,C		; Use the lesser of the two
	 MOVE A,D		;NO, USE D
	MOVN D,A		;CALCULATE HOW MANY LEFT NONOUTPUT
	ADD D,C
	PUSH P,D		;AND STORE IT
	MOVE C,A
	PUSH P,C		;STORE CHAR COUNT
	PUSH P,V
	MOVE A,MSGFAD
	IMULI A,5
	SUB V,WBOT
	ADD V,A
	CHR2BP			; Form byte pointer to stuff to type
	POP P,V
	MOVE B,A		; Set up for TSOUT
	MOVX A,.PRIOU		; Type on terminal
	SETZ D,
	CALL TSOUT		; Type it
	POP P,C			;RESTORE COUNT
	POP P,D			;RESTORE HOW MANY LEFT
	SKIPN D			;IF NOTHING LEFT
	RET			;RETURN
	SUB V,C			;UPDATE CHAR COUNT
	CALL REMAP		;SHAKE IT
	MOVE C,D
	JRST TYPB1		;GO AGAIN

;Type single message header-item
;Call:	A/ Pointer to name of header-item to type (without colon or CRLF)
;	CALL TYPSHD
;Return	+1: can't find header item, nothing typed
;	+2: OK, header and contents typed and cursor back at left margin

TYPSHD:	$SAVE <E>		; FNDHDR (called by FNDTO0) clobbers E
	TRVAR <SNAM,LENTH,<STR0,40>>
	MOVEM A,SNAM		; Save ptr to header name string
	MOVEI A,STR0		; Where to build string
	HRLI A,(POINT 7,)	;  ..
	MOVEI B,[BYTE (7) 15, 12, 0]	; Start with CRLF
	CALL MOVSTR		;  ..
	MOVE B,SNAM		; Now the header name
	CALL MOVSTR		;  ..
	MOVEI B,[ASCIZ /:/]	; Now a colon
	CALL MOVST0		; Move it and the null
	MOVEI T,STR0		; Set up for FNDTO0
	GTMBL (M,MX)   		; Get ptr to message block
	CALL FNDTO0		; Find this one if you can
	MOVE M,MSGNUM(MX)
	JUMPE V,R		; Not found, give failure return
	MOVE A,SNAM		; Get pointer to header-name
	CALL COUNTS		; Count the bytes in it
	ADDI A,1		; Count the colon too
	MOVEM A,LENTH		; Save length
	SUB V,A			; Back up so name is typed as well as contents
	ADD X,A			; Account for length in byte count
	MOVE A,SNAM		; Point to name of header-item
	TXNE F,F%VBTY		; Verbose-type?
	JRST TYPSH0		; Yes, don't compress address lists
	TXNE F,F%BREF		; Want brief address lists?
	CALL ADDRSP		; Yes, is this an address field?
	 SKIPA			; No to either, just type literally
	  JRST [CALL SETSFL	;MAKE SURE WE ARE OK
		PUSH P,V	;SAVE CHAR POINTER
		SUB V,WBOT
		MOVE A,MSGFAD
		IMULI A,5
		ADD V,A
		CHR2BP			; Form byte ptr to hdr name
		MOVE B,A		; Set up for SOUT
		MOVX A,.PRIOU		;  ..
		MOVE C,LENTH		; Length of header-item
		CALL TSOUT		; Type header name
		POP P,V			;RESTORE CHAR POINTER
		MOVE A,LENTH		; Adjust pointer and count to reflect
		ADDI V,(A)		;  that we've typed the header name
		SUBI X,(A)		;  ..
		CALL TYPMSA		; Type contents fancily
		JRST TYPSHX]		; All done
TYPSH0:	CALL SETSFL
	PUSH P,V
	SUB V,WBOT
	MOVE A,MSGFAD
	IMULI A,5
	ADD V,A
	CHR2BP			; Form byte pointer to header contents
	POP P,V
	MOVE B,A		; Set up for SOUT
	MOVX A,.PRIOU		; Type on terminal
	MOVE C,X		; Byte count
	SETZ D,
	CALL TSOUT
TYPSHX:	CALL CRLF
	RETSKP

;Type entire message, headers and text, literally

TYPLIT:	GTMBL (M,B)  		; Get ptr to message block
	MOVN C,MSGBON(B)	; Type entire message body
	MOVE V,MSGBOD(B)	;  ..
	CALL REMAP
	PUSH P,V
	SUB V,WBOT
	MOVE A,MSGFAD
	IMULI A,5
	ADD V,A
	CHR2BP			; Form byte pointer to stuff to type
	POP P,V
	MOVE B,A		; Set up for TSOUT
	MOVX A,.PRIOU		; Type on terminal
	SETZ D,
	CALLRET TSOUT		; Type and return
;See if current header item in msg being typed is an address item
;Call:
;	A/ pointer to name string for header item
;	CALL ADDRSP
;Return	+1: Not an address item
;	+2: Is an address item

ADDRSP:	MOVE B,A		; Set up for S%CMND
	MOVEI A,ADDRST		; Table of address header-names
	$CALL S%TBLK		; Lookup
	TXNN B,TL%EXM		; Found?
	RET			; No, nonskip
	RETSKP			; Yes, skip return

DEFINE XXX(S),<[ASCIZ /S/],,0>

ADDRST:	ADDRSC,,ADDRSC
	XXX (cc)
	XXX (Resent-cc)
	XXX (Resent-to)
	XXX (Reply-to)
	XXX (To)
ADDRSC==.-ADDRST-1
;TYPMSA - Type address header item fancily (compress address lists and
;	  suppress machine addresses enclosed in angle brackets)
;	  Name of item already typed, this routine only handles contents
;Call:
;	V/ character pointer to entire field
;	X/ length of field

TYPMSA:	$SAVE <X>		; Caller wants this preserved
	TRVAR <LDEPTH,MACHID,SPACE,NSPACE,NOTMCH>
	TXZ F,F%F1		; Not in quoted string
	SETZM LDEPTH		; Init depth of list nesting
	SETZM MACHID		; Not in mach-ID
	SETZM SPACE		; No spaces seen yet
	SETZM NSPACE		; No nonspace chars seen yet
	SETZM NOTMCH		; Nothing typed yet
	CALL SETSFL
	PUSH P,V
	SUB V,WBOT
	MOVE A,MSGFAD
	IMULI A,5
	ADD V,A
	CHR2BP			; Point to string
	POP P,V
	MOVE D,A		; Safer AC
TYPMA1:	SOJL X,TYPMAX		; When char count exhausted, return
	ILDB A,D		; Get next character
	TXNE F,F%F1		; Inside quoted string?
	JRST [	CAIN A,42		; Yes, close quote?
		TXZ F,F%F1		; Yes, clear flag
		JRST TYPMA2]		; No, continue
	CAIN A,42		; Open quote?
	JRST [	TXO F,F%F1		; Yes, flag quotedness
		JRST TYPMA2]		;  and continue
	CAIN A,74		; Open angle bracket?
	JRST [	AOS MACHID		; Yes, flag that
		SKIPN NOTMCH		; Anything typed so far ?
		CALL TPSPCS		; Handle spaces if nothing typed
		;SETZM SPACE		; Flush trailing spaces
		JRST TYPMA2]		; Continue
	CAIN A,";"		; Close of address list?
	JRST [	SOSG LDEPTH		; Yes, decrement nesting depth
		JRST TYPMA3		; Outer list closed - type the ;
		JRST TYPMA1]		; Flush this char otherwise
	CAIN A,":"		; Opening of address list?
	JRST [	AOS B,LDEPTH		; Yes, increment nesting depth
		CAIN B,1		; Outermost list?
		$CALL KBFTOR		; Yes, type the colon
		JRST TYPMA2]
TYPMA2:	SKIPE LDEPTH		; Inside an address list?
	JRST TYPMA1		; Yes, just flush chars
	SKIPN MACHID		; Inside mach-ID?
	JRST TYPMA3		; No, type this char out then
	CAIN A,76		; Yes, is this the closing angle bracket?
	 SOS MACHID		; Yes, count it
	SKIPN NOTMCH		; Anything typed so far ?
	 $CALL KBFTOR		; No - so type something
	JRST TYPMA1		; But don't type it
TYPMA3:	CAIN A,40		; Only count spaces, don't type now
	JRST [	AOS SPACE		;  ..
		JRST TYPMA1]		;  ..
	CAIN A,12		; Line feed?
	JRST [	SKIPN NSPACE		; Yes, did we type any nonspace chars?
		JRST TYPMA4		; No, reuse this line then
		AOS LFCNT		; Yes, advance to next line and count
		$CALL KBFTOR		; Type the LF
		SETZM SPACE		; Flush space count
		SETZM NSPACE		; Reinit nonspace count
		JRST TYPMA1]
	CALL TPSPCS		; Go handle spaces if any
	SETOM NOTMCH		; Flag that we typed something
	$CALL KBFTOR		; Nothing special, just type it
TYPMA4:	CAIE A,15		; Don't count returns as nonspace
	AOS NSPACE		; Count nonspace characters
	JRST TYPMA1


;Here to type out pending spaces if any

TPSPCS:	SKIPLE SPACE		; Spaces pending?
	JRST [	PUSH P,A		; Yes, save this char
		MOVEI A,40		; Type a space
		$CALL KBFTOR		;  ..
		POP P,A			; Restore current character
		SOS SPACE		; Count down spaces required
		JRST .-1]		; Go check again
	RET


;Here when done -- insure address lists closed, if not (because of badly-
; formatted message header), close lists, type CRLF (since suppression
; of address list contents suppressed the CRLF), and return.

TYPMAX:	SKIPN D,LDEPTH		; Address lists closed properly?
	RET			; Yes, all done then
TYPMX0:	MOVEI A,";"		; No, type a closure symbol
	$CALL KBFTOR		;  ..
	SOJG D,TYPMX0		;  for each unterminated list
	CALL CRLF		; Close the line
	SETZM LDEPTH		; Clean up the mess
	RET			;  and return

	END

; *** Edit 2466 to MSDSPL.MAC by PRATT on 6-Nov-85
; Don't do brief address list display on the From field


; *** Edit 2484 to MSDSPL.MAC by SANTEE on 21-Nov-85
; Clean up the various edit histories.
; *** Edit 2485 to MSDSPL.MAC by MAYO on 21-Nov-85
; 
; *** Edit 2486 to MSDSPL.MAC by PRATT on 22-Nov-85
; Copyright statements 
; *** Edit 2603 to MSDSPL.MAC by PRATT on 6-Dec-85
; Fix "type from me" code to handle username and node names 
; *** Edit 2605 to MSDSPL.MAC by PRATT on 9-Dec-85
; Fix up REDISTRIBUTE. Make headers say Resent, Fix sequence handling, Use
; Auto-send flag, Remove checking of trailer, Change brief-address-list header
; table, Don't include user defined headers in when resending. 
; *** Edit 2608 to MSDSPL.MAC by PRATT on 10-Dec-85
; Save F also in the type from me code (TYPFME) 
; *** Edit 2629 to MSDSPL.MAC by PRATT on 3-Jan-86
; If brief-address-list set, and no personal name has been set, make sure that
; the address within the "<>"'s are typed out.