commit f599b58afebcbc5a0e5bde9358eca6bba51ab81a (HEAD, refs/remotes/origin/master) Author: Po Lu Date: Wed Mar 9 06:58:01 2022 +0000 Don't update Haiku menu bar if nothing changed * haikumenu.c (set_frame_menubar): If Lisp-level contents didn't change, refrain from actually updating the menu bar. diff --git a/src/haikumenu.c b/src/haikumenu.c index 2f75a5dd03..8da00ffcb0 100644 --- a/src/haikumenu.c +++ b/src/haikumenu.c @@ -508,6 +508,10 @@ set_frame_menubar (struct frame *f, bool deep_p) int previous_menu_items_used = f->menu_bar_items_used; Lisp_Object *previous_items = alloca (previous_menu_items_used * sizeof *previous_items); + int count; + ptrdiff_t subitems, i; + int *submenu_start, *submenu_end, *submenu_n_panes; + Lisp_Object *submenu_names; XSETFRAME (Vmenu_updating_frame, f); @@ -552,6 +556,7 @@ set_frame_menubar (struct frame *f, bool deep_p) do always reinitialize them. */ if (first_time_p) previous_menu_items_used = 0; + buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contents; specbind (Qinhibit_quit, Qt); /* Don't let the debugger step into this code @@ -587,29 +592,23 @@ set_frame_menubar (struct frame *f, bool deep_p) /* Fill in menu_items with the current menu bar contents. This can evaluate Lisp code. */ save_menu_items (); + menu_items = f->menu_bar_vector; menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0; - init_menu_items (); - int i; - int count = BMenu_count_items (mbar); - int subitems = ASIZE (items) / 4; - - int *submenu_start, *submenu_end, *submenu_n_panes; - Lisp_Object *submenu_names; - + subitems = ASIZE (items) / 4; submenu_start = alloca ((subitems + 1) * sizeof *submenu_start); submenu_end = alloca (subitems * sizeof *submenu_end); submenu_n_panes = alloca (subitems * sizeof *submenu_n_panes); submenu_names = alloca (subitems * sizeof (Lisp_Object)); - for (i = 0; i < subitems; ++i) + init_menu_items (); + for (i = 0; i < subitems; i++) { Lisp_Object key, string, maps; - key = AREF (items, i * 4); - string = AREF (items, i * 4 + 1); - maps = AREF (items, i * 4 + 2); - + key = AREF (items, 4 * i); + string = AREF (items, 4 * i + 1); + maps = AREF (items, 4 * i + 2); if (NILP (string)) break; @@ -617,16 +616,44 @@ set_frame_menubar (struct frame *f, bool deep_p) string = ENCODE_UTF_8 (string); submenu_start[i] = menu_items_used; + menu_items_n_panes = 0; parse_single_submenu (key, string, maps); submenu_n_panes[i] = menu_items_n_panes; + submenu_end[i] = menu_items_used; submenu_names[i] = string; } - finish_menu_items (); + submenu_start[i] = -1; + finish_menu_items (); + + set_buffer_internal_1 (prev); + + FRAME_OUTPUT_DATA (f)->menu_up_to_date_p = 1; + + /* If there has been no change in the Lisp-level contents + of the menu bar, skip redisplaying it. Just exit. */ + + /* Compare the new menu items with the ones computed last time. */ + for (i = 0; i < previous_menu_items_used; i++) + if (menu_items_used == i + || (!EQ (previous_items[i], AREF (menu_items, i)))) + break; + if (i == menu_items_used && i == previous_menu_items_used && i != 0) + { + /* The menu items have not changed. Don't bother updating + the menus in any form, since it would be a no-op. */ + discard_menu_items (); + unbind_to (specpdl_count, Qnil); + return; + } + + /* Convert menu_items into widget_value trees + to display the menu. This cannot evaluate Lisp code. */ block_input (); + count = BMenu_count_items (mbar); for (i = 0; submenu_start[i] >= 0; ++i) { void *mn = NULL; @@ -642,12 +669,12 @@ set_frame_menubar (struct frame *f, bool deep_p) } unblock_input (); - set_buffer_internal_1 (prev); - - FRAME_OUTPUT_DATA (f)->menu_up_to_date_p = 1; + /* The menu items are different, so store them in the frame. */ fset_menu_bar_vector (f, menu_items); f->menu_bar_items_used = menu_items_used; } + + /* This undoes save_menu_items. */ unbind_to (specpdl_count, Qnil); } commit e8d35b98bb2fd685c83bb9e9da60c00eb7967d5d Author: Po Lu Date: Wed Mar 9 03:50:16 2022 +0000 Fix flicker during frame resize on Haiku * haikuterm.c (haiku_update_end): Call BWindow_Flush directly. (haiku_set_vertical_scroll_bar): Stop calling flush_frame. (haiku_flush): Only flip buffer of tooltip frames. diff --git a/src/haikuterm.c b/src/haikuterm.c index 3950e45fe9..413eedd668 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -1221,7 +1221,7 @@ static void haiku_update_end (struct frame *f) { MOUSE_HL_INFO (f)->mouse_face_defer = false; - flush_frame (f); + BWindow_Flush (FRAME_HAIKU_WINDOW (f)); } static void @@ -2287,7 +2287,6 @@ haiku_set_vertical_scroll_bar (struct window *w, bar->width, bar->height); BView_move_frame (bar->scroll_bar, left, top, left + width - 1, top + height - 1); - flush_frame (WINDOW_XFRAME (w)); BView_publish_scroll_bar (view, left, top, width, height); bar->left = left; bar->top = top; @@ -2515,7 +2514,7 @@ haiku_flush (struct frame *f) { /* This is needed for tooltip frames to work properly with double buffering. */ - if (FRAME_DIRTY_P (f)) + if (FRAME_DIRTY_P (f) && FRAME_TOOLTIP_P (f)) haiku_flip_buffers (f); if (FRAME_VISIBLE_P (f) && !FRAME_TOOLTIP_P (f)) commit 51784551c57a70ff9236d1fb980bc25d6e4755f9 Author: Po Lu Date: Wed Mar 9 11:29:05 2022 +0800 Fix the MS-DOS build * sed1v2.inp: Update for recent changes. diff --git a/msdos/sed1v2.inp b/msdos/sed1v2.inp index 86f00c024a..cc29ad0281 100644 --- a/msdos/sed1v2.inp +++ b/msdos/sed1v2.inp @@ -50,6 +50,7 @@ s/\.h\.in/.h-in/ /^LIB_ACL *=/s/@LIB_ACL@// /^LIB_EACCESS *=/s/@LIB_EACCESS@// /^LIB_FDATASYNC *=/s/@LIB_FDATASYNC@// +/^LIB_NANOSLEEP *=/s/@LIB_NANOSLEEP@// s/ *@LIBTIFF@// s/ *@LIBJPEG@// s/ *@LIBPNG@// commit 9cf69e1171d0621cf464794b4a6adcb766c99b54 Author: Po Lu Date: Wed Mar 9 03:21:36 2022 +0000 Improve handling of tooltips inside menus on Haiku * src/haiku_support.cc (BMenu_run): Make `process_pending_signals_function' return a struct timespec. * src/haiku_support.h: Update prototypes. * src/haikumenu.c (haiku_process_pending_signals_for_menu): Return result of `timer_run'. * src/haikuterm.c (haiku_flush): Flip buffers if frame is dirty. diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 057464c908..2f2adfd8f8 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -2697,7 +2697,7 @@ BMenu_run (void *menu, int x, int y, void (*run_help_callback) (void *, void *), void (*block_input_function) (void), void (*unblock_input_function) (void), - void (*process_pending_signals_function) (void), + struct timespec (*process_pending_signals_function) (void), void *run_help_callback_data) { BPopUpMenu *mn = (BPopUpMenu *) menu; @@ -2705,10 +2705,12 @@ BMenu_run (void *menu, int x, int y, void *buf; void *ptr = NULL; struct be_popup_menu_data data; - struct object_wait_info infos[2]; + struct object_wait_info infos[3]; struct haiku_menu_bar_help_event *event; BMessage *msg; ssize_t stat; + struct timespec next_time; + bigtime_t timeout; block_input_function (); port_popup_menu_to_emacs = create_port (1800, "popup menu port"); @@ -2733,6 +2735,10 @@ BMenu_run (void *menu, int x, int y, (void *) &data); infos[1].type = B_OBJECT_TYPE_THREAD; infos[1].events = B_EVENT_INVALID; + + infos[2].object = port_application_to_emacs; + infos[2].type = B_OBJECT_TYPE_PORT; + infos[2].events = B_EVENT_READ; unblock_input_function (); if (infos[1].object < B_OK) @@ -2749,10 +2755,16 @@ BMenu_run (void *menu, int x, int y, while (true) { - process_pending_signals_function (); + next_time = process_pending_signals_function (); + + if (next_time.tv_nsec < 0) + timeout = 100000; + else + timeout = (next_time.tv_sec * 1000000 + + next_time.tv_nsec / 1000); - if ((stat = wait_for_objects_etc ((object_wait_info *) &infos, 2, - B_RELATIVE_TIMEOUT, 10000)) < B_OK) + if ((stat = wait_for_objects_etc ((object_wait_info *) &infos, 3, + B_RELATIVE_TIMEOUT, timeout)) < B_OK) { if (stat == B_INTERRUPTED || stat == B_TIMED_OUT) continue; @@ -2792,6 +2804,7 @@ BMenu_run (void *menu, int x, int y, infos[0].events = B_EVENT_READ; infos[1].events = B_EVENT_INVALID; + infos[2].events = B_EVENT_READ; } } diff --git a/src/haiku_support.h b/src/haiku_support.h index 04079edbbc..fb86372c4f 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -744,7 +744,7 @@ extern "C" void (*run_help_callback) (void *, void *), void (*block_input_function) (void), void (*unblock_input_function) (void), - void (*process_pending_signals_function) (void), + struct timespec (*process_pending_signals_function) (void), void *run_help_callback_data); extern void diff --git a/src/haikumenu.c b/src/haikumenu.c index 74328086d6..2f75a5dd03 100644 --- a/src/haikumenu.c +++ b/src/haikumenu.c @@ -340,13 +340,12 @@ haiku_menu_show_help (void *help, void *data) show_help_echo (Qnil, Qnil, Qnil, Qnil); } -static void +static struct timespec haiku_process_pending_signals_for_menu (void) { process_pending_signals (); - input_pending = false; - detect_input_pending_run_timers (true); + return timer_check (); } Lisp_Object diff --git a/src/haikuterm.c b/src/haikuterm.c index 633e87fd43..3950e45fe9 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -2513,7 +2513,12 @@ haiku_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, static void haiku_flush (struct frame *f) { - if (FRAME_VISIBLE_P (f)) + /* This is needed for tooltip frames to work properly with double + buffering. */ + if (FRAME_DIRTY_P (f)) + haiku_flip_buffers (f); + + if (FRAME_VISIBLE_P (f) && !FRAME_TOOLTIP_P (f)) BWindow_Flush (FRAME_HAIKU_WINDOW (f)); } commit 6e66d1f90a078099911c52b5ed00b7385d095957 Author: Paul Eggert Date: Tue Mar 8 18:46:47 2022 -0800 Decouple mod-test.c from Gnulib mod-test.c should not use Gnulib code, as that creates unnecessary coupling between Emacs internals and this test module. Also Gnulib code is compiled without -fPIC whereas mod-test.c needs -fPIC and recompiling Gnulib with -fPIC would be too painful. * src/Makefile.in (LIB_NANOSLEEP): New macro. (LIBES): Use it. * test/Makefile.in (REPLACE_FREE, FREE_SOURCE_0, FREE_SOURCE_0): Remove. All uses removed. (LIB_CLOCK_GETTIME, LIB_NANOSLEEP): New macros. (MODULE_CFLAGS): Do not -I from lib as that would include Gnulib modifications to standard .h files (e.g., "#define nanosleep rpl_nanosleep") and we don’t want the Gnulib replacements. Instead, for gmp.h (on platforms lacking ) simply '-I.' with a suitable gmp.h. (gmp.h): New rule to create a suitable gmp.h. ($(test_module)): Depend on config.h since the code uses config.h. Depend on gmp.h if we need to create a suitable one. If compiling mini-gmp.h, compile the original one and not the Emacs-specific one, to lessen coupling with Emacs internals. Link with LIB_CLOCK_GETTIME and LIB_NANOSLEEP. (clean): Remove gmp.h. * test/src/emacs-module-resources/mod-test.c: Don’t include timespec.h. All uses of timespec.h APIs changed to use system-supplied APIs. Change _Static_assert to plain assert, so that we needn’t rely on Gnulib’s _Static_assert. (timespec_le) [CLOCK_REALTIME]: New function. Change use of timespec_cmp changed to use this instead. (Fmod_test_sleep_until, Fmod_test_nanoseconds): Define these functions and their Lisp names mod-test-sleep-until and mod-test-nanoseconds only if CLOCK_REALTIME, since they now won’t work on platforms lacking CLOCK_REALTIME. (Fmod_test_nanoseconds): Just use _Static_assert since it should work on all platforms. * test/src/emacs-module-tests.el (mod-test-sleep-until) (mod-test-nanoseconds, mod-test-double): Skip test if the corresponding functione is not defined. diff --git a/src/Makefile.in b/src/Makefile.in index 3353fb16d7..2b7c4bb316 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -146,6 +146,7 @@ M17N_FLT_LIBS = @M17N_FLT_LIBS@ LIB_ACL=@LIB_ACL@ LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@ LIB_EACCESS=@LIB_EACCESS@ +LIB_NANOSLEEP=@LIB_NANOSLEEP@ LIB_TIMER_TIME=@LIB_TIMER_TIME@ DBUS_CFLAGS = @DBUS_CFLAGS@ @@ -548,7 +549,7 @@ lisp = $(addprefix ${lispsource}/,${shortlisp}) LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(PGTK_LIBS) $(LIBX_BASE) $(LIBIMAGE) \ $(LIBX_OTHER) $(LIBSOUND) \ $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \ - $(WEBKIT_LIBS) \ + $(LIB_NANOSLEEP) $(WEBKIT_LIBS) \ $(LIB_EACCESS) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \ $(XDBE_LIBS) $(XSYNC_LIBS) \ diff --git a/test/Makefile.in b/test/Makefile.in index 79d3dcf92f..3b6e116e65 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -49,8 +49,6 @@ SEPCHAR = @SEPCHAR@ HAVE_NATIVE_COMP = @HAVE_NATIVE_COMP@ -REPLACE_FREE = @REPLACE_FREE@ - -include ${top_builddir}/src/verbose.mk # We never change directory before running Emacs, so a relative file @@ -265,27 +263,29 @@ endif GMP_H = @GMP_H@ LIBGMP = @LIBGMP@ +LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@ +LIB_NANOSLEEP = @LIB_NANOSLEEP@ -MODULE_CFLAGS = -I../src -I$(srcdir)/../src -I../lib -I$(srcdir)/../lib \ +MODULE_CFLAGS = $(and $(GMP_H),-I.) -I../src -I$(srcdir)/../src \ $(FPIC_CFLAGS) $(PROFILING_CFLAGS) \ $(WARN_CFLAGS) $(WERROR_CFLAGS) $(CFLAGS) +gmp.h: + echo '#include "$(srcdir)/../lib/mini-gmp.h"' >$@ + test_module = $(test_module_dir)/mod-test${SO} src/emacs-module-tests.log src/emacs-module-tests.elc: $(test_module) -FREE_SOURCE_0 = -FREE_SOURCE_1 = $(srcdir)/../lib/free.c - # In the compilation command, we can't use any object or archive file # as source because those are not compiled with -fPIC. Therefore we # use only source files. -$(test_module): $(test_module:${SO}=.c) ../src/emacs-module.h +$(test_module): $(test_module:${SO}=.c) ../src/emacs-module.h \ + ../src/config.h $(and $(GMP_H),gmp.h) $(AM_V_CCLD)${MKDIR_P} $(dir $@) $(AM_V_at)$(CC) -shared $(CPPFLAGS) $(MODULE_CFLAGS) $(LDFLAGS) \ -o $@ $< $(LIBGMP) \ - $(and $(GMP_H),$(srcdir)/../lib/mini-gmp-gnulib.c) \ - $(FREE_SOURCE_$(REPLACE_FREE)) \ - ../lib/libgnu.a + $(and $(GMP_H),$(srcdir)/../lib/mini-gmp.c) \ + $(LIB_CLOCK_GETTIME) $(LIB_NANOSLEEP) endif src/emacs-tests.log: ../lib-src/seccomp-filter.c @@ -345,7 +345,7 @@ clean: find . '(' -name '*.xml' -a ! -path '*resources*' ')' $(FIND_DELETE) rm -f ${srcdir}/lisp/gnus/mml-sec-resources/random_seed rm -f $(test_module_dir)/*.o $(test_module_dir)/*.so \ - $(test_module_dir)/*.dll + $(test_module_dir)/*.dll gmp.h bootstrap-clean: clean find $(srcdir) -name '*.elc' $(FIND_DELETE) diff --git a/test/src/emacs-module-resources/mod-test.c b/test/src/emacs-module-resources/mod-test.c index 015c1efd97..187af821c2 100644 --- a/test/src/emacs-module-resources/mod-test.c +++ b/test/src/emacs-module-resources/mod-test.c @@ -47,8 +47,6 @@ uintptr_t _beginthread (void (__cdecl *)(void *), unsigned, void *); #include #include -#include "timespec.h" - int plugin_is_GPL_compatible; #if INTPTR_MAX <= 0 @@ -74,9 +72,6 @@ int plugin_is_GPL_compatible; # error "INTPTR_MAX too large" #endif -/* Smoke test to verify that EMACS_LIMB_MAX is defined. */ -_Static_assert (0 < EMACS_LIMB_MAX, "EMACS_LIMB_MAX missing or incorrect"); - /* Always return symbol 't'. */ static emacs_value Fmod_test_return_t (emacs_env *env, ptrdiff_t nargs, emacs_value args[], @@ -422,6 +417,16 @@ signal_errno (emacs_env *env, const char *function) signal_system_error (env, errno, function); } +#ifdef CLOCK_REALTIME + +/* Whether A <= B. */ +static bool +timespec_le (struct timespec a, struct timespec b) +{ + return (a.tv_sec < b.tv_sec + || (a.tv_sec == b.tv_sec && a.tv_nsec <= b.tv_nsec)); +} + /* A long-running operation that occasionally calls `should_quit' or `process_input'. */ @@ -434,11 +439,13 @@ Fmod_test_sleep_until (emacs_env *env, ptrdiff_t nargs, emacs_value *args, if (env->non_local_exit_check (env)) return NULL; const bool process_input = env->is_not_nil (env, args[1]); - const struct timespec amount = make_timespec(0, 10000000); + const struct timespec amount = { .tv_nsec = 10000000 }; while (true) { - const struct timespec now = current_timespec (); - if (timespec_cmp (now, until) >= 0) + struct timespec now; + if (clock_gettime (CLOCK_REALTIME, &now) != 0) + return NULL; + if (timespec_le (until, now)) break; if (nanosleep (&amount, NULL) && errno != EINTR) { @@ -452,6 +459,7 @@ Fmod_test_sleep_until (emacs_env *env, ptrdiff_t nargs, emacs_value *args, } return env->intern (env, "finished"); } +#endif static emacs_value Fmod_test_add_nanosecond (emacs_env *env, ptrdiff_t nargs, emacs_value *args, @@ -553,6 +561,7 @@ make_big_integer (emacs_env *env, const mpz_t value) return result; } +#ifdef CLOCK_REALTIME static emacs_value Fmod_test_nanoseconds (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void *data) { assert (nargs == 1); @@ -560,11 +569,6 @@ Fmod_test_nanoseconds (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void mpz_t nanoseconds; assert (LONG_MIN <= time.tv_sec && time.tv_sec <= LONG_MAX); mpz_init_set_si (nanoseconds, time.tv_sec); -#ifdef __MINGW32__ - _Static_assert (1000000000 <= ULONG_MAX, "unsupported architecture"); -#else - static_assert (1000000000 <= ULONG_MAX, "unsupported architecture"); -#endif mpz_mul_ui (nanoseconds, nanoseconds, 1000000000); assert (0 <= time.tv_nsec && time.tv_nsec <= ULONG_MAX); mpz_add_ui (nanoseconds, nanoseconds, time.tv_nsec); @@ -572,6 +576,7 @@ Fmod_test_nanoseconds (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void mpz_clear (nanoseconds); return result; } +#endif static emacs_value Fmod_test_double (emacs_env *env, ptrdiff_t nargs, emacs_value *args, @@ -631,7 +636,7 @@ sleep_for_half_second (void) #ifdef WINDOWSNT Sleep (500); #else - const struct timespec sleep = {0, 500000000}; + const struct timespec sleep = { .tv_nsec = 500000000 }; if (nanosleep (&sleep, NULL) != 0) perror ("nanosleep"); #endif @@ -763,6 +768,11 @@ bind_function (emacs_env *env, const char *name, emacs_value Sfun) int emacs_module_init (struct emacs_runtime *ert) { + /* These smoke tests don't use _Static_assert because too many + compilers lack support for _Static_assert. */ + assert (0 < EMACS_LIMB_MAX); + assert (1000000000 <= ULONG_MAX); + /* Check that EMACS_MAJOR_VERSION is defined and an integral constant. */ char dummy[EMACS_MAJOR_VERSION]; @@ -815,9 +825,13 @@ emacs_module_init (struct emacs_runtime *ert) DEFUN ("mod-test-invalid-load", Fmod_test_invalid_load, 0, 0, NULL, NULL); DEFUN ("mod-test-invalid-finalizer", Fmod_test_invalid_finalizer, 0, 0, NULL, NULL); +#ifdef CLOCK_REALTIME DEFUN ("mod-test-sleep-until", Fmod_test_sleep_until, 2, 2, NULL, NULL); +#endif DEFUN ("mod-test-add-nanosecond", Fmod_test_add_nanosecond, 1, 1, NULL, NULL); +#ifdef CLOCK_REALTIME DEFUN ("mod-test-nanoseconds", Fmod_test_nanoseconds, 1, 1, NULL, NULL); +#endif DEFUN ("mod-test-double", Fmod_test_double, 1, 1, NULL, NULL); DEFUN ("mod-test-make-function-with-finalizer", Fmod_test_make_function_with_finalizer, 0, 0, NULL, NULL); diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el index ec83f91f00..1099fd0467 100644 --- a/test/src/emacs-module-tests.el +++ b/test/src/emacs-module-tests.el @@ -336,6 +336,7 @@ Return A + B (ert-deftest mod-test-sleep-until () "Check that `mod-test-sleep-until' either returns normally or quits. Interactively, you can try hitting \\[keyboard-quit] to quit." + (skip-unless (fboundp 'mod-test-sleep-until)) (dolist (arg '(nil t)) ;; Guard against some caller setting `inhibit-quit'. (with-local-quit @@ -390,6 +391,7 @@ Interactively, you can try hitting \\[keyboard-quit] to quit." (ert-deftest mod-test-nanoseconds () "Test truncation when converting to `struct timespec'." + (skip-unless (fboundp 'mod-test-nanoseconds)) (dolist (test-case '((0 . 0) (-1 . -1000000000) ((1 . 1000000000) . 1) @@ -408,6 +410,7 @@ Interactively, you can try hitting \\[keyboard-quit] to quit." (should (= (mod-test-nanoseconds input) expected)))))) (ert-deftest mod-test-double () + (skip-unless (fboundp 'mod-test-double)) (dolist (input (list 0 1 2 -1 42 12345678901234567890 most-positive-fixnum (1+ most-positive-fixnum) most-negative-fixnum (1- most-negative-fixnum))) commit ec35e2621a945797cc4978ebf2e0fe0b0f436705 Author: Paul Eggert Date: Tue Mar 8 18:46:47 2022 -0800 Do not include from This is because mod-test.c shouldn’t use source code from lib, but it does need to include . * lib-src/ebrowse.c, lib-src/emacsclient.c, lib-src/etags.c: * lib-src/make-docfile.c, lib-src/movemail.c: * lib-src/seccomp-filter.c, src/dynlib.h, src/lisp.h: * src/syssignal.h, src/sysstdio.h, src/systhread.h, src/tparam.h: Include . * src/conf_post.h: Do not include . All uses of attribute.h macros replaced with their _GL_ equivalents. diff --git a/lib-src/ebrowse.c b/lib-src/ebrowse.c index ac7e790187..b77572734f 100644 --- a/lib-src/ebrowse.c +++ b/lib-src/ebrowse.c @@ -26,6 +26,7 @@ along with GNU Emacs. If not, see . */ #include #include +#include #include #include #include diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 365e803e1c..7406ef3490 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c @@ -80,6 +80,7 @@ char *w32_getenv (const char *); #include #include +#include #include #include #include diff --git a/lib-src/etags.c b/lib-src/etags.c index aa5bc8839d..65b9fae8d5 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c @@ -112,6 +112,7 @@ University of California, as described above. */ # define O_CLOEXEC O_NOINHERIT #endif /* WINDOWSNT */ +#include #include #include #include diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c index f42b1988a2..d2d4b1d277 100644 --- a/lib-src/make-docfile.c +++ b/lib-src/make-docfile.c @@ -42,6 +42,7 @@ along with GNU Emacs. If not, see . */ #include #include +#include #include #include #include diff --git a/lib-src/movemail.c b/lib-src/movemail.c index 888688f90b..aa3c15e72e 100644 --- a/lib-src/movemail.c +++ b/lib-src/movemail.c @@ -69,6 +69,7 @@ along with GNU Emacs. If not, see . */ #include #include +#include #include #include "syswait.h" diff --git a/lib-src/seccomp-filter.c b/lib-src/seccomp-filter.c index b515851010..9f0de7d64f 100644 --- a/lib-src/seccomp-filter.c +++ b/lib-src/seccomp-filter.c @@ -59,7 +59,8 @@ variants of those files that can be used to sandbox Emacs before #include #include -#include "verify.h" +#include +#include #ifndef ARCH_CET_STATUS #define ARCH_CET_STATUS 0x3001 diff --git a/src/conf_post.h b/src/conf_post.h index dd350b8dc8..5108e44efb 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -32,13 +32,11 @@ along with GNU Emacs. If not, see . */ /* To help make dependencies clearer elsewhere, this file typically does not #include other files. The exceptions are stdbool.h because it is unlikely to interfere with configuration and bool is - such a core part of the C language, attribute.h because its - ATTRIBUTE_* macros are used here, and ms-w32.h (DOS_NT + such a core part of the C language, and ms-w32.h (DOS_NT only) because it historically was included here and changing that would take some work. */ #include -#include #if defined WINDOWSNT && !defined DEFER_MS_W32_H # include @@ -279,8 +277,8 @@ extern void _DebPrint (const char *fmt, ...); extern char *emacs_getenv_TZ (void); extern int emacs_setenv_TZ (char const *); -#define NO_INLINE ATTRIBUTE_NOINLINE -#define EXTERNALLY_VISIBLE ATTRIBUTE_EXTERNALLY_VISIBLE +#define NO_INLINE _GL_ATTRIBUTE_NOINLINE +#define EXTERNALLY_VISIBLE _GL_ATTRIBUTE_EXTERNALLY_VISIBLE #if GNUC_PREREQ (4, 4, 0) && defined __GLIBC_MINOR__ # define PRINTF_ARCHETYPE __gnu_printf__ @@ -310,9 +308,9 @@ extern int emacs_setenv_TZ (char const *); # define PRINTF_ARCHETYPE __printf__ #endif #define ATTRIBUTE_FORMAT_PRINTF(string_index, first_to_check) \ - ATTRIBUTE_FORMAT ((PRINTF_ARCHETYPE, string_index, first_to_check)) + _GL_ATTRIBUTE_FORMAT ((PRINTF_ARCHETYPE, string_index, first_to_check)) -#define ARG_NONNULL ATTRIBUTE_NONNULL +#define ARG_NONNULL _GL_ATTRIBUTE_NONNULL /* Declare NAME to be a pointer to an object of type TYPE, initialized to the address ADDR, which may be of a different type. Accesses @@ -320,15 +318,16 @@ extern int emacs_setenv_TZ (char const *); behavior, even if options like gcc -fstrict-aliasing are used. */ #define DECLARE_POINTER_ALIAS(name, type, addr) \ - type ATTRIBUTE_MAY_ALIAS *name = (type *) (addr) + type _GL_ATTRIBUTE_MAY_ALIAS *name = (type *) (addr) #if 3 <= __GNUC__ # define ATTRIBUTE_SECTION(name) __attribute__((section (name))) #else -#define ATTRIBUTE_SECTION(name) +# define ATTRIBUTE_SECTION(name) #endif -#define ATTRIBUTE_MALLOC_SIZE(args) ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE (args) +#define ATTRIBUTE_MALLOC_SIZE(args) \ + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE (args) /* Work around GCC bug 59600: when a function is inlined, the inlined code may have its addresses sanitized even if the function has the diff --git a/src/dynlib.h b/src/dynlib.h index ac3d8e58ab..03b8f98356 100644 --- a/src/dynlib.h +++ b/src/dynlib.h @@ -20,6 +20,7 @@ along with GNU Emacs. If not, see . */ #ifndef DYNLIB_H #define DYNLIB_H +#include #include typedef void *dynlib_handle_ptr; diff --git a/src/lisp.h b/src/lisp.h index deeca9bc86..778bd1bfa5 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -31,6 +31,7 @@ along with GNU Emacs. If not, see . */ #include #include +#include #include #include diff --git a/src/syssignal.h b/src/syssignal.h index 07055c04be..02fe44a382 100644 --- a/src/syssignal.h +++ b/src/syssignal.h @@ -22,6 +22,8 @@ along with GNU Emacs. If not, see . */ #include +#include + extern void init_signals (void); extern void block_child_signal (sigset_t *); extern void unblock_child_signal (sigset_t const *); diff --git a/src/sysstdio.h b/src/sysstdio.h index 5bcfe7d8a5..727a466be5 100644 --- a/src/sysstdio.h +++ b/src/sysstdio.h @@ -24,7 +24,9 @@ along with GNU Emacs. If not, see . */ #include #include #include -#include "unlocked-io.h" + +#include +#include extern FILE *emacs_fopen (char const *, char const *) ATTRIBUTE_MALLOC; extern void errputc (int); diff --git a/src/systhread.h b/src/systhread.h index fb1a0a72d6..bf4e0306cd 100644 --- a/src/systhread.h +++ b/src/systhread.h @@ -21,6 +21,8 @@ along with GNU Emacs. If not, see . */ #include +#include + #ifdef THREADS_ENABLED #ifdef HAVE_PTHREAD diff --git a/src/tparam.h b/src/tparam.h index 6361f138ea..653f01bdde 100644 --- a/src/tparam.h +++ b/src/tparam.h @@ -20,6 +20,8 @@ along with GNU Emacs. If not, see . */ #ifndef EMACS_TPARAM_H #define EMACS_TPARAM_H +#include + /* Don't try to include termcap.h. On some systems, configure finds a non-standard termcap.h that the main build won't find. */ commit f7032bdafe742c588c1b8b5054e2f383a41fff54 Author: Po Lu Date: Wed Mar 9 08:50:24 2022 +0800 * src/xterm.c (handle_one_xevent): Add more dead keys. diff --git a/src/xterm.c b/src/xterm.c index 94b8f60c71..772a9238a7 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10946,6 +10946,18 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif #ifdef XK_dead_semivoiced_sound || orig_keysym == XK_dead_semivoiced_sound +#endif +#ifdef XK_dead_hook + || orig_keysym == XK_dead_hook +#endif +#ifdef XK_dead_horn + || orig_keysym == XK_dead_horn +#endif +#ifdef XK_dead_stroke + || orig_keysym == XK_dead_stroke +#endif +#ifdef XK_dead_abovecomma + || orig_keysym == XK_dead_abovecomma #endif || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */ || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */ @@ -12976,6 +12988,18 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif #ifdef XK_dead_semivoiced_sound || keysym == XK_dead_semivoiced_sound +#endif +#ifdef XK_dead_hook + || keysym == XK_dead_hook +#endif +#ifdef XK_dead_horn + || keysym == XK_dead_horn +#endif +#ifdef XK_dead_stroke + || keysym == XK_dead_stroke +#endif +#ifdef XK_dead_abovecomma + || keysym == XK_dead_abovecomma #endif || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */ || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */ commit 45e78a57ff22fad10b703755f1bf47c32f6aeb45 Author: Lars Ingebrigtsen Date: Tue Mar 8 21:11:18 2022 +0100 Mark tramp test unstable on EMBA * test/lisp/net/tramp-tests.el (tramp-test44-asynchronous-requests): Mark timed-out EMBA test as unstable. diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 22c7fc6b2f..ef82d3ac61 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -6917,7 +6917,9 @@ This is needed in timer functions as well as process filters and sentinels." Such requests could arrive from timers, process filters and process sentinels. They shall not disturb each other." :tags (append '(:expensive-test :tramp-asynchronous-processes) - (and (getenv "EMACS_HYDRA_CI") '(:unstable))) + (and (or (getenv "EMACS_HYDRA_CI") + (getenv "EMACS_EMBA_CI")) + '(:unstable))) (skip-unless (tramp--test-enabled)) (skip-unless (tramp--test-supports-processes-p)) ;; Prior Emacs 27, `shell-file-name' was hard coded as "/bin/sh" for commit ed543ca3e0c3c10cc0f7c0f4e8ce0ad514c10ec8 Author: Michael Albinus Date: Tue Mar 8 17:28:30 2022 +0100 Implement abbreviate-file-name in Tramp for Google drive * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-get-home-directory): Implement for Google drive. diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index acded25292..d6120d2bee 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -1604,10 +1604,20 @@ If USER is a string, return its home directory instead of the user identified by VEC. If there is no user specified in either VEC or USER, or if there is no home directory, return nil." (let ((localname - (tramp-get-connection-property vec "default-location" nil))) - (if (zerop (length localname)) - (tramp-get-connection-property (tramp-get-process vec) "share" nil) - localname))) + (tramp-get-connection-property vec "default-location" nil)) + result) + (cond + ((zerop (length localname)) + (tramp-get-connection-property (tramp-get-process vec) "share" nil)) + ;; Google-drive. + ((not (string-prefix-p "/" localname)) + (dolist (item + (tramp-gvfs-get-directory-attributes + (tramp-make-tramp-file-name vec "/")) + result) + (when (string-equal (cdr (assoc "name" item)) localname) + (setq result (concat "/" (car item)))))) + (t localname)))) (defun tramp-gvfs-handle-get-remote-uid (vec id-format) "The uid of the remote connection VEC, in ID-FORMAT. commit 6dc51d4cca3a0507d4212616ce1b24147dee54cb Author: Jim Porter Date: Sat Mar 5 11:45:49 2022 -0800 Support applying indices to more Eshell dollar expansions For example, '${echo -e "hi\nbye"}[1]' should expand to "bye". * lisp/eshell/esh-var.el (eshell-parse-variable-ref): Support applying indices to '${}', '$()', and '$<>' forms. (Bug#54227) * lisp/eshell/esh-var-tests.el (esh-var-test/interp-lisp-indices) (esh-var-test/interp-cmd-indices) (esh-var-test/interp-cmd-external-indices) (esh-var-test/quoted-interp-lisp-indices) (esh-var-test/quoted-interp-cmd-indices): New tests. diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el index 8746f2bb93..ca4cbd744c 100644 --- a/lisp/eshell/esh-var.el +++ b/lisp/eshell/esh-var.el @@ -434,13 +434,15 @@ Possible options are: (throw 'eshell-incomplete ?\{) (forward-char) (prog1 - `(eshell-convert - (eshell-command-to-value - (eshell-as-subcommand - ,(let ((subcmd (or (eshell-unescape-inner-double-quote end) - (cons (point) end))) - (eshell-current-quoted nil)) - (eshell-parse-command subcmd))))) + `(eshell-apply-indices + (eshell-convert + (eshell-command-to-value + (eshell-as-subcommand + ,(let ((subcmd (or (eshell-unescape-inner-double-quote end) + (cons (point) end))) + (eshell-current-quoted nil)) + (eshell-parse-command subcmd))))) + indices) (goto-char (1+ end)))))) ((eq (char-after) ?\<) (let ((end (eshell-find-delimiter ?\< ?\>))) @@ -464,14 +466,16 @@ Possible options are: ;; properly. See bug#54190. (list (function (lambda () (delete-file ,temp)))))) - (quote ,temp))) + (eshell-apply-indices ,temp indices))) (goto-char (1+ end))))))) ((eq (char-after) ?\() (condition-case nil - `(eshell-command-to-value - (eshell-lisp-command - ',(read (or (eshell-unescape-inner-double-quote (point-max)) - (current-buffer))))) + `(eshell-apply-indices + (eshell-command-to-value + (eshell-lisp-command + ',(read (or (eshell-unescape-inner-double-quote (point-max)) + (current-buffer))))) + indices) (end-of-file (throw 'eshell-incomplete ?\()))) ((looking-at (rx-to-string diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el index d09dd614de..1d051d681a 100644 --- a/test/lisp/eshell/esh-var-tests.el +++ b/test/lisp/eshell/esh-var-tests.el @@ -137,10 +137,18 @@ "Interpolate Lisp form evaluation" (should (equal (eshell-test-command-result "+ $(+ 1 2) 3") 6))) +(ert-deftest esh-var-test/interp-lisp-indices () + "Interpolate Lisp form evaluation with index" + (should (equal (eshell-test-command-result "+ $(list 1 2)[1] 3") 5))) + (ert-deftest esh-var-test/interp-cmd () "Interpolate command result" (should (equal (eshell-test-command-result "+ ${+ 1 2} 3") 6))) +(ert-deftest esh-var-test/interp-cmd-indices () + "Interpolate command result with index" + (should (equal (eshell-test-command-result "+ ${list 1 2}[1] 3") 5))) + (ert-deftest esh-var-test/interp-cmd-external () "Interpolate command result from external command" (skip-unless (executable-find "echo")) @@ -148,6 +156,13 @@ (eshell-command-result-p "echo ${*echo hi}" "hi\n"))) +(ert-deftest esh-var-test/interp-cmd-external-indices () + "Interpolate command result from external command with index" + (skip-unless (executable-find "echo")) + (with-temp-eshell + (eshell-command-result-p "echo ${*echo \"hi\nbye\"}[1]" + "bye\n"))) + (ert-deftest esh-var-test/interp-temp-cmd () "Interpolate command result redirected to temp file" (should (equal (eshell-test-command-result "cat $") "hi"))) @@ -282,12 +297,20 @@ inside double-quotes" "echo \"hi $(concat \\\"the\\\" \\\"re\\\")\"") "hi there"))) +(ert-deftest esh-var-test/quoted-interp-lisp-indices () + "Interpolate Lisp form evaluation with index" + (should (equal (eshell-test-command-result "+ \"$(list 1 2)[1]\" 3") 5))) + (ert-deftest esh-var-test/quoted-interp-cmd () "Interpolate command result inside double-quotes" (should (equal (eshell-test-command-result "echo \"hi ${echo \\\"there\\\"}\"") "hi there"))) +(ert-deftest esh-var-test/quoted-interp-cmd-indices () + "Interpolate command result with index inside double-quotes" + (should (equal (eshell-test-command-result "+ \"${list 1 2}[1]\" 3") 5))) + (ert-deftest esh-var-test/quoted-interp-temp-cmd () "Interpolate command result redirected to temp file inside double-quotes" (should (equal (eshell-test-command-result "cat \"$\"") "hi"))) commit 58568033f4b648e0dc8d9d893ef2197aded0a69e Author: Jim Porter Date: Thu Mar 3 09:37:25 2022 -0800 Improve wording of Eshell variable interpolation code/documentation * lisp/eshell/esh-arg.el (eshell-unescape-inner-double-quote): Rename from 'eshell-parse-inner-double-quote'. * lisp/eshell/esh-cmd.el (eshell-with-temp-command): Improve docstring. * lisp/eshell/esh-var.el (eshell-parse-variable-ref): Use 'eshell-unescape-inner-double-quote' and improve robustness of quoted variable name matching. (eshell-parse-indices): Use 'eshell-unescape-inner-double-quote'. * doc/misc/eshell.texi (Dollars Expansion): Improve wording of subscript notation. diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index 5581e5cd9e..372e4c3ffb 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi @@ -1040,18 +1040,37 @@ returns the file name. Expands to the @var{i}th element of the result of @var{expr}, an expression in one of the above forms listed here. If multiple indices are supplied, this will return a list containing the elements for each -index. If @var{expr}'s value is a string, it will first be split at -whitespace to make it a list. If @var{expr}'s value is an alist -(@pxref{Association List Type, Association Lists, , elisp, The Emacs -Lisp Reference Manual}), this will call @code{assoc} on the result of -@var{expr}, returning the @code{cdr} of the element of the result -whose car is equal to @code{"i"}. Raises an error if the value is not -a sequence (@pxref{Sequences Arrays Vectors, Sequences, , elisp, The +index. The exact behavior depends on the type of @var{expr}'s value: + +@table @asis + +@item a sequence +Expands to the element at the (zero-based) index @var{i} of the +sequence (@pxref{Sequences Arrays Vectors, Sequences, , elisp, The Emacs Lisp Reference Manual}). -Multiple sets of indices can also be specified. For example, if -@var{var} is a list of lists, @samp{$@var{var}[0][0]} is equivalent to -@samp{(caar @var{var})}. +@item a string +Split the string at whitespace, and then expand to the @var{i}th +element of the resulting sequence. + +@item an alist +If @var{i} is a non-numeric value, expand to the value associated with +the key @code{"@var{i}"} in the alist. For example, if @var{var} is +@samp{(("dog" . "fido") ("cat" . "felix"))}, then +@samp{$@var{var}[dog]} expands to @code{"fido"}. Otherwise, this +behaves as with sequences; e.g., @samp{$@var{var}[0]} expands to +@code{("dog" . "fido")}. @xref{Association List Type, Association +Lists, , elisp, The Emacs Lisp Reference Manual}. + +@item anything else +Signals an error. + +@end table + +Multiple sets of indices can also be specified. For example, if +@var{var} is @samp{((1 2) (3 4))}, then @samp{$@var{var}[0][1]} will +expand to @code{2}, i.e.@: the second element of the first list member +(all indices are zero-based). @item $@var{expr}[@var{regexp} @var{i...}] As above (when @var{expr} expands to a string), but use @var{regexp} @@ -1063,8 +1082,8 @@ element of a colon-delimited string. Expands to the length of the result of @var{expr}, an expression in one of the above forms. For example, @samp{$#@var{var}} returns the length of the variable @var{var} and @samp{$#@var{var}[0]} returns the -length of the first element of @var{var}. Again, raises an error if -the result of @var{expr} is not a sequence. +length of the first element of @var{var}. Again, signals an error if +the result of @var{expr} is not a string or a sequence. @end table diff --git a/lisp/eshell/esh-arg.el b/lisp/eshell/esh-arg.el index e19481c4ba..ee3f907f85 100644 --- a/lisp/eshell/esh-arg.el +++ b/lisp/eshell/esh-arg.el @@ -354,8 +354,8 @@ after are both returned." (list 'eshell-escape-arg arg)))) (goto-char (1+ end))))))) -(defun eshell-parse-inner-double-quote (bound) - "Parse the inner part of a double quoted string. +(defun eshell-unescape-inner-double-quote (bound) + "Unescape escaped characters inside a double-quoted string. The string to parse starts at point and ends at BOUND. If Eshell is currently parsing a quoted string and there are any diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index 04b54d9d79..8be1136e31 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -350,24 +350,27 @@ This only returns external (non-Lisp) processes." (defvar eshell--sep-terms) -(defmacro eshell-with-temp-command (command &rest body) - "Narrow the buffer to COMMAND and execute the forms in BODY. -COMMAND can either be a string, or a cons cell demarcating a -buffer region. If COMMAND is a string, temporarily insert it -into the buffer before narrowing. Point will be set to the -beginning of the narrowed region. +(defmacro eshell-with-temp-command (region &rest body) + "Narrow the buffer to REGION and execute the forms in BODY. + +REGION is a cons cell (START . END) that specifies the region to +which to narrow the buffer. REGION can also be a string, in +which case the macro temporarily inserts it into the buffer at +point, and narrows the buffer to the inserted string. Before +executing BODY, point is set to the beginning of the narrowed +REGION. The value returned is the last form in BODY." (declare (indent 1)) - `(let ((cmd ,command)) - (if (stringp cmd) + `(let ((reg ,region)) + (if (stringp reg) ;; Since parsing relies partly on buffer-local state ;; (e.g. that of `eshell-parse-argument-hook'), we need to ;; perform the parsing in the Eshell buffer. (let ((begin (point)) end (inhibit-point-motion-hooks t)) (with-silent-modifications - (insert cmd) + (insert reg) (setq end (point)) (unwind-protect (save-restriction @@ -376,8 +379,8 @@ The value returned is the last form in BODY." ,@body) (delete-region begin end)))) (save-restriction - (narrow-to-region (car cmd) (cdr cmd)) - (goto-char (car cmd)) + (narrow-to-region (car reg) (cdr reg)) + (goto-char (car reg)) ,@body)))) (defun eshell-parse-command (command &optional args toplevel) diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el index af89e35f55..8746f2bb93 100644 --- a/lisp/eshell/esh-var.el +++ b/lisp/eshell/esh-var.el @@ -437,7 +437,7 @@ Possible options are: `(eshell-convert (eshell-command-to-value (eshell-as-subcommand - ,(let ((subcmd (or (eshell-parse-inner-double-quote end) + ,(let ((subcmd (or (eshell-unescape-inner-double-quote end) (cons (point) end))) (eshell-current-quoted nil)) (eshell-parse-command subcmd))))) @@ -470,13 +470,15 @@ Possible options are: (condition-case nil `(eshell-command-to-value (eshell-lisp-command - ',(read (or (eshell-parse-inner-double-quote (point-max)) + ',(read (or (eshell-unescape-inner-double-quote (point-max)) (current-buffer))))) (end-of-file (throw 'eshell-incomplete ?\()))) - ((looking-at (rx (or "'" "\"" "\\\""))) - (eshell-with-temp-command (or (eshell-parse-inner-double-quote (point-max)) - (cons (point) (point-max))) + ((looking-at (rx-to-string + `(or "'" ,(if eshell-current-quoted "\\\"" "\"")))) + (eshell-with-temp-command + (or (eshell-unescape-inner-double-quote (point-max)) + (cons (point) (point-max))) (let ((name (if (eq (char-after) ?\') (eshell-parse-literal-quote) (eshell-parse-double-quote)))) @@ -506,7 +508,7 @@ For example, \"[0 1][2]\" becomes: (if (not end) (throw 'eshell-incomplete ?\[) (forward-char) - (eshell-with-temp-command (or (eshell-parse-inner-double-quote end) + (eshell-with-temp-command (or (eshell-unescape-inner-double-quote end) (cons (point) end)) (let (eshell-glob-function (eshell-current-quoted nil)) (setq indices (cons (eshell-parse-arguments commit d509d1e1a884a33d6e8a5196bc0e8314b0a892f9 Merge: a7fdbed880 d184773c2e Author: Eli Zaretskii Date: Tue Mar 8 15:41:46 2022 +0200 Merge from origin/emacs-28 d184773 Avoid assertion violations in 'bidi_resolve_brackets' commit d184773c2e2a69bea9b96190c83727b4e7a16542 (refs/remotes/origin/emacs-28) Author: Eli Zaretskii Date: Tue Mar 8 15:35:39 2022 +0200 Avoid assertion violations in 'bidi_resolve_brackets' * src/bidi.c (bidi_resolve_brackets): Move assertion to where it really matters. (Bug#54295) diff --git a/src/bidi.c b/src/bidi.c index a548960048..9449e09944 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -2921,13 +2921,13 @@ bidi_resolve_brackets (struct bidi_it *bidi_it) int embedding_level = bidi_it->level_stack[bidi_it->stack_idx].level; bidi_type_t embedding_type = (embedding_level & 1) ? STRONG_R : STRONG_L; - eassert (bidi_it->prev_for_neutral.type != UNKNOWN_BT); eassert (bidi_it->bracket_pairing_pos > bidi_it->charpos); if (bidi_it->bracket_enclosed_type == embedding_type) /* N0b */ type = embedding_type; else if (bidi_it->bracket_enclosed_type == STRONG_L /* N0c, N0d */ || bidi_it->bracket_enclosed_type == STRONG_R) { + eassert (bidi_it->prev_for_neutral.type != UNKNOWN_BT); switch (bidi_it->prev_for_neutral.type) { case STRONG_R: @@ -2946,7 +2946,6 @@ bidi_resolve_brackets (struct bidi_it *bidi_it) break; default: /* N0d: Do not set the type for that bracket pair. */ - /* (Actuallly, this shouldn't happen.) */ break; } } commit a7fdbed880fb92392b93c3ad53e89c0ce7ba515f Author: Po Lu Date: Tue Mar 8 21:25:37 2022 +0800 Handle XI focus change events that specify implicit focus correctly * src/xterm.c (x_detect_focus_change): If detail is XINotifyPointer, set focus type to implicit. diff --git a/src/xterm.c b/src/xterm.c index 72c7c05d89..94b8f60c71 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -6480,7 +6480,8 @@ x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame, #ifdef HAVE_XINPUT2 case GenericEvent: { - XIEvent *xi_event = (XIEvent *) event->xcookie.data; + XIEvent *xi_event = event->xcookie.data; + XIEnterEvent *enter_or_focus = event->xcookie.data; struct frame *focus_frame = dpyinfo->x_focus_event_frame; int focus_state @@ -6490,13 +6491,14 @@ x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame, || xi_event->evtype == XI_FocusOut) x_focus_changed ((xi_event->evtype == XI_FocusIn ? FocusIn : FocusOut), - FOCUS_EXPLICIT, - dpyinfo, frame, bufp); + ((enter_or_focus->detail + == XINotifyPointer) + ? FOCUS_IMPLICIT : FOCUS_EXPLICIT), + dpyinfo, frame, bufp); else if ((xi_event->evtype == XI_Enter || xi_event->evtype == XI_Leave) - && (((XIEnterEvent *) xi_event)->detail - != XINotifyInferior) - && ((XIEnterEvent *) xi_event)->focus + && (enter_or_focus->detail != XINotifyInferior) + && enter_or_focus->focus && !(focus_state & FOCUS_EXPLICIT)) x_focus_changed ((xi_event->evtype == XI_Enter ? FocusIn : FocusOut), commit bbbb47704f6c7e56a96983976fbb0ab1acca652f Author: Po Lu Date: Tue Mar 8 18:31:12 2022 +0800 Fix detection of modifier keys on XInput 2 * src/xterm.c (handle_one_xevent): Fix iteration over sets of modifiers. diff --git a/src/xterm.c b/src/xterm.c index fdecca3bcd..72c7c05d89 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -12740,7 +12740,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, { for (i = 0; i < 8 * dpyinfo->modmap->max_keypermod; i++) { - if (xkey.keycode == dpyinfo->modmap->modifiermap[xev->detail]) + if (xev->detail == dpyinfo->modmap->modifiermap[i]) goto xi_done_keysym; } }