(Ftranslate_region): Handle multibyte chars in the arg
TABLE correctly.
This commit is contained in:
parent
83797c58bf
commit
10475277ce
1 changed files with 25 additions and 12 deletions
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue