commit 028913c446b8f06288f2e17be91aef701dc58ba4 (HEAD, refs/remotes/origin/master) Author: F. Jason Park Date: Fri Feb 7 18:54:22 2025 -0800 ; Make ERC test fixture more robust * test/lisp/erc/erc-tests.el (erc-tests--assert-printed-in-subprocess): Scan for sentinel before reading. (erc--find-mode, erc--essential-hook-ordering): Use contrived :result protocol expected by `erc-tests--assert-printed-in-subprocess'. * test/lisp/erc/resources/erc-tests-common.el (erc-tests-common-create-subprocess): Divert stderr to messages buffer. diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index df9e4d52f77..2279496e600 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -3558,12 +3558,23 @@ (should (eq (erc--normalize-module-symbol 'nickserv) 'services))) (defun erc-tests--assert-printed-in-subprocess (code expected) - (let ((proc (erc-tests-common-create-subprocess code '("-batch") nil))) - (while (accept-process-output proc 10)) - (goto-char (point-min)) - (unless (equal (read (current-buffer)) expected) - (message "Expected: %S\nGot: %s" expected (buffer-string)) - (ert-fail "Mismatch")))) + "Assert result emitted to standard output from CODE matches EXPECTED. +Expect CODE to print result using `prin1' as a list beginning with the +keyword :result." + (with-current-buffer + (get-buffer-create + (concat "*" (symbol-name (ert-test-name (ert-running-test))) "*")) + (unwind-protect + (let ((proc (erc-tests-common-create-subprocess code '("-batch") nil))) + (while (accept-process-output proc 10)) + (goto-char (point-min)) + (search-forward "(:result " nil t) + (unless (equal (ignore-errors (read (current-buffer))) expected) + (ert-fail (list "Mismatch" + :expected expected + :buffer-string (buffer-string))))) + (when noninteractive + (kill-buffer))))) ;; Worrying about which library a module comes from is mostly not ;; worth the hassle so long as ERC can find its minor mode. However, @@ -3573,25 +3584,25 @@ (ert-deftest erc--find-mode () (erc-tests--assert-printed-in-subprocess - `(let ((mods (mapcar #'cadddr (cdddr (get 'erc-modules 'custom-type)))) + '(let ((mods (mapcar #'cadddr (cdddr (get 'erc-modules 'custom-type)))) moded) (setq mods (sort mods (lambda (a b) (if (zerop (random 2)) a b)))) (dolist (mod mods) (unless (keywordp mod) (push (if-let* ((mode (erc--find-mode mod))) mod (list :missing mod)) moded))) - (message "%S" - (sort moded (lambda (a b) - (string< (symbol-name a) (symbol-name b)))))) + (prin1 (list :result + (sort moded (lambda (a b) + (string< (symbol-name a) (symbol-name b))))))) erc-tests--modules)) (ert-deftest erc--essential-hook-ordering () (erc-tests--assert-printed-in-subprocess '(progn (erc-update-modules) - (message "%S" - (list :erc-insert-modify-hook erc-insert-modify-hook - :erc-send-modify-hook erc-send-modify-hook))) + (prin1 (list :result + (list :erc-insert-modify-hook erc-insert-modify-hook + :erc-send-modify-hook erc-send-modify-hook)))) '( :erc-insert-modify-hook (erc-controls-highlight ; 0 erc-button-add-buttons ; 30 diff --git a/test/lisp/erc/resources/erc-tests-common.el b/test/lisp/erc/resources/erc-tests-common.el index 236fac84132..eedea8c44de 100644 --- a/test/lisp/erc/resources/erc-tests-common.el +++ b/test/lisp/erc/resources/erc-tests-common.el @@ -356,15 +356,17 @@ interspersing \"-l\" between members." (require 'erc) (cl-assert (equal erc-version ,erc-version) t) ,code)) - (proc (apply #'start-process - (symbol-name (ert-test-name (ert-running-test))) - (current-buffer) - (concat invocation-directory invocation-name) - `(,@(or init '("-Q")) - ,@switches - ,@(mapcan (lambda (f) (list "-l" f)) libs) - "-eval" ,(format "%S" prog))))) - (set-process-query-on-exit-flag proc t) + (proc (make-process + :name (symbol-name (ert-test-name (ert-running-test))) + :buffer (current-buffer) + :command `(,(concat invocation-directory invocation-name) + ,@(or init '("-Q")) + ,@switches + ,@(mapcan (lambda (f) (list "-l" f)) libs) + "-eval" ,(format "%S" prog)) + :connection-type 'pipe + :stderr (messages-buffer) + :noquery t))) proc)) (declare-function erc-track--setup "erc-track" ()) commit e9408918f4e7fe00eb4e25e1e5428fb26c4ad847 Author: F. Jason Park Date: Tue Feb 4 06:11:50 2025 -0800 More clearly define local module behavior in ERC * doc/misc/erc.texi (Modules): Label all local modules as being such. Move `querypoll' to the auxiliary section. Rework entire "Local Modules" portion. * lisp/erc/erc-goodies.el (erc-keep-place-indicator-mode) (erc-command-indicator-mode): Mention what buffer types they operate in. * lisp/erc/erc-nicks.el (erc-nicks-mode): Mention the mode is enabled in all buffers. * lisp/erc/erc-notify.el (erc-querypoll-mode): Mention which buffers it operates in. * lisp/erc/erc-sasl.el (erc-sasl-mode): Disable completely in target buffers so its mode variable is nil. * lisp/erc/erc-services.el (erc-services-regain-mode): Disable in target buffers. * lisp/erc/erc.el (erc-open): When activating local modules, skip those that have just been enabled by a fellow module. Do this even though their setup code is meant to be idempotent. * test/lisp/erc/erc-scenarios-base-local-modules.el (erc-scenarios-base-local-modules--toggle-helpers): Revise to assert current behavior. (Bug#57955) diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi index 7c934d8bb3a..1c0afa3b300 100644 --- a/doc/misc/erc.texi +++ b/doc/misc/erc.texi @@ -452,7 +452,7 @@ Buttonize URLs, nicknames, and other text Mark unidentified users on freenode and other servers supporting CAPAB. @cindex modules, command-indicator -@item command-indicator +@item command-indicator (local) Echo command lines for ``slash commands'', like @kbd{/JOIN #erc} and @kbd{/HELP join} @@ -494,7 +494,7 @@ Display a menu in ERC buffers Detect netsplits @cindex modules, nicks -@item nicks +@item nicks (local) Automatically colorize nicks @cindex modules, nickbar @@ -519,10 +519,6 @@ or your nickname is mentioned @item page Process CTCP PAGE requests from IRC -@cindex modules, querypoll -@item querypoll -Update query participant data by continually polling the server - @cindex modules, readonly @item readonly Make displayed lines read-only @@ -536,7 +532,7 @@ Replace text in messages Enable an input history @cindex modules, sasl -@item sasl +@item sasl (local) Enable SASL authentication @cindex modules, scrolltobottom @@ -583,22 +579,26 @@ Translate morse code in messages For various reasons, the following modules aren't currently listed in the Custom interface for @code{erc-modules}, but feel free to add them -explicitly. They may be managed by another module or considered more -useful when toggled interactively or just deemed experimental. +explicitly. They may be managed by another module or just deemed too +niche or experimental. @table @code @cindex modules, fill-wrap -@item fill-wrap +@item fill-wrap (local) Wrap long lines using @code{visual-line-mode} @cindex modules, keep-place-indicator -@item keep-place-indicator +@item keep-place-indicator (local) Remember your place in buffers with a visible reminder; activated interactively or via something like @code{erc-join-hook} +@cindex modules, querypoll +@item querypoll (local) +Update query participant data by continually polling the server + @cindex modules, services-regain -@item services-regain +@item services-regain (local) Automatically ask NickServ to reclaim your nick when reconnecting; experimental as of ERC 5.6 @@ -618,51 +618,84 @@ always loads anyway. @subheading Local Modules @cindex local modules -All modules operate as minor modes under the hood, and some newer ones -may be defined as buffer-local. These so-called ``local modules'' are -a work in progress and their behavior and interface are subject to -change. As of ERC 5.5, the only practical differences are as follows: +@c Earlier language in code comments, commit messages, and tracker +@c discussions used to describe a local module as being "active" in a +@c buffer if it had a local binding but "disabled" if that binding's +@c value was nil. For better or worse, ERC has since abandoned that +@c distinction and now considers "active" to be synonymous with +@c "enabled". + +All modules operate as minor modes under the hood, and newer ones are +mostly defined as buffer-local. These so-called @dfn{local modules} are +a work in progress, and their behavior and interface are subject to +change. As of ERC 5.6, the only practical differences are as follows: @enumerate @item -``Control variables,'' like @code{erc-sasl-mode}, retain their values -across IRC sessions and override @code{erc-module} membership when -influencing module activation. +@dfn{Mode variables}, a.k.a. @dfn{control variables}, like +@code{erc-sasl-mode}, retain their values across IRC sessions. @item Removing a local module from @code{erc-modules} via Customize not only -disables its mode but also kills its control variable in all ERC -buffers. +disables its mode but also kills its mode variable in all ERC buffers. @item -``Mode toggles,'' like @code{erc-sasl-mode} and the complementary -@code{erc-sasl-enable}/@code{erc-sasl-disable} pairing, behave -differently than their global counterparts. +@dfn{Mode commands}, like @code{erc-sasl-mode} and its one-way variants +@code{erc-sasl-enable} and @code{erc-sasl-disable}, behave differently +than their global counterparts. @end enumerate -In target buffers, a local module's activation state survives -``reassociation'' by default, but modules themselves always have the -final say. For example, a module may reset all instances of itself in -its network context upon reconnecting. Moreover, the value of a mode -variable may be meaningless in buffers that its module has no interest -in. For example, the value of @code{erc-sasl-mode} doesn't matter in -target buffers and may even remain non-@code{nil} after SASL has been -disabled for the current connection (and vice versa). - -When it comes to server buffers, a module's activation state only -persists for sessions revived via the automatic reconnection mechanism -or a manual @samp{/reconnect} issued at the prompt. In other words, -this doesn't apply to sessions revived by an entry-point command, such -as @code{erc-tls}, because such commands always ensure a clean slate -by looking only to @code{erc-modules}. Although a session revived in -this manner may indeed harvest other information from a previous -server buffer, it simply doesn't care which modules might have been -active during that connection. - -Lastly, a local mode's toggle command, like @code{erc-sasl-mode}, only -affects the current buffer, but its ``non-mode'' cousins, like +To detect whether a module is local, examine its mode variable. For +example, if you run @kbd{C-h v erc-sasl-mode @key{RET}}, you'll notice +it says ``Automatically becomes buffer-local when set''. You can do the +same in Lisp code with @code{(local-variable-if-set-p 'erc-sasl-mode)}. + +In an ERC buffer, a local module is either enabled or disabled if its +mode variable has a local binding. This @dfn{activation state} may +contradict a module's presence in @code{erc-modules}, namely, in buffers +where it isn't applicable or has otherwise been disabled. In fact, a +local module's membership in @code{erc-modules} does nothing more than +guarantee + +@enumerate +@item +its setup code runs in @emph{new} buffers +@item +its mode variable has a local binding in all affected buffers +@end enumerate + +In keeping with this, all built-in local modules disable themselves in +nonapplicable buffers rather than remain no-ops. Some also take strides +to enable themselves elsewhere when needed or at least emit a helpful +error. For example, the @samp{nicks} module does both in server +buffers, where it shares resources among the target buffers it primarily +services. ERC expects third-party local modules to mimic this pattern +and to document what buffer types they operate in: server, query, or +channel. (In the case of @samp{nicks}, it would be all three: it's +@dfn{session-local}.) + +In ERC, you can think of an IRC session as a group of buffers sharing +the same connection to a server. After a connection ends, this +association endures so that ERC can revive the session when +reconnecting. As it does with connection parameters, ERC therefore +persists a local module's activation state through reconnections, +reenabling modules that were previously active while ensuring others are +disabled. A couple related things to note here are + +@enumerate +@item +each module must manage its own application data and restore or reset +its environment accordingly +@item +session persistence is less predictable if a user changes the makeup of +@code{erc-modules} between sessions +@end enumerate + +When it comes to a local module's various activation commands, the +primary mode command, like @code{erc-sasl-mode}, for example, only +affects the current buffer, but its unidirectional cousins, like @code{erc-sasl-enable} and @code{erc-sasl-disable}, operate on all -buffers belonging to their connection (when called interactively). -And unlike global toggles, none of these ever mutates -@code{erc-modules}. +buffers belonging to their connection (when called interactively). And +unlike global toggles, none of these ever mutates @code{erc-modules}. + @c FIXME add section to Advanced chapter for creating modules, and @c move this there. diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el index cfd0d3415ea..24a3205e0cd 100644 --- a/lisp/erc/erc-goodies.el +++ b/lisp/erc/erc-goodies.el @@ -372,7 +372,9 @@ than the indicator's position." "Buffer-local `keep-place' with fringe arrow and/or highlighted face. Play nice with global module `keep-place' but don't depend on it. Expect that users may want different combinations of `keep-place' -and `keep-place-indicator' in different buffers." +and `keep-place-indicator' in different buffers. + +This module is local to individual buffers." ((cond (erc-keep-place-mode) ((memq 'keep-place erc-modules) (erc-keep-place-mode +1)) @@ -589,7 +591,9 @@ message's speaker." Skip those appearing in `erc-noncommands-list'. Users can run \\[erc-command-indicator-toggle-hidden] to hide and -reveal echoed command lines after they've been inserted." +reveal echoed command lines after they've been inserted. + +This module is local to individual buffers." ((add-hook 'erc--input-review-functions #'erc--command-indicator-permit-insertion 80 t) (erc-command-indicator-toggle-hidden -1)) diff --git a/lisp/erc/erc-nicks.el b/lisp/erc/erc-nicks.el index b0629f7754c..a3e9b1f7b46 100644 --- a/lisp/erc/erc-nicks.el +++ b/lisp/erc/erc-nicks.el @@ -541,7 +541,9 @@ Abandon search after examining LIMIT faces." nick-object) (define-erc-module nicks nil - "Uniquely colorize nicknames in target buffers." + "Uniquely colorize nicknames in target buffers. + +This module is local per connection." ((if erc--target (progn (erc-with-server-buffer diff --git a/lisp/erc/erc-notify.el b/lisp/erc/erc-notify.el index 82754cb1989..1e04c90177e 100644 --- a/lisp/erc/erc-notify.el +++ b/lisp/erc/erc-notify.el @@ -299,7 +299,8 @@ like `nickbar', to provide UI feedback when changes occur. Once ERC implements the `monitor' extension, this module will serve as an optional fallback for keeping query-participant rolls up to date on servers that lack support or are stingy with their allotments. Until -such time, this module should be considered experimental. +such time, this module should be considered experimental and only really +useful for bots and other non-interactive Lisp programs. This is a local ERC module, so selectively polling only a subset of query targets is possible but cumbersome. To do so, ensure @@ -307,7 +308,8 @@ query targets is possible but cumbersome. To do so, ensure as appropriate in desired query buffers. To stop polling for the current connection, toggle off the command \\[erc-querypoll-mode] from a server buffer, or run \\`M-x C-u erc-querypoll-disable RET' from a -target buffer." +target buffer. Note that this module's minor mode must remain active in +at least the server buffer." ((if erc--target (if (erc-query-buffer-p) (progn ; accommodate those who eschew `erc-modules' diff --git a/lisp/erc/erc-sasl.el b/lisp/erc/erc-sasl.el index a16f554f2d1..5228fc5e5aa 100644 --- a/lisp/erc/erc-sasl.el +++ b/lisp/erc/erc-sasl.el @@ -34,13 +34,6 @@ ;; ;; - Implement a proxy mechanism that chooses the strongest available ;; mechanism for you. Requires CAP 3.2 (see bug#49860). -;; -;; - Integrate with whatever solution ERC eventually settles on to -;; handle user options for different network contexts. At the -;; moment, this does its own thing for stashing and restoring -;; session options, but ERC should make abstractions available for -;; all local modules to use, possibly based on connection-local -;; variables. ;;; Code: (require 'erc) @@ -315,9 +308,10 @@ If necessary, pass PROMPT to `read-passwd'." (define-erc-module sasl nil "Non-IRCv3 SASL support for ERC. -This doesn't solicit or validate a suite of supported mechanisms." - ;; See bug#49860 for a CAP 3.2-aware WIP implementation. - ((unless erc--target +This local module only enables its minor mode in server buffers, and it +doesn't currently solicit or validate supported mechanisms." + ((if erc--target + (erc-sasl-mode -1) (setq erc-sasl--state (make-erc-sasl--state)) ;; If the previous attempt failed during registration, this may be ;; non-nil and contain erroneous values, but how can we detect that? diff --git a/lisp/erc/erc-services.el b/lisp/erc/erc-services.el index 429424117eb..25da873076e 100644 --- a/lisp/erc/erc-services.el +++ b/lisp/erc/erc-services.el @@ -613,8 +613,10 @@ In practical terms, this means that this module, which is still somewhat experimental, is likely only useful in conjunction with SASL authentication or CertFP rather than the traditional approach provided by the `services' module it shares a library with (see Info -node `(erc) SASL' for more)." - nil nil localp) +node `(erc) SASL' for more). + +This local module's minor mode is only active in server buffers." + ((when erc--target (erc-services-regain-mode -1))) nil localp) (cl-defmethod erc--nickname-in-use-make-request ((want string) temp &context (erc-server-connected null) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index afa8e0a7b72..0d72b46360e 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -2662,7 +2662,9 @@ side effect of setting the current buffer to the one it returns. Use (erc--initialize-markers old-point continued-session) (erc-determine-parameters server port nick full-name user passwd) (save-excursion (run-mode-hooks) - (dolist (mod (car delayed-modules)) (funcall mod +1)) + (dolist (mod (car delayed-modules)) + (unless (and (boundp mod) (symbol-value mod)) + (funcall mod +1))) (dolist (var (cdr delayed-modules)) (set var nil))) ;; Saving log file on exit diff --git a/test/lisp/erc/erc-scenarios-base-local-modules.el b/test/lisp/erc/erc-scenarios-base-local-modules.el index 71923cc11f2..1d670b8f508 100644 --- a/test/lisp/erc/erc-scenarios-base-local-modules.el +++ b/test/lisp/erc/erc-scenarios-base-local-modules.el @@ -117,20 +117,25 @@ (erc-cmd-QUIT "") (funcall expect 10 "finished"))) - (ert-info ("Disabling works from a target buffer") + (ert-info ("Explicit disabling affects entire session") + ;; Even though the mode variable is nil (but locally bound) in + ;; this target buffer, disabling interactively with + ;; `erc-sasl-disable', deactivates the module session-wide. (with-current-buffer "#chan" - (should erc-sasl-mode) - (call-interactively #'erc-sasl-disable) (should-not erc-sasl-mode) (should (local-variable-p 'erc-sasl-mode)) + (should (buffer-local-value 'erc-sasl-mode (get-buffer "foonet"))) + (call-interactively #'erc-sasl-disable) (should-not (buffer-local-value 'erc-sasl-mode (get-buffer "foonet"))) + (should-not erc-sasl-mode) (erc-cmd-RECONNECT) (funcall expect 10 "Some enigma, some riddle") - (should-not erc-sasl-mode) ; regression + (should-not erc-sasl-mode) (should (local-variable-p 'erc-sasl-mode))) (with-current-buffer "foonet" (should (local-variable-p 'erc-sasl-mode)) + (should-not erc-sasl-mode) (funcall expect 10 "User modes for tester`") (erc-cmd-QUIT "") (funcall expect 10 "finished"))) @@ -139,7 +144,8 @@ (with-current-buffer "#chan" (call-interactively #'erc-sasl-enable) (should (local-variable-p 'erc-sasl-mode)) - (should erc-sasl-mode) + (should-not erc-sasl-mode) + (should (buffer-local-value 'erc-sasl-mode (get-buffer "foonet"))) (erc-cmd-RECONNECT) (funcall expect 10 "Well met; good morrow, Titus and Hortensius.") (erc-cmd-QUIT "")) commit 0e4883f18eecea59e537e2368a0f5674888a1af7 Author: Paul Eggert Date: Fri Feb 7 13:02:02 2025 -0800 Update from Gnulib by running admin/merge-gnulib diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex index 456696f4c9e..faad184e345 100644 --- a/doc/misc/texinfo.tex +++ b/doc/misc/texinfo.tex @@ -3,9 +3,9 @@ % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % -\def\texinfoversion{2024-11-04.20} +\def\texinfoversion{2025-01-31.21} % -% Copyright 1985, 1986, 1988, 1990-2024 Free Software Foundation, Inc. +% Copyright 1985, 1986, 1988, 1990-2025 Free Software Foundation, Inc. % % This texinfo.tex file is free software: you can redistribute it and/or % modify it under the terms of the GNU General Public License as @@ -156,8 +156,9 @@ % Give the space character the catcode for a space. \def\spaceisspace{\catcode`\ =10\relax} -% Likewise for ^^M, the end of line character. -\def\endlineisspace{\catcode13=10\relax} +% Used to ignore an active newline that may appear immediately after +% a macro name. +{\catcode13=\active \gdef\ignoreactivenewline{\let^^M\empty}} \chardef\dashChar = `\- \chardef\slashChar = `\/ @@ -957,6 +958,10 @@ \ifx\byeerror\relax\else\errmessage{\byeerror}\fi \tracingstats=1\ptexend} +% set in \donoderef below, but we need to define this here so that +% conditionals balance inside the large \ifpdf ... \fi blocks below. +\newif\ifnodeseen +\nodeseenfalse \message{pdf,} % adobe `portable' document format @@ -975,6 +980,11 @@ \newif\ifpdf \newif\ifpdfmakepagedest +\newif\ifluatex +\ifx\luatexversion\thisisundefined\else + \luatextrue +\fi + % % For LuaTeX % @@ -982,8 +992,7 @@ \newif\iftxiuseunicodedestname \txiuseunicodedestnamefalse % For pdfTeX etc. -\ifx\luatexversion\thisisundefined -\else +\ifluatex % Use Unicode destination names \txiuseunicodedestnametrue % Escape PDF strings with converting UTF-16 from UTF-8 @@ -1072,12 +1081,17 @@ \fi \fi +\newif\ifxetex +\ifx\XeTeXrevision\thisisundefined\else + \xetextrue +\fi + \newif\ifpdforxetex \pdforxetexfalse \ifpdf \pdforxetextrue \fi -\ifx\XeTeXrevision\thisisundefined\else +\ifxetex \pdforxetextrue \fi @@ -1167,58 +1181,90 @@ be supported due to the design of the PDF format; use regular TeX (DVI output) for that.)} +% definitions for pdftex or luatex with pdf output \ifpdf + % Strings in PDF outlines can either be ASCII, or encoded in UTF-16BE + % with BOM. Unfortunately there is no simple way with pdftex to output + % UTF-16, so we have to do some quite convoluted expansion games if we + % find the string contains a non-ASCII codepoint if we want these to + % display correctly. We generated the UTF-16 sequences in + % \DeclareUnicodeCharacter and we access them here. + % + \def\defpdfoutlinetextunicode#1{% + \def\pdfoutlinetext{#1}% + % + % Make UTF-8 sequences expand to UTF-16 definitions. + \passthroughcharsfalse \utfbytespdftrue + \utfviiidefinedwarningfalse + % + % Completely expand, eliminating any control sequences such as \code, + % leaving only possibly \utfbytes. + \let\utfbytes\relax + \pdfaccentliterals + \xdef\pdfoutlinetextchecked{#1}% + \checkutfbytes + }% + % Check if \utfbytes occurs in expansion. + \def\checkutfbytes{% + \expandafter\checkutfbytesz\pdfoutlinetextchecked\utfbytes\finish + }% + \def\checkutfbytesz#1\utfbytes#2\finish{% + \def\after{#2}% + \ifx\after\empty + % No further action needed. Output ASCII string as-is, as converting + % to UTF-16 is somewhat slow (and uses more space). + \global\let\pdfoutlinetext\pdfoutlinetextchecked + \else + \passthroughcharstrue % pass UTF-8 sequences unaltered + \xdef\pdfoutlinetext{\pdfoutlinetext}% + \expandafter\expandutfsixteen\expandafter{\pdfoutlinetext}\pdfoutlinetext + \fi + }% % - % Color manipulation macros using ideas from pdfcolor.tex, - % except using rgb instead of cmyk; the latter is said to render as a - % very dark gray on-screen and a very dark halftone in print, instead - % of actual black. The dark red here is dark enough to print on paper as - % nearly black, but still distinguishable for online viewing. We use - % black by default, though. - \def\rgbDarkRed{0.50 0.09 0.12} - \def\rgbBlack{0 0 0} - % - % rg sets the color for filling (usual text, etc.); - % RG sets the color for stroking (thin rules, e.g., normal _'s). - \def\pdfsetcolor#1{\pdfliteral{#1 rg #1 RG}} + \catcode2=1 % begin-group character + \catcode3=2 % end-group character % - % Set color, and create a mark which defines \thiscolor accordingly, - % so that \makeheadline knows which color to restore. - \def\curcolor{0 0 0}% - \def\setcolor#1{% - \ifx#1\curcolor\else - \xdef\currentcolordefs{\gdef\noexpand\thiscolor{#1}}% - \domark - \pdfsetcolor{#1}% - \xdef\curcolor{#1}% - \fi - } + % argument should be pure UTF-8 with no control sequences. convert to + % UTF-16BE by inserting null bytes before bytes < 128 and expanding + % UTF-8 multibyte sequences to saved UTF-16BE sequences. + \def\expandutfsixteen#1#2{% + \bgroup \asciitounicode + \passthroughcharsfalse + \let\utfbytes\asis + % + % for Byte Order Mark (BOM) + \catcode"FE=12 + \catcode"FF=12 + % + % we want to treat { and } in #1 as any other ASCII bytes. however, + % we need grouping characters for \scantokens and definitions/assignments, + % so define alternative grouping characters using control characters + % that are unlikely to occur. + % this does not affect 0x02 or 0x03 bytes arising from expansion as + % these are tokens with different catcodes. + \catcode"02=1 % begin-group character + \catcode"03=2 % end-group character + % + \expandafter\xdef\expandafter#2\scantokens{% + ^^02^^fe^^ff#1^^03}% + % NB we need \scantokens to provide both the open and close group tokens + % for \xdef otherwise there is an e-TeX error "File ended while + % scanning definition of..." + % NB \scantokens is a e-TeX command which is assumed to be provided by + % pdfTeX. + % + \egroup + }% % - \let\maincolor\rgbBlack - \pdfsetcolor{\maincolor} - \edef\thiscolor{\maincolor} - \def\currentcolordefs{} + \catcode2=12 \catcode3=12 % defaults % - \def\makefootline{% - \baselineskip24pt - \line{\pdfsetcolor{\maincolor}\the\footline}% - } + % Color support % - \def\makeheadline{% - \vbox to 0pt{% - \vskip-22.5pt - \line{% - \vbox to8.5pt{}% - % Extract \thiscolor definition from the marks. - \getcolormarks - % Typeset the headline with \maincolor, then restore the color. - \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% - }% - \vss - }% - \nointerlineskip - } + % rg sets the color for filling (usual text, etc.); + % RG sets the color for stroking (thin rules, e.g., normal _'s). + \def\pdfsetcolor#1{\pdfliteral{#1 rg #1 RG}} % + % PDF outline support % \pdfcatalog{/PageMode /UseOutlines} % @@ -1315,18 +1361,15 @@ \def\pdfoutlinetext{#1}% \else \ifx \declaredencoding \utfeight - \ifx\luatexversion\thisisundefined - % For pdfTeX with UTF-8. - % TODO: the PDF format can use UTF-16 in bookmark strings, - % but the code for this isn't done yet. - % Use ASCII approximations. - \passthroughcharsfalse - \def\pdfoutlinetext{#1}% - \else + \ifluatex % For LuaTeX with UTF-8. % Pass through Unicode characters for title texts. \passthroughcharstrue - \def\pdfoutlinetext{#1}% + \pdfaccentliterals + \xdef\pdfoutlinetext{#1}% + \else + % For pdfTeX with UTF-8. + \defpdfoutlinetextunicode{#1}% \fi \else % For non-Latin-1 or non-UTF-8 encodings. @@ -1348,11 +1391,6 @@ % used to mark target names; must be expandable. \def\pdfmkpgn#1{#1} % - % by default, use black for everything. - \def\urlcolor{\rgbBlack} - \let\linkcolor\rgbBlack - \def\endlink{\setcolor{\maincolor}\pdfendlink} - % % Adding outlines to PDF; macros for calculating structure of outlines % come from Petr Olsak \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% @@ -1416,6 +1454,10 @@ \def\unnsecentry{\numsecentry}% \def\unnsubsecentry{\numsubsecentry}% \def\unnsubsubsecentry{\numsubsubsecentry}% + % + % Treat index initials like @section. Note that this is the wrong + % level if the index is not at the level of @appendix or @chapter. + \def\idxinitialentry{\numsecentry}% \readdatafile{toc}% % % Read toc second time, this time actually producing the outlines. @@ -1437,6 +1479,8 @@ \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% \def\numsubsubsecentry##1##2##3##4{% count is always zero \dopdfoutline{##1}{}{##3}{##4}}% + \def\idxinitialentry##1##2##3##4{% + \dopdfoutline{##1}{}{idx.##1.##2}{##4}}% % % PDF outlines are displayed using system fonts, instead of % document fonts. Therefore we cannot use special characters, @@ -1450,6 +1494,7 @@ % we use for the index sort strings. % \indexnofonts + \ifnodeseen\else \dopdfoutlinecontents \fi % for @contents at beginning \setupdatafile % We can have normal brace characters in the PDF outlines, unlike % Texinfo index files. So set that up. @@ -1458,6 +1503,10 @@ \catcode`\\=\active \otherbackslash \input \tocreadfilename \endgroup + \ifnodeseen \dopdfoutlinecontents \fi % for @contents at end + } + \def\dopdfoutlinecontents{% + \expandafter\dopdfoutline\expandafter{\putwordTOC}{}{txi.CONTENTS}{}% } {\catcode`[=1 \catcode`]=2 \catcode`{=\other \catcode`}=\other @@ -1484,55 +1533,16 @@ \else \let \startlink \pdfstartlink \fi - % make a live url in pdf output. - \def\pdfurl#1{% - \begingroup - % it seems we really need yet another set of dummies; have not - % tried to figure out what each command should do in the context - % of @url. for now, just make @/ a no-op, that's the only one - % people have actually reported a problem with. - % - \normalturnoffactive - \def\@{@}% - \let\/=\empty - \makevalueexpandable - % do we want to go so far as to use \indexnofonts instead of just - % special-casing \var here? - \def\var##1{##1}% - % - \leavevmode\setcolor{\urlcolor}% - \startlink attr{/Border [0 0 0]}% - user{/Subtype /Link /A << /S /URI /URI (#1) >>}% - \endgroup} - % \pdfgettoks - Surround page numbers in #1 with @pdflink. #1 may - % be a simple number, or a list of numbers in the case of an index - % entry. - \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} - \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} - \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} - \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} - \def\maketoks{% - \expandafter\poptoks\the\toksA|ENDTOKS|\relax - \ifx\first0\adn0 - \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 - \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 - \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 - \else - \ifnum0=\countA\else\makelink\fi - \ifx\first.\let\next=\done\else - \let\next=\maketoks - \addtokens{\toksB}{\the\toksD} - \ifx\first,\addtokens{\toksB}{\space}\fi - \fi - \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi - \next} - \def\makelink{\addtokens{\toksB}% - {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\pdfmakeurl#1{% + \startlink attr{/Border [0 0 0]}% + user{/Subtype /Link /A << /S /URI /URI (#1) >>}% + }% + \def\endlink{\setcolor{\maincolor}\pdfendlink} + % \def\pdflink#1{\pdflinkpage{#1}{#1}}% \def\pdflinkpage#1#2{% \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} \setcolor{\linkcolor}#2\endlink} - \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} \else % non-pdf mode \let\pdfmkdest = \gobble @@ -1541,13 +1551,12 @@ \let\setcolor = \gobble \let\pdfsetcolor = \gobble \let\pdfmakeoutlines = \relax -\fi % \ifx\pdfoutput +\fi % % For XeTeX % -\ifx\XeTeXrevision\thisisundefined -\else +\ifxetex % % XeTeX version check % @@ -1573,45 +1582,8 @@ \fi % % Color support - % - \def\rgbDarkRed{0.50 0.09 0.12} - \def\rgbBlack{0 0 0} - % \def\pdfsetcolor#1{\special{pdf:scolor [#1]}} % - % Set color, and create a mark which defines \thiscolor accordingly, - % so that \makeheadline knows which color to restore. - \def\setcolor#1{% - \xdef\currentcolordefs{\gdef\noexpand\thiscolor{#1}}% - \domark - \pdfsetcolor{#1}% - } - % - \def\maincolor{\rgbBlack} - \pdfsetcolor{\maincolor} - \edef\thiscolor{\maincolor} - \def\currentcolordefs{} - % - \def\makefootline{% - \baselineskip24pt - \line{\pdfsetcolor{\maincolor}\the\footline}% - } - % - \def\makeheadline{% - \vbox to 0pt{% - \vskip-22.5pt - \line{% - \vbox to8.5pt{}% - % Extract \thiscolor definition from the marks. - \getcolormarks - % Typeset the headline with \maincolor, then restore the color. - \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% - }% - \vss - }% - \nointerlineskip - } - % % PDF outline support % % Emulate pdfTeX primitive @@ -1649,11 +1621,6 @@ \safewhatsit{\pdfdest name{\pdfdestname} xyz}% } % - % by default, use black for everything. - \def\urlcolor{\rgbBlack} - \def\linkcolor{\rgbBlack} - \def\endlink{\setcolor{\maincolor}\pdfendlink} - % \def\dopdfoutline#1#2#3#4{% \setpdfoutlinetext{#1} \setpdfdestname{#3} @@ -1667,7 +1634,6 @@ % \def\pdfmakeoutlines{% \begingroup - % % For XeTeX, counts of subentries are not necessary. % Therefore, we read toc only once. % @@ -1686,6 +1652,11 @@ \def\numsubsubsecentry##1##2##3##4{% \dopdfoutline{##1}{4}{##3}{##4}}% % + % Note this is at the wrong level unless the index is in an @appendix + % or @chapter. + \def\idxinitialentry##1##2##3##4{% + \dopdfoutline{##1}{2}{idx.##1.##2}{##4}}% + % \let\appentry\numchapentry% \let\appsecentry\numsecentry% \let\appsubsecentry\numsubsecentry% @@ -1700,15 +1671,23 @@ % Therefore, the encoding and the language may not be considered. % \indexnofonts + \pdfaccentliterals + \ifnodeseen\else \dopdfoutlinecontents \fi % for @contents at beginning + % \setupdatafile % We can have normal brace characters in the PDF outlines, unlike % Texinfo index files. So set that up. \def\{{\lbracecharliteral}% \def\}{\rbracecharliteral}% \catcode`\\=\active \otherbackslash - \input \tocreadfilename + \input \tocreadfilename\relax + \ifnodeseen \dopdfoutlinecontents \fi % for @contents at end \endgroup } + \def\dopdfoutlinecontents{% + \expandafter\dopdfoutline\expandafter + {\putwordTOC}{1}{txi.CONTENTS}{txi.CONTENTS}% + } {\catcode`[=1 \catcode`]=2 \catcode`{=\other \catcode`}=\other \gdef\lbracecharliteral[{]% @@ -1721,7 +1700,7 @@ % However, due to a UTF-16 conversion issue of xdvipdfmx 20150315, % ``\special{pdf:dest ...}'' cannot handle non-ASCII strings. % It is fixed by xdvipdfmx 20160106 (TeX Live SVN r39753). -% + % \def\skipspaces#1{\def\PP{#1}\def\D{|}% \ifx\PP\D\let\nextsp\relax \else\let\nextsp\skipspaces @@ -1736,55 +1715,17 @@ \edef\temp{#1}% \expandafter\skipspaces\temp|\relax } - % make a live url in pdf output. - \def\pdfurl#1{% - \begingroup - % it seems we really need yet another set of dummies; have not - % tried to figure out what each command should do in the context - % of @url. for now, just make @/ a no-op, that's the only one - % people have actually reported a problem with. - % - \normalturnoffactive - \def\@{@}% - \let\/=\empty - \makevalueexpandable - % do we want to go so far as to use \indexnofonts instead of just - % special-casing \var here? - \def\var##1{##1}% - % - \leavevmode\setcolor{\urlcolor}% - \special{pdf:bann << /Border [0 0 0] - /Subtype /Link /A << /S /URI /URI (#1) >> >>}% - \endgroup} + \def\pdfmakeurl#1{% + \special{pdf:bann << /Border [0 0 0] + /Subtype /Link /A << /S /URI /URI (#1) >> >>}% + } \def\endlink{\setcolor{\maincolor}\special{pdf:eann}} - \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} - \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} - \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} - \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} - \def\maketoks{% - \expandafter\poptoks\the\toksA|ENDTOKS|\relax - \ifx\first0\adn0 - \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 - \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 - \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 - \else - \ifnum0=\countA\else\makelink\fi - \ifx\first.\let\next=\done\else - \let\next=\maketoks - \addtokens{\toksB}{\the\toksD} - \ifx\first,\addtokens{\toksB}{\space}\fi - \fi - \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi - \next} - \def\makelink{\addtokens{\toksB}% - {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} \def\pdflink#1{\pdflinkpage{#1}{#1}}% \def\pdflinkpage#1#2{% \special{pdf:bann << /Border [0 0 0] /Type /Annot /Subtype /Link /A << /S /GoTo /D (#1) >> >>}% \setcolor{\linkcolor}#2\endlink} - \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} -% + % % % @image support % @@ -1841,6 +1782,164 @@ } \fi +% common definitions and code for pdftex, luatex and xetex +\ifpdforxetex + % The dark red here is dark enough to print on paper as + % nearly black, but still distinguishable for online viewing. We use + % black by default, though. + \def\rgbDarkRed{0.50 0.09 0.12} + \def\rgbBlack{0 0 0} + % + % Set color, and create a mark which defines \thiscolor accordingly, + % so that \makeheadline knows which color to restore. + \def\curcolor{0 0 0}% + \def\setcolor#1{% + \ifx#1\curcolor\else + \xdef\currentcolordefs{\gdef\noexpand\thiscolor{#1}}% + \domark + \pdfsetcolor{#1}% + \xdef\curcolor{#1}% + \fi + } + % + \let\maincolor\rgbBlack + \pdfsetcolor{\maincolor} + \edef\thiscolor{\maincolor} + \def\currentcolordefs{} + % + \def\makefootline{% + \baselineskip24pt + \line{\pdfsetcolor{\maincolor}\the\footline}% + } + % + \def\makeheadline{% + \vbox to 0pt{% + \vskip-22.5pt + \line{% + \vbox to8.5pt{}% + % Extract \thiscolor definition from the marks. + \getcolormarks + % Typeset the headline with \maincolor, then restore the color. + \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% + }% + \vss + }% + \nointerlineskip + } + % + % by default, use black for everything. + \def\urlcolor{\rgbBlack} + \let\linkcolor\rgbBlack + % + % make a live url in pdf output. + \def\pdfurl#1{% + \begingroup + % it seems we really need yet another set of dummies; have not + % tried to figure out what each command should do in the context + % of @url. for now, just make @/ a no-op, that's the only one + % people have actually reported a problem with. + % + \normalturnoffactive + \def\@{@}% + \let\/=\empty + \makevalueexpandable + % do we want to go so far as to use \indexnofonts instead of just + % special-casing \var here? + \def\var##1{##1}% + % + \leavevmode\setcolor{\urlcolor}% + \pdfmakeurl{#1}% + \endgroup} + % + % \pdfgettoks - Surround page numbers in #1 with @pdflink. #1 may + % be a simple number, or a list of numbers in the case of an index + % entry. + \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} + \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} + \def\maketoks{% + \expandafter\poptoks\the\toksA|ENDTOKS|\relax + \ifx\first0\adn0 + \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 + \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 + \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 + \else + \ifnum0=\countA\else\makelink\fi + \ifx\first.\let\next=\done\else + \let\next=\maketoks + \addtokens{\toksB}{\the\toksD} + \ifx\first,\addtokens{\toksB}{\space}\fi + \fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \next} + \def\makelink{\addtokens{\toksB}% + {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} +\fi + +\ifpdforxetex + % for pdftex. + {\catcode`^^cc=13 + \gdef\pdfaccentliteralsutfviii{% + % For PDF outline only. Unicode combining accents follow the + % character they modify. Note we need at least the first byte + % of the UTF-8 sequences to have an active catcode to allow the + % definitions to do their magic. + \def\"##1{##1^^cc^^88}% U+0308 + \def\'##1{##1^^cc^^81}% U+0301 + \def\,##1{##1^^cc^^a7}% U+0327 + \def\=##1{##1^^cc^^85}% U+0305 + \def\^##1{##1^^cc^^82}% U+0302 + \def\`##1{##1^^cc^^80}% U+0300 + \def\~##1{##1^^cc^^83}% U+0303 + \def\dotaccent##1{##1^^cc^^87}% U+0307 + \def\H##1{##1^^cc^^8b}% U+030B + \def\ogonek##1{##1^^cc^^a8}% U+0328 + \def\ringaccent##1{##1^^cc^^8a}% U+030A + \def\u##1{##1^^cc^^8c}% U+0306 + \def\ubaraccent##1{##1^^cc^^b1}% U+0331 + \def\udotaccent##1{##1^^cc^^a3}% U+0323 + \def\v##1{##1^^cc^^8c}% U+030C + % this definition of @tieaccent will only work with exactly two characters + % in argument as we need to insert the combining character between them. + \def\tieaccent##1{\tieaccentz##1}% + \def\tieaccentz##1##2{##1^^cd^^a1##2} % U+0361 + }}% + % + % for xetex and luatex, which both support extended ^^^^ escapes and + % process the Unicode codepoint as a single token. + \gdef\pdfaccentliteralsnative{% + \def\"##1{##1^^^^0308}% + \def\'##1{##1^^^^0301}% + \def\,##1{##1^^^^0327}% + \def\=##1{##1^^^^0305}% + \def\^##1{##1^^^^0302}% + \def\`##1{##1^^^^0300}% + \def\~##1{##1^^^^0303}% + \def\dotaccent##1{##1^^^^0307}% + \def\H##1{##1^^^^030b}% + \def\ogonek##1{##1^^^^0328}% + \def\ringaccent##1{##1^^^^030a}% + \def\u##1{##1^^^^0306}% + \def\ubaraccent##1{##1^^^^0331}% + \def\udotaccent##1{##1^^^^0323}% + \def\v##1{##1^^^^030c}% + \def\tieaccent##1{\tieaccentz##1}% + \def\tieaccentz##1##2{##1^^^^0361##2} % U+0361 + }% + % + % use the appropriate definition + \ifluatex + \let\pdfaccentliterals\pdfaccentliteralsnative + \else + \ifxetex + \let\pdfaccentliterals\pdfaccentliteralsnative + \else + \let\pdfaccentliterals\pdfaccentliteralsutfviii + \fi + \fi +\fi % \message{fonts,} @@ -2772,15 +2871,15 @@ % @cite unconditionally uses \sl with \smartitaliccorrection. \def\cite#1{{\sl #1}\smartitaliccorrection} -% @var unconditionally uses \sl. This gives consistency for -% parameter names whether they are in @def, @table @code or a -% regular paragraph. -% To get ttsl font for @var when used in code context, @set txicodevaristt. -% The \null is to reset \spacefactor. +% By default, use ttsl font for @var when used in code context. +% To unconditionally use \sl for @var, @clear txicodevaristt. This +% gives consistency for parameter names whether they are in @def, +% @table @code or a regular paragraph. \def\aftersmartic{} \def\var#1{% \let\saveaftersmartic = \aftersmartic \def\aftersmartic{\null\let\aftersmartic=\saveaftersmartic}% + % The \null is to reset \spacefactor. % \ifflagclear{txicodevaristt}% {\def\varnext{{{\sl #1}}\smartitaliccorrection}}% @@ -2788,7 +2887,6 @@ \varnext } -% To be removed after next release \def\SETtxicodevaristt{}% @set txicodevaristt \let\i=\smartitalic @@ -2808,7 +2906,7 @@ \def\ii#1{{\it #1}} % italic font % @b, explicit bold. Also @strong. -\def\b#1{{\bf #1}} +\def\b#1{{\bf \defcharsdefault #1}} \let\strong=\b % @sansserif, explicit sans. @@ -3039,9 +3137,7 @@ \unhbox0\ (\urefcode{#1})% \fi \else - \ifx\XeTeXrevision\thisisundefined - \unhbox0\ (\urefcode{#1})% DVI, always show arg and url - \else + \ifxetex % For XeTeX \ifurefurlonlylink % PDF plus option to not display url, show just arg @@ -3051,6 +3147,8 @@ % visibility, if the pdf is eventually used to print, etc. \unhbox0\ (\urefcode{#1})% \fi + \else + \unhbox0\ (\urefcode{#1})% DVI, always show arg and url \fi \fi \else @@ -3670,15 +3768,24 @@ {\font\thisecfont = #1ctt\ecsize \space at \nominalsize}% % else {\ifx\curfontstyle\bfstylename - % bold: - \font\thisecfont = #1cb\ifusingit{i}{x}\ecsize \space at \nominalsize + \etcfontbold{#1}% \else - % regular: - \font\thisecfont = #1c\ifusingit{ti}{rm}\ecsize \space at \nominalsize + \ifrmisbold + \etcfontbold{#1}% + \else + % regular: + \font\thisecfont = #1c\ifusingit{ti}{rm}\ecsize \space + at \nominalsize + \fi \fi}% \thisecfont } +\def\etcfontbold#1{% + % bold: + \font\thisecfont = #1cb\ifusingit{i}{x}\ecsize \space at \nominalsize +} + % @registeredsymbol - R in a circle. The font for the R should really % be smaller yet, but lllsize is the best we can do for now. % Adapted from the plain.tex definition of \copyright. @@ -5528,7 +5635,6 @@ \def\initial{% \bgroup - \initialglyphs \initialx } @@ -5551,7 +5657,10 @@ % % No shrink because it confuses \balancecolumns. \vskip 1.67\baselineskip plus 1\baselineskip - \leftline{\secfonts \kern-0.05em \secbf #1}% + \doindexinitialentry{#1}% + \initialglyphs + \leftline{% + \secfonts \kern-0.05em \secbf #1}% % \secfonts is inside the argument of \leftline so that the change of % \baselineskip will not affect any glue inserted before the vbox that % \leftline creates. @@ -5561,6 +5670,32 @@ \egroup % \initialglyphs } +\def\doindexinitialentry#1{% + \ifpdforxetex + \global\advance\idxinitialno by 1 + \def\indexlbrace{\{} + \def\indexrbrace{\}} + \def\indexbackslash{\realbackslash} + \def\indexatchar{\@} + \writetocentry{idxinitial}{\asis #1}{IDX\the\idxinitialno}% + % The @asis removes a pair of braces around e.g. {@indexatchar} that + % are output by texindex. + % + \vbox to 0pt{}% + % This vbox fixes the \pdfdest location for double column formatting. + % Without it, the \pdfdest is output above topskip glue at the top + % of a column as this glue is not added until the first box. + \pdfmkdest{idx.\asis #1.IDX\the\idxinitialno}% + \fi +} + +% No listing in TOC +\def\idxinitialentry#1#2#3#4{} + +% For index initials. +\newcount\idxinitialno \idxinitialno=1 + + \newdimen\entryrightmargin \entryrightmargin=0pt @@ -6782,12 +6917,13 @@ % Prepare to read what we've written to \tocfile. % -\def\startcontents#1{% +\def\startcontents#1#2{% % If @setchapternewpage on, and @headings double, the contents should % start on an odd page, unlike chapters. \contentsalignmacro \immediate\closeout\tocfile % + #2% % Don't need to put `Contents' or `Short Contents' in the headline. % It is abundantly clear what they are. \chapmacro{#1}{Yomitfromtoc}{}% @@ -6818,7 +6954,7 @@ % Normal (long) toc. % \def\contents{% - \startcontents{\putwordTOC}% + \startcontents{\putwordTOC}{\contentsmkdest}% \openin 1 \tocreadfilename\space \ifeof 1 \else \findsecnowidths @@ -6834,9 +6970,13 @@ \contentsendroman } +\def\contentsmkdest{% + \pdfmkdest{txi.CONTENTS}% +} + % And just the chapters. \def\summarycontents{% - \startcontents{\putwordShortTOC}% + \startcontents{\putwordShortTOC}{}% % \let\partentry = \shortpartentry \let\numchapentry = \shortchapentry @@ -7925,7 +8065,7 @@ {\rm\enskip}% hskip 0.5 em of \rmfont }{}% % - \boldbrax + \parenbrackglyphs % arguments will be output next, if any. } @@ -7935,7 +8075,10 @@ \def\^^M{}% for line continuation \df \ifdoingtypefn \tt \else \sl \fi \ifflagclear{txicodevaristt}{}% - {\def\var##1{{\setregularquotes \ttsl ##1}}}% + % use \ttsl for @var in both @def* and @deftype*. + % the kern prevents an italic correction at end, which appears + % too much for ttsl. + {\def\var##1{{\setregularquotes \ttsl ##1\kern 0pt }}}% #1% \egroup } @@ -7952,8 +8095,9 @@ \let\lparen = ( \let\rparen = ) % Be sure that we always have a definition for `(', etc. For example, -% if the fn name has parens in it, \boldbrax will not be in effect yet, -% so TeX would otherwise complain about undefined control sequence. +% if the fn name has parens in it, \parenbrackglyphs will not be in +% effect yet, so TeX would otherwise complain about undefined control +% sequence. { \activeparens \gdef\defcharsdefault{% @@ -7963,49 +8107,28 @@ } \globaldefs=1 \defcharsdefault - \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} + \gdef\parenbrackglyphs{\let(=\opnr\let)=\cpnr\let[=\lbrb\let]=\rbrb} \gdef\magicamp{\let&=\amprm} } \let\ampchar\& -\newcount\parencount - -% If we encounter &foo, then turn on ()-hacking afterwards -\newif\ifampseen -\def\amprm#1 {\ampseentrue{\rm\ }} - -\def\parenfont{% - \ifampseen - % At the first level, print parens in roman, - % otherwise use the default font. - \ifnum \parencount=1 \rm \fi - \else - % The \sf parens (in \boldbrax) actually are a little bolder than - % the contained text. This is especially needed for [ and ] . - \sf - \fi -} -\def\infirstlevel#1{% - \ifampseen - \ifnum\parencount=1 - #1% - \fi - \fi -} -\def\bfafterword#1 {#1 \bf} +\def\amprm#1 {{\rm\ }} +\newcount\parencount +% opening and closing parentheses in roman font \def\opnr{% + \ptexslash % italic correction \global\advance\parencount by 1 - {\parenfont(}% - \infirstlevel \bfafterword + {\sf(}% } -\def\clnr{% - {\parenfont)}% - \infirstlevel \sl +\def\cpnr{% + \ptexslash % italic correction + {\sf)}% \global\advance\parencount by -1 } \newcount\brackcount +% left and right square brackets in bold font \def\lbrb{% \global\advance\brackcount by 1 {\bf[}% @@ -8535,7 +8658,7 @@ \expandafter\xdef\csname\the\macname\endcsname{% \begingroup \noexpand\spaceisspace - \noexpand\endlineisspace + \noexpand\ignoreactivenewline \noexpand\expandafter % skip any whitespace after the macro name. \expandafter\noexpand\csname\the\macname @@@\endcsname}% \expandafter\xdef\csname\the\macname @@@\endcsname{% @@ -8836,8 +8959,13 @@ \ifx\lastnode\empty\else \setref{\lastnode}{#1}% \global\let\lastnode=\empty + \setnodeseenonce \fi } +\def\setnodeseenonce{ + \global\nodeseentrue + \let\setnodeseenonce\relax +} % @nodedescription, @nodedescriptionblock - do nothing for TeX \parseargdef\nodedescription{} @@ -9575,7 +9703,9 @@ % For pdfTeX and LuaTeX <= 0.80 \dopdfimage{#1}{#2}{#3}% \else - \ifx\XeTeXrevision\thisisundefined + \ifxetex + \doxeteximage{#1}{#2}{#3}% + \else % For epsf.tex % \epsfbox itself resets \epsf?size at each figure. \setbox0 = \hbox{\ignorespaces #2}% @@ -9583,9 +9713,6 @@ \setbox0 = \hbox{\ignorespaces #3}% \ifdim\wd0 > 0pt \epsfysize=#3\relax \fi \epsfbox{#1.eps}% - \else - % For XeTeX - \doxeteximage{#1}{#2}{#3}% \fi \fi % @@ -9931,25 +10058,24 @@ \newif\iftxinativeunicodecapable \newif\iftxiusebytewiseio -\ifx\XeTeXrevision\thisisundefined - \ifx\luatexversion\thisisundefined - \txinativeunicodecapablefalse - \txiusebytewiseiotrue - \else +\ifxetex + \txinativeunicodecapabletrue + \txiusebytewiseiofalse +\else + \ifluatex \txinativeunicodecapabletrue \txiusebytewiseiofalse + \else + \txinativeunicodecapablefalse + \txiusebytewiseiotrue \fi -\else - \txinativeunicodecapabletrue - \txiusebytewiseiofalse \fi % Set I/O by bytes instead of UTF-8 sequence for XeTeX and LuaTex % for non-UTF-8 (byte-wise) encodings. % \def\setbytewiseio{% - \ifx\XeTeXrevision\thisisundefined - \else + \ifxetex \XeTeXdefaultencoding "bytes" % For subsequent files to be read \XeTeXinputencoding "bytes" % For document root file % Unfortunately, there seems to be no corresponding XeTeX command for @@ -9958,8 +10084,7 @@ % place of non-ASCII characters. \fi - \ifx\luatexversion\thisisundefined - \else + \ifluatex \directlua{ local utf8_char, byte, gsub = unicode.utf8.char, string.byte, string.gsub local function convert_char (char) @@ -10068,8 +10193,7 @@ \fi % lattwo \fi % ascii % - \ifx\XeTeXrevision\thisisundefined - \else + \ifxetex \ifx \declaredencoding \utfeight \else \ifx \declaredencoding \ascii @@ -10352,11 +10476,15 @@ \gdef\UTFviiiDefined#1{% \ifx #1\relax - \message{\linenumber Unicode char \string #1 not defined for Texinfo}% + \ifutfviiidefinedwarning + \message{\linenumber Unicode char \string #1 not defined for Texinfo}% + \fi \else \expandafter #1% \fi } +\newif\ifutfviiidefinedwarning +\utfviiidefinedwarningtrue % Give non-ASCII bytes the active definitions for processing UTF-8 sequences \begingroup @@ -10366,8 +10494,8 @@ % Loop from \countUTFx to \countUTFy, performing \UTFviiiTmp % substituting ~ and $ with a character token of that value. - \def\UTFviiiLoop{% - \global\catcode\countUTFx\active + \gdef\UTFviiiLoop{% + \catcode\countUTFx\active \uccode`\~\countUTFx \uccode`\$\countUTFx \uppercase\expandafter{\UTFviiiTmp}% @@ -10375,7 +10503,7 @@ \ifnum\countUTFx < \countUTFy \expandafter\UTFviiiLoop \fi} - + % % For bytes other than the first in a UTF-8 sequence. Not expected to % be expanded except when writing to auxiliary files. \countUTFx = "80 @@ -10409,6 +10537,16 @@ \else\expandafter\UTFviiiFourOctets\expandafter$\fi }}% \UTFviiiLoop + % + % for pdftex only, used to expand ASCII to UTF-16BE. + \gdef\asciitounicode{% + \countUTFx = "20 + \countUTFy = "80 + \def\UTFviiiTmp{% + \def~{\nullbyte $}}% + \UTFviiiLoop + } + {\catcode0=11 \gdef\nullbyte{^^00}}% \endgroup \def\globallet{\global\let} % save some \expandafter's below @@ -10433,8 +10571,8 @@ \fi } -% These macros are used here to construct the name of a control -% sequence to be defined. +% These macros are used here to construct the names of macros +% that expand to the definitions for UTF-8 sequences. \def\UTFviiiTwoOctetsName#1#2{% \csname u8:#1\string #2\endcsname}% \def\UTFviiiThreeOctetsName#1#2#3{% @@ -10442,6 +10580,35 @@ \def\UTFviiiFourOctetsName#1#2#3#4{% \csname u8:#1\string #2\string #3\string #4\endcsname}% +% generate UTF-16 from codepoint +\def\utfsixteentotoks#1#2{% + \countUTFz = "#2\relax + \ifnum \countUTFz > 65535 + % doesn't work for codepoints > U+FFFF + % we don't define glyphs for any of these anyway, so it doesn't matter + #1={U+#2}% + \else + \countUTFx = \countUTFz + \divide\countUTFx by 256 + \countUTFy = \countUTFx + \multiply\countUTFx by 256 + \advance\countUTFz by -\countUTFx + \uccode`,=\countUTFy + \uccode`;=\countUTFz + \ifnum\countUTFy = 0 + \uppercase{#1={\nullbyte\string;}}% + \else\ifnum\countUTFz = 0 + \uppercase{#1={\string,\nullbyte}}% + \else + \uppercase{#1={\string,\string;}}% + \fi\fi + % NB \uppercase cannot insert a null byte + \fi +} + +\newif\ifutfbytespdf +\utfbytespdffalse + % For UTF-8 byte sequences (TeX, e-TeX and pdfTeX), % provide a definition macro to replace a Unicode character; % this gets used by the @U command @@ -10458,18 +10625,22 @@ \countUTFz = "#1\relax \begingroup \parseXMLCharref - - % Give \u8:... its definition. The sequence of seven \expandafter's - % expands after the \gdef three times, e.g. % + % Completely expand \UTFviiiTmp, which looks like: % 1. \UTFviiTwoOctetsName B1 B2 % 2. \csname u8:B1 \string B2 \endcsname % 3. \u8: B1 B2 (a single control sequence token) + \xdef\UTFviiiTmp{\UTFviiiTmp}% % - \expandafter\expandafter - \expandafter\expandafter - \expandafter\expandafter - \expandafter\gdef \UTFviiiTmp{#2}% + \ifpdf + \toksA={#2}% + \utfsixteentotoks\toksB{#1}% + \expandafter\xdef\UTFviiiTmp{% + \noexpand\ifutfbytespdf\noexpand\utfbytes{\the\toksB}% + \noexpand\else\the\toksA\noexpand\fi}% + \else + \expandafter\gdef\UTFviiiTmp{#2}% + \fi % \expandafter\ifx\csname uni:#1\endcsname \relax \else \message{Internal error, already defined: #1}% @@ -10479,8 +10650,9 @@ \expandafter\globallet\csname uni:#1\endcsname \UTFviiiTmp \endgroup} % - % Given the value in \countUTFz as a Unicode code point, set \UTFviiiTmp - % to the corresponding UTF-8 sequence. + % Given the value in \countUTFz as a Unicode code point, set + % \UTFviiiTmp to one of the \UTVviii*OctetsName macros followed by + % the corresponding UTF-8 sequence. \gdef\parseXMLCharref{% \ifnum\countUTFz < "20\relax \errhelp = \EMsimple @@ -10540,7 +10712,7 @@ } % Suppress ligature creation from adjacent characters. -\ifx\luatexversion\thisisundefined +\ifluatex \def\nolig{{}} \else % Braces do not suppress ligature creation in LuaTeX, e.g. in of{}fice @@ -11325,6 +11497,25 @@ % \global\mathchardef\checkmark="1370% actually the square root sign \DeclareUnicodeCharacter{2713}{\ensuremath\checkmark}% + % + % These are all the combining accents. We need these empty definitions + % at present for the sake of PDF outlines. + \DeclareUnicodeCharacter{0300}{}% + \DeclareUnicodeCharacter{0301}{}% + \DeclareUnicodeCharacter{0302}{}% + \DeclareUnicodeCharacter{0303}{}% + \DeclareUnicodeCharacter{0305}{}% + \DeclareUnicodeCharacter{0306}{}% + \DeclareUnicodeCharacter{0307}{}% + \DeclareUnicodeCharacter{0308}{}% + \DeclareUnicodeCharacter{030A}{}% + \DeclareUnicodeCharacter{030B}{}% + \DeclareUnicodeCharacter{030C}{}% + \DeclareUnicodeCharacter{0323}{}% + \DeclareUnicodeCharacter{0327}{}% + \DeclareUnicodeCharacter{0328}{}% + \DeclareUnicodeCharacter{0331}{}% + \DeclareUnicodeCharacter{0361}{}% }% end of \unicodechardefs % UTF-8 byte sequence (pdfTeX) definitions (replacing and @U command) @@ -11463,12 +11654,12 @@ \pdfhorigin = 1 true in \pdfvorigin = 1 true in \else - \ifx\XeTeXrevision\thisisundefined - \special{papersize=#8,#7}% - \else + \ifxetex \pdfpageheight #7\relax \pdfpagewidth #8\relax % XeTeX does not have \pdfhorigin and \pdfvorigin. + \else + \special{papersize=#8,#7}% \fi \fi % @@ -11668,21 +11859,21 @@ #1#2#3=\countB\relax } -\ifx\XeTeXrevision\thisisundefined - \ifx\luatexversion\thisisundefined +\ifxetex % XeTeX + \mtsetprotcode\textrm + \def\mtfontexpand#1{} +\else + \ifluatex % LuaTeX + \mtsetprotcode\textrm + \def\mtfontexpand#1{\expandglyphsinfont#1 20 20 1\relax} + \else \ifpdf % pdfTeX \mtsetprotcode\textrm \def\mtfontexpand#1{\pdffontexpand#1 20 20 1 autoexpand\relax} \else % TeX \def\mtfontexpand#1{} \fi - \else % LuaTeX - \mtsetprotcode\textrm - \def\mtfontexpand#1{\expandglyphsinfont#1 20 20 1\relax} \fi -\else % XeTeX - \mtsetprotcode\textrm - \def\mtfontexpand#1{} \fi @@ -11691,18 +11882,18 @@ \def\microtypeON{% \microtypetrue % - \ifx\XeTeXrevision\thisisundefined - \ifx\luatexversion\thisisundefined + \ifxetex % XeTeX + \XeTeXprotrudechars=2 + \else + \ifluatex % LuaTeX + \adjustspacing=2 + \protrudechars=2 + \else \ifpdf % pdfTeX \pdfadjustspacing=2 \pdfprotrudechars=2 \fi - \else % LuaTeX - \adjustspacing=2 - \protrudechars=2 \fi - \else % XeTeX - \XeTeXprotrudechars=2 \fi % \mtfontexpand\textrm @@ -11713,18 +11904,18 @@ \def\microtypeOFF{% \microtypefalse % - \ifx\XeTeXrevision\thisisundefined - \ifx\luatexversion\thisisundefined + \ifxetex % XeTeX + \XeTeXprotrudechars=0 + \else + \ifluatex % LuaTeX + \adjustspacing=0 + \protrudechars=0 + \else \ifpdf % pdfTeX \pdfadjustspacing=0 \pdfprotrudechars=0 \fi - \else % LuaTeX - \adjustspacing=0 - \protrudechars=0 \fi - \else % XeTeX - \XeTeXprotrudechars=0 \fi } diff --git a/lib/attribute.h b/lib/attribute.h index 4939d776e72..625195c8565 100644 --- a/lib/attribute.h +++ b/lib/attribute.h @@ -257,7 +257,9 @@ because the function need not return exactly once and can depend on state addressed by its arguments.) See also and - . */ + . + ATTENTION! Efforts are underway to change the meaning of this attribute. + See . */ /* Applies to: functions, pointer to functions, function type. */ #define UNSEQUENCED _GL_ATTRIBUTE_UNSEQUENCED @@ -284,7 +286,9 @@ because the function need not return exactly once and can affect state addressed by its arguments.) See also and - . */ + . + ATTENTION! Efforts are underway to change the meaning of this attribute. + See . */ /* Applies to: functions, pointer to functions, function type. */ #define REPRODUCIBLE _GL_ATTRIBUTE_REPRODUCIBLE diff --git a/lib/flexmember.h b/lib/flexmember.h index 15ee4f5e281..b4d86c29fb5 100644 --- a/lib/flexmember.h +++ b/lib/flexmember.h @@ -28,11 +28,12 @@ #include /* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below. - On older platforms without _Alignof, use a pessimistic bound that is + If _Alignof might not exist or might not work correctly on + structs with flexible array members, use a pessimistic bound that is safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1. - On newer platforms, use _Alignof to get a tighter bound. */ + Otherwise, use _Alignof to get a tighter bound. */ -#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 +#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 || defined _Alignof # define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1)) #else # define FLEXALIGNOF(type) _Alignof (type) diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 22d102b1d86..fa2250cf686 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -281,7 +281,6 @@ EXECINFO_H = @EXECINFO_H@ EXEEXT = @EXEEXT@ FILE_HAS_ACL_LIB = @FILE_HAS_ACL_LIB@ FIND_DELETE = @FIND_DELETE@ -FIRSTFILE_OBJ = @FIRSTFILE_OBJ@ FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ FONT_OBJ = @FONT_OBJ@ @@ -960,7 +959,6 @@ HAVE_WCHAR_H = @HAVE_WCHAR_H@ HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ HAVE_XSERVER = @HAVE_XSERVER@ HAVE__EXIT = @HAVE__EXIT@ -HYBRID_MALLOC = @HYBRID_MALLOC@ IEEE754_H = @IEEE754_H@ IMAGEMAGICK_CFLAGS = @IMAGEMAGICK_CFLAGS@ IMAGEMAGICK_LIBS = @IMAGEMAGICK_LIBS@ @@ -1137,7 +1135,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -PAXCTL = @PAXCTL@ PAXCTL_dumped = @PAXCTL_dumped@ PAXCTL_notdumped = @PAXCTL_notdumped@ PGTK_LIBS = @PGTK_LIBS@ @@ -1147,10 +1144,8 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_CFLAGS = @PNG_CFLAGS@ PNG_LIBS = @PNG_LIBS@ -POST_ALLOC_OBJ = @POST_ALLOC_OBJ@ PRAGMA_COLUMNS = @PRAGMA_COLUMNS@ PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@ -PRE_ALLOC_OBJ = @PRE_ALLOC_OBJ@ PRIPTR_PREFIX = @PRIPTR_PREFIX@ PROFILING_CFLAGS = @PROFILING_CFLAGS@ PTHREAD_H_DEFINES_STRUCT_TIMESPEC = @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ @@ -1388,7 +1383,6 @@ TREE_SITTER_LIBS = @TREE_SITTER_LIBS@ UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@ UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@ UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@ -UNEXEC_OBJ = @UNEXEC_OBJ@ UNISTD_H_DEFINES_STRUCT_TIMESPEC = @UNISTD_H_DEFINES_STRUCT_TIMESPEC@ UNISTD_H_HAVE_SYS_RANDOM_H = @UNISTD_H_HAVE_SYS_RANDOM_H@ UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@ @@ -1501,10 +1495,16 @@ gl_GNULIB_ENABLED_verify_CONDITION = @gl_GNULIB_ENABLED_verify_CONDITION@ gl_LIBOBJDEPS = @gl_LIBOBJDEPS@ gl_LIBOBJS = @gl_LIBOBJS@ gl_LTLIBOBJS = @gl_LTLIBOBJS@ +gl_libgnu_LIBOBJDEPS = @gl_libgnu_LIBOBJDEPS@ +gl_libgnu_LIBOBJS = @gl_libgnu_LIBOBJS@ +gl_libgnu_LTLIBOBJS = @gl_libgnu_LTLIBOBJS@ gltests_LIBOBJDEPS = @gltests_LIBOBJDEPS@ gltests_LIBOBJS = @gltests_LIBOBJS@ gltests_LTLIBOBJS = @gltests_LTLIBOBJS@ gltests_WITNESS = @gltests_WITNESS@ +gltests_libgnu_LIBOBJDEPS = @gltests_libgnu_LIBOBJDEPS@ +gltests_libgnu_LIBOBJS = @gltests_libgnu_LIBOBJS@ +gltests_libgnu_LTLIBOBJS = @gltests_libgnu_LTLIBOBJS@ gsettingsschemadir = @gsettingsschemadir@ host = @host@ host_alias = @host_alias@ @@ -1552,9 +1552,9 @@ x_default_search_path = @x_default_search_path@ noinst_LIBRARIES += libgnu.a libgnu_a_SOURCES = -libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS) -libgnu_a_LIBADD = $(gl_LIBOBJS) -libgnu_a_DEPENDENCIES = $(gl_LIBOBJS) +libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS) $(GL_CFLAG_ALLOW_WARNINGS) +libgnu_a_LIBADD = $(gl_libgnu_LIBOBJS) +libgnu_a_DEPENDENCIES = $(gl_libgnu_LIBOBJS) EXTRA_libgnu_a_SOURCES = ## begin gnulib module absolute-header @@ -4446,5 +4446,5 @@ mostlyclean-local: mostlyclean-generic : distclean-local: distclean-gnulib-libobjs distclean-gnulib-libobjs: - -rm -f @gl_LIBOBJDEPS@ + -rm -f @gl_libgnu_LIBOBJDEPS@ maintainer-clean-local: distclean-gnulib-libobjs diff --git a/lib/intprops.h b/lib/intprops.h index 92dfef2500a..83efe39910a 100644 --- a/lib/intprops.h +++ b/lib/intprops.h @@ -34,6 +34,14 @@ signed or floating type. Do not evaluate E. */ #define EXPR_SIGNED(e) _GL_EXPR_SIGNED (e) +/* The same value as as the arithmetic expression E, but with E's type + after integer promotions. For example, if E is of type 'enum {A, B}' + then 'switch (INT_PROMOTE (E))' pacifies gcc -Wswitch-enum if some + enum values are deliberately omitted from the switch's cases. + Here, unary + is safer than a cast or inline function, as unary + + does only integer promotions. */ +#define INT_PROMOTE(e) (+ (e)) + /* Minimum and maximum values for integer types and expressions. */ diff --git a/m4/acl.m4 b/m4/acl.m4 index c9cb6dd09ed..7e4b0e354d9 100644 --- a/m4/acl.m4 +++ b/m4/acl.m4 @@ -1,5 +1,5 @@ # acl.m4 -# serial 34 +# serial 35 dnl Copyright (C) 2002, 2004-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -18,7 +18,7 @@ AC_DEFUN([gl_FUNC_ACL_ARG], , [enable_acl=auto]) AC_ARG_WITH([libsmack], [AS_HELP_STRING([--without-libsmack], - [do not use libsmack, even on systems that have it])] + [do not use libsmack, even on systems that have it])], [], [with_libsmack=maybe]) ]) diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4 index b3b1391bd54..6eff85bea12 100644 --- a/m4/gnulib-common.m4 +++ b/m4/gnulib-common.m4 @@ -1,5 +1,5 @@ # gnulib-common.m4 -# serial 106 +# serial 107 dnl Copyright (C) 2007-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -753,7 +753,9 @@ AC_DEFUN([gl_COMMON_BODY], [ than _GL_ATTRIBUTE_PURE because the function need not return exactly once and can affect state addressed by its arguments.) See also and - . */ + . + ATTENTION! Efforts are underway to change the meaning of this attribute. + See . */ /* Applies to: functions, pointer to functions, function types. */ #ifndef _GL_ATTRIBUTE_REPRODUCIBLE /* This may be revisited when gcc and clang support [[reproducible]] or possibly @@ -804,7 +806,9 @@ AC_DEFUN([gl_COMMON_BODY], [ _GL_ATTRIBUTE_CONST because the function need not return exactly once and can depend on state addressed by its arguments.) See also and - . */ + . + ATTENTION! Efforts are underway to change the meaning of this attribute. + See . */ /* Applies to: functions, pointer to functions, function types. */ #ifndef _GL_ATTRIBUTE_UNSEQUENCED /* This may be revisited when gcc and clang support [[unsequenced]] or possibly diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 980baf83998..42f67d0a42b 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -1057,27 +1057,35 @@ AC_DEFUN([gl_INIT], gl_libobjs= gl_ltlibobjs= gl_libobjdeps= + gl_libgnu_libobjs= + gl_libgnu_ltlibobjs= + gl_libgnu_libobjdeps= if test -n "$gl_LIBOBJS"; then # Remove the extension. changequote(,)dnl sed_drop_objext='s/\.o$//;s/\.obj$//' sed_dirname1='s,//*,/,g' sed_dirname2='s,\(.\)/$,\1,' - sed_dirname3='s,^[^/]*$,.,' - sed_dirname4='s,\(.\)/[^/]*$,\1,' + sed_dirname3='s,[^/]*$,,' sed_basename1='s,.*/,,' changequote([, ])dnl for i in `for i in $gl_LIBOBJS; do echo "$i"; done | sed -e "$sed_drop_objext" | sort | uniq`; do gl_libobjs="$gl_libobjs $i.$ac_objext" gl_ltlibobjs="$gl_ltlibobjs $i.lo" - i_dir=`echo "$i" | sed -e "$sed_dirname1" -e "$sed_dirname2" -e "$sed_dirname3" -e "$sed_dirname4"` + i_dir=`echo "$i" | sed -e "$sed_dirname1" -e "$sed_dirname2" -e "$sed_dirname3"` i_base=`echo "$i" | sed -e "$sed_basename1"` - gl_libobjdeps="$gl_libobjdeps $i_dir/\$(DEPDIR)/$i_base.Po" + gl_libgnu_libobjs="$gl_libgnu_libobjs $i_dir""libgnu_a-$i_base.$ac_objext" + gl_libgnu_ltlibobjs="$gl_libgnu_ltlibobjs $i_dir""libgnu_la-$i_base.lo" + gl_libobjdeps="$gl_libobjdeps $i_dir\$(DEPDIR)/$i_base.Po" + gl_libgnu_libobjdeps="$gl_libgnu_libobjdeps $i_dir\$(DEPDIR)/libgnu_a-$i_base.Po" done fi AC_SUBST([gl_LIBOBJS], [$gl_libobjs]) AC_SUBST([gl_LTLIBOBJS], [$gl_ltlibobjs]) AC_SUBST([gl_LIBOBJDEPS], [$gl_libobjdeps]) + AC_SUBST([gl_libgnu_LIBOBJS], [$gl_libgnu_libobjs]) + AC_SUBST([gl_libgnu_LTLIBOBJS], [$gl_libgnu_ltlibobjs]) + AC_SUBST([gl_libgnu_LIBOBJDEPS], [$gl_libgnu_libobjdeps]) ]) gltests_libdeps= gltests_ltlibdeps= @@ -1121,27 +1129,35 @@ changequote([, ])dnl gltests_libobjs= gltests_ltlibobjs= gltests_libobjdeps= + gltests_libgnu_libobjs= + gltests_libgnu_ltlibobjs= + gltests_libgnu_libobjdeps= if test -n "$gltests_LIBOBJS"; then # Remove the extension. changequote(,)dnl sed_drop_objext='s/\.o$//;s/\.obj$//' sed_dirname1='s,//*,/,g' sed_dirname2='s,\(.\)/$,\1,' - sed_dirname3='s,^[^/]*$,.,' - sed_dirname4='s,\(.\)/[^/]*$,\1,' + sed_dirname3='s,[^/]*$,,' sed_basename1='s,.*/,,' changequote([, ])dnl for i in `for i in $gltests_LIBOBJS; do echo "$i"; done | sed -e "$sed_drop_objext" | sort | uniq`; do gltests_libobjs="$gltests_libobjs $i.$ac_objext" gltests_ltlibobjs="$gltests_ltlibobjs $i.lo" - i_dir=`echo "$i" | sed -e "$sed_dirname1" -e "$sed_dirname2" -e "$sed_dirname3" -e "$sed_dirname4"` + i_dir=`echo "$i" | sed -e "$sed_dirname1" -e "$sed_dirname2" -e "$sed_dirname3"` i_base=`echo "$i" | sed -e "$sed_basename1"` - gltests_libobjdeps="$gltests_libobjdeps $i_dir/\$(DEPDIR)/$i_base.Po" + gltests_libgnu_libobjs="$gltests_libgnu_libobjs $i_dir""libgnu_a-$i_base.$ac_objext" + gltests_libgnu_ltlibobjs="$gltests_libgnu_ltlibobjs $i_dir""libgnu_la-$i_base.lo" + gltests_libobjdeps="$gltests_libobjdeps $i_dir\$(DEPDIR)/$i_base.Po" + gltests_libgnu_libobjdeps="$gltests_libgnu_libobjdeps $i_dir\$(DEPDIR)/libgnu_a-$i_base.Po" done fi AC_SUBST([gltests_LIBOBJS], [$gltests_libobjs]) AC_SUBST([gltests_LTLIBOBJS], [$gltests_ltlibobjs]) AC_SUBST([gltests_LIBOBJDEPS], [$gltests_libobjdeps]) + AC_SUBST([gltests_libgnu_LIBOBJS], [$gltests_libgnu_libobjs]) + AC_SUBST([gltests_libgnu_LTLIBOBJS], [$gltests_libgnu_ltlibobjs]) + AC_SUBST([gltests_libgnu_LIBOBJDEPS], [$gltests_libgnu_libobjdeps]) ]) AC_REQUIRE([gl_CC_GNULIB_WARNINGS]) LIBGNU_LIBDEPS="$gl_libdeps" commit 93206cbcea31add3da76cc1025b2f148312fe6f1 Author: Stefan Kangas Date: Thu Jan 23 23:49:52 2025 +0100 Remove leading '*' from docstrings in cc-vars.el * lisp/progmodes/cc-vars.el (c-make-font-lock-extra-types-blurb): Remove leading '*' from generated docstrings. (Bug#75793) diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el index 3c386eb07e9..0687801d69f 100644 --- a/lisp/progmodes/cc-vars.el +++ b/lisp/progmodes/cc-vars.el @@ -1566,7 +1566,7 @@ working due to this change." (defun c-make-font-lock-extra-types-blurb (mode1 mode2 example) (concat "\ -*List of extra types (aside from the type keywords) to recognize in " +List of extra types (aside from the type keywords) to recognize in " mode1 " mode. Each list item should be a regexp matching a single identifier. " example " commit 7169a5d5636ddede2fe70a31de098031f20f70b1 Author: João Távora Date: Fri Feb 7 20:33:41 2025 +0000 Eglot: fix bug in eglot--lookup-mode When lookup in eglot-server-programs fails, fall back to a half-decent (((foo-mode . "foo")) . nil) return value. This enables interactive M-x eglot for modes not yet registered in e-s-p. * lisp/progmodes/eglot.el (eglot--lookup-mode): Fallback when lookup fails. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 502effd098d..728227f0e9a 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1322,22 +1322,28 @@ in `eglot-server-programs' (which see). CONTACT-PROXY is the value of the corresponding `eglot-server-programs' entry." (cl-loop + with lang-from-sym = (lambda (sym &optional language-id) + (cons sym + (or language-id + (or (get sym 'eglot-language-id) + (replace-regexp-in-string + "\\(?:-ts\\)?-mode$" "" + (symbol-name sym)))))) for (modes . contact) in eglot-server-programs for llists = (mapcar #'eglot--ensure-list - (if (or (symbolp modes) (keywordp (cadr modes))) - (list modes) modes)) + (if (or (symbolp modes) (keywordp (cadr modes))) + (list modes) modes)) for normalized = (mapcar (jsonrpc-lambda (sym &key language-id &allow-other-keys) - (cons sym - (or language-id - (or (get sym 'eglot-language-id) - (replace-regexp-in-string - "\\(?:-ts\\)?-mode$" "" - (symbol-name sym)))))) + (funcall lang-from-sym sym language-id)) llists) when (cl-some (lambda (cell) (provided-mode-derived-p mode (car cell))) normalized) - return (cons normalized contact))) + return (cons normalized contact) + ;; If lookup fails at least return some suitable LANGUAGES. + finally (cl-return + (cons (list (funcall lang-from-sym major-mode)) + nil)))) (defun eglot--guess-contact (&optional interactive) "Helper for `eglot'. commit 0c0f5f5df24947f0658c274f9fa62829ef5401dd Author: Stefan Kangas Date: Fri Feb 7 21:22:38 2025 +0100 Mark IRIX support in GUD as obsolete * lisp/progmodes/gud.el (gud-irix-p, gud-dbx-use-stopformat-p) (gud-irixdbx-marker-filter): Mark as obsolete. We stopped supporting IRIX in Emacs 26.1 (commit 6bc8689c0428). * lisp/progmodes/gud.el (dbx): Suppress obsoletion warnings. diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el index b63de1abff2..7ced54170ff 100644 --- a/lisp/progmodes/gud.el +++ b/lisp/progmodes/gud.el @@ -1261,42 +1261,16 @@ containing the executable being debugged." output)) -;; The dbx in IRIX is a pain. It doesn't print the file name when -;; stopping at a breakpoint (but you do get it from the `up' and -;; `down' commands...). The only way to extract the information seems -;; to be with a `file' command, although the current line number is -;; available in $curline. Thus we have to look for output which -;; appears to indicate a breakpoint. Then we prod the dbx sub-process -;; to output the information we want with a combination of the -;; `printf' and `file' commands as a pseudo marker which we can -;; recognize next time through the marker-filter. This would be like -;; the gdb marker but you can't get the file name without a newline... -;; Note that gud-remove won't work since Irix dbx expects a breakpoint -;; number rather than a line number etc. Maybe this could be made to -;; work by listing all the breakpoints and picking the one(s) with the -;; correct line number, but life's too short. -;; d.love@dl.ac.uk (Dave Love) can be blamed for this - (defvar gud-irix-p nil "Non-nil to assume the interface appropriate for IRIX dbx. This works in IRIX 4, 5 and 6, but `gud-dbx-use-stopformat-p' provides a better solution in 6.1 upwards.") +(make-obsolete-variable 'gud-irix-p nil "31.1") (defvar gud-dbx-use-stopformat-p nil "Non-nil to use the dbx feature present at least from Irix 6.1 whereby $stopformat=1 produces an output format compatible with `gud-dbx-marker-filter'.") -;; [Irix dbx seemed to be a moving target. The dbx output changed -;; subtly sometime between OS v4.0.5 and v5.2 so that, for instance, -;; the output from `up' is no longer spotted by gud (and it's probably -;; not distinctive enough to try to match it -- use C-<, C-> -;; exclusively) . For 5.3 and 6.0, the $curline variable changed to -;; `long long'(why?!), so the printf stuff needed changing. The line -;; number was cast to `long' as a compromise between the new `long -;; long' and the original `int'. This was reported not to work in 6.2, -;; so it's changed back to int -- don't make your sources too long. -;; From Irix6.1 (but not 6.0?) dbx supported an undocumented feature -;; whereby `set $stopformat=1' reportedly produces output compatible -;; with `gud-dbx-marker-filter', which we prefer. +(make-obsolete-variable 'gud-dbx-use-stopformat-p nil "31.1") (defvar-keymap gud-dbx-repeat-map :doc "Keymap to repeat `dbx' stepping instructions \\`C-x C-a C-n n n'. @@ -1313,13 +1287,8 @@ Used in `repeat-mode'." gud-irix-p) (keymap-set gud-dbx-repeat-map "f" #'gud-finish)) - -;; The process filter is also somewhat -;; unreliable, sometimes not spotting the markers; I don't know -;; whether there's anything that can be done about that.] - -;; this filter is influenced by the xdb one rather than the gdb one (defun gud-irixdbx-marker-filter (string) + (declare (obsolete nil "31.1")) (let (result (case-fold-search nil)) (if (or (string-match comint-prompt-regexp string) (string-match ".*\012" string)) @@ -1417,8 +1386,9 @@ and source-file directory for your debugger." (gud-mips-p (gud-common-init command-line nil 'gud-mipsdbx-marker-filter)) (gud-irix-p - (gud-common-init command-line 'gud-dbx-massage-args - 'gud-irixdbx-marker-filter)) + (with-suppressed-warnings ((obsolete gud-irixdbx-marker-filter)) + (gud-common-init command-line 'gud-dbx-massage-args + #'gud-irixdbx-marker-filter))) (t (gud-common-init command-line 'gud-dbx-massage-args 'gud-dbx-marker-filter))) commit 280b25e0096bb97fb473a8da9b4635fb2d6e5385 Author: Stephen Gildea Date: Fri Feb 7 09:17:26 2025 -0800 time-stamp: Better handling of some edge cases * lisp/time-stamp.el (time-stamp-count): Require confirmation if large. (time-stamp-once): Correctly handle a start regexp matching 0 chars. * test/lisp/time-stamp-tests.el (time-stamp-custom-start): New test. diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el index ad356eb2bd6..4117db71058 100644 --- a/lisp/time-stamp.el +++ b/lisp/time-stamp.el @@ -114,7 +114,7 @@ limit yourself to the formats recommended by that older version." (defcustom time-stamp-active t - "Non-nil to enable time-stamping of buffers by \\[time-stamp]. + "Non-nil enables time-stamping of buffers by \\[time-stamp]. Can be toggled by \\[time-stamp-toggle-active]. This option does not affect when `time-stamp' is run, only what it @@ -257,7 +257,7 @@ then instead of changing this variable, include a newline (written as `time-stamp-count' is best changed with a file-local variable. If you were to change it in your init file, you would be incompatible with other people's files.") -;;;###autoload(put 'time-stamp-count 'safe-local-variable 'integerp) +;;;###autoload(put 'time-stamp-count 'safe-local-variable (lambda (c) (and (integerp c) (< c 100)))) (defvar time-stamp-pattern nil ;Do not change! @@ -342,12 +342,11 @@ To enable automatic time-stamping for only a specific file, add this line to a local variables list near the end of the file: eval: (add-hook \\='before-save-hook \\='time-stamp nil t) -If the file has no time stamp template, this function does nothing. +If the file has no time stamp template or if `time-stamp-active' is nil, +this function does nothing. You can set `time-stamp-pattern' in a file's local variables list -to customize the information in the time stamp and where it is written. - -The time stamp is updated only if `time-stamp-active' is non-nil." +to customize the information in the time stamp and where it is written." (interactive) (let ((line-limit time-stamp-line-limit) (ts-start time-stamp-start) @@ -421,6 +420,7 @@ The time stamp is updated only if `time-stamp-active' is non-nil." Returns the end point, which is where `time-stamp' begins the next search." (let ((case-fold-search nil) (end nil) + (advance-nudge 0) end-search-start (end-length nil)) (save-excursion @@ -430,6 +430,9 @@ Returns the end point, which is where `time-stamp' begins the next search." (while (and (< (goto-char start) search-limit) (not end) (re-search-forward ts-start search-limit 'move)) + ;; Whether or not we find a template, we must + ;; advance through the buffer. + (setq advance-nudge (if (> (point) start) 0 1)) (setq start (point)) (if (not time-stamp-inserts-lines) (forward-line format-lines)) @@ -444,7 +447,8 @@ Returns the end point, which is where `time-stamp' begins the next search." (if (re-search-forward ts-end line-end t) (progn (setq end (match-beginning 0)) - (setq end-length (- (match-end 0) end)))))))))))) + (setq end-length (- (match-end 0) end))) + (setq start (+ start advance-nudge))))))))))) (if end (progn ;; do all warnings outside save-excursion @@ -478,7 +482,7 @@ Returns the end point, which is where `time-stamp' begins the next search." (setq end (point)))))))))))) ;; return the location after this time stamp, if there was one (and end end-length - (+ end end-length)))) + (+ end (max advance-nudge end-length))))) ;;;###autoload diff --git a/test/lisp/time-stamp-tests.el b/test/lisp/time-stamp-tests.el index a7aa00dc267..f4fcce3e957 100644 --- a/test/lisp/time-stamp-tests.el +++ b/test/lisp/time-stamp-tests.el @@ -138,6 +138,31 @@ (iter-yield-from (time-stamp-test-pattern-sequential)) (iter-yield-from (time-stamp-test-pattern-multiply))) +(ert-deftest time-stamp-custom-start () + "Test that `time-stamp' isn't stuck by a start matching 0 characters." + (with-time-stamp-test-env + (with-time-stamp-test-time ref-time1 + (let ((time-stamp-pattern "^%Y-%m-%d<-TS")) ;start matches 0 chars + (with-temp-buffer + (insert "\n<-TS\n") + ;; we should advance to line 2 and find the template + (time-stamp) + (should (equal (buffer-string) "\n2006-01-02<-TS\n")))) + (let ((time-stamp-pattern "\\b%Y-%m-%d\\b") ;start and end match 0 chars + (time-stamp-count 2)) + (with-temp-buffer + (insert "..") + ;; the two time stamps should be in different places + (time-stamp) + (should (equal (buffer-string) "2006-01-02..2006-01-02")))) + (let ((time-stamp-pattern "::%S\\_>") ;end matches 0 chars + (time-stamp-count 2)) + (with-temp-buffer + (insert "::0::0") + ;; the second template should be found immediately after the first + (time-stamp) + (should (equal (buffer-string) "::05::05"))))))) + (ert-deftest time-stamp-custom-pattern () "Test that `time-stamp-pattern' is parsed correctly." (iter-do (pattern-parts (time-stamp-test-pattern-all)) @@ -246,17 +271,17 @@ (let ((time-stamp-start "TS: <") (time-stamp-format "%Y-%m-%d") (time-stamp-count 0) ;changed later in the test - (buffer-expected-once "TS: <2006-01-02>\nTS: <>") - (buffer-expected-twice "TS: <2006-01-02>\nTS: <2006-01-02>")) + (buffer-expected-once "TS: <2006-01-02>TS: <>") + (buffer-expected-twice "TS: <2006-01-02>TS: <2006-01-02>")) (with-time-stamp-test-time ref-time1 (with-temp-buffer - (insert "TS: <>\nTS: <>") + (insert "TS: <>TS: <>") (time-stamp) ;; even with count = 0, expect one time stamp (should (equal (buffer-string) buffer-expected-once))) (with-temp-buffer (setq time-stamp-count 1) - (insert "TS: <>\nTS: <>") + (insert "TS: <>TS: <>") (time-stamp) (should (equal (buffer-string) buffer-expected-once)) @@ -698,7 +723,7 @@ (should (equal (time-stamp-string "%5z" ref-time1) "+0000")) (let ((time-stamp-time-zone "PST8")) (should (equal (time-stamp-string "%5z" ref-time1) "-0800"))) - (let ((time-stamp-time-zone "HST10")) + (let ((time-stamp-time-zone '(-36000 "HST"))) (should (equal (time-stamp-string "%5z" ref-time1) "-1000"))) (let ((time-stamp-time-zone "CET-1")) (should (equal (time-stamp-string "%5z" ref-time1) "+0100"))) @@ -887,6 +912,7 @@ (should (safe-local-variable-p 'time-stamp-inserts-lines t)) (should-not (safe-local-variable-p 'time-stamp-inserts-lines 17)) (should (safe-local-variable-p 'time-stamp-count 2)) + (should-not (safe-local-variable-p 'time-stamp-count 100)) (should-not (safe-local-variable-p 'time-stamp-count t)) (should (safe-local-variable-p 'time-stamp-pattern "a string")) (should-not (safe-local-variable-p 'time-stamp-pattern 17))) commit a62b58648ac54feb8fb81aefdb0461cb11bf6a81 Author: Robert Pluim Date: Fri Feb 7 15:48:47 2025 +0100 ; * src/keyboard.c (syms_of_keyboard): Fix previous change. diff --git a/src/keyboard.c b/src/keyboard.c index 2b904b64cbe..ac143af83f4 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -13965,7 +13965,10 @@ function is called to remap that sequence. */); pdumper_do_now_and_after_load (syms_of_keyboard_for_pdumper); DEFSYM (Qactivate_mark_hook, "activate-mark-hook"); +#ifdef HAVE_NS + DEFSYM (Qns_put_working_text, "ns-put-working-text"); DEFSYM (Qns_unput_working_text, "ns-unput-working-text"); +#endif DEFSYM (Qinternal_timer_start_idle, "internal-timer-start-idle"); DEFSYM (Qconcat, "concat"); DEFSYM (Qsuspend_hook, "suspend-hook"); commit 0065c9dbb8fb7d2b802e8f9a327f33049afec4ad Author: Michael Albinus Date: Fri Feb 7 15:14:47 2025 +0100 Suppress unneded events in special-event-map * src/keyboard.c (keys_of_keyboard): Don't add ns-put-working-text and ns-unput-working-text to Vspecial_event_map unless on NS port. diff --git a/src/keyboard.c b/src/keyboard.c index e91bd3d68b4..2b904b64cbe 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -14014,10 +14014,12 @@ keys_of_keyboard (void) initial_define_lispy_key (Vspecial_event_map, "end-session", "kill-emacs"); #endif +#ifdef HAVE_NS initial_define_lispy_key (Vspecial_event_map, "ns-put-working-text", "ns-put-working-text"); initial_define_lispy_key (Vspecial_event_map, "ns-unput-working-text", "ns-unput-working-text"); +#endif /* Here we used to use `ignore-event' which would simple set prefix-arg to current-prefix-arg, as is done in `handle-switch-frame'. But `handle-switch-frame is not run from the special-map. commit 8be3be7330953dd015df28369c1f071178248bb4 Author: Michael Albinus Date: Fri Feb 7 14:41:58 2025 +0100 Use insert-special-event in Tramp * lisp/net/tramp-gvfs.el (tramp-gvfs-monitor-process-filter): * lisp/net/tramp-sh.el (tramp-sh-gio-monitor-process-filter) (tramp-sh-inotifywait-process-filter): Use `insert-special-event' if possible. diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index b31095fb914..53a6ffc48aa 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -1569,11 +1569,15 @@ If FILE-SYSTEM is non-nil, return file system attributes." (when (and (member action '(moved deleted)) (string-equal file (process-get proc 'tramp-watch-name))) (delete-process proc)) - ;; Usually, we would add an Emacs event now. Unfortunately, - ;; `unread-command-events' does not accept several events at - ;; once. Therefore, we apply the callback directly. + ;; Add an Emacs event now. + ;; `insert-special-event' exists since Emacs 31. (when (member action events) - (file-notify-callback (list proc action file file1))))) + (tramp-compat-funcall + (if (fboundp 'insert-special-event) + 'insert-special-event + (lookup-key special-event-map [file-notify])) + `(file-notify + ,(list proc action file file1) file-notify-callback))))) ;; Save rest of the string. (when (string-empty-p string) (setq string nil)) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 40013852153..e268489b7c8 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -3898,13 +3898,14 @@ Fall back to normal file name handler if no Tramp handler exists." (concat remote-prefix file) (when file1 (concat remote-prefix file1))))) (setq string (replace-match "" nil nil string)) - ;; Usually, we would add an Emacs event now. Unfortunately, - ;; `unread-command-events' does not accept several events at - ;; once. Therefore, we apply the handler directly. + ;; Add an Emacs event now. + ;; `insert-special-event' exists since Emacs 31. (when (member (cl-caadr object) events) (tramp-compat-funcall - (lookup-key special-event-map [file-notify]) - `(file-notify ,object file-notify-callback)))))) + (if (fboundp 'insert-special-event) + 'insert-special-event + (lookup-key special-event-map [file-notify])) + `(file-notify ,object file-notify-callback)))))) ;; Save rest of the string. (while (string-match (rx bol "\n") string) @@ -3934,13 +3935,14 @@ Fall back to normal file name handler if no Tramp handler exists." (or (match-string 2 line) (file-name-nondirectory (process-get proc 'tramp-watch-name)))))) - ;; Usually, we would add an Emacs event now. Unfortunately, - ;; `unread-command-events' does not accept several events at - ;; once. Therefore, we apply the handler directly. + ;; Add an Emacs event now. + ;; `insert-special-event' exists since Emacs 31. (when (member (cl-caadr object) events) (tramp-compat-funcall - (lookup-key special-event-map [file-notify]) - `(file-notify ,object file-notify-callback))))))) + (if (fboundp 'insert-special-event) + 'insert-special-event + (lookup-key special-event-map [file-notify])) + `(file-notify ,object file-notify-callback))))))) (defun tramp-sh-handle-file-system-info (filename) "Like `file-system-info' for Tramp files." commit 1ef9de69b3c3d8254ab58bf455137a4439dce516 Author: João Távora Date: Fri Feb 7 11:08:29 2025 +0000 Eglot: add support for call and type hierarchies * lisp/progmodes/eglot.el (eglot--lsp-interface-alist): Add new interfaces. (eglot-client-capabilities): Advertise support for callHierarchy and typeHierarchy. (eglot-ignored-server-capabilities): Add new providers. (eglot--goto): New helper. (eglot-menu): Add new menu items. (eglot-handle-request window/showDocument): Use eglot--goto. (button, tree-widget): Require them. (eglot--hierarchy-item): New button type. (eglot--hierarchy-interactive, eglot--hierarchy-children) (eglot--hierarchy-label, eglot--hierarchy-1, eglot--hierarchy-2): New internal functions. (eglot--define-hierarchy-command): New macro. (eglot-show-type-hierarchy, eglot-show-call-hierarchy) (eglot-hierarchy-center-on-node): New commands. (eglot--hierarchy-roots, eglot--hierarchy-specs): New local variables. (eglot-hierarchy-label-map): New keymap. (eglot-hierarchy-mode): New major mode. * doc/misc/eglot.texi (Eglot Commands, Eglot Features): Describe new feature. * etc/EGLOT-NEWS (Changes in upcoming Eglot): Mention new feature. diff --git a/doc/misc/eglot.texi b/doc/misc/eglot.texi index 722766843ec..333e369e440 100644 --- a/doc/misc/eglot.texi +++ b/doc/misc/eglot.texi @@ -452,6 +452,11 @@ be it the type of a variable, or the name of a formal parameter in a function call. @xref{Eglot Commands} and the @code{eglot-inlay-hints-mode} minor mode. +@item +Display of function call and type hierarchies via the +@code{eglot-show-call-hierarchy} and @code{eglot-show-type-hierarchy} +commands (@pxref{Eglot Commands}). + @item Code reformatting via the @code{eglot-format} and related commands (@pxref{Eglot Commands}). Automatic reformatting of source code is also @@ -738,6 +743,16 @@ instead of indicating problems. For example, a C++ language server can serve hints about positional parameter names in function calls and a variable's automatically deduced type. Inlay hints help the user not have to remember these things by heart. + +@cindex type hierarchy +@item M-x eglot-show-type-hierarchy +Pop up a special buffer showing a interactive tree which represents a +hierarchy of subtypes and supertypes for the symbol at point. + +@cindex call hierarchy +@item M-x eglot-call-type-hierarchy +Pop up a special buffer showing a interactive tree which represents a +hierarchy of callers and callee for the symbol at point. @end ftable The following Eglot commands are used less commonly, mostly for diff --git a/etc/EGLOT-NEWS b/etc/EGLOT-NEWS index 02355e25f93..20a2e694426 100644 --- a/etc/EGLOT-NEWS +++ b/etc/EGLOT-NEWS @@ -20,6 +20,13 @@ https://github.com/joaotavora/eglot/issues/1234. * Changes in upcoming Eglot +** Support for call and type hierarchies + +The new commands 'eglot-show-type-hierarchy' and +'eglot-show-call-hierarchy', when invoked on a symbol, pop up a special +buffer showing an interactive tree which represents a hierarchy of sub- +and super-types or callers and callees for that symbol. + ** New 'eglot-advertise-cancellation' variable Tweaking this variable may help some LSP servers avoid doing costly but diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 7b1c174c4d7..502effd098d 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -566,7 +566,9 @@ under cursor." (const :tag "Decorate color references" :colorProvider) (const :tag "Fold regions of buffer" :foldingRangeProvider) (const :tag "Execute custom commands" :executeCommandProvider) - (const :tag "Inlay hints" :inlayHintProvider))) + (const :tag "Inlay hints" :inlayHintProvider) + (const :tag "Type hierarchies" :typeHierarchyProvider) + (const :tag "Call hierarchies" :callHierarchyProvider))) (defcustom eglot-advertise-cancellation nil "If non-nil, Eglot attemps to inform server of cancelled requests. @@ -717,7 +719,13 @@ This can be useful when using docker to run a language server.") (WorkspaceSymbol (:name :kind) (:containerName :location :data)) (InlayHint (:position :label) (:kind :textEdits :tooltip :paddingLeft :paddingRight :data)) - (InlayHintLabelPart (:value) (:tooltip :location :command))) + (InlayHintLabelPart (:value) (:tooltip :location :command)) + ;; HACK! 'HierarchyItem' doesn't exist, only `CallHierarchyItem' + ;; and `TypeHierarchyItem'. But they're the same, so no bother. + (HierarchyItem (:name :kind) + (:tags :detail :uri :range :selectionRange :data)) + (CallHierarchyIncomingCall (:from :fromRanges) ()) + (CallHierarchyOutgoingCall (:to :fromRanges) ())) "Alist (INTERFACE-NAME . INTERFACE) of known external LSP interfaces. INTERFACE-NAME is a symbol designated by the spec as @@ -1066,6 +1074,8 @@ object." :rangeFormatting `(:dynamicRegistration :json-false) :rename `(:dynamicRegistration :json-false) :inlayHint `(:dynamicRegistration :json-false) + :callHierarchy `(:dynamicRegistration :json-false) + :typeHierarchy `(:dynamicRegistration :json-false) :publishDiagnostics (list :relatedInformation :json-false ;; TODO: We can support :codeDescription after ;; adding an appropriate UI to @@ -1782,6 +1792,15 @@ in project `%s'." (let ((warning-minimum-level :error)) (display-warning 'eglot (apply #'eglot--format format args) :warning))) +(defun eglot--goto (range) + "Goto and momentarily highlight RANGE in current buffer." + (pcase-let ((`(,beg . ,end) (eglot-range-region range))) + ;; FIXME: it is very naughty to use someone else's `--' + ;; function, but `xref--goto-char' happens to have + ;; exactly the semantics we want vis-a-vis widening. + (xref--goto-char beg) + (pulse-momentary-highlight-region beg end 'highlight))) + (defalias 'eglot--bol (if (fboundp 'pos-bol) #'pos-bol (lambda (&optional n) (let ((inhibit-field-text-motion t)) @@ -2285,6 +2304,9 @@ If it is activated, also signal textDocument/didOpen." :visible (eglot-server-capable :codeActionProvider)] ["Quickfix" eglot-code-action-quickfix :visible (eglot-server-capable :codeActionProvider)] + "--" + ["Show type hierarchy" eglot-show-type-hierarchy] + ["Show call hierarchy" eglot-show-call-hierarchy] "--")) (easy-menu-define eglot-server-menu nil "Manage server communication" @@ -2699,12 +2721,7 @@ THINGS are either registrations or unregisterations (sic)." (select-frame-set-input-focus (selected-frame))) ((display-buffer (current-buffer)))) (when selection - (pcase-let ((`(,beg . ,end) (eglot-range-region selection))) - ;; FIXME: it is very naughty to use someone else's `--' - ;; function, but `xref--goto-char' happens to have - ;; exactly the semantics we want vis-a-vis widening. - (xref--goto-char beg) - (pulse-momentary-highlight-region beg end 'highlight))))))) + (eglot--goto selection)))))) (t (setq success :json-false))) `(:success ,success))) @@ -4369,6 +4386,194 @@ If NOERROR, return predicate, else erroring function." (jit-lock-unregister #'eglot--update-hints) (remove-overlays nil nil 'eglot--inlay-hint t)))) + +;;; Call and type hierarchies +(require 'button) +(require 'tree-widget) + +(define-button-type 'eglot--hierarchy-item + 'follow-link t + 'face 'font-lock-function-name-face) + +(defun eglot--hierarchy-interactive (specs) + (let ((ans + (completing-read "[eglot] Direction (default both)?" + (cons "both" (mapcar #'cl-fourth specs)) + nil t nil nil "both"))) + (list + (cond ((equal ans "both") t) + (t (cl-third (cl-find ans specs :key #'cl-fourth :test #'equal))))))) + +(defmacro eglot--define-hierarchy-command + (name kind feature preparer specs) + `(defun ,name (direction) + ,(concat + "Show " kind " hierarchy for symbol at point.\n" + "DIRECTION can be:\n" + (cl-loop for (_ _ d e) in specs + concat (format " - `%s' for %s;\n" d e)) + "or t, the default, to consider both.\n" + "Interactively with a prefix argument, prompt for DIRECTION.") + (interactive (if current-prefix-arg + (eglot--hierarchy-interactive ',specs) + (list t))) + (let* ((specs ',specs) + (specs (if (eq t direction) specs + (list + (cl-find direction specs :key #'cl-third))))) + (eglot--hierarchy-1 + (format "*EGLOT %s hierarchy for %s*" + ,kind + (eglot-project-nickname (eglot--current-server-or-lose))) + ,feature ,preparer specs)))) + +(eglot--define-hierarchy-command + eglot-show-type-hierarchy + "type" + :typeHierarchyProvider + :textDocument/prepareTypeHierarchy + ((:typeHierarchy/supertypes " ↑ " derived "supertypes" "derives from") + (:typeHierarchy/subtypes " ↓ " base "subtypes" "base of"))) + +(eglot--define-hierarchy-command + eglot-show-call-hierarchy + "call" + :callHierarchyProvider + :textDocument/prepareCallHierarchy + ((:callHierarchy/incomingCalls " ← " incoming "incoming calls" "called by" + :from :fromRanges) + (:callHierarchy/outgoingCalls " → " base "outgoing calls" "calls" + :to :fromRanges))) + +(defvar-local eglot--hierarchy-roots nil) +(defvar-local eglot--hierarchy-specs nil) + +(defun eglot--hierarchy-children (node) + (cl-flet ((get-them (method node) + (eglot--dbind ((HierarchyItem) name) node + (let* ((sym (intern (format "eglot--%s" method))) + (plist (text-properties-at 0 name)) + (probe (cl-getf plist sym :none))) + (cond ((eq probe :none) + (let ((v (ignore-errors (jsonrpc-request + (eglot--current-server-or-lose) method + `(:item ,node))))) + (put-text-property 0 1 sym v name) + v)) + (t probe)))))) + (cl-loop + with specs = eglot--hierarchy-specs + for (method bullet _ _ hint key ranges) in specs + for resp = (get-them method node) + for items = + (cl-loop for r across resp + for item = (if key (plist-get r key) r) + collect item + do (eglot--dbind ((HierarchyItem) name) item + (put-text-property 0 1 'eglot--hierarchy-method + method name) + (put-text-property 0 1 'eglot--hierarchy-bullet + (propertize bullet + 'help-echo hint) + name) + (when ranges + (put-text-property 0 1 'eglot--hierarchy-call-sites + (plist-get r ranges) + name)))) + append items))) + +(defvar eglot-hierarchy-label-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map button-map) + (define-key map [mouse-3] (eglot--mouse-call + #'eglot-hierarchy-center-on-node)) + map) + "Keymap active in labels Eglot hierarchy buffers.") + +(defun eglot--hierarchy-label (node) + (eglot--dbind ((HierarchyItem) name uri _detail ((:range item-range))) node + (with-temp-buffer + (insert (propertize + (or (get-text-property + 0 'eglot--hierarchy-bullet name) + " ∘ ") + 'face 'shadow)) + (insert-text-button + name + :type 'eglot--hierarchy-item + 'eglot--hierarchy-node node + 'help-echo "mouse-1, RET: goto definition, mouse-3: center on node" + 'keymap eglot-hierarchy-label-map + 'action + (lambda (_btn) + (pop-to-buffer (find-file-noselect (eglot-uri-to-path uri))) + (eglot--goto + (or + (elt + (get-text-property 0 'eglot--hierarchy-call-sites name) + 0) + item-range)))) + (buffer-string)))) + +(defun eglot--hierarchy-1 (name provider preparer specs) + (eglot-server-capable-or-lose provider) + (let* ((server (eglot-current-server)) + (roots (jsonrpc-request + server + preparer + (eglot--TextDocumentPositionParams)))) + (with-current-buffer (get-buffer-create name) + (eglot-hierarchy-mode) + (setq-local + eglot--hierarchy-roots roots + eglot--hierarchy-specs specs + eglot--cached-server server + buffer-read-only t + revert-buffer-function + (lambda (&rest _ignore) + ;; flush cache, would defeat purpose of a revert + (mapc (lambda (r) + (eglot--dbind ((HierarchyItem) name) r + (set-text-properties 0 1 nil name))) + eglot--hierarchy-roots) + (eglot--hierarchy-2))) + (eglot--hierarchy-2)))) + +(defun eglot--hierarchy-2 () + (cl-labels ((expander-for (node) + (lambda (_widget) + (mapcar + #'convert + (eglot--hierarchy-children node)))) + (convert (node) + (let ((w (widget-convert + 'tree-widget + :tag (eglot--hierarchy-label node) + :expander (expander-for node)))) + (widget-put w :empty-icon + (widget-get w :leaf-icon)) + w))) + (let ((inhibit-read-only t)) + (erase-buffer) + (mapc (lambda (r) + (widget-create (convert r))) + eglot--hierarchy-roots) + (goto-char (point-min)))) + (pop-to-buffer (current-buffer))) + +(define-derived-mode eglot-hierarchy-mode special-mode + "Eglot special" "Eglot mode for viewing hierarchies. +\\{eglot-hierarchy-mode-map}" + :interactive nil) + +(defun eglot-hierarchy-center-on-node () + "Refresh hierarchy, centering on node at point." + (interactive) + (setq-local eglot--hierarchy-roots + (list (get-text-property (point) + 'eglot--hierarchy-node))) + (eglot--hierarchy-2)) + ;;; Hacks ;;; commit f806b9cba6568433e36878ed005673a5788c004f Author: Eli Zaretskii Date: Fri Feb 7 13:37:56 2025 +0200 ; * src/keyboard.c (Finsert_special_event): Don't use "//". diff --git a/src/keyboard.c b/src/keyboard.c index ace5e1e3fef..e91bd3d68b4 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -11663,7 +11663,7 @@ Only 'input_event' slots KIND and ARG are set. */) #endif : EQ (XCAR (event), Qiconify_frame) ? ICONIFY_EVENT : EQ (XCAR (event), Qmake_frame_visible) ? DEICONIFY_EVENT - // : EQ (XCAR (event), Qselect_window) ? SELECT_WINDOW_EVENT + /* : EQ (XCAR (event), Qselect_window) ? SELECT_WINDOW_EVENT */ : EQ (XCAR (event), Qsave_session) ? SAVE_SESSION_EVENT #ifdef HAVE_DBUS : EQ (XCAR (event), Qdbus_event) ? DBUS_EVENT commit d41178368eb73873f34c15b58062a7447802c914 Author: Michael Albinus Date: Fri Feb 7 12:04:05 2025 +0100 New function insert-special-event and special event sleep-event * doc/lispref/commands.texi (Misc Events): Add sleep-event. (Special Events): New function insert-special-event. * etc/NEWS: New function insert-special-event. New event 'sleep-event'. Fix typos. * src/keyboard.c (Finsert_special_event): New defun. (syms_of_keyboard): Declare Qsleep_event. Define subroutine Sinsert_special_event. Add sleep-event to Vspecial_event_map. (Bug#63620) (kbd_buffer_get_event, make_lispy_event) (init_while_no_input_ignore_events, is_ignored_event): * src/termhooks.h (event_kind): Add SLEEP_EVENT. diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 39514145a1e..c3891b70406 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -2756,6 +2756,14 @@ To test the signal handler, you can make Emacs send a signal to itself: (signal-process (emacs-pid) 'sigusr1) @end smallexample +@cindex @code{sleep-event} event +@item (sleep-event @var{sleep-wake}) +This event is injected when the device Emacs is running on enters or +leaves the sleep state. A non-@code{nil} @var{sleep-wake} indicates +entering the sleep state. + +This is implemented only on GNU/Linux. + @cindex @code{language-change} event @item language-change This kind of event is generated on MS-Windows when the input language @@ -4029,6 +4037,30 @@ The keymap which defines how to handle special events---and which events are special---is in the variable @code{special-event-map} (@pxref{Controlling Active Maps}). +@defun insert-special-event +@cindex inserting special events +This function inserts a special event into the input event queue. Only +event types which are contained in the @code{special-event-map} keymap +are accepted. As a result, the handler specified in the keymap is +invoked. + +The function returns @code{nil}. Example: + +@example +(defun my-event-handler (event) + (interactive "e") + (message "Event arrived: %S" event)) +@result{} my-event-handler + +(keymap-set special-event-map "" #'my-event-handler) +@result{} my-event-handler + +(insert-special-event '(sleep-event t)) +@result{} nil +@result{} "Event arrived: (sleep-event t)" +@end example +@end defun + @node Waiting @section Waiting for Elapsed Time or Input @cindex waiting diff --git a/etc/NEWS b/etc/NEWS index ade635aa924..df1aff9213e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -486,9 +486,9 @@ Emacs exit. ** Message --- -*** In-Reply-To header contains only a message id. -The In-Reply-To header created when replying to a message now contains -only the originating message's id, conforming to RFC5322. The previous +*** "In-Reply-To" header contains only a message id. +The "In-Reply-To" header created when replying to a message now contains +only the originating message's id, conforming to RFC 5322. The previous behavior included additional information about the originating message. The new variable 'message-header-use-obsolete-in-reply-to', nil by default, can be set to a non-nil value to restore the previous behavior. @@ -993,7 +993,7 @@ instead. Since Python 2 EOL was over 5 years ago, this release removes Python 2-only builtins such as "file" from the default highlighting in 'python-mode' and 'python-ts-mode'. If you would like them highlighted, -customize the new user option `python-2-support' to a non-nil value and +customize the new user option 'python-2-support' to a non-nil value and restart Emacs. --- @@ -1354,6 +1354,17 @@ provide instructions for finding the definition. New convenience function 'find-function-update-type-alist' offers a concise way to update a symbol's 'find-function-type-alist' property. +** Special Events + ++++ +*** New primitive 'insert-special-event'. +This function inserts the special EVENT into the input event queue. + ++++ +*** New event type 'sleep-event'. +This event is sent when the device running Emacs enters or leaves the +sleep state. + * Changes in Emacs 31.1 on Non-Free Operating Systems diff --git a/src/keyboard.c b/src/keyboard.c index 2d8c45c05ee..ace5e1e3fef 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4273,6 +4273,7 @@ kbd_buffer_get_event (KBOARD **kbp, case CONFIG_CHANGED_EVENT: case FOCUS_OUT_EVENT: case SELECT_WINDOW_EVENT: + case SLEEP_EVENT: { obj = make_lispy_event (&event->ie); kbd_fetch_ptr = next_kbd_event (event); @@ -7110,6 +7111,9 @@ make_lispy_event (struct input_event *event) #endif #endif /* USE_FILE_NOTIFY */ + case SLEEP_EVENT: + return Fcons (Qsleep_event, event->arg); + case CONFIG_CHANGED_EVENT: return list3 (Qconfig_changed_event, event->arg, event->frame_or_window); @@ -11631,6 +11635,63 @@ If CHECK-TIMERS is non-nil, timers that are ready to run will do so. */) ? Qt : Qnil); } +DEFUN ("insert-special-event", Finsert_special_event, Sinsert_special_event, + 1, 1, 0, + doc: /* Insert the special EVENT into the input event queue. +Only 'input_event' slots KIND and ARG are set. */) + (Lisp_Object event) +{ + /* Check, that it is a special event. */ + CHECK_CONS (event); + if (NILP (access_keymap + (get_keymap (Vspecial_event_map, 0, 1), event, 0, 0, 1))) + signal_error ("Invalid event kind", XCAR (event)); + + /* Construct an input event. */ + struct input_event ie; + EVENT_INIT (ie); + ie.kind = + (EQ (XCAR (event), Qdelete_frame) ? DELETE_WINDOW_EVENT +#ifdef HAVE_NTGUI + : EQ (XCAR (event), Qend_session) ? END_SESSION_EVENT +#endif +#ifdef HAVE_NS + : EQ (XCAR (event), Qns_put_working_text) ? KEY_NS_PUT_WORKING_TEXT +#endif +#ifdef HAVE_NS + : EQ (XCAR (event), Qns_unput_working_text) ? KEY_NS_UNPUT_WORKING_TEXT +#endif + : EQ (XCAR (event), Qiconify_frame) ? ICONIFY_EVENT + : EQ (XCAR (event), Qmake_frame_visible) ? DEICONIFY_EVENT + // : EQ (XCAR (event), Qselect_window) ? SELECT_WINDOW_EVENT + : EQ (XCAR (event), Qsave_session) ? SAVE_SESSION_EVENT +#ifdef HAVE_DBUS + : EQ (XCAR (event), Qdbus_event) ? DBUS_EVENT +#endif +#ifdef THREADS_ENABLED + : EQ (XCAR (event), Qthread_event) ? THREAD_EVENT +#endif +#ifdef USE_FILE_NOTIFY + : EQ (XCAR (event), Qfile_notify) ? FILE_NOTIFY_EVENT +#endif /* USE_FILE_NOTIFY */ + : EQ (XCAR (event), Qconfig_changed_event) ? CONFIG_CHANGED_EVENT +#if defined (WINDOWSNT) + : EQ (XCAR (event), Qlanguage_change) ? LANGUAGE_CHANGE_EVENT +#endif + : EQ (XCAR (event), Qfocus_in) ? FOCUS_IN_EVENT + : EQ (XCAR (event), Qfocus_out) ? FOCUS_OUT_EVENT + : EQ (XCAR (event), Qmove_frame) ? MOVE_FRAME_EVENT + : EQ (XCAR (event), Qsleep_event) ? SLEEP_EVENT + : NO_EVENT); + ie.frame_or_window = Qnil; + ie.arg = CDR (event); + + /* Store it into the input event queue. */ + kbd_buffer_store_event (&ie); + + return (Qnil); +} + /* Reallocate recent_keys copying the recorded keystrokes in the right order. */ static void @@ -12803,6 +12864,7 @@ init_while_no_input_ignore_events (void) #ifdef THREADS_ENABLED events = Fcons (Qthread_event, events); #endif + events = Fcons (Qsleep_event, events); return events; } @@ -12826,6 +12888,7 @@ is_ignored_event (union buffered_input_event *event) #ifdef HAVE_DBUS case DBUS_EVENT: ignore_event = Qdbus_event; break; #endif + case SLEEP_EVENT: ignore_event = Qsleep_event; break; default: ignore_event = Qnil; break; } @@ -12931,6 +12994,7 @@ syms_of_keyboard (void) #endif /* USE_FILE_NOTIFY */ DEFSYM (Qtouch_end, "touch-end"); + DEFSYM (Qsleep_event, "sleep-event"); /* Menu and tool bar item parts. */ DEFSYM (QCenable, ":enable"); @@ -13144,6 +13208,7 @@ syms_of_keyboard (void) defsubr (&Srecursive_edit); defsubr (&Sinternal_track_mouse); defsubr (&Sinput_pending_p); + defsubr (&Sinsert_special_event); defsubr (&Slossage_size); defsubr (&Srecent_keys); defsubr (&Sthis_command_keys); @@ -14017,6 +14082,8 @@ keys_of_keyboard (void) "handle-focus-out"); initial_define_lispy_key (Vspecial_event_map, "move-frame", "handle-move-frame"); + initial_define_lispy_key (Vspecial_event_map, "sleep-event", + "ignore"); } /* Mark the pointers in the kboard objects. diff --git a/src/termhooks.h b/src/termhooks.h index 0795148f1af..a77ca25e159 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -291,6 +291,9 @@ enum event_kind , FILE_NOTIFY_EVENT #endif + /* Sleep/wake event. */ + , SLEEP_EVENT + /* Pre-edit text was changed. */ , PREEDIT_TEXT_EVENT commit 92aecdfd9fda59f3ea66c5709f0bc7af882a0c0d Author: Gerd Möllmann Date: Fri Feb 7 11:27:06 2025 +0100 ; Fix files-tests * test/lisp/files-tests.el (files-tests--with-buffer-offer-save): Override symbol function of read-key instead of read-event. diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el index e085d052e1c..5e2c4eb2669 100644 --- a/test/lisp/files-tests.el +++ b/test/lisp/files-tests.el @@ -1973,7 +1973,7 @@ FN-TEST is the function to test: either `save-some-buffers' or `save-some-buffers-default-predicate' let-bound to a value specified inside ARGS-RESULTS. -During the call to FN-TEST,`read-event' is overridden with a function that +During the call to FN-TEST,`read-key' is overridden with a function that just returns `n' and `kill-emacs' is overridden to do nothing. ARGS-RESULTS is a list of elements (FN-ARGS CALLERS-DIR EXPECTED), where @@ -2004,7 +2004,7 @@ CALLERS-DIR specifies the value to let-bind (setq nb-saved-buffers 0) (with-current-buffer (car buffers) (cl-letf - (((symbol-function 'read-event) + (((symbol-function 'read-key) ;; Increase counter and answer 'n' when prompted ;; to save a buffer. (lambda (&rest _) (cl-incf nb-saved-buffers) ?n))