commit 592873a52d00fa46bcf63b0dd38073f038ecb935 (HEAD, refs/remotes/origin/master) Author: Juri Linkov Date: Thu May 2 09:53:06 2024 +0300 * lisp/emacs-lisp/warnings.el: Fix 'warning-display-at-bottom'. (display-warning): Move point to the beginning of the last line instead of its end for 'warning-display-at-bottom' (bug#69983). diff --git a/lisp/emacs-lisp/warnings.el b/lisp/emacs-lisp/warnings.el index 6a1187fdb0f..8c1e43934ff 100644 --- a/lisp/emacs-lisp/warnings.el +++ b/lisp/emacs-lisp/warnings.el @@ -383,7 +383,7 @@ entirely by setting `warning-suppress-types' or (when warning-display-at-bottom (with-selected-window window (goto-char (point-max)) - (set-window-point window (1- (point-max))) + (forward-line -1) (recenter -1))) (sit-for 0))))))))) commit 7d15d17353c02b0ded3671ecfaf2f4a8c19d43c1 Author: Eli Zaretskii Date: Thu May 2 09:50:37 2024 +0300 ; Improve commentary in intervals.h * src/intervals.h (INTERVAL_GENERALLY_WRITABLE_P) (INTERVAL_EXPRESSLY_WRITABLE_P): Clarify commentary. diff --git a/src/intervals.h b/src/intervals.h index 4ddb7f12b92..5718874543a 100644 --- a/src/intervals.h +++ b/src/intervals.h @@ -204,16 +204,16 @@ set_interval_plist (INTERVAL i, Lisp_Object plist) #define INTERVAL_VISIBLE_P(i) \ (i && NILP (textget ((i)->plist, Qinvisible))) -/* Is this interval writable by virtue of not being marked read-only, or - a general value of Vinhibit_read_only (which is read from the value - provided as RO)? Replace later with cache access. */ +/* Is this interval writable by virtue of not being marked read-only + by the 'read-only' property (passed via RO), or due to the general + value of Vinhibit_read_only? Replace later with cache access. */ #define INTERVAL_GENERALLY_WRITABLE_P(i, ro) \ (NILP (ro) || (!NILP (Vinhibit_read_only) \ && !CONSP (Vinhibit_read_only))) -/* Is this interval writable by virtue of an explicit inhibit-read-only - property, or the specific presence of its Qread_only property (which - is read from the value provided as RO) in Vinhibit_read_only? */ +/* Is this interval writable by virtue of its explicit + 'inhibit-read-only' property, or due to the presence of its + 'read-only' property (passed via RO) in Vinhibit_read_only list? */ #define INTERVAL_EXPRESSLY_WRITABLE_P(i, ro) \ (!NILP (textget ((i)->plist, Qinhibit_read_only)) \ || (!NILP (ro) \ commit 0023891e84285c2ea2a8029f479135f792c9d1e9 Author: Juri Linkov Date: Thu May 2 09:46:48 2024 +0300 Support hints in the :repeat keyword of defvar-keymap for repeat-mode * lisp/keymap.el (defvar-keymap): Add :hints to the :repeat keyword. Put the property 'repeat-hint' on the command symbol. * lisp/repeat.el (repeat-echo-message-string): Show hint strings defined with the property 'repeat-hint' on the command symbol (bug#70576). diff --git a/etc/NEWS b/etc/NEWS index 4b0106fcb07..9d986c06f2f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2619,6 +2619,10 @@ major mode. ** The variable 'rx-constituents' is now obsolete. Use 'rx-define', 'rx-let' and 'rx-let-eval' instead. +--- +** 'defvar-keymap' can specify hints for 'repeat-mode'. +Using ':repeat (:hints ((command . "hint") ...))' will show +the hint string in the echo area together with repeatable keys. * Changes in Emacs 30.1 on Non-Free Operating Systems diff --git a/lisp/keymap.el b/lisp/keymap.el index b2b475c7d71..cbd26f1060e 100644 --- a/lisp/keymap.el +++ b/lisp/keymap.el @@ -603,10 +603,11 @@ non-nil, all commands in the map will have the `repeat-map' symbol property. More control is available over which commands are repeatable; the -value can also be a property list with properties `:enter' and -`:exit', for example: +value can also be a property list with properties `:enter', +`:exit' and `:hints', for example: - :repeat (:enter (commands ...) :exit (commands ...)) + :repeat (:enter (commands ...) :exit (commands ...) + :hints ((command . \"hint\") ...)) `:enter' specifies the list of additional commands that only enter `repeat-mode'. When the list is empty, then only the @@ -621,6 +622,10 @@ Specifying a list of commands is useful when those commands exist in this specific map, but should not have the `repeat-map' symbol property. +`:hints' is a list of cons pairs where car is a command and +cdr is a string that is displayed alongside of the repeatable key +in the echo area. + \(fn VARIABLE-NAME &key DOC FULL PARENT SUPPRESS NAME PREFIX KEYMAP REPEAT &rest [KEY DEFINITION]...)" (declare (indent 1)) (let ((opts nil) @@ -660,7 +665,9 @@ property. (setq def (pop defs)) (when (and (memq (car def) '(function quote)) (not (memq (cadr def) (plist-get repeat :exit)))) - (push `(put ,def 'repeat-map ',variable-name) props))))) + (push `(put ,def 'repeat-map ',variable-name) props))) + (dolist (def (plist-get repeat :hints)) + (push `(put ',(car def) 'repeat-hint ',(cdr def)) props)))) (let ((defvar-form `(defvar ,variable-name diff --git a/lisp/repeat.el b/lisp/repeat.el index 0a59494c097..412afc35ba7 100644 --- a/lisp/repeat.el +++ b/lisp/repeat.el @@ -553,20 +553,27 @@ This function can be used to force exit of repetition while it's active." (defun repeat-echo-message-string (keymap) "Return a string with the list of repeating keys in KEYMAP." (let (keys) - (map-keymap (lambda (key cmd) (and cmd (push key keys))) keymap) - (format-message "Repeat with %s%s" - (mapconcat (lambda (key) - (substitute-command-keys - (format "\\`%s'" - (key-description (vector key))))) - keys ", ") - (if repeat-exit-key - (substitute-command-keys - (format ", or exit with \\`%s'" - (if (key-valid-p repeat-exit-key) - repeat-exit-key - (key-description repeat-exit-key)))) - "")))) + (map-keymap (lambda (key cmd) (and cmd (push (cons key cmd) keys))) + keymap) + (format-message + "Repeat with %s%s" + (mapconcat (lambda (key-cmd) + (let* ((key (car key-cmd)) + (cmd (cdr key-cmd)) + (hint (when (symbolp cmd) + (get cmd 'repeat-hint)))) + (substitute-command-keys + (format "\\`%s'%s" + (key-description (vector key)) + (if hint (format ":%s" hint) ""))))) + keys ", ") + (if repeat-exit-key + (substitute-command-keys + (format ", or exit with \\`%s'" + (if (key-valid-p repeat-exit-key) + repeat-exit-key + (key-description repeat-exit-key)))) + "")))) (defun repeat-echo-message (keymap) "Display in the echo area the repeating keys defined by KEYMAP. commit a1613505e24e8d5eae79b130809d217b1db23065 Author: Juri Linkov Date: Thu May 2 09:28:53 2024 +0300 * lisp/progmodes/ruby-ts-mode.el (ruby-ts-mode): Add 'text' (bug#67036). Add 'text' lambda to 'treesit-thing-settings' that should fall back to the default functions for sentence/sexp navigation. diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el index 7133cb0b5b0..5f4e11e0b4c 100644 --- a/lisp/progmodes/ruby-ts-mode.el +++ b/lisp/progmodes/ruby-ts-mode.el @@ -1171,7 +1171,22 @@ leading double colon is not added." "global_variable" ) eol) - #'ruby-ts--sexp-p))))) + #'ruby-ts--sexp-p)) + (text ,(lambda (node) + (or (member (treesit-node-type node) + '("comment" "string_content" "heredoc_content")) + ;; for C-M-f in hash[:key] and hash['key'] + (and (member (treesit-node-text node) + '("[" "]")) + (equal (treesit-node-type + (treesit-node-parent node)) + "element_reference")) + ;; for C-M-f in "abc #{ghi} def" + (and (member (treesit-node-text node) + '("#{" "}")) + (equal (treesit-node-type + (treesit-node-parent node)) + "interpolation")))))))) ;; AFAIK, Ruby can not nest methods (setq-local treesit-defun-prefer-top-level nil) commit bf026b8e55626b35144f93056744f3fd50bc126b Author: Yuan Fu Date: Wed May 1 21:50:21 2024 -0700 Tighten regexp for rust-ts-mode keyword workaround * lisp/progmodes/rust-ts-mode.el (rust-ts-mode--font-lock-settings): Add bos and eos. diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index 7bc05898d15..baf0e1ec013 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -217,7 +217,7 @@ to be checked as its standard input." ;; If these keyword are in a macro body, they're marked as ;; identifiers. ((identifier) @font-lock-keyword-face - (:match ,(rx (or "else" "in" "move")) @font-lock-keyword-face))) + (:match ,(rx bos (or "else" "in" "move") eos) @font-lock-keyword-face))) :language 'rust :feature 'number commit 07c47ea002b4702285bbf467ec09c9b281eb19b7 Author: Yuan Fu Date: Wed May 1 21:21:00 2024 -0700 Fix fontification for else in macro body in rust-ts-mode * lisp/progmodes/rust-ts-mode.el (rust-ts-mode--font-lock-settings): Add a rule for else in macro body. Also added the same rule for "in" and "move" keyword, as they seems to have the same problem. diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index 25f1df4a9f9..7bc05898d15 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -213,7 +213,11 @@ to be checked as its standard input." :language 'rust :feature 'keyword - `([,@rust-ts-mode--keywords] @font-lock-keyword-face) + `([,@rust-ts-mode--keywords] @font-lock-keyword-face + ;; If these keyword are in a macro body, they're marked as + ;; identifiers. + ((identifier) @font-lock-keyword-face + (:match ,(rx (or "else" "in" "move")) @font-lock-keyword-face))) :language 'rust :feature 'number commit 0f92d433d2b806eb58a9a4c0197344b08ea5ae65 Author: Noah Peart Date: Tue Apr 30 02:55:18 2024 -0700 Add font-locking for typed parameters in python-ts-mode (bug#70665) * lisp/progmodes/python.el (python--treesit-settings): Add tree-sitter font-locking rule for typed parameters. * test/lisp/progmodes/python-tests.el (python-ts-mode-types-face-1): Test for font-lock-variable-name-face in typed parameter. diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index d6c29e5ffc6..4ff5e9d4878 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -1202,6 +1202,7 @@ fontified." (class_definition name: (identifier) @font-lock-type-face) (parameters (identifier) @font-lock-variable-name-face) + (parameters (typed_parameter (identifier) @font-lock-variable-name-face)) (parameters (default_parameter name: (identifier) @font-lock-variable-name-face))) :feature 'builtin diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index e11440cdb5b..878f60f1614 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -7545,6 +7545,9 @@ always located at the beginning of buffer." (ert-deftest python-ts-mode-types-face-1 () (python-ts-tests-with-temp-buffer "def f(val: Callable[[Type0], (Type1, Type2)]):" + (search-forward "val") + (goto-char (match-beginning 0)) + (should (eq (face-at-point) font-lock-variable-name-face)) (dolist (test '("Callable" "Type0" "Type1" "Type2")) (search-forward test) (goto-char (match-beginning 0)) commit b84fa71f8985284560bacda7d407e3559583844f Author: Po Lu Date: Thu May 2 11:31:37 2024 +0800 Port visible bell to Android * java/org/gnu/emacs/EmacsDrawRectangle.java (perform): Ignore GC_INVERT. * java/org/gnu/emacs/EmacsFillRectangle.java (EmacsFillRectangle) : New variable. (perform): If the transfer mode is invert, copy the source to itself with invertFilter as the color filter. * java/org/gnu/emacs/EmacsGC.java (EmacsGC) : Delete now-redundant ALUs. (markDirty): Cease updating the paint's transfermode. * java/org/gnu/emacs/EmacsSafThread.java (openDocument1): Fix typo in documentation. * src/android.c (android_blit_xor): Delete unused function. (android_copy_area): Remove calls to unused blit functions. * src/androidgui.h (enum android_gc_function): Rename XOR to INVERT. * src/androidterm.c (android_flash): Replace with GXinvert. diff --git a/java/org/gnu/emacs/EmacsDrawRectangle.java b/java/org/gnu/emacs/EmacsDrawRectangle.java index e40a7c16068..ea0f1c28106 100644 --- a/java/org/gnu/emacs/EmacsDrawRectangle.java +++ b/java/org/gnu/emacs/EmacsDrawRectangle.java @@ -22,13 +22,23 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.PorterDuff.Mode; +import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; +import android.graphics.Xfermode; import android.util.Log; public final class EmacsDrawRectangle { + private static final Xfermode srcInAlu; + + static + { + srcInAlu = new PorterDuffXfermode (Mode.SRC_IN); + }; + public static void perform (EmacsDrawable drawable, EmacsGC gc, int x, int y, int width, int height) @@ -40,8 +50,10 @@ public final class EmacsDrawRectangle Canvas canvas; Bitmap clipBitmap; - /* TODO implement stippling. */ - if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) + /* TODO implement stippling for this request. */ + if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED + /* And GC_INVERT also. */ + || gc.fill_style == EmacsGC.GC_INVERT) return; canvas = drawable.lockCanvas (gc); @@ -103,7 +115,7 @@ maskRect, new Rect (0, 0, /* Set the transfer mode to SRC_IN to preserve only the parts of the source that overlap with the mask. */ maskPaint = new Paint (); - maskPaint.setXfermode (EmacsGC.srcInAlu); + maskPaint.setXfermode (srcInAlu); maskPaint.setStyle (Paint.Style.STROKE); /* Draw the source. */ diff --git a/java/org/gnu/emacs/EmacsFillRectangle.java b/java/org/gnu/emacs/EmacsFillRectangle.java index f338a54f97b..7642deed7c3 100644 --- a/java/org/gnu/emacs/EmacsFillRectangle.java +++ b/java/org/gnu/emacs/EmacsFillRectangle.java @@ -21,6 +21,8 @@ import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.ColorMatrixColorFilter; import android.graphics.Paint; import android.graphics.Rect; @@ -28,30 +30,42 @@ public final class EmacsFillRectangle { + /* Color filter that inverts colors from the source. */ + private static final ColorFilter invertFilter; + + static + { + invertFilter = new ColorMatrixColorFilter (new float[] { + -1f, 0f, 0f, 0f, 255f, + 0f, -1f, 0f, 0f, 255f, + 0f, 0f, -1f, 0f, 255f, + 0f, 0f, 0f, 1f, 0f, + }); + }; + public static void perform (EmacsDrawable drawable, EmacsGC gc, int x, int y, int width, int height) { - Paint maskPaint, paint; - Canvas maskCanvas; - Bitmap maskBitmap; + Paint paint; Rect rect; - Rect maskRect, dstRect; Canvas canvas; - Bitmap clipBitmap; + Bitmap invertBitmap; canvas = drawable.lockCanvas (gc); - if (canvas == null) + /* Clip masks are not respected or implemented when specified with + this request. */ + if (canvas == null || gc.clip_mask != null) return; rect = new Rect (x, y, x + width, y + height); - paint = gc.gcPaint; - paint.setStyle (Paint.Style.FILL); - - if (gc.clip_mask == null) + if (gc.function != EmacsGC.GC_INVERT) { + paint = gc.gcPaint; + paint.setStyle (Paint.Style.FILL); + if (gc.fill_style != EmacsGC.GC_FILL_OPAQUE_STIPPLED) canvas.drawRect (rect, paint); else @@ -59,57 +73,17 @@ public final class EmacsFillRectangle } else { - /* Drawing with a clip mask involves calculating the - intersection of the clip mask with the dst rect, and - extrapolating the corresponding part of the src rect. */ - - clipBitmap = gc.clip_mask.bitmap; - dstRect = new Rect (x, y, x + width, y + height); - maskRect = new Rect (gc.clip_x_origin, - gc.clip_y_origin, - (gc.clip_x_origin - + clipBitmap.getWidth ()), - (gc.clip_y_origin - + clipBitmap.getHeight ())); - - if (!maskRect.setIntersect (dstRect, maskRect)) - /* There is no intersection between the clip mask and the - dest rect. */ - return; - - /* Finally, create a temporary bitmap that is the size of - maskRect. */ - - maskBitmap - = Bitmap.createBitmap (maskRect.width (), maskRect.height (), - Bitmap.Config.ARGB_8888); - - /* Draw the mask onto the maskBitmap. */ - maskCanvas = new Canvas (maskBitmap); - maskRect.offset (-gc.clip_x_origin, - -gc.clip_y_origin); - maskCanvas.drawBitmap (gc.clip_mask.bitmap, - maskRect, new Rect (0, 0, - maskRect.width (), - maskRect.height ()), - paint); - maskRect.offset (gc.clip_x_origin, - gc.clip_y_origin); - - /* Set the transfer mode to SRC_IN to preserve only the parts - of the source that overlap with the mask. */ - maskPaint = new Paint (); - maskPaint.setXfermode (EmacsGC.srcInAlu); - - /* Draw the source. */ - maskCanvas.drawRect (maskRect, maskPaint); - - /* Finally, draw the mask bitmap to the destination. */ - paint.setXfermode (null); - canvas.drawBitmap (maskBitmap, null, maskRect, paint); - - /* Recycle this unused bitmap. */ - maskBitmap.recycle (); + paint = new Paint (); + + /* Simply invert the destination, which is only implemented for + this request. As Android doesn't permit copying a bitmap to + itself, a copy of the source must be procured beforehand. */ + invertBitmap = Bitmap.createBitmap (drawable.getBitmap (), + x, y, width, height); + paint.setColorFilter (invertFilter); + canvas.drawBitmap (invertBitmap, null, rect, paint); + paint.setColorFilter (null); + invertBitmap.recycle (); } drawable.damageRect (rect); diff --git a/java/org/gnu/emacs/EmacsGC.java b/java/org/gnu/emacs/EmacsGC.java index ec2b9c9e475..bb11f76c800 100644 --- a/java/org/gnu/emacs/EmacsGC.java +++ b/java/org/gnu/emacs/EmacsGC.java @@ -27,9 +27,7 @@ import android.graphics.ColorFilter; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffColorFilter; -import android.graphics.PorterDuffXfermode; import android.graphics.Shader.TileMode; -import android.graphics.Xfermode; import android.graphics.drawable.BitmapDrawable; @@ -40,8 +38,8 @@ public final class EmacsGC extends EmacsHandleObject { - public static final int GC_COPY = 0; - public static final int GC_XOR = 1; + public static final int GC_COPY = 0; + public static final int GC_INVERT = 1; public static final int GC_FILL_SOLID = 0; public static final int GC_FILL_OPAQUE_STIPPLED = 1; @@ -49,8 +47,6 @@ public final class EmacsGC extends EmacsHandleObject public static final int GC_LINE_SOLID = 0; public static final int GC_LINE_ON_OFF_DASH = 1; - public static final Xfermode xorAlu, srcInAlu; - public int function, fill_style; public int foreground, background; public int clip_x_origin, clip_y_origin; @@ -72,12 +68,6 @@ public final class EmacsGC extends EmacsHandleObject rectangles changed. 0 if there are no clip rectangles. */ public long clipRectID; - static - { - xorAlu = new PorterDuffXfermode (Mode.XOR); - srcInAlu = new PorterDuffXfermode (Mode.SRC_IN); - } - /* The following fields are only set on immutable GCs. */ public @@ -131,8 +121,6 @@ public final class EmacsGC extends EmacsHandleObject /* A line_width of 0 is equivalent to that of 1. */ gcPaint.setStrokeWidth (line_width < 1 ? 1 : line_width); gcPaint.setColor (foreground | 0xff000000); - gcPaint.setXfermode (function == GC_XOR - ? xorAlu : srcInAlu); /* Update the stipple object with the new stipple bitmap, or delete it if the stipple has been cleared on systems too old to support diff --git a/java/org/gnu/emacs/EmacsSafThread.java b/java/org/gnu/emacs/EmacsSafThread.java index 14c3f222833..ee8c2e7e0c3 100644 --- a/java/org/gnu/emacs/EmacsSafThread.java +++ b/java/org/gnu/emacs/EmacsSafThread.java @@ -1623,10 +1623,10 @@ In addition, arbitrary runtime exceptions (such as mode is merely w. This may be ascribed to a mix-up in Android's documentation - regardin DocumentsProvider: the `openDocument' function is only - documented to accept r or rw, whereas the default - implementation of the `openFile' function (which documents rwt) - delegates to `openDocument'. */ + regarding DocumentsProvider: the `openDocument' function is only + documented to accept r or rw, whereas the default implementation + of the `openFile' function (which documents rwt) delegates to + `openDocument'. */ if (read && write && truncate && fileDescriptor != null && !EmacsNative.ftruncate (fileDescriptor.getFd ())) diff --git a/src/android.c b/src/android.c index 2777add5059..c76afdb9bf2 100644 --- a/src/android.c +++ b/src/android.c @@ -4381,286 +4381,6 @@ android_blit_copy (int src_x, int src_y, int width, int height, } -/* Xor a rectangle SRC_X, SRC_Y, WIDTH and HEIGHT from SRC, described - by SRC_INFO, to DST_X and DST_Y in DST, as described by DST_INFO. - - Ignore the alpha channel when computing the exclusive-or of the - destination pixel. - - If MASK is set, mask the source data using MASK_INFO, translating - it by GC->clip_x_origin and GC->clip_y_origin. MASK must be a - pixmap of depth 1. - - N.B. that currently only copies between bitmaps of depth 24 are - implemented. */ - -static void -android_blit_xor (int src_x, int src_y, int width, int height, - int dst_x, int dst_y, struct android_gc *gc, - unsigned char *src, AndroidBitmapInfo *src_info, - unsigned char *dst, AndroidBitmapInfo *dst_info, - unsigned char *mask, AndroidBitmapInfo *mask_info) -{ -#if 0 - uintptr_t start, end; - int mask_offset; - size_t pixel, offset, offset1; - unsigned char *src_current, *dst_current; - unsigned char *mask_current; - int overflow, temp, i; - bool backwards; - unsigned int *long_src, *long_dst; -#endif /* 0 */ - - /* Note that this alu hasn't been tested -- it probably does not - work! */ - emacs_abort (); - -#if 0 - /* Assert that the specified coordinates are within bounds. */ - eassert (src_x >= 0 && src_y >= 0 - && dst_x >= 0 && dst_y >= 0); - eassert (src_x + width <= src_info->width); - eassert (src_y + height <= src_info->height); - eassert (dst_x + width <= dst_info->width); - eassert (dst_y + height <= dst_info->height); - - /* Now check that each bitmap has the correct format. */ - eassert (src_info->format == dst_info->format - && src_info->format == ANDROID_BITMAP_FORMAT_RGBA_8888); - pixel = sizeof (unsigned int); - - /* Android doesn't have A1 bitmaps, so A8 is used to represent - packed bitmaps of depth 1. */ - eassert (!mask || mask_info->format == ANDROID_BITMAP_FORMAT_A_8); - - /* Calculate the address of the first pixel of the first row to be - copied in both src and dst. Compare them to determine the - direction in which the copy is to take place. */ - - overflow = ckd_mul (&start, src_y, src_info->stride); - overflow |= ckd_mul (&end, src_x, pixel); - overflow |= ckd_add (&start, (uintptr_t) src, start); - - if (overflow) - return; - - src_current = (unsigned char *) start; - - overflow = ckd_mul (&start, dst_y, src_info->stride); - overflow |= ckd_mul (&end, dst_x, pixel); - overflow |= ckd_add (&start, (uintptr_t) dst, start); - - if (overflow) - return; - - dst_current = (unsigned char *) start; - backwards = false; - - /* Now see if copying should proceed from the bottom up. */ - - if (src == dst && dst_current >= src_current) - { - backwards = true; - - /* Walk src and dst from bottom to top, in order to avoid - overlap. Calculate the coordinate of the last pixel of the - last row in both src and dst. */ - - overflow = ckd_mul (&start, src_y + height - 1, - src_info->stride); - if (mask) /* If a mask is set, put the pointers before the end - of the row. */ - overflow |= ckd_mul (&end, src_x + width - 1, pixel); - else - overflow |= ckd_mul (&end, src_x, pixel); - overflow |= ckd_add (&start, start, end); - overflow |= ckd_add (&start, (uintptr_t) src, start); - - if (overflow) - return; - - src_current = (unsigned char *) start; - - overflow = ckd_mul (&start, dst_y + height - 1, - dst_info->stride); - if (mask) /* If a mask is set, put the pointers before the end - of the row. */ - overflow |= ckd_mul (&end, dst_x + width - 1, pixel); - else - overflow |= ckd_mul (&end, dst_x, pixel); - overflow |= ckd_add (&start, start, end); - overflow |= ckd_add (&start, (uintptr_t) dst, start); - - if (overflow) - return; - - dst_current = (unsigned char *) start; - } - - if (!mask) - { - /* Change the direction of the copy depending on how SRC and DST - overlap. */ - - for (i = 0; i < height; ++i) - { - if (backwards) - { - for (i = width - 1; i <= 0; --i) - (((unsigned int *) dst_current)[i]) - /* Keep the alpha channel intact. */ - ^= (((unsigned int *) src_current)[i]) & 0xffffff; - - /* Proceed to the last row. */ - src_current -= src_info->stride; - dst_current -= dst_info->stride; - } - else - { - for (i = 0; i < width; ++i) - (((unsigned int *) dst_current)[i]) - /* Keep the alpha channel intact. */ - ^= (((unsigned int *) src_current)[i]) & 0xffffff; - - /* Proceed to the next row. */ - src_current += src_info->stride; - dst_current += dst_info->stride; - } - } - } - else - { - /* Adjust the source and destination Y. The start is MAX - (dst_y, gc->clip_y_origin); the difference between that value - and dst_y is the offset to apply to src_y. */ - - temp = dst_y; - dst_y = MAX (dst_y, gc->clip_y_origin); - src_y += dst_y - temp; - height -= dst_y - temp; - - /* Verify that the bounds are correct. */ - eassert (dst_y + height - <= gc->clip_y_origin + mask_info->height); - eassert (dst_y >= gc->clip_y_origin); - - /* There is a mask. For each scan line... */ - - if (backwards) - { - /* Calculate the number of pixels at the end of the - mask. */ - - mask_offset = dst_x + width; - mask_offset -= mask_info->width + gc->clip_x_origin; - - if (mask_info < 0) - mask_info = 0; - - /* Calculate the last column of the mask that will be - consulted. */ - - temp = dst_x - gc->clip_x_origin; - temp += MIN (mask_info->width - temp, - width - mask_offset); - - if (temp < 0) - return; - - /* Now calculate the last row of the mask that will be - consulted. */ - i = dst_y - gc->clip_y_origin + height; - - /* Turn both into offsets. */ - - if (ckd_mul (&offset, temp, pixel) - || ckd_mul (&offset1, i, mask_info->stride) - || ckd_add (&offset, offset, offset1) - || ckd_add (&start, (uintptr_t) mask, offset)) - return; - - mask = mask_current = (unsigned char *) start; - - for (i = 0; i < height; ++i) - { - /* Skip backwards past the end of the mask. */ - - long_src = (unsigned int *) (src_current - mask_offset * pixel); - long_dst = (unsigned int *) (dst_current - mask_offset * pixel); - mask = mask_current; - - /* For each pixel covered by the mask... */ - temp = MIN (mask_info->width - temp, width - mask_offset); - while (temp--) - /* XOR the source to the destination, masked by the - mask. */ - *long_dst-- ^= ((*(long_src--) & (0u - (*(mask--) & 1))) - & 0xffffff); - - /* Return to the last row. */ - src_current -= src_info->stride; - dst_current -= dst_info->stride; - mask_current -= mask_info->stride; - } - } - else - { - /* Calculate the first column of the mask that will be - consulted. */ - - mask_offset = dst_x - gc->clip_x_origin; - - /* Adjust the mask by that much. */ - - if (mask_offset > 0) - mask += mask_offset; - else - { - /* Offset src and dst by the mask offset. */ - src_current += -mask_offset * pixel; - dst_current += -mask_offset * pixel; - width -= mask_offset; - } - - /* Now move mask to the position of the first row. */ - - mask += gc->clip_y_origin * mask_info->stride; - - for (i = 0; i < height; ++i) - { - long_src = (unsigned int *) src_current; - long_dst = (unsigned int *) dst_current; - mask_current = mask; - - if (mask_offset > 0) - { - /* Copy bytes according to the mask. */ - temp = MIN (mask_info->width - mask_offset, width); - while (temp--) - *long_dst++ ^= ((*(long_src++) - & (0u - (*(mask_current++) & 1))) - & 0xffffff); - } - else - { - /* Copy bytes according to the mask. */ - temp = MIN (mask_info->width, width); - while (temp--) - *long_dst++ = ((*(long_src++) - & (0u - (*(mask_current++) & 1))) - & 0xffffff); - } - - src_current += src_info->stride; - dst_current += dst_info->stride; - mask += mask_info->stride; - } - } - } -#endif /* 0 */ -} - void android_copy_area (android_drawable src, android_drawable dest, struct android_gc *gc, int src_x, int src_y, @@ -4763,10 +4483,10 @@ android_copy_area (android_drawable src, android_drawable dest, do_blit = android_blit_copy; break; - case ANDROID_GC_XOR: - do_blit = android_blit_xor; - break; - + /* case ANDROID_GC_INVERT: */ + /* do_blit = android_blit_invert; */ + /* A GC with its operation set to ANDROID_GC_INVERT is never given + to CopyArea. */ default: emacs_abort (); } diff --git a/src/androidgui.h b/src/androidgui.h index 5e4f6ec3989..3b3e08ca024 100644 --- a/src/androidgui.h +++ b/src/androidgui.h @@ -56,7 +56,7 @@ struct android_point enum android_gc_function { ANDROID_GC_COPY = 0, - ANDROID_GC_XOR = 1, + ANDROID_GC_INVERT = 1, }; enum android_gc_value_mask diff --git a/src/androidterm.c b/src/androidterm.c index f849f0d9919..2979e5c1401 100644 --- a/src/androidterm.c +++ b/src/androidterm.c @@ -151,14 +151,8 @@ android_flash (struct frame *f) fd_set fds; block_input (); - - values.function = ANDROID_GC_XOR; - values.foreground = (FRAME_FOREGROUND_PIXEL (f) - ^ FRAME_BACKGROUND_PIXEL (f)); - - gc = android_create_gc ((ANDROID_GC_FUNCTION - | ANDROID_GC_FOREGROUND), - &values); + values.function = ANDROID_GC_INVERT; + gc = android_create_gc (ANDROID_GC_FUNCTION, &values); /* Get the height not including a menu bar widget. */ int height = FRAME_PIXEL_HEIGHT (f); commit d3e95fcae9078a0ea8fcb15a4aee417e6e546ee5 Author: Po Lu Date: Thu May 2 10:23:09 2024 +0800 Switch to GXinvert in XTflash * src/xterm.c (XTflash): Move to inverting the regions of the display being flashed. Suggested by Manuel Giraud . diff --git a/src/xterm.c b/src/xterm.c index c6cc4a9cae6..44f0cc55fd7 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -11550,19 +11550,9 @@ XTflash (struct frame *f) int fd, rc; block_input (); - - if (FRAME_X_VISUAL_INFO (f)->class == TrueColor) - { - values.function = GXxor; - values.foreground = (FRAME_FOREGROUND_PIXEL (f) - ^ FRAME_BACKGROUND_PIXEL (f)); - - gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - GCFunction | GCForeground, &values); - } - else - gc = FRAME_X_OUTPUT (f)->normal_gc; - + values.function = GXinvert; + gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + GCFunction, &values); /* Get the height not including a menu bar widget. */ int height = FRAME_PIXEL_HEIGHT (f); @@ -11649,8 +11639,7 @@ XTflash (struct frame *f) flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); - if (FRAME_X_VISUAL_INFO (f)->class == TrueColor) - XFreeGC (FRAME_X_DISPLAY (f), gc); + XFreeGC (FRAME_X_DISPLAY (f), gc); x_flush (f); unblock_input (); commit bcaf946cb143f9d2e5c17c89012c4f9f7541379a Author: Po Lu Date: Thu May 2 09:54:16 2024 +0800 ; * doc/emacs/android.texi (Android Startup): Correct wording. diff --git a/doc/emacs/android.texi b/doc/emacs/android.texi index 71bc6540760..84cb6445c96 100644 --- a/doc/emacs/android.texi +++ b/doc/emacs/android.texi @@ -148,7 +148,7 @@ attempts to open the file with the wrapper will fail. system provides access to outside the normal filesystem APIs. Emacs uses pseudo-directories named @file{/content/by-authority} and @file{/content/by-authority-named} to access those files. Do not make -any assumptions about the contents of this directory, or try to open +any assumptions about the contents of these directories, or try to open files in it yourself. This feature is not provided on Android 4.3 and earlier, in which commit 08a38d6e7aad1c918b95801402de189aeaf64da5 Author: Po Lu Date: Thu May 2 09:51:31 2024 +0800 ; Update commentary in intervals.h * src/intervals.h (INTERVAL_GENERALLY_WRITABLE_P) (INTERVAL_EXPRESSLY_WRITABLE_P): Mention significance of RO. diff --git a/src/intervals.h b/src/intervals.h index 5c6ef33a3a9..4ddb7f12b92 100644 --- a/src/intervals.h +++ b/src/intervals.h @@ -205,15 +205,15 @@ set_interval_plist (INTERVAL i, Lisp_Object plist) (i && NILP (textget ((i)->plist, Qinvisible))) /* Is this interval writable by virtue of not being marked read-only, or - a general value of Vinhibit_read_only? Replace later with cache - access. */ + a general value of Vinhibit_read_only (which is read from the value + provided as RO)? Replace later with cache access. */ #define INTERVAL_GENERALLY_WRITABLE_P(i, ro) \ (NILP (ro) || (!NILP (Vinhibit_read_only) \ && !CONSP (Vinhibit_read_only))) /* Is this interval writable by virtue of an explicit inhibit-read-only - property, or the specific presence of its Qread_only property in - Vinhibit_read_only? */ + property, or the specific presence of its Qread_only property (which + is read from the value provided as RO) in Vinhibit_read_only? */ #define INTERVAL_EXPRESSLY_WRITABLE_P(i, ro) \ (!NILP (textget ((i)->plist, Qinhibit_read_only)) \ || (!NILP (ro) \ commit 468f3f1cb44b8807c49add4235af3fe20ea7a73b Author: Andrea Corallo Date: Wed May 1 14:14:01 2024 -0400 (disassemble): Fix case of `(byte-code ...)` argument * lisp/emacs-lisp/disass.el (disassemble): Handle (byte-code ...) here.. (disassemble-internal): ...instead of here. (disassemble-1): Adjust text to reflect the existence of other compiled functions. diff --git a/lisp/emacs-lisp/disass.el b/lisp/emacs-lisp/disass.el index 60881ab176b..91427166137 100644 --- a/lisp/emacs-lisp/disass.el +++ b/lisp/emacs-lisp/disass.el @@ -64,8 +64,11 @@ redefine OBJECT if it is a symbol." obarray 'fboundp t nil nil def)) nil 0 t))) (let ((lb lexical-binding)) - (if (and (consp object) (not (functionp object))) - (setq object `(lambda () ,object))) + (when (and (consp object) (not (eq (car object) 'lambda))) + (setq object + (if (eq (car object) 'byte-code) + (apply #'make-byte-code 0 (cdr object)) + `(lambda () ,object)))) (or indent (setq indent 0)) ;Default indent to zero (save-excursion (if (or interactive-p (null buffer)) @@ -113,8 +116,6 @@ redefine OBJECT if it is a symbol." (if (eq (car-safe obj) 'macro) ;Handle macros. (setq macro t obj (cdr obj))) - (if (eq (car-safe obj) 'byte-code) - (setq obj `(lambda () ,obj))) (when (or (consp obj) (interpreted-function-p obj)) (unless (functionp obj) (error "Not a function")) (if interactive-p (message (if name @@ -263,7 +264,7 @@ OBJ should be a call to BYTE-CODE generated by the byte compiler." (and (eq (car-safe arg) 'macro) (byte-code-function-p (cdr arg)))) (cond ((byte-code-function-p arg) - (insert "\n")) + (insert "\n")) (t (insert "\n"))) (disassemble-internal arg commit f68e9172735963950428eafc466fd10473fca7c1 Author: Philip Kaludercic Date: Sat Mar 9 08:11:03 2024 +0100 Add Compat as an Eglot dependency * lisp/progmodes/eglot.el (eglot--format-markup): Remove fboundp check for 'text-property-search-forward'. (eglot-alternatives): Use Compat's 'executable-find' (eglot--executable-find): Remove function. Additionally this should make 'package-get-version' available for releases of Emacs previous to 27.1. (bug#62198) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 6896baf30ce..a2ef0599305 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -7,7 +7,7 @@ ;; Maintainer: João Távora ;; URL: https://github.com/joaotavora/eglot ;; Keywords: convenience, languages -;; Package-Requires: ((emacs "26.3") (jsonrpc "1.0.24") (flymake "1.2.1") (project "0.9.8") (xref "1.6.2") (eldoc "1.14.0") (seq "2.23") (external-completion "0.1")) +;; Package-Requires: ((emacs "26.3") (jsonrpc "1.0.24") (flymake "1.2.1") (project "0.9.8") (xref "1.6.2") (eldoc "1.14.0") (seq "2.23") (external-completion "0.1") (compat "27.1")) ;; This is a GNU ELPA :core package. Avoid adding functionality ;; that is not available in the version of Emacs recorded above or any @@ -111,6 +111,7 @@ (require 'diff-mode) (require 'diff) (require 'track-changes nil t) +(require 'compat) ;; These dependencies are also GNU ELPA core packages. Because of ;; bug#62576, since there is a risk that M-x package-install, despite @@ -190,8 +191,8 @@ path of the PROGRAM that was chosen (interactively or automatically)." (lambda (&optional interactive _project) ;; JT@2021-06-13: This function is way more complicated than it - ;; could be because it accounts for the fact that - ;; `eglot--executable-find' may take much longer to execute on + ;; could be because it accounts for the fact that Compat's + ;; `executable-find' may take much longer to execute on ;; remote files. (let* ((listified (cl-loop for a in alternatives collect (if (listp a) a (list a)))) @@ -203,7 +204,7 @@ automatically)." nil) (interactive (let* ((augmented (mapcar (lambda (a) - (let ((found (eglot--executable-find + (let ((found (compat-call executable-find (car a) t))) (and found (cons (car a) (cons found (cdr a)))))) @@ -223,7 +224,7 @@ automatically)." nil)))) (t (cl-loop for (p . args) in listified - for probe = (eglot--executable-find p t) + for probe = (compat-call executable-find p t) when probe return (cons probe args) finally (funcall err))))))) @@ -600,11 +601,6 @@ It is nil if Eglot is not byte-complied.") (defconst eglot--{} (make-hash-table :size 0) "The empty JSON object.") -(defun eglot--executable-find (command &optional remote) - "Like Emacs 27's `executable-find', ignore REMOTE on Emacs 26." - (if (>= emacs-major-version 27) (executable-find command remote) - (executable-find command))) - (defun eglot--accepted-formats () (if (and (not eglot-prefer-plaintext) (fboundp 'gfm-view-mode)) ["markdown" "plaintext"] ["plaintext"])) @@ -1324,7 +1320,7 @@ be guessed." main-mode base-prompt)) ((and program (not (file-name-absolute-p program)) - (not (eglot--executable-find program t))) + (not (compat-call executable-find program t))) (if full-program-invocation (concat (format "[eglot] I guess you want to run `%s'" full-program-invocation) @@ -1881,10 +1877,9 @@ Doubles as an indicator of snippet support." (font-lock-ensure) (goto-char (point-min)) (let ((inhibit-read-only t)) - (when (fboundp 'text-property-search-forward) ;; FIXME: use compat - (while (setq match (text-property-search-forward 'invisible)) - (delete-region (prop-match-beginning match) - (prop-match-end match))))) + (while (setq match (text-property-search-forward 'invisible)) + (delete-region (prop-match-beginning match) + (prop-match-end match)))) (string-trim (buffer-string)))))) (defun eglot--read-server (prompt &optional dont-if-just-the-one) commit 83bdeee92b0c8bf27ff18f99f3414c725308d2ed Author: Po Lu Date: Wed May 1 21:34:50 2024 +0800 Fix minor typos in haikuterm.c * src/haikuterm.c (haiku_fill_underline) (haiku_draw_text_decoration): Don't pass view to unused frame parameter. diff --git a/src/haikuterm.c b/src/haikuterm.c index b960e36ef26..09d70230bab 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -856,7 +856,7 @@ haiku_fill_underline (struct frame *f, struct glyph_string *s, void *view; segment = thickness * 3; - view = FRAME_HAIKU_VIEW (s->f); + view = FRAME_HAIKU_VIEW (f); switch (style) { @@ -989,7 +989,7 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face, s->underline_thickness = thickness; s->underline_position = position; - haiku_fill_underline (view, s, s->face->underline, + haiku_fill_underline (s->f, s, s->face->underline, position, thickness); /* Place a second underline above the first if this was @@ -999,7 +999,7 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face, { /* Compute the position of the second underline. */ position = position - thickness - 1; - haiku_fill_underline (view, s, s->face->underline, + haiku_fill_underline (s->f, s, s->face->underline, position, thickness); } } commit a5f57a86347eb950d201875cb8bba92d424611db Author: Po Lu Date: Wed May 1 22:02:15 2024 +0800 Implement dots and dashes on Nextstep * src/Makefile.in (NON_OBJC_CFLAGS): Add -Wstrict-flex-arrays. * src/nsterm.m (ns_draw_dash, ns_fill_underline): New functions. (ns_draw_text_decoration): Port dash and dot display from X. diff --git a/src/Makefile.in b/src/Makefile.in index 747ec7d406f..e839a74dabf 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -417,7 +417,8 @@ pdmp := endif # Flags that might be in WARN_CFLAGS but are not valid for Objective C. -NON_OBJC_CFLAGS = -Wignored-attributes -Wignored-qualifiers -Wopenmp-simd -Wnested-externs +NON_OBJC_CFLAGS = -Wignored-attributes -Wignored-qualifiers -Wopenmp-simd \ + -Wnested-externs -Wstrict-flex-arrays # Ditto, but for C++. NON_CXX_CFLAGS = -Wmissing-prototypes -Wnested-externs -Wold-style-definition \ -Wstrict-prototypes -Wno-override-init diff --git a/src/nsterm.m b/src/nsterm.m index bd4010f2844..71fa6e22164 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -3310,7 +3310,66 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. [[NSGraphicsContext currentContext] restoreGraphicsState]; } +/* Draw a dashed underline of thickness THICKNESS and width WIDTH onto + the focused frame at a vertical offset of OFFSET from the position of + the glyph string S, with each segment SEGMENT pixels in length. */ +static void +ns_draw_dash (struct glyph_string *s, int width, int segment, + int offset, int thickness) +{ + CGFloat pattern[2], y_center = s->ybase + offset + thickness / 2.0; + NSBezierPath *path = [[NSBezierPath alloc] init]; + + pattern[0] = segment; + pattern[1] = segment; + + [path setLineDash: pattern count: 2 phase: (CGFloat) s->x]; + [path setLineWidth: thickness]; + [path moveToPoint: NSMakePoint (s->x, y_center)]; + [path lineToPoint: NSMakePoint (s->x + width, y_center)]; + [path stroke]; + [path release]; +} + +/* Draw an underline of STYLE onto the focused frame at an offset of + POSITION from the baseline of the glyph string S, S->WIDTH in length, + and THICKNESS in height. */ + +static void +ns_fill_underline (struct glyph_string *s, enum face_underline_type style, + int position, int thickness) +{ + int segment; + NSRect rect; + + segment = thickness * 3; + + switch (style) + { + /* FACE_UNDERLINE_DOUBLE_LINE is treated identically to SINGLE, as + the second line will be filled by another invocation of this + function. */ + case FACE_UNDERLINE_SINGLE: + case FACE_UNDERLINE_DOUBLE_LINE: + rect = NSMakeRect (s->x, s->ybase + position, s->width, thickness); + NSRectFill (rect); + break; + + case FACE_UNDERLINE_DOTS: + segment = thickness; + FALLTHROUGH; + + case FACE_UNDERLINE_DASHES: + ns_draw_dash (s, s->width, segment, position, thickness); + break; + + case FACE_NO_UNDERLINE: + case FACE_UNDERLINE_WAVE: + default: + emacs_abort (); + } +} static void ns_draw_text_decoration (struct glyph_string *s, struct face *face, @@ -3337,18 +3396,14 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. ns_draw_underwave (s, width, x); } - else if (s->face->underline == FACE_UNDERLINE_SINGLE - || s->face->underline == FACE_UNDERLINE_DOUBLE_LINE) + else if (face->underline >= FACE_UNDERLINE_SINGLE) { - - NSRect r; unsigned long thickness, position; /* If the prev was underlined, match its appearance. */ if (s->prev - && ((s->prev->face->underline == FACE_UNDERLINE_SINGLE) - || (s->prev->face->underline - == FACE_UNDERLINE_DOUBLE_LINE)) + && (s->prev->face->underline != FACE_UNDERLINE_WAVE + && s->prev->face->underline >= FACE_UNDERLINE_SINGLE) && s->prev->underline_thickness > 0 && (s->prev->face->underline_at_descent_line_p == s->face->underline_at_descent_line_p) @@ -3414,12 +3469,11 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. s->underline_thickness = thickness; s->underline_position = position; - r = NSMakeRect (x, s->ybase + position, width, thickness); - if (!face->underline_defaulted_p) [[NSColor colorWithUnsignedLong:face->underline_color] set]; - NSRectFill (r); + ns_fill_underline (s, s->face->underline, position, + thickness); /* Place a second underline above the first if this was requested in the face specification. */ @@ -3428,8 +3482,8 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. { /* Compute the position of the second underline. */ position = position - thickness - 1; - r = NSMakeRect (x, s->ybase + position, width, thickness); - NSRectFill (r); + ns_fill_underline (s, s->face->underline, position, + thickness); } } } commit 04635f399b01925b8ed6bcf555e2f528cba2e401 Author: Basil L. Contovounesios Date: Wed May 1 13:08:30 2024 +0200 ; Silence obsoletion warning in mwheel-tests. diff --git a/test/lisp/mwheel-tests.el b/test/lisp/mwheel-tests.el index 2b0f0ff384a..f60b9ecd3b0 100644 --- a/test/lisp/mwheel-tests.el +++ b/test/lisp/mwheel-tests.el @@ -23,10 +23,12 @@ (require 'mwheel) (ert-deftest mwheel-test-enable/disable () - (mouse-wheel-mode 1) - (should (eq (lookup-key (current-global-map) `[,mouse-wheel-up-event]) 'mwheel-scroll)) - (mouse-wheel-mode -1) - (should (eq (lookup-key (current-global-map) `[,mouse-wheel-up-event]) nil))) + (with-suppressed-warnings ((obsolete mouse-wheel-up-event)) + (mouse-wheel-mode 1) + (should (eq (lookup-key (current-global-map) `[,mouse-wheel-up-event]) + 'mwheel-scroll)) + (mouse-wheel-mode -1) + (should-not (lookup-key (current-global-map) `[,mouse-wheel-up-event])))) (ert-deftest mwheel-test--create-scroll-keys () (should (equal (mouse-wheel--create-scroll-keys 10 'mouse-4) commit f804a492bf890b53d704809bd8cf6306f9c17d76 Author: Basil L. Contovounesios Date: Wed May 1 13:07:17 2024 +0200 ; Update pvec_type hash for CHECK_STRUCTS This follows commit 2fa839c1886 of 2024-04-28 "(COMPILED): Rename to CLOSURE". diff --git a/src/pdumper.c b/src/pdumper.c index 2963efc56ab..65da3feff75 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -3050,7 +3050,7 @@ dump_vectorlike (struct dump_context *ctx, Lisp_Object lv, dump_off offset) { -#if CHECK_STRUCTS && !defined HASH_pvec_type_2D583AC566 +#if CHECK_STRUCTS && !defined HASH_pvec_type_99104541E2 # error "pvec_type changed. See CHECK_STRUCTS comment in config.h." #endif const struct Lisp_Vector *v = XVECTOR (lv); commit 65fa47e3fa15c5553974a6d99080f21b4117245b Author: Basil L. Contovounesios Date: Tue Apr 30 08:31:58 2024 +0200 Assume match before calling help-xref-button help-xref-button fails if not preceded by a valid match, so a preceding unconditional search should not be allowed to fail silently. * lisp/emacs-lisp/ert.el (ert-describe-test): * lisp/help-fns.el (help-fns--compiler-macro) (help-fns-function-description-header, describe-variable) (help-fns--customize-variable, describe-face) (help-fns--face-attributes, describe-keymap): Let unconditional re-search-backward before help-xref-button fail early, as that would indicate a logic bug, and the backtrace would more accurately point to the actual source of the mistake. diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el index 8ab57d2b238..6a665c8181d 100644 --- a/lisp/emacs-lisp/ert.el +++ b/lisp/emacs-lisp/ert.el @@ -2816,8 +2816,7 @@ To be used in the ERT results buffer." (insert (format-message " defined in `%s'" (file-name-nondirectory file-name))) (save-excursion - (re-search-backward (substitute-command-keys "`\\([^`']+\\)'") - nil t) + (re-search-backward (substitute-command-keys "`\\([^`']+\\)'")) (help-xref-button 1 'help-function-def test-name file-name))) (insert ".") (fill-region-as-paragraph (point-min) (point)) diff --git a/lisp/help-fns.el b/lisp/help-fns.el index cfe27077055..9bf2f61aee6 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -658,16 +658,14 @@ the C sources, too." (progn (insert (format-message " `%s'" handler)) (save-excursion - (re-search-backward (substitute-command-keys "`\\([^`']+\\)'") - nil t) + (re-search-backward (substitute-command-keys "`\\([^`']+\\)'")) (help-xref-button 1 'help-function handler))) ;; FIXME: Obsolete since 24.4. (let ((lib (get function 'compiler-macro-file))) (when (stringp lib) (insert (format-message " in `%s'" lib)) (save-excursion - (re-search-backward (substitute-command-keys "`\\([^`']+\\)'") - nil t) + (re-search-backward (substitute-command-keys "`\\([^`']+\\)'")) (help-xref-button 1 'help-function-cmacro function lib))))))) (unless (bolp) (insert ". See " @@ -1132,8 +1130,7 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)." (setq help-mode--current-data (list :symbol function :file file-name)) (save-excursion - (re-search-backward (substitute-command-keys "`\\([^`']+\\)'") - nil t) + (re-search-backward (substitute-command-keys "`\\([^`']+\\)'")) (help-xref-button 1 'help-function-def function file-name)))) (princ ".")))) @@ -1332,8 +1329,7 @@ it is displayed along with the global value." :file file-name)) (save-excursion (re-search-backward (substitute-command-keys - "`\\([^`']+\\)'") - nil t) + "`\\([^`']+\\)'")) (help-xref-button 1 'help-variable-def variable file-name))) (if valvoid @@ -1572,8 +1568,7 @@ This cancels value editing without updating the value." (princ (concat " You can " customize-label (or text " this variable."))) (with-current-buffer standard-output (save-excursion - (re-search-backward - (concat "\\(" customize-label "\\)") nil t) + (re-search-backward (concat "\\(" customize-label "\\)")) (help-xref-button 1 'help-customize-variable variable))) (terpri)))) @@ -1803,8 +1798,7 @@ If FRAME is omitted or nil, use the selected frame." "\n\n")) (with-current-buffer standard-output (save-excursion - (re-search-backward - (concat "\\(" customize-label "\\)") nil t) + (re-search-backward (concat "\\(" customize-label "\\)")) (help-xref-button 1 'help-customize-face f))) (setq file-name (find-lisp-object-file-name f 'defface)) (if (not file-name) @@ -1817,7 +1811,7 @@ If FRAME is omitted or nil, use the selected frame." ;; Make a hyperlink to the library. (save-excursion (re-search-backward - (substitute-command-keys "`\\([^`']+\\)'") nil t) + (substitute-command-keys "`\\([^`']+\\)'")) (help-xref-button 1 'help-face-def f file-name)) (princ ".") (terpri) @@ -1864,7 +1858,7 @@ If FRAME is omitted or nil, use the selected frame." (not (eq attr 'unspecified))) ;; Make a hyperlink to the parent face. (save-excursion - (re-search-backward ": \\([^:]+\\)" nil t) + (re-search-backward ": \\([^:]+\\)") (help-xref-button 1 'help-face attr))) (insert "\n"))) (terpri))) @@ -2115,9 +2109,7 @@ keymap value." "C source code" (help-fns-short-filename file-name)))) (save-excursion - (re-search-backward (substitute-command-keys - "`\\([^`']+\\)'") - nil t) + (re-search-backward (substitute-command-keys "`\\([^`']+\\)'")) (setq help-mode--current-data (list :symbol keymap :file file-name)) (help-xref-button 1 'help-variable-def commit 54dbd8b4fa2253682d044cc53bd658e361bff8a0 Author: Po Lu Date: Wed May 1 15:57:29 2024 +0800 Disable on-screen keyboard outside fields in Custom buffers * lisp/cus-edit.el (Custom-display-on-screen-keyboard-p): New function. (Custom-mode): Install it as the touch-screen-keyboard-function. * lisp/touch-screen.el (touch-screen-keyboard-function): New variable. (touch-screen-handle-point-up): Don't special-case the splash screen with respect to touch-screen-display-keyboard in keeping with user feedback. diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index 1659c285d84..e7d0eaa9215 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -5363,6 +5363,12 @@ If several parents are listed, go to the first of them." (setq-local widget-link-suffix "")) (setq show-trailing-whitespace nil)) +(defvar touch-screen-keyboard-function) ; In touch-screen.el. + +(defun Custom-display-on-screen-keyboard-p () + "Return whether it is okay to display the virtual keyboard at point." + (get-char-property (point) 'field)) + (define-derived-mode Custom-mode nil "Custom" "Major mode for editing customization buffers. @@ -5401,6 +5407,8 @@ if that value is non-nil." custom--hidden-state 'hidden) (setq-local revert-buffer-function #'custom--revert-buffer) (setq-local text-conversion-style 'action) + (setq-local touch-screen-keyboard-function + #'Custom-display-on-screen-keyboard-p) (make-local-variable 'custom-options) (make-local-variable 'custom-local-buffer) (custom--initialize-widget-variables) diff --git a/lisp/touch-screen.el b/lisp/touch-screen.el index e44b266a617..ca02ca3caf6 100644 --- a/lisp/touch-screen.el +++ b/lisp/touch-screen.el @@ -154,6 +154,17 @@ selected.") Used in an attempt to keep this word selected during later dragging.") +;; Should this variable be documented? +(defvar-local touch-screen-keyboard-function nil + "Function that decides whether to display the on screen keyboard. +If set, this function is called with point set to the position of the +tap involved when a command listed in `touch-screen-set-point-commands' +is about to be invoked in response to a tap, the current buffer, or the +text beneath point (in the case of an `inhibit-read-only' text +property), is not read only, and `touch-screen-display-keyboard' is nil, +and should return non-nil if it is appropriate to display the on-screen +keyboard afterwards.") + ;;; Scroll gesture. @@ -1374,18 +1385,22 @@ is not read-only." ;; caller of `read-key-sequence' such as ;; `describe-key'. (throw 'input-event event) - (if (and (or (not buffer-read-only) - ;; Display the on screen - ;; keyboard even if just the - ;; text under point is not - ;; read-only. - (get-text-property point - 'inhibit-read-only) - touch-screen-display-keyboard) - ;; Detect the splash screen and - ;; avoid displaying the on screen - ;; keyboard there. - (not (equal (buffer-name) "*GNU Emacs*"))) + (if (or touch-screen-display-keyboard + (and (or (not buffer-read-only) + inhibit-read-only + ;; Display the on screen + ;; keyboard even if just the + ;; text under point is not + ;; read-only. + (get-text-property + point 'inhibit-read-only)) + ;; If the major mode has defined + ;; bespoke criteria for + ;; displaying the on screen + ;; keyboard, consult it here. + (or (not touch-screen-keyboard-function) + (funcall + touch-screen-keyboard-function)))) ;; Once the on-screen keyboard has been ;; opened, add ;; `touch-screen-window-selection-changed'