Google
 

Trailing-Edge - PDP-10 Archives - mit_emacs_170_teco_1220 - emacs/files.emacs
There are no other files named files.emacs in the archive.
!* -*-TECO-*-!

!* Note: we use FS X MODIF to mean that the buffer has changed
since the last Auto Save, and FS MODIF to mean it has changed
since the last real save.  FS MODIF is the one which controls the mode line.!

!& Minibuffer:! !S Invoke recursive editing using a small window.
See the source for calling information.!

!* The first arg should be the buffer that the next higher level is editing.
The current TECO buffer now should be for minibuffer commands.
The second arg should be the number of screen lines (default 3).
If it is negative, the caller should have set up FS TOPLINE
and FS LINES himself, and set QMini Re-display to a function to
handle drawing the line of dashes.
The definitions of Altmode and ^G are bound while in the minibuffer.!

    0[..F
    [.G [			    !* Bind ^G, Altmode.!
    @:I.G`			    !* ^G should ring the bell.!
       FG FF"N 0'		    !* If exists arg for it to flush, that is all.!
       H"E FS ^R EXIT'	    !* Else if minibuffer empty, exit it.!
       HK			    !* If not empty, make it empty, so ^G^G exits.!
       FSRGETTY"E FT_Flushed
'
       `
    @:I`
	FF"N 		    !* IF ALTMODE HAS ARG, INSERT THAT MANY ALTMODES,!
       !I! 1033.FS^RLAST	    !* MAKE IF NEXT CHAR IS ALTMODE IT SHOULDN'T EXIT.!
       !J! FM(9 @ FS ^R INIT)' !* JUST INSERT ALTMODES, DON'T OVERWRITE.!
	0,0A-35."E OI'		    !* FOLLOWING A ^] =) SAME IDEA.!
	FS ^R PREV-33."N	    !* ELSE IF LAST CHAR WAS NOT ALTMODE,!
	    O J'		    !* JUST INSERT THIS ALTMODE IN BUFFER.!
	1FS^R RUB 		    !* ALTMODE-ALTMODE - EXIT MINI.  DELETE THE 1ST ALTMODE!
	ZJ H"N -2 @F=//"N	    !* BUT IF DONT HAVE 2 ALTMODES AT END OF BUFFER,!
	      2,33.I''		    !* MAKE SOME.!
	FS RGETTY"E @FT '
	FS ^R EXIT`

    FS RGETTY"N
      @:I*| 1:<			    !* HERE IS MACRO TO DISPLAY DASHES BELOW MINI!
	    FS TOPLIN+(FS LINES) F[ TOPLIN
            FS PJATY+1"G :FT------------------------------ 0U..H '
	    F]TOP LINE >W
	    0FS ^R DISP |(
         ) FO..q Mini_Re-displayU..0 !* The user can supply something to use instead.!
      Q..0F[ ^R DISPLAY	    !* Put the dash drawing function into FS ^R DISPLAY.!
				    !* It will clear itself out, so only be done once.!
      FS REFRESHF"N M.V Mini_Outer_Refresh
	!* Save the FS REFRESH from outside the minibuffer.!
	!* Our definition of FS REFRESH will call that one first thing.!
	@:I..0| MMini_Outer_RefreshW ..0|'
      Q..0F[REFRESH'		    !* Put the dash drawing function into FS REFRESH also.!

    [..J Q..J"E :I..J'
    F=..J (((((((((((((((((((( (   !* SET ..J TO OUR STRING ARG, WITH PARENS.!
        :I..J()		    !* # OF PARENS SHOULD BE RECURSION DEPTH OF MINIBUFFER!
     )F"L *(-1)'-1< :I..J(..J)>  !* SO PUT 1 SET, THEN AS MANY AS IN THE ..J WE PUSHED.!

    1033.FS ^R LAST		    !* FAKE OUT ALTMODE IF 1ST CHAR TYPED!
    FS CASEF"G @' "N HFC'	    !* ADJUST CASE OF TEXT SO WILL DISPLAY WITHOUT FLAGGING.!
    :"l			    !* If size arg isn't negative, set window size!
       f"e w 3' f[lines'	    !* from arg, or 3 by default.!
				    !* (if arg negative, caller must set this up)!
    0F[WINDOW
    -1F[CTLMTA			    !* Make it easy to insert control characters.!
    0F[^R STAR			    !* We don't care whether minibuffer is modified.!
    0F[^R NORM			    !* Make ordinary characters insert as usual.!

    				    !* Edit.  Return on 2 Altmodes, or maybe ^G.!

    1033.FS ^R LAST		    !* In case recursive mini, fake out altmode if typed next.!
    FS RGETTY"E FT
'
    FS Top Line,(FS Lines+1)@f  !* Say the lines we occupied now need redisplay.!
    0
!^R Execute Minibuffer:! !^R Read and run TECO commands.
Uses the minibuffer to read them.  Pushes the command string
onto a ring buffer in Q.N.  An explicit argument initializes
the minibuffer with the command from the top of that ring buffer.
Once inside the minibuffer, ^R Prefix Control-Meta C-Y pops to previous saved
minibuffer commands, going around the ring.!

    m.m ^R_Pop_Minibuffer_Ring[...Y
    q..o,( f[b bind
         ff"n g:.n(0)'	    !* Make new buffer, maybe fill with previous string.!
         )m(m.m &_mini buffer)Minibuffer'    !*read stuff in new buffer, with old as arg!
    h"e 0'			    !* Buffer empty =) user ^Gd, so do nothing.!
    f=(q:.n(0)f"e w :i*')..o"n  !* If this command not same as previous minibuffer,!
      q.n[..o zj-5d		    !* push this command onto ring buffer of!
      j 5,0i ]..o		    !* minibuffer commands.!
      hx:.n(0)'
    f]b bind ]...Y m:.n(0) w   !* In any case, run it, after restoring normal environment!
!^R Re-execute Minibuffer:! !^R Re-execute the last minibuffered commands.
With a numeric argument N, re-executes the N'th most recent minibuffer.!
    0,30:G:.N(f"g-1')[1
    @FT Re-execute_command_1
    1m(m.m &_Yes_or_No)"e 0'
    M:.N(f"g-1') 
!^R Pop Minibuffer Ring:! !^R Gets back earlier command, in minibuffer.
Repeated use goes through all the remembered minibuffer commands
and eventually returns to the most recent one.  An argument serves as
a repeat count, which can be negative.!
    Q..F"N FG 0'		    !* Don't allow this at top level.!
    [0
    z"n				    !* If minibuffer empty, just get top thing on ring.!
      <			    !* Rotate forwards if and as desired.!
	  q.n[..o q:.n(0)u0
	  j5d zj 5,0i
	  q0,z-5fsword ]..o
	  >
      -<			    !* Rotate backwards if and as desired.!
	  q.n[..o
	  z-5fsword( zj-5d j5,0i),0fsword
	  ]..o > '
    hk
    q:.n(0)"e fg 0'
    g:.n(0) h			    !* Insert what's now on top of ring.!
!& Mini Initialized:! !S Convenient interface to minibuffer.
See source for calling conventions.!

!* Takes string args describing the text to present to the user
in the minibuffer, and runs the edited text.
The string args are 1) stuff to be edited, to go before the
pointer, 2) stuff to go after the pointer, and 3) the "mode"
for the minibuffer.  An argument of 1 causes 
ET <default file>  ET to be inserted as the first thing.
An argument of 2 uses the buffer filenames instead of the defaults.!

    m.m ^R_Pop_Minibuffer_Ring[...Y
    q..o,( f[ b bind		    !* Set up new buffer with 1), the pointer, 2)!
	     "n iET_ g(-1"e fs d file' "# qBuffer_Filenames f"ew fs d file'')
		  i__ET_'
	     i
	     .( i )j
        )m(m.m&_mini buffer)  !* Edit it, passing 3) along.!
    h"e 0'			    !* Buffer empty =) user ^Gd, so do nothing.!
    f=:.n(0)..o"n		    !* If this command not same as previous minibuffer,!
      q.n[..o zj-5d		    !* push this command onto ring buffer of!
      j 5,0i ]..o		    !* minibuffer commands.!
      hx:.n(0)'
    f]b bind ]...Y m:.n(0) w   !* In any case, run it, after restoring normal environment!
!^R Visit File:! !^R Visit new file in selected buffer.
Nonzero numeric argument means file is read-only.
Nonzero precomma argument means always at least offer to save old file.
File name is string argument.!

    QBuffer_FilenamesF"N FS D FILE'
    f:m(m.m Visit_File)
!Visit File:! !C Visit new file in selected buffer.
File name is string argument.
Nonzero numeric argument makes file read-only;
negative makes buffer read-only too.
Nonzero precomma argument means always at least offer to save old file.
We execute Visit File Hook if it is nonzero.
All visiting of files is by means of this function.!

!* If QJournal_Visit_Version is nonzero,
   we read in that version, even though setting visited version to >.!

    MMM_&_Check_Top_Levelfiles
    "L :I..0 Read'"# :I..0 Visit'	    !* Put "Visit" or "Read" in Q0, for prompting.!
    5,f..0_Filefs dfile

!* Some old libraries set this to 1, then next time give it as
   precomma arg.  We want to make sure that precomma arg is always 0.!
    0UInhibit_Write

    [0 [1 [2 0[4
    QBuffer_Index[3

    QVisit_File_Save_OldU0
    "N Q0"E 1U0''
    FS Modif"N			    !* If file is modified since last real save,!
     Q0"N			    !* and we should possibly save it,!
      Q0"L O Do Save'
      @FT
Write_out_changes_in_		    !* ask user whether he wants to save the changes.!
      QBuffer_FilenamesU0
      Q0"E @FT buffer'
      "# @FT file_0'
      1M(M.M &_Yes_or_No)"N
   !Do Save!
        1,M(M.M ^R_Save_File)'''

    0FS Read Only
    0,FSZ FS BOUND		    !* Flush all of old file despite bounds.!
    0U:.B(Q3+8!*bufdat!)	    !* Zero out date of last file read or written.!
    F[ D FILE
    0FO..Q Journal_Visit_VersionF"G FS D VERSIO'
    1:< ER >U2			    !* Open file.  Did we win? !
    Q2"L 0,7:G2U1
	 F~1 OPN004_"N
	   F~1 OPN0076"N
             F~1 OPN0077"N
	       F~1 OPN0100"N
	         F~1 OPN0104"N
		   Q2FSERR'''''    !* Error other than file not found => report it!
	 HK @FT (New_File)
	  0 FS ECHO ACT'	    !* File not found => read it as empty.!
      "# 0[2 1:< FS IF CDATE U2>   !* File found => Remember its creation date!
	 FS IF LINK"N FS IFILEU4 @FT (Link_to_4)
 0FS ECHO ACT'
	 @Y  Q2U:.B(Q3+8!*bufdat!) ]2 '	    !* and read it in.  Don't save date if get URK.!
    Q4"N 20.ER EC'		    !* If file is link, open link to get link's version #.!
    F]D FILE
    0FS Modif			    !* Until changed, it doesn't need writing.!
    0FS X Modif
    FF&1*U:.B(Q3+12!*bufnwr!) !* Record read-onliness.!
    "L -1FS READ ONLY'	    !* Negative arg means make buffer actually read-only.!
    FS D FILEU1 Q1UBuffer_Filenames	    !* Remember what we are visiting.!
    Q1U:.B(Q3+2!*bufvis!)	    !* Keep buffer table up to date so LIST BUFFERS wins.!
    Q2"E FS IF VERSF"LW FS IF FN2:F6'' "# 0' U:.B(Q3+9!*bufver!)
    0U:.B(Q3+10!*bufsav!)	    !* Turn auto save off first - force re-init.!
    QAuto_Save_DefaultUAuto_Save_Mode   !* Turn auto save on if default is on.!
    FSZU:.B(Q3+11!*bufsiz!)	    !* Remember size when read.!
    FS ^R MDLY FS ^R MCNT
    J M(M.M &_Process_File_Options)	    !* Set local vars and mode as specified in file.!
    0FO..QVisit_File_HookU1 Q1"N M1 '
    1:M(M.M&_Maybe_Display_Directory)	    !* Display dir if QAuto directory display says!
!& Process File Options:! !S Set mode and local vars from file.
Select the mode specified at the front of the loaded file,
and if it's last page specifies local variable values,
set them up.!
    [0 [1 [2 [3 [4 .[P  fn qPj
    0[5				    !* Q5 is nonzero if major mode has been set.!
    0[6				    !* No old or new string vars seen in lcl modes list.!
  1@:< J
    FS OS TECO"N		    !* If on 10X or 20X,!
      :FB EDIT_BY_"L		    !* and if it appears to have an edit history,!
        <L 1A-;"N 1;'>''	    !* move over comment lines!
      @F	_
R
    :FB -*-"L			    !* If 1st nonblank line contains "-*-", then!
      .U1 1:FB:-*-+2"E FKC Q1,.X1' !* it might be old style "-*-Lisp-*-", or!
          "# Q1J :FBMode:"L	    !* New style and contain "Mode: Lisp,"!
	     .,(FB;-*- FKC.)X1'' !* In either case, put mode name in Q1.!
      FQ1"G M(M.M 1_Mode) 1U5''  !* select mode foo.!
    FS OS TECO"N Q5"E 		    !* If on 20X and didnt set a major mode at all,!
      QBuffer_Filenames F[ DFILE !* use FN2!
      FS DFN2U1 FQ1"E :I1<Null>' 1,M.M&_1_ModeU0
      Q0"N M0W 1U5'		    !* Call & FOO Mode if it is defined!
      "# J @F_
L
         12F~(FILECREATED"E	    !* Special hack to recognize interlisp files.!
           M(M.M Interlisp_Mode)W 1U5''''
    ZJ :Z,Z-10000FB		    !* Find the start of the last page,!

"E Z-10000"L J''		    !* or beg of file if file is short and no pages.!
    .-Z"N			    !* If we found one or the other,!
      :SLocal_Modes"L		    !* search for the start of them local vars.!
	Q5"E 1M(M.M &_Init_Buffer_Locals)  !* Flush all but permanent local variables.!
	     :IModeFundamental'
	.( FKC 0X0 )J		    !* Get the line prefix.!
	1A-:"E C'  :X1	    !* Get the line suffix.!

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

	< L .-Z;		    !* Then look at each line for the local variable.!
	  FQ0F~0"N !<!>'	    !* Ignore lines not starting with prefix.!
	  FQ0C 1A-15."E !<!>'	    !* Ignore blank lines, in case prefix is null.!
	  4F~END:@;
	  .,( S: .-2,.+1F=::"E C'	    !* Scan over name of variable.  Win for ...:.!
	      ).-1X3		    !* Put name of variable or ^R character into Q3.!
	  .u6 @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 q6-1j'   !* Read as number. If no digits, fake out test below.!
	     .,( :s1		    !* Did the digits, plus leading and trailing spaces,!
:w .)@f_	"n	    !* account for everything on the line before the suffix?!
	        q6,.x4''	    !* If not, it is an old-fashioned string value.!
	  F~3 Mode"E
	    -[Initial_Local_Count !* But avoid flushing any locals we just made.!
	    M(M.M 4_Mode)
	    -1FS QP UNW
	    !<!>'
	  FQ3-2:G3-"E	    !* If the local name is a ^R character,!
	   M4 M(M.M Make_Local_Q)3 !<!>'	    !* Execute it to get the local value.!
	  Q4 M.L 3		    !* Make the var local.!
	  >
	-1U5''
    >(  !* Save the results of the errset.!
      !** Here, Q5 is positive if all we did is set the major mode,!
      !** in which case we already did & Set Mode Line.!
      Q5:"G M(M.M &_Set_Mode_Line)'
      )"E J '
    !"! @FT
    Error_processing_file's_mode_or_local_variables
     0FS ECHO ACT
    J 
!Find File:! !C Visit a file in its own buffer.
If the file is already in some buffer, select that buffer.
Otherwise, visit the file in a buffer named after the file.!

    mMM_&_Check_Top_Levelfiles
    qBuffer_Filenamesf"e w' f[D File
    5,fFind_File[0 et0 ]0	    !* Read in the argument.!

    FS D FN1:F6( FS D FILE(	    !* Get the filenames and just the FN1.!
    F]D FILE )[3 )[4		    !* Q3 gets the filenames, Q4 the FN1.!
    Q3 M(M.M &_Find_File)[1	    !* Ask what buffer the specified file is in.!
    FQ1"G
      Q1 M(M.M Select_Buffer)	    !* Already in some buffer => select it.!
      QBuffer_FilenamesF[D FILE  !* If cdate of file in buffer equals that of file we would!
      1:< ER >"L '
      FS IFCDATEU1 EC		    !* read now, just return.  Otherwise, must re-visit file.!
      Q1-Q:.B(QBuffer_Index+8!*bufdat!)"E '
      FS Modif"N !"!
	FT While_you've_been_editing_this_file,_it_has_changed_on_disk!
	   You_may_lose_some_work_if_you_are_not_careful.
	   I_will_leave_you_what_you_have_edited,_not_what_is_on_disk.
	   I_suggest_that_you_file_this_out_under_a_different_name_and
	   then_SRCCOM_the_two_files.
	    '
      !"!
      FT Since_EMACS_last_visited_or_saved_this_file,
         it_has_been_changed_on_disk.
	 Luckily,_you_haven't_edited_the_buffer_since_then.
	 Should_I_read_in_the_version_from_disk
      M(M.M &_Yes_or_No)"L 1,M(M.M Revert_File)'
      0U..H '
    Q4 U1 [2			    !* Else get the FN1 as string, as desired buffer name.!
  !Retry!
    1,Q1M(M.M &_Find_Buffer)U2	    !* Does it exist?!
    Q2+1"G
      M.M List_BuffersF[Help Mac
      3,M(M.M &_Read_Line) A_buffer_named_1_already_exists.
	  Type_buffer_name_to_use,_or_CR_to_reuse_1:_U1
      F]Help Mac
      FQ1"L 0U..H '			    !* If he rubs out, abort.!
      FQ1"G Q1U4 O Retry''	    !* If he specifies something, warn if that too exists.!
    Q4 M(M.M Select_Buffer)	    !* Select the appropriate buffer!
    ET 3			    !* and set its filenames to the specified ones.!
    FF&1"N 'M(M.M Visit_File)	    !* and visit the file in it.!
    
!Auto Save Mode:! !C Turn Auto Save on or off.
Zero or negative argument => Auto Save mode is turned off.
Positive argument => it is turned on.  No arg => toggle mode on or off.
We save under the filenames you visited, if possible,
when Auto Save Visited File is nonzero.  Otherwise, we save
under the filenames in Auto Save Filename.
When you visit a file, Auto Save is turned on or off according to
the value of Auto Save Default.!

    1fs mode ch
    qbuffer_index[1
!* Q0 gets -1 if auto save mode should be turned on.!
    ff"e q:.b(q1+10!*bufsav!)"'e[0'	    !* No arg => that is iff the mode was off.!
    "# "'g[0'			    !* Otherwise, mode is on if arg is > 0.!

    0F[VARMAC			    !* Set QAuto Save Mode to match the truth.!
    Q0UAuto_Save_Mode		    !* But it should not call this function again.!
    F]VARMAC

    q0"e 0u:.b(q1+10!*bufsav!) 0' !* Just turning it off is trivial.!
   
    1,m(m.m&_Auto_Save_Setup)	    !* Actually turn auto saving on.!
    0
!& Auto Save Setup:! !S Turn on Auto Saving, initializing variables.!

!*
A nonzero precomma argument means 
  if we should be saving as auto save file and already are, do nothing.!

    QBuffer_Filenames[3 Q3F"N F[D FILE'
    FS CLKINTF"E+4*60*60' FS CLKINT	    !* Arrange to auto-save after 4-8 mins of idle time.!
    -1[0			    !* 1 => save as visited names, else later!
				    !* Q0 is set to filenames to save as.!
    QBuffer_Index[1
    [2 [4

!* It is ok to save as the visited filenames if:
there is a visited file,
we are visiting the most recent version,
the file actually has a version number (can fail only on ITS),
is not read-only,
the device is one which is fast to write on,
and the user has said he likes that kind of auto saving.!
    Q3"N FS D VERS"E
      Q:.B(Q1+12!*bufnwr!)"E
        FSDDFAST"N
	  QAuto_Save_Visited_File"N
	    1U0			    !* If we should save as visited filenames, put 1 in Q0.!
	    '''''

!* Figure out names to save as, if not visited names.!

    Q0-1"N
      qAuto_Save_Filenamesf[d file
      fsOSTeco"e		    !* ITS.  Use buffer number.!
        1:< 4,6:g(fsDFN1:f6)u2	    !* If Auto Save Filenames fn1 ends with 00!
	    f~2 00"e		    !* then replace with buffer number.!
	      0,4:g(fsDFN1:f6)u2   !* 2: First 4 letters from Auto Save Filenames.!
	      q:.b(q1+7!*bufnum!):\u4   !* 4: Buffer number for this buffer.!
	      fq4-2,fq4:g4u4	    !* Get at most low 2 digits of buf num as string.!
	      f624fsDFN1' > ' !* Set to autosave filenames.!
      "#
        fq(fs d fn2)"e		    !* On Twenex, use buffer name as extension!
	  q:.b(Q1+1!*Bufnam!)fs DFN2''	    !* unless otherwise specified.!
      fs d fileu0'

    "N Q0-1"N			    !* If saving as auto save file is wanted!
      Q:.B(Q1+10!*bufsav!)U2	    !* and already happening with same filenames,!
      FQ2"G F~20"E ''''	    !* then we don't need to do anything.!

    Q0U:.B(Q1+10!*bufsav!)	    !* Now turn on right style of autosaving.!
    0UAuto_Save_Count		    !* 0 auto saves done since saving was turned on.!

    Q0-1"E			    !* If saving as visited filenames,!
      '			    !* we are done.!

!* Saving as special auto save filenames, in Q0 and in FS D FILE.!
    FS D VERSION"E		    !* If multiple saves are possible, find number of lowest!
      0U2
      1:< -2 FS D VERSW ER	    !* one that exists.  It will be first one deleted.!
	  FS IF VERSU2
	  0 FS D VERSW ER
	  FS IF VERS+1-Q2U2>	    !* Q2 gets the number versions of the Auto Save file.!
      EC Q2-QAuto_Save_MaxU2	    !* Compare that with desired number.!
      Q2< -2 FS D VERSW @ED >	    !* If too many, delete some.!
      '
    
!Revert File:! !C Undo changes to a file.
Reads back the file being edited from disk
(or the most recent auto save file, if that isn't the same thing).
A numeric argument means ignore the Auto Save files.
A nonzero pre-comma argument waives confirmation.!

    MMM_&_Check_Top_Levelfiles
    QBuffer_Filenames[0
    .[1
    QBuffer_Index[2 [3

    FF&1"E			    !* Choose visited filenames or auto save filenames.!
      Q:.B(Q2+10!*bufsav!)U3 FQ3"G  !* If we recently wrote an auto-save file, read it.!
	QAuto_Save_Count"N
	  Q3U0'''
    Q0"E :I*No_file_to_revert_from fs err'

    "E			    !* Query, unless that is inhibited by precomma arg.!
      @ft Restore_file_from_disk
      1m(m.m&_Yes_or_No)"e 0''

    B[B 0,FSZFS BOUND
    ER0
    QBuffer_Index[2
    FS IF CDATE U:.B(Q2+8!*bufdat!)
    FS IF VERSF"LW FS IF FN2:F6' U:.B(Q2+9!*Bufver!)
    @Y  0FS MODIFW 0FS X MODIF
    FS WINDOW+QB:J"L 0L .FS WINDOW'
    Q1:J
    FS ^R MDLY FS ^R MCNT
    M(M.M &_Process_File_Options)  !* Reprocess local modes!
    0FO..Q Visit_File_HookU1	    !* Redo user's own processing.!
    Q1"N M1' 
!& Auto Save All Buffers:! !S Auto save all buffers.
We don't need to select a buffer unless we save it.
Argument is nonzero if have already auto-saved anything.
Nonzero precomma arg means ignore selected buffer.!

    Q..F-Q.F"N 0'
    FQ.B/5[0 0[1 [..O
    QBuffer_Name[2
    [3
    0[4				    !* Q4 nonzero if we have switched buffers.!
    [5
    FN Q4"N Q2M(M.M Select_Buffer)'     !* So then we must switch back.!
    < Q1-Q0;			    !* Look at each buffer.!
      Q:.B(Q1+10!*bufsav!)"N	    !* If buffer has auto save turned on!
       "'E F"EW F~:.B(Q1+1!*Bufnam!)2'"N !* and is not the selected buffer!
        Q:.B(Q1+4!*bufbuf!)[..O
        FSZ*(FS X MODIF)(]..O)"N  !* and has changes in it, and isn't empty,!
	  Q:.B(Q1+1!*bufnam!)M(M.M Select_Buffer)  !* then select it!
	  1U4
	  Q3"E			    !* Announce that we are starting to auto save.!
	    FSRGETTY"N @FT _(Auto_Save)'
	    "# @FT''	    !* (Don't use FG - it screws FS TYISRC$) !
	  1U3
	  F[D FILE		    !* Don't clobber TECO default filenames.!
	  1:< 2,1M(M.M ^R_Save_File) >"L
	      QBuffer_FilenamesU5
	      FG @FT_(Auto_Save_error_for_5!) 60 0FS ECHO ACT'
	  '''
      Q:.B(Q1)+Q1U1 >
    
!^R Save File:! !^R Save visited file on disk if modified.
An argument means do an auto-save type save.
"1," as argument indicates that this call was not explicitly
requested, and the user should be asked to confirm if
the file has become a lot smaller.  "2," means an Auto Save,
which should abort rather than query if anything might be wrong.!

    Q..F-Q.F"N 0'
    QBuffer_Index[5
    FF&1"E FS MODIF"N 1FS X MODIF''	    !* If want real save,!
				    !* Make FS X MODIF nonzero if we need a real save.!
    Q:.B(Q5+10!*bufsav!)[1	    !* Q1 has the BUFSAV slot.!
    QBuffer_Filenames[0	    !* Q0 gets appropriate filenames to save as.!
    1[2				    !* Q2 has 1 if saving as buffer filenames, -1 if not.!
    FQ1"G FF&1"N
	Q1U0 -1U2''
    Q0"N Q0'F[D FILE

    Q2"G
     Q:.B(Q5+12!*bufnwr!)"N	    !* If saving as visited file and file read-only,!
       "N 0'		    !* if implicit, don't do it.!
       @FT File_is_read_only.__Save_anyway !* If explicit, ask user if he means it.!
       1M(M.M&_Yes_or_No)"E 0''
     Q0"N			    !* If saving as visited file w/ known filenames,!
      FS DD FAST"L		    !* if dev is disk or fast to open,!
        1:< ER FS IF CDATE[4 EC   !* See if date of existing file matches when we last!
	    Q:.B(Q5+8!*bufdat!)[3   !* read or wrote the file.!
	    Q4"N Q3"N Q4-Q3"N	    !* If not, warn user he may be losing.!
	      :I*A FS ECHO DIS
	      @FT The_file_now_on_disk_is_not_what_you_last_visited_or_saved!

	      FQ1"L 0UAuto_Save_Count'
	      -2"E @FT Not_auto_saving_0.  !* Auto save should never ask questions.!
	             60 0FS ECHO ACT'
	      FS X MODIF"N @FT Should_I_write_the_file_anyway
	                    1M(M.M &_Yes_or_No)"E 0''
	      "# @FT Luckily_you_have_not_edited_the_buffer_since_then.
		     Use_Revert_File_to_read_the_version_off_disk.
		 0FS ECHO ACT'
	      ''' >'''

    FS X MODIFIED"E		    !* If don't need to write since no changes,!
      @FT			    !* tell the user so.!
      (No_changes_need_to_be_written)
      FQ1"L FF&1"E
        0UAuto_Save_Count'' !* Wants real save => mark last auto save as real.!
      0FS ECHO ACT'

    Q2"G			    !* If saving for real, not as Auto Save filenames,!
      Q0"E "N '		    !* No file visited => if implicit, just don't save.!
	@M(M.M Write_File) '    !* If explicit, ask for filenames.!
      FS OS TECO"N		    !* On Twenex,!
       fs xjname [j
       f~jSNDMSG*(f~jHERMES)"n    !* Unless from cretinous Twenex mail program!
         0FS D VERS"N		    !* always save as new version,!
	   FS D FILEU0
	   Q0U:.B(Q5+2!*bufvis!)    !* and permanently clobber visited version to 0.!
	   1FS MODE CH
	   Q0UBuffer_Filenames''''

    "N 3*FSZ-(2*Q:.B(Q5+11!*bufsiz!))"L  !* If file has shrunk, ask for confirmation.!
      -2"E @FT
(File_has_shrunk_--_not_auto-saving_0) 60 0FSECHO ACT'
        0F[TYI SOURCE
	@FT
File_has_shrunk_a_lot.__Save_anyway
	@FG 1M(M.M &_Yes_or_No)"E 0FS ERR'''

    Q1"N FQ1"L			    !* If we auto-save as visited file!
      QAuto_Save_Max-1"E	    !* and only want one auto save,!
        QAuto_Save_Count"G	    !* and we have at least one auto save,!
	  Q:.B(Q5+9!*Bufver!)FS D VERS	    !* re-use the last version number.!
	  1,M(M.M Write_File)	    !* Write; 1, says don't clobber visited version.!
				    !* No need now to increment count or delete anything.!
	  FF&1"E		    !* If real save, say we have no auto saves.!
	    0UAuto_Save_Count'
	  0''''
    Q2,M(M.M Write_File)	    !* Write it.!
    Q1"E 0'			    !* Nothing else to do unless in Auto Save mode.!

    %Auto_Save_Count		    !* Incr. # of auto saves done.!
    FQ1"G
      FF&1"N		    !* If we saved as special auto-save filenames,!
        1FS MODIF		    !* we still need a real save,!
	O Del Auto Save''	    !* and delete one auto save.!
!* If saving as auto save file names, then if we have saved enough
auto saves recently, delete one of them.!
    "# QAuto_Save_Count-QAuto_Save_Max"G
       !Del Auto Save!
       1:< 0 FS D VERSW ER >"E    !* and delete the Auto Save file N versions back !
	 FS IF VERS(EC)-QAuto_Save_Max F"G FS D VERS
	   1:<@ED>''''		    !* from what we just wrote.!

!* If this is a real save, count of auto saves since last real save is now 0.!
    FF&1"E 0UAuto_Save_Count'
    0
!Write Region:! !C Write region to file.
Specify filenames with a suffix string argument.
Two numeric arguments may be used to specify the region,
which otherwise is from point to mark.!

    5,1FWrite_Region_to_File[1 ET1
    EI FF"N F' "# :,.'FP EF !* ACTUALLY OPEN AND WRITE!
    FSOFILE[1 FSRGETTY"E :FT'
    :I*C FS ECHO DIS
    @FTWritten:_1  FS ECHO LINES-1"N @FT
'
    0FS ECHO ACT
!Write File:! !C Store buffer in specified file.
This file becomes the one being visited.
Specify filename as string argument.
Precomma arguments have hairy meanings; see the code.!

!* "1," says called by ^R Save File;
inhibits calling & Set Mode Line and auto-save reinitialization.
Also inhibits setting visited filenames.
Also means if we lose trying to write a specific version number
we should write an incremented version number.

"-1," as argument inhibits updating the buffer's file cdate as well.

If not at top level (can't switch files now),
doesn't update anything about the current buffer except FS MODIFED,
but does return the written file's creation date so the caller can store it.!

    QBuffer_Index[2 [4
    0F[VBW 0F[VZW                 !* Write whole bfr regardless of virtual bounds!
    :F"L Q.F-Q..F"E		    !* If at top level, default to buffer filenames.!
      Q:.B(Q2+2!*bufvis!)F"N FS D FILE'''
    5,1FWrite_File[1 ET1	    !* Set default names and open file.!
    F[D FILE ET[TECO]_OUTPUT 0FS D VERSW
    < 1:< EI >F"E 0;'U4		    !* Try with different versions!
       F~(0,7:G4)OPN0130"N	    !* If we get error because two people trying at once,!
         F~(0,7:G4)OPN0750"N
	   Q4FS ERR''		    !* Try other version numbers!
       &77777.FS D VERS>	    !* till we find one which is not in use.!
    F]D FILE
    FS OF CDATE [3		    !* Remember file date.!
    HP				    !* Write the data.!
    -1"E :'1< EF >+0U4	    !* Close the file.  If ^X=1, save any error code.!
    Q4"L F~(0,7:G4)OPN0750"E	    !* If can't write specific version,!
           0FS D VERS EF'	    !* Write a new version.!
	 "# Q4FS ERR''
    0FS MODIF			    !* Have written out => can flush without writing it again.!
    0FS X MODIF
    +1"E FSRGETTY"E O NoPrint'' !* Don't announce auto saves on printing tty.!
    FSOFILE[1 FSRGETTY"E :FT'
    :I*C FS ECHO DIS
    @FTWritten:_1  FS ECHO LINES-1"N @FT
'
    0FSECHO ACT
  !No Print!
    Q..F-Q.F"N Q3 '		    !* File written.  If not from EMACS's current buffer, that's all.!
    FSZ U:.B(Q2+11!*bufsiz!)	    !* Update last saved size even if auto save.!
    FS ^R MDLY FS ^R MCNT
    :"L			    !* If precomma arg not -1,!
      Q3 U:.B(Q2+8!*bufdat!)	    !* update last saved file date and version.!
      FS OF VERSF"L
        FS OFILEF[D FILE FS DFN2:F6(
	    F]D FILE)' U:.B(Q2+9!*bufver!)
      1FS MODE CH'
    "N 0'			    !* If doing ^R Save File, return -- filename not changed.!
    FS D FILEU1
    M(M.M Set_Visited_Filename) 1
    0
!Set Visited Filename:! !C Change visited filename, without writing file.
What EMACS believes to be the name of the visited file
is set from a string argument.  No file's name is actually changed.!

    MMM_&_Check_Top_LevelFiles
    QBuffer_FilenamesF"EW' F[D FILE
    5,1FVisited_Filename[1 ET1	    !* Set default names.!
    FS D FILEU1 Q1UBuffer_Filenames	    !* Remember what we are visiting.!
    Q1U:.B(QBuffer_Index+2!*bufvis!)	    !* Keep buffer table up to date so LIST BUFFERS wins.!
    0[2
    0U1 1:< ER
	    FS IFVERSF"LW FS IFFN2:F6'U1  !* What is latest version of this new file?!
	    FS IF CDATU2	    !* What is latest date?!
	    EC>
    Q1U:.B(QBuffer_Index+9!*bufver!)
    Q2U:.B(QBuffer_Index+8!*bufdat!)
    0FO..Q Visit_File_HookU1	    !* Execute Visit File Hook if there is one.!
    Q1"N 1M1'
    Q:.B(QBuffer_Index+10!*Bufsav!)"N	    !* If auto saving is on,!
      1,M(M.M &_Auto_Save_Setup)'  !* reinitialize it.!
    1FS MODE CH		    !* Show new filenames in mode line.!
    M(M.M&_Maybe_Display_Directory) 0
!^R Set File Read-Only:! !^R Make file read-only, or not.
The argument or lack of one is interpreted just as by Visit File:
no argument makes file writable, positive arg makes file read-only,
negative arg makes file and buffer read-only.!

    QBuffer_Index[1
    FF&1F"N W '[2		    !* Get our arg, or 0 if none.!
    Q2U:.B(Q1+12!*bufnwr!)	    !* Set both kinds of read-onliness.!
    Q2"'LFS READ ONLY
    Q:.B(Q1+10!*bufsav!)"N	    !* If we are auto saving, may need to re-init.!
      1,M(M.M &_Auto_Save_Setup)'
    1FS MODE CH		    !* Cause redisplay of mode line.!
    0

!*** less fundamental file commands that use the TECO default filenames!
!Delete File:! !Kill File:! !C Delete a file.  Filename is argument.
Invoke with ^R Instant Extended Command to see the defaults.!

    5,4F Delete_File[1
    FS OSTECO"E 20.' ER1	    !* Open file, don't chase links,!
    FS I FILE[1		    !* just to find out its real name.!
    FS OSTECO"E
      @FT Delete_1
      1M(M.M &_Yes_or_no)"E 0''
    EC ED			    !* Now delete.!
    FS OSTECO"N
      fs echo act"n :i*Cfs echo dis'
      @FT Deleted:_1

      0fsecho active'
    M(M.M&_Maybe_Display_Directory)
    0
!Copy File:! !C Copy a file.
Arguments are old filename and new filename.
The defaults are left set to the old filename.!

    5,4F Copy_FileFS D FILE
    F[D FILE
      5,1F to_File[1
    :E_1
    M(M.M&_Maybe_Display_Directory)
    0
!Rename File:! !C Rename a file.
Arguments are old filename and new filename.
The defaults are left set to the old filename.!

    5,4F Rename_FileFS D FILE
    F[D FILE
      5,1F to_File[1
    EN1
    M(M.M&_Maybe_Display_Directory)
    0
!Insert File:! !C Insert contents of file into existing text.
File name is string argument.  Example:  M-X Insert FileFOO BAR.
The pointer is left at the beginning, and the mark at the end.!

    5,4F Insert_File[1
    ER1			    !* OPEN FILE.!
    .,.m(m.m&_Save_for_Undo)Insert_File
    .F[VBW  FSZ-.F[VZ            !* NARROW BOUNDS TO INCLUDE NO CHARS, AT PT!
    @Y				    !* ACTUALLY READ IT.!
    1 M(M.M&_Maybe_Display_Directory) !* SOMETHING TO READ WHILE TAPE IS SPINNING.!
    J Z: H			    !* SET MARK AT END.!
!Append to File:! !C Append region to end of specified file.
The range to write can also be specified with numeric args.!

    5,F Append_to_File[1
    ET1
    Q..O[0 FF"E :-B,.-B'	    !* PUT CURRENT BUFFER IN Q0.  COMPUTE RANGE TO WRITE
!	   "# -B,-B' F(	    !* SUBTRACTING B FROM BOTH #S, SINCE G0 IS RELATIVE TO B.!
        F[ B BIND                  !* READ FILE INTO NEW BUFFER.!
        EW			    !* START COPYING OLD FILE INTO NEW FILE!
        1:<ER>"E
          5FY                       !* READ 1 WD AHEAD SO DETECT EOF AND REMOVE PADDING!
          < ZJ 51200 FY             !* COPY 10K AT A TIME.!
            Z-51200-5:;             !* GOT ALL WE ASKED FOR =) COPY OUT,!
            B,51200P B,51200K>      !* SAVING THE LAST WORD FOR NEXT TIME.!
          ZJ 5<0,0A-3"N 1,0A:@;' -D>  !* DELETE TRAILING ^C OR ^@S IN LAST WORD!
          '
        ) G0                        !* THEN STICK ON THE REGION WE ARE APPENDING!
    HP EF EC
    fsOFileu1 @ftWritten:_1
   0fsEchoAct
    M(M.M&_Maybe_Display_Directory)!* SOMETHING TO READ WHILE TAPE IS SPINNING.!
    0
!Prepend to File:! !C Append region to start of specified file.
The range to write can also be specified with numeric args.!

    5,F Append_to_File[1
    ET1
    Q..O[0 FF"E :-B,.-B'	    !* PUT CURRENT BUFFER IN Q0.  COMPUTE RANGE TO WRITE
!	   "# -B,-B' F(	    !* SUBTRACTING B FROM BOTH #S, SINCE G0 IS RELATIVE TO B.!
        )F( "E '		    !* DO NOTHING IF RANGE IS EMPTY (CODE BELOW WOULD LOSE)!
        F[ B BIND                  !* READ FILE INTO NEW BUFFER.!
        EW			    !* START COPYING OLD FILE INTO NEW FILE!
        ) G0                        !* FIRST STICK IN THE REGION WE ARE APPENDING!
    1:<ER>"E                       !* IF FILE EXISTS!
      < ZJ .U0 Z+4/5*5-Z,0I         !* PAD TO WORD BOUNDARY SO FY IS FAST.!
        51200 FY                    !* COPY 10K AT A TIME.!
        Q0J .+4/5*5-.D              !* FIRST DELETE THE PADDING SO IT ISNT WRITTEN!
        Z-51200-Q0:;                !* THE FY GOT ALL WE ASKED FOR =) COPY OUT,!
        B,51200P B,51200K>          !* SAVING THE LAST WORD FOR NEXT TIME.!
      ZJ 5<0,0A-3"N 1,0A"N 0;'' -D> !* DELETE TRAILING ^C OR ^@S IN LAST WORD!
      '
    HP EF EC
    fsOFileu1 @ftWritten:_1
   0fsEchoAct
    M(M.M&_Maybe_Display_Directory)!* SOMETHING TO READ WHILE TAPE IS SPINNING.!
    0
!^R Directory Display:! !^R Display current buffer's file's directory.
Uses whatever directory display macro the user has
selected (value of Directory Lister).  With non-zero argument,
reads directory name from terminal.!

    ff "e QBuffer_Filenamesf"n f[d file'
	         mDirectory_Lister  '  !* If no arg, just do it!
    1,F Directory:_ U..0
    ET..0 mDirectory_Lister  '
!^R Dired:! !^R Run Dired for the directory of the current visited file.
With no argument, edits that directory.
With an argument of 1, shows only the versions of the file in the buffer.
With an argument of 4, asks for input, which may contain device colon,
directory semicolon, and a file name, only versions of that file are shown.!

 QBuffer_Filenamesf"n fs D File  !* If we don't have buffer file names, assume arg of 4!
   -4"L Fm(m.m DIRED) ''    !* With arg of 1 or none, pass numeric arg and null string!
 1,F Directory;_ f"e ' [..0    !* With an arg of 4, or no buffer file names!
 m(m.m DIRED) ..0 	    !* We ask for a string arg and pass it along!