changeset 38364:835bdb0887ed

(unwind_read): New function. (Finsert_file_contents): Record it as unwind-function for the case that reading is interrupted by C-g.
author Gerd Moellmann <gerd@gnu.org>
date Wed, 11 Jul 2001 12:04:09 +0000
parents 413a99578997
children 61ddd379cd65
files src/fileio.c
diffstat 1 files changed, 53 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/fileio.c	Wed Jul 11 11:17:44 2001 +0000
+++ b/src/fileio.c	Wed Jul 11 12:04:09 2001 +0000
@@ -3418,6 +3418,53 @@
   return Qnil;
 }
 
+
+/* Unwind-function for reading from a file in insert-file-contents.
+
+   INFO is a pair (INSERTED-BYTES . VISIT).  INSERTED-BYTES is the
+   number of bytes successfully inserted into current_buffer.  VISIT
+   is the same as the parameter VISIT Of insert-file-contents.
+
+   When reading is interrupted by C-g, this leaves the newly read part
+   of the current buffer undecoded.  If this happens in a multibyte
+   buffer, prevent invalid characters by either discarding what has
+   been read or switching the buffer to unibyte.
+
+           PT                 GPT
+   +-----------------------------------------------------+
+   |       |  inserted bytes   |  GAP_SIZE |             |
+   +-----------------------------------------------------+
+           \                             /
+	    +--------- the gap ---------+	 */
+
+static Lisp_Object
+unwind_read (info)
+     Lisp_Object info;
+{
+  if (!NILP (current_buffer->enable_multibyte_characters))
+    {
+      int nbytes = XINT (XCAR (info));
+      int visit = !NILP (XCDR (info));
+
+      if (visit || Z == nbytes)
+	current_buffer->enable_multibyte_characters = Qnil;
+      else
+	{
+	  ZV -= nbytes;
+	  ZV_BYTE -= nbytes;
+	  Z -= nbytes;
+	  Z_BYTE -= nbytes;
+      
+	  GPT = PT;
+	  GPT_BYTE = PT_BYTE;
+	  GAP_SIZE = nbytes + GAP_SIZE;
+	}
+    }
+      
+  return Qnil;
+}
+
+
 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
   1, 5, 0,
   "Insert contents of file FILENAME after point.\n\
@@ -4131,17 +4178,22 @@
 	/* try is reserved in some compilers (Microsoft C) */
       int trytry = min (total - how_much, READ_BUF_SIZE);
       int this;
+      int count = BINDING_STACK_SIZE ();
 
       /* For a special file, GAP_SIZE should be checked every time.  */
       if (not_regular && GAP_SIZE < trytry)
 	make_gap (total - GAP_SIZE);
 
-      /* Allow quitting out of the actual I/O.  */
+      /* Allow quitting out of the actual I/O.  If we do,
+         remove 's */
+      record_unwind_protect (unwind_read,
+			     Fcons (make_number (inserted), visit));
       immediate_quit = 1;
       QUIT;
       this = emacs_read (fd, BYTE_POS_ADDR (PT_BYTE + inserted - 1) + 1,
 			 trytry);
       immediate_quit = 0;
+      --specpdl_ptr;
 
       if (this <= 0)
 	{