# https://invisible-island.net/archives/xterm/patches/xterm-401.patch.gz
# patch by Thomas E. Dickey <dickey@invisible-island.net>
# created  Wed Jul  2 23:36:36 UTC 2025
# ------------------------------------------------------------------------------
# MANIFEST                           |    5 
# VTPrsTbl.c                         |   61 +++++++-
# charproc.c                         |  129 ++++++++++++-----
# ctlseqs.ms                         |   27 ++-
# ctlseqs.txt                        |   73 ++++++---
# fontutils.c                        |    5 
# fontutils.h                        |    6 
# input.c                            |    4 
# menu.h                             |    4 
# misc.c                             |   85 +++++++++--
# package/debian/changelog           |    6 
# package/freebsd/Makefile           |    4 
# package/pkgsrc/Makefile            |    2 
# package/xterm.spec                 |    7 
# ptyx.h                             |   34 ++++
# util.c                             |    5 
# version.h                          |    6 
# xterm-401/vttests/query-allowed.pl |  258 +++++++++++++++++++++++++++++++++++
# xterm.appdata.xml                  |    2 
# xterm.h                            |   11 -
# xterm.log.html                     |   29 +++
# 21 files changed, 642 insertions(+), 121 deletions(-)
# ------------------------------------------------------------------------------
Index: MANIFEST
--- xterm-400+/MANIFEST	2025-06-15 10:21:39.000000000 +0000
+++ xterm-401/MANIFEST	2025-06-23 07:49:26.000000000 +0000
@@ -1,4 +1,4 @@
-MANIFEST for xterm, version xterm-400
+MANIFEST for xterm, version xterm-401
 --------------------------------------------------------------------------------
 MANIFEST                        this file
 256colres.h                     resource-definitions for 256-color mode
@@ -224,7 +224,8 @@
 vttests/palettes.pl             Demonstrate how to set palette colors using xterm's control sequences.
 vttests/paste64.pl              script to test base64-selection option
 vttests/pointer-shapes.sh       exercise xterm's pointer-shape control
-vttests/print-vt-chars.pl       demo-script
+vttests/print-vt-chars.pl       print GL and GR with the same charset
+vttests/query-allowed.pl        demonstrate OSC 60, 61, and 62
 vttests/query-color.pl          demonstrate OSC 4
 vttests/query-dynamic.pl        demonstrate OSC 10 to OSC 19
 vttests/query-fonts.pl          script to demo/test font-querying
Index: VTPrsTbl.c
--- xterm-400+/VTPrsTbl.c	2025-03-17 00:32:09.000000000 +0000
+++ xterm-401/VTPrsTbl.c	2025-06-24 07:40:25.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: VTPrsTbl.c,v 1.126 2025/03/17 00:32:09 tom Exp $ */
+/* $XTermId: VTPrsTbl.c,v 1.131 2025/06/24 07:40:25 tom Exp $ */
 
 /*
  * Copyright 1999-2024,2025 by Thomas E. Dickey
@@ -71,9 +71,39 @@
 #define CASE_DECRQLP CASE_CSI_IGNORE
 #endif
 
-#if !OPT_WIDE_CHARS
-#undef  CASE_ESC_PERCENT
-#define CASE_ESC_PERCENT CASE_ESC_IGNORE
+#if !OPT_DEC_RECTOPS
+#undef  CASE_DECRQCRA
+#define CASE_DECRQCRA CASE_GROUND_STATE
+#undef  CASE_DECCRA
+#define CASE_DECCRA CASE_GROUND_STATE
+#undef  CASE_DECERA
+#define CASE_DECERA CASE_GROUND_STATE
+#undef  CASE_DECFRA
+#define CASE_DECFRA CASE_GROUND_STATE
+#undef  CASE_DECSERA
+#define CASE_DECSERA CASE_GROUND_STATE
+#undef  CASE_DECSACE
+#define CASE_DECSACE CASE_GROUND_STATE
+#undef  CASE_DECCARA
+#define CASE_DECCARA CASE_GROUND_STATE
+#undef  CASE_DECRARA
+#define CASE_DECRARA CASE_GROUND_STATE
+#undef  CASE_DECSCPP
+#define CASE_DECSCPP CASE_GROUND_STATE
+#undef  CASE_DECSNLS
+#define CASE_DECSNLS CASE_GROUND_STATE
+#undef  CASE_DECRQDE
+#define CASE_DECRQDE CASE_GROUND_STATE
+#undef  CASE_DECRQPSR
+#define CASE_DECRQPSR CASE_GROUND_STATE
+#undef  CASE_DECRQUPSS
+#define CASE_DECRQUPSS CASE_GROUND_STATE
+#undef  CASE_RQM
+#define CASE_RQM CASE_GROUND_STATE
+#undef  CASE_DECRQM
+#define CASE_DECRQM CASE_GROUND_STATE
+#undef  CASE_XTERM_CHECKSUM
+#define CASE_XTERM_CHECKSUM CASE_GROUND_STATE
 #endif
 
 #if !OPT_MOD_FKEYS
@@ -89,8 +119,29 @@
 #define CASE_XTERM_REPORT_MOD_FKEYS CASE_GROUND_STATE
 #endif
 
+#if !OPT_STATUS_LINE
+#undef  CASE_DECSASD
+#define CASE_DECSASD CASE_GROUND_STATE
+#undef  CASE_DECSSDT
+#define CASE_DECSSDT CASE_GROUND_STATE
+#endif
+
+#if !OPT_VT525_COLORS
+#undef  CASE_DECAC
+#define CASE_DECAC CASE_GROUND_STATE
+#undef  CASE_DECATC
+#define CASE_DECATC CASE_GROUND_STATE
+#undef  CASE_DECTID
+#define CASE_DECTID CASE_GROUND_STATE
+#endif
+
+#if !OPT_WIDE_CHARS
+#undef  CASE_ESC_PERCENT
+#define CASE_ESC_PERCENT CASE_ESC_IGNORE
+#endif
+
 #if !OPT_XTERM_SGR
-#undef CASE_CSI_HASH_STATE
+#undef  CASE_CSI_HASH_STATE
 #define CASE_CSI_HASH_STATE CASE_CSI_IGNORE
 #endif
 
Index: charproc.c
--- xterm-400+/charproc.c	2025-06-08 23:03:44.000000000 +0000
+++ xterm-401/charproc.c	2025-06-25 08:21:04.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: charproc.c,v 1.2074 2025/06/08 23:03:44 tom Exp $ */
+/* $XTermId: charproc.c,v 1.2088 2025/06/25 08:21:04 tom Exp $ */
 
 /*
  * Copyright 1999-2024,2025 by Thomas E. Dickey
@@ -279,7 +279,6 @@
     { "set-scroll-on-tty-output", HandleScrollTtyOutput },
     { "set-scrollbar",		HandleScrollbar },
     { "set-select",		HandleSetSelect },
-    { "set-sun-keyboard",	HandleSunKeyboard },
     { "set-titeInhibit",	HandleTiteInhibit },
     { "set-visual-bell",	HandleSetVisualBell },
     { "set-vt-font",		HandleSetFont },
@@ -375,6 +374,9 @@
 #if OPT_SIXEL_GRAPHICS
     { "set-sixel-scrolling",	HandleSixelScrolling },
 #endif
+#if OPT_SUNPC_KBD
+    { "set-sun-keyboard",	HandleSunKeyboard },
+#endif
 #if OPT_SUN_FUNC_KEYS
     { "set-sun-function-keys",	HandleSunFunctionKeys },
 #endif
@@ -5961,23 +5963,21 @@
 	    break;
 #endif
 
-	case CASE_DECSASD:
 #if OPT_STATUS_LINE
+	case CASE_DECSASD:
 	    if (screen->vtXX_level >= 2) {
 		handle_DECSASD(xw, zero_if_default(0));
 	    }
-#endif
 	    ResetState(sp);
 	    break;
 
 	case CASE_DECSSDT:
-#if OPT_STATUS_LINE
 	    if (screen->vtXX_level >= 2) {
 		handle_DECSSDT(xw, zero_if_default(0));
 	    }
-#endif
 	    ResetState(sp);
 	    break;
+#endif
 
 #if OPT_XTERM_SGR		/* most are related, all use csi_hash_table[] */
 	case CASE_CSI_HASH_STATE:
@@ -5986,15 +5986,15 @@
 	    sp->parsestate = csi_hash_table;
 	    break;
 
-	case CASE_XTERM_CHECKSUM:
 #if OPT_DEC_RECTOPS
+	case CASE_XTERM_CHECKSUM:
 	    if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewSetChecksum)) {
 		TRACE(("CASE_XTERM_CHECKSUM\n"));
 		screen->checksum_ext = zero_if_default(0);
 	    }
-#endif
 	    ResetState(sp);
 	    break;
+#endif
 
 	case CASE_XTERM_PUSH_SGR:
 	    TRACE(("CASE_XTERM_PUSH_SGR\n"));
@@ -7971,6 +7971,9 @@
 	case srm_DECRPL:	/* ignore */
 	case srm_DECVCCM:	/* ignore */
 	case srm_DECXRLM:	/* ignore */
+#if !OPT_SHIFT_FONTS
+	case srm_DECHEBM:	/* ignore */
+#endif
 	default:
 	    TRACE(("DATA_ERROR: unknown private code %d\n", code));
 	    break;
@@ -8312,6 +8315,9 @@
 	case srm_DECRPL:	/* ignore */
 	case srm_DECVCCM:	/* ignore */
 	case srm_DECXRLM:	/* ignore */
+#if !OPT_SHIFT_FONTS
+	case srm_DECHEBM:	/* ignore */
+#endif
 	default:
 	    break;
 	}
@@ -8748,6 +8754,9 @@
 	case srm_DECRPL:	/* ignore */
 	case srm_DECVCCM:	/* ignore */
 	case srm_DECXRLM:	/* ignore */
+#if !OPT_SHIFT_FONTS
+	case srm_DECHEBM:	/* ignore */
+#endif
 	default:
 	    break;
 	}
@@ -9030,8 +9039,8 @@
 		       win_attrs.y, win_attrs.x));
 		if (!discount_frame_extents(xw, &result_y, &result_x)) {
 		    TRACE(("...cancelled translation\n"));
-		    result_y = win_attrs.y;
-		    result_x = win_attrs.x;
+		    result_y = win_attrs.y + win_attrs.border_width;
+		    result_x = win_attrs.x + win_attrs.border_width;
 		}
 		break;
 	    }
@@ -9159,6 +9168,7 @@
 	       ? "window title" \
 	       : "no titles")))
 
+#if OPT_TITLE_MODES
     case ewPushTitle:		/* save the window's title(s) on stack */
 	if (AllowWindowOps(xw, ewPushTitle)) {
 	    SaveTitle item;
@@ -9209,6 +9219,7 @@
 	    }
 	}
 	break;
+#endif /* OPT_TITLE_MODES */
 
     default:			/* DECSLPP (24, 25, 36, 48, 72, 144) */
 	if (AllowWindowOps(xw, ewSetWinLines)) {
@@ -10487,18 +10498,28 @@
 #endif
     ,DATA(GetIconTitle)
     ,DATA(GetWinTitle)
+#if OPT_TITLE_MODES
     ,DATA(PushTitle)
     ,DATA(PopTitle)
+#endif
 /* this item uses all remaining numbers in the sequence */
     ,DATA(SetWinLines)
 /* starting at this point, numbers do not apply */
-    ,DATA(SetXprop)
-    ,DATA(GetSelection)
-    ,DATA(SetSelection)
+    ,DATA(ColumnMode)
+#if OPT_DEC_RECTOPS
     ,DATA(GetChecksum)
     ,DATA(SetChecksum)
+#endif
+#if OPT_PASTE64
+    ,DATA(GetSelection)
+    ,DATA(SetSelection)
+#endif
+#if OPT_SET_XPROP
+    ,DATA(SetXprop)
+#endif
+#if OPT_STATUS_LINE
     ,DATA(StatusLine)
-    ,DATA(ColumnMode)
+#endif
     ,DATA_END
 };
 #undef DATA
@@ -10527,37 +10548,47 @@
 };
 #undef DATA
 
+#if OPT_QUERY_ALLOW
+
+#define DATA(mixed, plain, flags) \
+	{ mixed, \
+	  offsetof(TScreen, plain), \
+	  sizeof(((TScreen*)0)->plain), \
+	  flags }
+/* *INDENT-OFF* */
+static const struct {
+    const char *     name;
+    size_t           offset;
+    size_t           length;
+    const FlagList * codes;
+} allow_categories[] = {
+    DATA(XtNallowColorOps,      disallow_color_ops, tblColorOps),
+    DATA(XtNallowFontOps,       disallow_font_ops,  tblFontOps),
+    DATA(XtNallowMouseOps,      disallow_mouse_ops, tblMouseOps),
+    DATA(XtNallowPasteControls, disallow_paste_ops, tblPasteOps),
+    DATA(XtNallowTcapOps,       disallow_tcap_ops,  tblTcapOps),
+    DATA("allowWinOps",         disallow_win_ops,   tblWindowOps),
+    DATA(XtNallowWindowOps,     disallow_win_ops,   tblWindowOps),
+};
+/* *INDENT-ON* */
+#undef DATA
+
 void
 unparse_disallowed_ops(XtermWidget xw, char *value)
 {
     TScreen *screen = TScreenOf(xw);
-#define DATA(mixed, plain, flags) { #mixed, offsetof(TScreen, plain), sizeof(screen->plain), flags }
-    /* *INDENT-OFF* */
-    static const struct {
-	const char *	name;
-	size_t		offset;
-	size_t		length;
-	const FlagList *codes;
-    } table[] = {
-	DATA(allowColorOps,	 disallow_color_ops, tblColorOps),
-	DATA(allowFontOps,	 disallow_font_ops,  tblFontOps),
-	DATA(allowMouseOps,	 disallow_mouse_ops, tblMouseOps),
-	DATA(allowPasteControls, disallow_paste_ops, tblPasteOps),
-	DATA(allowTcapOps,	 disallow_tcap_ops,  tblTcapOps),
-	DATA(allowWinOps,	 disallow_win_ops,   tblWindowOps),
-    };
-    /* *INDENT-ON* */
-#undef DATA
     Cardinal j, k, jk;
     char delim = ';';
 
-    for (j = 0; j < XtNumber(table); ++j) {
-	if (!x_strcasecmp(value, table[j].name)) {
-	    const char *flags = (char *) screen + table[j].offset;
+    TRACE(("unparse_disallowed_ops(%s)\n", value));
+    for (j = 0; j < XtNumber(allow_categories); ++j) {
+	if (!x_strcasecmp(value, allow_categories[j].name)) {
+	    const char *flags = (char *) screen + allow_categories[j].offset;
 
-	    for (k = 0; k < table[j].length; ++k) {
+	    TRACE(("...found table\n"));
+	    for (k = 0; k < allow_categories[j].length; ++k) {
 		if (flags[k]) {
-		    const FlagList *codes = table[j].codes;
+		    const FlagList *codes = allow_categories[j].codes;
 		    Boolean found = False;
 
 		    unparseputc(xw, delim);
@@ -10578,6 +10609,28 @@
     }
 }
 
+void
+unparse_allowable_ops(XtermWidget xw, char *value)
+{
+    Cardinal j, k;
+    char delim = ';';
+
+    TRACE(("unparse_allowable_ops(%s)\n", value));
+    for (j = 0; j < XtNumber(allow_categories); ++j) {
+	if (!x_strcasecmp(value, allow_categories[j].name)) {
+	    const FlagList *codes = allow_categories[j].codes;
+
+	    for (k = 0; codes[k].name; ++k) {
+		unparseputc(xw, delim);
+		unparseputs(xw, codes[k].name);
+		delim = ',';
+	    }
+	    break;
+	}
+    }
+}
+#endif /* OPT_QUERY_ALLOW */
+
 /* ARGSUSED */
 static void
 VTInitialize(Widget wrequest,
@@ -11969,8 +12022,10 @@
 	deleteScrollback(screen);
     }
 
+#if OPT_TITLE_MODES
     for (n = 0; n < MAX_SAVED_TITLES; ++n)
 	xtermFreeTitle(&screen->saved_titles.data[n]);
+#endif
 
 #if OPT_STATUS_LINE
     free(screen->status_fmt);
@@ -14225,7 +14280,9 @@
 
 	/* reset the mouse mode */
 	screen->send_mouse_pos = MOUSE_OFF;
+#if OPT_FOCUS_EVENT
 	screen->send_focus_pos = OFF;
+#endif
 	screen->extend_coords = 0;
 	screen->waitingForTrackInfo = False;
 	screen->eventMode = NORMAL;
Index: ctlseqs.ms
--- xterm-400+/ctlseqs.ms	2025-06-08 23:01:30.000000000 +0000
+++ xterm-401/ctlseqs.ms	2025-06-22 20:29:42.000000000 +0000
@@ -1,5 +1,5 @@
 .\"#! troff -ms $1		-*- Nroff -*-
-.\" $XTermId: ctlseqs.ms,v 1.738 2025/06/08 23:01:30 tom Exp $
+.\" $XTermId: ctlseqs.ms,v 1.741 2025/06/22 20:29:42 tom Exp $
 .\" ---------------------------------------------------------------------------
 .\" Copyright 1996-2024,2025 by Thomas E. Dickey
 .\" Copyright 1991, 1994 X Consortium
@@ -40,8 +40,8 @@
 .\"
 .ds XT XTerm
 .ds xt xterm
-.ds LF Patch #400
-.ds RF 2025/06/08
+.ds LF Patch #401
+.ds RF 2025/06/22
 .\"
 .if n .pl 9999v		\" no page breaks in nroff
 .ND
@@ -2951,7 +2951,7 @@
   \*(Os\*6\*0\*s\*;\*(Pt\*s\*(ST
 .sP
 where \*(Pt is a comma-separated list
-of the \fIallowed\fP optional runtime features,
+of the \fIallowed\fP optional runtime feature categories,
 i.e., zero or more of these resource names:
 .iP
   \fBallowColorOps\fR
@@ -2962,17 +2962,32 @@
   \fBallowTitleOps\fR
   \fBallowWindowOps\fR
 .sP
+Except for \fBallowPasteControls\fP,
+those resources can be enabled or disabled at runtime using menus.
+They cannot be changed using control sequences.
+.sP
   \*(Ps = \*6\*1 \(-> Query disallowed features (XTQDISALLOWED).
-The second parameter (i.e., the main feature)
+The second parameter (i.e., the main feature category)
 must be one of the resource names returned by \*(Os\*6\*0.
 \fI\*(XT\fP replies with
 .sP
   \*(Os\*6\*1\*s\*;\*(Pt\*s\*(ST
 .sP
 where \*(Pt is a comma-separated list
-of the optional runtime features which would be disallowed
+of the optional runtime feature subcategories which would be disallowed
 if the main feature is disabled.
 .sP
+  \*(Ps = \*6\*2 \(-> Query allowable features (XTQALLOWABLE).
+The second parameter (i.e., the main feature category)
+must be one of the resource names that might be returned by \*(Os\*6\*0.
+\fI\*(XT\fP replies with
+.sP
+  \*(Os\*6\*2\*s\*;\*(Pt\*s\*(ST
+.sP
+where \*(Pt is a comma-separated list
+of the optional runtime feature subcategories which correspond to
+the main feature category.
+.sP
   \*(Ps = \*1\*0\*4\*;\fIc\fP \(-> Reset Color Number \fIc\fP.  It is reset to
 the color specified by the corresponding X resource.
 Any number of \fIc\fP parameters may be given.
Index: ctlseqs.txt
--- xterm-400+/ctlseqs.txt	2025-06-08 23:01:30.000000000 +0000
+++ xterm-401/ctlseqs.txt	2025-06-22 20:30:07.000000000 +0000
@@ -21,7 +21,7 @@
                              Thomas Dickey
                       XFree86 Project (1996-2006)
                     invisible-island.net (2006-2025)
-               updated for XTerm Patch #400 (2025/06/08)
+               updated for XTerm Patch #401 (2025/06/22)
 
 
 
@@ -2176,7 +2176,8 @@
             OSC 6 0  ; Pt ST
 
           where Pt is a comma-separated list of the allowed optional
-          runtime features, i.e., zero or more of these resource names:
+          runtime feature categories, i.e., zero or more of these
+          resource names:
 
             allowColorOps
             allowFontOps
@@ -2186,15 +2187,31 @@
             allowTitleOps
             allowWindowOps
 
+          Except for allowPasteControls, those resources can be enabled
+          or disabled at runtime using menus.  They cannot be changed
+          using control sequences.
+
             Ps = 6 1  -> Query disallowed features (XTQDISALLOWED).  The
-          second parameter (i.e., the main feature) must be one of the
-          resource names returned by OSC 6 0 .  XTerm replies with
+          second parameter (i.e., the main feature category) must be one
+          of the resource names returned by OSC 6 0 .  XTerm replies
+          with
 
             OSC 6 1  ; Pt ST
 
           where Pt is a comma-separated list of the optional runtime
-          features which would be disallowed if the main feature is
-          disabled.
+          feature subcategories which would be disallowed if the main
+          feature is disabled.
+
+            Ps = 6 2  -> Query allowable features (XTQALLOWABLE).  The
+          second parameter (i.e., the main feature category) must be one
+          of the resource names that might be returned by OSC 6 0 .
+          XTerm replies with
+
+            OSC 6 2  ; Pt ST
+
+          where Pt is a comma-separated list of the optional runtime
+          feature subcategories which correspond to the main feature
+          category.
 
             Ps = 1 0 4 ; c -> Reset Color Number c.  It is reset to the
           color specified by the corresponding X resource.  Any number
@@ -3775,44 +3792,44 @@
         be used in termcap for vi(1), for example, to turn off saving of
         lines, but restore whatever the original state was on exit.
 
-    while the SCOSC/SCORC  pair  was  added  in  1995  by  XFree86  (and
+    while  the  SCOSC/SCORC  pair  was  added  in  1995  by XFree86 (and
     documented long afterwards).
 
-    The  SCO  ANSI  console  terminal  descriptions  did  not  use these
-    controls (they used the VT100-compatible SC/RC  pair).   SCOSC/SCORC
-    were  an artifact of DOS 2.00 (January 1983), by Microsoft and later
+    The SCO  ANSI  console  terminal  descriptions  did  not  use  these
+    controls  (they  used the VT100-compatible SC/RC pair).  SCOSC/SCORC
+    were an artifact of DOS 2.00 (January 1983), by Microsoft and  later
     supported by SCO and other vendors.
 
-    The SCOSC/SCORC pair is considered a private mode because the  final
+    The  SCOSC/SCORC pair is considered a private mode because the final
     characters (s  and u ) fall in the range from "`" to "~" (octal 0140
-    to octal 0176).  Other private control sequences can be  constructed
+    to  octal 0176).  Other private control sequences can be constructed
     by using octets 074 to 077 (characters "<", "=", ">", or "?") at the
     beginning  of  the  parameter  string.   The  XTSAVE  and  XTRESTORE
     controls use "?") in this manner.
 
     Because  the  XTSAVE  and  XTRESTORE  controls  are  private,  other
-    terminals may behave differently.  For example, DEC  (a  contributor
-    to  the  early xterm as well as a manufacturer of terminals) used an
-    incompatible private control in one of its terminals more than  five
+    terminals  may  behave differently.  For example, DEC (a contributor
+    to the early xterm as well as a manufacturer of terminals)  used  an
+    incompatible  private control in one of its terminals more than five
     years later (for the VT420 PCTerm, announced in February 1992).
 
-    In  that  model  of  the  VT420, CSI ? Pm ; Pc r selects the PC TERM
-    emulation mode.  When this mode is enabled, the keyboard sends  scan
-    codes  rather than characters (analogous to X keyboard events).  The
-    first parameter of this private control enables or disables PC  TERM
+    In that model of the VT420, CSI ? Pm ; Pc  r  selects  the  PC  TERM
+    emulation  mode.  When this mode is enabled, the keyboard sends scan
+    codes rather than characters (analogous to X keyboard events).   The
+    first  parameter of this private control enables or disables PC TERM
     mode, while the second selects a character set.  An ambiguity arises
     if an application omits the second parameter.  In that special case,
-    it  cannot  be  distinguished from XTRESTORE.  DEC did not take this
+    it cannot be distinguished from XTRESTORE.  DEC did  not  take  this
     into account when designing the feature.
 
-    If there were potential users, xterm could  accommodate  this  by  a
-    resource  setting.   In  retrospect (thirty years later), there have
-    been no uses of PC TERM, while the XTRESTORE  feature  is  still  in
+    If  there  were  potential  users, xterm could accommodate this by a
+    resource setting.  In retrospect (thirty years  later),  there  have
+    been  no  uses  of  PC TERM, while the XTRESTORE feature is still in
     use.
 
 o   The aixterm manual page gives the format of the control sequence for
-    foreground and background colors 8-15, but  does  not  specify  what
-    those  colors  are.  That is implied by the description's mention of
+    foreground  and  background  colors  8-15, but does not specify what
+    those colors are.  That is implied by the description's  mention  of
     HFT:
 
         The aixterm command provides a standard terminal type for
@@ -3822,7 +3839,7 @@
         the -v flag.
 
     Unlike xterm, there are no resource names for the 16 colors, leaving
-    the  reader  to  assume that the mapping is hard-coded.  The control
-    sequences for colors 8-15 are not specified by ECMA-48,  but  rather
-    (as  done  in  other instances by xterm) chosen to not conflict with
+    the reader to assume that the mapping is  hard-coded.   The  control
+    sequences  for  colors 8-15 are not specified by ECMA-48, but rather
+    (as done in other instances by xterm) chosen to  not  conflict  with
     current or future standards.
Index: fontutils.c
--- xterm-400+/fontutils.c	2025-04-06 23:33:58.000000000 +0000
+++ xterm-401/fontutils.c	2025-06-23 21:52:22.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: fontutils.c,v 1.790 2025/04/06 23:33:58 tom Exp $ */
+/* $XTermId: fontutils.c,v 1.791 2025/06/23 21:52:22 tom Exp $ */
 
 /*
  * Copyright 1998-2024,2025 by Thomas E. Dickey
@@ -3867,8 +3867,6 @@
     xtermSetCursorBox(screen);
 }
 
-#if OPT_BOX_CHARS || OPT_REPORT_FONTS
-
 /*
  * Returns true if the given character is missing from the specified font.
  */
@@ -3906,7 +3904,6 @@
     }
     return result;
 }
-#endif
 
 #if OPT_BOX_CHARS || OPT_WIDE_CHARS
 /*
Index: fontutils.h
--- xterm-400+/fontutils.h	2024-12-01 19:48:57.000000000 +0000
+++ xterm-401/fontutils.h	2025-06-23 21:55:10.000000000 +0000
@@ -1,7 +1,7 @@
-/* $XTermId: fontutils.h,v 1.150 2024/12/01 19:48:57 tom Exp $ */
+/* $XTermId: fontutils.h,v 1.151 2025/06/23 21:55:10 tom Exp $ */
 
 /*
- * Copyright 1998-2022,2024 by Thomas E. Dickey
+ * Copyright 1998-2024,2025 by Thomas E. Dickey
  *
  *                         All Rights Reserved
  *
@@ -140,8 +140,8 @@
 	  (fontList)[fNorm].fs->per_char != NULL)) \
 	 ? &((fontList)[fNorm]) \
 	 : &((fontList)[(which)]))
-extern Bool xtermMissingChar (unsigned /* ch */, XTermFonts */* font */);
 #endif
+extern Bool xtermMissingChar (unsigned /* ch */, XTermFonts */* font */);
 
 #if OPT_LOAD_VTFONTS
 extern void HandleLoadVTFonts PROTO_XT_ACTIONS_ARGS;
Index: input.c
--- xterm-400+/input.c	2025-04-02 00:30:06.000000000 +0000
+++ xterm-401/input.c	2025-06-23 19:53:25.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: input.c,v 1.387 2025/04/02 00:30:06 tom Exp $ */
+/* $XTermId: input.c,v 1.388 2025/06/23 19:53:25 tom Exp $ */
 
 /*
  * Copyright 1999-2024,2025 by Thomas E. Dickey
@@ -1240,7 +1240,9 @@
 
 	    TRACE_FK("...map");
 	    if (evt_state & ControlMask) {
+#if OPT_SUNPC_KBD
 		kd.keysym += (KeySym) xw->misc.ctrl_fkeys;
+#endif
 		UIntClr(evt_state, ControlMask);
 	    }
 	    TRACE_FK(" to");
Index: menu.h
--- xterm-400+/menu.h	2025-06-08 23:07:32.000000000 +0000
+++ xterm-401/menu.h	2025-06-23 20:23:21.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: menu.h,v 1.148 2025/06/08 23:07:32 tom Exp $ */
+/* $XTermId: menu.h,v 1.149 2025/06/23 20:23:21 tom Exp $ */
 
 /*
  * Copyright 1999-2024,2025 by Thomas E. Dickey
@@ -399,6 +399,8 @@
 
 #if OPT_SUNPC_KBD
 extern void update_sun_kbd(void);
+#else
+#define update_sun_kbd() /* nothing */
 #endif
 
 #if OPT_HP_FUNC_KEYS
Index: misc.c
--- xterm-400+/misc.c	2025-06-15 18:27:59.000000000 +0000
+++ xterm-401/misc.c	2025-06-23 23:59:35.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: misc.c,v 1.1113 2025/06/15 18:27:59 tom Exp $ */
+/* $XTermId: misc.c,v 1.1123 2025/06/23 23:59:35 tom Exp $ */
 
 /*
  * Copyright 1999-2024,2025 by Thomas E. Dickey
@@ -131,6 +131,10 @@
 static Boolean xtermAllocColor(XtermWidget, XColor *, const char *);
 static Cursor make_hidden_cursor(XtermWidget);
 
+#if OPT_SET_XPROP
+static void ChangeXprop(char *);
+#endif
+
 #if OPT_EXEC_XTERM
 /* Like readlink(2), but returns a malloc()ed buffer, or NULL on
    error; adapted from libc docs */
@@ -2608,9 +2612,9 @@
 			   (vi->class == TrueColor
 			    || vi->class == DirectColor));
 
-	    if (resource.reportColors) {
+	    if_OPT_REPORT_COLORS({
 		printf(MYFMT, MYARG);
-	    }
+	    });
 	    TRACE((MYFMT, MYARG));
 	    TRACE(("...shifts %u/%u/%u\n",
 		   xw->rgb_shifts[0],
@@ -3101,18 +3105,20 @@
     size_t have = strlen(spec);
 
     if (have == 0 || have > MAX_U_STRING) {
-	if (resource.reportColors) {
+	if_OPT_REPORT_COLORS({
 	    printf("color  (ignored, length %lu)\n", (unsigned long) have);
-	}
+	});
     } else if (XParseColor(screen->display, cmap, spec, def)) {
+#if OPT_REPORT_COLORS
 	XColor save_def = *def;
-	if (resource.reportColors) {
+#endif
+	if_OPT_REPORT_COLORS({
 	    printf("color  %04x/%04x/%04x = \"%s\"\n",
 		   def->red, def->green, def->blue,
 		   spec);
-	}
+	});
 	if (allocateBestRGB(xw, def)) {
-	    if (resource.reportColors) {
+	    if_OPT_REPORT_COLORS({
 		if (def->red != save_def.red ||
 		    def->green != save_def.green ||
 		    def->blue != save_def.blue) {
@@ -3120,7 +3126,7 @@
 			   def->red, def->green, def->blue,
 			   spec);
 		}
-	    }
+	    });
 	    TRACE(("xtermAllocColor -> %x/%x/%x\n",
 		   def->red, def->green, def->blue));
 	    result = True;
@@ -3482,11 +3488,18 @@
     ,OSC_Unused_30 = 30		/* Konsole (unused) */
     ,OSC_Unused_31 = 31		/* Konsole (unused) */
     ,OSC_NewLogFile = 46
+#if OPT_SHIFT_FONTS
     ,OSC_FontOps = 50
+#endif
     ,OSC_Unused_51		/* Emacs (unused) */
+#if OPT_PASTE64
     ,OSC_SelectionData = 52
+#endif
+#if OPT_QUERY_ALLOW
     ,OSC_AllowedOps = 60
     ,OSC_DisallowedOps = 61
+    ,OSC_AllowableOps = 62
+#endif
 } OscMiscOps;
 
 static Bool
@@ -3920,6 +3933,7 @@
 
 /***====================================================================***/
 
+#if OPT_QUERY_ALLOW
 static void
 report_allowed_ops(XtermWidget xw, int final)
 {
@@ -3932,7 +3946,7 @@
 #define CASE(name) \
     if (screen->name) { \
 	unparseputc(xw, delimiter); \
-	unparseputs(xw, #name); \
+	unparseputs(xw, XtN##name); \
 	delimiter = ','; \
     }
     CASE(allowColorOps);
@@ -3957,6 +3971,16 @@
     unparseputc1(xw, final);
 }
 
+static void
+report_allowable_ops(XtermWidget xw, char *value, int final)
+{
+    unparseputc1(xw, ANSI_OSC);
+    unparseputn(xw, OSC_AllowableOps);
+    unparse_allowable_ops(xw, value);
+    unparseputc1(xw, final);
+}
+#endif /* OPT_QUERY_ALLOW */
+
 /***====================================================================***/
 
 void
@@ -4045,11 +4069,17 @@
      */
     if (xw->work.palette_changed) {
 	switch (mode) {
+#if OPT_QUERY_ALLOW
 	case OSC_AllowedOps:
 	case OSC_DisallowedOps:
+#endif
+#if OPT_SHIFT_FONTS
 	case OSC_FontOps:
+#endif
 	case OSC_NewLogFile:
+#if OPT_PASTE64
 	case OSC_SelectionData:
+#endif
 	case OSC_Unused_30:
 	case OSC_Unused_31:
 	case OSC_Unused_51:
@@ -4069,7 +4099,9 @@
      * a special case.
      */
     switch (mode) {
+#if OPT_SHIFT_FONTS
     case OSC_FontOps:
+#endif
 #if OPT_ISO_COLORS
     case OSC_Reset(OSC_SetAnsiColor):
     case OSC_Reset(OSC_GetAnsiColors):
@@ -4081,6 +4113,7 @@
     case OSC_Reset(OSC_TEXT_CURSOR):
     case OSC_Reset(OSC_MOUSE_FG):
     case OSC_Reset(OSC_MOUSE_BG):
+#endif
 #if OPT_HIGHLIGHT_COLOR
     case OSC_Reset(OSC_HIGHLIGHT_BG):
     case OSC_Reset(OSC_HIGHLIGHT_FG):
@@ -4090,10 +4123,12 @@
     case OSC_Reset(OSC_TEK_BG):
     case OSC_Reset(OSC_TEK_CURSOR):
 #endif
+#if OPT_QUERY_ALLOW
     case OSC_AllowedOps:
+#endif
+    case OSC_Unused_30:
 	need_data = False;
 	break;
-#endif
     default:
 	break;
     }
@@ -4137,10 +4172,13 @@
 	ChangeTitle(xw, buf);
 	break;
 
+#if OPT_SET_XPROP
     case OSC_X_Property:	/* change X property */
 	if (AllowWindowOps(xw, ewSetXprop))
 	    ChangeXprop(buf);
 	break;
+#endif
+
 #if OPT_ISO_COLORS
     case OSC_GetAnsiColors:
 	ansi_colors = NUM_ANSI_COLORS;
@@ -4272,15 +4310,15 @@
 	break;
 #endif /* ALLOWLOGGING */
 
-    case OSC_FontOps:
 #if OPT_SHIFT_FONTS
+    case OSC_FontOps:
 	if (*buf == '?') {
 	    QueryFontRequest(xw, buf, final);
 	} else if (xw->misc.shift_fonts) {
 	    ChangeFontRequest(xw, buf);
 	}
-#endif /* OPT_SHIFT_FONTS */
 	break;
+#endif /* OPT_SHIFT_FONTS */
 
 #if OPT_PASTE64
     case OSC_SelectionData:
@@ -4288,6 +4326,7 @@
 	break;
 #endif
 
+#if OPT_QUERY_ALLOW
     case OSC_AllowedOps:	/* XTQALLOWED */
 	report_allowed_ops(xw, final);
 	break;
@@ -4296,6 +4335,11 @@
 	report_disallowed_ops(xw, buf, final);
 	break;
 
+    case OSC_AllowableOps:	/* XTQALLOWABLE */
+	report_allowable_ops(xw, buf, final);
+	break;
+#endif
+
     case OSC_Unused_30:
     case OSC_Unused_31:
     case OSC_Unused_51:
@@ -4549,7 +4593,7 @@
     return cp;
 }
 
-#if OPT_MOD_FKEYS || OPT_DEC_RECTOPS || (OPT_VT525_COLORS && OPT_ISO_COLORS)
+#if OPT_MOD_FKEYS || OPT_DEC_RECTOPS || (OPT_VT525_COLORS && OPT_ISO_COLORS) || OPT_TITLE_MODES
 static int
 parse_int_param(const char **cp)
 {
@@ -4831,7 +4875,7 @@
 #if OPT_VT525_COLORS && OPT_ISO_COLORS
     const char *cp2;
 #endif
-#if (OPT_VT525_COLORS && OPT_ISO_COLORS) || OPT_MOD_FKEYS
+#if (OPT_VT525_COLORS && OPT_ISO_COLORS) || OPT_MOD_FKEYS || OPT_TITLE_MODES
     int ival;
 #endif
 
@@ -5053,6 +5097,7 @@
 		}
 	    } else
 #endif
+#if OPT_TITLE_MODES
 		/*
 		 * This query returns the settings assuming the default value
 		 * of DEF_TITLE_MODES, which is zero.  Someone could in
@@ -5090,7 +5135,9 @@
 		}
 		if (okay)
 		    sprintf(reply, ">%st", buffer);
-	    } else {
+	    } else
+#endif /* OPT_TITLE_MODES */
+	    {
 		okay = False;
 	    }
 
@@ -6307,7 +6354,8 @@
 
 #define Strlen(s) strlen((const char *)(s))
 
-void
+#if OPT_SET_XPROP
+static void
 ChangeXprop(char *buf)
 {
     Display *dpy = XtDisplay(toplevel);
@@ -6330,6 +6378,7 @@
 	XSetTextProperty(dpy, w, &text_prop, aprop);
     }
 }
+#endif /* OPT_SET_XPROP */
 
 /***====================================================================***/
 
@@ -7889,6 +7938,7 @@
 	}
 }
 
+#if OPT_TITLE_MODES
 static void
 xtermInitTitle(TScreen *screen, int which)
 {
@@ -7972,6 +8022,7 @@
     FreeAndNull(item->iconName);
     FreeAndNull(item->windowName);
 }
+#endif /* OPT_TITLE_MODES */
 
 #if OPT_XTERM_SGR
 void
Index: package/debian/changelog
--- xterm-400+/package/debian/changelog	2025-06-01 14:41:00.000000000 +0000
+++ xterm-401/package/debian/changelog	2025-06-16 22:40:22.000000000 +0000
@@ -1,3 +1,9 @@
+xterm-dev (401) unstable; urgency=low
+
+  * maintenance updates
+
+ -- Thomas E. Dickey <dickey@invisible-island.net>  Mon, 16 Jun 2025 18:40:22 -0400
+
 xterm-dev (400) unstable; urgency=low
 
   * maintenance updates
Index: package/freebsd/Makefile
--- xterm-400+/package/freebsd/Makefile	2025-06-01 18:55:17.000000000 +0000
+++ xterm-401/package/freebsd/Makefile	2025-06-16 22:40:22.000000000 +0000
@@ -1,4 +1,4 @@
-# $XTermId: Makefile,v 1.123 2025/06/01 18:55:17 tom Exp $
+# $XTermId: Makefile,v 1.124 2025/06/16 22:40:22 tom Exp $
 
 # This is adapted from the FreeBSD port, installing as "xterm-dev" with
 # separate resource- and manpage files.
@@ -6,7 +6,7 @@
 # and "make makesum".
 
 PORTNAME=	xterm
-DISTVERSION=	400
+DISTVERSION=	401
 CATEGORIES=	x11
 MASTER_SITES=	https://invisible-island.net/archives/xterm/:src1 \
 		https://invisible-mirror.net/archives/xterm/:src1
Index: package/pkgsrc/Makefile
--- xterm-400+/package/pkgsrc/Makefile	2025-06-01 14:41:00.000000000 +0000
+++ xterm-401/package/pkgsrc/Makefile	2025-06-16 22:40:22.000000000 +0000
@@ -1,6 +1,6 @@
 # $NetBSD: Makefile,v 1.156 2024/10/27 05:42:46 pin Exp $
 
-DISTNAME=	xterm-400
+DISTNAME=	xterm-401
 CATEGORIES=	x11
 MASTER_SITES=	https://invisible-island.net/archives/xterm/
 EXTRACT_SUFX=	.tgz
Index: package/xterm.spec
--- xterm-400+/package/xterm.spec	2025-06-01 14:41:00.000000000 +0000
+++ xterm-401/package/xterm.spec	2025-07-02 08:02:29.000000000 +0000
@@ -1,11 +1,11 @@
-# $XTermId: xterm.spec,v 1.181 2025/06/01 14:41:00 tom Exp $
+# $XTermId: xterm.spec,v 1.187 2025/07/02 08:02:29 tom Exp $
 Summary: X terminal emulator (development version)
 %global my_middle xterm
 %global my_suffix -dev
 %global fullname %{my_middle}%{my_suffix}
 %global my_class XTermDev
 Name: %{fullname}
-Version: 400
+Version: 401
 Release: 1
 License: X11
 Group: User Interface/X
@@ -270,6 +270,9 @@
 
 %changelog
 
+* Sun Jun 22 2025 Thomas E. Dickey
+- testing xterm-dev 400-3
+
 * Fri Nov 25 2022 Thomas E. Dickey
 - Fedora 37 has no xorg-x11-docs
 
Index: ptyx.h
--- xterm-400+/ptyx.h	2025-04-01 22:27:18.000000000 +0000
+++ xterm-401/ptyx.h	2025-06-23 23:54:48.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: ptyx.h,v 1.1141 2025/04/01 22:27:18 tom Exp $ */
+/* $XTermId: ptyx.h,v 1.1152 2025/06/23 23:54:48 tom Exp $ */
 
 /*
  * Copyright 1999-2024,2025 by Thomas E. Dickey
@@ -571,6 +571,10 @@
 #define OPT_DEC_RECTOPS 1 /* true if xterm is configured for VT420 rectangles */
 #endif
 
+#ifndef OPT_SET_XPROP
+#define OPT_SET_XPROP 1 /* true if xterm can set X properties */
+#endif
+
 #ifndef OPT_SGR2_HASH
 #define OPT_SGR2_HASH 1 /* true if xterm hashes color-lookups for faint color */
 #endif
@@ -707,6 +711,10 @@
 #define OPT_PRINT_COLORS 1 /* true if we print color information */
 #endif
 
+#ifndef OPT_QUERY_ALLOW
+#define OPT_QUERY_ALLOW	1 /* report allowed/disallowed features */
+#endif
+
 #ifndef OPT_READLINE
 #define OPT_READLINE	0 /* mouse-click/paste support for readline */
 #endif
@@ -799,6 +807,10 @@
 #define OPT_TEK4014     1 /* true if we're using tek4014 emulation */
 #endif
 
+#ifndef OPT_TITLE_MODES
+#define OPT_TITLE_MODES 1 /* true if we provide title-stack */
+#endif
+
 #ifndef OPT_TOOLBAR
 #define OPT_TOOLBAR	0 /* true if xterm supports toolbar menus */
 #endif
@@ -1461,17 +1473,27 @@
 #endif
     , ewGetIconTitle = 20
     , ewGetWinTitle = 21
+#if OPT_TITLE_MODES
     , ewPushTitle = 22
     , ewPopTitle = 23
+#endif
     /* these do not fit into that scheme, which is why we use an array */
     , ewSetWinLines
+    , ewColumnMode
+#if OPT_SET_XPROP
     , ewSetXprop
+#endif
+#if OPT_PASTE64
     , ewGetSelection
     , ewSetSelection
+#endif
+#if OPT_DEC_RECTOPS
     , ewGetChecksum
     , ewSetChecksum
+#endif
+#if OPT_STATUS_LINE
     , ewStatusLine
-    , ewColumnMode
+#endif
     /* get the size of the array... */
     , ewLAST
 } WindowOps;
@@ -1599,6 +1621,12 @@
 #define if_OPT_DIRECT_COLOR2_else(cond, test, stmt) \
 	if_OPT_DIRECT_COLOR2(cond, test, stmt else)
 
+#if OPT_REPORT_COLORS
+#define if_OPT_REPORT_COLORS(stmt) if (resource.reportColors) stmt
+#else
+#define if_OPT_REPORT_COLORS(stmt) /* nothing */
+#endif
+
 #define COLOR_RES_NAME(root) "color" root
 
 #if OPT_COLOR_CLASS
@@ -2828,7 +2856,9 @@
 
 	int		title_modes;	/* control set/get of titles	*/
 	int		title_modes0;	/* ...initial value         	*/
+#if OPT_TITLE_MODES
 	SavedTitles	saved_titles;
+#endif
 
 	/* Improved VT100 emulation stuff.				*/
 	String		keyboard_dialect; /* default keyboard dialect	*/
Index: util.c
--- xterm-400+/util.c	2025-06-10 13:41:16.000000000 +0000
+++ xterm-401/util.c	2025-06-22 18:22:34.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: util.c,v 1.960 2025/06/10 13:41:16 tom Exp $ */
+/* $XTermId: util.c,v 1.961 2025/06/22 18:22:34 tom Exp $ */
 
 /*
  * Copyright 1999-2024,2025 by Thomas E. Dickey
@@ -4274,7 +4274,8 @@
 			unsigned part = ucs2dec(screen, ch);
 			if (xtermIsDecGraphic(part)
 			    && IsDecLineDrawing(part)
-			    && screen->force_box_chars) {
+			    && (screen->force_box_chars
+				|| screen->broken_box_chars)) {
 			    SetMissing("case 2");
 			    ch = part;
 			}
Index: version.h
--- xterm-400+/version.h	2025-06-15 20:26:03.000000000 +0000
+++ xterm-401/version.h	2025-07-02 07:49:40.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: version.h,v 1.579 2025/06/15 20:26:03 tom Exp $ */
+/* $XTermId: version.h,v 1.583 2025/07/02 07:49:40 tom Exp $ */
 
 /*
  * Copyright 1998-2024,2025 by Thomas E. Dickey
@@ -38,8 +38,8 @@
  * version of X to which this version of xterm has been built.  The resulting
  * number in parentheses is my patch number (Thomas E. Dickey).
  */
-#define XTERM_PATCH   400
-#define XTERM_DATE    2025-06-15
+#define XTERM_PATCH   401
+#define XTERM_DATE    2025-07-02
 
 #ifndef __vendorversion__
 #define __vendorversion__ "XTerm"
Index: vttests/query-allowed.pl
--- /dev/null	2025-07-02 18:58:01.219999954 +0000
+++ xterm-401/vttests/query-allowed.pl	2025-06-23 00:09:50.000000000 +0000
@@ -0,0 +1,258 @@
+#!/usr/bin/env perl
+# $XTermId: query-allowed.pl,v 1.8 2025/06/23 00:09:50 tom Exp $
+# -----------------------------------------------------------------------------
+# Copyright 2022,2025 by Thomas E. Dickey
+#
+#                         All Rights Reserved
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name(s) of the above copyright
+# holders shall not be used in advertising or otherwise to promote the
+# sale, use or other dealings in this Software without prior written
+# authorization.
+# -----------------------------------------------------------------------------
+# Exercise OSC 60 and 61 which report allowed- and disallowed-operations.
+# Use OSC 62 to provide some context of the OSC 61 responses.
+
+use strict;
+
+use Getopt::Std;
+use IO::Handle;
+
+$| = 1;
+
+our ( $opt_a, $opt_v, $opt_8 );
+
+sub main::HELP_MESSAGE() {
+    printf STDERR <<EOF
+Usage: $0 [options]
+Options:
+  -8      use 8-bit controls
+  -a      test all settings, resetting
+  -v      verbose, show responses
+EOF
+      ;
+    exit 1;
+}
+
+$Getopt::Std::STANDARD_HELP_VERSION = 1;
+getopts('av8') || &main::HELP_MESSAGE;
+
+our $version = 401;    # xterm #401 supports OSC 62
+
+our $CSI = "\x1b\[";
+our $ST  = "\x1b\\";
+our $OSC = "\x1b\]";
+$CSI = "\x9b" if ($opt_8);
+$ST  = "\x9c" if ($opt_8);
+$OSC = "\x9d" if ($opt_8);
+
+sub no_reply($) {
+    open TTY, "+</dev/tty" or die("Cannot open /dev/tty\n");
+    autoflush TTY 1;
+    my $old = `stty -g`;
+    system "stty raw -echo min 0 time 5";
+
+    print TTY @_;
+    close TTY;
+    system "stty $old";
+}
+
+sub get_reply($) {
+    my $query = shift;
+    printf "Query: %s\n", visible($query) if $opt_v;
+    open TTY, "+</dev/tty" or die("Cannot open /dev/tty\n");
+    autoflush TTY 1;
+    my $old = `stty -g`;
+    system "stty raw -echo min 0 time 5";
+
+    print TTY $query;
+    my $reply = <TTY>;
+    close TTY;
+    system "stty $old";
+    if ( defined $reply ) {
+        die("^C received\n") if ( "$reply" eq "\003" );
+    }
+    printf "Reply: %s\n", visible($reply) if $opt_v;
+    return $reply;
+}
+
+sub visible($) {
+    my $reply = $_[0];
+    my $n;
+    my $result = "";
+    for ( $n = 0 ; $n < length($reply) ; ) {
+        my $c = substr( $reply, $n, 1 );
+        if ( $c =~ /[[:print:]]/ ) {
+            $result .= $c;
+        }
+        else {
+            my $k = ord substr( $reply, $n, 1 );
+            if ( ord $k == 0x1b ) {
+                $result .= "\\E";
+            }
+            elsif ( $k == 0x7f ) {
+                $result .= "^?";
+            }
+            elsif ( $k == 32 ) {
+                $result .= "\\s";
+            }
+            elsif ( $k < 32 ) {
+                $result .= sprintf( "^%c", $k + 64 );
+            }
+            elsif ( $k > 128 ) {
+                $result .= sprintf( "\\%03o", $k );
+            }
+            else {
+                $result .= chr($k);
+            }
+        }
+        $n += 1;
+    }
+
+    return $result;
+}
+
+sub extract_list($$) {
+    my $prefix = shift;
+    my $result = shift;
+    my @result = ();
+    if (    $result ne ""
+        and index( $result, $prefix ) == 0
+        and index( $result, $ST ) == length($result) - length($ST) )
+    {
+        $result = substr( $result, length($prefix) );
+        $result = substr( $result, 0, length($result) - length($ST) );
+        @result = split /,/, $result;
+    }
+    else {
+        $prefix =~ s/;$//;
+        my $check = $prefix . $ST;
+        printf "? unexpected reply: %s\n", visible($result)
+          if $result ne $check;
+    }
+    return @result;
+}
+
+sub report_list($$) {
+    my $label  = $_[0];
+    my @result = @{ $_[1] };
+    if ( $#result >= 0 ) {
+        my $prefix = "      ";
+        my $result = $prefix . $label . ":";
+        $prefix .= " ";
+        for my $n ( 0 .. $#result ) {
+            my $value = visible( $result[$n] );
+            if ( length( $result . $value ) >= 72 ) {
+                printf "%s\n", $result;
+                $result = $prefix;
+            }
+            $result .= " " . $value;
+        }
+        printf "%s\n", $result unless ( $result eq $prefix );
+    }
+}
+
+sub GetCategories() {
+    my $prefix = sprintf( "%s60", $OSC );
+    my $result = get_reply( $prefix . $ST );
+    return extract_list( $prefix . ";", $result );
+}
+
+sub GetDisallowed($) {
+    my $category = shift;
+    my $prefix   = sprintf( "%s61;", $OSC );
+    my $result   = get_reply( $prefix . $category . $ST );
+    return extract_list( $prefix, $result );
+}
+
+sub GetAllowable($) {
+    my $category = shift;
+    my $prefix   = sprintf( "%s62;", $OSC );
+    my $result   = get_reply( $prefix . $category . $ST );
+    return extract_list( $prefix, $result );
+}
+
+sub GetVersion() {
+    my $result = get_reply( $CSI . ">0q" );
+    if ( $result =~ /XTerm\(\d+\)/ ) {
+        $version =~ s/^.*XTerm\((\d+).*/$1/;
+    }
+}
+
+sub doit() {
+    my %categories = qw(
+      allowColorOps 0
+      allowFontOps 0
+      allowMouseOps 0
+      allowPasteControls 0
+      allowTcapOps 0
+      allowTitleOps 0
+      allowWindowOps 0
+    );
+    my @list = GetCategories;
+    printf "Enabled categories:\n" if $#list >= 0;
+
+    for my $n ( 0 .. $#list ) {
+        my $category = $list[$n];
+        printf " %3d: %s\n", $n + 1, $category;
+        if ( defined $categories{$category} ) {
+            $categories{$category} = 1;
+        }
+        else {
+            printf "? unexpected category\n";
+            next;
+        }
+        if ($opt_a) {
+            my @disallow = GetDisallowed($category);
+            report_list( "Disallow", \@disallow );
+            if ( $version > 400 ) {
+                my @allowable = GetAllowable($category);
+                report_list( "Allowable", \@allowable );
+            }
+        }
+    }
+    my $extra = 0;
+    for my $keys ( keys %categories ) {
+        if ( $categories{$keys} == 0 ) {
+            $extra = 1;
+            last;
+        }
+    }
+    if ($extra) {
+        printf "Disabled categories:\n";
+        for my $category ( keys %categories ) {
+            if ( $categories{$category} == 0 ) {
+                my @allowable = GetAllowable($category);
+                report_list( $category, \@allowable );
+            }
+        }
+    }
+}
+
+printf "\x1b G" if ($opt_8);
+
+GetVersion;
+doit;
+
+printf "\x1b F" if ($opt_8);
+
+1;
Index: xterm.appdata.xml
--- xterm-400+/xterm.appdata.xml	2025-06-15 20:26:24.000000000 +0000
+++ xterm-401/xterm.appdata.xml	2025-07-02 07:51:04.000000000 +0000
@@ -35,7 +35,7 @@
     <keyword>terminal</keyword>
   </keywords>
   <releases>
-    <release version="400" date="2025-06-15"/>
+    <release version="401" date="2025-07-02"/>
   </releases>
   <url type="homepage">https://invisible-island.net/xterm/</url>
   <update_contact>dickey@invisible-island.net</update_contact>
Index: xterm.h
--- xterm-400+/xterm.h	2025-04-08 07:36:09.000000000 +0000
+++ xterm-401/xterm.h	2025-06-23 23:31:45.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: xterm.h,v 1.964 2025/04/08 07:36:09 tom Exp $ */
+/* $XTermId: xterm.h,v 1.968 2025/06/23 23:31:45 tom Exp $ */
 
 /*
  * Copyright 1999-2024,2025 by Thomas E. Dickey
@@ -1075,7 +1075,7 @@
 #if OPT_FOCUS_EVENT
 extern void SendFocusButton(XtermWidget /* xw */, XFocusChangeEvent * /* event */);
 #else
-#define SendFocusBotton(xw, event) /* nothing */
+#define SendFocusButton(xw, event) /* nothing */
 #endif
 
 #if OPT_PASTE64
@@ -1157,7 +1157,6 @@
 extern void saveCharsets (TScreen * /* screen */, DECNRCM_codes * /* target */);
 extern void set_max_col(TScreen * /* screen */, int /* cols */);
 extern void set_max_row(TScreen * /* screen */, int /* rows */);
-extern void unparse_disallowed_ops (XtermWidget /* xw */, char * /* value */);
 extern void unparse_end (XtermWidget /* xw */);
 extern void unparseputc (XtermWidget /* xw */, int /* c */);
 extern void unparseputc1 (XtermWidget /* xw */, int /* c */);
@@ -1186,6 +1185,11 @@
 extern void setExtendedColors (XtermWidget /* xw */);
 #endif
 
+#if OPT_QUERY_ALLOW
+extern void unparse_disallowed_ops (XtermWidget /* xw */, char * /* value */);
+extern void unparse_allowable_ops (XtermWidget /* xw */, char * /* value */);
+#endif
+
 #ifdef NO_LEAKS
 extern void noleaks_charproc (void);
 #endif
@@ -1344,7 +1348,6 @@
 extern void ChangeGroup(XtermWidget /* xw */, const char * /* attribute */, char * /* value */);
 extern void ChangeIconName (XtermWidget /* xw */, char * /* name */);
 extern void ChangeTitle (XtermWidget /* xw */, char * /* name */);
-extern void ChangeXprop (char * /* name */);
 extern GCC_NORETURN void Cleanup (int /* code */);
 extern void HandleBellPropertyChange   PROTO_XT_EV_HANDLER_ARGS;
 extern void HandleEightBitKeyPressed   PROTO_XT_ACTIONS_ARGS;
Index: xterm.log.html
--- xterm-400+/xterm.log.html	2025-06-15 20:25:37.000000000 +0000
+++ xterm-401/xterm.log.html	2025-07-02 08:03:04.000000000 +0000
@@ -30,7 +30,7 @@
  * sale, use or other dealings in this Software without prior written        *
  * authorization.                                                            *
  *****************************************************************************
-  $XTermId: xterm.log.html,v 1.2702 2025/06/15 20:25:37 tom Exp $
+  $XTermId: xterm.log.html,v 1.2709 2025/07/02 08:03:04 tom Exp $
   -->
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
 <html>
@@ -70,6 +70,8 @@
   CHANGELOG</a>).</p>
 
   <ul>
+    <li><a href="#xterm_401">Patch #401 - 2025/07/02</a></li>
+
     <li><a href="#xterm_400">Patch #400 - 2025/06/15</a></li>
 
     <li><a href="#xterm_399">Patch #399 - 2025/05/18</a></li>
@@ -1078,6 +1080,31 @@
     <li><a href="#xterm_01">Patch #1 - 1996/1/6</a></li>
   </ul>
 
+  <h1><a name="xterm_401" id="xterm_401">Patch #401 -
+  2025/07/02</a></h1>
+
+  <ul>
+    <li>adjust reported window-position by the shell window's
+    border with in XTWINOPS 13, for better match with the position
+    set via XTWINOPS 3, fixing a mismatch seen with esctest.</li>
+
+    <li>improve ifdef'ing of infrequently-configured features.</li>
+
+    <li>add <tt>vttests/query-allowed.pl</tt>, to illustrate OSC
+    60, 61, and 62.</li>
+
+    <li>add <em>OSC 62</em>, to provide a list of features which
+    can be specified to be disabled/enabled via resource settings
+    or menus.</li>
+
+    <li>restore a check needed for Debian #1084794, which was lost
+    in the changes for <a href="#xterm_400">patch #400</a> (report
+    by Sean C Farley).</li>
+
+    <li>correct spelling for "allowWindowOps" in OSC 61. The
+    original spelling "allowWinOps" is still accepted.</li>
+  </ul>
+
   <h1><a name="xterm_400" id="xterm_400">Patch #400 -
   2025/06/15</a></h1>
 
