aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJoakim Verona2013-02-02 00:03:52 +0100
committerJoakim Verona2013-02-02 00:03:52 +0100
commit9aa1f4ecdb156a4135c3f7f6125a2b5a40258038 (patch)
tree4026361436b73220b9ae03f2251d2248eeaac700 /src
parentae8a4617f3829786fc675b0dd8d818697da6a214 (diff)
parent35e854998e2ab2155875683411beb0518236da18 (diff)
downloademacs-9aa1f4ecdb156a4135c3f7f6125a2b5a40258038.tar.gz
emacs-9aa1f4ecdb156a4135c3f7f6125a2b5a40258038.zip
auto upstream
Diffstat (limited to 'src')
-rw-r--r--src/.gdbinit1
-rw-r--r--src/ChangeLog59
-rw-r--r--src/conf_post.h4
-rw-r--r--src/dired.c120
-rw-r--r--src/fileio.c46
-rw-r--r--src/filelock.c18
-rw-r--r--src/lisp.h3
-rw-r--r--src/print.c2
-rw-r--r--src/sysdep.c18
-rw-r--r--src/w32.c60
-rw-r--r--src/window.c10
-rw-r--r--src/window.h36
-rw-r--r--src/xdisp.c111
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
359define pwinx 359define 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 @@
12013-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
102013-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
292013-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
12013-01-31 Glenn Morris <rgm@gnu.org> 602013-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;
54static Lisp_Object Qfile_attributes_lessp; 55static Lisp_Object Qfile_attributes_lessp;
55 56
56static ptrdiff_t scmp (const char *, const char *, ptrdiff_t); 57static ptrdiff_t scmp (const char *, const char *, ptrdiff_t);
58static 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. */
59static ptrdiff_t 61static ptrdiff_t
@@ -66,6 +68,44 @@ dirent_namelen (struct dirent *dp)
66#endif 68#endif
67} 69}
68 70
71static DIR *
72open_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
70Lisp_Object 110Lisp_Object
71directory_files_internal_w32_unwind (Lisp_Object arg) 111directory_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
416static int file_name_completion_stat (Lisp_Object dirname, struct dirent *dp, 444static int file_name_completion_stat (int, struct dirent *, struct stat *);
417 struct stat *st_addr);
418static Lisp_Object Qdefault_directory; 445static Lisp_Object Qdefault_directory;
419 446
420static Lisp_Object 447static 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
774static int 800static int
775file_name_completion_stat (Lisp_Object dirname, struct dirent *dp, 801file_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,
886so last access time will always be midnight of that day. */) 899so 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
923static Lisp_Object
924file_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. */
2766Lisp_Object
2767emacs_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
2762DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0, 2787DEFUN ("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.
2764The value is the link target, as a string. 2789The 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
2800DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0, 2812DEFUN ("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);
3299extern Lisp_Object restore_point_unwind (Lisp_Object); 3299extern Lisp_Object restore_point_unwind (Lisp_Object);
3300extern _Noreturn void report_file_error (const char *, Lisp_Object); 3300extern _Noreturn void report_file_error (const char *, Lisp_Object);
3301extern bool internal_delete_file (Lisp_Object); 3301extern bool internal_delete_file (Lisp_Object);
3302extern Lisp_Object emacs_readlinkat (int, const char *);
3302extern bool file_directory_p (const char *); 3303extern bool file_directory_p (const char *);
3303extern bool file_accessible_directory_p (const char *); 3304extern bool file_accessible_directory_p (const char *);
3304extern void init_fileio (void); 3305extern void init_fileio (void);
@@ -3571,8 +3572,6 @@ extern int emacs_open (const char *, int, int);
3571extern int emacs_close (int); 3572extern int emacs_close (int);
3572extern ptrdiff_t emacs_read (int, char *, ptrdiff_t); 3573extern ptrdiff_t emacs_read (int, char *, ptrdiff_t);
3573extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t); 3574extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t);
3574enum { READLINK_BUFSIZE = 1024 };
3575extern char *emacs_readlink (const char *, char [READLINK_BUFSIZE]);
3576 3575
3577extern void unlock_all_files (void); 3576extern void unlock_all_files (void);
3578extern void lock_file (Lisp_Object); 3577extern 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
2251static 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. */
2260char *
2261emacs_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.
diff --git a/src/w32.c b/src/w32.c
index d0af53889e7..64f8a0335ac 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -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
4277int
4278fstatat (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. */
4279int 4303int
@@ -4816,6 +4840,28 @@ readlink (const char *name, char *buf, size_t buf_size)
4816 return retval; 4840 return retval;
4817} 4841}
4818 4842
4843ssize_t
4844readlinkat (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
5194ssize_t
5195careadlinkatcwd (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. */
118static Lisp_Object Qtemp_buffer_show_hook; 118static Lisp_Object Qtemp_buffer_show_hook;
119 119
120/* Incremented for each window created. */
121static int sequence_number;
122
123/* Nonzero after init_window_once has finished. */ 120/* Nonzero after init_window_once has finished. */
124static int window_initialized; 121static 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;
369static Lisp_Object Qmargin, Qpointer; 369static Lisp_Object Qmargin, Qpointer;
370static Lisp_Object Qline_height; 370static Lisp_Object Qline_height;
371 371
372/* These setters are used only in this file, so they can be private. */
373static void
374wset_base_line_number (struct window *w, Lisp_Object val)
375{
376 w->base_line_number = val;
377}
378static void
379wset_base_line_pos (struct window *w, Lisp_Object val)
380{
381 w->base_line_pos = val;
382}
383static void
384wset_column_number_displayed (struct window *w, Lisp_Object val)
385{
386 w->column_number_displayed = val;
387}
388static void
389wset_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)
10837static int 10815static int
10838mode_line_update_needed (struct window *w) 10816mode_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
21295static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------"; 21257static 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. */