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