diff options
| author | Joakim Verona | 2011-06-16 00:22:07 +0200 |
|---|---|---|
| committer | Joakim Verona | 2011-06-16 00:22:07 +0200 |
| commit | a7513ade3bc0fe79430d5541d88c9dcda0932bec (patch) | |
| tree | 4383951ba698a11e9f8933a9d8c72e00aa872a10 /src/composite.c | |
| parent | 4bd51ad5c3445b644dfb017d5b57b10a90aa325f (diff) | |
| parent | 4bba86e6210a74326e843a8fdc8409127105e1fe (diff) | |
| download | emacs-a7513ade3bc0fe79430d5541d88c9dcda0932bec.tar.gz emacs-a7513ade3bc0fe79430d5541d88c9dcda0932bec.zip | |
merge from upstream
Diffstat (limited to 'src/composite.c')
| -rw-r--r-- | src/composite.c | 349 |
1 files changed, 188 insertions, 161 deletions
diff --git a/src/composite.c b/src/composite.c index 58bc68597cc..51b7669cb4f 100644 --- a/src/composite.c +++ b/src/composite.c | |||
| @@ -152,13 +152,14 @@ int n_compositions; | |||
| 152 | COMPOSITION-ID. */ | 152 | COMPOSITION-ID. */ |
| 153 | Lisp_Object composition_hash_table; | 153 | Lisp_Object composition_hash_table; |
| 154 | 154 | ||
| 155 | Lisp_Object Qauto_composed; | 155 | static Lisp_Object Qauto_composed; |
| 156 | Lisp_Object Qauto_composition_function; | 156 | static Lisp_Object Qauto_composition_function; |
| 157 | /* Maximum number of characters to look back for | 157 | /* Maximum number of characters to look back for |
| 158 | auto-compositions. */ | 158 | auto-compositions. */ |
| 159 | #define MAX_AUTO_COMPOSITION_LOOKBACK 3 | 159 | #define MAX_AUTO_COMPOSITION_LOOKBACK 3 |
| 160 | 160 | ||
| 161 | EXFUN (Fremove_list_of_text_properties, 4); | 161 | static Lisp_Object Fcomposition_get_gstring (Lisp_Object, Lisp_Object, |
| 162 | Lisp_Object, Lisp_Object); | ||
| 162 | 163 | ||
| 163 | /* Temporary variable used in macros COMPOSITION_XXX. */ | 164 | /* Temporary variable used in macros COMPOSITION_XXX. */ |
| 164 | Lisp_Object composition_temp; | 165 | Lisp_Object composition_temp; |
| @@ -178,8 +179,8 @@ get_composition_id (EMACS_INT charpos, EMACS_INT bytepos, EMACS_INT nchars, | |||
| 178 | Lisp_Object id, length, components, key, *key_contents; | 179 | Lisp_Object id, length, components, key, *key_contents; |
| 179 | int glyph_len; | 180 | int glyph_len; |
| 180 | struct Lisp_Hash_Table *hash_table = XHASH_TABLE (composition_hash_table); | 181 | struct Lisp_Hash_Table *hash_table = XHASH_TABLE (composition_hash_table); |
| 181 | int hash_index; | 182 | EMACS_INT hash_index; |
| 182 | unsigned hash_code; | 183 | EMACS_UINT hash_code; |
| 183 | struct composition *cmp; | 184 | struct composition *cmp; |
| 184 | EMACS_INT i; | 185 | EMACS_INT i; |
| 185 | int ch; | 186 | int ch; |
| @@ -292,7 +293,7 @@ get_composition_id (EMACS_INT charpos, EMACS_INT bytepos, EMACS_INT nchars, | |||
| 292 | } | 293 | } |
| 293 | else if (VECTORP (components) || CONSP (components)) | 294 | else if (VECTORP (components) || CONSP (components)) |
| 294 | { | 295 | { |
| 295 | EMACS_UINT len = XVECTOR (key)->size; | 296 | EMACS_UINT len = ASIZE (key); |
| 296 | 297 | ||
| 297 | /* The number of elements should be odd. */ | 298 | /* The number of elements should be odd. */ |
| 298 | if ((len % 2) == 0) | 299 | if ((len % 2) == 0) |
| @@ -325,8 +326,8 @@ get_composition_id (EMACS_INT charpos, EMACS_INT bytepos, EMACS_INT nchars, | |||
| 325 | : COMPOSITION_WITH_RULE_ALTCHARS)); | 326 | : COMPOSITION_WITH_RULE_ALTCHARS)); |
| 326 | cmp->hash_index = hash_index; | 327 | cmp->hash_index = hash_index; |
| 327 | glyph_len = (cmp->method == COMPOSITION_WITH_RULE_ALTCHARS | 328 | glyph_len = (cmp->method == COMPOSITION_WITH_RULE_ALTCHARS |
| 328 | ? (XVECTOR (key)->size + 1) / 2 | 329 | ? (ASIZE (key) + 1) / 2 |
| 329 | : XVECTOR (key)->size); | 330 | : ASIZE (key)); |
| 330 | cmp->glyph_len = glyph_len; | 331 | cmp->glyph_len = glyph_len; |
| 331 | cmp->offsets = (short *) xmalloc (sizeof (short) * glyph_len * 2); | 332 | cmp->offsets = (short *) xmalloc (sizeof (short) * glyph_len * 2); |
| 332 | cmp->font = NULL; | 333 | cmp->font = NULL; |
| @@ -354,7 +355,7 @@ get_composition_id (EMACS_INT charpos, EMACS_INT bytepos, EMACS_INT nchars, | |||
| 354 | 355 | ||
| 355 | for (i = 1; i < glyph_len; i += 2) | 356 | for (i = 1; i < glyph_len; i += 2) |
| 356 | { | 357 | { |
| 357 | int rule, gref, nref, xoff, yoff; | 358 | int rule, gref, nref; |
| 358 | int this_width; | 359 | int this_width; |
| 359 | float this_left; | 360 | float this_left; |
| 360 | 361 | ||
| @@ -376,7 +377,7 @@ get_composition_id (EMACS_INT charpos, EMACS_INT bytepos, EMACS_INT nchars, | |||
| 376 | | | | 377 | | | |
| 377 | 6---7---8 -- descent | 378 | 6---7---8 -- descent |
| 378 | */ | 379 | */ |
| 379 | COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff); | 380 | COMPOSITION_DECODE_REFS (rule, gref, nref); |
| 380 | this_left = (leftmost | 381 | this_left = (leftmost |
| 381 | + (gref % 3) * (rightmost - leftmost) / 2.0 | 382 | + (gref % 3) * (rightmost - leftmost) / 2.0 |
| 382 | - (nref % 3) * this_width / 2.0); | 383 | - (nref % 3) * this_width / 2.0); |
| @@ -655,28 +656,28 @@ static Lisp_Object | |||
| 655 | gstring_lookup_cache (Lisp_Object header) | 656 | gstring_lookup_cache (Lisp_Object header) |
| 656 | { | 657 | { |
| 657 | struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table); | 658 | struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table); |
| 658 | int i = hash_lookup (h, header, NULL); | 659 | EMACS_INT i = hash_lookup (h, header, NULL); |
| 659 | 660 | ||
| 660 | return (i >= 0 ? HASH_VALUE (h, i) : Qnil); | 661 | return (i >= 0 ? HASH_VALUE (h, i) : Qnil); |
| 661 | } | 662 | } |
| 662 | 663 | ||
| 663 | Lisp_Object | 664 | Lisp_Object |
| 664 | composition_gstring_put_cache (Lisp_Object gstring, int len) | 665 | composition_gstring_put_cache (Lisp_Object gstring, EMACS_INT len) |
| 665 | { | 666 | { |
| 666 | struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table); | 667 | struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table); |
| 667 | unsigned hash; | 668 | EMACS_UINT hash; |
| 668 | Lisp_Object header, copy; | 669 | Lisp_Object header, copy; |
| 669 | int i; | 670 | EMACS_INT i; |
| 670 | 671 | ||
| 671 | header = LGSTRING_HEADER (gstring); | 672 | header = LGSTRING_HEADER (gstring); |
| 672 | hash = h->hashfn (h, header); | 673 | hash = h->hashfn (h, header); |
| 673 | if (len < 0) | 674 | if (len < 0) |
| 674 | { | 675 | { |
| 675 | len = LGSTRING_GLYPH_LEN (gstring); | 676 | EMACS_UINT j, glyph_len = LGSTRING_GLYPH_LEN (gstring); |
| 676 | for (i = 0; i < len; i++) | 677 | for (j = 0; j < glyph_len; j++) |
| 677 | if (NILP (LGSTRING_GLYPH (gstring, i))) | 678 | if (NILP (LGSTRING_GLYPH (gstring, j))) |
| 678 | break; | 679 | break; |
| 679 | len = i; | 680 | len = j; |
| 680 | } | 681 | } |
| 681 | 682 | ||
| 682 | copy = Fmake_vector (make_number (len + 2), Qnil); | 683 | copy = Fmake_vector (make_number (len + 2), Qnil); |
| @@ -796,7 +797,7 @@ fill_gstring_header (Lisp_Object header, Lisp_Object start, Lisp_Object end, Lis | |||
| 796 | 797 | ||
| 797 | if (NILP (string)) | 798 | if (NILP (string)) |
| 798 | { | 799 | { |
| 799 | if (NILP (current_buffer->enable_multibyte_characters)) | 800 | if (NILP (BVAR (current_buffer, enable_multibyte_characters))) |
| 800 | error ("Attempt to shape unibyte text"); | 801 | error ("Attempt to shape unibyte text"); |
| 801 | validate_region (&start, &end); | 802 | validate_region (&start, &end); |
| 802 | from = XFASTINT (start); | 803 | from = XFASTINT (start); |
| @@ -857,7 +858,7 @@ fill_gstring_body (Lisp_Object gstring) | |||
| 857 | for (i = 0; i < len; i++) | 858 | for (i = 0; i < len; i++) |
| 858 | { | 859 | { |
| 859 | Lisp_Object g = LGSTRING_GLYPH (gstring, i); | 860 | Lisp_Object g = LGSTRING_GLYPH (gstring, i); |
| 860 | EMACS_INT c = XINT (AREF (header, i + 1)); | 861 | int c = XFASTINT (AREF (header, i + 1)); |
| 861 | 862 | ||
| 862 | if (NILP (g)) | 863 | if (NILP (g)) |
| 863 | { | 864 | { |
| @@ -971,11 +972,12 @@ static int _work_char; | |||
| 971 | category Z? or C? are not composable except for ZWNJ and ZWJ. */ | 972 | category Z? or C? are not composable except for ZWNJ and ZWJ. */ |
| 972 | 973 | ||
| 973 | #define CHAR_COMPOSABLE_P(C) \ | 974 | #define CHAR_COMPOSABLE_P(C) \ |
| 974 | ((C) == 0x200C || (C) == 0x200D \ | 975 | ((C) > ' ' \ |
| 975 | || (_work_val = CHAR_TABLE_REF (Vunicode_category_table, (C)), \ | 976 | && ((C) == 0x200C || (C) == 0x200D \ |
| 976 | (SYMBOLP (_work_val) \ | 977 | || (_work_val = CHAR_TABLE_REF (Vunicode_category_table, (C)), \ |
| 977 | && (_work_char = SDATA (SYMBOL_NAME (_work_val))[0]) != 'C' \ | 978 | (SYMBOLP (_work_val) \ |
| 978 | && _work_char != 'Z'))) | 979 | && (_work_char = SDATA (SYMBOL_NAME (_work_val))[0]) != 'C' \ |
| 980 | && _work_char != 'Z')))) | ||
| 979 | 981 | ||
| 980 | /* Update cmp_it->stop_pos to the next position after CHARPOS (and | 982 | /* Update cmp_it->stop_pos to the next position after CHARPOS (and |
| 981 | BYTEPOS) where character composition may happen. If BYTEPOS is | 983 | BYTEPOS) where character composition may happen. If BYTEPOS is |
| @@ -993,7 +995,8 @@ static int _work_char; | |||
| 993 | void | 995 | void |
| 994 | composition_compute_stop_pos (struct composition_it *cmp_it, EMACS_INT charpos, EMACS_INT bytepos, EMACS_INT endpos, Lisp_Object string) | 996 | composition_compute_stop_pos (struct composition_it *cmp_it, EMACS_INT charpos, EMACS_INT bytepos, EMACS_INT endpos, Lisp_Object string) |
| 995 | { | 997 | { |
| 996 | EMACS_INT start, end, c; | 998 | EMACS_INT start, end; |
| 999 | int c; | ||
| 997 | Lisp_Object prop, val; | 1000 | Lisp_Object prop, val; |
| 998 | /* This is from forward_to_next_line_start in xdisp.c. */ | 1001 | /* This is from forward_to_next_line_start in xdisp.c. */ |
| 999 | const int MAX_NEWLINE_DISTANCE = 500; | 1002 | const int MAX_NEWLINE_DISTANCE = 500; |
| @@ -1028,7 +1031,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, EMACS_INT charpos, | |||
| 1028 | cmp_it->stop_pos = endpos = start; | 1031 | cmp_it->stop_pos = endpos = start; |
| 1029 | cmp_it->ch = -1; | 1032 | cmp_it->ch = -1; |
| 1030 | } | 1033 | } |
| 1031 | if (NILP (current_buffer->enable_multibyte_characters) | 1034 | if (NILP (BVAR (current_buffer, enable_multibyte_characters)) |
| 1032 | || NILP (Vauto_composition_mode)) | 1035 | || NILP (Vauto_composition_mode)) |
| 1033 | return; | 1036 | return; |
| 1034 | if (bytepos < 0) | 1037 | if (bytepos < 0) |
| @@ -1115,7 +1118,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, EMACS_INT charpos, | |||
| 1115 | if (! NILP (val)) | 1118 | if (! NILP (val)) |
| 1116 | { | 1119 | { |
| 1117 | Lisp_Object elt; | 1120 | Lisp_Object elt; |
| 1118 | int ridx, back, len; | 1121 | int ridx, back, blen; |
| 1119 | 1122 | ||
| 1120 | for (ridx = 0; CONSP (val); val = XCDR (val), ridx++) | 1123 | for (ridx = 0; CONSP (val); val = XCDR (val), ridx++) |
| 1121 | { | 1124 | { |
| @@ -1132,17 +1135,17 @@ composition_compute_stop_pos (struct composition_it *cmp_it, EMACS_INT charpos, | |||
| 1132 | bpos = (NILP (string) ? CHAR_TO_BYTE (cpos) | 1135 | bpos = (NILP (string) ? CHAR_TO_BYTE (cpos) |
| 1133 | : string_char_to_byte (string, cpos)); | 1136 | : string_char_to_byte (string, cpos)); |
| 1134 | if (STRINGP (AREF (elt, 0))) | 1137 | if (STRINGP (AREF (elt, 0))) |
| 1135 | len = fast_looking_at (AREF (elt, 0), cpos, bpos, | 1138 | blen = fast_looking_at (AREF (elt, 0), cpos, bpos, |
| 1136 | start + 1, limit, string); | 1139 | start + 1, limit, string); |
| 1137 | else | 1140 | else |
| 1138 | len = 1; | 1141 | blen = 1; |
| 1139 | if (len > 0) | 1142 | if (blen > 0) |
| 1140 | { | 1143 | { |
| 1141 | /* Make CPOS point to the last character of | 1144 | /* Make CPOS point to the last character of |
| 1142 | match. Note that LEN is byte-length. */ | 1145 | match. Note that BLEN is byte-length. */ |
| 1143 | if (len > 1) | 1146 | if (blen > 1) |
| 1144 | { | 1147 | { |
| 1145 | bpos += len; | 1148 | bpos += blen; |
| 1146 | if (NILP (string)) | 1149 | if (NILP (string)) |
| 1147 | cpos = BYTE_TO_CHAR (bpos) - 1; | 1150 | cpos = BYTE_TO_CHAR (bpos) - 1; |
| 1148 | else | 1151 | else |
| @@ -1248,8 +1251,8 @@ composition_reseat_it (struct composition_it *cmp_it, EMACS_INT charpos, EMACS_I | |||
| 1248 | else if (w) | 1251 | else if (w) |
| 1249 | { | 1252 | { |
| 1250 | Lisp_Object lgstring = Qnil; | 1253 | Lisp_Object lgstring = Qnil; |
| 1251 | Lisp_Object val, elt, re; | 1254 | Lisp_Object val, elt; |
| 1252 | int len, i; | 1255 | int i; |
| 1253 | 1256 | ||
| 1254 | val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch); | 1257 | val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch); |
| 1255 | for (i = 0; i < cmp_it->rule_idx; i++, val = XCDR (val)); | 1258 | for (i = 0; i < cmp_it->rule_idx; i++, val = XCDR (val)); |
| @@ -1364,7 +1367,7 @@ composition_reseat_it (struct composition_it *cmp_it, EMACS_INT charpos, EMACS_I | |||
| 1364 | int | 1367 | int |
| 1365 | composition_update_it (struct composition_it *cmp_it, EMACS_INT charpos, EMACS_INT bytepos, Lisp_Object string) | 1368 | composition_update_it (struct composition_it *cmp_it, EMACS_INT charpos, EMACS_INT bytepos, Lisp_Object string) |
| 1366 | { | 1369 | { |
| 1367 | int i, c; | 1370 | int i, c IF_LINT (= 0); |
| 1368 | 1371 | ||
| 1369 | if (cmp_it->ch < 0) | 1372 | if (cmp_it->ch < 0) |
| 1370 | { | 1373 | { |
| @@ -1470,7 +1473,7 @@ struct position_record | |||
| 1470 | /* Update the members of POSITION to the previous character boundary. */ | 1473 | /* Update the members of POSITION to the previous character boundary. */ |
| 1471 | #define BACKWARD_CHAR(POSITION, STOP) \ | 1474 | #define BACKWARD_CHAR(POSITION, STOP) \ |
| 1472 | do { \ | 1475 | do { \ |
| 1473 | if ((POSITION).pos == STOP) \ | 1476 | if ((POSITION).pos == (STOP)) \ |
| 1474 | (POSITION).p = GPT_ADDR; \ | 1477 | (POSITION).p = GPT_ADDR; \ |
| 1475 | do { \ | 1478 | do { \ |
| 1476 | (POSITION).pos_byte--; \ | 1479 | (POSITION).pos_byte--; \ |
| @@ -1480,173 +1483,198 @@ struct position_record | |||
| 1480 | } while (0) | 1483 | } while (0) |
| 1481 | 1484 | ||
| 1482 | /* This is like find_composition, but find an automatic composition | 1485 | /* This is like find_composition, but find an automatic composition |
| 1483 | instead. If found, set *GSTRING to the glyph-string representing | 1486 | instead. It is assured that POS is not within a static |
| 1484 | the composition, and return 1. Otherwise, return 0. */ | 1487 | composition. If found, set *GSTRING to the glyph-string |
| 1488 | representing the composition, and return 1. Otherwise, *GSTRING to | ||
| 1489 | Qnil, and return 0. */ | ||
| 1485 | 1490 | ||
| 1486 | static int | 1491 | static int |
| 1487 | find_automatic_composition (EMACS_INT pos, EMACS_INT limit, EMACS_INT *start, EMACS_INT *end, Lisp_Object *gstring, Lisp_Object string) | 1492 | find_automatic_composition (EMACS_INT pos, EMACS_INT limit, |
| 1493 | EMACS_INT *start, EMACS_INT *end, | ||
| 1494 | Lisp_Object *gstring, Lisp_Object string) | ||
| 1488 | { | 1495 | { |
| 1489 | EMACS_INT head, tail, stop; | 1496 | EMACS_INT head, tail, stop; |
| 1490 | /* Limit to check a composition after POS. */ | 1497 | /* Forward limit position of checking a composition taking a |
| 1498 | looking-back count into account. */ | ||
| 1491 | EMACS_INT fore_check_limit; | 1499 | EMACS_INT fore_check_limit; |
| 1492 | struct position_record orig, cur, check, prev; | 1500 | struct position_record cur, prev; |
| 1493 | Lisp_Object check_val, val, elt; | ||
| 1494 | int check_lookback; | ||
| 1495 | int c; | 1501 | int c; |
| 1496 | Lisp_Object window; | 1502 | Lisp_Object window; |
| 1497 | struct window *w; | 1503 | struct window *w; |
| 1504 | int need_adjustment = 0; | ||
| 1498 | 1505 | ||
| 1499 | window = Fget_buffer_window (Fcurrent_buffer (), Qnil); | 1506 | window = Fget_buffer_window (Fcurrent_buffer (), Qnil); |
| 1500 | if (NILP (window)) | 1507 | if (NILP (window)) |
| 1501 | return 0; | 1508 | return 0; |
| 1502 | w = XWINDOW (window); | 1509 | w = XWINDOW (window); |
| 1503 | 1510 | ||
| 1504 | orig.pos = pos; | 1511 | cur.pos = pos; |
| 1505 | if (NILP (string)) | 1512 | if (NILP (string)) |
| 1506 | { | 1513 | { |
| 1507 | head = BEGV, tail = ZV, stop = GPT; | 1514 | head = BEGV, tail = ZV, stop = GPT; |
| 1508 | orig.pos_byte = CHAR_TO_BYTE (orig.pos); | 1515 | cur.pos_byte = CHAR_TO_BYTE (cur.pos); |
| 1509 | orig.p = BYTE_POS_ADDR (orig.pos_byte); | 1516 | cur.p = BYTE_POS_ADDR (cur.pos_byte); |
| 1510 | } | 1517 | } |
| 1511 | else | 1518 | else |
| 1512 | { | 1519 | { |
| 1513 | head = 0, tail = SCHARS (string), stop = -1; | 1520 | head = 0, tail = SCHARS (string), stop = -1; |
| 1514 | orig.pos_byte = string_char_to_byte (string, orig.pos); | 1521 | cur.pos_byte = string_char_to_byte (string, cur.pos); |
| 1515 | orig.p = SDATA (string) + orig.pos_byte; | 1522 | cur.p = SDATA (string) + cur.pos_byte; |
| 1516 | } | 1523 | } |
| 1517 | if (limit < pos) | 1524 | if (limit < 0) |
| 1518 | fore_check_limit = min (tail, pos + MAX_AUTO_COMPOSITION_LOOKBACK); | 1525 | /* Finding a composition covering the character after POS is the |
| 1526 | same as setting LIMIT to POS. */ | ||
| 1527 | limit = pos; | ||
| 1528 | if (limit <= pos) | ||
| 1529 | fore_check_limit = min (tail, pos + 1 + MAX_AUTO_COMPOSITION_LOOKBACK); | ||
| 1519 | else | 1530 | else |
| 1520 | fore_check_limit = min (tail, limit + MAX_AUTO_COMPOSITION_LOOKBACK); | 1531 | fore_check_limit = min (tail, limit + MAX_AUTO_COMPOSITION_LOOKBACK); |
| 1521 | cur = orig; | ||
| 1522 | 1532 | ||
| 1523 | retry: | 1533 | /* Provided that we have these possible compositions now: |
| 1524 | check_val = Qnil; | ||
| 1525 | /* At first, check if POS is composable. */ | ||
| 1526 | c = STRING_CHAR (cur.p); | ||
| 1527 | if (! CHAR_COMPOSABLE_P (c)) | ||
| 1528 | { | ||
| 1529 | if (limit < 0) | ||
| 1530 | return 0; | ||
| 1531 | if (limit >= cur.pos) | ||
| 1532 | goto search_forward; | ||
| 1533 | } | ||
| 1534 | else | ||
| 1535 | { | ||
| 1536 | val = CHAR_TABLE_REF (Vcomposition_function_table, c); | ||
| 1537 | if (! NILP (val)) | ||
| 1538 | check_val = val, check = cur; | ||
| 1539 | else | ||
| 1540 | while (cur.pos + 1 < fore_check_limit) | ||
| 1541 | { | ||
| 1542 | EMACS_INT b, e; | ||
| 1543 | 1534 | ||
| 1544 | FORWARD_CHAR (cur, stop); | 1535 | POS: 1 2 3 4 5 6 7 8 9 |
| 1545 | if (get_property_and_range (cur.pos, Qcomposition, &val, &b, &e, | 1536 | |-A-| |
| 1546 | Qnil) | 1537 | |-B-|-C-|--D--| |
| 1547 | && COMPOSITION_VALID_P (b, e, val)) | ||
| 1548 | { | ||
| 1549 | fore_check_limit = cur.pos; | ||
| 1550 | break; | ||
| 1551 | } | ||
| 1552 | c = STRING_CHAR (cur.p); | ||
| 1553 | if (! CHAR_COMPOSABLE_P (c)) | ||
| 1554 | break; | ||
| 1555 | val = CHAR_TABLE_REF (Vcomposition_function_table, c); | ||
| 1556 | if (NILP (val)) | ||
| 1557 | continue; | ||
| 1558 | check_val = val, check = cur; | ||
| 1559 | break; | ||
| 1560 | } | ||
| 1561 | cur = orig; | ||
| 1562 | } | ||
| 1563 | /* Rewind back to the position where we can safely search forward | ||
| 1564 | for compositions. */ | ||
| 1565 | while (cur.pos > head) | ||
| 1566 | { | ||
| 1567 | EMACS_INT b, e; | ||
| 1568 | 1538 | ||
| 1569 | BACKWARD_CHAR (cur, stop); | 1539 | Here, it is known that characters after positions 1 and 9 can |
| 1570 | if (get_property_and_range (cur.pos, Qcomposition, &val, &b, &e, Qnil) | 1540 | never be composed (i.e. ! CHAR_COMPOSABLE_P (CH)), and |
| 1571 | && COMPOSITION_VALID_P (b, e, val)) | 1541 | composition A is an invalid one because it's partially covered by |
| 1572 | break; | 1542 | the valid composition C. And to know whether a composition is |
| 1543 | valid or not, the only way is to start searching forward from a | ||
| 1544 | position that can not be a tail part of composition (it's 2 in | ||
| 1545 | the above case). | ||
| 1546 | |||
| 1547 | Now we have these cases (1 through 4): | ||
| 1548 | |||
| 1549 | -- character after POS is ... -- | ||
| 1550 | not composable composable | ||
| 1551 | LIMIT <= POS (1) (3) | ||
| 1552 | POS < LIMIT (2) (4) | ||
| 1553 | |||
| 1554 | Among them, in case (2), we simply search forward from POS. | ||
| 1555 | |||
| 1556 | In the other cases, we at first rewind back to the position where | ||
| 1557 | the previous character is not composable or the beginning of | ||
| 1558 | buffer (string), then search compositions forward. In case (1) | ||
| 1559 | and (3) we repeat this process until a composition is found. */ | ||
| 1560 | |||
| 1561 | while (1) | ||
| 1562 | { | ||
| 1573 | c = STRING_CHAR (cur.p); | 1563 | c = STRING_CHAR (cur.p); |
| 1574 | if (! CHAR_COMPOSABLE_P (c)) | 1564 | if (! CHAR_COMPOSABLE_P (c)) |
| 1575 | break; | ||
| 1576 | val = CHAR_TABLE_REF (Vcomposition_function_table, c); | ||
| 1577 | if (! NILP (val)) | ||
| 1578 | check_val = val, check = cur; | ||
| 1579 | } | ||
| 1580 | prev = cur; | ||
| 1581 | /* Now search forward. */ | ||
| 1582 | search_forward: | ||
| 1583 | *gstring = Qnil; | ||
| 1584 | if (! NILP (check_val) || limit >= orig.pos) | ||
| 1585 | { | ||
| 1586 | if (NILP (check_val)) | ||
| 1587 | cur = orig; | ||
| 1588 | else | ||
| 1589 | cur = check; | ||
| 1590 | while (cur.pos < fore_check_limit) | ||
| 1591 | { | 1565 | { |
| 1592 | int need_adjustment = 0; | 1566 | if (limit <= pos) /* case (1) */ |
| 1567 | { | ||
| 1568 | do { | ||
| 1569 | if (cur.pos <= limit) | ||
| 1570 | return 0; | ||
| 1571 | BACKWARD_CHAR (cur, stop); | ||
| 1572 | c = STRING_CHAR (cur.p); | ||
| 1573 | } while (! CHAR_COMPOSABLE_P (c)); | ||
| 1574 | fore_check_limit = cur.pos + 1; | ||
| 1575 | } | ||
| 1576 | else /* case (2) */ | ||
| 1577 | /* No need of rewinding back. */ | ||
| 1578 | goto search_forward; | ||
| 1579 | } | ||
| 1593 | 1580 | ||
| 1594 | if (NILP (check_val)) | 1581 | /* Rewind back to the position where we can safely search |
| 1582 | forward for compositions. It is assured that the character | ||
| 1583 | at cur.pos is composable. */ | ||
| 1584 | while (head < cur.pos) | ||
| 1585 | { | ||
| 1586 | prev = cur; | ||
| 1587 | BACKWARD_CHAR (cur, stop); | ||
| 1588 | c = STRING_CHAR (cur.p); | ||
| 1589 | if (! CHAR_COMPOSABLE_P (c)) | ||
| 1595 | { | 1590 | { |
| 1596 | c = STRING_CHAR (cur.p); | 1591 | cur = prev; |
| 1597 | check_val = CHAR_TABLE_REF (Vcomposition_function_table, c); | 1592 | break; |
| 1598 | } | 1593 | } |
| 1599 | for (; CONSP (check_val); check_val = XCDR (check_val)) | 1594 | } |
| 1595 | |||
| 1596 | search_forward: | ||
| 1597 | /* Now search forward. */ | ||
| 1598 | *gstring = Qnil; | ||
| 1599 | prev = cur; /* remember the start of searching position. */ | ||
| 1600 | while (cur.pos < fore_check_limit) | ||
| 1601 | { | ||
| 1602 | Lisp_Object val; | ||
| 1603 | |||
| 1604 | c = STRING_CHAR (cur.p); | ||
| 1605 | for (val = CHAR_TABLE_REF (Vcomposition_function_table, c); | ||
| 1606 | CONSP (val); val = XCDR (val)) | ||
| 1600 | { | 1607 | { |
| 1601 | elt = XCAR (check_val); | 1608 | Lisp_Object elt = XCAR (val); |
| 1602 | if (VECTORP (elt) && ASIZE (elt) == 3 && NATNUMP (AREF (elt, 1)) | 1609 | |
| 1603 | && cur.pos - XFASTINT (AREF (elt, 1)) >= head) | 1610 | if (VECTORP (elt) && ASIZE (elt) == 3 && NATNUMP (AREF (elt, 1))) |
| 1604 | { | 1611 | { |
| 1605 | check.pos = cur.pos - XFASTINT (AREF (elt, 1)); | 1612 | EMACS_INT check_pos = cur.pos - XFASTINT (AREF (elt, 1)); |
| 1606 | if (check.pos == cur.pos) | 1613 | struct position_record check; |
| 1607 | check.pos_byte = cur.pos_byte; | 1614 | |
| 1608 | else | 1615 | if (check_pos < head |
| 1609 | check.pos_byte = CHAR_TO_BYTE (check.pos); | 1616 | || (limit <= pos ? pos < check_pos |
| 1610 | val = autocmp_chars (elt, check.pos, check.pos_byte, | 1617 | : limit <= check_pos)) |
| 1611 | tail, w, NULL, string); | 1618 | continue; |
| 1619 | for (check = cur; check_pos < check.pos; ) | ||
| 1620 | BACKWARD_CHAR (check, stop); | ||
| 1621 | *gstring = autocmp_chars (elt, check.pos, check.pos_byte, | ||
| 1622 | tail, w, NULL, string); | ||
| 1612 | need_adjustment = 1; | 1623 | need_adjustment = 1; |
| 1613 | if (! NILP (val)) | 1624 | if (NILP (*gstring)) |
| 1625 | { | ||
| 1626 | /* As we have called Lisp, there's a possibility | ||
| 1627 | that buffer/string is relocated. */ | ||
| 1628 | if (NILP (string)) | ||
| 1629 | cur.p = BYTE_POS_ADDR (cur.pos_byte); | ||
| 1630 | else | ||
| 1631 | cur.p = SDATA (string) + cur.pos_byte; | ||
| 1632 | } | ||
| 1633 | else | ||
| 1614 | { | 1634 | { |
| 1615 | *gstring = val; | 1635 | /* We found a candidate of a target composition. */ |
| 1616 | *start = check.pos; | 1636 | *start = check.pos; |
| 1617 | *end = check.pos + LGSTRING_CHAR_LEN (*gstring); | 1637 | *end = check.pos + LGSTRING_CHAR_LEN (*gstring); |
| 1618 | if (*start <= orig.pos ? *end > orig.pos | 1638 | if (pos < limit |
| 1619 | : limit >= orig.pos) | 1639 | ? pos < *end |
| 1640 | : *start <= pos && pos < *end) | ||
| 1641 | /* This is the target composition. */ | ||
| 1620 | return 1; | 1642 | return 1; |
| 1621 | cur.pos = *end; | 1643 | cur.pos = *end; |
| 1622 | cur.pos_byte = CHAR_TO_BYTE (cur.pos); | 1644 | if (NILP (string)) |
| 1645 | { | ||
| 1646 | cur.pos_byte = CHAR_TO_BYTE (cur.pos); | ||
| 1647 | cur.p = BYTE_POS_ADDR (cur.pos_byte); | ||
| 1648 | } | ||
| 1649 | else | ||
| 1650 | { | ||
| 1651 | cur.pos_byte = string_char_to_byte (string, cur.pos); | ||
| 1652 | cur.p = SDATA (string) + cur.pos_byte; | ||
| 1653 | } | ||
| 1623 | break; | 1654 | break; |
| 1624 | } | 1655 | } |
| 1625 | } | 1656 | } |
| 1626 | } | 1657 | } |
| 1627 | if (need_adjustment) | 1658 | if (! CONSP (val)) |
| 1628 | { | 1659 | /* We found no composition here. */ |
| 1629 | /* As we have called Lisp, there's a possibility that | ||
| 1630 | buffer/string is relocated. */ | ||
| 1631 | if (NILP (string)) | ||
| 1632 | cur.p = BYTE_POS_ADDR (cur.pos_byte); | ||
| 1633 | else | ||
| 1634 | cur.p = SDATA (string) + cur.pos_byte; | ||
| 1635 | } | ||
| 1636 | if (! CONSP (check_val)) | ||
| 1637 | FORWARD_CHAR (cur, stop); | 1660 | FORWARD_CHAR (cur, stop); |
| 1638 | check_val = Qnil; | ||
| 1639 | } | 1661 | } |
| 1640 | } | 1662 | |
| 1641 | if (! NILP (*gstring)) | 1663 | if (pos < limit) /* case (2) and (4)*/ |
| 1642 | return (limit >= 0 || (*start <= orig.pos && *end > orig.pos)); | 1664 | return 0; |
| 1643 | if (limit >= 0 && limit < orig.pos && prev.pos > head) | 1665 | if (! NILP (*gstring)) |
| 1644 | { | 1666 | return 1; |
| 1667 | if (prev.pos == head) | ||
| 1668 | return 0; | ||
| 1645 | cur = prev; | 1669 | cur = prev; |
| 1670 | if (need_adjustment) | ||
| 1671 | { | ||
| 1672 | if (NILP (string)) | ||
| 1673 | cur.p = BYTE_POS_ADDR (cur.pos_byte); | ||
| 1674 | else | ||
| 1675 | cur.p = SDATA (string) + cur.pos_byte; | ||
| 1676 | } | ||
| 1646 | BACKWARD_CHAR (cur, stop); | 1677 | BACKWARD_CHAR (cur, stop); |
| 1647 | orig = cur; | ||
| 1648 | fore_check_limit = orig.pos; | ||
| 1649 | goto retry; | ||
| 1650 | } | 1678 | } |
| 1651 | return 0; | 1679 | return 0; |
| 1652 | } | 1680 | } |
| @@ -1657,7 +1685,7 @@ find_automatic_composition (EMACS_INT pos, EMACS_INT limit, EMACS_INT *start, EM | |||
| 1657 | EMACS_INT | 1685 | EMACS_INT |
| 1658 | composition_adjust_point (EMACS_INT last_pt, EMACS_INT new_pt) | 1686 | composition_adjust_point (EMACS_INT last_pt, EMACS_INT new_pt) |
| 1659 | { | 1687 | { |
| 1660 | EMACS_INT charpos, bytepos, startpos, beg, end, pos; | 1688 | EMACS_INT beg, end; |
| 1661 | Lisp_Object val; | 1689 | Lisp_Object val; |
| 1662 | int i; | 1690 | int i; |
| 1663 | 1691 | ||
| @@ -1674,7 +1702,7 @@ composition_adjust_point (EMACS_INT last_pt, EMACS_INT new_pt) | |||
| 1674 | return new_pt; | 1702 | return new_pt; |
| 1675 | } | 1703 | } |
| 1676 | 1704 | ||
| 1677 | if (NILP (current_buffer->enable_multibyte_characters) | 1705 | if (NILP (BVAR (current_buffer, enable_multibyte_characters)) |
| 1678 | || NILP (Vauto_composition_mode)) | 1706 | || NILP (Vauto_composition_mode)) |
| 1679 | return new_pt; | 1707 | return new_pt; |
| 1680 | 1708 | ||
| @@ -1851,7 +1879,7 @@ See `find-composition' for more details. */) | |||
| 1851 | 1879 | ||
| 1852 | if (!find_composition (from, to, &start, &end, &prop, string)) | 1880 | if (!find_composition (from, to, &start, &end, &prop, string)) |
| 1853 | { | 1881 | { |
| 1854 | if (!NILP (current_buffer->enable_multibyte_characters) | 1882 | if (!NILP (BVAR (current_buffer, enable_multibyte_characters)) |
| 1855 | && ! NILP (Vauto_composition_mode) | 1883 | && ! NILP (Vauto_composition_mode) |
| 1856 | && find_automatic_composition (from, to, &start, &end, &gstring, | 1884 | && find_automatic_composition (from, to, &start, &end, &gstring, |
| 1857 | string)) | 1885 | string)) |
| @@ -2032,4 +2060,3 @@ See also the documentation of `auto-composition-mode'. */); | |||
| 2032 | defsubr (&Sfind_composition_internal); | 2060 | defsubr (&Sfind_composition_internal); |
| 2033 | defsubr (&Scomposition_get_gstring); | 2061 | defsubr (&Scomposition_get_gstring); |
| 2034 | } | 2062 | } |
| 2035 | |||