commit 8762f6c7c974d028816a74169e3d6fdecaec8d6d (HEAD, refs/remotes/origin/master) Author: Jim Porter Date: Thu Oct 3 17:24:18 2024 -0700 Don't add visual-wrap-prefix properties to unsafe multi-line display specs This makes sure we don't interfere with other display specs, e.g. for images displayed in 'image-mode' (bug#73600). * lisp/visual-wrap.el (visual-wrap--safe-display-specs): New variable. (visual-wrap--display-property-safe-p): New function. (visual-wrap--apply-to-line): Use 'pos-eol'; we don't want to respect field boundaries here. (visual-wrap-prefix-function): Check for unsafe display properties at the end of the line and skip past them if present. * test/lisp/visual-wrap-tests.el: New test file. diff --git a/lisp/visual-wrap.el b/lisp/visual-wrap.el index f2a186ce320..b921e1f0549 100644 --- a/lisp/visual-wrap.el +++ b/lisp/visual-wrap.el @@ -73,6 +73,36 @@ extra indent = 2 (face-extend-p face nil t) (face-background face nil t))))) +(defvar visual-wrap--safe-display-specs + '(height raise) + "A list of display specs that don't interfere with wrap prefixes. +A \"safe\" display spec is one that won't interfere with the additional +text properties that `visual-wrap-prefix-mode' uses. + +Specs that replace the text are unsafe, since they generally determine +the range of text to replace via `eq'. If `visual-wrap-prefix-mode' +were to add text properties to some subset of this range, it would +violate this assumption.") + +(defun visual-wrap--display-property-safe-p (display) + "Return non-nil if the display property DISPLAY is \"safe\". +A \"safe\" display property is one where all the display specs are +members of `visual-wrap--safe-display-specs' (which see)." + ;; The display property could be a single display spec; if so, wrap it + ;; in a list so we can iterate over it in our loop below. + (when (and (consp display) (not (consp (car display)))) + (setq display (list display))) + ;; Loop over all the display specs to check if they're safe. Assume + ;; any display property other than a vector or list (e.g. a string) is + ;; unsafe. + (when (or (vectorp display) (listp display)) + (not (catch 'unsafe + (mapc (lambda (spec) + (unless (memq (car-safe spec) + visual-wrap--safe-display-specs) + (throw 'unsafe t))) + display))))) + (defun visual-wrap--prefix-face (fcp _beg end) ;; If the fill-context-prefix already specifies a face, just use that. (cond ((get-text-property 0 'face fcp)) @@ -128,11 +158,11 @@ extra indent = 2 ;; the buffer.) (add-display-text-property position (min (+ position (length first-line-prefix)) - (line-end-position)) + (pos-eol)) 'min-width `((,next-line-prefix . width)))) (setq next-line-prefix (visual-wrap--adjust-prefix next-line-prefix)) (put-text-property - position (line-end-position) 'wrap-prefix + position (pos-eol) 'wrap-prefix (if (numberp next-line-prefix) `(space :align-to (,next-line-prefix . width)) next-line-prefix))))) @@ -209,8 +239,27 @@ by `visual-wrap-extra-indent'." (forward-line 0) (setq beg (point)) (while (< (point) end) - (visual-wrap--apply-to-line (point)) - (forward-line)) + ;; Check if the display property at the end of this line is "safe". + (if (visual-wrap--display-property-safe-p + (get-char-property (pos-eol) 'display)) + ;; If so, we can apply our visual wrapping properties to this + ;; line and continue to the next line. + (progn + (visual-wrap--apply-to-line (point)) + (forward-line)) + ;; Otherwise, skip ahead until the end of any unsafe display + ;; properties. NOTE: We do this out of an abundance of caution to + ;; be as certain as possible that we're not interfering with the + ;; display engine. If this results in cases where we fail to add + ;; wrapping properties when we should, then we should remove the + ;; `while' loop below. Without that loop, this should be the same + ;; logic `handle_single_display_spec' in xdisp.c uses for + ;; determining what text to replace. See bug#73600. + (goto-char (next-single-char-property-change (pos-eol) 'display)) + (while (not (visual-wrap--display-property-safe-p + (get-char-property (point) 'display))) + (goto-char (next-single-char-property-change (point) 'display))) + (unless (bolp) (forward-line 1)))) `(jit-lock-bounds ,beg . ,end)) ;;;###autoload diff --git a/test/lisp/visual-wrap-tests.el b/test/lisp/visual-wrap-tests.el new file mode 100644 index 00000000000..04977afe207 --- /dev/null +++ b/test/lisp/visual-wrap-tests.el @@ -0,0 +1,120 @@ +;;; visual-wrap-tests.el --- Tests for `visual-wrap-prefix-mode' -*- lexical-binding: t; -*- + +;; Copyright (C) 2024 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; Tets for `visual-wrap-prefix-mode'. + +;;; Code: + +(require 'visual-wrap) +(require 'ert) + +;;; Tests: + +(ert-deftest visual-wrap-tests/simple () + "Test adding wrapping properties to text without display properties." + (with-temp-buffer + (insert "greetings\n* hello\n* hi") + (visual-wrap-prefix-function (point-min) (point-max)) + (should (equal-including-properties + (buffer-string) + #("greetings\n* hello\n* hi" + 10 12 ( wrap-prefix (space :align-to (2 . width)) + display (min-width ((2 . width)))) + 12 17 ( wrap-prefix (space :align-to (2 . width))) + 18 20 ( wrap-prefix (space :align-to (2 . width)) + display (min-width ((2 . width)))) + 20 22 ( wrap-prefix (space :align-to (2 . width)))))))) + +(ert-deftest visual-wrap-tests/safe-display () + "Test adding wrapping properties to text with safe display properties." + (with-temp-buffer + (insert #("* hello" 2 7 (display (raise 1)))) + (visual-wrap-prefix-function (point-min) (point-max)) + (should (equal-including-properties + (buffer-string) + #("* hello" + 0 2 ( wrap-prefix (space :align-to (2 . width)) + display (min-width ((2 . width)))) + 2 7 ( wrap-prefix (space :align-to (2 . width)) + display (raise 1))))))) + +(ert-deftest visual-wrap-tests/unsafe-display/within-line () + "Test adding wrapping properties to text with unsafe display properties. +When these properties don't extend across multiple lines, +`visual-wrap-prefix-mode' can still add wrapping properties." + (with-temp-buffer + (insert #("* [img]" 2 7 (display (image :type bmp)))) + (visual-wrap-prefix-function (point-min) (point-max)) + (should (equal-including-properties + (buffer-string) + #("* [img]" + 0 2 ( wrap-prefix (space :align-to (2 . width)) + display (min-width ((2 . width)))) + 2 7 ( wrap-prefix (space :align-to (2 . width)) + display (image :type bmp))))))) + +(ert-deftest visual-wrap-tests/unsafe-display/spanning-lines () + "Test adding wrapping properties to text with unsafe display properties. +When these properties do extend across multiple lines, +`visual-wrap-prefix-mode' must avoid adding wrapping properties." + (with-temp-buffer + (insert #("* a\n* b" 0 7 (display (image :type bmp)))) + (visual-wrap-prefix-function (point-min) (point-max)) + (should (equal-including-properties + (buffer-string) + #("* a\n* b" 0 7 (display (image :type bmp))))))) + +(ert-deftest visual-wrap-tests/unsafe-display/multiple-1 () + "Test adding wrapping properties to text with unsafe display properties. +This tests a multi-line unsafe display prop immediately followed by a +single-line unsafe display prop. `visual-wrap-prefix-mode' should *not* +add wrapping properties to either block." + (with-temp-buffer + (insert #("* a\n* b" + 0 4 (display ((image :type bmp))) + 4 7 (display ((image :type bmp) (height 1.5))))) + (visual-wrap-prefix-function (point-min) (point-max)) + (should (equal-including-properties + (buffer-string) + ;; NOTE: See the note in `visual-wrap-prefix-function'. If + ;; applying the change mentioned there, then this case + ;; should add wrapping properties to the second block. + #("* a\n* b" + 0 4 (display ((image :type bmp))) + 4 7 (display ((image :type bmp) (height 1.5)))))))) + +(ert-deftest visual-wrap-tests/unsafe-display/multiple-2 () + "Test adding wrapping properties to text with unsafe display properties. +This tests a multi-line unsafe display prop immediately followed by +another multi-line unsafe display prop. `visual-wrap-prefix-mode' +should *not* add wrapping properties to either block." + (with-temp-buffer + (insert #("* a\n* b\n" + 0 4 (display ((image :type bmp))) + 4 8 (display ((image :type bmp) (height 1.5))))) + (visual-wrap-prefix-function (point-min) (point-max)) + (should (equal-including-properties + (buffer-string) + #("* a\n* b\n" + 0 4 (display ((image :type bmp))) + 4 8 (display ((image :type bmp) (height 1.5)))))))) + +;; visual-wrap-tests.el ends here commit 3b5226af3f737c82f9bbedd8fbe067bab4b4b67a Author: Eli Zaretskii Date: Mon May 26 19:53:21 2025 +0300 Fix DST time calculations on MS-Windows * src/w32.c (w32_fix_tzset): New function. * src/timefns.c (emacs_localtime_rz, tzlookup): * src/w32.c (sys_localtime): Call 'w32_fix_tzset'. (Bug#11281) diff --git a/src/timefns.c b/src/timefns.c index 4d296ff8dcd..8cf424bbe7e 100644 --- a/src/timefns.c +++ b/src/timefns.c @@ -189,6 +189,7 @@ emacs_localtime_rz (timezone_t tz, time_t const *t, struct tm *tm) display-time) are in real danger of missing timezone and DST changes. Calling tzset before each localtime call fixes that. */ tzset (); + w32_fix_tzset (); #endif tm = localtime_rz (tz, t, tm); if (!tm && errno == ENOMEM) @@ -306,6 +307,9 @@ tzlookup (Lisp_Object zone, bool settz) block_input (); emacs_setenv_TZ (zone_string); tzset (); +#ifdef WINDOWSNT + w32_fix_tzset (); +#endif timezone_t old_tz = local_tz; local_tz = new_tz; tzfree (old_tz); diff --git a/src/w32.c b/src/w32.c index 5de721ad71f..9e17c2e5fbb 100644 --- a/src/w32.c +++ b/src/w32.c @@ -10289,6 +10289,30 @@ w32_read_registry (HKEY rootkey, Lisp_Object lkey, Lisp_Object lname) } +/* mingw.org's MinGW doesn't declare _dstbias. MinGW64 defines it as a + macro. */ +#ifndef _dstbias +__MINGW_IMPORT int _dstbias; +#endif + +/* Fix a bug in MS implementation of 'tzset'. This function should be + called immediately after 'tzset'. */ +void +w32_fix_tzset (void) +{ + char *tz_env = getenv ("TZ"); + + /* When TZ is defined in the environment, '_tzset' updates _daylight, + but not _dstbias. Then if we are switching from a timezone without + DST to a timezone with DST, 'localtime' and friends will apply zero + DST bias, which is incorrect. (When TZ is not defined, '_tzset' + does update _dstbias using values obtained from Windows API + GetTimeZoneInformation.) Here we fix that blunder by detecting + this situation and forcing _dstbias to be 1 hour. */ + if (tz_env && _daylight && !_dstbias) + _dstbias = -3600; +} + /* The Windows CRT functions are "optimized for speed", so they don't check for timezone and DST changes if they were last called less than 1 minute ago (see http://support.microsoft.com/kb/821231). So @@ -10299,6 +10323,7 @@ struct tm * sys_localtime (const time_t *t) { tzset (); + w32_fix_tzset (); return localtime (t); } diff --git a/src/w32.h b/src/w32.h index ae3999ffcfd..9d9887ec782 100644 --- a/src/w32.h +++ b/src/w32.h @@ -234,6 +234,7 @@ extern int openat (int, const char *, int, int); extern int fchmodat (int, char const *, mode_t, int); extern int lchmod (char const *, mode_t); extern bool symlinks_supported (const char *); +extern void w32_fix_tzset (void); /* Return total and free memory info. */ commit 53371c959462a677a29ee869b3b6627facf3ed79 Author: Xiyue Deng Date: Fri May 16 02:48:52 2025 -0700 Make xoauth2 auth fail when a smtp server replies 334 (Bug#78366) * lisp/mail/smtpmail.el (smtpmail-try-auth-method): Throw error 535 when receiving a "334 server challenge" reply. diff --git a/lisp/mail/smtpmail.el b/lisp/mail/smtpmail.el index 9337ee9401a..2461ddcfd0d 100644 --- a/lisp/mail/smtpmail.el +++ b/lisp/mail/smtpmail.el @@ -642,11 +642,21 @@ USER and PASSWORD should be non-nil." (cl-defmethod smtpmail-try-auth-method (process (_mech (eql 'xoauth2)) user password) - (smtpmail-command-or-throw - process - (concat "AUTH XOAUTH2 " - (base64-encode-string - (concat "user=" user "\1auth=Bearer " password "\1\1") t)))) + (let ((ret (smtpmail-command-or-throw + process + (concat "AUTH XOAUTH2 " + (base64-encode-string + (concat "user=" user "\1auth=Bearer " password "\1\1") + t))))) + (if (eq (car ret) 334) + ;; When a server returns 334 server challenge, it usually means + ;; the credentials it received were wrong (e.g. was an actual + ;; password instead of an access token). In such a case, we + ;; should return a string with 535 to indicate a failure so that + ;; smtpmail will try other authentication mechanisms. See also + ;; https://debbugs.gnu.org/78366. + (throw 'done "535 5.7.8 Authentication credentials invalid") + ret))) (defun smtpmail-response-code (string) (when string