merge trunk
[bpt/emacs.git] / src / composite.c
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 \f
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 \f
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 \f
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 CFT_ELEMENT
919 which is an element of composition-function-table (which see).
920 LIMIT limits the characters to compose. STRING, if not nil, is a
921 target string. WIN is a window where the characters are being
922 displayed. */
923
924 static Lisp_Object
925 autocmp_chars (cft_element, charpos, bytepos, limit, win, face, string)
926 Lisp_Object cft_element;
927 EMACS_INT charpos, bytepos, limit;
928 struct window *win;
929 struct face *face;
930 Lisp_Object string;
931 {
932 int count = SPECPDL_INDEX ();
933 FRAME_PTR f = XFRAME (win->frame);
934 Lisp_Object pos = make_number (charpos);
935 EMACS_INT pt = PT, pt_byte = PT_BYTE;
936 int lookback;
937
938 record_unwind_save_match_data ();
939 for (lookback = -1; CONSP (cft_element); cft_element = XCDR (cft_element))
940 {
941 Lisp_Object elt = XCAR (cft_element);
942 Lisp_Object re;
943 Lisp_Object font_object = Qnil, gstring;
944 EMACS_INT len, to;
945
946 if (! VECTORP (elt) || ASIZE (elt) != 3)
947 continue;
948 if (lookback < 0)
949 {
950 lookback = XFASTINT (AREF (elt, 1));
951 if (limit > charpos + MAX_COMPOSITION_COMPONENTS)
952 limit = charpos + MAX_COMPOSITION_COMPONENTS;
953 }
954 else if (lookback != XFASTINT (AREF (elt, 1)))
955 break;
956 re = AREF (elt, 0);
957 if (NILP (re))
958 len = 1;
959 else if ((len = fast_looking_at (re, charpos, bytepos, limit, -1, string))
960 > 0)
961 {
962 if (NILP (string))
963 len = BYTE_TO_CHAR (bytepos + len) - charpos;
964 else
965 len = string_byte_to_char (string, bytepos + len) - charpos;
966 }
967 if (len > 0)
968 {
969 limit = to = charpos + len;
970 #ifdef HAVE_WINDOW_SYSTEM
971 if (FRAME_WINDOW_P (f))
972 {
973 font_object = font_range (charpos, &to, win, face, string);
974 if (! FONT_OBJECT_P (font_object)
975 || (! NILP (re)
976 && to < limit
977 && (fast_looking_at (re, charpos, bytepos, to, -1, string) <= 0)))
978 {
979 if (NILP (string))
980 TEMP_SET_PT_BOTH (pt, pt_byte);
981 return unbind_to (count, Qnil);
982 }
983 }
984 else
985 #endif /* not HAVE_WINDOW_SYSTEM */
986 font_object = win->frame;
987 gstring = Fcomposition_get_gstring (pos, make_number (to),
988 font_object, string);
989 if (NILP (LGSTRING_ID (gstring)))
990 {
991 Lisp_Object args[6];
992
993 /* Save point as marker before calling out to lisp. */
994 if (NILP (string))
995 {
996 Lisp_Object m = Fmake_marker ();
997 set_marker_both (m, Qnil, pt, pt_byte);
998 record_unwind_protect (restore_point_unwind, m);
999 }
1000
1001 args[0] = Vauto_composition_function;
1002 args[1] = AREF (elt, 2);
1003 args[2] = pos;
1004 args[3] = make_number (to);
1005 args[4] = font_object;
1006 args[5] = string;
1007 gstring = safe_call (6, args);
1008 }
1009 else if (NILP (string))
1010 {
1011 TEMP_SET_PT_BOTH (pt, pt_byte);
1012 }
1013 return unbind_to (count, gstring);
1014 }
1015 }
1016 if (NILP (string))
1017 TEMP_SET_PT_BOTH (pt, pt_byte);
1018 return unbind_to (count, Qnil);
1019 }
1020
1021 static Lisp_Object _work_val;
1022 static int _work_char;
1023
1024 /* 1 iff the character C is composable. */
1025 #define CHAR_COMPOSABLE_P(C) \
1026 ((C) == 0x200C || (C) == 0x200D \
1027 || (_work_val = CHAR_TABLE_REF (Vunicode_category_table, (C)), \
1028 (SYMBOLP (_work_val) \
1029 && (_work_char = SDATA (SYMBOL_NAME (_work_val))[0]) != 'C' \
1030 && _work_char != 'Z')))
1031
1032 /* Update cmp_it->stop_pos to the next position after CHARPOS (and
1033 BYTEPOS) where character composition may happen. If BYTEPOS is
1034 negative, compute it. ENDPOS is a limit of searching. If it is
1035 less than CHARPOS, search backward to ENDPOS+1 assuming that
1036 set_iterator_to_next works in reverse order. In this case, if a
1037 composition closest to CHARPOS is found, set cmp_it->stop_pos to
1038 the last character of the composition.
1039
1040 If no composition is found, set cmp_it->ch to -2. If a static
1041 composition is found, set cmp_it->ch to -1. Otherwise, set
1042 cmp_it->ch to the character that triggers the automatic
1043 composition. */
1044
1045 void
1046 composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string)
1047 struct composition_it *cmp_it;
1048 EMACS_INT charpos, bytepos, endpos;
1049 Lisp_Object string;
1050 {
1051 EMACS_INT start, end, c;
1052 Lisp_Object prop, val;
1053 /* This is from forward_to_next_line_start in xdisp.c. */
1054 const int MAX_NEWLINE_DISTANCE = 500;
1055
1056 if (charpos < endpos)
1057 {
1058 if (endpos > charpos + MAX_NEWLINE_DISTANCE)
1059 endpos = charpos + MAX_NEWLINE_DISTANCE;
1060 }
1061 else if (endpos < charpos)
1062 {
1063 /* We search backward for a position to check composition. */
1064 if (endpos < 0)
1065 {
1066 /* But we don't know where to stop the searching. */
1067 endpos = NILP (string) ? BEGV - 1 : -1;
1068 /* Usually we don't reach ENDPOS because we stop searching
1069 at an uncomposable character (NL, LRE, etc). */
1070 }
1071 }
1072 cmp_it->id = -1;
1073 cmp_it->ch = -2;
1074 cmp_it->reversed_p = 0;
1075 cmp_it->stop_pos = endpos;
1076 if (charpos == endpos)
1077 return;
1078 /* FIXME: Bidi is not yet handled well in static composition. */
1079 if (charpos < endpos
1080 && find_composition (charpos, endpos, &start, &end, &prop, string)
1081 && COMPOSITION_VALID_P (start, end, prop))
1082 {
1083 cmp_it->stop_pos = endpos = start;
1084 cmp_it->ch = -1;
1085 }
1086 if (NILP (string))
1087 {
1088 /* A composition never strides over PT. */
1089 if (PT > charpos)
1090 {
1091 if (PT < endpos)
1092 cmp_it->stop_pos = endpos = PT;
1093 }
1094 else if (PT < charpos && PT > endpos)
1095 {
1096 cmp_it->stop_pos = endpos = PT - 1;
1097 }
1098 }
1099 if (NILP (current_buffer->enable_multibyte_characters)
1100 || NILP (Vauto_composition_mode))
1101 return;
1102 if (bytepos < 0)
1103 {
1104 if (NILP (string))
1105 bytepos = CHAR_TO_BYTE (charpos);
1106 else
1107 bytepos = string_char_to_byte (string, charpos);
1108 }
1109
1110 start = charpos;
1111 if (charpos < endpos)
1112 {
1113 /* Forward search. */
1114 while (charpos < endpos)
1115 {
1116 if (STRINGP (string))
1117 FETCH_STRING_CHAR_ADVANCE (c, string, charpos, bytepos);
1118 else
1119 FETCH_CHAR_ADVANCE (c, charpos, bytepos);
1120 if (c == '\n')
1121 {
1122 cmp_it->ch = -2;
1123 break;
1124 }
1125 val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1126 if (! NILP (val))
1127 {
1128 Lisp_Object elt;
1129
1130 for (; CONSP (val); val = XCDR (val))
1131 {
1132 elt = XCAR (val);
1133 if (VECTORP (elt) && ASIZE (elt) == 3
1134 && NATNUMP (AREF (elt, 1))
1135 && charpos - 1 - XFASTINT (AREF (elt, 1)) >= start)
1136 break;
1137 }
1138 if (CONSP (val))
1139 {
1140 cmp_it->lookback = XFASTINT (AREF (elt, 1));
1141 cmp_it->stop_pos = charpos - 1 - cmp_it->lookback;
1142 cmp_it->ch = c;
1143 return;
1144 }
1145 }
1146 }
1147 }
1148 else
1149 {
1150 /* Search backward for a pattern that may be composed and the
1151 position of (possibly) the last character of the match is
1152 closest to (but not after) START. The reason for the last
1153 character is that set_iterator_to_next works in reverse order,
1154 and thus we must stop at the last character for composition
1155 check. */
1156 unsigned char *p;
1157 int len;
1158 /* Limit byte position used in fast_looking_at. This is the
1159 byte position of the character after START. */
1160 EMACS_INT limit;
1161
1162 if (NILP (string))
1163 p = BYTE_POS_ADDR (bytepos);
1164 else
1165 p = SDATA (string) + bytepos;
1166 c = STRING_CHAR_AND_LENGTH (p, len);
1167 limit = bytepos + len;
1168 while (CHAR_COMPOSABLE_P (c))
1169 {
1170 for (val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1171 CONSP (val); val = XCDR (val))
1172 {
1173 Lisp_Object elt = XCAR (val);
1174 int back, len;
1175
1176 if (VECTORP (elt) && ASIZE (elt) == 3
1177 && NATNUMP (AREF (elt, 1))
1178 && charpos - (back = XFASTINT (AREF (elt, 1))) > endpos)
1179 {
1180 EMACS_INT cpos = charpos - back, bpos;
1181
1182 if (back == 0)
1183 bpos = bytepos;
1184 else
1185 bpos = (NILP (string) ? CHAR_TO_BYTE (cpos)
1186 : string_char_to_byte (string, cpos));
1187 if (STRINGP (AREF (elt, 0)))
1188 len = fast_looking_at (AREF (elt, 0), cpos, bpos,
1189 start + 1, limit, string);
1190 else
1191 len = 1;
1192 if (len > 0)
1193 {
1194 /* Make CPOS point to the last character of match.
1195 Note that LEN is byte-length. */
1196 bpos += len;
1197 if (NILP (string))
1198 cpos = BYTE_TO_CHAR (bpos) - 1;
1199 else
1200 cpos = string_byte_to_char (string, bpos) - 1;
1201 back = cpos - (charpos - back);
1202 if (cmp_it->stop_pos < cpos
1203 || (cmp_it->stop_pos == cpos
1204 && cmp_it->lookback < back))
1205 {
1206 cmp_it->stop_pos = cpos;
1207 cmp_it->ch = c;
1208 cmp_it->lookback = back;
1209 }
1210 }
1211 }
1212 }
1213 if (charpos - 1 == endpos)
1214 break;
1215 if (STRINGP (string))
1216 {
1217 p--, bytepos--;
1218 while (! CHAR_HEAD_P (*p))
1219 p--, bytepos--;
1220 charpos--;
1221 }
1222 else
1223 {
1224 DEC_BOTH (charpos, bytepos);
1225 p = BYTE_POS_ADDR (bytepos);
1226 }
1227 c = STRING_CHAR (p);
1228 }
1229 if (cmp_it->ch >= 0)
1230 /* We found a position to check. */
1231 return;
1232 /* Skip all uncomposable characters. */
1233 if (NILP (string))
1234 {
1235 while (charpos - 1 > endpos && ! CHAR_COMPOSABLE_P (c))
1236 {
1237 DEC_BOTH (charpos, bytepos);
1238 c = FETCH_MULTIBYTE_CHAR (bytepos);
1239 }
1240 }
1241 else
1242 {
1243 while (charpos - 1 > endpos && ! CHAR_COMPOSABLE_P (c))
1244 {
1245 p--;
1246 while (! CHAR_HEAD_P (*p))
1247 p--;
1248 charpos--;
1249 c = STRING_CHAR (p);
1250 }
1251 }
1252 }
1253 cmp_it->stop_pos = charpos;
1254 }
1255
1256 /* Check if the character at CHARPOS (and BYTEPOS) is composed
1257 (possibly with the following characters) on window W. ENDPOS limits
1258 characters to be composed. FACE, in non-NULL, is a base face of
1259 the character. If STRING is not nil, it is a string containing the
1260 character to check, and CHARPOS and BYTEPOS are indices in the
1261 string. In that case, FACE must not be NULL.
1262
1263 If the character is composed, setup members of CMP_IT (id, nglyphs,
1264 from, to, reversed_p), and return 1. Otherwise, update
1265 CMP_IT->stop_pos, and return 0. */
1266
1267 int
1268 composition_reseat_it (cmp_it, charpos, bytepos, endpos, w, face, string)
1269 struct composition_it *cmp_it;
1270 EMACS_INT charpos, bytepos, endpos;
1271 struct window *w;
1272 struct face *face;
1273 Lisp_Object string;
1274 {
1275 if (endpos <= charpos)
1276 {
1277 if (NILP (string))
1278 {
1279 if (endpos < 0)
1280 endpos = BEGV;
1281 if (endpos < PT && PT < charpos)
1282 endpos = PT;
1283 }
1284 else if (endpos < 0)
1285 endpos = 0;
1286 }
1287 else
1288 {
1289 if (NILP (string) && charpos < PT && PT < endpos)
1290 endpos = PT;
1291 }
1292
1293 if (cmp_it->ch == -2)
1294 {
1295 composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string);
1296 if (cmp_it->stop_pos != charpos)
1297 /* The current position is not composed. */
1298 return 0;
1299 }
1300
1301 if (cmp_it->ch < 0)
1302 {
1303 /* We are looking at a static composition. */
1304 EMACS_INT start, end;
1305 Lisp_Object prop;
1306
1307 find_composition (charpos, -1, &start, &end, &prop, string);
1308 cmp_it->id = get_composition_id (charpos, bytepos, end - start,
1309 prop, string);
1310 if (cmp_it->id < 0)
1311 goto no_composition;
1312 cmp_it->nchars = end - start;
1313 cmp_it->nglyphs = composition_table[cmp_it->id]->glyph_len;
1314 }
1315 else if (w)
1316 {
1317 Lisp_Object val, elt;
1318 int i;
1319
1320 val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch);
1321 if (charpos < endpos)
1322 {
1323 for (; CONSP (val); val = XCDR (val))
1324 {
1325 elt = XCAR (val);
1326 if (cmp_it->lookback == XFASTINT (AREF (elt, 1)))
1327 break;
1328 }
1329 if (NILP (val))
1330 goto no_composition;
1331
1332 val = autocmp_chars (val, charpos, bytepos, endpos, w, face, string);
1333 if (! composition_gstring_p (val))
1334 goto no_composition;
1335 cmp_it->reversed_p = 0;
1336 }
1337 else
1338 {
1339 EMACS_INT saved_charpos = charpos, saved_bytepos = bytepos;
1340
1341 if (cmp_it->lookback > 0)
1342 {
1343 charpos -= cmp_it->lookback;
1344 if (charpos < endpos)
1345 goto no_composition;
1346 if (STRINGP (string))
1347 bytepos = string_char_to_byte (string, charpos);
1348 else
1349 bytepos = CHAR_TO_BYTE (charpos);
1350 }
1351 val = autocmp_chars (val, charpos, bytepos, saved_charpos + 1,
1352 w, face, string);
1353 if (! composition_gstring_p (val)
1354 || charpos + LGSTRING_CHAR_LEN (val) <= saved_charpos)
1355 {
1356 charpos = saved_charpos, bytepos = saved_bytepos;
1357 goto no_composition;
1358 }
1359 cmp_it->reversed_p = 1;
1360 }
1361 if (NILP (LGSTRING_ID (val)))
1362 val = composition_gstring_put_cache (val, -1);
1363 cmp_it->id = XINT (LGSTRING_ID (val));
1364 for (i = 0; i < LGSTRING_GLYPH_LEN (val); i++)
1365 if (NILP (LGSTRING_GLYPH (val, i)))
1366 break;
1367 cmp_it->nglyphs = i;
1368 cmp_it->from = 0;
1369 cmp_it->to = i;
1370 }
1371 else
1372 goto no_composition;
1373 return 1;
1374
1375 no_composition:
1376 if (charpos == endpos)
1377 return 0;
1378 if (charpos < endpos)
1379 {
1380 charpos++;
1381 if (STRINGP (string))
1382 bytepos += MULTIBYTE_LENGTH_NO_CHECK (SDATA (string) + bytepos);
1383 else
1384 INC_POS (bytepos);
1385 }
1386 else
1387 {
1388 charpos--;
1389 /* BYTEPOS is calculated in composition_compute_stop_pos */
1390 bytepos = -1;
1391 }
1392 composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string);
1393 return 0;
1394 }
1395
1396 /* Update nchars, nbytes, and width of the current grapheme cluster
1397 which is identified by CMP_IT->from (if the composition is static
1398 or automatic in l2r context) or CMPT_IT->to (if the composition is
1399 automatic in r2l context). In addition, in the former case, update
1400 CMP_IT->to, and in the latter case, update CMP_IT->from. */
1401
1402 int
1403 composition_update_it (cmp_it, charpos, bytepos, string)
1404 struct composition_it *cmp_it;
1405 EMACS_INT charpos, bytepos;
1406 Lisp_Object string;
1407 {
1408 int i, c;
1409
1410 if (cmp_it->ch < 0)
1411 {
1412 struct composition *cmp = composition_table[cmp_it->id];
1413
1414 cmp_it->to = cmp_it->nglyphs;
1415 if (cmp_it->nglyphs == 0)
1416 c = -1;
1417 else
1418 {
1419 for (i = 0; i < cmp->glyph_len; i++)
1420 if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
1421 break;
1422 if (c == '\t')
1423 c = ' ';
1424 }
1425 cmp_it->width = cmp->width;
1426 }
1427 else
1428 {
1429 Lisp_Object gstring = composition_gstring_from_id (cmp_it->id);
1430
1431 if (cmp_it->nglyphs == 0)
1432 {
1433 c = -1;
1434 cmp_it->nchars = LGSTRING_CHAR_LEN (gstring);
1435 cmp_it->width = 0;
1436 }
1437 else if (! cmp_it->reversed_p)
1438 {
1439 Lisp_Object glyph = LGSTRING_GLYPH (gstring, cmp_it->from);
1440 int from = LGLYPH_FROM (glyph);
1441
1442 c = XINT (LGSTRING_CHAR (gstring, from));
1443 cmp_it->nchars = LGLYPH_TO (glyph) - from + 1;
1444 cmp_it->width = (LGLYPH_WIDTH (glyph) > 0
1445 ? CHAR_WIDTH (LGLYPH_CHAR (glyph)) : 0);
1446 for (cmp_it->to = cmp_it->from + 1; cmp_it->to < cmp_it->nglyphs;
1447 cmp_it->to++)
1448 {
1449 glyph = LGSTRING_GLYPH (gstring, cmp_it->to);
1450 if (LGLYPH_FROM (glyph) != from)
1451 break;
1452 if (LGLYPH_WIDTH (glyph) > 0)
1453 cmp_it->width += CHAR_WIDTH (LGLYPH_CHAR (glyph));
1454 }
1455 }
1456 else
1457 {
1458 int from_idx = cmp_it->to - 1;
1459 Lisp_Object glyph = LGSTRING_GLYPH (gstring, from_idx);
1460 int from = LGLYPH_FROM (glyph);
1461
1462 c = XINT (LGSTRING_CHAR (gstring, from));
1463 cmp_it->nchars = LGLYPH_TO (glyph) - from + 1;
1464 cmp_it->width = (LGLYPH_WIDTH (glyph) > 0
1465 ? CHAR_WIDTH (LGLYPH_CHAR (glyph)) : 0);
1466 for (from_idx--; from_idx >= 0; from_idx--)
1467 {
1468 glyph = LGSTRING_GLYPH (gstring, from_idx);
1469 if (LGLYPH_FROM (glyph) != from)
1470 break;
1471 if (LGLYPH_WIDTH (glyph) > 0)
1472 cmp_it->width += CHAR_WIDTH (LGLYPH_CHAR (glyph));
1473 }
1474 cmp_it->from = from_idx + 1;
1475 charpos -= cmp_it->nchars - 1;
1476 bytepos += CHAR_BYTES (c);
1477 if (STRINGP (string))
1478 cmp_it->nbytes = bytepos - string_char_to_byte (string, charpos);
1479 else
1480 cmp_it->nbytes = bytepos - CHAR_TO_BYTE (charpos);
1481 return c;
1482 }
1483 }
1484
1485 charpos += cmp_it->nchars;
1486 if (STRINGP (string))
1487 cmp_it->nbytes = string_char_to_byte (string, charpos) - bytepos;
1488 else
1489 cmp_it->nbytes = CHAR_TO_BYTE (charpos) - bytepos;
1490 return c;
1491 }
1492
1493
1494 struct position_record
1495 {
1496 EMACS_INT pos, pos_byte;
1497 unsigned char *p;
1498 };
1499
1500 /* Update the members of POSITION to the next character boundary. */
1501 #define FORWARD_CHAR(POSITION, STOP) \
1502 do { \
1503 (POSITION).pos++; \
1504 if ((POSITION).pos == (STOP)) \
1505 { \
1506 (POSITION).p = GAP_END_ADDR; \
1507 (POSITION).pos_byte = GPT_BYTE; \
1508 } \
1509 else \
1510 { \
1511 (POSITION).pos_byte += BYTES_BY_CHAR_HEAD (*((POSITION).p)); \
1512 (POSITION).p += BYTES_BY_CHAR_HEAD (*((POSITION).p)); \
1513 } \
1514 } while (0)
1515
1516 /* Update the members of POSITION to the previous character boundary. */
1517 #define BACKWARD_CHAR(POSITION, STOP) \
1518 do { \
1519 if ((POSITION).pos == STOP) \
1520 (POSITION).p = GPT_ADDR; \
1521 do { \
1522 (POSITION).pos_byte--; \
1523 (POSITION).p--; \
1524 } while (! CHAR_HEAD_P (*((POSITION).p))); \
1525 (POSITION).pos--; \
1526 } while (0)
1527
1528 /* This is like find_composition, but find an automatic composition
1529 instead. If found, set *GSTRING to the glyph-string representing
1530 the composition, and return 1. Otherwise, return 0. */
1531
1532 static int
1533 find_automatic_composition (pos, limit, start, end, gstring, string)
1534 EMACS_INT pos, limit, *start, *end;
1535 Lisp_Object *gstring, string;
1536 {
1537 EMACS_INT head, tail, stop;
1538 /* Limit to check a composition after POS. */
1539 EMACS_INT fore_check_limit;
1540 struct position_record orig, cur, check, prev;
1541 Lisp_Object check_val, val, elt;
1542 int check_lookback;
1543 int c;
1544 Lisp_Object window;
1545 struct window *w;
1546
1547 window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
1548 if (NILP (window))
1549 return 0;
1550 w = XWINDOW (window);
1551
1552 orig.pos = pos;
1553 if (NILP (string))
1554 {
1555 head = BEGV, tail = ZV, stop = GPT;
1556 orig.pos_byte = CHAR_TO_BYTE (orig.pos);
1557 orig.p = BYTE_POS_ADDR (orig.pos_byte);
1558 }
1559 else
1560 {
1561 head = 0, tail = SCHARS (string), stop = -1;
1562 orig.pos_byte = string_char_to_byte (string, orig.pos);
1563 orig.p = SDATA (string) + orig.pos_byte;
1564 }
1565 if (limit < pos)
1566 fore_check_limit = min (tail, pos + MAX_AUTO_COMPOSITION_LOOKBACK);
1567 else
1568 fore_check_limit = min (tail, limit + MAX_AUTO_COMPOSITION_LOOKBACK);
1569 cur = orig;
1570
1571 retry:
1572 check_val = Qnil;
1573 /* At first, check if POS is composable. */
1574 c = STRING_CHAR (cur.p);
1575 if (! CHAR_COMPOSABLE_P (c))
1576 {
1577 if (limit < 0)
1578 return 0;
1579 if (limit >= cur.pos)
1580 goto search_forward;
1581 }
1582 else
1583 {
1584 val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1585 if (! NILP (val))
1586 check_val = val, check = cur;
1587 else
1588 while (cur.pos + 1 < fore_check_limit)
1589 {
1590 EMACS_INT b, e;
1591
1592 FORWARD_CHAR (cur, stop);
1593 if (get_property_and_range (cur.pos, Qcomposition, &val, &b, &e,
1594 Qnil)
1595 && COMPOSITION_VALID_P (b, e, val))
1596 {
1597 fore_check_limit = cur.pos;
1598 break;
1599 }
1600 c = STRING_CHAR (cur.p);
1601 if (! CHAR_COMPOSABLE_P (c))
1602 break;
1603 val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1604 if (NILP (val))
1605 continue;
1606 check_val = val, check = cur;
1607 break;
1608 }
1609 cur = orig;
1610 }
1611 /* Rewind back to the position where we can safely search forward
1612 for compositions. */
1613 while (cur.pos > head)
1614 {
1615 EMACS_INT b, e;
1616
1617 BACKWARD_CHAR (cur, stop);
1618 if (get_property_and_range (cur.pos, Qcomposition, &val, &b, &e, Qnil)
1619 && COMPOSITION_VALID_P (b, e, val))
1620 break;
1621 c = STRING_CHAR (cur.p);
1622 if (! CHAR_COMPOSABLE_P (c))
1623 break;
1624 val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1625 if (! NILP (val))
1626 check_val = val, check = cur;
1627 }
1628 prev = cur;
1629 /* Now search forward. */
1630 search_forward:
1631 *gstring = Qnil;
1632 if (! NILP (check_val) || limit >= orig.pos)
1633 {
1634 if (NILP (check_val))
1635 cur = orig;
1636 else
1637 cur = check;
1638 while (cur.pos < fore_check_limit)
1639 {
1640 int need_adjustment = 0;
1641
1642 if (NILP (check_val))
1643 {
1644 c = STRING_CHAR (cur.p);
1645 check_val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1646 }
1647 for (; CONSP (check_val); check_val = XCDR (check_val))
1648 {
1649 elt = XCAR (check_val);
1650 if (VECTORP (elt) && ASIZE (elt) == 3 && NATNUMP (AREF (elt, 1))
1651 && cur.pos - XFASTINT (AREF (elt, 1)) >= head)
1652 {
1653 check.pos = cur.pos - XFASTINT (AREF (elt, 1));
1654 if (check.pos == cur.pos)
1655 check.pos_byte = cur.pos_byte;
1656 else
1657 check.pos_byte = CHAR_TO_BYTE (check.pos);
1658 val = autocmp_chars (check_val, check.pos, check.pos_byte,
1659 tail, w, NULL, string);
1660 need_adjustment = 1;
1661 if (! NILP (val))
1662 {
1663 *gstring = val;
1664 *start = check.pos;
1665 *end = check.pos + LGSTRING_CHAR_LEN (*gstring);
1666 if (*start <= orig.pos ? *end > orig.pos
1667 : limit >= orig.pos)
1668 return 1;
1669 cur.pos = *end;
1670 cur.pos_byte = CHAR_TO_BYTE (cur.pos);
1671 break;
1672 }
1673 }
1674 }
1675 if (need_adjustment)
1676 {
1677 /* As we have called Lisp, there's a possibility that
1678 buffer/string is relocated. */
1679 if (NILP (string))
1680 cur.p = BYTE_POS_ADDR (cur.pos_byte);
1681 else
1682 cur.p = SDATA (string) + cur.pos_byte;
1683 }
1684 if (! CONSP (check_val))
1685 FORWARD_CHAR (cur, stop);
1686 check_val = Qnil;
1687 }
1688 }
1689 if (! NILP (*gstring))
1690 return (limit >= 0 || (*start <= orig.pos && *end > orig.pos));
1691 if (limit >= 0 && limit < orig.pos && prev.pos > head)
1692 {
1693 cur = prev;
1694 BACKWARD_CHAR (cur, stop);
1695 orig = cur;
1696 fore_check_limit = orig.pos;
1697 goto retry;
1698 }
1699 return 0;
1700 }
1701
1702 /* Return the adjusted point provided that point is moved from LAST_PT
1703 to NEW_PT. */
1704
1705 int
1706 composition_adjust_point (last_pt, new_pt)
1707 EMACS_INT last_pt, new_pt;
1708 {
1709 EMACS_INT charpos, bytepos, startpos, beg, end, pos;
1710 Lisp_Object val;
1711 int i;
1712
1713 if (new_pt == BEGV || new_pt == ZV)
1714 return new_pt;
1715
1716 /* At first check the static composition. */
1717 if (get_property_and_range (new_pt, Qcomposition, &val, &beg, &end, Qnil)
1718 && COMPOSITION_VALID_P (beg, end, val))
1719 {
1720 if (beg < new_pt /* && end > new_pt <- It's always the case. */
1721 && (last_pt <= beg || last_pt >= end))
1722 return (new_pt < last_pt ? beg : end);
1723 return new_pt;
1724 }
1725
1726 if (NILP (current_buffer->enable_multibyte_characters)
1727 || NILP (Vauto_composition_mode))
1728 return new_pt;
1729
1730 /* Next check the automatic composition. */
1731 if (! find_automatic_composition (new_pt, (EMACS_INT) -1, &beg, &end, &val,
1732 Qnil)
1733 || beg == new_pt)
1734 return new_pt;
1735 for (i = 0; i < LGSTRING_GLYPH_LEN (val); i++)
1736 {
1737 Lisp_Object glyph = LGSTRING_GLYPH (val, i);
1738
1739 if (NILP (glyph))
1740 break;
1741 if (beg + LGLYPH_FROM (glyph) == new_pt)
1742 return new_pt;
1743 if (beg + LGLYPH_TO (glyph) >= new_pt)
1744 return (new_pt < last_pt
1745 ? beg + LGLYPH_FROM (glyph)
1746 : beg + LGLYPH_TO (glyph) + 1);
1747 }
1748 return new_pt;
1749 }
1750
1751 DEFUN ("composition-get-gstring", Fcomposition_get_gstring,
1752 Scomposition_get_gstring, 4, 4, 0,
1753 doc: /* Return a glyph-string for characters between FROM and TO.
1754 If the glyph string is for graphic display, FONT-OBJECT must be
1755 a font-object to use for those characters.
1756 Otherwise (for terminal display), FONT-OBJECT must be a terminal ID, a
1757 frame, or nil for the selected frame's terminal device.
1758
1759 If the optional 4th argument STRING is not nil, it is a string
1760 containing the target characters between indices FROM and TO.
1761
1762 A glyph-string is a vector containing information about how to display
1763 a specific character sequence. The format is:
1764 [HEADER ID GLYPH ...]
1765
1766 HEADER is a vector of this form:
1767 [FONT-OBJECT CHAR ...]
1768 where
1769 FONT-OBJECT is a font-object for all glyphs in the glyph-string,
1770 or the terminal coding system of the specified terminal.
1771 CHARs are characters to be composed by GLYPHs.
1772
1773 ID is an identification number of the glyph-string. It may be nil if
1774 not yet shaped.
1775
1776 GLYPH is a vector whose elements have this form:
1777 [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
1778 [ [X-OFF Y-OFF WADJUST] | nil] ]
1779 where
1780 FROM-IDX and TO-IDX are used internally and should not be touched.
1781 C is the character of the glyph.
1782 CODE is the glyph-code of C in FONT-OBJECT.
1783 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
1784 X-OFF and Y-OFF are offsets to the base position for the glyph.
1785 WADJUST is the adjustment to the normal width of the glyph.
1786
1787 If GLYPH is nil, the remaining elements of the glyph-string vector
1788 should be ignored. */)
1789 (from, to, font_object, string)
1790 Lisp_Object font_object, from, to, string;
1791 {
1792 Lisp_Object gstring, header;
1793 EMACS_INT frompos, topos;
1794
1795 CHECK_NATNUM (from);
1796 CHECK_NATNUM (to);
1797 if (XINT (to) > XINT (from) + MAX_COMPOSITION_COMPONENTS)
1798 to = make_number (XINT (from) + MAX_COMPOSITION_COMPONENTS);
1799 if (! FONT_OBJECT_P (font_object))
1800 {
1801 struct coding_system *coding;
1802 struct terminal *terminal = get_terminal (font_object, 1);
1803
1804 coding = ((TERMINAL_TERMINAL_CODING (terminal)->common_flags
1805 & CODING_REQUIRE_ENCODING_MASK)
1806 ? TERMINAL_TERMINAL_CODING (terminal) : &safe_terminal_coding);
1807 font_object = CODING_ID_NAME (coding->id);
1808 }
1809
1810 header = fill_gstring_header (Qnil, from, to, font_object, string);
1811 gstring = gstring_lookup_cache (header);
1812 if (! NILP (gstring))
1813 return gstring;
1814
1815 frompos = XINT (from);
1816 topos = XINT (to);
1817 if (LGSTRING_GLYPH_LEN (gstring_work) < topos - frompos)
1818 gstring_work = Fmake_vector (make_number (topos - frompos + 2), Qnil);
1819 LGSTRING_SET_HEADER (gstring_work, header);
1820 LGSTRING_SET_ID (gstring_work, Qnil);
1821 fill_gstring_body (gstring_work);
1822 return gstring_work;
1823 }
1824
1825 \f
1826 /* Emacs Lisp APIs. */
1827
1828 DEFUN ("compose-region-internal", Fcompose_region_internal,
1829 Scompose_region_internal, 2, 4, 0,
1830 doc: /* Internal use only.
1831
1832 Compose text in the region between START and END.
1833 Optional 3rd and 4th arguments are COMPONENTS and MODIFICATION-FUNC
1834 for the composition. See `compose-region' for more details. */)
1835 (start, end, components, modification_func)
1836 Lisp_Object start, end, components, modification_func;
1837 {
1838 validate_region (&start, &end);
1839 if (!NILP (components)
1840 && !INTEGERP (components)
1841 && !CONSP (components)
1842 && !STRINGP (components))
1843 CHECK_VECTOR (components);
1844
1845 compose_text (XINT (start), XINT (end), components, modification_func, Qnil);
1846 return Qnil;
1847 }
1848
1849 DEFUN ("compose-string-internal", Fcompose_string_internal,
1850 Scompose_string_internal, 3, 5, 0,
1851 doc: /* Internal use only.
1852
1853 Compose text between indices START and END of STRING.
1854 Optional 4th and 5th arguments are COMPONENTS and MODIFICATION-FUNC
1855 for the composition. See `compose-string' for more details. */)
1856 (string, start, end, components, modification_func)
1857 Lisp_Object string, start, end, components, modification_func;
1858 {
1859 CHECK_STRING (string);
1860 CHECK_NUMBER (start);
1861 CHECK_NUMBER (end);
1862
1863 if (XINT (start) < 0 ||
1864 XINT (start) > XINT (end)
1865 || XINT (end) > SCHARS (string))
1866 args_out_of_range (start, end);
1867
1868 compose_text (XINT (start), XINT (end), components, modification_func, string);
1869 return string;
1870 }
1871
1872 DEFUN ("find-composition-internal", Ffind_composition_internal,
1873 Sfind_composition_internal, 4, 4, 0,
1874 doc: /* Internal use only.
1875
1876 Return information about composition at or nearest to position POS.
1877 See `find-composition' for more details. */)
1878 (pos, limit, string, detail_p)
1879 Lisp_Object pos, limit, string, detail_p;
1880 {
1881 Lisp_Object prop, tail, gstring;
1882 EMACS_INT start, end, from, to;
1883 int id;
1884
1885 CHECK_NUMBER_COERCE_MARKER (pos);
1886 from = XINT (pos);
1887 if (!NILP (limit))
1888 {
1889 CHECK_NUMBER_COERCE_MARKER (limit);
1890 to = XINT (limit);
1891 }
1892 else
1893 to = -1;
1894
1895 if (!NILP (string))
1896 {
1897 CHECK_STRING (string);
1898 if (XINT (pos) < 0 || XINT (pos) > SCHARS (string))
1899 args_out_of_range (string, pos);
1900 }
1901 else
1902 {
1903 if (XINT (pos) < BEGV || XINT (pos) > ZV)
1904 args_out_of_range (Fcurrent_buffer (), pos);
1905 }
1906
1907 if (!find_composition (from, to, &start, &end, &prop, string))
1908 {
1909 if (!NILP (current_buffer->enable_multibyte_characters)
1910 && ! NILP (Vauto_composition_mode)
1911 && find_automatic_composition (from, to, &start, &end, &gstring,
1912 string))
1913 return list3 (make_number (start), make_number (end), gstring);
1914 return Qnil;
1915 }
1916 if ((end <= XINT (pos) || start > XINT (pos)))
1917 {
1918 EMACS_INT s, e;
1919
1920 if (find_automatic_composition (from, to, &s, &e, &gstring, string)
1921 && (e <= XINT (pos) ? e > end : s < start))
1922 return list3 (make_number (s), make_number (e), gstring);
1923 }
1924 if (!COMPOSITION_VALID_P (start, end, prop))
1925 return Fcons (make_number (start), Fcons (make_number (end),
1926 Fcons (Qnil, Qnil)));
1927 if (NILP (detail_p))
1928 return Fcons (make_number (start), Fcons (make_number (end),
1929 Fcons (Qt, Qnil)));
1930
1931 if (COMPOSITION_REGISTERD_P (prop))
1932 id = COMPOSITION_ID (prop);
1933 else
1934 {
1935 int start_byte = (NILP (string)
1936 ? CHAR_TO_BYTE (start)
1937 : string_char_to_byte (string, start));
1938 id = get_composition_id (start, start_byte, end - start, prop, string);
1939 }
1940
1941 if (id >= 0)
1942 {
1943 Lisp_Object components, relative_p, mod_func;
1944 enum composition_method method = COMPOSITION_METHOD (prop);
1945 int width = composition_table[id]->width;
1946
1947 components = Fcopy_sequence (COMPOSITION_COMPONENTS (prop));
1948 relative_p = (method == COMPOSITION_WITH_RULE_ALTCHARS
1949 ? Qnil : Qt);
1950 mod_func = COMPOSITION_MODIFICATION_FUNC (prop);
1951 tail = Fcons (components,
1952 Fcons (relative_p,
1953 Fcons (mod_func,
1954 Fcons (make_number (width), Qnil))));
1955 }
1956 else
1957 tail = Qnil;
1958
1959 return Fcons (make_number (start), Fcons (make_number (end), tail));
1960 }
1961
1962 \f
1963 void
1964 syms_of_composite ()
1965 {
1966 int i;
1967
1968 Qcomposition = intern_c_string ("composition");
1969 staticpro (&Qcomposition);
1970
1971 /* Make a hash table for static composition. */
1972 {
1973 Lisp_Object args[6];
1974 extern Lisp_Object QCsize;
1975
1976 args[0] = QCtest;
1977 args[1] = Qequal;
1978 args[2] = QCweakness;
1979 /* We used to make the hash table weak so that unreferenced
1980 compositions can be garbage-collected. But, usually once
1981 created compositions are repeatedly used in an Emacs session,
1982 and thus it's not worth to save memory in such a way. So, we
1983 make the table not weak. */
1984 args[3] = Qnil;
1985 args[4] = QCsize;
1986 args[5] = make_number (311);
1987 composition_hash_table = Fmake_hash_table (6, args);
1988 staticpro (&composition_hash_table);
1989 }
1990
1991 /* Make a hash table for glyph-string. */
1992 {
1993 Lisp_Object args[6];
1994 extern Lisp_Object QCsize;
1995
1996 args[0] = QCtest;
1997 args[1] = Qequal;
1998 args[2] = QCweakness;
1999 args[3] = Qnil;
2000 args[4] = QCsize;
2001 args[5] = make_number (311);
2002 gstring_hash_table = Fmake_hash_table (6, args);
2003 staticpro (&gstring_hash_table);
2004 }
2005
2006 staticpro (&gstring_work_headers);
2007 gstring_work_headers = Fmake_vector (make_number (8), Qnil);
2008 for (i = 0; i < 8; i++)
2009 ASET (gstring_work_headers, i, Fmake_vector (make_number (i + 2), Qnil));
2010 staticpro (&gstring_work);
2011 gstring_work = Fmake_vector (make_number (10), Qnil);
2012
2013 /* Text property `composition' should be nonsticky by default. */
2014 Vtext_property_default_nonsticky
2015 = Fcons (Fcons (Qcomposition, Qt), Vtext_property_default_nonsticky);
2016
2017 DEFVAR_LISP ("compose-chars-after-function", &Vcompose_chars_after_function,
2018 doc: /* Function to adjust composition of buffer text.
2019
2020 This function is called with three arguments: FROM, TO, and OBJECT.
2021 FROM and TO specify the range of text whose composition should be
2022 adjusted. OBJECT, if non-nil, is a string that contains the text.
2023
2024 This function is called after a text with `composition' property is
2025 inserted or deleted to keep `composition' property of buffer text
2026 valid.
2027
2028 The default value is the function `compose-chars-after'. */);
2029 Vcompose_chars_after_function = intern_c_string ("compose-chars-after");
2030
2031 Qauto_composed = intern_c_string ("auto-composed");
2032 staticpro (&Qauto_composed);
2033
2034 Qauto_composition_function = intern_c_string ("auto-composition-function");
2035 staticpro (&Qauto_composition_function);
2036
2037 DEFVAR_LISP ("auto-composition-mode", &Vauto_composition_mode,
2038 doc: /* Non-nil if Auto-Composition mode is enabled.
2039 Use the command `auto-composition-mode' to change this variable. */);
2040 Vauto_composition_mode = Qt;
2041
2042 DEFVAR_LISP ("auto-composition-function", &Vauto_composition_function,
2043 doc: /* Function to call to compose characters automatically.
2044 This function is called from the display routine with four arguments:
2045 FROM, TO, WINDOW, and STRING.
2046
2047 If STRING is nil, the function must compose characters in the region
2048 between FROM and TO in the current buffer.
2049
2050 Otherwise, STRING is a string, and FROM and TO are indices into the
2051 string. In this case, the function must compose characters in the
2052 string. */);
2053 Vauto_composition_function = Qnil;
2054
2055 DEFVAR_LISP ("composition-function-table", &Vcomposition_function_table,
2056 doc: /* Char-table of functions for automatic character composition.
2057 For each character that has to be composed automatically with
2058 preceding and/or following characters, this char-table contains
2059 a function to call to compose that character.
2060
2061 The element at index C in the table, if non-nil, is a list of
2062 this form: ([PATTERN PREV-CHARS FUNC] ...)
2063
2064 PATTERN is a regular expression which C and the surrounding
2065 characters must match.
2066
2067 PREV-CHARS is a non-negative integer (less than 4) specifying how many
2068 characters before C to check the matching with PATTERN. If it is 0,
2069 PATTERN must match C and the following characters. If it is 1,
2070 PATTERN must match a character before C and the following characters.
2071
2072 If PREV-CHARS is 0, PATTERN can be nil, which means that the
2073 single character C should be composed.
2074
2075 FUNC is a function to return a glyph-string representing a
2076 composition of the characters that match PATTERN. It is
2077 called with one argument GSTRING.
2078
2079 GSTRING is a template of a glyph-string to return. It is already
2080 filled with a proper header for the characters to compose, and
2081 glyphs corresponding to those characters one by one. The
2082 function must return a new glyph-string with the same header as
2083 GSTRING, or modify GSTRING itself and return it.
2084
2085 See also the documentation of `auto-composition-mode'. */);
2086 Vcomposition_function_table = Fmake_char_table (Qnil, Qnil);
2087
2088 defsubr (&Scompose_region_internal);
2089 defsubr (&Scompose_string_internal);
2090 defsubr (&Sfind_composition_internal);
2091 defsubr (&Scomposition_get_gstring);
2092 }
2093
2094 /* arch-tag: 79cefaf8-ca48-4eed-97e5-d5afb290d272
2095 (do not change this comment) */