commit ebde448a14d44719b78b8b873a88448b73d72572 (HEAD, refs/remotes/origin/master) Merge: bd3b2a6781 1030cc1897 Author: Stefan Kangas Date: Wed Apr 20 06:30:27 2022 +0200 ; Merge from origin/emacs-28 The following commit was skipped: 1030cc1897 Fix regression with multiple mode: entries in the prop line commit bd3b2a6781331fc5b7d950af422fd0c3bd8db19b Author: Po Lu Date: Wed Apr 20 03:06:58 2022 +0000 Fix enabling menu bar multiple times on Haiku * src/haiku_support.cc (FrameResized): Adjust width and height appropriately when sending menu bar resize event. * src/haikufns.c (haiku_set_menu_bar_lines): Don't always reset FRAME_MENU_BAR_LINES and FRAME_MENU_BAR_HEIGHT. * src/haikumenu.c (free_frame_menubar): Clear Haiku menu bar. (set_frame_menubar): Fix coding style. * src/haikuterm.c (haiku_read_socket): Don't adjust height here anymore. diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 290b2541f4..af37fe7a62 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -1272,8 +1272,8 @@ class EmacsMenuBar : public BMenuBar { struct haiku_menu_bar_resize_event rq; rq.window = this->Window (); - rq.height = std::lrint (newHeight); - rq.width = std::lrint (newWidth); + rq.height = std::lrint (newHeight + 1); + rq.width = std::lrint (newWidth + 1); haiku_write (MENU_BAR_RESIZE, &rq); BMenuBar::FrameResized (newWidth, newHeight); diff --git a/src/haikufns.c b/src/haikufns.c index 151874e26f..b19fdd5488 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -1278,9 +1278,6 @@ haiku_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval fset_redisplay (f); - FRAME_MENU_BAR_LINES (f) = 0; - FRAME_MENU_BAR_HEIGHT (f) = 0; - if (nlines) { FRAME_EXTERNAL_MENU_BAR (f) = 1; @@ -1289,11 +1286,14 @@ haiku_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval } else { + FRAME_MENU_BAR_LINES (f) = 0; + FRAME_MENU_BAR_HEIGHT (f) = 0; + if (FRAME_EXTERNAL_MENU_BAR (f)) free_frame_menubar (f); + FRAME_EXTERNAL_MENU_BAR (f) = 0; - if (FRAME_HAIKU_P (f)) - FRAME_HAIKU_MENU_BAR (f) = 0; + FRAME_HAIKU_MENU_BAR (f) = 0; } adjust_frame_glyphs (f); diff --git a/src/haikumenu.c b/src/haikumenu.c index 54ee3f160f..9779c34a99 100644 --- a/src/haikumenu.c +++ b/src/haikumenu.c @@ -486,14 +486,19 @@ haiku_menu_show (struct frame *f, int x, int y, int menuflags, void free_frame_menubar (struct frame *f) { + void *mbar; + FRAME_MENU_BAR_LINES (f) = 0; FRAME_MENU_BAR_HEIGHT (f) = 0; FRAME_EXTERNAL_MENU_BAR (f) = 0; block_input (); - void *mbar = FRAME_HAIKU_MENU_BAR (f); + mbar = FRAME_HAIKU_MENU_BAR (f); + FRAME_HAIKU_MENU_BAR (f) = NULL; + if (mbar) BMenuBar_delete (mbar); + if (FRAME_OUTPUT_DATA (f)->menu_bar_open_p) --popup_activated_p; FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 0; @@ -516,8 +521,7 @@ set_frame_menubar (struct frame *f, bool deep_p) { void *mbar = FRAME_HAIKU_MENU_BAR (f); void *view = FRAME_HAIKU_VIEW (f); - - int first_time_p = 0; + bool first_time_p = false; if (!mbar) { @@ -529,6 +533,7 @@ set_frame_menubar (struct frame *f, bool deep_p) initial dimensions of that menu bar. */ if (FRAME_VISIBLE_P (f)) haiku_wait_for_event (f, MENU_BAR_RESIZE); + unblock_input (); } diff --git a/src/haikuterm.c b/src/haikuterm.c index 9cd1d0f015..64c657fef5 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -3514,11 +3514,11 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) int old_height = FRAME_MENU_BAR_HEIGHT (f); - FRAME_MENU_BAR_HEIGHT (f) = b->height + 1; + FRAME_MENU_BAR_HEIGHT (f) = b->height; FRAME_MENU_BAR_LINES (f) = (b->height + FRAME_LINE_HEIGHT (f)) / FRAME_LINE_HEIGHT (f); - if (old_height != b->height + 1) + if (old_height != b->height) { adjust_frame_size (f, -1, -1, 3, true, Qmenu_bar_lines); haiku_clear_under_internal_border (f); commit 992cf3cb675e074079341cc54c3b16d37a8b9ca8 Author: Paul Eggert Date: Tue Apr 19 19:16:29 2022 -0700 Update from gnulib diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex index 58b6abee78..8872e5e055 100644 --- a/doc/misc/texinfo.tex +++ b/doc/misc/texinfo.tex @@ -3,9 +3,9 @@ % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % -\def\texinfoversion{2022-01-02.12} +\def\texinfoversion{2022-04-09.08} % -% Copyright 1985, 1986, 1988, 1990-2021 Free Software Foundation, Inc. +% Copyright 1985, 1986, 1988, 1990-2022 Free Software Foundation, Inc. % % This texinfo.tex file is free software: you can redistribute it and/or % modify it under the terms of the GNU General Public License as @@ -3171,16 +3171,8 @@ % Default is `distinct'. \kbdinputstyle distinct -% @kbd is like @code, except that if the argument is just one @key command, -% then @kbd has no effect. -\def\kbd#1{{\def\look{#1}\expandafter\kbdsub\look??\par}} - -\def\xkey{\key} -\def\kbdsub#1#2#3\par{% - \def\one{#1}\def\three{#3}\def\threex{??}% - \ifx\one\xkey\ifx\threex\three \key{#2}% - \else{\tclose{\kbdfont\setcodequotes\look}}\fi - \else{\tclose{\kbdfont\setcodequotes\look}}\fi +\def\kbd#1{% + \tclose{\kbdfont\setcodequotes#1}% } % definition of @key that produces a lozenge. Doesn't adjust to text size. @@ -4417,7 +4409,7 @@ % Find the correct column width \hsize=\expandafter\csname col\the\colcount\endcsname % - \rightskip=0pt + \advance\rightskip by -1\rightskip % Zero leaving only any stretch \ifnum\colcount=1 \advance\hsize by\leftskip % Add indent of surrounding text \else @@ -5961,7 +5953,7 @@ % Chapters, sections, etc. % Let's start with @part. -\outer\parseargdef\part{\partzzz{#1}} +\parseargdef\part{\partzzz{#1}} \def\partzzz#1{% \chapoddpage \null @@ -8680,9 +8672,11 @@ } \def\wordTop{Top} -% Until the next @node or @bye command, divert output to a box that is not -% output. -\def\ignorenode{\setbox\dummybox\vbox\bgroup\def\node{\egroup\node}% +% Until the next @node, @part or @bye command, divert output to a box that +% is not output. +\def\ignorenode{\setbox\dummybox\vbox\bgroup +\def\part{\egroup\part}% +\def\node{\egroup\node}% \ignorenodebye } @@ -9391,13 +9385,12 @@ \catcode`\^^M = 5 % in case we're inside an example \normalturnoffactive % allow _ et al. in names \makevalueexpandable - % If the image is by itself, center it. \ifvmode \imagevmodetrue \else \ifx\centersub\centerV % for @center @image, we need a vbox so we can have our vertical space \imagevmodetrue - \vbox\bgroup % vbox has better behavior than vtop herev + \vbox\bgroup % vbox has better behavior than vtop here \fi\fi % \ifimagevmode @@ -9405,11 +9398,14 @@ % Usually we'll have text after the image which will insert % \parskip glue, so insert it here too to equalize the space % above and below. - \nobreak\vskip\parskip - \nobreak + \vskip\parskip + % + % Place image in a \vtop for a top page margin that is (close to) correct, + % as \topskip glue is relative to the first baseline. + \vtop\bgroup\hrule height 0pt\vskip-\parskip \fi % - % Leave vertical mode so that indentation from an enclosing + % Enter horizontal mode so that indentation from an enclosing % environment such as @quotation is respected. % However, if we're at the top level, we don't want the % normal paragraph indentation. @@ -9438,6 +9434,7 @@ \fi % \ifimagevmode + \egroup \medskip % space after a standalone image \fi \ifx\centersub\centerV \egroup \fi @@ -10898,6 +10895,9 @@ \DeclareUnicodeCharacter{1EF8}{\~Y}% \DeclareUnicodeCharacter{1EF9}{\~y}% % + % Exotic spaces + \DeclareUnicodeCharacter{2007}{\hphantom{0}}% + % % Punctuation \DeclareUnicodeCharacter{2013}{--}% \DeclareUnicodeCharacter{2014}{---}% diff --git a/lib/mini-gmp.c b/lib/mini-gmp.c index 2b1ddee079..95f067f82d 100644 --- a/lib/mini-gmp.c +++ b/lib/mini-gmp.c @@ -90,6 +90,7 @@ see https://www.gnu.org/licenses/. */ #define gmp_assert_nocarry(x) do { \ mp_limb_t __cy = (x); \ assert (__cy == 0); \ + (void) (__cy); \ } while (0) #define gmp_clz(count, x) do { \ diff --git a/lib/string.in.h b/lib/string.in.h index c9432948c1..b6840fa912 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -125,14 +125,22 @@ _GL_EXTERN_C void rpl_free (void *); # if defined _MSC_VER _GL_EXTERN_C void __cdecl free (void *); # else +# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2) +_GL_EXTERN_C void free (void *) throw (); +# else _GL_EXTERN_C void free (void *); +# endif # endif # endif #else # if defined _MSC_VER _GL_EXTERN_C void __cdecl free (void *); # else +# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2) +_GL_EXTERN_C void free (void *) throw (); +# else _GL_EXTERN_C void free (void *); +# endif # endif #endif @@ -230,10 +238,11 @@ _GL_CXXALIAS_SYS_CAST2 (memchr, void const *, (void const *__s, int __c, size_t __n)); # endif # if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -_GL_CXXALIASWARN1 (memchr, void *, (void *__s, int __c, size_t __n)); + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ + || defined __clang__) +_GL_CXXALIASWARN1 (memchr, void *, (void *__s, int __c, size_t __n) throw ()); _GL_CXXALIASWARN1 (memchr, void const *, - (void const *__s, int __c, size_t __n)); + (void const *__s, int __c, size_t __n) throw ()); # elif __GLIBC__ >= 2 _GL_CXXALIASWARN (memchr); # endif @@ -315,9 +324,10 @@ _GL_CXXALIAS_SYS_CAST2 (memrchr, void *, (void const *, int, size_t), void const *, (void const *, int, size_t)); # if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -_GL_CXXALIASWARN1 (memrchr, void *, (void *, int, size_t)); -_GL_CXXALIASWARN1 (memrchr, void const *, (void const *, int, size_t)); + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ + || defined __clang__) +_GL_CXXALIASWARN1 (memrchr, void *, (void *, int, size_t) throw ()); +_GL_CXXALIASWARN1 (memrchr, void const *, (void const *, int, size_t) throw ()); # else _GL_CXXALIASWARN (memrchr); # endif @@ -345,9 +355,11 @@ _GL_CXXALIAS_SYS_CAST2 (rawmemchr, void *, (void const *__s, int __c_in), void const *, (void const *__s, int __c_in)); # if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -_GL_CXXALIASWARN1 (rawmemchr, void *, (void *__s, int __c_in)); -_GL_CXXALIASWARN1 (rawmemchr, void const *, (void const *__s, int __c_in)); + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ + || defined __clang__) +_GL_CXXALIASWARN1 (rawmemchr, void *, (void *__s, int __c_in) throw ()); +_GL_CXXALIASWARN1 (rawmemchr, void const *, + (void const *__s, int __c_in) throw ()); # else _GL_CXXALIASWARN (rawmemchr); # endif @@ -449,9 +461,11 @@ _GL_CXXALIAS_SYS_CAST2 (strchrnul, char const *, (char const *__s, int __c_in)); # endif # if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -_GL_CXXALIASWARN1 (strchrnul, char *, (char *__s, int __c_in)); -_GL_CXXALIASWARN1 (strchrnul, char const *, (char const *__s, int __c_in)); + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ + || defined __clang__) +_GL_CXXALIASWARN1 (strchrnul, char *, (char *__s, int __c_in) throw ()); +_GL_CXXALIASWARN1 (strchrnul, char const *, + (char const *__s, int __c_in) throw ()); # else _GL_CXXALIASWARN (strchrnul); # endif @@ -651,10 +665,11 @@ _GL_CXXALIAS_SYS_CAST2 (strpbrk, char *, (char const *__s, char const *__accept), const char *, (char const *__s, char const *__accept)); # if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -_GL_CXXALIASWARN1 (strpbrk, char *, (char *__s, char const *__accept)); + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ + || defined __clang__) +_GL_CXXALIASWARN1 (strpbrk, char *, (char *__s, char const *__accept) throw ()); _GL_CXXALIASWARN1 (strpbrk, char const *, - (char const *__s, char const *__accept)); + (char const *__s, char const *__accept) throw ()); # elif __GLIBC__ >= 2 _GL_CXXALIASWARN (strpbrk); # endif @@ -759,10 +774,12 @@ _GL_CXXALIAS_SYS_CAST2 (strstr, const char *, (const char *haystack, const char *needle)); # endif # if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -_GL_CXXALIASWARN1 (strstr, char *, (char *haystack, const char *needle)); + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ + || defined __clang__) +_GL_CXXALIASWARN1 (strstr, char *, + (char *haystack, const char *needle) throw ()); _GL_CXXALIASWARN1 (strstr, const char *, - (const char *haystack, const char *needle)); + (const char *haystack, const char *needle) throw ()); # elif __GLIBC__ >= 2 _GL_CXXALIASWARN (strstr); # endif @@ -808,10 +825,12 @@ _GL_CXXALIAS_SYS_CAST2 (strcasestr, const char *, (const char *haystack, const char *needle)); # endif # if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -_GL_CXXALIASWARN1 (strcasestr, char *, (char *haystack, const char *needle)); + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ + || defined __clang__) +_GL_CXXALIASWARN1 (strcasestr, char *, + (char *haystack, const char *needle) throw ()); _GL_CXXALIASWARN1 (strcasestr, const char *, - (const char *haystack, const char *needle)); + (const char *haystack, const char *needle) throw ()); # else _GL_CXXALIASWARN (strcasestr); # endif diff --git a/lib/verify.h b/lib/verify.h index 07b2f4866f..c5c63ae97c 100644 --- a/lib/verify.h +++ b/lib/verify.h @@ -34,7 +34,7 @@ #ifndef __cplusplus # if (201112L <= __STDC_VERSION__ \ || (!defined __STRICT_ANSI__ \ - && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || 4 <= __clang_major__))) + && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || 5 <= __clang_major__))) # define _GL_HAVE__STATIC_ASSERT 1 # endif # if (202000L <= __STDC_VERSION__ \ @@ -215,6 +215,9 @@ template # define _GL_VERIFY(R, DIAGNOSTIC, ...) \ extern int (*_GL_GENSYM (_gl_verify_function) (void)) \ [_GL_VERIFY_TRUE (R, DIAGNOSTIC)] +# if 4 < __GNUC__ + (6 <= __GNUC_MINOR__) +# pragma GCC diagnostic ignored "-Wnested-externs" +# endif #endif /* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h. */ diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4 index c5ced04f18..30911d1581 100644 --- a/m4/gnulib-common.m4 +++ b/m4/gnulib-common.m4 @@ -1,4 +1,4 @@ -# gnulib-common.m4 serial 72 +# gnulib-common.m4 serial 73 dnl Copyright (C) 2007-2022 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -106,6 +106,10 @@ AC_DEFUN([gl_COMMON_BODY], [ #endif #ifdef __has_c_attribute +# if ((defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) <= 201710 \ + && _GL_GNUC_PREREQ (4, 6)) +# pragma GCC diagnostic ignored "-Wpedantic" +# endif # define _GL_HAS_C_ATTRIBUTE(attr) __has_c_attribute (__##attr##__) #else # define _GL_HAS_C_ATTRIBUTE(attr) 0 commit 67940394c03450e767724a461c061921e2329bab Author: Paul Eggert Date: Tue Apr 19 19:02:05 2022 -0700 Pacify gcc -std=c99 with printf %p * src/print.c (print_vectorlike): Assign pointer-to-function to void * before printing it with %p, as the C standard doesn’t bless printing function pointers with %p. diff --git a/src/print.c b/src/print.c index baf515047b..54d8bdfa3d 100644 --- a/src/print.c +++ b/src/print.c @@ -1701,10 +1701,10 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag, case PVEC_USER_PTR: { + void *finalizer = XUSER_PTR (obj)->finalizer; print_c_string ("#p, - XUSER_PTR (obj)->finalizer); + XUSER_PTR (obj)->p, finalizer); strout (buf, i, i, printcharfun); printchar ('>', printcharfun); } @@ -1875,7 +1875,8 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag, print_string (XTHREAD (obj)->name, printcharfun); else { - int len = sprintf (buf, "%p", XTHREAD (obj)); + void *p = XTHREAD (obj); + int len = sprintf (buf, "%p", p); strout (buf, len, len, printcharfun); } printchar ('>', printcharfun); @@ -1887,7 +1888,8 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag, print_string (XMUTEX (obj)->name, printcharfun); else { - int len = sprintf (buf, "%p", XMUTEX (obj)); + void *p = XMUTEX (obj); + int len = sprintf (buf, "%p", p); strout (buf, len, len, printcharfun); } printchar ('>', printcharfun); @@ -1899,7 +1901,8 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag, print_string (XCONDVAR (obj)->name, printcharfun); else { - int len = sprintf (buf, "%p", XCONDVAR (obj)); + void *p = XCONDVAR (obj); + int len = sprintf (buf, "%p", p); strout (buf, len, len, printcharfun); } printchar ('>', printcharfun); commit cfadba6f2391424431e0f2e08ec9f97336231564 Author: Paul Eggert Date: Tue Apr 19 19:00:22 2022 -0700 Pacify gcc -std=c99 * src/sysdep.c (system_process_attributes): Use %llu instead of %Lu for sscanf, as %llu is standard and %Lu is not, and the latter can provoke warnings if gcc is used pedantically. diff --git a/src/sysdep.c b/src/sysdep.c index 36636d0ed5..9c1e59c02b 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -3420,7 +3420,7 @@ system_process_attributes (Lisp_Object pid) utime stime cutime cstime priority nice thcount . start vsize rss */ if (q && (sscanf (q + 2, ("%c %d %d %d %d %d %*u %lu %lu %lu %lu " - "%Lu %Lu %Lu %Lu %ld %ld %d %*d %Lu %lu %ld"), + "%llu %llu %llu %llu %ld %ld %d %*d %llu %lu %ld"), &c, &ppid, &pgrp, &sess, &tty, &tpgid, &minflt, &cminflt, &majflt, &cmajflt, &u_time, &s_time, &cutime, &cstime, commit f165887819e81013638fa599ecb94ea27c53811f Author: Po Lu Date: Wed Apr 20 09:10:48 2022 +0800 Check for integer overflow when writing Motif targets tables * src/xterm.c (xm_setup_dnd_targets): Check for integer overflow when adding list to target table. diff --git a/src/xterm.c b/src/xterm.c index 03d5a503f8..92c8ac09c9 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1488,7 +1488,6 @@ xm_get_drag_window (struct x_display_info *dpyinfo) return drag_window; } -/* TODO: overflow checks when inserting targets. */ static int xm_setup_dnd_targets (struct x_display_info *dpyinfo, Atom *targets, int ntargets) @@ -1503,6 +1502,7 @@ xm_setup_dnd_targets (struct x_display_info *dpyinfo, xm_byte_order byteorder; uint8_t *data; ptrdiff_t total_bytes, total_items, i; + uint32_t size, target_count; drag_window = xm_get_drag_window (dpyinfo); @@ -1609,19 +1609,55 @@ xm_setup_dnd_targets (struct x_display_info *dpyinfo, if (idx == -1) { - header.target_list_count++; - header.total_data_size += 2 + ntargets * 4; + target_count = header.target_list_count; + rc = false; - recs[header.target_list_count - 1] - = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec, - targets, ntargets * 4)); - recs[header.target_list_count - 1]->n_targets = ntargets; + if (INT_ADD_WRAPV (header.target_list_count, 1, + &header.target_list_count) + || INT_MULTIPLY_WRAPV (ntargets, 4, &size) + || INT_ADD_WRAPV (header.total_data_size, size, + &header.total_data_size) + || INT_ADD_WRAPV (header.total_data_size, 2, + &header.total_data_size)) + { + /* Overflow, remove every entry from the targets table + and add one for our current targets list. This + confuses real Motif but not GTK 2.x, and there is no + other choice. */ - for (i = 0; i < ntargets; ++i) - recs[header.target_list_count - 1]->targets[i] = targets_sorted[i]; + for (i = 0; i < target_count; ++i) + xfree (recs[i]); - idx = header.target_list_count - 1; - rc = false; + xfree (recs); + + header.byte_order = XM_BYTE_ORDER_CUR_FIRST; + header.protocol = 0; + header.target_list_count = 1; + header.total_data_size = 8 + 2 + ntargets * 4; + + recs = xmalloc (sizeof *recs); + recs[0] = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec, + targets, ntargets * 4)); + + recs[0]->n_targets = ntargets; + + for (i = 0; i < ntargets; ++i) + recs[0]->targets[i] = targets_sorted[i]; + + idx = 0; + } + else + { + recs[header.target_list_count - 1] + = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec, + targets, ntargets * 4)); + recs[header.target_list_count - 1]->n_targets = ntargets; + + for (i = 0; i < ntargets; ++i) + recs[header.target_list_count - 1]->targets[i] = targets_sorted[i]; + + idx = header.target_list_count - 1; + } } } commit 612e855aa08dfd026e28273b04d54b34978d3e0d Author: Lars Ingebrigtsen Date: Tue Apr 19 18:36:04 2022 +0200 Fix previous description of fallback order * doc/emacs/custom.texi (Specifying File Variables): Document fallback mode order. diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index 63e3bb5815..46a2291b74 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -1237,16 +1237,16 @@ been introduced to handle a file in a newer Emacs version, you can use several @code{mode} entries to use the new mode (called @code{my-new-mode}) in the new Emacs, and fall back to the old mode (called @code{my-old-mode}) in older Emacs versions. If you're -enabling the modes in the first line of the file, you should use this -order: +enabling the modes in the first line of the file, can say: @example --*- mode: my-new; mode: my-old -*- +-*- mode: my-old; mode: my-new -*- @end example - Emacs will ignore undefined modes until it finds one it can use. -However, if you're using a local variable block at the end up the -file, the order is reversed: + Emacs will use the final defined mode it finds, so in older Emacs +versions it will ignore @code{my-new-mode}, while in Emacs versions +where @code{my-new-mode} is defined, it'll ignore @code{my-old-mode}. +Similarly, in a local variable block at the end of the file: @example Local variables: @@ -1254,9 +1254,6 @@ mode: my-old mode: my-new @end example - Here Emacs will use the @emph{last} defined mode it finds. (This is -for historical reasons.) - Do not use the @code{mode} keyword for minor modes. To enable or disable a minor mode in a local variables list, use the @code{eval} keyword with a Lisp expression that runs the mode command commit 247e587d56f9be5164b3783e04cfba73fd667175 Author: Lars Ingebrigtsen Date: Tue Apr 19 18:21:21 2022 +0200 Document how to specify fallback modes * doc/emacs/custom.texi (Specifying File Variables): Document fallback mode order. diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index a3c9c7c206..63e3bb5815 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -1232,6 +1232,31 @@ Manual}. These four keywords are not really variables; setting them in any other context has no special meaning. + If you're editing a file across Emacs versions, and a new mode has +been introduced to handle a file in a newer Emacs version, you can use +several @code{mode} entries to use the new mode (called +@code{my-new-mode}) in the new Emacs, and fall back to the old mode +(called @code{my-old-mode}) in older Emacs versions. If you're +enabling the modes in the first line of the file, you should use this +order: + +@example +-*- mode: my-new; mode: my-old -*- +@end example + + Emacs will ignore undefined modes until it finds one it can use. +However, if you're using a local variable block at the end up the +file, the order is reversed: + +@example +Local variables: +mode: my-old +mode: my-new +@end example + + Here Emacs will use the @emph{last} defined mode it finds. (This is +for historical reasons.) + Do not use the @code{mode} keyword for minor modes. To enable or disable a minor mode in a local variables list, use the @code{eval} keyword with a Lisp expression that runs the mode command diff --git a/etc/NEWS b/etc/NEWS index 496ff32d20..3442ebd81b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1441,6 +1441,11 @@ functions. * Lisp Changes in Emacs 29.1 ++++ +** The local variable section now supports defining fallback modes. +This was previously only available when using a property line (i.e., +putting the modes on the first line of a file). + +++ ** New function 'flush-standard-output'. This enables you do display incomplete lines from batch-based Emacs commit 1030cc18979453605e4f76ed46d1e93d6c71c68f (refs/remotes/origin/emacs-28) Author: Lars Ingebrigtsen Date: Tue Apr 19 18:08:20 2022 +0200 Fix regression with multiple mode: entries in the prop line * lisp/files.el (hack-local-variables): Fix regression with multiple mode: entries in the prop line. Do not merge to master. diff --git a/lisp/files.el b/lisp/files.el index 30e8da4da3..b187c0b3a0 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -3888,7 +3888,7 @@ inhibited." ;; Note this is a no-op if enable-local-variables is nil. (hack-dir-local-variables)) (let ((result (append (hack-local-variables--find-variables handle-mode) - (hack-local-variables-prop-line)))) + (hack-local-variables-prop-line handle-mode)))) (if (and enable-local-variables (not (inhibit-local-variables-p))) (progn commit e45abc832db7d1a64a0761dcb51565b7c282999a Author: Lars Ingebrigtsen Date: Tue Apr 19 18:06:31 2022 +0200 Fix regression with multiple mode: entries in the prop line * lisp/files.el (hack-local-variables--find-variables): Use the final mode: line (which is the same as having several mode: bits in the header line. diff --git a/lisp/files.el b/lisp/files.el index a9d4b5aea8..2b0dc54db8 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -3900,7 +3900,7 @@ inhibited." ;; Note this is a no-op if enable-local-variables is nil. (hack-dir-local-variables)) (let ((result (append (hack-local-variables--find-variables handle-mode) - (hack-local-variables-prop-line)))) + (hack-local-variables-prop-line handle-mode)))) (if (and enable-local-variables (not (inhibit-local-variables-p))) (progn diff --git a/test/lisp/files-resources/file-mode-prop-line b/test/lisp/files-resources/file-mode-prop-line new file mode 100644 index 0000000000..e0e7ad24d7 --- /dev/null +++ b/test/lisp/files-resources/file-mode-prop-line @@ -0,0 +1 @@ +-*- mode: notexist; mode: text -*- diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el index c886bd7985..c5b0fe0bbb 100644 --- a/test/lisp/files-tests.el +++ b/test/lisp/files-tests.el @@ -1825,5 +1825,9 @@ Prompt users for any modified buffer with `buffer-offer-save' non-nil." (find-file (ert-resource-file "file-mode-multiple")) (should (eq major-mode 'outline-mode))) +(ert-deftest files-test-set-mode-prop-line () + (find-file (ert-resource-file "file-mode-prop-line")) + (should (eq major-mode 'text-mode))) + (provide 'files-tests) ;;; files-tests.el ends here commit 35592141cc8951c91a4bd6cc02f73d1ddd35aca4 Author: Lars Ingebrigtsen Date: Tue Apr 19 16:22:37 2022 +0200 Allow several mode: elements in the local variable section * etc/NEWS (mode): Fall back on outline-mode in older Emacsen. * lisp/files.el (hack-local-variables--find-variables): Use the final mode: line (which is the same as having several mode: bits in the header line. diff --git a/etc/NEWS b/etc/NEWS index 3e7788277d..496ff32d20 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2071,6 +2071,7 @@ along with GNU Emacs. If not, see . Local variables: coding: utf-8 +mode: outline mode: emacs-news paragraph-separate: "[ ]*$" end: diff --git a/lisp/files.el b/lisp/files.el index 135a6177e9..a9d4b5aea8 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -3978,8 +3978,7 @@ major-mode." (forward-line 1)) (goto-char (point-min)) - (while (not (or (eobp) - (and (eq handle-mode t) result))) + (while (not (eobp)) ;; Find the variable name; (unless (looking-at hack-local-variable-regexp) (user-error "Malformed local variable line: %S" @@ -4005,7 +4004,8 @@ major-mode." (not (string-match "-minor\\'" (setq val2 (downcase (symbol-name val))))) - (setq result (intern (concat val2 "-mode")))) + ;; Allow several mode: elements. + (push (intern (concat val2 "-mode")) result)) (cond ((eq var 'coding)) ((eq var 'lexical-binding) (unless hack-local-variables--warned-lexical @@ -4029,7 +4029,10 @@ major-mode." val) result)))))) (forward-line 1))))))) - result)) + (if (eq handle-mode t) + ;; Return the final mode: setting that's defined. + (car (seq-filter #'fboundp result)) + result))) (defun hack-local-variables-apply () "Apply the elements of `file-local-variables-alist'. diff --git a/test/lisp/files-resources/file-mode-multiple b/test/lisp/files-resources/file-mode-multiple new file mode 100644 index 0000000000..ac051ccbcb --- /dev/null +++ b/test/lisp/files-resources/file-mode-multiple @@ -0,0 +1,5 @@ +Local variables: +mode: text +mode: test-mode-undef +mode: outline +end: diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el index f76d047f30..c886bd7985 100644 --- a/test/lisp/files-tests.el +++ b/test/lisp/files-tests.el @@ -1821,5 +1821,9 @@ Prompt users for any modified buffer with `buffer-offer-save' non-nil." ;; Check that the mode cookie doesn't override the explicit setting. (should (eq major-mode 'emacs-lisp-mode))) +(ert-deftest files-test-set-mode-multiple () + (find-file (ert-resource-file "file-mode-multiple")) + (should (eq major-mode 'outline-mode))) + (provide 'files-tests) ;;; files-tests.el ends here commit 71005decb4fb447635d7b2367104dd18bdfa64ac Author: Stefan Monnier Date: Tue Apr 19 08:25:19 2022 -0400 Fix GCC warnings when CHECK_LISP_OBJECT_TYPE * src/lisp.h (lisp_h_Qni): New macro. (DEFUN): Use it. * src/alloc.c (syms_of_alloc): Use it. * src/bytecode.c (Fbyte_code): Fix Lisp_Object/int mixup. diff --git a/src/alloc.c b/src/alloc.c index 4fc4044587..b9712859c3 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -7837,14 +7837,14 @@ N should be nonnegative. */); static union Aligned_Lisp_Subr Swatch_gc_cons_threshold = {{{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) }, { .a4 = watch_gc_cons_threshold }, - 4, 4, "watch_gc_cons_threshold", {0}, 0}}; + 4, 4, "watch_gc_cons_threshold", {0}, lisp_h_Qnil}}; XSETSUBR (watcher, &Swatch_gc_cons_threshold.s); Fadd_variable_watcher (Qgc_cons_threshold, watcher); static union Aligned_Lisp_Subr Swatch_gc_cons_percentage = {{{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) }, { .a4 = watch_gc_cons_percentage }, - 4, 4, "watch_gc_cons_percentage", {0}, 0}}; + 4, 4, "watch_gc_cons_percentage", {0}, lisp_h_Qnil}}; XSETSUBR (watcher, &Swatch_gc_cons_percentage.s); Fadd_variable_watcher (Qgc_cons_percentage, watcher); } diff --git a/src/bytecode.c b/src/bytecode.c index 6246498616..74b7d16aff 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -325,7 +325,7 @@ If the third argument is incorrect, Emacs may crash. */) the original unibyte form. */ bytestr = Fstring_as_unibyte (bytestr); } - Lisp_Object fun = CALLN (Fmake_byte_code, 0, bytestr, vector, maxdepth); + Lisp_Object fun = CALLN (Fmake_byte_code, Qnil, bytestr, vector, maxdepth); return exec_byte_code (fun, 0, 0, NULL); } diff --git a/src/lisp.h b/src/lisp.h index fb43bfa791..75f369f524 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -342,6 +342,7 @@ typedef EMACS_INT Lisp_Word; # define lisp_h_XIL(i) (i) # define lisp_h_XLP(o) ((void *) (uintptr_t) (o)) # endif +# define lisp_h_Qnil 0 #else # if LISP_WORDS_ARE_POINTERS # define lisp_h_XLI(o) ((EMACS_INT) (o).i) @@ -352,6 +353,7 @@ typedef EMACS_INT Lisp_Word; # define lisp_h_XIL(i) ((Lisp_Object) {i}) # define lisp_h_XLP(o) ((void *) (uintptr_t) (o).i) # endif +# define lisp_h_Qnil {0} #endif #define lisp_h_PSEUDOVECTORP(a,code) \ @@ -3173,12 +3175,12 @@ CHECK_SUBR (Lisp_Object x) /* This version of DEFUN declares a function prototype with the right arguments, so we can catch errors with maxargs at compile-time. */ -#define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ - SUBR_SECTION_ATTRIBUTE \ - static union Aligned_Lisp_Subr sname = \ - {{{ PVEC_SUBR << PSEUDOVECTOR_AREA_BITS }, \ - { .a ## maxargs = fnname }, \ - minargs, maxargs, lname, {intspec}, 0}}; \ +#define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ + SUBR_SECTION_ATTRIBUTE \ + static union Aligned_Lisp_Subr sname = \ + {{{ PVEC_SUBR << PSEUDOVECTOR_AREA_BITS }, \ + { .a ## maxargs = fnname }, \ + minargs, maxargs, lname, {intspec}, lisp_h_Qnil}}; \ Lisp_Object fnname /* defsubr (Sname); commit 4478f915374a497ec20b51f873ed1b65f22c27dc Author: Lars Ingebrigtsen Date: Tue Apr 19 13:48:06 2022 +0200 Revert prompting changes in viper-cmd * lisp/emulation/viper-cmd.el (viper-quote-region) (viper-read-string-with-history, viper-query-replace): Revert prompting changes done in 50512e3 -- the way viper prompts in command mode is special (bug#55007). diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el index 83944285e9..54838638d6 100644 --- a/lisp/emulation/viper-cmd.el +++ b/lisp/emulation/viper-cmd.el @@ -1783,7 +1783,7 @@ Undo previous insertion and inserts new." (do-not-change-default t)) (setq quote-str (viper-read-string-with-history - "Quote string" + "Quote string: " nil 'viper-quote-region-history ;; FIXME: Use comment-region. @@ -1992,17 +1992,24 @@ problems." #'viper-minibuffer-standard-hook (if (or (not (listp old)) (eq (car old) 'lambda)) (list old) old)))) - (val "")) + (val "") + (padding "") + temp-msg) (setq keymap (or keymap minibuffer-local-map) initial (or initial "") - viper-initial initial) + viper-initial initial + temp-msg (if default + (format "(default %s) " default) + "")) (setq viper-incomplete-ex-cmd nil) - (setq val (read-from-minibuffer (format-prompt prompt default) - nil - keymap nil history-var default)) - (setq minibuffer-setup-hook nil) + (setq val (read-from-minibuffer prompt + (concat temp-msg initial val padding) + keymap nil history-var)) + (setq minibuffer-setup-hook nil + padding (viper-array-to-string (this-command-keys)) + temp-msg "") ;; the following tries to be smart about what to put in history (if (not (string= val (car (symbol-value history-var)))) (push val (symbol-value history-var))) @@ -3815,7 +3822,7 @@ Null string will repeat previous search." (let (buffer buffer-name) (setq buffer-name (funcall viper-read-buffer-function - (format-prompt "Kill buffer" + (format "Kill buffer (%s): " (buffer-name (current-buffer))))) (setq buffer (if (null buffer-name) @@ -4161,8 +4168,8 @@ and regexp replace." (interactive) (let (str) (setq str (viper-read-string-with-history - (if viper-re-query-replace "Query replace regexp" - "Query replace") + (if viper-re-query-replace "Query replace regexp: " + "Query replace: ") nil ; no initial 'viper-replace1-history (car viper-replace1-history) ; default @@ -4177,7 +4184,7 @@ and regexp replace." (query-replace-regexp str (viper-read-string-with-history - (format-message "Query replace regexp `%s' with" str) + (format-message "Query replace regexp `%s' with: " str) nil ; no initial 'viper-replace1-history (car viper-replace1-history) ; default @@ -4185,7 +4192,7 @@ and regexp replace." (query-replace str (viper-read-string-with-history - (format-message "Query replace `%s' with" str) + (format-message "Query replace `%s' with: " str) nil ; no initial 'viper-replace1-history (car viper-replace1-history) ; default commit 843dc435f797e6804663ae074d3d88993c4cd8a4 Author: Lars Ingebrigtsen Date: Tue Apr 19 13:42:17 2022 +0200 Be more resilient against invalid headers in mml-generate-mime * lisp/gnus/mml.el (mml-generate-mime): Don't bug out when called with invalid headers (bug#55014). diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el index 5a52602506..093e582ea7 100644 --- a/lisp/gnus/mml.el +++ b/lisp/gnus/mml.el @@ -500,7 +500,8 @@ type detected." (when (and (consp (car cont)) (= (length cont) 1) content-type) - (setcdr (assq 'type (cdr (car cont))) content-type)) + (when-let ((spec (assq 'type (cdr (car cont))))) + (setcdr spec content-type))) (when (fboundp 'libxml-parse-html-region) (setq cont (mapcar #'mml-expand-all-html-into-multipart-related cont))) (prog1 commit 5df658a96a4bc7f8f96e3b2bf58dad32f81ce06a Author: Philip Kaludercic Date: Tue Apr 19 13:16:51 2022 +0200 Fix handling of intspecs as string by rcirc-define-command * rcirc.el (rcirc-define-command): Check if an interactive specification is a string, in which case it was to be wrapped in a list so that the result of its interpretation is passed as the first argument of the command resulting from the macro expansion. diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el index f34be6daf3..31888f3913 100644 --- a/lisp/net/rcirc.el +++ b/lisp/net/rcirc.el @@ -2616,15 +2616,22 @@ that, an interactive form can specified." (defun ,fn-name (,argument &optional process target) ,(concat documentation "\n\nNote: If PROCESS or TARGET are nil, the values given" - "\nby `rcirc-buffer-process' and `rcirc-target' will be used.") - (interactive (list ,interactive-spec)) + "\nby `rcirc-buffer-process' and `rcirc-target' will be used.") + (interactive ,(if (stringp interactive-spec) + ;; HACK: Necessary to wrap the result of + ;; the interactive spec in a list. + `(list (call-interactively + (lambda (&rest args) + (interactive ,interactive-spec) + args))) + `(list ,interactive-spec))) (unless (if (listp ,argument) (<= ,required (length ,argument) ,total) (string-match ,regexp ,argument)) (user-error "Malformed input (%s): %S" ',command ,argument)) (push ,(upcase (symbol-name command)) rcirc-pending-requests) (let ((process (or process (rcirc-buffer-process))) - (target (or target rcirc-target))) + (target (or target rcirc-target))) (ignore target process) (let (,@(cl-loop for i from 0 for arg in (delq '&optional arguments) commit 5fe75feafc706b16af2f1e47a77c8fe46efd348c Author: Po Lu Date: Tue Apr 19 18:51:28 2022 +0800 Fix `x-mouse-click-focus-ignore-position' for odd coincidences across displays * src/xterm.c (handle_one_xevent): Save the display alongside the next mouse click timeout. (x_delete_display): Clear that display here if applicable. (x_initialize): Likewise. diff --git a/src/xterm.c b/src/xterm.c index 3eecd5e204..03d5a503f8 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -756,6 +756,10 @@ static bool toolkit_scroll_bar_interaction; static Time ignore_next_mouse_click_timeout; +/* The display that ignore_next_mouse_click_timeout applies to. */ + +static struct x_display_info *mouse_click_timeout_display; + /* Used locally within XTread_socket. */ static int x_noop_count; @@ -15169,7 +15173,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, f = any; if (f && x_mouse_click_focus_ignore_position) - ignore_next_mouse_click_timeout = event->xmotion.time + 200; + { + ignore_next_mouse_click_timeout = event->xmotion.time + 200; + mouse_click_timeout_display = dpyinfo; + } /* EnterNotify counts as mouse movement, so update things that depend on mouse position. */ @@ -16046,7 +16053,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, && event->xbutton.button < 9 && f) { - if (ignore_next_mouse_click_timeout) + if (ignore_next_mouse_click_timeout + && dpyinfo == mouse_click_timeout_display) { if (event->type == ButtonPress && event->xbutton.time > ignore_next_mouse_click_timeout) @@ -16115,7 +16123,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (! popup_activated ()) #endif { - if (ignore_next_mouse_click_timeout) + if (ignore_next_mouse_click_timeout + && dpyinfo == mouse_click_timeout_display) { if (event->type == ButtonPress && event->xbutton.time > ignore_next_mouse_click_timeout) @@ -16412,7 +16421,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, f = any; if (f && x_mouse_click_focus_ignore_position) - ignore_next_mouse_click_timeout = xi_event->time + 200; + { + ignore_next_mouse_click_timeout = xev->time + 200; + mouse_click_timeout_display = dpyinfo; + } /* EnterNotify counts as mouse movement, so update things that depend on mouse position. */ @@ -23578,6 +23590,9 @@ x_delete_display (struct x_display_info *dpyinfo) if (next_noop_dpyinfo == dpyinfo) next_noop_dpyinfo = dpyinfo->next; + if (mouse_click_timeout_display == dpyinfo) + mouse_click_timeout_display = NULL; + if (x_display_list == dpyinfo) x_display_list = dpyinfo->next; else @@ -23865,6 +23880,7 @@ x_initialize (void) x_noop_count = 0; any_help_event_p = false; ignore_next_mouse_click_timeout = 0; + mouse_click_timeout_display = NULL; #ifdef USE_GTK current_count = -1; commit 237f4f9295d17d15c58ffce9728b72aa1e529172 Author: Eli Zaretskii Date: Tue Apr 19 12:50:01 2022 +0300 Fix dimensions of console window of restarted Emacs on MS-Windows * src/w32.c (get_console_font_size): New function. (w32_reexec_emacs): Call 'get_console_font_size' to set up the dimensions of the restarted Emacs's console window to the same values as that of the original Emacs. diff --git a/src/w32.c b/src/w32.c index 74923ffece..a8f69565d6 100644 --- a/src/w32.c +++ b/src/w32.c @@ -348,6 +348,7 @@ static BOOL g_b_init_reg_open_key_ex_w; static BOOL g_b_init_reg_query_value_ex_w; static BOOL g_b_init_expand_environment_strings_w; static BOOL g_b_init_get_user_default_ui_language; +static BOOL g_b_init_get_console_font_size; BOOL g_b_init_compare_string_w; BOOL g_b_init_debug_break_process; @@ -537,6 +538,18 @@ typedef LONG (WINAPI *RegQueryValueExW_Proc) (HKEY,LPCWSTR,LPDWORD,LPDWORD,LPBYT typedef DWORD (WINAPI *ExpandEnvironmentStringsW_Proc) (LPCWSTR,LPWSTR,DWORD); typedef LANGID (WINAPI *GetUserDefaultUILanguage_Proc) (void); +typedef COORD (WINAPI *GetConsoleFontSize_Proc) (HANDLE, DWORD); +typedef struct +{ + DWORD nFont; + COORD dwFontSize; +} CONSOLE_FONT_INFO; +typedef BOOL (WINAPI *GetCurrentConsoleFont_Proc) ( + HANDLE, + BOOL, + CONSOLE_FONT_INFO *); + + /* ** A utility function ** */ static BOOL is_windows_9x (void) @@ -10618,6 +10631,47 @@ realpath (const char *file_name, char *resolved_name) return xstrdup (tgt); } +static void +get_console_font_size (HANDLE hscreen, int *font_width, int *font_height) +{ + static GetCurrentConsoleFont_Proc s_pfn_Get_Current_Console_Font = NULL; + static GetConsoleFontSize_Proc s_pfn_Get_Console_Font_Size = NULL; + + /* Default guessed values, for when we cannot obtain the actual ones. */ + *font_width = 8; + *font_height = 12; + + if (!is_windows_9x ()) + { + if (g_b_init_get_console_font_size == 0) + { + HMODULE hm_kernel32 = LoadLibrary ("Kernel32.dll"); + if (hm_kernel32) + { + s_pfn_Get_Current_Console_Font = (GetCurrentConsoleFont_Proc) + get_proc_addr (hm_kernel32, "GetCurrentConsoleFont"); + s_pfn_Get_Console_Font_Size = (GetConsoleFontSize_Proc) + get_proc_addr (hm_kernel32, "GetConsoleFontSize"); + } + g_b_init_get_console_font_size = 1; + } + } + if (s_pfn_Get_Current_Console_Font && s_pfn_Get_Console_Font_Size) + { + CONSOLE_FONT_INFO font_info; + + if (s_pfn_Get_Current_Console_Font (hscreen, FALSE, &font_info)) + { + COORD font_size = s_pfn_Get_Console_Font_Size (hscreen, + font_info.nFont); + if (font_size.X > 0) + *font_width = font_size.X; + if (font_size.Y > 0) + *font_height = font_size.Y; + } + } +} + /* A replacement for Posix execvp, used to restart Emacs. This is needed because the low-level Windows API to start processes accepts the command-line arguments as a single string, so we cannot safely @@ -10642,18 +10696,27 @@ w32_reexec_emacs (char *cmd_line, const char *wdir) if (screen_handle != INVALID_HANDLE_VALUE && GetConsoleScreenBufferInfo (screen_handle, &screen_info)) { + int font_width, font_height; + /* Make the restarted Emacs's console window the same - dimensions as ours. FIXME: for some reason this doesn't - seem to work! */ - si.dwFlags |= STARTF_USECOUNTCHARS; + dimensions as ours. */ si.dwXCountChars = screen_info.dwSize.X; si.dwYCountChars = screen_info.dwSize.Y; + get_console_font_size (screen_handle, &font_width, &font_height); + si.dwXSize = + (screen_info.srWindow.Right - screen_info.srWindow.Left + 1) + * font_width; + si.dwYSize = + (screen_info.srWindow.Bottom - screen_info.srWindow.Top + 1) + * font_height; + si.dwFlags |= STARTF_USESIZE | STARTF_USECOUNTCHARS; } /* This is a kludge: it causes the restarted "emacs -nw" to have a new console window created for it, and that new window might have different (default) properties, not the ones of the parent process's console window. But without this, - restarting Emacs in the -nw mode simply doesn't work. + restarting Emacs in the -nw mode simply doesn't work, + probably because the parent's console is still in use. FIXME! */ dwCreationFlags = CREATE_NEW_CONSOLE; } @@ -10742,6 +10805,7 @@ globals_of_w32 (void) g_b_init_compare_string_w = 0; g_b_init_debug_break_process = 0; g_b_init_get_user_default_ui_language = 0; + g_b_init_get_console_font_size = 0; num_of_processors = 0; /* The following sets a handler for shutdown notifications for console apps. This actually applies to Emacs in both console and commit d168decab4a03cd48b8b96257c36ffa575c720e6 Author: Po Lu Date: Tue Apr 19 15:47:34 2022 +0800 Deal with Motif drag window related races * src/xterm.c (xm_drag_window_error_handler): New function. (xm_get_drag_window): If a drag window was created and we have the temp display grabbed, use that instead. diff --git a/src/xterm.c b/src/xterm.c index c4652c19c6..3eecd5e204 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1366,10 +1366,16 @@ xm_write_drag_initiator_info (Display *dpy, Window wdesc, PropModeReplace, (unsigned char *) buf, 8); } +static int +xm_drag_window_error_handler (Display *display, XErrorEvent *event) +{ + return 0; +} + static Window xm_get_drag_window (struct x_display_info *dpyinfo) { - Atom actual_type; + Atom actual_type, _MOTIF_DRAG_WINDOW; int rc, actual_format; unsigned long nitems, bytes_remaining; unsigned char *tmp_data = NULL; @@ -1377,6 +1383,7 @@ xm_get_drag_window (struct x_display_info *dpyinfo) XSetWindowAttributes attrs; XWindowAttributes wattrs; Display *temp_display; + void *old_handler; drag_window = None; rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window, @@ -1420,16 +1427,44 @@ xm_get_drag_window (struct x_display_info *dpyinfo) XGrabServer (temp_display); XSetCloseDownMode (temp_display, RetainPermanent); - attrs.override_redirect = True; - drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display), - -1, -1, 1, 1, 0, CopyFromParent, InputOnly, - CopyFromParent, CWOverrideRedirect, &attrs); - XChangeProperty (temp_display, DefaultRootWindow (temp_display), - XInternAtom (temp_display, - "_MOTIF_DRAG_WINDOW", False), - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &drag_window, 1); + + /* We can't use XErrorHandler since it's not in the Xlib + specification, and Emacs tries to be portable. */ + old_handler = (void *) XSetErrorHandler (xm_drag_window_error_handler); + + _MOTIF_DRAG_WINDOW = XInternAtom (temp_display, + "_MOTIF_DRAG_WINDOW", False); + + /* Some other program might've created a drag window between now + and when we first looked. Use that if it exists. */ + + tmp_data = NULL; + rc = XGetWindowProperty (temp_display, DefaultRootWindow (temp_display), + _MOTIF_DRAG_WINDOW, 0, 1, False, XA_WINDOW, + &actual_type, &actual_format, &nitems, + &bytes_remaining, &tmp_data) == Success; + + if (rc && actual_type == XA_WINDOW + && actual_format == 32 && nitems == 1 + && tmp_data) + drag_window = *(Window *) tmp_data; + + if (tmp_data) + XFree (tmp_data); + + if (drag_window == None) + { + attrs.override_redirect = True; + drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display), + -1, -1, 1, 1, 0, CopyFromParent, InputOnly, + CopyFromParent, CWOverrideRedirect, &attrs); + XChangeProperty (temp_display, DefaultRootWindow (temp_display), + _MOTIF_DRAG_WINDOW, XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &drag_window, 1); + } + XCloseDisplay (temp_display); + XSetErrorHandler (old_handler); /* Make sure the drag window created is actually valid for the current display, and the XOpenDisplay above didn't