diff options
| author | Kenichi Handa | 1998-02-20 01:40:47 +0000 |
|---|---|---|
| committer | Kenichi Handa | 1998-02-20 01:40:47 +0000 |
| commit | c9c0f7cf48021bcbaf899525ba0d0fe1556aae8d (patch) | |
| tree | 0cc690f28f94d6c73e8b266fda18266cae9fc3dd /src | |
| parent | 2d9eea4477dda68e9fa018ddfa0dca19920d1fc2 (diff) | |
| download | emacs-c9c0f7cf48021bcbaf899525ba0d0fe1556aae8d.tar.gz emacs-c9c0f7cf48021bcbaf899525ba0d0fe1556aae8d.zip | |
(MULTIBYTE_BYTES_WIDTH): New macro.
(current_column_1): Don't follow a display table for a heading
byte of a multibyte character. Use the macro
MULTIBYTE_BYTES_WIDTH.
(Fmove_to_column): Likewise.
(compute_motion): Likewise. Handling of wide-column character
fixed.
Diffstat (limited to 'src')
| -rw-r--r-- | src/indent.c | 202 |
1 files changed, 95 insertions, 107 deletions
diff --git a/src/indent.c b/src/indent.c index 28a661dd9f1..733272ee97b 100644 --- a/src/indent.c +++ b/src/indent.c | |||
| @@ -266,6 +266,67 @@ skip_invisible (pos, next_boundary_p, to, window) | |||
| 266 | return pos; | 266 | return pos; |
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | /* Set variables WIDTH and BYTES for a multibyte sequence starting at P. | ||
| 270 | |||
| 271 | C is *P which should satisfy `BASE_LEADING_CODE_P (c)'. | ||
| 272 | |||
| 273 | DP is a display table or NULL. | ||
| 274 | |||
| 275 | This macro is used in current_column_1, Fmove_to_column, and | ||
| 276 | compute_motion. */ | ||
| 277 | |||
| 278 | #define MULTIBYTE_BYTES_WIDTH(p, c, dp) \ | ||
| 279 | do { \ | ||
| 280 | unsigned char *pend = p + 1; \ | ||
| 281 | \ | ||
| 282 | wide_column = 0; \ | ||
| 283 | while (! CHAR_HEAD_P (*pend)) pend++; \ | ||
| 284 | \ | ||
| 285 | if (c == LEADING_CODE_COMPOSITION) \ | ||
| 286 | { \ | ||
| 287 | int id = str_cmpchar_id (p, pend - p); \ | ||
| 288 | int ch = MAKE_COMPOSITE_CHAR (id); \ | ||
| 289 | \ | ||
| 290 | if (id >= 0) \ | ||
| 291 | { \ | ||
| 292 | bytes = cmpchar_table[id]->len; \ | ||
| 293 | if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, ch))) \ | ||
| 294 | width = XVECTOR (DISP_CHAR_VECTOR (dp, ch))->size; \ | ||
| 295 | else \ | ||
| 296 | wide_column = width = cmpchar_table[id]->width; \ | ||
| 297 | } \ | ||
| 298 | else \ | ||
| 299 | { \ | ||
| 300 | bytes = 1; \ | ||
| 301 | width = 4; \ | ||
| 302 | } \ | ||
| 303 | } \ | ||
| 304 | else \ | ||
| 305 | { \ | ||
| 306 | bytes = BYTES_BY_CHAR_HEAD (c); \ | ||
| 307 | if (bytes >= 2 && bytes <= pend - p) \ | ||
| 308 | { \ | ||
| 309 | int ch; \ | ||
| 310 | \ | ||
| 311 | if (dp && (ch = STRING_CHAR (p, bytes), \ | ||
| 312 | VECTORP (DISP_CHAR_VECTOR (dp, ch)))) \ | ||
| 313 | width = XVECTOR (DISP_CHAR_VECTOR (dp, ch))->size; \ | ||
| 314 | else \ | ||
| 315 | wide_column = width = WIDTH_BY_CHAR_HEAD (c); \ | ||
| 316 | } \ | ||
| 317 | else \ | ||
| 318 | { \ | ||
| 319 | bytes = 1; \ | ||
| 320 | width = 4; \ | ||
| 321 | } \ | ||
| 322 | } \ | ||
| 323 | if (p + bytes < pend) \ | ||
| 324 | { \ | ||
| 325 | width += 4 * (pend - (p + bytes)); \ | ||
| 326 | bytes = pend - p; \ | ||
| 327 | } \ | ||
| 328 | } while (0) | ||
| 329 | |||
| 269 | DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0, | 330 | DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0, |
| 270 | "Return the horizontal position of point. Beginning of line is column 0.\n\ | 331 | "Return the horizontal position of point. Beginning of line is column 0.\n\ |
| 271 | This is calculated by adding together the widths of all the displayed\n\ | 332 | This is calculated by adding together the widths of all the displayed\n\ |
| @@ -439,7 +500,9 @@ current_column_1 () | |||
| 439 | } | 500 | } |
| 440 | 501 | ||
| 441 | c = FETCH_BYTE (scan_byte); | 502 | c = FETCH_BYTE (scan_byte); |
| 442 | if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) | 503 | if (dp != 0 |
| 504 | && ! (multibyte && BASE_LEADING_CODE_P (c)) | ||
| 505 | && VECTORP (DISP_CHAR_VECTOR (dp, c))) | ||
| 443 | { | 506 | { |
| 444 | col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; | 507 | col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; |
| 445 | scan++; | 508 | scan++; |
| @@ -460,42 +523,14 @@ current_column_1 () | |||
| 460 | } | 523 | } |
| 461 | else if (multibyte && BASE_LEADING_CODE_P (c)) | 524 | else if (multibyte && BASE_LEADING_CODE_P (c)) |
| 462 | { | 525 | { |
| 463 | scan_byte--; | 526 | unsigned char *ptr; |
| 464 | /* Start of multi-byte form. */ | 527 | int bytes, width, wide_column; |
| 465 | if (c == LEADING_CODE_COMPOSITION) | ||
| 466 | { | ||
| 467 | unsigned char *ptr = BYTE_POS_ADDR (scan_byte); | ||
| 468 | 528 | ||
| 469 | int cmpchar_id | 529 | scan_byte--; |
| 470 | = str_cmpchar_id (ptr, next_boundary_byte - scan_byte); | 530 | ptr = BYTE_POS_ADDR (scan_byte); |
| 471 | if (cmpchar_id >= 0) | 531 | MULTIBYTE_BYTES_WIDTH (ptr, c, dp); |
| 472 | { | 532 | scan_byte += bytes; |
| 473 | scan_byte += cmpchar_table[cmpchar_id]->len; | 533 | col += width; |
| 474 | col += cmpchar_table[cmpchar_id]->width; | ||
| 475 | } | ||
| 476 | else | ||
| 477 | { /* invalid composite character */ | ||
| 478 | scan_byte++; | ||
| 479 | col += 4; | ||
| 480 | } | ||
| 481 | } | ||
| 482 | else | ||
| 483 | { | ||
| 484 | /* Here, we check that the following bytes are valid | ||
| 485 | constituents of multi-byte form. */ | ||
| 486 | int len = BYTES_BY_CHAR_HEAD (c), i; | ||
| 487 | |||
| 488 | for (i = 1, scan_byte++; i < len; i++, scan_byte++) | ||
| 489 | /* We don't need range checking for PTR because there | ||
| 490 | are anchors (`\0') at GAP and Z. */ | ||
| 491 | if (CHAR_HEAD_P (FETCH_BYTE (scan_byte))) | ||
| 492 | break; | ||
| 493 | |||
| 494 | if (i < len) | ||
| 495 | col += 4, scan_byte -= i - 1; | ||
| 496 | else | ||
| 497 | col += WIDTH_BY_CHAR_HEAD (c); | ||
| 498 | } | ||
| 499 | } | 534 | } |
| 500 | else if (ctl_arrow && (c < 040 || c == 0177)) | 535 | else if (ctl_arrow && (c < 040 || c == 0177)) |
| 501 | col += 2; | 536 | col += 2; |
| @@ -838,7 +873,9 @@ The return value is the current column.") | |||
| 838 | break; | 873 | break; |
| 839 | 874 | ||
| 840 | c = FETCH_BYTE (pos_byte); | 875 | c = FETCH_BYTE (pos_byte); |
| 841 | if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) | 876 | if (dp != 0 |
| 877 | && ! (multibyte && BASE_LEADING_CODE_P (c)) | ||
| 878 | && VECTORP (DISP_CHAR_VECTOR (dp, c))) | ||
| 842 | { | 879 | { |
| 843 | col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; | 880 | col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; |
| 844 | pos_byte++; | 881 | pos_byte++; |
| @@ -867,41 +904,13 @@ The return value is the current column.") | |||
| 867 | { | 904 | { |
| 868 | /* Start of multi-byte form. */ | 905 | /* Start of multi-byte form. */ |
| 869 | unsigned char *ptr; | 906 | unsigned char *ptr; |
| 907 | int bytes, width, wide_column; | ||
| 870 | 908 | ||
| 871 | pos_byte--; /* rewind to the character head */ | 909 | pos_byte--; |
| 872 | ptr = BYTE_POS_ADDR (pos_byte); | 910 | ptr = BYTE_POS_ADDR (pos_byte); |
| 873 | if (c == LEADING_CODE_COMPOSITION) | 911 | MULTIBYTE_BYTES_WIDTH (ptr, c, dp); |
| 874 | { | 912 | pos_byte += bytes; |
| 875 | int cmpchar_id = str_cmpchar_id (ptr, end_byte - pos_byte); | 913 | col += width; |
| 876 | |||
| 877 | if (cmpchar_id >= 0) | ||
| 878 | { | ||
| 879 | col += cmpchar_table[cmpchar_id]->width; | ||
| 880 | pos_byte += cmpchar_table[cmpchar_id]->len; | ||
| 881 | } | ||
| 882 | else | ||
| 883 | { /* invalid composite character */ | ||
| 884 | col += 4; | ||
| 885 | pos_byte++; | ||
| 886 | } | ||
| 887 | } | ||
| 888 | else | ||
| 889 | { | ||
| 890 | /* Here, we check that the following bytes are valid | ||
| 891 | constituents of multi-byte form. */ | ||
| 892 | int len = BYTES_BY_CHAR_HEAD (c), i; | ||
| 893 | |||
| 894 | for (i = 1, ptr++; i < len; i++, ptr++) | ||
| 895 | /* We don't need range checking for PTR because there | ||
| 896 | are anchors (`\0') both at GPT and Z. */ | ||
| 897 | if (CHAR_HEAD_P (*ptr)) | ||
| 898 | break; | ||
| 899 | |||
| 900 | if (i < len) | ||
| 901 | col += 4, pos_byte++; | ||
| 902 | else | ||
| 903 | col += WIDTH_BY_CHAR_HEAD (c), pos_byte += i; | ||
| 904 | } | ||
| 905 | } | 914 | } |
| 906 | else | 915 | else |
| 907 | col += 4; | 916 | col += 4; |
| @@ -1046,8 +1055,8 @@ compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, | |||
| 1046 | Lisp_Object window; | 1055 | Lisp_Object window; |
| 1047 | 1056 | ||
| 1048 | int multibyte = !NILP (current_buffer->enable_multibyte_characters); | 1057 | int multibyte = !NILP (current_buffer->enable_multibyte_characters); |
| 1049 | int wide_column = 0; /* Set to 1 when a previous character | 1058 | int wide_column_end_hpos = 0; /* Horizontal position at the end of |
| 1050 | is wide-colomn. */ | 1059 | last wide-column character. */ |
| 1051 | int prev_pos; /* Previous buffer position. */ | 1060 | int prev_pos; /* Previous buffer position. */ |
| 1052 | int prev_pos_byte; /* Previous buffer position. */ | 1061 | int prev_pos_byte; /* Previous buffer position. */ |
| 1053 | int contin_hpos; /* HPOS of last column of continued line. */ | 1062 | int contin_hpos; /* HPOS of last column of continued line. */ |
| @@ -1187,7 +1196,7 @@ compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, | |||
| 1187 | /* Remember the previous value. */ | 1196 | /* Remember the previous value. */ |
| 1188 | prev_tab_offset = tab_offset; | 1197 | prev_tab_offset = tab_offset; |
| 1189 | 1198 | ||
| 1190 | if (wide_column) | 1199 | if (wide_column_end_hpos > width) |
| 1191 | { | 1200 | { |
| 1192 | hpos -= prev_hpos; | 1201 | hpos -= prev_hpos; |
| 1193 | tab_offset += prev_hpos; | 1202 | tab_offset += prev_hpos; |
| @@ -1223,7 +1232,7 @@ compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, | |||
| 1223 | */ | 1232 | */ |
| 1224 | 1233 | ||
| 1225 | if (contin_hpos && prev_hpos == 0 | 1234 | if (contin_hpos && prev_hpos == 0 |
| 1226 | && contin_hpos < width && !wide_column) | 1235 | && contin_hpos < width && !wide_column_end_hpos) |
| 1227 | { | 1236 | { |
| 1228 | /* Line breaking occurs in the middle of multi-column | 1237 | /* Line breaking occurs in the middle of multi-column |
| 1229 | character. Go back to previous line. */ | 1238 | character. Go back to previous line. */ |
| @@ -1240,7 +1249,8 @@ compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, | |||
| 1240 | if (vpos > tovpos || vpos == tovpos && hpos >= tohpos) | 1249 | if (vpos > tovpos || vpos == tovpos && hpos >= tohpos) |
| 1241 | { | 1250 | { |
| 1242 | if (contin_hpos && prev_hpos == 0 | 1251 | if (contin_hpos && prev_hpos == 0 |
| 1243 | && ((hpos > tohpos && contin_hpos == width) || wide_column)) | 1252 | && ((hpos > tohpos && contin_hpos == width) |
| 1253 | || (wide_column_end_hpos > width))) | ||
| 1244 | { /* Line breaks because we can't put the character at the | 1254 | { /* Line breaks because we can't put the character at the |
| 1245 | previous line any more. It is not the multi-column | 1255 | previous line any more. It is not the multi-column |
| 1246 | character continued in middle. Go back to previous | 1256 | character continued in middle. Go back to previous |
| @@ -1260,7 +1270,7 @@ compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, | |||
| 1260 | prev_hpos = hpos; | 1270 | prev_hpos = hpos; |
| 1261 | prev_pos = pos; | 1271 | prev_pos = pos; |
| 1262 | prev_pos_byte = pos_byte; | 1272 | prev_pos_byte = pos_byte; |
| 1263 | wide_column = 0; | 1273 | wide_column_end_hpos = 0; |
| 1264 | 1274 | ||
| 1265 | /* Consult the width run cache to see if we can avoid inspecting | 1275 | /* Consult the width run cache to see if we can avoid inspecting |
| 1266 | the text character-by-character. */ | 1276 | the text character-by-character. */ |
| @@ -1348,8 +1358,9 @@ compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, | |||
| 1348 | } | 1358 | } |
| 1349 | } | 1359 | } |
| 1350 | 1360 | ||
| 1351 | if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)) | 1361 | if (dp != 0 |
| 1352 | && ! (multibyte && BASE_LEADING_CODE_P (c))) | 1362 | && ! (multibyte && BASE_LEADING_CODE_P (c)) |
| 1363 | && VECTORP (DISP_CHAR_VECTOR (dp, c))) | ||
| 1353 | hpos += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; | 1364 | hpos += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; |
| 1354 | else if (c >= 040 && c < 0177) | 1365 | else if (c >= 040 && c < 0177) |
| 1355 | hpos++; | 1366 | hpos++; |
| @@ -1429,37 +1440,14 @@ compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, | |||
| 1429 | { | 1440 | { |
| 1430 | /* Start of multi-byte form. */ | 1441 | /* Start of multi-byte form. */ |
| 1431 | unsigned char *ptr; | 1442 | unsigned char *ptr; |
| 1432 | int len, actual_len; | 1443 | int bytes, width, wide_column; |
| 1433 | |||
| 1434 | pos--, pos_byte--; /* rewind POS */ | ||
| 1435 | 1444 | ||
| 1445 | pos_byte--; /* rewind POS_BYTE */ | ||
| 1436 | ptr = BYTE_POS_ADDR (pos_byte); | 1446 | ptr = BYTE_POS_ADDR (pos_byte); |
| 1437 | len = BUFFER_CEILING_OF (pos_byte) - pos_byte + 1; | 1447 | MULTIBYTE_BYTES_WIDTH (ptr, c, dp); |
| 1438 | 1448 | pos_byte += bytes; | |
| 1439 | c = STRING_CHAR_AND_LENGTH (ptr, len, actual_len); | 1449 | wide_column_end_hpos = hpos + wide_column; |
| 1440 | 1450 | hpos += width; | |
| 1441 | if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) | ||
| 1442 | hpos += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; | ||
| 1443 | else if (actual_len == 1) | ||
| 1444 | hpos += 4; | ||
| 1445 | else if (COMPOSITE_CHAR_P (c)) | ||
| 1446 | { | ||
| 1447 | int id = COMPOSITE_CHAR_ID (c); | ||
| 1448 | int width = (id < n_cmpchars) ? cmpchar_table[id]->width : 0; | ||
| 1449 | hpos += width; | ||
| 1450 | if (width > 1) | ||
| 1451 | wide_column = 1; | ||
| 1452 | } | ||
| 1453 | else | ||
| 1454 | { | ||
| 1455 | int width = WIDTH_BY_CHAR_HEAD (*ptr); | ||
| 1456 | hpos += width; | ||
| 1457 | if (width > 1) | ||
| 1458 | wide_column = 1; | ||
| 1459 | } | ||
| 1460 | |||
| 1461 | pos++; | ||
| 1462 | pos_byte += actual_len; | ||
| 1463 | } | 1451 | } |
| 1464 | else | 1452 | else |
| 1465 | hpos += (ctl_arrow && c < 0200) ? 2 : 4; | 1453 | hpos += (ctl_arrow && c < 0200) ? 2 : 4; |