/* Composite sequence support.
- Copyright (C) 2001-2011 Free Software Foundation, Inc.
+ Copyright (C) 2001-2012 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
Lisp_Object prop, Lisp_Object string)
{
Lisp_Object id, length, components, key, *key_contents;
- int glyph_len;
+ ptrdiff_t glyph_len;
struct Lisp_Hash_Table *hash_table = XHASH_TABLE (composition_hash_table);
ptrdiff_t hash_index;
EMACS_UINT hash_code;
+ enum composition_method method;
struct composition *cmp;
EMACS_INT i;
int ch;
+ /* Maximum length of a string of glyphs. XftGlyphExtents limits
+ this to INT_MAX, and Emacs limits it further. Divide INT_MAX - 1
+ by 2 because x_produce_glyphs computes glyph_len * 2 + 1. Divide
+ the size by MAX_MULTIBYTE_LENGTH because encode_terminal_code
+ multiplies glyph_len by MAX_MULTIBYTE_LENGTH. */
+ enum {
+ GLYPH_LEN_MAX = min ((INT_MAX - 1) / 2,
+ min (PTRDIFF_MAX, SIZE_MAX) / MAX_MULTIBYTE_LENGTH)
+ };
+
/* PROP should be
Form-A: ((LENGTH . COMPONENTS) . MODIFICATION-FUNC)
or
/* This composition is a new one. We must register it. */
/* Check if we have sufficient memory to store this information. */
- if (composition_table_size == 0)
- {
- composition_table
- = (struct composition **) xmalloc (sizeof (composition_table[0]) * 256);
- composition_table_size = 256;
- }
- else if (composition_table_size <= n_compositions)
- {
- if ((min (MOST_POSITIVE_FIXNUM,
- min (PTRDIFF_MAX, SIZE_MAX) / sizeof composition_table[0])
- - 256)
- < composition_table_size)
- memory_full (SIZE_MAX);
- composition_table
- = (struct composition **) xrealloc (composition_table,
- sizeof (composition_table[0])
- * (composition_table_size + 256));
- composition_table_size += 256;
- }
+ if (composition_table_size <= n_compositions)
+ composition_table = xpalloc (composition_table, &composition_table_size,
+ 1, -1, sizeof *composition_table);
key_contents = XVECTOR (key)->contents;
/* Register the composition in composition_hash_table. */
hash_index = hash_put (hash_table, key, id, hash_code);
+ method = (NILP (components)
+ ? COMPOSITION_RELATIVE
+ : ((INTEGERP (components) || STRINGP (components))
+ ? COMPOSITION_WITH_ALTCHARS
+ : COMPOSITION_WITH_RULE_ALTCHARS));
+
+ glyph_len = (method == COMPOSITION_WITH_RULE_ALTCHARS
+ ? (ASIZE (key) + 1) / 2
+ : ASIZE (key));
+
+ if (GLYPH_LEN_MAX < glyph_len)
+ memory_full (SIZE_MAX);
+
/* Register the composition in composition_table. */
cmp = (struct composition *) xmalloc (sizeof (struct composition));
- cmp->method = (NILP (components)
- ? COMPOSITION_RELATIVE
- : ((INTEGERP (components) || STRINGP (components))
- ? COMPOSITION_WITH_ALTCHARS
- : COMPOSITION_WITH_RULE_ALTCHARS));
+ cmp->method = method;
cmp->hash_index = hash_index;
- glyph_len = (cmp->method == COMPOSITION_WITH_RULE_ALTCHARS
- ? (ASIZE (key) + 1) / 2
- : ASIZE (key));
cmp->glyph_len = glyph_len;
- cmp->offsets = (short *) xmalloc (sizeof (short) * glyph_len * 2);
+ cmp->offsets = xnmalloc (glyph_len, 2 * sizeof *cmp->offsets);
cmp->font = NULL;
if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
{
int this_width;
ch = XINT (key_contents[i]);
+ /* TAB in a composition means display glyphs with padding
+ space on the left or right. */
this_width = (ch == '\t' ? 1 : CHAR_WIDTH (ch));
if (cmp->width < this_width)
cmp->width = this_width;
args[4] = font_object;
args[5] = string;
lgstring = safe_call (6, args);
- if (NILP (string))
- TEMP_SET_PT_BOTH (pt, pt_byte);
}
return unbind_to (count, lgstring);
}
if (cmp_it->lookback == 0)
goto no_composition;
lgstring = Qnil;
- /* Try to find a shorter compostion that starts after CPOS. */
+ /* Try to find a shorter composition that starts after CPOS. */
composition_compute_stop_pos (cmp_it, charpos, bytepos, cpos,
string);
if (cmp_it->ch == -2 || cmp_it->stop_pos < charpos)
else
{
for (i = 0; i < cmp->glyph_len; i++)
+ /* TAB in a composition means display glyphs with padding
+ space on the left or right. */
if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
break;
if (c == '\t')