Google
 

Trailing-Edge - PDP-10 Archives - mit_emacs_170_teco_1220 - emacs/aux.emacs
There are no other files named aux.emacs in the archive.
!* -*-TECO-*-  Random autoloading functions, not used very often,
and not providing any fundamental capability not present in EMACS :EJ.!

!~Filename~:! !Random functions autoloaded by standard EMACS.!
AUX
!Edit Options:! !C Edit some or all of the permanent options.
String argument is a filter for the option names -- you will be editing all
    options whose names contain the string.  If you don't give a string
    argument, all options will appear for editing.
A variable is an option if its comment starts with "*" or "*".  (The variable
    name must not contain a colon.)
When you exit the recursive edit with ^R Exit, the values are updated.
To abort, use Abort Recursive Edit.
If you are only editing a few options, only part of the screen will be used,
    to reduce the amount of redisplay upon exit.
The format of the table is fairly obvious; type HELP to get details.!

 [0[1[2[3[4[9 1,fPattern:_u9 fq9"e 0u9'!* 9: STRARG, filter, which if null!
					!* means to match any option so we set!
					!* it to 0 for quick testing and to!
					!* avoid searches.!

 0[..f					!* No buffer hacking allowed.!
 [..j					!* Save mode line.!
 f[Lines f[Window f[BBind		!* Temporary buffer. fsWindow is saved since we!
					!* dont use the whole screen if we dont have to,!
					!* and we want to ensure that redisplay on return!
					!* is minimized.!

 q:..q(0)u3				!* 3: no. of elements per ..Q entry!
 1-q3u0					!* 0: ..Q index.!

 !* Critical efficiency iteration coming up here -- there may be an awful lot!
 !* of variables to consider.  We use Excl < Excl > instead of nested conditionals!
 !* since they are fast and we want to keep the size of the conditionals down!
 !* since Teco has to slowly skip over them, not cacheing them for instance.!

 q9"n 0s9'				!* Set the filtering search default,!
					!* if one, outside the loop.!

 -(fq..q-5/(q:..q(0)*5))u2		!* 2: Iteration count.  Cant give it!
					!* to the iteration directly since we!
					!* want to use Excl < Excl >.!
 <  %2;					!* Iterate over ..Q symbol table.!
    q0+q3u0				!* 0: up to next symbol entry.!
    q:..q(q0+2)u4 fq4-2"l !<!>'		!* Comment too short -- not option.!
    0:g4-*"n 1:g4-*"n !<!>''	!* To be an option either 1st or 2nd!
					!* character of comment must be a *.!

    !* We have an option variable.  See if it passes through the filter.!

    .(g:..q(q0))j			!* Insert its name.!
    q9"n :s"e .,zk !<!>''		!* If name doesnt match filter, skip!
					!* it.!

    !* This is a matching option.!

    zj i:				!* End name with colon, tab.!
    q:..q(q0+1)u1 fq1:"l 34i .(g1)j	!* String, put in quote and the string.!
      < @:f"l .-z; 29i c > !'! 34i'	!* Quote any ^]s or!
						!* double-quotes with ^].!
    "#	q1\'				!* Number, just get it.!
    i
   .u1 9i g4				!* Get comment, indented, on next line.!
    q1j 1a-!"e d @:f!l .,zk'	!* If varMacro, ignore the teco code.!
    q1j :l .,zk				!* But just the 1st line of comment.!
					!* (Most will actually be only one line!
					!* anyway.)!
    i
					!* End the comment line.!
    >

 !* Option table of either all or just the matching options is now prepared.!

 :i..jEdit_Options			!* Mode line for recursive edit.!
 m.m&_Edit_Options_Helpf[HelpMacro	!* Help for recursive edit format details.!

 0u0 j <l .-z; %0w>		    !* 0: Total number of lines needed.!
 fsLinesu1 q1"e fsHeight-(fsEchoLines)-1u1'	    !* 1: current fsLines!
 q0+2-q1"l q0+2fsLines'	    !* Set fsLines so that only the amount!
				    !* of screen needed is used, reducing!
				    !* redisplay of rest of buffer.!

 j 0u..H 			    !* Into , allowing redisplay.!


 !* Now change the values: !

 128*5,32:i*[..D			!* ..D: Make a syntax table for parsing!
					!* the string values.!
 *5:f..D_/			!* ..D: Thinks ^] is a Lisp escape.!
 "*5:f..D_| !'!			!* ..D: Thinks dquote is string delimiter.! 

 j
 <  0,1af	_:"l l !<!>' .-z;	!* Skip any indented lines.!
    .,(:s:;).-1x1			!* 1: Variable name.!
    q1u3				!* 3: Get this options current value.!
    @f	_l			!* Skip over indentation to value.!
    1a-34"n :\u2			!* 2: Numeric value.!
	    q2-q3"n q2u1''		!* Reset the option iff its value has!
					!* changed.  This is just in case there!
					!* is a variable macro attached -- no!
					!* sense calling it if no change.!

    "# .+1,(@fll).-1x2			!* 2: String value except that it has!
					!* ^]-quoted dquotes inside.!
       @:i2"2" !''!			!* 2: Now the exact string value.!

					!* Note that this is why we use ^] as!
					!* the quoting character -- the!
					!* delimited Teco insert respects!
					!* superquoting, namely ^]^] and ^]dquote.!
       q3fp"l q2u1'			!* Was a number before -- reset to new string.!
       "# f=23"n q2u1'''	!* Was a different string before -- reset.!

    l >					!* On to next option.!

 					!* Now all the variables are changed.!
!& Edit Options Help:! !S fsHelpMacro for MM Edit Options.!
!* Q-reg 9 has the string used to filter the option names.!

 fsLinesf"n-5"l			!* Good to have at least 5 lines for!
					!* this message, especially details.!
    5fsLines''w			!* Dont bind, so when exit redisplay!
					!* doesnt keep part of message.!

 :ftYou_are_editing_a_table_of_all_the_permanent_EMACS_options	!* Start HELP.!
 q9"n f=9"n ft
whose_names_contain_"9" !''!''	!* Tailor it a bit.!
 ft.
When_you_exit,_via_			!* Now find out what the exiter is.!
 2,(33.fs^RInit)m(m.mWhere_Is)"e ftM-X_^R_Exit'	!* (This is like using ^R Exit\!
							!* in documentation for a command.)!
 ft,_the_options_left_in_the_buffer_will_be
reset.__You_can_abort_with_
 2,(m.mAbort_Recursive_Edit)m(m.mWhere_Is)"e ftM-X_Abort_Recursive_Edit'
ft.
Do_you_wish_to_see_details_about_the_option_table_format?

 m(m.m&_Yes_or_No)"e 0u..h '		!* User doesnt want to see it.  Clear!
					!* ..H so typeout goes away.!

 0fsLinesw				!* For full details, always use whole!
					!* screen so not MOREing a lot.!

:ftThe_format_of_the_table_is_simple:__each_option_name_is_followed_by_a_colon,
some_indentation,_the_value,_and_then_on_the_next_line_the_comment_(which_is
indented_--_any_indented_line_(if_not_inside_a_value)_is_ignored_later_when
the_values_are_reset).

The_value_is_either_a_number_(with_an_optional_hyphen_preceding_it)_or_a_string
(in_which_case_it_is_surrounded_by_double-quotes_("...")_and_may_be_more_than
one_line_if_desired).

If_there_is_a_double-quote_inside_the_string,_it_must_be_quoted_by_the
_character_(Control-]).__Any_s_inside_the_string_must_also_be_quoted_with
.__(It's_ugly,_but_it_greatly_simplifies_the_implementation_and_these_should
be_rare.)

For_instance,_consider_the_following_example_options_in_this_format:

Option_Number_One:	"this_is_a_string"
Null_String_Option:	""
Option_Number_Two:	-1234
Option_Number_Three:	"Quoth_the_raven:_"Nevermore!"."
One_Bracket_Option:	""

 
!Edit Syntax Table:! !C Delimiter syntax table editor.
String arg is Q-register to edit.  Default is ..D.
Response to "Character:" is ^G to quit, ^Q to quote,
Altmode to leave the macro, or character whose entry to edit.
When editing a character's entry, you are in overwrite mode.
After you exit the recursive edit, you are asked for another character.
First char in each table entry is space for delimiter, or A.
Second is space, (, ), /, |, ', or A for lisp syntax.!

    1,F Q-reg:[9 FQ9"E :I9..D'  !* Read location of table (default is "..D").!
    FQ9-(5*200.)"N
      :I* Q9_has_wrong_length_for_a_dispatch_table FS ERR'
    f[D File ETGAZONK_.DEL	    !* Prevent clobberage by C-X C-W.!
    [3 0[..F			    !* Prevent auto-saving.!
    [..J :I..J Delimiter_Table_Editor.__
    :I*M(M.M Describe)Edit_Syntax_Table F[HELP MAC
    -1F[^R Replace		    !* Enter overwrite mode.!
    2F[CASEN 2F[CASE		    !* Convert all insertions to upper case.!
    F[B BIND G9
    J 0.U..0 40.< i^ q..0+100.i
		  fssail"N 2rdic q..0f	
"L -2d i q..0i''
		  q..0-33."e -2d i_'
		  I= 5C I	_ %..0&3"E-2DI
'
		  >
    140.<I_ Q..0I I= 5C I	_ %..0&3"E-2DI
'
         >
    177.*10F^?
    FS SAIL"N 177.*10F'
    0FS MODIF F[WINDOW
    f+
    < J 0@V @FT
Character:_
      FIU3 Q3-@;		    !* Exit if user types Altmode.!
      Q3-"EW'		    !* Quit if he types ^] or ^G (don't make the changes).!
      Q3-"EW'
      Q3-"EFIU3'		    !* ^Q quotes next character.!
      Q3*10J 3C			    !* Go to spot in buffer for the specified char.!
       >
    j 200.<3d5c2d>		    !* Delete the char names, leaving only edited contents.!
    0:F9 ..O		    !* Change contents of dispatch string to new stuff.!
    
!Kill Some Buffers:! !C Offers to kill each buffer, one by one.
If the buffer contains a modified file and you say to kill it,
you are asked whether to write the file out first.!

    0[1 [2 [3 [4
    < Q1*5-FQ.B;		    !* Stop after hacking all the buffers.!
      Q:.B(Q1+1!*bufnam!)U2	    !* Get next buffer's name.!
      Q:.B(Q1+2!*bufvis!)U4	    !* Get the name of the file it contains.!
      Q:.B(Q1+4!*bufbuf!)[..O	    !* Select it, TECO style, so we can check its FS MODIF!
      FT Buffer_2_
      Q4"N FT (File_4)_'
      FS Modif"N
        FT HAS_BEEN_EDITED'
       "# FT is_unmodified'
      FT .
_Kill_it_(Y_or_N_or_^R)?
      FI:FCU3 FT3

      Q3-"E 0[..F		    !* If answer is ^R, call ^R to show buffer to be killed.!
        [..J :I..JWant_to_kill_buffer_2?__
        0U..H  ]..J ]..F ]..O !<!>'	    !* Zero ..F to prohibit buffer hacking.!
      ]..O
      Q3-Y"E			    !* If answer is yes, kill the buffer.!
        M(M.M Kill_Buffer)2   !* Don't advance Q1 since next buffer has been moved down.!
	!<!>'
      Q1+Q:.B(Q1)U1>		    !* Advance to next buffer.!
    0U..H 			    !* Cause redisplay.!
!Edit Tab Stops:! !C Edit the tab stops used by ^R Tab to Tab Stop.
The bottom two lines just number the columns for your benefit.
The first two lines, stored in Tab Stop Definitions, are meaningful.
Periods or colons in the first line mark the tab stop columns.
A colon means tab out with whitespace;  a period means tab out by
copying text from the second line (you must put the text there).!

    0[..f
    :I* m(m.m Describe)Edit_Tab_Stops  F[help mac
    f[b bind
    gTab_Stop_Definitions	    !* Push to temp. buffer holding the tab stops.!
    j 2@l .,zk			    !* Flush anything past two lines.!
    0@f"n i
'				    !* Make sure ends with CRLF.!
    -@l ."e zj i
'				    !* Make sure there are realy two lines, not one. !

    zj fswidth/10<i_123456789> i
0				    !* Display the column position numbers' low digits!
    0u0 fswidth/10<10,%0*10\> i
				    !* and their high digits.!
    -1f[ ^r replace		    !* Make printing chars replace.!
    [..j :i..j Edit_Tab_Stops__(Overwrite)
    f[d file etgazonk_.del	    !* Prevent clobberage from accidental ^X^W.!
    j 
    j 2:@l 0@f"e :0@l'	    !* Find end of 2nd line, or end of 1st if 2nd is empty!
    0,.xTab_Stop_Definitions	    !* Store them as defnitions of tab stops.!
    
!& Compare Windows:! !S Compare text in two windows.
Compares the text in the two windows, starting at the
cursor in each window, leaving point in each window
at the first discrepancy, if any, or to end of buffer.
Quitting leaves point at place comparison had reached.

The variable Collapse in Comparison should be a string
of "insignificant" characters.  Any sequence of those characters
matches any other such sequence.  If the variable is not
defined, the default is CR, LF, TAB and SPACE.!

    [A -1[B [P [2
    [Q				    !* QQ is an in/out parameter to!
				    !* & Compare String with Buffer.!
    [D

    0FO..QWindow_2_Buffer"E
      :I*O1B	Only_One_Window FS ERR'

    Q..OUD			    !* QD will be passed down to & Compare...!
    .UQ				    !* Pass point seperately in case of!
				    !* comparing window with itself.!

    FS QP PTRUP		    !* Save stack to undo following pushes.!

    FS TOP LINE"N		    !* Now TECO-select the other window,!
      QWindow_1_SizeF[LINES 0F[TOP LINE
      :I2 1'
    "# QWindow_2_SizeF[LINES QWindow_1_Size+1F[TOP LINE
       :I2 2'
    QWindow_2_WindowF[WINDOW   !* but don't take the time for an EMACS buffer switch.!
    -1F[D FORCE
    QOther_Window_Buffer[..O
    QWindow_2_Point:J

    0FO..QCollapse_in_ComparisonUA
    QA"E :IA_	
'
    @FTComparing...
   0FS ECHOACT
    QD, QAM(M.M &_Compare_String_with_Buffer)UB    !* Do comparison.  QB gets flag.!

    :I*C FS ECHO DIS
    QB"L @FTMatch
'
    QB"E @FTMatch_so_far
'
    QB"G @FTMismatch
'
    0FS ECHOACT

    .UWindow_2_Point	    !* Remember change in point or FS WINDOW of other window.!
    FS WINDOW UWindow_2_Window
    0@V				    !* Redisplay the other window.!

    QPFSQP UN			    !* Return to original window.!
    QQJ				    !* Return to point as we selected it.!
    
!& Compare String with Buffer:! !S Compares current buffer with another.
The precomma arg should be the other buffer.
QQ is the position to start the comparison.
The postcomma arg should be a collection of "special" characters to
be collapsed in the comparison.  Typically, this arg might
consist of space, tab, CR, and LF.  Any nonempty string of
members of this arg matches any other nonempty
string of members of this arg.

We move point in both buffers up to the first mismatch,
and return nonzero if the buffers match up to the end.!

  -1F[NOQUIT			    !* So that ^G caught by ERRSET below.!
  [1				    !* 1 will hold!
				    !* the other buffer to compare!
  [2				    !* with the current buffer, 2 the string!
       				    !* of characters to collapse!
  <
  FQ1-QQ"E .-Z"E		    !* At end of both => return success.!
    -1'
  1'  .-Z"E1'		    !* At end of only one => return failure.!

  !* If one buffer has a special character after point !
  !* and other has one before or after,!
  (-1,1A F2:"'L)  (QQ:G1 F2:"'L) "L
    (-1,1A F2:"'L)  (-1,0A F2:"'L) "L
      (QQ:G1 F2:"'L)  (QQ-1:G1 F2:"'L) "L
      !* We have found two runs of special characters.  Skip each one.!
      @F2R
      :<QQ:G1 F2:; %QW>
      '''

  FQ1-QQ"E .-Z"E		    !* At end of both => return success.!
    -1'
  1'  .-Z"E1'		    !* At end of only one => return failure.!

  QQ:G1-(1A)"N 1'		    !* Quit right away if no match.!

  !* At this point, we assume that the strings before point
     in the two buffers are a match, and that in at least one
     buffer the character after point is not special.!
  :< QQ:G1-(1A):@; C %Q >	    !* Advance in both buffs past exact match.!
  
  FQ1-QQ"E .-Z"E		    !* At end of both => return success.!
    -1'
  1'  .-Z"E1'		    !* At end of only one => return failure.!

  QQ:G1-(1A)"E 0'		    !* Must have been ^G-ed.!
  >
!List Redefinitions:! !C Describe how the current mode differs from Fundamental mode.!

    qBuffer_Index[9
    13!*buflcl!-q:.b(q9)/2+qInitial_Local_Count-1[1
    qInitial_Local_Count*2+q9+13!*buflcl!-1[2
    [3[4[5

    !* m9 FOO is nonzero if there is a local named foo.!
    [9 :@i9| [1[2[3[4 :i3
	     < %1;
	       q:.b(%2)u4
	       fq4"g f~43"e -1''
	       %2>
	     0|

    qComment_Startu3
    fq3"g FT Comments_start_with_"3"!''!
	  FT_in_column_ qComment_Column:=
	  qComment_Endu3 fq3"g ft ,_and_end_with_"3"!''!'
	  ft.

	  0fo..qComment_Multi_Line"n ft They_can_extend_across_multiple_lines.
''
    "# FT No_comment_characteristics_are_defined.
'
    m9 Fill_Column"'n+(m9 Auto_Fill_Mode"'n)+(
          qAuto_Fill_Mode"n m9 Space_Indent_Flag"'n')"n
      FT Text_is_filled qAuto_Fill_Mode"n ft_automatically'
      ft _to_column_ qFill_Column:= ft.
      qAuto_Fill_Mode"n qSpace_Indent_Flag"n
        ft__New_lines_are_indented.''
      ft
'

    FT Parenthesis_matching_is
    qDisplay_Matching_Paren"e ft_disabled'"# ft_enabled' ft.

    fqParagraph_Delimiter"e
      FT Paragraphs_are_delimited_only_by_blank_lines.
'
    ft


    [1[2 -u5
    < %1;
      q:.b(%2)u3 %2
      fq3:"l
	f~3Auto_Fill_Mode"e !<!>'
	f~3Comment_Start"e !<!>'
	f~3Comment_End"e !<!>'
	f~3Comment_Column"e !<!>'
	f~3Comment_Multi_Line"e !<!>'
	f~3Fill_Column"e !<!>'
	f~3Display_Matching_Paren"e !<!>'
	f~3Paragraph_Delimiter"e
	  fqParagraph_Delimiter"e !<!>''
	f~3Space_Indent_Flag"e !<!>'
	fq:..q(:fo..q3+2)"g
	  %5"e ft
Variables_redefined:

'
!*	  m(m.mView_Q-register)3!
	  ft

	  '' >
    ]2]1 -u5

!* Now describe any locals which are ^R key definitions.!
    FQ1"L M(M.M &_Load_BARE)'
    < %1;
      q:.b(%2)u3 %2
      fq3"l q3@fsqphomeu3
	0:g3-Q"e fq3-2:g3-"e
	  %5"e ft
Keys_redefined_in_this_buffer:

'
	  1,fq3:g3u4 f4u4
	  q4-(q4fs ^R Indir)"n	    !* If this is an indirect character,!
	    q4m(m.m &_Charprint)
	    ft is_an_alias_of_	    !* then say of what.!
	    q4-(3/1000000.)m(m.m &_Charprint)
	    ft.'
	  "# q4,3m(m.m&_^R_Briefly_Describe)'
	  ft
'''>
    ft(Done)

    
!& Process Init Vars:! !S Read the user's EVARS file of variable settings.
A filename string may be given as a numeric argument, to specify a non-standard
vars file.!

!* The default file referred to is FOO;FOO EVARS on ITS, EMACS.VARS on Twenex.
The contents look like a local variables list but with no
special lines to begin it or end it, and no prefix or suffix.
A qvector slot may also be named, as in ":.X(A)" for the
slot for the character A in the qvector in Q.X (the C-X command)
and is treated like a ^R character name.
The major mode should NOT be specified.
Lines starting with spaces may appear between variables, as comments.!

!* This function is copied before it is executed, and AUX is then
flushed from core.  If this were not done, then if the EVARS file
loaded a library, it would keep AUX from ever going away.!

    F[D FILE

    FF&1"N  FS D FILE'	    !* Filename given as numeric arg.!
    "# FS OSTECO"E		    !* No filename given, so use default.!
	  ET FOO_EVARS
	  FS XUNAME FS DFN1'
       "# ET EMACS.VARS'	    !* Select proper filename based on op sys,!
       FS HSNAME FS DSNAM'	    !* and the right directory.!

    [1 [3 [4
    Q..O[5 F[B BIND Q..O[6	    !* Q5 has original bfr, Q6 has temp bfr.!
    [..O			    !* Make sure, when we pop the BBIND,!
				    !* that the temp bfr is back in Q..O to be killed.!

    128*5,32:i*[2		    !* Q2 gets a syntax table for parsing!
				    !* the string values.!
    *5:f2_/		    !* It thinks ^] is a Lisp escape.!
    "*5:f2_| !'!		    !* It thinks dquote is string delimiter.! 

    1:< ER @Y >"L '		    !* Make temp buffer, and read in the file.!
    <	.-Z;
	@:F"E L !<!>'	    !* Ignore blank lines, in case prefix is null.!
	1AF_	:"L @L!<!>' !* Ignore lines starting with whitespace.!
	.,( C S: .-2,.+1F=::"E C' !* Scan over name of variable.  Win for ...:.!
				    !* The C before the S makes us win on :.X(A)!
	    ).-1X3		    !* Put name of variable or ^R character into Q3.!

	!* Get the specified value in Q4.!
	.u1 @f	_l	    !* Skip over indentation to value.!
	1a-34"e q2[..d		    !* Is it a quoted string value?!
	  .+1,(@fll).-1x4
	  ]..d
	  @:i4"4" !''!'
	"# .( :\u4 )-."e q1-1j'	    !* Is it a numeric value? (with at least one digit)!
	   @f_	l
	   :@f"n		    !* Or an old-fashioned string value?!
	     q1j :X4''

	Q5U..O			    !* Go to the EMACS bfr to execute the definition.!
	FQ3-2:G3F:"'L+(	    !* If the variable name is a ^R character,!
	0:G3-:"'E)"L		    !* or a slot in a vector such as :.X(..),!
	  M4U3'		    !* Execute value-string to get the actual value.!
				    !* Add some extra Altmodes in case needed.!
	"# F=3 *"E M4'
	   "# Q4 M.V3''	    !* Set the variable.!
	Q6U..O @L >		    !* Back to temp bfr, and advance to next line.!

!* The dumped EMACS has an actual copy of this macro as an impure string.!
!* Replace it with a bootstrap that refers to AUX.  This is to save space --!
!* since it won't be used again in most cases, except when the user invokes it!
!* manually (after editing vars file, say) or when invoked by some subsystem!
!* that has its own vars file.!

    :@i*| [1 fs qp ptr[2
	  !* Must kill since the M.A will otherwise get MM-variable: !
	  m(m.mKill_Variable)MM_&_Process_Init_Varsw
	  :g(m.a AUX&_Process_Init_Vars)u1
	  q2fs qp unwin
	  f:m(q1(]1))
	| m.v MM_&_Process_Init_Vars
    
!Tabify:! !C Convert spaces after point to tabs.
Groups of spaces which could be transparently replaced with a tab are.
Numeric arg specifies tab stop spacing.  Precomma numeric arg specifies
minimum number of spaces to change (default 3).!

    [1[2[3[4			    !* save regs *!
    "N F[ TABWID' FS TABWIDU1 !* Set tab width.!
    F"E 3',32:I4		    !* minimum number of spaces!
    0S4			    !* initialize search string *!
    .[0  fn q0j		    !* Preserve point.!
    <  :S;			    !* Find next triple of consecutive spaces.!
       .-FQ4( @F_L		    !* Push where they start.  Search for end of run.!
            FSSHPOSU2		    !* Q2 gets hpos of end of spaces.!
	    Q2-(Q2/Q1*Q1)U3	    !* Q3 has where they end, past last tab stop.!
	    Q3R)-.U2		    !* Q2 has # spaces up to that tab stop.!
       Q2+1"L Q2D Q1-1-Q2/Q1,9I'    !* Replace all of them except last odd few with tabs.!
       Q3C>			    !* Move past the excess spaces at the end.!
    
!& Correct Word Spelling:! !S Check spelling of word at point and offer numbered replacements.
0-9 => Replace misspelled word with that spelling.
% => Read a digit and query replace from beginning of buffer.
space => Exit and make no changes.
^L => Redisplay choices.

If a Spell job does not already exist, create one and give contents
of Spell Initialization as additional JCL.

If given a negative argument, kill the Spell job.!

    :i*Cfs Echo Disp	    !* Clear the echo area.!

    "L :m(m.m&_Kill_Spell_Job)'  !* Kill it?!
      
    fs osteco"E
      :iOITS			    !* For & ... Get Spell Job!
      :iD			    !* Delimiter for commands.!
      fs msname:f6[F
      fs uname:F6[U
      :iFDSK:F;_SPELL_U'	    !* Filename for temp file.!
     
    fs osteco"G		    !* On Twenex, use the Job Index (UINDEX) for temp file.!
      :iOTWENEX
      :iD,
      fs msname
      fs uindex:\[U
      :iFF[SPELL-TEMP-U].TXT.0'

    [..j
    [0[1[3
    .[P				    !* Point before correction.!
    :cw -fwl			    !* Go to beginning of word.!
    .[B				    !* Beginning of word.!
    fwx0 fwl			    !* Get the word into 0.!
				    !* of the word to 0.!
    .[E				    !* End of the word.!
    z[L				    !* Z before correcting.!
    f[B Bind			    !* Create a buffer to lowercase it in.!
    g0 0j fwfc fwx1		    !* Get lower-cased version to 1, since!
				    !* Case Replace wants lower case.!
    f]B Bind
    :i..j Checking_spelling_of_0. fr 0
    1m(m.m&_O_Get_Spell_Job)BASK_0_FDQUIT
    !* Q1: old word, QF: file of new ones.!
    q1,qFm(m.m &_Spell_Replace_Word)"N QP :J'  !* If value=1 if we!
					      !* should restore point simply.!
      (2*QP)-(QB+QE)"G z-QL+QP :J'  !* Else hairily.!
                    "# QP :J'	    !* But simply in that case.!
    
!& Twenex Get Spell Job:! !S Get or create an Ispell fork take argument as jcl.
Gives Spell Initialization as JCL first if it exists and this creates
a new Ispell fork.  A numeric argument means to assume this won't print
anything on the screen.!

    -1fo..QISpell_Fork		 !* -1 If no ispell fork yet.!
    f[d file
    :i*fo..QSpell_Initialization !* If there's anything there,!
    F=I"N :iII,'		         !* append a comma.!

    0fo..QIspell_Filename"E	    !* See if it's SYS: or EMACS:.!
     1:<e?EMACS:ISPELL.EXE"E :I*EMACS:ISPELL.EXEm.vIspell_Filename 0;'
        e?SYS:ISPELL.EXE"E :I*SYS:ISPELL.EXEm.vIspell_Filename 0;'
	:i*NIP	No_ISPELL.EXE_program_in_SYS:_or_EMACS:FS ERR>'
    QIspell_Filename	    !* Ispell program name in S.!

    qJ"L
      "G @fz S_I	    !* QI is empty string, or init and a comma.!
[1'
      "# fz S_I		    !* Arg>0 means it won't print anything on the screen.!
[1'
      Q1m.vISpell_Fork'
    qJ"G
      "G 0,qISpell_Fork@fz S_
'
      "# 0,qIspell_Forkfz S_
''
    
!& ITS Get Spell Job:! !S Get or create a Spell job to take string arg as JCL.
Gives Spell Initialization as JCL first if it exists and this creates
a new Spell job.  A numeric argument means to assume this won't print
anything on the screen.!

    fs uname:f6[U		    !* Uname, for spell job.!
    fs jname:f6[J		    !* Our jname, to proceed.!
    f[d file
    ((F=Editor_TypeMAILT"'E)+(Fs Lispt))"N
      :i*NML	Does_not_work_as_inferior_to_MAIL_or_Lispfs err 0'
    e?USR:U_ESPELL"N oNew Spell' !* Use old spell job if it exists.!
    "G
     @:JOB_ESPELL		    !* If the numarg is 1, then use @, else .!
          :JCL_
          :CONTINUE
          :JOB_J
          :CONTINUE_
    '

    "#
      :JOB_ESPELL
          :JCL_
	  :CONTINUE
	  :JOB_J
	  :continue_
    '

    !New Spell!
    :i*fo..QSpell_Initialization
    F=I"N :iI I'	    !* If there is anything, append altmode.!
    "G
     @:ESPELL_I
          :JOB_J
	  :CONTINUE_
     '
    "#
      :ESPELL_I
           :JOB_J
	   :CONTINUE_'

!& Spell Replace Word:! !S Replace the word at point from the choices in the argument file.!
    f[D File [2
    e?2"N F+ :i*ESP	Error_in_Spell_Program:_Maybe_Directory_FullFS ERR'
    [1[N
    [O			    !* O is old word.!
    Q..O[B			    !* Pointer to old buffer.!
    f[Lines f[B Bind
    er 2 Y 			    !* Read the info from Spell, and delete the file.!
    ec @ed 2
    1au1 d			    !* Dispatch off failure/success code and delete it.!
    q1-#"E
      @ft Word_not_found._ 0 fs echoactivew 1'  !* Don't restore point.!
    q1-*"E
      @ft Found_it._ 0 fs echoactivew 1'
    q1-+"E
      fwx1 @ft Found_it_because_of_1._ 0fs echoactivew 1'
!* Display and Choose words.!
    zj -2d			    !* Remove stray crlf at end of file.!
    @ft Type_a_digit_to_replace_word,_%_for_Query_Replace,_space_to_flush.
    0u0 J
    <g0 i=			    !* Number the words and put them one!
      :l			    !* line so they can be filled.!
      2d
      i__ %0w .-z@; >
    @FA				    !* Fill it to make choices fit on the screen.!
    j 0u0 <l .-z@; %0w>		    !* Count lines.!
    q0+2fs Lines'		    !* Set fsLines so that only the amount!
				    !* of screen needed is used, reducing!
				    !* redisplay of rest of buffer.!
 !Redisplay!
 f[window  j @v			    !* Display choices.!
 0u3				    !* Flag: 0 means straight replace, else query.!
 !Retry!			    !* q3 nonzero means retrying query replace that had a bad character typed at it.!
    Q3"E @fiu1'		    !* Put character user typed in 1.!
    (Q3"'N)+(q1-%"'E)"N	    !* If user typed a %, then query replace prompt.!
     @ft			    !* Also if this is retry of query replace, reprompt.!
     Query_replace_O_with_which_word_(0...9)?_
     @fiu1 1u3'		    !* Non-zero means trying to do a query replace.!
    q1"D			    !* Replace word if it's a digit.!
      q1u1
      j
      :s1="E fg o Retry'
      fwfc fwxN			    !* Get the lc'd word without the number.!
      Q3"N @ftN_'
      0,q0+2@f		    !* Let it know we clobbered top part of screen.!
      qB[..O			    !* Temporarily select our old buffer.!
				    !* We'll let the stack unwind do it for good.!
      q3"E			    !* If this is straight replace,!
        -fwl fwl		    !* delimit word to be changed by Case Replace.!
	qNu1			    !* Case replace wants new text in Q1.!
	m(m.m &_Case_Replace)w 0'	    !* preserve case. Return 0 (restore point).!
      "#			    !* It must be query replace.!
        :i*CFSEchodisp
	@ftO_with_N
	.(j 1m(m.m Query_Replace)ONw):j
	0,1a-
 "E R'		    !* Restore point, but not inside crlf.!
	1''			    !* Return 1 (don't restore point).!
    q1-204"E o Redisplay'
    q1-236"E o Redisplay'
    q1-32"E 1'		    !* Just space exits.  Don't restore point.!
     "# fg o Retry'		    !* Anything else retries.!
    1
!& Kill Spell Job:! !S Kill Spell job or Ispell fork.!

    FS OSTECO"G		    !* Kill it on Twenex?!
       -1fo..qISpell_Fork"L fg ' !* Not if it's not there.!
       "# -qISpell_Forkfz
	  -1uISpell_Fork'
	  @ft Ispell_fork_reset._
	  0fs echoactive 0'
	 
    FS OSTECO"E		    !* On ITS?!
     fs jname:f6[3		    !* Our jname, to proceed.!
     @ :JOB_ESPELL
	   :KILL
	   :JOB_3
	   :CONTINUE_
	@ft Spell_job_killed._
	0fs echoactive'
    0
!& Correct Buffer Spelling:! !& Send buffer to Spell for correction.
Writes out the current file and calls Spell to correct it.  Spell
outputs a file, which is then read back into the EMACS buffer.  The
output file is temporary, and deleted, unless this command is given a
string argument, which specifies the filename of the corrected file.  If
the Spell program errors out, type Q <return> to return to EMACS, and
use Revert File to recover the buffer.!

    f[D File
    fs msname:f6[S		    !* For temporary file directory.!

    :I*
    !* The output filename is used if there is no output file specified!
    !* as a string argument.  If no string arg is given, the output file is!
    !* deleted after it is read in.!

    m(m.m^R_Save_File)	    !* Under buffer filename, query if smaller.!
    QBuffer_FilenameuF
    F=A"N QAuC'	    !* Make the output file be strarg, if given.!

    "#			    !* Otherwise, use temporary name.!
     fs osteco"E fs uname:f6[U		    !* Uname, for temp file and spell job.!
                  :iCDSK:S;_OSPEL_U'
               "# FS UINDEX:\[U   !* User index, for temp file.!
		  :iCS[EMACS-SPELL-U].TXT.0''

    fs osteco"E
       !* Filenames sep. by comma, commands by altmode on ITS.!
       0m(m.m&_ITS_Get_Spell_Job)CORRECT_F,CQUIT'
       !* On Twenex, files are separated by space, commands by comma.!
    "# 0m(m.m&_Twenex_Get_Spell_Job)CORRECT_F_C,QUIT'

    !* Check to see that the output file exists before deleting he current text.!
    !* If the output file is temporary, just put it in the buffer and!
    !* delete it.  Leave the buffer with fs modified set.  If the output!
    !* file was specified by the user, then read in the file with Visit File,!
    !* and don't delete it.!

    e?C"N F+ :i*ESP	Error_in_Spell_Program_--_Output_file_not_found.fs err'
    HK
    F=A"E ER C @Y @ED C'
    "# 0FsModified
       m(m.mVisit_File)C'

!& Spell JCL:! !S Give the string argument to SPELL as JCL.
Sample use: M-X Command to SpellDUMP DICT >
If this command starts a new Spell, it is first given the
contents Qof Spell Initialization.!

    [S
    fs osteco"E :iSITS :iD'
              "# :iSTWENEX :iD,'
    !* It probably won't mess with the screen, so give arg of 1.!
    1m(m.m&_S_Get_Spell_Job)DQUIT'