From cb8c87a423a4897d873180a9e9be99e2ec20488d Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 7 Apr 2023 18:31:42 +0300 Subject: [PATCH 01/15] Allow active region when IM is used * lisp/international/quail.el (quail-minibuffer-message): Bind deactivate-mark to allow setting active region in the minibuffer when an input method is used. (Bug#62709) --- lisp/international/quail.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/international/quail.el b/lisp/international/quail.el index 2ffe3392335..317ea8495de 100644 --- a/lisp/international/quail.el +++ b/lisp/international/quail.el @@ -1995,7 +1995,8 @@ Remaining args are for FUNC." (defun quail-minibuffer-message (string) (message nil) (let ((point-max (point-max)) - (inhibit-quit t)) + (inhibit-quit t) + (deactivate-mark nil)) (save-excursion (goto-char point-max) (insert string)) From 88847dee125aa333b79829744eb4b16e8fd59ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Fri, 7 Apr 2023 19:33:12 +0100 Subject: [PATCH 02/15] Jsonrpc: don't bind inhibit-read-only to t so early Related to https://github.com/joaotavora/eglot/discussions/1202, where because of this very wide binding to inhibit-read-only to t, Eglot was managing to write into read-only buffers from the response handlers that ran from within the stack of the jsonrpc.el process filter. This is of course illegal and dangerous, but Eglot wasn't made aware because of the binding. * lisp/jsonrpc.el (jsonrpc--process-filter): Don't bind inhibit-read-only so early. --- lisp/jsonrpc.el | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lisp/jsonrpc.el b/lisp/jsonrpc.el index f583d116d20..3f9d4a7e818 100644 --- a/lisp/jsonrpc.el +++ b/lisp/jsonrpc.el @@ -566,15 +566,14 @@ With optional CLEANUP, kill any associated buffers." (cl-return-from jsonrpc--process-filter)) (when (buffer-live-p (process-buffer proc)) (with-current-buffer (process-buffer proc) - (let* ((inhibit-read-only t) - (jsonrpc--in-process-filter t) + (let* ((jsonrpc--in-process-filter t) (connection (process-get proc 'jsonrpc-connection)) (expected-bytes (jsonrpc--expected-bytes connection))) ;; Insert the text, advancing the process marker. ;; (save-excursion (goto-char (process-mark proc)) - (insert string) + (let ((inhibit-read-only t)) (insert string)) (set-marker (process-mark proc) (point))) ;; Loop (more than one message might have arrived) ;; @@ -623,7 +622,8 @@ With optional CLEANUP, kill any associated buffers." (jsonrpc-connection-receive connection json-message))))) (goto-char message-end) - (delete-region (point-min) (point)) + (let ((inhibit-read-only t)) + (delete-region (point-min) (point))) (setq expected-bytes nil)))) (t ;; Message is still incomplete From 588017927061cd95bcf2192f88917292913a7f11 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Apr 2023 10:41:53 +0300 Subject: [PATCH 03/15] ; Minor addition to the Emacs FAQ * doc/misc/efaq.texi (Fullscreen mode on MS-Windows): Tell how to avoid the initial screen changing size on display without using the Registry. Suggested by David Hedlund . --- doc/misc/efaq.texi | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi index 4a8c863230f..0a0c375d273 100644 --- a/doc/misc/efaq.texi +++ b/doc/misc/efaq.texi @@ -3133,13 +3133,23 @@ example, you can put the following in your init file: To avoid the slightly distracting visual effect of Emacs starting with its default frame size and then growing to fullscreen, you can add an -@samp{Emacs.Geometry} entry to the Windows registry settings. -@xref{X Resources,,, emacs, The GNU Emacs Manual}. - -To compute the correct values for width and height, first maximize the -Emacs frame and then evaluate @code{(frame-height)} and +@samp{Emacs.Geometry} entry to the Windows Registry settings. @xref{X +Resources,,, emacs, The GNU Emacs Manual}. To compute the correct +values for width and height you use in the Registry settings, first +maximize the Emacs frame and then evaluate @code{(frame-height)} and @code{(frame-width)} with @kbd{M-:}. +Alternatively, you can avoid the visual effect of Emacs changing its +frame size entirely in your init file (i.e., without using the +Registry), like this: + +@lisp +(setq frame-resize-pixelwise t) +(set-frame-position nil 0 0) +(set-frame-size nil (display-pixel-width) (display-pixel-height) t) +@end lisp + + @node Emacs in a Linux console @section How can I alleviate the limitations of the Linux console? @cindex Console, Linux console, TTY, fbterm From ce63462dbda5b197d1f8564b735277692b8491ef Mon Sep 17 00:00:00 2001 From: garid3000 Date: Tue, 4 Apr 2023 17:27:47 +0900 Subject: [PATCH 04/15] Add cyrillic-mongolian input method * lisp/leim/quail/cyrillic.el (cyrillic-mongolian): New input method. (Bug#56617) --- lisp/leim/quail/cyrillic.el | 119 ++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/lisp/leim/quail/cyrillic.el b/lisp/leim/quail/cyrillic.el index ba0b9c9ca12..9e8df41e80c 100644 --- a/lisp/leim/quail/cyrillic.el +++ b/lisp/leim/quail/cyrillic.el @@ -1844,6 +1844,125 @@ Doubling the postfix separates the letter and postfix ("E**" ["У*"]) ("e**" ["у*"])) + +;; Mongolian layout: Mongolian alphabet has 2 letters: Ө Ү, +;; and the layout is quite different than other cyrillic layouts. +;; written by Garid Z. +(quail-define-package + "cyrillic-mongolian" "Mongolian" "MN-" t + "Input method for cyrillic Mongolian" + nil t nil nil nil nil nil nil nil nil t) + +;; № - " ₮ : . _ , % ? е щ +;; Ф Ц У Ж Э Н Г Ш Ү З К Ъ +;; Й Ы Б Ө А Х Р О Л Д П +;; Я Ч Ё С М И Т Ь В Ю + + +(quail-define-rules + ;; (lowercase 1st row) + ("q" ?ф) + ("w" ?ц) + ("e" ?у) + ("r" ?ж) + ("t" ?э) + ("y" ?н) + ("u" ?г) + ("i" ?ш) + ("o" ?ү) + ("p" ?з) + ("[" ?к) + ("]" ?ъ) + ;; (lowercase 2nd row) + ("a" ?й) + ("s" ?ы) + ("d" ?б) + ("f" ?ө) + ("g" ?а) + ("h" ?х) + ("j" ?р) + ("k" ?о) + ("l" ?л) + (";" ?д) + ("'" ?п) + ;; (lowercase 3rd row) + ("z" ?я) + ("x" ?ч) + ("c" ?ё) + ("v" ?с) + ("b" ?м) + ("n" ?и) + ("m" ?т) + ("," ?ь) + ("." ?в) + ("/" ?ю) + + + ;; (uppercase 1st row) + ("Q" ?Ф) + ("W" ?Ц) + ("E" ?У) + ("R" ?Ж) + ("T" ?Э) + ("Y" ?Н) + ("U" ?Г) + ("I" ?Ш) + ("O" ?Ү) + ("P" ?З) + ("{" ?К) + ("}" ?Ъ) + ;; (uppercase 2nd row) + ("A" ?Й) + ("S" ?Ы) + ("D" ?Б) + ("F" ?Ө) + ("G" ?А) + ("H" ?Х) + ("J" ?Р) + ("K" ?О) + ("L" ?Л) + (":" ?Д) + ("\"" ?П) + ;; (uppercase 3rd row) + ("Z" ?Я) + ("X" ?Ч) + ("C" ?Ё) + ("V" ?С) + ("B" ?М) + ("N" ?И) + ("M" ?Т) + ("<" ?Ь) + (">" ?В) + ("?" ?Ю) + + + ;; (number row without shift) + ("1" ?№) + ("2" ?-) + ("3" ?\") + ("4" ?₮) + ("5" ?:) + ("6" ?.) + ("7" ?_) + ("8" ?,) + ("9" ?%) + ("0" ??) + ("-" ?е) + ("=" ?щ) + ;; (number row with shift) + ("!" ?1) + ("@" ?2) + ("#" ?3) + ("$" ?4) + ("%" ?5) + ("^" ?6) + ("&" ?7) + ("*" ?8) + ("(" ?9) + (")" ?0) + ("_" ?Е) + ("+" ?Щ)) + ;; Local Variables: ;; coding: utf-8 ;; End: From ca1a0fda98a886d97306c7fd4b352ed358fddbce Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Apr 2023 10:52:35 +0300 Subject: [PATCH 05/15] ; Fix last change. --- lisp/leim/quail/cyrillic.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/leim/quail/cyrillic.el b/lisp/leim/quail/cyrillic.el index 9e8df41e80c..d0874124fc7 100644 --- a/lisp/leim/quail/cyrillic.el +++ b/lisp/leim/quail/cyrillic.el @@ -1846,8 +1846,8 @@ Doubling the postfix separates the letter and postfix ;; Mongolian layout: Mongolian alphabet has 2 letters: Ө Ү, -;; and the layout is quite different than other cyrillic layouts. -;; written by Garid Z. +;; and the layout is quite different from other cyrillic layouts. +;; Written by Garid Zorigoo. (quail-define-package "cyrillic-mongolian" "Mongolian" "MN-" t "Input method for cyrillic Mongolian" From 5be79fd05a51a42d591833019775cb743aa5055f Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Apr 2023 10:55:26 +0300 Subject: [PATCH 06/15] ; * etc/NEWS: Announce 'cyrillic-mongolian' IM. --- etc/NEWS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/etc/NEWS b/etc/NEWS index dc4eb64a63a..d0ae723587d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1577,6 +1577,11 @@ This input method is based on the russian-computer input method, and is intended for typing in the Chuvash language written in the Cyrillic script. +--- +*** New input method 'cyrillic-mongolian'. +This input method is for typing in the Mongolian language using the +Cyrillic script. + * Changes in Specialized Modes and Packages in Emacs 29.1 From 6a2863ca0167a1b4a431dfae3640c97a846d4826 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Apr 2023 12:43:34 +0300 Subject: [PATCH 07/15] Fix handling of sliced images * lisp/image.el (image-slice-map): New keymap, without some bindings that make no sense with sliced images. (insert-image, insert-sliced-image): Use it. (insert-sliced-image): Make the 'keymap' property rear-nonsticky, to prevent calling image commands when point is to the right of the slice. (Bug#62679) * lisp/image/image-crop.el (image-cut, image-crop): Doc fixes. (image-crop): Don't try using stock MS-Widows convert.exe program. Use 'image--get-image' to support sliced images. --- lisp/image.el | 21 +++++++++++-- lisp/image/image-crop.el | 65 ++++++++++++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 19 deletions(-) diff --git a/lisp/image.el b/lisp/image.el index 3f878bd4de0..818679a4d7b 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -188,6 +188,19 @@ or \"ffmpeg\") is installed." "C-" #'image-mouse-increase-size "C-" #'image-mouse-increase-size) +(defvar-keymap image-slice-map + :doc "Map put into text properties on sliced images." + "i" (define-keymap + "-" #'image-decrease-size + "+" #'image-increase-size + "o" #'image-save + "c" #'image-crop + "x" #'image-cut) + "C-" #'image-mouse-decrease-size + "C-" #'image-mouse-decrease-size + "C-" #'image-mouse-increase-size + "C-" #'image-mouse-increase-size) + (defun image-load-path-for-library (library image &optional path no-error) "Return a suitable search path for images used by LIBRARY. @@ -665,7 +678,9 @@ is non-nil, this is inhibited." image) rear-nonsticky t inhibit-isearch ,inhibit-isearch - keymap ,image-map)))) + keymap ,(if slice + image-slice-map + image-map))))) ;;;###autoload @@ -701,8 +716,8 @@ The image is automatically split into ROWS x COLS slices." (insert string) (add-text-properties start (point) `(display ,(list (list 'slice x y dx dy) image) - rear-nonsticky (display) - keymap ,image-map)) + rear-nonsticky (display keymap) + keymap ,image-slice-map)) (setq x (+ x dx)))) (setq x 0.0 y (+ y dy)) diff --git a/lisp/image/image-crop.el b/lisp/image/image-crop.el index be6e22bc606..9ef848c5bc8 100644 --- a/lisp/image/image-crop.el +++ b/lisp/image/image-crop.el @@ -35,6 +35,7 @@ (declare-function image-property "image.el" (image property)) (declare-function image-size "image.c" (spec &optional pixels frame)) (declare-function imagep "image.c" (spec)) +(declare-function image--get-image "image.el" (&optional position)) (defgroup image-crop () "Image cropping." @@ -113,18 +114,14 @@ and the cropped image data.") (defun image-cut (&optional color) "Cut a rectangle from the image under point, filling it with COLOR. COLOR defaults to the value of `image-cut-color'. -Interactively, with prefix argument, prompt for COLOR to use." - (interactive (list (and current-prefix-arg (read-color "Use color: ")))) - (image-crop (if (zerop (length color)) image-cut-color color))) +Interactively, with prefix argument, prompt for COLOR to use. -;;;###autoload -(defun image-crop (&optional cut) - "Crop the image under point. -If CUT is non-nil, remove a rectangle from the image instead of -cropping the image. In that case CUT should be the name of a -color to fill the rectangle. +This command presents the image with a rectangular area superimposed +on it, and allows moving and resizing the area to define which +part of it to cut. -While cropping the image, the following key bindings are available: +While moving/resizing the cutting area, the following key bindings +are available: `q': Exit without changing anything. `RET': Crop/cut the image. @@ -132,15 +129,51 @@ While cropping the image, the following key bindings are available: rectangle shape. `s': Same as `m', but make the rectangle into a square first. -After cropping an image, you can save it by `M-x image-save' or +After cutting the image, you can save it by `M-x image-save' or \\\\[image-save] when point is over the image." + (interactive (list (and current-prefix-arg + (read-color "Color to use for filling: ")))) + (image-crop (if (zerop (length color)) image-cut-color color))) + +;;;###autoload +(defun image-crop (&optional cut) + "Crop the image under point. +This command presents the image with a rectangular area superimposed +on it, and allows moving and resizing the area to define which +part of it to crop. + +While moving/resizing the cropping area, the following key bindings +are available: + +`q': Exit without changing anything. +`RET': Crop/cut the image. +`m': Make mouse movements move the rectangle instead of altering the + rectangle shape. +`s': Same as `m', but make the rectangle into a square first. + +After cropping the image, you can save it by `M-x image-save' or +\\\\[image-save] when point is over the image. + +When called from Lisp, if CUT is non-nil, remove a rectangle from +the image instead of cropping the image. In that case, CUT should +be the name of a color to fill the rectangle." (interactive) (unless (image-type-available-p 'svg) - (error "SVG support is needed to crop images")) - (unless (executable-find (car image-crop-crop-command)) - (error "Couldn't find %s command to crop the image" - (car image-crop-crop-command))) - (let ((image (get-text-property (point) 'display))) + (error "SVG support is needed to crop and cut images")) + (let* ((crop-cmd (car image-crop-crop-command)) + (found (executable-find crop-cmd))) + (unless found + (error "Couldn't find `%s' command to crop/cut the image" crop-cmd)) + (if (and (memq system-type '(windows-nt ms-dos)) + ;; MS-Windows has an incompatible convert.exe, used to + ;; convert filesystems... + (string-equal crop-cmd "convert") + (= 0 (string-search "Invalid drive specification." + (shell-command-to-string + (format "%s %s" crop-cmd null-device))))) + (error "The program `%s' is not an image conversion program" + found))) + (let ((image (image--get-image))) (unless (imagep image) (user-error "No image under point")) (when (overlays-at (point)) From 96714c106b7a3f86ca4c78052178a62d351f1751 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Apr 2023 14:33:06 +0300 Subject: [PATCH 08/15] Improve documentation of image-related commands * lisp/image.el (image-map): Make it inherit from 'image-slice-map' instead of repeating the bindings. * doc/emacs/files.texi (Image Mode): Document the key bindings set by 'insert-image'. Add indexing. * doc/lispref/display.texi (Showing Images): Make the description of user commands more concise. Add index entries and cross-reference to the Emacs manual. * etc/NEWS: Rearrange entries relevant to image commands. --- doc/emacs/files.texi | 93 ++++++++++++++++++++++++++++++++++++++++ doc/lispref/display.texi | 30 +++++++------ etc/NEWS | 32 +++++++------- lisp/image.el | 24 ++++------- 4 files changed, 135 insertions(+), 44 deletions(-) diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index c0e702da947..29cc22e7557 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -2281,10 +2281,15 @@ behavior by using the options @code{image-auto-resize} and @code{image-auto-resize-on-window-resize}. @findex image-transform-fit-to-window +@kindex s w (Image mode) @findex image-transform-set-percent +@kindex s p (Image mode) @findex image-transform-set-scale +@kindex s s (Image mode) @findex image-transform-reset-to-initial +@kindex s 0 (Image mode) @findex image-transform-reset-to-original +@kindex s o (Image mode) To resize the image manually you can use the command @code{image-transform-fit-to-window} bound to @kbd{s w} that fits the image to both the window height and width. To scale the image to a @@ -2345,6 +2350,94 @@ frames at once. You can go to a specific frame with @kbd{F} (@code{image-reverse-speed}) reverses it. The command @kbd{a 0} (@code{image-reset-speed}) resets the speed to the original value. +In addition to the above key bindings, which are specific to Image +mode, images shown in any Emacs buffer have special key bindings when +point is at or inside the image: + +@table @kbd +@cindex resize images +@cindex image resize +@findex image-increase-size +@kindex i + (Image mode) +@item i + +Increase the image size (@code{image-increase-size}) by 20%. Prefix +numeric argument controls the increment; the value of @var{n} means to +multiply the size by the factor of @w{@code{1 + @var{n} / 10}}, so +@w{@kbd{C-u 5 i +}} means to increase the size by 50%. + +@findex image-decrease-size +@kindex i - (Image mode) +@item i - +Decrease the image size (@code{image-increase-size}) by 20%. Prefix +numeric argument controls the decrement; the value of @var{n} means to +multiply the size by the factor of @w{@code{1 - @var{n} / 10}}, so +@w{@kbd{C-u 3 i -}} means to decrease the size by 30%. + +@cindex rotating images +@cindex image rotation +@findex image-rotate +@kindex i r (Image mode) +@item i r +Rotate the image by 90 degrees clockwise (@code{image-rotate}). +With the prefix argument, rotate by 90 degrees counter-clockwise instead. +Note that this command is not available for sliced images. + +@findex image-flip-horizontally +@kindex i h (Image mode) +@item i h +Flip the image horizontally (@code{image-flip-horizontally}). This +presents the image as if reflected in a vertical mirror. +Note that this command is not available for sliced images. + +@findex image-flip-vertically +@kindex i v (Image mode) +@item i v +Flip the image vertically (@code{image-flip-vertically}). This +presents the image as if reflected in a horizontal mirror. +Note that this command is not available for sliced images. + +@findex image-save +@kindex i o (Image mode) +@item i o +Save the image to a file (@code{image-save}). This command prompts +you for the name of the file to save the image. + +@cindex cropping images +@vindex image-crop-crop-command +@findex image-crop +@kindex i c (Image mode) +@item i c +Crop the image (@code{image-crop}). This command is available only if +your system has an external program installed that can be used for +cropping and cutting of images; the user option +@code{image-crop-crop-command} determines what program to use, and +defaults to the ImageMagick's @command{convert} program. The command +displays the image with a rectangular frame superimposed on it, and +lets you use the mouse to move and resize the frame. Type @kbd{m} to +cause mouse movements to move the frame instead of resizing it; type +@kbd{s} to move a square frame instead. When you are satisfied with +the position and size of the cropping frame, type @kbd{@key{RET}} to +actually crop the part under the frame; or type @kbd{q} to exit +without cropping. You can then save the cropped image using @w{@kbd{i +o}} or @w{@kbd{M-x image-save}}. + +@findex image-cut +@kindex i x (Image mode) +@vindex image-cut-color +@vindex image-crop-cut-command +@item i x +Cut a rectangle from the image (@code{image-cut}). This works the +same as @code{image-crop} (and also requires an external program, +defined by the variable @code{image-crop-cut-command}, to perform the +image cut), but instead of cropping the image, it removes the part +inside the frame and fills that part with the color specified by +@code{image-cut-color}. With prefix argument, the command prompts for +the color to use. +@end table + +The size and rotation commands are ``repeating'', which means that you +can continue adjusting the image without using the @kbd{i} prefix. + @cindex ImageMagick support @vindex imagemagick-enabled-types @vindex imagemagick-types-inhibit diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 85fac4b30a6..8184021d998 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -6876,7 +6876,7 @@ This function puts image @var{image} in front of @var{pos} in the current buffer. The argument @var{pos} should be an integer or a marker. It specifies the buffer position where the image should appear. The argument @var{string} specifies the text that should hold the image -as an alternative to the default. +as an alternative to the default @samp{x}. The argument @var{image} must be an image descriptor, perhaps returned by @code{create-image} or stored by @code{defimage}. @@ -6889,7 +6889,7 @@ buffer's text. Internally, this function creates an overlay, and gives it a @code{before-string} property containing text that has a @code{display} -property whose value is the image. (Whew!) +property whose value is the image. (Whew! that was a mouthful@dots{}) @end defun @defun remove-images start end &optional buffer @@ -6936,41 +6936,47 @@ This function returns @code{t} if point is on an image, and @code{nil} otherwise. @end defun +@cindex operations on images Images inserted with the insertion functions above also get a local keymap installed in the text properties (or overlays) that span the displayed image. This keymap defines the following commands: @table @kbd +@findex image-increase-size @item i + -Increase the image size (@code{image-increase-size}). A prefix value -of @samp{4} means to increase the size by 40%. The default is 20%. +Increase the image size (@code{image-increase-size}) +@findex image-decrease-size @item i - -Decrease the image size (@code{image-increase-size}). A prefix value -of @samp{4} means to decrease the size by 40%. The default is 20%. +Decrease the image size (@code{image-decrease-size}). +@findex image-rotate @item i r -Rotate the image by 90 degrees clockwise (@code{image-rotate}). -A prefix means to rotate by 90 degrees counter-clockwise instead. +Rotate the image (@code{image-rotate}). +@findex image-flip-horizontally @item i h Flip the image horizontally (@code{image-flip-horizontally}). +@findex image-flip-vertically @item i v Flip the image vertically (@code{image-flip-vertically}). +@findex image-save @item i o Save the image to a file (@code{image-save}). +@findex image-crop @item i c -Crop the image interactively (@code{image-crop}). +Interactively crop the image (@code{image-crop}). +@findex image-cut @item i x -Cut a rectangle from the image interactively (@code{image-cut}). +Interactively cut a rectangle from the image (@code{image-cut}). @end table -The size and rotation commands are ``repeating'', which means that you -can continue adjusting the image without using the @kbd{i} prefix. +@xref{Image Mode,,, emacs, The GNU Emacs Manual}, for more details +about these image-specific key bindings. @node Multi-Frame Images @subsection Multi-Frame Images diff --git a/etc/NEWS b/etc/NEWS index d0ae723587d..84dbb94a71a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -222,9 +222,9 @@ In previous Emacs versions, images have had the '+', '-' and 'r' keys bound when point is over an image. In Emacs 29.1, additional commands were added, and this made it more likely that users would trigger the image commands by mistake. To avoid this, all image commands have -moved to the 'i' keymap, so '+' is now 'i +', '-' is now 'i -', and -'r' is now 'i r'. In addition, these commands are now repeating, so -you can rotate an image twice by saying 'i r r', for instance. +moved to the 'i' prefix keymap, so '+' is now 'i +', '-' is now 'i -', +and 'r' is now 'i r'. In addition, these commands are now repeating, +so, for example, you can rotate an image twice by typing 'i r r'. +++ ** Emacs now picks the correct coding-system for X input methods. @@ -2628,11 +2628,6 @@ This controls whether or not to show a message when opening certain image formats saying how to edit it as text. The default is to show this message for SVG and XPM. -+++ -*** New commands: 'image-flip-horizontally' and 'image-flip-vertically'. -These commands horizontally and vertically flip the image under point, -and are bound to 'i h' and 'i v', respectively. - +++ *** New command 'image-transform-set-percent'. It allows setting the image size to a percentage of its original size, @@ -2648,6 +2643,19 @@ The old name was confusing, and is now an obsolete function alias. ** Images ++++ +** New commands 'image-crop' and 'image-cut'. +These commands allow interactively cropping/cutting the image at +point. The commands are bound to keys 'i c' and 'i x' (respectively) +in the local keymap over images. They rely on external programs, by +default "convert" from ImageMagick, to do the actual cropping/eliding +of the image file. + ++++ +*** New commands: 'image-flip-horizontally' and 'image-flip-vertically'. +These commands horizontally and vertically flip the image under point, +and are bound to 'i h' and 'i v', respectively. + +++ *** Users can now add special image conversion functions. This is done via 'image-converter-add-handler'. @@ -3243,14 +3251,6 @@ macro, which allows you to isolate package configuration in your init file in a way that is declarative, tidy, and performance-oriented. See the new Info manual "(use-package) Top" for more. -+++ -** New commands 'image-crop' and 'image-cut'. -These commands allow interactively cropping/cutting the image at -point. The commands are bound to keys 'i c' and 'i x' (respectively) -in the local keymap over images. They rely on external programs, by -default "convert" from ImageMagick, to do the actual cropping/eliding -of the image file. - --- ** New package 'wallpaper'. This package provides the command 'wallpaper-set', which sets the diff --git a/lisp/image.el b/lisp/image.el index 818679a4d7b..6a8293fedf3 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -172,22 +172,6 @@ or \"ffmpeg\") is installed." (define-error 'unknown-image-type "Unknown image type") -(defvar-keymap image-map - :doc "Map put into text properties on images." - "i" (define-keymap - "-" #'image-decrease-size - "+" #'image-increase-size - "r" #'image-rotate - "o" #'image-save - "c" #'image-crop - "x" #'image-cut - "h" #'image-flip-horizontally - "v" #'image-flip-vertically) - "C-" #'image-mouse-decrease-size - "C-" #'image-mouse-decrease-size - "C-" #'image-mouse-increase-size - "C-" #'image-mouse-increase-size) - (defvar-keymap image-slice-map :doc "Map put into text properties on sliced images." "i" (define-keymap @@ -201,6 +185,14 @@ or \"ffmpeg\") is installed." "C-" #'image-mouse-increase-size "C-" #'image-mouse-increase-size) +(defvar-keymap image-map + :doc "Map put into text properties on images." + :parent image-slice-map + "i" (define-keymap + "r" #'image-rotate + "h" #'image-flip-horizontally + "v" #'image-flip-vertically)) + (defun image-load-path-for-library (library image &optional path no-error) "Return a suitable search path for images used by LIBRARY. From b36c21e27dc6fa96c7c09b0e3a8fe9dcbdcea78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=ADn?= Date: Sun, 2 Apr 2023 22:39:44 +0200 Subject: [PATCH 09/15] Change cursor color on NS port when it matches the face background * src/macfont.m (CG_SET_FILL_COLOR_WITH_FRAME_CURSOR): New macro. (CG_SET_FILL_COLOR_WITH_FRAME_BACKGROUND): New macro. (macfont_draw): When the cursor's color matches the face background, set the fill color of the cursor to the face foreground. * src/nsterm.m (ns_maybe_dumpglyphs_background): When dumping the background of a glyph string, apply the logic mentioned above. (Bug#62573) --- src/macfont.m | 50 +++++++++++++++++++++++++++++++++++--------------- src/nsterm.m | 20 ++++++++++++-------- 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/macfont.m b/src/macfont.m index d0cdbcd08c7..9f9f6f4efaf 100644 --- a/src/macfont.m +++ b/src/macfont.m @@ -632,21 +632,35 @@ get_cgcolor_from_nscolor (NSColor *nsColor, struct frame *f) #define CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND(context, face) \ do { \ - CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face)); \ - CGContextSetFillColorWithColor (context, refcol_) ; \ - CGColorRelease (refcol_); \ + CGColorRef refcol = get_cgcolor (NS_FACE_FOREGROUND (face)); \ + CGContextSetFillColorWithColor (context, refcol); \ + CGColorRelease (refcol); \ } while (0) #define CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND(context, face) \ do { \ - CGColorRef refcol_ = get_cgcolor (NS_FACE_BACKGROUND (face)); \ - CGContextSetFillColorWithColor (context, refcol_); \ - CGColorRelease (refcol_); \ + CGColorRef refcol = get_cgcolor (NS_FACE_BACKGROUND (face)); \ + CGContextSetFillColorWithColor (context, refcol); \ + CGColorRelease (refcol); \ + } while (0) +#define CG_SET_FILL_COLOR_WITH_FRAME_CURSOR(context, frame) \ + do { \ + CGColorRef refcol \ + = get_cgcolor_from_nscolor (FRAME_CURSOR_COLOR (frame), frame); \ + CGContextSetFillColorWithColor (context, refcol); \ + CGColorRelease (refcol); \ + } while (0) +#define CG_SET_FILL_COLOR_WITH_FRAME_BACKGROUND(context, frame) \ + do { \ + CGColorRef refcol \ + = get_cgcolor_from_nscolor (FRAME_BACKGROUND_COLOR (frame), frame); \ + CGContextSetFillColorWithColor (context, refcol); \ + CGColorRelease (refcol); \ } while (0) #define CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND(context, face) \ do { \ - CGColorRef refcol_ = get_cgcolor (NS_FACE_FOREGROUND (face)); \ - CGContextSetStrokeColorWithColor (context, refcol_); \ - CGColorRelease (refcol_); \ + CGColorRef refcol = get_cgcolor (NS_FACE_FOREGROUND (face)); \ + CGContextSetStrokeColorWithColor (context, refcol); \ + CGColorRelease (refcol); \ } while (0) @@ -2933,9 +2947,12 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y, { if (s->hl == DRAW_CURSOR) { - CGColorRef colorref = get_cgcolor_from_nscolor (FRAME_CURSOR_COLOR (f), f); - CGContextSetFillColorWithColor (context, colorref); - CGColorRelease (colorref); + if (face && (NS_FACE_BACKGROUND (face) + == [(NSColor *) FRAME_CURSOR_COLOR (f) + unsignedLong])) + CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face); + else + CG_SET_FILL_COLOR_WITH_FRAME_CURSOR (context, f); } else CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face); @@ -2949,9 +2966,12 @@ macfont_draw (struct glyph_string *s, int from, int to, int x, int y, CGContextScaleCTM (context, 1, -1); if (s->hl == DRAW_CURSOR) { - CGColorRef colorref = get_cgcolor_from_nscolor (FRAME_BACKGROUND_COLOR (f), f); - CGContextSetFillColorWithColor (context, colorref); - CGColorRelease (colorref); + if (face && (NS_FACE_BACKGROUND (face) + == [(NSColor *) FRAME_CURSOR_COLOR (f) + unsignedLong])) + CG_SET_FILL_COLOR_WITH_FACE_BACKGROUND (context, face); + else + CG_SET_FILL_COLOR_WITH_FRAME_BACKGROUND (context, f); } else CG_SET_FILL_COLOR_WITH_FACE_FOREGROUND (context, face); diff --git a/src/nsterm.m b/src/nsterm.m index c9f955000ac..37462cf49e2 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -3750,14 +3750,18 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p) { struct face *face = s->face; if (!face->stipple) - { - if (s->hl != DRAW_CURSOR) - [(NS_FACE_BACKGROUND (face) != 0 - ? [NSColor colorWithUnsignedLong:NS_FACE_BACKGROUND (face)] - : FRAME_BACKGROUND_COLOR (s->f)) set]; - else - [FRAME_CURSOR_COLOR (s->f) set]; - } + { + if (s->hl != DRAW_CURSOR) + [(NS_FACE_BACKGROUND (face) != 0 + ? [NSColor colorWithUnsignedLong:NS_FACE_BACKGROUND (face)] + : FRAME_BACKGROUND_COLOR (s->f)) set]; + else if (face && (NS_FACE_BACKGROUND (face) + == [(NSColor *) FRAME_CURSOR_COLOR (s->f) + unsignedLong])) + [[NSColor colorWithUnsignedLong:NS_FACE_FOREGROUND (face)] set]; + else + [FRAME_CURSOR_COLOR (s->f) set]; + } else { struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f); From b63a9eda01c692d1c6dae8ef6563678f8ddd7faf Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Apr 2023 15:36:44 +0300 Subject: [PATCH 10/15] Fix "C-h k" and "C-h c" with Paste from Kill Menu * lisp/subr.el (event-basic-type, event-modifiers): Return nil if EVENT is a string. (Bug#62626) --- lisp/subr.el | 74 +++++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/lisp/subr.el b/lisp/subr.el index 2e31929e548..46dcd97d829 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -1520,31 +1520,32 @@ EVENT may be an event or an event type. If EVENT is a symbol that has never been used in an event that has been read as input in the current Emacs session, then this function may fail to include the `click' modifier." - (let ((type event)) - (if (listp type) - (setq type (car type))) - (if (symbolp type) - ;; Don't read event-symbol-elements directly since we're not - ;; sure the symbol has already been parsed. - (cdr (internal-event-symbol-parse-modifiers type)) - (let ((list nil) - (char (logand type (lognot (logior ?\M-\0 ?\C-\0 ?\S-\0 - ?\H-\0 ?\s-\0 ?\A-\0))))) - (if (not (zerop (logand type ?\M-\0))) - (push 'meta list)) - (if (or (not (zerop (logand type ?\C-\0))) - (< char 32)) - (push 'control list)) - (if (or (not (zerop (logand type ?\S-\0))) - (/= char (downcase char))) - (push 'shift list)) - (or (zerop (logand type ?\H-\0)) - (push 'hyper list)) - (or (zerop (logand type ?\s-\0)) - (push 'super list)) - (or (zerop (logand type ?\A-\0)) - (push 'alt list)) - list)))) + (unless (stringp event) + (let ((type event)) + (if (listp type) + (setq type (car type))) + (if (symbolp type) + ;; Don't read event-symbol-elements directly since we're not + ;; sure the symbol has already been parsed. + (cdr (internal-event-symbol-parse-modifiers type)) + (let ((list nil) + (char (logand type (lognot (logior ?\M-\0 ?\C-\0 ?\S-\0 + ?\H-\0 ?\s-\0 ?\A-\0))))) + (if (not (zerop (logand type ?\M-\0))) + (push 'meta list)) + (if (or (not (zerop (logand type ?\C-\0))) + (< char 32)) + (push 'control list)) + (if (or (not (zerop (logand type ?\S-\0))) + (/= char (downcase char))) + (push 'shift list)) + (or (zerop (logand type ?\H-\0)) + (push 'hyper list)) + (or (zerop (logand type ?\s-\0)) + (push 'super list)) + (or (zerop (logand type ?\A-\0)) + (push 'alt list)) + list))))) (defun event-basic-type (event) "Return the basic type of the given event (all modifiers removed). @@ -1552,17 +1553,18 @@ The value is a printing character (not upper case) or a symbol. EVENT may be an event or an event type. If EVENT is a symbol that has never been used in an event that has been read as input in the current Emacs session, then this function may return nil." - (if (consp event) - (setq event (car event))) - (if (symbolp event) - (car (get event 'event-symbol-elements)) - (let* ((base (logand event (1- ?\A-\0))) - (uncontrolled (if (< base 32) (logior base 64) base))) - ;; There are some numbers that are invalid characters and - ;; cause `downcase' to get an error. - (condition-case () - (downcase uncontrolled) - (error uncontrolled))))) + (unless (stringp event) + (if (consp event) + (setq event (car event))) + (if (symbolp event) + (car (get event 'event-symbol-elements)) + (let* ((base (logand event (1- ?\A-\0))) + (uncontrolled (if (< base 32) (logior base 64) base))) + ;; There are some numbers that are invalid characters and + ;; cause `downcase' to get an error. + (condition-case () + (downcase uncontrolled) + (error uncontrolled)))))) (defsubst mouse-movement-p (object) "Return non-nil if OBJECT is a mouse movement event." From 14d1c00e806cbd864acc6b4a6f84a4453954b898 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Apr 2023 16:00:29 +0300 Subject: [PATCH 11/15] Allow reindentation of images inserted by 'mm-inline-image' * lisp/gnus/mm-view.el (mm-inline-image): Use "x" as text on which to put the image 'display' property, so that indentation commands don't destroy the image inadvertently. (Bug#62637) --- lisp/gnus/mm-view.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/gnus/mm-view.el b/lisp/gnus/mm-view.el index 8dfb0deb418..2c407353559 100644 --- a/lisp/gnus/mm-view.el +++ b/lisp/gnus/mm-view.el @@ -98,7 +98,7 @@ This is only used if `mm-inline-large-images' is set to (truncate (* mm-inline-large-images-proportion (- (nth 3 edges) (nth 1 edges))))))) image)) - " ") + "x") (insert "\n") (mm-handle-set-undisplayer handle From 08cda286c3f5ccf4a898516204884bd7daaae971 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Apr 2023 18:36:23 +0300 Subject: [PATCH 12/15] Improve the documentation of the XDS support * doc/lispref/frames.texi (Drag and Drop): Rephrase and rearrange the documentation of XDS support. Add indexing. Document 'x-dnd-save-direct' and 'x-dnd-save-direct-immediately'. Original patch from Po Lu . * lisp/x-dnd.el (x-dnd-types-alist, x-dnd-test-function) (x-dnd-default-test-function, x-dnd-direct-save-function): Doc fixes. (x-dnd-save-direct, x-dnd-save-direct-immediately): Rename the second argument to FILENAME. Doc fix. --- doc/lispref/frames.texi | 88 ++++++++++++++++++++++-------- lisp/x-dnd.el | 116 +++++++++++++++++++++++----------------- 2 files changed, 131 insertions(+), 73 deletions(-) diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 7cae94d2627..c78ab1c34ba 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -4112,7 +4112,7 @@ has the same meaning as the @var{action} argument to Emacs implements receiving text and URLs individually for each window system, and does not by default support receiving other kinds of data as drops. To support receiving other kinds of data, use the -X-specific interface described below: +X-specific interface described below. @vindex x-dnd-test-function @vindex x-dnd-known-types @@ -4141,29 +4141,71 @@ depending on the specific drag-and-drop protocol being used. For example, the data type used for plain text may be either @code{"STRING"} or @code{"text/plain"}. +@cindex XDS +@cindex direct save protocol @vindex x-dnd-direct-save-function -@c FIXME: This description is overly-complicated and confusing. In -@c particular, the two calls to the function basically sound -@c identical, so it is unclear how should the function distinguish -@c between the first and the second one. The description of who asks -@c whom to do what is also very hard to understand. Needs rewording, -@c and needs shorter sentences. Perhaps examples could help. - However, @code{x-dnd-types-alist} does not handle a special kind of -drop sent by a program that wants Emacs to tell it where to save a -file in a specific location determined by the user. These drops are -instead handled by a function that is the value of the variable -@code{x-dnd-direct-save-function}. This function should accept two arguments. -If the first argument is non-@code{nil}, then the second argument is a -file name to save (with leading directories) that the other -program recommends, and the -function should return the full file name under which it should be -saved. After the function completes, Emacs will ask the other program -to save the file under the name that was returned, and if the file was -successfully saved, call the function again with the first argument -set to a non-@code{nil} value and the second argument set to the file -name that was returned. The function should then perform whatever -action is appropriate (i.e., opening the file or refreshing a -directory listing.) + When Emacs runs on X window system, it supports the X Direct Save +(@acronym{XDS}) protocol, which allows users to save a file by +dragging and dropping it onto an Emacs window, such as a Dired window. +To comply with the unique requirements of @acronym{XDS}, these +drag-and-drop requests are processed specially: instead of being +handled according to @code{x-dnd-types-alist}, they are handled by the +@dfn{direct-save function} that is the value of the variable +@code{x-dnd-direct-save-function}. The value should be a function of +two arguments, @var{need-name} and @var{filename}. The @acronym{XDS} +protocol uses a two-step procedure for dragging files: + +@enumerate 1 +@item +The application from which the file is dragged asks Emacs to provide +the full file name under which to save the file. For this purpose, +the direct-save function is called with its first argument +@var{need-name} non-@code{nil}, and the second argument @var{filename} +set to the basename of the file to be saved. It should return the +fully-expanded absolute file name under which to save the file. For +example, if a file is dragged to a Dired window, the natural directory +for the file is the directory of the file shown at location of the +drop. If saving the file is not possible for some reason, the +function should return @code{nil}, which will cancel the drag-and-drop +operation. + +@item +The application from which the file is dragged saves the file under +the name returned by the first call to the direct-save function. If +it succeeds in saving the file, the direct-save function is called +again, this time with the first argument @var{need-name} set to +@code{nil} and the second argument @var{filename} set to the full +absolute name of the saved file. The function is then expected to do +whatever is needed given the fact that file was saved. For example, +Dired should update the directory on display by showing the new file +there. +@end enumerate + +The default value of @code{x-dnd-direct-save-function} is +@code{x-dnd-save-direct}. + +@defun x-dnd-save-direct need-name filename +When called with the @var{need-name} argument non-@code{nil}, this +function prompts the user for the absolute file name under which it +should be saved. If the specified file already exists, it +additionally asks the user whether to overwrite it, and returns the +absolute file name only if the user confirms the overwriting. + +When called with the @var{need-name} argument @code{nil}, it reverts +the Dired listing if the current buffer is in Dired mode or one of its +descendants, and otherwise visits the file by calling @code{find-file} +(@pxref{Visiting Functions}). +@end defun + +@defun x-dnd-save-direct-immediately need-name filename +This function works like @code{x-dnd-save-direct}, but when called +with its @var{need-name} argument non-@code{nil}, it doesn't prompt +the user for the full name of the file to be saved; instead, it +returns its argument @var{filename} expanded against the current +buffer's default directory (@pxref{File Name Expansion}). (It still +asks for confirmation if a file by that name already exists in the +default directory.) +@end defun @cindex initiating drag-and-drop On capable window systems, Emacs also supports dragging contents diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index b213b155249..9286a1858cf 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -34,20 +34,20 @@ ;;; Customizable variables (defcustom x-dnd-test-function #'x-dnd-default-test-function - "The function drag and drop uses to determine if to accept or reject a drop. -The function takes three arguments, WINDOW, ACTION and TYPES. -WINDOW is where the mouse is when the function is called. WINDOW -may be a frame if the mouse isn't over a real window (i.e. menu -bar, tool bar or scroll bar). ACTION is the suggested action -from the drag and drop source, one of the symbols move, copy, -link or ask. TYPES is a vector of available types for the drop. - -Each element of TYPE should either be a string (containing the + "Function to be used by drag-and-drop to determine whether to accept a drop. +The function takes three arguments: WINDOW, ACTION, and TYPES. +WINDOW is where the window under the mouse is when the function is called. +WINDOW may be a frame if the mouse isn't over a real window (e.g., menu +bar, tool bar, scroll bar, etc.). +ACTION is the suggested action from the drag and drop source, one of the +symbols `move', `copy', `link' or `ask'. +TYPES is a vector of available types for the drop. +Each element of TYPES should either be a string (containing the name of the type's X atom), or a symbol, whose name will be used. The function shall return nil to reject the drop or a cons with -two values, the wanted action as car and the wanted type as cdr. -The wanted action can be copy, move, link, ask or private. +two values, the wanted action as `car' and the wanted type as `cdr'. +The wanted action can be `copy', `move', `link', `ask' or `private'. The default value for this variable is `x-dnd-default-test-function'." :version "22.1" @@ -70,14 +70,18 @@ The default value for this variable is `x-dnd-default-test-function'." (,(purecopy "DndTypeFile") . x-dnd-handle-offix-file) (,(purecopy "DndTypeFiles") . x-dnd-handle-offix-files) (,(purecopy "DndTypeText") . dnd-insert-text)) - "Which function to call to handle a drop of that type. -If the type for the drop is not present, or the function is nil, -the drop is rejected. The function takes three arguments, WINDOW, ACTION -and DATA. WINDOW is where the drop occurred, ACTION is the action for -this drop (copy, move, link, private or ask) as determined by a previous -call to `x-dnd-test-function'. DATA is the drop data. -The function shall return the action used (copy, move, link or private) -if drop is successful, nil if not." + "Functions to call to handle drag-and-drop of known types. +If the type of the drop is not present in the alist, or the +function corresponding to the type is nil, the drop of that +type will be rejected. + +Each function takes three arguments: WINDOW, ACTION, and DATA. +WINDOW is the window where the drop occurred. +ACTION is the action for this drop (`copy', `move', `link', `private' +or `ask'), as determined by a previous call to `x-dnd-test-function'. +DATA is the drop data. +The function shall return the action it used (one of the above, +excluding `ask') if drop is successful, nil if not." :version "22.1" :type 'alist :group 'x) @@ -122,22 +126,27 @@ like xterm) for text." :group 'x) (defcustom x-dnd-direct-save-function #'x-dnd-save-direct - "Function called when a file is dropped that Emacs must save. -It is called with two arguments: the first is either nil or t, -and the second is a string. + "Function called when a file is dropped via XDS protocol. +The value should be a function of two arguments that supports +the X Direct Save (XDS) protocol. The function will be called +twice during the protocol execution. -If the first argument is t, the second argument is the name the -dropped file should be saved under. The function should return a -complete file name describing where the file should be saved. +When the function is called with the first argument non-nil, +it should return an absolute file name whose base name is +the value of the second argument, a string. The return value +is the file name for the dragged file to be saved. The function +can also return nil if saving the file should be refused for some +reason; in that case the drop will be canceled. -It can also return nil, which means to cancel the drop. - -If the first argument is nil, the second is the name of the file -that was dropped." +When the function is called with the first argument nil, the +second argument specifies the file name where the file was saved; +the function should then do whatever is appropriate when such a +file is saved, like show the file in the Dired buffer or visit +the file." :version "29.1" - :type '(choice (const :tag "Prompt for name before saving" + :type '(choice (const :tag "Prompt for file name to save" x-dnd-save-direct) - (const :tag "Save and open immediately without prompting" + (const :tag "Save in `default-directory' without prompting" x-dnd-save-direct-immediately) (function :tag "Other function")) :group 'x) @@ -222,14 +231,14 @@ any protocol specific data.") (cdr (x-dnd-get-state-cons-for-frame frame-or-window))) (defun x-dnd-default-test-function (_window _action types) - "The default test function for drag and drop. + "The default test function for drag-and-drop. WINDOW is where the mouse is when this function is called. It may be a frame if the mouse is over the menu bar, scroll bar or tool bar. ACTION is the suggested action from the source, and TYPES are the types the drop data can have. This function only accepts drops with types in `x-dnd-known-types'. It always returns the action `private', unless `types' contains a value -inside `x-dnd-copy-types'." +inside `x-dnd-copy-types', in which case it may return `copy'." (let ((type (x-dnd-choose-type types))) (when type (let ((list x-dnd-copy-types)) (catch 'out @@ -1564,17 +1573,24 @@ was taken, or the direct save failed." (when (not (equal file-name original-file-name)) (delete-file file-name))))) -(defun x-dnd-save-direct (need-name name) - "Handle dropping a file that should be saved immediately. -NEED-NAME tells whether or not the file was not yet saved. NAME -is either the name of the file, or the name the drop source wants -us to save under. +(defun x-dnd-save-direct (need-name filename) + "Handle dropping a file FILENAME that should be saved first, asking the user. +NEED-NAME non-nil means the caller requests the full absolute +file name of FILENAME under which to save it; FILENAME is just +the base name in that case. The function then prompts the user +for where to save to file and returns the result to the caller. -Prompt the user for a file name, then open it." +NEED-NAME nil means the file was saved as FILENAME (which should +be the full absolute file name in that case). The function then +refreshes the Dired display, if the current buffer is in Dired +mode, or visits the file otherwise. + +This function is intended to be the value of `x-dnd-direct-save-function', +which see." (if need-name (let ((file-name (read-file-name "Write file: " default-directory - nil nil name))) + nil nil filename))) (when (file-exists-p file-name) (unless (y-or-n-p (format-message "File `%s' exists; overwrite? " file-name)) @@ -1584,18 +1600,18 @@ Prompt the user for a file name, then open it." ;; interface can be found. (if (derived-mode-p 'dired-mode) (revert-buffer) - (find-file name)))) + (find-file filename)))) -(defun x-dnd-save-direct-immediately (need-name name) - "Save and open a dropped file, like `x-dnd-save-direct'. -NEED-NAME tells whether or not the file was not yet saved. NAME -is either the name of the file, or the name the drop source wants -us to save under. +(defun x-dnd-save-direct-immediately (need-name filename) + "Handle dropping a file FILENAME that should be saved first. +Like `x-dnd-save-direct', but do not prompt for the file name; +instead, return its absolute file name for saving in the current +directory. -Unlike `x-dnd-save-direct', do not prompt for the name by which -to save the file. Simply save it in the current directory." +This function is intended to be the value of `x-dnd-direct-save-function', +which see." (if need-name - (let ((file-name (expand-file-name name))) + (let ((file-name (expand-file-name filename))) (when (file-exists-p file-name) (unless (y-or-n-p (format-message "File `%s' exists; overwrite? " file-name)) @@ -1605,7 +1621,7 @@ to save the file. Simply save it in the current directory." ;; interface can be found. (if (derived-mode-p 'dired-mode) (revert-buffer) - (find-file name)))) + (find-file filename)))) (defun x-dnd-handle-octet-stream-for-drop (save-to) "Save the contents of the XDS selection to SAVE-TO. From 74ddfe811f980122816ba831bea18ca18afedb85 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Apr 2023 19:14:15 +0300 Subject: [PATCH 13/15] ; * doc/misc/calc.texi (Rewrites Tutorial): Fix a typo (bug#62658). --- doc/misc/calc.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/misc/calc.texi b/doc/misc/calc.texi index ac6604473a8..4b62eee56e2 100644 --- a/doc/misc/calc.texi +++ b/doc/misc/calc.texi @@ -5394,7 +5394,7 @@ a variable containing a vector of rules. 1: [merge, secsqr] 1: [a/x + b/x := (a + b)/x, ... ] . . - ' [merge,sinsqr] @key{RET} = + ' [merge,secsqr] @key{RET} = @end group @end smallexample From 11126c6d30aa17c3e672706ed3956f89214aa80f Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Apr 2023 20:10:49 +0300 Subject: [PATCH 14/15] Fix 'C-h k' for "Paste from Kill Menu" in context menus * lisp/mouse.el (context-menu-region): Make the entries be symbols, not just integers, to prevent "C-h c" from interpreting them as character keys. (Bug#62626) --- lisp/mouse.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/mouse.el b/lisp/mouse.el index d93594deb04..60542e47448 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -524,7 +524,8 @@ Some context functions add menu items below the separator." (i 0)) (dolist (item (reverse yank-menu)) (when (consp item) - (define-key submenu (vector (setq i (1+ i))) + (define-key submenu + (vector (intern (format "kill-%d" (setq i (1+ i))))) `(menu-item ,(cadr item) ,(lambda () (interactive) (mouse-yank-from-menu click (car item))))))) From 5ef7ff05736b9d1b4d806cfe04ec5d99c090e748 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 9 Apr 2023 07:50:01 -0400 Subject: [PATCH 15/15] ; Start a new ChangeLog.4 file. --- ChangeLog.4 | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 ChangeLog.4 diff --git a/ChangeLog.4 b/ChangeLog.4 new file mode 100644 index 00000000000..0792df934ff --- /dev/null +++ b/ChangeLog.4 @@ -0,0 +1,38 @@ +2022-04-04 Eli Zaretskii + + * Version 28.1 released. + +2022-04-03 Eli Zaretskii + + Bump Emacs version to 28.1 + + * README: + * configure.ac: + * nt/README.W32: + * msdos/sed2v2.inp: Bump Emacs version to 28.1 + +This file records repository revisions from +commit f2ae39829812098d8269eafbc0fcb98959ee5bb7 (exclusive) to +commit de7901abbc21114721057c907cc52455e228f826 (inclusive). +See ChangeLog.3 for earlier changes. + +;; Local Variables: +;; coding: utf-8 +;; End: + + Copyright (C) 2022 Free Software Foundation, Inc. + + This file is part of GNU Emacs. + + GNU Emacs is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + GNU Emacs is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Emacs. If not, see .