/* Composite sequence support.
- Copyright (C) 2001-2014 Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H14PRO021
static Lisp_Object gstring_work_headers;
static Lisp_Object
-fill_gstring_header (Lisp_Object header, Lisp_Object start, Lisp_Object end,
- Lisp_Object font_object, Lisp_Object string)
+fill_gstring_header (Lisp_Object header, ptrdiff_t from, ptrdiff_t from_byte,
+ ptrdiff_t to, Lisp_Object font_object, Lisp_Object string)
{
- ptrdiff_t from, to, from_byte;
- ptrdiff_t len, i;
+ ptrdiff_t len = to - from, i;
- if (NILP (string))
- {
- if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
- error ("Attempt to shape unibyte text");
- validate_region (&start, &end);
- from = XFASTINT (start);
- to = XFASTINT (end);
- from_byte = CHAR_TO_BYTE (from);
- }
- else
- {
- CHECK_STRING (string);
- if (! STRING_MULTIBYTE (string))
- error ("Attempt to shape unibyte text");
- /* The caller checks that START and END are nonnegative integers. */
- if (! (XINT (start) <= XINT (end) && XINT (end) <= SCHARS (string)))
- args_out_of_range_3 (string, start, end);
- from = XINT (start);
- to = XINT (end);
- from_byte = string_char_to_byte (string, from);
- }
-
- len = to - from;
if (len == 0)
error ("Attempt to shape zero-length text");
if (VECTORP (header))
return unbind_to (count, lgstring);
}
-static Lisp_Object _work_val;
-
/* 1 iff the character C is composable. Characters of general
category Z? or C? are not composable except for ZWNJ and ZWJ. */
-#define CHAR_COMPOSABLE_P(C) \
- ((C) > ' ' \
- && ((C) == 0x200C || (C) == 0x200D \
- || (_work_val = CHAR_TABLE_REF (Vunicode_category_table, (C)), \
- (INTEGERP (_work_val) \
- && (XINT (_work_val) <= UNICODE_CATEGORY_So)))))
+static bool
+char_composable_p (int c)
+{
+ Lisp_Object val;
+ return (c > ' '
+ && (c == 0x200C || c == 0x200D
+ || (val = CHAR_TABLE_REF (Vunicode_category_table, c),
+ (INTEGERP (val) && (XINT (val) <= UNICODE_CATEGORY_So)))));
+}
/* Update cmp_it->stop_pos to the next position after CHARPOS (and
BYTEPOS) where character composition may happen. If BYTEPOS is
val = CHAR_TABLE_REF (Vcomposition_function_table, c);
if (! NILP (val))
{
- Lisp_Object elt;
- int ridx;
-
- for (ridx = 0; CONSP (val); val = XCDR (val), ridx++)
+ for (int ridx = 0; CONSP (val); val = XCDR (val), ridx++)
{
- elt = XCAR (val);
+ Lisp_Object elt = XCAR (val);
if (VECTORP (elt) && ASIZE (elt) == 3
&& NATNUMP (AREF (elt, 1))
&& charpos - 1 - XFASTINT (AREF (elt, 1)) >= start)
- break;
- }
- if (CONSP (val))
- {
- cmp_it->rule_idx = ridx;
- cmp_it->lookback = XFASTINT (AREF (elt, 1));
- cmp_it->stop_pos = charpos - 1 - cmp_it->lookback;
- cmp_it->ch = c;
- return;
+ {
+ cmp_it->rule_idx = ridx;
+ cmp_it->lookback = XFASTINT (AREF (elt, 1));
+ cmp_it->stop_pos = charpos - 1 - cmp_it->lookback;
+ cmp_it->ch = c;
+ return;
+ }
}
}
}
- if (charpos == endpos)
+ if (charpos == endpos
+ && !(STRINGP (string) && endpos == SCHARS (string)))
{
/* We couldn't find a composition point before ENDPOS. But,
some character after ENDPOS may be composed with
p = SDATA (string) + bytepos;
c = STRING_CHAR_AND_LENGTH (p, len);
limit = bytepos + len;
- while (CHAR_COMPOSABLE_P (c))
+ while (char_composable_p (c))
{
val = CHAR_TABLE_REF (Vcomposition_function_table, c);
if (! NILP (val))
/* Skip all uncomposable characters. */
if (NILP (string))
{
- while (charpos - 1 > endpos && ! CHAR_COMPOSABLE_P (c))
+ while (charpos - 1 > endpos && ! char_composable_p (c))
{
DEC_BOTH (charpos, bytepos);
c = FETCH_MULTIBYTE_CHAR (bytepos);
}
else
{
- while (charpos - 1 > endpos && ! CHAR_COMPOSABLE_P (c))
+ while (charpos - 1 > endpos && ! char_composable_p (c))
{
p--;
while (! CHAR_HEAD_P (*p))
cmp_it->width = 0;
for (i = cmp_it->nchars - 1; i >= 0; i--)
{
- c = XINT (LGSTRING_CHAR (gstring, cmp_it->from + i));
+ c = XINT (LGSTRING_CHAR (gstring, from + i));
cmp_it->nbytes += CHAR_BYTES (c);
cmp_it->width += CHAR_WIDTH (c);
}
|-B-|-C-|--D--|
Here, it is known that characters after positions 1 and 9 can
- never be composed (i.e. ! CHAR_COMPOSABLE_P (CH)), and
+ never be composed (i.e. ! char_composable_p (CH)), and
composition A is an invalid one because it's partially covered by
the valid composition C. And to know whether a composition is
valid or not, the only way is to start searching forward from a
while (1)
{
c = STRING_CHAR (cur.p);
- if (! CHAR_COMPOSABLE_P (c))
+ if (! char_composable_p (c))
{
if (limit <= pos) /* case (1) */
{
return 0;
BACKWARD_CHAR (cur, stop);
c = STRING_CHAR (cur.p);
- } while (! CHAR_COMPOSABLE_P (c));
+ } while (! char_composable_p (c));
fore_check_limit = cur.pos + 1;
}
else /* case (2) */
prev = cur;
BACKWARD_CHAR (cur, stop);
c = STRING_CHAR (cur.p);
- if (! CHAR_COMPOSABLE_P (c))
+ if (! char_composable_p (c))
{
cur = prev;
break;
frame, or nil for the selected frame's terminal device.
If the optional 4th argument STRING is not nil, it is a string
-containing the target characters between indices FROM and TO.
+containing the target characters between indices FROM and TO,
+which are treated as in `substring'. Otherwise FROM and TO are
+character positions in current buffer; they can be in either order,
+and can be integers or markers.
A glyph-string is a vector containing information about how to display
a specific character sequence. The format is:
(Lisp_Object from, Lisp_Object to, Lisp_Object font_object, Lisp_Object string)
{
Lisp_Object gstring, header;
- ptrdiff_t frompos, topos;
+ ptrdiff_t frompos, frombyte, topos;
- CHECK_NATNUM (from);
- CHECK_NATNUM (to);
if (! FONT_OBJECT_P (font_object))
{
struct coding_system *coding;
- struct terminal *terminal = get_terminal (font_object, 1);
+ struct terminal *terminal = decode_live_terminal (font_object);
coding = ((TERMINAL_TERMINAL_CODING (terminal)->common_flags
& CODING_REQUIRE_ENCODING_MASK)
font_object = CODING_ID_NAME (coding->id);
}
- header = fill_gstring_header (Qnil, from, to, font_object, string);
+ if (NILP (string))
+ {
+ if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
+ error ("Attempt to shape unibyte text");
+ validate_region (&from, &to);
+ frompos = XFASTINT (from);
+ topos = XFASTINT (to);
+ frombyte = CHAR_TO_BYTE (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);
+ }
+
+ header = fill_gstring_header (Qnil, frompos, frombyte,
+ topos, font_object, string);
gstring = gstring_lookup_cache (header);
if (! NILP (gstring))
return gstring;
- frompos = XINT (from);
- topos = XINT (to);
if (LGSTRING_GLYPH_LEN (gstring_work) < topos - frompos)
gstring_work = Fmake_vector (make_number (topos - frompos + 2), Qnil);
LGSTRING_SET_HEADER (gstring_work, header);
Scompose_string_internal, 3, 5, 0,
doc: /* Internal use only.
-Compose text between indices START and END of STRING.
-Optional 4th and 5th arguments are COMPONENTS and MODIFICATION-FUNC
+Compose text between indices START and END of STRING, where
+START and END are treated as in `substring'. Optional 4th
+and 5th arguments are COMPONENTS and MODIFICATION-FUNC
for the composition. See `compose-string' for more details. */)
- (Lisp_Object string, Lisp_Object start, Lisp_Object end, Lisp_Object components, Lisp_Object modification_func)
+ (Lisp_Object string, Lisp_Object start, Lisp_Object end,
+ Lisp_Object components, Lisp_Object modification_func)
{
- CHECK_STRING (string);
- CHECK_NUMBER (start);
- CHECK_NUMBER (end);
+ ptrdiff_t from, to;
- if (XINT (start) < 0 ||
- XINT (start) > XINT (end)
- || XINT (end) > SCHARS (string))
- args_out_of_range (start, end);
-
- compose_text (XINT (start), XINT (end), components, modification_func, string);
+ CHECK_STRING (string);
+ validate_subarray (string, start, end, SCHARS (string), &from, &to);
+ compose_text (from, to, components, modification_func, string);
return string;
}