1 /* Composite sequence support.
   2    Copyright (C) 2001, 2002, 2003, 2004, 2005,
   3                  2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
   4    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
   5      National Institute of Advanced Industrial Science and Technology (AIST)
   6      Registration Number H14PRO021
   7    Copyright (C) 2003, 2006
   8      National Institute of Advanced Industrial Science and Technology (AIST)
   9      Registration Number H13PRO009
  10 
  11 This file is part of GNU Emacs.
  12 
  13 GNU Emacs is free software: you can redistribute it and/or modify
  14 it under the terms of the GNU General Public License as published by
  15 the Free Software Foundation, either version 3 of the License, or
  16 (at your option) any later version.
  17 
  18 GNU Emacs is distributed in the hope that it will be useful,
  19 but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 GNU General Public License for more details.
  22 
  23 You should have received a copy of the GNU General Public License
  24 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
  25 
  26 #include <config.h>
  27 #include <setjmp.h>
  28 #include "lisp.h"
  29 #include "buffer.h"
  30 #include "character.h"
  31 #include "coding.h"
  32 #include "intervals.h"
  33 #include "window.h"
  34 #include "frame.h"
  35 #include "dispextern.h"
  36 #include "font.h"
  37 #include "termhooks.h"
  38 
  39 
  40 /* Emacs uses special text property `composition' to support character
  41    composition.  A sequence of characters that have the same (i.e. eq)
  42    `composition' property value is treated as a single composite
  43    sequence (we call it just `composition' here after).  Characters in
  44    a composition are all composed somehow on the screen.
  45 
  46    The property value has this form when the composition is made:
  47         ((LENGTH . COMPONENTS) . MODIFICATION-FUNC)
  48    then turns to this form:
  49         (COMPOSITION-ID . (LENGTH COMPONENTS-VEC . MODIFICATION-FUNC))
  50    when the composition is registered in composition_hash_table and
  51    composition_table.  These rather peculiar structures were designed
  52    to make it easy to distinguish them quickly (we can do that by
  53    checking only the first element) and to extract LENGTH (from the
  54    former form) and COMPOSITION-ID (from the latter form).
  55 
  56    We register a composition when it is displayed, or when the width
  57    is required (for instance, to calculate columns).
  58 
  59    LENGTH -- Length of the composition.  This information is used to
  60         check the validity of the composition.
  61 
  62    COMPONENTS --  Character, string, vector, list, or nil.
  63 
  64         If it is nil, characters in the text are composed relatively
  65         according to their metrics in font glyphs.
  66 
  67         If it is a character or a string, the character or characters
  68         in the string are composed relatively.
  69 
  70         If it is a vector or list of integers, the element is a
  71         character or an encoded composition rule.  The characters are
  72         composed according to the rules.  (2N)th elements are
  73         characters to be composed and (2N+1)th elements are
  74         composition rules to tell how to compose (2N+2)th element with
  75         the previously composed 2N glyphs.
  76 
  77    COMPONENTS-VEC -- Vector of integers.  In a relative composition,
  78         the elements are the characters to be composed.  In a rule-base
  79         composition, the elements are characters or encoded
  80         composition rules.
  81 
  82    MODIFICATION-FUNC -- If non nil, it is a function to call when the
  83         composition gets invalid after a modification in a buffer.  If
  84         it is nil, a function in `composition-function-table' of the
  85         first character in the sequence is called.
  86 
  87    COMPOSITION-ID --Identification number of the composition.  It is
  88         used as an index to composition_table for the composition.
  89 
  90    When Emacs has to display a composition or has to know its
  91    displaying width, the function get_composition_id is called.  It
  92    returns COMPOSITION-ID so that the caller can access the
  93    information about the composition through composition_table.  If a
  94    COMPOSITION-ID has not yet been assigned to the composition,
  95    get_composition_id checks the validity of `composition' property,
  96    and, if valid, assigns a new ID, registers the information in
  97    composition_hash_table and composition_table, and changes the form
  98    of the property value.  If the property is invalid,
  99    get_composition_id returns -1 without changing the property value.
 100 
 101    We use two tables to keep the information about composition;
 102    composition_hash_table and composition_table.
 103 
 104    The former is a hash table whose keys are COMPONENTS-VECs and
 105    values are the corresponding COMPOSITION-IDs.  This hash table is
 106    weak, but as each key (COMPONENTS-VEC) is also kept as a value of the
 107    `composition' property, it won't be collected as garbage until all
 108    bits of text that have the same COMPONENTS-VEC are deleted.
 109 
 110    The latter is a table of pointers to `struct composition' indexed
 111    by COMPOSITION-ID.  This structure keeps the other information (see
 112    composite.h).
 113 
 114    In general, a text property holds information about individual
 115    characters.  But, a `composition' property holds information about
 116    a sequence of characters (in this sense, it is like the `intangible'
 117    property).  That means that we should not share the property value
 118    in adjacent compositions -- we can't distinguish them if they have the
 119    same property.  So, after any changes, we call
 120    `update_compositions' and change a property of one of adjacent
 121    compositions to a copy of it.  This function also runs a proper
 122    composition modification function to make a composition that gets
 123    invalid by the change valid again.
 124 
 125    As the value of the `composition' property holds information about a
 126    specific range of text, the value gets invalid if we change the
 127    text in the range.  We treat the `composition' property as always
 128    rear-nonsticky (currently by setting default-text-properties to
 129    (rear-nonsticky (composition))) and we never make properties of
 130    adjacent compositions identical.  Thus, any such changes make the
 131    range just shorter.  So, we can check the validity of the `composition'
 132    property by comparing LENGTH information with the actual length of
 133    the composition.
 134 
 135 */
 136 
 137 
 138 Lisp_Object Qcomposition;
 139 
 140 /* Table of pointers to the structure `composition' indexed by
 141    COMPOSITION-ID.  This structure is for storing information about
 142    each composition except for COMPONENTS-VEC.  */
 143 struct composition **composition_table;
 144 
 145 /* The current size of `composition_table'.  */
 146 static int composition_table_size;
 147 
 148 /* Number of compositions currently made. */
 149 int n_compositions;
 150 
 151 /* Hash table for compositions.  The key is COMPONENTS-VEC of
 152    `composition' property.  The value is the corresponding
 153    COMPOSITION-ID.  */
 154 Lisp_Object composition_hash_table;
 155 
 156 /* Function to call to adjust composition.  */
 157 Lisp_Object Vcompose_chars_after_function;
 158 
 159 Lisp_Object Qauto_composed;
 160 Lisp_Object Vauto_composition_mode;
 161 Lisp_Object Vauto_composition_function;
 162 Lisp_Object Qauto_composition_function;
 163 Lisp_Object Vcomposition_function_table;
 164 
 165 /* Maximum number of characters to look back for
 166    auto-compositions.  */
 167 #define MAX_AUTO_COMPOSITION_LOOKBACK 3
 168 
 169 EXFUN (Fremove_list_of_text_properties, 4);
 170 
 171 /* Temporary variable used in macros COMPOSITION_XXX.  */
 172 Lisp_Object composition_temp;
 173 
 174 
 175 /* Return COMPOSITION-ID of a composition at buffer position
 176    CHARPOS/BYTEPOS and length NCHARS.  The `composition' property of
 177    the sequence is PROP.  STRING, if non-nil, is a string that
 178    contains the composition instead of the current buffer.
 179 
 180    If the composition is invalid, return -1.  */
 181 
 182 int
 183 get_composition_id (charpos, bytepos, nchars, prop, string)
 184      int charpos, bytepos, nchars;
 185      Lisp_Object prop, string;
 186 {
 187   Lisp_Object id, length, components, key, *key_contents;
 188   int glyph_len;
 189   struct Lisp_Hash_Table *hash_table = XHASH_TABLE (composition_hash_table);
 190   int hash_index;
 191   unsigned hash_code;
 192   struct composition *cmp;
 193   int i, ch;
 194 
 195   /* PROP should be
 196         Form-A: ((LENGTH . COMPONENTS) . MODIFICATION-FUNC)
 197      or
 198         Form-B: (COMPOSITION-ID . (LENGTH COMPONENTS-VEC . MODIFICATION-FUNC))
 199   */
 200   if (nchars == 0 || !CONSP (prop))
 201     goto invalid_composition;
 202 
 203   id = XCAR (prop);
 204   if (INTEGERP (id))
 205     {
 206       /* PROP should be Form-B.  */
 207       if (XINT (id) < 0 || XINT (id) >= n_compositions)
 208         goto invalid_composition;
 209       return XINT (id);
 210     }
 211 
 212   /* PROP should be Form-A.
 213      Thus, ID should be (LENGTH . COMPONENTS).  */
 214   if (!CONSP (id))
 215     goto invalid_composition;
 216   length = XCAR (id);
 217   if (!INTEGERP (length) || XINT (length) != nchars)
 218     goto invalid_composition;
 219 
 220   components = XCDR (id);
 221 
 222   /* Check if the same composition has already been registered or not
 223      by consulting composition_hash_table.  The key for this table is
 224      COMPONENTS (converted to a vector COMPONENTS-VEC) or, if it is
 225      nil, vector of characters in the composition range.  */
 226   if (INTEGERP (components))
 227     key = Fmake_vector (make_number (1), components);
 228   else if (STRINGP (components) || CONSP (components))
 229     key = Fvconcat (1, &components);
 230   else if (VECTORP (components))
 231     key = components;
 232   else if (NILP (components))
 233     {
 234       key = Fmake_vector (make_number (nchars), Qnil);
 235       if (STRINGP (string))
 236         for (i = 0; i < nchars; i++)
 237           {
 238             FETCH_STRING_CHAR_ADVANCE (ch, string, charpos, bytepos);
 239             XVECTOR (key)->contents[i] = make_number (ch);
 240           }
 241       else
 242         for (i = 0; i < nchars; i++)
 243           {
 244             FETCH_CHAR_ADVANCE (ch, charpos, bytepos);
 245             XVECTOR (key)->contents[i] = make_number (ch);
 246           }
 247     }
 248   else
 249     goto invalid_composition;
 250 
 251   hash_index = hash_lookup (hash_table, key, &hash_code);
 252   if (hash_index >= 0)
 253     {
 254       /* We have already registered the same composition.  Change PROP
 255          from Form-A above to Form-B while replacing COMPONENTS with
 256          COMPONENTS-VEC stored in the hash table.  We can directly
 257          modify the cons cell of PROP because it is not shared.  */
 258       key = HASH_KEY (hash_table, hash_index);
 259       id = HASH_VALUE (hash_table, hash_index);
 260       XSETCAR (prop, id);
 261       XSETCDR (prop, Fcons (make_number (nchars), Fcons (key, XCDR (prop))));
 262       return XINT (id);
 263     }
 264 
 265   /* This composition is a new one.  We must register it.  */
 266 
 267   /* Check if we have sufficient memory to store this information.  */
 268   if (composition_table_size == 0)
 269     {
 270       composition_table_size = 256;
 271       composition_table
 272         = (struct composition **) xmalloc (sizeof (composition_table[0])
 273                                            * composition_table_size);
 274     }
 275   else if (composition_table_size <= n_compositions)
 276     {
 277       composition_table_size += 256;
 278       composition_table
 279         = (struct composition **) xrealloc (composition_table,
 280                                             sizeof (composition_table[0])
 281                                             * composition_table_size);
 282     }
 283 
 284   key_contents = XVECTOR (key)->contents;
 285 
 286   /* Check if the contents of COMPONENTS are valid if COMPONENTS is a
 287      vector or a list.  It should be a sequence of:
 288         char1 rule1 char2 rule2 char3 ...    ruleN charN+1  */
 289 
 290   if (VECTORP (components)
 291       && ASIZE (components) >= 2
 292       && VECTORP (AREF (components, 0)))
 293     {
 294       /* COMPONENTS is a glyph-string.  */
 295       int len = ASIZE (key);
 296 
 297       for (i = 1; i < len; i++)
 298         if (! VECTORP (AREF (key, i)))
 299           goto invalid_composition;
 300     }
 301   else if (VECTORP (components) || CONSP (components))
 302     {
 303       int len = XVECTOR (key)->size;
 304 
 305       /* The number of elements should be odd.  */
 306       if ((len % 2) == 0)
 307         goto invalid_composition;
 308       /* All elements should be integers (character or encoded
 309          composition rule).  */
 310       for (i = 0; i < len; i++)
 311         {
 312           if (!INTEGERP (key_contents[i]))
 313             goto invalid_composition;
 314         }
 315     }
 316 
 317   /* Change PROP from Form-A above to Form-B.  We can directly modify
 318      the cons cell of PROP because it is not shared.  */
 319   XSETFASTINT (id, n_compositions);
 320   XSETCAR (prop, id);
 321   XSETCDR (prop, Fcons (make_number (nchars), Fcons (key, XCDR (prop))));
 322 
 323   /* Register the composition in composition_hash_table.  */
 324   hash_index = hash_put (hash_table, key, id, hash_code);
 325 
 326   /* Register the composition in composition_table.  */
 327   cmp = (struct composition *) xmalloc (sizeof (struct composition));
 328 
 329   cmp->method = (NILP (components)
 330                  ? COMPOSITION_RELATIVE
 331                  : ((INTEGERP (components) || STRINGP (components))
 332                     ? COMPOSITION_WITH_ALTCHARS
 333                     : COMPOSITION_WITH_RULE_ALTCHARS));
 334   cmp->hash_index = hash_index;
 335   glyph_len = (cmp->method == COMPOSITION_WITH_RULE_ALTCHARS
 336                ? (XVECTOR (key)->size + 1) / 2
 337                : XVECTOR (key)->size);
 338   cmp->glyph_len = glyph_len;
 339   cmp->offsets = (short *) xmalloc (sizeof (short) * glyph_len * 2);
 340   cmp->font = NULL;
 341 
 342   if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
 343     {
 344       /* Relative composition.  */
 345       cmp->width = 0;
 346       for (i = 0; i < glyph_len; i++)
 347         {
 348           int this_width;
 349           ch = XINT (key_contents[i]);
 350           this_width = (ch == '\t' ? 1 : CHAR_WIDTH (ch));
 351           if (cmp->width < this_width)
 352             cmp->width = this_width;
 353         }
 354     }
 355   else
 356     {
 357       /* Rule-base composition.  */
 358       float leftmost = 0.0, rightmost;
 359 
 360       ch = XINT (key_contents[0]);
 361       rightmost = ch != '\t' ? CHAR_WIDTH (ch) : 1;
 362 
 363       for (i = 1; i < glyph_len; i += 2)
 364         {
 365           int rule, gref, nref, xoff, yoff;
 366           int this_width;
 367           float this_left;
 368 
 369           rule = XINT (key_contents[i]);
 370           ch = XINT (key_contents[i + 1]);
 371           this_width = ch != '\t' ? CHAR_WIDTH (ch) : 1;
 372 
 373           /* A composition rule is specified by an integer value
 374              that encodes global and new reference points (GREF and
 375              NREF).  GREF and NREF are specified by numbers as
 376              below:
 377                 0---1---2 -- ascent
 378                 |       |
 379                 |       |
 380                 |       |
 381                 9--10--11 -- center
 382                 |       |
 383              ---3---4---5--- baseline
 384                 |       |
 385                 6---7---8 -- descent
 386           */
 387           COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
 388           this_left = (leftmost
 389                        + (gref % 3) * (rightmost - leftmost) / 2.0
 390                        - (nref % 3) * this_width / 2.0);
 391 
 392           if (this_left < leftmost)
 393             leftmost = this_left;
 394           if (this_left + this_width > rightmost)
 395             rightmost = this_left + this_width;
 396         }
 397 
 398       cmp->width = rightmost - leftmost;
 399       if (cmp->width < (rightmost - leftmost))
 400         /* To get a ceiling integer value.  */
 401         cmp->width++;
 402     }
 403 
 404   composition_table[n_compositions] = cmp;
 405 
 406   return n_compositions++;
 407 
 408  invalid_composition:
 409   /* Would it be better to remove this `composition' property?  */
 410   return -1;
 411 }
 412 
 413 
 414 /* Find a static composition at or nearest to position POS of OBJECT
 415    (buffer or string).
 416 
 417    OBJECT defaults to the current buffer.  If there's a composition at
 418    POS, set *START and *END to the start and end of the sequence,
 419    *PROP to the `composition' property, and return 1.
 420 
 421    If there's no composition at POS and LIMIT is negative, return 0.
 422 
 423    Otherwise, search for a composition forward (LIMIT > POS) or
 424    backward (LIMIT < POS).  In this case, LIMIT bounds the search.
 425 
 426    If a composition is found, set *START, *END, and *PROP as above,
 427    and return 1, else return 0.
 428 
 429    This doesn't check the validity of composition.  */
 430 
 431 int
 432 find_composition (pos, limit, start, end, prop, object)
 433      int pos, limit;
 434      EMACS_INT *start, *end;
 435      Lisp_Object *prop, object;
 436 {
 437   Lisp_Object val;
 438 
 439   if (get_property_and_range (pos, Qcomposition, prop, start, end, object))
 440     return 1;
 441 
 442   if (limit < 0 || limit == pos)
 443     return 0;
 444 
 445   if (limit > pos)              /* search forward */
 446     {
 447       val = Fnext_single_property_change (make_number (pos), Qcomposition,
 448                                           object, make_number (limit));
 449       pos = XINT (val);
 450       if (pos == limit)
 451         return 0;
 452     }
 453   else                          /* search backward */
 454     {
 455       if (get_property_and_range (pos - 1, Qcomposition, prop, start, end,
 456                                   object))
 457         return 1;
 458       val = Fprevious_single_property_change (make_number (pos), Qcomposition,
 459                                               object, make_number (limit));
 460       pos = XINT (val);
 461       if (pos == limit)
 462         return 0;
 463       pos--;
 464     }
 465   get_property_and_range (pos, Qcomposition, prop, start, end, object);
 466   return 1;
 467 }
 468 
 469 /* Run a proper function to adjust the composition sitting between
 470    FROM and TO with property PROP.  */
 471 
 472 static void
 473 run_composition_function (from, to, prop)
 474      int from, to;
 475      Lisp_Object prop;
 476 {
 477   Lisp_Object func;
 478   EMACS_INT start, end;
 479 
 480   func = COMPOSITION_MODIFICATION_FUNC (prop);
 481   /* If an invalid composition precedes or follows, try to make them
 482      valid too.  */
 483   if (from > BEGV
 484       && find_composition (from - 1, -1, &start, &end, &prop, Qnil)
 485       && !COMPOSITION_VALID_P (start, end, prop))
 486     from = start;
 487   if (to < ZV
 488       && find_composition (to, -1, &start, &end, &prop, Qnil)
 489       && !COMPOSITION_VALID_P (start, end, prop))
 490     to = end;
 491   if (!NILP (Ffboundp (func)))
 492     call2 (func, make_number (from), make_number (to));
 493 }
 494 
 495 /* Make invalid compositions adjacent to or inside FROM and TO valid.
 496    CHECK_MASK is bitwise `or' of mask bits defined by macros
 497    CHECK_XXX (see the comment in composite.h).
 498 
 499    It also resets the text-property `auto-composed' to a proper region
 500    so that automatic character composition works correctly later while
 501    displaying the region.
 502 
 503    This function is called when a buffer text is changed.  If the
 504    change is deletion, FROM == TO.  Otherwise, FROM < TO.  */
 505 
 506 void
 507 update_compositions (from, to, check_mask)
 508      EMACS_INT from, to;
 509      int check_mask;
 510 {
 511   Lisp_Object prop;
 512   EMACS_INT start, end;
 513   /* The beginning and end of the region to set the property
 514      `auto-composed' to nil.  */
 515   EMACS_INT min_pos = from, max_pos = to;
 516 
 517   if (inhibit_modification_hooks)
 518     return;
 519 
 520   /* If FROM and TO are not in a valid range, do nothing.  */
 521   if (! (BEGV <= from && from <= to && to <= ZV))
 522     return;
 523 
 524   if (check_mask & CHECK_HEAD)
 525     {
 526       /* FROM should be at composition boundary.  But, insertion or
 527          deletion will make two compositions adjacent and
 528          indistinguishable when they have same (eq) property.  To
 529          avoid it, in such a case, we change the property of the
 530          latter to the copy of it.  */
 531       if (from > BEGV
 532           && find_composition (from - 1, -1, &start, &end, &prop, Qnil)
 533           && COMPOSITION_VALID_P (start, end, prop))
 534         {
 535           min_pos = start;
 536           if (end > to)
 537             max_pos = end;
 538           if (from < end)
 539             Fput_text_property (make_number (from), make_number (end),
 540                                 Qcomposition,
 541                                 Fcons (XCAR (prop), XCDR (prop)), Qnil);
 542           run_composition_function (start, end, prop);
 543           from = end;
 544         }
 545       else if (from < ZV
 546                && find_composition (from, -1, &start, &from, &prop, Qnil)
 547                && COMPOSITION_VALID_P (start, from, prop))
 548         {
 549           if (from > to)
 550             max_pos = from;
 551           run_composition_function (start, from, prop);
 552         }
 553     }
 554 
 555   if (check_mask & CHECK_INSIDE)
 556     {
 557       /* In this case, we are sure that (check & CHECK_TAIL) is also
 558          nonzero.  Thus, here we should check only compositions before
 559          (to - 1).  */
 560       while (from < to - 1
 561              && find_composition (from, to, &start, &from, &prop, Qnil)
 562              && COMPOSITION_VALID_P (start, from, prop)
 563              && from < to - 1)
 564         run_composition_function (start, from, prop);
 565     }
 566 
 567   if (check_mask & CHECK_TAIL)
 568     {
 569       if (from < to
 570           && find_composition (to - 1, -1, &start, &end, &prop, Qnil)
 571           && COMPOSITION_VALID_P (start, end, prop))
 572         {
 573           /* TO should be also at composition boundary.  But,
 574              insertion or deletion will make two compositions adjacent
 575              and indistinguishable when they have same (eq) property.
 576              To avoid it, in such a case, we change the property of
 577              the former to the copy of it.  */
 578           if (to < end)
 579             {
 580               Fput_text_property (make_number (start), make_number (to),
 581                                   Qcomposition,
 582                                   Fcons (XCAR (prop), XCDR (prop)), Qnil);
 583               max_pos = end;
 584             }
 585           run_composition_function (start, end, prop);
 586         }
 587       else if (to < ZV
 588                && find_composition (to, -1, &start, &end, &prop, Qnil)
 589                && COMPOSITION_VALID_P (start, end, prop))
 590         {
 591           run_composition_function (start, end, prop);
 592           max_pos = end;
 593         }
 594     }
 595   if (min_pos < max_pos)
 596     {
 597       int count = SPECPDL_INDEX ();
 598 
 599       specbind (Qinhibit_read_only, Qt);
 600       specbind (Qinhibit_modification_hooks, Qt);
 601       specbind (Qinhibit_point_motion_hooks, Qt);
 602       Fremove_list_of_text_properties (make_number (min_pos),
 603                                        make_number (max_pos),
 604                                        Fcons (Qauto_composed, Qnil), Qnil);
 605       unbind_to (count, Qnil);
 606     }
 607 }
 608 
 609 
 610 /* Modify composition property values in LIST destructively.  LIST is
 611    a list as returned from text_property_list.  Change values to the
 612    top-level copies of them so that none of them are `eq'.  */
 613 
 614 void
 615 make_composition_value_copy (list)
 616      Lisp_Object list;
 617 {
 618   Lisp_Object plist, val;
 619 
 620   for (; CONSP (list); list = XCDR (list))
 621     {
 622       plist = XCAR (XCDR (XCDR (XCAR (list))));
 623       while (CONSP (plist) && CONSP (XCDR (plist)))
 624         {
 625           if (EQ (XCAR (plist), Qcomposition)
 626               && (val = XCAR (XCDR (plist)), CONSP (val)))
 627             XSETCAR (XCDR (plist), Fcons (XCAR (val), XCDR (val)));
 628           plist = XCDR (XCDR (plist));
 629         }
 630     }
 631 }
 632 
 633 
 634 /* Make text in the region between START and END a composition that
 635    has COMPONENTS and MODIFICATION-FUNC.
 636 
 637    If STRING is non-nil, then operate on characters contained between
 638    indices START and END in STRING.  */
 639 
 640 void
 641 compose_text (start, end, components, modification_func, string)
 642      int start, end;
 643      Lisp_Object components, modification_func, string;
 644 {
 645   Lisp_Object prop;
 646 
 647   prop = Fcons (Fcons (make_number (end - start), components),
 648                 modification_func);
 649   Fput_text_property  (make_number (start), make_number (end),
 650                        Qcomposition, prop, string);
 651 }
 652 
 653 
 654 static Lisp_Object autocmp_chars P_ ((Lisp_Object, EMACS_INT, EMACS_INT,
 655                                       EMACS_INT, struct window *,
 656                                       struct face *, Lisp_Object));
 657 
 658 
 659 /* Lisp glyph-string handlers */
 660 
 661 /* Hash table for automatic composition.  The key is a header of a
 662    lgstring (Lispy glyph-string), and the value is a body of a
 663    lgstring.  */
 664 
 665 static Lisp_Object gstring_hash_table;
 666 
 667 static Lisp_Object gstring_lookup_cache P_ ((Lisp_Object));
 668 
 669 static Lisp_Object
 670 gstring_lookup_cache (header)
 671      Lisp_Object header;
 672 {
 673   struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
 674   int i = hash_lookup (h, header, NULL);
 675 
 676   return (i >= 0 ? HASH_VALUE (h, i) : Qnil);
 677 }
 678 
 679 Lisp_Object
 680 composition_gstring_put_cache (gstring, len)
 681      Lisp_Object gstring;
 682      int len;
 683 {
 684   struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
 685   unsigned hash;
 686   Lisp_Object header, copy;
 687   int i;
 688 
 689   header = LGSTRING_HEADER (gstring);
 690   hash = h->hashfn (h, header);
 691   if (len < 0)
 692     {
 693       len = LGSTRING_GLYPH_LEN (gstring);
 694       for (i = 0; i < len; i++)
 695         if (NILP (LGSTRING_GLYPH (gstring, i)))
 696           break;
 697       len = i;
 698     }
 699 
 700   copy = Fmake_vector (make_number (len + 2), Qnil);
 701   LGSTRING_SET_HEADER (copy, Fcopy_sequence (header));
 702   for (i = 0; i < len; i++)
 703     LGSTRING_SET_GLYPH (copy, i, Fcopy_sequence (LGSTRING_GLYPH (gstring, i)));
 704   i = hash_put (h, LGSTRING_HEADER (copy), copy, hash);
 705   LGSTRING_SET_ID (copy, make_number (i));
 706   return copy;
 707 }
 708 
 709 Lisp_Object
 710 composition_gstring_from_id (id)
 711      int id;
 712 {
 713   struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
 714 
 715   return HASH_VALUE (h, id);
 716 }
 717 
 718 static Lisp_Object fill_gstring_header P_ ((Lisp_Object, Lisp_Object,
 719                                             Lisp_Object, Lisp_Object,
 720                                             Lisp_Object));
 721 
 722 int
 723 composition_gstring_p (gstring)
 724      Lisp_Object gstring;
 725 {
 726   Lisp_Object header;
 727   int i;
 728 
 729   if (! VECTORP (gstring) || ASIZE (gstring) < 2)
 730     return 0;
 731   header = LGSTRING_HEADER (gstring);
 732   if (! VECTORP (header) || ASIZE (header) < 2)
 733     return 0;
 734   if (! NILP (LGSTRING_FONT (gstring))
 735       && (! FONT_OBJECT_P (LGSTRING_FONT (gstring))
 736           && ! CODING_SYSTEM_P (LGSTRING_FONT (gstring))))
 737     return 0;
 738   for (i = 1; i < ASIZE (LGSTRING_HEADER (gstring)); i++)
 739     if (! NATNUMP (AREF (LGSTRING_HEADER (gstring), i)))
 740       return 0;
 741   if (! NILP (LGSTRING_ID (gstring)) && ! NATNUMP (LGSTRING_ID (gstring)))
 742     return 0;
 743   for (i = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
 744     {
 745       Lisp_Object glyph = LGSTRING_GLYPH (gstring, i);
 746       if (NILP (glyph))
 747         break;
 748       if (! VECTORP (glyph) || ASIZE (glyph) != LGLYPH_SIZE)
 749         return 0;
 750     }
 751   return 1;
 752 }
 753 
 754 int
 755 composition_gstring_width (gstring, from, to, metrics)
 756      Lisp_Object gstring;
 757      int from, to;
 758      struct font_metrics *metrics;
 759 {
 760   Lisp_Object *glyph;
 761   int width = 0;
 762 
 763   if (metrics)
 764     {
 765       Lisp_Object font_object = LGSTRING_FONT (gstring);
 766 
 767       if (FONT_OBJECT_P (font_object))
 768         {
 769           struct font *font = XFONT_OBJECT (font_object);
 770 
 771           metrics->ascent = font->ascent;
 772           metrics->descent = font->descent;
 773         }
 774       else
 775         {
 776           metrics->ascent = 1;
 777           metrics->descent = 0;
 778         }
 779       metrics->width = metrics->lbearing = metrics->rbearing = 0;
 780     }
 781   for (glyph = &LGSTRING_GLYPH (gstring, from); from < to; from++, glyph++)
 782     {
 783       int x;
 784 
 785       if (NILP (LGLYPH_ADJUSTMENT (*glyph)))
 786         width += LGLYPH_WIDTH (*glyph);
 787       else
 788         width += LGLYPH_WADJUST (*glyph);
 789       if (metrics)
 790         {
 791           x = metrics->width + LGLYPH_LBEARING (*glyph) + LGLYPH_XOFF (*glyph);
 792           if (metrics->lbearing > x)
 793             metrics->lbearing = x;
 794           x = metrics->width + LGLYPH_RBEARING (*glyph) + LGLYPH_XOFF (*glyph);
 795           if (metrics->rbearing < x)
 796             metrics->rbearing = x;
 797           metrics->width = width;
 798           x = LGLYPH_ASCENT (*glyph) - LGLYPH_YOFF (*glyph);
 799           if (metrics->ascent < x)
 800             metrics->ascent = x;
 801           x = LGLYPH_DESCENT (*glyph) + LGLYPH_YOFF (*glyph);
 802           if (metrics->descent < x)
 803             metrics->descent = x;
 804         }
 805     }
 806   return width;
 807 }
 808 
 809 
 810 static Lisp_Object gstring_work;
 811 static Lisp_Object gstring_work_headers;
 812 
 813 static Lisp_Object
 814 fill_gstring_header (header, start, end, font_object, string)
 815      Lisp_Object header, start, end, font_object, string;
 816 {
 817   EMACS_INT from, to, from_byte;
 818   EMACS_INT len, i;
 819 
 820   if (NILP (string))
 821     {
 822       if (NILP (current_buffer->enable_multibyte_characters))
 823         error ("Attempt to shape unibyte text");
 824       validate_region (&start, &end);
 825       from = XFASTINT (start);
 826       to = XFASTINT (end);
 827       from_byte = CHAR_TO_BYTE (from);
 828     }
 829   else
 830     {
 831       CHECK_STRING (string);
 832       if (! STRING_MULTIBYTE (string))
 833         error ("Attempt to shape unibyte text");
 834       /* FROM and TO are checked by the caller.  */
 835       from = XINT (start);
 836       to = XINT (end);
 837       if (from < 0 || from > to || to > SCHARS (string))
 838         args_out_of_range_3 (string, start, end);
 839       from_byte = string_char_to_byte (string, from);
 840     }
 841 
 842   len = to - from;
 843   if (len == 0)
 844     error ("Attempt to shape zero-length text");
 845   if (VECTORP (header))
 846     {
 847       if (ASIZE (header) != len + 1)
 848         args_out_of_range (header, make_number (len + 1));
 849     }
 850   else
 851     {
 852       if (len <= 8)
 853         header = AREF (gstring_work_headers, len - 1);
 854       else
 855         header = Fmake_vector (make_number (len + 1), Qnil);
 856     }
 857 
 858   ASET (header, 0, font_object);
 859   for (i = 0; i < len; i++)
 860     {
 861       int c;
 862 
 863       if (NILP (string))
 864         FETCH_CHAR_ADVANCE_NO_CHECK (c, from, from_byte);
 865       else
 866         FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, from, from_byte);
 867       ASET (header, i + 1, make_number (c));
 868     }
 869   return header;
 870 }
 871 
 872 extern void font_fill_lglyph_metrics P_ ((Lisp_Object, Lisp_Object));
 873 
 874 static void
 875 fill_gstring_body (gstring)
 876      Lisp_Object gstring;
 877 {
 878   Lisp_Object font_object = LGSTRING_FONT (gstring);
 879   Lisp_Object header = AREF (gstring, 0);
 880   EMACS_INT len = LGSTRING_CHAR_LEN (gstring);
 881   EMACS_INT i;
 882 
 883   for (i = 0; i < len; i++)
 884     {
 885       Lisp_Object g = LGSTRING_GLYPH (gstring, i);
 886       EMACS_INT c = XINT (AREF (header, i + 1));
 887 
 888       if (NILP (g))
 889         {
 890           g = LGLYPH_NEW ();
 891           LGSTRING_SET_GLYPH (gstring, i, g);
 892         }
 893       LGLYPH_SET_FROM (g, i);
 894       LGLYPH_SET_TO (g, i);
 895       LGLYPH_SET_CHAR (g, c);
 896       if (FONT_OBJECT_P (font_object))
 897         {
 898           font_fill_lglyph_metrics (g, font_object);
 899         }
 900       else
 901         {
 902           int width = XFASTINT (CHAR_TABLE_REF (Vchar_width_table, c));
 903 
 904           LGLYPH_SET_CODE (g, c);
 905           LGLYPH_SET_LBEARING (g, 0);
 906           LGLYPH_SET_RBEARING (g, width);
 907           LGLYPH_SET_WIDTH (g, width);
 908           LGLYPH_SET_ASCENT (g, 1);
 909           LGLYPH_SET_DESCENT (g, 0);
 910         }
 911       LGLYPH_SET_ADJUSTMENT (g, Qnil);
 912     }
 913   if (i < LGSTRING_GLYPH_LEN (gstring))
 914     LGSTRING_SET_GLYPH (gstring, i, Qnil);
 915 }
 916 
 917 
 918 /* Try to compose the characters at CHARPOS according to composition
 919    rule RULE ([PATTERN PREV-CHARS FUNC]).  LIMIT limits the characters
 920    to compose.  STRING, if not nil, is a target string.  WIN is a
 921    window where the characters are being displayed.  If characters are
 922    successfully composed, return the composition as a glyph-string
 923    object.  Otherwise return nil.  */
 924 
 925 static Lisp_Object
 926 autocmp_chars (rule, charpos, bytepos, limit, win, face, string)
 927      Lisp_Object rule;
 928      EMACS_INT charpos, bytepos, limit;
 929      struct window *win;
 930      struct face *face;
 931      Lisp_Object string;
 932 {
 933   int count = SPECPDL_INDEX ();
 934   FRAME_PTR f = XFRAME (win->frame);
 935   Lisp_Object pos = make_number (charpos);
 936   EMACS_INT to;
 937   EMACS_INT pt = PT, pt_byte = PT_BYTE;
 938   Lisp_Object re, font_object, lgstring;
 939   int len;
 940 
 941   record_unwind_save_match_data ();
 942   re = AREF (rule, 0);
 943   if (NILP (re))
 944     len = 1;
 945   else if (! STRINGP (re))
 946     return unbind_to (count, Qnil);
 947   else if ((len = fast_looking_at (re, charpos, bytepos, limit, -1, string))
 948            > 0)
 949     {
 950       if (NILP (string))
 951         len = BYTE_TO_CHAR (bytepos + len) - charpos;
 952       else
 953         len = string_byte_to_char (string, bytepos + len) - charpos;
 954     }
 955   if (len <= 0)
 956     return unbind_to (count, Qnil);
 957   to = limit = charpos + len;
 958 #ifdef HAVE_WINDOW_SYSTEM
 959   if (FRAME_WINDOW_P (f))
 960     {
 961       font_object = font_range (charpos, &to, win, face, string);
 962       if (! FONT_OBJECT_P (font_object)
 963           || (! NILP (re)
 964               && to < limit
 965               && (fast_looking_at (re, charpos, bytepos, to, -1, string) <= 0)))
 966         return unbind_to (count, Qnil);
 967     }
 968   else
 969 #endif  /* not HAVE_WINDOW_SYSTEM */
 970     font_object = win->frame;
 971   lgstring = Fcomposition_get_gstring (pos, make_number (to), font_object,
 972                                        string);
 973   if (NILP (LGSTRING_ID (lgstring)))
 974     {
 975       Lisp_Object args[6];
 976 
 977       /* Save point as marker before calling out to lisp.  */
 978       if (NILP (string))
 979         {
 980           Lisp_Object m = Fmake_marker ();
 981           set_marker_both (m, Qnil, pt, pt_byte);
 982           record_unwind_protect (restore_point_unwind, m);
 983         }
 984 
 985       args[0] = Vauto_composition_function;
 986       args[1] = AREF (rule, 2);
 987       args[2] = pos;
 988       args[3] = make_number (to);
 989       args[4] = font_object;
 990       args[5] = string;
 991       lgstring = safe_call (6, args);
 992       if (NILP (string))
 993         TEMP_SET_PT_BOTH (pt, pt_byte);
 994     }
 995   return unbind_to (count, lgstring);
 996 }
 997 
 998 static Lisp_Object _work_val;
 999 static int _work_char;
1000 
1001 /* 1 iff the character C is composable.  */
1002 #define CHAR_COMPOSABLE_P(C)                                            \
1003   ((C) == 0x200C || (C) == 0x200D                                       \
1004    || (_work_val = CHAR_TABLE_REF (Vunicode_category_table, (C)),       \
1005        (SYMBOLP (_work_val)                                             \
1006         && (_work_char = SDATA (SYMBOL_NAME (_work_val))[0]) != 'C'     \
1007         && _work_char != 'Z')))
1008 
1009 /* Update cmp_it->stop_pos to the next position after CHARPOS (and
1010    BYTEPOS) where character composition may happen.  If BYTEPOS is
1011    negative, compute it.  ENDPOS is a limit of searching.  If it is
1012    less than CHARPOS, search backward to ENDPOS+1 assuming that
1013    set_iterator_to_next works in reverse order.  In this case, if a
1014    composition closest to CHARPOS is found, set cmp_it->stop_pos to
1015    the last character of the composition.
1016 
1017    If no composition is found, set cmp_it->ch to -2.  If a static
1018    composition is found, set cmp_it->ch to -1.  Otherwise, set
1019    cmp_it->ch to the character that triggers the automatic
1020    composition.  */
1021 
1022 void
1023 composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string)
1024      struct composition_it *cmp_it;
1025      EMACS_INT charpos, bytepos, endpos;
1026      Lisp_Object string;
1027 {
1028   EMACS_INT start, end, c;
1029   Lisp_Object prop, val;
1030   /* This is from forward_to_next_line_start in xdisp.c.  */
1031   const int MAX_NEWLINE_DISTANCE = 500;
1032 
1033   if (charpos < endpos)
1034     {
1035       if (endpos > charpos + MAX_NEWLINE_DISTANCE)
1036         endpos = charpos + MAX_NEWLINE_DISTANCE;
1037     }
1038   else if (endpos < charpos)
1039     {
1040       /* We search backward for a position to check composition.  */
1041       if (endpos < 0)
1042         {
1043           /* But we don't know where to stop the searching.  */
1044           endpos = NILP (string) ? BEGV - 1 : -1;
1045           /* Usually we don't reach ENDPOS because we stop searching
1046              at an uncomposable character (NL, LRE, etc).  */
1047         }
1048     }
1049   cmp_it->id = -1;
1050   cmp_it->ch = -2;
1051   cmp_it->reversed_p = 0;
1052   cmp_it->stop_pos = endpos;
1053   if (charpos == endpos)
1054     return;
1055   /* FIXME: Bidi is not yet handled well in static composition.  */
1056   if (charpos < endpos
1057       && find_composition (charpos, endpos, &start, &end, &prop, string)
1058       && COMPOSITION_VALID_P (start, end, prop))
1059     {
1060       cmp_it->stop_pos = endpos = start;
1061       cmp_it->ch = -1;
1062     }
1063   if (NILP (string))
1064     {
1065       /* A composition never strides over PT.  */
1066       if (PT > charpos)
1067         {
1068           if (PT < endpos)
1069             cmp_it->stop_pos = endpos = PT;
1070         }
1071       else if (PT < charpos && PT > endpos)
1072         {
1073           cmp_it->stop_pos = endpos = PT - 1;
1074         }
1075     }
1076   if (NILP (current_buffer->enable_multibyte_characters)
1077       || NILP (Vauto_composition_mode))
1078     return;
1079   if (bytepos < 0)
1080     {
1081       if (NILP (string))
1082         bytepos = CHAR_TO_BYTE (charpos);
1083       else
1084         bytepos = string_char_to_byte (string, charpos);
1085     }
1086 
1087   start = charpos;
1088   if (charpos < endpos)
1089     {
1090       /* Forward search.  */
1091       while (charpos < endpos)
1092         {
1093           if (STRINGP (string))
1094             FETCH_STRING_CHAR_ADVANCE (c, string, charpos, bytepos);
1095           else
1096             FETCH_CHAR_ADVANCE (c, charpos, bytepos);
1097           if (c == '\n')
1098             {
1099               cmp_it->ch = -2;
1100               break;
1101             }
1102           val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1103           if (! NILP (val))
1104             {
1105               Lisp_Object elt;
1106               int ridx;
1107 
1108               for (ridx = 0; CONSP (val); val = XCDR (val), ridx++)
1109                 {
1110                   elt = XCAR (val);
1111                   if (VECTORP (elt) && ASIZE (elt) == 3
1112                       && NATNUMP (AREF (elt, 1))
1113                       && charpos - 1 - XFASTINT (AREF (elt, 1)) >= start)
1114                     break;
1115                 }
1116               if (CONSP (val))
1117                 {
1118                   cmp_it->rule_idx = ridx;
1119                   cmp_it->lookback = XFASTINT (AREF (elt, 1));
1120                   cmp_it->stop_pos = charpos - 1 - cmp_it->lookback;
1121                   cmp_it->ch = c;
1122                   return;
1123                 }
1124             }
1125         }
1126     }
1127   else if (charpos > endpos)
1128     {
1129       /* Search backward for a pattern that may be composed and the
1130          position of (possibly) the last character of the match is
1131          closest to (but not after) START.  The reason for the last
1132          character is that set_iterator_to_next works in reverse order,
1133          and thus we must stop at the last character for composition
1134          check.  */
1135       unsigned char *p;
1136       int len;
1137       /* Limit byte position used in fast_looking_at.  This is the
1138          byte position of the character after START. */
1139       EMACS_INT limit;
1140 
1141       if (NILP (string))
1142         p = BYTE_POS_ADDR (bytepos);
1143       else
1144         p = SDATA (string) + bytepos;
1145       c = STRING_CHAR_AND_LENGTH (p, len);
1146       limit = bytepos + len;
1147       while (CHAR_COMPOSABLE_P (c))
1148         {
1149           val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1150           if (! NILP (val))
1151             {
1152               Lisp_Object elt;
1153               int ridx, back, len;
1154 
1155               for (ridx = 0; CONSP (val); val = XCDR (val), ridx++)
1156                 {
1157                   elt = XCAR (val);
1158                   if (VECTORP (elt) && ASIZE (elt) == 3
1159                       && NATNUMP (AREF (elt, 1))
1160                       && charpos - (back = XFASTINT (AREF (elt, 1))) > endpos)
1161                     {
1162                       EMACS_INT cpos = charpos - back, bpos;
1163 
1164                       if (back == 0)
1165                         bpos = bytepos;
1166                       else
1167                         bpos = (NILP (string) ? CHAR_TO_BYTE (cpos)
1168                                 : string_char_to_byte (string, cpos));
1169                       if (STRINGP (AREF (elt, 0)))
1170                         len = fast_looking_at (AREF (elt, 0), cpos, bpos,
1171                                                start + 1, limit, string);
1172                       else
1173                         len = 1;
1174                       if (len > 0)
1175                         {
1176                           /* Make CPOS point to the last character of
1177                              match.  Note that LEN is byte-length.  */
1178                           if (len > 1)
1179                             {
1180                               bpos += len;
1181                               if (NILP (string))
1182                                 cpos = BYTE_TO_CHAR (bpos) - 1;
1183                               else
1184                                 cpos = string_byte_to_char (string, bpos) - 1;
1185                             }
1186                           back = cpos - (charpos - back);
1187                           if (cmp_it->stop_pos < cpos
1188                               || (cmp_it->stop_pos == cpos
1189                                   && cmp_it->lookback < back))
1190                             {
1191                               cmp_it->rule_idx = ridx;
1192                               cmp_it->stop_pos = cpos;
1193                               cmp_it->ch = c;
1194                               cmp_it->lookback = back;
1195                               cmp_it->nchars = back + 1;
1196                             }
1197                         }
1198                     }
1199                 }
1200             }
1201           if (charpos - 1 == endpos)
1202             break;
1203           if (STRINGP (string))
1204             {
1205               p--, bytepos--;
1206               while (! CHAR_HEAD_P (*p))
1207                 p--, bytepos--;
1208               charpos--;
1209             }
1210           else
1211             {
1212               DEC_BOTH (charpos, bytepos);
1213               p = BYTE_POS_ADDR (bytepos);
1214             }
1215           c = STRING_CHAR (p);
1216         }
1217       if (cmp_it->ch >= 0)
1218         /* We found a position to check.  */
1219         return;
1220       /* Skip all uncomposable characters.  */
1221       if (NILP (string))
1222         {
1223           while (charpos - 1 > endpos && ! CHAR_COMPOSABLE_P (c))
1224             {
1225               DEC_BOTH (charpos, bytepos);
1226               c = FETCH_MULTIBYTE_CHAR (bytepos);
1227             }
1228         }
1229       else
1230         {
1231           while (charpos - 1 > endpos && ! CHAR_COMPOSABLE_P (c))
1232             {
1233               p--;
1234               while (! CHAR_HEAD_P (*p))
1235                 p--;
1236               charpos--;
1237               c = STRING_CHAR (p);
1238             }
1239         }
1240     }
1241   cmp_it->stop_pos = charpos;
1242 }
1243 
1244 /* Check if the character at CHARPOS (and BYTEPOS) is composed
1245    (possibly with the following characters) on window W.  ENDPOS limits
1246    characters to be composed.  FACE, in non-NULL, is a base face of
1247    the character.  If STRING is not nil, it is a string containing the
1248    character to check, and CHARPOS and BYTEPOS are indices in the
1249    string.  In that case, FACE must not be NULL.
1250 
1251    If the character is composed, setup members of CMP_IT (id, nglyphs,
1252    from, to, reversed_p), and return 1.  Otherwise, update
1253    CMP_IT->stop_pos, and return 0.  */
1254 
1255 int
1256 composition_reseat_it (cmp_it, charpos, bytepos, endpos, w, face, string)
1257      struct composition_it *cmp_it;
1258      EMACS_INT charpos, bytepos, endpos;
1259      struct window *w;
1260      struct face *face;
1261      Lisp_Object string;
1262 {
1263   if (endpos <= charpos)
1264     {
1265       if (NILP (string))
1266         {
1267           if (endpos < 0)
1268             endpos = BEGV;
1269           if (endpos < PT && PT < charpos) 
1270             endpos = PT;
1271         }
1272       else if (endpos < 0)
1273         endpos = 0;
1274     }
1275   else
1276     {
1277       if (NILP (string) && charpos < PT && PT < endpos)
1278         endpos = PT;
1279     }
1280 
1281   if (cmp_it->ch == -2)
1282     {
1283       composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string);
1284       if (cmp_it->ch == -2 || cmp_it->stop_pos != charpos)
1285         /* The current position is not composed.  */
1286         return 0;
1287     }
1288 
1289   if (cmp_it->ch < 0)
1290     {
1291       /* We are looking at a static composition.  */
1292       EMACS_INT start, end;
1293       Lisp_Object prop;
1294 
1295       find_composition (charpos, -1, &start, &end, &prop, string);
1296       cmp_it->id = get_composition_id (charpos, bytepos, end - start,
1297                                        prop, string);
1298       if (cmp_it->id < 0)
1299         goto no_composition;
1300       cmp_it->nchars = end - start;
1301       cmp_it->nglyphs = composition_table[cmp_it->id]->glyph_len;
1302     }
1303   else if (w)
1304     {
1305       Lisp_Object lgstring = Qnil;
1306       Lisp_Object val, elt, re;
1307       int len, i;
1308 
1309       val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch);
1310       for (i = 0; i < cmp_it->rule_idx; i++, val = XCDR (val));
1311       if (charpos < endpos)
1312         {
1313           for (; CONSP (val); val = XCDR (val))
1314             {
1315               elt = XCAR (val);
1316               if (! VECTORP (elt) || ASIZE (elt) != 3
1317                   || ! INTEGERP (AREF (elt, 1)))
1318                 continue;
1319               if (XFASTINT (AREF (elt, 1)) != cmp_it->lookback)
1320                 goto no_composition;              
1321               lgstring = autocmp_chars (elt, charpos, bytepos, endpos,
1322                                         w, face, string);
1323               if (composition_gstring_p (lgstring))
1324                 break;
1325               lgstring = Qnil;
1326               /* Composition failed perhaps because the font doesn't
1327                  support sufficient range of characters.  Try the
1328                  other composition rules if any.  */
1329             }
1330           cmp_it->reversed_p = 0;
1331         }
1332       else
1333         {
1334           EMACS_INT cpos = charpos, bpos = bytepos;
1335 
1336           while (1)
1337             {
1338               elt = XCAR (val);
1339               if (cmp_it->lookback > 0)
1340                 {
1341                   cpos -= cmp_it->lookback;
1342                   if (STRINGP (string))
1343                     bpos = string_char_to_byte (string, cpos);
1344                   else
1345                     bpos = CHAR_TO_BYTE (cpos);
1346                 }
1347               lgstring = autocmp_chars (elt, cpos, bpos, charpos + 1, w, face,
1348                                         string);
1349               if (composition_gstring_p (lgstring)
1350                   && cpos + LGSTRING_CHAR_LEN (lgstring) - 1 == charpos)
1351                 break;
1352               /* Composition failed or didn't cover the current
1353                  character.  */
1354               if (cmp_it->lookback == 0)
1355                 goto no_composition;
1356               lgstring = Qnil;
1357               /* Try to find a shorter compostion that starts after CPOS.  */
1358               composition_compute_stop_pos (cmp_it, charpos, bytepos, cpos,
1359                                             string);
1360               if (cmp_it->ch == -2 || cmp_it->stop_pos < charpos)
1361                 goto no_composition;
1362               val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch);
1363               for (i = 0; i < cmp_it->rule_idx; i++, val = XCDR (val));
1364             }
1365           cmp_it->reversed_p = 1;
1366         }
1367       if (NILP (lgstring))
1368         goto no_composition;
1369       if (NILP (LGSTRING_ID (lgstring)))
1370         lgstring = composition_gstring_put_cache (lgstring, -1);
1371       cmp_it->id = XINT (LGSTRING_ID (lgstring));
1372       for (i = 0; i < LGSTRING_GLYPH_LEN (lgstring); i++)
1373         if (NILP (LGSTRING_GLYPH (lgstring, i)))
1374           break;
1375       cmp_it->nglyphs = i;
1376       cmp_it->from = 0;
1377       cmp_it->to = i;
1378     }
1379   else
1380     goto no_composition;
1381   return 1;
1382 
1383  no_composition:
1384   if (charpos == endpos)
1385     return 0;
1386   if (charpos < endpos)
1387     {
1388       charpos++;
1389       if (NILP (string))
1390         INC_POS (bytepos);
1391       else
1392         bytepos += MULTIBYTE_FORM_LENGTH (SDATA (string) + bytepos, 0);
1393     }
1394   else
1395     {
1396       charpos--;
1397       /* BYTEPOS is calculated in composition_compute_stop_pos */
1398       bytepos = -1;
1399     }
1400   composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string);
1401   return 0;
1402 }
1403 
1404 /* Update charpos, nchars, nbytes, and width of the current grapheme
1405    cluster.
1406 
1407    If the composition is static or automatic in L2R context, the
1408    cluster is identified by CMP_IT->from, and CHARPOS is the position
1409    of the first character of the cluster.  In this case, update
1410    CMP_IT->to too.
1411 
1412    If the composition is automatic in R2L context, the cluster is
1413    identified by CMP_IT->to, and CHARPOS is the position of the last
1414    character of the cluster.  In this case, update CMP_IT->from too.
1415 
1416    The return value is the character code of the first character of
1417    the cluster, or -1 if the composition is somehow broken.  */
1418 
1419 int
1420 composition_update_it (cmp_it, charpos, bytepos, string)
1421      struct composition_it *cmp_it;
1422      EMACS_INT charpos, bytepos;
1423      Lisp_Object string;
1424 {
1425   int i, c;
1426 
1427   if (cmp_it->ch < 0)
1428     {
1429       /* static composition */
1430       struct composition *cmp = composition_table[cmp_it->id];
1431 
1432       cmp_it->charpos = charpos;
1433       cmp_it->to = cmp_it->nglyphs;
1434       if (cmp_it->nglyphs == 0)
1435         c = -1;
1436       else
1437         {
1438           for (i = 0; i < cmp->glyph_len; i++)
1439             if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
1440               break;
1441           if (c == '\t')
1442             c = ' ';
1443         }
1444       cmp_it->width = cmp->width;
1445       charpos += cmp_it->nchars;
1446       if (STRINGP (string))
1447         cmp_it->nbytes = string_char_to_byte (string, charpos) - bytepos;
1448       else
1449         cmp_it->nbytes = CHAR_TO_BYTE (charpos) - bytepos;
1450     }
1451   else
1452     {
1453       /* automatic composition */
1454       Lisp_Object gstring = composition_gstring_from_id (cmp_it->id);
1455       Lisp_Object glyph;
1456       int from, to;
1457 
1458       if (cmp_it->nglyphs == 0)
1459         {
1460           cmp_it->nchars = LGSTRING_CHAR_LEN (gstring);
1461           cmp_it->width = 0;
1462           cmp_it->from = cmp_it->to = 0;
1463           return -1;
1464         }
1465       if (! cmp_it->reversed_p)
1466         {
1467           glyph = LGSTRING_GLYPH (gstring, cmp_it->from);
1468           from = LGLYPH_FROM (glyph);
1469           for (cmp_it->to = cmp_it->from + 1; cmp_it->to < cmp_it->nglyphs;
1470                cmp_it->to++)
1471             {
1472               glyph = LGSTRING_GLYPH (gstring, cmp_it->to);
1473               if (LGLYPH_FROM (glyph) != from)
1474                 break;
1475             }
1476           cmp_it->charpos = charpos;
1477         }
1478       else
1479         {
1480           glyph = LGSTRING_GLYPH (gstring, cmp_it->to - 1);
1481           from = LGLYPH_FROM (glyph);
1482           cmp_it->charpos = charpos - (LGLYPH_TO (glyph) - from);
1483           for (cmp_it->from = cmp_it->to - 1; cmp_it->from > 0;
1484                cmp_it->from--)
1485             {
1486               glyph = LGSTRING_GLYPH (gstring, cmp_it->from - 1);
1487               if (LGLYPH_FROM (glyph) != from)
1488                 break;
1489             }
1490         }
1491       glyph = LGSTRING_GLYPH (gstring, cmp_it->from);
1492       cmp_it->nchars = LGLYPH_TO (glyph) + 1 - from;
1493       cmp_it->nbytes = 0;
1494       cmp_it->width = 0;
1495       for (i = cmp_it->nchars - 1; i >= 0; i--)
1496         {
1497           c = XINT (LGSTRING_CHAR (gstring, i));
1498           cmp_it->nbytes += CHAR_BYTES (c);
1499           cmp_it->width = (LGLYPH_WIDTH (glyph) > 0
1500                            ? CHAR_WIDTH (LGLYPH_CHAR (glyph)) : 0);
1501         }
1502     }
1503   return c;
1504 }
1505 
1506 
1507 struct position_record
1508 {
1509   EMACS_INT pos, pos_byte;
1510   unsigned char *p;
1511 };
1512 
1513 /* Update the members of POSITION to the next character boundary.  */
1514 #define FORWARD_CHAR(POSITION, STOP)                                    \
1515   do {                                                                  \
1516     (POSITION).pos++;                                                   \
1517     if ((POSITION).pos == (STOP))                                       \
1518       {                                                                 \
1519         (POSITION).p = GAP_END_ADDR;                                    \
1520         (POSITION).pos_byte = GPT_BYTE;                                 \
1521       }                                                                 \
1522     else                                                                \
1523       {                                                                 \
1524         (POSITION).pos_byte += BYTES_BY_CHAR_HEAD (*((POSITION).p));    \
1525         (POSITION).p += BYTES_BY_CHAR_HEAD (*((POSITION).p));           \
1526       }                                                                 \
1527   } while (0)
1528 
1529 /* Update the members of POSITION to the previous character boundary.  */
1530 #define BACKWARD_CHAR(POSITION, STOP)           \
1531   do {                                          \
1532     if ((POSITION).pos == STOP)                 \
1533       (POSITION).p = GPT_ADDR;                  \
1534     do {                                        \
1535       (POSITION).pos_byte--;                    \
1536       (POSITION).p--;                           \
1537     } while (! CHAR_HEAD_P (*((POSITION).p)));  \
1538     (POSITION).pos--;                           \
1539   } while (0)
1540 
1541 /* This is like find_composition, but find an automatic composition
1542    instead.  If found, set *GSTRING to the glyph-string representing
1543    the composition, and return 1.  Otherwise, return 0.  */
1544 
1545 static int
1546 find_automatic_composition (pos, limit, start, end, gstring, string)
1547      EMACS_INT pos, limit, *start, *end;
1548      Lisp_Object *gstring, string;
1549 {
1550   EMACS_INT head, tail, stop;
1551   /* Limit to check a composition after POS.  */
1552   EMACS_INT fore_check_limit;
1553   struct position_record orig, cur, check, prev;
1554   Lisp_Object check_val, val, elt;
1555   int check_lookback;
1556   int c;
1557   Lisp_Object window;
1558   struct window *w;
1559 
1560   window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
1561   if (NILP (window))
1562     return 0;
1563   w = XWINDOW (window);
1564 
1565   orig.pos = pos;
1566   if (NILP (string))
1567     {
1568       head = BEGV, tail = ZV, stop = GPT;
1569       orig.pos_byte = CHAR_TO_BYTE (orig.pos);
1570       orig.p = BYTE_POS_ADDR (orig.pos_byte);
1571     }
1572   else
1573     {
1574       head = 0, tail = SCHARS (string), stop = -1;
1575       orig.pos_byte = string_char_to_byte (string, orig.pos);
1576       orig.p = SDATA (string) + orig.pos_byte;
1577     }
1578   if (limit < pos)
1579     fore_check_limit = min (tail, pos + MAX_AUTO_COMPOSITION_LOOKBACK);
1580   else
1581     fore_check_limit = min (tail, limit + MAX_AUTO_COMPOSITION_LOOKBACK);
1582   cur = orig;
1583 
1584  retry:
1585   check_val = Qnil;
1586   /* At first, check if POS is composable.  */
1587   c = STRING_CHAR (cur.p);
1588   if (! CHAR_COMPOSABLE_P (c))
1589     {
1590       if (limit < 0)
1591         return 0;
1592       if (limit >= cur.pos)
1593         goto search_forward;
1594     }
1595   else
1596     {
1597       val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1598       if (! NILP (val))
1599         check_val = val, check = cur;
1600       else
1601         while (cur.pos + 1 < fore_check_limit)
1602           {
1603             EMACS_INT b, e;
1604 
1605             FORWARD_CHAR (cur, stop);
1606             if (get_property_and_range (cur.pos, Qcomposition, &val, &b, &e,
1607                                         Qnil)
1608                 && COMPOSITION_VALID_P (b, e, val))
1609               {
1610                 fore_check_limit = cur.pos;
1611                 break;
1612               }
1613             c = STRING_CHAR (cur.p);
1614             if (! CHAR_COMPOSABLE_P (c))
1615               break;
1616             val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1617             if (NILP (val))
1618               continue;
1619             check_val = val, check = cur;
1620             break;
1621           }
1622       cur = orig;
1623     }
1624   /* Rewind back to the position where we can safely search forward
1625      for compositions.  */
1626   while (cur.pos > head)
1627     {
1628       EMACS_INT b, e;
1629 
1630       BACKWARD_CHAR (cur, stop);
1631       if (get_property_and_range (cur.pos, Qcomposition, &val, &b, &e, Qnil)
1632           && COMPOSITION_VALID_P (b, e, val))
1633         break;
1634       c = STRING_CHAR (cur.p);
1635       if (! CHAR_COMPOSABLE_P (c))
1636         break;
1637       val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1638       if (! NILP (val))
1639         check_val = val, check = cur;
1640     }
1641   prev = cur;
1642   /* Now search forward.  */
1643  search_forward:
1644   *gstring = Qnil;
1645   if (! NILP (check_val) || limit >= orig.pos)
1646     {
1647       if (NILP (check_val))
1648         cur = orig;
1649       else
1650         cur = check;
1651       while (cur.pos < fore_check_limit)
1652         {
1653           int need_adjustment = 0;
1654 
1655           if (NILP (check_val))
1656             {
1657               c = STRING_CHAR (cur.p);
1658               check_val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1659             }
1660           for (; CONSP (check_val); check_val = XCDR (check_val))
1661             {
1662               elt = XCAR (check_val);
1663               if (VECTORP (elt) && ASIZE (elt) == 3 && NATNUMP (AREF (elt, 1))
1664                   && cur.pos - XFASTINT (AREF (elt, 1)) >= head)
1665                 {
1666                   check.pos = cur.pos - XFASTINT (AREF (elt, 1));
1667                   if (check.pos == cur.pos)
1668                     check.pos_byte = cur.pos_byte;
1669                   else
1670                     check.pos_byte = CHAR_TO_BYTE (check.pos);
1671                   val = autocmp_chars (elt, check.pos, check.pos_byte,
1672                                        tail, w, NULL, string);
1673                   need_adjustment = 1;
1674                   if (! NILP (val))
1675                     {
1676                       *gstring = val;
1677                       *start = check.pos;
1678                       *end = check.pos + LGSTRING_CHAR_LEN (*gstring);
1679                       if (*start <= orig.pos ? *end > orig.pos
1680                           : limit >= orig.pos)
1681                         return 1;
1682                       cur.pos = *end;
1683                       cur.pos_byte = CHAR_TO_BYTE (cur.pos);
1684                       break;
1685                     }
1686                 }
1687             }
1688           if (need_adjustment)
1689             {
1690               /* As we have called Lisp, there's a possibility that
1691                  buffer/string is relocated.  */
1692               if (NILP (string))
1693                 cur.p  = BYTE_POS_ADDR (cur.pos_byte);
1694               else
1695                 cur.p = SDATA (string) + cur.pos_byte;
1696             }
1697           if (! CONSP (check_val))
1698             FORWARD_CHAR (cur, stop);
1699           check_val = Qnil;
1700         }
1701     }
1702   if (! NILP (*gstring))
1703     return (limit >= 0 || (*start <= orig.pos && *end > orig.pos));
1704   if (limit >= 0 && limit < orig.pos && prev.pos > head)
1705     {
1706       cur = prev;
1707       BACKWARD_CHAR (cur, stop);
1708       orig = cur;
1709       fore_check_limit = orig.pos;
1710       goto retry;
1711     }
1712   return 0;
1713 }
1714 
1715 /* Return the adjusted point provided that point is moved from LAST_PT
1716    to NEW_PT.  */
1717 
1718 int
1719 composition_adjust_point (last_pt, new_pt)
1720      EMACS_INT last_pt, new_pt;
1721 {
1722   EMACS_INT charpos, bytepos, startpos, beg, end, pos;
1723   Lisp_Object val;
1724   int i;
1725 
1726   if (new_pt == BEGV || new_pt == ZV)
1727     return new_pt;
1728 
1729   /* At first check the static composition. */
1730   if (get_property_and_range (new_pt, Qcomposition, &val, &beg, &end, Qnil)
1731       && COMPOSITION_VALID_P (beg, end, val))
1732     {
1733       if (beg < new_pt /* && end > new_pt   <- It's always the case.  */
1734           && (last_pt <= beg || last_pt >= end))
1735         return (new_pt < last_pt ? beg : end);
1736       return new_pt;
1737     }
1738 
1739   if (NILP (current_buffer->enable_multibyte_characters)
1740       || NILP (Vauto_composition_mode))
1741     return new_pt;
1742 
1743   /* Next check the automatic composition.  */
1744   if (! find_automatic_composition (new_pt, (EMACS_INT) -1, &beg, &end, &val,
1745                                     Qnil)
1746       || beg == new_pt)
1747     return new_pt;
1748   for (i = 0; i < LGSTRING_GLYPH_LEN (val); i++)
1749     {
1750       Lisp_Object glyph = LGSTRING_GLYPH (val, i);
1751 
1752       if (NILP (glyph))
1753         break;
1754       if (beg + LGLYPH_FROM (glyph) == new_pt)
1755         return new_pt;
1756       if (beg + LGLYPH_TO (glyph) >= new_pt)
1757         return (new_pt < last_pt
1758                 ? beg + LGLYPH_FROM (glyph)
1759                 : beg + LGLYPH_TO (glyph) + 1);
1760     }
1761   return new_pt;
1762 }
1763 
1764 DEFUN ("composition-get-gstring", Fcomposition_get_gstring,
1765        Scomposition_get_gstring, 4, 4, 0,
1766        doc: /* Return a glyph-string for characters between FROM and TO.
1767 If the glyph string is for graphic display, FONT-OBJECT must be
1768 a font-object to use for those characters.
1769 Otherwise (for terminal display), FONT-OBJECT must be a terminal ID, a
1770 frame, or nil for the selected frame's terminal device.
1771 
1772 If the optional 4th argument STRING is not nil, it is a string
1773 containing the target characters between indices FROM and TO.
1774 
1775 A glyph-string is a vector containing information about how to display
1776 a specific character sequence.  The format is:
1777    [HEADER ID GLYPH ...]
1778 
1779 HEADER is a vector of this form:
1780     [FONT-OBJECT CHAR ...]
1781 where
1782     FONT-OBJECT is a font-object for all glyphs in the glyph-string,
1783     or the terminal coding system of the specified terminal.
1784     CHARs are characters to be composed by GLYPHs.
1785 
1786 ID is an identification number of the glyph-string.  It may be nil if
1787 not yet shaped.
1788 
1789 GLYPH is a vector whose elements have this form:
1790     [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
1791       [ [X-OFF Y-OFF WADJUST] | nil] ]
1792 where
1793     FROM-IDX and TO-IDX are used internally and should not be touched.
1794     C is the character of the glyph.
1795     CODE is the glyph-code of C in FONT-OBJECT.
1796     WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
1797     X-OFF and Y-OFF are offsets to the base position for the glyph.
1798     WADJUST is the adjustment to the normal width of the glyph.
1799 
1800 If GLYPH is nil, the remaining elements of the glyph-string vector
1801 should be ignored.  */)
1802      (from, to, font_object, string)
1803      Lisp_Object font_object, from, to, string;
1804 {
1805   Lisp_Object gstring, header;
1806   EMACS_INT frompos, topos;
1807 
1808   CHECK_NATNUM (from);
1809   CHECK_NATNUM (to);
1810   if (XINT (to) > XINT (from) + MAX_COMPOSITION_COMPONENTS)
1811     to = make_number (XINT (from) + MAX_COMPOSITION_COMPONENTS);
1812   if (! FONT_OBJECT_P (font_object))
1813     {
1814       struct coding_system *coding;
1815       struct terminal *terminal = get_terminal (font_object, 1);
1816 
1817       coding = ((TERMINAL_TERMINAL_CODING (terminal)->common_flags
1818                  & CODING_REQUIRE_ENCODING_MASK)
1819                 ? TERMINAL_TERMINAL_CODING (terminal) : &safe_terminal_coding);
1820       font_object = CODING_ID_NAME (coding->id);
1821     }
1822 
1823   header = fill_gstring_header (Qnil, from, to, font_object, string);
1824   gstring = gstring_lookup_cache (header);
1825   if (! NILP (gstring))
1826     return gstring;
1827 
1828   frompos = XINT (from);
1829   topos = XINT (to);
1830   if (LGSTRING_GLYPH_LEN (gstring_work) < topos - frompos)
1831     gstring_work = Fmake_vector (make_number (topos - frompos + 2), Qnil);
1832   LGSTRING_SET_HEADER (gstring_work, header);
1833   LGSTRING_SET_ID (gstring_work, Qnil);
1834   fill_gstring_body (gstring_work);
1835   return gstring_work;
1836 }
1837 
1838 
1839 /* Emacs Lisp APIs.  */
1840 
1841 DEFUN ("compose-region-internal", Fcompose_region_internal,
1842        Scompose_region_internal, 2, 4, 0,
1843        doc: /* Internal use only.
1844 
1845 Compose text in the region between START and END.
1846 Optional 3rd and 4th arguments are COMPONENTS and MODIFICATION-FUNC
1847 for the composition.  See `compose-region' for more details.  */)
1848      (start, end, components, modification_func)
1849      Lisp_Object start, end, components, modification_func;
1850 {
1851   validate_region (&start, &end);
1852   if (!NILP (components)
1853       && !INTEGERP (components)
1854       && !CONSP (components)
1855       && !STRINGP (components))
1856     CHECK_VECTOR (components);
1857 
1858   compose_text (XINT (start), XINT (end), components, modification_func, Qnil);
1859   return Qnil;
1860 }
1861 
1862 DEFUN ("compose-string-internal", Fcompose_string_internal,
1863        Scompose_string_internal, 3, 5, 0,
1864        doc: /* Internal use only.
1865 
1866 Compose text between indices START and END of STRING.
1867 Optional 4th and 5th arguments are COMPONENTS and MODIFICATION-FUNC
1868 for the composition.  See `compose-string' for more details.  */)
1869      (string, start, end, components, modification_func)
1870      Lisp_Object string, start, end, components, modification_func;
1871 {
1872   CHECK_STRING (string);
1873   CHECK_NUMBER (start);
1874   CHECK_NUMBER (end);
1875 
1876   if (XINT (start) < 0 ||
1877       XINT (start) > XINT (end)
1878       || XINT (end) > SCHARS (string))
1879     args_out_of_range (start, end);
1880 
1881   compose_text (XINT (start), XINT (end), components, modification_func, string);
1882   return string;
1883 }
1884 
1885 DEFUN ("find-composition-internal", Ffind_composition_internal,
1886        Sfind_composition_internal, 4, 4, 0,
1887        doc: /* Internal use only.
1888 
1889 Return information about composition at or nearest to position POS.
1890 See `find-composition' for more details.  */)
1891      (pos, limit, string, detail_p)
1892      Lisp_Object pos, limit, string, detail_p;
1893 {
1894   Lisp_Object prop, tail, gstring;
1895   EMACS_INT start, end, from, to;
1896   int id;
1897 
1898   CHECK_NUMBER_COERCE_MARKER (pos);
1899   from = XINT (pos);
1900   if (!NILP (limit))
1901     {
1902       CHECK_NUMBER_COERCE_MARKER (limit);
1903       to = XINT (limit);
1904     }
1905   else
1906     to = -1;
1907 
1908   if (!NILP (string))
1909     {
1910       CHECK_STRING (string);
1911       if (XINT (pos) < 0 || XINT (pos) > SCHARS (string))
1912         args_out_of_range (string, pos);
1913     }
1914   else
1915     {
1916       if (XINT (pos) < BEGV || XINT (pos) > ZV)
1917         args_out_of_range (Fcurrent_buffer (), pos);
1918     }
1919 
1920   if (!find_composition (from, to, &start, &end, &prop, string))
1921     {
1922       if (!NILP (current_buffer->enable_multibyte_characters)
1923           && ! NILP (Vauto_composition_mode)
1924           && find_automatic_composition (from, to, &start, &end, &gstring,
1925                                          string))
1926         return list3 (make_number (start), make_number (end), gstring);
1927       return Qnil;
1928     }
1929   if ((end <= XINT (pos) || start > XINT (pos)))
1930     {
1931       EMACS_INT s, e;
1932 
1933       if (find_automatic_composition (from, to, &s, &e, &gstring, string)
1934           && (e <= XINT (pos) ? e > end : s < start))
1935         return list3 (make_number (s), make_number (e), gstring);
1936     }
1937   if (!COMPOSITION_VALID_P (start, end, prop))
1938     return Fcons (make_number (start), Fcons (make_number (end),
1939                                               Fcons (Qnil, Qnil)));
1940   if (NILP (detail_p))
1941     return Fcons (make_number (start), Fcons (make_number (end),
1942                                               Fcons (Qt, Qnil)));
1943 
1944   if (COMPOSITION_REGISTERD_P (prop))
1945     id = COMPOSITION_ID (prop);
1946   else
1947     {
1948       int start_byte = (NILP (string)
1949                         ? CHAR_TO_BYTE (start)
1950                         : string_char_to_byte (string, start));
1951       id = get_composition_id (start, start_byte, end - start, prop, string);
1952     }
1953 
1954   if (id >= 0)
1955     {
1956       Lisp_Object components, relative_p, mod_func;
1957       enum composition_method method = COMPOSITION_METHOD (prop);
1958       int width = composition_table[id]->width;
1959 
1960       components = Fcopy_sequence (COMPOSITION_COMPONENTS (prop));
1961       relative_p = (method == COMPOSITION_WITH_RULE_ALTCHARS
1962                     ? Qnil : Qt);
1963       mod_func = COMPOSITION_MODIFICATION_FUNC (prop);
1964       tail = Fcons (components,
1965                     Fcons (relative_p,
1966                            Fcons (mod_func,
1967                                   Fcons (make_number (width), Qnil))));
1968     }
1969   else
1970     tail = Qnil;
1971 
1972   return Fcons (make_number (start), Fcons (make_number (end), tail));
1973 }
1974 
1975 
1976 void
1977 syms_of_composite ()
1978 {
1979   int i;
1980 
1981   Qcomposition = intern_c_string ("composition");
1982   staticpro (&Qcomposition);
1983 
1984   /* Make a hash table for static composition.  */
1985   {
1986     Lisp_Object args[6];
1987     extern Lisp_Object QCsize;
1988 
1989     args[0] = QCtest;
1990     args[1] = Qequal;
1991     args[2] = QCweakness;
1992     /* We used to make the hash table weak so that unreferenced
1993        compositions can be garbage-collected.  But, usually once
1994        created compositions are repeatedly used in an Emacs session,
1995        and thus it's not worth to save memory in such a way.  So, we
1996        make the table not weak.  */
1997     args[3] = Qnil;
1998     args[4] = QCsize;
1999     args[5] = make_number (311);
2000     composition_hash_table = Fmake_hash_table (6, args);
2001     staticpro (&composition_hash_table);
2002   }
2003 
2004   /* Make a hash table for glyph-string.  */
2005   {
2006     Lisp_Object args[6];
2007     extern Lisp_Object QCsize;
2008 
2009     args[0] = QCtest;
2010     args[1] = Qequal;
2011     args[2] = QCweakness;
2012     args[3] = Qnil;
2013     args[4] = QCsize;
2014     args[5] = make_number (311);
2015     gstring_hash_table = Fmake_hash_table (6, args);
2016     staticpro (&gstring_hash_table);
2017   }
2018 
2019   staticpro (&gstring_work_headers);
2020   gstring_work_headers = Fmake_vector (make_number (8), Qnil);
2021   for (i = 0; i < 8; i++)
2022     ASET (gstring_work_headers, i, Fmake_vector (make_number (i + 2), Qnil));
2023   staticpro (&gstring_work);
2024   gstring_work = Fmake_vector (make_number (10), Qnil);
2025 
2026   /* Text property `composition' should be nonsticky by default.  */
2027   Vtext_property_default_nonsticky
2028     = Fcons (Fcons (Qcomposition, Qt), Vtext_property_default_nonsticky);
2029 
2030   DEFVAR_LISP ("compose-chars-after-function", &Vcompose_chars_after_function,
2031                doc: /* Function to adjust composition of buffer text.
2032 
2033 This function is called with three arguments: FROM, TO, and OBJECT.
2034 FROM and TO specify the range of text whose composition should be
2035 adjusted.  OBJECT, if non-nil, is a string that contains the text.
2036 
2037 This function is called after a text with `composition' property is
2038 inserted or deleted to keep `composition' property of buffer text
2039 valid.
2040 
2041 The default value is the function `compose-chars-after'.  */);
2042   Vcompose_chars_after_function = intern_c_string ("compose-chars-after");
2043 
2044   Qauto_composed = intern_c_string ("auto-composed");
2045   staticpro (&Qauto_composed);
2046 
2047   Qauto_composition_function = intern_c_string ("auto-composition-function");
2048   staticpro (&Qauto_composition_function);
2049 
2050   DEFVAR_LISP ("auto-composition-mode", &Vauto_composition_mode,
2051                doc: /* Non-nil if Auto-Composition mode is enabled.
2052 Use the command `auto-composition-mode' to change this variable. */);
2053   Vauto_composition_mode = Qt;
2054 
2055   DEFVAR_LISP ("auto-composition-function", &Vauto_composition_function,
2056                doc: /* Function to call to compose characters automatically.
2057 This function is called from the display routine with four arguments:
2058 FROM, TO, WINDOW, and STRING.
2059 
2060 If STRING is nil, the function must compose characters in the region
2061 between FROM and TO in the current buffer.
2062 
2063 Otherwise, STRING is a string, and FROM and TO are indices into the
2064 string.  In this case, the function must compose characters in the
2065 string.  */);
2066   Vauto_composition_function = Qnil;
2067 
2068   DEFVAR_LISP ("composition-function-table", &Vcomposition_function_table,
2069                doc: /* Char-table of functions for automatic character composition.
2070 For each character that has to be composed automatically with
2071 preceding and/or following characters, this char-table contains
2072 a function to call to compose that character.
2073 
2074 The element at index C in the table, if non-nil, is a list of
2075 composition rules of this form: ([PATTERN PREV-CHARS FUNC] ...)
2076 
2077 PATTERN is a regular expression which C and the surrounding
2078 characters must match.
2079 
2080 PREV-CHARS is a non-negative integer (less than 4) specifying how many
2081 characters before C to check the matching with PATTERN.  If it is 0,
2082 PATTERN must match C and the following characters.  If it is 1,
2083 PATTERN must match a character before C and the following characters.
2084 
2085 If PREV-CHARS is 0, PATTERN can be nil, which means that the
2086 single character C should be composed.
2087 
2088 FUNC is a function to return a glyph-string representing a
2089 composition of the characters that match PATTERN.  It is
2090 called with one argument GSTRING.
2091 
2092 GSTRING is a template of a glyph-string to return.  It is already
2093 filled with a proper header for the characters to compose, and
2094 glyphs corresponding to those characters one by one.  The
2095 function must return a new glyph-string with the same header as
2096 GSTRING, or modify GSTRING itself and return it.
2097 
2098 See also the documentation of `auto-composition-mode'.  */);
2099   Vcomposition_function_table = Fmake_char_table (Qnil, Qnil);
2100 
2101   defsubr (&Scompose_region_internal);
2102   defsubr (&Scompose_string_internal);
2103   defsubr (&Sfind_composition_internal);
2104   defsubr (&Scomposition_get_gstring);
2105 }
2106 
2107 /* arch-tag: 79cefaf8-ca48-4eed-97e5-d5afb290d272
2108    (do not change this comment) */