diff options
author | Sean Whitton <spwhitton@spwhitton.name> | 2022-01-16 15:58:41 -0700 |
---|---|---|
committer | Sean Whitton <spwhitton@spwhitton.name> | 2022-01-16 15:58:41 -0700 |
commit | 574d33b4737cf0829eb85c802710bfc42093f6d1 (patch) | |
tree | 32d9bdcfd80db07cae90485c658841d1c0d025a6 | |
parent | be8c25fd3dacc0ebfe20e6c64914ea2dcecdbac9 (diff) | |
parent | 714e11d53534416b6519396a9df5d62054731810 (diff) | |
download | emacs-574d33b4737cf0829eb85c802710bfc42093f6d1.tar.gz |
Merge remote-tracking branch 'origin/master' into athena/unstable
65 files changed, 1085 insertions, 402 deletions
@@ -226,6 +226,33 @@ e.g. 'emacs25'). On Red Hat-based systems, the corresponding command is On FreeBSD, the command is 'pkg install -y `pkg rquery %dn emacs-devel`'. +* Alternative window systems + +If you want to use Emacs on one of the alternative window systems +available on GNU/Linux and some Unix systems, such as Wayland or +Broadway, you can build the PGTK ("Pure GTK") port of Emacs, which +utilizes the GTK+ toolkit to support those window systems. To this +end, invoke the configure script with the '--with-pgtk' option, like +this: + + ./configure --with-pgtk + +This build is only supported with GTK+ version 3, and it is an error +to specify any other X-specific configuration option when PGTK is +enabled. + +With the PGTK build, you will be able to switch between running Emacs +on X, Wayland and Broadway using the 'GDK_BACKEND' environment +variable. GTK+ should automatically detect and use the correct value +for your system, but you can also specify it manually. For example, +to force GTK+ to run under Broadway, start Emacs like this: + + GDK_BACKEND=broadway emacs ... + +(where '...' denotes any further options you may want to pass to Emacs). + +The GNUstep build also supports the Wayland window system. If that is +what you want, see nextstep/INSTALL. DETAILED BUILDING AND INSTALLATION: diff --git a/configure.ac b/configure.ac index baf8c8018ec..955f0918fd4 100644 --- a/configure.ac +++ b/configure.ac @@ -3409,41 +3409,6 @@ if test "${with_xim}" != "no"; then [Define to 1 to default runtime use of XIM to on.]) fi - -if test "${HAVE_XIM}" != "no"; then - late_CFLAGS=$CFLAGS - if test "$GCC" = yes; then - CFLAGS="$CFLAGS --pedantic-errors" - fi - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include <X11/Xlib.h> -#include <X11/Xresource.h>]], -[[Display *display; -XrmDatabase db; -char *res_name; -char *res_class; -XIDProc *callback; -XPointer *client_data; -#ifndef __GNUC__ -/* If we're not using GCC, it's probably not XFree86, and this is - probably right, but we can't use something like --pedantic-errors. */ -extern Bool XRegisterIMInstantiateCallback(Display*, XrmDatabase, char*, - char*, XIMProc, XPointer*); -#endif -(void)XRegisterIMInstantiateCallback(display, db, res_name, res_class, callback, - client_data);]])], - [emacs_cv_arg6_star=yes]) - AH_TEMPLATE(XRegisterIMInstantiateCallback_arg6, - [Define to the type of the 6th arg of XRegisterIMInstantiateCallback, -either XPointer or XPointer*.])dnl - if test "$emacs_cv_arg6_star" = yes; then - AC_DEFINE(XRegisterIMInstantiateCallback_arg6, [XPointer*]) - else - AC_DEFINE(XRegisterIMInstantiateCallback_arg6, [XPointer]) - fi - CFLAGS=$late_CFLAGS -fi - # Check for XRender HAVE_XRENDER=no if test "${HAVE_X11}" = "yes"; then diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index c641b8ccb14..ba58f70caf3 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -515,12 +515,14 @@ error if there is only one frame. @item C-x 5 u @kindex C-x 5 u @findex undelete-frame -@findex undelete-frame-mode -When @code{undelete-frame-mode} is enabled, undelete one of the 16 -most recently deleted frames. Without a prefix argument, undelete the -most recently deleted frame. With a numerical prefix argument between -1 and 16, where 1 is the most recently deleted frame, undelete the -corresponding deleted frame. +@findex undelete-frame-max +Undelete one of the recently deleted frames. The user option +@code{undelete-frame-max} specifies the maximum number of deleted +frames to keep (the default is 1). Without a prefix argument, +undelete the most recently deleted frame. With a numerical prefix +argument between 1 and the number specified by @code{undelete-frame-max}, +where 1 is the most recently deleted frame, undelete the corresponding +deleted frame. @item C-z @kindex C-z @r{(X windows)} diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index 9a23f23e0ed..edcc6075f75 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -2317,10 +2317,15 @@ them. @item M-? Find all the references for the identifier at point. -@item M-x xref-query-replace-in-results @key{RET} @var{regexp} @key{RET} @var{replacement} @key{RET} +@item M-x xref-query-replace-in-results @key{RET} @var{replacement} @key{RET} +@itemx C-u M-x xref-query-replace-in-results @key{RET} @var{regexp} @key{RET} @var{replacement} @key{RET} Interactively replace @var{regexp} with @var{replacement} in the names of all the identifiers shown in the @file{*xref*} buffer. +@item M-x xref-find-references-and-replace @key{RET} @var{from} @key{RET} @var{to} @key{RET} +Interactively rename all instances of the identifier @var{from} to the +new name @var{to}. + @item M-x tags-search @key{RET} @var{regexp} @key{RET} Search for @var{regexp} through the files in the selected tags table. @@ -2358,13 +2363,21 @@ shown. The default value is @code{nil}, which just shows the results in the @file{*xref*} buffer, but doesn't select any of them. @findex xref-query-replace-in-results - @kbd{M-x xref-query-replace-in-results} reads a regexp to match identifier -names and a replacement string, just like ordinary @kbd{M-x -query-replace-regexp}. It then performs the specified replacement in -the names of the matching identifiers in all the places in all the -files where these identifiers are referenced. This is useful when you + @kbd{M-x xref-query-replace-in-results} reads a @var{replacement} +string, just like ordinary @kbd{M-x query-replace-regexp}. It then +renames the identifiers shown in the @file{*xref*} buffer in all the +places in all the files where these identifiers are referenced, such +that their new name is @var{replacement}. This is useful when you rename your identifiers as part of refactoring. This command should -be invoked in the @file{*xref*} buffer generated by @kbd{M-?}. +be invoked in the @file{*xref*} buffer generated by @kbd{M-?}. With a +prefix argument, the command also prompts for a regexp to match +identifier names, and renames that regexp in the names of the matching +identifiers with @var{replacement}. + +@findex xref-find-references-and-replace + @kbd{M-x xref-find-references-and-replace} works similarly to +@code{xref-query-replace-in-results}, but is more convenient when you +want to rename a single identifier specified by its name @var{from}. @findex tags-search @kbd{M-x tags-search} reads a regexp using the minibuffer, then diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi index 397bddbe995..a57cfac8daf 100644 --- a/doc/emacs/search.texi +++ b/doc/emacs/search.texi @@ -436,14 +436,6 @@ incremental search adds the @samp{control-S} character to the search string. @item -@findex isearch-char-by-name -@kindex C-x 8 RET @r{(Incremental Search)} -Type @kbd{C-x 8 @key{RET}} (@code{isearch-char-by-name}), followed by -a Unicode name or code-point in hex. This adds the specified -character into the search string, similar to the usual -@code{insert-char} command (@pxref{Inserting Text}). - -@item @kindex C-^ @r{(Incremental Search)} @findex isearch-toggle-input-method @findex isearch-toggle-specified-input-method @@ -471,6 +463,14 @@ transient input method (@pxref{transient input method}) with @kbd{C-x \} (@code{isearch-transient-input-method}) to insert a single character to the search string using an input method, and automatically disable the input method afterwards. + +@item +@findex isearch-char-by-name +@kindex C-x 8 RET @r{(Incremental Search)} +Type @kbd{C-x 8 @key{RET}} (@code{isearch-char-by-name}), followed by +a Unicode name or code-point in hex. This adds the specified +character into the search string, similar to the usual +@code{insert-char} command (@pxref{Inserting Text}). @end itemize @findex isearch-emoji-by-name diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index ca7d9ada0ba..2eeb8b7ed74 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -3154,10 +3154,8 @@ raises @var{frame} above all other child frames of its parent. @deffn Command lower-frame &optional frame This function lowers frame @var{frame} (default, the selected frame) below all other frames belonging to the same or a higher z-group as -@var{frame}.@footnote{Lowering frames is not supported on Haiku, due -to limitations imposed by the system.} If @var{frame} is a child -frame (@pxref{Child Frames}), this lowers @var{frame} below all other -child frames of its parent. +@var{frame}. If @var{frame} is a child frame (@pxref{Child Frames}), +this lowers @var{frame} below all other child frames of its parent. @end deffn @defun frame-restack frame1 frame2 &optional above diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi index f2dce71e96c..2378e9efd7e 100644 --- a/doc/lispref/functions.texi +++ b/doc/lispref/functions.texi @@ -670,11 +670,10 @@ records. @xref{Function Cells}. @end defun @defun function-alias-p object &optional noerror -Use the @code{function-alias-p} function to check whether an object is -a function alias. If it isn't, this predicate will return -@code{nil}. If it is, the value returned will be a list of symbol -representing the function alias chain. For instance, if @code{a} is -an alias for @code{b}, and @code{b} is an alias for @code{c}: +Checks whether @var{object} is a function alias. If it is, it returns +a list of symbols representing the function alias chain, else +@code{nil}. For instance, if @code{a} is an alias for @code{b}, and +@code{b} is an alias for @code{c}: @example (function-alias-p 'a) diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index 61870311ed8..b3efdfbacba 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi @@ -12223,7 +12223,6 @@ controlling variable is a predicate list, as described above. @vindex gnus-treat-highlight-citation @vindex gnus-treat-highlight-headers @vindex gnus-treat-highlight-signature -@vindex gnus-treat-play-sounds @vindex gnus-treat-x-pgp-sig @vindex gnus-treat-unfold-headers @vindex gnus-treat-fold-headers @@ -12359,8 +12358,6 @@ is controlled by @code{gnus-body-boundary-delimiter}. @xref{Article Highlighting}. -@vindex gnus-treat-play-sounds -@item gnus-treat-play-sounds @item gnus-treat-ansi-sequences (t) @vindex gnus-treat-x-pgp-sig @item gnus-treat-x-pgp-sig (head) @@ -243,6 +243,16 @@ These will take you (respectively) to the next and previous "page". --- *** 'describe-char' now also outputs the name of emoji combinations. +** Outline Mode + +*** Support for a default visibility state. +Customize the option 'outline-default-state' to define what headings +are visible when the mode is set. When equal to a number, the option +'outline-default-rules' determines the visibility of the subtree +starting at the corresponding level. Values are provided to show +a heading subtree unless the heading match a regexp, or its subtree +has long lines or is long. + ** Outline Minor Mode +++ @@ -277,11 +287,12 @@ height use 'window-height' in combination with 'body-lines'. +++ *** Deleted frames can now be undeleted. -The 16 most recently deleted frames can be undeleted with 'C-x 5 u' when -'undelete-frame-mode' is enabled. Without a prefix argument, undelete -the most recently deleted frame. With a numerical prefix argument -between 1 and 16, where 1 is the most recently deleted frame, undelete -the corresponding deleted frame. +The most recently deleted frame can be undeleted with 'C-x 5 u' when +the new user option 'undelete-frame-max' has its default value 1. +Without a prefix argument, undelete the most recently deleted frame. +With a numerical prefix argument between 1 and 'undelete-frame-max', +where 1 is the most recently deleted frame, undelete the corresponding +deleted frame. ** Tab Bars and Tab Lines @@ -594,6 +605,12 @@ to enable the display of the buffer list. It is bound to 'C-M-,' and jumps to the location where 'xref-go-back' ('M-,', also known as 'xref-pop-marker-stack') was invoked previously. +*** 'xref-query-replace-in-results' does not prompt for FROM when +called without prefix argument, to make the most common case faster: +replacing entire matches. + +*** New command 'xref-find-references-and-replace' to rename one identifier. + ** File notifications +++ diff --git a/lisp/battery.el b/lisp/battery.el index 45334163fa6..b7b81a11a1c 100644 --- a/lisp/battery.el +++ b/lisp/battery.el @@ -96,12 +96,14 @@ Value does not include \".\" or \"..\"." (cond ((member battery-upower-service (dbus-list-activatable-names)) #'battery-upower) ((and (eq system-type 'gnu/linux) + (file-readable-p "/sys/") (battery--find-linux-sysfs-batteries)) #'battery-linux-sysfs) ((and (eq system-type 'gnu/linux) (file-directory-p "/proc/acpi/battery")) #'battery-linux-proc-acpi) ((and (eq system-type 'gnu/linux) + (file-readable-p "/proc/") (file-readable-p "/proc/apm")) #'battery-linux-proc-apm) ((and (eq system-type 'berkeley-unix) diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el index cf3ea8c3ddf..688c76e0c54 100644 --- a/lisp/emacs-lisp/easy-mmode.el +++ b/lisp/emacs-lisp/easy-mmode.el @@ -696,7 +696,11 @@ Valid keywords and arguments are: (defmacro easy-mmode-defmap (m bs doc &rest args) "Define a constant M whose value is the result of `easy-mmode-define-keymap'. The M, BS, and ARGS arguments are as per that function. DOC is -the constant's documentation." +the constant's documentation. + +This macro is deprecated; use `defvar-keymap' instead." + ;; FIXME: Declare obsolete in favor of `defvar-keymap'. It is still + ;; used for `gud-menu-map' and `gud-minor-mode-map', so fix that first. (declare (doc-string 3) (indent 1)) `(defconst ,m (easy-mmode-define-keymap ,bs nil (if (boundp ',m) ,m) ,(cons 'list args)) diff --git a/lisp/emacs-lisp/inline.el b/lisp/emacs-lisp/inline.el index 963e117ff34..de0112db631 100644 --- a/lisp/emacs-lisp/inline.el +++ b/lisp/emacs-lisp/inline.el @@ -71,7 +71,7 @@ (defmacro inline-quote (_exp) "Similar to backquote, but quotes code and only accepts , and not ,@." - (declare (debug backquote-form)) + (declare (debug (backquote-form))) (error "inline-quote can only be used within define-inline")) (defmacro inline-const-p (_exp) diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el index b44917f7d56..33ce55a3de8 100644 --- a/lisp/emacs-lisp/macroexp.el +++ b/lisp/emacs-lisp/macroexp.el @@ -366,14 +366,18 @@ Assumes the caller has bound `macroexpand-all-environment'." form) (macroexp--expand-all newform)))) - (`(funcall . ,(or `(,exp . ,args) pcase--dontcare)) + (`(funcall ,exp . ,args) (let ((eexp (macroexp--expand-all exp)) (eargs (macroexp--all-forms args))) ;; Rewrite (funcall #'foo bar) to (foo bar), in case `foo' ;; has a compiler-macro, or to unfold it. (pcase eexp - (`#',f (macroexp--expand-all `(,f . ,eargs))) + ((and `#',f + (guard (not (or (special-form-p f) (macrop f)))));; bug#46636 + (macroexp--expand-all `(,f . ,eargs))) (_ `(funcall ,eexp . ,eargs))))) + (`(funcall . ,_) form) ;bug#53227 + (`(,func . ,_) (let ((handler (function-get func 'compiler-macro)) (funargs (function-get func 'funarg-positions))) diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el index d199716b2c5..e782cdb1dab 100644 --- a/lisp/emacs-lisp/pp.el +++ b/lisp/emacs-lisp/pp.el @@ -273,7 +273,10 @@ Use the `pp-max-width' variable to control the desired line length." (insert "(") (pp--insert start (pop sexp)) (while sexp - (pp--insert " " (pop sexp))) + (if (consp sexp) + (pp--insert " " (pop sexp)) + (pp--insert " . " sexp) + (setq sexp nil))) (insert ")"))) (defun pp--format-function (sexp) diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index 870d34527b0..658edd67527 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -1299,6 +1299,9 @@ If FUNCTION is non-nil, place point on the entry for FUNCTION (if any)." (text-property-search-forward 'shortdoc-function function t) (beginning-of-line))) +;;;###autoload +(defalias 'shortdoc #'shortdoc-display-group) + (defun shortdoc--display-function (data) (let ((function (pop data)) (start-section (point)) diff --git a/lisp/ffap.el b/lisp/ffap.el index f9220817a71..b5d2a02cd1d 100644 --- a/lisp/ffap.el +++ b/lisp/ffap.el @@ -1449,10 +1449,13 @@ which may actually result in an URL rather than a filename." (ffap-file-exists-string (substring name 0 (match-beginning 0))))) ;; If it contains a colon, get rid of it (and return if exists) ((and (string-match path-separator name) - (setq name (ffap-string-at-point 'nocolon)) - (> (length name) 0) - (ffap-file-exists-string name))) - ;; File does not exist, try the alist: + (let ((this-name (ffap-string-at-point 'nocolon))) + ;; But don't interpret the first part if ":/bin" as + ;; the empty string. + (when (> (length this-name) 0) + (setq name this-name) + (ffap-file-exists-string name))))) + ;; File does not exist, try the alist: ((let ((alist ffap-alist) tem try case-fold-search) (while (and alist (not try)) (setq tem (car alist) alist (cdr alist)) diff --git a/lisp/frame.el b/lisp/frame.el index 599ffe591a5..5926a4d748b 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -2529,6 +2529,13 @@ deleting them." (if iconify (iconify-frame this) (delete-frame this))) (setq this next)))) + +(defcustom undelete-frame-max 1 + "Maximum number of deleted frames before oldest are thrown away." + :type 'integer + :group 'frames + :version "29.1") + (eval-when-compile (require 'frameset)) (defvar undelete-frame--deleted-frames nil @@ -2536,7 +2543,7 @@ deleting them." (defun undelete-frame--handle-delete-frame (frame) "Save the configuration of frames deleted with `delete-frame'. -Only the 16 most recently deleted frames are saved." +Only the `undelete-frame-max' most recently deleted frames are saved." (when (frame-live-p frame) (setq undelete-frame--deleted-frames (cons @@ -2555,54 +2562,45 @@ Only the 16 most recently deleted frames are saved." (cons '(display . :never) frameset-filter-alist)))) undelete-frame--deleted-frames)) - (if (> (length undelete-frame--deleted-frames) 16) + (if (> (length undelete-frame--deleted-frames) undelete-frame-max) (setq undelete-frame--deleted-frames (butlast undelete-frame--deleted-frames))))) -(define-minor-mode undelete-frame-mode - "Enable the `undelete-frame' command." - :group 'frames - :global t - (if undelete-frame-mode - (add-hook 'delete-frame-functions - #'undelete-frame--handle-delete-frame -75) - (remove-hook 'delete-frame-functions - #'undelete-frame--handle-delete-frame) - (setq undelete-frame--deleted-frames nil))) +(add-hook 'after-init-hook + (lambda () + (add-hook 'delete-frame-functions + #'undelete-frame--handle-delete-frame -75))) (defun undelete-frame (&optional arg) "Undelete a frame deleted with `delete-frame'. -Without a prefix argument, undelete the most recently deleted -frame. -With a numerical prefix argument ARG between 1 and 16, where 1 is -most recently deleted frame, undelete the ARGth deleted frame. +Without a prefix argument, undelete the most recently deleted frame. +With a numerical prefix argument ARG between 1 and `undelete-frame-max', +where 1 is most recently deleted frame, undelete the ARGth deleted frame. When called from Lisp, returns the new frame." (interactive "P") - (if (not undelete-frame-mode) - (user-error "Undelete-Frame mode is disabled") - (if (consp arg) - (user-error "Missing deleted frame number argument") - (let* ((number (pcase arg ('nil 1) ('- -1) (_ arg))) - (frames (frame-list)) - (frameset (nth (1- number) undelete-frame--deleted-frames)) - (graphic (display-graphic-p))) - (if (not (<= 1 number 16)) - (user-error "%d is not a valid deleted frame number argument" - number) - (if (not frameset) - (user-error "No deleted frame with number %d" number) - (if (not (eq graphic (car frameset))) - (user-error - "Cannot undelete a %s display frame on a %s display" - (if graphic "non-graphic" "graphic") - (if graphic "graphic" "non-graphic")) - (setq undelete-frame--deleted-frames - (delq frameset undelete-frame--deleted-frames)) - (frameset-restore (cdr frameset)) - (let ((frame (car (seq-difference (frame-list) frames)))) - (when frame - (select-frame-set-input-focus frame) - frame))))))))) + (if (consp arg) + (user-error "Missing deleted frame number argument") + (let* ((number (pcase arg ('nil 1) ('- -1) (_ arg))) + (frames (frame-list)) + (frameset (nth (1- number) undelete-frame--deleted-frames)) + (graphic (display-graphic-p))) + (if (not (<= 1 number undelete-frame-max)) + (user-error "%d is not a valid deleted frame number argument" + number) + (if (not frameset) + (user-error "No deleted frame with number %d" number) + (if (not (eq graphic (car frameset))) + (user-error + "Cannot undelete a %s display frame on a %s display" + (if graphic "non-graphic" "graphic") + (if graphic "graphic" "non-graphic")) + (setq undelete-frame--deleted-frames + (delq frameset undelete-frame--deleted-frames)) + (frameset-restore (cdr frameset)) + (let ((frame (car (seq-difference (frame-list) frames)))) + (when frame + (select-frame-set-input-focus frame) + frame)))))))) ;;; Window dividers. (defgroup window-divider nil diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el index d3e476b5d64..6dfdcaf55c7 100644 --- a/lisp/gnus/gnus-sum.el +++ b/lisp/gnus/gnus-sum.el @@ -11898,7 +11898,8 @@ Returns nil if no threads were there to be hidden." (beginning-of-line) (let ((start (point)) (starteol (line-end-position)) - (article (gnus-summary-article-number))) + (article (unless (gnus-summary-article-intangible-p) + (gnus-summary-article-number)))) ;; Go forward until either the buffer ends or the subthread ends. (when (and (not (eobp)) (or (zerop (gnus-summary-next-thread 1 t)) @@ -11912,7 +11913,9 @@ Returns nil if no threads were there to be hidden." (let ((ol (make-overlay starteol (point) nil t nil))) (overlay-put ol 'invisible 'gnus-sum) (overlay-put ol 'evaporate t))) - (gnus-summary-goto-subject article) + (if article + (gnus-summary-goto-subject article) + (gnus-summary-position-point)) ;; We moved backward past the start point (invisible thread?) (when (> start (point)) (goto-char starteol))) diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index 090cb9b245b..cff628061e9 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el @@ -246,7 +246,7 @@ during splitting, which may be slow." (nnimap-header-parameters)) t) (unless (process-live-p (get-buffer-process (current-buffer))) - (error "Server closed connection")) + (error "IMAP server %S closed connection" nnimap-address)) (nnimap-transform-headers) (nnheader-remove-cr-followed-by-lf)) (insert-buffer-substring diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el index 624c64d4d75..0dcff9743ad 100644 --- a/lisp/gnus/nntp.el +++ b/lisp/gnus/nntp.el @@ -306,7 +306,7 @@ backend doesn't catch this error.") (nntp-record-command string)) (process-send-string process (concat string nntp-end-of-line)) (or (memq (process-status process) '(open run)) - (nntp-report "Server closed connection"))) + (nntp-report "NNTP server %S closed connection" nntp-address))) (defun nntp-record-command (string) "Record the command STRING." @@ -369,7 +369,7 @@ retried once before actually displaying the error report." (nntp-snarf-error-message) nil)) ((not (memq (process-status process) '(open run))) - (nntp-report "Server closed connection")) + (nntp-report "NNTP server %S closed connection" nntp-address)) (t (goto-char (point-max)) (let ((limit (point-min)) @@ -1431,7 +1431,7 @@ If SEND-IF-FORCE, only send authinfo to the server if the ;; be the process's former output buffer (i.e. now killed) (or (and process (memq (process-status process) '(open run))) - (nntp-report "Server closed connection"))))) + (nntp-report "NNTP server %S closed connection" nntp-address))))) (defun nntp-accept-response () "Wait for output from the process that outputs to BUFFER." @@ -1450,7 +1450,7 @@ If SEND-IF-FORCE, only send authinfo to the server if the (when group (let ((entry (nntp-find-connection-entry nntp-server-buffer))) (cond ((not entry) - (nntp-report "Server closed connection")) + (nntp-report "NNTP server %S closed connection" nntp-address)) ((not (equal group (caddr entry))) (with-current-buffer (process-buffer (car entry)) (erase-buffer) diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el index fbd698e234a..b77f9181a9c 100644 --- a/lisp/hi-lock.el +++ b/lisp/hi-lock.el @@ -854,6 +854,27 @@ SPACES-REGEXP is a regexp to substitute spaces in font-lock search." ;; continue standard unloading nil) +;;; Mouse support +(defalias 'highlight-symbol-at-mouse 'hi-lock-face-symbol-at-mouse) +(defun hi-lock-face-symbol-at-mouse (event) + "Highlight symbol at mouse click EVENT." + (interactive "e") + (save-excursion + (mouse-set-point event) + (highlight-symbol-at-point))) + +;;;###autoload +(defun hi-lock-context-menu (menu click) + "Populate MENU with a menu item to highlight symbol at CLICK." + (when (thing-at-mouse click 'symbol) + (define-key-after menu [highlight-search-separator] menu-bar-separator + 'middle-separator) + (define-key-after menu [highlight-search-mouse] + '(menu-item "Highlight Symbol" highlight-symbol-at-mouse + :help "Highlight symbol at point") + 'highlight-search-separator)) + menu) + (provide 'hi-lock) ;;; hi-lock.el ends here diff --git a/lisp/image-dired.el b/lisp/image-dired.el index 536f29441ae..b81df8567bd 100644 --- a/lisp/image-dired.el +++ b/lisp/image-dired.el @@ -609,9 +609,7 @@ See also `image-dired-thumbnail-storage'." ((eq 'use-image-dired-dir image-dired-thumbnail-storage) (let* ((f (expand-file-name file)) (hash - ;; SHA1 is slightly faster than MD5, so let's use it. - ;; (We don't need anything crytographically strong.) - (sha1 (file-name-as-directory (file-name-directory f))))) + (md5 (file-name-as-directory (file-name-directory f))))) (format "%s%s%s.thumb.%s" (file-name-as-directory (expand-file-name (image-dired-dir))) (file-name-base f) diff --git a/lisp/indent.el b/lisp/indent.el index 40669b38424..d20c8053c5f 100644 --- a/lisp/indent.el +++ b/lisp/indent.el @@ -77,10 +77,11 @@ This variable has no effect unless `tab-always-indent' is `complete'." :group 'indent :type '(choice (const :tag "Always complete" nil) - (const :tag "Unless at the end of a line" 'eol) - (const :tag "Unless looking at a word" 'word) - (const :tag "Unless at a word or parenthesis" 'word-or-paren) - (const :tag "Unless at a word, parenthesis, or punctuation." 'word-or-paren-or-punct)) + (const :tag "Unless at the end of a line" eol) + (const :tag "Unless looking at a word" word) + (const :tag "Unless at a word or parenthesis" word-or-paren) + (const :tag "Unless at a word, parenthesis, or punctuation." + word-or-paren-or-punct)) :version "28.1") (defvar indent-line-ignored-functions '(indent-relative @@ -170,7 +171,7 @@ prefix argument is ignored." (let ((old-tick (buffer-chars-modified-tick)) (old-point (point)) (old-indent (current-indentation)) - (syn `(,(syntax-after (point))))) + (syn (syntax-after (point)))) ;; Indent the line. (or (not (eq (indent--funcall-widened indent-line-function) 'noindent)) @@ -182,21 +183,21 @@ prefix argument is ignored." (cond ;; If the text was already indented right, try completion. ((and (eq tab-always-indent 'complete) - (eq old-point (point)) - (eq old-tick (buffer-chars-modified-tick)) + (eql old-point (point)) + (eql old-tick (buffer-chars-modified-tick)) (or (null tab-first-completion) (eq last-command this-command) - (and (equal tab-first-completion 'eol) + (and (eq tab-first-completion 'eol) (eolp)) - (and (member tab-first-completion - '(word word-or-paren word-or-paren-or-punct)) - (not (member 2 syn))) - (and (member tab-first-completion - '(word-or-paren word-or-paren-or-punct)) - (not (or (member 4 syn) - (member 5 syn)))) - (and (equal tab-first-completion 'word-or-paren-or-punct) - (not (member 1 syn))))) + (and (memq tab-first-completion + '(word word-or-paren word-or-paren-or-punct)) + (not (eql 2 syn))) + (and (memq tab-first-completion + '(word-or-paren word-or-paren-or-punct)) + (not (or (eql 4 syn) + (eql 5 syn)))) + (and (eq tab-first-completion 'word-or-paren-or-punct) + (not (eql 1 syn))))) (completion-at-point)) ;; If a prefix argument was given, rigidly indent the following diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el index 264a1f09dc2..df488708afa 100644 --- a/lisp/international/emoji.el +++ b/lisp/international/emoji.el @@ -55,6 +55,14 @@ "Face for emojis that have derivations." :version "29.1") +(defvar emoji-alternate-names nil + "Alist of emojis and lists of alternate names for the emojis. +Each element in the alist should have the emoji (as a string) as +the first element, and the rest of the elements should be strings +representing names. For instance: + + (\"🤗\" \"hug\" \"hugging\" \"kind\")") + (defvar emoji--labels nil) (defvar emoji--all-bases nil) (defvar emoji--derived nil) @@ -90,8 +98,9 @@ of selecting from emoji display." ;;;###autoload (defun emoji-search () "Choose and insert an emoji glyph by typing its Unicode name. -This command prompts for an emoji name, with completion, and inserts it. -It recognizes the Unicode Standard names of emoji." +This command prompts for an emoji name, with completion, and +inserts it. It recognizes the Unicode Standard names of emoji, +and also consults the `emoji-alternate-names' alist." (interactive "*") (emoji--init) (emoji--choose-emoji)) @@ -647,29 +656,47 @@ We prefer the earliest unique letter." (defun emoji--choose-emoji () ;; Use the list of names. - (let ((name - (completing-read - "Insert emoji: " - (lambda (string pred action) - (if (eq action 'metadata) - (list 'metadata - (cons - 'affixation-function - ;; Add the glyphs to the start of the displayed - ;; strings when TAB-ing. - (lambda (strings) - (mapcar - (lambda (name) - (list name - (concat - (or (gethash name emoji--all-bases) " ") - "\t") - "")) - strings)))) - (complete-with-action action emoji--all-bases string pred))) - nil t))) + (let* ((table + (if (not emoji-alternate-names) + ;; If we don't have alternate names, do the efficient version. + emoji--all-bases + ;; Compute all the (possibly non-unique) names. + (let ((table nil)) + (maphash + (lambda (name glyph) + (push (concat name "\t" glyph) table)) + emoji--all-bases) + (dolist (elem emoji-alternate-names) + (dolist (name (cdr elem)) + (push (concat name "\t" (car elem)) table))) + (sort table #'string<)))) + (name + (completing-read + "Insert emoji: " + (lambda (string pred action) + (if (eq action 'metadata) + (list 'metadata + (cons + 'affixation-function + ;; Add the glyphs to the start of the displayed + ;; strings when TAB-ing. + (lambda (strings) + (mapcar + (lambda (name) + (if emoji-alternate-names + (list name "" "") + (list name + (concat + (or (gethash name emoji--all-bases) " ") + "\t") + ""))) + strings)))) + (complete-with-action action table string pred))) + nil t))) (when (cl-plusp (length name)) - (let* ((glyph (gethash name emoji--all-bases)) + (let* ((glyph (if emoji-alternate-names + (cadr (split-string name "\t")) + (gethash name emoji--all-bases))) (derived (gethash glyph emoji--derived))) (if (not derived) ;; Simple glyph with no derivations. diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el index 6d5b0d84e6b..05d461e41e9 100644 --- a/lisp/ldefs-boot.el +++ b/lisp/ldefs-boot.el @@ -8861,8 +8861,12 @@ Define a constant M whose value is the result of `easy-mmode-define-keymap'. The M, BS, and ARGS arguments are as per that function. DOC is the constant's documentation. +This macro is deprecated; use `defvar-keymap' instead. + \(fn M BS DOC &rest ARGS)" nil t) +(function-put 'easy-mmode-defmap 'doc-string-elt '3) + (function-put 'easy-mmode-defmap 'lisp-indent-function '1) (autoload 'easy-mmode-defsyntax "easy-mmode" "\ @@ -8871,6 +8875,8 @@ CSS contains a list of syntax specifications of the form (CHAR . SYNTAX). \(fn ST CSS DOC &rest ARGS)" nil t) +(function-put 'easy-mmode-defsyntax 'doc-string-elt '3) + (function-put 'easy-mmode-defsyntax 'lisp-indent-function '1) (register-definition-prefixes "easy-mmode" '("easy-mmode-")) @@ -10291,6 +10297,31 @@ disabled. ;;;### (autoloads nil "elide-head" "elide-head.el" (0 0 0 0)) ;;; Generated autoloads from elide-head.el +(autoload 'elide-head-mode "elide-head" "\ +Toggle eliding (hiding) header material in the current buffer. + +This is a minor mode. If called interactively, toggle the `Elide-Head +mode' mode. If the prefix argument is positive, enable the mode, and +if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable the +mode if ARG is nil, omitted, or is a positive number. Disable the +mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `elide-head-mode'. + +The mode's hook is called both when the mode is enabled and when it is +disabled. + +When Elide Header mode is enabled, headers are hidden according +to `elide-head-headers-to-hide'. + +This is suitable as an entry on `find-file-hook' or appropriate +mode hooks. + +\(fn &optional ARG)" t nil) + (autoload 'elide-head "elide-head" "\ Hide header material in buffer according to `elide-head-headers-to-hide'. @@ -10301,6 +10332,8 @@ This is suitable as an entry on `find-file-hook' or appropriate mode hooks. \(fn &optional ARG)" t nil) +(make-obsolete 'elide-head 'elide-head-mode '"29.1") + (register-definition-prefixes "elide-head" '("elide-head-")) ;;;*** @@ -16764,6 +16797,11 @@ be found in variable `hi-lock-interactive-patterns'." t nil) (autoload 'hi-lock-find-patterns "hi-lock" "\ Add patterns from the current buffer to the list of hi-lock patterns." t nil) +(autoload 'hi-lock-context-menu "hi-lock" "\ +Populate MENU with a menu item to highlight symbol at CLICK. + +\(fn MENU CLICK)" nil nil) + (register-definition-prefixes "hi-lock" '("hi-lock-" "turn-on-hi-lock-if-enabled")) ;;;*** @@ -19155,25 +19193,37 @@ system." t nil) (put 'info-lookup-symbol 'info-file "emacs") (autoload 'info-lookup-symbol "info-look" "\ -Display the definition of SYMBOL, as found in the relevant manual. -When this command is called interactively, it reads SYMBOL from the -minibuffer. In the minibuffer, use \\<minibuffer-local-completion-map>\\[next-history-element] to yank the default argument -value into the minibuffer so you can edit it. The default symbol is the -one found at point. +Look up and display documentation of SYMBOL in the relevant Info manual. +SYMBOL should be an identifier: a function or method, a macro, a variable, +a data type, a class, etc. -With prefix arg MODE a query for the symbol help mode is offered. +Interactively, prompt for SYMBOL; you can use \\<minibuffer-local-completion-map>\\[next-history-element] in the minibuffer +to yank the default argument value into the minibuffer so you can edit it. +The default symbol is the one found at point. + +MODE is the major mode whose Info manuals to search for the documentation +of SYMBOL. It defaults to the current buffer's `major-mode'; if that +mode doesn't have any Info manuals known to Emacs, the command will +prompt for MODE to use, with completion. With prefix arg, the command +always prompts for MODE. \(fn SYMBOL &optional MODE)" t nil) (put 'info-lookup-file 'info-file "emacs") (autoload 'info-lookup-file "info-look" "\ -Display the documentation of a file. -When this command is called interactively, it reads FILE from the minibuffer. -In the minibuffer, use \\<minibuffer-local-completion-map>\\[next-history-element] to yank the default file name -into the minibuffer so you can edit it. +Look up and display documentation of FILE in the relevant Info manual. +FILE should be the name of a file; a notable example is a standard header +file that is part of the C or C++ standard library. + +Interactively, prompt for FILE; you can use \\<minibuffer-local-completion-map>\\[next-history-element] in the minibuffer +to yank the default argument value into the minibuffer so you can edit it. The default file name is the one found at point. -With prefix arg MODE a query for the file help mode is offered. +MODE is the major mode whose Info manuals to search for the documentation +of FILE. It defaults to the current buffer's `major-mode'; if that +mode doesn't have any Info manuals known to Emacs, the command will +prompt for MODE to use, with completion. With prefix arg, the command +always prompts for MODE. \(fn FILE &optional MODE)" t nil) @@ -19859,7 +19909,7 @@ one of the aforementioned options instead of using this mode. ;;;### (autoloads nil "jsonrpc" "jsonrpc.el" (0 0 0 0)) ;;; Generated autoloads from jsonrpc.el -(push (purecopy '(jsonrpc 1 0 14)) package--builtin-versions) +(push (purecopy '(jsonrpc 1 0 15)) package--builtin-versions) (register-definition-prefixes "jsonrpc" '("jsonrpc-")) @@ -21311,6 +21361,11 @@ Default bookmark handler for Man buffers. \(fn BOOKMARK)" nil nil) +(autoload 'Man-context-menu "man" "\ +Populate MENU with commands that open a man page at point. + +\(fn MENU CLICK)" nil nil) + (register-definition-prefixes "man" '("Man-" "man")) ;;;*** @@ -31067,6 +31122,8 @@ If FUNCTION is non-nil, place point on the entry for FUNCTION (if any). \(fn GROUP &optional FUNCTION)" t nil) +(defalias 'shortdoc #'shortdoc-display-group) + (register-definition-prefixes "shortdoc" '("alist" "buffer" "define-short-documentation-group" "file" "hash-table" "keymaps" "list" "number" "overlay" "process" "regexp" "sequence" "shortdoc-" "string" "text-properties" "vector")) ;;;*** @@ -39394,6 +39451,32 @@ unless `windmove-create-window' is non-nil and a new window is created. \(fn &optional ARG)" t nil) +(defvar windmove-mode t "\ +Non-nil if Windmove mode is enabled. +See the `windmove-mode' command +for a description of this minor mode.") + +(custom-autoload 'windmove-mode "windmove" nil) + +(autoload 'windmove-mode "windmove" "\ +Global minor mode for default windmove commands. + +This is a minor mode. If called interactively, toggle the `Windmove +mode' mode. If the prefix argument is positive, enable the mode, and +if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable the +mode if ARG is nil, omitted, or is a positive number. Disable the +mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='windmove-mode)'. + +The mode's hook is called both when the mode is enabled and when it is +disabled. + +\(fn &optional ARG)" t nil) + (autoload 'windmove-default-keybindings "windmove" "\ Set up keybindings for `windmove'. Keybindings are of the form MODIFIERS-{left,right,up,down}, @@ -39969,24 +40052,23 @@ Zone out, completely." t nil) ;;;### (autoloads nil nil ("abbrev.el" "bindings.el" "buff-menu.el" ;;;;;; "button.el" "calc/calc-aent.el" "calc/calc-embed.el" "calc/calc-misc.el" -;;;;;; "calc/calc-yank.el" "case-table.el" "cedet/ede/base.el" "cedet/ede/config.el" -;;;;;; "cedet/ede/cpp-root.el" "cedet/ede/custom.el" "cedet/ede/dired.el" -;;;;;; "cedet/ede/emacs.el" "cedet/ede/files.el" "cedet/ede/generic.el" -;;;;;; "cedet/ede/linux.el" "cedet/ede/locate.el" "cedet/ede/make.el" -;;;;;; "cedet/ede/shell.el" "cedet/ede/speedbar.el" "cedet/ede/system.el" -;;;;;; "cedet/ede/util.el" "cedet/semantic/analyze.el" "cedet/semantic/analyze/complete.el" -;;;;;; "cedet/semantic/analyze/refs.el" "cedet/semantic/bovine.el" -;;;;;; "cedet/semantic/bovine/c-by.el" "cedet/semantic/bovine/c.el" -;;;;;; "cedet/semantic/bovine/el.el" "cedet/semantic/bovine/gcc.el" -;;;;;; "cedet/semantic/bovine/make-by.el" "cedet/semantic/bovine/make.el" -;;;;;; "cedet/semantic/bovine/scm-by.el" "cedet/semantic/bovine/scm.el" -;;;;;; "cedet/semantic/complete.el" "cedet/semantic/ctxt.el" "cedet/semantic/db-file.el" -;;;;;; "cedet/semantic/db-find.el" "cedet/semantic/db-global.el" -;;;;;; "cedet/semantic/db-mode.el" "cedet/semantic/db-typecache.el" -;;;;;; "cedet/semantic/db.el" "cedet/semantic/debug.el" "cedet/semantic/decorate/include.el" -;;;;;; "cedet/semantic/decorate/mode.el" "cedet/semantic/dep.el" -;;;;;; "cedet/semantic/doc.el" "cedet/semantic/edit.el" "cedet/semantic/find.el" -;;;;;; "cedet/semantic/format.el" "cedet/semantic/grammar-wy.el" +;;;;;; "calc/calc-yank.el" "case-table.el" "cedet/ede/cpp-root.el" +;;;;;; "cedet/ede/custom.el" "cedet/ede/dired.el" "cedet/ede/emacs.el" +;;;;;; "cedet/ede/files.el" "cedet/ede/generic.el" "cedet/ede/linux.el" +;;;;;; "cedet/ede/locate.el" "cedet/ede/make.el" "cedet/ede/speedbar.el" +;;;;;; "cedet/ede/system.el" "cedet/ede/util.el" "cedet/semantic/analyze.el" +;;;;;; "cedet/semantic/analyze/complete.el" "cedet/semantic/analyze/refs.el" +;;;;;; "cedet/semantic/bovine.el" "cedet/semantic/bovine/c-by.el" +;;;;;; "cedet/semantic/bovine/c.el" "cedet/semantic/bovine/el.el" +;;;;;; "cedet/semantic/bovine/gcc.el" "cedet/semantic/bovine/make-by.el" +;;;;;; "cedet/semantic/bovine/make.el" "cedet/semantic/bovine/scm-by.el" +;;;;;; "cedet/semantic/bovine/scm.el" "cedet/semantic/complete.el" +;;;;;; "cedet/semantic/ctxt.el" "cedet/semantic/db-file.el" "cedet/semantic/db-find.el" +;;;;;; "cedet/semantic/db-global.el" "cedet/semantic/db-mode.el" +;;;;;; "cedet/semantic/db-typecache.el" "cedet/semantic/db.el" "cedet/semantic/debug.el" +;;;;;; "cedet/semantic/decorate/include.el" "cedet/semantic/decorate/mode.el" +;;;;;; "cedet/semantic/dep.el" "cedet/semantic/doc.el" "cedet/semantic/edit.el" +;;;;;; "cedet/semantic/find.el" "cedet/semantic/format.el" "cedet/semantic/grammar-wy.el" ;;;;;; "cedet/semantic/grm-wy-boot.el" "cedet/semantic/html.el" ;;;;;; "cedet/semantic/ia-sb.el" "cedet/semantic/ia.el" "cedet/semantic/idle.el" ;;;;;; "cedet/semantic/imenu.el" "cedet/semantic/lex-spp.el" "cedet/semantic/lex.el" @@ -40005,8 +40087,8 @@ Zone out, completely." t nil) ;;;;;; "cedet/srecode/insert.el" "cedet/srecode/java.el" "cedet/srecode/map.el" ;;;;;; "cedet/srecode/mode.el" "cedet/srecode/srt-wy.el" "cedet/srecode/srt.el" ;;;;;; "cedet/srecode/template.el" "cedet/srecode/texi.el" "composite.el" -;;;;;; "cus-face.el" "cus-start.el" "custom.el" "dired-aux.el" "dired-x.el" -;;;;;; "electric.el" "emacs-lisp/backquote.el" "emacs-lisp/byte-run.el" +;;;;;; "cus-face.el" "cus-load.el" "cus-start.el" "custom.el" "dired-aux.el" +;;;;;; "dired-x.el" "electric.el" "emacs-lisp/backquote.el" "emacs-lisp/byte-run.el" ;;;;;; "emacs-lisp/cl-extra.el" "emacs-lisp/cl-macs.el" "emacs-lisp/cl-preloaded.el" ;;;;;; "emacs-lisp/cl-seq.el" "emacs-lisp/easymenu.el" "emacs-lisp/eieio-custom.el" ;;;;;; "emacs-lisp/eieio-opt.el" "emacs-lisp/float-sup.el" "emacs-lisp/lisp-mode.el" @@ -40028,30 +40110,41 @@ Zone out, completely." t nil) ;;;;;; "eshell/em-pred.el" "eshell/em-prompt.el" "eshell/em-rebind.el" ;;;;;; "eshell/em-script.el" "eshell/em-smart.el" "eshell/em-term.el" ;;;;;; "eshell/em-tramp.el" "eshell/em-unix.el" "eshell/em-xtra.el" -;;;;;; "faces.el" "files.el" "font-core.el" "font-lock.el" "format.el" -;;;;;; "frame.el" "help.el" "hfy-cmap.el" "ibuf-ext.el" "indent.el" -;;;;;; "international/characters.el" "international/charscript.el" -;;;;;; "international/cp51932.el" "international/emoji-zwj.el" "international/eucjp-ms.el" +;;;;;; "eshell/esh-groups.el" "faces.el" "files.el" "finder-inf.el" +;;;;;; "font-core.el" "font-lock.el" "format.el" "frame.el" "help.el" +;;;;;; "hfy-cmap.el" "ibuf-ext.el" "indent.el" "international/characters.el" +;;;;;; "international/charprop.el" "international/charscript.el" +;;;;;; "international/cp51932.el" "international/emoji-labels.el" +;;;;;; "international/emoji-zwj.el" "international/eucjp-ms.el" ;;;;;; "international/iso-transl.el" "international/mule-cmds.el" -;;;;;; "international/mule-conf.el" "international/mule.el" "isearch.el" -;;;;;; "jit-lock.el" "jka-cmpr-hook.el" "keymap.el" "language/burmese.el" -;;;;;; "language/cham.el" "language/chinese.el" "language/cyrillic.el" -;;;;;; "language/czech.el" "language/english.el" "language/ethiopic.el" -;;;;;; "language/european.el" "language/georgian.el" "language/greek.el" -;;;;;; "language/hebrew.el" "language/indian.el" "language/japanese.el" -;;;;;; "language/khmer.el" "language/korean.el" "language/lao.el" -;;;;;; "language/misc-lang.el" "language/romanian.el" "language/sinhala.el" -;;;;;; "language/slovak.el" "language/tai-viet.el" "language/thai.el" -;;;;;; "language/tibetan.el" "language/utf-8-lang.el" "language/vietnamese.el" -;;;;;; "ldefs-boot.el" "leim/ja-dic/ja-dic.el" "leim/leim-list.el" -;;;;;; "leim/quail/4Corner.el" "leim/quail/ARRAY30.el" "leim/quail/CCDOSPY.el" -;;;;;; "leim/quail/CTLau-b5.el" "leim/quail/CTLau.el" "leim/quail/ECDICT.el" -;;;;;; "leim/quail/ETZY.el" "leim/quail/PY-b5.el" "leim/quail/PY.el" -;;;;;; "leim/quail/Punct-b5.el" "leim/quail/Punct.el" "leim/quail/QJ-b5.el" -;;;;;; "leim/quail/QJ.el" "leim/quail/SW.el" "leim/quail/TONEPY.el" -;;;;;; "leim/quail/ZIRANMA.el" "leim/quail/ZOZY.el" "leim/quail/arabic.el" -;;;;;; "leim/quail/cham.el" "leim/quail/compose.el" "leim/quail/croatian.el" -;;;;;; "leim/quail/cyril-jis.el" "leim/quail/cyrillic.el" "leim/quail/czech.el" +;;;;;; "international/mule-conf.el" "international/mule.el" "international/uni-bidi.el" +;;;;;; "international/uni-brackets.el" "international/uni-category.el" +;;;;;; "international/uni-combining.el" "international/uni-comment.el" +;;;;;; "international/uni-decimal.el" "international/uni-decomposition.el" +;;;;;; "international/uni-digit.el" "international/uni-lowercase.el" +;;;;;; "international/uni-mirrored.el" "international/uni-name.el" +;;;;;; "international/uni-numeric.el" "international/uni-old-name.el" +;;;;;; "international/uni-special-lowercase.el" "international/uni-special-titlecase.el" +;;;;;; "international/uni-special-uppercase.el" "international/uni-titlecase.el" +;;;;;; "international/uni-uppercase.el" "isearch.el" "jit-lock.el" +;;;;;; "jka-cmpr-hook.el" "keymap.el" "language/burmese.el" "language/cham.el" +;;;;;; "language/chinese.el" "language/cyrillic.el" "language/czech.el" +;;;;;; "language/english.el" "language/ethiopic.el" "language/european.el" +;;;;;; "language/georgian.el" "language/greek.el" "language/hebrew.el" +;;;;;; "language/indian.el" "language/japanese.el" "language/khmer.el" +;;;;;; "language/korean.el" "language/lao.el" "language/misc-lang.el" +;;;;;; "language/romanian.el" "language/sinhala.el" "language/slovak.el" +;;;;;; "language/tai-viet.el" "language/thai.el" "language/tibetan.el" +;;;;;; "language/utf-8-lang.el" "language/vietnamese.el" "ldefs-boot.el" +;;;;;; "leim/ja-dic/ja-dic.el" "leim/leim-list.el" "leim/quail/4Corner.el" +;;;;;; "leim/quail/ARRAY30.el" "leim/quail/CCDOSPY.el" "leim/quail/CTLau-b5.el" +;;;;;; "leim/quail/CTLau.el" "leim/quail/ECDICT.el" "leim/quail/ETZY.el" +;;;;;; "leim/quail/PY-b5.el" "leim/quail/PY.el" "leim/quail/Punct-b5.el" +;;;;;; "leim/quail/Punct.el" "leim/quail/QJ-b5.el" "leim/quail/QJ.el" +;;;;;; "leim/quail/SW.el" "leim/quail/TONEPY.el" "leim/quail/ZIRANMA.el" +;;;;;; "leim/quail/ZOZY.el" "leim/quail/arabic.el" "leim/quail/cham.el" +;;;;;; "leim/quail/compose.el" "leim/quail/croatian.el" "leim/quail/cyril-jis.el" +;;;;;; "leim/quail/cyrillic.el" "leim/quail/czech.el" "leim/quail/emoji.el" ;;;;;; "leim/quail/georgian.el" "leim/quail/greek.el" "leim/quail/hanja-jis.el" ;;;;;; "leim/quail/hanja.el" "leim/quail/hanja3.el" "leim/quail/hebrew.el" ;;;;;; "leim/quail/ipa-praat.el" "leim/quail/latin-alt.el" "leim/quail/latin-ltx.el" diff --git a/lisp/man.el b/lisp/man.el index adf244a11ad..a53a696c313 100644 --- a/lisp/man.el +++ b/lisp/man.el @@ -1976,6 +1976,32 @@ Uses `Man-name-local-regexp'." (bookmark-default-handler `("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bookmark))))) +;;; Mouse support +(defun Man-at-mouse (e) + "Open man manual at point." + (interactive "e") + (save-excursion + (mouse-set-point e) + (man (Man-default-man-entry)))) + +;;;###autoload +(defun Man-context-menu (menu click) + "Populate MENU with commands that open a man page at point." + (save-excursion + (mouse-set-point click) + (when (save-excursion + (skip-syntax-backward "^ ") + (and (looking-at + "[[:space:]]*\\([[:alnum:]_-]+([[:alnum:]]+)\\)") + (match-string 1))) + (define-key-after menu [man-separator] menu-bar-separator + 'middle-separator) + (define-key-after menu [man-at-mouse] + '(menu-item "Open man page" Man-at-mouse + :help "Open man page around mouse click") + 'man-separator))) + menu) + ;; Init the man package variables, if not already done. (Man-init-defvars) diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index 36cbd6a9c51..e5a070b24ad 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el @@ -109,14 +109,9 @@ (bindings--define-key menu [separator-tab] menu-bar-separator)) - (bindings--define-key menu [enable-undelete-frame-mode] - '(menu-item "Enable Undeleting Frames" undelete-frame-mode - :visible (null undelete-frame-mode) - :help "Enable undeleting frames in this session")) (bindings--define-key menu [undelete-last-deleted-frame] '(menu-item "Undelete Frame" undelete-frame - :visible (and undelete-frame-mode - (car undelete-frame--deleted-frames)) + :visible (car undelete-frame--deleted-frames) :help "Undelete the most recently deleted frame")) ;; Don't use delete-frame as event name because that is a special diff --git a/lisp/mouse.el b/lisp/mouse.el index 1a76b9a0b66..502683d3d1e 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -298,6 +298,10 @@ and should return the same menu with changes such as added new menu items." (function-item context-menu-buffers) (function-item context-menu-vc) (function-item context-menu-ffap) + (function-item hi-lock-context-menu) + (function-item occur-context-menu) + (function-item Man-context-menu) + (function-item dictionary-context-menu) (function :tag "Custom function"))) :version "28.1") @@ -320,6 +324,8 @@ the function `context-menu-filter-function'." (fun (mouse-posn-property (event-start click) 'context-menu-function))) + (select-window (posn-window (event-start click))) + (if (functionp fun) (setq menu (funcall fun menu click)) (run-hook-wrapped 'context-menu-functions diff --git a/lisp/net/dictionary.el b/lisp/net/dictionary.el index 507363cc0f8..e0824f39716 100644 --- a/lisp/net/dictionary.el +++ b/lisp/net/dictionary.el @@ -1376,7 +1376,7 @@ any buffer where (dictionary-tooltip-mode 1) has been called." (dictionary-search word))) ;;;###autoload -(defun context-menu-dictionary (menu click) +(defun dictionary-context-menu (menu click) "Populate MENU with dictionary commands at CLICK. When you add this function to `context-menu-functions', the context menu will contain an item that searches diff --git a/lisp/net/mailcap.el b/lisp/net/mailcap.el index bf3c8edd1e3..b65f7c25b83 100644 --- a/lisp/net/mailcap.el +++ b/lisp/net/mailcap.el @@ -319,8 +319,9 @@ attribute name (viewer, test, etc). This looks like: Where VIEWERINFO specifies how the content-type is viewed. Can be a string, in which case it is run through a shell, with appropriate -parameters, or a symbol, in which case the symbol is `funcall'ed if -and only if it exists as a function, with the buffer as an argument. +parameters, or a symbol, in which case the symbol must name a function +of zero arguments which is called in a buffer holding the MIME part's +content. TESTINFO is a test for the viewer's applicability, or nil. If nil, it means the viewer is always valid. If it is a Lisp function, it is @@ -439,9 +440,10 @@ MAILCAPS if set; otherwise (on Unix) use the path from RFC 1524, plus ("/usr/local/etc/mailcap" system))))) (when (stringp path) (setq path (mapcar #'list (split-string path path-separator t)))) - (when (seq-some (lambda (f) - (file-has-changed-p (car f) 'mail-parse-mailcaps)) - path) + (when (or (null mailcap--computed-mime-data) + (seq-some (lambda (f) + (file-has-changed-p (car f) 'mail-parse-mailcaps)) + path)) ;; Clear out all old data. (setq mailcap--computed-mime-data nil) ;; Add the Emacs-distributed defaults (which will be used as @@ -1174,34 +1176,45 @@ See \"~/.mailcap\", `mailcap-mime-data' and related files and variables." (mailcap-parse-mailcaps) (let ((command (mailcap-mime-info (mailcap-extension-to-mime (file-name-extension file))))) - (unless command - (error "No viewer for %s" (file-name-extension file))) - ;; Remove quotes around the file name - we'll use shell-quote-argument. - (while (string-match "['\"]%s['\"]" command) - (setq command (replace-match "%s" t t command))) - (setq command (replace-regexp-in-string - "%s" - (shell-quote-argument (convert-standard-filename file)) - command - nil t)) - ;; Handlers such as "gio open" and kde-open5 start viewer in background - ;; and exit immediately. Avoid `start-process' since it assumes - ;; :connection-type `pty' and kills children processes with SIGHUP - ;; when temporary terminal session is finished (Bug#44824). - ;; An alternative is `process-connection-type' let-bound to nil for - ;; `start-process-shell-command' call (with no chance to report failure). - (make-process - :name "mailcap-view-file" - :connection-type 'pipe - :buffer nil ; "*Messages*" may be suitable for debugging - :sentinel (lambda (proc event) - (when (and (memq (process-status proc) '(exit signal)) - (/= (process-exit-status proc) 0)) - (message - "Command %s: %s." - (mapconcat #'identity (process-command proc) " ") - (substring event 0 -1)))) - :command (list shell-file-name shell-command-switch command)))) + (if (functionp command) + ;; command is a viewer function (a mode) expecting the file + ;; contents to be in the current buffer. + (let ((buf (generate-new-buffer (file-name-nondirectory file)))) + (set-buffer buf) + (insert-file-contents file) + (setq buffer-file-name file) + (funcall command) + (set-buffer-modified-p nil) + (pop-to-buffer buf)) + ;; command is a program to run with file as an argument. + (unless command + (error "No viewer for %s" (file-name-extension file))) + ;; Remove quotes around the file name - we'll use shell-quote-argument. + (while (string-match "['\"]%s['\"]" command) + (setq command (replace-match "%s" t t command))) + (setq command (replace-regexp-in-string + "%s" + (shell-quote-argument (convert-standard-filename file)) + command + nil t)) + ;; Handlers such as "gio open" and kde-open5 start viewer in background + ;; and exit immediately. Avoid `start-process' since it assumes + ;; :connection-type `pty' and kills children processes with SIGHUP + ;; when temporary terminal session is finished (Bug#44824). + ;; An alternative is `process-connection-type' let-bound to nil for + ;; `start-process-shell-command' call (with no chance to report failure). + (make-process + :name "mailcap-view-file" + :connection-type 'pipe + :buffer nil ; "*Messages*" may be suitable for debugging + :sentinel (lambda (proc event) + (when (and (memq (process-status proc) '(exit signal)) + (/= (process-exit-status proc) 0)) + (message + "Command %s: %s." + (mapconcat #'identity (process-command proc) " ") + (substring event 0 -1)))) + :command (list shell-file-name shell-command-switch command))))) (provide 'mailcap) diff --git a/lisp/org/ob-gnuplot.el b/lisp/org/ob-gnuplot.el index 69a5f5f91bd..895738822de 100644 --- a/lisp/org/ob-gnuplot.el +++ b/lisp/org/ob-gnuplot.el @@ -129,6 +129,7 @@ code." (title (cdr (assq :title params))) (lines (cdr (assq :line params))) (sets (cdr (assq :set params))) + (missing (cdr (assq :missing params))) (x-labels (cdr (assq :xlabels params))) (y-labels (cdr (assq :ylabels params))) (timefmt (cdr (assq :timefmt params))) @@ -138,6 +139,7 @@ code." (file-name-directory (buffer-file-name)))) (add-to-body (lambda (text) (setq body (concat text "\n" body))))) ;; append header argument settings to body + (when missing (funcall add-to-body (format "set datafile missing '%s'" missing))) (when title (funcall add-to-body (format "set title '%s'" title))) (when lines (mapc (lambda (el) (funcall add-to-body el)) lines)) (when sets @@ -288,21 +290,14 @@ Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE." (with-temp-file data-file (insert (let ((org-babel-gnuplot-timestamp-fmt (or (plist-get params :timefmt) "%Y-%m-%d-%H:%M:%S"))) - (replace-regexp-in-string - ;; org export backend adds "|" at the beginning/end of - ;; the table lines. Strip those. - "^|\\(.+\\)|$" - "\\1" - (orgtbl-to-generic - table - (org-combine-plists - '( :sep "\t" :fmt org-babel-gnuplot-quote-tsv-field - ;; Two setting below are needed to make :fmt work. - :raw t - ;; Use `org', not `ascii' because `ascii' may - ;; sometimes mishandle quoted strings. - :backend org) - params)))))) + (orgtbl-to-generic + table + (org-combine-plists + '( :sep "\t" :fmt org-babel-gnuplot-quote-tsv-field + ;; Two setting below are needed to make :fmt work. + :raw t + :backend ascii) + params))))) data-file) (provide 'ob-gnuplot) diff --git a/lisp/org/org-agenda.el b/lisp/org/org-agenda.el index fed36ac9b63..94aea1b0a32 100644 --- a/lisp/org/org-agenda.el +++ b/lisp/org/org-agenda.el @@ -86,6 +86,8 @@ (declare-function org-capture "org-capture" (&optional goto keys)) (declare-function org-clock-modify-effort-estimate "org-clock" (&optional value)) +(declare-function org-element-type "org-element" (&optional element)) + (defvar calendar-mode-map) (defvar org-clock-current-task) (defvar org-current-tag-alist) @@ -5729,7 +5731,8 @@ displayed in agenda view." (org-at-planning-p) (org-before-first-heading-p) (and org-agenda-include-inactive-timestamps - (org-at-clock-log-p))) + (org-at-clock-log-p)) + (not (eq 'timestamp (org-element-type (org-element-context))))) (throw :skip nil)) (org-agenda-skip)) (let* ((pos (match-beginning 0)) diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el index 1053bbe22cc..5337d9df746 100644 --- a/lisp/org/org-version.el +++ b/lisp/org/org-version.el @@ -11,7 +11,7 @@ Inserted by installing Org mode or when a release is made." (defun org-git-version () "The Git version of Org mode. Inserted by installing Org or when a release is made." - (let ((org-git-version "release_9.5.2-3-geb9f34")) + (let ((org-git-version "release_9.5.2-9-g7ba24c")) org-git-version)) (provide 'org-version) diff --git a/lisp/org/org.el b/lisp/org/org.el index fba45caabe6..f5d4df3d9c6 100644 --- a/lisp/org/org.el +++ b/lisp/org/org.el @@ -18731,17 +18731,19 @@ With prefix arg UNCOMPILED, load the uncompiled versions." "Is S an ID created by UUIDGEN?" (string-match "\\`[0-9a-f]\\{8\\}-[0-9a-f]\\{4\\}-[0-9a-f]\\{4\\}-[0-9a-f]\\{4\\}-[0-9a-f]\\{12\\}\\'" (downcase s))) -(defun org-in-src-block-p (&optional inside) +(defun org-in-src-block-p (&optional inside element) "Whether point is in a code source block. When INSIDE is non-nil, don't consider we are within a source -block when point is at #+BEGIN_SRC or #+END_SRC." - (let ((case-fold-search t)) - (or (and (eq (get-char-property (point) 'src-block) t)) - (and (not inside) - (save-match-data - (save-excursion - (beginning-of-line) - (looking-at ".*#\\+\\(begin\\|end\\)_src"))))))) +block when point is at #+BEGIN_SRC or #+END_SRC. +When ELEMENT is provided, it is considered to be element at point." + (save-match-data (setq element (or element (org-element-at-point)))) + (when (eq 'src-block (org-element-type element)) + (or (not inside) + (not (or (= (line-beginning-position) + (org-element-property :post-affiliated element)) + (= (1+ (line-end-position)) + (- (org-element-property :end element) + (org-element-property :post-blank element)))))))) (defun org-context () "Return a list of contexts of the current cursor position. diff --git a/lisp/org/ox-ascii.el b/lisp/org/ox-ascii.el index c22bb13b6dd..38b2a5772c1 100644 --- a/lisp/org/ox-ascii.el +++ b/lisp/org/ox-ascii.el @@ -1929,7 +1929,11 @@ a communication channel." (org-export-table-cell-alignment table-cell info))))) (setq contents (concat data - (make-string (- width (string-width (or data ""))) ?\s)))) + ;; FIXME: If CONTENTS was transformed by filters, + ;; the whole width calculation can be wrong. + ;; At least, make sure that we do not throw error + ;; when CONTENTS is larger than width. + (make-string (max 0 (- width (string-width (or data "")))) ?\s)))) ;; Return cell. (concat (format " %s " contents) (when (memq 'right (org-export-table-cell-borders table-cell info)) diff --git a/lisp/outline.el b/lisp/outline.el index 4027142c94e..8e4af64370b 100644 --- a/lisp/outline.el +++ b/lisp/outline.el @@ -351,7 +351,8 @@ Turning on outline mode calls the value of `text-mode-hook' and then of '(outline-font-lock-keywords t nil nil backward-paragraph)) (setq-local imenu-generic-expression (list (list nil (concat "^\\(?:" outline-regexp "\\).*$") 0))) - (add-hook 'change-major-mode-hook #'outline-show-all nil t)) + (add-hook 'change-major-mode-hook #'outline-show-all nil t) + (add-hook 'hack-local-variables-hook #'outline-apply-default-state nil t)) (defvar outline-minor-mode-map) @@ -434,7 +435,8 @@ See the command `outline-mode' for more information on this mode." nil t) (setq-local line-move-ignore-invisible t) ;; Cause use of ellipses for invisible text. - (add-to-invisibility-spec '(outline . t))) + (add-to-invisibility-spec '(outline . t)) + (outline-apply-default-state)) (when outline-minor-mode-highlight (if font-lock-fontified (font-lock-remove-keywords nil outline-font-lock-keywords)) @@ -1303,6 +1305,178 @@ convenient way to make a table of contents of the buffer." (insert "\n\n")))))) (kill-new (buffer-string))))))) +(defcustom outline-default-state nil + "If non-nil, some headings are initially outlined. + +Note that the default state is applied when the major mode is set +or when the command `outline-apply-default-state' is called +interactively. + +When nil, headings visibility is left unchanged. + +If equal to `outline-show-all', all text of buffer is shown. + +If equal to `outline-show-only-headings', only headings are shown. + +If equal to a number, show only headings up to and including the +corresponding level. See `outline-default-rules' to customize +visibility of the subtree at the choosen level. + +If equal to a lambda function or function name, this function is +expected to toggle headings visibility, and will be called after +the mode is enabled." + :version "29.1" + :type '(choice (const :tag "Disabled" nil) + (const :tag "Show all" outline-show-all) + (const :tag "Only headings" outline-show-only-headings) + (natnum :tag "Show headings up to level" :value 1) + (function :tag "Custom function"))) + +(defcustom outline-default-rules nil + "Determines visibility of subtree starting at `outline-default-state' level. + +When nil, the subtree is hidden unconditionally. + +When equal to a list, each element should be one of the following: + +- A cons cell with CAR `match-regexp' and CDR a regexp, the + subtree will be hidden when the outline heading match the + regexp. + +- `subtree-has-long-lines' to only show the heading branches when + long lines are detected in its subtree (see + `outline-default-long-line' for the definition of long lines). + +- `subtree-is-long' to only show the heading branches when its + subtree contains more than `outline-default-line-count' lines. + +- A lambda function or function name which will be evaluated with + point at the beginning of the heading and the match data set + appropriately, the function being expected to toggle the + heading visibility." + :version "29.1" + :type '(choice (const :tag "Hide subtree" nil) + (set :tag "Show subtree unless" + (cons :tag "Heading match regexp" + (const match-regexp) string) + (const :tag "Subtree has long lines" + subtree-has-long-lines) + (const :tag "Subtree is long" + subtree-is-long) + (cons :tag "Custom function" + (const custom-function) function)))) + +(defcustom outline-default-long-line 1000 + "Minimal number of characters in a line for a heading to be outlined." + :version "29.1" + :type '(natnum :tag "Number of characters")) + +(defcustom outline-default-line-count 50 + "Minimal number of lines for a heading to be outlined." + :version "29.1" + :type '(natnum :tag "Number of lines")) + +(defun outline-apply-default-state () + "Apply the outline state defined by `outline-default-state'." + (interactive) + (cond + ((integerp outline-default-state) + (outline--show-headings-up-to-level outline-default-state)) + ((functionp outline-default-state) + (funcall outline-default-state)))) + +(defun outline-show-only-headings () + "Show only headings." + (interactive) + (outline-show-all) + (outline-hide-region-body (point-min) (point-max))) + +(eval-when-compile (require 'so-long)) +(autoload 'so-long-detected-long-line-p "so-long") +(defvar so-long-skip-leading-comments) +(defvar so-long-threshold) +(defvar so-long-max-lines) + +(defun outline--show-headings-up-to-level (level) + "Show only headings up to a LEVEL level. + +Like `outline-hide-sublevels' but, for each heading at level +LEVEL, decides of subtree visibility according to +`outline-default-rules'." + (if (not outline-default-rules) + (outline-hide-sublevels level) + (if (< level 1) + (error "Must keep at least one level of headers")) + (save-excursion + (let* (outline-view-change-hook + (beg (progn + (goto-char (point-min)) + ;; Skip the prelude, if any. + (unless (outline-on-heading-p t) (outline-next-heading)) + (point))) + (end (progn + (goto-char (point-max)) + ;; Keep empty last line, if available. + (if (bolp) (1- (point)) (point)))) + (heading-regexp + (cdr-safe + (assoc 'match-regexp outline-default-rules))) + (check-line-count + (memq 'subtree-is-long outline-default-rules)) + (check-long-lines + (memq 'subtree-has-long-lines outline-default-rules)) + (custom-function + (cdr-safe + (assoc 'custom-function outline-default-rules)))) + (if (< end beg) + (setq beg (prog1 end (setq end beg)))) + ;; First hide everything. + (outline-hide-sublevels level) + ;; Then unhide the top level headers. + (outline-map-region + (lambda () + (let ((current-level (funcall outline-level))) + (when (< current-level level) + (outline-show-heading) + (outline-show-entry)) + (when (= current-level level) + (cond + ((and heading-regexp + (let ((beg (point)) + (end (progn (outline-end-of-heading) (point)))) + (string-match-p heading-regexp (buffer-substring beg end)))) + ;; hide entry when heading match regexp + (outline-hide-entry)) + ((and check-line-count + (save-excursion + (let ((beg (point)) + (end (progn (outline-end-of-subtree) (point)))) + (<= outline-default-line-count (count-lines beg end))))) + ;; show only branches when line count of subtree > + ;; threshold + (outline-show-branches)) + ((and check-long-lines + (save-excursion + (let ((beg (point)) + (end (progn (outline-end-of-subtree) (point)))) + (save-restriction + (narrow-to-region beg end) + (let ((so-long-skip-leading-comments nil) + (so-long-threshold outline-default-long-line) + (so-long-max-lines nil)) + (so-long-detected-long-line-p)))))) + ;; show only branches when long lines are detected + ;; in subtree + (outline-show-branches)) + (custom-function + ;; call custom function if defined + (funcall custom-function)) + (t + ;; if no previous clause succeeds, show subtree + (outline-show-subtree)))))) + beg end))) + (run-hooks 'outline-view-change-hook))) + (defun outline--cycle-state () "Return the cycle state of current heading. Return either 'hide-all, 'headings-only, or 'show-all." diff --git a/lisp/paren.el b/lisp/paren.el index a1f74f2097e..0065bba72e7 100644 --- a/lisp/paren.el +++ b/lisp/paren.el @@ -330,9 +330,7 @@ It is the default value of `show-paren-data-function'." (let ((open-paren-line-string (blink-paren-open-paren-line-string openparen)) (message-log-max nil)) - (minibuffer-message - "Matches %s" - (substring-no-properties open-paren-line-string))))) + (minibuffer-message "Matches %s" open-paren-line-string)))) ;; Always set the overlay face, since it varies. (overlay-put show-paren--overlay 'priority show-paren-priority) (overlay-put show-paren--overlay 'face face)))))) diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el index b1bef82842d..b42279415bc 100644 --- a/lisp/progmodes/gud.el +++ b/lisp/progmodes/gud.el @@ -744,10 +744,10 @@ The option \"--fullname\" must be included in this value." output)) -(easy-mmode-defmap gud-minibuffer-local-map - '(("\C-i" . comint-dynamic-complete-filename)) - "Keymap for minibuffer prompting of gud startup command." - :inherit minibuffer-local-map) +(defvar-keymap gud-minibuffer-local-map + :doc "Keymap for minibuffer prompting of gud startup command." + :parent minibuffer-local-map + "C-i" #'comint-dynamic-complete-filename) (defun gud-query-cmdline (minor-mode &optional init) (let* ((hist-sym (gud-symbol 'history nil minor-mode)) @@ -869,7 +869,8 @@ the buffer in which this command was invoked." COMMAND is the prefix for which we seek completion. CONTEXT is the text before COMMAND on the line." (let* ((complete-list - (gud-gdb-run-command-fetch-lines (concat "complete " context command) + (gud-gdb-run-command-fetch-lines (concat "server complete " + context command) (current-buffer) ;; From string-match above. (length context)))) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index edd3139a7aa..5889f2ab670 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -3216,11 +3216,13 @@ detecting a prompt at the end of the buffer." (defun python-shell-send-string-no-output (string &optional process) "Send STRING to PROCESS and inhibit output. Return the output." - (let ((process (or process (python-shell-get-process-or-error))) - (comint-preoutput-filter-functions - '(python-shell-output-filter)) - (python-shell-output-filter-in-progress t) - (inhibit-quit t)) + (or process (setq process (python-shell-get-process-or-error))) + (cl-letf (((process-filter process) + (lambda (_proc str) + (with-current-buffer (process-buffer process) + (python-shell-output-filter str)))) + (python-shell-output-filter-in-progress t) + (inhibit-quit t)) (or (with-local-quit (python-shell-send-string string process) diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 9ce63a8f8a1..37e2159782f 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -118,16 +118,16 @@ When it is a file name, it should be the \"expanded\" version.") (defcustom xref-file-name-display 'project-relative "Style of file name display in *xref* buffers. -If the value is the symbol `abs', the default, show the file names -in their full absolute form. +If the value is the symbol `abs', show the file names in their +full absolute form. If `nondirectory', show only the nondirectory (a.k.a. \"base name\") part of the file name. -If `project-relative', show only the file name relative to the -current project root. If there is no current project, or if the -file resides outside of its root, show that particular file name -in its full absolute form." +If `project-relative', the default, show only the file name +relative to the current project root. If there is no current +project, or if the file resides outside of its root, show that +particular file name in its full absolute form." :type '(choice (const :tag "absolute file name" abs) (const :tag "nondirectory file name" nondirectory) (const :tag "relative to project root" project-relative)) @@ -738,11 +738,20 @@ quit the *xref* buffer." "Perform interactive replacement of FROM with TO in all displayed xrefs. This command interactively replaces FROM with TO in the names of the -references displayed in the current *xref* buffer." +references displayed in the current *xref* buffer. + +When called interactively, it uses '.*' as FROM, which means +replace the whole name. Unless called with prefix argument, in +which case the user is prompted for both FROM and TO." (interactive - (let ((fr (read-regexp "Xref query-replace (regexp)" ".*"))) - (list fr - (read-regexp (format "Xref query-replace (regexp) %s with: " fr))))) + (let* ((fr + (if current-prefix-arg + (read-regexp "Query-replace (regexp)" ".*") + ".*")) + (prompt (if current-prefix-arg + (format "Query-replace (regexp) %s with: " fr) + "Query-replace all matches with: "))) + (list fr (read-regexp prompt)))) (let* (item xrefs iter) (save-excursion (while (setq item (xref--search-property 'xref-item)) @@ -1469,6 +1478,22 @@ is nil, prompt only if there's no usable symbol at point." (interactive (list (xref--read-identifier "Find references of: "))) (xref--find-xrefs identifier 'references identifier nil)) +(defun xref-find-references-and-replace (from to) + "Replace all references to identifier FROM with TO." + (interactive + (let ((common + (query-replace-read-args "Query replace identifier" nil))) + (list (nth 0 common) (nth 1 common)))) + (require 'xref) + (with-current-buffer + (let ((xref-show-xrefs-function + ;; Some future-proofing (bug#44905). + (custom--standard-value 'xref-show-xrefs-function)) + ;; Disable auto-jumping, it will mess up replacement logic. + xref-auto-jump-to-first-xref) + (xref-find-references from)) + (xref-query-replace-in-results ".*" to))) + ;;;###autoload (defun xref-find-definitions-at-mouse (event) "Find the definition of identifier at or around mouse click. diff --git a/lisp/simple.el b/lisp/simple.el index c73c94b53ad..8b1e7fe78b0 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -2957,7 +2957,8 @@ undo record: if we undo from 4, `pending-undo-list' will be at 3, (defcustom undo-no-redo nil "If t, `undo' doesn't go through redo entries." - :type 'boolean) + :type 'boolean + :group 'undo) (defvar pending-undo-list nil "Within a run of consecutive undo commands, list remaining to be undone. diff --git a/lisp/subr.el b/lisp/subr.el index b0d2ab623b1..81c02338531 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -4294,11 +4294,13 @@ in which case `save-window-excursion' cannot help." (defmacro with-output-to-temp-buffer (bufname &rest body) "Bind `standard-output' to buffer BUFNAME, eval BODY, then show that buffer. -This construct makes buffer BUFNAME empty before running BODY. -It does not make the buffer current for BODY. -Instead it binds `standard-output' to that buffer, so that output -generated with `prin1' and similar functions in BODY goes into -the buffer. +This is a convenience macro meant for displaying help buffers and +the like. It empties the BUFNAME buffer before evaluating BODY +and disables undo in that buffer. + +It does not make the buffer current for BODY. Instead it binds +`standard-output' to that buffer, so that output generated with +`prin1' and similar functions in BODY goes into the buffer. At the end of BODY, this marks buffer BUFNAME unmodified and displays it in a window, but does not select it. The normal way to do this is @@ -6555,7 +6557,7 @@ signalled. If NOERROR, the non-loop parts of the chain is returned." (eq func orig-func)) (if noerror (throw 'loop chain) - (error "Alias loop for `%s'" orig-func))) + (signal 'cyclic-function-indirection (list orig-func)))) (push func chain)) chain)))) diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el index e52e488edab..cd63c9208ba 100644 --- a/lisp/term/x-win.el +++ b/lisp/term/x-win.el @@ -1527,16 +1527,32 @@ This uses `icon-map-list' to map icon file names to stock icon names." (defvar x-preedit-overlay nil "The overlay currently used to display preedit text from a compose sequence.") +;; With some input methods, text gets inserted before Emacs is told to +;; remove any preedit text that was displayed, which causes both the +;; preedit overlay and the text to be visible for a brief period of +;; time. This pre-command-hook clears the overlay before any command +;; and should be set whenever a preedit overlay is visible. +(defun x-clear-preedit-text () + "Clear the pre-edit overlay and remove itself from pre-command-hook. +This function should be installed in `pre-command-hook' whenever +preedit text is displayed." + (when x-preedit-overlay + (delete-overlay x-preedit-overlay) + (setq x-preedit-overlay nil)) + (remove-hook 'pre-command-hook #'x-clear-preedit-text)) + (defun x-preedit-text (event) "Display preedit text from a compose sequence in EVENT. EVENT is a preedit-text event." (interactive "e") (when x-preedit-overlay (delete-overlay x-preedit-overlay) - (setq x-preedit-overlay nil)) + (setq x-preedit-overlay nil) + (remove-hook 'pre-command-hook #'x-clear-preedit-text)) (when (nth 1 event) (let ((string (propertize (nth 1 event) 'face '(:underline t)))) (setq x-preedit-overlay (make-overlay (point) (point))) + (add-hook 'pre-command-hook #'x-clear-preedit-text) (overlay-put x-preedit-overlay 'window (selected-window)) (overlay-put x-preedit-overlay 'before-string (if x-display-cursor-at-start-of-preedit-string diff --git a/lisp/vc/pcvs-info.el b/lisp/vc/pcvs-info.el index 11d14f95766..b48a4a1cbf1 100644 --- a/lisp/vc/pcvs-info.el +++ b/lisp/vc/pcvs-info.el @@ -130,9 +130,11 @@ to confuse some users sometimes." (defvar cvs-bakprefix ".#" "The prefix that CVS prepends to files when rcsmerge'ing.") -(easy-mmode-defmap cvs-status-map - '(([(mouse-2)] . cvs-mode-toggle-mark)) - "Local keymap for text properties of status.") +(declare-function cvs-mode-toggle-mark "pcvs" (e)) + +(defvar-keymap cvs-status-map + :doc "Local keymap for text properties of status." + "<mouse-2>" #'cvs-mode-toggle-mark) ;; Constructor: diff --git a/src/buffer.c b/src/buffer.c index 10ac91915c6..a3091015d9b 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1247,7 +1247,7 @@ buffer_local_value (Lisp_Object variable, Lisp_Object buffer) { /* Look in local_var_alist. */ struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); XSETSYMBOL (variable, sym); /* Update In case of aliasing. */ - result = Fassoc (variable, BVAR (buf, local_var_alist), Qnil); + result = assq_no_quit (variable, BVAR (buf, local_var_alist)); if (!NILP (result)) { if (blv->fwd.fwdptr) diff --git a/src/data.c b/src/data.c index 5d0790692b7..f287c38fcdf 100644 --- a/src/data.c +++ b/src/data.c @@ -2103,7 +2103,7 @@ Instead, use `add-hook' and specify t for the LOCAL argument. */) /* Make sure this buffer has its own value of symbol. */ XSETSYMBOL (variable, sym); /* Update in case of aliasing. */ - tem = Fassq (variable, BVAR (current_buffer, local_var_alist)); + tem = assq_no_quit (variable, BVAR (current_buffer, local_var_alist)); if (NILP (tem)) { if (let_shadows_buffer_binding_p (sym)) @@ -2183,7 +2183,7 @@ From now on the default value will apply in this buffer. Return VARIABLE. */) /* Get rid of this buffer's alist element, if any. */ XSETSYMBOL (variable, sym); /* Propagate variable indirection. */ - tem = Fassq (variable, BVAR (current_buffer, local_var_alist)); + tem = assq_no_quit (variable, BVAR (current_buffer, local_var_alist)); if (!NILP (tem)) bset_local_var_alist (current_buffer, @@ -2224,7 +2224,7 @@ Also see `buffer-local-boundp'.*/) case SYMBOL_PLAINVAL: return Qnil; case SYMBOL_LOCALIZED: { - Lisp_Object tail, elt, tmp; + Lisp_Object tmp; struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); XSETBUFFER (tmp, buf); XSETSYMBOL (variable, sym); /* Update in case of aliasing. */ @@ -2232,13 +2232,9 @@ Also see `buffer-local-boundp'.*/) if (EQ (blv->where, tmp)) /* The binding is already loaded. */ return blv_found (blv) ? Qt : Qnil; else - for (tail = BVAR (buf, local_var_alist); CONSP (tail); tail = XCDR (tail)) - { - elt = XCAR (tail); - if (EQ (variable, XCAR (elt))) - return Qt; - } - return Qnil; + return NILP (assq_no_quit (variable, BVAR (buf, local_var_alist))) + ? Qnil + : Qt; } case SYMBOL_FORWARDED: { diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c index da56031e2a4..a38ba35ad80 100644 --- a/src/emacsgtkfixed.c +++ b/src/emacsgtkfixed.c @@ -164,13 +164,9 @@ XSetWMSizeHints (Display *d, if ((hints->flags & PMinSize) && f) { -#ifdef HAVE_PGTK - int w = f->output_data.pgtk->size_hints.min_width; - int h = f->output_data.pgtk->size_hints.min_height; -#else int w = f->output_data.x->size_hints.min_width; int h = f->output_data.x->size_hints.min_height; -#endif + data[5] = w; data[6] = h; } diff --git a/src/frame.c b/src/frame.c index e5d74edc168..959f0c9c142 100644 --- a/src/frame.c +++ b/src/frame.c @@ -2385,7 +2385,7 @@ DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "", doc: /* Delete FRAME, eliminating it from use. FRAME must be a live frame and defaults to the selected one. -When `undelete-frame-mode' is enabled, the 16 most recently deleted +When `undelete-frame-max' is more than 0, the most recently deleted frames can be undeleted with `undelete-frame', which see. A frame may not be deleted if its minibuffer serves as surrogate diff --git a/src/gtkutil.c b/src/gtkutil.c index 36ed55bc039..48e981d0d9a 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -6256,13 +6256,16 @@ xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event, } XNoOp (FRAME_X_DISPLAY (f)); +#ifdef USABLE_SIGIO + raise (SIGIO); +#endif return true; } bool xg_filter_key (struct frame *frame, XEvent *xkey) { - GdkEvent *xg_event = gdk_event_new ((xkey->type == ButtonPress + GdkEvent *xg_event = gdk_event_new ((xkey->type == KeyPress #ifdef HAVE_XINPUT2 || (xkey->type == GenericEvent && xkey->xgeneric.evtype == XI_KeyPress) diff --git a/src/haiku_draw_support.cc b/src/haiku_draw_support.cc index 5d355ac2058..270a619b89b 100644 --- a/src/haiku_draw_support.cc +++ b/src/haiku_draw_support.cc @@ -313,7 +313,7 @@ BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int x, BRect bounds = bc.Bounds (); for (int y = 0; y < BE_RECT_HEIGHT (bounds); ++y) { - for (int x = 0; x <= BE_RECT_WIDTH (bounds); ++x) + for (int x = 0; x < BE_RECT_WIDTH (bounds); ++x) { if (bits[y * (stride / 4) + x] == 0xFF000000) bits[y * (stride / 4) + x] = RGB_COLOR_UINT32 (low_color); diff --git a/src/haiku_support.cc b/src/haiku_support.cc index d49e319b98c..22605335c55 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -1861,7 +1861,7 @@ BWindow_retitle (void *window, const char *title) void BWindow_resize (void *window, int width, int height) { - ((BWindow *) window)->ResizeTo (width, height); + ((BWindow *) window)->ResizeTo (width - 1, height - 1); } /* Activate WINDOW, making it the subject of keyboard focus and @@ -2224,7 +2224,11 @@ BWindow_set_tooltip_decoration (void *window) if (!w->LockLooper ()) gui_abort ("Failed to lock window while setting ttip decoration"); w->SetLook (B_BORDERED_WINDOW_LOOK); - w->SetFeel (B_FLOATING_APP_WINDOW_FEEL); + w->SetFeel (kMenuWindowFeel); + w->SetFlags (B_NOT_ZOOMABLE + | B_NOT_MINIMIZABLE + | B_AVOID_FRONT + | B_AVOID_FOCUS); w->UnlockLooper (); } @@ -2818,7 +2822,7 @@ be_popup_file_dialog (int open_p, const char *default_dir, int must_match_p, int enum haiku_event_type type; char *ptr = NULL; - if (!haiku_read_with_timeout (&type, buf, 200, 100000)) + if (!haiku_read_with_timeout (&type, buf, 200, 1000000)) { block_input_function (); if (type != FILE_PANEL_EVENT) diff --git a/src/haikuterm.c b/src/haikuterm.c index 47199c139c6..05f9788f184 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -55,6 +55,8 @@ struct unhandled_event uint8_t buffer[200]; }; +static bool any_help_event_p = false; + char * get_keysym_name (int keysym) { @@ -370,6 +372,13 @@ haiku_frame_raise_lower (struct frame *f, bool raise_p) BWindow_sync (FRAME_HAIKU_WINDOW (f)); unblock_input (); } + else + { + block_input (); + BWindow_send_behind (FRAME_HAIKU_WINDOW (f), NULL); + BWindow_sync (FRAME_HAIKU_WINDOW (f)); + unblock_input (); + } } /* Unfortunately, NOACTIVATE is not implementable on Haiku. */ @@ -2472,10 +2481,7 @@ haiku_default_font_parameter (struct frame *f, Lisp_Object parms) struct haiku_font_pattern ptn; ptn.specified = 0; - if (f->tooltip) - BFont_populate_plain_family (&ptn); - else - BFont_populate_fixed_family (&ptn); + BFont_populate_fixed_family (&ptn); if (ptn.specified & FSPEC_FAMILY) font = font_open_by_name (f, build_unibyte_string (ptn.family)); @@ -2590,6 +2596,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) struct unhandled_event *unhandled_events = NULL; int button_or_motion_p; int need_flush = 0; + int do_help = 0; if (!buf) buf = xmalloc (200); @@ -2770,8 +2777,9 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) } haiku_new_focus_frame (x_display_list->focused_frame); - help_echo_string = Qnil; - gen_help_event (Qnil, frame, Qnil, Qnil, 0); + + if (any_help_event_p) + do_help = -1; } else { @@ -2816,9 +2824,9 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) remember_mouse_glyph (f, b->x, b->y, &FRAME_DISPLAY_INFO (f)->last_mouse_glyph); dpyinfo->last_mouse_glyph_frame = f; - gen_help_event (help_echo_string, frame, help_echo_window, - help_echo_object, help_echo_pos); } + else + help_echo_string = previous_help_echo_string; if (!NILP (Vmouse_autoselect_window)) { @@ -2838,6 +2846,10 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) last_mouse_window = window; } + + if (!NILP (help_echo_string) + || !NILP (previous_help_echo_string)) + do_help = 1; } break; } @@ -3235,7 +3247,10 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) struct frame *f = haiku_window_to_frame (b->window); if (!f) - continue; + { + free (b->ref); + continue; + } inev.kind = DRAG_N_DROP_EVENT; inev.arg = build_string_from_utf8 (b->ref); @@ -3286,6 +3301,28 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) xfree (old); } + if (do_help && !(hold_quit && hold_quit->kind != NO_EVENT)) + { + Lisp_Object help_frame = Qnil; + + if (x_display_list->last_mouse_frame) + XSETFRAME (help_frame, + x_display_list->last_mouse_frame); + + if (do_help > 0) + { + any_help_event_p = true; + gen_help_event (help_echo_string, help_frame, + help_echo_window, help_echo_object, + help_echo_pos); + } + else + { + help_echo_string = Qnil; + gen_help_event (Qnil, help_frame, Qnil, Qnil, 0); + } + } + if (need_flush) flush_dirty_back_buffers (); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 0155ae991d3..4c38ff5a597 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -153,10 +153,24 @@ static int evq_flush (struct input_event *hold_quit) { struct event_queue_t *evq = &event_q; - int i, n = evq->nr; - for (i = 0; i < n; i++) - kbd_buffer_store_buffered_event (&evq->q[i], hold_quit); - evq->nr = 0; + int n = 0; + + while (evq->nr > 0) + { + /* kbd_buffer_store_buffered_event may do longjmp, so + we need to shift event queue first and pass the event + to kbd_buffer_store_buffered_event so that events in + queue are not processed twice. Bug#52941 */ + union buffered_input_event ev = evq->q[0]; + int i; + for (i = 1; i < evq->nr; i++) + evq->q[i - 1] = evq->q[i]; + evq->nr--; + + kbd_buffer_store_buffered_event (&ev, hold_quit); + n++; + } + return n; } diff --git a/src/xdisp.c b/src/xdisp.c index 977d31703fb..c695e466e78 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -19157,7 +19157,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) struct glyph_row *row; row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix); - while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos) + while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos + && !row->ends_at_zv_p) ++row; TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row), diff --git a/src/xfaces.c b/src/xfaces.c index 8064d47c947..e148b5d3987 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -6423,8 +6423,12 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos, cached faces since we've looked up these faces, we need to look them up again. */ if (!default_face) - default_face = FACE_FROM_ID (f, - lookup_basic_face (w, f, DEFAULT_FACE_ID)); + { + if (FRAME_FACE_CACHE (f)->used == 0) + recompute_basic_faces (f); + default_face = FACE_FROM_ID (f, + lookup_basic_face (w, f, DEFAULT_FACE_ID)); + } } /* Optimize common cases where we can use the default face. */ diff --git a/src/xfns.c b/src/xfns.c index ffad0bc3d1a..d73e951754b 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -2643,11 +2643,7 @@ best_xim_style (struct x_display_info *dpyinfo, int nr_supported = ARRAYELTS (supported_xim_styles); if (dpyinfo->preferred_xim_style) - { - for (j = 0; j < xim->count_styles; ++j) - if (dpyinfo->preferred_xim_style == xim->supported_styles[j]) - return dpyinfo->preferred_xim_style; - } + return dpyinfo->preferred_xim_style; for (i = 0; i < nr_supported; ++i) for (j = 0; j < xim->count_styles; ++j) diff --git a/src/xsettings.h b/src/xsettings.h index 266526df101..ccaa36489d0 100644 --- a/src/xsettings.h +++ b/src/xsettings.h @@ -21,15 +21,14 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #define XSETTINGS_H #ifndef HAVE_PGTK +#include "dispextern.h" #include <X11/Xlib.h> #endif struct x_display_info; struct pgtk_display_info; -#ifndef HAVE_PGTK -typedef struct x_display_info Display_Info; -#else +#ifdef HAVE_PGTK typedef struct pgtk_display_info Display_Info; #endif diff --git a/src/xterm.c b/src/xterm.c index a74c31c3f6e..3328e659301 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -20,6 +20,72 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ /* New display code by Gerd Moellmann <gerd@gnu.org>. */ /* Xt features made by Fred Pierresteguy. */ +/* X window system support for GNU Emacs + + This file is part of the X window system support for GNU Emacs. It + contains subroutines comprising the redisplay interface, setting up + scroll bars and widgets, and handling input. + + INPUT + + Emacs handles input by running pselect in a loop, which returns + whenever there is input available on the connection to the X + server. On some systems, Emacs also arranges for any new input on + that connection to send an asynchronous signal. Whenever pselect + returns, or such a signal is received and input is not blocked, + XTread_socket is called and translates X11 events read by Xlib into + struct input_events, which are then stored in the keyboard buffer, + to be processed and acted upon at some later time. The function + handle_one_xevent is responsible for handling core events after + they are filtered, and filtering X Input Extension events. It also + performs actions on some special events, such as updating the + dimensions of a frame after a ConfigureNotify is sent by the X + server to inform us that it changed. + + Before such events are translated, an Emacs build with + internationalization enabled (the default since X11R6) will filter + events through an X Input Method (XIM) or GTK, which might decide + to intercept the event and send a different one in its place, for + reasons such as enabling the user to insert international + characters that aren't on his keyboard by typing a sequence of + characters which are. See the function x_filter_event and its + callers for more details. + + Events that cause Emacs to quit are treated specially by the code + that stores them in the keyboard buffer and generally cause an + immediate interrupt. Such an interrupt can lead to a longjmp from + the code that stored the keyboard event, which isn't safe inside + XTread_socket. To avoid this problem, XTread_socket is provided a + special event buffer named hold_quit. When a quit event is + encountered, it is stored inside this special buffer, which will + cause the keyboard code that called XTread_socket to store it at a + later time when it is safe to do so. + + handle_one_xevent will generally have to determine which frame an + event should be attributed to. This is not easy, because events + can come from multiple X windows, and a frame can also have + multiple windows. handle_one_xevent usually calls the function + x_any_window_to_frame, which searches for a frame by toplevel + window and widget windows. There are also some other functions for + searching by specific types of window, such as + x_top_window_to_frame (which only searches for frames by toplevel + window), and x_menubar_window_to_frame (which will only search + through frame menu bars). + + INPUT FOCUS + + Under X, the window where keyboard input is sent is not always + explictly defined. When there is a focus window, it receives what + is referred to as "explicit focus", but when there is none, it + receives "implicit focus" whenever the pointer enters it, and loses + that focus when the pointer leaves. When the toplevel window of a + frame receives an explicit focus event (FocusIn or FocusOut), we + treat that frame as having the current input focus, but when there + is no focus window, we treat each frame as having the input focus + whenever the pointer enters it, and undo that treatment when the + pointer leaves it. See the callers of x_detect_focus_change for + more details. */ + #include <config.h> #include <stdlib.h> #include <math.h> @@ -5923,7 +5989,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, if (!f1 && insist > 0) f1 = SELECTED_FRAME (); - if (f1) + if (f1 && FRAME_X_P (f1)) { /* Ok, we found a frame. Store all the values. last_mouse_glyph is a rectangle used to reduce the @@ -5933,7 +5999,6 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, on it, i.e. into the same rectangles that matrices on the frame are divided into. */ - /* FIXME: what if F1 is not an X frame? */ dpyinfo = FRAME_DISPLAY_INFO (f1); remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph); dpyinfo->last_mouse_glyph_frame = f1; @@ -8308,6 +8373,7 @@ x_filter_event (struct x_display_info *dpyinfo, XEvent *event) #ifdef USE_GTK } else if (f1 && (event->type == KeyPress + || event->type == KeyRelease #ifdef HAVE_XINPUT2 || xinput_event #endif @@ -8369,8 +8435,10 @@ event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data) && xev->type == GenericEvent && (xev->xgeneric.extension == dpyinfo->xi2_opcode) - && (xev->xgeneric.evtype - == XI_KeyPress)) + && ((xev->xgeneric.evtype + == XI_KeyPress) + || (xev->xgeneric.evtype + == XI_KeyRelease))) #endif )) { @@ -10643,7 +10711,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (f && xev->evtype == XI_ButtonPress && !popup_activated () - && !x_window_to_scroll_bar (xev->display, xev->event, 2) + && !x_window_to_scroll_bar (dpyinfo->display, xev->event, 2) && !FRAME_NO_ACCEPT_FOCUS (f)) { /* When clicking into a child frame or when clicking @@ -10816,7 +10884,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, xkey.type = KeyPress; xkey.serial = xev->serial; xkey.send_event = xev->send_event; - xkey.display = xev->display; + xkey.display = dpyinfo->display; xkey.window = xev->event; xkey.root = xev->root; xkey.subwindow = xev->child; @@ -11162,7 +11230,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, xkey.type = KeyRelease; xkey.serial = xev->serial; xkey.send_event = xev->send_event; - xkey.display = xev->display; + xkey.display = dpyinfo->display; xkey.window = xev->event; xkey.root = xev->root; xkey.subwindow = xev->child; @@ -11458,9 +11526,24 @@ handle_one_xevent (struct x_display_info *dpyinfo, XkbFreeKeyboard (dpyinfo->xkb_desc, XkbAllComponentsMask, True); dpyinfo->xkb_desc = NULL; } - - x_find_modifier_meanings (dpyinfo); } + else + { + dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display, + (XkbKeySymsMask + | XkbKeyTypesMask + | XkbModifierMapMask + | XkbVirtualModsMask), + XkbUseCoreKbd); + + if (dpyinfo->xkb_desc) + XkbGetNames (dpyinfo->display, + XkbGroupNamesMask | XkbVirtualModNamesMask, + dpyinfo->xkb_desc); + } + + XkbRefreshKeyboardMapping (&xkbevent->map); + x_find_modifier_meanings (dpyinfo); } } #endif @@ -12617,9 +12700,11 @@ xim_initialize (struct x_display_info *dpyinfo, char *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, hence the configure test. */ - (XRegisterIMInstantiateCallback_arg6) xim_inst); + /* 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); #else /* not HAVE_X11R6_XIM */ xim_open_dpy (dpyinfo, resource_name); @@ -12644,8 +12729,7 @@ xim_close_dpy (struct x_display_info *dpyinfo) { Bool ret = XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->rdb, xim_inst->resource_name, - emacs_class, xim_instantiate_callback, - (XRegisterIMInstantiateCallback_arg6) xim_inst); + emacs_class, xim_instantiate_callback, (void *) xim_inst); eassert (ret == True); } xfree (xim_inst->resource_name); diff --git a/src/xwidget.c b/src/xwidget.c index 45879b15cbe..fce0aafb099 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -1855,7 +1855,7 @@ webkit_js_to_lisp (JSCValue *value) const gint32 dlen = jsc_value_to_int32 (len); Lisp_Object obj; - if (! (0 <= dlen && dlen < PTRDIFF_MAX + 1.0)) + if (! (0 <= dlen && dlen < G_MAXINT32 + 1)) memory_full (SIZE_MAX); ptrdiff_t n = dlen; diff --git a/test/lisp/emacs-lisp/edebug-tests.el b/test/lisp/emacs-lisp/edebug-tests.el index d238bffdaa1..35259a796a0 100644 --- a/test/lisp/emacs-lisp/edebug-tests.el +++ b/test/lisp/emacs-lisp/edebug-tests.el @@ -1094,5 +1094,15 @@ This avoids potential duplicate definitions (Bug#41988)." (edebug-new-definition name)))) (should-error (eval-buffer) :type 'invalid-read-syntax)))) +(ert-deftest edebug-tests-inline () + "Check that Edebug can instrument inline functions (Bug#53068)." + (with-temp-buffer + (print '(define-inline edebug-tests-inline (arg) + (inline-quote ,arg)) + (current-buffer)) + (let ((edebug-all-defs t) + (edebug-initial-mode 'Go-nonstop)) + (eval-buffer)))) + (provide 'edebug-tests) ;;; edebug-tests.el ends here diff --git a/test/lisp/ffap-tests.el b/test/lisp/ffap-tests.el index aebc9b6dbb9..0fdc31e8b61 100644 --- a/test/lisp/ffap-tests.el +++ b/test/lisp/ffap-tests.el @@ -141,6 +141,23 @@ left alone when opening a URL in an external browser." (let (kill-buffer-query-functions) (kill-buffer (call-interactively #'find-file-at-point))))))) +(ert-deftest ffap-test-path () + (skip-unless (file-exists-p "/bin")) + (skip-unless (file-exists-p "/usr/bin")) + (with-temp-buffer + (insert "/usr/bin:/bin") + (goto-char (point-min)) + (should (equal (ffap-file-at-point) "/usr/bin"))) + (with-temp-buffer + (insert "/usr/bin:/bin") + (goto-char (point-min)) + (search-forward ":") + (should (equal (ffap-file-at-point) "/bin"))) + (with-temp-buffer + (insert ":/bin") + (goto-char (point-min)) + (should (equal (ffap-file-at-point) nil)))) + (provide 'ffap-tests) ;;; ffap-tests.el ends here diff --git a/test/lisp/net/mailcap-resources/mailcap b/test/lisp/net/mailcap-resources/mailcap new file mode 100644 index 00000000000..ad3f7404fda --- /dev/null +++ b/test/lisp/net/mailcap-resources/mailcap @@ -0,0 +1,9 @@ +audio/ogg; mpv %s +audio/flac; mpv %s +audio/x-wav; aplay %s +text/*; emacsclient -t %s +application/pdf; acroread %s; test=false +application/pdf; evince %s +application/pdf; okular %s +image/*; eog %s +image/svg+xml; inkscape %s diff --git a/test/lisp/net/mailcap-resources/test.test b/test/lisp/net/mailcap-resources/test.test new file mode 100644 index 00000000000..9daeafb9864 --- /dev/null +++ b/test/lisp/net/mailcap-resources/test.test @@ -0,0 +1 @@ +test diff --git a/test/lisp/net/mailcap-tests.el b/test/lisp/net/mailcap-tests.el index 362cb22bb2f..b439c08c791 100644 --- a/test/lisp/net/mailcap-tests.el +++ b/test/lisp/net/mailcap-tests.el @@ -63,4 +63,74 @@ (append mailcap-tests-path-extensions mailcap-tests-mime-extensions)))) +(defmacro with-pristine-mailcap (&rest body) + ;; We only want the mailcap info we define ourselves. + `(let (mailcap--computed-mime-data + mailcap-mime-data + mailcap-user-mime-data) + ;; `mailcap-mime-info' calls `mailcap-parse-mailcaps' which parses + ;; the system's mailcaps. We don't want that for our test. + (cl-letf (((symbol-function 'mailcap-parse-mailcaps) #'ignore)) + ,@body))) + +(ert-deftest mailcap-parsing-and-mailcap-mime-info () + (with-pristine-mailcap + ;; One mailcap entry has a test=false field. The shell command + ;; execution errors when running the tests from the Makefile + ;; because then HOME=/nonexistent. + (ert-with-temp-directory home + (setenv "HOME" home) + ;; Now parse our resource mailcap file. + (mailcap-parse-mailcap (ert-resource-file "mailcap")) + + ;; Assert that we get what we have defined. + (dolist (type '("audio/ogg" "audio/flac")) + (should (string= "mpv %s" (mailcap-mime-info type)))) + (should (string= "aplay %s" (mailcap-mime-info "audio/x-wav"))) + (should (string= "emacsclient -t %s" + (mailcap-mime-info "text/plain"))) + ;; evince is chosen because acroread has test=false and okular + ;; comes later. + (should (string= "evince %s" + (mailcap-mime-info "application/pdf"))) + (should (string= "inkscape %s" + (mailcap-mime-info "image/svg+xml"))) + (should (string= "eog %s" + (mailcap-mime-info "image/jpg"))) + ;; With REQUEST being a number, all fields of the selected entry + ;; should be returned. + (should (equal '((viewer . "evince %s") + (type . "application/pdf")) + (mailcap-mime-info "application/pdf" 1))) + ;; With 'all, all applicable entries should be returned. + (should (equal '(((viewer . "evince %s") + (type . "application/pdf")) + ((viewer . "okular %s") + (type . "application/pdf"))) + (mailcap-mime-info "application/pdf" 'all))) + (let* ((c nil) + (toggle (lambda (_) (setq c (not c))))) + (mailcap-add "audio/ogg" "toggle %s" toggle) + (should (string= "toggle %s" (mailcap-mime-info "audio/ogg"))) + ;; The test results are cached, so in order to have the test + ;; re-evaluated, one needs to clear the cache. + (setq mailcap-viewer-test-cache nil) + (should (string= "mpv %s" (mailcap-mime-info "audio/ogg"))) + (setq mailcap-viewer-test-cache nil) + (should (string= "toggle %s" (mailcap-mime-info "audio/ogg"))))))) + +(defvar mailcap--test-result nil) +(defun mailcap--test-viewer () + (setq mailcap--test-result (string= (buffer-string) "test\n"))) + +(ert-deftest mailcap-view-file () + (with-pristine-mailcap + ;; Try using a lambda as viewer and check wether + ;; `mailcap-view-file' works correctly. + (let* ((mailcap-mime-extensions '((".test" . "test/test")))) + (mailcap-add "test/test" 'mailcap--test-viewer) + (save-window-excursion + (mailcap-view-file (ert-resource-file "test.test"))) + (should mailcap--test-result)))) + ;;; mailcap-tests.el ends here diff --git a/test/lisp/so-long-tests/spelling-tests.el b/test/lisp/so-long-tests/spelling-tests.el index 09ffa3c8006..ce4b0844c99 100644 --- a/test/lisp/so-long-tests/spelling-tests.el +++ b/test/lisp/so-long-tests/spelling-tests.el @@ -36,12 +36,11 @@ ;; make lisp/so-long-tests/spelling-tests SELECTOR=t ;; Only define the test if spell-checking is possible. -(when (and ispell-program-name - (executable-find ispell-program-name) - (condition-case () - (progn (ispell-check-version) t) - (error nil)) - (member "british" (ispell-valid-dictionary-list))) +(when (ignore-errors + (and ispell-program-name + (executable-find ispell-program-name) + (progn (ispell-check-version) t) + (member "british" (ispell-valid-dictionary-list)))) (ert-deftest so-long-spelling () "Check the spelling in the source code." :tags '(:unstable) ;; It works for me, but I'm not sure about others. @@ -51,9 +50,9 @@ ;; The Emacs test Makefile's use of HOME=/nonexistent triggers an error ;; when starting the inferior ispell process, so we set HOME to a valid ;; (but empty) temporary directory for this test. - (ert-with-temp-file tmpdir - :directory t - :suffix "so-long.ispell" + (ert-with-temp-directory tmpdir + :prefix "so-long." + :suffix ".ispell" (let* ((process-environment (cons (format "HOME=%s" tmpdir) process-environment)) (find-spelling-mistake |