Google
 

Trailing-Edge - PDP-10 Archives - mit_emacs_170_teco_1220 - emacs/bliss.emacs
There are no other files named bliss.emacs in the archive.
!* -*-TECO-*-	This library implements EMACS BLISS MODE.
                It is a version of ECC's PL1 mode, modified
                by T.Hess [HESS@DEC]!

!~FILENAME~:! !Package for editing BLISS code (BLISS Mode).!
BLISS
!BLISS Mode:! !C Set up for editing BLISS code.
$BLSIND ..D$ is set up for use by BLISS indent macros. (E.g. no special
    Lisp characters, and "words" are $, _, and alphanumerics.
Calls user-providable macro, INIT BLISS MODE, which can put BLISS
    macros into desired qregs.  If no macro exits, calls
    & Default Init BLISS Mode.  See the description of that subr
    for more details on what it does and how to construct your own.!

 m(m.m_&_Init_Buffer_Locals)	    !* Discard locals of old mode, and set: *!
				    !* .Q: Make Local Q-Reg. *!
				    !* .0: old value of $Switch Mode Process *!
				    !* Options$ *!

				    !* Standard stuff to set up:  *!

 1,:i*!m.LComment_Startw	    !* Comment start... *!
 1,:i*!_m.LComment_Beginw	    !* begin... *!
 1,:I*_)%M.LImbedded_Comment_Endw
 1,:I*%(_M.LImbedded_Comment_Beginw
 1,m.m&_Indent_Without_Tabsm.LMM_&_Indentw	    !* Dont use tabs. *!
 1,m.m&_XIndent_Without_Tabsm.LMM_&_XIndentw	    !* ... *!
 1,40m.lComment_Columnw	    !* Set comment column. *!

				    !* Now either personal or standard init: *!
				    !* They can use .0, .Q. *!
 1:<m(m.mInit_BLISS_Mode)	    !* Call users init. *!
    >"N				    !* User has no init,  *!
	m(m.m&_Default_Init_BLISS_Mode)'  !* ...so use default one. *!

  m.vBLSIND_..Dw		    !* Create a var for our dispatch table. *!
 ^:IBLSIND_..D\________________________________________________________________________________________________________________________________________A_____________________________A____A____A___AA___AA____A____'____(____)____A____A_________A____A____/___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA____A____;____A____A____A____A____A___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA____A____A____A____A___AA____A___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA___AA____A____|____A____A________\  !* And setup the dispatch table. *!

 q.0,1M(M.M&_Set_Mode_Line)BLISS !* Set, display mode. *!
 
!^R Indent BLISS Stmt:! !^R Indentation via previous statement type.
If there are non-label tokens to left, then just calls
    ^R BLISS Indent Relative.
If non-null arg, calls ^R Indent Nested.
Calls macros to indent statements after prev stmt's type, e.g.
    looks for macro named & BLISS Indent After Begin Stmt.
None found, it will call & BLISS Indent After Stmt.
If the previous statement was unfinished (i.e. we are not indenting
    a new statement really), then macros such as & BLISS Indent Unfin If Stmt
    are called.
The default unfinished-stmt macro is & BLISS Indent Unfin Stmt.
^R Print Last BLISS Indenter will print the name of the indentation
    macro called.!
!* The name of the indentation macro called is left in $Last BLISS Indenter$.
 * All indent macros are passes two args:
 *     ARG1 points to where to indent (previous indentation has been
 *	    deleted).
 *     ARG2 points to the prev stmt's token, so that the macro can see
 *	    its indentation or whatever it wants.
 * Indent macros should return two values, bounding the buffer area changed.
 *!
 [.2[.3[.4[.5
 :i*m.vLast_BLISS_Indenterw	    !* Start null.  Generally, subrs *!
				    !* will put their own names in here. *!
 .m(m.m&_BLISS_Tokens_to_Leftp)"N !* Toks left => ^R BLISS Indent Relative. *!
	 f^m(m.m^R_BLISS_Indent_Relative) '
 ff"G				    !* ARG => goto ^R Indent Nested. *!

	 :iLast_BLISS_Indenter(^R_Indent_Nested)	    !* We must put *!
				    !* name in since macro is EMACS *!
				    !* and doesnt like us... *!
	 f^m(m.m^R_Indent_Nested) '

 .[.1				    !* .1: where indent. *!

 1m(m.m&_BLISS_End_Prev_Stmt)u.2  !* .2: end of prev statement. *!
 q.2j
 m(m.m&_BLISS_Next_Token)u.5u.3
				    !* .3: before token after prev stmt. *!
				    !* .5: after token... *!
 q.5-."L q.2j m(m.m&_BLISS_Next_Token)u.5u.3 '
				    !* Don't pass . *!
 q.3-q.1"L			    !* Prev stmt unfinished. *!
            q.3,q.5x.4		    !* .4: string of token. *!
            1:< q.1,q.3m(m.m&_BLISS_Indent_Unfin_.4_Stmt)u.3u.1
                >"N		    !* No indent macro found. *!
                    q.1,q.3m(m.m&_BLISS_Indent_Unfin_Stmt)u.3u.1  !* Default. *!
                    ''
        "#			    !* Prev stmt finished. *!
            .-b"N		    !* There is a prev stmt. *!
                1m(m.m&_BLISS_End_Prev_Stmt)u.2   !* Go back another stmt. *!
                q.2j
                m(m.m&_BLISS_Next_Token)u.5u.3 
				    !* Get token, which is *!
				    !* the token for the statement just *!
				    !* before where we want to indent. *!
		q.5-."L q.2j m(m.m&_BLISS_Next_Token)u.5u.3 '
				    !* Don't pass . *!
                q.3,q.5x.4'	    !* String of token. *!
              "#		    !* No prev stmt in buffer. *!
                bu.3bu.5 :i.4'
            1:< q.1,q.3m(m.m&_BLISS_Indent_After_.4_Stmt)u.3u.1 !* Try ind. *!
                 >"N		    !* No macro for indenting that. *!
                    q.1,q.3m(m.m&_BLISS_Indent_After_Stmt)u.3u.1 !* Default. *!
                    ''
 fsrgetty"n q.1,q.3 '	    !* .1,.3 bound buffer area changed. *!
 fsechodis Afsechodis
 0t 
!^R Insert BLISS End:! !^R Insert end and show matching block.
Indents if no whitespace to left of cursor.
Displays buffer around matching block statement.
    ARG = number of seconds to display there.
Inserts a comment after the "end;" to show what was ended, e.g.
    "%( begin-name )%"  or  "%( if-begin )%".
    The MARK is left before this comment, point after so you can easily
    delete it with ^R Kill Region.!
 0,0a-_"N 0,0a-	"N	    !* If no whitespace to left... *!
   ^m(m.m^R_Indent_BLISS_Stmt)f'' !* ...then indent... *!
 .,(iEND;).f			    !* ...and insert end. *!
 .:				    !* Leave MARK after end;. *!
 .[.1 fnq.1j			    !* .1: Auto-restoring point. *!
 4r .[.6			    !* .: Start before END. *!
 [.2 [.4[.5 0[.3		    !* .3: BEGIN level counter. *!

 <  b-."E FG 1'		    !* Go back statements until find *!
				    !* a matching BEGIN *!

    1m(m.m&_BLISS_End_Prev_Stmt)j    !* Back 1 semicolon... *!
    m(m.m&_BLISS_Next_Token)u.5u.4   !* ... and fwd to prev stmt token. *!
    q.4u.2			    !* .2: Save beginning of this stmt. *!

    q.4,q.5f~IF"E		    !* IF: check last sub-stmt. *!
        q.4m(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4'
    q.4,q.5f~ELSE"E		    !* ELSE: check last sub-stmt. *!
        q.4m(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4'
    q.4,q.5f~INCR"E		    !* INCR: check last sub-stmt. *!
        q.4m(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4'
    q.4,q.5f~DECR"E		    !* DECR: check last sub-stmt. *!
        q.4m(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4'
    q.4,q.5f~DO"E		    !* DO: check last sub-stmt. *!
        q.4m(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4'
    q.4,q.5f~WHILE"E		    !* WHILE: check last sub-stmt. *!
        q.4m(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4'
    q.4,q.5f~UNTIL"E		    !* UNTIL: check last sub-stmt. *!
        q.4m(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4'
    q.4,q.5f~GLOBAL"E		    !* GLOBAL: check next token *!
        q.5+1m(m.m&_BLISS_Next_Token)u.5u.4    !* Might be ROUTINE *!
	q.4u.2'			    !* Pretend "GLOBAL" doesn't exist *!
    q.4,q.5f~ROUTINE"E		    !* ROUTINE: check first stmt after = *!
        q.5m(m.m&_BLISS_Skip_Decl)"E 1;'
	m(m.m&_BLISS_Next_Token)u.5u.4'
    q.4,q.5f~MODULE"E		    !* MODULE: check first stmt after = *!
        q.5m(m.m&_BLISS_Skip_Decl)"E 1;'
	m(m.m&_BLISS_Next_Token)u.5u.4'
    q.4,q.5f~MACRO"E		    !* MACRO: check first stmt after = *!
        q.5m(m.m&_BLISS_Skip_Decl)"E 1;'
	m(m.m&_BLISS_Next_Token)u.5u.4'

    q.4,q.5f~BEGIN"E q.3-1u.3'	    !* Dec level counter on BEGIN,  *!
    q.4,q.5f~END"E q.4-q.6"N %.3w''   !* Inc on END (finds ARG2 first). *!
    q.3-1:;			    !* Found match when level = 0. *!
    >
				    !* .4,.5: Bound BEGIN *!
 q.4,q.5x.4'			    !* .4 :=  BEGIN *!

 q.2j				    !* First token of statement containing *!
				    !* matching BEGIN *!
 fwx.5				    !* Now figure something for comment: *!
 5f~MACRO"E			    !* MACRO *!
     .[.6 q.1j i_% .u.1 ].6j	    !* Change END; to END; % *!
     Onamit'
 6f~MODULE"E Onamit'	    !* MODULE *!
 .m(m.m&_BLISS_Get_Statement_Label)u.3	    !* .3: 0 or label. *!
 q.3"E 7f~ROUTINE"E Onamit'	    !* Unlabelled ROUTINE *!
       "# 5f~BEGIN"N		    !* Unlabelled, if not BEGIN,  *!
	     fwx.3		    !* .3: token starting stmt (IF/...). *!
	     :i.3.3-.4'	    !* .3: IF-BEGIN, ELSE-... *!
	  "# fwx.3'''		    !* .3: BEGIN. *!
 Ocomend

!namit!				    !*  get next token. *!
  fw+.m(m.m&_BLISS_Next_Token)x.3 !* .3: token after ROUTINE/MACRO/MODULE *!
  :i.3.5_.3		    !* .3: "declaration"+nexttoken. *!
!comend!
 q.1j i_%(_.3_)%		    !* Comment the end statement. MARK is *!
				    !* before the comment from earlier. *!
 q.1-fku.1			    !* .1: Point after ; *!
 q.2j				    !* Back to match and... *!
 0 ^v				    !* ...Display there. *!
 *30:w			    !* Wait ARG seconds or til input. *!
 1 				    !* Exit, restore point. *!
!& BLISS Get Statement Label:! !S Return label for statement at ARG.
ARG: Point within statement.
Returns string containing label, or
Returns 0 if no label found.!
 .[.0 fnq.0j			    !* .0: Auto-restoring point. *!
 1m(m.m&_BLISS_End_Prev_Stmt)j    !* Move to end last stmt. *!
 1,.m(m.m&_BLISS_Next_Token)[.2[.1   !* .1,.2: Bound next token. *!
 q.2j 0,1a-:"N 0 '		    !* Return 0, no label found. *!
 q.1,q.2x* 			    !* Return label string. *!
!Indent BLISS Region:! !C Indents each line from here to MARK.
On each line it:
    moves past labels, comments to first token,
    then calls ^R Delete Horizontal Space,
    then calls ^R Indent BLISS Stmt.
Leaves mark and point around changed region, and old text in kill stack.!
 :[.1 .u.2 [.3[.4[.5
 q.1,q.2fu.2u.1		    !* Order point and mark. *!
 q.1j				    !* To beginning of region. *!
 1[9 q.1,q.2x.5			    !* Save text, set kill direction. *!
 q.1,q.2m(m.m&_Kill_Text)	    !* Kill region to save it on kill stack. *!
 g.5				    !* Get back region now to edit it. *!
 q.1j z-q.2u.2			    !* Reset .2 so doesnt change as edit. *!

 <  0l
    m(m.m&_BLISS_Next_Token)u.4u.3   !* Find next token. May be on another line *!
    q.3j			    !* Go to its left edge: first tok on its *!
				    !* line. *!
    z-.-q.2:;			    !* See if done. *!
    ^m(m.m^R_Delete_Horizontal_Space)w
    ^m(m.m^R_Indent_BLISS_Stmt)w	    !* Indent that line. *!
    l
    >

 q.1				    !* Set MARK at beginning of region. *!
 z-q.2j				    !* Set point at end. *!
 q.1,. 			    !* Display and exit. *!
!^R BLISS Indent Relative:! !^R BLISS Indent Relative to last line's words.
Successive calls get successive indentation points;  each call
    aligns under ARGth next word in previous line.
Words are separated by spaces, tabs, underscores, commas, periods.
To facilitate moving into a line, and changing an indentation, if
    there is whitespace to the right and left (i.e. this is a new
    indent call here), then the cursor is moved one column left.!
 qLast_BLISS_Indenter[.1
 :iLast_BLISS_Indenter.1(^R_BLISS_Indent_Relative)
 [1 ^:I1| qLast_BLISS_Indenteru.1   !* 1: Macro for weird tabbing. *!
	  :iLast_BLISS_Indenter.1(^R_Tab_to_Tab_Stop)  !* ... *!
	  :M(M.M^R_Tab_to_Tab_Stop)|	    !* ... *!
 0,1af_	+1"G		    !* If char to right is whitespace,  *!
    0,0af_	+1"G		    !* ...as is char to left,  *!
	fs hpos-1(		    !* ...then note column left,  *!
		   -d)m(m.m&_Indent)w	    !* ...and move there. *!
	''			    !* ... *!
 .[P FSHPOS[0			    !* P: orig point. 0: hpos. *!
 ^-f_	L		    !* Move left past whitespace. *!
 .[Q FSHPOS[2			    !* Q: point left of white. 2: hpos. *!
 0L<    B-."E QPJ :m1'		    !* No line for relative indenting *!
				    !* so just tab stop. *!
        -L1A-15."N0;'>		    !* Back to non-blank line. *!
 Q0"G1:<0,Q0+1:FM>"ER'		    !* Cursor to orig hpos. *!
		  "#0L1:<0,Q2+1:FM>"ER'	    !* ... *!
				   "#QPJ:M1'''	    !* ... *!

 < F:FB_.,	_"E:L'"#R'	    !* Find end of word. *!
     ^F_.,_	R	    !* Right to start next word. *!
     >				    !* Go to start of ARGth next word. *!

 FSHPOS(QQ,QPK			    !* Back to orig point, remove white left. *!
         ):M(M.M&_Indent)	    !* And indent to column found. *!
!^R Global BLISS Comment:! !^R Call ^R for large comment.
While in global comment ^R:
Comment column is set to 10,
^R Indent for Comment is called initially,
MM Auto Fill Mode$ is entered with auto-indent,
$Comment Begin$ is set to "%(*" to mark global comments.
"%(** )%" (comment with just a *) expand into %( * * *... )%,
    aligned with any surrounding global comments (for boxes),
    or if no surrounding comments expand into $BLISS Star Line Width$ wide
    (default is 51).
When ^R returns, comment-ends within each global comment will be
    vertically aligned.!
 0fo..qGlob_of_Comments_Flag"N	    !* Already in Global Comment. *!
    f:^m(m.m^R_Indent_for_Comment)'	    !* So just do M-;. *!
 1m.vGlob_of_Comments_Flagw	    !* Signal now in glob mode. *!
 fn0m.vGlob_of_Comments_Flagw   !* When leave, signal not in mode. *!
 [.1[.2
 m.m^R_End_Comment[..\	    !* Redefine M-\ temporarily *!
 :i*Global_Comment[..j
 10[Comment_Column
 :i*%(*[Comment_Start	    !* So mark each global comment *!
				    !* for later comment-end aligning. *!
 :i*_)%[Comment_End		    !* For ^R Comment end *!
 :i*%(*[Comment_Begin	    !* For comment continuation *!

 1[Space_Indent_Flag
 fs qp ptr			    !* Q: Pop to here to restore fill mode. *!
  [Auto_Fill_Mode		    !* Save whether auto-filling now. *!
  m(m.m_Auto_Fill_Mode)	    !* Into auto fill mode. *!
  :l gComment_Start		    !* Put in comment starter... *!
  1m(m.m^R_Indent_for_Comment)	    !* ... and then align it. *!
  .-z"L -l' :l			    !* Position at end of started comment. *!
   w				    !* Enter ^R mode for globals. *!
  0l				    !* Always be at line beginning. *!
				    !* so that HPOS works in virtl bufs. *!
  :fb%(*"L			    !* If we are in a global comment,  *!
     < l :fb%(*"E 1;' >'	    !* ...then go to line after comments. *!
  fs z-.f[ vzw		    !* Bounds around buffer before point. *!
  m(m.m&_Align_Global_BLISS_Comment_Ends)   !* Align those before point. *!
  zj f] vzw			    !* Restore bounds. *!
  .f[ vbw			    !* Bounds around buffer after point. *!
  m(m.m&_Align_Global_BLISS_Comment_Ends)   !* Align those after point. *!
  bj f] vbw			    !* Restore bounds. *!
  qQ fs qp unwindw		    !* Pop down and restore auto-fill. *!
 m(m.m&_Process_Options)	    !* Auto-fill may change. *!
 m(m.m&_Set_Mode_Line)		    !* ... *!
 
!& Align Global BLISS Comment Ends:! !S Ends within contiguous global comments.
Contiguous global comments are comments starting with "%(*", on
    successive lines.
Contiguous global comments have their comment-ends aligned vertically.
If a global comment consists soley of "*", i.e. it is "%(** )%",
    then it will expand out into a "%( * * * * ...* )%" comment, aligned
    with its contiguous global comments.  If no contiguous comments,
    expands out into %( * *...)%, $BLISS Star Line Width$ wide, default 51,
    and extending to left margin.
After alignment, "%(*" is replaced by "%( ".!
 [.1[.2[.3
 bj				    !* Go thru whole buffer. *!
 < :s%(*; fkc			    !* Find next contig global comment. *!
   0u.1				    !* .1: Max width of gc within cgc. *!
   0u.2				    !* .2: %(* )% found flag. *!
   0u.3				    !* .3: Count of gcs in this cgc. *!
   .( < :fb%(*;		    !* Next gc start in this cgc. *!
	%.3w			    !* .3: Inc gc count. *!
	.-1f_		    !* Replace with regular comment start. *!
	4f=*_)%"E 1u.2'	    !* .2: Found a %(** )% in this cgc. *!
	:fb)%;			    !* Find next gc end in this cgc. *!
	fs hpos,q.1 f u.1 w	    !* .1: Max width of gc. *!
	l >			    !* Next line, maybe end of cgc. *!
      fs z-.f[ vzw		    !* Set virtual buffer to end with cgc. *!
      )j			    !* Back to start of cgc. *!
   q.3-1"E			    !* If just one gc in cgc,  *!
      q.2"N			    !* ...and if was %(** )%,  *!
	-^f_	b k	    !* ...then kill indentation,  *!
	51fo..qBLISS_Star_Line_Widthu.1''    !* ...and set width of star line. *!
   q.1-2u.1			    !* .1: HPOS to put %( at. *!
   q.2"N			    !* If have a %( * * *...)% in * cgc,  *!
      (q.1-qComment_Column-3&1)+q.1u.1'   !* .1: round up if need to, to *!
				    !* make the * * )% come out evenly. *!
   < :s)%;			    !* Next gc end. *!
     -7f=%(_*_)%"E		    !* If comment was just a *, expand  *!
	 2r			    !* ...into * * * * ... *!
	 q.1-(fs hpos)/2 <i*_>    !* ... *!
	 2c '			    !* ... (to match 2r next). *!
     2r q.1m(m.m&_Indent) f	    !* Indent the comment end, tell ^R. *!
     l >			    !* Next line, continue. *!
   zj f] vzw			    !* Restore boundaries. *!
   >				    !* Continue with next cgc. *!
 				    !* Done aligning. *!
!^R End Global BLISS Comment:! !^R Exit large comment ^R.
Calls ^R End Comment, then exits ^R, so that global comment ^R
    is ended, and comment column will be reset to its old (one-line
    comment form) value.
If given an ARG, will inhibit alignment of global comment-ends, by
    replace all global comment-starts ("%(*") by regular comment-starts
    ("%( ").!
 ^m(m.m^R_End_Comment) f
 ff"G			    !* Given an ARG. *!
    .( bj			    !* ...so replace all %(*,  *!
       < :s%(*; .-1f_>	    !* ...with %( . *!
       )j'			    !* ...and return to original point. *!
 fs ^R_Exit  		    !* Exit this global com mode ^R. *!
!^R Slurp BLISS to Char:! !^R Prev line back to CHAR moved to point, indented.
Non-comment text from previous line (back to CHAR typed) is moved
    onto the current line, after indentation, and then ^R Indent
    BLISS Stmt is called to re-align.  Now that the prev line is
    changed, things might look better.
Any comment on prev line is left there, and ^R Indent for Comment is
    called on it to align it after the text is removed from before it.!
 [.1[.2[.3[.4[.5[.6
 m.i fiu.5			    !* .5: Get char to slurp to. *!
 z-.u.1				    !* .1: Original point. *!
 0l ^f_	 r		    !* Line begin, past indentation. *!
 z-.u.6				    !* .6: Where to put slurped stuff. *!
 0:l z-.u.3			    !* .3: Prev lines end. *!
 .m(m.m&_Back_Over_BLISS_Line_Comment)j   !* Before any comment & white. *!
 .u.2				    !* .2: Point before any comment. *!
 < .,(0l).:fb.5; >	    !* Search back ARG chars on this line. *!
 .,q.2f( fx.4 ) f		    !* .4: Slurped chars. *!
 z-.-q.3"N			    !* If was a comment, reindent it. *!
    ^m(m.m^R_Indent_for_Comment) f'	    !* ... *!
 z-q.6j				    !* Back to where to put text. *!
 .,(g.4 i ). f		    !* Get the slurped text. *!
 0l				    !* Back before text. *!
 ^m(m.m^R_Indent_BLISS_Stmt) f   !* Now reindent slurped text line. *!
 z-q.1j w 1 			    !* Exit, with orig point restored. *!
!^R Print Last BLISS Indenter:! !^R Print macro name in echo area.!
 qLast_BLISS_Indenter[.0	    !* Put name in more usable qreg. *!
 fs echo displayw		    !* Clear the... *!
 Cfs echo displayw		    !* ... echo area. *!
 ^ft.0			    !* Print name. *!
 0fs echo activew
 				    !* Exit. *!
!& BLISS Indent After Stmt:! !S Default after-indent, same as prev stmt.
If no prev stmt (i.e. 1st stmt in buffer), then indentation is
given by the variable $1st Stmt Indentation$, default = 10.
ARG1 -> where to indent.
ARG2 -> token for previous statement.
Returns two vals surrounding insertion.
Leaves pointer after indentation.!
 qLast_BLISS_Indenter[.1
 :iLast_BLISS_Indenter.1(&_BLISS_Indent_After_Stmt)
 u.1				    !* Where to indent. *!
 [.2				    !* Pointer to prev stmt token. *!
 [.3				    !* Indentation amount. *!

 q.2-b"E			    !* This is 1st statement, no prev. *!
    4u.3			    !* Indentation amount, default. *!
    1:<q1st_Stmt_Indentationu.3>' !* See if user provides an amount. *!
  "#				    !* There is a previous stmt. *!
    q.2j fs hposu.3'		    !* See how much prev stmt indented. *!

 q.1j				    !* Go to where indent. *!
 q.3-(fshpos)-1"L ^m(m.m^R_BLISS_Indent_Relative) '   !* If past where indent *!
				    !* to then call indent relative. *!
 q.3m(m.m&_Indent) 		    !* Indent and return ptrs around. *!
!& BLISS Indent After Compound:! !S Handle indentation for stmt after IF etc.
Compound stmts are IF-, ELSE-, INCR-, WHILE-, ...
ARG1 -> where to indent.
ARG2 -> token for previous statement.
Returns two vals surrounding insertion.
Leaves pointer after indentation.
If (e.g.) IF ... BEGIN, then indent aligns with BEGIN, +
    $COMP BLOCK Indentation$, i.e. $...$ over from BLOCK.
    (Default $COMP BLOCK$ is 0.)
If non-BLOCK, aligns with IF.!
 qLast_BLISS_Indenter[.1
 :iLast_BLISS_Indenter.1(&_BLISS_Indent_After_Compound)
 u.1				    !* Where to indent. *!
 [.2				    !* Pointer to prev stmt token. *!
 1:<qCOMP_BLOCK_Indentationu.3>"N	    !* Get $...$ or make. *!
        0m.vCOMP_BLOCK_Indentationu.3'   !* Default is 0. *!

 q.2j fs hpos[.6		    !* .6 has (default) indentation. *!
				    !* e.g. indentation of non-BEGIN IF. *!

				    !* Check for IF-BEGIN, IF-UNTIL, etc. *!
				    !* and align with BEGIN or UNTIL:  *!

 q.2m(m.m&_BLISS_Last_Sub-Stmt_Token)[.5[.4  !* .4,.5 around final token. *!
 q.4,q.5f~BEGIN"E q.4j fs hpos+q.3u.6'    !* IF ... BEGIN. *!
 q.4,q.5f~DO"E q.4j fs hpos+q.3u.6'	    !* IF ... DO. *!
 q.4,q.5f~UNTIL"E q.4j fs hpos+q.3u.6'    !* IF ... UNTIL. *!
 q.4,q.5f~WHILE"E q.4j fs hpos+q.3u.6'    !* IF ... WHILE. *!
 q.4,q.5f~INCR"E q.4j fs hpos+q.3u.6'	    !* IF ... INCR. *!
 q.4,q.5f~DECR"E q.4j fs hpos+q.3u.6'	    !* IF ... DECR. *!

 q.1j				    !* Go to where indent. *!
 q.6-(fshpos)-1"L ^m(m.m^R_BLISS_Indent_Relative) '	    !* If past where indent *!
				    !* to then call indent relative. *!
 q.6m(m.m&_Indent) 		    !* Indent and return ptrs around. *!
!& BLISS Indent Unfin Begin Stmt:! !S Indent after BEGIN.
ARG1: where to indent.
ARG2: BEGIN token.!
 ,m(m.m&_BLISS_Indent_After_New_Block)  
!& BLISS Indent After New Block:! !S Next statement indented more, for BEGIN etc.
ARG1 -> where to indent.
ARG2 -> BEGIN token.
2 Vals returned, around indentation.
Pointer left after indentation.
Indentation aligns with whatever follows the BEGIN, etc.!
 qLast_BLISS_Indenter[.1
 :iLast_BLISS_Indenter.1(&_BLISS_Indent_After_New_Block)
 u.1 [.2
 q.2j				    !* Start of Begin token. *!
 fs hpos+4[.3			    !* Record this column. *!
 q.1j
 q.3-(fshpos)-1"L ^m(m.m^R_BLISS_Indent_Relative) '   !* If past where indent *!
				    !* to then call indent relative. *!
 q.3m(m.m&_Indent) 		    !* Indent and return ptrs around. *!
!& BLISS Indent After Routine Stmt:! !S Indent $1st Routine Stmt Indentation$ amount.
If no $...$ then default 0.
ARG1 -> where to indent.
ARG2 -> ROUTINE token.
Returns two vals around indentation.
Leaves pointer after indentation.!
 [.1 [.2 [.3
 qLast_BLISS_Indenter[.4
 :iLast_BLISS_Indenter.4(&_BLISS_Indent_After_Routine_Stmt)
 0fo..q1st_Routine_Stmt_Indentationu.3	    !* Indentation amount. *!
 q.1j				    !* Where to indent. *!
 q.3-(fshpos)-1"L .,. '	    !* If past where indent do nothing. *!
 q.3m(m.m&_Indent) 		    !* Indent and return ptrs around. *!
!& BLISS Indent After End Stmt:! !S Insert indentation by matching BEGIN/ROUTINE
ARG1 -> where to indent.
ARG2 -> END token.
Returns 2 vals around indentation.
Returns with pointer after indentation.!
 qLast_BLISS_Indenter[.1
 :iLast_BLISS_Indenter.1(&_BLISS_Indent_After_End_Stmt)
 u.1 [.2 [.4[.5
 0[.3				    !* BEGIN/ROUTINE level counter. *!
 q.2j				    !* Start from END token. *!

!Put in sometime search for matching label subr... *!

 <  b-.;			    !* Go back statements until find *!
				    !* a matching BEGIN *!

    1m(m.m&_BLISS_End_Prev_Stmt)j    !* Back 1 semicolon... *!
    m(m.m&_BLISS_Next_Token)u.5u.4   !* ... and fwd to prev stmt token. *!
    q.4u.2			    !* Save beginning of this stmt. *!

    q.4,q.5f~IF"E		    !* IF: check last sub-stmt. *!
        q.4m(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4'
    q.4,q.5f~ELSE"E		    !* ELSE: check last sub-stmt. *!
        q.4m(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4'
    q.4,q.5f~INCR"E		    !* INCR: check last sub-stmt. *!
        q.4m(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4'
    q.4,q.5f~DECR"E		    !* DECR: check last sub-stmt. *!
        q.4m(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4'
    q.4,q.5f~DO"E		    !* DO: check last sub-stmt. *!
        q.4m(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4'
    q.4,q.5f~WHILE"E		    !* WHILE: check last sub-stmt. *!
        q.4m(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4'
    q.4,q.5f~UNTIL"E		    !* UNTIL: check last sub-stmt. *!
        q.4m(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4'

    q.4,q.5f~BEGIN"E q.3-1u.3'	    !*   or BEGIN,  *!
    q.4,q.5f~END"E %.3w'	    !* Inc on END (finds ARG2 first). *!
    q.3-1:;			    !* Found match when level = 0. *!
    >

 q.2j				    !* First token of statement containing *!
				    !* matching BEGIN *!
 fs hpos[.3			    !* Save match's indentation. *!
 q.1j
 q.3-(fshpos)-1"L ^m(m.m^R_BLISS_Indent_Relative) '	    !* If past where indent *!
				    !* to then call indent relative. *!
 q.3m(m.m&_Indent) 		    !* Indent and return ptrs around. *!
!& BLISS Indent Unfin Stmt:! !S Indent new line of unfinished statement.
Default for indenting unfinished statements. Does:
Case1: If there is an open paren, aligns with next non-white.
Case2: If $Unfin Stmt Indentation$ is defined it will indent
       $Unfin Stmt Indentation$ more than the start of the stmt.
Case3: If prev line contains start of stmt, aligns with 1st word after
       beginning of stmt token (which may be part of token).
Case4: Calls ^R BLISS Indent Relative.
ARG1 -> where to indent.
ARG2 -> token starting unfinished statement.
Returns 2 vals around indentation.
Point left after indentation.!
 qLast_BLISS_Indenter[.1
 :iLast_BLISS_Indenter.1(&_BLISS_Indent_Unfin_Stmt)
 u.1				    !* Where to indent. *!
 [.2				    !* Pointer to prev stmt token. *!
 [.4				    !* Extra indentation amount. *!
 [.3[.5
 1:<    fo..qUnfin_Stmt_Indentationu.4	    !* Get $...$ if defined. *!
        q.2j fs hposu.3	    !* How much prev stmt indented. *!
        q.3+q.4u.5		    !* Set column to indent to by $...$. *!

        >"N			    !* Not defined. *!
            q.1j -l		    !* To line before current. *!
	    q.2-."g		    !* Line has stmt token. *!
                   5*.,5*.+1:g..d[.6    !* Save . dispatch. *!
		   5*.:f..d     !* Change it to be break char. *!
                   2:fwl fshposu.5 !* Align with next word. *!
		   5*.:f..d.6 '    !* Change back. *!
		 "#		    !* Line doesnt have stmt token. *!
		   0u.5''	    !* Force call to indent rel. *!

 q.1j				    !* Go to where indent. *!
 1:<    -:ful			    !* See if any open parens. *!
        ^f_	jw		    !* Yes, go past white-space. *!
        fs hposu.5		    !* Will indent to this column. *!
        >
 q.1j				    !* Where indent *!
 q.5-(fshpos)-1"L ^m(m.m^R_BLISS_Indent_Relative) '	    !* If past where indent *!
				    !* to then call indent relative. *!
 q.5m(m.m&_Indent) 		    !* Indent and return ptrs around. *!
!& BLISS Indent Unfin If Stmt:! !S Indent new line of unfinished IF statement.
Indents same amount as the IF if the THEN hasn't occured yet.
If THEN has occured, just calls & BLISS Indent Unfin Stmt.
ARG1 -> where to indent.
ARG2 -> token starting unfinished statement.
Returns 2 vals around indentation.
Point left after indentation.!
 qLast_BLISS_Indenter[.1
 :iLast_BLISS_Indenter.1(&_BLISS_Indent_Unfin_If_Stmt)
 u.1				    !* Where to indent. *!
 [.2				    !* Pointer to prev stmt token. *!
 fsqpptr[.0			    !* .0: Unwind to here to restore vbuf. *!
 fsz-q.1f[vzw			    !* VBuf ends at point so dont consider *!
				    !* any statements after this unfin one. *!
 q.2j
 .,zm(m.m&_BLISS_Token_Search)THEN"N	    !* Point after last THEN. *!
    .,1m(m.m&_BLISS_Token_Search)IF"E	    !* No following IF, so  *!
       q.0 fs qp unwindw	    !* Restore vbuf. *!
       q.1,q.2m(m.m&_BLISS_Indent_Unfin_Stmt) '    !* treat as random. *!
       2r'			    !* Before IF under which to indent. *!
 q.0 fs qp unwindw		    !* Restore vbuf. *!
 fs hpos[.3			    !* See how much IF was indented. *!
 q.1j				    !* Go to where indent. *!
 q.3-(fshpos)-1"L		    !* Past where indent to,  *!
    ^m(m.m^R_BLISS_Indent_Relative) '	    !* so call indent relative. *!
 q.3m(m.m&_Indent) 		    !* Indent and return ptrs around. *!
!& BLISS Indent Unfin Comp:! !S Indent new line of unfinished compound.
Indents same amount as the last sub-statement so far.
ARG1 -> where to indent.
ARG2 -> token starting unfinished statement.
Returns 2 vals around indentation.
Point left after indentation.!
 qLast_BLISS_Indenter[.1
 :iLast_BLISS_Indenter.1(&_BLISS_Indent_Unfin_Comp)
 u.1				    !* Where to indent. *!
 [.2				    !* Pointer to prev stmt token. *!
 [.4[.5
 q.2,q.1f[hboundw		    !* Virtual buf around this unfin stmt. *!
 bm(m.m&_BLISS_Last_Sub-Stmt_Token)u.5u.4    !* Find last sub-stmt token. *!
 q.4j				    !* Go there. *!
 f]hboundw			    !* Restore original buf boundaries. *!
 q.4,q.5f~IF"E Ocfound'	    !* IF compound *!
 q.4,q.5f~INCR"E Ocfound'	    !* INCR compound *!
 q.4,q.5f~DECR"E Ocfound'	    !* DECR compound *!
 q.4,q.5f~DO"E Ocfound'	    !* DO compound *!
 q.4,q.5f~UNTIL"E Ocfound'	    !* UNTIL compound *!
 q.4,q.5f~WHILE"E Ocfound'	    !* WHILE compound *!

 q.1,q.4m(m.m&_BLISS_Indent_Unfin_Stmt)  !* No compound - use default *!

!cfound!
 q.4j fs hpos[.3		    !* See how much compound was indented. *!
 q.1j				    !* Go to where indent. *!
 q.3-(fshpos)-1"L ^m(m.m^R_BLISS_Indent_Relative) '
				    !* If past where indent to *!
				    !* Then call indent relative. *!
 q.3m(m.m&_Indent) 		    !* Indent and return ptrs around. *!
!& BLISS Next Non-Begin Token:! !C Returns next token which isn't BEGIN.!
 [.1[.2
 m(m.m&_BLISS_Next_Token)u.2u.1
 !BEGLP!			    !* pass over Begins *!
 q.1,q.2F~BEGIN"E m(m.m&_BLISS_Next_Token)u.2u.1 q.2j oBEGLP '
 q.1,q.2 
!& BLISS Next Token:! !S Return ptrs around next token in buffer.
ARG gives place to start from in buffer.
    No ARG means here.
ARG,: Labels are skipped unless pre-comma argument given.
Comments are skipped.!
 .[.1				    !* Save point while search. *!
 [.2[.3				    !* .3,.2 will bound token. *!
 qBLSIND_..D[..D		    !* Use BLISS break-chars. *!
 ff"G j'			    !* Position at ARG1 if any. *!

 z-b"E q.1j z,z '		    !* Empty buffer, no token. *!

 <				    !* Loop over comments, maybe labels. *!
				    !* Search for end of token or beginning *!
				    !* of comment:  *!
    :s%(!"E		    !* Search for token end. *!
        zj 0a"B q.1j z,z '	    !* No tokens found. *!
	.u.2			    !* .2: End of buf is end of token. *!
	-fwl .u.3 1;'		    !* .3: Mark beginning of token. *!
    0a-!"E 1@l !<!>'		    !* Skip to next line for comment *!
    -1a-%"E :s)%"E zu.3zu.2 1;' ' !* Skip imbedded comment. *!
    "#   .-1u.2			    !* .2: Possible end of token. *!
	 (ff&2)1a-:"N	    !* If pre-comma (i.e. accept labels) *!
				    !* or if not a label,  *!
	    q.2j-fwl .u.3 1;'	    !* .3: then have token. *!
	 '			    !* Skip past a label. *!
    >

 q.1j				    !* Restore point. *!
 q.3,q.2 			    !* Return bounds of token. *!
				    !* z,z if none found. *!
!& BLISS Skip Decl:! !S Searches for = , but not within parens.
Comments are skiped.
ARG1 is point in buffer to start from.
Returns 0 if search unsuccessful: end of statement (;) or end of buffer
 reached first, non-0 if successful.!
 0[.1 .[.2 j 0[.3		    !* .3 is return val. Init notfound. *!

 <
   :s=%(;!()"E 1;'	    !* Found nothing. *!
   0a-;"E 1;'		    !* End of statement found first. *!
   0a-!"E 1@l '		    !* Skip to next line for comment *!
   -1a-%"E :s)%"E 1;''	    !* Skip imbedded comments *!
   0a-("E %.1'		    !* .1: Paren depth *!
   0a-)"E q.1-1u.1'		    !* .1: Decr depth counter on ) *!
   0a-="E q.1"E 1u.3 1;''	    !* Found =  *!
  >
 q.3"E  q.2j '			    !* If unsuccessful, dont move. *!
 q.3 				    !* Return 0 lost, 1 won. *!
!& BLISS Token Search:! !S Searches for a token in a statement.
Comments are skipped.
ARG1 is point in buffer to start from.
ARG2 is iteration: i.e. search for ARG2th token.
STRINGARG is token to search for.
Returns 0 if search unsuccessful: end of statement (;) or end of buffer
    reached first, non-0 if successful.
Returns with pointer after token if successful.!
 :i*[.1 .[.2 j 0[.3	    !* .3 is return val. Init notfound. *!
 qBLSIND_..D[..D		    !* Use dispatch table for BLISS. *!

 f<!DONE!
      <				    !* For skipping comments. *!
        :s.1%(;!"E f;DONE'  !* Found nothing. *!
        fk+fq.1+2"E r 1u.3 1;'	    !* .3: Found token. *!
        0a-;"E f;DONE'	    !* End of statement found first. *!
	0a-!"E 1@l !<!>'	    !* Skip to next line for comment *!
        -1a-%"E :s)%"E f;DONE'  !* Skip imbedded comments, but allow *!
		 r 1u.3'	    !* .3: paren to end token. *!
        >>

 q.3"E  q.2j '			    !* If unsuccessful, dont move. *!
 q.3 				    !* Return 0 lost, 1 won. *!
!& BLISS Tokens to Leftp:! !S Returns 0 if no tokens to left on line.
ARG is pointer into line where to look left from.
Labels or comments are not counted.!
 [.1 .[.2 [.3[.4
 q.1j 0l			    !* To beginning of line. *!
 m(m.m&_BLISS_Next_Token)u.4u.3   !* Find next token after that. *!
 q.2j				    !* Back to original point. *!
 q.3-q.1"L 1 '		    !* Token is to left. *!
	"# 0 '		    !* Token is not to left. *!
!& BLISS Last Sub-Stmt Token:! !S Finds last stmt in compound stmt (if, on).
If current statement is "IF a THEN IF b THEN c;" this subr will return
    ptrs surrounding c's statement token.
ARG1 points to statement token from where to start, i.e. the compound
    statement's token (IF).
    If ARG1 points to a non-compound statement token, pointers around
    that token are returned.!
 [.1 .[.2 [.3[.4
 q.1j				    !* Position at starting stmt token. *!

 f<!Found!			    !* Find last sub-stmt token. *!
  1f<!Next!			    !* Check if compound statement. *!
     .m(m.m&_BLISS_Next_Token)u.4u.3
     q.3j			    !* Position at next token. *!

     fwf~IF"E			    !* IF-compound statement. *!
        .,1m(m.m&_BLISS_Token_Search)THEN"E f;Found'	 !* No THEN clause. *!

				    !* & BLISS Token Search skips comments *!
				    !* Returns 0 if ; or z reached first. *!
        1;'			    !* Again check if compound *!

     fwf~DO"E			    !* DO-compound statement. *!
        .,1m(m.m&_BLISS_Token_Search)WHILEUNTIL"E f;Found'
	1;'			    !* Again check if compound *!
     fwf~INCR"E		    !* INCR-compound statement. *!
        .,1m(m.m&_BLISS_Token_Search)DO"E f;Found'
	1;'			    !* Again check if compound *!
     fwf~DECR"E		    !* DECR-compound statement. *!
        .,1m(m.m&_BLISS_Token_Search)DO"E f;Found'
	1;'			    !* Again check if compound *!
     fwf~WHILE"E		    !* WHILE-compound statement. *!
        .,1m(m.m&_BLISS_Token_Search)DO"E f;Found'
	1;'			    !* Again check if compound *!
     fwf~UNTIL"E		    !* UNTIL-compound statement. *!
        .,1m(m.m&_BLISS_Token_Search)DO"E f;Found'
	1;'			    !* Again check if compound *!

     fwf~ELSE"E		    !* ELSE-compound statement. *!
        .+4m(m.m&_BLISS_Next_Token)u.4u.3 q.3j    !* Position after ELSE ... *!
        1;'			    !*    and again check if compound. *!

     f;Found			    !* Non-compound statement found. *!
     >				    !* End next. *!
    >				    !* End found. *!

 q.3,q.4(q.2j) 		    !* Return ptrs around token. *!
!& BLISS End Prev Stmt:! !S Return ptr to end prev ARG'th statement.
Value returned points to the semicolon.
ARG = 1 means find first end-; looking back from here.!
 .[.1				    !* Save point while search. *!

 <				    !* Look back ARG statements. *!
      <				    !* Look back one statement. *!
         -:s;)%!"E bj 1; '	    !* No previous statement. *!
                  "# 1a-!"E !<!>' !* Skip past comment *!
		     1a-;"E 1;'   !* Find end of prev stmt. *!
                     -:s%('	    !* Skip past imbedded comments. *!
         >			    !* Point at end of prev stmt. *!
     >

 .(q.1j) 			    !* Return semicolon-ptr and restore *!
				    !* point. *!
!& Back Over BLISS Line Comment:! !S From point, move left on line past comment.
ARG is ptr into some line to check left from.
Returns ptr to before comment and white-space before it.
If no comment on line, no movement: ARG is returned.!
 .[.1 j
 .,(0l).:fb%(!"E  '	    !* No comment found on line. *!
 -^fq_	[.2j		    !* Move before any white space. *!
 .(q.1j) 			    !* Return that place, reset point. *!
!& Setup BLISS Library:! !S Put macros into $MM ...$ qregs for speed.!
 m.m&_BLISS_End_Prev_Stmtm.vMM_&_BLISS_End_Prev_Stmtw
 m.m&_BLISS_Next_Tokenm.vMM_&_BLISS_Next_Tokenw
 m.m&_BLISS_Indent_After_Stmtm.vMM_&_BLISS_Indent_After_Stmtw
 m.m&_BLISS_Indent_After_New_Blockm.vMM_&_BLISS_Indent_After_Begin_Stmtw
 m.m&_BLISS_Indent_After_Endm.vMM_&_BLISS_Indent_After_End_Stmtw
 m.m&_BLISS_Indent_Unfin_Stmtm.vMM_&_BLISS_Indent_Unfin_Stmtw
 m.m&_BLISS_Indent_Unfin_If_Stmtm.vMM_&_BLISS_Indent_Unfin_If_Stmtw
 m.m&_BLISS_Indent_Unfin_Compm.vMM_&_BLISS_Indent_Unfin_Else_Stmtw
 m.m&_BLISS_Indent_Unfin_Compm.vMM_&_BLISS_Indent_Unfin_Do_Stmtw
 m.m&_BLISS_Indent_Unfin_Compm.vMM_&_BLISS_Indent_Unfin_Incr_Stmtw
 m.m&_BLISS_Indent_Unfin_Compm.vMM_&_BLISS_Indent_Unfin_Decr_Stmtw
 m.m&_BLISS_Indent_Unfin_Compm.vMM_&_BLISS_Indent_Unfin_While_Stmtw
 m.m&_BLISS_Indent_Unfin_Compm.vMM_&_BLISS_Indent_Unfin_Until_Stmtw
 m.m&_BLISS_Last_Sub-Stmt_Tokenm.vMM_&_BLISS_Last_Sub-Stmt_Tokenw
 m.m&_BLISS_Indent_After_Compoundm.vMM_&_BLISS_Indent_After_If_Stmtw
 m.m&_BLISS_Indent_After_Compoundm.vMM_&_BLISS_Indent_After_Else_Stmtw
 m.m&_BLISS_Indent_After_Compoundm.vMM_&_BLISS_Indent_After_Do_Stmtw
 m.m&_BLISS_Indent_After_Compoundm.vMM_&_BLISS_Indent_After_Incr_Stmtw
 m.m&_BLISS_Indent_After_Compoundm.vMM_&_BLISS_Indent_After_Decr_Stmtw
 m.m&_BLISS_Indent_After_Compoundm.vMM_&_BLISS_Indent_After_While_Stmtw
 m.m&_BLISS_Indent_After_Compoundm.vMM_&_BLISS_Indent_After_Until_Stmtw

 m.m&_BLISS_Token_Searchm.vMM_&_BLISS_Token_Searchw
 m.m&_BLISS_Indent_After_Routine_Stmtm.vMM_&_BLISS_Indent_After_Routine_Stmtw
 
!& Default Init BLISS Mode:! !S Default setup for BLISS mode.
It sets up the following characters for this mode and buffer:
    RUBOUT	Tab-hacking rubout,
    C-RUBOUT    Normal rubout,
    TAB 	^R Indent BLISS Stmt,
    C-M-?	^R Print Last BLISS Indenter,
    M-; 	^R Indent for Comment,
    M-\ 	^R Insert BLISS End,
    C-M-;	^R Global BLISS Comment,
    C-M-\	^R End Global BLISS Comment,
    M-{ 	^R Slurp BLISS To Char.
Turns on Auto Fill if $BLISS Auto Fill Default$ is non-0.
Users who want to provide their own MM Init BLISS Mode$ can make ^R keys
    (q-registers) and variables local to this mode and buffer by using the
    following subroutine which is global to Init BLISS Mode:
    .Q: Make Local Q-register!

				    !* Set up local ^R keys: *!

 1,q(1,q. m.Qw)m.Q.	    !* Exchange rubout flavors. *!
 1,m.m^R_Indent_BLISS_Stmtm.QI  !* Use Bliss-indenting tab. *!
 1,m.m^R_Print_Last_BLISS_Indenterm.Q...? !* C-M-? For tracing. *!
 1,m.m^R_Indent_for_Commentm.Q..;
 1,m.m^R_Insert_BLISS_Endm.Q..\
 1,m.m^R_Global_BLISS_Commentm.Q...;
 1,m.m^R_End_Global_BLISS_Commentm.Q...\
 1,m.m^R_Slurp_BLISS_To_Charm.Q..{

 0fo..qBLISS_Auto_Fill_Default(   !* Default is to auto-fill,  *!
   )m(m.m_Auto_Fill_Mode)	    !* ...will cause unfin indenting. *!
 1,1m.LSpace_Indent_Flagw	    !* ... *!
 				    !* Done. *!

!* Following should be kept as long comments:
 * Local Modes:
 * Fill Column:76
 * Comment End: *!
!*
 * End:
 * *!