(eshell-parse-argument-hook): Put `number' property on entire argument
[emacs.git] / src / composite.c
blobcd84f3932b05ed2ebc87f75429c9a0456008efaa
1 /* Composite sequence support.
2 Copyright (C) 2001, 2002, 2003, 2004, 2005,
3 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
4 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
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
11 This file is part of GNU Emacs.
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.
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.
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/>. */
26 #include <config.h>
27 #include "lisp.h"
28 #include "buffer.h"
29 #include "character.h"
30 #include "coding.h"
31 #include "intervals.h"
32 #include "window.h"
33 #include "frame.h"
34 #include "dispextern.h"
35 #include "font.h"
36 #include "termhooks.h"
39 /* Emacs uses special text property `composition' to support character
40 composition. A sequence of characters that have the same (i.e. eq)
41 `composition' property value is treated as a single composite
42 sequence (we call it just `composition' here after). Characters in
43 a composition are all composed somehow on the screen.
45 The property value has this form when the composition is made:
46 ((LENGTH . COMPONENTS) . MODIFICATION-FUNC)
47 then turns to this form:
48 (COMPOSITION-ID . (LENGTH COMPONENTS-VEC . MODIFICATION-FUNC))
49 when the composition is registered in composition_hash_table and
50 composition_table. These rather peculiar structures were designed
51 to make it easy to distinguish them quickly (we can do that by
52 checking only the first element) and to extract LENGTH (from the
53 former form) and COMPOSITION-ID (from the latter form).
55 We register a composition when it is displayed, or when the width
56 is required (for instance, to calculate columns).
58 LENGTH -- Length of the composition. This information is used to
59 check the validity of the composition.
61 COMPONENTS -- Character, string, vector, list, or nil.
63 If it is nil, characters in the text are composed relatively
64 according to their metrics in font glyphs.
66 If it is a character or a string, the character or characters
67 in the string are composed relatively.
69 If it is a vector or list of integers, the element is a
70 character or an encoded composition rule. The characters are
71 composed according to the rules. (2N)th elements are
72 characters to be composed and (2N+1)th elements are
73 composition rules to tell how to compose (2N+2)th element with
74 the previously composed 2N glyphs.
76 COMPONENTS-VEC -- Vector of integers. In relative composition, the
77 elements are characters to be composed. In rule-base
78 composition, the elements are characters or encoded
79 composition rules.
81 MODIFICATION-FUNC -- If non nil, it is a function to call when the
82 composition gets invalid after a modification in a buffer. If
83 it is nil, a function in `composition-function-table' of the
84 first character in the sequence is called.
86 COMPOSITION-ID --Identification number of the composition. It is
87 used as an index to composition_table for the composition.
89 When Emacs has to display a composition or has to know its
90 displaying width, the function get_composition_id is called. It
91 returns COMPOSITION-ID so that the caller can access the
92 information about the composition through composition_table. If a
93 COMPOSITION-ID has not yet been assigned to the composition,
94 get_composition_id checks the validity of `composition' property,
95 and, if valid, assigns a new ID, registers the information in
96 composition_hash_table and composition_table, and changes the form
97 of the property value. If the property is invalid, return -1
98 without changing the property value.
100 We use two tables to keep information about composition;
101 composition_hash_table and composition_table.
103 The former is a hash table in which keys are COMPONENTS-VECs and
104 values are the corresponding COMPOSITION-IDs. This hash table is
105 weak, but as each key (COMPONENTS-VEC) is also kept as a value of the
106 `composition' property, it won't be collected as garbage until all
107 bits of text that have the same COMPONENTS-VEC are deleted.
109 The latter is a table of pointers to `struct composition' indexed
110 by COMPOSITION-ID. This structure keeps the other information (see
111 composite.h).
113 In general, a text property holds information about individual
114 characters. But, a `composition' property holds information about
115 a sequence of characters (in this sense, it is like the `intangible'
116 property). That means that we should not share the property value
117 in adjacent compositions -- we can't distinguish them if they have the
118 same property. So, after any changes, we call
119 `update_compositions' and change a property of one of adjacent
120 compositions to a copy of it. This function also runs a proper
121 composition modification function to make a composition that gets
122 invalid by the change valid again.
124 As the value of the `composition' property holds information about a
125 specific range of text, the value gets invalid if we change the
126 text in the range. We treat the `composition' property as always
127 rear-nonsticky (currently by setting default-text-properties to
128 (rear-nonsticky (composition))) and we never make properties of
129 adjacent compositions identical. Thus, any such changes make the
130 range just shorter. So, we can check the validity of the `composition'
131 property by comparing LENGTH information with the actual length of
132 the composition.
137 Lisp_Object Qcomposition;
139 /* Table of pointers to the structure `composition' indexed by
140 COMPOSITION-ID. This structure is for storing information about
141 each composition except for COMPONENTS-VEC. */
142 struct composition **composition_table;
144 /* The current size of `composition_table'. */
145 static int composition_table_size;
147 /* Number of compositions currently made. */
148 int n_compositions;
150 /* Hash table for compositions. The key is COMPONENTS-VEC of
151 `composition' property. The value is the corresponding
152 COMPOSITION-ID. */
153 Lisp_Object composition_hash_table;
155 /* Function to call to adjust composition. */
156 Lisp_Object Vcompose_chars_after_function;
158 Lisp_Object Qauto_composed;
159 Lisp_Object Vauto_composition_function;
160 Lisp_Object Qauto_composition_function;
161 Lisp_Object Vcomposition_function_table;
163 /* Maxinum number of characters to lookback to check
164 auto-composition. */
165 #define MAX_AUTO_COMPOSITION_LOOKBACK 3
167 EXFUN (Fremove_list_of_text_properties, 4);
169 /* Temporary variable used in macros COMPOSITION_XXX. */
170 Lisp_Object composition_temp;
173 /* Return COMPOSITION-ID of a composition at buffer position
174 CHARPOS/BYTEPOS and length NCHARS. The `composition' property of
175 the sequence is PROP. STRING, if non-nil, is a string that
176 contains the composition instead of the current buffer.
178 If the composition is invalid, return -1. */
181 get_composition_id (charpos, bytepos, nchars, prop, string)
182 int charpos, bytepos, nchars;
183 Lisp_Object prop, string;
185 Lisp_Object id, length, components, key, *key_contents;
186 int glyph_len;
187 struct Lisp_Hash_Table *hash_table = XHASH_TABLE (composition_hash_table);
188 int hash_index;
189 unsigned hash_code;
190 struct composition *cmp;
191 int i, ch;
193 /* PROP should be
194 Form-A: ((LENGTH . COMPONENTS) . MODIFICATION-FUNC)
196 Form-B: (COMPOSITION-ID . (LENGTH COMPONENTS-VEC . MODIFICATION-FUNC))
198 if (nchars == 0 || !CONSP (prop))
199 goto invalid_composition;
201 id = XCAR (prop);
202 if (INTEGERP (id))
204 /* PROP should be Form-B. */
205 if (XINT (id) < 0 || XINT (id) >= n_compositions)
206 goto invalid_composition;
207 return XINT (id);
210 /* PROP should be Form-A.
211 Thus, ID should be (LENGTH . COMPONENTS). */
212 if (!CONSP (id))
213 goto invalid_composition;
214 length = XCAR (id);
215 if (!INTEGERP (length) || XINT (length) != nchars)
216 goto invalid_composition;
218 components = XCDR (id);
220 /* Check if the same composition has already been registered or not
221 by consulting composition_hash_table. The key for this table is
222 COMPONENTS (converted to a vector COMPONENTS-VEC) or, if it is
223 nil, vector of characters in the composition range. */
224 if (INTEGERP (components))
225 key = Fmake_vector (make_number (1), components);
226 else if (STRINGP (components) || CONSP (components))
227 key = Fvconcat (1, &components);
228 else if (VECTORP (components))
229 key = components;
230 else if (NILP (components))
232 key = Fmake_vector (make_number (nchars), Qnil);
233 if (STRINGP (string))
234 for (i = 0; i < nchars; i++)
236 FETCH_STRING_CHAR_ADVANCE (ch, string, charpos, bytepos);
237 XVECTOR (key)->contents[i] = make_number (ch);
239 else
240 for (i = 0; i < nchars; i++)
242 FETCH_CHAR_ADVANCE (ch, charpos, bytepos);
243 XVECTOR (key)->contents[i] = make_number (ch);
246 else
247 goto invalid_composition;
249 hash_index = hash_lookup (hash_table, key, &hash_code);
250 if (hash_index >= 0)
252 /* We have already registered the same composition. Change PROP
253 from Form-A above to Form-B while replacing COMPONENTS with
254 COMPONENTS-VEC stored in the hash table. We can directly
255 modify the cons cell of PROP because it is not shared. */
256 key = HASH_KEY (hash_table, hash_index);
257 id = HASH_VALUE (hash_table, hash_index);
258 XSETCAR (prop, id);
259 XSETCDR (prop, Fcons (make_number (nchars), Fcons (key, XCDR (prop))));
260 return XINT (id);
263 /* This composition is a new one. We must register it. */
265 /* Check if we have sufficient memory to store this information. */
266 if (composition_table_size == 0)
268 composition_table_size = 256;
269 composition_table
270 = (struct composition **) xmalloc (sizeof (composition_table[0])
271 * composition_table_size);
273 else if (composition_table_size <= n_compositions)
275 composition_table_size += 256;
276 composition_table
277 = (struct composition **) xrealloc (composition_table,
278 sizeof (composition_table[0])
279 * composition_table_size);
282 key_contents = XVECTOR (key)->contents;
284 /* Check if the contents of COMPONENTS are valid if COMPONENTS is a
285 vector or a list. It should be a sequence of:
286 char1 rule1 char2 rule2 char3 ... ruleN charN+1 */
288 if (VECTORP (components)
289 && ASIZE (components) >= 2
290 && VECTORP (AREF (components, 0)))
292 /* COMPONENTS is a glyph-string. */
293 int len = ASIZE (key);
295 for (i = 1; i < len; i++)
296 if (! VECTORP (AREF (key, i)))
297 goto invalid_composition;
299 else if (VECTORP (components) || CONSP (components))
301 int len = XVECTOR (key)->size;
303 /* The number of elements should be odd. */
304 if ((len % 2) == 0)
305 goto invalid_composition;
306 /* All elements should be integers (character or encoded
307 composition rule). */
308 for (i = 0; i < len; i++)
310 if (!INTEGERP (key_contents[i]))
311 goto invalid_composition;
315 /* Change PROP from Form-A above to Form-B. We can directly modify
316 the cons cell of PROP because it is not shared. */
317 XSETFASTINT (id, n_compositions);
318 XSETCAR (prop, id);
319 XSETCDR (prop, Fcons (make_number (nchars), Fcons (key, XCDR (prop))));
321 /* Register the composition in composition_hash_table. */
322 hash_index = hash_put (hash_table, key, id, hash_code);
324 /* Register the composition in composition_table. */
325 cmp = (struct composition *) xmalloc (sizeof (struct composition));
327 cmp->method = (NILP (components)
328 ? COMPOSITION_RELATIVE
329 : ((INTEGERP (components) || STRINGP (components))
330 ? COMPOSITION_WITH_ALTCHARS
331 : COMPOSITION_WITH_RULE_ALTCHARS));
332 cmp->hash_index = hash_index;
333 glyph_len = (cmp->method == COMPOSITION_WITH_RULE_ALTCHARS
334 ? (XVECTOR (key)->size + 1) / 2
335 : XVECTOR (key)->size);
336 cmp->glyph_len = glyph_len;
337 cmp->offsets = (short *) xmalloc (sizeof (short) * glyph_len * 2);
338 cmp->font = NULL;
340 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
342 /* Relative composition. */
343 cmp->width = 0;
344 for (i = 0; i < glyph_len; i++)
346 int this_width;
347 ch = XINT (key_contents[i]);
348 this_width = (ch == '\t' ? 1 : CHAR_WIDTH (ch));
349 if (cmp->width < this_width)
350 cmp->width = this_width;
353 else
355 /* Rule-base composition. */
356 float leftmost = 0.0, rightmost;
358 ch = XINT (key_contents[0]);
359 rightmost = ch != '\t' ? CHAR_WIDTH (ch) : 1;
361 for (i = 1; i < glyph_len; i += 2)
363 int rule, gref, nref, xoff, yoff;
364 int this_width;
365 float this_left;
367 rule = XINT (key_contents[i]);
368 ch = XINT (key_contents[i + 1]);
369 this_width = ch != '\t' ? CHAR_WIDTH (ch) : 1;
371 /* A composition rule is specified by an integer value
372 that encodes global and new reference points (GREF and
373 NREF). GREF and NREF are specified by numbers as
374 below:
375 0---1---2 -- ascent
379 9--10--11 -- center
381 ---3---4---5--- baseline
383 6---7---8 -- descent
385 COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
386 this_left = (leftmost
387 + (gref % 3) * (rightmost - leftmost) / 2.0
388 - (nref % 3) * this_width / 2.0);
390 if (this_left < leftmost)
391 leftmost = this_left;
392 if (this_left + this_width > rightmost)
393 rightmost = this_left + this_width;
396 cmp->width = rightmost - leftmost;
397 if (cmp->width < (rightmost - leftmost))
398 /* To get a ceiling integer value. */
399 cmp->width++;
402 composition_table[n_compositions] = cmp;
404 return n_compositions++;
406 invalid_composition:
407 /* Would it be better to remove this `composition' property? */
408 return -1;
412 /* Find a static composition at or nearest to position POS of OBJECT
413 (buffer or string).
415 OBJECT defaults to the current buffer. If there's a composition at
416 POS, set *START and *END to the start and end of the sequence,
417 *PROP to the `composition' property, and return 1.
419 If there's no composition at POS and LIMIT is negative, return 0.
421 Otherwise, search for a composition forward (LIMIT > POS) or
422 backward (LIMIT < POS). In this case, LIMIT bounds the search.
424 If a composition is found, set *START, *END, and *PROP as above,
425 and return 1, else return 0.
427 This doesn't check the validity of composition. */
430 find_composition (pos, limit, start, end, prop, object)
431 int pos, limit;
432 EMACS_INT *start, *end;
433 Lisp_Object *prop, object;
435 Lisp_Object val;
437 if (get_property_and_range (pos, Qcomposition, prop, start, end, object))
438 return 1;
440 if (limit < 0 || limit == pos)
441 return 0;
443 if (limit > pos) /* search forward */
445 val = Fnext_single_property_change (make_number (pos), Qcomposition,
446 object, make_number (limit));
447 pos = XINT (val);
448 if (pos == limit)
449 return 0;
451 else /* search backward */
453 if (get_property_and_range (pos - 1, Qcomposition, prop, start, end,
454 object))
455 return 1;
456 val = Fprevious_single_property_change (make_number (pos), Qcomposition,
457 object, make_number (limit));
458 pos = XINT (val);
459 if (pos == limit)
460 return 0;
461 pos--;
463 get_property_and_range (pos, Qcomposition, prop, start, end, object);
464 return 1;
467 /* Run a proper function to adjust the composition sitting between
468 FROM and TO with property PROP. */
470 static void
471 run_composition_function (from, to, prop)
472 int from, to;
473 Lisp_Object prop;
475 Lisp_Object func;
476 EMACS_INT start, end;
478 func = COMPOSITION_MODIFICATION_FUNC (prop);
479 /* If an invalid composition precedes or follows, try to make them
480 valid too. */
481 if (from > BEGV
482 && find_composition (from - 1, -1, &start, &end, &prop, Qnil)
483 && !COMPOSITION_VALID_P (start, end, prop))
484 from = start;
485 if (to < ZV
486 && find_composition (to, -1, &start, &end, &prop, Qnil)
487 && !COMPOSITION_VALID_P (start, end, prop))
488 to = end;
489 if (!NILP (Ffboundp (func)))
490 call2 (func, make_number (from), make_number (to));
493 /* Make invalid compositions adjacent to or inside FROM and TO valid.
494 CHECK_MASK is bitwise `or' of mask bits defined by macros
495 CHECK_XXX (see the comment in composite.h).
497 It also resets the text-property `auto-composed' to a proper region
498 so that automatic character composition works correctly later while
499 displaying the region.
501 This function is called when a buffer text is changed. If the
502 change is deletion, FROM == TO. Otherwise, FROM < TO. */
504 void
505 update_compositions (from, to, check_mask)
506 EMACS_INT from, to;
507 int check_mask;
509 Lisp_Object prop;
510 EMACS_INT start, end;
511 /* The beginning and end of the region to set the property
512 `auto-composed' to nil. */
513 EMACS_INT min_pos = from, max_pos = to;
515 if (inhibit_modification_hooks)
516 return;
518 /* If FROM and TO are not in a valid range, do nothing. */
519 if (! (BEGV <= from && from <= to && to <= ZV))
520 return;
522 if (check_mask & CHECK_HEAD)
524 /* FROM should be at composition boundary. But, insertion or
525 deletion will make two compositions adjacent and
526 indistinguishable when they have same (eq) property. To
527 avoid it, in such a case, we change the property of the
528 latter to the copy of it. */
529 if (from > BEGV
530 && find_composition (from - 1, -1, &start, &end, &prop, Qnil)
531 && COMPOSITION_VALID_P (start, end, prop))
533 min_pos = start;
534 if (end > to)
535 max_pos = end;
536 if (from < end)
537 Fput_text_property (make_number (from), make_number (end),
538 Qcomposition,
539 Fcons (XCAR (prop), XCDR (prop)), Qnil);
540 run_composition_function (start, end, prop);
541 from = end;
543 else if (from < ZV
544 && find_composition (from, -1, &start, &from, &prop, Qnil)
545 && COMPOSITION_VALID_P (start, from, prop))
547 if (from > to)
548 max_pos = from;
549 run_composition_function (start, from, prop);
553 if (check_mask & CHECK_INSIDE)
555 /* In this case, we are sure that (check & CHECK_TAIL) is also
556 nonzero. Thus, here we should check only compositions before
557 (to - 1). */
558 while (from < to - 1
559 && find_composition (from, to, &start, &from, &prop, Qnil)
560 && COMPOSITION_VALID_P (start, from, prop)
561 && from < to - 1)
562 run_composition_function (start, from, prop);
565 if (check_mask & CHECK_TAIL)
567 if (from < to
568 && find_composition (to - 1, -1, &start, &end, &prop, Qnil)
569 && COMPOSITION_VALID_P (start, end, prop))
571 /* TO should be also at composition boundary. But,
572 insertion or deletion will make two compositions adjacent
573 and indistinguishable when they have same (eq) property.
574 To avoid it, in such a case, we change the property of
575 the former to the copy of it. */
576 if (to < end)
578 Fput_text_property (make_number (start), make_number (to),
579 Qcomposition,
580 Fcons (XCAR (prop), XCDR (prop)), Qnil);
581 max_pos = end;
583 run_composition_function (start, end, prop);
585 else if (to < ZV
586 && find_composition (to, -1, &start, &end, &prop, Qnil)
587 && COMPOSITION_VALID_P (start, end, prop))
589 run_composition_function (start, end, prop);
590 max_pos = end;
593 if (min_pos < max_pos)
595 int count = SPECPDL_INDEX ();
597 specbind (Qinhibit_read_only, Qt);
598 specbind (Qinhibit_modification_hooks, Qt);
599 specbind (Qinhibit_point_motion_hooks, Qt);
600 Fremove_list_of_text_properties (make_number (min_pos),
601 make_number (max_pos),
602 Fcons (Qauto_composed, Qnil), Qnil);
603 unbind_to (count, Qnil);
608 /* Modify composition property values in LIST destructively. LIST is
609 a list as returned from text_property_list. Change values to the
610 top-level copies of them so that none of them are `eq'. */
612 void
613 make_composition_value_copy (list)
614 Lisp_Object list;
616 Lisp_Object plist, val;
618 for (; CONSP (list); list = XCDR (list))
620 plist = XCAR (XCDR (XCDR (XCAR (list))));
621 while (CONSP (plist) && CONSP (XCDR (plist)))
623 if (EQ (XCAR (plist), Qcomposition)
624 && (val = XCAR (XCDR (plist)), CONSP (val)))
625 XSETCAR (XCDR (plist), Fcons (XCAR (val), XCDR (val)));
626 plist = XCDR (XCDR (plist));
632 /* Make text in the region between START and END a composition that
633 has COMPONENTS and MODIFICATION-FUNC.
635 If STRING is non-nil, then operate on characters contained between
636 indices START and END in STRING. */
638 void
639 compose_text (start, end, components, modification_func, string)
640 int start, end;
641 Lisp_Object components, modification_func, string;
643 Lisp_Object prop;
645 prop = Fcons (Fcons (make_number (end - start), components),
646 modification_func);
647 Fput_text_property (make_number (start), make_number (end),
648 Qcomposition, prop, string);
652 static Lisp_Object autocmp_chars P_ ((Lisp_Object, EMACS_INT, EMACS_INT,
653 EMACS_INT, struct window *,
654 struct face *, Lisp_Object));
657 /* Lisp glyph-string handlers */
659 /* Hash table for automatic composition. The key is a header of a
660 lgstring (Lispy glyph-string), and the value is a body of a
661 lgstring. */
663 static Lisp_Object gstring_hash_table;
665 static Lisp_Object gstring_lookup_cache P_ ((Lisp_Object));
667 static Lisp_Object
668 gstring_lookup_cache (header)
669 Lisp_Object header;
671 struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
672 int i = hash_lookup (h, header, NULL);
674 return (i >= 0 ? HASH_VALUE (h, i) : Qnil);
677 Lisp_Object
678 composition_gstring_put_cache (gstring, len)
679 Lisp_Object gstring;
680 int len;
682 struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
683 unsigned hash;
684 Lisp_Object header, copy;
685 int i;
687 header = LGSTRING_HEADER (gstring);
688 hash = h->hashfn (h, header);
689 if (len < 0)
691 len = LGSTRING_GLYPH_LEN (gstring);
692 for (i = 0; i < len; i++)
693 if (NILP (LGSTRING_GLYPH (gstring, i)))
694 break;
695 len = i;
698 copy = Fmake_vector (make_number (len + 2), Qnil);
699 LGSTRING_SET_HEADER (copy, Fcopy_sequence (header));
700 for (i = 0; i < len; i++)
701 LGSTRING_SET_GLYPH (copy, i, Fcopy_sequence (LGSTRING_GLYPH (gstring, i)));
702 i = hash_put (h, LGSTRING_HEADER (copy), copy, hash);
703 LGSTRING_SET_ID (copy, make_number (i));
704 return copy;
707 Lisp_Object
708 composition_gstring_from_id (id)
709 int id;
711 struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
713 return HASH_VALUE (h, id);
716 static Lisp_Object fill_gstring_header P_ ((Lisp_Object, Lisp_Object,
717 Lisp_Object, Lisp_Object,
718 Lisp_Object));
721 composition_gstring_p (gstring)
722 Lisp_Object gstring;
724 Lisp_Object header;
725 int i;
727 if (! VECTORP (gstring) || ASIZE (gstring) < 2)
728 return 0;
729 header = LGSTRING_HEADER (gstring);
730 if (! VECTORP (header) || ASIZE (header) < 2)
731 return 0;
732 if (! NILP (LGSTRING_FONT (gstring))
733 && (! FONT_OBJECT_P (LGSTRING_FONT (gstring))
734 && ! CODING_SYSTEM_P (LGSTRING_FONT (gstring))))
735 return 0;
736 for (i = 1; i < ASIZE (LGSTRING_HEADER (gstring)); i++)
737 if (! NATNUMP (AREF (LGSTRING_HEADER (gstring), i)))
738 return 0;
739 if (! NILP (LGSTRING_ID (gstring)) && ! NATNUMP (LGSTRING_ID (gstring)))
740 return 0;
741 for (i = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
743 Lisp_Object glyph = LGSTRING_GLYPH (gstring, i);
744 if (NILP (glyph))
745 break;
746 if (! VECTORP (glyph) || ASIZE (glyph) != LGLYPH_SIZE)
747 return 0;
749 return 1;
753 composition_gstring_width (gstring, from, to, metrics)
754 Lisp_Object gstring;
755 int from, to;
756 struct font_metrics *metrics;
758 Lisp_Object *glyph;
759 int width = 0;
761 if (metrics)
763 Lisp_Object font_object = LGSTRING_FONT (gstring);
765 if (FONT_OBJECT_P (font_object))
767 struct font *font = XFONT_OBJECT (font_object);
769 metrics->ascent = font->ascent;
770 metrics->descent = font->descent;
772 else
774 metrics->ascent = 1;
775 metrics->descent = 0;
777 metrics->width = metrics->lbearing = metrics->rbearing = 0;
779 for (glyph = &LGSTRING_GLYPH (gstring, from); from < to; from++, glyph++)
781 int x;
783 if (NILP (LGLYPH_ADJUSTMENT (*glyph)))
784 width += LGLYPH_WIDTH (*glyph);
785 else
786 width += LGLYPH_WADJUST (*glyph);
787 if (metrics)
789 x = metrics->width + LGLYPH_LBEARING (*glyph) + LGLYPH_XOFF (*glyph);
790 if (metrics->lbearing > x)
791 metrics->lbearing = x;
792 x = metrics->width + LGLYPH_RBEARING (*glyph) + LGLYPH_XOFF (*glyph);
793 if (metrics->rbearing < x)
794 metrics->rbearing = x;
795 metrics->width = width;
796 x = LGLYPH_ASCENT (*glyph) - LGLYPH_YOFF (*glyph);
797 if (metrics->ascent < x)
798 metrics->ascent = x;
799 x = LGLYPH_DESCENT (*glyph) + LGLYPH_YOFF (*glyph);
800 if (metrics->descent < x)
801 metrics->descent = x;
804 return width;
808 static Lisp_Object gstring_work;
809 static Lisp_Object gstring_work_headers;
811 static Lisp_Object
812 fill_gstring_header (header, start, end, font_object, string)
813 Lisp_Object header, start, end, font_object, string;
815 EMACS_INT from, to, from_byte;
816 EMACS_INT len, i;
818 if (NILP (string))
820 if (NILP (current_buffer->enable_multibyte_characters))
821 error ("Attempt to shape unibyte text");
822 validate_region (&start, &end);
823 from = XFASTINT (start);
824 to = XFASTINT (end);
825 from_byte = CHAR_TO_BYTE (from);
827 else
829 CHECK_STRING (string);
830 if (! STRING_MULTIBYTE (string))
831 error ("Attempt to shape unibyte text");
832 /* FROM and TO are checked by the caller. */
833 from = XINT (start);
834 to = XINT (end);
835 if (from < 0 || from > to || to > SCHARS (string))
836 args_out_of_range_3 (string, start, end);
837 from_byte = string_char_to_byte (string, from);
840 len = to - from;
841 if (len == 0)
842 error ("Attempt to shape zero-length text");
843 if (VECTORP (header))
845 if (ASIZE (header) != len + 1)
846 args_out_of_range (header, make_number (len + 1));
848 else
850 if (len <= 8)
851 header = AREF (gstring_work_headers, len - 1);
852 else
853 header = Fmake_vector (make_number (len + 1), Qnil);
856 ASET (header, 0, font_object);
857 for (i = 0; i < len; i++)
859 int c;
861 if (NILP (string))
862 FETCH_CHAR_ADVANCE_NO_CHECK (c, from, from_byte);
863 else
864 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, from, from_byte);
865 ASET (header, i + 1, make_number (c));
867 return header;
870 extern void font_fill_lglyph_metrics P_ ((Lisp_Object, Lisp_Object));
872 static void
873 fill_gstring_body (gstring)
874 Lisp_Object gstring;
876 Lisp_Object font_object = LGSTRING_FONT (gstring);
877 Lisp_Object header = AREF (gstring, 0);
878 EMACS_INT len = LGSTRING_CHAR_LEN (gstring);
879 EMACS_INT i;
881 for (i = 0; i < len; i++)
883 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
884 EMACS_INT c = XINT (AREF (header, i + 1));
886 if (NILP (g))
888 g = LGLYPH_NEW ();
889 LGSTRING_SET_GLYPH (gstring, i, g);
891 LGLYPH_SET_FROM (g, i);
892 LGLYPH_SET_TO (g, i);
893 LGLYPH_SET_CHAR (g, c);
894 if (FONT_OBJECT_P (font_object))
896 font_fill_lglyph_metrics (g, font_object);
898 else
900 int width = XFASTINT (CHAR_TABLE_REF (Vchar_width_table, c));
902 LGLYPH_SET_CODE (g, c);
903 LGLYPH_SET_LBEARING (g, 0);
904 LGLYPH_SET_RBEARING (g, width);
905 LGLYPH_SET_WIDTH (g, width);
906 LGLYPH_SET_ASCENT (g, 1);
907 LGLYPH_SET_DESCENT (g, 0);
909 LGLYPH_SET_ADJUSTMENT (g, Qnil);
911 if (i < LGSTRING_GLYPH_LEN (gstring))
912 LGSTRING_SET_GLYPH (gstring, i, Qnil);
916 /* Try to compose the characters at CHARPOS according to CFT_ELEMENT
917 which is an element of composition-function-table (which see).
918 LIMIT limits the characters to compose. STRING, if not nil, is a
919 target string. WIN is a window where the characters are being
920 displayed. */
922 static Lisp_Object
923 autocmp_chars (cft_element, charpos, bytepos, limit, win, face, string)
924 Lisp_Object cft_element;
925 EMACS_INT charpos, bytepos, limit;
926 struct window *win;
927 struct face *face;
928 Lisp_Object string;
930 int count = SPECPDL_INDEX ();
931 FRAME_PTR f = XFRAME (win->frame);
932 Lisp_Object pos = make_number (charpos);
933 EMACS_INT pt = PT, pt_byte = PT_BYTE;
934 int lookback;
936 record_unwind_save_match_data ();
937 for (lookback = -1; CONSP (cft_element); cft_element = XCDR (cft_element))
939 Lisp_Object elt = XCAR (cft_element);
940 Lisp_Object re;
941 Lisp_Object font_object = Qnil, gstring;
942 EMACS_INT len, to;
944 if (! VECTORP (elt) || ASIZE (elt) != 3)
945 continue;
946 if (lookback < 0)
948 lookback = XFASTINT (AREF (elt, 1));
949 if (limit > charpos + MAX_COMPOSITION_COMPONENTS)
950 limit = charpos + MAX_COMPOSITION_COMPONENTS;
952 else if (lookback != XFASTINT (AREF (elt, 1)))
953 break;
954 re = AREF (elt, 0);
955 if (NILP (re))
956 len = 1;
957 else if ((len = fast_looking_at (re, charpos, bytepos, limit, -1, string))
958 > 0)
960 if (NILP (string))
961 len = BYTE_TO_CHAR (bytepos + len) - charpos;
962 else
963 len = string_byte_to_char (string, bytepos + len) - charpos;
965 if (len > 0)
967 limit = to = charpos + len;
968 #ifdef HAVE_WINDOW_SYSTEM
969 if (FRAME_WINDOW_P (f))
971 font_object = font_range (charpos, &to, win, face, string);
972 if (! FONT_OBJECT_P (font_object)
973 || (! NILP (re)
974 && to < limit
975 && (fast_looking_at (re, charpos, bytepos, to, -1, string) <= 0)))
977 if (NILP (string))
978 TEMP_SET_PT_BOTH (pt, pt_byte);
979 return unbind_to (count, Qnil);
982 else
983 #endif /* not HAVE_WINDOW_SYSTEM */
984 font_object = win->frame;
985 gstring = Fcomposition_get_gstring (pos, make_number (to),
986 font_object, string);
987 if (NILP (LGSTRING_ID (gstring)))
989 Lisp_Object args[6];
991 args[0] = Vauto_composition_function;
992 args[1] = AREF (elt, 2);
993 args[2] = pos;
994 args[3] = make_number (to);
995 args[4] = font_object;
996 args[5] = string;
997 gstring = safe_call (6, args);
999 if (NILP (string))
1000 TEMP_SET_PT_BOTH (pt, pt_byte);
1001 return unbind_to (count, gstring);
1004 if (NILP (string))
1005 TEMP_SET_PT_BOTH (pt, pt_byte);
1006 return unbind_to (count, Qnil);
1010 /* Update cmp_it->stop_pos to the next position after CHARPOS (and
1011 BYTEPOS) where character composition may happen. If BYTEPOS is
1012 negative, compoute it. If it is a static composition, set
1013 cmp_it->ch to -1. Otherwise, set cmp_it->ch to the character that
1014 triggers a automatic composition. */
1016 void
1017 composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string)
1018 struct composition_it *cmp_it;
1019 EMACS_INT charpos, bytepos, endpos;
1020 Lisp_Object string;
1022 EMACS_INT start, end, c;
1023 Lisp_Object prop, val;
1024 /* This is from forward_to_next_line_start in xdisp.c. */
1025 const int MAX_NEWLINE_DISTANCE = 500;
1027 if (endpos > charpos + MAX_NEWLINE_DISTANCE)
1028 endpos = charpos + MAX_NEWLINE_DISTANCE;
1029 cmp_it->stop_pos = endpos;
1030 cmp_it->id = -1;
1031 cmp_it->ch = -2;
1032 if (find_composition (charpos, endpos, &start, &end, &prop, string)
1033 && COMPOSITION_VALID_P (start, end, prop))
1035 cmp_it->stop_pos = endpos = start;
1036 cmp_it->ch = -1;
1038 if (NILP (string) && PT > charpos && PT < endpos)
1039 cmp_it->stop_pos = PT;
1040 if (NILP (current_buffer->enable_multibyte_characters)
1041 || ! FUNCTIONP (Vauto_composition_function))
1042 return;
1043 if (bytepos < 0)
1045 if (STRINGP (string))
1046 bytepos = string_char_to_byte (string, charpos);
1047 else
1048 bytepos = CHAR_TO_BYTE (charpos);
1051 start = charpos;
1052 while (charpos < endpos)
1054 if (STRINGP (string))
1055 FETCH_STRING_CHAR_ADVANCE (c, string, charpos, bytepos);
1056 else
1057 FETCH_CHAR_ADVANCE (c, charpos, bytepos);
1058 if (c == '\n')
1060 cmp_it->ch = -2;
1061 break;
1063 val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1064 if (! NILP (val))
1066 Lisp_Object elt;
1068 for (; CONSP (val); val = XCDR (val))
1070 elt = XCAR (val);
1071 if (VECTORP (elt) && ASIZE (elt) == 3 && NATNUMP (AREF (elt, 1))
1072 && charpos - 1 - XFASTINT (AREF (elt, 1)) >= start)
1073 break;
1075 if (CONSP (val))
1077 cmp_it->lookback = XFASTINT (AREF (elt, 1));
1078 cmp_it->stop_pos = charpos - 1 - cmp_it->lookback;
1079 cmp_it->ch = c;
1080 return;
1084 cmp_it->stop_pos = charpos;
1087 /* Check if the character at CHARPOS (and BYTEPOS) is composed
1088 (possibly with the following characters) on window W. ENDPOS limits
1089 characters to be composed. FACE, in non-NULL, is a base face of
1090 the character. If STRING is not nil, it is a string containing the
1091 character to check, and CHARPOS and BYTEPOS are indices in the
1092 string. In that case, FACE must not be NULL.
1094 If the character is composed, setup members of CMP_IT (id, nglyphs,
1095 and from), and return 1. Otherwise, update CMP_IT->stop_pos, and
1096 return 0. */
1099 composition_reseat_it (cmp_it, charpos, bytepos, endpos, w, face, string)
1100 struct composition_it *cmp_it;
1101 EMACS_INT charpos, bytepos, endpos;
1102 struct window *w;
1103 struct face *face;
1104 Lisp_Object string;
1106 if (cmp_it->ch == -2)
1108 composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string);
1109 if (cmp_it->ch == -2)
1110 return 0;
1113 if (cmp_it->ch < 0)
1115 /* We are looking at a static composition. */
1116 EMACS_INT start, end;
1117 Lisp_Object prop;
1119 find_composition (charpos, -1, &start, &end, &prop, string);
1120 cmp_it->id = get_composition_id (charpos, bytepos, end - start,
1121 prop, string);
1122 if (cmp_it->id < 0)
1123 goto no_composition;
1124 cmp_it->nchars = end - start;
1125 cmp_it->nglyphs = composition_table[cmp_it->id]->glyph_len;
1127 else if (w)
1129 Lisp_Object val, elt;
1130 int i;
1132 val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch);
1133 for (; CONSP (val); val = XCDR (val))
1135 elt = XCAR (val);
1136 if (cmp_it->lookback == XFASTINT (AREF (elt, 1)))
1137 break;
1139 if (NILP (val))
1140 goto no_composition;
1142 val = autocmp_chars (val, charpos, bytepos, endpos, w, face, string);
1143 if (! composition_gstring_p (val))
1144 goto no_composition;
1145 if (NILP (LGSTRING_ID (val)))
1146 val = composition_gstring_put_cache (val, -1);
1147 cmp_it->id = XINT (LGSTRING_ID (val));
1148 for (i = 0; i < LGSTRING_GLYPH_LEN (val); i++)
1149 if (NILP (LGSTRING_GLYPH (val, i)))
1150 break;
1151 cmp_it->nglyphs = i;
1153 else
1154 goto no_composition;
1155 cmp_it->from = 0;
1156 return 1;
1158 no_composition:
1159 charpos++;
1160 if (STRINGP (string))
1161 bytepos += MULTIBYTE_LENGTH_NO_CHECK (SDATA (string) + bytepos);
1162 else
1163 INC_POS (bytepos);
1164 composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string);
1165 return 0;
1169 composition_update_it (cmp_it, charpos, bytepos, string)
1170 struct composition_it *cmp_it;
1171 EMACS_INT charpos, bytepos;
1172 Lisp_Object string;
1174 int i, c;
1176 if (cmp_it->ch < 0)
1178 struct composition *cmp = composition_table[cmp_it->id];
1180 cmp_it->to = cmp_it->nglyphs;
1181 if (cmp_it->nglyphs == 0)
1182 c = -1;
1183 else
1185 for (i = 0; i < cmp->glyph_len; i++)
1186 if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
1187 break;
1188 if (c == '\t')
1189 c = ' ';
1191 cmp_it->width = cmp->width;
1193 else
1195 Lisp_Object gstring = composition_gstring_from_id (cmp_it->id);
1197 if (cmp_it->nglyphs == 0)
1199 c = -1;
1200 cmp_it->nchars = LGSTRING_CHAR_LEN (gstring);
1201 cmp_it->width = 0;
1203 else
1205 Lisp_Object glyph = LGSTRING_GLYPH (gstring, cmp_it->from);
1206 int from = LGLYPH_FROM (glyph);
1208 c = XINT (LGSTRING_CHAR (gstring, from));
1209 cmp_it->nchars = LGLYPH_TO (glyph) - from + 1;
1210 cmp_it->width = (LGLYPH_WIDTH (glyph) > 0
1211 ? CHAR_WIDTH (LGLYPH_CHAR (glyph)) : 0);
1212 for (cmp_it->to = cmp_it->from + 1; cmp_it->to < cmp_it->nglyphs;
1213 cmp_it->to++)
1215 glyph = LGSTRING_GLYPH (gstring, cmp_it->to);
1216 if (LGLYPH_FROM (glyph) != from)
1217 break;
1218 if (LGLYPH_WIDTH (glyph) > 0)
1219 cmp_it->width += CHAR_WIDTH (LGLYPH_CHAR (glyph));
1224 charpos += cmp_it->nchars;
1225 if (STRINGP (string))
1226 cmp_it->nbytes = string_char_to_byte (string, charpos) - bytepos;
1227 else
1228 cmp_it->nbytes = CHAR_TO_BYTE (charpos) - bytepos;
1229 return c;
1233 struct position_record
1235 EMACS_INT pos, pos_byte;
1236 unsigned char *p;
1239 /* Update the members of POSTION to the next character boundary. */
1240 #define FORWARD_CHAR(POSITION, STOP) \
1241 do { \
1242 (POSITION).pos++; \
1243 if ((POSITION).pos == (STOP)) \
1245 (POSITION).p = GAP_END_ADDR; \
1246 (POSITION).pos_byte = GPT_BYTE; \
1248 else \
1250 (POSITION).pos_byte += BYTES_BY_CHAR_HEAD (*((POSITION).p)); \
1251 (POSITION).p += BYTES_BY_CHAR_HEAD (*((POSITION).p)); \
1253 } while (0)
1255 /* Update the members of POSTION to the previous character boundary. */
1256 #define BACKWARD_CHAR(POSITION, STOP) \
1257 do { \
1258 if ((POSITION).pos == STOP) \
1259 (POSITION).p = GPT_ADDR; \
1260 do { \
1261 (POSITION).pos_byte--; \
1262 (POSITION).p--; \
1263 } while (! CHAR_HEAD_P (*((POSITION).p))); \
1264 (POSITION).pos--; \
1265 } while (0)
1267 static Lisp_Object _work_val;
1268 static int _work_char;
1270 /* 1 iff the character C is composable. */
1271 #define CHAR_COMPOSABLE_P(C) \
1272 (_work_val = CHAR_TABLE_REF (Vunicode_category_table, (C)), \
1273 (SYMBOLP (_work_val) \
1274 && (_work_char = SDATA (SYMBOL_NAME (_work_val))[0]) != 'C' \
1275 && _work_char != 'Z'))
1277 /* This is like find_composition, but find an automatic composition
1278 instead. If found, set *GSTRING to the glyph-string representing
1279 the composition, and return 1. Otherwise, return 0. */
1281 static int
1282 find_automatic_composition (pos, limit, start, end, gstring, string)
1283 EMACS_INT pos, limit, *start, *end;
1284 Lisp_Object *gstring, string;
1286 EMACS_INT head, tail, stop;
1287 /* Limit to check a composition after POS. */
1288 EMACS_INT fore_check_limit;
1289 struct position_record orig, cur, check, prev;
1290 Lisp_Object check_val, val, elt;
1291 int check_lookback;
1292 int c;
1293 Lisp_Object window;
1294 struct window *w;
1296 window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
1297 if (NILP (window))
1298 return 0;
1299 w = XWINDOW (window);
1301 orig.pos = pos;
1302 if (NILP (string))
1304 head = BEGV, tail = ZV, stop = GPT;
1305 orig.pos_byte = CHAR_TO_BYTE (orig.pos);
1306 orig.p = BYTE_POS_ADDR (orig.pos_byte);
1308 else
1310 head = 0, tail = SCHARS (string), stop = -1;
1311 orig.pos_byte = string_char_to_byte (string, orig.pos);
1312 orig.p = SDATA (string) + orig.pos_byte;
1314 if (limit < pos)
1315 fore_check_limit = min (tail, pos + MAX_AUTO_COMPOSITION_LOOKBACK);
1316 else
1317 fore_check_limit = min (tail, limit + MAX_AUTO_COMPOSITION_LOOKBACK);
1318 cur = orig;
1320 retry:
1321 check_val = Qnil;
1322 /* At first, check if POS is composable. */
1323 c = STRING_CHAR (cur.p, 0);
1324 if (! CHAR_COMPOSABLE_P (c))
1326 if (limit < 0)
1327 return 0;
1328 if (limit >= cur.pos)
1329 goto search_forward;
1331 else
1333 val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1334 if (! NILP (val))
1335 check_val = val, check = cur;
1336 else
1337 while (cur.pos + 1 < fore_check_limit)
1339 EMACS_INT b, e;
1341 FORWARD_CHAR (cur, stop);
1342 if (get_property_and_range (cur.pos, Qcomposition, &val, &b, &e,
1343 Qnil)
1344 && COMPOSITION_VALID_P (b, e, val))
1346 fore_check_limit = cur.pos;
1347 break;
1349 c = STRING_CHAR (cur.p, 0);
1350 if (! CHAR_COMPOSABLE_P (c))
1351 break;
1352 val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1353 if (NILP (val))
1354 continue;
1355 check_val = val, check = cur;
1356 break;
1358 cur = orig;
1360 /* Rewind back to the position where we can safely search forward
1361 for compositions. */
1362 while (cur.pos > head)
1364 EMACS_INT b, e;
1366 BACKWARD_CHAR (cur, stop);
1367 if (get_property_and_range (cur.pos, Qcomposition, &val, &b, &e, Qnil)
1368 && COMPOSITION_VALID_P (b, e, val))
1369 break;
1370 c = STRING_CHAR (cur.p, 0);
1371 if (! CHAR_COMPOSABLE_P (c))
1372 break;
1373 val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1374 if (! NILP (val))
1375 check_val = val, check = cur;
1377 prev = cur;
1378 /* Now search forward. */
1379 search_forward:
1380 *gstring = Qnil;
1381 if (! NILP (check_val) || limit >= orig.pos)
1383 if (NILP (check_val))
1384 cur = orig;
1385 else
1386 cur = check;
1387 while (cur.pos < fore_check_limit)
1389 int need_adjustment = 0;
1391 if (NILP (check_val))
1393 c = STRING_CHAR (cur.p, 0);
1394 check_val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1396 for (; CONSP (check_val); check_val = XCDR (check_val))
1398 elt = XCAR (check_val);
1399 if (VECTORP (elt) && ASIZE (elt) == 3 && NATNUMP (AREF (elt, 1))
1400 && cur.pos - XFASTINT (AREF (elt, 1)) >= head)
1402 check.pos = cur.pos - XFASTINT (AREF (elt, 1));
1403 if (check.pos == cur.pos)
1404 check.pos_byte = cur.pos_byte;
1405 else
1406 check.pos_byte = CHAR_TO_BYTE (check.pos);
1407 val = autocmp_chars (check_val, check.pos, check.pos_byte,
1408 tail, w, NULL, string);
1409 need_adjustment = 1;
1410 if (! NILP (val))
1412 *gstring = val;
1413 *start = check.pos;
1414 *end = check.pos + LGSTRING_CHAR_LEN (*gstring);
1415 if (*start <= orig.pos ? *end > orig.pos
1416 : limit >= orig.pos)
1417 return 1;
1418 cur.pos = *end;
1419 cur.pos_byte = CHAR_TO_BYTE (cur.pos);
1420 break;
1424 if (need_adjustment)
1426 /* As we have called Lisp, there's a possibilily that
1427 buffer/string is relocated. */
1428 if (NILP (string))
1429 cur.p = BYTE_POS_ADDR (cur.pos_byte);
1430 else
1431 cur.p = SDATA (string) + cur.pos_byte;
1433 if (! CONSP (check_val))
1434 FORWARD_CHAR (cur, stop);
1435 check_val = Qnil;
1438 if (! NILP (*gstring))
1439 return (limit >= 0 || (*start <= orig.pos && *end > orig.pos));
1440 if (limit >= 0 && limit < orig.pos && prev.pos > head)
1442 cur = prev;
1443 BACKWARD_CHAR (cur, stop);
1444 orig = cur;
1445 fore_check_limit = orig.pos;
1446 goto retry;
1448 return 0;
1452 composition_adjust_point (last_pt)
1453 EMACS_INT last_pt;
1455 EMACS_INT charpos, bytepos, startpos, beg, end, pos;
1456 Lisp_Object val;
1457 int i;
1459 if (PT == BEGV || PT == ZV)
1460 return PT;
1462 /* At first check the static composition. */
1463 if (get_property_and_range (PT, Qcomposition, &val, &beg, &end, Qnil)
1464 && COMPOSITION_VALID_P (beg, end, val))
1466 if (beg < PT /* && end > PT <- It's always the case. */
1467 && (last_pt <= beg || last_pt >= end))
1468 return (PT < last_pt ? beg : end);
1469 return PT;
1472 if (NILP (current_buffer->enable_multibyte_characters)
1473 || ! FUNCTIONP (Vauto_composition_function))
1474 return PT;
1476 /* Next check the automatic composition. */
1477 if (! find_automatic_composition (PT, (EMACS_INT) -1, &beg, &end, &val, Qnil)
1478 || beg == PT)
1479 return PT;
1480 for (i = 0; i < LGSTRING_GLYPH_LEN (val); i++)
1482 Lisp_Object glyph = LGSTRING_GLYPH (val, i);
1484 if (NILP (glyph))
1485 break;
1486 if (beg + LGLYPH_FROM (glyph) == PT)
1487 return PT;
1488 if (beg + LGLYPH_TO (glyph) >= PT)
1489 return (PT < last_pt
1490 ? beg + LGLYPH_FROM (glyph)
1491 : beg + LGLYPH_TO (glyph) + 1);
1493 return PT;
1496 DEFUN ("composition-get-gstring", Fcomposition_get_gstring,
1497 Scomposition_get_gstring, 4, 4, 0,
1498 doc: /* Return a glyph-string for characters between FROM and TO.
1499 If the glyph string is for graphic display, FONT-OBJECT must be
1500 a font-object to use for those characters.
1501 Otherwise (for terminal display), FONT-OBJECT must be a terminal ID, a
1502 frame, or nil for the selected frame's terminal device.
1504 If the optional 4th argument STRING is not nil, it is a string
1505 containing the target characters between indices FROM and TO.
1507 A glyph-string is a vector containing information about how to display
1508 a specific character sequence. The format is:
1509 [HEADER ID GLYPH ...]
1511 HEADER is a vector of this form:
1512 [FONT-OBJECT CHAR ...]
1513 where
1514 FONT-OBJECT is a font-object for all glyphs in the glyph-string,
1515 or the terminal coding system of the specified terminal.
1516 CHARs are characters to be composed by GLYPHs.
1518 ID is an identification number of the glyph-string. It may be nil if
1519 not yet shaped.
1521 GLYPH is a vector whose elements have this form:
1522 [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
1523 [ [X-OFF Y-OFF WADJUST] | nil] ]
1524 where
1525 FROM-IDX and TO-IDX are used internally and should not be touched.
1526 C is the character of the glyph.
1527 CODE is the glyph-code of C in FONT-OBJECT.
1528 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
1529 X-OFF and Y-OFF are offsets to the base position for the glyph.
1530 WADJUST is the adjustment to the normal width of the glyph.
1532 If GLYPH is nil, the remaining elements of the glyph-string vector
1533 should be ignored. */)
1534 (from, to, font_object, string)
1535 Lisp_Object font_object, from, to, string;
1537 Lisp_Object gstring, header;
1538 EMACS_INT frompos, topos;
1540 CHECK_NATNUM (from);
1541 CHECK_NATNUM (to);
1542 if (XINT (to) > XINT (from) + MAX_COMPOSITION_COMPONENTS)
1543 to = make_number (XINT (from) + MAX_COMPOSITION_COMPONENTS);
1544 if (! FONT_OBJECT_P (font_object))
1546 struct coding_system *coding;
1547 struct terminal *terminal = get_terminal (font_object, 1);
1549 coding = ((TERMINAL_TERMINAL_CODING (terminal)->common_flags
1550 & CODING_REQUIRE_ENCODING_MASK)
1551 ? TERMINAL_TERMINAL_CODING (terminal) : &safe_terminal_coding);
1552 font_object = CODING_ID_NAME (coding->id);
1555 header = fill_gstring_header (Qnil, from, to, font_object, string);
1556 gstring = gstring_lookup_cache (header);
1557 if (! NILP (gstring))
1558 return gstring;
1560 frompos = XINT (from);
1561 topos = XINT (to);
1562 if (LGSTRING_GLYPH_LEN (gstring_work) < topos - frompos)
1563 gstring_work = Fmake_vector (make_number (topos - frompos + 2), Qnil);
1564 LGSTRING_SET_HEADER (gstring_work, header);
1565 LGSTRING_SET_ID (gstring_work, Qnil);
1566 fill_gstring_body (gstring_work);
1567 return gstring_work;
1571 /* Emacs Lisp APIs. */
1573 DEFUN ("compose-region-internal", Fcompose_region_internal,
1574 Scompose_region_internal, 2, 4, 0,
1575 doc: /* Internal use only.
1577 Compose text in the region between START and END.
1578 Optional 3rd and 4th arguments are COMPONENTS and MODIFICATION-FUNC
1579 for the composition. See `compose-region' for more details. */)
1580 (start, end, components, modification_func)
1581 Lisp_Object start, end, components, modification_func;
1583 validate_region (&start, &end);
1584 if (!NILP (components)
1585 && !INTEGERP (components)
1586 && !CONSP (components)
1587 && !STRINGP (components))
1588 CHECK_VECTOR (components);
1590 compose_text (XINT (start), XINT (end), components, modification_func, Qnil);
1591 return Qnil;
1594 DEFUN ("compose-string-internal", Fcompose_string_internal,
1595 Scompose_string_internal, 3, 5, 0,
1596 doc: /* Internal use only.
1598 Compose text between indices START and END of STRING.
1599 Optional 4th and 5th arguments are COMPONENTS and MODIFICATION-FUNC
1600 for the composition. See `compose-string' for more details. */)
1601 (string, start, end, components, modification_func)
1602 Lisp_Object string, start, end, components, modification_func;
1604 CHECK_STRING (string);
1605 CHECK_NUMBER (start);
1606 CHECK_NUMBER (end);
1608 if (XINT (start) < 0 ||
1609 XINT (start) > XINT (end)
1610 || XINT (end) > SCHARS (string))
1611 args_out_of_range (start, end);
1613 compose_text (XINT (start), XINT (end), components, modification_func, string);
1614 return string;
1617 DEFUN ("find-composition-internal", Ffind_composition_internal,
1618 Sfind_composition_internal, 4, 4, 0,
1619 doc: /* Internal use only.
1621 Return information about composition at or nearest to position POS.
1622 See `find-composition' for more details. */)
1623 (pos, limit, string, detail_p)
1624 Lisp_Object pos, limit, string, detail_p;
1626 Lisp_Object prop, tail, gstring;
1627 EMACS_INT start, end, from, to;
1628 int id;
1630 CHECK_NUMBER_COERCE_MARKER (pos);
1631 from = XINT (pos);
1632 if (!NILP (limit))
1634 CHECK_NUMBER_COERCE_MARKER (limit);
1635 to = XINT (limit);
1637 else
1638 to = -1;
1640 if (!NILP (string))
1642 CHECK_STRING (string);
1643 if (XINT (pos) < 0 || XINT (pos) > SCHARS (string))
1644 args_out_of_range (string, pos);
1646 else
1648 if (XINT (pos) < BEGV || XINT (pos) > ZV)
1649 args_out_of_range (Fcurrent_buffer (), pos);
1652 if (!find_composition (from, to, &start, &end, &prop, string))
1654 if (!NILP (current_buffer->enable_multibyte_characters)
1655 && FUNCTIONP (Vauto_composition_function)
1656 && find_automatic_composition (from, to, &start, &end, &gstring,
1657 string))
1658 return list3 (make_number (start), make_number (end), gstring);
1659 return Qnil;
1661 if ((end <= XINT (pos) || start > XINT (pos)))
1663 EMACS_INT s, e;
1665 if (find_automatic_composition (from, to, &s, &e, &gstring, string)
1666 && (e <= XINT (pos) ? e > end : s < start))
1667 return list3 (make_number (start), make_number (end), gstring);
1669 if (!COMPOSITION_VALID_P (start, end, prop))
1670 return Fcons (make_number (start), Fcons (make_number (end),
1671 Fcons (Qnil, Qnil)));
1672 if (NILP (detail_p))
1673 return Fcons (make_number (start), Fcons (make_number (end),
1674 Fcons (Qt, Qnil)));
1676 if (COMPOSITION_REGISTERD_P (prop))
1677 id = COMPOSITION_ID (prop);
1678 else
1680 int start_byte = (NILP (string)
1681 ? CHAR_TO_BYTE (start)
1682 : string_char_to_byte (string, start));
1683 id = get_composition_id (start, start_byte, end - start, prop, string);
1686 if (id >= 0)
1688 Lisp_Object components, relative_p, mod_func;
1689 enum composition_method method = COMPOSITION_METHOD (prop);
1690 int width = composition_table[id]->width;
1692 components = Fcopy_sequence (COMPOSITION_COMPONENTS (prop));
1693 relative_p = (method == COMPOSITION_WITH_RULE_ALTCHARS
1694 ? Qnil : Qt);
1695 mod_func = COMPOSITION_MODIFICATION_FUNC (prop);
1696 tail = Fcons (components,
1697 Fcons (relative_p,
1698 Fcons (mod_func,
1699 Fcons (make_number (width), Qnil))));
1701 else
1702 tail = Qnil;
1704 return Fcons (make_number (start), Fcons (make_number (end), tail));
1708 void
1709 syms_of_composite ()
1711 int i;
1713 Qcomposition = intern ("composition");
1714 staticpro (&Qcomposition);
1716 /* Make a hash table for static composition. */
1718 Lisp_Object args[6];
1719 extern Lisp_Object QCsize;
1721 args[0] = QCtest;
1722 args[1] = Qequal;
1723 args[2] = QCweakness;
1724 /* We used to make the hash table weak so that unreferenced
1725 compositions can be garbage-collected. But, usually once
1726 created compositions are repeatedly used in an Emacs session,
1727 and thus it's not worth to save memory in such a way. So, we
1728 make the table not weak. */
1729 args[3] = Qnil;
1730 args[4] = QCsize;
1731 args[5] = make_number (311);
1732 composition_hash_table = Fmake_hash_table (6, args);
1733 staticpro (&composition_hash_table);
1736 /* Make a hash table for glyph-string. */
1738 Lisp_Object args[6];
1739 extern Lisp_Object QCsize;
1741 args[0] = QCtest;
1742 args[1] = Qequal;
1743 args[2] = QCweakness;
1744 args[3] = Qnil;
1745 args[4] = QCsize;
1746 args[5] = make_number (311);
1747 gstring_hash_table = Fmake_hash_table (6, args);
1748 staticpro (&gstring_hash_table);
1751 staticpro (&gstring_work_headers);
1752 gstring_work_headers = Fmake_vector (make_number (8), Qnil);
1753 for (i = 0; i < 8; i++)
1754 ASET (gstring_work_headers, i, Fmake_vector (make_number (i + 2), Qnil));
1755 staticpro (&gstring_work);
1756 gstring_work = Fmake_vector (make_number (10), Qnil);
1758 /* Text property `composition' should be nonsticky by default. */
1759 Vtext_property_default_nonsticky
1760 = Fcons (Fcons (Qcomposition, Qt), Vtext_property_default_nonsticky);
1762 DEFVAR_LISP ("compose-chars-after-function", &Vcompose_chars_after_function,
1763 doc: /* Function to adjust composition of buffer text.
1765 This function is called with three arguments: FROM, TO, and OBJECT.
1766 FROM and TO specify the range of text whose composition should be
1767 adjusted. OBJECT, if non-nil, is a string that contains the text.
1769 This function is called after a text with `composition' property is
1770 inserted or deleted to keep `composition' property of buffer text
1771 valid.
1773 The default value is the function `compose-chars-after'. */);
1774 Vcompose_chars_after_function = intern ("compose-chars-after");
1776 Qauto_composed = intern ("auto-composed");
1777 staticpro (&Qauto_composed);
1779 Qauto_composition_function = intern ("auto-composition-function");
1780 staticpro (&Qauto_composition_function);
1782 DEFVAR_LISP ("auto-composition-function", &Vauto_composition_function,
1783 doc: /* Function to call to compose characters automatically.
1784 This function is called from the display routine with four arguments:
1785 FROM, TO, WINDOW, and STRING.
1787 If STRING is nil, the function must compose characters in the region
1788 between FROM and TO in the current buffer.
1790 Otherwise, STRING is a string, and FROM and TO are indices into the
1791 string. In this case, the function must compose characters in the
1792 string. */);
1793 Vauto_composition_function = Qnil;
1795 DEFVAR_LISP ("composition-function-table", &Vcomposition_function_table,
1796 doc: /* Char-table of functions for automatic character composition.
1797 For each character that has to be composed automatically with
1798 preceding and/or following characters, this char-table contains
1799 a function to call to compose that character.
1801 The element at index C in the table, if non-nil, is a list of
1802 this form: ([PATTERN PREV-CHARS FUNC] ...)
1804 PATTERN is a regular expression which C and the surrounding
1805 characters must match.
1807 PREV-CHARS is a non-negative integer (less than 4) specifying how many
1808 characters before C to check the matching with PATTERN. If it is 0,
1809 PATTERN must match C and the following characters. If it is 1,
1810 PATTERN must match a character before C and the following characters.
1812 If PREV-CHARS is 0, PATTERN can be nil, which means that the
1813 single character C should be composed.
1815 FUNC is a function to return a glyph-string representing a
1816 composition of the characters that match PATTERN. It is
1817 called with one argument GSTRING.
1819 GSTRING is a template of a glyph-string to return. It is already
1820 filled with a proper header for the characters to compose, and
1821 glyphs corresponding to those characters one by one. The
1822 function must return a new glyph-string with the same header as
1823 GSTRING, or modify GSTRING itself and return it.
1825 See also the documentation of `auto-composition-mode'. */);
1826 Vcomposition_function_table = Fmake_char_table (Qnil, Qnil);
1828 defsubr (&Scompose_region_internal);
1829 defsubr (&Scompose_string_internal);
1830 defsubr (&Sfind_composition_internal);
1831 defsubr (&Scomposition_get_gstring);
1834 /* arch-tag: 79cefaf8-ca48-4eed-97e5-d5afb290d272
1835 (do not change this comment) */