changeset 8317:c59be9428778

(Fwrite_region): Do unwind the new unwind protect. (Vwrite_region_annotations_so_far): New variable. (syms_of_fileio): Set up Lisp var. (build_annotations): Handle annotate functions that switch buffers. Set Vwrite_region_annotations_so_far. (Fwrite_region): Handle change of buffer in build_annotations. Add an unwind protect to restore original buffer and kill the temp.
author Richard M. Stallman <rms@gnu.org>
date Sun, 24 Jul 1994 05:42:51 +0000
parents abf26f5c67e4
children 3fc49ff2ea03
files src/fileio.c
diffstat 1 files changed, 62 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/fileio.c	Sun Jul 24 05:34:16 1994 +0000
+++ b/src/fileio.c	Sun Jul 24 05:42:51 1994 +0000
@@ -121,6 +121,10 @@
 /* Functions to be called to create text property annotations for file.  */
 Lisp_Object Vwrite_region_annotate_functions;
 
+/* During build_annotations, each time an annotation function is called,
+   this holds the annotations made by the previous functions.  */
+Lisp_Object Vwrite_region_annotations_so_far;
+
 /* File name in which we write a list of all our auto save files.  */
 Lisp_Object Vauto_save_list_file_name;
 
@@ -2927,6 +2931,23 @@
 
 static Lisp_Object build_annotations ();
 
+/* If build_annotations switched buffers, switch back to BUF.
+   Kill the temporary buffer that was selected in the meantime.  */
+
+static Lisp_Object 
+build_annotations_unwind (buf)
+     Lisp_Object buf;
+{
+  Lisp_Object tembuf;
+
+  if (XBUFFER (buf) == current_buffer)
+    return Qnil;
+  tembuf = Fcurrent_buffer ();
+  Fset_buffer (buf);
+  Fkill_buffer (tembuf);
+  return Qnil;
+}
+
 DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 5,
   "r\nFWrite region to file: ",
   "Write current region into specified file.\n\
@@ -2954,6 +2975,7 @@
   struct stat st;
   int tem;
   int count = specpdl_ptr - specpdl;
+  int count1;
 #ifdef VMS
   unsigned char *fname = 0;	/* If non-0, original filename (must rename) */
 #endif /* VMS */
@@ -2962,6 +2984,7 @@
   Lisp_Object annotations;
   int visiting, quietly;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+  struct buffer *given_buffer;
 #ifdef MSDOS
   int buffer_file_type
     = NILP (current_buffer->buffer_file_type) ? O_TEXT : O_BINARY;
@@ -3013,7 +3036,16 @@
       XFASTINT (end) = Z;
     }
 
+  record_unwind_protect (build_annotations_unwind, Fcurrent_buffer ());
+  count1 = specpdl_ptr - specpdl;
+
+  given_buffer = current_buffer;
   annotations = build_annotations (start, end);
+  if (current_buffer != given_buffer)
+    {
+      start = BEGV;
+      end = ZV;
+    }
 
 #ifdef CLASH_DETECTION
   if (!auto_saving)
@@ -3215,8 +3247,10 @@
 #ifndef FOO
   stat (fn, &st);
 #endif
-  /* Discard the unwind protect */
-  specpdl_ptr = specpdl + count;
+  /* Discard the unwind protect for close_file_unwind.  */
+  specpdl_ptr = specpdl + count1;
+  /* Restore the original current buffer.  */
+  unbind_to (count);
 
 #ifdef CLASH_DETECTION
   if (!auto_saving)
@@ -3260,7 +3294,11 @@
 
 /* Build the complete list of annotations appropriate for writing out
    the text between START and END, by calling all the functions in
-   write-region-annotate-functions and merging the lists they return.  */
+   write-region-annotate-functions and merging the lists they return.
+   If one of these functions switches to a different buffer, we assume
+   that buffer contains altered text.  Therefore, the caller must
+   make sure to restore the current buffer in all cases,
+   as save-excursion would do.  */
 
 static Lisp_Object
 build_annotations (start, end)
@@ -3275,7 +3313,21 @@
   GCPRO2 (annotations, p);
   while (!NILP (p))
     {
+      struct buffer *given_buffer = current_buffer;
+      Vwrite_region_annotations_so_far = annotations;
       res = call2 (Fcar (p), start, end);
+      /* If the function makes a different buffer current,
+	 assume that means this buffer contains altered text to be output.
+	 Reset START and END from the buffer bounds
+	 and discard all previous annotations because they should have
+	 been dealt with by this function.  */
+      if (current_buffer != given_buffer)
+	{
+	  Lisp_Object tem;
+	  start = BEGV;
+	  end = ZV;
+	  annotations = Qnil;
+	}
       Flength (res);   /* Check basic validity of return value */
       annotations = merge (annotations, res, Qcar_less_than_car);
       p = Fcdr (p);
@@ -4074,6 +4126,13 @@
 lists are merged destructively.");
   Vwrite_region_annotate_functions = Qnil;
 
+  DEFVAR_LISP ("write-region-annotations-so-far",
+	       &Vwrite_region_annotations_so_far,
+    "When an annotation function is called, this holds the previous annotations.\n\
+These are the annotations made by other annotation functions\n\
+that were already called.  See also `write-region-annotate-functions'.");
+  Vwrite_region_annotations_so_far = Qnil;
+
   DEFVAR_LISP ("inhibit-file-name-handlers", &Vinhibit_file_name_handlers,
     "A list of file name handlers that temporarily should not be used.\n\
 This applies only to the operation `inhibit-file-name-operation'.");