From: Stephen Berman Date: Tue, 25 Jun 2024 10:38:03 +0000 (+0200) Subject: Fix tabbing between widgets (bug#70594) X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=0b3f3afcd88051215c041502bb66747ac6eb2cd5;p=emacs.git Fix tabbing between widgets (bug#70594) * lisp/wid-edit.el (widget-move): Don't error when tabbing in a buffer with only one active widget and 'widget-skip-inactive' enabled. Improve code by handling forward and backward movement in a single loop. (cherry picked from commit 2f18929319a4883575acb7440c920ad059a84105) --- diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el index 3b467434d29..b599aa680a4 100644 --- a/lisp/wid-edit.el +++ b/lisp/wid-edit.el @@ -1276,42 +1276,40 @@ This is much faster.") ARG may be negative to move backward. When the second optional argument is non-nil, nothing is shown in the echo area." - (let ((wrapped 0) - (number arg) - (old (widget-tabable-at))) - ;; Forward. - (while (> arg 0) - (cond ((eobp) - (goto-char (point-min)) - (setq wrapped (1+ wrapped))) - (widget-use-overlay-change - (goto-char (next-overlay-change (point)))) - (t - (forward-char 1))) - (and (= wrapped 2) - (eq arg number) - (error "No buttons or fields found")) - (let ((new (widget-tabable-at))) - (when new - (unless (eq new old) - (setq arg (1- arg)) - (setq old new))))) - ;; Backward. - (while (< arg 0) - (cond ((bobp) - (goto-char (point-max)) - (setq wrapped (1+ wrapped))) - (widget-use-overlay-change - (goto-char (previous-overlay-change (point)))) - (t - (backward-char 1))) - (and (= wrapped 2) - (eq arg number) - (error "No buttons or fields found")) - (let ((new (widget-tabable-at))) - (when new - (unless (eq new old) - (setq arg (1+ arg)))))) + (let* ((wrapped 0) + (number arg) + (fwd (> arg 0)) ; widget-forward is caller. + (bwd (< arg 0)) ; widget-backward is caller. + (old (widget-tabable-at)) + (tabable (if old 1 0)) + pos) + (catch 'one + (while (> (abs arg) 0) + (cond ((or (and fwd (eobp)) (and bwd (bobp))) + (goto-char (cond (fwd (point-min)) + (bwd (point-max)))) + (setq wrapped (1+ wrapped))) + (widget-use-overlay-change + (goto-char (cond (fwd (next-overlay-change (point))) + (bwd (previous-overlay-change (point)))))) + (t + (cond (fwd (forward-char 1)) + (bwd (backward-char 1))))) + (and (= wrapped 2) + (eq arg number) + (if (= tabable 1) + (progn + (goto-char pos) + (throw 'one (message "Only one tabable widget"))) + (error "No buttons or fields found"))) + (let ((new (widget-tabable-at))) + (when new + (if (eq new old) + (setq pos (point)) + (cl-incf tabable) + (setq arg (cond (fwd (1- arg)) + (bwd (1+ arg)))) + (setq old new)))))) (let ((new (widget-tabable-at))) (while (and (eq (widget-tabable-at) new) (not (bobp))) (backward-char)))