changeset 22895:9f800ebc6091

(Fsubst_char_in_region): Use replace_range in the case where we may need to combine bytes. (Ftranslate_region): Likewise.
author Richard M. Stallman <rms@gnu.org>
date Mon, 03 Aug 1998 22:25:08 +0000
parents 186b2098dcd8
children 6d368c9a689e
files src/editfns.c
diffstat 1 files changed, 65 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/editfns.c	Mon Aug 03 17:54:35 1998 +0000
+++ b/src/editfns.c	Mon Aug 03 22:25:08 1998 +0000
@@ -1938,9 +1938,44 @@
 	      changed = 1;
 	    }
 
-	  if (NILP (noundo))
-	    record_change (pos, 1);
-	  for (i = 0; i < len; i++) *p++ = tostr[i];
+	  /* Take care of the case where the new character
+	     combines with neighboring bytes.  */ 
+	  if (len == 1
+	      && ((! CHAR_HEAD_P (tostr[0])
+		   && pos_byte > BEGV_BYTE
+		   && ! ASCII_BYTE_P (FETCH_BYTE (pos_byte - 1)))
+		  ||
+		  (! ASCII_BYTE_P (tostr[0])
+		   && pos_byte + 1 < ZV_BYTE
+		   && ! CHAR_HEAD_P (FETCH_BYTE (pos_byte + 1)))))
+	    {
+	      Lisp_Object tem, string;
+
+	      struct gcpro gcpro1;
+
+	      tem = current_buffer->undo_list;
+	      GCPRO1 (tem);
+
+	      /* Make a multibyte string containing this
+		 single-byte character.  */
+	      string = Fmake_string (make_number (1),
+				     make_number (tochar));
+	      SET_STRING_BYTES (XSTRING (string), 1);
+	      /* replace_range is less efficient, because it moves the gap,
+		 but it handles combining correctly.  */
+	      replace_range (pos, pos + 1, string,
+			     0, 0, 0);
+	      if (! NILP (noundo))
+		current_buffer->undo_list = tem;
+
+	      UNGCPRO;
+	    }
+	  else
+	    {
+	      if (NILP (noundo))
+		record_change (pos, 1);
+	      for (i = 0; i < len; i++) *p++ = tostr[i];
+	    }
 	}
       INC_BOTH (pos, pos_byte);
     }
@@ -1995,9 +2030,33 @@
 	  nc = tt[oc];
 	  if (nc != oc)
 	    {
-	      record_change (pos, 1);
-	      *p = nc;
-	      signal_after_change (pos, 1, 1);
+	      /* Take care of the case where the new character
+		 combines with neighboring bytes.  */ 
+	      if ((! CHAR_HEAD_P (nc)
+		   && pos_byte > BEGV_BYTE
+		   && ! ASCII_BYTE_P (FETCH_BYTE (pos_byte - 1)))
+		  ||
+		  (! ASCII_BYTE_P (nc)
+		   && pos_byte + 1 < ZV_BYTE
+		   && ! CHAR_HEAD_P (FETCH_BYTE (pos_byte + 1))))
+		{
+		  Lisp_Object string;
+
+		  string = Fmake_string (make_number (1),
+					 make_number (nc));
+		  SET_STRING_BYTES (XSTRING (string), 1);
+
+		  /* This is less efficient, because it moves the gap,
+		     but it handles combining correctly.  */
+		  replace_range (pos, pos + 1, string,
+				 1, 0, 0);
+		}
+	      else
+		{
+		  record_change (pos, 1);
+		  *p = nc;
+		  signal_after_change (pos, 1, 1);
+		}
 	      ++cnt;
 	    }
 	}