aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKarl Heuer1995-05-18 22:43:03 +0000
committerKarl Heuer1995-05-18 22:43:03 +0000
commit2ab90d49d6558911cbc481b2f43e8bbc9fbf7131 (patch)
treee2efbdca4e1ae7841f521af4f5c61dca7ef5cd3c /src
parent4efffd8098eacf85291b1222cab1bcbd874bc919 (diff)
downloademacs-2ab90d49d6558911cbc481b2f43e8bbc9fbf7131.tar.gz
emacs-2ab90d49d6558911cbc481b2f43e8bbc9fbf7131.zip
(compute_motion): Handle overlay strings.
New arg DID_MOTION. All callers changed.
Diffstat (limited to 'src')
-rw-r--r--src/indent.c320
1 files changed, 166 insertions, 154 deletions
diff --git a/src/indent.c b/src/indent.c
index e075e236d1b..9d4c5ff11a1 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -576,6 +576,12 @@ struct position val_compute_motion;
576 can't hit the requested column exactly (because of a tab or other 576 can't hit the requested column exactly (because of a tab or other
577 multi-column character), overshoot. 577 multi-column character), overshoot.
578 578
579 DID_MOTION is 1 if FROMHPOS has already accounted for overlay strings
580 at FROM. This is the case if FROMVPOS and FROMVPOS came from an
581 earlier call to compute_motion. The other common case is that FROMHPOS
582 is zero and FROM is a position that "belongs" at column zero, but might
583 be shifted by overlay strings; in this case DID_MOTION should be 0.
584
579 WIDTH is the number of columns available to display text; 585 WIDTH is the number of columns available to display text;
580 compute_motion uses this to handle continuation lines and such. 586 compute_motion uses this to handle continuation lines and such.
581 HSCROLL is the number of columns not being displayed at the left 587 HSCROLL is the number of columns not being displayed at the left
@@ -629,8 +635,9 @@ struct position val_compute_motion;
629 the scroll bars if they are turned on. */ 635 the scroll bars if they are turned on. */
630 636
631struct position * 637struct position *
632compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, tab_offset, win) 638compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, hscroll, tab_offset, win)
633 int from, fromvpos, fromhpos, to, tovpos, tohpos; 639 int from, fromvpos, fromhpos, to, tovpos, tohpos;
640 int did_motion;
634 register int width; 641 register int width;
635 int hscroll, tab_offset; 642 int hscroll, tab_offset;
636 struct window *win; 643 struct window *win;
@@ -651,11 +658,9 @@ compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, ta
651 int selective_rlen 658 int selective_rlen
652 = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp)) 659 = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp))
653 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size : 0); 660 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size : 0);
654#ifdef USE_TEXT_PROPERTIES 661 /* The next location where the `invisible' property changes, or an
655 /* The next location where the `invisible' property changes */ 662 overlay starts or ends. */
656 int next_invisible = from; 663 int next_boundary = from;
657 Lisp_Object prop, position;
658#endif
659 664
660 /* For computing runs of characters with similar widths. 665 /* For computing runs of characters with similar widths.
661 Invariant: width_run_width is zero, or all the characters 666 Invariant: width_run_width is zero, or all the characters
@@ -683,35 +688,38 @@ compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, ta
683 width_table = 0; 688 width_table = 0;
684 689
685 if (tab_width <= 0 || tab_width > 1000) tab_width = 8; 690 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
686 for (pos = from; pos < to; )
687 {
688 /* Stop if past the target screen position. */
689 if (vpos > tovpos
690 || (vpos == tovpos && hpos >= tohpos))
691 break;
692 691
693 prev_vpos = vpos; 692 pos = from;
694 prev_hpos = hpos; 693 while (1)
695 694 {
696#ifdef USE_TEXT_PROPERTIES 695 while (pos == next_boundary)
697 /* if the `invisible' property is set, we can skip to
698 the next property change */
699 while (pos == next_invisible && pos < to)
700 { 696 {
701 XSETFASTINT (position, pos); 697 /* If the caller says that the screen position came from an earlier
702 698 call to compute_motion, then we've already accounted for the
703 /* Give faster response for overlay lookup near POS. */ 699 overlay strings at point. This is only true the first time
704 recenter_overlay_lists (current_buffer, pos); 700 through, so clear the flag after testing it. */
701 if (!did_motion)
702 /* We need to skip past the overlay strings. Currently those
703 strings must contain single-column printing characters;
704 if we want to relax that restriction, something will have
705 to be changed here. */
706 hpos += overlay_strings (pos, win, (char **)0);
707 did_motion = 0;
708
709 if (pos >= to)
710 break;
705 711
706 prop = Fget_char_property (position,
707 Qinvisible,
708 Fcurrent_buffer ());
709 { 712 {
710 Lisp_Object end, limit, proplimit; 713 Lisp_Object prop, position, end, limit, proplimit;
714
715 XSETFASTINT (position, pos);
716
717 /* Give faster response for overlay lookup near POS. */
718 recenter_overlay_lists (current_buffer, pos);
711 719
712 /* We must not advance farther than the next overlay change. 720 /* We must not advance farther than the next overlay change.
713 The overlay change might change the invisible property; 721 The overlay change might change the invisible property;
714 we have no way of telling. */ 722 or there might be overlay strings to be displayed there. */
715 limit = Fnext_overlay_change (position); 723 limit = Fnext_overlay_change (position);
716 /* As for text properties, this gives a lower bound 724 /* As for text properties, this gives a lower bound
717 for where the invisible text property could change. */ 725 for where the invisible text property could change. */
@@ -722,7 +730,7 @@ compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, ta
722 in invisible status. If that is plenty far away, 730 in invisible status. If that is plenty far away,
723 use that lower bound. */ 731 use that lower bound. */
724 if (XFASTINT (proplimit) > pos + 100 || XFASTINT (proplimit) >= to) 732 if (XFASTINT (proplimit) > pos + 100 || XFASTINT (proplimit) >= to)
725 next_invisible = XINT (proplimit); 733 next_boundary = XFASTINT (proplimit);
726 /* Otherwise, scan for the next `invisible' property change. */ 734 /* Otherwise, scan for the next `invisible' property change. */
727 else 735 else
728 { 736 {
@@ -733,18 +741,48 @@ compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, ta
733 proplimit = limit; 741 proplimit = limit;
734 end = Fnext_single_property_change (position, Qinvisible, 742 end = Fnext_single_property_change (position, Qinvisible,
735 buffer, proplimit); 743 buffer, proplimit);
736 if (INTEGERP (end) && XINT (end) < to) 744 next_boundary = XFASTINT (end);
737 next_invisible = XINT (end);
738 else
739 next_invisible = to;
740 } 745 }
746 /* if the `invisible' property is set, we can skip to
747 the next property change */
748 prop = Fget_char_property (position, Qinvisible,
749 Fcurrent_buffer ());
741 if (TEXT_PROP_MEANS_INVISIBLE (prop)) 750 if (TEXT_PROP_MEANS_INVISIBLE (prop))
742 pos = next_invisible; 751 pos = next_boundary;
743 } 752 }
744 } 753 }
754
755 /* Handle right margin. */
756 if (hpos >= width
757 && (hpos > width
758 || (pos < ZV && FETCH_CHAR (pos) != '\n')))
759 {
760 if (hscroll
761 || (truncate_partial_width_windows
762 && width + 1 < FRAME_WIDTH (XFRAME (WINDOW_FRAME (win))))
763 || !NILP (current_buffer->truncate_lines))
764 {
765 /* Truncating: skip to newline. */
766 pos = find_before_next_newline (pos, to, 1);
767 hpos = width;
768 }
769 else
770 {
771 /* Continuing. */
772 vpos += hpos / width;
773 tab_offset += hpos - hpos % width;
774 hpos %= width;
775 }
776 }
777
778 /* Stop if past the target buffer position or screen position. */
745 if (pos >= to) 779 if (pos >= to)
746 break; 780 break;
747#endif 781 if (vpos > tovpos || (vpos == tovpos && hpos >= tohpos))
782 break;
783
784 prev_vpos = vpos;
785 prev_hpos = hpos;
748 786
749 /* Consult the width run cache to see if we can avoid inspecting 787 /* Consult the width run cache to see if we can avoid inspecting
750 the text character-by-character. */ 788 the text character-by-character. */
@@ -796,128 +834,97 @@ compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, ta
796 834
797 /* We have to scan the text character-by-character. */ 835 /* We have to scan the text character-by-character. */
798 else 836 else
799 { 837 {
800 c = FETCH_CHAR (pos); 838 c = FETCH_CHAR (pos);
801 pos++; 839 pos++;
802
803 /* Perhaps add some info to the width_run_cache. */
804 if (current_buffer->width_run_cache)
805 {
806 /* Is this character part of the current run? If so, extend
807 the run. */
808 if (pos - 1 == width_run_end
809 && width_table[c] == width_run_width)
810 width_run_end = pos;
811
812 /* The previous run is over, since this is a character at a
813 different position, or a different width. */
814 else
815 {
816 /* Have we accumulated a run to put in the cache?
817 (Currently, we only cache runs of width == 1). */
818 if (width_run_start < width_run_end
819 && width_run_width == 1)
820 know_region_cache (current_buffer,
821 current_buffer->width_run_cache,
822 width_run_start, width_run_end);
823
824 /* Start recording a new width run. */
825 width_run_width = width_table[c];
826 width_run_start = pos - 1;
827 width_run_end = pos;
828 }
829 }
830 840
831 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) 841 /* Perhaps add some info to the width_run_cache. */
832 hpos += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; 842 if (current_buffer->width_run_cache)
833 else if (c >= 040 && c < 0177) 843 {
834 hpos++; 844 /* Is this character part of the current run? If so, extend
835 else if (c == '\t') 845 the run. */
836 { 846 if (pos - 1 == width_run_end
837 hpos += tab_width - ((hpos + tab_offset + hscroll - (hscroll > 0) 847 && width_table[c] == width_run_width)
838 /* Add tab_width here to make sure 848 width_run_end = pos;
839 positive. hpos can be negative 849
840 after continuation but can't be 850 /* The previous run is over, since this is a character at a
841 less than -tab_width. */ 851 different position, or a different width. */
842 + tab_width) 852 else
843 % tab_width); 853 {
844 } 854 /* Have we accumulated a run to put in the cache?
845 else if (c == '\n') 855 (Currently, we only cache runs of width == 1). */
846 { 856 if (width_run_start < width_run_end
847 if (selective > 0 && indented_beyond_p (pos, selective)) 857 && width_run_width == 1)
848 { 858 know_region_cache (current_buffer,
849 /* Skip any number of invisible lines all at once */ 859 current_buffer->width_run_cache,
850 do 860 width_run_start, width_run_end);
851 pos = find_before_next_newline (pos, to, 1) + 1; 861
852 while (pos < to 862 /* Start recording a new width run. */
853 && indented_beyond_p (pos, selective)); 863 width_run_width = width_table[c];
854 /* Allow for the " ..." that is displayed for them. */ 864 width_run_start = pos - 1;
855 if (selective_rlen) 865 width_run_end = pos;
856 { 866 }
857 hpos += selective_rlen; 867 }
858 if (hpos >= width)
859 hpos = width;
860 }
861 --pos;
862 /* We have skipped the invis text, but not the
863 newline after. */
864 }
865 else
866 {
867 /* A visible line. */
868 vpos++;
869 hpos = 0;
870 hpos -= hscroll;
871 /* Count the truncation glyph on column 0 */
872 if (hscroll > 0)
873 hpos++;
874 tab_offset = 0;
875 }
876 }
877 else if (c == CR && selective < 0)
878 {
879 /* In selective display mode,
880 everything from a ^M to the end of the line is invisible.
881 Stop *before* the real newline. */
882 pos = find_before_next_newline (pos, to, 1);
883 /* Allow for the " ..." that is displayed for them. */
884 if (selective_rlen)
885 {
886 hpos += selective_rlen;
887 if (hpos >= width)
888 hpos = width;
889 }
890 }
891 else
892 hpos += (ctl_arrow && c < 0200) ? 2 : 4;
893 }
894 868
895 /* Handle right margin. */ 869 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
896 if (hpos >= width 870 hpos += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
897 && (hpos > width 871 else if (c >= 040 && c < 0177)
898 || (pos < ZV 872 hpos++;
899 && FETCH_CHAR (pos) != '\n'))) 873 else if (c == '\t')
900 {
901 if (vpos > tovpos
902 || (vpos == tovpos && hpos >= tohpos))
903 break;
904 if (hscroll
905 || (truncate_partial_width_windows
906 && width + 1 < FRAME_WIDTH (XFRAME (WINDOW_FRAME (win))))
907 || !NILP (current_buffer->truncate_lines))
908 { 874 {
909 /* Truncating: skip to newline. */ 875 int tem = (hpos + tab_offset + hscroll - (hscroll > 0)) % tab_width;
910 pos = find_before_next_newline (pos, to, 1); 876 if (tem < 0)
911 hpos = width; 877 tem += tab_width;
878 hpos += tab_width - tem;
912 } 879 }
913 else 880 else if (c == '\n')
914 { 881 {
915 /* Continuing. */ 882 if (selective > 0 && indented_beyond_p (pos, selective))
916 vpos++; 883 {
917 hpos -= width; 884 /* Skip any number of invisible lines all at once */
918 tab_offset += width; 885 do
886 pos = find_before_next_newline (pos, to, 1) + 1;
887 while (pos < to
888 && indented_beyond_p (pos, selective));
889 /* Allow for the " ..." that is displayed for them. */
890 if (selective_rlen)
891 {
892 hpos += selective_rlen;
893 if (hpos >= width)
894 hpos = width;
895 }
896 --pos;
897 /* We have skipped the invis text, but not the
898 newline after. */
899 }
900 else
901 {
902 /* A visible line. */
903 vpos++;
904 hpos = 0;
905 hpos -= hscroll;
906 /* Count the truncation glyph on column 0 */
907 if (hscroll > 0)
908 hpos++;
909 tab_offset = 0;
910 }
919 } 911 }
920 912 else if (c == CR && selective < 0)
913 {
914 /* In selective display mode,
915 everything from a ^M to the end of the line is invisible.
916 Stop *before* the real newline. */
917 pos = find_before_next_newline (pos, to, 1);
918 /* Allow for the " ..." that is displayed for them. */
919 if (selective_rlen)
920 {
921 hpos += selective_rlen;
922 if (hpos >= width)
923 hpos = width;
924 }
925 }
926 else
927 hpos += (ctl_arrow && c < 0200) ? 2 : 4;
921 } 928 }
922 } 929 }
923 930
@@ -1022,7 +1029,7 @@ DEFUN ("compute-motion", Fcompute_motion, Scompute_motion, 7, 7, 0,
1022 CHECK_LIVE_WINDOW (window, 0); 1029 CHECK_LIVE_WINDOW (window, 0);
1023 1030
1024 pos = compute_motion (XINT (from), XINT (XCONS (frompos)->cdr), 1031 pos = compute_motion (XINT (from), XINT (XCONS (frompos)->cdr),
1025 XINT (XCONS (frompos)->car), 1032 XINT (XCONS (frompos)->car), 0,
1026 XINT (to), XINT (XCONS (topos)->cdr), 1033 XINT (to), XINT (XCONS (topos)->cdr),
1027 XINT (XCONS (topos)->car), 1034 XINT (XCONS (topos)->car),
1028 XINT (width), hscroll, tab_offset, 1035 XINT (width), hscroll, tab_offset,
@@ -1086,6 +1093,7 @@ vmotion (from, vtarget, w)
1086 : !NILP (current_buffer->selective_display) ? -1 : 0); 1093 : !NILP (current_buffer->selective_display) ? -1 : 0);
1087 Lisp_Object window; 1094 Lisp_Object window;
1088 int start_hpos = 0; 1095 int start_hpos = 0;
1096 int did_motion;
1089 1097
1090 XSETWINDOW (window, w); 1098 XSETWINDOW (window, w);
1091 1099
@@ -1131,6 +1139,7 @@ vmotion (from, vtarget, w)
1131 pos = *compute_motion (XFASTINT (prevline), 0, 1139 pos = *compute_motion (XFASTINT (prevline), 0,
1132 lmargin + (XFASTINT (prevline) == BEG 1140 lmargin + (XFASTINT (prevline) == BEG
1133 ? start_hpos : 0), 1141 ? start_hpos : 0),
1142 0,
1134 from, 1 << (INTBITS - 2), 0, 1143 from, 1 << (INTBITS - 2), 0,
1135 width, hscroll, 0, w); 1144 width, hscroll, 0, w);
1136 vpos -= pos.vpos; 1145 vpos -= pos.vpos;
@@ -1157,7 +1166,7 @@ vmotion (from, vtarget, w)
1157 to determine hpos of starting point */ 1166 to determine hpos of starting point */
1158 if (from > BEGV && FETCH_CHAR (from - 1) != '\n') 1167 if (from > BEGV && FETCH_CHAR (from - 1) != '\n')
1159 { 1168 {
1160 Lisp_Object propval; 1169 Lisp_Object propval;
1161 1170
1162 XSETFASTINT (prevline, find_next_newline_no_quit (from, -1)); 1171 XSETFASTINT (prevline, find_next_newline_no_quit (from, -1));
1163 while (XFASTINT (prevline) > BEGV 1172 while (XFASTINT (prevline) > BEGV
@@ -1176,15 +1185,18 @@ vmotion (from, vtarget, w)
1176 pos = *compute_motion (XFASTINT (prevline), 0, 1185 pos = *compute_motion (XFASTINT (prevline), 0,
1177 lmargin + (XFASTINT (prevline) == BEG 1186 lmargin + (XFASTINT (prevline) == BEG
1178 ? start_hpos : 0), 1187 ? start_hpos : 0),
1188 0,
1179 from, 1 << (INTBITS - 2), 0, 1189 from, 1 << (INTBITS - 2), 0,
1180 width, hscroll, 0, w); 1190 width, hscroll, 0, w);
1191 did_motion = 1;
1181 } 1192 }
1182 else 1193 else
1183 { 1194 {
1184 pos.hpos = lmargin + (from == BEG ? start_hpos : 0); 1195 pos.hpos = lmargin + (from == BEG ? start_hpos : 0);
1185 pos.vpos = 0; 1196 pos.vpos = 0;
1197 did_motion = 0;
1186 } 1198 }
1187 return compute_motion (from, vpos, pos.hpos, 1199 return compute_motion (from, vpos, pos.hpos, did_motion,
1188 ZV, vtarget, - (1 << (INTBITS - 2)), 1200 ZV, vtarget, - (1 << (INTBITS - 2)),
1189 width, hscroll, pos.vpos * width, w); 1201 width, hscroll, pos.vpos * width, w);
1190} 1202}