Subject: Re: bug#78474: 31.0.50; Wrong char insertion in rxvt

From: Robert Pluim <[email-masked]>
Date: Mon, 21 Jul 2025 14:12:54 +0200

>>>>> On Thu, 17 Jul 2025 08:30:44 +0300, Eli Zaretskii <[email-masked]> said:

    Eli> Feel free to suggest a patch with such a variable.

See below. I have zero ego about the name of the option.

Perhaps the "stty -tabs" workaround should go into PROBLEMS.

    Eli> We should also think how to make the accessibility-related knobs more
    Eli> discoverable.  Perhaps a new section in the user manual is in order.

Indeed, I didnʼt find a good place to put this. What else would go in
this new node apart from this new user option? `text-scale-increase',
I guess, and discussion of the high-contrast themes.

(did anyone ever (re-)implement sticky modifier keys for Emacs? Thatʼs
about the only thing I miss from XEmacs)

Robert
-- 

diff --git c/etc/NEWS i/etc/NEWS
index f7aebdf538f..637df26d246 100644
--- c/etc/NEWS
+++ i/etc/NEWS
@@ -78,6 +78,13 @@ the 'standard-display-table's extra slots with Unicode characters.
 Please see the documentation of that function to see which slots of the
 display table it changes.
 
++++
+** New user option 'tty-allow-tabs-for-motion'.
+The display optimization where TAB characters may be used to move around
+on a TTY frame can now be disabled by customizing the user option
+'tty-allow-tabs-for-motion' to nil (default t).  This is to accomodate
+screen readers which may interpret those TAB characters literally.
+
 +++
 ** Child frames are now supported on TTY frames.
 This supports use-cases like Posframe, Corfu, and child frames acting
diff --git c/lisp/cus-start.el i/lisp/cus-start.el
index 09364b68e11..d74459657f3 100644
--- c/lisp/cus-start.el
+++ i/lisp/cus-start.el
@@ -602,6 +602,7 @@ minibuffer-prompt-properties--setter
 						    "21.1")
              ;; term.c
              (visible-cursor cursor boolean "22.1")
+             (tty-allow-tabs-for-motion cursor boolean "31.1")
              ;; terminal.c
              (ring-bell-function display
               (choice
diff --git c/src/cm.c i/src/cm.c
index 150d1c9a580..a464fd5d0d4 100644
--- c/src/cm.c
+++ i/src/cm.c
@@ -225,7 +225,8 @@ calccost (struct tty_display_info *tty,
 	goto dodelta;		/* skip all the tab junk */
     }
     /* Tabs (the toughie) */
-    if (tty->Wcm->cc_tab >= BIG || !tty->Wcm->cm_usetabs)
+    if (!tty_allow_tabs_for_motion /* Bug#78474.  */
+	|| tty->Wcm->cc_tab >= BIG || !tty->Wcm->cm_usetabs)
 	goto olddelta;		/* forget it! */
 
     /*
diff --git c/src/term.c i/src/term.c
index 8aa47322d19..acb21c66e05 100644
--- c/src/term.c
+++ i/src/term.c
@@ -5167,6 +5167,17 @@ syms_of_term (void)
 trigger redisplay.  */);
   tty_menu_calls_mouse_position_function = 0;
 
+  DEFVAR_BOOL ("tty-allow-tabs-for-motion", tty_allow_tabs_for_motion,
+    doc: /* Whether TTY frames may use TAB characters for moving around.
+As a display optimization, Emacs may move between two positions on a TTY
+frame by emitting TAB characters, combined with TTY motion commands,
+when this is more efficient than using only motion commands.  These
+characters can interfere with the functioning of some software, such as
+screen readers, which interpret the TAB characters literally.  Set this
+to nil to disable this optimization, but be warned that this may affect
+redisplay performance.  */);
+  tty_allow_tabs_for_motion = 1;
+
   defsubr (&Stty_display_color_p);
   defsubr (&Stty_display_color_cells);
   defsubr (&Stty_no_underline);