diff --git a/src/character.h b/src/character.h index 3642a54044..75672f8d54 100644 --- a/src/character.h +++ b/src/character.h @@ -122,6 +122,10 @@ #define MAKE_CHAR_MULTIBYTE(c) \ /* This is the maximum byte length of multibyte form. */ #define MAX_MULTIBYTE_LENGTH 5 +/* Nonzero iff C is an ASCII byte. */ +#define ASCII_BYTE_P(c) UNSIGNED_CMP (c, <, 0x80) + + /* Nonzero iff X is a character. */ #define CHARACTERP(x) (FIXNATP (x) && XFIXNAT (x) <= MAX_CHAR) diff --git a/src/composite.c b/src/composite.c index 364d5c9316..121a554754 100644 --- a/src/composite.c +++ b/src/composite.c @@ -1744,20 +1744,45 @@ Otherwise (for terminal display), FONT-OBJECT must be a terminal ID, a if (NILP (string)) { - if (NILP (BVAR (current_buffer, enable_multibyte_characters))) - error ("Attempt to shape unibyte text"); - validate_region (&from, &to); + validate_region (&from, &to); frompos = XFIXNAT (from); topos = XFIXNAT (to); - frombyte = CHAR_TO_BYTE (frompos); + if (!NILP (BVAR (current_buffer, enable_multibyte_characters))) + frombyte = CHAR_TO_BYTE (frompos); + else + { + ptrdiff_t pos; + + /* fill_gstring_header below uses + FETCH_CHAR_ADVANCE_NO_CHECK that assumes the current + buffer is multibyte, but it is safe as long as it only + fetches ASCII chars. */ + for (pos = frompos; pos < topos; pos++) + if (!ASCII_BYTE_P (*(BYTE_POS_ADDR (pos)))) + error ("Attempt to shape non-ASCII part of unibyte text"); + frombyte = frompos; + } + } else { CHECK_STRING (string); validate_subarray (string, from, to, SCHARS (string), &frompos, &topos); - if (! STRING_MULTIBYTE (string)) - error ("Attempt to shape unibyte text"); - frombyte = string_char_to_byte (string, frompos); + if (STRING_MULTIBYTE (string)) + frombyte = string_char_to_byte (string, frompos); + else + { + ptrdiff_t pos; + + /* fill_gstring_header below uses + FETCH_STRING_CHAR_ADVANCE_NO_CHECK that assumes the + string is multibyte, but it is safe as long as it only + fetches ASCII chars. */ + for (pos = frompos; pos < topos; pos++) + if (!ASCII_BYTE_P (SREF (string, pos))) + error ("Attempt to shape non-ASCII part of unibyte text"); + frombyte = string_char_to_byte (string, frompos); + } } header = fill_gstring_header (frompos, frombyte,