From xemacs-m  Thu Jun 12 23:31:58 1997
Received: from crystal.WonderWorks.COM (crystal.WonderWorks.com [192.203.206.1])
	by xemacs.org (8.8.5/8.8.5) with ESMTP id XAA26256
	for <xemacs-beta@xemacs.org>; Thu, 12 Jun 1997 23:31:55 -0500 (CDT)
Received: by crystal.WonderWorks.COM 
	id QQctsc04782; Fri, 13 Jun 1997 00:31:55 -0400 (EDT)
Date: Fri, 13 Jun 1997 00:31:55 -0400 (EDT)
Message-Id: <QQctsc04782.199706130431@crystal.WonderWorks.COM>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
From: Kyle Jones <kyle_jones@wonderworks.com>
To: xemacs-beta@xemacs.org
Subject: [PATCH] 20.3-b6: other half of the process output fix
X-Mailer: VM 6.33 under 20.3 "Moscow" XEmacs Lucid (beta6)
X-Face: /cA45WHG7jWq>(O3&Z57Y<"WsX5ddc,4c#w0F*zrV#=M
        0@~@,s;b,aMtR5Sqs"+nU.z^CSFQ9t`z2>W,S,]:[+2^
        Nbf6v4g>!&,7R4Ot4Wg{&tm=WX7P["9%a)_da48-^tGy
        ,qz]Z,Zz\{E.,]'EO+F)@$KtF&V

The code that handles process output when there is no filter
function does not bounds check the clip region and point values
that it saves.  If a before/after-change-function changes
things, there can be trouble.

This patch implements the bounds checking.  It also reverses a
big chunk of the previous patch in favor of a less invasive
solution.

Recommended for the official 19.15 patches.

Fri Jun 13 00:25:46 1997  Kyle Jones  <kyle_jones@wonderworks.com>

	* src/process.c (status_notify):
	  Revert back to the code that does not use
	  save_excursion_restore.  Just bounds check opoint
	  instead.

	* src/process.c (read_process_output):
	  Bounds check saved clip region and point values for
	  validity before using them.  Call Fwiden before calling
	  Fnarrow_to_region to insure values will not be out of
	  range.

--- 1.1	1997/06/13 03:35:22
+++ src/process.c	1997/06/13 04:15:38
@@ -1771,12 +1771,24 @@
 
       /* If the restriction isn't what it should be, set it.  */
       if (old_begv != BUF_BEGV (buf) || old_zv != BUF_ZV (buf))
-	Fnarrow_to_region (make_int (old_begv), make_int (old_zv),
-			   p->buffer);
+	{
+	  Fwiden(p->buffer);
+	  old_begv = bufpos_clip_to_bounds (BUF_BEG (buf),
+					    old_begv,
+					    BUF_Z (buf));
+	  old_zv = bufpos_clip_to_bounds (BUF_BEG (buf),
+					  old_zv,
+					  BUF_Z (buf));
+	  Fnarrow_to_region (make_int (old_begv), make_int (old_zv),
+			     p->buffer);
+	}
 
       /* Handling the process output should not deactivate the mark.  */
       zmacs_region_stays = old_zmacs_region_stays;
       buf->read_only = old_read_only;
+      old_point = bufpos_clip_to_bounds (BUF_BEGV (buf),
+					 old_point,
+					 BUF_ZV (buf));
       BUF_SET_PT (buf, old_point);
 
       UNGCPRO;
@@ -2600,19 +2612,19 @@
 	     when a process becomes runnable.  */
 	  else if (!EQ (symbol, Qrun) && !NILP (p->buffer))
 	    {
-	      int speccount = specpdl_depth ();
+	      Lisp_Object old_read_only = Qnil;
+	      Lisp_Object old = Fcurrent_buffer ();
+	      Bufpos opoint;
+              struct gcpro ngcpro1, ngcpro2;
 
 	      /* Avoid error if buffer is deleted
 		 (probably that's why the process is dead, too) */
 	      if (!BUFFER_LIVE_P (XBUFFER (p->buffer)))
 		continue;
 
-	      record_unwind_protect (save_excursion_restore,
-				     save_excursion_save ());
+              NGCPRO2 (old, old_read_only);
 	      Fset_buffer (p->buffer);
-	      record_unwind_protect (save_excursion_restore,
-				     save_excursion_save ());
-	      specbind(Qbuffer_read_only, Qnil);
+	      opoint = BUF_PT (current_buffer);
 	      /* Insert new output into buffer
 		 at the current end-of-output marker,
 		 thus preserving logical ordering of input and output.  */
@@ -2620,13 +2632,27 @@
 		BUF_SET_PT (current_buffer, marker_position (p->mark));
 	      else
 		BUF_SET_PT (current_buffer, BUF_ZV (current_buffer));
+	      if (BUF_PT (current_buffer) <= opoint)
+		opoint += (string_char_length (XSTRING (msg))
+                           + string_char_length (XSTRING (p->name))
+                           + 10);
+
+	      old_read_only = current_buffer->read_only;
+	      current_buffer->read_only = Qnil;
 	      buffer_insert_c_string (current_buffer, "\nProcess ");
 	      Finsert (1, &p->name);
 	      buffer_insert_c_string (current_buffer, " ");
 	      Finsert (1, &msg);
+	      current_buffer->read_only = old_read_only;
 	      Fset_marker (p->mark, make_int (BUF_PT (current_buffer)),
 			   p->buffer);
-	      unbind_to(speccount, Qnil);
+
+	      opoint = bufpos_clip_to_bounds(BUF_BEGV (XBUFFER (p->buffer)),
+					     opoint,
+					     BUF_ZV (XBUFFER (p->buffer)));
+	      BUF_SET_PT (current_buffer, opoint);
+	      Fset_buffer (old);
+              NUNGCPRO;
 	    }
 	}
     } /* end for */

