aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenichi Handa2010-05-25 09:32:24 +0900
committerKenichi Handa2010-05-25 09:32:24 +0900
commit10f72a3793087770f131a0dc729f29ff50f08ad9 (patch)
tree3d6a77b09c6d1b8a36795a50be909c9ed010d39d /src
parent9ba3dd48988911d24100dad2b67e5b45189083dd (diff)
downloademacs-10f72a3793087770f131a0dc729f29ff50f08ad9.tar.gz
emacs-10f72a3793087770f131a0dc729f29ff50f08ad9.zip
Fix bidi-composition interaction in backward scanning..
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog23
-rw-r--r--src/composite.c401
-rw-r--r--src/dispextern.h26
-rw-r--r--src/xdisp.c19
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 @@
12010-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
12010-05-18 Chong Yidong <cyd@stupidchicken.com> 242010-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
924static Lisp_Object 925static Lisp_Object
925autocmp_chars (cft_element, charpos, bytepos, limit, win, face, string) 926autocmp_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
1021static Lisp_Object _work_val; 998static 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
1402int 1419int
1403composition_update_it (cmp_it, charpos, bytepos, string) 1420composition_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
2059a function to call to compose that character. 2072a function to call to compose that character.
2060 2073
2061The element at index C in the table, if non-nil, is a list of 2074The element at index C in the table, if non-nil, is a list of
2062this form: ([PATTERN PREV-CHARS FUNC] ...) 2075composition rules of this form: ([PATTERN PREV-CHARS FUNC] ...)
2063 2076
2064PATTERN is a regular expression which C and the surrounding 2077PATTERN is a regular expression which C and the surrounding
2065characters must match. 2078characters 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
1996struct it 2006struct 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;