diff options
-rwxr-xr-x | build-aux/gitlog-to-emacslog | 2 | ||||
-rw-r--r-- | doc/emacs/display.texi | 1 | ||||
-rw-r--r-- | doc/emacs/emacs.texi | 1 | ||||
-rw-r--r-- | doc/emacs/windows.texi | 86 | ||||
-rw-r--r-- | etc/NEWS | 19 | ||||
-rw-r--r-- | lisp/calendar/todo-mode.el | 25 | ||||
-rw-r--r-- | lisp/comint.el | 7 | ||||
-rw-r--r-- | lisp/dired.el | 15 | ||||
-rw-r--r-- | lisp/emacs-lisp/map.el | 36 | ||||
-rw-r--r-- | lisp/midnight.el | 8 | ||||
-rw-r--r-- | lisp/minibuffer.el | 2 | ||||
-rw-r--r-- | lisp/net/tramp-sh.el | 1 | ||||
-rw-r--r-- | lisp/progmodes/compile.el | 8 | ||||
-rw-r--r-- | lisp/progmodes/idlw-toolbar.el | 4 | ||||
-rw-r--r-- | lisp/replace.el | 17 | ||||
-rw-r--r-- | lisp/startup.el | 10 | ||||
-rw-r--r-- | lisp/term.el | 7 | ||||
-rw-r--r-- | lisp/xt-mouse.el | 129 | ||||
-rw-r--r-- | src/alloc.c | 2 | ||||
-rw-r--r-- | src/font.c | 2 | ||||
-rw-r--r-- | src/frame.c | 2 | ||||
-rw-r--r-- | src/ftfont.c | 7 | ||||
-rw-r--r-- | src/gtkutil.c | 100 | ||||
-rw-r--r-- | src/keyboard.c | 8 | ||||
-rw-r--r-- | src/term.c | 7 | ||||
-rw-r--r-- | src/w32font.c | 3 | ||||
-rw-r--r-- | src/xdisp.c | 7 | ||||
-rw-r--r-- | src/xwidget.c | 4 | ||||
-rw-r--r-- | test/automated/xt-mouse-tests.el | 110 | ||||
-rw-r--r-- | test/lisp/emacs-lisp/map-tests.el | 9 |
30 files changed, 463 insertions, 176 deletions
diff --git a/build-aux/gitlog-to-emacslog b/build-aux/gitlog-to-emacslog index bcc47b1b28d..5c187f5eae0 100755 --- a/build-aux/gitlog-to-emacslog +++ b/build-aux/gitlog-to-emacslog @@ -77,7 +77,7 @@ test -d .git || { # Maybe we should skip all "Merge branch 'master'" messages. # See eg the cairo-related ones. ./build-aux/gitlog-to-changelog \ - --ignore-matching="^; |^Merge branch '(master|emacs-[0-9][0-9])' of git\.(savannah|sv)\.gnu\.org:/srv/git/emacs$|^Merge remote-tracking branch '.*'$" \ + --ignore-matching="^; |^Merge branch '[^']*' of git\.(savannah|sv)\.gnu\.org:/srv/git/emacs|^Merge remote-tracking branch '.*'$" \ --ignore-line='^; ' --format='%B' \ "$gen_origin..$new_origin" >"ChangeLog.tmp" || exit diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index c8987c279c5..01f899f1c09 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -1601,7 +1601,6 @@ screen lines. Setting the variable @code{truncate-lines} in any way makes it local to the current buffer; until that time, the default value, which is normally @code{nil}, is in effect. -@vindex truncate-partial-width-windows If a split window becomes too narrow, Emacs may automatically enable line truncation. @xref{Split Window}, for the variable @code{truncate-partial-width-windows} which controls this. diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi index dc99d493241..c23c96f0745 100644 --- a/doc/emacs/emacs.texi +++ b/doc/emacs/emacs.texi @@ -519,6 +519,7 @@ Multiple Windows * Pop Up Window:: Finding a file or buffer in another window. * Change Window:: Deleting windows and changing their sizes. * Displaying Buffers:: How Emacs picks a window for displaying a buffer. +* Temporary Displays:: Displaying non-editable buffers. * Window Convenience:: Convenience functions for window handling. Displaying a Buffer in a Window diff --git a/doc/emacs/windows.texi b/doc/emacs/windows.texi index f99234b5c1b..702963f75c5 100644 --- a/doc/emacs/windows.texi +++ b/doc/emacs/windows.texi @@ -117,10 +117,14 @@ variable @code{truncate-lines} (@pxref{Line Truncation}); it is instead controlled by the variable @code{truncate-partial-width-windows}. If the value of this variable is a positive integer (the default is 50), that specifies the minimum -width for a partial-width window before automatic line truncation -occurs; if the value is @code{nil}, automatic line truncation is -disabled; and for any other non-@code{nil} value, Emacs truncates -lines in every partial-width window regardless of its width. +total width for a partial-width window before automatic line +truncation occurs; if the value is @code{nil}, automatic line +truncation is disabled; and for any other non-@code{nil} value, Emacs +truncates lines in every partial-width window regardless of its width. +The total width of a window is in column units as reported by +@code{window-total-width} (@pxref{Window Sizes,,, elisp, The Emacs +Lisp Reference Manual}), it includes the fringes, the continuation and +truncation glyphs, the margins, and the scroll bar. On text terminals, side-by-side windows are separated by a vertical divider which is drawn using the @code{vertical-border} face. @@ -206,7 +210,7 @@ Choice}, for how Emacs picks or creates the window to use. Select buffer @var{bufname} in another window (@code{switch-to-buffer-other-window}). -@findex display-buffer +@findex display-buffer @r{(command)} @item C-x 4 C-o @var{bufname} @key{RET} @kindex C-x 4 C-o Display buffer @var{bufname} in some window, without trying to select @@ -345,7 +349,6 @@ user's attention will be diverted to that buffer. These commands usually work by calling @code{switch-to-buffer} internally (@pxref{Select Buffer}). -@findex display-buffer Some commands try to display intelligently, trying not to take over the selected window, e.g., by splitting off a new window and displaying the desired buffer there. Such commands, which include the @@ -374,11 +377,12 @@ Several of these commands are bound in the @kbd{C-x 5} prefix key. @menu * Window Choice:: How @code{display-buffer} works. +* Temporary Displays:: Displaying non-editable buffers. @end menu @node Window Choice @subsection How @code{display-buffer} works -@findex display-buffer +@findex display-buffer, detailed description The @code{display-buffer} command (as well as commands that call it internally) chooses a window to display by following the steps given @@ -411,15 +415,15 @@ By default, this step is skipped. To enable it, change the variable @code{graphic-only} means to do this only on graphical displays. @item -Otherwise, try to create a new window by splitting the selected -window, and display the buffer in that new window. +Otherwise, try to create a new window by splitting a window on the +selected frame, and display the buffer in that new window. @vindex split-height-threshold @vindex split-width-threshold The split can be either vertical or horizontal, depending on the variables @code{split-height-threshold} and @code{split-width-threshold}. These variables should have integer -values. If @code{split-height-threshold} is smaller than the selected +values. If @code{split-height-threshold} is smaller than the chosen window's height, the split puts the new window below. Otherwise, if @code{split-width-threshold} is smaller than the window's width, the split puts the new window on the right. If neither condition holds, @@ -427,6 +431,12 @@ Emacs tries to split so that the new window is below---but only if the window was not split before (to avoid excessive splitting). @item +Otherwise, display the buffer in a window previously showing it. +Normally, only windows on the selected frame are considered, but if +@code{pop-up-frames} is non-@code{nil} the window may be also on another +frame. + +@item Otherwise, display the buffer in an existing window on the selected frame. @@ -435,6 +445,62 @@ If all the above methods fail for whatever reason, create a new frame and display the buffer there. @end itemize +A more advanced and flexible way to customize the behavior of +@code{display-buffer} is by using the option @code{display-buffer-alist} +mentioned in the next section. + + +@node Temporary Displays +@subsection Displaying non-editable buffers. +@cindex pop-up windows +@cindex temporary windows + +Some buffers are shown in windows for perusal rather than for editing. +Help commands (@pxref{Help}) typically use a buffer called @file{*Help*} +for that purpose, minibuffer completion (@pxref{Completion}) uses a +buffer called @file{*Completions*} instead. Such buffers are usually +displayed only for a short period of time. + + Normally, Emacs chooses the window for such temporary displays via +@code{display-buffer} as described above. The @file{*Completions*} +buffer, on the other hand, is normally displayed in a window at the +bottom of the selected frame, regardless of the number of windows +already shown on that frame. + + If you prefer Emacs to display a temporary buffer in a different +fashion, we recommend to customize the variable +@code{display-buffer-alist} (@pxref{Choosing Window,,Choosing a Window +for Display, elisp, The Emacs Lisp Reference Manual}). For example, +to display @file{*Completions*} by splitting a window as described in +the previous section, use the following form in your initialization +file (@pxref{Init File}): + +@example +@group +(customize-set-variable + 'display-buffer-alist + '(("\\*Completions\\*" display-buffer-pop-up-window))) +@end group +@end example + +@findex temp-buffer-resize-mode + The @file{*Completions*} buffer is also special in the sense that +Emacs usually tries to make its window just as large as necessary to +display all of its contents. To resize windows showing other +temporary displays like, for example, the @file{*Help*} buffer +accordingly, turn on the minor mode (@pxref{Minor Modes}) +@code{temp-buffer-resize-mode} (@pxref{Temporary Displays,,Temporary +Displays, elisp, The Emacs Lisp Reference Manual}). + +@vindex temp-buffer-max-height +@vindex temp-buffer-max-width + The maximum size of windows resized by @code{temp-buffer-resize-mode} +can be controlled by customizing the options +@code{temp-buffer-max-height} and @code{temp-buffer-max-width} +(@pxref{Temporary Displays,,Temporary Displays, elisp, The Emacs Lisp +Reference Manual}) and cannot exceed the size of the containing frame. + + @node Window Convenience @section Convenience Features for Window Handling @@ -321,6 +321,12 @@ command line when 'initial-buffer-choice' is non-nil. ** The value of 'initial-scratch-message' is now treated as a doc string and can contain escape sequences for command keys, quotes, and the like. +--- +** The default height of GUI frames was enlarged. +This is so there's enough space in the initial window to display the +optional text about recovering crashes sessions, without losing the +splash image display. + * Changes in Emacs 25.1 @@ -1695,7 +1701,8 @@ symbol-function was changed not to signal 'void-function' any more. *** As a consequence, the second arg of 'indirect-function' is now obsolete. +++ -** Comint, term, and compile do not set the EMACS env var any more. +** Although comint, term, and compile still set the EMACS variable, +this is now considered deprecated and will be removed in a future release. Use the INSIDE_EMACS environment variable instead. ** 'C-up', 'C-down', 'C-left' and 'C-right' are now defined in term @@ -2240,6 +2247,16 @@ frames. 'window-divider-default-places', 'window-divider-default-bottom-width' and 'window-divider-default-right-width'. ++++ +*** The window displaying the '*Completions*' buffer with minibuffer +completion candidates is now shown at the bottom of the selected +frame. The size of that window is always as large as required to +display all the candidates, except when limited by the minimum size +of the other windows on that frame; those other windows are resized +to provide space for the '*Completions*' display. The Emacs manual +describes how to customize 'display-buffer-alist' to get back the old +behavior, see the node "Temporary Displays" there. + --- ** Tearoff menus and detachable toolbars for Gtk+ have been removed. Those features have been deprecated in Gtk+ for a long time. diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el index 94cd08eaa4e..9574c03043e 100644 --- a/lisp/calendar/todo-mode.el +++ b/lisp/calendar/todo-mode.el @@ -1414,7 +1414,12 @@ the archive of the file moved to, creating it if it does not exist." (setq todo-files (funcall todo-files-function)) (todo-reevaluate-filelist-defcustoms)) (dolist (buf buffers) + ;; Make sure archive file is in Todo Archive mode so that + ;; todo-categories has correct value. (with-current-buffer (find-file-noselect buf) + (when (equal (file-name-extension (buffer-file-name)) "toda") + (unless (derived-mode-p 'todo-archive-mode) + (todo-archive-mode))) (widen) (goto-char (point-max)) (let* ((beg (re-search-backward @@ -1466,10 +1471,18 @@ the archive of the file moved to, creating it if it does not exist." (re-search-backward (concat "^" (regexp-quote todo-category-beg) "\\(" (regexp-quote cat) "\\)$") nil t) - (replace-match new nil nil nil 1))) - (setq todo-categories - (append todo-categories (list (cons (or new cat) counts)))) - (todo-update-categories-sexp) + (replace-match new nil nil nil 1)) + (setq todo-categories + (append todo-categories (list (cons (or new cat) counts)))) + (goto-char (point-min)) + (if (looking-at "((\"") + ;; Delete existing sexp. + (delete-region (line-beginning-position) (line-end-position)) + ;; Otherwise, file is new, so make space for categories sexp. + (insert "\n") + (goto-char (point-min))) + ;; Insert (new or updated) sexp. + (prin1 todo-categories (current-buffer))) ;; If archive was just created, save it to avoid "File ;; <xyz> no longer exists!" message on invoking ;; `todo-view-archived-items'. @@ -1500,9 +1513,7 @@ the archive of the file moved to, creating it if it does not exist." (setq todo-category-number 1)) (todo-category-select))))) (set-window-buffer (selected-window) - (set-buffer (find-file-noselect nfile))) - (todo-category-number (or new cat)) - (todo-category-select)))) + (set-buffer (find-file-noselect nfile)))))) (defun todo-merge-category (&optional file) "Merge current category into another existing category. diff --git a/lisp/comint.el b/lisp/comint.el index dcd4a5ae4cf..cb79c175f0e 100644 --- a/lisp/comint.el +++ b/lisp/comint.el @@ -816,6 +816,13 @@ series of processes in the same Comint buffer. The hook (format "COLUMNS=%d" (window-width))) (list "TERM=emacs" (format "TERMCAP=emacs:co#%d:tc=unknown:" (window-width)))) + + ;; This hack is for backward compatibility with Bash 4.3 and + ;; earlier. It can break common uses of 'configure', so + ;; remove it once Bash 4.4 or later is common. + (unless (getenv "EMACS") + (list "EMACS=t")) + (list (format "INSIDE_EMACS=%s,comint" emacs-version)) process-environment)) (default-directory diff --git a/lisp/dired.el b/lisp/dired.el index 6c7445c3486..2a65bd09cc5 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -2740,9 +2740,18 @@ instead of `dired-actual-switches'." (save-excursion (goto-char (point-min)) (dired-goto-file-1 file file (point-max))) - ;; Otherwise, look for it as a relative name. The - ;; hair is to get the result of `dired-goto-subdir' - ;; without calling it if we don't have any subdirs. + ;; Next, look for it as a relative name with leading + ;; subdirectories. (This happens in Dired buffers + ;; created by find-dired, for example.) + (save-excursion + (goto-char (point-min)) + (dired-goto-file-1 (file-relative-name file + default-directory) + file (point-max))) + ;; Otherwise, look for it as a relative name, a base + ;; name only. The hair is to get the result of + ;; `dired-goto-subdir' without calling it if we don't + ;; have any subdirs. (save-excursion (when (if (string= dir (expand-file-name default-directory)) (goto-char (point-min)) diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el index ec8d3d79d9f..ba15a65f5e1 100644 --- a/lisp/emacs-lisp/map.el +++ b/lisp/emacs-lisp/map.el @@ -123,33 +123,26 @@ MAP can be a list, hash-table or array." default))) (defmacro map-put (map key value) - "Associate KEY with VALUE in MAP and return MAP. + "Associate KEY with VALUE in MAP and return VALUE. If KEY is already present in MAP, replace the associated value with VALUE. MAP can be a list, hash-table or array." - (macroexp-let2 nil map map - `(progn - (setf (map-elt ,map ,key) ,value) - ,map))) + `(setf (map-elt ,map ,key) ,value)) -(defmacro map-delete (map key) +(defun map-delete (map key) "Delete KEY from MAP and return MAP. No error is signaled if KEY is not a key of MAP. If MAP is an array, store nil at the index KEY. MAP can be a list, hash-table or array." - (declare (debug t)) - (gv-letplace (mgetter msetter) `(gv-delay-error ,map) - (macroexp-let2 nil key key - `(if (not (listp ,mgetter)) - (map--delete ,mgetter ,key) - ;; The alist case is special, since it can't be handled by the - ;; map--delete function. - (setf (alist-get ,key (gv-synthetic-place ,mgetter ,msetter) - nil t) - nil) - ,mgetter)))) + (map--dispatch map + :list (setf (alist-get key map nil t) nil) + :hash-table (remhash key map) + :array (and (>= key 0) + (<= key (seq-length map)) + (aset map key nil))) + map) (defun map-nested-elt (map keys &optional default) "Traverse MAP using KEYS and return the looked up value or DEFAULT if nil. @@ -337,15 +330,6 @@ MAP can be a list, hash-table or array." (cdr pair))) map)) -(defun map--delete (map key) - (map--dispatch map - :list (error "No place to remove the mapping for %S" key) - :hash-table (remhash key map) - :array (and (>= key 0) - (<= key (seq-length map)) - (aset map key nil))) - map) - (defun map--apply-hash-table (function map) "Private function used to apply FUNCTION over MAP, MAP being a hash-table." (let (result) diff --git a/lisp/midnight.el b/lisp/midnight.el index 0e68eb923cd..878c5a7f71f 100644 --- a/lisp/midnight.el +++ b/lisp/midnight.el @@ -53,8 +53,12 @@ the time when it is run.") "Non-nil means run `midnight-hook' at midnight." :global t :initialize #'custom-initialize-default - (if midnight-mode (timer-activate midnight-timer) - (cancel-timer midnight-timer))) + ;; Disable first, since the ':initialize' function above already + ;; starts the timer when the mode is turned on for the first time, + ;; via setting 'midnight-delay', which calls 'midnight-delay-set', + ;; which starts the timer. + (when (timerp midnight-timer) (cancel-timer midnight-timer)) + (if midnight-mode (timer-activate midnight-timer))) ;;; time conversion diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index ecac0aeb135..6540059b965 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -1835,7 +1835,7 @@ variables.") 'display-buffer-below-selected)) ,(if temp-buffer-resize-mode '(window-height . resize-temp-buffer-window) - '(window-height . shrink-window-if-larger-than-buffer)) + '(window-height . fit-window-to-buffer)) ,(when temp-buffer-resize-mode '(preserve-size . (nil . t)))) nil diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 402e1cc3332..7260107d0f7 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -542,6 +542,7 @@ as given in your `~/.profile'." (defcustom tramp-remote-process-environment `("TMOUT=0" "LC_CTYPE=''" ,(format "TERM=%s" tramp-terminal-type) + "EMACS=t" ;; Deprecated; remove this line once Bash 4.4-or-later is common. ,(format "INSIDE_EMACS='%s,tramp:%s'" emacs-version tramp-version) "CDPATH=" "HISTORY=" "MAIL=" "MAILCHECK=" "MAILPATH=" "PAGER=cat" "autocorrect=" "correct=") diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index b7ab408f744..0b15a283090 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -1702,6 +1702,14 @@ Returns the compilation buffer created." (list "TERM=emacs" (format "TERMCAP=emacs:co#%d:tc=unknown:" (window-width)))) + + ;; Set the EMACS variable, but + ;; don't override users' setting of $EMACS. + ;; Remove this hack once Bash 4.4-or-later is common, + ;; since it can break 'configure'. + (unless (getenv "EMACS") + (list "EMACS=t")) + (list (format "INSIDE_EMACS=%s,compile" emacs-version)) (copy-sequence process-environment)))) (set (make-local-variable 'compilation-arguments) diff --git a/lisp/progmodes/idlw-toolbar.el b/lisp/progmodes/idlw-toolbar.el index 0e0714e27ed..d857bfd88c3 100644 --- a/lisp/progmodes/idlw-toolbar.el +++ b/lisp/progmodes/idlw-toolbar.el @@ -439,7 +439,7 @@ static char * file[] = { \" \", \" \", \" \"};") - "The Cont icon.") + "The Cont icon.") (defvar idlwave-toolbar-to-here-icon (idlwave-toolbar-make-button @@ -918,7 +918,7 @@ static char * file[] = { (help (aref x 3)) (key (vector 'tool-bar func)) (def (list 'menu-item - "a" + "" func :image (symbol-value icon) :visible show diff --git a/lisp/replace.el b/lisp/replace.el index a2ce78a8bb2..2c6a23ae618 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -293,7 +293,8 @@ As each match is found, the user must type a character saying what to do with it. For directions, type \\[help-command] at that time. In Transient Mark mode, if the mark is active, operate on the contents -of the region. Otherwise, operate from point to the end of the buffer. +of the region. Otherwise, operate from point to the end of the buffer's +accessible portion. Use \\<minibuffer-local-map>\\[next-history-element] \ to pull the last incremental search string to the minibuffer @@ -355,7 +356,8 @@ As each match is found, the user must type a character saying what to do with it. For directions, type \\[help-command] at that time. In Transient Mark mode, if the mark is active, operate on the contents -of the region. Otherwise, operate from point to the end of the buffer. +of the region. Otherwise, operate from point to the end of the buffer's +accessible portion. Use \\<minibuffer-local-map>\\[next-history-element] \ to pull the last incremental search regexp to the minibuffer @@ -452,7 +454,8 @@ Use `\\#&' or `\\#N' if you want a number instead of a string. In interactive use, `\\#' in itself stands for `replace-count'. In Transient Mark mode, if the mark is active, operate on the contents -of the region. Otherwise, operate from point to the end of the buffer. +of the region. Otherwise, operate from point to the end of the buffer's +accessible portion. Use \\<minibuffer-local-map>\\[next-history-element] \ to pull the last incremental search regexp to the minibuffer @@ -507,7 +510,8 @@ each successive replacement uses the next successive replacement string, wrapping around from the last such string to the first. In Transient Mark mode, if the mark is active, operate on the contents -of the region. Otherwise, operate from point to the end of the buffer. +of the region. Otherwise, operate from point to the end of the buffer's +accessible portion. Non-interactively, TO-STRINGS may be a list of replacement strings. @@ -573,7 +577,7 @@ replace backward. Operates on the region between START and END (if both are nil, from point to the end of the buffer). Interactively, if Transient Mark mode is enabled and the mark is active, operates on the contents of the region; -otherwise from point to the end of the buffer. +otherwise from point to the end of the buffer's accessible portion. Use \\<minibuffer-local-map>\\[next-history-element] \ to pull the last incremental search string to the minibuffer @@ -620,7 +624,8 @@ regexp in `search-whitespace-regexp'. This function is not affected by `replace-character-fold' In Transient Mark mode, if the mark is active, operate on the contents -of the region. Otherwise, operate from point to the end of the buffer. +of the region. Otherwise, operate from point to the end of the buffer's +accessible portion. Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace only matches surrounded by word boundaries. A negative prefix arg means diff --git a/lisp/startup.el b/lisp/startup.el index 15a79f6f5bf..536289c3891 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -1890,10 +1890,12 @@ we put it on this frame." (when frame (let* ((img (create-image (fancy-splash-image-file))) (image-height (and img (cdr (image-size img nil frame)))) - ;; We test frame-height so that, if the frame is split - ;; by displaying a warning, that doesn't cause the normal - ;; splash screen to be used. - (frame-height (1- (frame-height frame)))) + ;; We test frame-height and not window-height so that, + ;; if the frame is split by displaying a warning, that + ;; doesn't cause the normal splash screen to be used. + ;; We subtract 2 from frame-height to account for the + ;; echo area and the mode line. + (frame-height (- (frame-height frame) 2))) (> frame-height (+ image-height 19))))))) diff --git a/lisp/term.el b/lisp/term.el index c1e827875d1..ecaca505683 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -1462,6 +1462,13 @@ Using \"emacs\" loses, because bash disables editing if $TERM == emacs.") (format "TERMINFO=%s" data-directory) (format term-termcap-format "TERMCAP=" term-term-name term-height term-width) + + ;; This is for backwards compatibility with Bash 4.3 and earlier. + ;; Remove this hack once Bash 4.4-or-later is common, because + ;; it breaks './configure' of some packages that expect it to + ;; say where to find EMACS. + (format "EMACS=%s (term:%s)" emacs-version term-protocol-version) + (format "INSIDE_EMACS=%s,term:%s" emacs-version term-protocol-version) (format "LINES=%d" term-height) (format "COLUMNS=%d" term-width)) diff --git a/lisp/xt-mouse.el b/lisp/xt-mouse.el index 5975e60272f..e52095789ba 100644 --- a/lisp/xt-mouse.el +++ b/lisp/xt-mouse.el @@ -134,23 +134,35 @@ http://invisible-island.net/xterm/ctlseqs/ctlseqs.html)." (fdiff (- f (* 1.0 maxwrap dbig)))) (+ (truncate fdiff) (* maxwrap dbig)))))) -(defun xterm-mouse--read-utf8-char (&optional prompt seconds) - "Read an utf-8 encoded character from the current terminal. -This function reads and returns an utf-8 encoded character of -command input. If the user generates an event which is not a -character (i.e., a mouse click or function key event), read-char -signals an error. - -The returned event may come directly from the user, or from a -keyboard macro. It is not decoded by the keyboard's input coding -system and always treated with an utf-8 input encoding. - -The optional arguments PROMPT and SECONDS work like in -`read-event'." - (let ((tmp (keyboard-coding-system))) - (set-keyboard-coding-system 'utf-8) - (prog1 (read-event prompt t seconds) - (set-keyboard-coding-system tmp)))) +(defcustom xterm-mouse-utf-8 nil + "Non-nil if UTF-8 coordinates should be used to read mouse coordinates. +Set this to non-nil if you are sure that your terminal +understands UTF-8 coordinates, but not SGR coordinates." + :version "25.1" + :type 'boolean + :risky t + :group 'xterm) + +(defun xterm-mouse--read-coordinate () + "Read a mouse coordinate from the current terminal. +If `xterm-mouse-utf-8' was non-nil when +`turn-on-xterm-mouse-tracking-on-terminal' was called, reads the +coordinate as an UTF-8 code unit sequence; otherwise, reads a +single byte." + (let ((previous-keyboard-coding-system (keyboard-coding-system))) + (unwind-protect + (progn + (set-keyboard-coding-system + (if (terminal-parameter nil 'xterm-mouse-utf-8) + 'utf-8-unix + ;; Use Latin-1 instead of no-conversion to avoid flicker + ;; due to `set-keyboard-coding-system' changing the meta + ;; mode. + 'latin-1)) + ;; Wait only a little; we assume that the entire escape sequence + ;; has already been sent when this function is called. + (read-char nil nil 0.1)) + (set-keyboard-coding-system previous-keyboard-coding-system)))) ;; In default mode, each numeric parameter of XTerm's mouse report is ;; a single char, possibly encoded as utf-8. The actual numeric @@ -170,7 +182,7 @@ The optional arguments PROMPT and SECONDS work like in (<= ?0 c ?9)) (setq n (+ (* 10 n) c (- ?0)))) (cons n c)) - (cons (- (setq c (xterm-mouse--read-utf8-char)) 32) c)))) + (cons (- (setq c (xterm-mouse--read-coordinate)) 32) c)))) ;; XTerm reports mouse events as ;; <EVENT-CODE> <X> <Y> in default mode, and @@ -314,6 +326,38 @@ down the SHIFT key while pressing the mouse button." (mapc #'turn-off-xterm-mouse-tracking-on-terminal (terminal-list)) (setq mouse-position-function nil))) +(defun xterm-mouse-tracking-enable-sequence () + "Return a control sequence to enable XTerm mouse tracking. +The returned control sequence enables basic mouse tracking, mouse +motion events and finally extended tracking on terminals that +support it. The following escape sequences are understood by +modern xterms: + +\"\\e[?1000h\" \"Basic mouse mode\": Enables reports for mouse + clicks. There is a limit to the maximum row/column + position (<= 223), which can be reported in this + basic mode. + +\"\\e[?1002h\" \"Mouse motion mode\": Enables reports for mouse + motion events during dragging operations. + +\"\\e[?1005h\" \"UTF-8 coordinate extension\": Enables an + extension to the basic mouse mode, which uses UTF-8 + characters to overcome the 223 row/column limit. + This extension may conflict with non UTF-8 + applications or non UTF-8 locales. It is only + enabled when the option `xterm-mouse-utf-8' is + non-nil. + +\"\\e[?1006h\" \"SGR coordinate extension\": Enables a newer + alternative extension to the basic mouse mode, which + overcomes the 223 row/column limit without the + drawbacks of the UTF-8 coordinate extension. + +The two extension modes are mutually exclusive, where the last +given escape sequence takes precedence over the former." + (apply #'concat (xterm-mouse--tracking-sequence ?h))) + (defconst xterm-mouse-tracking-enable-sequence "\e[?1000h\e[?1002h\e[?1005h\e[?1006h" "Control sequence to enable xterm mouse tracking. @@ -343,10 +387,34 @@ escape sequences are understood by modern xterms: The two extension modes are mutually exclusive, where the last given escape sequence takes precedence over the former.") +(make-obsolete-variable + 'xterm-mouse-tracking-enable-sequence + "use the function `xterm-mouse-tracking-enable-sequence' instead." + "25.1") + +(defun xterm-mouse-tracking-disable-sequence () + "Return a control sequence to disable XTerm mouse tracking. +The control sequence resets the modes set by +`xterm-mouse-tracking-enable-sequence'." + (apply #'concat (nreverse (xterm-mouse--tracking-sequence ?l)))) + (defconst xterm-mouse-tracking-disable-sequence "\e[?1006l\e[?1005l\e[?1002l\e[?1000l" "Reset the modes set by `xterm-mouse-tracking-enable-sequence'.") +(make-obsolete-variable + 'xterm-mouse-tracking-disable-sequence + "use the function `xterm-mouse-tracking-disable-sequence' instead." + "25.1") + +(defun xterm-mouse--tracking-sequence (suffix) + "Return a control sequence to enable or disable mouse tracking. +SUFFIX is the last character of each escape sequence (?h to +enable, ?l to disable)." + (mapcar + (lambda (code) (format "\e[?%d%c" code suffix)) + `(1000 1002 ,@(when xterm-mouse-utf-8 '(1005)) 1006))) + (defun turn-on-xterm-mouse-tracking-on-terminal (&optional terminal) "Enable xterm mouse tracking on TERMINAL." (when (and xterm-mouse-mode (eq t (terminal-live-p terminal)) @@ -360,18 +428,19 @@ given escape sequence takes precedence over the former.") (with-selected-frame (car (frames-on-display-list terminal)) (define-key input-decode-map "\e[M" 'xterm-mouse-translate) (define-key input-decode-map "\e[<" 'xterm-mouse-translate-extended)) - (condition-case err - (send-string-to-terminal xterm-mouse-tracking-enable-sequence - terminal) - ;; FIXME: This should use a dedicated error signal. - (error (if (equal (cadr err) "Terminal is currently suspended") - nil ;The sequence will be sent upon resume. - (signal (car err) (cdr err))))) - (push xterm-mouse-tracking-enable-sequence - (terminal-parameter nil 'tty-mode-set-strings)) - (push xterm-mouse-tracking-disable-sequence - (terminal-parameter nil 'tty-mode-reset-strings)) - (set-terminal-parameter terminal 'xterm-mouse-mode t)))) + (let ((enable (xterm-mouse-tracking-enable-sequence)) + (disable (xterm-mouse-tracking-disable-sequence))) + (condition-case err + (send-string-to-terminal enable terminal) + ;; FIXME: This should use a dedicated error signal. + (error (if (equal (cadr err) "Terminal is currently suspended") + nil ; The sequence will be sent upon resume. + (signal (car err) (cdr err))))) + (push enable (terminal-parameter nil 'tty-mode-set-strings)) + (push disable (terminal-parameter nil 'tty-mode-reset-strings)) + (set-terminal-parameter terminal 'xterm-mouse-mode t) + (set-terminal-parameter terminal 'xterm-mouse-utf-8 + xterm-mouse-utf-8))))) (defun turn-off-xterm-mouse-tracking-on-terminal (terminal) "Disable xterm mouse tracking on TERMINAL." diff --git a/src/alloc.c b/src/alloc.c index 1e4ec8b0573..56a535411c8 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3724,7 +3724,6 @@ make_save_ptr_int (void *a, ptrdiff_t b) return val; } -#if ! (defined USE_X_TOOLKIT || defined USE_GTK) Lisp_Object make_save_ptr_ptr (void *a, void *b) { @@ -3735,7 +3734,6 @@ make_save_ptr_ptr (void *a, void *b) p->data[1].pointer = b; return val; } -#endif Lisp_Object make_save_funcptr_ptr_obj (void (*a) (void), void *b, Lisp_Object c) diff --git a/src/font.c b/src/font.c index 5ab3b3e8399..2519599bc63 100644 --- a/src/font.c +++ b/src/font.c @@ -5317,7 +5317,7 @@ syms_of_font (void) DEFSYM (Qja, "ja"); DEFSYM (Qko, "ko"); - DEFSYM (QCuser_spec, "user-spec"); + DEFSYM (QCuser_spec, ":user-spec"); staticpro (&scratch_font_spec); scratch_font_spec = Ffont_spec (0, NULL); diff --git a/src/frame.c b/src/frame.c index 88102a36625..9c8926c42c7 100644 --- a/src/frame.c +++ b/src/frame.c @@ -4563,7 +4563,7 @@ On Nextstep, this just calls `ns-parse-geometry'. */) This function does not make the coordinates positive. */ -#define DEFAULT_ROWS 35 +#define DEFAULT_ROWS 36 #define DEFAULT_COLS 80 long diff --git a/src/ftfont.c b/src/ftfont.c index a402245a067..7285aee9bd4 100644 --- a/src/ftfont.c +++ b/src/ftfont.c @@ -2596,7 +2596,12 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font, language information, and select a proper flt for them here. */ int c1 = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, 1)); - if (CHAR_HAS_CATEGORY (c1, '^')) + /* For the combining characters in the range U+300..U+36F, + "combining" is the sole FLT provided by the m17n-lib. In + addition, it is the sole FLT that can handle the other + combining characters with non-OTF fonts. */ + if ((0x300 <= c1 && c1 <= 0x36F) + || (! otf && CHAR_HAS_CATEGORY (c1, '^'))) flt = mflt_get (msymbol ("combining")); } if (! flt && ! otf) diff --git a/src/gtkutil.c b/src/gtkutil.c index ba059b73a70..e791e6ac317 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -252,35 +252,6 @@ xg_create_default_cursor (Display *dpy) return gdk_cursor_new_for_display (gdpy, GDK_LEFT_PTR); } -static GdkPixbuf * -xg_get_pixbuf_from_pixmap (struct frame *f, Pixmap pix) -{ - int iunused; - GdkPixbuf *tmp_buf; - Window wunused; - unsigned int width, height, uunused; - XImage *xim; - - XGetGeometry (FRAME_X_DISPLAY (f), pix, &wunused, &iunused, &iunused, - &width, &height, &uunused, &uunused); - - xim = XGetImage (FRAME_X_DISPLAY (f), pix, 0, 0, width, height, - ~0, XYPixmap); - if (!xim) return 0; - - tmp_buf = gdk_pixbuf_new_from_data ((guchar *) xim->data, - GDK_COLORSPACE_RGB, - FALSE, - xim->bitmap_unit, - width, - height, - xim->bytes_per_line, - NULL, - NULL); - XDestroyImage (xim); - return tmp_buf; -} - /* Apply GMASK to GPIX and return a GdkPixbuf with an alpha channel. */ static GdkPixbuf * @@ -288,46 +259,43 @@ xg_get_pixbuf_from_pix_and_mask (struct frame *f, Pixmap pix, Pixmap mask) { - int width, height; - GdkPixbuf *icon_buf, *tmp_buf; - - tmp_buf = xg_get_pixbuf_from_pixmap (f, pix); - icon_buf = gdk_pixbuf_add_alpha (tmp_buf, FALSE, 0, 0, 0); - g_object_unref (G_OBJECT (tmp_buf)); - - width = gdk_pixbuf_get_width (icon_buf); - height = gdk_pixbuf_get_height (icon_buf); + GdkPixbuf *icon_buf = 0; + int iunused; + Window wunused; + unsigned int width, height, depth, uunused; - if (mask) + if (FRAME_DISPLAY_INFO (f)->red_bits != 8) + return 0; + XGetGeometry (FRAME_X_DISPLAY (f), pix, &wunused, &iunused, &iunused, + &width, &height, &uunused, &depth); + if (depth != 24) + return 0; + XImage *xim = XGetImage (FRAME_X_DISPLAY (f), pix, 0, 0, width, height, + ~0, XYPixmap); + if (xim) { - GdkPixbuf *mask_buf = xg_get_pixbuf_from_pixmap (f, mask); - guchar *pixels = gdk_pixbuf_get_pixels (icon_buf); - guchar *mask_pixels = gdk_pixbuf_get_pixels (mask_buf); - int rowstride = gdk_pixbuf_get_rowstride (icon_buf); - int mask_rowstride = gdk_pixbuf_get_rowstride (mask_buf); - int y; - - for (y = 0; y < height; ++y) - { - guchar *iconptr, *maskptr; - int x; - - iconptr = pixels + y * rowstride; - maskptr = mask_pixels + y * mask_rowstride; - - for (x = 0; x < width; ++x) - { - /* In a bitmap, RGB is either 255/255/255 or 0/0/0. Checking - just R is sufficient. */ - if (maskptr[0] == 0) - iconptr[3] = 0; /* 0, 1, 2 is R, G, B. 3 is alpha. */ - - iconptr += rowstride/width; - maskptr += mask_rowstride/width; - } - } + XImage *xmm = (! mask ? 0 + : XGetImage (FRAME_X_DISPLAY (f), mask, 0, 0, + width, height, ~0, XYPixmap)); + icon_buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height); + if (icon_buf) + { + guchar *pixels = gdk_pixbuf_get_pixels (icon_buf); + int rowjunkwidth = gdk_pixbuf_get_rowstride (icon_buf) - width * 4; + for (int y = 0; y < height; y++, pixels += rowjunkwidth) + for (int x = 0; x < width; x++) + { + unsigned long rgb = XGetPixel (xim, x, y); + *pixels++ = (rgb >> 16) & 255; + *pixels++ = (rgb >> 8) & 255; + *pixels++ = rgb & 255; + *pixels++ = xmm && !XGetPixel (xmm, x, y) ? 0 : 255; + } + } - g_object_unref (G_OBJECT (mask_buf)); + if (xmm) + XDestroyImage (xmm); + XDestroyImage (xim); } return icon_buf; diff --git a/src/keyboard.c b/src/keyboard.c index 1a5dbd0f617..54643eebba4 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -2529,7 +2529,7 @@ read_char (int commandflag, Lisp_Object map, if (KEYMAPP (map) && INTERACTIVE && !NILP (prev_event) && ! EVENT_HAS_PARAMETERS (prev_event) /* Don't bring up a menu if we already have another event. */ - && NILP (Vunread_command_events) + && !CONSP (Vunread_command_events) && !detect_input_pending_run_timers (0)) { c = read_char_minibuf_menu_prompt (commandflag, map); @@ -2660,7 +2660,7 @@ read_char (int commandflag, Lisp_Object map, && !EQ (XCAR (prev_event), Qmenu_bar) && !EQ (XCAR (prev_event), Qtool_bar) /* Don't bring up a menu if we already have another event. */ - && NILP (Vunread_command_events)) + && !CONSP (Vunread_command_events)) { c = read_char_x_menu_prompt (map, prev_event, used_mouse_menu); @@ -9877,7 +9877,7 @@ clear_input_pending (void) bool requeued_events_pending_p (void) { - return (!NILP (Vunread_command_events)); + return (CONSP (Vunread_command_events)); } DEFUN ("input-pending-p", Finput_pending_p, Sinput_pending_p, 0, 1, 0, @@ -9888,7 +9888,7 @@ if there is a doubt, the value is t. If CHECK-TIMERS is non-nil, timers that are ready to run will do so. */) (Lisp_Object check_timers) { - if (!NILP (Vunread_command_events) + if (CONSP (Vunread_command_events) || !NILP (Vunread_post_input_method_events) || !NILP (Vunread_input_method_events)) return (Qt); diff --git a/src/term.c b/src/term.c index 17f36795998..a77e5729b5b 100644 --- a/src/term.c +++ b/src/term.c @@ -3402,9 +3402,11 @@ static void tty_pop_down_menu (Lisp_Object arg) { tty_menu *menu = XSAVE_POINTER (arg, 0); + struct buffer *orig_buffer = XSAVE_POINTER (arg, 1); block_input (); tty_menu_destroy (menu); + set_buffer_internal (orig_buffer); unblock_input (); } @@ -3683,7 +3685,10 @@ tty_menu_show (struct frame *f, int x, int y, int menuflags, pane = selidx = 0; - record_unwind_protect (tty_pop_down_menu, make_save_ptr (menu)); + /* We save and restore the current buffer because tty_menu_activate + triggers redisplay, which switches buffers at will. */ + record_unwind_protect (tty_pop_down_menu, + make_save_ptr_ptr (menu, current_buffer)); specbind (Qoverriding_terminal_local_map, Fsymbol_value (Qtty_menu_navigation_map)); diff --git a/src/w32font.c b/src/w32font.c index a1878adb4bd..018e6572563 100644 --- a/src/w32font.c +++ b/src/w32font.c @@ -796,7 +796,8 @@ w32font_list_internal (struct frame *f, Lisp_Object font_spec, && !EQ (spec_charset, Qiso10646_1) && !EQ (spec_charset, Qunicode_bmp) && !EQ (spec_charset, Qunicode_sip) - && !EQ (spec_charset, Qunknown)) + && !EQ (spec_charset, Qunknown) + && !EQ (spec_charset, Qascii_0)) return Qnil; } diff --git a/src/xdisp.c b/src/xdisp.c index bdc8af8b5bf..290f69878da 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -31386,8 +31386,11 @@ Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI). */); Vtruncate_partial_width_windows, doc: /* Non-nil means truncate lines in windows narrower than the frame. For an integer value, truncate lines in each window narrower than the -full frame width, provided the window width is less than that integer; -otherwise, respect the value of `truncate-lines'. +full frame width, provided the total window width in column units is less +than that integer; otherwise, respect the value of `truncate-lines'. +The total width of the window is as returned by `window-total-width', it +includes the fringes, the continuation and truncation glyphs, the +display margins (if any), and the scroll bar For any other non-nil value, truncate lines in all windows that do not span the full frame width. diff --git a/src/xwidget.c b/src/xwidget.c index d438d879098..c24475f5312 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -767,14 +767,14 @@ VALUE is the amount to scroll, either relatively or absolutely. */) Lisp_Object value) { CHECK_XWIDGET (xwidget); - CHECK_NATNUM (value); + CHECK_NUMBER (value); struct xwidget *xw = XXWIDGET (xwidget); GtkAdjustment *adjustment = ((EQ (Qhorizontal, axis) ? gtk_scrolled_window_get_hadjustment : gtk_scrolled_window_get_vadjustment) (GTK_SCROLLED_WINDOW (xw->widgetscrolledwindow_osr))); - double final_value = XFASTINT (value); + double final_value = XINT (value); if (EQ (Qt, relative)) final_value += gtk_adjustment_get_value (adjustment); gtk_adjustment_set_value (adjustment, final_value); diff --git a/test/automated/xt-mouse-tests.el b/test/automated/xt-mouse-tests.el new file mode 100644 index 00000000000..c7e835c0311 --- /dev/null +++ b/test/automated/xt-mouse-tests.el @@ -0,0 +1,110 @@ +;;; xt-mouse-tests.el --- Test suite for xt-mouse. -*- lexical-binding: t; -*- + +;; Copyright (C) 2016 Free Software Foundation, Inc. + +;; Author: Philipp Stephani <phst@google.com> + +;; 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 <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;;; Code: + +(require 'xt-mouse) + +(defmacro with-xterm-mouse-mode (&rest body) + "Run BODY with `xterm-mouse-mode' temporarily enabled." + (declare (indent 0)) + ;; Make the frame huge so that the test input events below don't hit + ;; the menu bar. + `(cl-letf (((frame-width nil) 2000) + ((frame-height nil) 2000) + ;; Reset XTerm parameters so that the tests don't get + ;; confused. + ((terminal-parameter nil 'xterm-mouse-x) nil) + ((terminal-parameter nil 'xterm-mouse-y) nil) + ((terminal-parameter nil 'xterm-mouse-last-down) nil) + ((terminal-parameter nil 'xterm-mouse-last-click) nil)) + (if xterm-mouse-mode + (progn ,@body) + (unwind-protect + (progn + ;; `xterm-mouse-mode' doesn't work in the initial + ;; terminal. Since we can't create a second terminal in + ;; batch mode, fake it temporarily. + (cl-letf (((symbol-function 'terminal-name) + (lambda (&optional _terminal) "fake-terminal"))) + (xterm-mouse-mode)) + ,@body) + (xterm-mouse-mode 0))))) + +(ert-deftest xt-mouse-tracking-basic () + (should (equal (xterm-mouse-tracking-enable-sequence) + "\e[?1000h\e[?1002h\e[?1006h")) + (should (equal (xterm-mouse-tracking-disable-sequence) + "\e[?1006l\e[?1002l\e[?1000l")) + (with-xterm-mouse-mode + (should xterm-mouse-mode) + (should (terminal-parameter nil 'xterm-mouse-mode)) + (should-not (terminal-parameter nil 'xterm-mouse-utf-8)) + (let* ((unread-command-events (append "\e[M%\xD9\x81" + "\e[M'\xD9\x81" nil)) + (key (read-key))) + (should (consp key)) + (cl-destructuring-bind (event-type position . rest) key + (should (equal event-type 'S-mouse-2)) + (should (consp position)) + (cl-destructuring-bind (_ _ xy . rest) position + (should (equal xy '(184 . 95)))))))) + +(ert-deftest xt-mouse-tracking-utf-8 () + (let ((xterm-mouse-utf-8 t)) + (should (equal (xterm-mouse-tracking-enable-sequence) + "\e[?1000h\e[?1002h\e[?1005h\e[?1006h")) + (should (equal (xterm-mouse-tracking-disable-sequence) + "\e[?1006l\e[?1005l\e[?1002l\e[?1000l")) + (with-xterm-mouse-mode + (should xterm-mouse-mode) + (should (terminal-parameter nil 'xterm-mouse-mode)) + (should (terminal-parameter nil 'xterm-mouse-utf-8)) + ;; The keyboard driver doesn't decode bytes in + ;; `unread-command-events'. + (let* ((unread-command-events (append "\e[M%\u0640\u0131" + "\e[M'\u0640\u0131" nil)) + (key (read-key))) + (should (consp key)) + (cl-destructuring-bind (event-type position . rest) key + (should (equal event-type 'S-mouse-2)) + (should (consp position)) + (cl-destructuring-bind (_ _ xy . rest) position + (should (equal xy '(1567 . 271))))))))) + +(ert-deftest xt-mouse-tracking-sgr () + (with-xterm-mouse-mode + (should xterm-mouse-mode) + (should (terminal-parameter nil 'xterm-mouse-mode)) + (should-not (terminal-parameter nil 'xterm-mouse-utf-8)) + (let* ((unread-command-events (append "\e[<5;1569;273;M" + "\e[<5;1569;273;m" nil)) + (key (read-key))) + (should (consp key)) + (cl-destructuring-bind (event-type position . rest) key + (should (equal event-type 'S-mouse-2)) + (should (consp position)) + (cl-destructuring-bind (_ _ xy . rest) position + (should (equal xy '(1568 . 271)))))))) + +;;; xt-mouse-tests.el ends here diff --git a/test/lisp/emacs-lisp/map-tests.el b/test/lisp/emacs-lisp/map-tests.el index d145c197a4e..20cb0f6b399 100644 --- a/test/lisp/emacs-lisp/map-tests.el +++ b/test/lisp/emacs-lisp/map-tests.el @@ -87,9 +87,16 @@ Evaluate BODY for each created map. (let ((vec [3 4 5])) (should-error (setf (map-elt vec 3) 6)))) +(ert-deftest test-map-put-alist-new-key () + "Regression test for Bug#23105." + (let ((alist '((0 . a)))) + (map-put alist 2 'b) + (should (eq (map-elt alist 2) + 'b)))) + (ert-deftest test-map-put-return-value () (let ((ht (make-hash-table))) - (should (eq (map-put ht 'a 'hello) ht)))) + (should (eq (map-put ht 'a 'hello) 'hello)))) (ert-deftest test-map-delete () (with-maps-do map |