Mercurial > emacs
comparison src/indent.c @ 20938:12e635300b44
(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.
author | Kenichi Handa <handa@m17n.org> |
---|---|
date | Fri, 20 Feb 1998 01:40:47 +0000 |
parents | c80b908e5af5 |
children | 020b0eade8c5 |
comparison
equal
deleted
inserted
replaced
20937:f77dcb2556c5 | 20938:12e635300b44 |
---|---|
264 if (TEXT_PROP_MEANS_INVISIBLE (prop)) | 264 if (TEXT_PROP_MEANS_INVISIBLE (prop)) |
265 return *next_boundary_p; | 265 return *next_boundary_p; |
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\ |
272 representations of the character between the start of the previous line\n\ | 333 representations of the character between the start of the previous line\n\ |
273 and point. (eg control characters will have a width of 2 or 4, tabs\n\ | 334 and point. (eg control characters will have a width of 2 or 4, tabs\n\ |
437 scan_byte = CHAR_TO_BYTE (scan); | 498 scan_byte = CHAR_TO_BYTE (scan); |
438 next_boundary_byte = CHAR_TO_BYTE (next_boundary); | 499 next_boundary_byte = CHAR_TO_BYTE (next_boundary); |
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++; |
446 scan_byte++; | 509 scan_byte++; |
447 continue; | 510 continue; |
458 col += tab_width; | 521 col += tab_width; |
459 col = col / tab_width * tab_width; | 522 col = col / tab_width * tab_width; |
460 } | 523 } |
461 else if (multibyte && BASE_LEADING_CODE_P (c)) | 524 else if (multibyte && BASE_LEADING_CODE_P (c)) |
462 { | 525 { |
526 unsigned char *ptr; | |
527 int bytes, width, wide_column; | |
528 | |
463 scan_byte--; | 529 scan_byte--; |
464 /* Start of multi-byte form. */ | 530 ptr = BYTE_POS_ADDR (scan_byte); |
465 if (c == LEADING_CODE_COMPOSITION) | 531 MULTIBYTE_BYTES_WIDTH (ptr, c, dp); |
466 { | 532 scan_byte += bytes; |
467 unsigned char *ptr = BYTE_POS_ADDR (scan_byte); | 533 col += width; |
468 | |
469 int cmpchar_id | |
470 = str_cmpchar_id (ptr, next_boundary_byte - scan_byte); | |
471 if (cmpchar_id >= 0) | |
472 { | |
473 scan_byte += cmpchar_table[cmpchar_id]->len; | |
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; |
502 else if (c < 040 || c >= 0177) | 537 else if (c < 040 || c >= 0177) |
503 col += 4; | 538 col += 4; |
836 character on which the cursor will appear. */ | 871 character on which the cursor will appear. */ |
837 if (col >= goal) | 872 if (col >= goal) |
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++; |
845 pos++; | 882 pos++; |
846 continue; | 883 continue; |
865 col++; | 902 col++; |
866 else if (multibyte && BASE_LEADING_CODE_P (c)) | 903 else if (multibyte && BASE_LEADING_CODE_P (c)) |
867 { | 904 { |
868 /* Start of multi-byte form. */ | 905 /* Start of multi-byte form. */ |
869 unsigned char *ptr; | 906 unsigned char *ptr; |
870 | 907 int bytes, width, wide_column; |
871 pos_byte--; /* rewind to the character head */ | 908 |
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; |
908 } | 917 } |
909 endloop: | 918 endloop: |
1044 /* The next buffer pos where we should consult the width run cache. */ | 1053 /* The next buffer pos where we should consult the width run cache. */ |
1045 int next_width_run = from; | 1054 int next_width_run = from; |
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. */ |
1054 int prev_tab_offset; /* Previous tab offset. */ | 1063 int prev_tab_offset; /* Previous tab offset. */ |
1055 | 1064 |
1185 { | 1194 { |
1186 /* Continuing. */ | 1195 /* Continuing. */ |
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; |
1194 } | 1203 } |
1195 else | 1204 else |
1221 \---- prev_hpos | 1230 \---- prev_hpos |
1222 ---------- | 1231 ---------- |
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. */ |
1230 hpos = contin_hpos; | 1239 hpos = contin_hpos; |
1231 vpos = vpos - 1; | 1240 vpos = vpos - 1; |
1238 } | 1247 } |
1239 | 1248 |
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 |
1247 buffer position, screen position, and set tab offset | 1257 buffer position, screen position, and set tab offset |
1248 to previous value. It's the beginning of the | 1258 to previous value. It's the beginning of the |
1258 break; | 1268 break; |
1259 | 1269 |
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. */ |
1267 if (current_buffer->width_run_cache && pos >= next_width_run) | 1277 if (current_buffer->width_run_cache && pos >= next_width_run) |
1268 { | 1278 { |
1346 width_run_start = pos - 1; | 1356 width_run_start = pos - 1; |
1347 width_run_end = pos; | 1357 width_run_end = pos; |
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++; |
1356 else if (c == '\t') | 1367 else if (c == '\t') |
1357 { | 1368 { |
1427 } | 1438 } |
1428 else if (multibyte && BASE_LEADING_CODE_P (c)) | 1439 else if (multibyte && BASE_LEADING_CODE_P (c)) |
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 | 1444 |
1434 pos--, pos_byte--; /* rewind POS */ | 1445 pos_byte--; /* rewind POS_BYTE */ |
1435 | |
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; |
1466 } | 1454 } |
1467 } | 1455 } |