aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenichi Handa2008-09-05 00:47:23 +0000
committerKenichi Handa2008-09-05 00:47:23 +0000
commit90b3fe912530f5170ae660f0a9a9a66f35714491 (patch)
tree5f7a8e6a1eddb3200a5d5a018f45e1427c7a4525 /src
parentcbf21103d9fad16fe87d9affbc955c75cce657e4 (diff)
downloademacs-90b3fe912530f5170ae660f0a9a9a66f35714491.tar.gz
emacs-90b3fe912530f5170ae660f0a9a9a66f35714491.zip
(autocmp_chars): Check lookback count.
(composition_compute_stop_pos): Set cmp_it->lookback. (composition_reseat_it): Check lookback count. (struct position_record): New struct. (FORWARD_CHAR, BACKWARD_CHAR, CHAR_COMPOSABLE_P): New macros. (find_automatic_composition): New function. (composition_adjust_point): Use find_automatic_composition.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog12
-rw-r--r--src/composite.c356
2 files changed, 264 insertions, 104 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 2cb1c7b8cb0..ff10dd9b61e 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,15 @@
12008-09-05 Kenichi Handa <handa@m17n.org>
2
3 * composite.c (autocmp_chars): Check lookback count.
4 (composition_compute_stop_pos): Set cmp_it->lookback.
5 (composition_reseat_it): Check lookback count.
6 (struct position_record): New struct.
7 (FORWARD_CHAR, BACKWARD_CHAR, CHAR_COMPOSABLE_P): New macros.
8 (find_automatic_composition): New function.
9 (composition_adjust_point): Use find_automatic_composition.
10
11 * dispextern.h (struct composition_it): New member lookback.
12
12008-09-02 Chong Yidong <cyd@stupidchicken.com> 132008-09-02 Chong Yidong <cyd@stupidchicken.com>
2 14
3 * indent.c (Fvertical_motion): Don't call move_it_by_lines again 15 * indent.c (Fvertical_motion): Don't call move_it_by_lines again
diff --git a/src/composite.c b/src/composite.c
index 257ca66632d..6e9c823d8c1 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -402,8 +402,8 @@ get_composition_id (charpos, bytepos, nchars, prop, string)
402} 402}
403 403
404 404
405/* Find a composition at or nearest to position POS of OBJECT (buffer 405/* Find a static composition at or nearest to position POS of OBJECT
406 or string). 406 (buffer or string).
407 407
408 OBJECT defaults to the current buffer. If there's a composition at 408 OBJECT defaults to the current buffer. If there's a composition at
409 POS, set *START and *END to the start and end of the sequence, 409 POS, set *START and *END to the start and end of the sequence,
@@ -916,9 +916,10 @@ autocmp_chars (cft_element, charpos, bytepos, limit, win, face, string)
916 FRAME_PTR f = XFRAME (win->frame); 916 FRAME_PTR f = XFRAME (win->frame);
917 Lisp_Object pos = make_number (charpos); 917 Lisp_Object pos = make_number (charpos);
918 EMACS_INT pt = PT, pt_byte = PT_BYTE; 918 EMACS_INT pt = PT, pt_byte = PT_BYTE;
919 int lookback;
919 920
920 record_unwind_save_match_data (); 921 record_unwind_save_match_data ();
921 for (; CONSP (cft_element); cft_element = XCDR (cft_element)) 922 for (lookback = -1; CONSP (cft_element); cft_element = XCDR (cft_element))
922 { 923 {
923 Lisp_Object elt = XCAR (cft_element); 924 Lisp_Object elt = XCAR (cft_element);
924 Lisp_Object re; 925 Lisp_Object re;
@@ -927,6 +928,10 @@ autocmp_chars (cft_element, charpos, bytepos, limit, win, face, string)
927 928
928 if (! VECTORP (elt) || ASIZE (elt) != 3) 929 if (! VECTORP (elt) || ASIZE (elt) != 3)
929 continue; 930 continue;
931 if (lookback < 0)
932 lookback = XFASTINT (AREF (elt, 1));
933 else if (lookback != XFASTINT (AREF (elt, 1)))
934 break;
930 re = AREF (elt, 0); 935 re = AREF (elt, 0);
931 if (NILP (string)) 936 if (NILP (string))
932 TEMP_SET_PT_BOTH (charpos, bytepos); 937 TEMP_SET_PT_BOTH (charpos, bytepos);
@@ -1029,7 +1034,8 @@ composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string)
1029 } 1034 }
1030 if (CONSP (val)) 1035 if (CONSP (val))
1031 { 1036 {
1032 cmp_it->stop_pos = charpos - 1 - XFASTINT (AREF (elt, 1)); 1037 cmp_it->lookback = XFASTINT (AREF (elt, 1));
1038 cmp_it->stop_pos = charpos - 1 - cmp_it->lookback;
1033 cmp_it->ch = c; 1039 cmp_it->ch = c;
1034 break; 1040 break;
1035 } 1041 }
@@ -1072,12 +1078,19 @@ composition_reseat_it (cmp_it, charpos, bytepos, endpos, w, face, string)
1072 } 1078 }
1073 else 1079 else
1074 { 1080 {
1075 Lisp_Object val; 1081 Lisp_Object val, elt;
1076 int i; 1082 int i;
1077 1083
1078 val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch); 1084 val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch);
1085 for (; CONSP (val); val = XCDR (val))
1086 {
1087 elt = XCAR (val);
1088 if (cmp_it->lookback == XFASTINT (AREF (elt, 1)))
1089 break;
1090 }
1079 if (NILP (val)) 1091 if (NILP (val))
1080 goto no_composition; 1092 goto no_composition;
1093
1081 val = autocmp_chars (val, charpos, bytepos, endpos, w, face, string); 1094 val = autocmp_chars (val, charpos, bytepos, endpos, w, face, string);
1082 if (! composition_gstring_p (val)) 1095 if (! composition_gstring_p (val))
1083 goto no_composition; 1096 goto no_composition;
@@ -1167,19 +1180,214 @@ composition_update_it (cmp_it, charpos, bytepos, string)
1167} 1180}
1168 1181
1169 1182
1183struct position_record
1184{
1185 EMACS_INT pos, pos_byte;
1186 unsigned char *p;
1187};
1188
1189/* Update the members of POSTION to the next character boundary. */
1190#define FORWARD_CHAR(POSITION, STOP) \
1191 do { \
1192 if ((POSITION).pos == (STOP)) \
1193 (POSITION).p = GAP_END_ADDR; \
1194 (POSITION).pos++; \
1195 (POSITION).pos_byte += BYTES_BY_CHAR_HEAD (*((POSITION).p)); \
1196 (POSITION).p += BYTES_BY_CHAR_HEAD (*((POSITION).p)); \
1197 } while (0)
1198
1199/* Update the members of POSTION to the previous character boundary. */
1200#define BACKWARD_CHAR(POSITION, STOP) \
1201 do { \
1202 if ((POSITION).pos == STOP) \
1203 (POSITION).p = GPT_ADDR; \
1204 do { \
1205 (POSITION).pos_byte--; \
1206 (POSITION).p--; \
1207 } while (! CHAR_HEAD_P (*((POSITION).p))); \
1208 (POSITION).pos--; \
1209 } while (0)
1210
1211static Lisp_Object _work_val;
1212static int _work_char;
1213
1214/* 1 iff the character C is composable. */
1215#define CHAR_COMPOSABLE_P(C) \
1216 (_work_val = CHAR_TABLE_REF (Vunicode_category_table, (C)), \
1217 (SYMBOLP (_work_val) \
1218 && (_work_char = SDATA (SYMBOL_NAME (_work_val))[0]) != 'C' \
1219 && _work_char != 'Z'))
1220
1221/* This is like find_composition, but find an automatic composition
1222 instead. If found, set *GSTRING to the glyph-string representing
1223 the composition, and return 1. Otherwise, return 0. */
1224
1225static int
1226find_automatic_composition (pos, limit, start, end, gstring, string)
1227 EMACS_INT pos, limit, *start, *end;
1228 Lisp_Object *gstring, string;
1229{
1230 EMACS_INT head, tail, stop;
1231 struct position_record orig, cur, check, prev;
1232 Lisp_Object check_val, val, elt;
1233 int check_lookback;
1234 int c;
1235 struct window *w;
1236
1237 orig.pos = pos;
1238 if (NILP (string))
1239 {
1240 head = BEGV, tail = ZV, stop = GPT;
1241 orig.pos_byte = CHAR_TO_BYTE (orig.pos);
1242 orig.p = BYTE_POS_ADDR (orig.pos_byte);
1243 }
1244 else
1245 {
1246 head = 0, tail = SCHARS (string), stop = -1;
1247 orig.pos_byte = string_char_to_byte (string, orig.pos);
1248 orig.p = SDATA (string) + orig.pos_byte;
1249 }
1250 if (limit < pos)
1251 {
1252 head = max (head, limit);
1253 tail = min (tail, pos + 3);
1254 }
1255 else
1256 {
1257 tail = min (tail, limit + 3);
1258 }
1259 w = XWINDOW (selected_window);
1260 cur = orig;
1261
1262 retry:
1263 check_val = Qnil;
1264 /* At first, check if POS is compoable. */
1265 c = STRING_CHAR (cur.p, 0);
1266 if (! CHAR_COMPOSABLE_P (c))
1267 {
1268 if (limit < 0)
1269 return 0;
1270 if (limit >= cur.pos)
1271 goto search_forward;
1272 }
1273 else
1274 {
1275 val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1276 if (! NILP (val))
1277 check_val = val, check = cur;
1278 else
1279 while (cur.pos + 1 < tail)
1280 {
1281 FORWARD_CHAR (cur, stop);
1282 c = STRING_CHAR (cur.p, 0);
1283 if (! CHAR_COMPOSABLE_P (c))
1284 break;
1285 val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1286 if (NILP (val))
1287 continue;
1288 check_val = val, check = cur;
1289 break;
1290 }
1291 cur = orig;
1292 }
1293 /* Rewind back to the position where we can safely search forward
1294 for compositions. */
1295 while (cur.pos > head)
1296 {
1297 BACKWARD_CHAR (cur, stop);
1298 c = STRING_CHAR (cur.p, 0);
1299 if (! CHAR_COMPOSABLE_P (c))
1300 break;
1301 val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1302 if (! NILP (val))
1303 check_val = val, check = cur;
1304 }
1305 prev = cur;
1306 /* Now search forward. */
1307 search_forward:
1308 *gstring = Qnil;
1309 if (! NILP (check_val) || limit >= orig.pos)
1310 {
1311 if (NILP (check_val))
1312 cur = orig;
1313 else
1314 cur = check;
1315 while (cur.pos < tail)
1316 {
1317 int need_adjustment = 0;
1318
1319 if (NILP (check_val))
1320 {
1321 c = STRING_CHAR (cur.p, 0);
1322 check_val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1323 }
1324 for (; CONSP (check_val); check_val = XCDR (check_val))
1325 {
1326 elt = XCAR (check_val);
1327 if (VECTORP (elt) && ASIZE (elt) == 3 && NATNUMP (AREF (elt, 1))
1328 && cur.pos - XFASTINT (AREF (elt, 1)) >= head)
1329 {
1330 check.pos = cur.pos - XFASTINT (AREF (elt, 1));
1331 if (check.pos == cur.pos)
1332 check.pos_byte = cur.pos_byte;
1333 else
1334 check.pos_byte = CHAR_TO_BYTE (check.pos);
1335 val = autocmp_chars (check_val, check.pos, check.pos_byte,
1336 tail, w, NULL, string);
1337 need_adjustment = 1;
1338 if (! NILP (val))
1339 {
1340 *gstring = val;
1341 *start = check.pos;
1342 *end = check.pos + LGSTRING_CHAR_LEN (*gstring);
1343 if (*start <= orig.pos ? *end > orig.pos
1344 : limit >= orig.pos)
1345 return 1;
1346 cur.pos = *end;
1347 cur.pos_byte = CHAR_TO_BYTE (cur.pos);
1348 break;
1349 }
1350 }
1351 }
1352 if (need_adjustment)
1353 {
1354 /* As we have called Lisp, there's a possibilily that
1355 buffer/string is relocated. */
1356 if (NILP (string))
1357 cur.p = BYTE_POS_ADDR (cur.pos_byte);
1358 else
1359 cur.p = SDATA (string) + cur.pos_byte;
1360 }
1361 if (! CONSP (check_val))
1362 FORWARD_CHAR (cur, stop);
1363 check_val = Qnil;
1364 }
1365 }
1366 if (! NILP (*gstring))
1367 return (limit >= 0 || (*start <= orig.pos && *end > orig.pos));
1368 if (limit >= 0 && limit < orig.pos && prev.pos > head)
1369 {
1370 cur = prev;
1371 BACKWARD_CHAR (cur, stop);
1372 orig = cur;
1373 tail = orig.pos;
1374 goto retry;
1375 }
1376 return 0;
1377}
1378
1170int 1379int
1171composition_adjust_point (last_pt) 1380composition_adjust_point (last_pt)
1172 EMACS_INT last_pt; 1381 EMACS_INT last_pt;
1173{ 1382{
1174 /* Now check the automatic composition. */
1175 EMACS_INT charpos, bytepos, startpos, beg, end, pos; 1383 EMACS_INT charpos, bytepos, startpos, beg, end, pos;
1176 Lisp_Object val, cat; 1384 Lisp_Object val;
1177 EMACS_INT limit; 1385 int i;
1178 int c;
1179 1386
1180 if (PT == BEGV || PT == ZV) 1387 if (PT == BEGV || PT == ZV)
1181 return PT; 1388 return PT;
1182 1389
1390 /* At first check the static composition. */
1183 if (get_property_and_range (PT, Qcomposition, &val, &beg, &end, Qnil) 1391 if (get_property_and_range (PT, Qcomposition, &val, &beg, &end, Qnil)
1184 && COMPOSITION_VALID_P (beg, end, val) 1392 && COMPOSITION_VALID_P (beg, end, val)
1185 && beg < PT /* && end > PT <- It's always the case. */ 1393 && beg < PT /* && end > PT <- It's always the case. */
@@ -1190,97 +1398,22 @@ composition_adjust_point (last_pt)
1190 || ! FUNCTIONP (Vauto_composition_function)) 1398 || ! FUNCTIONP (Vauto_composition_function))
1191 return PT; 1399 return PT;
1192 1400
1193 c = FETCH_MULTIBYTE_CHAR (PT_BYTE); 1401 /* Next check the automatic composition. */
1194 cat = CHAR_TABLE_REF (Vunicode_category_table, c); 1402 if (! find_automatic_composition (PT, -1, &beg, &end, &val, Qnil)
1195 if (SYMBOLP (cat) 1403 || beg == PT)
1196 && ((c = SDATA (SYMBOL_NAME (cat))[0]) == 'C' || c == 'Z'))
1197 /* A control character is never composed. */
1198 return PT; 1404 return PT;
1199 1405 for (i = 0; i < LGSTRING_GLYPH_LEN (val); i++)
1200 charpos = PT;
1201 bytepos = PT_BYTE;
1202 limit = (last_pt < PT ? last_pt : BEGV);
1203 do {
1204 DEC_BOTH (charpos, bytepos);
1205 c = FETCH_MULTIBYTE_CHAR (bytepos);
1206 cat = CHAR_TABLE_REF (Vunicode_category_table, c);
1207 if (SYMBOLP (cat)
1208 && ((c = SDATA (SYMBOL_NAME (cat))[0]) == 'C' || c == 'Z'))
1209 {
1210 INC_BOTH (charpos, bytepos);
1211 break;
1212 }
1213 } while (charpos > limit);
1214
1215
1216 limit = (last_pt < PT ? ZV : last_pt);
1217 if (limit > PT + 3)
1218 limit = PT + 3;
1219 startpos = charpos;
1220 while (charpos < limit)
1221 { 1406 {
1222 c = FETCH_MULTIBYTE_CHAR (bytepos); 1407 Lisp_Object glyph = LGSTRING_GLYPH (val, i);
1223 if (charpos > PT)
1224 {
1225 int ch;
1226
1227 cat = CHAR_TABLE_REF (Vunicode_category_table, c);
1228 if (SYMBOLP (cat)
1229 && ((ch = SDATA (SYMBOL_NAME (cat))[0]) == 'C' || ch == 'Z'))
1230 return PT;
1231 }
1232 val = CHAR_TABLE_REF (Vcomposition_function_table, c);
1233 if (! CONSP (val))
1234 {
1235 INC_BOTH (charpos, bytepos);
1236 continue;
1237 }
1238 for (; CONSP (val); val = XCDR (val))
1239 {
1240 Lisp_Object elt = XCAR (val);
1241 1408
1242 if (VECTORP (elt) && ASIZE (elt) == 3 && NATNUMP (AREF (elt, 1)) 1409 if (NILP (glyph))
1243 && (pos = charpos - XFASTINT (AREF (elt, 1))) < PT 1410 break;
1244 && pos >= startpos) 1411 if (beg + LGLYPH_FROM (glyph) == PT)
1245 { 1412 return PT;
1246 Lisp_Object gstring; 1413 if (beg + LGLYPH_TO (glyph) >= PT)
1247 EMACS_INT pos_byte; 1414 return (PT < last_pt
1248 1415 ? beg + LGLYPH_FROM (glyph)
1249 if (XFASTINT (AREF (elt, 1)) == 0) 1416 : beg + LGLYPH_TO (glyph) + 1);
1250 pos_byte = bytepos;
1251 else
1252 pos_byte = CHAR_TO_BYTE (pos);
1253 gstring = autocmp_chars (val, pos, pos_byte, Z,
1254 XWINDOW (selected_window), NULL, Qnil);
1255 if (composition_gstring_p (gstring))
1256 {
1257 if (pos + LGSTRING_CHAR_LEN (gstring) > PT)
1258 {
1259 int i;
1260
1261 for (i = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
1262 {
1263 Lisp_Object glyph = LGSTRING_GLYPH (gstring, i);
1264
1265 if (NILP (glyph))
1266 break;
1267 if (pos + LGLYPH_FROM (glyph) == PT)
1268 return PT;
1269 if (pos + LGLYPH_TO (glyph) + 1 > PT)
1270 return (PT < last_pt
1271 ? pos + LGLYPH_FROM (glyph)
1272 : pos + LGLYPH_TO (glyph) + 1);
1273 }
1274 return PT;
1275 }
1276 charpos = startpos = pos + LGSTRING_CHAR_LEN (gstring);
1277 bytepos = CHAR_TO_BYTE (charpos);
1278 break;
1279 }
1280 }
1281 }
1282 if (! CONSP (val))
1283 INC_BOTH (charpos, bytepos);
1284 } 1417 }
1285 return PT; 1418 return PT;
1286} 1419}
@@ -1395,19 +1528,19 @@ See `find-composition' for more detail. */)
1395 (pos, limit, string, detail_p) 1528 (pos, limit, string, detail_p)
1396 Lisp_Object pos, limit, string, detail_p; 1529 Lisp_Object pos, limit, string, detail_p;
1397{ 1530{
1398 Lisp_Object prop, tail; 1531 Lisp_Object prop, tail, gstring;
1399 EMACS_INT start, end; 1532 EMACS_INT start, end, from, to;
1400 int id; 1533 int id;
1401 1534
1402 CHECK_NUMBER_COERCE_MARKER (pos); 1535 CHECK_NUMBER_COERCE_MARKER (pos);
1403 start = XINT (pos); 1536 from = XINT (pos);
1404 if (!NILP (limit)) 1537 if (!NILP (limit))
1405 { 1538 {
1406 CHECK_NUMBER_COERCE_MARKER (limit); 1539 CHECK_NUMBER_COERCE_MARKER (limit);
1407 end = XINT (limit); 1540 to = XINT (limit);
1408 } 1541 }
1409 else 1542 else
1410 end = -1; 1543 to = -1;
1411 1544
1412 if (!NILP (string)) 1545 if (!NILP (string))
1413 { 1546 {
@@ -1421,8 +1554,23 @@ See `find-composition' for more detail. */)
1421 args_out_of_range (Fcurrent_buffer (), pos); 1554 args_out_of_range (Fcurrent_buffer (), pos);
1422 } 1555 }
1423 1556
1424 if (!find_composition (start, end, &start, &end, &prop, string)) 1557 if (!find_composition (from, to, &start, &end, &prop, string))
1425 return Qnil; 1558 {
1559 if (!NILP (current_buffer->enable_multibyte_characters)
1560 && FUNCTIONP (Vauto_composition_function)
1561 && find_automatic_composition (from, to, &start, &end, &gstring,
1562 string))
1563 return list3 (make_number (start), make_number (end), gstring);
1564 return Qnil;
1565 }
1566 if ((end <= XINT (pos) || start > XINT (pos)))
1567 {
1568 EMACS_INT s, e;
1569
1570 if (find_automatic_composition (from, to, &s, &e, &gstring, string)
1571 && (e <= XINT (pos) ? e > end : s < start))
1572 return list3 (make_number (start), make_number (end), gstring);
1573 }
1426 if (!COMPOSITION_VALID_P (start, end, prop)) 1574 if (!COMPOSITION_VALID_P (start, end, prop))
1427 return Fcons (make_number (start), Fcons (make_number (end), 1575 return Fcons (make_number (start), Fcons (make_number (end),
1428 Fcons (Qnil, Qnil))); 1576 Fcons (Qnil, Qnil)));