# https://invisible-island.net/archives/xterm/patches/xterm-405.patch.gz
# patch by Thomas E. Dickey <dickey@invisible-island.net>
# created  Sun Dec 14 17:42:45 UTC 2025
# ------------------------------------------------------------------------------
# MANIFEST                 |    2 +-
# button.c                 |   32 ++++++++++----------------------
# charproc.c               |   22 +++++++++++-----------
# misc.c                   |    4 ++--
# package/debian/changelog |    6 ++++++
# package/freebsd/Makefile |    4 ++--
# package/pkgsrc/Makefile  |    2 +-
# package/xterm.spec       |    8 ++++----
# screen.c                 |    6 +++---
# util.c                   |   10 +++++-----
# version.h                |    6 +++---
# xterm.appdata.xml        |    2 +-
# xterm.h                  |    6 ++++--
# xterm.log.html           |   18 +++++++++++++++++-
# 14 files changed, 70 insertions(+), 58 deletions(-)
# ------------------------------------------------------------------------------
Index: MANIFEST
--- xterm-404+/MANIFEST	2025-10-21 07:35:54.000000000 +0000
+++ xterm-405/MANIFEST	2025-12-01 01:19:31.000000000 +0000
@@ -1,4 +1,4 @@
-MANIFEST for xterm, version xterm-404
+MANIFEST for xterm, version xterm-405
 --------------------------------------------------------------------------------
 MANIFEST                        this file
 256colres.h                     resource-definitions for 256-color mode
Index: button.c
--- xterm-404+/button.c	2025-11-25 21:56:34.000000000 +0000
+++ xterm-405/button.c	2025-12-04 09:22:53.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: button.c,v 1.679 2025/11/25 21:56:34 tom Exp $ */
+/* $XTermId: button.c,v 1.680 2025/12/04 09:22:53 tom Exp $ */
 
 /*
  * Copyright 1999-2024,2025 by Thomas E. Dickey
@@ -671,6 +671,7 @@
 static Bool
 ValidMouseEvent(XtermWidget xw, XEvent *event)
 {
+    TScreen *screen = TScreenOf(xw);
     int xpos = -1;
     int ypos = -1;
     Bool result = False;
@@ -683,9 +684,7 @@
 	ypos = ((XMotionEvent *) event)->y;
     }
 
-    if (xpos >= 0 && ypos >= 0) {
-	TScreen *screen = TScreenOf(xw);
-
+    if (xpos >= OriginX(screen) && ypos >= OriginY(screen)) {
 	if ((ypos < LimitsY(screen)) &&
 	    (xpos < LimitsX(screen))) {
 	    result = True;
@@ -5507,25 +5506,14 @@
 	/* Compute character position of mouse pointer */
 	row = (event->y - OriginY(screen)) / FontHeight(screen);
 	col = (event->x - OriginX(screen)) / FontWidth(screen);
+    }
 
-	/* Limit to screen dimensions */
-	if (row < 0)
-	    row = 0;
-	else if (row > screen->max_row)
-	    row = screen->max_row;
-
-	if (col < 0)
-	    col = 0;
-	else if (col > screen->max_col)
-	    col = screen->max_col;
-
-	if (mouse_limit > 0) {
-	    /* Limit to representable mouse dimensions */
-	    if (row > mouse_limit)
-		row = mouse_limit;
-	    if (col > mouse_limit)
-		col = mouse_limit;
-	}
+    if (mouse_limit > 0) {
+	/* Limit to representable mouse dimensions */
+	if (row > mouse_limit)
+	    row = mouse_limit;
+	if (col > mouse_limit)
+	    col = mouse_limit;
     }
 
     /* Build key sequence starting with \E[M */
Index: charproc.c
--- xterm-404+/charproc.c	2025-11-28 12:51:20.000000000 +0000
+++ xterm-405/charproc.c	2025-12-12 20:52:47.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: charproc.c,v 1.2104 2025/11/28 12:51:20 tom Exp $ */
+/* $XTermId: charproc.c,v 1.2107 2025/12/12 20:52:47 tom Exp $ */
 
 /*
  * Copyright 1999-2024,2025 by Thomas E. Dickey
@@ -6033,7 +6033,7 @@
 	    break;
 #endif
 
-	case CASE_XTERM_PUSH_SGR:
+	case CASE_XTERM_PUSH_SGR:	/* XTPUSHSGR */
 	    TRACE(("CASE_XTERM_PUSH_SGR\n"));
 	    value = 0;
 	    if (nparam == 0 || (nparam == 1 && GetParam(0) == DEFAULT)) {
@@ -6058,20 +6058,20 @@
 	    ResetState(sp);
 	    break;
 
-	case CASE_XTERM_REPORT_SGR:
+	case CASE_XTERM_REPORT_SGR:	/* XTREPORTSGR */
 	    TRACE(("CASE_XTERM_REPORT_SGR\n"));
 	    xtermParseRect(xw, ParamPair(0), &myRect);
 	    xtermReportSGR(xw, &myRect);
 	    ResetState(sp);
 	    break;
 
-	case CASE_XTERM_POP_SGR:
+	case CASE_XTERM_POP_SGR:	/* XTPOPSGR */
 	    TRACE(("CASE_XTERM_POP_SGR\n"));
 	    xtermPopSGR(xw);
 	    ResetState(sp);
 	    break;
 
-	case CASE_XTERM_PUSH_COLORS:
+	case CASE_XTERM_PUSH_COLORS:	/* XTPUSHCOLORS */
 	    TRACE(("CASE_XTERM_PUSH_COLORS\n"));
 	    if (nparam == 0) {
 		xtermPushColors(xw, DEFAULT);
@@ -6083,7 +6083,7 @@
 	    ResetState(sp);
 	    break;
 
-	case CASE_XTERM_POP_COLORS:
+	case CASE_XTERM_POP_COLORS:	/* XTPOPCOLORS */
 	    TRACE(("CASE_XTERM_POP_COLORS\n"));
 	    if (nparam == 0) {
 		xtermPopColors(xw, DEFAULT);
@@ -6095,13 +6095,13 @@
 	    ResetState(sp);
 	    break;
 
-	case CASE_XTERM_REPORT_COLORS:
+	case CASE_XTERM_REPORT_COLORS:	/* XTREPORTCOLORS */
 	    TRACE(("CASE_XTERM_REPORT_COLORS\n"));
 	    xtermReportColors(xw);
 	    ResetState(sp);
 	    break;
 
-	case CASE_XTERM_TITLE_STACK:
+	case CASE_XTERM_TITLE_STACK:	/* XTTITLEPOS */
 	    xtermReportTitleStack(xw);
 	    ResetState(sp);
 	    break;
@@ -13861,7 +13861,7 @@
 
 		/* *INDENT-EQLS* */
 		params.draw_flags = NOBACKGROUND;
-		params.on_wide    = size > 1;
+		params.on_wide    = SelectedSize(size) > 1;
 
 		for_each_combData(off, ld) {
 		    if (!(ld->combData[off][my_col]))
@@ -13960,12 +13960,12 @@
 
     SelectSize(ld, cursor_col, base, size);
 
+#if OPT_ISO_COLORS
 #if EXP_BOGUS_FG
     /*
      * If the cursor happens to be on blanks, and we have not set both
      * foreground and background color, do not treat it as a colored cell.
      */
-#if OPT_ISO_COLORS
     if (base == ' ') {
 	if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) {
 	    TRACE(("HideCursor - do not treat as a colored cell\n"));
@@ -14044,7 +14044,7 @@
 
 	/* *INDENT-EQLS* */
 	params.draw_flags  = NOBACKGROUND;
-	params.on_wide     = size > 1;
+	params.on_wide     = SelectedSize(size) > 1;
 
 	for_each_combData(off, ld) {
 	    if (!(ld->combData[off][my_col]))
Index: misc.c
--- xterm-404+/misc.c	2025-11-16 21:19:25.000000000 +0000
+++ xterm-405/misc.c	2025-12-03 00:57:03.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: misc.c,v 1.1126 2025/11/16 21:19:25 tom Exp $ */
+/* $XTermId: misc.c,v 1.1127 2025/12/03 00:57:03 tom Exp $ */
 
 /*
  * Copyright 1999-2024,2025 by Thomas E. Dickey
@@ -7956,7 +7956,7 @@
 {
     if (which-- <= 0) {
 	which = screen->saved_titles.used++;
-	screen->saved_titles.used %= MAX_SAVED_TITLES;
+	which %= MAX_SAVED_TITLES;
     }
     which %= MAX_SAVED_TITLES;
     xtermFreeTitle(&screen->saved_titles.data[which]);
Index: package/debian/changelog
--- xterm-404+/package/debian/changelog	2025-10-21 07:35:54.000000000 +0000
+++ xterm-405/package/debian/changelog	2025-12-01 01:19:31.000000000 +0000
@@ -1,3 +1,9 @@
+xterm-dev (405) unstable; urgency=low
+
+  * maintenance updates
+
+ -- Thomas E. Dickey <dickey@invisible-island.net>  Sun, 30 Nov 2025 20:19:31 -0500
+
 xterm-dev (404) unstable; urgency=low
 
   * maintenance updates
Index: package/freebsd/Makefile
--- xterm-404+/package/freebsd/Makefile	2025-10-21 07:35:54.000000000 +0000
+++ xterm-405/package/freebsd/Makefile	2025-12-01 01:19:31.000000000 +0000
@@ -1,4 +1,4 @@
-# $XTermId: Makefile,v 1.127 2025/10/21 07:35:54 tom Exp $
+# $XTermId: Makefile,v 1.128 2025/12/01 01:19:31 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=	404
+DISTVERSION=	405
 CATEGORIES=	x11
 MASTER_SITES=	https://invisible-island.net/archives/xterm/:src1 \
 		https://invisible-mirror.net/archives/xterm/:src1
Index: package/pkgsrc/Makefile
--- xterm-404+/package/pkgsrc/Makefile	2025-10-21 07:35:54.000000000 +0000
+++ xterm-405/package/pkgsrc/Makefile	2025-12-01 01:19:31.000000000 +0000
@@ -1,6 +1,6 @@
 # $NetBSD: Makefile,v 1.156 2024/10/27 05:42:46 pin Exp $
 
-DISTNAME=	xterm-404
+DISTNAME=	xterm-405
 CATEGORIES=	x11
 MASTER_SITES=	https://invisible-island.net/archives/xterm/
 EXTRACT_SUFX=	.tgz
Index: package/xterm.spec
--- xterm-404+/package/xterm.spec	2025-10-21 07:35:54.000000000 +0000
+++ xterm-405/package/xterm.spec	2025-12-14 17:26:24.000000000 +0000
@@ -1,11 +1,11 @@
-# $XTermId: xterm.spec,v 1.202 2025/10/21 07:35:54 tom Exp $
+# $XTermId: xterm.spec,v 1.205 2025/12/14 17:26:24 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: 404
+Version: 405
 Release: 1
 License: X11
 Group: User Interface/X
@@ -269,8 +269,8 @@
 
 %changelog
 
-* Tue Oct 21 2025 Thomas E. Dickey
-- testing xterm-dev 404-1
+* Fri Dec 12 2025 Thomas E. Dickey
+- testing xterm-dev 405-4
 
 * Fri Nov 25 2022 Thomas E. Dickey
 - Fedora 37 has no xorg-x11-docs
Index: screen.c
--- xterm-404+/screen.c	2025-11-29 11:30:11.000000000 +0000
+++ xterm-405/screen.c	2025-12-12 01:19:35.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: screen.c,v 1.664 2025/11/29 11:30:11 tom Exp $ */
+/* $XTermId: screen.c,v 1.665 2025/12/12 01:19:35 tom Exp $ */
 
 /*
  * Copyright 1999-2024,2025 by Thomas E. Dickey
@@ -1858,7 +1858,7 @@
 			    if (com_off[i] != 0) {
 				int my_x;
 
-				params.on_wide = sizes[i] > 1;
+				params.on_wide = SelectedSize(sizes[i]) > 1;
 				if (params.on_wide)
 				    my_x = LineCursorX(screen, ld, i - 1);
 				else
@@ -1937,7 +1937,7 @@
 		for (i = lastind; i < col; i++) {
 		    int my_x;
 
-		    params.on_wide = sizes[i] > 1;
+		    params.on_wide = SelectedSize(sizes[i]) > 1;
 		    if (params.on_wide)
 			my_x = LineCursorX(screen, ld, i - 1);
 		    else
Index: util.c
--- xterm-404+/util.c	2025-11-29 11:33:39.000000000 +0000
+++ xterm-405/util.c	2025-12-12 01:16:39.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: util.c,v 1.964 2025/11/29 11:33:39 tom Exp $ */
+/* $XTermId: util.c,v 1.965 2025/12/12 01:16:39 tom Exp $ */
 
 /*
  * Copyright 1999-2024,2025 by Thomas E. Dickey
@@ -4063,7 +4063,7 @@
 	    recur.draw_flags |= DOUBLEWFONT;
 
 	    for (nlen = 0; nlen < len; ++nlen) {
-		int ch_width = size[nlen];
+		int ch_width = SelectedSize(size[nlen]);
 		if (ch_width > 1)
 		    ncells += (ch_width - 1);
 	    }
@@ -4233,7 +4233,7 @@
 		Boolean replace = False;
 		Boolean missing = False;
 		unsigned ch = (unsigned) text[last];
-		int ch_width = size[last];
+		int ch_width = SelectedSize(size[last]);
 		int filler = 0;
 #if OPT_WIDE_CHARS
 		int needed = forceDbl ? 2 : ch_width;
@@ -4548,7 +4548,7 @@
 		drewBoxes = True;
 		continue;
 	    }
-	    ch_width = size[last];
+	    ch_width = SelectedSize(size[last]);
 	    isMissing =
 		IsXtermMissingChar(screen, ch,
 				   ((recur.on_wide || ch_width > 1)
@@ -4738,7 +4738,7 @@
 	    IChar ch = mapped[src];
 
 	    if (ch != HIDDEN_CHAR) {
-		int ch_width = size[src];
+		int ch_width = SelectedSize(size[src]);
 		if (!needWide
 		    && !IsIcon(screen)
 		    && ((recur.on_wide || ch_width > 1)
Index: version.h
--- xterm-404+/version.h	2025-11-30 23:50:01.000000000 +0000
+++ xterm-405/version.h	2025-12-14 17:26:24.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: version.h,v 1.597 2025/11/30 23:50:01 tom Exp $ */
+/* $XTermId: version.h,v 1.600 2025/12/14 17:26:24 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   404
-#define XTERM_DATE    2025-11-30
+#define XTERM_PATCH   405
+#define XTERM_DATE    2025-12-14
 
 #ifndef __vendorversion__
 #define __vendorversion__ "XTerm"
Index: xterm.appdata.xml
--- xterm-404+/xterm.appdata.xml	2025-11-30 23:50:01.000000000 +0000
+++ xterm-405/xterm.appdata.xml	2025-12-14 17:26:24.000000000 +0000
@@ -35,7 +35,7 @@
     <keyword>terminal</keyword>
   </keywords>
   <releases>
-    <release version="404" date="2025-11-30"/>
+    <release version="405" date="2025-12-14"/>
   </releases>
   <url type="homepage">https://invisible-island.net/xterm/</url>
   <update_contact>dickey@invisible-island.net</update_contact>
Index: xterm.h
--- xterm-404+/xterm.h	2025-11-30 10:04:24.000000000 +0000
+++ xterm-405/xterm.h	2025-12-12 21:48:55.000000000 +0000
@@ -1,4 +1,4 @@
-/* $XTermId: xterm.h,v 1.975 2025/11/30 10:04:24 tom Exp $ */
+/* $XTermId: xterm.h,v 1.977 2025/12/12 21:48:55 tom Exp $ */
 
 /*
  * Copyright 1999-2024,2025 by Thomas E. Dickey
@@ -1116,8 +1116,10 @@
 #define IsLatin1(screen, n)  (IsAscii1(n) || ((n) >= Upper8Bits(screen)))
 #endif
 
+#define SelectedSize(n) (((n) >= 1 && (n) <= 2) ? (n) : 0)
+
 #define SelectSize(ld, col, source, target) \
-    target = source ? CharWidth(screen, source) : 1; \
+    target = (Char) (source ? CharWidth(screen, source) : 1); \
     if_OPT_WIDE_CHARS(screen, { \
 	size_t off; \
 	for_each_combData(off, ld) { \
Index: xterm.log.html
--- xterm-404+/xterm.log.html	2025-11-30 23:50:10.000000000 +0000
+++ xterm-405/xterm.log.html	2025-12-14 17:28:28.000000000 +0000
@@ -30,7 +30,7 @@
  * sale, use or other dealings in this Software without prior written        *
  * authorization.                                                            *
  *****************************************************************************
-  $XTermId: xterm.log.html,v 1.2744 2025/11/30 23:50:10 tom Exp $
+  $XTermId: xterm.log.html,v 1.2749 2025/12/14 17:28:28 tom Exp $
   -->
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
 <html>
@@ -70,6 +70,8 @@
   CHANGELOG</a>).</p>
 
   <ul>
+    <li><a href="#xterm_405">Patch #405 - 2025/12/14</a></li>
+
     <li><a href="#xterm_404">Patch #404 - 2025/11/30</a></li>
 
     <li><a href="#xterm_403">Patch #403 - 2025/10/19</a></li>
@@ -1086,6 +1088,20 @@
     <li><a href="#xterm_01">Patch #1 - 1996/1/6</a></li>
   </ul>
 
+  <h1><a name="xterm_405" id="xterm_405">Patch #405 -
+  2025/12/14</a></h1>
+
+  <ul>
+    <li>correct sign-extension in drawing changes made in <a href=
+    "#xterm_404">patch #404</a> (Debian #1122519)</li>
+
+    <li>further improvements to limit-checking for mouse button and
+    motion events (report by James Holderness).</li>
+
+    <li>correct index expression when handling overflow of title
+    stack.</li>
+  </ul>
+
   <h1><a name="xterm_404" id="xterm_404">Patch #404 -
   2025/11/30</a></h1>
 
