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 }