From 8120f5156ccfa0e4992685a05abcb4838d76fb8a Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Thu, 18 May 2023 23:47:27 -0700 Subject: [PATCH 1/4] ; Silence byte compiler in erc-netsplit-JOIN * etc/ERC-NEWS: Partially revert edit from c9f1ad2a870 "Revive option erc-query-on-unjoined-chan-privmsg". * lisp/erc/erc-netsplit.el (erc-netsplit-JOIN): Silence byte compiler warning re ignored return value from `delete' when removing nicks. Could probably suppress rather than reconstitute since the CAR of an `erc-netsplit-list' entry originates from the trailing "reason" param of the instigating "QUIT" command and should look something like "irc.example.org chat.example.org", which cannot be confused for a nickname. * test/lisp/erc/resources/erc-scenarios-common.el: Fix wording in Commentary. --- etc/ERC-NEWS | 4 ++-- lisp/erc/erc-netsplit.el | 4 +++- test/lisp/erc/resources/erc-scenarios-common.el | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS index 1aa445c5b9c..d257bdcbf51 100644 --- a/etc/ERC-NEWS +++ b/etc/ERC-NEWS @@ -366,8 +366,8 @@ In an effort to help further tame ERC's complexity, the variable 'erc-default-recipients' is now expected to hold but a single target. As a consequence, functions like 'erc-add-default-channel' that imagine an alternate, aspirational model of buffer-target relations -have been deprecated. Grep for their names in ChangeLog.4 for -details. +have been deprecated. For specifics, see entries in Emacs' +ChangeLog.4 from around June 30, 2022. A number of less consequential deprecations also debut in this release. For example, the function 'erc-auto-query' was deemed too diff --git a/lisp/erc/erc-netsplit.el b/lisp/erc/erc-netsplit.el index f3572014f27..5dd11ab1869 100644 --- a/lisp/erc/erc-netsplit.el +++ b/lisp/erc/erc-netsplit.el @@ -117,7 +117,9 @@ join from that split has been detected or not.") parsed 'notice (process-buffer proc) 'netjoin-done ?s (car elt)) (setq erc-netsplit-list (delq elt erc-netsplit-list))) - (delete nick elt)) + ;; Avoid `ignored-return-value' warning for `delete'. + (let ((tail (nthcdr 2 elt))) ; (t n1 ... nN) + (setcdr tail (delete nick (cdr tail))))) (setq no-next-hook t)))) no-next-hook)) diff --git a/test/lisp/erc/resources/erc-scenarios-common.el b/test/lisp/erc/resources/erc-scenarios-common.el index f259c88594b..32e7556d602 100644 --- a/test/lisp/erc/resources/erc-scenarios-common.el +++ b/test/lisp/erc/resources/erc-scenarios-common.el @@ -51,7 +51,7 @@ ;; argument, a `let*'-style VAR-LIST. Relying on such a macro is ;; unfortunate because in many ways it actually hampers readability by ;; favoring magic over verbosity. But without it (or something -;; similar), any failing test would cause all subsequent tests in this +;; similar), any failing test would cause all subsequent tests in a ;; file to fail like dominoes (making all but the first backtrace ;; useless). ;; From c297b828bb716885f92d3117c2abbb1ff21dbb08 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Thu, 18 May 2023 23:47:27 -0700 Subject: [PATCH 2/4] Fix custom type of erc-autojoin-channels-alist * lisp/erc/erc-join.el (erc-autojoin-channels-alist): In ERC 5.4, the type of this option changed to accept symbols signifying IRC network names. However, the option's definition was not updated to reflect that. See commit 9bb8d90cddf "Allow irc network symbols in erc-autojoin-channels-alist". --- lisp/erc/erc-join.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lisp/erc/erc-join.el b/lisp/erc/erc-join.el index 17104da1a8b..45cfd565f89 100644 --- a/lisp/erc/erc-join.el +++ b/lisp/erc/erc-join.el @@ -78,10 +78,11 @@ keeps track of what channels you are on, and will join them again when you get disconnected. When you restart Emacs, however, those changes are lost, and the customization you saved the last time is used again." - :type '(repeat (cons :tag "Server" - (regexp :tag "Name") - (repeat :tag "Channels" - (string :tag "Name"))))) + :type '(alist :options (Libera.Chat) + :key-type (choice :tag "Server" + (symbol :tag "Network") + (regexp :tag "Host or domain")) + :value-type (repeat :tag "Channels" (string :tag "Name")))) (defcustom erc-autojoin-timing 'connect "When ERC should attempt to autojoin a channel. From 6f940c6a1183dd1660f35e6c82d33183a6892cb4 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 22 May 2023 11:52:33 +0800 Subject: [PATCH 3/4] Plug various leaks and fix input method initialization * src/image.c (free_bitmap_record): Free bm->name correctly even if the display connection has been closed. * src/xfns.c (x_window): Use dpyinfo-specific `use_xim' flag. * src/xterm.c (use_xim): Remove global variable. (xim_destroy_callback): Free `xim_styles' if present, and set it to NULL to be on the safe side. (xim_open_dpy): Consult dpyinfo->use_xim instead. Don't leak `xim_styles' if an IM was previously opened. (xim_initialize): Use dpyinfo-specific `use_xim' flag. (xim_close_dpy): Check if `dpyinfo->xim_callback_data' is set before unregistering the instantiation callback. (x_term_init): Determine whether or not to use XIM for each display opened, instead of using the resources of the last display opened to toggle a global flag. (x_delete_terminal): Always call `image_destroy_all_bitmaps' and `xim_close_dpy'. Free storage used to hold bitmap records. * src/xterm.h (struct x_display_info): New field `use_xim'. --- src/image.c | 14 ++++- src/xfns.c | 54 +++++++++--------- src/xterm.c | 156 ++++++++++++++++++++++++++++++++++------------------ src/xterm.h | 11 ++-- 4 files changed, 147 insertions(+), 88 deletions(-) diff --git a/src/image.c b/src/image.c index 87a0c1ca497..c9420b48f4a 100644 --- a/src/image.c +++ b/src/image.c @@ -842,9 +842,17 @@ static void free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm) { #ifdef HAVE_X_WINDOWS - XFreePixmap (dpyinfo->display, bm->pixmap); - if (bm->have_mask) - XFreePixmap (dpyinfo->display, bm->mask); + /* Free the pixmap and mask. Only do this if DPYINFO->display is + still set, which may not be the case if the connection has + already been closed in response to an IO error. */ + + if (dpyinfo->display) + { + XFreePixmap (dpyinfo->display, bm->pixmap); + if (bm->have_mask) + XFreePixmap (dpyinfo->display, bm->mask); + } + #ifdef USE_CAIRO if (bm->stipple) cairo_pattern_destroy (bm->stipple); diff --git a/src/xfns.c b/src/xfns.c index 9e004f6a678..234a48c908f 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -4252,9 +4252,9 @@ x_window (struct frame *f, long window_prompting) #ifdef HAVE_X_I18N FRAME_XIC (f) = NULL; - if (use_xim) + if (FRAME_DISPLAY_INFO (f)->use_xim) create_frame_xic (f); -#endif +#endif /* HAVE_X_I18N */ f->output_data.x->wm_hints.input = True; f->output_data.x->wm_hints.flags |= InputHint; @@ -4355,32 +4355,32 @@ x_window (struct frame *f) #ifdef HAVE_X_I18N FRAME_XIC (f) = NULL; - if (use_xim) - { - block_input (); - create_frame_xic (f); - if (FRAME_XIC (f)) - { - /* XIM server might require some X events. */ - unsigned long fevent = NoEventMask; - XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL); + if (FRAME_DISPLAY_INFO (f)->use_xim) + { + block_input (); + create_frame_xic (f); + if (FRAME_XIC (f)) + { + /* XIM server might require some X events. */ + unsigned long fevent = NoEventMask; + XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL); - if (fevent != NoEventMask) - { - XSetWindowAttributes attributes; - XWindowAttributes wattr; - unsigned long attribute_mask; + if (fevent != NoEventMask) + { + XSetWindowAttributes attributes; + XWindowAttributes wattr; + unsigned long attribute_mask; - XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - &wattr); - attributes.event_mask = wattr.your_event_mask | fevent; - attribute_mask = CWEventMask; - XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - attribute_mask, &attributes); - } - } - unblock_input (); - } + XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + &wattr); + attributes.event_mask = wattr.your_event_mask | fevent; + attribute_mask = CWEventMask; + XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + attribute_mask, &attributes); + } + } + unblock_input (); + } #endif append_wm_protocols (FRAME_DISPLAY_INFO (f), f); @@ -4427,7 +4427,7 @@ x_window (struct frame *f) initial_set_up_x_back_buffer (f); #ifdef HAVE_X_I18N - if (use_xim) + if (FRAME_DISPLAY_INFO (f)->use_xim) { create_frame_xic (f); if (FRAME_XIC (f)) diff --git a/src/xterm.c b/src/xterm.c index 15bd9f98d17..0450230efe6 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -798,13 +798,6 @@ typedef int (*Emacs_XIOErrorHandler) (Display *); #define USE_CAIRO_XCB_SURFACE #endif -/* Default to using XIM if available. */ -#ifdef USE_XIM -bool use_xim = true; -#else -bool use_xim = false; /* configure --without-xim */ -#endif - #if XCB_SHAPE_MAJOR_VERSION > 1 \ || (XCB_SHAPE_MAJOR_VERSION == 1 && \ XCB_SHAPE_MINOR_VERSION >= 1) @@ -26666,7 +26659,12 @@ xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data) /* No need to call XCloseIM. */ dpyinfo->xim = NULL; - XFree (dpyinfo->xim_styles); + + /* Also free IM values; those are allocated separately upon + XGetIMValues. */ + if (dpyinfo->xim_styles) + XFree (dpyinfo->xim_styles); + dpyinfo->xim_styles = NULL; unblock_input (); } @@ -26684,10 +26682,20 @@ xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name) XIM xim; const char *locale; - if (use_xim) + if (dpyinfo->use_xim) { if (dpyinfo->xim) - XCloseIM (dpyinfo->xim); + { + XCloseIM (dpyinfo->xim); + + /* Free values left over from the last time the IM + connection was established. */ + + if (dpyinfo->xim_styles) + XFree (dpyinfo->xim_styles); + dpyinfo->xim_styles = NULL; + } + xim = XOpenIM (dpyinfo->display, dpyinfo->rdb, resource_name, emacs_class); dpyinfo->xim = xim; @@ -26716,7 +26724,6 @@ xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name) build_string (locale)); } } - else #endif /* HAVE_XIM */ dpyinfo->xim = NULL; @@ -26785,7 +26792,7 @@ xim_initialize (struct x_display_info *dpyinfo, char *resource_name) { dpyinfo->xim = NULL; #ifdef HAVE_XIM - if (use_xim) + if (dpyinfo->use_xim) { #ifdef HAVE_X11R6_XIM struct xim_inst_t *xim_inst = xmalloc (sizeof *xim_inst); @@ -26794,15 +26801,19 @@ xim_initialize (struct x_display_info *dpyinfo, char *resource_name) dpyinfo->xim_callback_data = xim_inst; xim_inst->dpyinfo = dpyinfo; xim_inst->resource_name = xstrdup (resource_name); - ret = XRegisterIMInstantiateCallback - (dpyinfo->display, dpyinfo->rdb, xim_inst->resource_name, - emacs_class, xim_instantiate_callback, - /* This is XPointer in XFree86 but (XPointer *) on Tru64, at - least, but the configure test doesn't work because - xim_instantiate_callback can either be XIMProc or - XIDProc, so just cast to void *. */ - (void *) xim_inst); - eassert (ret == True); + + /* The last argument is XPointer in XFree86 but (XPointer *) on + Tru64, at least, but the configure test doesn't work because + xim_instantiate_callback can either be XIMProc or XIDProc, so + just cast to void *. */ + + ret = XRegisterIMInstantiateCallback (dpyinfo->display, + dpyinfo->rdb, + xim_inst->resource_name, + emacs_class, + xim_instantiate_callback, + (void *) xim_inst); + eassert (ret); #else /* not HAVE_X11R6_XIM */ xim_open_dpy (dpyinfo, resource_name); #endif /* not HAVE_X11R6_XIM */ @@ -26811,32 +26822,56 @@ xim_initialize (struct x_display_info *dpyinfo, char *resource_name) } -/* Close the connection to the XIM server on display DPYINFO. */ +/* Close the connection to the XIM server on display DPYINFO. + Unregister any IM instantiation callback previously installed, + close the connection to the IM server if possible, and free any + retrieved IM values. */ static void xim_close_dpy (struct x_display_info *dpyinfo) { #ifdef HAVE_XIM - if (use_xim) - { #ifdef HAVE_X11R6_XIM - struct xim_inst_t *xim_inst = dpyinfo->xim_callback_data; + struct xim_inst_t *xim_inst; + Bool rc; + + /* If dpyinfo->xim_callback_data is not set, then IM support wasn't + initialized, which can happen if Xlib doesn't understand the C + locale being used. */ + + if (dpyinfo->xim_callback_data) + { + xim_inst = dpyinfo->xim_callback_data; if (dpyinfo->display) { - Bool ret = XUnregisterIMInstantiateCallback - (dpyinfo->display, dpyinfo->rdb, xim_inst->resource_name, - emacs_class, xim_instantiate_callback, (void *) xim_inst); - eassert (ret == True); + rc = XUnregisterIMInstantiateCallback (dpyinfo->display, + dpyinfo->rdb, + xim_inst->resource_name, + emacs_class, + xim_instantiate_callback, + (void *) xim_inst); + eassert (rc); } + xfree (xim_inst->resource_name); xfree (xim_inst); -#endif /* HAVE_X11R6_XIM */ - if (dpyinfo->display) - XCloseIM (dpyinfo->xim); - dpyinfo->xim = NULL; - XFree (dpyinfo->xim_styles); } +#endif /* HAVE_X11R6_XIM */ + + /* Now close the connection to the input method server. This may + access the display connection, and isn't safe if the display has + already been closed. */ + + if (dpyinfo->display && dpyinfo->xim) + XCloseIM (dpyinfo->xim); + dpyinfo->xim = NULL; + + /* Free the list of XIM styles retrieved. */ + + if (dpyinfo->xim_styles) + XFree (dpyinfo->xim_styles); + dpyinfo->xim_styles = NULL; #endif /* HAVE_XIM */ } @@ -30766,14 +30801,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) dpyinfo->fixes_pointer_blanking = (egetenv ("EMACS_XFIXES") != NULL); #endif -#ifdef HAVE_X_I18N - /* Avoid initializing input methods if the X library does not - support Emacs's locale. When the current locale is not - supported, decoding input method strings becomes undefined. */ - if (XSupportsLocale ()) - xim_initialize (dpyinfo, resource_name); -#endif - xsettings_initialize (dpyinfo); /* This is only needed for distinguishing keyboard and process input. */ @@ -30832,25 +30859,33 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) XSynchronize (dpyinfo->display, True); } +#ifdef HAVE_X_I18N { AUTO_STRING (useXIM, "useXIM"); AUTO_STRING (UseXIM, "UseXIM"); Lisp_Object value = gui_display_get_resource (dpyinfo, useXIM, UseXIM, Qnil, Qnil); + + /* `USE_XIM' controls whether Emacs should use X input methods by + default, not whether or not XIM is available. */ + #ifdef USE_XIM + dpyinfo->use_xim = true; + if (STRINGP (value) && (!strcmp (SSDATA (value), "false") || !strcmp (SSDATA (value), "off"))) - use_xim = false; -#else + dpyinfo->use_xim = false; +#else /* !USE_XIM */ + dpyinfo->use_xim = false; + if (STRINGP (value) && (!strcmp (SSDATA (value), "true") || !strcmp (SSDATA (value), "on"))) - use_xim = true; -#endif + dpyinfo->use_xim = true; +#endif /* USE_XIM */ } -#ifdef HAVE_X_I18N { AUTO_STRING (inputStyle, "inputStyle"); AUTO_STRING (InputStyle, "InputStyle"); @@ -30872,10 +30907,19 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) #ifdef USE_GTK else if (!strcmp (SSDATA (value), "native")) dpyinfo->prefer_native_input = true; -#endif +#endif /* HAVE_GTK */ } } -#endif + + /* Now that defaults have been set up, initialize input method + support. */ + + /* Avoid initializing input methods if the X library does not + support Emacs's locale. When the current locale is not + supported, decoding input method strings becomes undefined. */ + if (XSupportsLocale ()) + xim_initialize (dpyinfo, resource_name); +#endif /* HAVE_X_I18N */ #ifdef HAVE_X_SM /* Only do this for the very first display in the Emacs session. @@ -31268,14 +31312,22 @@ x_delete_terminal (struct terminal *terminal) #ifdef HAVE_X_I18N /* We must close our connection to the XIM server before closing the X display. */ - if (dpyinfo->xim) - xim_close_dpy (dpyinfo); + xim_close_dpy (dpyinfo); #endif + /* Destroy all bitmap images created on the display. */ + image_destroy_all_bitmaps (dpyinfo); + + /* Free the storage allocated to hold bitmap records. */ + xfree (dpyinfo->bitmaps); + + /* In case someone decides to use `bitmaps' again... */ + dpyinfo->bitmaps = NULL; + dpyinfo->bitmaps_last = 0; + /* Normally, the display is available... */ if (dpyinfo->display) { - image_destroy_all_bitmaps (dpyinfo); XSetCloseDownMode (dpyinfo->display, DestroyAll); /* Delete the scratch cursor GC, should it exist. */ diff --git a/src/xterm.h b/src/xterm.h index 28ae00ca190..34a713ea2ca 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -649,7 +649,11 @@ struct x_display_info /* The named coding system to use for this input method. */ Lisp_Object xim_coding; -#endif + + /* Whether or not X input methods should be used on this + display. */ + bool use_xim; +#endif /* HAVE_X_I18N */ /* A cache mapping color names to RGB values. */ struct color_name_cache_entry **color_names; @@ -922,11 +926,6 @@ struct x_display_info #endif }; -#ifdef HAVE_X_I18N -/* Whether or not to use XIM if we have it. */ -extern bool use_xim; -#endif - #ifdef HAVE_XINPUT2 /* Defined in xmenu.c. */ extern int popup_activated_flag; From 438b1205c54dbdeff234d14dcf2287cbf6769522 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Mon, 22 May 2023 12:56:45 +0200 Subject: [PATCH 4/4] Mark failing filenotify test as :unstable * test/lisp/filenotify-tests.el (file-notify-test04-autorevert-remote): Tag as :unstable. --- test/lisp/filenotify-tests.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el index bc094345ffe..97b7c46c689 100644 --- a/test/lisp/filenotify-tests.el +++ b/test/lisp/filenotify-tests.el @@ -1032,7 +1032,7 @@ delivered." (file-notify--test-cleanup)))) (file-notify--deftest-remote file-notify-test04-autorevert - "Check autorevert via file notification for remote files.") + "Check autorevert via file notification for remote files." t) (ert-deftest file-notify-test05-file-validity () "Check `file-notify-valid-p' for files."