From 10475277ce0d5f813792940aabbd270ebd717f02 Mon Sep 17 00:00:00 2001 From: Kenichi Handa Date: Mon, 1 Mar 2004 06:19:10 +0000 Subject: [PATCH] (Ftranslate_region): Handle multibyte chars in the arg TABLE correctly. --- src/editfns.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/editfns.c b/src/editfns.c index 9a1ce81f316..31493e3c774 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -2741,7 +2741,6 @@ DEFUN ("translate-region", Ftranslate_region, Stranslate_region, 3, 3, 0, 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 @@ It returns the number of characters changed. */) 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 @@ It returns the number of characters changed. */) 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 @@ It returns the number of characters changed. */) 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 @@ It returns the number of characters changed. */) 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); } -- 2.39.2