(Ftranslate_region): Handle multibyte chars in the arg

TABLE correctly.
This commit is contained in:
Kenichi Handa 2004-03-01 06:19:10 +00:00
parent 83797c58bf
commit 10475277ce

View file

@ -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);
}