aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrea Corallo2020-03-09 07:49:33 +0000
committerAndrea Corallo2020-03-09 07:49:33 +0000
commit87ee6ff4eb6df369965f37fba073e3ef1bb5d0bd (patch)
tree2af79516bca28e875879e01cb45b16fa4525a905 /src
parent9838ee7ed870844470703b2648f8b59c0575bd46 (diff)
parenta461baae79af3cea8780e9d9a845a1e859e96e5e (diff)
downloademacs-87ee6ff4eb6df369965f37fba073e3ef1bb5d0bd.tar.gz
emacs-87ee6ff4eb6df369965f37fba073e3ef1bb5d0bd.zip
Merge remote-tracking branch 'savannah/master' into HEAD
Diffstat (limited to 'src')
-rw-r--r--src/composite.c18
-rw-r--r--src/conf_post.h7
-rw-r--r--src/editfns.c19
-rw-r--r--src/emacs.c1
-rw-r--r--src/fileio.c53
-rw-r--r--src/font.c4
-rw-r--r--src/font.h2
-rw-r--r--src/fontset.c12
-rw-r--r--src/fringe.c7
-rw-r--r--src/gnutls.c19
-rw-r--r--src/intervals.c12
-rw-r--r--src/intervals.h24
-rw-r--r--src/nsterm.m11
-rw-r--r--src/pdumper.c9
-rw-r--r--src/process.c13
-rw-r--r--src/sysdep.c15
-rw-r--r--src/systime.h3
-rw-r--r--src/timefns.c83
-rw-r--r--src/w32.c106
-rw-r--r--src/w32term.c42
-rw-r--r--src/xdisp.c4
21 files changed, 303 insertions, 161 deletions
diff --git a/src/composite.c b/src/composite.c
index 05365cfb65e..84de334ce0d 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -818,6 +818,11 @@ fill_gstring_body (Lisp_Object gstring)
818 Lisp_Object header = AREF (gstring, 0); 818 Lisp_Object header = AREF (gstring, 0);
819 ptrdiff_t len = LGSTRING_CHAR_LEN (gstring); 819 ptrdiff_t len = LGSTRING_CHAR_LEN (gstring);
820 ptrdiff_t i; 820 ptrdiff_t i;
821 struct font *font = NULL;
822 unsigned int code;
823
824 if (FONT_OBJECT_P (font_object))
825 font = XFONT_OBJECT (font_object);
821 826
822 for (i = 0; i < len; i++) 827 for (i = 0; i < len; i++)
823 { 828 {
@@ -832,10 +837,15 @@ fill_gstring_body (Lisp_Object gstring)
832 LGLYPH_SET_FROM (g, i); 837 LGLYPH_SET_FROM (g, i);
833 LGLYPH_SET_TO (g, i); 838 LGLYPH_SET_TO (g, i);
834 LGLYPH_SET_CHAR (g, c); 839 LGLYPH_SET_CHAR (g, c);
835 if (FONT_OBJECT_P (font_object)) 840
836 { 841 if (font != NULL)
837 font_fill_lglyph_metrics (g, font_object); 842 code = font->driver->encode_char (font, LGLYPH_CHAR (g));
838 } 843 else
844 code = FONT_INVALID_CODE;
845 if (code != FONT_INVALID_CODE)
846 {
847 font_fill_lglyph_metrics (g, font, code);
848 }
839 else 849 else
840 { 850 {
841 int width = XFIXNAT (CHAR_TABLE_REF (Vchar_width_table, c)); 851 int width = XFIXNAT (CHAR_TABLE_REF (Vchar_width_table, c));
diff --git a/src/conf_post.h b/src/conf_post.h
index 2f8d19fdca8..eb8fb18c00c 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -78,6 +78,7 @@ typedef bool bool_bf;
78# define __has_attribute_no_address_safety_analysis false 78# define __has_attribute_no_address_safety_analysis false
79# define __has_attribute_no_sanitize_address GNUC_PREREQ (4, 8, 0) 79# define __has_attribute_no_sanitize_address GNUC_PREREQ (4, 8, 0)
80# define __has_attribute_no_sanitize_undefined GNUC_PREREQ (4, 9, 0) 80# define __has_attribute_no_sanitize_undefined GNUC_PREREQ (4, 9, 0)
81# define __has_attribute_returns_nonnull GNUC_PREREQ (4, 9, 0)
81# define __has_attribute_warn_unused_result GNUC_PREREQ (3, 4, 0) 82# define __has_attribute_warn_unused_result GNUC_PREREQ (3, 4, 0)
82#endif 83#endif
83 84
@@ -321,6 +322,12 @@ extern int emacs_setenv_TZ (char const *);
321 322
322#define ATTRIBUTE_MALLOC_SIZE(args) ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE (args) 323#define ATTRIBUTE_MALLOC_SIZE(args) ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE (args)
323 324
325#if __has_attribute (returns_nonnull)
326# define ATTRIBUTE_RETURNS_NONNULL __attribute__ ((returns_nonnull))
327#else
328# define ATTRIBUTE_RETURNS_NONNULL
329#endif
330
324/* Work around GCC bug 59600: when a function is inlined, the inlined 331/* Work around GCC bug 59600: when a function is inlined, the inlined
325 code may have its addresses sanitized even if the function has the 332 code may have its addresses sanitized even if the function has the
326 no_sanitize_address attribute. This bug is fixed in GCC 4.9.0 and 333 no_sanitize_address attribute. This bug is fixed in GCC 4.9.0 and
diff --git a/src/editfns.c b/src/editfns.c
index ddf190b1752..eb15566fb48 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -1262,14 +1262,17 @@ name, or nil if there is no such user. */)
1262 if (q) 1262 if (q)
1263 { 1263 {
1264 Lisp_Object login = Fuser_login_name (INT_TO_INTEGER (pw->pw_uid)); 1264 Lisp_Object login = Fuser_login_name (INT_TO_INTEGER (pw->pw_uid));
1265 USE_SAFE_ALLOCA; 1265 if (!NILP (login))
1266 char *r = SAFE_ALLOCA (strlen (p) + SBYTES (login) + 1); 1266 {
1267 memcpy (r, p, q - p); 1267 USE_SAFE_ALLOCA;
1268 char *s = lispstpcpy (&r[q - p], login); 1268 char *r = SAFE_ALLOCA (strlen (p) + SBYTES (login) + 1);
1269 r[q - p] = upcase ((unsigned char) r[q - p]); 1269 memcpy (r, p, q - p);
1270 strcpy (s, q + 1); 1270 char *s = lispstpcpy (&r[q - p], login);
1271 full = build_string (r); 1271 r[q - p] = upcase ((unsigned char) r[q - p]);
1272 SAFE_FREE (); 1272 strcpy (s, q + 1);
1273 full = build_string (r);
1274 SAFE_FREE ();
1275 }
1273 } 1276 }
1274#endif /* AMPERSAND_FULL_NAME */ 1277#endif /* AMPERSAND_FULL_NAME */
1275 1278
diff --git a/src/emacs.c b/src/emacs.c
index ce1c9edc2dc..fcc02a3a874 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1974,7 +1974,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1974 /* This calls putenv and so must precede init_process_emacs. */ 1974 /* This calls putenv and so must precede init_process_emacs. */
1975 init_timefns (); 1975 init_timefns ();
1976 1976
1977 /* This sets Voperating_system_release, which init_process_emacs uses. */
1978 init_editfns (); 1977 init_editfns ();
1979 1978
1980 /* These two call putenv. */ 1979 /* These two call putenv. */
diff --git a/src/fileio.c b/src/fileio.c
index 2532f5233c4..ffe79559a3f 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2077,7 +2077,7 @@ permissions. */)
2077 report_file_error ("Copying permissions from", file); 2077 report_file_error ("Copying permissions from", file);
2078 case -3: 2078 case -3:
2079 xsignal2 (Qfile_date_error, 2079 xsignal2 (Qfile_date_error,
2080 build_string ("Resetting file times"), newname); 2080 build_string ("Cannot set file date"), newname);
2081 case -4: 2081 case -4:
2082 report_file_error ("Copying permissions to", newname); 2082 report_file_error ("Copying permissions to", newname);
2083 } 2083 }
@@ -2253,9 +2253,8 @@ permissions. */)
2253 2253
2254 if (!NILP (keep_time)) 2254 if (!NILP (keep_time))
2255 { 2255 {
2256 struct timespec atime = get_stat_atime (&st); 2256 struct timespec ts[] = { get_stat_atime (&st), get_stat_mtime (&st) };
2257 struct timespec mtime = get_stat_mtime (&st); 2257 if (futimens (ofd, ts) != 0)
2258 if (set_file_times (ofd, SSDATA (encoded_newname), atime, mtime) != 0)
2259 xsignal2 (Qfile_date_error, 2258 xsignal2 (Qfile_date_error,
2260 build_string ("Cannot set file date"), newname); 2259 build_string ("Cannot set file date"), newname);
2261 } 2260 }
@@ -3430,39 +3429,41 @@ The value is an integer. */)
3430} 3429}
3431 3430
3432 3431
3433DEFUN ("set-file-times", Fset_file_times, Sset_file_times, 1, 2, 0, 3432DEFUN ("set-file-times", Fset_file_times, Sset_file_times, 1, 3, 0,
3434 doc: /* Set times of file FILENAME to TIMESTAMP. 3433 doc: /* Set times of file FILENAME to TIMESTAMP.
3435Set both access and modification times. 3434If optional FLAG is `nofollow', do not follow FILENAME if it is a
3436Return t on success, else nil. 3435symbolic link. Set both access and modification times. Return t on
3437Use the current time if TIMESTAMP is nil. TIMESTAMP is in the format of 3436success, else nil. Use the current time if TIMESTAMP is nil.
3438`current-time'. */) 3437TIMESTAMP is in the format of `current-time'. */)
3439 (Lisp_Object filename, Lisp_Object timestamp) 3438 (Lisp_Object filename, Lisp_Object timestamp, Lisp_Object flag)
3440{ 3439{
3441 Lisp_Object absname, encoded_absname; 3440 int nofollow = symlink_nofollow_flag (flag);
3442 Lisp_Object handler;
3443 struct timespec t = lisp_time_argument (timestamp);
3444 3441
3445 absname = Fexpand_file_name (filename, BVAR (current_buffer, directory)); 3442 struct timespec ts[2];
3443 if (!NILP (timestamp))
3444 ts[0] = ts[1] = lisp_time_argument (timestamp);
3445 else
3446 ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW;
3446 3447
3447 /* If the file name has special constructs in it, 3448 /* If the file name has special constructs in it,
3448 call the corresponding file name handler. */ 3449 call the corresponding file name handler. */
3449 handler = Ffind_file_name_handler (absname, Qset_file_times); 3450 Lisp_Object
3451 absname = Fexpand_file_name (filename, BVAR (current_buffer, directory)),
3452 handler = Ffind_file_name_handler (absname, Qset_file_times);
3450 if (!NILP (handler)) 3453 if (!NILP (handler))
3451 return call3 (handler, Qset_file_times, absname, timestamp); 3454 return call4 (handler, Qset_file_times, absname, timestamp, flag);
3452 3455
3453 encoded_absname = ENCODE_FILE (absname); 3456 Lisp_Object encoded_absname = ENCODE_FILE (absname);
3454 3457
3455 { 3458 if (utimensat (AT_FDCWD, SSDATA (encoded_absname), ts, nofollow) != 0)
3456 if (set_file_times (-1, SSDATA (encoded_absname), t, t) != 0) 3459 {
3457 {
3458#ifdef MSDOS 3460#ifdef MSDOS
3459 /* Setting times on a directory always fails. */ 3461 /* Setting times on a directory always fails. */
3460 if (file_directory_p (encoded_absname)) 3462 if (file_directory_p (encoded_absname))
3461 return Qnil; 3463 return Qnil;
3462#endif 3464#endif
3463 report_file_error ("Setting file times", absname); 3465 report_file_error ("Setting file times", absname);
3464 } 3466 }
3465 }
3466 3467
3467 return Qt; 3468 return Qt;
3468} 3469}
diff --git a/src/font.c b/src/font.c
index bb39aef92d5..2a456300619 100644
--- a/src/font.c
+++ b/src/font.c
@@ -4416,10 +4416,8 @@ DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
4416 4416
4417 4417
4418void 4418void
4419font_fill_lglyph_metrics (Lisp_Object glyph, Lisp_Object font_object) 4419font_fill_lglyph_metrics (Lisp_Object glyph, struct font *font, unsigned int code)
4420{ 4420{
4421 struct font *font = XFONT_OBJECT (font_object);
4422 unsigned code = font->driver->encode_char (font, LGLYPH_CHAR (glyph));
4423 struct font_metrics metrics; 4421 struct font_metrics metrics;
4424 4422
4425 LGLYPH_SET_CODE (glyph, code); 4423 LGLYPH_SET_CODE (glyph, code);
diff --git a/src/font.h b/src/font.h
index 0561e3c83f5..8614e7fa10a 100644
--- a/src/font.h
+++ b/src/font.h
@@ -886,7 +886,7 @@ extern Lisp_Object font_update_drivers (struct frame *f, Lisp_Object list);
886extern Lisp_Object font_range (ptrdiff_t, ptrdiff_t, ptrdiff_t *, 886extern Lisp_Object font_range (ptrdiff_t, ptrdiff_t, ptrdiff_t *,
887 struct window *, struct face *, 887 struct window *, struct face *,
888 Lisp_Object); 888 Lisp_Object);
889extern void font_fill_lglyph_metrics (Lisp_Object, Lisp_Object); 889extern void font_fill_lglyph_metrics (Lisp_Object, struct font *, unsigned int);
890 890
891extern Lisp_Object font_put_extra (Lisp_Object font, Lisp_Object prop, 891extern Lisp_Object font_put_extra (Lisp_Object font, Lisp_Object prop,
892 Lisp_Object val); 892 Lisp_Object val);
diff --git a/src/fontset.c b/src/fontset.c
index bca9452418e..c2bb8b21f26 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -367,8 +367,14 @@ fontset_add (Lisp_Object fontset, Lisp_Object range, Lisp_Object elt, Lisp_Objec
367static int 367static int
368fontset_compare_rfontdef (const void *val1, const void *val2) 368fontset_compare_rfontdef (const void *val1, const void *val2)
369{ 369{
370 return (RFONT_DEF_SCORE (*(Lisp_Object *) val1) 370 Lisp_Object v1 = *(Lisp_Object *) val1, v2 = *(Lisp_Object *) val2;
371 - RFONT_DEF_SCORE (*(Lisp_Object *) val2)); 371 if (NILP (v1) && NILP (v2))
372 return 0;
373 else if (NILP (v1))
374 return INT_MIN;
375 else if (NILP (v2))
376 return INT_MAX;
377 return (RFONT_DEF_SCORE (v1) - RFONT_DEF_SCORE (v2));
372} 378}
373 379
374/* Update a cons cell which has this form: 380/* Update a cons cell which has this form:
@@ -400,6 +406,8 @@ reorder_font_vector (Lisp_Object font_group, struct font *font)
400 for (i = 0; i < size; i++) 406 for (i = 0; i < size; i++)
401 { 407 {
402 Lisp_Object rfont_def = AREF (vec, i); 408 Lisp_Object rfont_def = AREF (vec, i);
409 if (NILP (rfont_def))
410 continue;
403 Lisp_Object font_def = RFONT_DEF_FONT_DEF (rfont_def); 411 Lisp_Object font_def = RFONT_DEF_FONT_DEF (rfont_def);
404 Lisp_Object font_spec = FONT_DEF_SPEC (font_def); 412 Lisp_Object font_spec = FONT_DEF_SPEC (font_def);
405 int score = RFONT_DEF_SCORE (rfont_def) & 0xFF; 413 int score = RFONT_DEF_SCORE (rfont_def) & 0xFF;
diff --git a/src/fringe.c b/src/fringe.c
index 97aad843c2e..2a46e3c34f2 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -1500,7 +1500,8 @@ DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap, Sdefine_fringe_bitmap,
1500BITMAP is a symbol identifying the new fringe bitmap. 1500BITMAP is a symbol identifying the new fringe bitmap.
1501BITS is either a string or a vector of integers. 1501BITS is either a string or a vector of integers.
1502HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS. 1502HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.
1503WIDTH must be an integer between 1 and 16, or nil which defaults to 8. 1503WIDTH must be an integer from 1 to 16, or nil which defaults to 8. An
1504error is signaled if WIDTH is outside this range.
1504Optional fifth arg ALIGN may be one of `top', `center', or `bottom', 1505Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
1505indicating the positioning of the bitmap relative to the rows where it 1506indicating the positioning of the bitmap relative to the rows where it
1506is used; the default is to center the bitmap. Fifth arg may also be a 1507is used; the default is to center the bitmap. Fifth arg may also be a
@@ -1535,7 +1536,9 @@ If BITMAP already exists, the existing definition is replaced. */)
1535 else 1536 else
1536 { 1537 {
1537 CHECK_FIXNUM (width); 1538 CHECK_FIXNUM (width);
1538 fb.width = max (0, min (XFIXNUM (width), 255)); 1539 fb.width = max (1, min (XFIXNUM (width), 16));
1540 if (fb.width != XFIXNUM (width))
1541 args_out_of_range (width, build_string ("Width must be from 1 to 16"));
1539 } 1542 }
1540 1543
1541 fb.period = 0; 1544 fb.period = 0;
diff --git a/src/gnutls.c b/src/gnutls.c
index 31fcd37c0a6..70176c41cdd 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -2834,16 +2834,21 @@ Any GnuTLS extension with ID up to 100
2834void 2834void
2835syms_of_gnutls (void) 2835syms_of_gnutls (void)
2836{ 2836{
2837 DEFSYM (Qlibgnutls_version, "libgnutls-version"); 2837 DEFVAR_LISP ("libgnutls-version", Vlibgnutls_version,
2838 Fset (Qlibgnutls_version, 2838 doc: /* The version of libgnutls that Emacs was compiled with.
2839The version number is encoded as an integer with the major version in
2840the ten thousands place, minor version in the hundreds, and patch
2841level in the ones. For builds without libgnutls, the value is -1. */);
2842 Vlibgnutls_version = make_fixnum
2839#ifdef HAVE_GNUTLS 2843#ifdef HAVE_GNUTLS
2840 make_fixnum (GNUTLS_VERSION_MAJOR * 10000 2844 (GNUTLS_VERSION_MAJOR * 10000
2841 + GNUTLS_VERSION_MINOR * 100 2845 + GNUTLS_VERSION_MINOR * 100
2842 + GNUTLS_VERSION_PATCH) 2846 + GNUTLS_VERSION_PATCH)
2843#else 2847#else
2844 make_fixnum (-1) 2848 (-1)
2845#endif 2849#endif
2846 ); 2850 ;
2851
2847#ifdef HAVE_GNUTLS 2852#ifdef HAVE_GNUTLS
2848 gnutls_global_initialized = 0; 2853 gnutls_global_initialized = 0;
2849 PDUMPER_IGNORE (gnutls_global_initialized); 2854 PDUMPER_IGNORE (gnutls_global_initialized);
diff --git a/src/intervals.c b/src/intervals.c
index a66594ceea2..594d8924ebc 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -298,7 +298,7 @@ rotate_right (INTERVAL A)
298 set_interval_parent (c, A); 298 set_interval_parent (c, A);
299 299
300 /* A's total length is decreased by the length of B and its left child. */ 300 /* A's total length is decreased by the length of B and its left child. */
301 A->total_length -= B->total_length - TOTAL_LENGTH (c); 301 A->total_length -= TOTAL_LENGTH (B) - TOTAL_LENGTH0 (c);
302 eassert (TOTAL_LENGTH (A) > 0); 302 eassert (TOTAL_LENGTH (A) > 0);
303 eassert (LENGTH (A) > 0); 303 eassert (LENGTH (A) > 0);
304 304
@@ -349,7 +349,7 @@ rotate_left (INTERVAL A)
349 set_interval_parent (c, A); 349 set_interval_parent (c, A);
350 350
351 /* A's total length is decreased by the length of B and its right child. */ 351 /* A's total length is decreased by the length of B and its right child. */
352 A->total_length -= B->total_length - TOTAL_LENGTH (c); 352 A->total_length -= TOTAL_LENGTH (B) - TOTAL_LENGTH0 (c);
353 eassert (TOTAL_LENGTH (A) > 0); 353 eassert (TOTAL_LENGTH (A) > 0);
354 eassert (LENGTH (A) > 0); 354 eassert (LENGTH (A) > 0);
355 355
@@ -723,13 +723,13 @@ previous_interval (register INTERVAL interval)
723 i->position - LEFT_TOTAL_LENGTH (i) \ 723 i->position - LEFT_TOTAL_LENGTH (i) \
724 - LENGTH (INTERVAL_PARENT (i)) 724 - LENGTH (INTERVAL_PARENT (i))
725 725
726/* Find the interval containing POS, given some non-NULL INTERVAL in 726/* Find the interval containing POS, given some interval I in
727 the same tree. Note that we update interval->position in each 727 the same tree. Note that we update interval->position in each
728 interval we traverse, assuming it is already correctly set for the 728 interval we traverse, assuming it is already correctly set for the
729 argument I. We don't assume that any other interval already has a 729 argument I. We don't assume that any other interval already has a
730 correctly set ->position. */ 730 correctly set ->position. */
731INTERVAL 731INTERVAL
732update_interval (register INTERVAL i, ptrdiff_t pos) 732update_interval (INTERVAL i, ptrdiff_t pos)
733{ 733{
734 if (!i) 734 if (!i)
735 return NULL; 735 return NULL;
@@ -739,7 +739,7 @@ update_interval (register INTERVAL i, ptrdiff_t pos)
739 if (pos < i->position) 739 if (pos < i->position)
740 { 740 {
741 /* Move left. */ 741 /* Move left. */
742 if (pos >= i->position - TOTAL_LENGTH (i->left)) 742 if (pos >= i->position - LEFT_TOTAL_LENGTH (i))
743 { 743 {
744 i->left->position = i->position - TOTAL_LENGTH (i->left) 744 i->left->position = i->position - TOTAL_LENGTH (i->left)
745 + LEFT_TOTAL_LENGTH (i->left); 745 + LEFT_TOTAL_LENGTH (i->left);
@@ -757,7 +757,7 @@ update_interval (register INTERVAL i, ptrdiff_t pos)
757 else if (pos >= INTERVAL_LAST_POS (i)) 757 else if (pos >= INTERVAL_LAST_POS (i))
758 { 758 {
759 /* Move right. */ 759 /* Move right. */
760 if (pos < INTERVAL_LAST_POS (i) + TOTAL_LENGTH (i->right)) 760 if (pos < INTERVAL_LAST_POS (i) + RIGHT_TOTAL_LENGTH (i))
761 { 761 {
762 i->right->position = INTERVAL_LAST_POS (i) 762 i->right->position = INTERVAL_LAST_POS (i)
763 + LEFT_TOTAL_LENGTH (i->right); 763 + LEFT_TOTAL_LENGTH (i->right);
diff --git a/src/intervals.h b/src/intervals.h
index a93b10e9fff..9a7ba910a10 100644
--- a/src/intervals.h
+++ b/src/intervals.h
@@ -96,24 +96,27 @@ struct interval
96/* True if this interval has both left and right children. */ 96/* True if this interval has both left and right children. */
97#define BOTH_KIDS_P(i) ((i)->left != NULL && (i)->right != NULL) 97#define BOTH_KIDS_P(i) ((i)->left != NULL && (i)->right != NULL)
98 98
99/* The total size of all text represented by this interval and all its 99/* The total size of all text represented by the nonnull interval I
100 children in the tree. This is zero if the interval is null. */ 100 and all its children in the tree. */
101#define TOTAL_LENGTH(i) ((i) == NULL ? 0 : (i)->total_length) 101#define TOTAL_LENGTH(i) ((i)->total_length)
102
103/* Likewise, but also defined to be zero if I is null. */
104#define TOTAL_LENGTH0(i) ((i) ? TOTAL_LENGTH (i) : 0)
102 105
103/* The size of text represented by this interval alone. */ 106/* The size of text represented by this interval alone. */
104#define LENGTH(i) ((i)->total_length \ 107#define LENGTH(i) (TOTAL_LENGTH (i) \
105 - TOTAL_LENGTH ((i)->right) \ 108 - RIGHT_TOTAL_LENGTH (i) \
106 - TOTAL_LENGTH ((i)->left)) 109 - LEFT_TOTAL_LENGTH (i))
107 110
108/* The position of the character just past the end of I. Note that 111/* The position of the character just past the end of I. Note that
109 the position cache i->position must be valid for this to work. */ 112 the position cache i->position must be valid for this to work. */
110#define INTERVAL_LAST_POS(i) ((i)->position + LENGTH (i)) 113#define INTERVAL_LAST_POS(i) ((i)->position + LENGTH (i))
111 114
112/* The total size of the left subtree of this interval. */ 115/* The total size of the left subtree of this interval. */
113#define LEFT_TOTAL_LENGTH(i) ((i)->left ? (i)->left->total_length : 0) 116#define LEFT_TOTAL_LENGTH(i) TOTAL_LENGTH0 ((i)->left)
114 117
115/* The total size of the right subtree of this interval. */ 118/* The total size of the right subtree of this interval. */
116#define RIGHT_TOTAL_LENGTH(i) ((i)->right ? (i)->right->total_length : 0) 119#define RIGHT_TOTAL_LENGTH(i) TOTAL_LENGTH0 ((i)->right)
117 120
118/* These macros are for dealing with the interval properties. */ 121/* These macros are for dealing with the interval properties. */
119 122
@@ -234,7 +237,7 @@ set_interval_plist (INTERVAL i, Lisp_Object plist)
234 237
235/* Declared in alloc.c. */ 238/* Declared in alloc.c. */
236 239
237extern INTERVAL make_interval (void); 240extern INTERVAL make_interval (void) ATTRIBUTE_RETURNS_NONNULL;
238 241
239/* Declared in intervals.c. */ 242/* Declared in intervals.c. */
240 243
@@ -246,7 +249,8 @@ extern void traverse_intervals (INTERVAL, ptrdiff_t,
246 Lisp_Object); 249 Lisp_Object);
247extern void traverse_intervals_noorder (INTERVAL, 250extern void traverse_intervals_noorder (INTERVAL,
248 void (*) (INTERVAL, void *), void *); 251 void (*) (INTERVAL, void *), void *);
249extern INTERVAL split_interval_right (INTERVAL, ptrdiff_t); 252extern INTERVAL split_interval_right (INTERVAL, ptrdiff_t)
253 ATTRIBUTE_RETURNS_NONNULL;
250extern INTERVAL split_interval_left (INTERVAL, ptrdiff_t); 254extern INTERVAL split_interval_left (INTERVAL, ptrdiff_t);
251extern INTERVAL find_interval (INTERVAL, ptrdiff_t); 255extern INTERVAL find_interval (INTERVAL, ptrdiff_t);
252extern INTERVAL next_interval (INTERVAL); 256extern INTERVAL next_interval (INTERVAL);
diff --git a/src/nsterm.m b/src/nsterm.m
index 8e256149220..851a5617d7b 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1141,6 +1141,7 @@ ns_update_end (struct frame *f)
1141 1141
1142#ifdef NS_DRAW_TO_BUFFER 1142#ifdef NS_DRAW_TO_BUFFER
1143 [NSGraphicsContext setCurrentContext:nil]; 1143 [NSGraphicsContext setCurrentContext:nil];
1144 [view setNeedsDisplay:YES];
1144#else 1145#else
1145 block_input (); 1146 block_input ();
1146 1147
@@ -1194,12 +1195,6 @@ ns_focus (struct frame *f, NSRect *r, int n)
1194 /* clipping */ 1195 /* clipping */
1195 if (r) 1196 if (r)
1196 { 1197 {
1197#ifdef NS_IMPL_COCOA
1198 int i;
1199 for (i = 0 ; i < n ; i++)
1200 [view setNeedsDisplayInRect:r[i]];
1201#endif
1202
1203 [[NSGraphicsContext currentContext] saveGraphicsState]; 1198 [[NSGraphicsContext currentContext] saveGraphicsState];
1204 if (n == 2) 1199 if (n == 2)
1205 NSRectClipList (r, 2); 1200 NSRectClipList (r, 2);
@@ -1224,7 +1219,9 @@ ns_unfocus (struct frame *f)
1224 gsaved = NO; 1219 gsaved = NO;
1225 } 1220 }
1226 1221
1227#ifdef NS_IMPL_GNUSTEP 1222#ifdef NS_DRAW_TO_BUFFER
1223 [FRAME_NS_VIEW (f) setNeedsDisplay:YES];
1224#else
1228 if (f != ns_updating_frame) 1225 if (f != ns_updating_frame)
1229 { 1226 {
1230 if (focus_view != NULL) 1227 if (focus_view != NULL)
diff --git a/src/pdumper.c b/src/pdumper.c
index 4ecdea14538..2e2220a9b29 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -3692,14 +3692,12 @@ dump_unwind_cleanup (void *data)
3692 Vprocess_environment = ctx->old_process_environment; 3692 Vprocess_environment = ctx->old_process_environment;
3693} 3693}
3694 3694
3695/* Return DUMP_OFFSET, making sure it is within the heap. */ 3695/* Check that DUMP_OFFSET is within the heap. */
3696static dump_off 3696static void
3697dump_check_dump_off (struct dump_context *ctx, dump_off dump_offset) 3697dump_check_dump_off (struct dump_context *ctx, dump_off dump_offset)
3698{ 3698{
3699 eassert (dump_offset > 0); 3699 eassert (dump_offset > 0);
3700 if (ctx) 3700 eassert (!ctx || dump_offset < ctx->end_heap);
3701 eassert (dump_offset < ctx->end_heap);
3702 return dump_offset;
3703} 3701}
3704 3702
3705static void 3703static void
@@ -3822,6 +3820,7 @@ decode_emacs_reloc (struct dump_context *ctx, Lisp_Object lreloc)
3822 } 3820 }
3823 else 3821 else
3824 { 3822 {
3823 eassume (ctx); /* Pacify GCC 9.2.1 -O3 -Wnull-dereference. */
3825 eassert (!dump_object_emacs_ptr (target_value)); 3824 eassert (!dump_object_emacs_ptr (target_value));
3826 reloc.u.dump_offset = dump_recall_object (ctx, target_value); 3825 reloc.u.dump_offset = dump_recall_object (ctx, target_value);
3827 if (reloc.u.dump_offset <= 0) 3826 if (reloc.u.dump_offset <= 0)
diff --git a/src/process.c b/src/process.c
index 91d426103d8..e4e5e57aeee 100644
--- a/src/process.c
+++ b/src/process.c
@@ -8277,19 +8277,6 @@ init_process_emacs (int sockfd)
8277 memset (datagram_address, 0, sizeof datagram_address); 8277 memset (datagram_address, 0, sizeof datagram_address);
8278#endif 8278#endif
8279 8279
8280#if defined (DARWIN_OS)
8281 /* PTYs are broken on Darwin < 6, but are sometimes useful for interactive
8282 processes. As such, we only change the default value. */
8283 if (initialized)
8284 {
8285 char const *release = (STRINGP (Voperating_system_release)
8286 ? SSDATA (Voperating_system_release)
8287 : 0);
8288 if (!release || !release[0] || (release[0] < '7' && release[1] == '.')) {
8289 Vprocess_connection_type = Qnil;
8290 }
8291 }
8292#endif
8293#endif /* subprocesses */ 8280#endif /* subprocesses */
8294 kbd_is_on_hold = 0; 8281 kbd_is_on_hold = 0;
8295} 8282}
diff --git a/src/sysdep.c b/src/sysdep.c
index e8e8bbfb502..149d80f19ec 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -2752,21 +2752,6 @@ emacs_perror (char const *message)
2752 errno = err; 2752 errno = err;
2753} 2753}
2754 2754
2755/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2756 ATIME and MTIME, respectively.
2757 FD must be either negative -- in which case it is ignored --
2758 or a file descriptor that is open on FILE.
2759 If FD is nonnegative, then FILE can be NULL. */
2760int
2761set_file_times (int fd, const char *filename,
2762 struct timespec atime, struct timespec mtime)
2763{
2764 struct timespec timespec[2];
2765 timespec[0] = atime;
2766 timespec[1] = mtime;
2767 return fdutimens (fd, filename, timespec);
2768}
2769
2770/* Rename directory SRCFD's entry SRC to directory DSTFD's entry DST. 2755/* Rename directory SRCFD's entry SRC to directory DSTFD's entry DST.
2771 This is like renameat except that it fails if DST already exists, 2756 This is like renameat except that it fails if DST already exists,
2772 or if this operation is not supported atomically. Return 0 if 2757 or if this operation is not supported atomically. Return 0 if
diff --git a/src/systime.h b/src/systime.h
index 00ca4a1c58d..b59a3d1c690 100644
--- a/src/systime.h
+++ b/src/systime.h
@@ -67,9 +67,6 @@ timespec_valid_p (struct timespec t)
67 return t.tv_nsec >= 0; 67 return t.tv_nsec >= 0;
68} 68}
69 69
70/* defined in sysdep.c */
71extern int set_file_times (int, const char *, struct timespec, struct timespec);
72
73/* defined in keyboard.c */ 70/* defined in keyboard.c */
74extern void set_waiting_for_input (struct timespec *); 71extern void set_waiting_for_input (struct timespec *);
75 72
diff --git a/src/timefns.c b/src/timefns.c
index 0aa8775f9ff..404ce4973b7 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -421,6 +421,9 @@ decode_float_time (double t, struct lisp_time *result)
421 else if (flt_radix_power_size <= scale) 421 else if (flt_radix_power_size <= scale)
422 return isnan (t) ? EDOM : EOVERFLOW; 422 return isnan (t) ? EDOM : EOVERFLOW;
423 423
424 /* Compute TICKS, HZ such that TICKS / HZ exactly equals T, where HZ is
425 T's frequency or 1, whichever is greater. Here, “frequency” means
426 1/precision. Cache HZ values in flt_radix_power. */
424 double scaled = scalbn (t, scale); 427 double scaled = scalbn (t, scale);
425 eassert (trunc (scaled) == scaled); 428 eassert (trunc (scaled) == scaled);
426 ticks = double_to_integer (scaled); 429 ticks = double_to_integer (scaled);
@@ -442,6 +445,7 @@ decode_float_time (double t, struct lisp_time *result)
442static Lisp_Object 445static Lisp_Object
443ticks_hz_list4 (Lisp_Object ticks, Lisp_Object hz) 446ticks_hz_list4 (Lisp_Object ticks, Lisp_Object hz)
444{ 447{
448 /* mpz[0] = floor ((ticks * trillion) / hz). */
445 mpz_t const *zticks = bignum_integer (&mpz[0], ticks); 449 mpz_t const *zticks = bignum_integer (&mpz[0], ticks);
446#if FASTER_TIMEFNS && TRILLION <= ULONG_MAX 450#if FASTER_TIMEFNS && TRILLION <= ULONG_MAX
447 mpz_mul_ui (mpz[0], *zticks, TRILLION); 451 mpz_mul_ui (mpz[0], *zticks, TRILLION);
@@ -449,6 +453,9 @@ ticks_hz_list4 (Lisp_Object ticks, Lisp_Object hz)
449 mpz_mul (mpz[0], *zticks, ztrillion); 453 mpz_mul (mpz[0], *zticks, ztrillion);
450#endif 454#endif
451 mpz_fdiv_q (mpz[0], mpz[0], *bignum_integer (&mpz[1], hz)); 455 mpz_fdiv_q (mpz[0], mpz[0], *bignum_integer (&mpz[1], hz));
456
457 /* mpz[0] = floor (mpz[0] / trillion), with US = the high six digits of the
458 12-digit remainder, and PS = the low six digits. */
452#if FASTER_TIMEFNS && TRILLION <= ULONG_MAX 459#if FASTER_TIMEFNS && TRILLION <= ULONG_MAX
453 unsigned long int fullps = mpz_fdiv_q_ui (mpz[0], mpz[0], TRILLION); 460 unsigned long int fullps = mpz_fdiv_q_ui (mpz[0], mpz[0], TRILLION);
454 int us = fullps / 1000000; 461 int us = fullps / 1000000;
@@ -458,11 +465,14 @@ ticks_hz_list4 (Lisp_Object ticks, Lisp_Object hz)
458 int ps = mpz_fdiv_q_ui (mpz[1], mpz[1], 1000000); 465 int ps = mpz_fdiv_q_ui (mpz[1], mpz[1], 1000000);
459 int us = mpz_get_ui (mpz[1]); 466 int us = mpz_get_ui (mpz[1]);
460#endif 467#endif
468
469 /* mpz[0] = floor (mpz[0] / 1 << LO_TIME_BITS), with lo = remainder. */
461 unsigned long ulo = mpz_get_ui (mpz[0]); 470 unsigned long ulo = mpz_get_ui (mpz[0]);
462 if (mpz_sgn (mpz[0]) < 0) 471 if (mpz_sgn (mpz[0]) < 0)
463 ulo = -ulo; 472 ulo = -ulo;
464 int lo = ulo & ((1 << LO_TIME_BITS) - 1); 473 int lo = ulo & ((1 << LO_TIME_BITS) - 1);
465 mpz_fdiv_q_2exp (mpz[0], mpz[0], LO_TIME_BITS); 474 mpz_fdiv_q_2exp (mpz[0], mpz[0], LO_TIME_BITS);
475
466 return list4 (make_integer_mpz (), make_fixnum (lo), 476 return list4 (make_integer_mpz (), make_fixnum (lo),
467 make_fixnum (us), make_fixnum (ps)); 477 make_fixnum (us), make_fixnum (ps));
468} 478}
@@ -482,6 +492,7 @@ mpz_set_time (mpz_t rop, time_t t)
482static void 492static void
483timespec_mpz (struct timespec t) 493timespec_mpz (struct timespec t)
484{ 494{
495 /* mpz[0] = sec * TIMESPEC_HZ + nsec. */
485 mpz_set_ui (mpz[0], t.tv_nsec); 496 mpz_set_ui (mpz[0], t.tv_nsec);
486 mpz_set_time (mpz[1], t.tv_sec); 497 mpz_set_time (mpz[1], t.tv_sec);
487 mpz_addmul_ui (mpz[0], mpz[1], TIMESPEC_HZ); 498 mpz_addmul_ui (mpz[0], mpz[1], TIMESPEC_HZ);
@@ -491,11 +502,14 @@ timespec_mpz (struct timespec t)
491static Lisp_Object 502static Lisp_Object
492timespec_ticks (struct timespec t) 503timespec_ticks (struct timespec t)
493{ 504{
505 /* For speed, use intmax_t arithmetic if it will do. */
494 intmax_t accum; 506 intmax_t accum;
495 if (FASTER_TIMEFNS 507 if (FASTER_TIMEFNS
496 && !INT_MULTIPLY_WRAPV (t.tv_sec, TIMESPEC_HZ, &accum) 508 && !INT_MULTIPLY_WRAPV (t.tv_sec, TIMESPEC_HZ, &accum)
497 && !INT_ADD_WRAPV (t.tv_nsec, accum, &accum)) 509 && !INT_ADD_WRAPV (t.tv_nsec, accum, &accum))
498 return make_int (accum); 510 return make_int (accum);
511
512 /* Fall back on bignum arithmetic. */
499 timespec_mpz (t); 513 timespec_mpz (t);
500 return make_integer_mpz (); 514 return make_integer_mpz ();
501} 515}
@@ -505,12 +519,19 @@ timespec_ticks (struct timespec t)
505static Lisp_Object 519static Lisp_Object
506lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz) 520lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz)
507{ 521{
522 /* The idea is to return the floor of ((T.ticks * HZ) / T.hz). */
523
524 /* For speed, just return T.ticks if T.hz == HZ. */
508 if (FASTER_TIMEFNS && EQ (t.hz, hz)) 525 if (FASTER_TIMEFNS && EQ (t.hz, hz))
509 return t.ticks; 526 return t.ticks;
527
528 /* Check HZ for validity. */
510 if (FIXNUMP (hz)) 529 if (FIXNUMP (hz))
511 { 530 {
512 if (XFIXNUM (hz) <= 0) 531 if (XFIXNUM (hz) <= 0)
513 invalid_hz (hz); 532 invalid_hz (hz);
533
534 /* For speed, use intmax_t arithmetic if it will do. */
514 intmax_t ticks; 535 intmax_t ticks;
515 if (FASTER_TIMEFNS && FIXNUMP (t.ticks) && FIXNUMP (t.hz) 536 if (FASTER_TIMEFNS && FIXNUMP (t.ticks) && FIXNUMP (t.hz)
516 && !INT_MULTIPLY_WRAPV (XFIXNUM (t.ticks), XFIXNUM (hz), &ticks)) 537 && !INT_MULTIPLY_WRAPV (XFIXNUM (t.ticks), XFIXNUM (hz), &ticks))
@@ -520,6 +541,7 @@ lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz)
520 else if (! (BIGNUMP (hz) && 0 < mpz_sgn (*xbignum_val (hz)))) 541 else if (! (BIGNUMP (hz) && 0 < mpz_sgn (*xbignum_val (hz))))
521 invalid_hz (hz); 542 invalid_hz (hz);
522 543
544 /* Fall back on bignum arithmetic. */
523 mpz_mul (mpz[0], 545 mpz_mul (mpz[0],
524 *bignum_integer (&mpz[0], t.ticks), 546 *bignum_integer (&mpz[0], t.ticks),
525 *bignum_integer (&mpz[1], hz)); 547 *bignum_integer (&mpz[1], hz));
@@ -531,11 +553,17 @@ lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz)
531static Lisp_Object 553static Lisp_Object
532lisp_time_seconds (struct lisp_time t) 554lisp_time_seconds (struct lisp_time t)
533{ 555{
556 /* The idea is to return the floor of T.ticks / T.hz. */
557
534 if (!FASTER_TIMEFNS) 558 if (!FASTER_TIMEFNS)
535 return lisp_time_hz_ticks (t, make_fixnum (1)); 559 return lisp_time_hz_ticks (t, make_fixnum (1));
560
561 /* For speed, use EMACS_INT arithmetic if it will do. */
536 if (FIXNUMP (t.ticks) && FIXNUMP (t.hz)) 562 if (FIXNUMP (t.ticks) && FIXNUMP (t.hz))
537 return make_fixnum (XFIXNUM (t.ticks) / XFIXNUM (t.hz) 563 return make_fixnum (XFIXNUM (t.ticks) / XFIXNUM (t.hz)
538 - (XFIXNUM (t.ticks) % XFIXNUM (t.hz) < 0)); 564 - (XFIXNUM (t.ticks) % XFIXNUM (t.hz) < 0));
565
566 /* For speed, inline what lisp_time_hz_ticks would do. */
539 mpz_fdiv_q (mpz[0], 567 mpz_fdiv_q (mpz[0],
540 *bignum_integer (&mpz[0], t.ticks), 568 *bignum_integer (&mpz[0], t.ticks),
541 *bignum_integer (&mpz[1], t.hz)); 569 *bignum_integer (&mpz[1], t.hz));
@@ -577,6 +605,7 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
577 && intmax_numerator % intmax_denominator == 0) 605 && intmax_numerator % intmax_denominator == 0)
578 return intmax_numerator / intmax_denominator; 606 return intmax_numerator / intmax_denominator;
579 607
608 /* Compute number of base-FLT_RADIX digits in numerator and denominator. */
580 mpz_t const *n = bignum_integer (&mpz[0], numerator); 609 mpz_t const *n = bignum_integer (&mpz[0], numerator);
581 mpz_t const *d = bignum_integer (&mpz[1], denominator); 610 mpz_t const *d = bignum_integer (&mpz[1], denominator);
582 ptrdiff_t ndig = mpz_sizeinbase (*n, FLT_RADIX); 611 ptrdiff_t ndig = mpz_sizeinbase (*n, FLT_RADIX);
@@ -588,7 +617,8 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
588 /* Scale with SCALE when doing integer division. That is, compute 617 /* Scale with SCALE when doing integer division. That is, compute
589 (N * FLT_RADIX**SCALE) / D [or, if SCALE is negative, N / (D * 618 (N * FLT_RADIX**SCALE) / D [or, if SCALE is negative, N / (D *
590 FLT_RADIX**-SCALE)] as a bignum, convert the bignum to double, 619 FLT_RADIX**-SCALE)] as a bignum, convert the bignum to double,
591 then divide the double by FLT_RADIX**SCALE. */ 620 then divide the double by FLT_RADIX**SCALE. First scale N
621 (or scale D, if SCALE is negative) ... */
592 ptrdiff_t scale = ddig - ndig + DBL_MANT_DIG; 622 ptrdiff_t scale = ddig - ndig + DBL_MANT_DIG;
593 if (scale < 0) 623 if (scale < 0)
594 { 624 {
@@ -603,12 +633,12 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
603 mpz_mul_2exp (mpz[0], *n, scale * LOG2_FLT_RADIX); 633 mpz_mul_2exp (mpz[0], *n, scale * LOG2_FLT_RADIX);
604 n = &mpz[0]; 634 n = &mpz[0];
605 } 635 }
606 636 /* ... and then divide, with quotient Q and remainder R. */
607 mpz_t *q = &mpz[2]; 637 mpz_t *q = &mpz[2];
608 mpz_t *r = &mpz[3]; 638 mpz_t *r = &mpz[3];
609 mpz_tdiv_qr (*q, *r, *n, *d); 639 mpz_tdiv_qr (*q, *r, *n, *d);
610 640
611 /* The amount to add to the absolute value of *Q so that truncating 641 /* The amount to add to the absolute value of Q so that truncating
612 it to double will round correctly. */ 642 it to double will round correctly. */
613 int incr; 643 int incr;
614 644
@@ -647,6 +677,7 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
647 if (!FASTER_TIMEFNS || incr != 0) 677 if (!FASTER_TIMEFNS || incr != 0)
648 (mpz_sgn (*n) < 0 ? mpz_sub_ui : mpz_add_ui) (*q, *q, incr); 678 (mpz_sgn (*n) < 0 ? mpz_sub_ui : mpz_add_ui) (*q, *q, incr);
649 679
680 /* Rescale the integer Q back to double. This step does not round. */
650 return scalbn (mpz_get_d (*q), -scale); 681 return scalbn (mpz_get_d (*q), -scale);
651} 682}
652 683
@@ -895,6 +926,10 @@ lisp_to_timespec (struct lisp_time t)
895 mpz_t *q = &mpz[0]; 926 mpz_t *q = &mpz[0];
896 mpz_t const *qt = q; 927 mpz_t const *qt = q;
897 928
929 /* Floor-divide (T.ticks * TIMESPEC_HZ) by T.hz,
930 yielding quotient Q (tv_sec) and remainder NS (tv_nsec).
931 Return an invalid timespec if Q does not fit in time_t.
932 For speed, prefer fixnum arithmetic if it works. */
898 if (FASTER_TIMEFNS && EQ (t.hz, timespec_hz)) 933 if (FASTER_TIMEFNS && EQ (t.hz, timespec_hz))
899 { 934 {
900 if (FIXNUMP (t.ticks)) 935 if (FIXNUMP (t.ticks))
@@ -938,8 +973,8 @@ lisp_to_timespec (struct lisp_time t)
938 ns = mpz_fdiv_q_ui (*q, *q, TIMESPEC_HZ); 973 ns = mpz_fdiv_q_ui (*q, *q, TIMESPEC_HZ);
939 } 974 }
940 975
941 /* With some versions of MinGW, tv_sec is a 64-bit type, whereas 976 /* Check that Q fits in time_t, not merely in T.tv_sec. With some versions
942 time_t is a 32-bit type. */ 977 of MinGW, tv_sec is a 64-bit type, whereas time_t is a 32-bit type. */
943 time_t sec; 978 time_t sec;
944 if (mpz_time (*qt, &sec)) 979 if (mpz_time (*qt, &sec))
945 { 980 {
@@ -1019,10 +1054,14 @@ lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1019 { 1054 {
1020 if (EQ (b, make_fixnum (0))) 1055 if (EQ (b, make_fixnum (0)))
1021 return a; 1056 return a;
1057
1058 /* For speed, use EMACS_INT arithmetic if it will do. */
1022 if (FIXNUMP (a)) 1059 if (FIXNUMP (a))
1023 return make_int (subtract 1060 return make_int (subtract
1024 ? XFIXNUM (a) - XFIXNUM (b) 1061 ? XFIXNUM (a) - XFIXNUM (b)
1025 : XFIXNUM (a) + XFIXNUM (b)); 1062 : XFIXNUM (a) + XFIXNUM (b));
1063
1064 /* For speed, use mpz_add_ui/mpz_sub_ui if it will do. */
1026 if (eabs (XFIXNUM (b)) <= ULONG_MAX) 1065 if (eabs (XFIXNUM (b)) <= ULONG_MAX)
1027 { 1066 {
1028 ((XFIXNUM (b) < 0) == subtract ? mpz_add_ui : mpz_sub_ui) 1067 ((XFIXNUM (b) < 0) == subtract ? mpz_add_ui : mpz_sub_ui)
@@ -1031,6 +1070,7 @@ lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1031 } 1070 }
1032 } 1071 }
1033 1072
1073 /* Fall back on bignum arithmetic if necessary. */
1034 if (!mpz_done) 1074 if (!mpz_done)
1035 (subtract ? mpz_sub : mpz_add) (mpz[0], 1075 (subtract ? mpz_sub : mpz_add) (mpz[0],
1036 *bignum_integer (&mpz[0], a), 1076 *bignum_integer (&mpz[0], a),
@@ -1039,9 +1079,7 @@ lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1039} 1079}
1040 1080
1041/* Given Lisp operands A and B, add their values, and return the 1081/* Given Lisp operands A and B, add their values, and return the
1042 result as a Lisp timestamp that is in (TICKS . HZ) form if either A 1082 result as a Lisp timestamp. Subtract instead of adding if SUBTRACT. */
1043 or B are in that form or are floats, (HI LO US PS) form otherwise.
1044 Subtract instead of adding if SUBTRACT. */
1045static Lisp_Object 1083static Lisp_Object
1046time_arith (Lisp_Object a, Lisp_Object b, bool subtract) 1084time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1047{ 1085{
@@ -1124,21 +1162,22 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1124 (subtract ? mpz_submul : mpz_addmul) (*iticks, *fa, *nb); 1162 (subtract ? mpz_submul : mpz_addmul) (*iticks, *fa, *nb);
1125 1163
1126 /* Normalize iticks/ihz by dividing both numerator and 1164 /* Normalize iticks/ihz by dividing both numerator and
1127 denominator by ig = gcd (iticks, ihz). However, if that 1165 denominator by ig = gcd (iticks, ihz). For speed, though,
1128 would cause the denominator to become less than hzmin, 1166 skip this division if ihz = 1. */
1129 rescale the denominator upwards from its ordinary value by
1130 multiplying numerator and denominator so that the denominator
1131 becomes at least hzmin. This rescaling avoids returning a
1132 timestamp that is less precise than both a and b, or a
1133 timestamp that looks obsolete when that might be a problem. */
1134 mpz_t *ig = &mpz[3]; 1167 mpz_t *ig = &mpz[3];
1135 mpz_gcd (*ig, *iticks, *ihz); 1168 mpz_gcd (*ig, *iticks, *ihz);
1136
1137 if (!FASTER_TIMEFNS || mpz_cmp_ui (*ig, 1) > 0) 1169 if (!FASTER_TIMEFNS || mpz_cmp_ui (*ig, 1) > 0)
1138 { 1170 {
1139 mpz_divexact (*iticks, *iticks, *ig); 1171 mpz_divexact (*iticks, *iticks, *ig);
1140 mpz_divexact (*ihz, *ihz, *ig); 1172 mpz_divexact (*ihz, *ihz, *ig);
1141 1173
1174 /* However, if dividing the denominator by ig would cause the
1175 denominator to become less than hzmin, rescale the denominator
1176 upwards by multiplying the normalized numerator and denominator
1177 so that the resulting denominator becomes at least hzmin.
1178 This rescaling avoids returning a timestamp that is less precise
1179 than both a and b, or a timestamp that looks obsolete when that
1180 might be a problem. */
1142 if (!FASTER_TIMEFNS || mpz_cmp (*ihz, *hzmin) < 0) 1181 if (!FASTER_TIMEFNS || mpz_cmp (*ihz, *hzmin) < 0)
1143 { 1182 {
1144 /* Rescale straightforwardly. Although this might not 1183 /* Rescale straightforwardly. Although this might not
@@ -1152,6 +1191,8 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1152 mpz_mul (*ihz, *ihz, *rescale); 1191 mpz_mul (*ihz, *ihz, *rescale);
1153 } 1192 }
1154 } 1193 }
1194
1195 /* mpz[0] and iticks now correspond to the (HZ . TICKS) pair. */
1155 hz = make_integer_mpz (); 1196 hz = make_integer_mpz ();
1156 mpz_swap (mpz[0], *iticks); 1197 mpz_swap (mpz[0], *iticks);
1157 ticks = make_integer_mpz (); 1198 ticks = make_integer_mpz ();
@@ -1213,6 +1254,8 @@ time_cmp (Lisp_Object a, Lisp_Object b)
1213 if (EQ (a, b)) 1254 if (EQ (a, b))
1214 return 0; 1255 return 0;
1215 1256
1257 /* Compare (ATICKS . AZ) to (BTICKS . BHZ) by comparing
1258 ATICKS * BHZ to BTICKS * AHZ. */
1216 struct lisp_time tb = lisp_time_struct (b, 0); 1259 struct lisp_time tb = lisp_time_struct (b, 0);
1217 mpz_t const *za = bignum_integer (&mpz[0], ta.ticks); 1260 mpz_t const *za = bignum_integer (&mpz[0], ta.ticks);
1218 mpz_t const *zb = bignum_integer (&mpz[1], tb.ticks); 1261 mpz_t const *zb = bignum_integer (&mpz[1], tb.ticks);
@@ -1490,6 +1533,7 @@ SEC is always an integer between 0 and 59.)
1490usage: (decode-time &optional TIME ZONE FORM) */) 1533usage: (decode-time &optional TIME ZONE FORM) */)
1491 (Lisp_Object specified_time, Lisp_Object zone, Lisp_Object form) 1534 (Lisp_Object specified_time, Lisp_Object zone, Lisp_Object form)
1492{ 1535{
1536 /* Compute broken-down local time LOCAL_TM from SPECIFIED_TIME and ZONE. */
1493 struct lisp_time lt = lisp_time_struct (specified_time, 0); 1537 struct lisp_time lt = lisp_time_struct (specified_time, 0);
1494 struct timespec ts = lisp_to_timespec (lt); 1538 struct timespec ts = lisp_to_timespec (lt);
1495 if (! timespec_valid_p (ts)) 1539 if (! timespec_valid_p (ts))
@@ -1504,6 +1548,7 @@ usage: (decode-time &optional TIME ZONE FORM) */)
1504 if (!tm) 1548 if (!tm)
1505 time_error (localtime_errno); 1549 time_error (localtime_errno);
1506 1550
1551 /* Let YEAR = LOCAL_TM.tm_year + TM_YEAR_BASE. */
1507 Lisp_Object year; 1552 Lisp_Object year;
1508 if (FASTER_TIMEFNS 1553 if (FASTER_TIMEFNS
1509 && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= local_tm.tm_year 1554 && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= local_tm.tm_year
@@ -1520,12 +1565,15 @@ usage: (decode-time &optional TIME ZONE FORM) */)
1520 year = make_integer_mpz (); 1565 year = make_integer_mpz ();
1521 } 1566 }
1522 1567
1568 /* Compute SEC from LOCAL_TM.tm_sec and HZ. */
1523 Lisp_Object hz = lt.hz, sec; 1569 Lisp_Object hz = lt.hz, sec;
1524 if (EQ (hz, make_fixnum (1)) || !EQ (form, Qt)) 1570 if (EQ (hz, make_fixnum (1)) || !EQ (form, Qt))
1525 sec = make_fixnum (local_tm.tm_sec); 1571 sec = make_fixnum (local_tm.tm_sec);
1526 else 1572 else
1527 { 1573 {
1528 Lisp_Object ticks; /* hz * tm_sec + mod (lt.ticks, hz) */ 1574 /* Let TICKS = HZ * LOCAL_TM.tm_sec + mod (LT.ticks, HZ)
1575 and SEC = (TICKS . HZ). */
1576 Lisp_Object ticks;
1529 intmax_t n; 1577 intmax_t n;
1530 if (FASTER_TIMEFNS && FIXNUMP (lt.ticks) && FIXNUMP (hz) 1578 if (FASTER_TIMEFNS && FIXNUMP (lt.ticks) && FIXNUMP (hz)
1531 && !INT_MULTIPLY_WRAPV (XFIXNUM (hz), local_tm.tm_sec, &n) 1579 && !INT_MULTIPLY_WRAPV (XFIXNUM (hz), local_tm.tm_sec, &n)
@@ -1655,6 +1703,7 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */)
1655 yeararg = args[5]; 1703 yeararg = args[5];
1656 } 1704 }
1657 1705
1706 /* Let SEC = floor (LT.ticks / HZ), with SUBSECTICKS the remainder. */
1658 struct lisp_time lt; 1707 struct lisp_time lt;
1659 decode_lisp_time (secarg, 0, &lt, 0); 1708 decode_lisp_time (secarg, 0, &lt, 0);
1660 Lisp_Object hz = lt.hz, sec, subsecticks; 1709 Lisp_Object hz = lt.hz, sec, subsecticks;
diff --git a/src/w32.c b/src/w32.c
index cf1a3b37678..698e10e234e 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -3178,18 +3178,9 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2])
3178 return _futime (fd, &_ut); 3178 return _futime (fd, &_ut);
3179 } 3179 }
3180 else 3180 else
3181 { 3181 return utimensat (fd, file, timespec, 0);
3182 struct utimbuf ut;
3183
3184 ut.actime = timespec[0].tv_sec;
3185 ut.modtime = timespec[1].tv_sec;
3186 /* Call 'utime', which is implemented below, not the MS library
3187 function, which fails on directories. */
3188 return utime (file, &ut);
3189 }
3190} 3182}
3191 3183
3192
3193/* ------------------------------------------------------------------------- */ 3184/* ------------------------------------------------------------------------- */
3194/* IO support and wrapper functions for the Windows API. */ 3185/* IO support and wrapper functions for the Windows API. */
3195/* ------------------------------------------------------------------------- */ 3186/* ------------------------------------------------------------------------- */
@@ -4970,7 +4961,7 @@ convert_time (FILETIME ft)
4970} 4961}
4971 4962
4972static void 4963static void
4973convert_from_time_t (time_t time, FILETIME * pft) 4964convert_from_timespec (struct timespec time, FILETIME * pft)
4974{ 4965{
4975 ULARGE_INTEGER tmp; 4966 ULARGE_INTEGER tmp;
4976 4967
@@ -4981,7 +4972,8 @@ convert_from_time_t (time_t time, FILETIME * pft)
4981 } 4972 }
4982 4973
4983 /* time in 100ns units since 1-Jan-1601 */ 4974 /* time in 100ns units since 1-Jan-1601 */
4984 tmp.QuadPart = (ULONGLONG) time * 10000000L + utc_base; 4975 tmp.QuadPart =
4976 (ULONGLONG) time.tv_sec * 10000000L + time.tv_nsec / 100 + utc_base;
4985 pft->dwHighDateTime = tmp.HighPart; 4977 pft->dwHighDateTime = tmp.HighPart;
4986 pft->dwLowDateTime = tmp.LowPart; 4978 pft->dwLowDateTime = tmp.LowPart;
4987} 4979}
@@ -5648,8 +5640,8 @@ fstatat (int fd, char const *name, struct stat *st, int flags)
5648 return stat_worker (name, st, ! (flags & AT_SYMLINK_NOFOLLOW)); 5640 return stat_worker (name, st, ! (flags & AT_SYMLINK_NOFOLLOW));
5649} 5641}
5650 5642
5651/* Provide fstat and utime as well as stat for consistent handling of 5643/* Provide fstat and utimensat as well as stat for consistent handling
5652 file timestamps. */ 5644 of file timestamps. */
5653int 5645int
5654fstat (int desc, struct stat * buf) 5646fstat (int desc, struct stat * buf)
5655{ 5647{
@@ -5760,23 +5752,65 @@ fstat (int desc, struct stat * buf)
5760 return 0; 5752 return 0;
5761} 5753}
5762 5754
5763/* A version of 'utime' which handles directories as well as 5755/* Emulate utimensat. */
5764 files. */
5765 5756
5766int 5757int
5767utime (const char *name, struct utimbuf *times) 5758utimensat (int fd, const char *name, const struct timespec times[2], int flag)
5768{ 5759{
5769 struct utimbuf deftime; 5760 struct timespec ltimes[2];
5770 HANDLE fh; 5761 HANDLE fh;
5771 FILETIME mtime; 5762 FILETIME mtime;
5772 FILETIME atime; 5763 FILETIME atime;
5764 DWORD flags_and_attrs = FILE_FLAG_BACKUP_SEMANTICS;
5765
5766 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5767 This is good enough for the current usage in Emacs, but is fragile.
5768
5769 FIXME: Add proper support for utimensat.
5770 Gnulib does this and can serve as a model. */
5771 char fullname[MAX_UTF8_PATH];
5772
5773 if (fd != AT_FDCWD)
5774 {
5775 char lastc = dir_pathname[strlen (dir_pathname) - 1];
5776
5777 if (_snprintf (fullname, sizeof fullname, "%s%s%s",
5778 dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", name)
5779 < 0)
5780 {
5781 errno = ENAMETOOLONG;
5782 return -1;
5783 }
5784 name = fullname;
5785 }
5773 5786
5774 if (times == NULL) 5787 if (times == NULL)
5775 { 5788 {
5776 deftime.modtime = deftime.actime = time (NULL); 5789 memset (ltimes, 0, sizeof (ltimes));
5777 times = &deftime; 5790 ltimes[0] = ltimes[1] = current_timespec ();
5791 }
5792 else
5793 {
5794 if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT)
5795 return 0; /* nothing to do */
5796 if ((times[0].tv_nsec != UTIME_NOW && times[0].tv_nsec != UTIME_OMIT
5797 && !(0 <= times[0].tv_nsec && times[0].tv_nsec < 1000000000))
5798 || (times[1].tv_nsec != UTIME_NOW && times[1].tv_nsec != UTIME_OMIT
5799 && !(0 <= times[1].tv_nsec && times[1].tv_nsec < 1000000000)))
5800 {
5801 errno = EINVAL; /* reject invalid timespec values */
5802 return -1;
5803 }
5804
5805 memcpy (ltimes, times, sizeof (ltimes));
5806 if (ltimes[0].tv_nsec == UTIME_NOW)
5807 ltimes[0] = current_timespec ();
5808 if (ltimes[1].tv_nsec == UTIME_NOW)
5809 ltimes[1] = current_timespec ();
5778 } 5810 }
5779 5811
5812 if (flag == AT_SYMLINK_NOFOLLOW)
5813 flags_and_attrs |= FILE_FLAG_OPEN_REPARSE_POINT;
5780 if (w32_unicode_filenames) 5814 if (w32_unicode_filenames)
5781 { 5815 {
5782 wchar_t name_utf16[MAX_PATH]; 5816 wchar_t name_utf16[MAX_PATH];
@@ -5790,7 +5824,7 @@ utime (const char *name, struct utimbuf *times)
5790 allows other processes to delete files inside it, 5824 allows other processes to delete files inside it,
5791 while we have the directory open. */ 5825 while we have the directory open. */
5792 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 5826 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
5793 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); 5827 0, OPEN_EXISTING, flags_and_attrs, NULL);
5794 } 5828 }
5795 else 5829 else
5796 { 5830 {
@@ -5801,13 +5835,26 @@ utime (const char *name, struct utimbuf *times)
5801 5835
5802 fh = CreateFileA (name_ansi, FILE_WRITE_ATTRIBUTES, 5836 fh = CreateFileA (name_ansi, FILE_WRITE_ATTRIBUTES,
5803 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 5837 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
5804 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); 5838 0, OPEN_EXISTING, flags_and_attrs, NULL);
5805 } 5839 }
5806 if (fh != INVALID_HANDLE_VALUE) 5840 if (fh != INVALID_HANDLE_VALUE)
5807 { 5841 {
5808 convert_from_time_t (times->actime, &atime); 5842 FILETIME *patime, *pmtime;
5809 convert_from_time_t (times->modtime, &mtime); 5843 if (ltimes[0].tv_nsec == UTIME_OMIT)
5810 if (!SetFileTime (fh, NULL, &atime, &mtime)) 5844 patime = NULL;
5845 else
5846 {
5847 convert_from_timespec (ltimes[0], &atime);
5848 patime = &atime;
5849 }
5850 if (ltimes[1].tv_nsec == UTIME_OMIT)
5851 pmtime = NULL;
5852 else
5853 {
5854 convert_from_timespec (ltimes[1], &mtime);
5855 pmtime = &mtime;
5856 }
5857 if (!SetFileTime (fh, NULL, patime, pmtime))
5811 { 5858 {
5812 CloseHandle (fh); 5859 CloseHandle (fh);
5813 errno = EACCES; 5860 errno = EACCES;
@@ -6726,16 +6773,16 @@ w32_copy_file (const char *from, const char *to,
6726 FIXME? */ 6773 FIXME? */
6727 else if (!keep_time) 6774 else if (!keep_time)
6728 { 6775 {
6729 struct timespec now; 6776 struct timespec tnow[2];
6730 DWORD attributes; 6777 DWORD attributes;
6731 6778
6779 tnow[0] = tnow[1] = current_timespec ();
6732 if (w32_unicode_filenames) 6780 if (w32_unicode_filenames)
6733 { 6781 {
6734 /* Ensure file is writable while its times are set. */ 6782 /* Ensure file is writable while its times are set. */
6735 attributes = GetFileAttributesW (to_w); 6783 attributes = GetFileAttributesW (to_w);
6736 SetFileAttributesW (to_w, attributes & ~FILE_ATTRIBUTE_READONLY); 6784 SetFileAttributesW (to_w, attributes & ~FILE_ATTRIBUTE_READONLY);
6737 now = current_timespec (); 6785 if (utimensat (AT_FDCWD, to, tnow, 0))
6738 if (set_file_times (-1, to, now, now))
6739 { 6786 {
6740 /* Restore original attributes. */ 6787 /* Restore original attributes. */
6741 SetFileAttributesW (to_w, attributes); 6788 SetFileAttributesW (to_w, attributes);
@@ -6750,8 +6797,7 @@ w32_copy_file (const char *from, const char *to,
6750 { 6797 {
6751 attributes = GetFileAttributesA (to_a); 6798 attributes = GetFileAttributesA (to_a);
6752 SetFileAttributesA (to_a, attributes & ~FILE_ATTRIBUTE_READONLY); 6799 SetFileAttributesA (to_a, attributes & ~FILE_ATTRIBUTE_READONLY);
6753 now = current_timespec (); 6800 if (utimensat (AT_FDCWD, to, tnow, 0))
6754 if (set_file_times (-1, to, now, now))
6755 { 6801 {
6756 SetFileAttributesA (to_a, attributes); 6802 SetFileAttributesA (to_a, attributes);
6757 if (acl) 6803 if (acl)
diff --git a/src/w32term.c b/src/w32term.c
index 4eb5045fc5b..f515f5604d6 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -4701,6 +4701,10 @@ static short temp_buffer[100];
4701/* Temporarily store lead byte of DBCS input sequences. */ 4701/* Temporarily store lead byte of DBCS input sequences. */
4702static char dbcs_lead = 0; 4702static char dbcs_lead = 0;
4703 4703
4704/* Temporarily store pending UTF-16 high surrogate unit and the modifiers. */
4705static unsigned short utf16_high;
4706static DWORD utf16_high_modifiers;
4707
4704/** 4708/**
4705 mouse_or_wdesc_frame: When not dropping and the mouse was grabbed 4709 mouse_or_wdesc_frame: When not dropping and the mouse was grabbed
4706 for DPYINFO, return the frame where the mouse was seen last. If 4710 for DPYINFO, return the frame where the mouse was seen last. If
@@ -4912,9 +4916,45 @@ w32_read_socket (struct terminal *terminal,
4912 XSETFRAME (inev.frame_or_window, f); 4916 XSETFRAME (inev.frame_or_window, f);
4913 inev.timestamp = msg.msg.time; 4917 inev.timestamp = msg.msg.time;
4914 4918
4919 if (utf16_high
4920 && (msg.msg.message != WM_UNICHAR
4921 || UTF_16_HIGH_SURROGATE_P (msg.msg.wParam)))
4922 {
4923 /* Flush the pending high surrogate if the low one
4924 isn't coming. (This should never happen, but I
4925 have paranoia about this stuff.) */
4926 struct input_event inev1;
4927 inev1.modifiers = utf16_high_modifiers;
4928 inev1.code = utf16_high;
4929 inev1.timestamp = inev.timestamp;
4930 inev1.arg = Qnil;
4931 kbd_buffer_store_event_hold (&inev1, hold_quit);
4932 utf16_high = 0;
4933 utf16_high_modifiers = 0;
4934 }
4935
4915 if (msg.msg.message == WM_UNICHAR) 4936 if (msg.msg.message == WM_UNICHAR)
4916 { 4937 {
4917 inev.code = msg.msg.wParam; 4938 /* Handle UTF-16 encoded codepoint above the BMP.
4939 This is needed to support Emoji input from input
4940 panel popped up by "Win+." shortcut. */
4941 if (UTF_16_HIGH_SURROGATE_P (msg.msg.wParam))
4942 {
4943 utf16_high = msg.msg.wParam;
4944 utf16_high_modifiers = inev.modifiers;
4945 inev.kind = NO_EVENT;
4946 break;
4947 }
4948 else if (UTF_16_LOW_SURROGATE_P (msg.msg.wParam)
4949 && utf16_high)
4950 {
4951 inev.code = surrogates_to_codepoint (msg.msg.wParam,
4952 utf16_high);
4953 utf16_high = 0;
4954 utf16_high_modifiers = 0;
4955 }
4956 else
4957 inev.code = msg.msg.wParam;
4918 } 4958 }
4919 else if (msg.msg.wParam < 256) 4959 else if (msg.msg.wParam < 256)
4920 { 4960 {
diff --git a/src/xdisp.c b/src/xdisp.c
index c2aa314c1ad..3c594b54add 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -31441,6 +31441,10 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
31441 struct window *w = XWINDOW (hlinfo->mouse_face_window); 31441 struct window *w = XWINDOW (hlinfo->mouse_face_window);
31442 struct frame *f = XFRAME (WINDOW_FRAME (w)); 31442 struct frame *f = XFRAME (WINDOW_FRAME (w));
31443 31443
31444 /* Don't bother doing anything if we are on a wrong frame. */
31445 if (f != hlinfo->mouse_face_mouse_frame)
31446 return;
31447
31444 if (/* If window is in the process of being destroyed, don't bother 31448 if (/* If window is in the process of being destroyed, don't bother
31445 to do anything. */ 31449 to do anything. */
31446 w->current_matrix != NULL 31450 w->current_matrix != NULL