diff options
| author | Kenichi Handa | 2010-05-25 09:32:24 +0900 |
|---|---|---|
| committer | Kenichi Handa | 2010-05-25 09:32:24 +0900 |
| commit | 10f72a3793087770f131a0dc729f29ff50f08ad9 (patch) | |
| tree | 3d6a77b09c6d1b8a36795a50be909c9ed010d39d /src | |
| parent | 9ba3dd48988911d24100dad2b67e5b45189083dd (diff) | |
| download | emacs-10f72a3793087770f131a0dc729f29ff50f08ad9.tar.gz emacs-10f72a3793087770f131a0dc729f29ff50f08ad9.zip | |
Fix bidi-composition interaction in backward scanning..
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 23 | ||||
| -rw-r--r-- | src/composite.c | 401 | ||||
| -rw-r--r-- | src/dispextern.h | 26 | ||||
| -rw-r--r-- | src/xdisp.c | 19 |
4 files changed, 251 insertions, 218 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 46346931085..347ee7b1f20 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,26 @@ | |||
| 1 | 2010-05-25 Kenichi Handa <handa@m17n.org> | ||
| 2 | |||
| 3 | * dispextern.h (struct composition_it): New members rule_idx and | ||
| 4 | charpos. | ||
| 5 | |||
| 6 | * xdisp.c (set_iterator_to_next): While scanning backward, assume | ||
| 7 | that the character positions of IT point the last character of the | ||
| 8 | current grapheme cluster. | ||
| 9 | (next_element_from_composition): Don't change character positions | ||
| 10 | of IT. | ||
| 11 | (append_composite_glyph): Set glyph->charpos to | ||
| 12 | it->cmp_it.charpos. | ||
| 13 | |||
| 14 | * composite.c (autocmp_chars): Change the first argument to RULE, | ||
| 15 | and try composition with RULE only. | ||
| 16 | (composition_compute_stop_pos): Record the index number of the | ||
| 17 | composition rule in CMP_IT->rule_idx. | ||
| 18 | (composition_reseat_it): Call autocmp_chars repeatedly until the | ||
| 19 | correct rule of the composition is found. | ||
| 20 | (composition_update_it): Set CMP_IT->charpos. Assume the CHARPOS | ||
| 21 | is at the last character of the current grapheme cluster when | ||
| 22 | CMP_IT->reversed_p is nonzero. | ||
| 23 | |||
| 1 | 2010-05-18 Chong Yidong <cyd@stupidchicken.com> | 24 | 2010-05-18 Chong Yidong <cyd@stupidchicken.com> |
| 2 | 25 | ||
| 3 | * character.c (Fstring, Funibyte_string): Use SAFE_ALLOCA to | 26 | * character.c (Fstring, Funibyte_string): Use SAFE_ALLOCA to |
diff --git a/src/composite.c b/src/composite.c index f392053bac9..dd07ab8f9a2 100644 --- a/src/composite.c +++ b/src/composite.c | |||
| @@ -915,15 +915,16 @@ fill_gstring_body (gstring) | |||
| 915 | } | 915 | } |
| 916 | 916 | ||
| 917 | 917 | ||
| 918 | /* Try to compose the characters at CHARPOS according to CFT_ELEMENT | 918 | /* Try to compose the characters at CHARPOS according to composition |
| 919 | which is an element of composition-function-table (which see). | 919 | rule RULE ([PATTERN PREV-CHARS FUNC]). LIMIT limits the characters |
| 920 | LIMIT limits the characters to compose. STRING, if not nil, is a | 920 | to compose. STRING, if not nil, is a target string. WIN is a |
| 921 | target string. WIN is a window where the characters are being | 921 | window where the characters are being displayed. If characters are |
| 922 | displayed. */ | 922 | successfully composed, return the composition as a glyph-string |
| 923 | object. Otherwise return nil. */ | ||
| 923 | 924 | ||
| 924 | static Lisp_Object | 925 | static Lisp_Object |
| 925 | autocmp_chars (cft_element, charpos, bytepos, limit, win, face, string) | 926 | autocmp_chars (rule, charpos, bytepos, limit, win, face, string) |
| 926 | Lisp_Object cft_element; | 927 | Lisp_Object rule; |
| 927 | EMACS_INT charpos, bytepos, limit; | 928 | EMACS_INT charpos, bytepos, limit; |
| 928 | struct window *win; | 929 | struct window *win; |
| 929 | struct face *face; | 930 | struct face *face; |
| @@ -932,90 +933,66 @@ autocmp_chars (cft_element, charpos, bytepos, limit, win, face, string) | |||
| 932 | int count = SPECPDL_INDEX (); | 933 | int count = SPECPDL_INDEX (); |
| 933 | FRAME_PTR f = XFRAME (win->frame); | 934 | FRAME_PTR f = XFRAME (win->frame); |
| 934 | Lisp_Object pos = make_number (charpos); | 935 | Lisp_Object pos = make_number (charpos); |
| 936 | EMACS_INT to; | ||
| 935 | EMACS_INT pt = PT, pt_byte = PT_BYTE; | 937 | EMACS_INT pt = PT, pt_byte = PT_BYTE; |
| 936 | int lookback; | 938 | Lisp_Object re, font_object, lgstring; |
| 939 | int len; | ||
| 937 | 940 | ||
| 938 | record_unwind_save_match_data (); | 941 | record_unwind_save_match_data (); |
| 939 | for (lookback = -1; CONSP (cft_element); cft_element = XCDR (cft_element)) | 942 | re = AREF (rule, 0); |
| 943 | if (NILP (re)) | ||
| 944 | len = 1; | ||
| 945 | else if (! STRINGP (re)) | ||
| 946 | return unbind_to (count, Qnil); | ||
| 947 | else if ((len = fast_looking_at (re, charpos, bytepos, limit, -1, string)) | ||
| 948 | > 0) | ||
| 940 | { | 949 | { |
| 941 | Lisp_Object elt = XCAR (cft_element); | 950 | if (NILP (string)) |
| 942 | Lisp_Object re; | 951 | len = BYTE_TO_CHAR (bytepos + len) - charpos; |
| 943 | Lisp_Object font_object = Qnil, gstring; | 952 | else |
| 944 | EMACS_INT len, to; | 953 | len = string_byte_to_char (string, bytepos + len) - charpos; |
| 945 | 954 | } | |
| 946 | if (! VECTORP (elt) || ASIZE (elt) != 3) | 955 | if (len <= 0) |
| 947 | continue; | 956 | return unbind_to (count, Qnil); |
| 948 | if (lookback < 0) | 957 | to = limit = charpos + len; |
| 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 | 958 | #ifdef HAVE_WINDOW_SYSTEM |
| 971 | if (FRAME_WINDOW_P (f)) | 959 | if (FRAME_WINDOW_P (f)) |
| 972 | { | 960 | { |
| 973 | font_object = font_range (charpos, &to, win, face, string); | 961 | font_object = font_range (charpos, &to, win, face, string); |
| 974 | if (! FONT_OBJECT_P (font_object) | 962 | if (! FONT_OBJECT_P (font_object) |
| 975 | || (! NILP (re) | 963 | || (! NILP (re) |
| 976 | && to < limit | 964 | && to < limit |
| 977 | && (fast_looking_at (re, charpos, bytepos, to, -1, string) <= 0))) | 965 | && (fast_looking_at (re, charpos, bytepos, to, -1, string) <= 0))) |
| 978 | { | 966 | return unbind_to (count, Qnil); |
| 979 | if (NILP (string)) | 967 | } |
| 980 | TEMP_SET_PT_BOTH (pt, pt_byte); | 968 | else |
| 981 | return unbind_to (count, Qnil); | ||
| 982 | } | ||
| 983 | } | ||
| 984 | else | ||
| 985 | #endif /* not HAVE_WINDOW_SYSTEM */ | 969 | #endif /* not HAVE_WINDOW_SYSTEM */ |
| 986 | font_object = win->frame; | 970 | font_object = win->frame; |
| 987 | gstring = Fcomposition_get_gstring (pos, make_number (to), | 971 | lgstring = Fcomposition_get_gstring (pos, make_number (to), font_object, |
| 988 | font_object, string); | 972 | string); |
| 989 | if (NILP (LGSTRING_ID (gstring))) | 973 | if (NILP (LGSTRING_ID (lgstring))) |
| 990 | { | 974 | { |
| 991 | Lisp_Object args[6]; | 975 | 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 | 976 | ||
| 1001 | args[0] = Vauto_composition_function; | 977 | /* Save point as marker before calling out to lisp. */ |
| 1002 | args[1] = AREF (elt, 2); | 978 | if (NILP (string)) |
| 1003 | args[2] = pos; | 979 | { |
| 1004 | args[3] = make_number (to); | 980 | Lisp_Object m = Fmake_marker (); |
| 1005 | args[4] = font_object; | 981 | set_marker_both (m, Qnil, pt, pt_byte); |
| 1006 | args[5] = string; | 982 | record_unwind_protect (restore_point_unwind, m); |
| 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 | } | 983 | } |
| 984 | |||
| 985 | args[0] = Vauto_composition_function; | ||
| 986 | args[1] = AREF (rule, 2); | ||
| 987 | args[2] = pos; | ||
| 988 | args[3] = make_number (to); | ||
| 989 | args[4] = font_object; | ||
| 990 | args[5] = string; | ||
| 991 | lgstring = safe_call (6, args); | ||
| 992 | if (NILP (string)) | ||
| 993 | TEMP_SET_PT_BOTH (pt, pt_byte); | ||
| 1015 | } | 994 | } |
| 1016 | if (NILP (string)) | 995 | return unbind_to (count, lgstring); |
| 1017 | TEMP_SET_PT_BOTH (pt, pt_byte); | ||
| 1018 | return unbind_to (count, Qnil); | ||
| 1019 | } | 996 | } |
| 1020 | 997 | ||
| 1021 | static Lisp_Object _work_val; | 998 | static Lisp_Object _work_val; |
| @@ -1126,8 +1103,9 @@ composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string) | |||
| 1126 | if (! NILP (val)) | 1103 | if (! NILP (val)) |
| 1127 | { | 1104 | { |
| 1128 | Lisp_Object elt; | 1105 | Lisp_Object elt; |
| 1106 | int ridx; | ||
| 1129 | 1107 | ||
| 1130 | for (; CONSP (val); val = XCDR (val)) | 1108 | for (ridx = 0; CONSP (val); val = XCDR (val), ridx++) |
| 1131 | { | 1109 | { |
| 1132 | elt = XCAR (val); | 1110 | elt = XCAR (val); |
| 1133 | if (VECTORP (elt) && ASIZE (elt) == 3 | 1111 | if (VECTORP (elt) && ASIZE (elt) == 3 |
| @@ -1137,6 +1115,7 @@ composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string) | |||
| 1137 | } | 1115 | } |
| 1138 | if (CONSP (val)) | 1116 | if (CONSP (val)) |
| 1139 | { | 1117 | { |
| 1118 | cmp_it->rule_idx = ridx; | ||
| 1140 | cmp_it->lookback = XFASTINT (AREF (elt, 1)); | 1119 | cmp_it->lookback = XFASTINT (AREF (elt, 1)); |
| 1141 | cmp_it->stop_pos = charpos - 1 - cmp_it->lookback; | 1120 | cmp_it->stop_pos = charpos - 1 - cmp_it->lookback; |
| 1142 | cmp_it->ch = c; | 1121 | cmp_it->ch = c; |
| @@ -1167,45 +1146,54 @@ composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string) | |||
| 1167 | limit = bytepos + len; | 1146 | limit = bytepos + len; |
| 1168 | while (CHAR_COMPOSABLE_P (c)) | 1147 | while (CHAR_COMPOSABLE_P (c)) |
| 1169 | { | 1148 | { |
| 1170 | for (val = CHAR_TABLE_REF (Vcomposition_function_table, c); | 1149 | val = CHAR_TABLE_REF (Vcomposition_function_table, c); |
| 1171 | CONSP (val); val = XCDR (val)) | 1150 | if (! NILP (val)) |
| 1172 | { | 1151 | { |
| 1173 | Lisp_Object elt = XCAR (val); | 1152 | Lisp_Object elt; |
| 1174 | int back, len; | 1153 | int ridx, back, len; |
| 1175 | 1154 | ||
| 1176 | if (VECTORP (elt) && ASIZE (elt) == 3 | 1155 | for (ridx = 0; CONSP (val); val = XCDR (val), ridx++) |
| 1177 | && NATNUMP (AREF (elt, 1)) | ||
| 1178 | && charpos - (back = XFASTINT (AREF (elt, 1))) > endpos) | ||
| 1179 | { | 1156 | { |
| 1180 | EMACS_INT cpos = charpos - back, bpos; | 1157 | elt = XCAR (val); |
| 1181 | 1158 | if (VECTORP (elt) && ASIZE (elt) == 3 | |
| 1182 | if (back == 0) | 1159 | && NATNUMP (AREF (elt, 1)) |
| 1183 | bpos = bytepos; | 1160 | && charpos - (back = XFASTINT (AREF (elt, 1))) > endpos) |
| 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 | { | 1161 | { |
| 1194 | /* Make CPOS point to the last character of match. | 1162 | EMACS_INT cpos = charpos - back, bpos; |
| 1195 | Note that LEN is byte-length. */ | 1163 | |
| 1196 | bpos += len; | 1164 | if (back == 0) |
| 1197 | if (NILP (string)) | 1165 | bpos = bytepos; |
| 1198 | cpos = BYTE_TO_CHAR (bpos) - 1; | ||
| 1199 | else | 1166 | else |
| 1200 | cpos = string_byte_to_char (string, bpos) - 1; | 1167 | bpos = (NILP (string) ? CHAR_TO_BYTE (cpos) |
| 1201 | back = cpos - (charpos - back); | 1168 | : string_char_to_byte (string, cpos)); |
| 1202 | if (cmp_it->stop_pos < cpos | 1169 | if (STRINGP (AREF (elt, 0))) |
| 1203 | || (cmp_it->stop_pos == cpos | 1170 | len = fast_looking_at (AREF (elt, 0), cpos, bpos, |
| 1204 | && cmp_it->lookback < back)) | 1171 | start + 1, limit, string); |
| 1172 | else | ||
| 1173 | len = 1; | ||
| 1174 | if (len > 0) | ||
| 1205 | { | 1175 | { |
| 1206 | cmp_it->stop_pos = cpos; | 1176 | /* Make CPOS point to the last character of |
| 1207 | cmp_it->ch = c; | 1177 | match. Note that LEN is byte-length. */ |
| 1208 | cmp_it->lookback = back; | 1178 | if (len > 1) |
| 1179 | { | ||
| 1180 | bpos += len; | ||
| 1181 | if (NILP (string)) | ||
| 1182 | cpos = BYTE_TO_CHAR (bpos) - 1; | ||
| 1183 | else | ||
| 1184 | cpos = string_byte_to_char (string, bpos) - 1; | ||
| 1185 | } | ||
| 1186 | back = cpos - (charpos - back); | ||
| 1187 | if (cmp_it->stop_pos < cpos | ||
| 1188 | || (cmp_it->stop_pos == cpos | ||
| 1189 | && cmp_it->lookback < back)) | ||
| 1190 | { | ||
| 1191 | cmp_it->rule_idx = ridx; | ||
| 1192 | cmp_it->stop_pos = cpos; | ||
| 1193 | cmp_it->ch = c; | ||
| 1194 | cmp_it->lookback = back; | ||
| 1195 | cmp_it->nchars = back + 1; | ||
| 1196 | } | ||
| 1209 | } | 1197 | } |
| 1210 | } | 1198 | } |
| 1211 | } | 1199 | } |
| @@ -1293,7 +1281,7 @@ composition_reseat_it (cmp_it, charpos, bytepos, endpos, w, face, string) | |||
| 1293 | if (cmp_it->ch == -2) | 1281 | if (cmp_it->ch == -2) |
| 1294 | { | 1282 | { |
| 1295 | composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string); | 1283 | composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string); |
| 1296 | if (cmp_it->stop_pos != charpos) | 1284 | if (cmp_it->ch == -2 || cmp_it->stop_pos != charpos) |
| 1297 | /* The current position is not composed. */ | 1285 | /* The current position is not composed. */ |
| 1298 | return 0; | 1286 | return 0; |
| 1299 | } | 1287 | } |
| @@ -1314,55 +1302,75 @@ composition_reseat_it (cmp_it, charpos, bytepos, endpos, w, face, string) | |||
| 1314 | } | 1302 | } |
| 1315 | else if (w) | 1303 | else if (w) |
| 1316 | { | 1304 | { |
| 1317 | Lisp_Object val, elt; | 1305 | Lisp_Object lgstring = Qnil; |
| 1318 | int i; | 1306 | Lisp_Object val, elt, re; |
| 1307 | int len, i; | ||
| 1319 | 1308 | ||
| 1320 | val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch); | 1309 | val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch); |
| 1310 | for (i = 0; i < cmp_it->rule_idx; i++, val = XCDR (val)); | ||
| 1321 | if (charpos < endpos) | 1311 | if (charpos < endpos) |
| 1322 | { | 1312 | { |
| 1323 | for (; CONSP (val); val = XCDR (val)) | 1313 | for (; CONSP (val); val = XCDR (val)) |
| 1324 | { | 1314 | { |
| 1325 | elt = XCAR (val); | 1315 | elt = XCAR (val); |
| 1326 | if (cmp_it->lookback == XFASTINT (AREF (elt, 1))) | 1316 | if (! VECTORP (elt) || ASIZE (elt) != 3 |
| 1317 | || ! INTEGERP (AREF (elt, 1))) | ||
| 1318 | continue; | ||
| 1319 | if (XFASTINT (AREF (elt, 1)) != cmp_it->lookback) | ||
| 1320 | goto no_composition; | ||
| 1321 | lgstring = autocmp_chars (elt, charpos, bytepos, endpos, | ||
| 1322 | w, face, string); | ||
| 1323 | if (composition_gstring_p (lgstring)) | ||
| 1327 | break; | 1324 | break; |
| 1325 | lgstring = Qnil; | ||
| 1326 | /* Composition failed perhaps because the font doesn't | ||
| 1327 | support sufficient range of characters. Try the | ||
| 1328 | other composition rules if any. */ | ||
| 1328 | } | 1329 | } |
| 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; | 1330 | cmp_it->reversed_p = 0; |
| 1336 | } | 1331 | } |
| 1337 | else | 1332 | else |
| 1338 | { | 1333 | { |
| 1339 | EMACS_INT saved_charpos = charpos, saved_bytepos = bytepos; | 1334 | EMACS_INT cpos = charpos, bpos = bytepos; |
| 1340 | 1335 | ||
| 1341 | if (cmp_it->lookback > 0) | 1336 | while (1) |
| 1342 | { | 1337 | { |
| 1343 | charpos -= cmp_it->lookback; | 1338 | elt = XCAR (val); |
| 1344 | if (charpos < endpos) | 1339 | if (cmp_it->lookback > 0) |
| 1340 | { | ||
| 1341 | cpos -= cmp_it->lookback; | ||
| 1342 | if (STRINGP (string)) | ||
| 1343 | bpos = string_char_to_byte (string, cpos); | ||
| 1344 | else | ||
| 1345 | bpos = CHAR_TO_BYTE (cpos); | ||
| 1346 | } | ||
| 1347 | lgstring = autocmp_chars (elt, cpos, bpos, charpos + 1, w, face, | ||
| 1348 | string); | ||
| 1349 | if (composition_gstring_p (lgstring) | ||
| 1350 | && cpos + LGSTRING_CHAR_LEN (lgstring) - 1 == charpos) | ||
| 1351 | break; | ||
| 1352 | /* Composition failed or didn't cover the current | ||
| 1353 | character. */ | ||
| 1354 | if (cmp_it->lookback == 0) | ||
| 1345 | goto no_composition; | 1355 | goto no_composition; |
| 1346 | if (STRINGP (string)) | 1356 | lgstring = Qnil; |
| 1347 | bytepos = string_char_to_byte (string, charpos); | 1357 | /* Try to find a shorter compostion that starts after CPOS. */ |
| 1348 | else | 1358 | composition_compute_stop_pos (cmp_it, charpos, bytepos, cpos, |
| 1349 | bytepos = CHAR_TO_BYTE (charpos); | 1359 | string); |
| 1350 | } | 1360 | if (cmp_it->ch == -2 || cmp_it->stop_pos < charpos) |
| 1351 | val = autocmp_chars (val, charpos, bytepos, saved_charpos + 1, | 1361 | goto no_composition; |
| 1352 | w, face, string); | 1362 | val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch); |
| 1353 | if (! composition_gstring_p (val) | 1363 | for (i = 0; i < cmp_it->rule_idx; i++, val = XCDR (val)); |
| 1354 | || charpos + LGSTRING_CHAR_LEN (val) <= saved_charpos) | ||
| 1355 | { | ||
| 1356 | charpos = saved_charpos, bytepos = saved_bytepos; | ||
| 1357 | goto no_composition; | ||
| 1358 | } | 1364 | } |
| 1359 | cmp_it->reversed_p = 1; | 1365 | cmp_it->reversed_p = 1; |
| 1360 | } | 1366 | } |
| 1361 | if (NILP (LGSTRING_ID (val))) | 1367 | if (NILP (lgstring)) |
| 1362 | val = composition_gstring_put_cache (val, -1); | 1368 | goto no_composition; |
| 1363 | cmp_it->id = XINT (LGSTRING_ID (val)); | 1369 | if (NILP (LGSTRING_ID (lgstring))) |
| 1364 | for (i = 0; i < LGSTRING_GLYPH_LEN (val); i++) | 1370 | lgstring = composition_gstring_put_cache (lgstring, -1); |
| 1365 | if (NILP (LGSTRING_GLYPH (val, i))) | 1371 | cmp_it->id = XINT (LGSTRING_ID (lgstring)); |
| 1372 | for (i = 0; i < LGSTRING_GLYPH_LEN (lgstring); i++) | ||
| 1373 | if (NILP (LGSTRING_GLYPH (lgstring, i))) | ||
| 1366 | break; | 1374 | break; |
| 1367 | cmp_it->nglyphs = i; | 1375 | cmp_it->nglyphs = i; |
| 1368 | cmp_it->from = 0; | 1376 | cmp_it->from = 0; |
| @@ -1378,10 +1386,10 @@ composition_reseat_it (cmp_it, charpos, bytepos, endpos, w, face, string) | |||
| 1378 | if (charpos < endpos) | 1386 | if (charpos < endpos) |
| 1379 | { | 1387 | { |
| 1380 | charpos++; | 1388 | charpos++; |
| 1381 | if (STRINGP (string)) | 1389 | if (NILP (string)) |
| 1382 | bytepos += MULTIBYTE_LENGTH_NO_CHECK (SDATA (string) + bytepos); | ||
| 1383 | else | ||
| 1384 | INC_POS (bytepos); | 1390 | INC_POS (bytepos); |
| 1391 | else | ||
| 1392 | bytepos += MULTIBYTE_FORM_LENGTH (SDATA (string) + bytepos, 0); | ||
| 1385 | } | 1393 | } |
| 1386 | else | 1394 | else |
| 1387 | { | 1395 | { |
| @@ -1393,11 +1401,20 @@ composition_reseat_it (cmp_it, charpos, bytepos, endpos, w, face, string) | |||
| 1393 | return 0; | 1401 | return 0; |
| 1394 | } | 1402 | } |
| 1395 | 1403 | ||
| 1396 | /* Update nchars, nbytes, and width of the current grapheme cluster | 1404 | /* Update charpos, nchars, nbytes, and width of the current grapheme |
| 1397 | which is identified by CMP_IT->from (if the composition is static | 1405 | cluster. |
| 1398 | or automatic in l2r context) or CMPT_IT->to (if the composition is | 1406 | |
| 1399 | automatic in r2l context). In addition, in the former case, update | 1407 | If the composition is static or automatic in L2R context, the |
| 1400 | CMP_IT->to, and in the latter case, update CMP_IT->from. */ | 1408 | cluster is identified by CMP_IT->from, and CHARPOS is the position |
| 1409 | of the first character of the cluster. In this case, update | ||
| 1410 | CMP_IT->to too. | ||
| 1411 | |||
| 1412 | If the composition is automatic in R2L context, the cluster is | ||
| 1413 | identified by CMP_IT->to, and CHARPOS is the position of the last | ||
| 1414 | character of the cluster. In this case, update CMP_IT->from too. | ||
| 1415 | |||
| 1416 | The return value is the character code of the first character of | ||
| 1417 | the cluster, or -1 if the composition is somehow broken. */ | ||
| 1401 | 1418 | ||
| 1402 | int | 1419 | int |
| 1403 | composition_update_it (cmp_it, charpos, bytepos, string) | 1420 | composition_update_it (cmp_it, charpos, bytepos, string) |
| @@ -1409,8 +1426,10 @@ composition_update_it (cmp_it, charpos, bytepos, string) | |||
| 1409 | 1426 | ||
| 1410 | if (cmp_it->ch < 0) | 1427 | if (cmp_it->ch < 0) |
| 1411 | { | 1428 | { |
| 1429 | /* static composition */ | ||
| 1412 | struct composition *cmp = composition_table[cmp_it->id]; | 1430 | struct composition *cmp = composition_table[cmp_it->id]; |
| 1413 | 1431 | ||
| 1432 | cmp_it->charpos = charpos; | ||
| 1414 | cmp_it->to = cmp_it->nglyphs; | 1433 | cmp_it->to = cmp_it->nglyphs; |
| 1415 | if (cmp_it->nglyphs == 0) | 1434 | if (cmp_it->nglyphs == 0) |
| 1416 | c = -1; | 1435 | c = -1; |
| @@ -1423,70 +1442,64 @@ composition_update_it (cmp_it, charpos, bytepos, string) | |||
| 1423 | c = ' '; | 1442 | c = ' '; |
| 1424 | } | 1443 | } |
| 1425 | cmp_it->width = cmp->width; | 1444 | cmp_it->width = cmp->width; |
| 1445 | charpos += cmp_it->nchars; | ||
| 1446 | if (STRINGP (string)) | ||
| 1447 | cmp_it->nbytes = string_char_to_byte (string, charpos) - bytepos; | ||
| 1448 | else | ||
| 1449 | cmp_it->nbytes = CHAR_TO_BYTE (charpos) - bytepos; | ||
| 1426 | } | 1450 | } |
| 1427 | else | 1451 | else |
| 1428 | { | 1452 | { |
| 1453 | /* automatic composition */ | ||
| 1429 | Lisp_Object gstring = composition_gstring_from_id (cmp_it->id); | 1454 | Lisp_Object gstring = composition_gstring_from_id (cmp_it->id); |
| 1455 | Lisp_Object glyph; | ||
| 1456 | int from, to; | ||
| 1430 | 1457 | ||
| 1431 | if (cmp_it->nglyphs == 0) | 1458 | if (cmp_it->nglyphs == 0) |
| 1432 | { | 1459 | { |
| 1433 | c = -1; | ||
| 1434 | cmp_it->nchars = LGSTRING_CHAR_LEN (gstring); | 1460 | cmp_it->nchars = LGSTRING_CHAR_LEN (gstring); |
| 1435 | cmp_it->width = 0; | 1461 | cmp_it->width = 0; |
| 1462 | cmp_it->from = cmp_it->to = 0; | ||
| 1463 | return -1; | ||
| 1436 | } | 1464 | } |
| 1437 | else if (! cmp_it->reversed_p) | 1465 | if (! cmp_it->reversed_p) |
| 1438 | { | 1466 | { |
| 1439 | Lisp_Object glyph = LGSTRING_GLYPH (gstring, cmp_it->from); | 1467 | glyph = LGSTRING_GLYPH (gstring, cmp_it->from); |
| 1440 | int from = LGLYPH_FROM (glyph); | 1468 | 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; | 1469 | for (cmp_it->to = cmp_it->from + 1; cmp_it->to < cmp_it->nglyphs; |
| 1447 | cmp_it->to++) | 1470 | cmp_it->to++) |
| 1448 | { | 1471 | { |
| 1449 | glyph = LGSTRING_GLYPH (gstring, cmp_it->to); | 1472 | glyph = LGSTRING_GLYPH (gstring, cmp_it->to); |
| 1450 | if (LGLYPH_FROM (glyph) != from) | 1473 | if (LGLYPH_FROM (glyph) != from) |
| 1451 | break; | 1474 | break; |
| 1452 | if (LGLYPH_WIDTH (glyph) > 0) | ||
| 1453 | cmp_it->width += CHAR_WIDTH (LGLYPH_CHAR (glyph)); | ||
| 1454 | } | 1475 | } |
| 1476 | cmp_it->charpos = charpos; | ||
| 1455 | } | 1477 | } |
| 1456 | else | 1478 | else |
| 1457 | { | 1479 | { |
| 1458 | int from_idx = cmp_it->to - 1; | 1480 | glyph = LGSTRING_GLYPH (gstring, cmp_it->to - 1); |
| 1459 | Lisp_Object glyph = LGSTRING_GLYPH (gstring, from_idx); | 1481 | from = LGLYPH_FROM (glyph); |
| 1460 | int from = LGLYPH_FROM (glyph); | 1482 | cmp_it->charpos = charpos - (LGLYPH_TO (glyph) - from); |
| 1461 | 1483 | for (cmp_it->from = cmp_it->to - 1; cmp_it->from > 0; | |
| 1462 | c = XINT (LGSTRING_CHAR (gstring, from)); | 1484 | cmp_it->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 | { | 1485 | { |
| 1468 | glyph = LGSTRING_GLYPH (gstring, from_idx); | 1486 | glyph = LGSTRING_GLYPH (gstring, cmp_it->from - 1); |
| 1469 | if (LGLYPH_FROM (glyph) != from) | 1487 | if (LGLYPH_FROM (glyph) != from) |
| 1470 | break; | 1488 | break; |
| 1471 | if (LGLYPH_WIDTH (glyph) > 0) | ||
| 1472 | cmp_it->width += CHAR_WIDTH (LGLYPH_CHAR (glyph)); | ||
| 1473 | } | 1489 | } |
| 1474 | cmp_it->from = from_idx + 1; | 1490 | } |
| 1475 | charpos -= cmp_it->nchars - 1; | 1491 | glyph = LGSTRING_GLYPH (gstring, cmp_it->from); |
| 1476 | bytepos += CHAR_BYTES (c); | 1492 | cmp_it->nchars = LGLYPH_TO (glyph) + 1 - from; |
| 1477 | if (STRINGP (string)) | 1493 | cmp_it->nbytes = 0; |
| 1478 | cmp_it->nbytes = bytepos - string_char_to_byte (string, charpos); | 1494 | cmp_it->width = 0; |
| 1479 | else | 1495 | for (i = cmp_it->nchars - 1; i >= 0; i--) |
| 1480 | cmp_it->nbytes = bytepos - CHAR_TO_BYTE (charpos); | 1496 | { |
| 1481 | return c; | 1497 | c = XINT (LGSTRING_CHAR (gstring, i)); |
| 1498 | cmp_it->nbytes += CHAR_BYTES (c); | ||
| 1499 | cmp_it->width = (LGLYPH_WIDTH (glyph) > 0 | ||
| 1500 | ? CHAR_WIDTH (LGLYPH_CHAR (glyph)) : 0); | ||
| 1482 | } | 1501 | } |
| 1483 | } | 1502 | } |
| 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; | 1503 | return c; |
| 1491 | } | 1504 | } |
| 1492 | 1505 | ||
| @@ -1655,7 +1668,7 @@ find_automatic_composition (pos, limit, start, end, gstring, string) | |||
| 1655 | check.pos_byte = cur.pos_byte; | 1668 | check.pos_byte = cur.pos_byte; |
| 1656 | else | 1669 | else |
| 1657 | check.pos_byte = CHAR_TO_BYTE (check.pos); | 1670 | check.pos_byte = CHAR_TO_BYTE (check.pos); |
| 1658 | val = autocmp_chars (check_val, check.pos, check.pos_byte, | 1671 | val = autocmp_chars (elt, check.pos, check.pos_byte, |
| 1659 | tail, w, NULL, string); | 1672 | tail, w, NULL, string); |
| 1660 | need_adjustment = 1; | 1673 | need_adjustment = 1; |
| 1661 | if (! NILP (val)) | 1674 | if (! NILP (val)) |
| @@ -2059,7 +2072,7 @@ preceding and/or following characters, this char-table contains | |||
| 2059 | a function to call to compose that character. | 2072 | a function to call to compose that character. |
| 2060 | 2073 | ||
| 2061 | The element at index C in the table, if non-nil, is a list of | 2074 | The element at index C in the table, if non-nil, is a list of |
| 2062 | this form: ([PATTERN PREV-CHARS FUNC] ...) | 2075 | composition rules of this form: ([PATTERN PREV-CHARS FUNC] ...) |
| 2063 | 2076 | ||
| 2064 | PATTERN is a regular expression which C and the surrounding | 2077 | PATTERN is a regular expression which C and the surrounding |
| 2065 | characters must match. | 2078 | characters must match. |
diff --git a/src/dispextern.h b/src/dispextern.h index 8e8da36daea..a68bc3e9899 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -1968,17 +1968,31 @@ struct composition_it | |||
| 1968 | are not iterating over a composition now. */ | 1968 | are not iterating over a composition now. */ |
| 1969 | int id; | 1969 | int id; |
| 1970 | /* If non-negative, character that triggers the automatic | 1970 | /* If non-negative, character that triggers the automatic |
| 1971 | composition at `stop_pos', and this is an automatic compositoin. | 1971 | composition at `stop_pos', and this is an automatic composition. |
| 1972 | If negative, this is a static composition. This is set to -2 | 1972 | If negative, this is a static composition. This is set to -2 |
| 1973 | temporarily if searching of composition reach a limit or a | 1973 | temporarily if searching of composition reach a limit or a |
| 1974 | newline. */ | 1974 | newline. */ |
| 1975 | int ch; | 1975 | int ch; |
| 1976 | /* If this an automatic composition, how many characters to look back | 1976 | /* If this is an automatic composition, index of a rule for making |
| 1977 | from the position where a character triggering the composition | 1977 | the automatic composition. Provided that ELT is an element of |
| 1978 | exists. */ | 1978 | Vcomposition_function_table for CH, (nth ELT RULE_IDX) is the |
| 1979 | rule for the composition. */ | ||
| 1980 | int rule_idx; | ||
| 1981 | /* If this is an automatic composition, how many characters to look | ||
| 1982 | back from the position where a character triggering the | ||
| 1983 | composition exists. */ | ||
| 1979 | int lookback; | 1984 | int lookback; |
| 1980 | /* If non-negative, number of glyphs of the glyph-string. */ | 1985 | /* If non-negative, number of glyphs of the glyph-string. */ |
| 1981 | int nglyphs; | 1986 | int nglyphs; |
| 1987 | /* Nonzero iff the composition is created while buffer is scanned in | ||
| 1988 | reverse order, and thus the grapheme clusters must be rendered | ||
| 1989 | from the last to the first. */ | ||
| 1990 | int reversed_p; | ||
| 1991 | |||
| 1992 | /** The following members contain information about the current | ||
| 1993 | grapheme cluster. */ | ||
| 1994 | /* Position of the first character of the current grapheme cluster. */ | ||
| 1995 | EMACS_INT charpos; | ||
| 1982 | /* Number of characters and bytes of the current grapheme cluster. */ | 1996 | /* Number of characters and bytes of the current grapheme cluster. */ |
| 1983 | int nchars, nbytes; | 1997 | int nchars, nbytes; |
| 1984 | /* Indices of the glyphs for the current grapheme cluster. */ | 1998 | /* Indices of the glyphs for the current grapheme cluster. */ |
| @@ -1987,10 +2001,6 @@ struct composition_it | |||
| 1987 | graphic display and in units of canonical characters on a | 2001 | graphic display and in units of canonical characters on a |
| 1988 | terminal display. */ | 2002 | terminal display. */ |
| 1989 | int width; | 2003 | int width; |
| 1990 | /* Nonzero iff the composition is created while buffer is scanned in | ||
| 1991 | reverse order, and thus the grapheme clusters must be rendered | ||
| 1992 | from the last to the first. */ | ||
| 1993 | int reversed_p; | ||
| 1994 | }; | 2004 | }; |
| 1995 | 2005 | ||
| 1996 | struct it | 2006 | struct it |
diff --git a/src/xdisp.c b/src/xdisp.c index 6b3097c9a1a..177a0a7e018 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -6339,10 +6339,10 @@ set_iterator_to_next (it, reseat_p) | |||
| 6339 | /* Update IT's char/byte positions to point to the last | 6339 | /* Update IT's char/byte positions to point to the last |
| 6340 | character of the previous grapheme cluster, or the | 6340 | character of the previous grapheme cluster, or the |
| 6341 | character visually after the current composition. */ | 6341 | character visually after the current composition. */ |
| 6342 | bidi_move_to_visually_next (&it->bidi_it); | 6342 | for (i = 0; i < it->cmp_it.nchars; i++) |
| 6343 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 6343 | IT_BYTEPOS (*it) = it->bidi_it.bytepos; | 6344 | IT_BYTEPOS (*it) = it->bidi_it.bytepos; |
| 6344 | IT_CHARPOS (*it) = it->bidi_it.charpos; | 6345 | IT_CHARPOS (*it) = it->bidi_it.charpos; |
| 6345 | |||
| 6346 | if (it->cmp_it.from > 0) | 6346 | if (it->cmp_it.from > 0) |
| 6347 | { | 6347 | { |
| 6348 | /* Proceed to the previous grapheme cluster. */ | 6348 | /* Proceed to the previous grapheme cluster. */ |
| @@ -7108,19 +7108,6 @@ next_element_from_composition (it) | |||
| 7108 | it->object = it->w->buffer; | 7108 | it->object = it->w->buffer; |
| 7109 | it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it), | 7109 | it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it), |
| 7110 | IT_BYTEPOS (*it), Qnil); | 7110 | IT_BYTEPOS (*it), Qnil); |
| 7111 | if (it->cmp_it.reversed_p) | ||
| 7112 | { | ||
| 7113 | /* Now it->position points the last character of the current | ||
| 7114 | grapheme cluster. Adjust it to point the first one. We | ||
| 7115 | have to do it here so that append_composite_glyph sets | ||
| 7116 | correct (struct glyph)->charpos. */ | ||
| 7117 | int i; | ||
| 7118 | for (i = 0; i < it->cmp_it.nchars - 1; i++) | ||
| 7119 | bidi_move_to_visually_next (&it->bidi_it); | ||
| 7120 | IT_CHARPOS (*it) = it->bidi_it.charpos; | ||
| 7121 | IT_BYTEPOS (*it) = it->bidi_it.bytepos; | ||
| 7122 | it->position = it->current.pos; | ||
| 7123 | } | ||
| 7124 | } | 7111 | } |
| 7125 | return 1; | 7112 | return 1; |
| 7126 | } | 7113 | } |
| @@ -21929,7 +21916,7 @@ append_composite_glyph (it) | |||
| 21929 | g[1] = *g; | 21916 | g[1] = *g; |
| 21930 | glyph = it->glyph_row->glyphs[it->area]; | 21917 | glyph = it->glyph_row->glyphs[it->area]; |
| 21931 | } | 21918 | } |
| 21932 | glyph->charpos = CHARPOS (it->position); | 21919 | glyph->charpos = it->cmp_it.charpos; |
| 21933 | glyph->object = it->object; | 21920 | glyph->object = it->object; |
| 21934 | glyph->pixel_width = it->pixel_width; | 21921 | glyph->pixel_width = it->pixel_width; |
| 21935 | glyph->ascent = it->ascent; | 21922 | glyph->ascent = it->ascent; |