aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2008-03-26 18:10:51 +0000
committerStefan Monnier2008-03-26 18:10:51 +0000
commitef6f5c0eef1d798d5be1c6fe1ac4d55fc8e3886e (patch)
treef5882c03cb46ab5af04ec510ecacef1c58acfeaa /src
parent8c01c0d4ebbe1b4baa88dabe0995538feb1d9b80 (diff)
downloademacs-ef6f5c0eef1d798d5be1c6fe1ac4d55fc8e3886e.tar.gz
emacs-ef6f5c0eef1d798d5be1c6fe1ac4d55fc8e3886e.zip
(scan_for_column): Extract from current_column_1.
Merge with the same code from Fmove_to_column. (current_column_1, Fmove_to_column): Use it.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog6
-rw-r--r--src/indent.c273
2 files changed, 93 insertions, 186 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 0e571c82623..3dd9051e454 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
12008-03-26 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * indent.c (scan_for_column): Extract from current_column_1.
4 Merge with the same code from Fmove_to_column.
5 (current_column_1, Fmove_to_column): Use it.
6
12008-03-25 Stefan Monnier <monnier@iro.umontreal.ca> 72008-03-25 Stefan Monnier <monnier@iro.umontreal.ca>
2 8
3 * keymap.c (map_keymap_internal): New fun. 9 * keymap.c (map_keymap_internal): New fun.
diff --git a/src/indent.c b/src/indent.c
index b4443825c5d..b4a47782e3e 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -504,13 +504,14 @@ current_column ()
504 return col; 504 return col;
505} 505}
506 506
507/* Return the column number of position POS 507/* Scanning from the beginning of the current line, stop at the buffer
508 by scanning forward from the beginning of the line. 508 position ENDPOS or at the column GOALCOL or at the end of line, whichever
509 This function handles characters that are invisible 509 comes first.
510 due to text properties or overlays. */ 510 Return the resulting buffer position and column in ENDPOS and GOALCOL.
511 511 PREVCOL gets set to the column of the previous position (it's always
512static double 512 strictly smaller than the goal column). */
513current_column_1 () 513static void
514scan_for_column (EMACS_INT *endpos, EMACS_INT *goalcol, EMACS_INT *prevcol)
514{ 515{
515 register EMACS_INT tab_width = XINT (current_buffer->tab_width); 516 register EMACS_INT tab_width = XINT (current_buffer->tab_width);
516 register int ctl_arrow = !NILP (current_buffer->ctl_arrow); 517 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
@@ -518,47 +519,57 @@ current_column_1 ()
518 int multibyte = !NILP (current_buffer->enable_multibyte_characters); 519 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
519 520
520 /* Start the scan at the beginning of this line with column number 0. */ 521 /* Start the scan at the beginning of this line with column number 0. */
521 register EMACS_INT col = 0; 522 register EMACS_INT col = 0, prev_col = 0;
523 EMACS_INT goal = goalcol ? *goalcol : MOST_POSITIVE_FIXNUM;
524 EMACS_INT end = endpos ? *endpos : PT;
522 EMACS_INT scan, scan_byte; 525 EMACS_INT scan, scan_byte;
523 EMACS_INT next_boundary; 526 EMACS_INT next_boundary;
527 {
524 EMACS_INT opoint = PT, opoint_byte = PT_BYTE; 528 EMACS_INT opoint = PT, opoint_byte = PT_BYTE;
525
526 scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1); 529 scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
527 current_column_bol_cache = PT; 530 current_column_bol_cache = PT;
528 scan = PT, scan_byte = PT_BYTE; 531 scan = PT, scan_byte = PT_BYTE;
529 SET_PT_BOTH (opoint, opoint_byte); 532 SET_PT_BOTH (opoint, opoint_byte);
530 next_boundary = scan; 533 next_boundary = scan;
534 }
531 535
532 if (tab_width <= 0 || tab_width > 1000) tab_width = 8; 536 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
533 537
534 /* Scan forward to the target position. */ 538 /* Scan forward to the target position. */
535 while (scan < opoint) 539 while (scan < end)
536 { 540 {
537 int c; 541 int c;
538 542
539 /* Occasionally we may need to skip invisible text. */ 543 /* Occasionally we may need to skip invisible text. */
540 while (scan == next_boundary) 544 while (scan == next_boundary)
541 { 545 {
542 int old_scan = scan; 546 EMACS_INT old_scan = scan;
543 /* This updates NEXT_BOUNDARY to the next place 547 /* This updates NEXT_BOUNDARY to the next place
544 where we might need to skip more invisible text. */ 548 where we might need to skip more invisible text. */
545 scan = skip_invisible (scan, &next_boundary, opoint, Qnil); 549 scan = skip_invisible (scan, &next_boundary, end, Qnil);
546 if (scan >= opoint)
547 goto endloop;
548 if (scan != old_scan) 550 if (scan != old_scan)
549 scan_byte = CHAR_TO_BYTE (scan); 551 scan_byte = CHAR_TO_BYTE (scan);
552 if (scan >= end)
553 goto endloop;
550 } 554 }
551 555
556 /* Test reaching the goal column. We do this after skipping
557 invisible characters, so that we put point before the
558 character on which the cursor will appear. */
559 if (col >= goal)
560 break;
561 prev_col = col;
562
552 /* Check composition sequence. */ 563 /* Check composition sequence. */
553 { 564 {
554 int len, len_byte, width; 565 int len, len_byte, width;
555 566
556 if (check_composition (scan, scan_byte, opoint, 567 if (check_composition (scan, scan_byte, end,
557 &len, &len_byte, &width)) 568 &len, &len_byte, &width))
558 { 569 {
559 scan += len; 570 scan += len;
560 scan_byte += len_byte; 571 scan_byte += len_byte;
561 if (scan <= opoint) 572 if (scan <= end)
562 col += width; 573 col += width;
563 continue; 574 continue;
564 } 575 }
@@ -566,6 +577,9 @@ current_column_1 ()
566 577
567 c = FETCH_BYTE (scan_byte); 578 c = FETCH_BYTE (scan_byte);
568 579
580 /* See if there is a display table and it relates
581 to this character. */
582
569 if (dp != 0 583 if (dp != 0
570 && ! (multibyte && BASE_LEADING_CODE_P (c)) 584 && ! (multibyte && BASE_LEADING_CODE_P (c))
571 && VECTORP (DISP_CHAR_VECTOR (dp, c))) 585 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
@@ -574,7 +588,7 @@ current_column_1 ()
574 EMACS_INT i, n; 588 EMACS_INT i, n;
575 589
576 /* This character is displayed using a vector of glyphs. 590 /* This character is displayed using a vector of glyphs.
577 Update the column based on those glyphs. */ 591 Update the column/position based on those glyphs. */
578 592
579 charvec = DISP_CHAR_VECTOR (dp, c); 593 charvec = DISP_CHAR_VECTOR (dp, c);
580 n = ASIZE (charvec); 594 n = ASIZE (charvec);
@@ -606,8 +620,8 @@ current_column_1 ()
606 } 620 }
607 else 621 else
608 { 622 {
609 /* The display table says nothing for this character. 623 /* The display table doesn't affect this character;
610 Display it as itself. */ 624 it displays as itself. */
611 625
612 if (c == '\n') 626 if (c == '\n')
613 goto endloop; 627 goto endloop;
@@ -620,15 +634,15 @@ current_column_1 ()
620 } 634 }
621 else if (multibyte && BASE_LEADING_CODE_P (c)) 635 else if (multibyte && BASE_LEADING_CODE_P (c))
622 { 636 {
637 /* Start of multi-byte form. */
623 unsigned char *ptr; 638 unsigned char *ptr;
624 int bytes, width, wide_column; 639 int bytes, width, wide_column;
625 640
626 ptr = BYTE_POS_ADDR (scan_byte); 641 ptr = BYTE_POS_ADDR (scan_byte);
627 MULTIBYTE_BYTES_WIDTH (ptr, dp); 642 MULTIBYTE_BYTES_WIDTH (ptr, dp);
628 scan_byte += bytes;
629 /* Subtract one to compensate for the increment 643 /* Subtract one to compensate for the increment
630 that is going to happen below. */ 644 that is going to happen below. */
631 scan_byte--; 645 scan_byte += bytes - 1;
632 col += width; 646 col += width;
633 } 647 }
634 else if (ctl_arrow && (c < 040 || c == 0177)) 648 else if (ctl_arrow && (c < 040 || c == 0177))
@@ -648,6 +662,26 @@ current_column_1 ()
648 last_known_column_point = PT; 662 last_known_column_point = PT;
649 last_known_column_modified = MODIFF; 663 last_known_column_modified = MODIFF;
650 664
665 if (goalcol)
666 *goalcol = col;
667 if (endpos)
668 *endpos = scan;
669 if (prevcol)
670 *prevcol = prev_col;
671}
672
673/* Return the column number of position POS
674 by scanning forward from the beginning of the line.
675 This function handles characters that are invisible
676 due to text properties or overlays. */
677
678static double
679current_column_1 ()
680{
681 EMACS_INT col = MOST_POSITIVE_FIXNUM;
682 EMACS_INT opoint = PT;
683
684 scan_for_column (&opoint, &col, NULL);
651 return col; 685 return col;
652} 686}
653 687
@@ -933,179 +967,47 @@ The return value is the current column. */)
933 (column, force) 967 (column, force)
934 Lisp_Object column, force; 968 Lisp_Object column, force;
935{ 969{
936 register EMACS_INT pos; 970 EMACS_INT pos;
937 register EMACS_INT col = current_column (); 971 EMACS_INT col, prev_col;
938 register EMACS_INT goal; 972 EMACS_INT goal;
939 register EMACS_INT end;
940 register int tab_width = XINT (current_buffer->tab_width);
941 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
942 register struct Lisp_Char_Table *dp = buffer_display_table ();
943 register int multibyte = !NILP (current_buffer->enable_multibyte_characters);
944 973
945 Lisp_Object val;
946 EMACS_INT prev_col = 0;
947 int c = 0;
948 EMACS_INT next_boundary, pos_byte;
949
950 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
951 CHECK_NATNUM (column); 974 CHECK_NATNUM (column);
952 goal = XINT (column); 975 goal = XINT (column);
953 976
954 pos = PT; 977 col = goal;
955 pos_byte = PT_BYTE; 978 pos = ZV;
956 end = ZV; 979 scan_for_column (&pos, &col, &prev_col);
957 980
958 /* If we're starting past the desired column, 981 SET_PT (pos);
959 back up to beginning of line and scan from there. */
960 if (col > goal)
961 {
962 end = pos;
963 pos = current_column_bol_cache;
964 pos_byte = CHAR_TO_BYTE (pos);
965 col = 0;
966 }
967 982
968 next_boundary = pos; 983 /* If a tab char made us overshoot, change it to spaces
969 984 and scan through it again. */
970 while (pos < end) 985 if (!NILP (force) && col > goal)
971 { 986 {
972 while (pos == next_boundary) 987 EMACS_INT pos_byte = PT_BYTE;
973 { 988 DEC_POS (pos_byte);
974 EMACS_INT prev = pos; 989 int c = FETCH_CHAR (pos_byte);
975 pos = skip_invisible (pos, &next_boundary, end, Qnil);
976 if (pos != prev)
977 pos_byte = CHAR_TO_BYTE (pos);
978 if (pos >= end)
979 goto endloop;
980 }
981
982 /* Test reaching the goal column. We do this after skipping
983 invisible characters, so that we put point before the
984 character on which the cursor will appear. */
985 if (col >= goal)
986 break;
987
988 /* Check composition sequence. */
989 {
990 int len, len_byte, width;
991
992 if (check_composition (pos, pos_byte, Z, &len, &len_byte, &width))
993 {
994 pos += len;
995 pos_byte += len_byte;
996 col += width;
997 continue;
998 }
999 }
1000
1001 c = FETCH_BYTE (pos_byte);
1002
1003 /* See if there is a display table and it relates
1004 to this character. */
1005
1006 if (dp != 0
1007 && ! (multibyte && BASE_LEADING_CODE_P (c))
1008 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
1009 {
1010 Lisp_Object charvec;
1011 EMACS_INT i, n;
1012
1013 /* This character is displayed using a vector of glyphs.
1014 Update the position based on those glyphs. */
1015
1016 charvec = DISP_CHAR_VECTOR (dp, c);
1017 n = ASIZE (charvec);
1018
1019 for (i = 0; i < n; i++)
1020 {
1021 /* This should be handled the same as
1022 next_element_from_display_vector does it. */
1023 Lisp_Object entry = AREF (charvec, i);
1024
1025 if (GLYPH_CODE_P (entry)
1026 && GLYPH_CODE_CHAR_VALID_P (entry))
1027 c = GLYPH_CODE_CHAR (entry);
1028 else
1029 c = ' ';
1030 990
1031 if (c == '\n') 991 if (c == '\t' && prev_col < goal)
1032 goto endloop;
1033 if (c == '\r' && EQ (current_buffer->selective_display, Qt))
1034 goto endloop;
1035 if (c == '\t')
1036 {
1037 prev_col = col;
1038 col += tab_width;
1039 col = col / tab_width * tab_width;
1040 }
1041 else
1042 ++col;
1043 }
1044 }
1045 else
1046 { 992 {
1047 /* The display table doesn't affect this character; 993 EMACS_INT goal_pt, goal_pt_byte;
1048 it displays as itself. */ 994
1049 995 /* Insert spaces in front of the tab to reach GOAL. Do this
1050 if (c == '\n') 996 first so that a marker at the end of the tab gets
1051 goto endloop; 997 adjusted. */
1052 if (c == '\r' && EQ (current_buffer->selective_display, Qt)) 998 SET_PT_BOTH (PT - 1, PT_BYTE - 1);
1053 goto endloop; 999 Finsert_char (make_number (' '), make_number (goal - prev_col), Qt);
1054 if (c == '\t') 1000
1055 { 1001 /* Now delete the tab, and indent to COL. */
1056 prev_col = col; 1002 del_range (PT, PT + 1);
1057 col += tab_width; 1003 goal_pt = PT;
1058 col = col / tab_width * tab_width; 1004 goal_pt_byte = PT_BYTE;
1059 } 1005 Findent_to (make_number (col), Qnil);
1060 else if (ctl_arrow && (c < 040 || c == 0177)) 1006 SET_PT_BOTH (goal_pt, goal_pt_byte);
1061 col += 2; 1007
1062 else if (c < 040 || c == 0177) 1008 /* Set the last_known... vars consistently. */
1063 col += 4; 1009 col = goal;
1064 else if (c < 0177)
1065 col++;
1066 else if (multibyte && BASE_LEADING_CODE_P (c))
1067 {
1068 /* Start of multi-byte form. */
1069 unsigned char *ptr;
1070 int bytes, width, wide_column;
1071
1072 ptr = BYTE_POS_ADDR (pos_byte);
1073 MULTIBYTE_BYTES_WIDTH (ptr, dp);
1074 pos_byte += bytes - 1;
1075 col += width;
1076 }
1077 else
1078 col += 4;
1079 } 1010 }
1080
1081 pos++;
1082 pos_byte++;
1083 }
1084 endloop:
1085
1086 SET_PT_BOTH (pos, pos_byte);
1087
1088 /* If a tab char made us overshoot, change it to spaces
1089 and scan through it again. */
1090 if (!NILP (force) && col > goal && c == '\t' && prev_col < goal)
1091 {
1092 EMACS_INT goal_pt, goal_pt_byte;
1093
1094 /* Insert spaces in front of the tab to reach GOAL. Do this
1095 first so that a marker at the end of the tab gets
1096 adjusted. */
1097 SET_PT_BOTH (PT - 1, PT_BYTE - 1);
1098 Finsert_char (make_number (' '), make_number (goal - prev_col), Qt);
1099
1100 /* Now delete the tab, and indent to COL. */
1101 del_range (PT, PT + 1);
1102 goal_pt = PT;
1103 goal_pt_byte = PT_BYTE;
1104 Findent_to (make_number (col), Qnil);
1105 SET_PT_BOTH (goal_pt, goal_pt_byte);
1106
1107 /* Set the last_known... vars consistently. */
1108 col = goal;
1109 } 1011 }
1110 1012
1111 /* If line ends prematurely, add space to the end. */ 1013 /* If line ends prematurely, add space to the end. */
@@ -1116,8 +1018,7 @@ The return value is the current column. */)
1116 last_known_column_point = PT; 1018 last_known_column_point = PT;
1117 last_known_column_modified = MODIFF; 1019 last_known_column_modified = MODIFF;
1118 1020
1119 XSETFASTINT (val, col); 1021 return make_number (col);
1120 return val;
1121} 1022}
1122 1023
1123/* compute_motion: compute buffer posn given screen posn and vice versa */ 1024/* compute_motion: compute buffer posn given screen posn and vice versa */