changeset 54213:29d4d158e5eb

(Ftranslate_region): Handle multibyte chars in the arg TABLE correctly.
author Kenichi Handa <handa@m17n.org>
date Mon, 01 Mar 2004 06:19:10 +0000
parents ba850aa09d2d
children a2f5ab3b6d1b
files src/editfns.c
diffstat 1 files changed, 25 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/editfns.c	Mon Mar 01 04:12:47 2004 +0000
+++ b/src/editfns.c	Mon Mar 01 06:19:10 2004 +0000
@@ -2741,7 +2741,6 @@
        doc: /* From START to END, translate characters according to TABLE.
 TABLE is a string; the Nth character in it is the mapping
 for the character with code N.
-This function does not alter multibyte characters.
 It returns the number of characters changed.  */)
      (start, end, table)
      Lisp_Object start;
@@ -2755,11 +2754,18 @@
   int size;			/* Size of translate table. */
   int pos;
   int multibyte = !NILP (current_buffer->enable_multibyte_characters);
+  int string_multibyte;
 
   validate_region (&start, &end);
   CHECK_STRING (table);
 
-  size = SBYTES (table);
+  if (multibyte != (SCHARS (table) < SBYTES (table)))
+    table = (multibyte
+	     ? string_make_multibyte (table)
+	     : string_make_unibyte (table));
+  string_multibyte = SCHARS (table) < SBYTES (table);
+
+  size = SCHARS (table);
   tt = SDATA (table);
 
   pos_byte = CHAR_TO_BYTE (XINT (start));
@@ -2771,7 +2777,8 @@
   for (; pos_byte < stop; )
     {
       register unsigned char *p = BYTE_POS_ADDR (pos_byte);
-      int len;
+      unsigned char *str;
+      int len, str_len;
       int oc;
       int pos_byte_next;
 
@@ -2780,22 +2787,27 @@
       else
 	oc = *p, len = 1;
       pos_byte_next = pos_byte + len;
-      if (oc < size && len == 1)
+      if (oc < size)
 	{
-	  nc = tt[oc];
+	  if (string_multibyte)
+	    {
+	      str = tt + string_char_to_byte (table, oc);
+	      nc = STRING_CHAR_AND_LENGTH (str, MAX_MULTIBYTE_LENGTH, str_len);
+	    }
+	  else
+	    {
+	      str = tt + oc;
+	      nc = tt[oc], str_len = 1;
+	    }
 	  if (nc != oc)
 	    {
 	      /* Take care of the case where the new character
 		 combines with neighboring bytes.  */
-	      if (!ASCII_BYTE_P (nc)
-		  && (CHAR_HEAD_P (nc)
-		      ? ! CHAR_HEAD_P (FETCH_BYTE (pos_byte + 1))
-		      : (pos_byte > BEG_BYTE
-			 && ! ASCII_BYTE_P (FETCH_BYTE (pos_byte - 1)))))
+	      if (len > 1 || str_len > 1)
 		{
 		  Lisp_Object string;
 
-		  string = make_multibyte_string (tt + oc, 1, 1);
+		  string = make_multibyte_string (str, 1, str_len);
 		  /* This is less efficient, because it moves the gap,
 		     but it handles combining correctly.  */
 		  replace_range (pos, pos + 1, string,
@@ -2812,7 +2824,8 @@
 	      else
 		{
 		  record_change (pos, 1);
-		  *p = nc;
+		  while (str_len-- > 0)
+		    *p++ = *str++;
 		  signal_after_change (pos, 1, 1);
 		  update_compositions (pos, pos + 1, CHECK_BORDER);
 		}