diff options
| author | Joakim Verona | 2013-02-02 00:03:52 +0100 |
|---|---|---|
| committer | Joakim Verona | 2013-02-02 00:03:52 +0100 |
| commit | 9aa1f4ecdb156a4135c3f7f6125a2b5a40258038 (patch) | |
| tree | 4026361436b73220b9ae03f2251d2248eeaac700 /src | |
| parent | ae8a4617f3829786fc675b0dd8d818697da6a214 (diff) | |
| parent | 35e854998e2ab2155875683411beb0518236da18 (diff) | |
| download | emacs-9aa1f4ecdb156a4135c3f7f6125a2b5a40258038.tar.gz emacs-9aa1f4ecdb156a4135c3f7f6125a2b5a40258038.zip | |
auto upstream
Diffstat (limited to 'src')
| -rw-r--r-- | src/.gdbinit | 1 | ||||
| -rw-r--r-- | src/ChangeLog | 59 | ||||
| -rw-r--r-- | src/conf_post.h | 4 | ||||
| -rw-r--r-- | src/dired.c | 120 | ||||
| -rw-r--r-- | src/fileio.c | 46 | ||||
| -rw-r--r-- | src/filelock.c | 18 | ||||
| -rw-r--r-- | src/lisp.h | 3 | ||||
| -rw-r--r-- | src/print.c | 2 | ||||
| -rw-r--r-- | src/sysdep.c | 18 | ||||
| -rw-r--r-- | src/w32.c | 60 | ||||
| -rw-r--r-- | src/window.c | 10 | ||||
| -rw-r--r-- | src/window.h | 36 | ||||
| -rw-r--r-- | src/xdisp.c | 111 |
13 files changed, 268 insertions, 220 deletions
diff --git a/src/.gdbinit b/src/.gdbinit index 4688b0a4421..4215ffa312b 100644 --- a/src/.gdbinit +++ b/src/.gdbinit | |||
| @@ -358,7 +358,6 @@ end | |||
| 358 | 358 | ||
| 359 | define pwinx | 359 | define pwinx |
| 360 | set $w = $arg0 | 360 | set $w = $arg0 |
| 361 | xgetint $w->sequence_number | ||
| 362 | if ($w->mini_p != Qnil) | 361 | if ($w->mini_p != Qnil) |
| 363 | printf "Mini " | 362 | printf "Mini " |
| 364 | end | 363 | end |
diff --git a/src/ChangeLog b/src/ChangeLog index 5c13e35306d..b4c3195973c 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,62 @@ | |||
| 1 | 2013-02-01 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Fix timestamp bug when write-region appends nothing (Bug#13149). | ||
| 4 | * fileio.c (Fwrite_region): When neither O_EXCL nor O_TRUNC is used, | ||
| 5 | the file's time stamp doesn't change if Emacs happens to write nothing | ||
| 6 | to the file, and on a buggy file system this could cause Emacs to | ||
| 7 | incorrectly infer that the file system doesn't have the bug. | ||
| 8 | Avoid this problem by inhibiting the inference in this case. | ||
| 9 | |||
| 10 | 2013-02-01 Dmitry Antipov <dmantipov@yandex.ru> | ||
| 11 | |||
| 12 | * window.h (struct window): Convert base_line_number, base_line_pos | ||
| 13 | and column_number_displayed members from Lisp_Object to ptrdiff_t. | ||
| 14 | Convert region_showing member from Lisp_Object to bitfield. | ||
| 15 | Remove sequence_number member. Adjust comments. | ||
| 16 | * window.c (sequence_number): Remove. | ||
| 17 | (make_window): Initialize column_number_displayed. | ||
| 18 | * print.c (print_object): Follow the printed representation of | ||
| 19 | frames and print window pointer to distinguish between windows. | ||
| 20 | (adjust_window_count): Invalidate base_line_pos. Adjust comment. | ||
| 21 | * xdisp.c (wset_base_line_number, wset_base_line_pos) | ||
| 22 | (wset_column_number_displayed, wset_region_showing): Remove. | ||
| 23 | (window_buffer_changed, mode_line_update_needed, redisplay_internal) | ||
| 24 | (try_scrolling, try_cursor_movement, redisplay_window) | ||
| 25 | (try_window_reusing_current_matrix, try_window_id, display_line) | ||
| 26 | (display_mode_lines, decode_mode_spec): Adjust users. | ||
| 27 | * .gdbinit (pwinx): Do not print sequence_number. | ||
| 28 | |||
| 29 | 2013-02-01 Paul Eggert <eggert@cs.ucla.edu> | ||
| 30 | |||
| 31 | Use fdopendir, fstatat and readlinkat, for efficiency (Bug#13539). | ||
| 32 | * conf_post.h (GNULIB_SUPPORT_ONLY_AT_FDCWD): Remove. | ||
| 33 | * dired.c: Include <fcntl.h>. | ||
| 34 | (open_directory): New function, which uses open and fdopendir | ||
| 35 | rather than opendir. DOS_NT platforms still use opendir, though. | ||
| 36 | (directory_files_internal, file_name_completion): Use it. | ||
| 37 | (file_attributes): New function, with most of the old Ffile_attributes. | ||
| 38 | (directory_files_internal, Ffile_attributes): Use it. | ||
| 39 | (file_attributes, file_name_completion_stat): First arg is now fd, | ||
| 40 | not dir name. All uses changed. Use fstatat rather than lstat + | ||
| 41 | stat. | ||
| 42 | (file_attributes): Use emacs_readlinkat rather than Ffile_symlink_p. | ||
| 43 | * fileio.c: Include <allocator.h>, <careadlinkat.h>. | ||
| 44 | (emacs_readlinkat): New function, with much of the old | ||
| 45 | Ffile_symlink_p, but with an fd argument for speed. | ||
| 46 | It uses readlinkat rather than careadlinkatcwd, so that it | ||
| 47 | need not assume the working directory. | ||
| 48 | (Ffile_symlink_p): Use it. | ||
| 49 | * filelock.c (current_lock_owner): Use emacs_readlinkat | ||
| 50 | rather than emacs_readlink. | ||
| 51 | * lisp.h (emacs_readlinkat): New decl. | ||
| 52 | (READLINK_BUFSIZE, emacs_readlink): Remove. | ||
| 53 | * sysdep.c: Do not include <allocator.h>, <careadlinkat.h>. | ||
| 54 | (emacs_norealloc_allocator, emacs_readlink): Remove. | ||
| 55 | This stuff is moved to fileio.c. | ||
| 56 | * w32.c (fstatat, readlinkat): New functions. | ||
| 57 | (careadlinkat): Don't check that fd == AT_FDCWD. | ||
| 58 | (careadlinkatcwd): Remove; no longer needed. | ||
| 59 | |||
| 1 | 2013-01-31 Glenn Morris <rgm@gnu.org> | 60 | 2013-01-31 Glenn Morris <rgm@gnu.org> |
| 2 | 61 | ||
| 3 | * fileio.c (choose_write_coding_system): Make it callable from Lisp. | 62 | * fileio.c (choose_write_coding_system): Make it callable from Lisp. |
diff --git a/src/conf_post.h b/src/conf_post.h index cd1e35bea7a..6c9747a436c 100644 --- a/src/conf_post.h +++ b/src/conf_post.h | |||
| @@ -182,10 +182,6 @@ extern void _DebPrint (const char *fmt, ...); | |||
| 182 | #endif | 182 | #endif |
| 183 | #endif | 183 | #endif |
| 184 | 184 | ||
| 185 | /* Tell gnulib to omit support for openat-related functions having a | ||
| 186 | first argument other than AT_FDCWD. */ | ||
| 187 | #define GNULIB_SUPPORT_ONLY_AT_FDCWD | ||
| 188 | |||
| 189 | #include <string.h> | 185 | #include <string.h> |
| 190 | #include <stdlib.h> | 186 | #include <stdlib.h> |
| 191 | 187 | ||
diff --git a/src/dired.c b/src/dired.c index a4c8621e9c0..ed0571fe9fe 100644 --- a/src/dired.c +++ b/src/dired.c | |||
| @@ -30,6 +30,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 30 | #include <grp.h> | 30 | #include <grp.h> |
| 31 | 31 | ||
| 32 | #include <errno.h> | 32 | #include <errno.h> |
| 33 | #include <fcntl.h> | ||
| 33 | #include <unistd.h> | 34 | #include <unistd.h> |
| 34 | 35 | ||
| 35 | #include <dirent.h> | 36 | #include <dirent.h> |
| @@ -54,6 +55,7 @@ static Lisp_Object Qfile_attributes; | |||
| 54 | static Lisp_Object Qfile_attributes_lessp; | 55 | static Lisp_Object Qfile_attributes_lessp; |
| 55 | 56 | ||
| 56 | static ptrdiff_t scmp (const char *, const char *, ptrdiff_t); | 57 | static ptrdiff_t scmp (const char *, const char *, ptrdiff_t); |
| 58 | static Lisp_Object file_attributes (int, char const *, Lisp_Object); | ||
| 57 | 59 | ||
| 58 | /* Return the number of bytes in DP's name. */ | 60 | /* Return the number of bytes in DP's name. */ |
| 59 | static ptrdiff_t | 61 | static ptrdiff_t |
| @@ -66,6 +68,44 @@ dirent_namelen (struct dirent *dp) | |||
| 66 | #endif | 68 | #endif |
| 67 | } | 69 | } |
| 68 | 70 | ||
| 71 | static DIR * | ||
| 72 | open_directory (char const *name, int *fdp) | ||
| 73 | { | ||
| 74 | DIR *d; | ||
| 75 | int fd, opendir_errno; | ||
| 76 | |||
| 77 | block_input (); | ||
| 78 | |||
| 79 | #ifdef DOS_NT | ||
| 80 | /* Directories cannot be opened. The emulation assumes that any | ||
| 81 | file descriptor other than AT_FDCWD corresponds to the most | ||
| 82 | recently opened directory. This hack is good enough for Emacs. */ | ||
| 83 | fd = 0; | ||
| 84 | d = opendir (name); | ||
| 85 | opendir_errno = errno; | ||
| 86 | #else | ||
| 87 | fd = emacs_open (name, O_RDONLY | O_DIRECTORY, 0); | ||
| 88 | if (fd < 0) | ||
| 89 | { | ||
| 90 | opendir_errno = errno; | ||
| 91 | d = 0; | ||
| 92 | } | ||
| 93 | else | ||
| 94 | { | ||
| 95 | d = fdopendir (fd); | ||
| 96 | opendir_errno = errno; | ||
| 97 | if (! d) | ||
| 98 | close (fd); | ||
| 99 | } | ||
| 100 | #endif | ||
| 101 | |||
| 102 | unblock_input (); | ||
| 103 | |||
| 104 | *fdp = fd; | ||
| 105 | errno = opendir_errno; | ||
| 106 | return d; | ||
| 107 | } | ||
| 108 | |||
| 69 | #ifdef WINDOWSNT | 109 | #ifdef WINDOWSNT |
| 70 | Lisp_Object | 110 | Lisp_Object |
| 71 | directory_files_internal_w32_unwind (Lisp_Object arg) | 111 | directory_files_internal_w32_unwind (Lisp_Object arg) |
| @@ -96,6 +136,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, | |||
| 96 | Lisp_Object id_format) | 136 | Lisp_Object id_format) |
| 97 | { | 137 | { |
| 98 | DIR *d; | 138 | DIR *d; |
| 139 | int fd; | ||
| 99 | ptrdiff_t directory_nbytes; | 140 | ptrdiff_t directory_nbytes; |
| 100 | Lisp_Object list, dirfilename, encoded_directory; | 141 | Lisp_Object list, dirfilename, encoded_directory; |
| 101 | struct re_pattern_buffer *bufp = NULL; | 142 | struct re_pattern_buffer *bufp = NULL; |
| @@ -142,9 +183,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, | |||
| 142 | /* Now *bufp is the compiled form of MATCH; don't call anything | 183 | /* Now *bufp is the compiled form of MATCH; don't call anything |
| 143 | which might compile a new regexp until we're done with the loop! */ | 184 | which might compile a new regexp until we're done with the loop! */ |
| 144 | 185 | ||
| 145 | block_input (); | 186 | d = open_directory (SSDATA (dirfilename), &fd); |
| 146 | d = opendir (SSDATA (dirfilename)); | ||
| 147 | unblock_input (); | ||
| 148 | if (d == NULL) | 187 | if (d == NULL) |
| 149 | report_file_error ("Opening directory", Fcons (directory, Qnil)); | 188 | report_file_error ("Opening directory", Fcons (directory, Qnil)); |
| 150 | 189 | ||
| @@ -259,20 +298,9 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, | |||
| 259 | 298 | ||
| 260 | if (attrs) | 299 | if (attrs) |
| 261 | { | 300 | { |
| 262 | /* Construct an expanded filename for the directory entry. | 301 | Lisp_Object fileattrs |
| 263 | Use the decoded names for input to Ffile_attributes. */ | 302 | = file_attributes (fd, dp->d_name, id_format); |
| 264 | Lisp_Object decoded_fullname, fileattrs; | ||
| 265 | struct gcpro gcpro1, gcpro2; | ||
| 266 | |||
| 267 | decoded_fullname = fileattrs = Qnil; | ||
| 268 | GCPRO2 (decoded_fullname, fileattrs); | ||
| 269 | |||
| 270 | /* Both Fexpand_file_name and Ffile_attributes can GC. */ | ||
| 271 | decoded_fullname = Fexpand_file_name (name, directory); | ||
| 272 | fileattrs = Ffile_attributes (decoded_fullname, id_format); | ||
| 273 | |||
| 274 | list = Fcons (Fcons (finalname, fileattrs), list); | 303 | list = Fcons (Fcons (finalname, fileattrs), list); |
| 275 | UNGCPRO; | ||
| 276 | } | 304 | } |
| 277 | else | 305 | else |
| 278 | list = Fcons (finalname, list); | 306 | list = Fcons (finalname, list); |
| @@ -413,8 +441,7 @@ These are all file names in directory DIRECTORY which begin with FILE. */) | |||
| 413 | return file_name_completion (file, directory, 1, Qnil); | 441 | return file_name_completion (file, directory, 1, Qnil); |
| 414 | } | 442 | } |
| 415 | 443 | ||
| 416 | static int file_name_completion_stat (Lisp_Object dirname, struct dirent *dp, | 444 | static int file_name_completion_stat (int, struct dirent *, struct stat *); |
| 417 | struct stat *st_addr); | ||
| 418 | static Lisp_Object Qdefault_directory; | 445 | static Lisp_Object Qdefault_directory; |
| 419 | 446 | ||
| 420 | static Lisp_Object | 447 | static Lisp_Object |
| @@ -422,6 +449,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, | |||
| 422 | Lisp_Object predicate) | 449 | Lisp_Object predicate) |
| 423 | { | 450 | { |
| 424 | DIR *d; | 451 | DIR *d; |
| 452 | int fd; | ||
| 425 | ptrdiff_t bestmatchsize = 0; | 453 | ptrdiff_t bestmatchsize = 0; |
| 426 | int matchcount = 0; | 454 | int matchcount = 0; |
| 427 | /* If ALL_FLAG is 1, BESTMATCH is the list of all matches, decoded. | 455 | /* If ALL_FLAG is 1, BESTMATCH is the list of all matches, decoded. |
| @@ -458,9 +486,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, | |||
| 458 | 486 | ||
| 459 | encoded_dir = ENCODE_FILE (dirname); | 487 | encoded_dir = ENCODE_FILE (dirname); |
| 460 | 488 | ||
| 461 | block_input (); | 489 | d = open_directory (SSDATA (Fdirectory_file_name (encoded_dir)), &fd); |
| 462 | d = opendir (SSDATA (Fdirectory_file_name (encoded_dir))); | ||
| 463 | unblock_input (); | ||
| 464 | if (!d) | 490 | if (!d) |
| 465 | report_file_error ("Opening directory", Fcons (dirname, Qnil)); | 491 | report_file_error ("Opening directory", Fcons (dirname, Qnil)); |
| 466 | 492 | ||
| @@ -495,7 +521,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, | |||
| 495 | SCHARS (encoded_file))) | 521 | SCHARS (encoded_file))) |
| 496 | continue; | 522 | continue; |
| 497 | 523 | ||
| 498 | if (file_name_completion_stat (encoded_dir, dp, &st) < 0) | 524 | if (file_name_completion_stat (fd, dp, &st) < 0) |
| 499 | continue; | 525 | continue; |
| 500 | 526 | ||
| 501 | directoryp = S_ISDIR (st.st_mode) != 0; | 527 | directoryp = S_ISDIR (st.st_mode) != 0; |
| @@ -772,14 +798,9 @@ scmp (const char *s1, const char *s2, ptrdiff_t len) | |||
| 772 | } | 798 | } |
| 773 | 799 | ||
| 774 | static int | 800 | static int |
| 775 | file_name_completion_stat (Lisp_Object dirname, struct dirent *dp, | 801 | file_name_completion_stat (int fd, struct dirent *dp, struct stat *st_addr) |
| 776 | struct stat *st_addr) | ||
| 777 | { | 802 | { |
| 778 | ptrdiff_t len = dirent_namelen (dp); | ||
| 779 | ptrdiff_t pos = SCHARS (dirname); | ||
| 780 | int value; | 803 | int value; |
| 781 | USE_SAFE_ALLOCA; | ||
| 782 | char *fullname = SAFE_ALLOCA (len + pos + 2); | ||
| 783 | 804 | ||
| 784 | #ifdef MSDOS | 805 | #ifdef MSDOS |
| 785 | /* Some fields of struct stat are *very* expensive to compute on MS-DOS, | 806 | /* Some fields of struct stat are *very* expensive to compute on MS-DOS, |
| @@ -792,23 +813,15 @@ file_name_completion_stat (Lisp_Object dirname, struct dirent *dp, | |||
| 792 | _djstat_flags = _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE; | 813 | _djstat_flags = _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE; |
| 793 | #endif /* MSDOS */ | 814 | #endif /* MSDOS */ |
| 794 | 815 | ||
| 795 | memcpy (fullname, SDATA (dirname), pos); | ||
| 796 | if (!IS_DIRECTORY_SEP (fullname[pos - 1])) | ||
| 797 | fullname[pos++] = DIRECTORY_SEP; | ||
| 798 | |||
| 799 | memcpy (fullname + pos, dp->d_name, len); | ||
| 800 | fullname[pos + len] = 0; | ||
| 801 | |||
| 802 | /* We want to return success if a link points to a nonexistent file, | 816 | /* We want to return success if a link points to a nonexistent file, |
| 803 | but we want to return the status for what the link points to, | 817 | but we want to return the status for what the link points to, |
| 804 | in case it is a directory. */ | 818 | in case it is a directory. */ |
| 805 | value = lstat (fullname, st_addr); | 819 | value = fstatat (fd, dp->d_name, st_addr, AT_SYMLINK_NOFOLLOW); |
| 806 | if (value == 0 && S_ISLNK (st_addr->st_mode)) | 820 | if (value == 0 && S_ISLNK (st_addr->st_mode)) |
| 807 | stat (fullname, st_addr); | 821 | fstatat (fd, dp->d_name, st_addr, 0); |
| 808 | #ifdef MSDOS | 822 | #ifdef MSDOS |
| 809 | _djstat_flags = save_djstat_flags; | 823 | _djstat_flags = save_djstat_flags; |
| 810 | #endif /* MSDOS */ | 824 | #endif /* MSDOS */ |
| 811 | SAFE_FREE (); | ||
| 812 | return value; | 825 | return value; |
| 813 | } | 826 | } |
| 814 | 827 | ||
| @@ -886,18 +899,8 @@ On some FAT-based filesystems, only the date of last access is recorded, | |||
| 886 | so last access time will always be midnight of that day. */) | 899 | so last access time will always be midnight of that day. */) |
| 887 | (Lisp_Object filename, Lisp_Object id_format) | 900 | (Lisp_Object filename, Lisp_Object id_format) |
| 888 | { | 901 | { |
| 889 | Lisp_Object values[12]; | ||
| 890 | Lisp_Object encoded; | 902 | Lisp_Object encoded; |
| 891 | struct stat s; | ||
| 892 | int lstat_result; | ||
| 893 | |||
| 894 | /* An array to hold the mode string generated by filemodestring, | ||
| 895 | including its terminating space and null byte. */ | ||
| 896 | char modes[sizeof "-rwxr-xr-x "]; | ||
| 897 | |||
| 898 | Lisp_Object handler; | 903 | Lisp_Object handler; |
| 899 | struct gcpro gcpro1; | ||
| 900 | char *uname = NULL, *gname = NULL; | ||
| 901 | 904 | ||
| 902 | filename = Fexpand_file_name (filename, Qnil); | 905 | filename = Fexpand_file_name (filename, Qnil); |
| 903 | 906 | ||
| @@ -913,9 +916,22 @@ so last access time will always be midnight of that day. */) | |||
| 913 | return call3 (handler, Qfile_attributes, filename, id_format); | 916 | return call3 (handler, Qfile_attributes, filename, id_format); |
| 914 | } | 917 | } |
| 915 | 918 | ||
| 916 | GCPRO1 (filename); | ||
| 917 | encoded = ENCODE_FILE (filename); | 919 | encoded = ENCODE_FILE (filename); |
| 918 | UNGCPRO; | 920 | return file_attributes (AT_FDCWD, SSDATA (encoded), id_format); |
| 921 | } | ||
| 922 | |||
| 923 | static Lisp_Object | ||
| 924 | file_attributes (int fd, char const *name, Lisp_Object id_format) | ||
| 925 | { | ||
| 926 | Lisp_Object values[12]; | ||
| 927 | struct stat s; | ||
| 928 | int lstat_result; | ||
| 929 | |||
| 930 | /* An array to hold the mode string generated by filemodestring, | ||
| 931 | including its terminating space and null byte. */ | ||
| 932 | char modes[sizeof "-rwxr-xr-x "]; | ||
| 933 | |||
| 934 | char *uname = NULL, *gname = NULL; | ||
| 919 | 935 | ||
| 920 | #ifdef WINDOWSNT | 936 | #ifdef WINDOWSNT |
| 921 | /* We usually don't request accurate owner and group info, because | 937 | /* We usually don't request accurate owner and group info, because |
| @@ -925,7 +941,7 @@ so last access time will always be midnight of that day. */) | |||
| 925 | w32_stat_get_owner_group = 1; | 941 | w32_stat_get_owner_group = 1; |
| 926 | #endif | 942 | #endif |
| 927 | 943 | ||
| 928 | lstat_result = lstat (SSDATA (encoded), &s); | 944 | lstat_result = fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW); |
| 929 | 945 | ||
| 930 | #ifdef WINDOWSNT | 946 | #ifdef WINDOWSNT |
| 931 | w32_stat_get_owner_group = 0; | 947 | w32_stat_get_owner_group = 0; |
| @@ -934,7 +950,7 @@ so last access time will always be midnight of that day. */) | |||
| 934 | if (lstat_result < 0) | 950 | if (lstat_result < 0) |
| 935 | return Qnil; | 951 | return Qnil; |
| 936 | 952 | ||
| 937 | values[0] = (S_ISLNK (s.st_mode) ? Ffile_symlink_p (filename) | 953 | values[0] = (S_ISLNK (s.st_mode) ? emacs_readlinkat (fd, name) |
| 938 | : S_ISDIR (s.st_mode) ? Qt : Qnil); | 954 | : S_ISDIR (s.st_mode) ? Qt : Qnil); |
| 939 | values[1] = make_number (s.st_nlink); | 955 | values[1] = make_number (s.st_nlink); |
| 940 | 956 | ||
diff --git a/src/fileio.c b/src/fileio.c index cd4bd4fa86e..fb6ecfedeb4 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -82,6 +82,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 82 | #endif | 82 | #endif |
| 83 | 83 | ||
| 84 | #include "systime.h" | 84 | #include "systime.h" |
| 85 | #include <allocator.h> | ||
| 86 | #include <careadlinkat.h> | ||
| 85 | #include <stat-time.h> | 87 | #include <stat-time.h> |
| 86 | 88 | ||
| 87 | #ifdef HPUX | 89 | #ifdef HPUX |
| @@ -2759,6 +2761,29 @@ If there is no error, returns nil. */) | |||
| 2759 | return Qnil; | 2761 | return Qnil; |
| 2760 | } | 2762 | } |
| 2761 | 2763 | ||
| 2764 | /* Relative to directory FD, return the symbolic link value of FILENAME. | ||
| 2765 | On failure, return nil. */ | ||
| 2766 | Lisp_Object | ||
| 2767 | emacs_readlinkat (int fd, char const *filename) | ||
| 2768 | { | ||
| 2769 | static struct allocator const emacs_norealloc_allocator = | ||
| 2770 | { xmalloc, NULL, xfree, memory_full }; | ||
| 2771 | Lisp_Object val; | ||
| 2772 | char readlink_buf[1024]; | ||
| 2773 | char *buf = careadlinkat (fd, filename, readlink_buf, sizeof readlink_buf, | ||
| 2774 | &emacs_norealloc_allocator, readlinkat); | ||
| 2775 | if (!buf) | ||
| 2776 | return Qnil; | ||
| 2777 | |||
| 2778 | val = build_string (buf); | ||
| 2779 | if (buf[0] == '/' && strchr (buf, ':')) | ||
| 2780 | val = concat2 (build_string ("/:"), val); | ||
| 2781 | if (buf != readlink_buf) | ||
| 2782 | xfree (buf); | ||
| 2783 | val = DECODE_FILE (val); | ||
| 2784 | return val; | ||
| 2785 | } | ||
| 2786 | |||
| 2762 | DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0, | 2787 | DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0, |
| 2763 | doc: /* Return non-nil if file FILENAME is the name of a symbolic link. | 2788 | doc: /* Return non-nil if file FILENAME is the name of a symbolic link. |
| 2764 | The value is the link target, as a string. | 2789 | The value is the link target, as a string. |
| @@ -2769,9 +2794,6 @@ points to a nonexistent file. */) | |||
| 2769 | (Lisp_Object filename) | 2794 | (Lisp_Object filename) |
| 2770 | { | 2795 | { |
| 2771 | Lisp_Object handler; | 2796 | Lisp_Object handler; |
| 2772 | char *buf; | ||
| 2773 | Lisp_Object val; | ||
| 2774 | char readlink_buf[READLINK_BUFSIZE]; | ||
| 2775 | 2797 | ||
| 2776 | CHECK_STRING (filename); | 2798 | CHECK_STRING (filename); |
| 2777 | filename = Fexpand_file_name (filename, Qnil); | 2799 | filename = Fexpand_file_name (filename, Qnil); |
| @@ -2784,17 +2806,7 @@ points to a nonexistent file. */) | |||
| 2784 | 2806 | ||
| 2785 | filename = ENCODE_FILE (filename); | 2807 | filename = ENCODE_FILE (filename); |
| 2786 | 2808 | ||
| 2787 | buf = emacs_readlink (SSDATA (filename), readlink_buf); | 2809 | return emacs_readlinkat (AT_FDCWD, SSDATA (filename)); |
| 2788 | if (! buf) | ||
| 2789 | return Qnil; | ||
| 2790 | |||
| 2791 | val = build_string (buf); | ||
| 2792 | if (buf[0] == '/' && strchr (buf, ':')) | ||
| 2793 | val = concat2 (build_string ("/:"), val); | ||
| 2794 | if (buf != readlink_buf) | ||
| 2795 | xfree (buf); | ||
| 2796 | val = DECODE_FILE (val); | ||
| 2797 | return val; | ||
| 2798 | } | 2810 | } |
| 2799 | 2811 | ||
| 2800 | DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0, | 2812 | DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0, |
| @@ -5024,7 +5036,11 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 5024 | && st.st_dev == st1.st_dev && st.st_ino == st1.st_ino) | 5036 | && st.st_dev == st1.st_dev && st.st_ino == st1.st_ino) |
| 5025 | { | 5037 | { |
| 5026 | EMACS_TIME modtime1 = get_stat_mtime (&st1); | 5038 | EMACS_TIME modtime1 = get_stat_mtime (&st1); |
| 5027 | if (EMACS_TIME_EQ (modtime, modtime1) | 5039 | /* If neither O_EXCL nor O_TRUNC is used, and Emacs happened to |
| 5040 | write nothing to the file, the file's time stamp won't change | ||
| 5041 | so it should not be used in this heuristic. */ | ||
| 5042 | if ((open_flags & (O_EXCL | O_TRUNC)) != 0 | ||
| 5043 | && EMACS_TIME_EQ (modtime, modtime1) | ||
| 5028 | && st.st_size == st1.st_size) | 5044 | && st.st_size == st1.st_size) |
| 5029 | { | 5045 | { |
| 5030 | timestamp_file_system = st.st_dev; | 5046 | timestamp_file_system = st.st_dev; |
diff --git a/src/filelock.c b/src/filelock.c index f21240f8340..228fe98e8c7 100644 --- a/src/filelock.c +++ b/src/filelock.c | |||
| @@ -390,12 +390,14 @@ current_lock_owner (lock_info_type *owner, char *lfname) | |||
| 390 | lock_info_type local_owner; | 390 | lock_info_type local_owner; |
| 391 | intmax_t n; | 391 | intmax_t n; |
| 392 | char *at, *dot, *colon; | 392 | char *at, *dot, *colon; |
| 393 | char readlink_buf[READLINK_BUFSIZE]; | 393 | Lisp_Object lfinfo_object = emacs_readlinkat (AT_FDCWD, lfname); |
| 394 | char *lfinfo = emacs_readlink (lfname, readlink_buf); | 394 | char *lfinfo; |
| 395 | struct gcpro gcpro1; | ||
| 395 | 396 | ||
| 396 | /* If nonexistent lock file, all is well; otherwise, got strange error. */ | 397 | /* If nonexistent lock file, all is well; otherwise, got strange error. */ |
| 397 | if (!lfinfo) | 398 | if (NILP (lfinfo_object)) |
| 398 | return errno == ENOENT ? 0 : -1; | 399 | return errno == ENOENT ? 0 : -1; |
| 400 | lfinfo = SSDATA (lfinfo_object); | ||
| 399 | 401 | ||
| 400 | /* Even if the caller doesn't want the owner info, we still have to | 402 | /* Even if the caller doesn't want the owner info, we still have to |
| 401 | read it to determine return value. */ | 403 | read it to determine return value. */ |
| @@ -407,12 +409,9 @@ current_lock_owner (lock_info_type *owner, char *lfname) | |||
| 407 | at = strrchr (lfinfo, '@'); | 409 | at = strrchr (lfinfo, '@'); |
| 408 | dot = strrchr (lfinfo, '.'); | 410 | dot = strrchr (lfinfo, '.'); |
| 409 | if (!at || !dot) | 411 | if (!at || !dot) |
| 410 | { | 412 | return -1; |
| 411 | if (lfinfo != readlink_buf) | ||
| 412 | xfree (lfinfo); | ||
| 413 | return -1; | ||
| 414 | } | ||
| 415 | len = at - lfinfo; | 413 | len = at - lfinfo; |
| 414 | GCPRO1 (lfinfo_object); | ||
| 416 | owner->user = xmalloc (len + 1); | 415 | owner->user = xmalloc (len + 1); |
| 417 | memcpy (owner->user, lfinfo, len); | 416 | memcpy (owner->user, lfinfo, len); |
| 418 | owner->user[len] = 0; | 417 | owner->user[len] = 0; |
| @@ -445,8 +444,7 @@ current_lock_owner (lock_info_type *owner, char *lfname) | |||
| 445 | owner->host[len] = 0; | 444 | owner->host[len] = 0; |
| 446 | 445 | ||
| 447 | /* We're done looking at the link info. */ | 446 | /* We're done looking at the link info. */ |
| 448 | if (lfinfo != readlink_buf) | 447 | UNGCPRO; |
| 449 | xfree (lfinfo); | ||
| 450 | 448 | ||
| 451 | /* On current host? */ | 449 | /* On current host? */ |
| 452 | if (STRINGP (Fsystem_name ()) | 450 | if (STRINGP (Fsystem_name ()) |
diff --git a/src/lisp.h b/src/lisp.h index 7128c3d4b18..dd8d1f38db6 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3299,6 +3299,7 @@ extern Lisp_Object close_file_unwind (Lisp_Object); | |||
| 3299 | extern Lisp_Object restore_point_unwind (Lisp_Object); | 3299 | extern Lisp_Object restore_point_unwind (Lisp_Object); |
| 3300 | extern _Noreturn void report_file_error (const char *, Lisp_Object); | 3300 | extern _Noreturn void report_file_error (const char *, Lisp_Object); |
| 3301 | extern bool internal_delete_file (Lisp_Object); | 3301 | extern bool internal_delete_file (Lisp_Object); |
| 3302 | extern Lisp_Object emacs_readlinkat (int, const char *); | ||
| 3302 | extern bool file_directory_p (const char *); | 3303 | extern bool file_directory_p (const char *); |
| 3303 | extern bool file_accessible_directory_p (const char *); | 3304 | extern bool file_accessible_directory_p (const char *); |
| 3304 | extern void init_fileio (void); | 3305 | extern void init_fileio (void); |
| @@ -3571,8 +3572,6 @@ extern int emacs_open (const char *, int, int); | |||
| 3571 | extern int emacs_close (int); | 3572 | extern int emacs_close (int); |
| 3572 | extern ptrdiff_t emacs_read (int, char *, ptrdiff_t); | 3573 | extern ptrdiff_t emacs_read (int, char *, ptrdiff_t); |
| 3573 | extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t); | 3574 | extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t); |
| 3574 | enum { READLINK_BUFSIZE = 1024 }; | ||
| 3575 | extern char *emacs_readlink (const char *, char [READLINK_BUFSIZE]); | ||
| 3576 | 3575 | ||
| 3577 | extern void unlock_all_files (void); | 3576 | extern void unlock_all_files (void); |
| 3578 | extern void lock_file (Lisp_Object); | 3577 | extern void lock_file (Lisp_Object); |
diff --git a/src/print.c b/src/print.c index 8420f8075a5..f5f8450545d 100644 --- a/src/print.c +++ b/src/print.c | |||
| @@ -1775,7 +1775,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag | |||
| 1775 | { | 1775 | { |
| 1776 | int len; | 1776 | int len; |
| 1777 | strout ("#<window ", -1, -1, printcharfun); | 1777 | strout ("#<window ", -1, -1, printcharfun); |
| 1778 | len = sprintf (buf, "%d", XWINDOW (obj)->sequence_number); | 1778 | len = sprintf (buf, "%p", XWINDOW (obj)); |
| 1779 | strout (buf, len, len, printcharfun); | 1779 | strout (buf, len, len, printcharfun); |
| 1780 | if (!NILP (XWINDOW (obj)->buffer)) | 1780 | if (!NILP (XWINDOW (obj)->buffer)) |
| 1781 | { | 1781 | { |
diff --git a/src/sysdep.c b/src/sysdep.c index 0e9a6826005..57ca8265a65 100644 --- a/src/sysdep.c +++ b/src/sysdep.c | |||
| @@ -30,9 +30,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 30 | #include <limits.h> | 30 | #include <limits.h> |
| 31 | #include <unistd.h> | 31 | #include <unistd.h> |
| 32 | 32 | ||
| 33 | #include <allocator.h> | ||
| 34 | #include <c-ctype.h> | 33 | #include <c-ctype.h> |
| 35 | #include <careadlinkat.h> | ||
| 36 | #include <ignore-value.h> | 34 | #include <ignore-value.h> |
| 37 | #include <utimens.h> | 35 | #include <utimens.h> |
| 38 | 36 | ||
| @@ -2247,22 +2245,6 @@ emacs_write (int fildes, const char *buf, ptrdiff_t nbyte) | |||
| 2247 | 2245 | ||
| 2248 | return (bytes_written); | 2246 | return (bytes_written); |
| 2249 | } | 2247 | } |
| 2250 | |||
| 2251 | static struct allocator const emacs_norealloc_allocator = | ||
| 2252 | { xmalloc, NULL, xfree, memory_full }; | ||
| 2253 | |||
| 2254 | /* Get the symbolic link value of FILENAME. Return a pointer to a | ||
| 2255 | NUL-terminated string. If readlink fails, return NULL and set | ||
| 2256 | errno. If the value fits in INITIAL_BUF, return INITIAL_BUF. | ||
| 2257 | Otherwise, allocate memory and return a pointer to that memory. If | ||
| 2258 | memory allocation fails, diagnose and fail without returning. If | ||
| 2259 | successful, store the length of the symbolic link into *LINKLEN. */ | ||
| 2260 | char * | ||
| 2261 | emacs_readlink (char const *filename, char initial_buf[READLINK_BUFSIZE]) | ||
| 2262 | { | ||
| 2263 | return careadlinkat (AT_FDCWD, filename, initial_buf, READLINK_BUFSIZE, | ||
| 2264 | &emacs_norealloc_allocator, careadlinkatcwd); | ||
| 2265 | } | ||
| 2266 | 2248 | ||
| 2267 | /* Return a struct timeval that is roughly equivalent to T. | 2249 | /* Return a struct timeval that is roughly equivalent to T. |
| 2268 | Use the least timeval not less than T. | 2250 | Use the least timeval not less than T. |
| @@ -4274,6 +4274,30 @@ lstat (const char * path, struct stat * buf) | |||
| 4274 | return stat_worker (path, buf, 0); | 4274 | return stat_worker (path, buf, 0); |
| 4275 | } | 4275 | } |
| 4276 | 4276 | ||
| 4277 | int | ||
| 4278 | fstatat (int fd, char const *name, struct stat *st, int flags) | ||
| 4279 | { | ||
| 4280 | /* Rely on a hack: an open directory is modeled as file descriptor 0. | ||
| 4281 | This is good enough for the current usage in Emacs, but is fragile. | ||
| 4282 | |||
| 4283 | FIXME: Add proper support for fdopendir, fstatatat, readlinkat. | ||
| 4284 | Gnulib does this and can serve as a model. */ | ||
| 4285 | char fullname[MAX_PATH]; | ||
| 4286 | |||
| 4287 | if (fd != AT_FDCWD) | ||
| 4288 | { | ||
| 4289 | if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, name) | ||
| 4290 | < 0) | ||
| 4291 | { | ||
| 4292 | errno = ENAMETOOLONG; | ||
| 4293 | return -1; | ||
| 4294 | } | ||
| 4295 | name = fullname; | ||
| 4296 | } | ||
| 4297 | |||
| 4298 | return stat_worker (name, st, ! (flags & AT_SYMLINK_NOFOLLOW)); | ||
| 4299 | } | ||
| 4300 | |||
| 4277 | /* Provide fstat and utime as well as stat for consistent handling of | 4301 | /* Provide fstat and utime as well as stat for consistent handling of |
| 4278 | file timestamps. */ | 4302 | file timestamps. */ |
| 4279 | int | 4303 | int |
| @@ -4816,6 +4840,28 @@ readlink (const char *name, char *buf, size_t buf_size) | |||
| 4816 | return retval; | 4840 | return retval; |
| 4817 | } | 4841 | } |
| 4818 | 4842 | ||
| 4843 | ssize_t | ||
| 4844 | readlinkat (int fd, char const *name, char *buffer, | ||
| 4845 | size_t buffer_size) | ||
| 4846 | { | ||
| 4847 | /* Rely on a hack: an open directory is modeled as file descriptor 0, | ||
| 4848 | as in fstatat. FIXME: Add proper support for readlinkat. */ | ||
| 4849 | char fullname[MAX_PATH]; | ||
| 4850 | |||
| 4851 | if (fd != AT_FDCWD) | ||
| 4852 | { | ||
| 4853 | if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, name) | ||
| 4854 | < 0) | ||
| 4855 | { | ||
| 4856 | errno = ENAMETOOLONG; | ||
| 4857 | return -1; | ||
| 4858 | } | ||
| 4859 | name = fullname; | ||
| 4860 | } | ||
| 4861 | |||
| 4862 | return readlink (name, buffer, buffer_size); | ||
| 4863 | } | ||
| 4864 | |||
| 4819 | /* If FILE is a symlink, return its target (stored in a static | 4865 | /* If FILE is a symlink, return its target (stored in a static |
| 4820 | buffer); otherwise return FILE. | 4866 | buffer); otherwise return FILE. |
| 4821 | 4867 | ||
| @@ -5168,12 +5214,6 @@ careadlinkat (int fd, char const *filename, | |||
| 5168 | char linkname[MAX_PATH]; | 5214 | char linkname[MAX_PATH]; |
| 5169 | ssize_t link_size; | 5215 | ssize_t link_size; |
| 5170 | 5216 | ||
| 5171 | if (fd != AT_FDCWD) | ||
| 5172 | { | ||
| 5173 | errno = EINVAL; | ||
| 5174 | return NULL; | ||
| 5175 | } | ||
| 5176 | |||
| 5177 | link_size = preadlinkat (fd, filename, linkname, sizeof(linkname)); | 5217 | link_size = preadlinkat (fd, filename, linkname, sizeof(linkname)); |
| 5178 | 5218 | ||
| 5179 | if (link_size > 0) | 5219 | if (link_size > 0) |
| @@ -5191,14 +5231,6 @@ careadlinkat (int fd, char const *filename, | |||
| 5191 | return NULL; | 5231 | return NULL; |
| 5192 | } | 5232 | } |
| 5193 | 5233 | ||
| 5194 | ssize_t | ||
| 5195 | careadlinkatcwd (int fd, char const *filename, char *buffer, | ||
| 5196 | size_t buffer_size) | ||
| 5197 | { | ||
| 5198 | (void) fd; | ||
| 5199 | return readlink (filename, buffer, buffer_size); | ||
| 5200 | } | ||
| 5201 | |||
| 5202 | 5234 | ||
| 5203 | /* Support for browsing other processes and their attributes. See | 5235 | /* Support for browsing other processes and their attributes. See |
| 5204 | process.c for the Lisp bindings. */ | 5236 | process.c for the Lisp bindings. */ |
diff --git a/src/window.c b/src/window.c index f75c17a3d4f..b9165e21d3b 100644 --- a/src/window.c +++ b/src/window.c | |||
| @@ -117,9 +117,6 @@ Lisp_Object minibuf_selected_window; | |||
| 117 | /* Hook run at end of temp_output_buffer_show. */ | 117 | /* Hook run at end of temp_output_buffer_show. */ |
| 118 | static Lisp_Object Qtemp_buffer_show_hook; | 118 | static Lisp_Object Qtemp_buffer_show_hook; |
| 119 | 119 | ||
| 120 | /* Incremented for each window created. */ | ||
| 121 | static int sequence_number; | ||
| 122 | |||
| 123 | /* Nonzero after init_window_once has finished. */ | 120 | /* Nonzero after init_window_once has finished. */ |
| 124 | static int window_initialized; | 121 | static int window_initialized; |
| 125 | 122 | ||
| @@ -287,8 +284,9 @@ adjust_window_count (struct window *w, int arg) | |||
| 287 | b = b->base_buffer; | 284 | b = b->base_buffer; |
| 288 | b->window_count += arg; | 285 | b->window_count += arg; |
| 289 | eassert (b->window_count >= 0); | 286 | eassert (b->window_count >= 0); |
| 290 | /* Catch redisplay's attention. */ | 287 | /* These should be recalculated by redisplay code. */ |
| 291 | w->window_end_valid = 0; | 288 | w->window_end_valid = 0; |
| 289 | w->base_line_pos = 0; | ||
| 292 | } | 290 | } |
| 293 | } | 291 | } |
| 294 | 292 | ||
| @@ -3430,8 +3428,6 @@ make_parent_window (Lisp_Object window, int horflag) | |||
| 3430 | adjust_window_count (p, 1); | 3428 | adjust_window_count (p, 1); |
| 3431 | XSETWINDOW (parent, p); | 3429 | XSETWINDOW (parent, p); |
| 3432 | 3430 | ||
| 3433 | p->sequence_number = ++sequence_number; | ||
| 3434 | |||
| 3435 | replace_window (window, parent, 1); | 3431 | replace_window (window, parent, 1); |
| 3436 | 3432 | ||
| 3437 | wset_next (o, Qnil); | 3433 | wset_next (o, Qnil); |
| @@ -3480,7 +3476,7 @@ make_window (void) | |||
| 3480 | w->nrows_scale_factor = w->ncols_scale_factor = 1; | 3476 | w->nrows_scale_factor = w->ncols_scale_factor = 1; |
| 3481 | w->phys_cursor_type = -1; | 3477 | w->phys_cursor_type = -1; |
| 3482 | w->phys_cursor_width = -1; | 3478 | w->phys_cursor_width = -1; |
| 3483 | w->sequence_number = ++sequence_number; | 3479 | w->column_number_displayed = -1; |
| 3484 | 3480 | ||
| 3485 | /* Reset window_list. */ | 3481 | /* Reset window_list. */ |
| 3486 | Vwindow_list = Qnil; | 3482 | Vwindow_list = Qnil; |
diff --git a/src/window.h b/src/window.h index 135f591ded7..f28ce1424d0 100644 --- a/src/window.h +++ b/src/window.h | |||
| @@ -192,23 +192,6 @@ struct window | |||
| 192 | and Qt, so bitfield can't be used here. */ | 192 | and Qt, so bitfield can't be used here. */ |
| 193 | Lisp_Object dedicated; | 193 | Lisp_Object dedicated; |
| 194 | 194 | ||
| 195 | /* Line number and position of a line somewhere above the top of the | ||
| 196 | screen. If this field is nil, it means we don't have a base | ||
| 197 | line. */ | ||
| 198 | Lisp_Object base_line_number; | ||
| 199 | /* If this field is nil, it means we don't have a base line. | ||
| 200 | If it is a buffer, it means don't display the line number | ||
| 201 | as long as the window shows that buffer. */ | ||
| 202 | Lisp_Object base_line_pos; | ||
| 203 | |||
| 204 | /* If we have highlighted the region (or any part of it), | ||
| 205 | this is the mark position that we used, as an integer. */ | ||
| 206 | Lisp_Object region_showing; | ||
| 207 | |||
| 208 | /* The column number currently displayed in this window's mode line, | ||
| 209 | or nil if column numbers are not being displayed. */ | ||
| 210 | Lisp_Object column_number_displayed; | ||
| 211 | |||
| 212 | /* If redisplay in this window goes beyond this buffer position, | 195 | /* If redisplay in this window goes beyond this buffer position, |
| 213 | must run the redisplay-end-trigger-hook. */ | 196 | must run the redisplay-end-trigger-hook. */ |
| 214 | Lisp_Object redisplay_end_trigger; | 197 | Lisp_Object redisplay_end_trigger; |
| @@ -238,9 +221,6 @@ struct window | |||
| 238 | /* Number saying how recently window was selected. */ | 221 | /* Number saying how recently window was selected. */ |
| 239 | int use_time; | 222 | int use_time; |
| 240 | 223 | ||
| 241 | /* Unique number of window assigned when it was created. */ | ||
| 242 | int sequence_number; | ||
| 243 | |||
| 244 | /* Number of columns display within the window is scrolled to the left. */ | 224 | /* Number of columns display within the window is scrolled to the left. */ |
| 245 | ptrdiff_t hscroll; | 225 | ptrdiff_t hscroll; |
| 246 | 226 | ||
| @@ -260,6 +240,19 @@ struct window | |||
| 260 | it should be positive. */ | 240 | it should be positive. */ |
| 261 | ptrdiff_t last_point; | 241 | ptrdiff_t last_point; |
| 262 | 242 | ||
| 243 | /* Line number and position of a line somewhere above the top of the | ||
| 244 | screen. If this field is zero, it means we don't have a base line. */ | ||
| 245 | ptrdiff_t base_line_number; | ||
| 246 | |||
| 247 | /* If this field is zero, it means we don't have a base line. | ||
| 248 | If it is -1, it means don't display the line number as long | ||
| 249 | as the window shows its buffer. */ | ||
| 250 | ptrdiff_t base_line_pos; | ||
| 251 | |||
| 252 | /* The column number currently displayed in this window's mode | ||
| 253 | line, or -1 if column numbers are not being displayed. */ | ||
| 254 | ptrdiff_t column_number_displayed; | ||
| 255 | |||
| 263 | /* Scaling factor for the glyph_matrix size calculation in this window. | 256 | /* Scaling factor for the glyph_matrix size calculation in this window. |
| 264 | Used if window contains many small images or uses proportional fonts, | 257 | Used if window contains many small images or uses proportional fonts, |
| 265 | as the normal may yield a matrix which is too small. */ | 258 | as the normal may yield a matrix which is too small. */ |
| @@ -340,6 +333,9 @@ struct window | |||
| 340 | the frame image that window_end_pos did not get onto the frame. */ | 333 | the frame image that window_end_pos did not get onto the frame. */ |
| 341 | unsigned window_end_valid : 1; | 334 | unsigned window_end_valid : 1; |
| 342 | 335 | ||
| 336 | /* Nonzero if we have highlighted the region (or any part of it). */ | ||
| 337 | unsigned region_showing : 1; | ||
| 338 | |||
| 343 | /* Amount by which lines of this window are scrolled in | 339 | /* Amount by which lines of this window are scrolled in |
| 344 | y-direction (smooth scrolling). */ | 340 | y-direction (smooth scrolling). */ |
| 345 | int vscroll; | 341 | int vscroll; |
diff --git a/src/xdisp.c b/src/xdisp.c index 9fb9487732f..33fe82e165e 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -369,28 +369,6 @@ Lisp_Object Qcenter; | |||
| 369 | static Lisp_Object Qmargin, Qpointer; | 369 | static Lisp_Object Qmargin, Qpointer; |
| 370 | static Lisp_Object Qline_height; | 370 | static Lisp_Object Qline_height; |
| 371 | 371 | ||
| 372 | /* These setters are used only in this file, so they can be private. */ | ||
| 373 | static void | ||
| 374 | wset_base_line_number (struct window *w, Lisp_Object val) | ||
| 375 | { | ||
| 376 | w->base_line_number = val; | ||
| 377 | } | ||
| 378 | static void | ||
| 379 | wset_base_line_pos (struct window *w, Lisp_Object val) | ||
| 380 | { | ||
| 381 | w->base_line_pos = val; | ||
| 382 | } | ||
| 383 | static void | ||
| 384 | wset_column_number_displayed (struct window *w, Lisp_Object val) | ||
| 385 | { | ||
| 386 | w->column_number_displayed = val; | ||
| 387 | } | ||
| 388 | static void | ||
| 389 | wset_region_showing (struct window *w, Lisp_Object val) | ||
| 390 | { | ||
| 391 | w->region_showing = val; | ||
| 392 | } | ||
| 393 | |||
| 394 | #ifdef HAVE_WINDOW_SYSTEM | 372 | #ifdef HAVE_WINDOW_SYSTEM |
| 395 | 373 | ||
| 396 | /* Test if overflow newline into fringe. Called with iterator IT | 374 | /* Test if overflow newline into fringe. Called with iterator IT |
| @@ -10829,7 +10807,7 @@ window_buffer_changed (struct window *w) | |||
| 10829 | 10807 | ||
| 10830 | return (((BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star) | 10808 | return (((BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star) |
| 10831 | || ((!NILP (Vtransient_mark_mode) && !NILP (BVAR (b, mark_active))) | 10809 | || ((!NILP (Vtransient_mark_mode) && !NILP (BVAR (b, mark_active))) |
| 10832 | != !NILP (w->region_showing))); | 10810 | != w->region_showing)); |
| 10833 | } | 10811 | } |
| 10834 | 10812 | ||
| 10835 | /* Nonzero if W has %c in its mode line and mode line should be updated. */ | 10813 | /* Nonzero if W has %c in its mode line and mode line should be updated. */ |
| @@ -10837,9 +10815,9 @@ window_buffer_changed (struct window *w) | |||
| 10837 | static int | 10815 | static int |
| 10838 | mode_line_update_needed (struct window *w) | 10816 | mode_line_update_needed (struct window *w) |
| 10839 | { | 10817 | { |
| 10840 | return (!NILP (w->column_number_displayed) | 10818 | return (w->column_number_displayed != -1 |
| 10841 | && !(PT == w->last_point && !window_outdated (w)) | 10819 | && !(PT == w->last_point && !window_outdated (w)) |
| 10842 | && (XFASTINT (w->column_number_displayed) != current_column ())); | 10820 | && (w->column_number_displayed != current_column ())); |
| 10843 | } | 10821 | } |
| 10844 | 10822 | ||
| 10845 | /*********************************************************************** | 10823 | /*********************************************************************** |
| @@ -13092,18 +13070,6 @@ redisplay_internal (void) | |||
| 13092 | clear_garbaged_frames (); | 13070 | clear_garbaged_frames (); |
| 13093 | } | 13071 | } |
| 13094 | 13072 | ||
| 13095 | |||
| 13096 | /* If showing the region, and mark has changed, we must redisplay | ||
| 13097 | the whole window. The assignment to this_line_start_pos prevents | ||
| 13098 | the optimization directly below this if-statement. */ | ||
| 13099 | if (((!NILP (Vtransient_mark_mode) | ||
| 13100 | && !NILP (BVAR (XBUFFER (w->buffer), mark_active))) | ||
| 13101 | != !NILP (w->region_showing)) | ||
| 13102 | || (!NILP (w->region_showing) | ||
| 13103 | && !EQ (w->region_showing, | ||
| 13104 | Fmarker_position (BVAR (XBUFFER (w->buffer), mark))))) | ||
| 13105 | CHARPOS (this_line_start_pos) = 0; | ||
| 13106 | |||
| 13107 | /* Optimize the case that only the line containing the cursor in the | 13073 | /* Optimize the case that only the line containing the cursor in the |
| 13108 | selected window has changed. Variables starting with this_ are | 13074 | selected window has changed. Variables starting with this_ are |
| 13109 | set in display_line and record information about the line | 13075 | set in display_line and record information about the line |
| @@ -13274,7 +13240,7 @@ redisplay_internal (void) | |||
| 13274 | && (EQ (selected_window, | 13240 | && (EQ (selected_window, |
| 13275 | BVAR (current_buffer, last_selected_window)) | 13241 | BVAR (current_buffer, last_selected_window)) |
| 13276 | || highlight_nonselected_windows) | 13242 | || highlight_nonselected_windows) |
| 13277 | && NILP (w->region_showing) | 13243 | && !w->region_showing |
| 13278 | && NILP (Vshow_trailing_whitespace) | 13244 | && NILP (Vshow_trailing_whitespace) |
| 13279 | && !cursor_in_echo_area) | 13245 | && !cursor_in_echo_area) |
| 13280 | { | 13246 | { |
| @@ -14771,7 +14737,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p, | |||
| 14771 | if (!just_this_one_p | 14737 | if (!just_this_one_p |
| 14772 | || current_buffer->clip_changed | 14738 | || current_buffer->clip_changed |
| 14773 | || BEG_UNCHANGED < CHARPOS (startp)) | 14739 | || BEG_UNCHANGED < CHARPOS (startp)) |
| 14774 | wset_base_line_number (w, Qnil); | 14740 | w->base_line_number = 0; |
| 14775 | 14741 | ||
| 14776 | /* If cursor ends up on a partially visible line, | 14742 | /* If cursor ends up on a partially visible line, |
| 14777 | treat that as being off the bottom of the screen. */ | 14743 | treat that as being off the bottom of the screen. */ |
| @@ -14920,7 +14886,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste | |||
| 14920 | region exists, cursor movement has to do more than just | 14886 | region exists, cursor movement has to do more than just |
| 14921 | set the cursor. */ | 14887 | set the cursor. */ |
| 14922 | && markpos_of_region () < 0 | 14888 | && markpos_of_region () < 0 |
| 14923 | && NILP (w->region_showing) | 14889 | && !w->region_showing |
| 14924 | && NILP (Vshow_trailing_whitespace) | 14890 | && NILP (Vshow_trailing_whitespace) |
| 14925 | /* This code is not used for mini-buffer for the sake of the case | 14891 | /* This code is not used for mini-buffer for the sake of the case |
| 14926 | of redisplaying to replace an echo area message; since in | 14892 | of redisplaying to replace an echo area message; since in |
| @@ -15486,7 +15452,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) | |||
| 15486 | 15452 | ||
| 15487 | /* Forget any recorded base line for line number display. */ | 15453 | /* Forget any recorded base line for line number display. */ |
| 15488 | if (!buffer_unchanged_p) | 15454 | if (!buffer_unchanged_p) |
| 15489 | wset_base_line_number (w, Qnil); | 15455 | w->base_line_number = 0; |
| 15490 | 15456 | ||
| 15491 | /* Redisplay the mode line. Select the buffer properly for that. | 15457 | /* Redisplay the mode line. Select the buffer properly for that. |
| 15492 | Also, run the hook window-scroll-functions | 15458 | Also, run the hook window-scroll-functions |
| @@ -15726,7 +15692,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) | |||
| 15726 | || current_buffer->clip_changed | 15692 | || current_buffer->clip_changed |
| 15727 | || BEG_UNCHANGED < CHARPOS (startp)) | 15693 | || BEG_UNCHANGED < CHARPOS (startp)) |
| 15728 | /* Forget any recorded base line for line number display. */ | 15694 | /* Forget any recorded base line for line number display. */ |
| 15729 | wset_base_line_number (w, Qnil); | 15695 | w->base_line_number = 0; |
| 15730 | 15696 | ||
| 15731 | if (!cursor_row_fully_visible_p (w, 1, 0)) | 15697 | if (!cursor_row_fully_visible_p (w, 1, 0)) |
| 15732 | { | 15698 | { |
| @@ -15793,11 +15759,9 @@ redisplay_window (Lisp_Object window, int just_this_one_p) | |||
| 15793 | debug_method_add (w, "recenter"); | 15759 | debug_method_add (w, "recenter"); |
| 15794 | #endif | 15760 | #endif |
| 15795 | 15761 | ||
| 15796 | /* w->vscroll = 0; */ | ||
| 15797 | |||
| 15798 | /* Forget any previously recorded base line for line number display. */ | 15762 | /* Forget any previously recorded base line for line number display. */ |
| 15799 | if (!buffer_unchanged_p) | 15763 | if (!buffer_unchanged_p) |
| 15800 | wset_base_line_number (w, Qnil); | 15764 | w->base_line_number = 0; |
| 15801 | 15765 | ||
| 15802 | /* Determine the window start relative to point. */ | 15766 | /* Determine the window start relative to point. */ |
| 15803 | init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); | 15767 | init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); |
| @@ -16017,10 +15981,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p) | |||
| 16017 | && !FRAME_WINDOW_P (f) | 15981 | && !FRAME_WINDOW_P (f) |
| 16018 | && !WINDOW_FULL_WIDTH_P (w)) | 15982 | && !WINDOW_FULL_WIDTH_P (w)) |
| 16019 | /* Line number to display. */ | 15983 | /* Line number to display. */ |
| 16020 | || INTEGERP (w->base_line_pos) | 15984 | || w->base_line_pos > 0 |
| 16021 | /* Column number is displayed and different from the one displayed. */ | 15985 | /* Column number is displayed and different from the one displayed. */ |
| 16022 | || (!NILP (w->column_number_displayed) | 15986 | || (w->column_number_displayed != -1 |
| 16023 | && (XFASTINT (w->column_number_displayed) != current_column ()))) | 15987 | && (w->column_number_displayed != current_column ()))) |
| 16024 | /* This means that the window has a mode line. */ | 15988 | /* This means that the window has a mode line. */ |
| 16025 | && (WINDOW_WANTS_MODELINE_P (w) | 15989 | && (WINDOW_WANTS_MODELINE_P (w) |
| 16026 | || WINDOW_WANTS_HEADER_LINE_P (w))) | 15990 | || WINDOW_WANTS_HEADER_LINE_P (w))) |
| @@ -16051,11 +16015,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p) | |||
| 16051 | goto need_larger_matrices; | 16015 | goto need_larger_matrices; |
| 16052 | } | 16016 | } |
| 16053 | 16017 | ||
| 16054 | if (!line_number_displayed | 16018 | if (!line_number_displayed && w->base_line_pos != -1) |
| 16055 | && !BUFFERP (w->base_line_pos)) | ||
| 16056 | { | 16019 | { |
| 16057 | wset_base_line_pos (w, Qnil); | 16020 | w->base_line_pos = 0; |
| 16058 | wset_base_line_number (w, Qnil); | 16021 | w->base_line_number = 0; |
| 16059 | } | 16022 | } |
| 16060 | 16023 | ||
| 16061 | finish_menu_bars: | 16024 | finish_menu_bars: |
| @@ -16306,7 +16269,7 @@ try_window_reusing_current_matrix (struct window *w) | |||
| 16306 | 16269 | ||
| 16307 | /* Can't do this if region may have changed. */ | 16270 | /* Can't do this if region may have changed. */ |
| 16308 | if (0 <= markpos_of_region () | 16271 | if (0 <= markpos_of_region () |
| 16309 | || !NILP (w->region_showing) | 16272 | || w->region_showing |
| 16310 | || !NILP (Vshow_trailing_whitespace)) | 16273 | || !NILP (Vshow_trailing_whitespace)) |
| 16311 | return 0; | 16274 | return 0; |
| 16312 | 16275 | ||
| @@ -17152,7 +17115,7 @@ try_window_id (struct window *w) | |||
| 17152 | GIVE_UP (11); | 17115 | GIVE_UP (11); |
| 17153 | 17116 | ||
| 17154 | /* Likewise if showing a region. */ | 17117 | /* Likewise if showing a region. */ |
| 17155 | if (!NILP (w->region_showing)) | 17118 | if (w->region_showing) |
| 17156 | GIVE_UP (10); | 17119 | GIVE_UP (10); |
| 17157 | 17120 | ||
| 17158 | /* Can't use this if overlay arrow position and/or string have | 17121 | /* Can't use this if overlay arrow position and/or string have |
| @@ -19262,7 +19225,7 @@ display_line (struct it *it) | |||
| 19262 | } | 19225 | } |
| 19263 | 19226 | ||
| 19264 | /* Is IT->w showing the region? */ | 19227 | /* Is IT->w showing the region? */ |
| 19265 | wset_region_showing (it->w, it->region_beg_charpos > 0 ? Qt : Qnil); | 19228 | it->w->region_showing = it->region_beg_charpos > 0; |
| 19266 | 19229 | ||
| 19267 | /* Clear the result glyph row and enable it. */ | 19230 | /* Clear the result glyph row and enable it. */ |
| 19268 | prepare_desired_row (row); | 19231 | prepare_desired_row (row); |
| @@ -20266,7 +20229,7 @@ display_mode_lines (struct window *w) | |||
| 20266 | 20229 | ||
| 20267 | /* These will be set while the mode line specs are processed. */ | 20230 | /* These will be set while the mode line specs are processed. */ |
| 20268 | line_number_displayed = 0; | 20231 | line_number_displayed = 0; |
| 20269 | wset_column_number_displayed (w, Qnil); | 20232 | w->column_number_displayed = -1; |
| 20270 | 20233 | ||
| 20271 | if (WINDOW_WANTS_MODELINE_P (w)) | 20234 | if (WINDOW_WANTS_MODELINE_P (w)) |
| 20272 | { | 20235 | { |
| @@ -21289,8 +21252,7 @@ decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_ | |||
| 21289 | returned with spaces to that value. Return a Lisp string in | 21252 | returned with spaces to that value. Return a Lisp string in |
| 21290 | *STRING if the resulting string is taken from that Lisp string. | 21253 | *STRING if the resulting string is taken from that Lisp string. |
| 21291 | 21254 | ||
| 21292 | Note we operate on the current buffer for most purposes, | 21255 | Note we operate on the current buffer for most purposes. */ |
| 21293 | the exception being w->base_line_pos. */ | ||
| 21294 | 21256 | ||
| 21295 | static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------"; | 21257 | static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------"; |
| 21296 | 21258 | ||
| @@ -21401,7 +21363,7 @@ decode_mode_spec (struct window *w, register int c, int field_width, | |||
| 21401 | else | 21363 | else |
| 21402 | { | 21364 | { |
| 21403 | ptrdiff_t col = current_column (); | 21365 | ptrdiff_t col = current_column (); |
| 21404 | wset_column_number_displayed (w, make_number (col)); | 21366 | w->column_number_displayed = col; |
| 21405 | pint2str (decode_mode_spec_buf, width, col); | 21367 | pint2str (decode_mode_spec_buf, width, col); |
| 21406 | return decode_mode_spec_buf; | 21368 | return decode_mode_spec_buf; |
| 21407 | } | 21369 | } |
| @@ -21460,27 +21422,24 @@ decode_mode_spec (struct window *w, register int c, int field_width, | |||
| 21460 | 21422 | ||
| 21461 | /* If we decided that this buffer isn't suitable for line numbers, | 21423 | /* If we decided that this buffer isn't suitable for line numbers, |
| 21462 | don't forget that too fast. */ | 21424 | don't forget that too fast. */ |
| 21463 | if (EQ (w->base_line_pos, w->buffer)) | 21425 | if (w->base_line_pos == -1) |
| 21464 | goto no_value; | 21426 | goto no_value; |
| 21465 | /* But do forget it, if the window shows a different buffer now. */ | ||
| 21466 | else if (BUFFERP (w->base_line_pos)) | ||
| 21467 | wset_base_line_pos (w, Qnil); | ||
| 21468 | 21427 | ||
| 21469 | /* If the buffer is very big, don't waste time. */ | 21428 | /* If the buffer is very big, don't waste time. */ |
| 21470 | if (INTEGERP (Vline_number_display_limit) | 21429 | if (INTEGERP (Vline_number_display_limit) |
| 21471 | && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit)) | 21430 | && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit)) |
| 21472 | { | 21431 | { |
| 21473 | wset_base_line_pos (w, Qnil); | 21432 | w->base_line_pos = 0; |
| 21474 | wset_base_line_number (w, Qnil); | 21433 | w->base_line_number = 0; |
| 21475 | goto no_value; | 21434 | goto no_value; |
| 21476 | } | 21435 | } |
| 21477 | 21436 | ||
| 21478 | if (INTEGERP (w->base_line_number) | 21437 | if (w->base_line_number > 0 |
| 21479 | && INTEGERP (w->base_line_pos) | 21438 | && w->base_line_pos > 0 |
| 21480 | && XFASTINT (w->base_line_pos) <= startpos) | 21439 | && w->base_line_pos <= startpos) |
| 21481 | { | 21440 | { |
| 21482 | line = XFASTINT (w->base_line_number); | 21441 | line = w->base_line_number; |
| 21483 | linepos = XFASTINT (w->base_line_pos); | 21442 | linepos = w->base_line_pos; |
| 21484 | linepos_byte = buf_charpos_to_bytepos (b, linepos); | 21443 | linepos_byte = buf_charpos_to_bytepos (b, linepos); |
| 21485 | } | 21444 | } |
| 21486 | else | 21445 | else |
| @@ -21503,8 +21462,8 @@ decode_mode_spec (struct window *w, register int c, int field_width, | |||
| 21503 | go back past it. */ | 21462 | go back past it. */ |
| 21504 | if (startpos == BUF_BEGV (b)) | 21463 | if (startpos == BUF_BEGV (b)) |
| 21505 | { | 21464 | { |
| 21506 | wset_base_line_number (w, make_number (topline)); | 21465 | w->base_line_number = topline; |
| 21507 | wset_base_line_pos (w, make_number (BUF_BEGV (b))); | 21466 | w->base_line_pos = BUF_BEGV (b); |
| 21508 | } | 21467 | } |
| 21509 | else if (nlines < height + 25 || nlines > height * 3 + 50 | 21468 | else if (nlines < height + 25 || nlines > height * 3 + 50 |
| 21510 | || linepos == BUF_BEGV (b)) | 21469 | || linepos == BUF_BEGV (b)) |
| @@ -21530,13 +21489,13 @@ decode_mode_spec (struct window *w, register int c, int field_width, | |||
| 21530 | give up on line numbers for this window. */ | 21489 | give up on line numbers for this window. */ |
| 21531 | if (position == limit_byte && limit == startpos - distance) | 21490 | if (position == limit_byte && limit == startpos - distance) |
| 21532 | { | 21491 | { |
| 21533 | wset_base_line_pos (w, w->buffer); | 21492 | w->base_line_pos = -1; |
| 21534 | wset_base_line_number (w, Qnil); | 21493 | w->base_line_number = 0; |
| 21535 | goto no_value; | 21494 | goto no_value; |
| 21536 | } | 21495 | } |
| 21537 | 21496 | ||
| 21538 | wset_base_line_number (w, make_number (topline - nlines)); | 21497 | w->base_line_number = topline - nlines; |
| 21539 | wset_base_line_pos (w, make_number (BYTE_TO_CHAR (position))); | 21498 | w->base_line_pos = BYTE_TO_CHAR (position); |
| 21540 | } | 21499 | } |
| 21541 | 21500 | ||
| 21542 | /* Now count lines from the start pos to point. */ | 21501 | /* Now count lines from the start pos to point. */ |