diff options
| author | Paul Eggert | 2013-02-11 15:37:18 -0800 |
|---|---|---|
| committer | Paul Eggert | 2013-02-11 15:37:18 -0800 |
| commit | a84b7c5334e232913111b840f2283d0138a6f5fb (patch) | |
| tree | 8ee4e55f7059d1eb918fb5966cd81ee3f84153bc /src | |
| parent | 71d4202f204ea5fad93eb34406f0ef671630f271 (diff) | |
| download | emacs-a84b7c5334e232913111b840f2283d0138a6f5fb.tar.gz emacs-a84b7c5334e232913111b840f2283d0138a6f5fb.zip | |
Tune by using memchr and memrchr.
* .bzrignore: Add string.h.
* admin/merge-gnulib (GNULIB_MODULES): Add memrchr.
* lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
* lib/memrchr.c, lib/string.in.h, m4/memrchr.m4, m4/string_h.m4:
New files, from gnulib.
* src/doc.c (Fsnarf_documentation):
* src/fileio.c (Fsubstitute_in_file_name):
* src/search.c (find_newline, scan_newline):
* src/xdisp.c (pos_visible_p, display_count_lines):
Use memchr and memrchr rather than scanning byte-by-byte.
* src/search.c (find_newline): Rename from scan_buffer.
Omit first arg TARGET, as it's always '\n'. All callers changed.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 9 | ||||
| -rw-r--r-- | src/doc.c | 5 | ||||
| -rw-r--r-- | src/editfns.c | 5 | ||||
| -rw-r--r-- | src/fileio.c | 10 | ||||
| -rw-r--r-- | src/lisp.h | 4 | ||||
| -rw-r--r-- | src/region-cache.h | 2 | ||||
| -rw-r--r-- | src/search.c | 172 | ||||
| -rw-r--r-- | src/xdisp.c | 101 |
8 files changed, 150 insertions, 158 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index b3d3958853b..30470f5730a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,14 @@ | |||
| 1 | 2013-02-11 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2013-02-11 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 2 | ||
| 3 | Tune by using memchr and memrchr. | ||
| 4 | * doc.c (Fsnarf_documentation): | ||
| 5 | * fileio.c (Fsubstitute_in_file_name): | ||
| 6 | * search.c (find_newline, scan_newline): | ||
| 7 | * xdisp.c (pos_visible_p, display_count_lines): | ||
| 8 | Use memchr and memrchr rather than scanning byte-by-byte. | ||
| 9 | * search.c (find_newline): Rename from scan_buffer. | ||
| 10 | Omit first arg TARGET, as it's always '\n'. All callers changed. | ||
| 11 | |||
| 3 | Clean up read_key_sequence a tiny bit more. | 12 | Clean up read_key_sequence a tiny bit more. |
| 4 | * keyboard.c (read_char_x_menu_prompt) [HAVE_MENUS]: | 13 | * keyboard.c (read_char_x_menu_prompt) [HAVE_MENUS]: |
| 5 | (read_key_sequence): Remove unused locals. | 14 | (read_key_sequence): Remove unused locals. |
| @@ -630,11 +630,10 @@ the same file name is found in the `doc-directory'. */) | |||
| 630 | break; | 630 | break; |
| 631 | 631 | ||
| 632 | buf[filled] = 0; | 632 | buf[filled] = 0; |
| 633 | p = buf; | ||
| 634 | end = buf + (filled < 512 ? filled : filled - 128); | 633 | end = buf + (filled < 512 ? filled : filled - 128); |
| 635 | while (p != end && *p != '\037') p++; | 634 | p = memchr (buf, '\037', end - buf); |
| 636 | /* p points to ^_Ffunctionname\n or ^_Vvarname\n or ^_Sfilename\n. */ | 635 | /* p points to ^_Ffunctionname\n or ^_Vvarname\n or ^_Sfilename\n. */ |
| 637 | if (p != end) | 636 | if (p) |
| 638 | { | 637 | { |
| 639 | end = strchr (p, '\n'); | 638 | end = strchr (p, '\n'); |
| 640 | 639 | ||
diff --git a/src/editfns.c b/src/editfns.c index 0f88a781b88..c5cd8b0b725 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -735,9 +735,8 @@ Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. */) | |||
| 735 | /* This is the ONLY_IN_LINE case, check that NEW_POS and | 735 | /* This is the ONLY_IN_LINE case, check that NEW_POS and |
| 736 | FIELD_BOUND are on the same line by seeing whether | 736 | FIELD_BOUND are on the same line by seeing whether |
| 737 | there's an intervening newline or not. */ | 737 | there's an intervening newline or not. */ |
| 738 | || (scan_buffer ('\n', | 738 | || (find_newline (XFASTINT (new_pos), XFASTINT (field_bound), |
| 739 | XFASTINT (new_pos), XFASTINT (field_bound), | 739 | fwd ? -1 : 1, &shortage, 1), |
| 740 | fwd ? -1 : 1, &shortage, 1), | ||
| 741 | shortage != 0))) | 740 | shortage != 0))) |
| 742 | /* Constrain NEW_POS to FIELD_BOUND. */ | 741 | /* Constrain NEW_POS to FIELD_BOUND. */ |
| 743 | new_pos = field_bound; | 742 | new_pos = field_bound; |
diff --git a/src/fileio.c b/src/fileio.c index 98a9b32ea91..89ad3396464 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -1710,8 +1710,9 @@ those `/' is discarded. */) | |||
| 1710 | else if (*p == '{') | 1710 | else if (*p == '{') |
| 1711 | { | 1711 | { |
| 1712 | o = ++p; | 1712 | o = ++p; |
| 1713 | while (p != endp && *p != '}') p++; | 1713 | p = memchr (p, '}', endp - p); |
| 1714 | if (*p != '}') goto missingclose; | 1714 | if (! p) |
| 1715 | goto missingclose; | ||
| 1715 | s = p; | 1716 | s = p; |
| 1716 | } | 1717 | } |
| 1717 | else | 1718 | else |
| @@ -1779,8 +1780,9 @@ those `/' is discarded. */) | |||
| 1779 | else if (*p == '{') | 1780 | else if (*p == '{') |
| 1780 | { | 1781 | { |
| 1781 | o = ++p; | 1782 | o = ++p; |
| 1782 | while (p != endp && *p != '}') p++; | 1783 | p = memchr (p, '}', endp - p); |
| 1783 | if (*p != '}') goto missingclose; | 1784 | if (! p) |
| 1785 | goto missingclose; | ||
| 1784 | s = p++; | 1786 | s = p++; |
| 1785 | } | 1787 | } |
| 1786 | else | 1788 | else |
diff --git a/src/lisp.h b/src/lisp.h index 14db66c6793..37d2b45e85b 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3346,8 +3346,8 @@ extern ptrdiff_t fast_c_string_match_ignore_case (Lisp_Object, const char *, | |||
| 3346 | extern ptrdiff_t fast_string_match_ignore_case (Lisp_Object, Lisp_Object); | 3346 | extern ptrdiff_t fast_string_match_ignore_case (Lisp_Object, Lisp_Object); |
| 3347 | extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t, | 3347 | extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t, |
| 3348 | ptrdiff_t, ptrdiff_t, Lisp_Object); | 3348 | ptrdiff_t, ptrdiff_t, Lisp_Object); |
| 3349 | extern ptrdiff_t scan_buffer (int, ptrdiff_t, ptrdiff_t, ptrdiff_t, | 3349 | extern ptrdiff_t find_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, |
| 3350 | ptrdiff_t *, bool); | 3350 | ptrdiff_t *, bool); |
| 3351 | extern EMACS_INT scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, | 3351 | extern EMACS_INT scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, |
| 3352 | EMACS_INT, bool); | 3352 | EMACS_INT, bool); |
| 3353 | extern ptrdiff_t find_next_newline (ptrdiff_t, int); | 3353 | extern ptrdiff_t find_next_newline (ptrdiff_t, int); |
diff --git a/src/region-cache.h b/src/region-cache.h index 697ae1c791f..e4c6b59ee95 100644 --- a/src/region-cache.h +++ b/src/region-cache.h | |||
| @@ -40,7 +40,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 40 | existing data structure, and disturb as little of the existing code | 40 | existing data structure, and disturb as little of the existing code |
| 41 | as possible. | 41 | as possible. |
| 42 | 42 | ||
| 43 | So here's the tack. We add some caching to the scan_buffer | 43 | So here's the tack. We add some caching to the find_newline |
| 44 | function, so that when it searches for a newline, it notes that the | 44 | function, so that when it searches for a newline, it notes that the |
| 45 | region between the start and end of the search contained no | 45 | region between the start and end of the search contained no |
| 46 | newlines; then, the next time around, it consults this cache to see | 46 | newlines; then, the next time around, it consults this cache to see |
diff --git a/src/search.c b/src/search.c index c4ccf6c257b..c25d2441018 100644 --- a/src/search.c +++ b/src/search.c | |||
| @@ -619,7 +619,7 @@ newline_cache_on_off (struct buffer *buf) | |||
| 619 | } | 619 | } |
| 620 | 620 | ||
| 621 | 621 | ||
| 622 | /* Search for COUNT instances of the character TARGET between START and END. | 622 | /* Search for COUNT newlines between START and END. |
| 623 | 623 | ||
| 624 | If COUNT is positive, search forwards; END must be >= START. | 624 | If COUNT is positive, search forwards; END must be >= START. |
| 625 | If COUNT is negative, search backwards for the -COUNTth instance; | 625 | If COUNT is negative, search backwards for the -COUNTth instance; |
| @@ -634,14 +634,14 @@ newline_cache_on_off (struct buffer *buf) | |||
| 634 | this is not the same as the usual convention for Emacs motion commands. | 634 | this is not the same as the usual convention for Emacs motion commands. |
| 635 | 635 | ||
| 636 | If we don't find COUNT instances before reaching END, set *SHORTAGE | 636 | If we don't find COUNT instances before reaching END, set *SHORTAGE |
| 637 | to the number of TARGETs left unfound, and return END. | 637 | to the number of newlines left unfound, and return END. |
| 638 | 638 | ||
| 639 | If ALLOW_QUIT, set immediate_quit. That's good to do | 639 | If ALLOW_QUIT, set immediate_quit. That's good to do |
| 640 | except when inside redisplay. */ | 640 | except when inside redisplay. */ |
| 641 | 641 | ||
| 642 | ptrdiff_t | 642 | ptrdiff_t |
| 643 | scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, | 643 | find_newline (ptrdiff_t start, ptrdiff_t end, |
| 644 | ptrdiff_t count, ptrdiff_t *shortage, bool allow_quit) | 644 | ptrdiff_t count, ptrdiff_t *shortage, bool allow_quit) |
| 645 | { | 645 | { |
| 646 | struct region_cache *newline_cache; | 646 | struct region_cache *newline_cache; |
| 647 | ptrdiff_t end_byte = -1; | 647 | ptrdiff_t end_byte = -1; |
| @@ -656,7 +656,7 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, | |||
| 656 | else | 656 | else |
| 657 | { | 657 | { |
| 658 | direction = -1; | 658 | direction = -1; |
| 659 | if (!end) | 659 | if (!end) |
| 660 | end = BEGV, end_byte = BEGV_BYTE; | 660 | end = BEGV, end_byte = BEGV_BYTE; |
| 661 | } | 661 | } |
| 662 | if (end_byte == -1) | 662 | if (end_byte == -1) |
| @@ -684,7 +684,7 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, | |||
| 684 | 684 | ||
| 685 | /* If we're looking for a newline, consult the newline cache | 685 | /* If we're looking for a newline, consult the newline cache |
| 686 | to see where we can avoid some scanning. */ | 686 | to see where we can avoid some scanning. */ |
| 687 | if (target == '\n' && newline_cache) | 687 | if (newline_cache) |
| 688 | { | 688 | { |
| 689 | ptrdiff_t next_change; | 689 | ptrdiff_t next_change; |
| 690 | immediate_quit = 0; | 690 | immediate_quit = 0; |
| @@ -723,32 +723,32 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, | |||
| 723 | 723 | ||
| 724 | while (cursor < ceiling_addr) | 724 | while (cursor < ceiling_addr) |
| 725 | { | 725 | { |
| 726 | unsigned char *scan_start = cursor; | ||
| 727 | |||
| 728 | /* The dumb loop. */ | 726 | /* The dumb loop. */ |
| 729 | while (*cursor != target && ++cursor < ceiling_addr) | 727 | unsigned char *nl = memchr (cursor, '\n', ceiling_addr - cursor); |
| 730 | ; | ||
| 731 | 728 | ||
| 732 | /* If we're looking for newlines, cache the fact that | 729 | /* If we're looking for newlines, cache the fact that |
| 733 | the region from start to cursor is free of them. */ | 730 | the region from start to cursor is free of them. */ |
| 734 | if (target == '\n' && newline_cache) | 731 | if (newline_cache) |
| 735 | know_region_cache (current_buffer, newline_cache, | 732 | { |
| 736 | BYTE_TO_CHAR (start_byte + scan_start - base), | 733 | unsigned char *low = cursor; |
| 737 | BYTE_TO_CHAR (start_byte + cursor - base)); | 734 | unsigned char *lim = nl ? nl : ceiling_addr; |
| 738 | 735 | know_region_cache (current_buffer, newline_cache, | |
| 739 | /* Did we find the target character? */ | 736 | BYTE_TO_CHAR (low - base + start_byte), |
| 740 | if (cursor < ceiling_addr) | 737 | BYTE_TO_CHAR (lim - base + start_byte)); |
| 741 | { | 738 | } |
| 742 | if (--count == 0) | 739 | |
| 743 | { | 740 | if (! nl) |
| 744 | immediate_quit = 0; | 741 | break; |
| 745 | return BYTE_TO_CHAR (start_byte + cursor - base + 1); | 742 | |
| 746 | } | 743 | if (--count == 0) |
| 747 | cursor++; | 744 | { |
| 748 | } | 745 | immediate_quit = 0; |
| 746 | return BYTE_TO_CHAR (nl + 1 - base + start_byte); | ||
| 747 | } | ||
| 748 | cursor = nl + 1; | ||
| 749 | } | 749 | } |
| 750 | 750 | ||
| 751 | start = BYTE_TO_CHAR (start_byte + cursor - base); | 751 | start = BYTE_TO_CHAR (ceiling_addr - base + start_byte); |
| 752 | } | 752 | } |
| 753 | } | 753 | } |
| 754 | else | 754 | else |
| @@ -760,7 +760,7 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, | |||
| 760 | ptrdiff_t tem; | 760 | ptrdiff_t tem; |
| 761 | 761 | ||
| 762 | /* Consult the newline cache, if appropriate. */ | 762 | /* Consult the newline cache, if appropriate. */ |
| 763 | if (target == '\n' && newline_cache) | 763 | if (newline_cache) |
| 764 | { | 764 | { |
| 765 | ptrdiff_t next_change; | 765 | ptrdiff_t next_change; |
| 766 | immediate_quit = 0; | 766 | immediate_quit = 0; |
| @@ -794,31 +794,32 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, | |||
| 794 | 794 | ||
| 795 | while (cursor >= ceiling_addr) | 795 | while (cursor >= ceiling_addr) |
| 796 | { | 796 | { |
| 797 | unsigned char *scan_start = cursor; | 797 | unsigned char *nl = memrchr (ceiling_addr, '\n', |
| 798 | 798 | cursor + 1 - ceiling_addr); | |
| 799 | while (*cursor != target && --cursor >= ceiling_addr) | ||
| 800 | ; | ||
| 801 | 799 | ||
| 802 | /* If we're looking for newlines, cache the fact that | 800 | /* If we're looking for newlines, cache the fact that |
| 803 | the region from after the cursor to start is free of them. */ | 801 | the region from after the cursor to start is free of them. */ |
| 804 | if (target == '\n' && newline_cache) | 802 | if (newline_cache) |
| 805 | know_region_cache (current_buffer, newline_cache, | 803 | { |
| 806 | BYTE_TO_CHAR (start_byte + cursor - base), | 804 | unsigned char *low = nl ? nl : ceiling_addr - 1; |
| 807 | BYTE_TO_CHAR (start_byte + scan_start - base)); | 805 | unsigned char *lim = cursor; |
| 808 | 806 | know_region_cache (current_buffer, newline_cache, | |
| 809 | /* Did we find the target character? */ | 807 | BYTE_TO_CHAR (low - base + start_byte), |
| 810 | if (cursor >= ceiling_addr) | 808 | BYTE_TO_CHAR (lim - base + start_byte)); |
| 811 | { | 809 | } |
| 812 | if (++count >= 0) | 810 | |
| 813 | { | 811 | if (! nl) |
| 814 | immediate_quit = 0; | 812 | break; |
| 815 | return BYTE_TO_CHAR (start_byte + cursor - base); | 813 | |
| 816 | } | 814 | if (++count >= 0) |
| 817 | cursor--; | 815 | { |
| 818 | } | 816 | immediate_quit = 0; |
| 817 | return BYTE_TO_CHAR (nl - base + start_byte); | ||
| 818 | } | ||
| 819 | cursor = nl - 1; | ||
| 819 | } | 820 | } |
| 820 | 821 | ||
| 821 | start = BYTE_TO_CHAR (start_byte + cursor - base); | 822 | start = BYTE_TO_CHAR (ceiling_addr - 1 - base + start_byte); |
| 822 | } | 823 | } |
| 823 | } | 824 | } |
| 824 | 825 | ||
| @@ -828,8 +829,7 @@ scan_buffer (int target, ptrdiff_t start, ptrdiff_t end, | |||
| 828 | return start; | 829 | return start; |
| 829 | } | 830 | } |
| 830 | 831 | ||
| 831 | /* Search for COUNT instances of a line boundary, which means either a | 832 | /* Search for COUNT instances of a line boundary. |
| 832 | newline or (if selective display enabled) a carriage return. | ||
| 833 | Start at START. If COUNT is negative, search backwards. | 833 | Start at START. If COUNT is negative, search backwards. |
| 834 | 834 | ||
| 835 | We report the resulting position by calling TEMP_SET_PT_BOTH. | 835 | We report the resulting position by calling TEMP_SET_PT_BOTH. |
| @@ -860,9 +860,6 @@ scan_newline (ptrdiff_t start, ptrdiff_t start_byte, | |||
| 860 | 860 | ||
| 861 | bool old_immediate_quit = immediate_quit; | 861 | bool old_immediate_quit = immediate_quit; |
| 862 | 862 | ||
| 863 | /* The code that follows is like scan_buffer | ||
| 864 | but checks for either newline or carriage return. */ | ||
| 865 | |||
| 866 | if (allow_quit) | 863 | if (allow_quit) |
| 867 | immediate_quit++; | 864 | immediate_quit++; |
| 868 | 865 | ||
| @@ -874,29 +871,25 @@ scan_newline (ptrdiff_t start, ptrdiff_t start_byte, | |||
| 874 | ceiling = min (limit_byte - 1, ceiling); | 871 | ceiling = min (limit_byte - 1, ceiling); |
| 875 | ceiling_addr = BYTE_POS_ADDR (ceiling) + 1; | 872 | ceiling_addr = BYTE_POS_ADDR (ceiling) + 1; |
| 876 | base = (cursor = BYTE_POS_ADDR (start_byte)); | 873 | base = (cursor = BYTE_POS_ADDR (start_byte)); |
| 877 | while (1) | ||
| 878 | { | ||
| 879 | while (*cursor != '\n' && ++cursor != ceiling_addr) | ||
| 880 | ; | ||
| 881 | 874 | ||
| 882 | if (cursor != ceiling_addr) | 875 | do |
| 876 | { | ||
| 877 | unsigned char *nl = memchr (cursor, '\n', ceiling_addr - cursor); | ||
| 878 | if (! nl) | ||
| 879 | break; | ||
| 880 | if (--count == 0) | ||
| 883 | { | 881 | { |
| 884 | if (--count == 0) | 882 | immediate_quit = old_immediate_quit; |
| 885 | { | 883 | start_byte += nl - base + 1; |
| 886 | immediate_quit = old_immediate_quit; | 884 | start = BYTE_TO_CHAR (start_byte); |
| 887 | start_byte = start_byte + cursor - base + 1; | 885 | TEMP_SET_PT_BOTH (start, start_byte); |
| 888 | start = BYTE_TO_CHAR (start_byte); | 886 | return 0; |
| 889 | TEMP_SET_PT_BOTH (start, start_byte); | ||
| 890 | return 0; | ||
| 891 | } | ||
| 892 | else | ||
| 893 | if (++cursor == ceiling_addr) | ||
| 894 | break; | ||
| 895 | } | 887 | } |
| 896 | else | 888 | cursor = nl + 1; |
| 897 | break; | ||
| 898 | } | 889 | } |
| 899 | start_byte += cursor - base; | 890 | while (cursor < ceiling_addr); |
| 891 | |||
| 892 | start_byte += ceiling_addr - base; | ||
| 900 | } | 893 | } |
| 901 | } | 894 | } |
| 902 | else | 895 | else |
| @@ -905,31 +898,28 @@ scan_newline (ptrdiff_t start, ptrdiff_t start_byte, | |||
| 905 | { | 898 | { |
| 906 | ceiling = BUFFER_FLOOR_OF (start_byte - 1); | 899 | ceiling = BUFFER_FLOOR_OF (start_byte - 1); |
| 907 | ceiling = max (limit_byte, ceiling); | 900 | ceiling = max (limit_byte, ceiling); |
| 908 | ceiling_addr = BYTE_POS_ADDR (ceiling) - 1; | 901 | ceiling_addr = BYTE_POS_ADDR (ceiling); |
| 909 | base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1); | 902 | base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1); |
| 910 | while (1) | 903 | while (1) |
| 911 | { | 904 | { |
| 912 | while (--cursor != ceiling_addr && *cursor != '\n') | 905 | unsigned char *nl = memrchr (ceiling_addr, '\n', |
| 913 | ; | 906 | cursor - ceiling_addr); |
| 907 | if (! nl) | ||
| 908 | break; | ||
| 914 | 909 | ||
| 915 | if (cursor != ceiling_addr) | 910 | if (++count == 0) |
| 916 | { | 911 | { |
| 917 | if (++count == 0) | 912 | immediate_quit = old_immediate_quit; |
| 918 | { | 913 | /* Return the position AFTER the match we found. */ |
| 919 | immediate_quit = old_immediate_quit; | 914 | start_byte += nl - base + 1; |
| 920 | /* Return the position AFTER the match we found. */ | 915 | start = BYTE_TO_CHAR (start_byte); |
| 921 | start_byte = start_byte + cursor - base + 1; | 916 | TEMP_SET_PT_BOTH (start, start_byte); |
| 922 | start = BYTE_TO_CHAR (start_byte); | 917 | return 0; |
| 923 | TEMP_SET_PT_BOTH (start, start_byte); | ||
| 924 | return 0; | ||
| 925 | } | ||
| 926 | } | 918 | } |
| 927 | else | 919 | |
| 928 | break; | 920 | cursor = nl; |
| 929 | } | 921 | } |
| 930 | /* Here we add 1 to compensate for the last decrement | 922 | start_byte += ceiling_addr - base; |
| 931 | of CURSOR, which took it past the valid range. */ | ||
| 932 | start_byte += cursor - base + 1; | ||
| 933 | } | 923 | } |
| 934 | } | 924 | } |
| 935 | 925 | ||
| @@ -942,7 +932,7 @@ scan_newline (ptrdiff_t start, ptrdiff_t start_byte, | |||
| 942 | ptrdiff_t | 932 | ptrdiff_t |
| 943 | find_next_newline_no_quit (ptrdiff_t from, ptrdiff_t cnt) | 933 | find_next_newline_no_quit (ptrdiff_t from, ptrdiff_t cnt) |
| 944 | { | 934 | { |
| 945 | return scan_buffer ('\n', from, 0, cnt, (ptrdiff_t *) 0, 0); | 935 | return find_newline (from, 0, cnt, (ptrdiff_t *) 0, 0); |
| 946 | } | 936 | } |
| 947 | 937 | ||
| 948 | /* Like find_next_newline, but returns position before the newline, | 938 | /* Like find_next_newline, but returns position before the newline, |
| @@ -953,7 +943,7 @@ ptrdiff_t | |||
| 953 | find_before_next_newline (ptrdiff_t from, ptrdiff_t to, ptrdiff_t cnt) | 943 | find_before_next_newline (ptrdiff_t from, ptrdiff_t to, ptrdiff_t cnt) |
| 954 | { | 944 | { |
| 955 | ptrdiff_t shortage; | 945 | ptrdiff_t shortage; |
| 956 | ptrdiff_t pos = scan_buffer ('\n', from, to, cnt, &shortage, 1); | 946 | ptrdiff_t pos = find_newline (from, to, cnt, &shortage, 1); |
| 957 | 947 | ||
| 958 | if (shortage == 0) | 948 | if (shortage == 0) |
| 959 | pos--; | 949 | pos--; |
diff --git a/src/xdisp.c b/src/xdisp.c index 3b82de9432d..463f4f9ef05 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -1392,21 +1392,9 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y, | |||
| 1392 | Lisp_Object cpos = make_number (charpos); | 1392 | Lisp_Object cpos = make_number (charpos); |
| 1393 | Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil); | 1393 | Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil); |
| 1394 | Lisp_Object string = string_from_display_spec (spec); | 1394 | Lisp_Object string = string_from_display_spec (spec); |
| 1395 | int newline_in_string = 0; | 1395 | bool newline_in_string |
| 1396 | 1396 | = (STRINGP (string) | |
| 1397 | if (STRINGP (string)) | 1397 | && memchr (SDATA (string), '\n', SBYTES (string))); |
| 1398 | { | ||
| 1399 | const char *s = SSDATA (string); | ||
| 1400 | const char *e = s + SBYTES (string); | ||
| 1401 | while (s < e) | ||
| 1402 | { | ||
| 1403 | if (*s++ == '\n') | ||
| 1404 | { | ||
| 1405 | newline_in_string = 1; | ||
| 1406 | break; | ||
| 1407 | } | ||
| 1408 | } | ||
| 1409 | } | ||
| 1410 | /* The tricky code below is needed because there's a | 1398 | /* The tricky code below is needed because there's a |
| 1411 | discrepancy between move_it_to and how we set cursor | 1399 | discrepancy between move_it_to and how we set cursor |
| 1412 | when the display line ends in a newline from a | 1400 | when the display line ends in a newline from a |
| @@ -14759,7 +14747,7 @@ compute_window_start_on_continuation_line (struct window *w) | |||
| 14759 | SET_TEXT_POS (start_pos, ZV, ZV_BYTE); | 14747 | SET_TEXT_POS (start_pos, ZV, ZV_BYTE); |
| 14760 | 14748 | ||
| 14761 | /* Find the start of the continued line. This should be fast | 14749 | /* Find the start of the continued line. This should be fast |
| 14762 | because scan_buffer is fast (newline cache). */ | 14750 | because find_newline is fast (newline cache). */ |
| 14763 | row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0); | 14751 | row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0); |
| 14764 | init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos), | 14752 | init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos), |
| 14765 | row, DEFAULT_FACE_ID); | 14753 | row, DEFAULT_FACE_ID); |
| @@ -21626,31 +21614,36 @@ display_count_lines (ptrdiff_t start_byte, | |||
| 21626 | ceiling = min (limit_byte - 1, ceiling); | 21614 | ceiling = min (limit_byte - 1, ceiling); |
| 21627 | ceiling_addr = BYTE_POS_ADDR (ceiling) + 1; | 21615 | ceiling_addr = BYTE_POS_ADDR (ceiling) + 1; |
| 21628 | base = (cursor = BYTE_POS_ADDR (start_byte)); | 21616 | base = (cursor = BYTE_POS_ADDR (start_byte)); |
| 21629 | while (1) | 21617 | |
| 21618 | do | ||
| 21630 | { | 21619 | { |
| 21631 | if (selective_display) | 21620 | if (selective_display) |
| 21632 | while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr) | 21621 | { |
| 21633 | ; | 21622 | while (*cursor != '\n' && *cursor != 015 |
| 21623 | && ++cursor != ceiling_addr) | ||
| 21624 | continue; | ||
| 21625 | if (cursor == ceiling_addr) | ||
| 21626 | break; | ||
| 21627 | } | ||
| 21634 | else | 21628 | else |
| 21635 | while (*cursor != '\n' && ++cursor != ceiling_addr) | 21629 | { |
| 21636 | ; | 21630 | cursor = memchr (cursor, '\n', ceiling_addr - cursor); |
| 21631 | if (! cursor) | ||
| 21632 | break; | ||
| 21633 | } | ||
| 21634 | |||
| 21635 | cursor++; | ||
| 21637 | 21636 | ||
| 21638 | if (cursor != ceiling_addr) | 21637 | if (--count == 0) |
| 21639 | { | 21638 | { |
| 21640 | if (--count == 0) | 21639 | start_byte += cursor - base; |
| 21641 | { | 21640 | *byte_pos_ptr = start_byte; |
| 21642 | start_byte += cursor - base + 1; | 21641 | return orig_count; |
| 21643 | *byte_pos_ptr = start_byte; | ||
| 21644 | return orig_count; | ||
| 21645 | } | ||
| 21646 | else | ||
| 21647 | if (++cursor == ceiling_addr) | ||
| 21648 | break; | ||
| 21649 | } | 21642 | } |
| 21650 | else | ||
| 21651 | break; | ||
| 21652 | } | 21643 | } |
| 21653 | start_byte += cursor - base; | 21644 | while (cursor < ceiling_addr); |
| 21645 | |||
| 21646 | start_byte += ceiling_addr - base; | ||
| 21654 | } | 21647 | } |
| 21655 | } | 21648 | } |
| 21656 | else | 21649 | else |
| @@ -21659,35 +21652,35 @@ display_count_lines (ptrdiff_t start_byte, | |||
| 21659 | { | 21652 | { |
| 21660 | ceiling = BUFFER_FLOOR_OF (start_byte - 1); | 21653 | ceiling = BUFFER_FLOOR_OF (start_byte - 1); |
| 21661 | ceiling = max (limit_byte, ceiling); | 21654 | ceiling = max (limit_byte, ceiling); |
| 21662 | ceiling_addr = BYTE_POS_ADDR (ceiling) - 1; | 21655 | ceiling_addr = BYTE_POS_ADDR (ceiling); |
| 21663 | base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1); | 21656 | base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1); |
| 21664 | while (1) | 21657 | while (1) |
| 21665 | { | 21658 | { |
| 21666 | if (selective_display) | 21659 | if (selective_display) |
| 21667 | while (--cursor != ceiling_addr | 21660 | { |
| 21668 | && *cursor != '\n' && *cursor != 015) | 21661 | while (--cursor >= ceiling_addr |
| 21669 | ; | 21662 | && *cursor != '\n' && *cursor != 015) |
| 21663 | continue; | ||
| 21664 | if (cursor < ceiling_addr) | ||
| 21665 | break; | ||
| 21666 | } | ||
| 21670 | else | 21667 | else |
| 21671 | while (--cursor != ceiling_addr && *cursor != '\n') | 21668 | { |
| 21672 | ; | 21669 | cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr); |
| 21670 | if (! cursor) | ||
| 21671 | break; | ||
| 21672 | } | ||
| 21673 | 21673 | ||
| 21674 | if (cursor != ceiling_addr) | 21674 | if (++count == 0) |
| 21675 | { | 21675 | { |
| 21676 | if (++count == 0) | 21676 | start_byte += cursor - base + 1; |
| 21677 | { | 21677 | *byte_pos_ptr = start_byte; |
| 21678 | start_byte += cursor - base + 1; | 21678 | /* When scanning backwards, we should |
| 21679 | *byte_pos_ptr = start_byte; | 21679 | not count the newline posterior to which we stop. */ |
| 21680 | /* When scanning backwards, we should | 21680 | return - orig_count - 1; |
| 21681 | not count the newline posterior to which we stop. */ | ||
| 21682 | return - orig_count - 1; | ||
| 21683 | } | ||
| 21684 | } | 21681 | } |
| 21685 | else | ||
| 21686 | break; | ||
| 21687 | } | 21682 | } |
| 21688 | /* Here we add 1 to compensate for the last decrement | 21683 | start_byte += ceiling_addr - base; |
| 21689 | of CURSOR, which took it past the valid range. */ | ||
| 21690 | start_byte += cursor - base + 1; | ||
| 21691 | } | 21684 | } |
| 21692 | } | 21685 | } |
| 21693 | 21686 | ||