libncurses: Import https://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.5.tar.gz changes

Change-Id: I3433d30ca01359fd2e3623ede96b531f0b39cbfa
Signed-off-by: micky387 <mickaelsaibi@free.fr>
diff --git a/ncurses/base/MKkeyname.awk b/ncurses/base/MKkeyname.awk
index 7901611..b3d04ee 100644
--- a/ncurses/base/MKkeyname.awk
+++ b/ncurses/base/MKkeyname.awk
@@ -1,6 +1,7 @@
-# $Id: MKkeyname.awk,v 1.48 2013/08/24 17:37:22 tom Exp $
+# $Id: MKkeyname.awk,v 1.51 2020/02/02 23:34:34 tom Exp $
 ##############################################################################
-# Copyright (c) 1999-2012,2013 Free Software Foundation, Inc.                #
+# Copyright 2020 Thomas E. Dickey                                            #
+# Copyright 1998-2016,2017 Free Software Foundation, Inc.                    #
 #                                                                            #
 # Permission is hereby granted, free of charge, to any person obtaining a    #
 # copy of this software and associated documentation files (the "Software"), #
@@ -70,14 +71,13 @@
 	print "NCURSES_EXPORT(NCURSES_CONST char *)"
 	print "safe_keyname (SCREEN *sp, int c)"
 	print "{"
-	print "	int i;"
 	print "	char name[20];"
-	print "	char *p;"
 	print "	NCURSES_CONST char *result = 0;"
 	print ""
 	print "	if (c == -1) {"
 	print "		result = \"-1\";"
 	print "	} else {"
+	print "		int i;"
 	if (bigstrings) {
 		print "		for (i = 0; _nc_key_names[i].offset != -1; i++) {"
 		print "			if (_nc_key_names[i].code == c) {"
@@ -114,7 +114,7 @@
 	print "				/* create and cache result as needed */"
 	print "				if (MyTable[c] == 0) {"
 	print "					int cc = c;"
-	print "					p = name;"
+	print "					char *p = name;"
 	print "#define P_LIMIT (sizeof(name) - (size_t) (p - name))"
 	print "					if (cc >= 128 && m_prefix) {"
 	print "						_nc_STRCPY(p, \"M-\", P_LIMIT);"
@@ -135,7 +135,7 @@
 	print "		} else if (result == 0 && HasTerminal(sp)) {"
 	print "			int j, k;"
 	print "			char * bound;"
-	print "			TERMTYPE *tp = &(TerminalOf(sp)->type);"
+	print "			TERMTYPE2 *tp = &TerminalType(TerminalOf(sp));"
 	print "			unsigned save_trace = _nc_tracing;"
 	print ""
 	print "			_nc_tracing = 0;	/* prevent recursion via keybound() */"
@@ -166,8 +166,8 @@
 	print "#if NO_LEAKS"
 	print "void _nc_keyname_leaks(void)"
 	print "{"
-	print "	int j;"
 	print "	if (MyTable != 0) {"
+	print "		int j;"
 	print "		for (j = 0; j < SIZEOF_TABLE; ++j) {"
 	print "			FreeIfNeeded(MyTable[j]);"
 	print "		}"
diff --git a/ncurses/base/MKlib_gen.sh b/ncurses/base/MKlib_gen.sh
index 4f7f19d..f0ac045 100755
--- a/ncurses/base/MKlib_gen.sh
+++ b/ncurses/base/MKlib_gen.sh
@@ -2,10 +2,11 @@
 #
 # MKlib_gen.sh -- generate sources from curses.h macro definitions
 #
-# ($Id: MKlib_gen.sh,v 1.50 2015/08/07 00:48:24 tom Exp $)
+# ($Id: MKlib_gen.sh,v 1.73 2022/10/01 13:14:20 tom Exp $)
 #
 ##############################################################################
-# Copyright (c) 1998-2014,2015 Free Software Foundation, Inc.                #
+# Copyright 2018-2021,2022 Thomas E. Dickey                                  #
+# Copyright 1998-2016,2017 Free Software Foundation, Inc.                    #
 #                                                                            #
 # Permission is hereby granted, free of charge, to any person obtaining a    #
 # copy of this software and associated documentation files (the "Software"), #
@@ -62,22 +63,31 @@
 if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
 if test "${LC_COLLATE+set}"  = set; then LC_COLLATE=C;  export LC_COLLATE;  fi
 
-preprocessor="$1 -DNCURSES_INTERNALS -I../include"
+preprocessor="$1 -DNCURSES_WATTR_MACROS -DNCURSES_INTERNALS -I../include"
 AWK="$2"
 USE="$3"
 
 # A patch discussed here:
 #	https://gcc.gnu.org/ml/gcc-patches/2014-06/msg02185.html
+#
 # introduces spurious #line markers into the preprocessor output.  The result
 # appears in gcc 5.0 and (with modification) in 5.1, making it necessary to
 # determine if we are using gcc, and if so, what version because the proposed
 # solution uses a nonstandard option.
-PRG=`echo "$1" | $AWK '{ sub(/^[[:space:]]*/,""); sub(/[[:space:]].*$/, ""); print; }' || exit 0`
-FSF=`"$PRG" --version 2>/dev/null || exit 0 | fgrep "Free Software Foundation" | head -n 1`
+#
+# As illustrated in
+#	https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60723
+#
+# gcc developers chose to ignore the problems with this, and summarized those
+# as "intriguing problems" in
+#	https://gcc.gnu.org/gcc-5/porting_to.html
+
+PRG=`echo "$1" | "$AWK" '{ sub(/^[ 	]*/,""); sub(/[ 	].*$/, ""); print; }' || exit 0`
+FSF=`("$PRG" --version 2>/dev/null || exit 0) | ${FGREP-grep -F} "Free Software Foundation" | head -n 1`
 ALL=`"$PRG" -dumpversion 2>/dev/null || exit 0`
-ONE=`echo "$ALL" | sed -e 's/\..*$//'`
+ONE=`echo "$ALL" | sed -e 's/[^0-9].*$//'`
 if test -n "$FSF" && test -n "$ALL" && test -n "$ONE" ; then
-	if test $ONE -ge 5 ; then
+	if test "$ONE" -ge 5 ; then
 		echo ".. adding -P option to work around $PRG $ALL" >&2
 		preprocessor="$preprocessor -P"
 	fi
@@ -91,14 +101,15 @@
 AW1=awk1_${PID}.awk
 AW2=awk2_${PID}.awk
 TMP=gen__${PID}.c
-trap "rm -f $ED1 $ED2 $ED3 $ED4 $AW1 $AW2 $TMP" 0 1 2 5 15
+trap "rm -f $ED1 $ED2 $ED3 $ED4 $AW1 $AW2 $TMP; exit 1" 1 2 3 15
+trap "rm -f $ED1 $ED2 $ED3 $ED4 $AW1 $AW2 $TMP" 0
 
 ALL=$USE
 if test "$USE" = implemented ; then
-	CALL="call_"
 	cat >$ED1 <<EOF1
 /^extern.*implemented/{
 	h
+	s/GCC_DEPRECATED([^)]*)//
 	s/NCURSES_SP_NAME(\([^)]*\))/NCURSES_SP_NAME___\1/
 	h
 	s/^.*implemented:\([^ 	*]*\).*/P_POUNDCif_USE_\1_SUPPORT/p
@@ -117,7 +128,6 @@
 }
 EOF1
 else
-	CALL=""
 	cat >$ED1 <<EOF1
 /^extern.*${ALL}/{
 	h
@@ -176,7 +186,8 @@
 
 if test "$USE" = generated ; then
 cat >$ED4 <<EOF
-	s/^\(.*\) \(.*\) (\(.*\))\$/NCURSES_EXPORT(\1) (\2) (\3)/
+	s/^\(.*\) \(.*\) (\(.*\))\$/NCURSES_EXPORT(\1) \2 (\3)/
+	/attr_[sg]et.* z)/s,z),z GCC_UNUSED),
 EOF
 else
 cat >$ED4 <<EOF
@@ -230,7 +241,7 @@
 	} else if ( $first == "bool" || $first == "NCURSES_BOOL" ) {
 		returnType = "Bool";
 	} else if ( $second == "*" ) {
-		returnType = "Ptr";
+		returnType = ($1 == "NCURSES_CONST") ? "CPtr" : "Ptr";
 	} else {
 		returnType = "Code";
 	}
@@ -241,6 +252,9 @@
 			break;
 		}
 	}
+	if (using == "implemented") {
+		printf "#undef %s\n", $myfunc;
+	}
 	print $0;
 	print "{";
 	argcount = 1;
@@ -273,6 +287,11 @@
 		dotrace = 0;
 	}
 
+	do_getstr = 0;
+	if ($myfunc ~ /get[n]?str/) {
+		do_getstr = 1;
+	}
+
 	call = "@@T((T_CALLED(\""
 	args = ""
 	comma = ""
@@ -309,7 +328,11 @@
 				call = call "%s"
 			} else if (pointer) {
 				if ( argtype == "char" ) {
-					call = call "%s"
+					if (do_getstr) {
+						call = call "%p"
+					} else {
+						call = call "%s"
+					}
 					comma = comma "_nc_visbuf2(" num ","
 					pointer = 0;
 				} else {
@@ -359,7 +382,7 @@
 	call = call ")); "
 
 	if (dotrace)
-		printf "%s", call
+		printf "%s\n\t@@", call
 
 	if (match($0, "^void")) {
 		call = ""
@@ -398,9 +421,10 @@
 
 cat >$AW2 <<EOF1
 BEGIN		{
+		printf "/* This file was generated by $0 $USE */\n"
+		print ""
 		print "/*"
 		print " * DO NOT EDIT THIS FILE BY HAND!"
-		printf " * It is generated by $0 %s.\n", "$USE"
 		if ( "$USE" == "generated" ) {
 			print " *"
 			print " * This is a file of trivial functions generated from macro"
@@ -417,14 +441,10 @@
 		print "#include <ncurses_cfg.h>"
 		print ""
 		print "#undef NCURSES_NOMACROS	/* _this_ file uses macros */"
+		print "#define NCURSES_NOMACROS 1"
 		print ""
 		print "#include <curses.priv.h>"
 		print ""
-		print "#undef vw_scanw"
-		print "#undef vwscanw"
-		print ""
-		print "#undef vw_printw"
-		print "#undef vwprintw"
 		}
 /^DECLARATIONS/	{start = 1; next;}
 		{
@@ -449,16 +469,17 @@
 			for (n = 1; n < start; ++n) {
 				value = calls[n];
 				if ( value !~ /P_POUNDC/ ) {
-					gsub(/[[:blank:]]+/," ",value);
-					sub(/^[[:alnum:]_]+ /,"",value);
-					sub(/^\* /,"",value);
-					gsub(/[[:alnum:]_]+ \* /,"",value);
+					gsub(/[ \t]+/," ",value);
+					sub(/^[0-9a-zA-Z_]+ /,"",value);
+					sub(/^[*][ \t]*/,"",value);
+					gsub("struct[ \t]*[0-9a-zA-Z_]+[ \t]*[*]","",value);
+					gsub(/[0-9a-zA-Z_]+[ \t]*[*][ \t]*/,"",value);
 					gsub(/ (const) /," ",value);
 					gsub(/ (int|short|attr_t|chtype|wchar_t|NCURSES_BOOL|NCURSES_OUTC|NCURSES_OUTC_sp|va_list) /," ",value);
 					gsub(/ void /,"",value);
 					sub(/^/,"call_",value);
-					gsub(/ (a[[:digit:]]|z) /, " 0 ", value);
-					gsub(/ int[[:blank:]]*[(][^)]+[)][(][^)]+[)]/, "0", value);
+					gsub(/ (a[0-9]|z) /, " 0 ", value);
+					gsub(/ int[ \t]*[(][^)]+[)][(][^)]+[)]/, "0", value);
 					printf "\t%s;\n", value;
 				} else {
 					print value;
@@ -484,7 +505,7 @@
 sed -n -f $ED1 \
 | sed -e 's/NCURSES_EXPORT(\(.*\)) \(.*\) (\(.*\))/\1 \2(\3)/' \
 | sed -f $ED2 \
-| $AWK -f $AW1 using=$USE \
+| "$AWK" -f $AW1 using="$USE" \
 | sed \
 	-e 's/ [ ]*$//g' \
 	-e 's/^\([a-zA-Z_][a-zA-Z_]*[ *]*\)/\1 gen_/' \
@@ -496,7 +517,7 @@
 	-e 's/  / /g' \
 	-e 's/^ //' \
 	-e 's/_Bool/NCURSES_BOOL/g' \
-| $AWK -f $AW2 \
+| "$AWK" -f $AW2 \
 | sed -f $ED3 \
 | sed \
 	-e 's/^.*T_CALLED.*returnCode( \([a-z].*) \));/	return \1;/' \
diff --git a/ncurses/base/MKunctrl.awk b/ncurses/base/MKunctrl.awk
index 51ceb63..e5362bd 100644
--- a/ncurses/base/MKunctrl.awk
+++ b/ncurses/base/MKunctrl.awk
@@ -1,6 +1,7 @@
-# $Id: MKunctrl.awk,v 1.27 2012/06/09 20:29:33 tom Exp $
+# $Id: MKunctrl.awk,v 1.30 2024/02/03 21:09:14 tom Exp $
 ##############################################################################
-# Copyright (c) 1998-2009,2012 Free Software Foundation, Inc.                #
+# Copyright 2020,2024 Thomas E. Dickey                                       #
+# Copyright 1998-2012,2017 Free Software Foundation, Inc.                    #
 #                                                                            #
 # Permission is hereby granted, free of charge, to any person obtaining a    #
 # copy of this software and associated documentation files (the "Software"), #
@@ -143,6 +144,7 @@
 		print  "\tint check = (int) ChCharOf(ch);"
 		print  "\tconst char *result;"
 		print  ""
+		print  "\t(void) sp;"
 		print  "\tif (check >= 0 && check < (int)SIZEOF(unctrl_table)) {"
 		print  "#if NCURSES_EXT_FUNCS"
 		print  "\t\tif ((sp != 0)"
@@ -153,6 +155,7 @@
 		print  "\t\telse"
 		print  "\t\tif ((check >= 160)"
 		print  "\t\t && (check < 256)"
+		print  "\t\t && !_nc_unicode_locale()"
 		print  "\t\t && ((sp != 0)"
 		print  "\t\t  && ((sp->_legacy_coding > 0)"
 		print  "\t\t   || (sp->_legacy_coding == 0"
diff --git a/ncurses/base/README b/ncurses/base/README
index 4677e42..2710b36 100644
--- a/ncurses/base/README
+++ b/ncurses/base/README
@@ -1,5 +1,6 @@
 -------------------------------------------------------------------------------
--- Copyright (c) 1998,2006 Free Software Foundation, Inc.                    --
+-- Copyright 2020 Thomas E. Dickey                                           --
+-- Copyright 1998,2006 Free Software Foundation, Inc.                        --
 --                                                                           --
 -- Permission is hereby granted, free of charge, to any person obtaining a   --
 -- copy of this software and associated documentation files (the             --
@@ -25,7 +26,7 @@
 -- sale, use or other dealings in this Software without prior written        --
 -- authorization.                                                            --
 -------------------------------------------------------------------------------
--- $Id: README,v 1.2 2006/04/22 22:19:37 tom Exp $
+-- $Id: README,v 1.3 2020/02/02 23:34:34 tom Exp $
 -------------------------------------------------------------------------------
 
 The functions in this directory are the generic (not device-specific) modules
diff --git a/ncurses/base/define_key.c b/ncurses/base/define_key.c
index c78375a..fb9ae36 100644
--- a/ncurses/base/define_key.c
+++ b/ncurses/base/define_key.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2014 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2009,2014 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -33,7 +34,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: define_key.c,v 1.21 2014/03/08 20:32:59 tom Exp $")
+MODULE_ID("$Id: define_key.c,v 1.22 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(define_key) (NCURSES_SP_DCLx const char *str, int keycode)
diff --git a/ncurses/base/key_defined.c b/ncurses/base/key_defined.c
index ef987a5..147e5fe 100644
--- a/ncurses/base/key_defined.c
+++ b/ncurses/base/key_defined.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 2003-2006,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020,2023 Thomas E. Dickey                                     *
+ * Copyright 2003-2006,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -31,8 +32,9 @@
  ****************************************************************************/
 
 #include <curses.priv.h>
+#include <tic.h>
 
-MODULE_ID("$Id: key_defined.c,v 1.9 2009/10/24 22:15:47 tom Exp $")
+MODULE_ID("$Id: key_defined.c,v 1.11 2023/06/24 15:36:32 tom Exp $")
 
 static int
 find_definition(TRIES * tree, const char *str)
@@ -40,7 +42,7 @@
     TRIES *ptr;
     int result = OK;
 
-    if (str != 0 && *str != '\0') {
+    if (VALID_STRING(str) && *str != '\0') {
 	for (ptr = tree; ptr != 0; ptr = ptr->sibling) {
 	    if (UChar(*str) == UChar(ptr->ch)) {
 		if (str[1] == '\0' && ptr->child != 0) {
diff --git a/ncurses/base/keybound.c b/ncurses/base/keybound.c
index 72790e8..bbd912a 100644
--- a/ncurses/base/keybound.c
+++ b/ncurses/base/keybound.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1999-2009,2011 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1999-2009,2011 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -33,7 +34,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: keybound.c,v 1.11 2011/10/22 16:47:05 tom Exp $")
+MODULE_ID("$Id: keybound.c,v 1.12 2020/02/02 23:34:34 tom Exp $")
 
 /*
  * Returns the count'th string definition which is associated with the
diff --git a/ncurses/base/keyok.c b/ncurses/base/keyok.c
index 37fddec..945228a 100644
--- a/ncurses/base/keyok.c
+++ b/ncurses/base/keyok.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2012,2014 Free Software Foundation, Inc.              *
+ * Copyright 2019-2020,2021 Thomas E. Dickey                                *
+ * Copyright 1998-2012,2014 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -33,13 +34,13 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: keyok.c,v 1.14 2014/03/08 20:32:59 tom Exp $")
+MODULE_ID("$Id: keyok.c,v 1.17 2021/06/17 21:26:02 tom Exp $")
 
 /*
  * Enable (or disable) ncurses' interpretation of a keycode by adding (or
  * removing) the corresponding 'tries' entry.
  *
- * Do this by storing a second tree of tries, which records the disabled keys. 
+ * Do this by storing a second tree of tries, which records the disabled keys.
  * The simplest way to copy is to make a function that returns the string (with
  * nulls set to 0200), then use that to reinsert the string into the
  * corresponding tree.
@@ -55,7 +56,6 @@
 #ifdef USE_TERM_DRIVER
 	code = CallDriver_2(sp, td_kyOk, c, flag);
 #else
-	T((T_CALLED("keyok(%d,%d)"), c, flag));
 	if (c >= 0) {
 	    int count = 0;
 	    char *s;
diff --git a/ncurses/base/legacy_coding.c b/ncurses/base/legacy_coding.c
index d8c8020..a71aee0 100644
--- a/ncurses/base/legacy_coding.c
+++ b/ncurses/base/legacy_coding.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 2005,2009 Free Software Foundation, Inc.                   *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 2005,2009 Free Software Foundation, Inc.                       *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -33,7 +34,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: legacy_coding.c,v 1.5 2009/10/24 22:15:00 tom Exp $")
+MODULE_ID("$Id: legacy_coding.c,v 1.6 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(use_legacy_coding) (NCURSES_SP_DCLx int level)
diff --git a/ncurses/base/lib_addch.c b/ncurses/base/lib_addch.c
index 4b16a47..a14bfd3 100644
--- a/ncurses/base/lib_addch.c
+++ b/ncurses/base/lib_addch.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2013,2014 Free Software Foundation, Inc.              *
+ * Copyright 2019-2021,2022 Thomas E. Dickey                                *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -36,7 +37,7 @@
 #include <curses.priv.h>
 #include <ctype.h>
 
-MODULE_ID("$Id: lib_addch.c,v 1.129 2014/08/16 20:41:04 tom Exp $")
+MODULE_ID("$Id: lib_addch.c,v 1.141 2022/06/12 15:16:41 tom Exp $")
 
 static const NCURSES_CH_T blankchar = NewChar(BLANK_TEXT);
 
@@ -51,7 +52,7 @@
  */
 
 /* Return bit mask for clearing color pair number if given ch has color */
-#define COLOR_MASK(ch) (~(attr_t)((ch) & A_COLOR ? A_COLOR : 0))
+#define COLOR_MASK(ch) (~(attr_t)(((ch) & A_COLOR) ? A_COLOR : 0))
 
 static NCURSES_INLINE NCURSES_CH_T
 render_char(WINDOW *win, NCURSES_CH_T ch)
@@ -117,14 +118,18 @@
 #endif
 
 static bool
-newline_forces_scroll(WINDOW *win, NCURSES_SIZE_T * ypos)
+newline_forces_scroll(WINDOW *win, NCURSES_SIZE_T *ypos)
 {
     bool result = FALSE;
 
-    if (*ypos >= win->_regtop && *ypos == win->_regbottom) {
-	*ypos = win->_regbottom;
-	result = TRUE;
-    } else {
+    if (*ypos >= win->_regtop && *ypos <= win->_regbottom) {
+	if (*ypos == win->_regbottom) {
+	    *ypos = win->_regbottom;
+	    result = TRUE;
+	} else if (*ypos < win->_maxy) {
+	    *ypos = (NCURSES_SIZE_T) (*ypos + 1);
+	}
+    } else if (*ypos < win->_maxy) {
 	*ypos = (NCURSES_SIZE_T) (*ypos + 1);
     }
     return result;
@@ -135,7 +140,7 @@
  * wrapped the cursor.  We don't do anything with this flag except set it when
  * wrapping, and clear it whenever we move the cursor.  If we try to wrap at
  * the lower-right corner of a window, we cannot move the cursor (since that
- * wouldn't be legal).  So we return an error (which is what SVr4 does). 
+ * wouldn't be legal).  So we return an error (which is what SVr4 does).
  * Unlike SVr4, we can successfully add a character to the lower-right corner
  * (Solaris 2.6 does this also, however).
  */
@@ -203,6 +208,20 @@
     WINDOW_EXT(win, addch_x) = x;
     WINDOW_EXT(win, addch_y) = y;
 
+    /*
+     * If the background character is a wide-character, that may interfere with
+     * processing multibyte characters in this function.
+     */
+    if (!is8bits(CharOf(CHDEREF(ch)))) {
+	if (WINDOW_EXT(win, addch_used) != 0) {
+	    /* discard the incomplete multibyte character */
+	    WINDOW_EXT(win, addch_used) = 0;
+	    TR(TRACE_VIRTPUT,
+	       ("Alert discarded incomplete multibyte"));
+	}
+	return 1;
+    }
+
     init_mb(state);
     buffer[WINDOW_EXT(win, addch_used)] = (char) CharOf(CHDEREF(ch));
     WINDOW_EXT(win, addch_used) += 1;
@@ -270,11 +289,11 @@
 
 		/* handle EILSEQ (i.e., when len >= -1) */
 		if (len == -1 && is8bits(CharOf(ch))) {
-		    int rc = OK;
 		    const char *s = NCURSES_SP_NAME(unctrl)
 		      (NCURSES_SP_ARGx (chtype) CharOf(ch));
 
 		    if (s[1] != '\0') {
+			int rc = OK;
 			while (*s != '\0') {
 			    rc = waddch(win, UChar(*s) | attr);
 			    if (rc != OK)
@@ -299,23 +318,32 @@
      * adjustments.
      */
     if_WIDEC({
-	int len = wcwidth(CharOf(ch));
+	int len = _nc_wacs_width(CharOf(ch));
 	int i;
 	int j;
-	wchar_t *chars;
 
 	if (len == 0) {		/* non-spacing */
 	    if ((x > 0 && y >= 0)
 		|| (win->_maxx >= 0 && win->_cury >= 1)) {
-		if (x > 0 && y >= 0)
-		    chars = (win->_line[y].text[x - 1].chars);
-		else
-		    chars = (win->_line[y - 1].text[win->_maxx].chars);
+		NCURSES_CH_T *dst;
+		wchar_t *chars;
+		if (x > 0 && y >= 0) {
+		    for (j = x - 1; j >= 0; --j) {
+			if (!isWidecExt(win->_line[y].text[j])) {
+			    win->_curx = (NCURSES_SIZE_T) j;
+			    break;
+			}
+		    }
+		    dst = &(win->_line[y].text[j]);
+		} else {
+		    dst = &(win->_line[y - 1].text[win->_maxx]);
+		}
+		chars = dst->chars;
 		for (i = 0; i < CCHARW_MAX; ++i) {
 		    if (chars[i] == 0) {
 			TR(TRACE_VIRTPUT,
-			   ("added non-spacing %d: %x",
-			    x, (int) CharOf(ch)));
+			   ("adding non-spacing %s (level %d)",
+			    _tracech_t(CHREF(ch)), i));
 			chars[i] = CharOf(ch);
 			break;
 		    }
@@ -339,6 +367,7 @@
 		    return ERR;
 		x = win->_curx;
 		y = win->_cury;
+		CHECK_POSITION(win, x, y);
 		line = win->_line + y;
 	    }
 	    /*
@@ -390,9 +419,9 @@
   testwrapping:
     );
 
-    TR(TRACE_VIRTPUT, ("cell (%ld, %ld..%d) = %s",
-		       (long) win->_cury, (long) win->_curx, x - 1,
-		       _tracech_t(CHREF(ch))));
+    TR(TRACE_VIRTPUT, ("cell (%d, %d..%d) = %s",
+		       win->_cury, win->_curx, x - 1,
+		       _tracech_t(CHREF(line->text[win->_curx]))));
 
     if (x > win->_maxx) {
 	return wrap_to_next_line(win);
@@ -427,7 +456,7 @@
 	       s[1] == 0
 	)
 	|| (
-	       (isprint((int)t) && !iscntrl((int)t))
+	       (isprint((int) t) && !iscntrl((int) t))
 #if USE_WIDEC_SUPPORT
 	       || ((sp == 0 || !sp->_legacy_coding) &&
 		   (WINDOW_EXT(win, addch_used)
@@ -443,6 +472,7 @@
      */
     x = win->_curx;
     y = win->_cury;
+    CHECK_POSITION(win, x, y);
 
     switch (t) {
     case '\t':
diff --git a/ncurses/base/lib_addstr.c b/ncurses/base/lib_addstr.c
index a1a55cb..a3753af 100644
--- a/ncurses/base/lib_addstr.c
+++ b/ncurses/base/lib_addstr.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc.              *
+ * Copyright 2019-2022,2023 Thomas E. Dickey                                *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -44,7 +45,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_addstr.c,v 1.52 2011/05/28 23:02:09 tom Exp $")
+MODULE_ID("$Id: lib_addstr.c,v 1.62 2023/11/21 21:47:23 tom Exp $")
 
 NCURSES_EXPORT(int)
 waddnstr(WINDOW *win, const char *astr, int n)
@@ -54,14 +55,17 @@
 
     T((T_CALLED("waddnstr(%p,%s,%d)"), (void *) win, _nc_visbufn(astr, n), n));
 
-    if (win && (str != 0)) {
+    if (win && (str != 0) && (n != 0)) {
+	bool explicit = (n > 0);
+
 	TR(TRACE_VIRTPUT | TRACE_ATTRS,
 	   ("... current %s", _traceattr(WINDOW_ATTRS(win))));
 	code = OK;
-	if (n < 0)
-	    n = (int) strlen(astr);
 
-	TR(TRACE_VIRTPUT, ("str is not null, length = %d", n));
+	TR(TRACE_VIRTPUT, ("str is not null, length = %d",
+			   (explicit ? n : (int) strlen(str))));
+	if (!explicit)
+	    n = INT_MAX;
 	while ((n-- > 0) && (*str != '\0')) {
 	    NCURSES_CH_T ch;
 	    TR(TRACE_VIRTPUT, ("*str = %#o", UChar(*str)));
@@ -87,7 +91,7 @@
 
     T((T_CALLED("waddchnstr(%p,%p,%d)"), (void *) win, (const void *) astr, n));
 
-    if (!win)
+    if (!win || !astr)
 	returnCode(ERR);
 
     y = win->_cury;
@@ -142,7 +146,7 @@
        _nc_viscbuf(astr, n),
        n));
 
-    if (!win)
+    if (!win || !astr)
 	returnCode(ERR);
 
     y = win->_cury;
@@ -183,7 +187,7 @@
 	if (isWidecExt(astr[i]))
 	    continue;
 
-	len = wcwidth(CharOf(astr[i]));
+	len = _nc_wacs_width(CharOf(astr[i]));
 
 	if (x + len - 1 <= win->_maxx) {
 	    line->text[x] = _nc_render(win, astr[i]);
@@ -194,6 +198,8 @@
 		    }
 		    SetWidecExt(line->text[x + j], j);
 		}
+	    } else {
+		len = 1;
 	    }
 	    x = (NCURSES_SIZE_T) (x + len);
 	    end += len - 1;
@@ -224,14 +230,17 @@
 
     T((T_CALLED("waddnwstr(%p,%s,%d)"), (void *) win, _nc_viswbufn(str, n), n));
 
-    if (win && (str != 0)) {
+    if (win && (str != 0) && (n != 0)) {
+	bool explicit = (n > 0);
+
 	TR(TRACE_VIRTPUT | TRACE_ATTRS,
 	   ("... current %s", _traceattr(WINDOW_ATTRS(win))));
 	code = OK;
-	if (n < 0)
-	    n = (int) wcslen(str);
 
-	TR(TRACE_VIRTPUT, ("str is not null, length = %d", n));
+	TR(TRACE_VIRTPUT, ("str is not null, length = %d",
+			   (explicit ? n : (int) wcslen(str))));
+	if (!explicit)
+	    n = INT_MAX;
 	while ((n-- > 0) && (*str != L('\0'))) {
 	    NCURSES_CH_T ch;
 	    TR(TRACE_VIRTPUT, ("*str[0] = %#lx", (unsigned long) *str));
diff --git a/ncurses/base/lib_beep.c b/ncurses/base/lib_beep.c
index b775d56..b1a60b9 100644
--- a/ncurses/base/lib_beep.c
+++ b/ncurses/base/lib_beep.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2013,2014 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2013,2014 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -46,7 +47,7 @@
 #define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: lib_beep.c,v 1.17 2014/03/08 20:32:59 tom Exp $")
+MODULE_ID("$Id: lib_beep.c,v 1.18 2020/02/02 23:34:34 tom Exp $")
 
 /*
  *	beep()
diff --git a/ncurses/base/lib_bkgd.c b/ncurses/base/lib_bkgd.c
index c46ca42..4f99080 100644
--- a/ncurses/base/lib_bkgd.c
+++ b/ncurses/base/lib_bkgd.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2012,2014 Free Software Foundation, Inc.              *
+ * Copyright 2018-2020,2021 Thomas E. Dickey                                *
+ * Copyright 1998-2014,2016 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -36,7 +37,9 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_bkgd.c,v 1.49 2014/09/04 09:36:20 tom Exp $")
+MODULE_ID("$Id: lib_bkgd.c,v 1.63 2021/05/08 14:58:12 tom Exp $")
+
+static const NCURSES_CH_T blank = NewChar(BLANK_TEXT);
 
 /*
  * Set the window's background information.
@@ -48,7 +51,7 @@
 #endif
 wbkgrndset(WINDOW *win, const ARG_CH_T ch)
 {
-    T((T_CALLED("wbkgdset(%p,%s)"), (void *) win, _tracech_t(ch)));
+    T((T_CALLED("wbkgrndset(%p,%s)"), (void *) win, _tracech_t(ch)));
 
     if (win) {
 	attr_t off = AttrOf(win->_nc_bkgd);
@@ -61,7 +64,7 @@
 	{
 	    int pair;
 
-	    if ((pair = GetPair(win->_nc_bkgd)) != 0)
+	    if (GetPair(win->_nc_bkgd) != 0)
 		SET_WINDOW_PAIR(win, 0);
 	    if ((pair = GetPair(CHDEREF(ch))) != 0)
 		SET_WINDOW_PAIR(win, pair);
@@ -102,44 +105,147 @@
 wbkgdset(WINDOW *win, chtype ch)
 {
     NCURSES_CH_T wch;
+    T((T_CALLED("wbkgdset(%p,%s)"), (void *) win, _tracechtype(ch)));
     SetChar2(wch, ch);
     wbkgrndset(win, CHREF(wch));
+    returnVoid;
 }
 
 /*
  * Set the window's background information and apply it to each cell.
  */
-#if USE_WIDEC_SUPPORT
-NCURSES_EXPORT(int)
-#else
 static NCURSES_INLINE int
-#undef wbkgrnd
-#endif
-wbkgrnd(WINDOW *win, const ARG_CH_T ch)
+_nc_background(WINDOW *win, const ARG_CH_T ch, bool narrow)
 {
+#undef  SP_PARM
+#define SP_PARM SP		/* to use Charable() */
     int code = ERR;
-    int x, y;
 
-    T((T_CALLED("wbkgd(%p,%s)"), (void *) win, _tracech_t(ch)));
+#if USE_WIDEC_SUPPORT
+    T((T_CALLED("%s(%p,%s)"),
+       narrow ? "wbkgd" : "wbkgrnd",
+       (void *) win,
+       _tracecchar_t(ch)));
+#define TraceChar(c) _tracecchar_t2(1, &(c))
+#else
+    T((T_CALLED("%s(%p,%s)"),
+       "wbkgd",
+       (void *) win,
+       _tracech_t(ch)));
+    (void) narrow;
+#define TraceChar(c) _tracechar(CharOf(c))
+#endif
 
-    if (win) {
+    if (SP == 0) {
+	;
+    } else if (win) {
 	NCURSES_CH_T new_bkgd = CHDEREF(ch);
-	NCURSES_CH_T old_bkgrnd;
+	NCURSES_CH_T old_bkgd;
+	int y;
+	NCURSES_CH_T old_char;
+	attr_t old_attr;
+	int old_pair;
+	NCURSES_CH_T new_char;
+	attr_t new_attr;
+	int new_pair;
 
-	memset(&old_bkgrnd, 0, sizeof(old_bkgrnd));
-	(void) wgetbkgrnd(win, &old_bkgrnd);
+	/* SVr4 trims color info if non-color terminal */
+	if (!SP->_pair_limit) {
+	    RemAttr(new_bkgd, A_COLOR);
+	    SetPair(new_bkgd, 0);
+	}
+
+	/* avoid setting background-character to a null */
+	if (CharOf(new_bkgd) == 0) {
+	    NCURSES_CH_T tmp_bkgd = blank;
+	    SetAttr(tmp_bkgd, AttrOf(new_bkgd));
+	    SetPair(tmp_bkgd, GetPair(new_bkgd));
+	    new_bkgd = tmp_bkgd;
+	}
+
+	memset(&old_bkgd, 0, sizeof(old_bkgd));
+	(void) wgetbkgrnd(win, &old_bkgd);
+
+	if (!memcmp(&old_bkgd, &new_bkgd, sizeof(new_bkgd))) {
+	    T(("...unchanged"));
+	    returnCode(OK);
+	}
+
+	old_char = old_bkgd;
+	RemAttr(old_char, ~A_CHARTEXT);
+	old_attr = AttrOf(old_bkgd);
+	old_pair = GetPair(old_bkgd);
+
+	if (!(old_attr & A_COLOR)) {
+	    old_pair = 0;
+	}
+	T(("... old background char %s, attr %s, pair %d",
+	   TraceChar(old_char), _traceattr(old_attr), old_pair));
+
+	new_char = new_bkgd;
+	RemAttr(new_char, ~A_CHARTEXT);
+	new_attr = AttrOf(new_bkgd);
+	new_pair = GetPair(new_bkgd);
+
+	/* SVr4 limits background character to printable 7-bits */
+	if (
+#if USE_WIDEC_SUPPORT
+	       narrow &&
+#endif
+	       !Charable(new_bkgd)) {
+	    new_char = old_char;
+	}
+	if (!(new_attr & A_COLOR)) {
+	    new_pair = 0;
+	}
+	T(("... new background char %s, attr %s, pair %d",
+	   TraceChar(new_char), _traceattr(new_attr), new_pair));
 
 	(void) wbkgrndset(win, CHREF(new_bkgd));
-	(void) wattrset(win, (int) AttrOf(win->_nc_bkgd));
+
+	/* SVr4 updates color pair if old/new match, otherwise just attrs */
+	if ((new_pair != 0) && (new_pair == old_pair)) {
+	    WINDOW_ATTRS(win) = new_attr;
+	    SET_WINDOW_PAIR(win, new_pair);
+	} else {
+	    WINDOW_ATTRS(win) = new_attr;
+	}
 
 	for (y = 0; y <= win->_maxy; y++) {
+	    int x;
+
 	    for (x = 0; x <= win->_maxx; x++) {
-		if (CharEq(win->_line[y].text[x], old_bkgrnd)) {
-		    win->_line[y].text[x] = win->_nc_bkgd;
+		NCURSES_CH_T *cp = &(win->_line[y].text[x]);
+		int tmp_pair = GetPair(*cp);
+		attr_t tmp_attr = AttrOf(*cp);
+
+		if (CharEq(*cp, old_bkgd)) {
+#if USE_WIDEC_SUPPORT
+		    if (!narrow) {
+			if (Charable(new_bkgd)) {
+			    SetChar2(*cp, CharOf(new_char));
+			} else {
+			    SetChar(*cp, L' ', AttrOf(new_char));
+			}
+			memcpy(cp->chars,
+			       new_char.chars,
+			       CCHARW_MAX * sizeof(cp->chars[0]));
+		    } else
+#endif
+			SetChar2(*cp, CharOf(new_char));
+		}
+		if (tmp_pair != 0) {
+		    if (tmp_pair == old_pair) {
+			SetAttr(*cp, (tmp_attr & ~old_attr) | new_attr);
+			SetPair(*cp, new_pair);
+		    } else {
+			SetAttr(*cp,
+				(tmp_attr & (~old_attr | A_COLOR))
+				| (new_attr & ALL_BUT_COLOR));
+		    }
 		} else {
-		    NCURSES_CH_T wch = win->_line[y].text[x];
-		    RemAttr(wch, (~(A_ALTCHARSET | A_CHARTEXT)));
-		    win->_line[y].text[x] = _nc_render(win, wch);
+		    SetAttr(*cp, (tmp_attr & ~old_attr) | new_attr);
+		    SetPair(*cp, new_pair);
 		}
 	    }
 	}
@@ -150,10 +256,18 @@
     returnCode(code);
 }
 
+#if USE_WIDEC_SUPPORT
+NCURSES_EXPORT(int)
+wbkgrnd(WINDOW *win, const ARG_CH_T ch)
+{
+    return _nc_background(win, ch, FALSE);
+}
+#endif
+
 NCURSES_EXPORT(int)
 wbkgd(WINDOW *win, chtype ch)
 {
     NCURSES_CH_T wch;
     SetChar2(wch, ch);
-    return wbkgrnd(win, CHREF(wch));
+    return _nc_background(win, CHREF(wch), TRUE);
 }
diff --git a/ncurses/base/lib_box.c b/ncurses/base/lib_box.c
index 6f17c97..186f112 100644
--- a/ncurses/base/lib_box.c
+++ b/ncurses/base/lib_box.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2010,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -42,7 +43,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_box.c,v 1.24 2010/04/24 23:51:57 tom Exp $")
+MODULE_ID("$Id: lib_box.c,v 1.26 2020/02/02 23:34:34 tom Exp $")
 
 #if USE_WIDEC_SUPPORT
 static NCURSES_INLINE chtype
@@ -114,10 +115,20 @@
     win->_line[endy].lastchar = win->_line[0].lastchar = endx;
 
     for (i = 0; i <= endy; i++) {
+#if USE_WIDEC_SUPPORT
+	if (endx > 0 && isWidecExt(win->_line[i].text[endx])) {
+	    SetChar2(win->_line[i].text[endx - 1], ' ');
+	}
+#endif
 	SetChar2(win->_line[i].text[0], wls);
 	SetChar2(win->_line[i].text[endx], wrs);
 	win->_line[i].firstchar = 0;
 	win->_line[i].lastchar = endx;
+#if USE_WIDEC_SUPPORT
+	if (isWidecExt(win->_line[i].text[1])) {
+	    SetChar2(win->_line[i].text[1], ' ');
+	}
+#endif
     }
     SetChar2(win->_line[0].text[0], wtl);
     SetChar2(win->_line[0].text[endx], wtr);
diff --git a/ncurses/base/lib_chgat.c b/ncurses/base/lib_chgat.c
index 1eb1f59..74c4f75 100644
--- a/ncurses/base/lib_chgat.c
+++ b/ncurses/base/lib_chgat.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2010,2014 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -42,35 +43,38 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_chgat.c,v 1.10 2014/02/01 22:13:31 tom Exp $")
+MODULE_ID("$Id: lib_chgat.c,v 1.13 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 wchgat(WINDOW *win,
        int n,
        attr_t attr,
-       NCURSES_PAIRS_T color,
+       NCURSES_PAIRS_T pair_arg,
        const void *opts GCC_UNUSED)
 {
-    int i;
+    int code = ERR;
+    int color_pair = pair_arg;
 
     T((T_CALLED("wchgat(%p,%d,%s,%d)"),
        (void *) win,
        n,
        _traceattr(attr),
-       (int) color));
+       color_pair));
 
+    set_extended_pair(opts, color_pair);
     if (win) {
 	struct ldat *line = &(win->_line[win->_cury]);
+	int i;
 
-	toggle_attr_on(attr, ColorPair(color));
+	toggle_attr_on(attr, ColorPair(color_pair));
 
 	for (i = win->_curx; i <= win->_maxx && (n == -1 || (n-- > 0)); i++) {
 	    SetAttr(line->text[i], attr);
-	    SetPair(line->text[i], color);
+	    SetPair(line->text[i], color_pair);
 	    CHANGED_CELL(line, i);
 	}
 
-	returnCode(OK);
-    } else
-	returnCode(ERR);
+	code = OK;
+    }
+    returnCode(code);
 }
diff --git a/ncurses/base/lib_clear.c b/ncurses/base/lib_clear.c
index 008744c..2a1c97c 100644
--- a/ncurses/base/lib_clear.c
+++ b/ncurses/base/lib_clear.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2000,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2000,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,7 +41,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_clear.c,v 1.8 2009/10/24 22:33:29 tom Exp $")
+MODULE_ID("$Id: lib_clear.c,v 1.9 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 wclear(WINDOW *win)
diff --git a/ncurses/base/lib_clearok.c b/ncurses/base/lib_clearok.c
index ffc7d02..d98287c 100644
--- a/ncurses/base/lib_clearok.c
+++ b/ncurses/base/lib_clearok.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2000,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2000,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,7 +41,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_clearok.c,v 1.5 2009/10/24 22:34:53 tom Exp $")
+MODULE_ID("$Id: lib_clearok.c,v 1.6 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 clearok(WINDOW *win, bool flag)
diff --git a/ncurses/base/lib_clrbot.c b/ncurses/base/lib_clrbot.c
index cbf2206..e5482b9 100644
--- a/ncurses/base/lib_clrbot.c
+++ b/ncurses/base/lib_clrbot.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2006,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2006,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,7 +41,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_clrbot.c,v 1.21 2009/10/24 22:33:19 tom Exp $")
+MODULE_ID("$Id: lib_clrbot.c,v 1.22 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 wclrtobot(WINDOW *win)
diff --git a/ncurses/base/lib_clreol.c b/ncurses/base/lib_clreol.c
index 7aff84b..0b6b0ff 100644
--- a/ncurses/base/lib_clreol.c
+++ b/ncurses/base/lib_clreol.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2001,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020,2021 Thomas E. Dickey                                     *
+ * Copyright 1998-2001,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,7 +41,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_clreol.c,v 1.22 2009/10/24 22:33:06 tom Exp $")
+MODULE_ID("$Id: lib_clreol.c,v 1.24 2021/10/23 19:06:01 tom Exp $")
 
 NCURSES_EXPORT(int)
 wclrtoeol(WINDOW *win)
@@ -60,7 +61,7 @@
 	 * If we have just wrapped the cursor, the clear applies to the
 	 * new line, unless we are at the lower right corner.
 	 */
-	if ((win->_flags & _WRAPPED) != 0
+	if (IS_WRAPPED(win) != 0
 	    && y < win->_maxy) {
 	    win->_flags &= ~_WRAPPED;
 	}
@@ -69,7 +70,7 @@
 	 * There's no point in clearing if we're not on a legal
 	 * position, either.
 	 */
-	if ((win->_flags & _WRAPPED) != 0
+	if (IS_WRAPPED(win)
 	    || y > win->_maxy
 	    || x > win->_maxx)
 	    returnCode(ERR);
diff --git a/ncurses/base/lib_color.c b/ncurses/base/lib_color.c
index 1322600..f001b22 100644
--- a/ncurses/base/lib_color.c
+++ b/ncurses/base/lib_color.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2013,2014 Free Software Foundation, Inc.              *
+ * Copyright 2018-2022,2023 Thomas E. Dickey                                *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -38,14 +39,17 @@
  * Handles color emulation of SYS V curses
  */
 
+#define NEW_PAIR_INTERNAL 1
+
 #include <curses.priv.h>
+#include <new_pair.h>
 #include <tic.h>
 
 #ifndef CUR
 #define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: lib_color.c,v 1.110 2014/03/08 20:04:44 tom Exp $")
+MODULE_ID("$Id: lib_color.c,v 1.150 2023/09/16 16:39:15 tom Exp $")
 
 #ifdef USE_TERM_DRIVER
 #define CanChange      InfoOf(SP_PARM).canchange
@@ -90,8 +94,6 @@
 
 #define DATA(r,g,b) {r,g,b, 0,0,0, 0}
 
-#define TYPE_CALLOC(type,elts) typeCalloc(type, (unsigned)(elts))
-
 #define MAX_PALETTE	8
 
 #define OkColorHi(n)	(((n) < COLORS) && ((n) < maxcolors))
@@ -136,14 +138,6 @@
 #endif
 
 /* *INDENT-ON* */
-
-/*
- * Ensure that we use color pairs only when colors have been started, and also
- * that the index is within the limits of the table which we allocated.
- */
-#define ValidPair(pair) \
-    ((SP_PARM != 0) && (pair >= 0) && (pair < SP_PARM->_pair_limit) && SP_PARM->_coloron)
-
 #if NCURSES_EXT_FUNCS
 /*
  * These are called from _nc_do_color(), which in turn is called from
@@ -193,12 +187,12 @@
     if (set_a_background) {
 	TPUTS_TRACE("set_a_background");
 	NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
-				TPARM_1(set_a_background, bg),
+				TIPARM_1(set_a_background, bg),
 				1, outc);
     } else {
 	TPUTS_TRACE("set_background");
 	NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
-				TPARM_1(set_background, toggled_colors(bg)),
+				TIPARM_1(set_background, toggled_colors(bg)),
 				1, outc);
     }
 #endif
@@ -213,12 +207,12 @@
     if (set_a_foreground) {
 	TPUTS_TRACE("set_a_foreground");
 	NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
-				TPARM_1(set_a_foreground, fg),
+				TIPARM_1(set_a_foreground, fg),
 				1, outc);
     } else {
 	TPUTS_TRACE("set_foreground");
 	NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
-				TPARM_1(set_foreground, toggled_colors(fg)),
+				TIPARM_1(set_foreground, toggled_colors(fg)),
 				1, outc);
     }
 #endif
@@ -251,6 +245,61 @@
     }
 }
 
+static bool
+init_direct_colors(NCURSES_SP_DCL0)
+{
+    static NCURSES_CONST char name[] = "RGB";
+
+    rgb_bits_t *result = &(SP_PARM->_direct_color);
+
+    result->value = 0;
+
+    if (COLORS >= 8) {
+	int n;
+	const char *s;
+	int width;
+
+	/* find the number of bits needed for the maximum color value */
+	for (width = 0; (1 << width) - 1 < (COLORS - 1); ++width) {
+	    ;
+	}
+
+	if (tigetflag(name) > 0) {
+	    n = (width + 2) / 3;
+	    result->bits.red = UChar(n);
+	    result->bits.green = UChar(n);
+	    result->bits.blue = UChar(width - (2 * n));
+	} else if ((n = tigetnum(name)) > 0) {
+	    result->bits.red = UChar(n);
+	    result->bits.green = UChar(n);
+	    result->bits.blue = UChar(n);
+	} else if ((s = tigetstr(name)) != 0 && VALID_STRING(s)) {
+	    int red = n;
+	    int green = n;
+	    int blue = width - (2 * n);
+
+	    switch (sscanf(s, "%d/%d/%d", &red, &green, &blue)) {
+	    default:
+		blue = width - (2 * n);
+		/* FALLTHRU */
+	    case 1:
+		green = n;
+		/* FALLTHRU */
+	    case 2:
+		red = n;
+		/* FALLTHRU */
+	    case 3:
+		/* okay */
+		break;
+	    }
+	    result->bits.red = UChar(red);
+	    result->bits.green = UChar(green);
+	    result->bits.blue = UChar(blue);
+	}
+    }
+    return (result->value != 0);
+}
+
 /*
  * Reset the color pair, e.g., to whatever color pair 0 is.
  */
@@ -310,7 +359,6 @@
 NCURSES_SP_NAME(start_color) (NCURSES_SP_DCL0)
 {
     int result = ERR;
-    int maxpairs = 0, maxcolors = 0;
 
     T((T_CALLED("start_color(%p)"), (void *) SP_PARM));
 
@@ -319,8 +367,8 @@
     } else if (SP_PARM->_coloron) {
 	result = OK;
     } else {
-	maxpairs = MaxPairs;
-	maxcolors = MaxColors;
+	int maxpairs = MaxPairs;
+	int maxcolors = MaxColors;
 	if (reset_color_pair(NCURSES_SP_ARG) != TRUE) {
 	    set_foreground_color(NCURSES_SP_ARGx
 				 default_fg(NCURSES_SP_ARG),
@@ -346,7 +394,10 @@
 	     * allow for default-color as a component of a color-pair.
 	     */
 	    SP_PARM->_pair_limit += (1 + (2 * maxcolors));
+#if !NCURSES_EXT_COLORS
+	    SP_PARM->_pair_limit = limit_PAIRS(SP_PARM->_pair_limit);
 #endif
+#endif /* NCURSES_EXT_FUNCS */
 	    SP_PARM->_pair_count = maxpairs;
 	    SP_PARM->_color_count = maxcolors;
 #if !USE_REENTRANT
@@ -354,19 +405,26 @@
 	    COLORS = maxcolors;
 #endif
 
-	    SP_PARM->_color_pairs = TYPE_CALLOC(colorpair_t, SP_PARM->_pair_limit);
+	    ReservePairs(SP_PARM, 16);
 	    if (SP_PARM->_color_pairs != 0) {
-		SP_PARM->_color_table = TYPE_CALLOC(color_t, maxcolors);
-		if (SP_PARM->_color_table != 0) {
-		    SP_PARM->_color_pairs[0] = PAIR_OF(default_fg(NCURSES_SP_ARG),
-						       default_bg(NCURSES_SP_ARG));
-		    init_color_table(NCURSES_SP_ARG);
+		if (init_direct_colors(NCURSES_SP_ARG)) {
+		    result = OK;
+		} else {
+		    TYPE_CALLOC(color_t, maxcolors, SP_PARM->_color_table);
+		    if (SP_PARM->_color_table != 0) {
+			MakeColorPair(SP_PARM->_color_pairs[0],
+				      default_fg(NCURSES_SP_ARG),
+				      default_bg(NCURSES_SP_ARG));
+			init_color_table(NCURSES_SP_ARG);
 
+			result = OK;
+		    }
+		}
+		if (result == OK) {
 		    T(("started color: COLORS = %d, COLOR_PAIRS = %d",
 		       COLORS, COLOR_PAIRS));
 
 		    SP_PARM->_coloron = 1;
-		    result = OK;
 		} else if (SP_PARM->_color_pairs != 0) {
 		    FreeAndNull(SP_PARM->_color_pairs);
 		}
@@ -388,7 +446,7 @@
 
 /* This function was originally written by Daniel Weaver <danw@znyx.com> */
 static void
-rgb2hls(int r, int g, int b, NCURSES_COLOR_T *h, NCURSES_COLOR_T *l, NCURSES_COLOR_T *s)
+rgb2hls(int r, int g, int b, int *h, int *l, int *s)
 /* convert RGB to HLS system */
 {
     int min, max, t;
@@ -399,7 +457,7 @@
 	max = b;
 
     /* calculate lightness */
-    *l = (NCURSES_COLOR_T) ((min + max) / 20);
+    *l = ((min + max) / 20);
 
     if (min == max) {		/* black, white and all shades of gray */
 	*h = 0;
@@ -409,19 +467,88 @@
 
     /* calculate saturation */
     if (*l < 50)
-	*s = (NCURSES_COLOR_T) (((max - min) * 100) / (max + min));
+	*s = (((max - min) * 100) / (max + min));
     else
-	*s = (NCURSES_COLOR_T) (((max - min) * 100) / (2000 - max - min));
+	*s = (((max - min) * 100) / (2000 - max - min));
 
     /* calculate hue */
     if (r == max)
-	t = (NCURSES_COLOR_T) (120 + ((g - b) * 60) / (max - min));
+	t = (120 + ((g - b) * 60) / (max - min));
     else if (g == max)
-	t = (NCURSES_COLOR_T) (240 + ((b - r) * 60) / (max - min));
+	t = (240 + ((b - r) * 60) / (max - min));
     else
-	t = (NCURSES_COLOR_T) (360 + ((r - g) * 60) / (max - min));
+	t = (360 + ((r - g) * 60) / (max - min));
 
-    *h = (NCURSES_COLOR_T) (t % 360);
+    *h = (t % 360);
+}
+
+/*
+ * Change all cells which use(d) a given color pair to force a repaint.
+ */
+NCURSES_EXPORT(void)
+_nc_change_pair(SCREEN *sp, int pair)
+{
+    int y, x;
+
+    if (CurScreen(sp)->_clear)
+	return;
+#if NO_LEAKS
+    if (_nc_globals.leak_checking)
+	return;
+#endif
+
+    for (y = 0; y <= CurScreen(sp)->_maxy; y++) {
+	struct ldat *ptr = &(CurScreen(sp)->_line[y]);
+	bool changed = FALSE;
+	for (x = 0; x <= CurScreen(sp)->_maxx; x++) {
+	    if (GetPair(ptr->text[x]) == pair) {
+		/* Set the old cell to zero to ensure it will be
+		   updated on the next doupdate() */
+		SetChar(ptr->text[x], 0, 0);
+		CHANGED_CELL(ptr, x);
+		changed = TRUE;
+	    }
+	}
+	if (changed)
+	    NCURSES_SP_NAME(_nc_make_oldhash) (NCURSES_SP_ARGx y);
+    }
+}
+
+NCURSES_EXPORT(void)
+_nc_reserve_pairs(SCREEN *sp, int want)
+{
+    int have = sp->_pair_alloc;
+
+    if (have == 0)
+	have = 1;
+    while (have <= want)
+	have *= 2;
+    if (have > sp->_pair_limit)
+	have = sp->_pair_limit;
+
+    if (sp->_color_pairs == 0) {
+	TYPE_CALLOC(colorpair_t, have, sp->_color_pairs);
+    } else if (have > sp->_pair_alloc) {
+#if NCURSES_EXT_COLORS
+	colorpair_t *next;
+
+	if ((next = typeCalloc(colorpair_t, have)) == 0)
+	    _nc_err_abort(MSG_NO_MEMORY);
+	memcpy(next, sp->_color_pairs, (size_t) sp->_pair_alloc * sizeof(*next));
+	_nc_copy_pairs(sp, next, sp->_color_pairs, sp->_pair_alloc);
+	free(sp->_color_pairs);
+	sp->_color_pairs = next;
+#else
+	TYPE_REALLOC(colorpair_t, have, sp->_color_pairs);
+	if (sp->_color_pairs != 0) {
+	    memset(sp->_color_pairs + sp->_pair_alloc, 0,
+		   sizeof(colorpair_t) * (size_t) (have - sp->_pair_alloc));
+	}
+#endif
+    }
+    if (sp->_color_pairs != 0) {
+	sp->_pair_alloc = have;
+    }
 }
 
 /*
@@ -429,32 +556,27 @@
  * values.
  */
 NCURSES_EXPORT(int)
-NCURSES_SP_NAME(init_pair) (NCURSES_SP_DCLx
-			    NCURSES_PAIRS_T pair,
-			    NCURSES_COLOR_T f,
-			    NCURSES_COLOR_T b)
+_nc_init_pair(SCREEN *sp, int pair, int f, int b)
 {
-    colorpair_t result;
+    static colorpair_t null_pair;
+    colorpair_t result = null_pair;
     colorpair_t previous;
     int maxcolors;
 
-    T((T_CALLED("init_pair(%p,%d,%d,%d)"),
-       (void *) SP_PARM,
-       (int) pair,
-       (int) f,
-       (int) b));
+    T((T_CALLED("init_pair(%p,%d,%d,%d)"), (void *) sp, pair, f, b));
 
-    if (!ValidPair(pair))
+    if (!ValidPair(sp, pair))
 	returnCode(ERR);
 
     maxcolors = MaxColors;
 
-    previous = SP_PARM->_color_pairs[pair];
+    ReservePairs(sp, pair);
+    previous = sp->_color_pairs[pair];
 #if NCURSES_EXT_FUNCS
-    if (SP_PARM->_default_color || SP_PARM->_assumed_color) {
+    if (sp->_default_color || sp->_assumed_color) {
 	bool isDefault = FALSE;
 	bool wasDefault = FALSE;
-	int default_pairs = SP_PARM->_default_pairs;
+	int default_pairs = sp->_default_pairs;
 
 	/*
 	 * Map caller's color number, e.g., -1, 0, 1, .., 7, etc., into
@@ -479,8 +601,8 @@
 	 * Check if the table entry that we are going to init/update used
 	 * default colors.
 	 */
-	if ((FORE_OF(previous) == COLOR_DEFAULT)
-	    || (BACK_OF(previous) == COLOR_DEFAULT))
+	if (isDefaultColor(FORE_OF(previous))
+	    || isDefaultColor(BACK_OF(previous)))
 	    wasDefault = TRUE;
 
 	/*
@@ -501,10 +623,10 @@
 	 * that does not will decrement the count - and possibly interfere
 	 * with sequentially adding new pairs.
 	 */
-	if (pair > (SP_PARM->_pair_count + default_pairs)) {
+	if (pair > (sp->_pair_count + default_pairs)) {
 	    returnCode(ERR);
 	}
-	SP_PARM->_default_pairs = default_pairs;
+	sp->_default_pairs = default_pairs;
     } else
 #endif
     {
@@ -520,34 +642,22 @@
      * initialized before a screen update is performed replacing original
      * pair colors with the new ones).
      */
-    result = PAIR_OF(f, b);
-    if (previous != 0
-	&& previous != result) {
-	int y, x;
-
-	for (y = 0; y <= CurScreen(SP_PARM)->_maxy; y++) {
-	    struct ldat *ptr = &(CurScreen(SP_PARM)->_line[y]);
-	    bool changed = FALSE;
-	    for (x = 0; x <= CurScreen(SP_PARM)->_maxx; x++) {
-		if (GetPair(ptr->text[x]) == pair) {
-		    /* Set the old cell to zero to ensure it will be
-		       updated on the next doupdate() */
-		    SetChar(ptr->text[x], 0, 0);
-		    CHANGED_CELL(ptr, x);
-		    changed = TRUE;
-		}
-	    }
-	    if (changed)
-		NCURSES_SP_NAME(_nc_make_oldhash) (NCURSES_SP_ARGx y);
-	}
+    MakeColorPair(result, f, b);
+    if ((FORE_OF(previous) != 0
+	 || BACK_OF(previous) != 0)
+	&& !isSamePair(previous, result)) {
+	_nc_change_pair(sp, pair);
     }
 
-    SP_PARM->_color_pairs[pair] = result;
-    if (GET_SCREEN_PAIR(SP_PARM) == pair)
-	SET_SCREEN_PAIR(SP_PARM, (chtype) (~0));	/* force attribute update */
+    _nc_reset_color_pair(sp, pair, &result);
+    sp->_color_pairs[pair] = result;
+    _nc_set_color_pair(sp, pair, cpINIT);
+
+    if (GET_SCREEN_PAIR(sp) == pair)
+	SET_SCREEN_PAIR(sp, (int) (~0));	/* force attribute update */
 
 #ifdef USE_TERM_DRIVER
-    CallDriver_3(SP_PARM, td_initpair, pair, f, b);
+    CallDriver_3(sp, td_initpair, pair, f, b);
 #else
     if (initialize_pair && InPalette(f) && InPalette(b)) {
 	const color_t *tp = DefaultPalette;
@@ -559,20 +669,29 @@
 	    (int) tp[b].red, (int) tp[b].green, (int) tp[b].blue));
 
 	NCURSES_PUTP2("initialize_pair",
-		      TPARM_7(initialize_pair,
-			      pair,
-			      (int) tp[f].red,
-			      (int) tp[f].green,
-			      (int) tp[f].blue,
-			      (int) tp[b].red,
-			      (int) tp[b].green,
-			      (int) tp[b].blue));
+		      TIPARM_7(initialize_pair,
+			       pair,
+			       (int) tp[f].red,
+			       (int) tp[f].green,
+			       (int) tp[f].blue,
+			       (int) tp[b].red,
+			       (int) tp[b].green,
+			       (int) tp[b].blue));
     }
 #endif
 
     returnCode(OK);
 }
 
+NCURSES_EXPORT(int)
+NCURSES_SP_NAME(init_pair) (NCURSES_SP_DCLx
+			    NCURSES_PAIRS_T pair,
+			    NCURSES_COLOR_T f,
+			    NCURSES_COLOR_T b)
+{
+    return _nc_init_pair(SP_PARM, pair, f, b);
+}
+
 #if NCURSES_SP_FUNCS
 NCURSES_EXPORT(int)
 init_pair(NCURSES_COLOR_T pair, NCURSES_COLOR_T f, NCURSES_COLOR_T b)
@@ -584,57 +703,63 @@
 #define okRGB(n) ((n) >= 0 && (n) <= 1000)
 
 NCURSES_EXPORT(int)
+_nc_init_color(SCREEN *sp, int color, int r, int g, int b)
+{
+    int result = ERR;
+    int maxcolors;
+
+    T((T_CALLED("init_color(%p,%d,%d,%d,%d)"),
+       (void *) sp,
+       color,
+       r, g, b));
+
+    if (sp == 0 || sp->_direct_color.value)
+	returnCode(result);
+
+    maxcolors = MaxColors;
+
+    if (InitColor
+	&& sp->_coloron
+	&& (color >= 0 && OkColorHi(color))
+	&& (okRGB(r) && okRGB(g) && okRGB(b))) {
+
+	sp->_color_table[color].init = 1;
+	sp->_color_table[color].r = r;
+	sp->_color_table[color].g = g;
+	sp->_color_table[color].b = b;
+
+	if (UseHlsPalette) {
+	    rgb2hls(r, g, b,
+		    &sp->_color_table[color].red,
+		    &sp->_color_table[color].green,
+		    &sp->_color_table[color].blue);
+	} else {
+	    sp->_color_table[color].red = r;
+	    sp->_color_table[color].green = g;
+	    sp->_color_table[color].blue = b;
+	}
+
+#ifdef USE_TERM_DRIVER
+	CallDriver_4(sp, td_initcolor, color, r, g, b);
+#else
+	NCURSES_PUTP2("initialize_color",
+		      TIPARM_4(initialize_color, color, r, g, b));
+#endif
+	sp->_color_defs = Max(color + 1, sp->_color_defs);
+
+	result = OK;
+    }
+    returnCode(result);
+}
+
+NCURSES_EXPORT(int)
 NCURSES_SP_NAME(init_color) (NCURSES_SP_DCLx
 			     NCURSES_COLOR_T color,
 			     NCURSES_COLOR_T r,
 			     NCURSES_COLOR_T g,
 			     NCURSES_COLOR_T b)
 {
-    int result = ERR;
-    int maxcolors;
-
-    T((T_CALLED("init_color(%p,%d,%d,%d,%d)"),
-       (void *) SP_PARM,
-       color,
-       r, g, b));
-
-    if (SP_PARM == 0)
-	returnCode(result);
-
-    maxcolors = MaxColors;
-
-    if (InitColor
-	&& SP_PARM->_coloron
-	&& (color >= 0 && OkColorHi(color))
-	&& (okRGB(r) && okRGB(g) && okRGB(b))) {
-
-	SP_PARM->_color_table[color].init = 1;
-	SP_PARM->_color_table[color].r = r;
-	SP_PARM->_color_table[color].g = g;
-	SP_PARM->_color_table[color].b = b;
-
-	if (UseHlsPalette) {
-	    rgb2hls(r, g, b,
-		    &SP_PARM->_color_table[color].red,
-		    &SP_PARM->_color_table[color].green,
-		    &SP_PARM->_color_table[color].blue);
-	} else {
-	    SP_PARM->_color_table[color].red = r;
-	    SP_PARM->_color_table[color].green = g;
-	    SP_PARM->_color_table[color].blue = b;
-	}
-
-#ifdef USE_TERM_DRIVER
-	CallDriver_4(SP_PARM, td_initcolor, color, r, g, b);
-#else
-	NCURSES_PUTP2("initialize_color",
-		      TPARM_4(initialize_color, color, r, g, b));
-#endif
-	SP_PARM->_color_defs = max(color + 1, SP_PARM->_color_defs);
-
-	result = OK;
-    }
-    returnCode(result);
+    return _nc_init_color(SP_PARM, color, r, g, b);
 }
 
 #if NCURSES_SP_FUNCS
@@ -676,7 +801,7 @@
     int code = FALSE;
 
     (void) SP_PARM;
-    T((T_CALLED("has_colors()")));
+    T((T_CALLED("has_colors(%p)"), (void *) SP_PARM));
     if (HasTerminal(SP_PARM)) {
 #ifdef USE_TERM_DRIVER
 	code = HasColor;
@@ -700,6 +825,73 @@
 }
 #endif
 
+static int
+_nc_color_content(SCREEN *sp, int color, int *r, int *g, int *b)
+{
+    int result = ERR;
+
+    T((T_CALLED("color_content(%p,%d,%p,%p,%p)"),
+       (void *) sp,
+       color,
+       (void *) r,
+       (void *) g,
+       (void *) b));
+
+    if (sp != 0) {
+	int maxcolors = MaxColors;
+
+	if (color >= 0 && OkColorHi(color) && sp->_coloron) {
+	    int c_r, c_g, c_b;
+
+	    if (sp->_direct_color.value) {
+		rgb_bits_t *work = &(sp->_direct_color);
+
+#define max_direct_color(name)	((1 << work->bits.name) - 1)
+#define value_direct_color(max) (1000 * ((color >> bitoff) & max)) / max
+
+		int max_r = max_direct_color(red);
+		int max_g = max_direct_color(green);
+		int max_b = max_direct_color(blue);
+
+		int bitoff = 0;
+
+		c_b = value_direct_color(max_b);
+		bitoff += work->bits.blue;
+
+		c_g = value_direct_color(max_g);
+		bitoff += work->bits.green;
+
+		c_r = value_direct_color(max_r);
+
+	    } else {
+		c_r = sp->_color_table[color].red;
+		c_g = sp->_color_table[color].green;
+		c_b = sp->_color_table[color].blue;
+	    }
+
+	    if (r)
+		*r = c_r;
+	    if (g)
+		*g = c_g;
+	    if (b)
+		*b = c_b;
+
+	    TR(TRACE_ATTRS, ("...color_content(%d,%d,%d,%d)",
+			     color, c_r, c_g, c_b));
+	    result = OK;
+	}
+    }
+    if (result != OK) {
+	if (r)
+	    *r = 0;
+	if (g)
+	    *g = 0;
+	if (b)
+	    *b = 0;
+    }
+    returnCode(result);
+}
+
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(color_content) (NCURSES_SP_DCLx
 				NCURSES_COLOR_T color,
@@ -707,40 +899,14 @@
 				NCURSES_COLOR_T *g,
 				NCURSES_COLOR_T *b)
 {
-    int result = ERR;
-    int maxcolors;
-
-    T((T_CALLED("color_content(%p,%d,%p,%p,%p)"),
-       (void *) SP_PARM,
-       color,
-       (void *) r,
-       (void *) g,
-       (void *) b));
-
-    if (SP_PARM == 0)
-	returnCode(result);
-
-    maxcolors = MaxColors;
-
-    if (color < 0 || !OkColorHi(color) || !SP_PARM->_coloron) {
-	result = ERR;
-    } else {
-	NCURSES_COLOR_T c_r = SP_PARM->_color_table[color].red;
-	NCURSES_COLOR_T c_g = SP_PARM->_color_table[color].green;
-	NCURSES_COLOR_T c_b = SP_PARM->_color_table[color].blue;
-
-	if (r)
-	    *r = c_r;
-	if (g)
-	    *g = c_g;
-	if (b)
-	    *b = c_b;
-
-	TR(TRACE_ATTRS, ("...color_content(%d,%d,%d,%d)",
-			 color, c_r, c_g, c_b));
-	result = OK;
+    int my_r, my_g, my_b;
+    int rc = _nc_color_content(SP_PARM, color, &my_r, &my_g, &my_b);
+    if (rc == OK) {
+	*r = limit_COLOR(my_r);
+	*g = limit_COLOR(my_g);
+	*b = limit_COLOR(my_b);
     }
-    returnCode(result);
+    return rc;
 }
 
 #if NCURSES_SP_FUNCS
@@ -755,29 +921,29 @@
 #endif
 
 NCURSES_EXPORT(int)
-NCURSES_SP_NAME(pair_content) (NCURSES_SP_DCLx
-			       NCURSES_PAIRS_T pair,
-			       NCURSES_COLOR_T *f,
-			       NCURSES_COLOR_T *b)
+_nc_pair_content(SCREEN *sp, int pair, int *f, int *b)
 {
     int result;
 
     T((T_CALLED("pair_content(%p,%d,%p,%p)"),
-       (void *) SP_PARM,
+       (void *) sp,
        (int) pair,
        (void *) f,
        (void *) b));
 
-    if (!ValidPair(pair)) {
+    if (!ValidPair(sp, pair)) {
 	result = ERR;
     } else {
-	NCURSES_COLOR_T fg = (NCURSES_COLOR_T) FORE_OF(SP_PARM->_color_pairs[pair]);
-	NCURSES_COLOR_T bg = (NCURSES_COLOR_T) BACK_OF(SP_PARM->_color_pairs[pair]);
+	int fg;
+	int bg;
 
+	ReservePairs(sp, pair);
+	fg = FORE_OF(sp->_color_pairs[pair]);
+	bg = BACK_OF(sp->_color_pairs[pair]);
 #if NCURSES_EXT_FUNCS
-	if (fg == COLOR_DEFAULT)
+	if (isDefaultColor(fg))
 	    fg = -1;
-	if (bg == COLOR_DEFAULT)
+	if (isDefaultColor(bg))
 	    bg = -1;
 #endif
 
@@ -787,7 +953,7 @@
 	    *b = bg;
 
 	TR(TRACE_ATTRS, ("...pair_content(%p,%d,%d,%d)",
-			 (void *) SP_PARM,
+			 (void *) sp,
 			 (int) pair,
 			 (int) fg, (int) bg));
 	result = OK;
@@ -795,6 +961,21 @@
     returnCode(result);
 }
 
+NCURSES_EXPORT(int)
+NCURSES_SP_NAME(pair_content) (NCURSES_SP_DCLx
+			       NCURSES_PAIRS_T pair,
+			       NCURSES_COLOR_T *f,
+			       NCURSES_COLOR_T *b)
+{
+    int my_f, my_b;
+    int rc = _nc_pair_content(SP_PARM, pair, &my_f, &my_b);
+    if (rc == OK) {
+	*f = limit_COLOR(my_f);
+	*b = limit_COLOR(my_b);
+    }
+    return rc;
+}
+
 #if NCURSES_SP_FUNCS
 NCURSES_EXPORT(int)
 pair_content(NCURSES_COLOR_T pair, NCURSES_COLOR_T *f, NCURSES_COLOR_T *b)
@@ -813,29 +994,29 @@
 #ifdef USE_TERM_DRIVER
     CallDriver_4(SP_PARM, td_docolor, old_pair, pair, reverse, outc);
 #else
-    NCURSES_COLOR_T fg = COLOR_DEFAULT;
-    NCURSES_COLOR_T bg = COLOR_DEFAULT;
-    NCURSES_COLOR_T old_fg = -1;
-    NCURSES_COLOR_T old_bg = -1;
+    int fg = COLOR_DEFAULT;
+    int bg = COLOR_DEFAULT;
+    int old_fg = -1;
+    int old_bg = -1;
 
-    if (!ValidPair(pair)) {
+    if (!ValidPair(SP_PARM, pair)) {
 	return;
     } else if (pair != 0) {
 	if (set_color_pair) {
 	    TPUTS_TRACE("set_color_pair");
 	    NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
-				    TPARM_1(set_color_pair, pair),
+				    TIPARM_1(set_color_pair, pair),
 				    1, outc);
 	    return;
 	} else if (SP_PARM != 0) {
-	    if (pair_content((NCURSES_COLOR_T) pair, &fg, &bg) == ERR)
+	    if (_nc_pair_content(SP_PARM, pair, &fg, &bg) == ERR)
 		return;
 	}
     }
 
     if (old_pair >= 0
 	&& SP_PARM != 0
-	&& pair_content((NCURSES_COLOR_T) old_pair, &old_fg, &old_bg) != ERR) {
+	&& _nc_pair_content(SP_PARM, old_pair, &old_fg, &old_bg) != ERR) {
 	if ((isDefaultColor(fg) && !isDefaultColor(old_fg))
 	    || (isDefaultColor(bg) && !isDefaultColor(old_bg))) {
 #if NCURSES_EXT_FUNCS
@@ -858,19 +1039,19 @@
 	}
     } else {
 	reset_color_pair(NCURSES_SP_ARG);
-	if (old_pair < 0)
+	if (old_pair < 0 && pair <= 0)
 	    return;
     }
 
 #if NCURSES_EXT_FUNCS
     if (isDefaultColor(fg))
-	fg = (NCURSES_COLOR_T) default_fg(NCURSES_SP_ARG);
+	fg = default_fg(NCURSES_SP_ARG);
     if (isDefaultColor(bg))
-	bg = (NCURSES_COLOR_T) default_bg(NCURSES_SP_ARG);
+	bg = default_bg(NCURSES_SP_ARG);
 #endif
 
     if (reverse) {
-	NCURSES_COLOR_T xx = fg;
+	int xx = fg;
 	fg = bg;
 	bg = xx;
     }
@@ -899,3 +1080,87 @@
 				   _nc_outc_wrapper);
 }
 #endif
+
+#if NCURSES_EXT_COLORS
+NCURSES_EXPORT(int)
+NCURSES_SP_NAME(init_extended_pair) (NCURSES_SP_DCLx int pair, int f, int b)
+{
+    return _nc_init_pair(SP_PARM, pair, f, b);
+}
+
+NCURSES_EXPORT(int)
+NCURSES_SP_NAME(init_extended_color) (NCURSES_SP_DCLx
+				      int color,
+				      int r, int g, int b)
+{
+    return _nc_init_color(SP_PARM, color, r, g, b);
+}
+
+NCURSES_EXPORT(int)
+NCURSES_SP_NAME(extended_color_content) (NCURSES_SP_DCLx
+					 int color,
+					 int *r, int *g, int *b)
+{
+    return _nc_color_content(SP_PARM, color, r, g, b);
+}
+
+NCURSES_EXPORT(int)
+NCURSES_SP_NAME(extended_pair_content) (NCURSES_SP_DCLx
+					int pair,
+					int *f, int *b)
+{
+    return _nc_pair_content(SP_PARM, pair, f, b);
+}
+
+NCURSES_EXPORT(void)
+NCURSES_SP_NAME(reset_color_pairs) (NCURSES_SP_DCL0)
+{
+    if (SP_PARM != 0) {
+	if (SP_PARM->_color_pairs) {
+	    _nc_free_ordered_pairs(SP_PARM);
+	    free(SP_PARM->_color_pairs);
+	    SP_PARM->_color_pairs = 0;
+	    SP_PARM->_pair_alloc = 0;
+	    ReservePairs(SP_PARM, 16);
+	    clearok(CurScreen(SP_PARM), TRUE);
+	    touchwin(StdScreen(SP_PARM));
+	}
+    }
+}
+
+#if NCURSES_SP_FUNCS
+NCURSES_EXPORT(int)
+init_extended_pair(int pair, int f, int b)
+{
+    return NCURSES_SP_NAME(init_extended_pair) (CURRENT_SCREEN, pair, f, b);
+}
+
+NCURSES_EXPORT(int)
+init_extended_color(int color, int r, int g, int b)
+{
+    return NCURSES_SP_NAME(init_extended_color) (CURRENT_SCREEN,
+						 color,
+						 r, g, b);
+}
+
+NCURSES_EXPORT(int)
+extended_color_content(int color, int *r, int *g, int *b)
+{
+    return NCURSES_SP_NAME(extended_color_content) (CURRENT_SCREEN,
+						    color,
+						    r, g, b);
+}
+
+NCURSES_EXPORT(int)
+extended_pair_content(int pair, int *f, int *b)
+{
+    return NCURSES_SP_NAME(extended_pair_content) (CURRENT_SCREEN, pair, f, b);
+}
+
+NCURSES_EXPORT(void)
+reset_color_pairs(void)
+{
+    NCURSES_SP_NAME(reset_color_pairs) (CURRENT_SCREEN);
+}
+#endif /* NCURSES_SP_FUNCS */
+#endif /* NCURSES_EXT_COLORS */
diff --git a/ncurses/base/lib_colorset.c b/ncurses/base/lib_colorset.c
index e935486..387edef 100644
--- a/ncurses/base/lib_colorset.c
+++ b/ncurses/base/lib_colorset.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2014 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2014,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -41,22 +42,23 @@
 #include <curses.priv.h>
 #include <ctype.h>
 
-MODULE_ID("$Id: lib_colorset.c,v 1.14 2014/02/01 22:10:42 tom Exp $")
+MODULE_ID("$Id: lib_colorset.c,v 1.16 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
-wcolor_set(WINDOW *win, NCURSES_PAIRS_T color_pair_number, void *opts)
+wcolor_set(WINDOW *win, NCURSES_PAIRS_T pair_arg, void *opts)
 {
     int code = ERR;
+    int color_pair = pair_arg;
 
-    T((T_CALLED("wcolor_set(%p,%d)"), (void *) win, (int) color_pair_number));
+    T((T_CALLED("wcolor_set(%p,%d)"), (void *) win, color_pair));
+    set_extended_pair(opts, color_pair);
     if (win
-	&& !opts
 	&& (SP != 0)
-	&& (color_pair_number >= 0)
-	&& (color_pair_number < SP->_pair_limit)) {
+	&& (color_pair >= 0)
+	&& (color_pair < SP->_pair_limit)) {
 	TR(TRACE_ATTRS, ("... current %ld", (long) GET_WINDOW_PAIR(win)));
-	SET_WINDOW_PAIR(win, color_pair_number);
-	if_EXT_COLORS(win->_color = color_pair_number);
+	SET_WINDOW_PAIR(win, color_pair);
+	if_EXT_COLORS(win->_color = color_pair);
 	code = OK;
     }
     returnCode(code);
diff --git a/ncurses/base/lib_delch.c b/ncurses/base/lib_delch.c
index 64c9da7..d39a8eb 100644
--- a/ncurses/base/lib_delch.c
+++ b/ncurses/base/lib_delch.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2001,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2001,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,7 +41,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_delch.c,v 1.13 2009/10/24 22:32:47 tom Exp $")
+MODULE_ID("$Id: lib_delch.c,v 1.14 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 wdelch(WINDOW *win)
diff --git a/ncurses/base/lib_delwin.c b/ncurses/base/lib_delwin.c
index 4bb536c..c96e417 100644
--- a/ncurses/base/lib_delwin.c
+++ b/ncurses/base/lib_delwin.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020-2021,2023 Thomas E. Dickey                                *
+ * Copyright 1998-2008,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -42,24 +43,29 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_delwin.c,v 1.20 2009/10/24 22:02:14 tom Exp $")
+MODULE_ID("$Id: lib_delwin.c,v 1.25 2023/10/21 11:12:44 tom Exp $")
 
 static bool
 cannot_delete(WINDOW *win)
 {
-    WINDOWLIST *p;
     bool result = TRUE;
-#ifdef USE_SP_WINDOWLIST
-    SCREEN *sp = _nc_screen_of(win);
+
+    if (IS_PAD(win)) {
+	result = FALSE;
+    } else {
+	WINDOWLIST *p;
+#if NCURSES_SP_FUNCS && defined(USE_SP_WINDOWLIST)
+	SCREEN *sp = _nc_screen_of(win);
 #endif
 
-    for (each_window(SP_PARM, p)) {
-	if (&(p->win) == win) {
-	    result = FALSE;
-	} else if ((p->win._flags & _SUBWIN) != 0
-		   && p->win._parent == win) {
-	    result = TRUE;
-	    break;
+	for (each_window(SP_PARM, p)) {
+	    if (&(p->win) == win) {
+		result = FALSE;
+	    } else if (IS_SUBWIN(&(p->win))
+		       && p->win._parent == win) {
+		result = TRUE;
+		break;
+	    }
 	}
     }
     return result;
@@ -76,15 +82,18 @@
 	if (win == 0
 	    || cannot_delete(win)) {
 	    result = ERR;
+	} else if (IS_PAD(win)) {
+	    win->_parent = NULL;
+	    result = _nc_freewin(win);
 	} else {
 #if NCURSES_SP_FUNCS
 	    SCREEN *sp = _nc_screen_of(win);
 #endif
-	    if (win->_flags & _SUBWIN)
+	    if (IS_SUBWIN(win)) {
 		touchwin(win->_parent);
-	    else if (CurScreen(SP_PARM) != 0)
+	    } else if (CurScreen(SP_PARM) != 0) {
 		touchwin(CurScreen(SP_PARM));
-
+	    }
 	    result = _nc_freewin(win);
 	}
 	_nc_unlock_global(curses);
diff --git a/ncurses/base/lib_dft_fgbg.c b/ncurses/base/lib_dft_fgbg.c
index 4d7fdd0..4dd43bb 100644
--- a/ncurses/base/lib_dft_fgbg.c
+++ b/ncurses/base/lib_dft_fgbg.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2011,2014 Free Software Foundation, Inc.              *
+ * Copyright 2020,2021 Thomas E. Dickey                                     *
+ * Copyright 1998-2014,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -37,7 +38,7 @@
 #define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: lib_dft_fgbg.c,v 1.27 2014/03/08 20:32:59 tom Exp $")
+MODULE_ID("$Id: lib_dft_fgbg.c,v 1.31 2021/04/03 22:27:18 tom Exp $")
 
 /*
  * Modify the behavior of color-pair 0 so that the library doesn't assume that
@@ -68,26 +69,29 @@
     int code = ERR;
 
     T((T_CALLED("assume_default_colors(%p,%d,%d)"), (void *) SP_PARM, fg, bg));
+    if (SP_PARM != 0) {
 #ifdef USE_TERM_DRIVER
-    if (sp != 0)
-	code = CallDriver_2(sp, td_defaultcolors, fg, bg);
+	code = CallDriver_2(SP_PARM, td_defaultcolors, fg, bg);
 #else
-    if ((orig_pair || orig_colors) && !initialize_pair) {
+	if ((orig_pair || orig_colors) && !initialize_pair) {
 
-	SP_PARM->_default_color = isDefaultColor(fg) || isDefaultColor(bg);
-	SP_PARM->_has_sgr_39_49 = (tigetflag("AX") == TRUE);
-	SP_PARM->_default_fg = isDefaultColor(fg) ? COLOR_DEFAULT : (fg & C_MASK);
-	SP_PARM->_default_bg = isDefaultColor(bg) ? COLOR_DEFAULT : (bg & C_MASK);
-	if (SP_PARM->_color_pairs != 0) {
-	    bool save = SP_PARM->_default_color;
-	    SP_PARM->_assumed_color = TRUE;
-	    SP_PARM->_default_color = TRUE;
-	    init_pair(0, (short) fg, (short) bg);
-	    SP_PARM->_default_color = save;
+	    SP_PARM->_default_color = isDefaultColor(fg) || isDefaultColor(bg);
+	    SP_PARM->_has_sgr_39_49 = (tigetflag("AX") == TRUE);
+	    SP_PARM->_default_fg = isDefaultColor(fg) ? COLOR_DEFAULT : fg;
+	    SP_PARM->_default_bg = isDefaultColor(bg) ? COLOR_DEFAULT : bg;
+	    if (SP_PARM->_color_pairs != 0) {
+		bool save = SP_PARM->_default_color;
+		SP_PARM->_assumed_color = TRUE;
+		SP_PARM->_default_color = TRUE;
+		NCURSES_SP_NAME(init_pair) (NCURSES_SP_ARGx 0,
+					    (short)fg,
+					    (short)bg);
+		SP_PARM->_default_color = save;
+	    }
+	    code = OK;
 	}
-	code = OK;
-    }
 #endif
+    }
     returnCode(code);
 }
 
diff --git a/ncurses/base/lib_driver.c b/ncurses/base/lib_driver.c
index fb63b3c..c53802f 100644
--- a/ncurses/base/lib_driver.c
+++ b/ncurses/base/lib_driver.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 2008-2012,2014 Free Software Foundation, Inc.              *
+ * Copyright 2018,2020 Thomas E. Dickey                                     *
+ * Copyright 2009-2012,2014 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -33,8 +34,9 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_driver.c,v 1.6 2014/04/11 08:21:23 jpf Exp $")
+MODULE_ID("$Id: lib_driver.c,v 1.9 2020/08/29 19:53:35 tom Exp $")
 
+#ifndef EXP_WIN32_DRIVER
 typedef struct DriverEntry {
     const char *name;
     TERM_DRIVER *driver;
@@ -42,7 +44,7 @@
 
 static DRIVER_ENTRY DriverTable[] =
 {
-#ifdef __MINGW32__
+#ifdef _WIN32
     {"win32console", &_nc_WIN_DRIVER},
 #endif
     {"tinfo", &_nc_TINFO_DRIVER}	/* must be last */
@@ -76,6 +78,7 @@
     }
     returnCode(code);
 }
+#endif /* !EXP_WIN32_DRIVER */
 
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(has_key) (SCREEN *sp, int keycode)
diff --git a/ncurses/base/lib_echo.c b/ncurses/base/lib_echo.c
index 9e1d3c2..de7832f 100644
--- a/ncurses/base/lib_echo.c
+++ b/ncurses/base/lib_echo.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020,2023 Thomas E. Dickey                                     *
+ * Copyright 1998-2000,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -44,7 +45,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_echo.c,v 1.8 2009/10/24 22:02:14 tom Exp $")
+MODULE_ID("$Id: lib_echo.c,v 1.10 2023/04/29 18:57:12 tom Exp $")
 
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(echo) (NCURSES_SP_DCL0)
@@ -52,7 +53,7 @@
     T((T_CALLED("echo(%p)"), (void *) SP_PARM));
     if (0 == SP_PARM)
 	returnCode(ERR);
-    SP_PARM->_echo = TRUE;
+    IsEcho(SP_PARM) = TRUE;
     returnCode(OK);
 }
 
@@ -70,7 +71,7 @@
     T((T_CALLED("noecho(%p)"), (void *) SP_PARM));
     if (0 == SP_PARM)
 	returnCode(ERR);
-    SP_PARM->_echo = FALSE;
+    IsEcho(SP_PARM) = FALSE;
     returnCode(OK);
 }
 
diff --git a/ncurses/base/lib_endwin.c b/ncurses/base/lib_endwin.c
index 9ebf769..85d2bdb 100644
--- a/ncurses/base/lib_endwin.c
+++ b/ncurses/base/lib_endwin.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2014 Free Software Foundation, Inc.              *
+ * Copyright 2020,2023 Thomas E. Dickey                                     *
+ * Copyright 1998-2014,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -42,7 +43,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_endwin.c,v 1.23 2014/03/08 20:32:59 tom Exp $")
+MODULE_ID("$Id: lib_endwin.c,v 1.28 2023/11/11 21:27:32 tom Exp $")
 
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(endwin) (NCURSES_SP_DCL0)
@@ -51,20 +52,24 @@
 
     T((T_CALLED("endwin(%p)"), (void *) SP_PARM));
 
-    if (SP_PARM) {
+    if (SP_PARM != NULL) {
+	if (SP_PARM->_endwin != ewSuspend) {
 #ifdef USE_TERM_DRIVER
-	TERMINAL_CONTROL_BLOCK *TCB = TCBOf(SP_PARM);
+	    TERMINAL_CONTROL_BLOCK *TCB = TCBOf(SP_PARM);
 
-	SP_PARM->_endwin = TRUE;
-	if (TCB && TCB->drv && TCB->drv->td_scexit)
-	    TCB->drv->td_scexit(SP_PARM);
+	    SP_PARM->_endwin = ewSuspend;
+	    if (TCB && TCB->drv && TCB->drv->td_scexit)
+		TCB->drv->td_scexit(SP_PARM);
 #else
-	SP_PARM->_endwin = TRUE;
-	SP_PARM->_mouse_wrap(SP_PARM);
-	_nc_screen_wrap();
-	_nc_mvcur_wrap();	/* wrap up cursor addressing */
+	    SP_PARM->_endwin = ewSuspend;
+	    SP_PARM->_mouse_wrap(SP_PARM);
+	    _nc_screen_wrap();
+	    _nc_mvcur_wrap();	/* wrap up cursor addressing */
 #endif
-	code = NCURSES_SP_NAME(reset_shell_mode) (NCURSES_SP_ARG);
+	    code = OK;
+	}
+	if (NCURSES_SP_NAME(reset_shell_mode) (NCURSES_SP_ARG) == ERR)
+	    code = ERR;
     }
 
     returnCode(code);
diff --git a/ncurses/base/lib_erase.c b/ncurses/base/lib_erase.c
index bbf10ef..aa9437a 100644
--- a/ncurses/base/lib_erase.c
+++ b/ncurses/base/lib_erase.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2005,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020,2022 Thomas E. Dickey                                     *
+ * Copyright 1998-2009,2016 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -41,21 +42,25 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_erase.c,v 1.17 2009/10/24 22:32:29 tom Exp $")
+MODULE_ID("$Id: lib_erase.c,v 1.20 2022/09/03 21:40:27 tom Exp $")
 
 NCURSES_EXPORT(int)
 werase(WINDOW *win)
 {
     int code = ERR;
-    int y;
-    NCURSES_CH_T blank;
-    NCURSES_CH_T *sp, *end, *start;
+    NCURSES_CH_T *start;
 
     T((T_CALLED("werase(%p)"), (void *) win));
 
     if (win) {
+	NCURSES_CH_T blank;
+	NCURSES_CH_T *sp;
+	int y;
+
 	blank = win->_nc_bkgd;
 	for (y = 0; y <= win->_maxy; y++) {
+	    NCURSES_CH_T *end;
+
 	    start = win->_line[y].text;
 	    end = &start[win->_maxx];
 
diff --git a/ncurses/base/lib_flash.c b/ncurses/base/lib_flash.c
index 7f25038..975d5f5 100644
--- a/ncurses/base/lib_flash.c
+++ b/ncurses/base/lib_flash.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2013,2014 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2013,2014 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -46,7 +47,7 @@
 #define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: lib_flash.c,v 1.14 2014/03/08 20:32:59 tom Exp $")
+MODULE_ID("$Id: lib_flash.c,v 1.15 2020/02/02 23:34:34 tom Exp $")
 
 /*
  *	flash()
diff --git a/ncurses/base/lib_freeall.c b/ncurses/base/lib_freeall.c
index 3936c92..75bbe77 100644
--- a/ncurses/base/lib_freeall.c
+++ b/ncurses/base/lib_freeall.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2012,2015 Free Software Foundation, Inc.              *
+ * Copyright 2018-2020,2021 Thomas E. Dickey                                *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -39,7 +40,7 @@
 extern int malloc_errfd;	/* FIXME */
 #endif
 
-MODULE_ID("$Id: lib_freeall.c,v 1.63 2015/05/02 23:46:26 tom Exp $")
+MODULE_ID("$Id: lib_freeall.c,v 1.76 2021/11/06 21:52:49 tom Exp $")
 
 /*
  * Free all ncurses data.  This is used for testing only (there's no practical
@@ -48,11 +49,11 @@
 NCURSES_EXPORT(void)
 NCURSES_SP_NAME(_nc_freeall) (NCURSES_SP_DCL0)
 {
-    WINDOWLIST *p, *q;
     static va_list empty_va;
 
     T((T_CALLED("_nc_freeall()")));
 #if NO_LEAKS
+    _nc_globals.leak_checking = TRUE;
     if (SP_PARM != 0) {
 	if (SP_PARM->_oldnum_list != 0) {
 	    FreeAndNull(SP_PARM->_oldnum_list);
@@ -60,12 +61,16 @@
 	if (SP_PARM->_panelHook.destroy != 0) {
 	    SP_PARM->_panelHook.destroy(SP_PARM->_panelHook.stdscr_pseudo_panel);
 	}
+#if NCURSES_EXT_COLORS
+	_nc_new_pair_leaks(SP_PARM);
+#endif
     }
 #endif
     if (SP_PARM != 0) {
 	_nc_lock_global(curses);
 
 	while (WindowList(SP_PARM) != 0) {
+	    WINDOWLIST *p, *q;
 	    bool deleted = FALSE;
 
 	    /* Delete only windows that're not a parent */
@@ -73,10 +78,24 @@
 		WINDOW *p_win = &(p->win);
 		bool found = FALSE;
 
+		if (IS_PAD(p_win))
+		    continue;
+
+#ifndef USE_SP_WINDOWLIST
+		if (p->screen != SP_PARM)
+		    continue;
+#endif
+
 		for (each_window(SP_PARM, q)) {
 		    WINDOW *q_win = &(q->win);
+
+#ifndef USE_SP_WINDOWLIST
+		    if (q->screen != SP_PARM)
+			continue;
+#endif
+
 		    if ((p != q)
-			&& (q_win->_flags & _SUBWIN)
+			&& IS_SUBWIN(q_win)
 			&& (p_win == q_win->_parent)) {
 			found = TRUE;
 			break;
@@ -131,10 +150,11 @@
 NCURSES_EXPORT(void)
 NCURSES_SP_NAME(_nc_free_and_exit) (NCURSES_SP_DCLx int code)
 {
+    T((T_CALLED("_nc_free_and_exit(%d)"), code));
     NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG);
     NCURSES_SP_NAME(_nc_freeall) (NCURSES_SP_ARG);
 #ifdef TRACE
-    trace(0);			/* close trace file, freeing its setbuf */
+    curses_trace(0);		/* close trace file, freeing its setbuf */
     {
 	static va_list fake;
 	free(_nc_varargs("?", fake));
@@ -143,7 +163,7 @@
     exit(code);
 }
 
-#else
+#else /* !HAVE_NC_FREEALL */
 NCURSES_EXPORT(void)
 _nc_freeall(void)
 {
@@ -154,12 +174,10 @@
 {
     if (SP_PARM) {
 	delscreen(SP_PARM);
-	if (SP_PARM->_term)
-	    NCURSES_SP_NAME(del_curterm) (NCURSES_SP_ARGx SP_PARM->_term);
     }
     exit(code);
 }
-#endif
+#endif /* HAVE_NC_FREEALL */
 
 #if NCURSES_SP_FUNCS
 NCURSES_EXPORT(void)
@@ -168,3 +186,16 @@
     NCURSES_SP_NAME(_nc_free_and_exit) (CURRENT_SCREEN, code);
 }
 #endif
+
+NCURSES_EXPORT(void)
+exit_curses(int code)
+{
+#if NO_LEAKS
+#if NCURSES_SP_FUNCS
+    NCURSES_SP_NAME(_nc_free_and_exit) (CURRENT_SCREEN, code);
+#else
+    _nc_free_and_exit(code);	/* deprecated... */
+#endif
+#endif
+    exit(code);
+}
diff --git a/ncurses/base/lib_getch.c b/ncurses/base/lib_getch.c
index 42eb9cc..8e47679 100644
--- a/ncurses/base/lib_getch.c
+++ b/ncurses/base/lib_getch.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2014,2015 Free Software Foundation, Inc.              *
+ * Copyright 2018-2022,2023 Thomas E. Dickey                                *
+ * Copyright 1998-2015,2016 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,9 +41,10 @@
 **
 */
 
+#define NEED_KEY_EVENT
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_getch.c,v 1.132 2015/05/09 17:10:41 tom Exp $")
+MODULE_ID("$Id: lib_getch.c,v 1.146 2023/04/29 18:57:12 tom Exp $")
 
 #include <fifo_defs.h>
 
@@ -69,16 +71,20 @@
 NCURSES_SP_NAME(set_escdelay) (NCURSES_SP_DCLx int value)
 {
     int code = OK;
-#if USE_REENTRANT
-    if (SP_PARM) {
-	SET_ESCDELAY(value);
-    } else {
+    if (value < 0) {
 	code = ERR;
-    }
+    } else {
+#if USE_REENTRANT
+	if (SP_PARM) {
+	    SET_ESCDELAY(value);
+	} else {
+	    code = ERR;
+	}
 #else
-    (void) SP_PARM;
-    ESCDELAY = value;
+	(void) SP_PARM;
+	ESCDELAY = value;
 #endif
+    }
     return code;
 }
 
@@ -87,12 +93,16 @@
 set_escdelay(int value)
 {
     int code;
+    if (value < 0) {
+	code = ERR;
+    } else {
 #if USE_REENTRANT
-    code = NCURSES_SP_NAME(set_escdelay) (CURRENT_SCREEN, value);
+	code = NCURSES_SP_NAME(set_escdelay) (CURRENT_SCREEN, value);
 #else
-    ESCDELAY = value;
-    code = OK;
+	ESCDELAY = value;
+	code = OK;
 #endif
+    }
     return code;
 }
 #endif
@@ -125,7 +135,7 @@
 }
 
 #ifdef USE_TERM_DRIVER
-# ifdef __MINGW32__
+# if defined(_NC_WINDOWS) && !defined(EXP_WIN32_DRIVER)
 static HANDLE
 _nc_get_handle(int fd)
 {
@@ -146,7 +156,14 @@
 #ifdef USE_TERM_DRIVER
     TERMINAL_CONTROL_BLOCK *TCB = TCBOf(sp);
     rc = TCBOf(sp)->drv->td_testmouse(TCBOf(sp), delay EVENTLIST_2nd(evl));
-# ifdef __MINGW32__
+# if defined(EXP_WIN32_DRIVER)
+    /* if we emulate terminfo on console, we have to use the console routine */
+    if (IsTermInfoOnConsole(sp)) {
+	rc = _nc_console_testmouse(sp,
+				   _nc_console_handle(sp->_ifd),
+				   delay EVENTLIST_2nd(evl));
+    } else
+# elif defined(_NC_WINDOWS)
     /* if we emulate terminfo on console, we have to use the console routine */
     if (IsTermInfoOnConsole(sp)) {
 	HANDLE fd = _nc_get_handle(sp->_ifd);
@@ -154,29 +171,36 @@
     } else
 # endif
 	rc = TCB->drv->td_testmouse(TCB, delay EVENTLIST_2nd(evl));
-#else
-#if USE_SYSMOUSE
+#else /* !USE_TERM_DRIVER */
+# if USE_SYSMOUSE
     if ((sp->_mouse_type == M_SYSMOUSE)
 	&& (sp->_sysmouse_head < sp->_sysmouse_tail)) {
 	rc = TW_MOUSE;
     } else
-#endif
+# endif
     {
+# if defined(EXP_WIN32_DRIVER)
+	rc = _nc_console_testmouse(sp,
+				   _nc_console_handle(sp->_ifd),
+				   delay
+				   EVENTLIST_2nd(evl));
+# else
 	rc = _nc_timed_wait(sp,
 			    TWAIT_MASK,
 			    delay,
 			    (int *) 0
 			    EVENTLIST_2nd(evl));
-#if USE_SYSMOUSE
+# endif
+# if USE_SYSMOUSE
 	if ((sp->_mouse_type == M_SYSMOUSE)
 	    && (sp->_sysmouse_head < sp->_sysmouse_tail)
 	    && (rc == 0)
 	    && (errno == EINTR)) {
 	    rc |= TW_MOUSE;
 	}
-#endif
+# endif
     }
-#endif
+#endif /* USE_TERM_DRIVER */
     return rc;
 }
 
@@ -224,11 +248,6 @@
     if (tail < 0)
 	return ERR;
 
-#ifdef HIDE_EINTR
-  again:
-    errno = 0;
-#endif
-
 #ifdef NCURSES_WGETCH_EVENTS
     if (evl
 #if USE_GPM_SUPPORT || USE_EMX_MOUSE || USE_SYSMOUSE
@@ -279,57 +298,51 @@
     } else
 #endif
 #if USE_KLIBC_KBD
-    if (NC_ISATTY(sp->_ifd) && sp->_cbreak) {
-	ch = _read_kbd(0, 1, !sp->_raw);
+    if (NC_ISATTY(sp->_ifd) && IsCbreak(sp)) {
+	ch = _read_kbd(0, 1, !IsRaw(sp));
 	n = (ch == -1) ? -1 : 1;
 	sp->_extended_key = (ch == 0);
     } else
 #endif
     {				/* Can block... */
-#ifdef USE_TERM_DRIVER
+#if defined(USE_TERM_DRIVER)
 	int buf;
-#ifdef __MINGW32__
-	if (NC_ISATTY(sp->_ifd) && IsTermInfoOnConsole(sp) && sp->_cbreak)
+# if defined(EXP_WIN32_DRIVER)
+	if (NC_ISATTY(sp->_ifd) && IsTermInfoOnConsole(sp) && IsCbreak(sp)) {
+	    _nc_set_read_thread(TRUE);
+	    n = _nc_console_read(sp,
+				 _nc_console_handle(sp->_ifd),
+				 &buf);
+	    _nc_set_read_thread(FALSE);
+	} else
+# elif defined(_NC_WINDOWS)
+	if (NC_ISATTY(sp->_ifd) && IsTermInfoOnConsole(sp) && IsCbreak(sp))
 	    n = _nc_mingw_console_read(sp,
 				       _nc_get_handle(sp->_ifd),
 				       &buf);
 	else
-#endif
+# endif	/* EXP_WIN32_DRIVER */
 	    n = CallDriver_1(sp, td_read, &buf);
 	ch = buf;
-#else
+#else /* !USE_TERM_DRIVER */
+#if defined(EXP_WIN32_DRIVER)
+	int buf;
+#endif
 	unsigned char c2 = 0;
-# if USE_PTHREADS_EINTR
-#  if USE_WEAK_SYMBOLS
-	if ((pthread_self) && (pthread_kill) && (pthread_equal))
-#  endif
-	    _nc_globals.read_thread = pthread_self();
-# endif
-	n = (int) read(sp->_ifd, &c2, (size_t) 1);
-#if USE_PTHREADS_EINTR
-	_nc_globals.read_thread = 0;
-#endif
-	ch = c2;
-#endif
-    }
 
-#ifdef HIDE_EINTR
-    /*
-     * Under System V curses with non-restarting signals, getch() returns
-     * with value ERR when a handled signal keeps it from completing.
-     * If signals restart system calls, OTOH, the signal is invisible
-     * except to its handler.
-     *
-     * We don't want this difference to show.  This piece of code
-     * tries to make it look like we always have restarting signals.
-     */
-    if (n <= 0 && errno == EINTR
-# if USE_PTHREADS_EINTR
-	&& (_nc_globals.have_sigwinch == 0)
-# endif
-	)
-	goto again;
+	_nc_set_read_thread(TRUE);
+#if defined(EXP_WIN32_DRIVER)
+	n = _nc_console_read(sp,
+			     _nc_console_handle(sp->_ifd),
+			     &buf);
+	c2 = buf;
+#else
+	n = (int) read(sp->_ifd, &c2, (size_t) 1);
 #endif
+	_nc_set_read_thread(FALSE);
+	ch = c2;
+#endif /* USE_TERM_DRIVER */
+    }
 
     if ((n == -1) || (n == 0)) {
 	TR(TRACE_IEVENT, ("read(%d,&ch,1)=%d, errno=%d", sp->_ifd, n, errno));
@@ -360,14 +373,24 @@
     tail = peek = 0;
 }
 
-static int kgetch(SCREEN *EVENTLIST_2nd(_nc_eventlist * evl));
+static int kgetch(SCREEN *, bool EVENTLIST_2nd(_nc_eventlist *));
 
 static void
 recur_wrefresh(WINDOW *win)
 {
 #ifdef USE_PTHREADS
     SCREEN *sp = _nc_screen_of(win);
-    if (_nc_use_pthreads && sp != CURRENT_SCREEN) {
+    bool same_sp;
+
+    if (_nc_use_pthreads) {
+	_nc_lock_global(curses);
+	same_sp = (sp == CURRENT_SCREEN);
+	_nc_unlock_global(curses);
+    } else {
+	same_sp = (sp == CURRENT_SCREEN);
+    }
+
+    if (_nc_use_pthreads && !same_sp) {
 	SCREEN *save_SP;
 
 	/* temporarily switch to the window's screen to check/refresh */
@@ -380,7 +403,7 @@
     } else
 #endif
 	if ((is_wintouched(win) || (win->_flags & _HASMOVED))
-	    && !(win->_flags & _ISPAD)) {
+	    && !IS_PAD(win)) {
 	wrefresh(win);
     }
 }
@@ -456,8 +479,8 @@
      */
     if (head == -1 &&
 	!sp->_notty &&
-	!sp->_raw &&
-	!sp->_cbreak &&
+	!IsRaw(sp) &&
+	!IsCbreak(sp) &&
 	!sp->_called_wgetch) {
 	char buf[MAXCOLUMNS], *bufp;
 
@@ -490,13 +513,13 @@
 
     recur_wrefresh(win);
 
-    if (win->_notimeout || (win->_delay >= 0) || (sp->_cbreak > 1)) {
+    if (win->_notimeout || (win->_delay >= 0) || (IsCbreak(sp) > 1)) {
 	if (head == -1) {	/* fifo is empty */
 	    int delay;
 
 	    TR(TRACE_IEVENT, ("timed delay in wgetch()"));
-	    if (sp->_cbreak > 1)
-		delay = (sp->_cbreak - 1) * 100;
+	    if (IsCbreak(sp) > 1)
+		delay = (IsCbreak(sp) - 1) * 100;
 	    else
 		delay = win->_delay;
 
@@ -527,7 +550,7 @@
 	 * This is tricky.  We only want to get special-key
 	 * events one at a time.  But we want to accumulate
 	 * mouse events until either (a) the mouse logic tells
-	 * us it's picked up a complete gesture, or (b)
+	 * us it has picked up a complete gesture, or (b)
 	 * there's a detectable time lapse after one.
 	 *
 	 * Note: if the mouse code starts failing to compose
@@ -537,7 +560,7 @@
 	int runcount = 0;
 
 	do {
-	    ch = kgetch(sp EVENTLIST_2nd(evl));
+	    ch = kgetch(sp, win->_notimeout EVENTLIST_2nd(evl));
 	    if (ch == KEY_MOUSE) {
 		++runcount;
 		if (sp->_mouse_inline(sp))
@@ -615,7 +638,7 @@
      * However, we provide the same visual result as Solaris, moving the
      * cursor to the left.
      */
-    if (sp->_echo && !(win->_flags & _ISPAD)) {
+    if (IsEcho(sp) && !IS_PAD(win)) {
 	chtype backup = (chtype) ((ch == KEY_BACKSPACE) ? '\b' : ch);
 	if (backup < KEY_MIN)
 	    wechochar(win, backup);
@@ -624,7 +647,7 @@
     /*
      * Simulate ICRNL mode
      */
-    if ((ch == '\r') && sp->_nl)
+    if ((ch == '\r') && IsNl(sp))
 	ch = '\n';
 
     /* Strip 8th-bit if so desired.  We do this only for characters that
@@ -649,7 +672,7 @@
     int code;
     int value;
 
-    T((T_CALLED("wgetch_events(%p,%p)"), win, evl));
+    T((T_CALLED("wgetch_events(%p,%p)"), (void *) win, (void *) evl));
     code = _nc_wgetch(win,
 		      &value,
 		      _nc_use_meta(win)
@@ -692,11 +715,11 @@
 */
 
 static int
-kgetch(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl))
+kgetch(SCREEN *sp, bool forever EVENTLIST_2nd(_nc_eventlist * evl))
 {
     TRIES *ptr;
     int ch = 0;
-    int timeleft = GetEscdelay(sp);
+    int timeleft = forever ? 9999999 : GetEscdelay(sp);
 
     TR(TRACE_IEVENT, ("kgetch() called"));
 
diff --git a/ncurses/base/lib_getstr.c b/ncurses/base/lib_getstr.c
index 0e44634..cac21fc 100644
--- a/ncurses/base/lib_getstr.c
+++ b/ncurses/base/lib_getstr.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2011 Free Software Foundation, Inc.              *
+ * Copyright 2018-2021,2023 Thomas E. Dickey                                *
+ * Copyright 1998-2011,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -38,9 +39,10 @@
 **
 */
 
+#define NEED_KEY_EVENT
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_getstr.c,v 1.30 2011/10/22 16:31:35 tom Exp $")
+MODULE_ID("$Id: lib_getstr.c,v 1.39 2023/04/29 19:00:17 tom Exp $")
 
 /*
  * This wipes out the last character, no matter whether it was a tab, control
@@ -76,7 +78,7 @@
 {
     SCREEN *sp = _nc_screen_of(win);
     TTY buf;
-    bool oldnl, oldecho, oldraw, oldcbreak;
+    TTY_FLAGS save_flags;
     char erasec;
     char killc;
     char *oldstr;
@@ -85,19 +87,18 @@
 
     T((T_CALLED("wgetnstr(%p,%p,%d)"), (void *) win, (void *) str, maxlen));
 
-    if (!win)
+    if (!win || !str)
 	returnCode(ERR);
 
+    maxlen = _nc_getstr_limit(maxlen);
+
     NCURSES_SP_NAME(_nc_get_tty_mode) (NCURSES_SP_ARGx &buf);
 
-    oldnl = sp->_nl;
-    oldecho = sp->_echo;
-    oldraw = sp->_raw;
-    oldcbreak = sp->_cbreak;
+    save_flags = sp->_tty_flags;
     NCURSES_SP_NAME(nl) (NCURSES_SP_ARG);
     NCURSES_SP_NAME(noecho) (NCURSES_SP_ARG);
-    NCURSES_SP_NAME(noraw) (NCURSES_SP_ARG);
-    NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG);
+    if (!save_flags._raw)
+	NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG);
 
     erasec = NCURSES_SP_NAME(erasechar) (NCURSES_SP_ARG);
     killc = NCURSES_SP_NAME(killchar) (NCURSES_SP_ARG);
@@ -111,7 +112,7 @@
     while ((ch = wgetch_events(win, evl)) != ERR) {
 	/*
 	 * Some terminals (the Wyse-50 is the most common) generate
-	 * a \n from the down-arrow key.  With this logic, it's the
+	 * a \n from the down-arrow key.  With this logic, it is the
 	 * user's choice whether to set kcud=\n for wgetch();
 	 * terminating *getstr() with \n should work either way.
 	 */
@@ -119,7 +120,7 @@
 	    || ch == '\r'
 	    || ch == KEY_DOWN
 	    || ch == KEY_ENTER) {
-	    if (oldecho == TRUE
+	    if (save_flags._echo == TRUE
 		&& win->_cury == win->_maxy
 		&& win->_scroll)
 		wechochar(win, (chtype) '\n');
@@ -135,18 +136,18 @@
 #endif
 	if (ch == erasec || ch == KEY_LEFT || ch == KEY_BACKSPACE) {
 	    if (str > oldstr) {
-		str = WipeOut(win, y, x, oldstr, str, oldecho);
+		str = WipeOut(win, y, x, oldstr, str, save_flags._echo);
 	    }
 	} else if (ch == killc) {
 	    while (str > oldstr) {
-		str = WipeOut(win, y, x, oldstr, str, oldecho);
+		str = WipeOut(win, y, x, oldstr, str, save_flags._echo);
 	    }
 	} else if (ch >= KEY_MIN
-		   || (maxlen >= 0 && str - oldstr >= maxlen)) {
+		   || (str - oldstr >= maxlen)) {
 	    NCURSES_SP_NAME(beep) (NCURSES_SP_ARG);
 	} else {
 	    *str++ = (char) ch;
-	    if (oldecho == TRUE) {
+	    if (save_flags._echo == TRUE) {
 		int oldy = win->_cury;
 		if (waddch(win, (chtype) ch) == ERR) {
 		    /*
@@ -156,9 +157,9 @@
 		     */
 		    win->_flags &= ~_WRAPPED;
 		    waddch(win, (chtype) ' ');
-		    str = WipeOut(win, y, x, oldstr, str, oldecho);
+		    str = WipeOut(win, y, x, oldstr, str, save_flags._echo);
 		    continue;
-		} else if (win->_flags & _WRAPPED) {
+		} else if (IS_WRAPPED(win)) {
 		    /*
 		     * If the last waddch forced a wrap &
 		     * scroll, adjust our reference point
@@ -187,11 +188,7 @@
     /* Restore with a single I/O call, to fix minor asymmetry between
      * raw/noraw, etc.
      */
-    sp->_nl = oldnl;
-    sp->_echo = oldecho;
-    sp->_raw = oldraw;
-    sp->_cbreak = oldcbreak;
-
+    sp->_tty_flags = save_flags;
     NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
 
     *str = '\0';
diff --git a/ncurses/base/lib_hline.c b/ncurses/base/lib_hline.c
index 1f03808..938c499 100644
--- a/ncurses/base/lib_hline.c
+++ b/ncurses/base/lib_hline.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -29,6 +30,8 @@
 /****************************************************************************
  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
+ *     and: Thomas E. Dickey                        1996-on                 *
+ *     and: Sven Verdoolaege                        2001                    *
  ****************************************************************************/
 
 /*
@@ -40,23 +43,21 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_hline.c,v 1.13 2010/12/19 01:48:39 tom Exp $")
+MODULE_ID("$Id: lib_hline.c,v 1.16 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 whline(WINDOW *win, chtype ch, int n)
 {
     int code = ERR;
-    int start;
-    int end;
 
     T((T_CALLED("whline(%p,%s,%d)"), (void *) win, _tracechtype(ch), n));
 
     if (win) {
 	struct ldat *line = &(win->_line[win->_cury]);
 	NCURSES_CH_T wch;
+	int start = win->_curx;
+	int end = start + n - 1;
 
-	start = win->_curx;
-	end = start + n - 1;
 	if (end > win->_maxx)
 	    end = win->_maxx;
 
@@ -68,6 +69,14 @@
 	    SetChar2(wch, ch);
 	wch = _nc_render(win, wch);
 
+#if USE_WIDEC_SUPPORT
+	if (start > 0 && isWidecExt(line->text[start])) {
+	    SetChar2(line->text[start - 1], ' ');
+	}
+	if (end < win->_maxx && isWidecExt(line->text[end + 1])) {
+	    SetChar2(line->text[end + 1], ' ');
+	}
+#endif
 	while (end >= start) {
 	    line->text[end] = wch;
 	    end--;
diff --git a/ncurses/base/lib_immedok.c b/ncurses/base/lib_immedok.c
index d51b60a..23afe5b 100644
--- a/ncurses/base/lib_immedok.c
+++ b/ncurses/base/lib_immedok.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2000,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2000,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,7 +41,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_immedok.c,v 1.5 2009/10/24 22:32:11 tom Exp $")
+MODULE_ID("$Id: lib_immedok.c,v 1.6 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(void)
 immedok(WINDOW *win, bool flag)
diff --git a/ncurses/base/lib_inchstr.c b/ncurses/base/lib_inchstr.c
index aebb6d6..38af239 100644
--- a/ncurses/base/lib_inchstr.c
+++ b/ncurses/base/lib_inchstr.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2010,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -41,7 +42,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_inchstr.c,v 1.12 2010/12/20 01:37:41 tom Exp $")
+MODULE_ID("$Id: lib_inchstr.c,v 1.17 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 winchnstr(WINDOW *win, chtype *str, int n)
@@ -50,16 +51,19 @@
 
     T((T_CALLED("winchnstr(%p,%p,%d)"), (void *) win, (void *) str, n));
 
-    if (!str)
-	returnCode(0);
+    if (!win || !str) {
+	i = ERR;
+    } else {
+	int row = win->_cury;
+	int col = win->_curx;
+	NCURSES_CH_T *text = win->_line[row].text;
 
-    if (win) {
-	for (; (n < 0 || (i < n)) && (win->_curx + i <= win->_maxx); i++)
-	    str[i] =
-		(chtype) CharOf(win->_line[win->_cury].text[win->_curx + i]) |
-		AttrOf(win->_line[win->_cury].text[win->_curx + i]);
+	for (; (n < 0 || (i < n)) && (col + i <= win->_maxx); i++) {
+	    str[i] = (((chtype) CharOf(text[col + i]) & A_CHARTEXT) |
+		      AttrOf(text[col + i]));
+	}
+	str[i] = (chtype) 0;
     }
-    str[i] = (chtype) 0;
 
     returnCode(i);
 }
diff --git a/ncurses/base/lib_initscr.c b/ncurses/base/lib_initscr.c
index 0e8a297..6b91491 100644
--- a/ncurses/base/lib_initscr.c
+++ b/ncurses/base/lib_initscr.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2014 Free Software Foundation, Inc.              *
+ * Copyright 2019,2020 Thomas E. Dickey                                     *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -29,7 +30,7 @@
 /****************************************************************************
  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
- *     and: Thomas E. Dickey                        1996-2003               *
+ *     and: Thomas E. Dickey                        1996-on                 *
  ****************************************************************************/
 
 /*
@@ -45,15 +46,13 @@
 #include <sys/termio.h>		/* needed for ISC */
 #endif
 
-MODULE_ID("$Id: lib_initscr.c,v 1.40 2014/04/26 18:47:51 juergen Exp $")
+MODULE_ID("$Id: lib_initscr.c,v 1.48 2020/09/07 14:26:48 tom Exp $")
 
 NCURSES_EXPORT(WINDOW *)
 initscr(void)
 {
     WINDOW *result;
 
-    NCURSES_CONST char *name;
-
     START_TRACE();
     T((T_CALLED("initscr()")));
 
@@ -62,11 +61,18 @@
 
     /* Portable applications must not call initscr() more than once */
     if (!_nc_globals.init_screen) {
+	const char *env;
+	char *name;
+
 	_nc_globals.init_screen = TRUE;
 
-	if ((name = getenv("TERM")) == 0
-	    || *name == '\0')
-	    name = "unknown";
+	env = getenv("TERM");
+	(void) VALID_TERM_ENV(env, "unknown");
+
+	if ((name = strdup(env)) == NULL) {
+	    fprintf(stderr, "Error opening allocating $TERM.\n");
+	    ExitProgram(EXIT_FAILURE);
+	}
 #ifdef __CYGWIN__
 	/*
 	 * 2002/9/21
@@ -86,7 +92,7 @@
 #endif
 	if (newterm(name, stdout, stdin) == 0) {
 	    fprintf(stderr, "Error opening terminal: %s.\n", name);
-	    exit(EXIT_FAILURE);
+	    ExitProgram(EXIT_FAILURE);
 	}
 
 	/* def_shell_mode - done in newterm/_nc_setupscreen */
@@ -95,6 +101,7 @@
 #else
 	def_prog_mode();
 #endif
+	free(name);
     }
     result = stdscr;
     _nc_unlock_global(curses);
diff --git a/ncurses/base/lib_insch.c b/ncurses/base/lib_insch.c
index 32eaed7..894605c 100644
--- a/ncurses/base/lib_insch.c
+++ b/ncurses/base/lib_insch.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2013,2016 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -43,7 +44,7 @@
 #include <curses.priv.h>
 #include <ctype.h>
 
-MODULE_ID("$Id: lib_insch.c,v 1.35 2013/05/18 21:58:56 tom Exp $")
+MODULE_ID("$Id: lib_insch.c,v 1.37 2020/02/02 23:34:34 tom Exp $")
 
 /*
  * Insert the given character, updating the current location to simplify
@@ -56,7 +57,6 @@
     int ch8 = (int) ChCharOf(ch);
     NCURSES_CH_T wch;
     int count;
-    NCURSES_CONST char *s;
     int tabsize = (
 #if USE_REENTRANT
 		      sp->_TABSIZE
@@ -102,6 +102,7 @@
 		win->_curx++;
 	    }
 	} else if (iscntrl(ch8)) {
+	    NCURSES_CONST char *s;
 	    s = NCURSES_SP_NAME(unctrl) (NCURSES_SP_ARGx (chtype) ch8);
 	    while (*s != '\0') {
 		code = _nc_insert_ch(sp, win, ChAttrOf(ch) | UChar(*s));
@@ -121,6 +122,7 @@
 	    if (count > 0) {
 		code = _nc_insert_wch(win, &wch);
 	    } else if (count == -1) {
+		NCURSES_CONST char *s;
 		/* handle EILSEQ */
 		s = NCURSES_SP_NAME(unctrl) (NCURSES_SP_ARGx (chtype) ch8);
 		if (strlen(s) > 1) {
@@ -145,15 +147,13 @@
 NCURSES_EXPORT(int)
 winsch(WINDOW *win, chtype c)
 {
-    NCURSES_SIZE_T oy;
-    NCURSES_SIZE_T ox;
     int code = ERR;
 
     T((T_CALLED("winsch(%p, %s)"), (void *) win, _tracechtype(c)));
 
     if (win != 0) {
-	oy = win->_cury;
-	ox = win->_curx;
+	NCURSES_SIZE_T oy = win->_cury;
+	NCURSES_SIZE_T ox = win->_curx;
 
 	code = _nc_insert_ch(_nc_screen_of(win), win, c);
 
diff --git a/ncurses/base/lib_insdel.c b/ncurses/base/lib_insdel.c
index 8f51bbe..7c00739 100644
--- a/ncurses/base/lib_insdel.c
+++ b/ncurses/base/lib_insdel.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2003,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2003,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -42,7 +43,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_insdel.c,v 1.13 2009/10/24 22:34:41 tom Exp $")
+MODULE_ID("$Id: lib_insdel.c,v 1.14 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 winsdelln(WINDOW *win, int n)
diff --git a/ncurses/base/lib_insnstr.c b/ncurses/base/lib_insnstr.c
index ce03e64..caec48e 100644
--- a/ncurses/base/lib_insnstr.c
+++ b/ncurses/base/lib_insnstr.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 2004,2009 Free Software Foundation, Inc.                   *
+ * Copyright 2018-2022,2023 Thomas E. Dickey                                *
+ * Copyright 2004-2009,2016 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,31 +41,56 @@
 #include <curses.priv.h>
 #include <ctype.h>
 
-MODULE_ID("$Id: lib_insnstr.c,v 1.3 2009/10/24 22:04:35 tom Exp $")
+MODULE_ID("$Id: lib_insnstr.c,v 1.10 2023/11/21 21:58:03 tom Exp $")
 
 NCURSES_EXPORT(int)
 winsnstr(WINDOW *win, const char *s, int n)
 {
     int code = ERR;
-    NCURSES_SIZE_T oy;
-    NCURSES_SIZE_T ox;
     const unsigned char *str = (const unsigned char *) s;
-    const unsigned char *cp;
 
     T((T_CALLED("winsnstr(%p,%s,%d)"), (void *) win, _nc_visbufn(s, n), n));
 
-    if (win != 0 && str != 0) {
+    if (win != 0 && str != 0 && n != 0) {
 	SCREEN *sp = _nc_screen_of(win);
-
-	oy = win->_cury;
-	ox = win->_curx;
-	for (cp = str; *cp && (n <= 0 || (cp - str) < n); cp++) {
-	    _nc_insert_ch(sp, win, (chtype) UChar(*cp));
+#if USE_WIDEC_SUPPORT
+	/*
+	 * If the output contains "wide" (multibyte) characters, we will not
+	 * really know the width of a character until we get the last byte
+	 * of the character.  Since the preceding byte(s) may use more columns
+	 * on the screen than the final character, it is best to route the
+	 * call to the wins_nwstr() function.
+	 */
+	if (sp->_screen_unicode) {
+	    size_t nn = (n > 0) ? (size_t) n : strlen(s);
+	    wchar_t *buffer = typeMalloc(wchar_t, nn + 1);
+	    if (buffer != 0) {
+		mbstate_t state;
+		size_t n3;
+		init_mb(state);
+		n3 = mbstowcs(buffer, s, nn);
+		if (n3 != (size_t) (-1)) {
+		    buffer[n3] = '\0';
+		    code = wins_nwstr(win, buffer, (int) n3);
+		}
+		free(buffer);
+	    }
 	}
-	win->_curx = ox;
-	win->_cury = oy;
-	_nc_synchook(win);
-	code = OK;
+	if (code == ERR)
+#endif
+	{
+	    NCURSES_SIZE_T oy = win->_cury;
+	    NCURSES_SIZE_T ox = win->_curx;
+	    const unsigned char *cp;
+
+	    for (cp = str; (n < 0 || (cp - str) < n) && *cp; cp++) {
+		_nc_insert_ch(sp, win, (chtype) UChar(*cp));
+	    }
+	    win->_curx = ox;
+	    win->_cury = oy;
+	    _nc_synchook(win);
+	    code = OK;
+	}
     }
     returnCode(code);
 }
diff --git a/ncurses/base/lib_instr.c b/ncurses/base/lib_instr.c
index f708ecc..221ebd2 100644
--- a/ncurses/base/lib_instr.c
+++ b/ncurses/base/lib_instr.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2013,2014 Free Software Foundation, Inc.              *
+ * Copyright 2020-2021,2023 Thomas E. Dickey                                *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -41,45 +42,48 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_instr.c,v 1.21 2014/02/01 22:09:27 tom Exp $")
+MODULE_ID("$Id: lib_instr.c,v 1.26 2023/06/03 12:37:04 tom Exp $")
 
 NCURSES_EXPORT(int)
 winnstr(WINDOW *win, char *str, int n)
 {
-    int i = 0, row, col;
+    int i = 0;
 
     T((T_CALLED("winnstr(%p,%p,%d)"), (void *) win, str, n));
 
-    if (!str)
-	returnCode(0);
-
-    if (win) {
-	getyx(win, row, col);
+    if (!win || !str) {
+	i = ERR;
+    } else {
+	int row = win->_cury;
+	int col = win->_curx;
+	NCURSES_CH_T *text = win->_line[row].text;
 
 	if (n < 0)
-	    n = win->_maxx - win->_curx + 1;
+	    n = win->_maxx - col + 1;
 
 	for (; i < n;) {
 #if USE_WIDEC_SUPPORT
-	    cchar_t *cell = &(win->_line[row].text[col]);
-	    wchar_t *wch;
+	    cchar_t *cell = &(text[col]);
 	    attr_t attrs;
 	    NCURSES_PAIRS_T pair;
-	    int n2;
-	    bool done = FALSE;
-	    mbstate_t state;
-	    size_t i3, n3;
 	    char *tmp;
 
 	    if (!isWidecExt(*cell)) {
+		wchar_t *wch;
+		int n2;
+
 		n2 = getcchar(cell, 0, 0, 0, 0);
 		if (n2 > 0
 		    && (wch = typeCalloc(wchar_t, (unsigned) n2 + 1)) != 0) {
+		    bool done = FALSE;
+
 		    if (getcchar(cell, wch, &attrs, &pair, 0) == OK) {
+			mbstate_t state;
+			size_t n3;
 
 			init_mb(state);
 			n3 = wcstombs(0, wch, (size_t) 0);
-			if (!isEILSEQ(n3) && (n3 != 0)) {
+			if (!isEILSEQ(n3) && (n3 != 0) && (n3 <= MB_LEN_MAX)) {
 			    size_t need = n3 + 10 + (size_t) i;
 			    int have = (int) n3 + i;
 
@@ -89,6 +93,8 @@
 			    } else if ((tmp = typeCalloc(char, need)) == 0) {
 				done = TRUE;
 			    } else {
+				size_t i3;
+
 				init_mb(state);
 				wcstombs(tmp, wch, n3);
 				for (i3 = 0; i3 < n3; ++i3)
@@ -103,14 +109,14 @@
 		}
 	    }
 #else
-	    str[i++] = (char) CharOf(win->_line[row].text[col]);
+	    str[i++] = (char) CharOf(text[col]);
 #endif
 	    if (++col > win->_maxx) {
 		break;
 	    }
 	}
+	str[i] = '\0';		/* SVr4 does not seem to count the null */
     }
-    str[i] = '\0';		/* SVr4 does not seem to count the null */
     T(("winnstr returns %s", _nc_visbuf(str)));
     returnCode(i);
 }
diff --git a/ncurses/base/lib_isendwin.c b/ncurses/base/lib_isendwin.c
index 923e35b..a54d500 100644
--- a/ncurses/base/lib_isendwin.c
+++ b/ncurses/base/lib_isendwin.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2000,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2009,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -42,14 +43,14 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_isendwin.c,v 1.7 2009/02/15 00:36:24 tom Exp $")
+MODULE_ID("$Id: lib_isendwin.c,v 1.9 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(bool)
 NCURSES_SP_NAME(isendwin) (NCURSES_SP_DCL0)
 {
     if (SP_PARM == NULL)
 	return FALSE;
-    return SP_PARM->_endwin;
+    return (SP_PARM->_endwin == ewSuspend);
 }
 
 #if NCURSES_SP_FUNCS
diff --git a/ncurses/base/lib_leaveok.c b/ncurses/base/lib_leaveok.c
index e6995f8..4d05b2c 100644
--- a/ncurses/base/lib_leaveok.c
+++ b/ncurses/base/lib_leaveok.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2000,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2000,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,7 +41,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_leaveok.c,v 1.6 2009/10/24 22:34:23 tom Exp $")
+MODULE_ID("$Id: lib_leaveok.c,v 1.7 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 leaveok(WINDOW *win, bool flag)
diff --git a/ncurses/base/lib_mouse.c b/ncurses/base/lib_mouse.c
index 36b6e1e..a03d8b8 100644
--- a/ncurses/base/lib_mouse.c
+++ b/ncurses/base/lib_mouse.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2014,2015 Free Software Foundation, Inc.              *
+ * Copyright 2018-2023,2024 Thomas E. Dickey                                *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -84,7 +85,7 @@
 #define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: lib_mouse.c,v 1.166 2015/07/05 00:28:27 tom Exp $")
+MODULE_ID("$Id: lib_mouse.c,v 1.200 2024/02/17 21:13:01 tom Exp $")
 
 #include <tic.h>
 
@@ -141,19 +142,29 @@
 #define	MASK_RESERVED_EVENT(x)	(mmask_t) NCURSES_MOUSE_MASK(x, 040)
 
 #if NCURSES_MOUSE_VERSION == 1
+
 #define BUTTON_CLICKED        (BUTTON1_CLICKED        | BUTTON2_CLICKED        | BUTTON3_CLICKED        | BUTTON4_CLICKED)
 #define BUTTON_PRESSED        (BUTTON1_PRESSED        | BUTTON2_PRESSED        | BUTTON3_PRESSED        | BUTTON4_PRESSED)
 #define BUTTON_RELEASED       (BUTTON1_RELEASED       | BUTTON2_RELEASED       | BUTTON3_RELEASED       | BUTTON4_RELEASED)
 #define BUTTON_DOUBLE_CLICKED (BUTTON1_DOUBLE_CLICKED | BUTTON2_DOUBLE_CLICKED | BUTTON3_DOUBLE_CLICKED | BUTTON4_DOUBLE_CLICKED)
 #define BUTTON_TRIPLE_CLICKED (BUTTON1_TRIPLE_CLICKED | BUTTON2_TRIPLE_CLICKED | BUTTON3_TRIPLE_CLICKED | BUTTON4_TRIPLE_CLICKED)
+
 #define MAX_BUTTONS  4
+
 #else
+
 #define BUTTON_CLICKED        (BUTTON1_CLICKED        | BUTTON2_CLICKED        | BUTTON3_CLICKED        | BUTTON4_CLICKED        | BUTTON5_CLICKED)
 #define BUTTON_PRESSED        (BUTTON1_PRESSED        | BUTTON2_PRESSED        | BUTTON3_PRESSED        | BUTTON4_PRESSED        | BUTTON5_PRESSED)
 #define BUTTON_RELEASED       (BUTTON1_RELEASED       | BUTTON2_RELEASED       | BUTTON3_RELEASED       | BUTTON4_RELEASED       | BUTTON5_RELEASED)
 #define BUTTON_DOUBLE_CLICKED (BUTTON1_DOUBLE_CLICKED | BUTTON2_DOUBLE_CLICKED | BUTTON3_DOUBLE_CLICKED | BUTTON4_DOUBLE_CLICKED | BUTTON5_DOUBLE_CLICKED)
 #define BUTTON_TRIPLE_CLICKED (BUTTON1_TRIPLE_CLICKED | BUTTON2_TRIPLE_CLICKED | BUTTON3_TRIPLE_CLICKED | BUTTON4_TRIPLE_CLICKED | BUTTON5_TRIPLE_CLICKED)
+
+#if NCURSES_MOUSE_VERSION == 2
 #define MAX_BUTTONS  5
+#else
+#define MAX_BUTTONS  11
+#endif
+
 #endif
 
 #define INVALID_EVENT	-1
@@ -225,7 +236,7 @@
     char buf[6];
     unsigned long ignore;
 
-    strcpy(buf, "\033[M");	/* should be the same as key_mouse */
+    _nc_STRCPY(buf, "\033[M", sizeof(buf));	/* should be the same as key_mouse */
     buf[3] = ' ' + (button - 1) + (down ? 0 : 0x40);
     buf[4] = ' ' + x - LEFT_COL + 1;
     buf[5] = ' ' + y - TOP_ROW + 1;
@@ -369,7 +380,7 @@
 }
 #endif /* USE_SYSMOUSE */
 
-#ifndef USE_TERM_DRIVER
+#if !defined(USE_TERM_DRIVER) || defined(EXP_WIN32_DRIVER)
 #define xterm_kmous "\033[M"
 
 static void
@@ -408,13 +419,22 @@
     } else {
 	int code = tigetnum("XM");
 	switch (code) {
+#ifdef EXP_XTERM_1005
+	case 1005:
+	    /* see "xterm+sm+1005" */
+	    sp->_mouse_xtermcap = "\033[?1005;1000%?%p1%{1}%=%th%el%;";
+	    sp->_mouse_format = MF_XTERM_1005;
+	    break;
+#endif
 	case 1006:
+	    /* see "xterm+sm+1006" */
+	    sp->_mouse_xtermcap = "\033[?1006;1000%?%p1%{1}%=%th%el%;";
+	    sp->_mouse_format = MF_SGR1006;
 	    break;
 	default:
-	    code = 1000;
+	    sp->_mouse_xtermcap = "\033[?1000%?%p1%{1}%=%th%el%;";
 	    break;
 	}
-	sp->_mouse_xtermcap = "\033[?1000%?%p1%{1}%=%th%el%;";
     }
 }
 #endif
@@ -422,14 +442,29 @@
 static void
 enable_xterm_mouse(SCREEN *sp, int enable)
 {
+    TPUTS_TRACE(enable
+		? "xterm mouse initialization"
+		: "xterm mouse deinitialization");
 #if USE_EMX_MOUSE
     sp->_emxmouse_activated = enable;
 #else
-    NCURSES_PUTP2("xterm-mouse", TPARM_1(sp->_mouse_xtermcap, enable));
+    NCURSES_PUTP2("xterm-mouse", TIPARM_1(sp->_mouse_xtermcap, enable));
 #endif
     sp->_mouse_active = enable;
 }
 
+#if defined(USE_TERM_DRIVER)
+static void
+enable_win32_mouse(SCREEN *sp, int enable)
+{
+#if defined(EXP_WIN32_DRIVER)
+    enable_xterm_mouse(sp, enable);
+#else
+    sp->_mouse_active = enable;
+#endif
+}
+#endif
+
 #if USE_GPM_SUPPORT
 static bool
 allow_gpm_mouse(SCREEN *sp GCC_UNUSED)
@@ -438,7 +473,7 @@
 
 #if USE_WEAK_SYMBOLS
     /* Danger Robinson: do not use dlopen for libgpm if already loaded */
-    if ((Gpm_Wgetch)) {
+    if ((Gpm_Wgetch) != 0) {
 	if (!sp->_mouse_gpm_loaded) {
 	    T(("GPM library was already dlopen'd, not by us"));
 	}
@@ -476,8 +511,6 @@
 	T(("unload GPM library"));
 	sp->_mouse_gpm_loaded = FALSE;
 	sp->_mouse_fd = -1;
-	dlclose(sp->_dlopen_gpm);
-	sp->_dlopen_gpm = 0;
     }
 }
 
@@ -485,20 +518,36 @@
 load_gpm_library(SCREEN *sp)
 {
     sp->_mouse_gpm_found = FALSE;
-    if ((sp->_dlopen_gpm = dlopen(LIBGPM_SONAME, my_RTLD)) != 0) {
+
+    /*
+     * If we already had a successful dlopen, reuse it.
+     */
+    if (sp->_dlopen_gpm != 0) {
+	sp->_mouse_gpm_found = TRUE;
+	sp->_mouse_gpm_loaded = TRUE;
+    } else if ((sp->_dlopen_gpm = dlopen(LIBGPM_SONAME, my_RTLD)) != 0) {
+#if (defined(__GNUC__) && (__GNUC__ >= 5)) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
 	if (GET_DLSYM(gpm_fd) == 0 ||
 	    GET_DLSYM(Gpm_Open) == 0 ||
 	    GET_DLSYM(Gpm_Close) == 0 ||
 	    GET_DLSYM(Gpm_GetEvent) == 0) {
+#if (defined(__GNUC__) && (__GNUC__ >= 5)) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
 	    T(("GPM initialization failed: %s", dlerror()));
 	    unload_gpm_library(sp);
+	    dlclose(sp->_dlopen_gpm);
+	    sp->_dlopen_gpm = 0;
 	} else {
 	    sp->_mouse_gpm_found = TRUE;
 	    sp->_mouse_gpm_loaded = TRUE;
 	}
     }
 }
-#endif
+#endif /* HAVE_LIBDL */
 
 static bool
 enable_gpm_mouse(SCREEN *sp, bool enable)
@@ -597,8 +646,8 @@
     /* OS/2 VIO */
 #if USE_EMX_MOUSE
     if (!sp->_emxmouse_thread
-	&& strstr(TerminalOf(sp)->type.term_names, "xterm") == 0
-	&& key_mouse) {
+	&& strstr(SP_TERMTYPE term_names, "xterm") == 0
+	&& NonEmpty(key_mouse)) {
 	int handles[2];
 
 	if (pipe(handles) < 0) {
@@ -641,13 +690,14 @@
 
 #if USE_SYSMOUSE
     {
+	static char dev_tty[] = "/dev/tty";
 	struct mouse_info the_mouse;
 	char *the_device = 0;
 
 	if (NC_ISATTY(sp->_ifd))
 	    the_device = ttyname(sp->_ifd);
 	if (the_device == 0)
-	    the_device = "/dev/tty";
+	    the_device = dev_tty;
 
 	sp->_mouse_fd = open(the_device, O_RDWR);
 
@@ -706,14 +756,12 @@
 
 #ifdef USE_TERM_DRIVER
     CallDriver(sp, td_initmouse);
-#else
+#endif
+#if !defined(USE_TERM_DRIVER) || defined(EXP_WIN32_DRIVER)
     /* we know how to recognize mouse events under "xterm" */
-    if (key_mouse != 0) {
-	if (!strcmp(key_mouse, xterm_kmous)
-	    || strstr(TerminalOf(sp)->type.term_names, "xterm") != 0) {
-	    init_xterm_mouse(sp);
-	}
-    } else if (strstr(TerminalOf(sp)->type.term_names, "xterm") != 0) {
+    if (NonEmpty(key_mouse)) {
+	init_xterm_mouse(sp);
+    } else if (strstr(SP_TERMTYPE term_names, "xterm") != 0) {
 	if (_nc_add_to_try(&(sp->_keytry), xterm_kmous, KEY_MOUSE) == OK)
 	    init_xterm_mouse(sp);
     }
@@ -727,13 +775,16 @@
 /* initialize the mouse */
 {
     bool result = FALSE;
-    int i;
+
+    T((T_CALLED("_nc_mouse_init(%p)"), (void *) sp));
 
     if (sp != 0) {
 	if (!sp->_mouse_initialized) {
+	    int i;
+
 	    sp->_mouse_initialized = TRUE;
 
-	    TR(MY_TRACE, ("_nc_mouse_init() called"));
+	    TR(MY_TRACE, ("set _mouse_initialized"));
 
 	    sp->_mouse_eventp = FirstEV(sp);
 	    for (i = 0; i < EV_MAX; i++)
@@ -741,11 +792,11 @@
 
 	    initialize_mousetype(sp);
 
-	    T(("_nc_mouse_init() set mousetype to %d", sp->_mouse_type));
+	    T(("set _mouse_type to %d", sp->_mouse_type));
 	}
 	result = sp->_mouse_initialized;
     }
-    return result;
+    returnCode(result);
 }
 
 /*
@@ -888,7 +939,7 @@
     do { \
 	    eventp->bstate = MASK_PRESS(n); \
 	    sp->_mouse_bstate |= MASK_PRESS(n); \
-	    if (kbuf[0] & 0x40) { \
+	    if (button & 0x40) { \
 		    eventp->bstate = MASK_RELEASE(n); \
 		    sp->_mouse_bstate &= ~MASK_PRESS(n); \
 	    } \
@@ -896,7 +947,7 @@
 #else
 #define PRESS_POSITION(n) \
     do { \
-	    eventp->bstate = (mmask_t) (sp->_mouse_bstate & MASK_PRESS(n) \
+	    eventp->bstate = (mmask_t) ((sp->_mouse_bstate & MASK_PRESS(n)) \
 				    ? REPORT_MOUSE_POSITION \
 				    : MASK_PRESS(n)); \
 	    sp->_mouse_bstate |= MASK_PRESS(n); \
@@ -921,7 +972,7 @@
 	break;
     case 1:
 	if (wheel) {
-#if NCURSES_MOUSE_VERSION == 2
+#if NCURSES_MOUSE_VERSION >= 2
 	    eventp->bstate = MASK_PRESS(5);
 	    /* See comment above for button 4 */
 #else
@@ -936,6 +987,17 @@
 	PRESS_POSITION(3);
 	break;
     default:
+	/*
+	 * case 3 is sent when the mouse buttons are released.
+	 *
+	 * If the terminal uses xterm mode 1003, a continuous series of
+	 * button-release events is sent as the mouse moves around the screen,
+	 * or as the wheel mouse is rotated.
+	 *
+	 * Return false in this case, so that when running in X10 mode, we will
+	 * recalculate bstate.
+	 */
+	eventp->bstate = REPORT_MOUSE_POSITION;
 	result = FALSE;
 	break;
     }
@@ -946,11 +1008,25 @@
 decode_X10_bstate(SCREEN *sp, MEVENT * eventp, unsigned intro)
 {
     bool result;
-    int b;
+    int button = 0;
+    int wheel = (intro & 96) == 96;
 
     eventp->bstate = 0;
 
-    if (!handle_wheel(sp, eventp, (int) intro, (intro & 96) == 96)) {
+    if (intro >= 96) {
+	if (intro >= 160) {
+	    button = (int) (intro - 152);	/* buttons 8-11 */
+	} else {
+	    button = (int) (intro - 92);	/* buttons 4-7 */
+	}
+    } else {
+	button = (intro & 3);
+    }
+
+    if (button > MAX_BUTTONS) {
+	eventp->bstate = REPORT_MOUSE_POSITION;
+    } else if (!handle_wheel(sp, eventp, (int) intro, wheel)) {
+
 	/*
 	 * Release events aren't reported for individual buttons, just for
 	 * the button set as a whole.  However, because there are normally
@@ -959,6 +1035,8 @@
 	 * the previous event.
 	 */
 	if (sp->_mouse_bstate & BUTTON_PRESSED) {
+	    int b;
+
 	    eventp->bstate = BUTTON_RELEASED;
 	    for (b = 1; b <= MAX_BUTTONS; ++b) {
 		if (!(sp->_mouse_bstate & MASK_PRESS(b)))
@@ -1019,18 +1097,14 @@
 static bool
 decode_xterm_X10(SCREEN *sp, MEVENT * eventp)
 {
-    unsigned char kbuf[4];
+#define MAX_KBUF 3
+    unsigned char kbuf[MAX_KBUF + 1];
     size_t grabbed;
     int res;
     bool result;
 
-# if USE_PTHREADS_EINTR
-#  if USE_WEAK_SYMBOLS
-    if ((pthread_self) && (pthread_kill) && (pthread_equal))
-#  endif
-	_nc_globals.read_thread = pthread_self();
-# endif
-    for (grabbed = 0; grabbed < 3; grabbed += (size_t) res) {
+    _nc_set_read_thread(TRUE);
+    for (grabbed = 0; grabbed < MAX_KBUF; grabbed += (size_t) res) {
 
 	/* For VIO mouse we add extra bit 64 to disambiguate button-up. */
 	res = (int) read(
@@ -1039,14 +1113,12 @@
 #else
 			    sp->_ifd,
 #endif
-			    kbuf + grabbed, 3 - grabbed);
+			    kbuf + grabbed, (size_t) (MAX_KBUF - (int) grabbed));
 	if (res == -1)
 	    break;
     }
-#if USE_PTHREADS_EINTR
-    _nc_globals.read_thread = 0;
-#endif
-    kbuf[3] = '\0';
+    _nc_set_read_thread(FALSE);
+    kbuf[MAX_KBUF] = '\0';
 
     TR(TRACE_IEVENT,
        ("_nc_mouse_inline sees the following xterm data: '%s'", kbuf));
@@ -1074,19 +1146,14 @@
     size_t grabbed;
     size_t limit = (sizeof(kbuf) - 1);
     unsigned coords[2];
-    int res;
     bool result;
 
     coords[0] = 0;
     coords[1] = 0;
 
-# if USE_PTHREADS_EINTR
-#  if USE_WEAK_SYMBOLS
-    if ((pthread_self) && (pthread_kill) && (pthread_equal))
-#  endif
-	_nc_globals.read_thread = pthread_self();
-# endif
+    _nc_set_read_thread(TRUE);
     for (grabbed = 0; grabbed < limit;) {
+	int res;
 
 	res = (int) read(
 #if USE_EMX_MOUSE
@@ -1094,15 +1161,17 @@
 #else
 			    sp->_ifd,
 #endif
-			    kbuf + grabbed, 1);
+			    (kbuf + grabbed), (size_t) 1);
 	if (res == -1)
 	    break;
 	grabbed += (size_t) res;
 	if (grabbed > 1) {
 	    size_t check = 1;
 	    int n;
-	    int rc;
+
 	    for (n = 0; n < 2; ++n) {
+		int rc;
+
 		if (check >= grabbed)
 		    break;
 		rc = _nc_conv_to_utf32(&coords[n], kbuf + check, (unsigned)
@@ -1115,9 +1184,7 @@
 		break;
 	}
     }
-#if USE_PTHREADS_EINTR
-    _nc_globals.read_thread = 0;
-#endif
+    _nc_set_read_thread(FALSE);
 
     TR(TRACE_IEVENT,
        ("_nc_mouse_inline sees the following xterm data: %s",
@@ -1156,29 +1223,26 @@
 {
     char kbuf[80];		/* bigger than any possible mouse response */
     int grabbed = 0;
-    int res;
     int ch = 0;
     int now = -1;
     int marker = 1;
 
     memset(result, 0, sizeof(*result));
-# if USE_PTHREADS_EINTR
-#  if USE_WEAK_SYMBOLS
-    if ((pthread_self) && (pthread_kill) && (pthread_equal))
-#  endif
-	_nc_globals.read_thread = pthread_self();
-# endif
+    _nc_set_read_thread(TRUE);
+
     do {
+	int res;
+
 	res = (int) read(
 #if USE_EMX_MOUSE
 			    (M_FD(sp) >= 0) ? M_FD(sp) : sp->_ifd,
 #else
 			    sp->_ifd,
 #endif
-			    kbuf + grabbed, 1);
+			    (kbuf + grabbed), (size_t) 1);
 	if (res == -1)
 	    break;
-	if ((grabbed + 3) >= (int) sizeof(kbuf)) {
+	if ((grabbed + MAX_KBUF) >= (int) sizeof(kbuf)) {
 	    result->nerror++;
 	    break;
 	}
@@ -1229,9 +1293,7 @@
 	}
 	++grabbed;
     } while (!isFinal(ch));
-#if USE_PTHREADS_EINTR
-    _nc_globals.read_thread = 0;
-#endif
+    _nc_set_read_thread(FALSE);
 
     kbuf[++grabbed] = 0;
     TR(TRACE_IEVENT,
@@ -1247,10 +1309,21 @@
     if (read_SGR(sp, &data)) {
 	int b = data.params[0];
 	int b3 = 1 + (b & 3);
+	int wheel = ((b & 64) == 64);
+
+	if (b >= 132) {
+	    b3 = MAX_BUTTONS + 1;
+	} else if (b >= 128) {
+	    b3 = (b - 120);	/* buttons 8-11 */
+	} else if (b >= 64) {
+	    b3 = (b - 60);	/* buttons 6-7 */
+	}
 
 	eventp->id = NORMAL_EVENT;
 	if (data.final == 'M') {
-	    (void) handle_wheel(sp, eventp, b, (b & 64) == 64);
+	    (void) handle_wheel(sp, eventp, b, wheel);
+	} else if (b3 > MAX_BUTTONS) {
+	    eventp->bstate = REPORT_MOUSE_POSITION;
 	} else {
 	    mmask_t pressed = (mmask_t) NCURSES_MOUSE_MASK(b3, NCURSES_BUTTON_PRESSED);
 	    mmask_t release = (mmask_t) NCURSES_MOUSE_MASK(b3, NCURSES_BUTTON_RELEASED);
@@ -1261,6 +1334,15 @@
 		eventp->bstate = REPORT_MOUSE_POSITION;
 	    }
 	}
+	if (b & 4) {
+	    eventp->bstate |= BUTTON_SHIFT;
+	}
+	if (b & 8) {
+	    eventp->bstate |= BUTTON_ALT;
+	}
+	if (b & 16) {
+	    eventp->bstate |= BUTTON_CTRL;
+	}
 	result = (eventp->bstate & REPORT_MOUSE_POSITION) ? TRUE : FALSE;
 	eventp->x = (data.params[1] ? (data.params[1] - 1) : 0);
 	eventp->y = (data.params[2] ? (data.params[2] - 1) : 0);
@@ -1324,11 +1406,14 @@
 static void
 mouse_activate(SCREEN *sp, int on)
 {
+    T((T_CALLED("mouse_activate(%p,%s)"),
+       (void *) SP_PARM, on ? "on" : "off"));
+
     if (!on && !sp->_mouse_initialized)
-	return;
+	returnVoid;
 
     if (!_nc_mouse_init(sp))
-	return;
+	returnVoid;
 
     if (on) {
 	sp->_mouse_bstate = 0;
@@ -1337,7 +1422,6 @@
 #if NCURSES_EXT_FUNCS
 	    NCURSES_SP_NAME(keyok) (NCURSES_SP_ARGx KEY_MOUSE, on);
 #endif
-	    TPUTS_TRACE("xterm mouse initialization");
 	    enable_xterm_mouse(sp, 1);
 	    break;
 #if USE_GPM_SUPPORT
@@ -1356,25 +1440,28 @@
 #endif
 #ifdef USE_TERM_DRIVER
 	case M_TERM_DRIVER:
-	    sp->_mouse_active = TRUE;
+	    enable_win32_mouse(sp, TRUE);
 	    break;
 #endif
 	case M_NONE:
-	    return;
+	    returnVoid;
+	default:
+	    T(("unexpected mouse mode"));
+	    break;
 	}
 	/* Make runtime binding to cut down on object size of applications that
 	 * do not use the mouse (e.g., 'clear').
 	 */
-	sp->_mouse_event = _nc_mouse_event;
+	/* *INDENT-EQLS* */
+	sp->_mouse_event  = _nc_mouse_event;
 	sp->_mouse_inline = _nc_mouse_inline;
-	sp->_mouse_parse = _nc_mouse_parse;
+	sp->_mouse_parse  = _nc_mouse_parse;
 	sp->_mouse_resume = _nc_mouse_resume;
-	sp->_mouse_wrap = _nc_mouse_wrap;
+	sp->_mouse_wrap   = _nc_mouse_wrap;
     } else {
 
 	switch (sp->_mouse_type) {
 	case M_XTERM:
-	    TPUTS_TRACE("xterm mouse deinitialization");
 	    enable_xterm_mouse(sp, 0);
 	    break;
 #if USE_GPM_SUPPORT
@@ -1390,14 +1477,18 @@
 #endif
 #ifdef USE_TERM_DRIVER
 	case M_TERM_DRIVER:
-	    sp->_mouse_active = FALSE;
+	    enable_win32_mouse(sp, FALSE);
 	    break;
 #endif
 	case M_NONE:
-	    return;
+	    returnVoid;
+	default:
+	    T(("unexpected mouse mode"));
+	    break;
 	}
     }
     NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG);
+    returnVoid;
 }
 
 /**************************************************************************
@@ -1495,7 +1586,7 @@
 		if (changed) {
 		    merge = FALSE;
 		    for (b = 1; b <= MAX_BUTTONS; ++b) {
-			if ((sp->_mouse_mask & MASK_CLICK(b))
+			if ((sp->_mouse_mask2 & MASK_CLICK(b))
 			    && (ep->bstate & MASK_PRESS(b))) {
 			    next->bstate &= ~MASK_RELEASE(b);
 			    next->bstate |= MASK_CLICK(b);
@@ -1576,7 +1667,7 @@
 		&& (next->bstate & BUTTON_CLICKED)) {
 		merge = FALSE;
 		for (b = 1; b <= MAX_BUTTONS; ++b) {
-		    if ((sp->_mouse_mask & MASK_DOUBLE_CLICK(b))
+		    if ((sp->_mouse_mask2 & MASK_DOUBLE_CLICK(b))
 			&& (ep->bstate & MASK_CLICK(b))
 			&& (next->bstate & MASK_CLICK(b))) {
 			next->bstate &= ~MASK_CLICK(b);
@@ -1594,7 +1685,7 @@
 		&& (next->bstate & BUTTON_CLICKED)) {
 		merge = FALSE;
 		for (b = 1; b <= MAX_BUTTONS; ++b) {
-		    if ((sp->_mouse_mask & MASK_TRIPLE_CLICK(b))
+		    if ((sp->_mouse_mask2 & MASK_TRIPLE_CLICK(b))
 			&& (ep->bstate & MASK_DOUBLE_CLICK(b))
 			&& (next->bstate & MASK_CLICK(b))) {
 			next->bstate &= ~MASK_CLICK(b);
@@ -1654,7 +1745,8 @@
 #endif /* TRACE */
 
     /* after all this, do we have a valid event? */
-    return ValidEvent(PREV(first_invalid));
+    ep = PREV(first_invalid);
+    return ValidEvent(ep) && ((ep->bstate & sp->_mouse_mask) != 0);
 }
 
 static void
@@ -1738,11 +1830,14 @@
 NCURSES_SP_NAME(getmouse) (NCURSES_SP_DCLx MEVENT * aevent)
 {
     int result = ERR;
+    MEVENT *eventp;
 
     T((T_CALLED("getmouse(%p,%p)"), (void *) SP_PARM, (void *) aevent));
 
-    if ((aevent != 0) && (SP_PARM != 0) && (SP_PARM->_mouse_type != M_NONE)) {
-	MEVENT *eventp = SP_PARM->_mouse_eventp;
+    if ((aevent != 0) &&
+	(SP_PARM != 0) &&
+	(SP_PARM->_mouse_type != M_NONE) &&
+	(eventp = SP_PARM->_mouse_eventp) != 0) {
 	/* compute the current-event pointer */
 	MEVENT *prev = PREV(eventp);
 
@@ -1791,11 +1886,13 @@
 NCURSES_SP_NAME(ungetmouse) (NCURSES_SP_DCLx MEVENT * aevent)
 {
     int result = ERR;
+    MEVENT *eventp;
 
     T((T_CALLED("ungetmouse(%p,%p)"), (void *) SP_PARM, (void *) aevent));
 
-    if (aevent != 0 && SP_PARM != 0) {
-	MEVENT *eventp = SP_PARM->_mouse_eventp;
+    if (aevent != 0 &&
+	SP_PARM != 0 &&
+	(eventp = SP_PARM->_mouse_eventp) != 0) {
 
 	/* stick the given event in the next-free slot */
 	*eventp = *aevent;
@@ -1823,7 +1920,6 @@
 /* set the mouse event mask */
 {
     mmask_t result = 0;
-    int b;
 
     T((T_CALLED("mousemask(%p,%#lx,%p)"),
        (void *) SP_PARM,
@@ -1836,7 +1932,10 @@
 
 	if (newmask || SP_PARM->_mouse_initialized) {
 	    _nc_mouse_init(SP_PARM);
+
 	    if (SP_PARM->_mouse_type != M_NONE) {
+		int b;
+
 		result = newmask &
 		    (REPORT_MOUSE_POSITION
 		     | BUTTON_ALT
@@ -1891,10 +1990,24 @@
 
     if (win != 0) {
 	y -= win->_yoffset;
-	result = ((win->_begy <= y &&
-		   win->_begx <= x &&
-		   (win->_begx + win->_maxx) >= x &&
-		   (win->_begy + win->_maxy) >= y) ? TRUE : FALSE);
+	if (IS_PAD(win)) {
+	    if (win->_pad._pad_y >= 0 &&
+		win->_pad._pad_x >= 0 &&
+		win->_pad._pad_top >= 0 &&
+		win->_pad._pad_left >= 0 &&
+		win->_pad._pad_right >= 0 &&
+		win->_pad._pad_bottom >= 0) {
+		result = ((win->_pad._pad_top <= y &&
+			   win->_pad._pad_left <= x &&
+			   win->_pad._pad_right >= x &&
+			   win->_pad._pad_bottom >= y) ? TRUE : FALSE);
+	    }
+	} else {
+	    result = ((win->_begy <= y &&
+		       win->_begx <= x &&
+		       (win->_begx + win->_maxx) >= x &&
+		       (win->_begy + win->_maxy) >= y) ? TRUE : FALSE);
+	}
     }
     returnBool(result);
 }
@@ -1963,6 +2076,7 @@
 	int y = *pY;
 	int x = *pX;
 
+	T(("transform input %d,%d", y, x));
 	if (to_screen) {
 	    y += win->_begy + win->_yoffset;
 	    x += win->_begx;
@@ -1978,6 +2092,7 @@
 	if (result) {
 	    *pX = x;
 	    *pY = y;
+	    T(("output transform %d,%d", y, x));
 	}
     }
     returnBool(result);
diff --git a/ncurses/base/lib_move.c b/ncurses/base/lib_move.c
index 488b195..d9ba8c0 100644
--- a/ncurses/base/lib_move.c
+++ b/ncurses/base/lib_move.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2004,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2004,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -41,7 +42,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_move.c,v 1.13 2009/10/24 22:34:07 tom Exp $")
+MODULE_ID("$Id: lib_move.c,v 1.14 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 wmove(WINDOW *win, int y, int x)
diff --git a/ncurses/base/lib_mvwin.c b/ncurses/base/lib_mvwin.c
index 18d31c1..fca014e 100644
--- a/ncurses/base/lib_mvwin.c
+++ b/ncurses/base/lib_mvwin.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright 2020,2021 Thomas E. Dickey                                     *
+ * Copyright 1998-2009,2010 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -42,7 +43,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_mvwin.c,v 1.18 2010/12/19 01:22:58 tom Exp $")
+MODULE_ID("$Id: lib_mvwin.c,v 1.20 2021/10/23 18:57:41 tom Exp $")
 
 NCURSES_EXPORT(int)
 mvwin(WINDOW *win, int by, int bx)
@@ -53,7 +54,7 @@
 
     T((T_CALLED("mvwin(%p,%d,%d)"), (void *) win, by, bx));
 
-    if (!win || (win->_flags & _ISPAD))
+    if (!win || IS_PAD(win))
 	returnCode(ERR);
 
     /*
@@ -62,7 +63,7 @@
      */
 #if 0
     /* Copying subwindows is allowed, but it is expensive... */
-    if (win->_flags & _SUBWIN) {
+    if (IS_SUBWIN(win)) {
 	int err = ERR;
 	WINDOW *parent = win->_parent;
 	if (parent) {		/* Now comes the complicated and costly part, you should really
diff --git a/ncurses/base/lib_newterm.c b/ncurses/base/lib_newterm.c
index edbf956..15d05a3 100644
--- a/ncurses/base/lib_newterm.c
+++ b/ncurses/base/lib_newterm.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2013,2014 Free Software Foundation, Inc.              *
+ * Copyright 2018-2020,2022 Thomas E. Dickey                                *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -48,7 +49,7 @@
 
 #include <tic.h>
 
-MODULE_ID("$Id: lib_newterm.c,v 1.92 2014/04/26 18:00:39 tom Exp $")
+MODULE_ID("$Id: lib_newterm.c,v 1.104 2022/07/09 18:58:58 tom Exp $")
 
 #ifdef USE_TERM_DRIVER
 #define NumLabels      InfoOf(SP_PARM).numlabels
@@ -76,6 +77,7 @@
 
     /* for extended XPG4 conformance requires cbreak() at this point */
     /* (SVr4 curses does this anyway) */
+    T((T_CALLED("_nc_initscr(%p) ->term %p"), (void *) SP_PARM, (void *) term));
     if (NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG) == OK) {
 	TTY buf;
 
@@ -86,6 +88,12 @@
 	buf.c_oflag &= (unsigned) ~(ONLCR);
 #elif HAVE_SGTTY_H
 	buf.sg_flags &= ~(ECHO | CRMOD);
+#elif defined(EXP_WIN32_DRIVER)
+	buf.dwFlagIn = CONMODE_IN_DEFAULT;
+	buf.dwFlagOut = CONMODE_OUT_DEFAULT | VT_FLAG_OUT;
+	if (WINCONSOLE.isTermInfoConsole) {
+	    buf.dwFlagIn |= VT_FLAG_IN;
+	}
 #else
 	memset(&buf, 0, sizeof(buf));
 #endif
@@ -93,7 +101,7 @@
 	if (result == OK)
 	    term->Nttyb = buf;
     }
-    return result;
+    returnCode(result);
 }
 
 /*
@@ -162,20 +170,16 @@
 
 NCURSES_EXPORT(SCREEN *)
 NCURSES_SP_NAME(newterm) (NCURSES_SP_DCLx
-			  NCURSES_CONST char *name,
+			  const char *name,
 			  FILE *ofp,
 			  FILE *ifp)
 {
-    int value;
     int errret;
     SCREEN *result = 0;
     SCREEN *current;
     TERMINAL *its_term;
     FILE *_ofp = ofp ? ofp : stdout;
     FILE *_ifp = ifp ? ifp : stdin;
-    int cols;
-    int slk_format;
-    int filter_mode;
     TERMINAL *new_term = 0;
 
     START_TRACE();
@@ -197,11 +201,18 @@
     current = CURRENT_SCREEN;
     its_term = (current ? current->_term : 0);
 
+#if defined(EXP_WIN32_DRIVER)
+    _setmode(fileno(_ifp), _O_BINARY);
+    _setmode(fileno(_ofp), _O_BINARY);
+#endif
+
     INIT_TERM_DRIVER();
     /* this loads the capability entry, then sets LINES and COLS */
     if (
 	   TINFO_SETUP_TERM(&new_term, name,
 			    fileno(_ofp), &errret, FALSE) != ERR) {
+	int slk_format;
+	int filter_mode;
 
 	_nc_set_screen(0);
 #ifdef USE_TERM_DRIVER
@@ -232,6 +243,9 @@
 	    _nc_set_screen(current);
 	    result = 0;
 	} else {
+	    int value;
+	    int cols;
+
 #ifdef USE_TERM_DRIVER
 	    TERMINAL_CONTROL_BLOCK *TCB;
 #elif !NCURSES_SP_FUNCS
@@ -265,7 +279,11 @@
 
 	    /* allow user to set maximum escape delay from the environment */
 	    if ((value = _nc_getenv_num("ESCDELAY")) >= 0) {
+#if NCURSES_EXT_FUNCS
 		NCURSES_SP_NAME(set_escdelay) (NCURSES_SP_ARGx value);
+#else
+		ESCDELAY = value;
+#endif
 	    }
 
 	    /* if the terminal type has real soft labels, set those up */
@@ -281,7 +299,7 @@
 #else
 	    SP_PARM->_use_meta = FALSE;
 #endif
-	    SP_PARM->_endwin = FALSE;
+	    SP_PARM->_endwin = ewInitial;
 #ifndef USE_TERM_DRIVER
 	    /*
 	     * Check whether we can optimize scrolling under dumb terminals in
@@ -341,8 +359,17 @@
 
 #if NCURSES_SP_FUNCS
 NCURSES_EXPORT(SCREEN *)
-newterm(NCURSES_CONST char *name, FILE *ofp, FILE *ifp)
+newterm(const char *name, FILE *ofp, FILE *ifp)
 {
-    return NCURSES_SP_NAME(newterm) (CURRENT_SCREEN_PRE, name, ofp, ifp);
+    SCREEN *rc;
+
+    _nc_init_pthreads();
+    _nc_lock_global(prescreen);
+    START_TRACE();
+    rc = NCURSES_SP_NAME(newterm) (CURRENT_SCREEN_PRE, name, ofp, ifp);
+    _nc_forget_prescr();
+    _nc_unlock_global(prescreen);
+
+    return rc;
 }
 #endif
diff --git a/ncurses/base/lib_newwin.c b/ncurses/base/lib_newwin.c
index a6c64be..a672319 100644
--- a/ncurses/base/lib_newwin.c
+++ b/ncurses/base/lib_newwin.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc.              *
+ * Copyright 2020,2021 Thomas E. Dickey                                     *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -43,7 +44,7 @@
 #include <curses.priv.h>
 #include <stddef.h>
 
-MODULE_ID("$Id: lib_newwin.c,v 1.71 2011/05/28 21:32:51 tom Exp $")
+MODULE_ID("$Id: lib_newwin.c,v 1.76 2021/10/23 18:53:38 tom Exp $")
 
 #define window_is(name) ((sp)->_##name == win)
 
@@ -91,8 +92,6 @@
 NCURSES_EXPORT(int)
 _nc_freewin(WINDOW *win)
 {
-    WINDOWLIST *p, *q;
-    int i;
     int result = ERR;
 #ifdef USE_SP_WINDOWLIST
     SCREEN *sp = _nc_screen_of(win);	/* pretend this is parameter */
@@ -101,17 +100,23 @@
     T((T_CALLED("_nc_freewin(%p)"), (void *) win));
 
     if (win != 0) {
+
 	if (_nc_nonsp_try_global(curses) == 0) {
+	    WINDOWLIST *p, *q;
+
 	    q = 0;
-	    for (each_window(SP_PARM, p)) {
+	    for (each_window(sp, p)) {
+
 		if (&(p->win) == win) {
 		    remove_window_from_screen(win);
 		    if (q == 0)
-			WindowList(SP_PARM) = p->next;
+			WindowList(sp) = p->next;
 		    else
 			q->next = p->next;
 
-		    if (!(win->_flags & _SUBWIN)) {
+		    if (!IS_SUBWIN(win)) {
+			int i;
+
 			for (i = 0; i <= win->_maxy; i++)
 			    FreeIfNeeded(win->_line[i].text);
 		    }
@@ -214,7 +219,7 @@
     if (num_columns == 0)
 	num_columns = orig->_maxx + 1 - begx;
 
-    if (orig->_flags & _ISPAD)
+    if (IS_PAD(orig))
 	flags |= _ISPAD;
 
     win = NCURSES_SP_NAME(_nc_makenew) (NCURSES_SP_ARGx num_lines, num_columns,
@@ -384,18 +389,18 @@
 NCURSES_EXPORT(WINDOW *)
 _nc_curscr_of(SCREEN *sp)
 {
-    return sp == 0 ? 0 : CurScreen(sp);
+    return (sp == 0) ? NULL : CurScreen(sp);
 }
 
 NCURSES_EXPORT(WINDOW *)
 _nc_newscr_of(SCREEN *sp)
 {
-    return sp == 0 ? 0 : NewScreen(sp);
+    return (sp == 0) ? NULL : NewScreen(sp);
 }
 
 NCURSES_EXPORT(WINDOW *)
 _nc_stdscr_of(SCREEN *sp)
 {
-    return sp == 0 ? 0 : StdScreen(sp);
+    return (sp == 0) ? NULL : StdScreen(sp);
 }
 #endif
diff --git a/ncurses/base/lib_nl.c b/ncurses/base/lib_nl.c
index 3425487..417b257 100644
--- a/ncurses/base/lib_nl.c
+++ b/ncurses/base/lib_nl.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020,2023 Thomas E. Dickey                                     *
+ * Copyright 1998-2000,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -44,7 +45,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_nl.c,v 1.12 2009/10/24 22:05:55 tom Exp $")
+MODULE_ID("$Id: lib_nl.c,v 1.14 2023/04/29 18:51:49 tom Exp $")
 
 #ifdef __EMX__
 #include <io.h>
@@ -56,7 +57,7 @@
     T((T_CALLED("nl(%p)"), (void *) SP_PARM));
     if (0 == SP_PARM)
 	returnCode(ERR);
-    SP_PARM->_nl = TRUE;
+    IsNl(SP_PARM) = TRUE;
 #ifdef __EMX__
     _nc_flush();
     _fsetmode(NC_OUTPUT(SP_PARM), "t");
@@ -78,7 +79,7 @@
     T((T_CALLED("nonl(%p)"), (void *) SP_PARM));
     if (0 == SP_PARM)
 	returnCode(ERR);
-    SP_PARM->_nl = FALSE;
+    IsNl(SP_PARM) = FALSE;
 #ifdef __EMX__
     _nc_flush();
     _fsetmode(NC_OUTPUT(SP_PARM), "b");
diff --git a/ncurses/base/lib_overlay.c b/ncurses/base/lib_overlay.c
index a206248..6d21c76 100644
--- a/ncurses/base/lib_overlay.c
+++ b/ncurses/base/lib_overlay.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2013 Free Software Foundation, Inc.              *
+ * Copyright 2020,2023 Thomas E. Dickey                                     *
+ * Copyright 1998-2013,2016 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,21 +41,19 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_overlay.c,v 1.31 2013/04/06 23:47:13 tom Exp $")
+MODULE_ID("$Id: lib_overlay.c,v 1.34 2023/09/16 16:39:07 tom Exp $")
 
 static int
 overlap(const WINDOW *const src, WINDOW *const dst, int const flag)
 {
     int rc = ERR;
-    int sx1, sy1, sx2, sy2;
-    int dx1, dy1, dx2, dy2;
-    int sminrow, smincol;
-    int dminrow, dmincol;
-    int dmaxrow, dmaxcol;
 
     T((T_CALLED("overlap(%p,%p,%d)"), (const void *) src, (void *) dst, flag));
 
     if (src != 0 && dst != 0) {
+	int sx1, sy1, sx2, sy2;
+	int dx1, dy1, dx2, dy2;
+
 	_nc_lock_global(curses);
 
 	T(("src : begy %ld, begx %ld, maxy %ld, maxx %ld",
@@ -79,12 +78,12 @@
 	dy2 = dy1 + dst->_maxy;
 
 	if (dx2 >= sx1 && dx1 <= sx2 && dy2 >= sy1 && dy1 <= sy2) {
-	    sminrow = max(sy1, dy1) - sy1;
-	    smincol = max(sx1, dx1) - sx1;
-	    dminrow = max(sy1, dy1) - dy1;
-	    dmincol = max(sx1, dx1) - dx1;
-	    dmaxrow = min(sy2, dy2) - dy1;
-	    dmaxcol = min(sx2, dx2) - dx1;
+	    int sminrow = Max(sy1, dy1) - sy1;
+	    int smincol = Max(sx1, dx1) - sx1;
+	    int dminrow = Max(sy1, dy1) - dy1;
+	    int dmincol = Max(sx1, dx1) - dx1;
+	    int dmaxrow = Min(sy2, dy2) - dy1;
+	    int dmaxcol = Min(sx2, dx2) - dx1;
 
 	    rc = copywin(src, dst,
 			 sminrow, smincol,
@@ -139,10 +138,6 @@
 	int over)
 {
     int rc = ERR;
-    int sx, sy, dx, dy;
-    bool touched;
-    attr_t bk;
-    attr_t mask;
 
     T((T_CALLED("copywin(%p, %p, %d, %d, %d, %d, %d, %d, %d)"),
        (const void *) src,
@@ -155,6 +150,9 @@
 	&& dst != 0
 	&& dmaxrow >= dminrow
 	&& dmaxcol >= dmincol) {
+	attr_t bk;
+	attr_t mask;
+
 	_nc_lock_global(curses);
 
 	bk = AttrOf(dst->_nc_bkgd);
@@ -163,18 +161,20 @@
 	/* make sure rectangle exists in source */
 	if ((sminrow + dmaxrow - dminrow) <= (src->_maxy + 1) &&
 	    (smincol + dmaxcol - dmincol) <= (src->_maxx + 1)) {
-	    bool copied = FALSE;
 
 	    T(("rectangle exists in source"));
 
 	    /* make sure rectangle fits in destination */
 	    if (dmaxrow <= dst->_maxy && dmaxcol <= dst->_maxx) {
+		int sx, sy, dx, dy;
+		bool copied = FALSE;
 
 		T(("rectangle fits in destination"));
 
 		for (dy = dminrow, sy = sminrow;
 		     dy <= dmaxrow;
 		     sy++, dy++) {
+		    bool touched;
 
 		    if (dy < 0 || sy < 0)
 			continue;
diff --git a/ncurses/base/lib_pad.c b/ncurses/base/lib_pad.c
index b87498b..d4bd7f1 100644
--- a/ncurses/base/lib_pad.c
+++ b/ncurses/base/lib_pad.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright 2020,2021 Thomas E. Dickey                                     *
+ * Copyright 1998-2010,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -42,7 +43,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_pad.c,v 1.46 2010/04/24 23:50:45 tom Exp $")
+MODULE_ID("$Id: lib_pad.c,v 1.50 2021/10/23 22:57:27 tom Exp $")
 
 NCURSES_EXPORT(WINDOW *)
 NCURSES_SP_NAME(newpad) (NCURSES_SP_DCLx int l, int c)
@@ -89,7 +90,7 @@
     T((T_CALLED("subpad(%d, %d)"), l, c));
 
     if (orig) {
-	if (!(orig->_flags & _ISPAD)
+	if (!IS_PAD(orig)
 	    || ((win = derwin(orig, l, c, begy, begx)) == NULL))
 	    returnWin(0);
     }
@@ -145,7 +146,7 @@
     if (win == 0)
 	returnCode(ERR);
 
-    if (!(win->_flags & _ISPAD))
+    if (!IS_PAD(win))
 	returnCode(ERR);
 
     sp = _nc_screen_of(win);
@@ -188,6 +189,12 @@
 
     T(("pad being refreshed"));
 
+#ifdef TRACE
+    if (USE_TRACEF(TRACE_UPDATE)) {
+	_tracedump("...pad", win);
+	_nc_unlock_global(tracef);
+    }
+#endif /* TRACE */
 #if USE_SCROLL_HINTS
     if (win->_pad._pad_y >= 0) {
 	displaced = pminrow - win->_pad._pad_y
@@ -289,7 +296,7 @@
 
     /*
      * Use the pad's current position, if it will be visible.
-     * If not, don't do anything; it's not an error.
+     * If not, don't do anything; it is not an error.
      */
     if (win->_leaveok == FALSE
 	&& win->_cury >= pminrow
@@ -327,7 +334,7 @@
     if (pad == 0)
 	returnCode(ERR);
 
-    if (!(pad->_flags & _ISPAD))
+    if (!IS_PAD(pad))
 	returnCode(wechochar(pad, ch));
 
     waddch(pad, ch);
diff --git a/ncurses/base/lib_printw.c b/ncurses/base/lib_printw.c
index 56528f6..d901b72 100644
--- a/ncurses/base/lib_printw.c
+++ b/ncurses/base/lib_printw.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2012 Free Software Foundation, Inc.              *
+ * Copyright 2018-2019,2020 Thomas E. Dickey                                *
+ * Copyright 1998-2012,2016 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -39,10 +40,10 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_printw.c,v 1.23 2012/09/03 17:55:28 tom Exp $")
+MODULE_ID("$Id: lib_printw.c,v 1.28 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
-printw(const char *fmt,...)
+printw(const char *fmt, ...)
 {
     va_list argp;
     int code;
@@ -56,14 +57,14 @@
 #endif
 
     va_start(argp, fmt);
-    code = vwprintw(stdscr, fmt, argp);
+    code = vw_printw(stdscr, fmt, argp);
     va_end(argp);
 
     returnCode(code);
 }
 
 NCURSES_EXPORT(int)
-wprintw(WINDOW *win, const char *fmt,...)
+wprintw(WINDOW *win, const char *fmt, ...)
 {
     va_list argp;
     int code;
@@ -77,16 +78,15 @@
 #endif
 
     va_start(argp, fmt);
-    code = vwprintw(win, fmt, argp);
+    code = vw_printw(win, fmt, argp);
     va_end(argp);
 
     returnCode(code);
 }
 
 NCURSES_EXPORT(int)
-mvprintw(int y, int x, const char *fmt,...)
+mvprintw(int y, int x, const char *fmt, ...)
 {
-    va_list argp;
     int code;
 
 #ifdef TRACE
@@ -98,17 +98,18 @@
 #endif
 
     if ((code = move(y, x)) != ERR) {
+	va_list argp;
+
 	va_start(argp, fmt);
-	code = vwprintw(stdscr, fmt, argp);
+	code = vw_printw(stdscr, fmt, argp);
 	va_end(argp);
     }
     returnCode(code);
 }
 
 NCURSES_EXPORT(int)
-mvwprintw(WINDOW *win, int y, int x, const char *fmt,...)
+mvwprintw(WINDOW *win, int y, int x, const char *fmt, ...)
 {
-    va_list argp;
     int code;
 
 #ifdef TRACE
@@ -120,8 +121,10 @@
 #endif
 
     if ((code = wmove(win, y, x)) != ERR) {
+	va_list argp;
+
 	va_start(argp, fmt);
-	code = vwprintw(win, fmt, argp);
+	code = vw_printw(win, fmt, argp);
 	va_end(argp);
     }
     returnCode(code);
@@ -144,3 +147,21 @@
     }
     returnCode(code);
 }
+
+NCURSES_EXPORT(int)
+vw_printw(WINDOW *win, const char *fmt, va_list argp)
+{
+    char *buf;
+    int code = ERR;
+#if NCURSES_SP_FUNCS
+    SCREEN *sp = _nc_screen_of(win);
+#endif
+
+    T((T_CALLED("vw_printw(%p,%s,va_list)"), (void *) win, _nc_visbuf(fmt)));
+
+    buf = NCURSES_SP_NAME(_nc_printf_string) (NCURSES_SP_ARGx fmt, argp);
+    if (buf != 0) {
+	code = waddstr(win, buf);
+    }
+    returnCode(code);
+}
diff --git a/ncurses/base/lib_redrawln.c b/ncurses/base/lib_redrawln.c
index 72905f8..c99d699 100644
--- a/ncurses/base/lib_redrawln.c
+++ b/ncurses/base/lib_redrawln.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2009,2010 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -39,7 +40,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_redrawln.c,v 1.17 2010/12/19 00:03:23 tom Exp $")
+MODULE_ID("$Id: lib_redrawln.c,v 1.18 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 wredrawln(WINDOW *win, int beg, int num)
diff --git a/ncurses/base/lib_refresh.c b/ncurses/base/lib_refresh.c
index a77bc48..bcaa462 100644
--- a/ncurses/base/lib_refresh.c
+++ b/ncurses/base/lib_refresh.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc.              *
+ * Copyright 2020-2021,2023 Thomas E. Dickey                                *
+ * Copyright 1998-2010,2011 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -42,7 +43,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_refresh.c,v 1.45 2011/06/25 19:02:22 Vassili.Courzakis Exp $")
+MODULE_ID("$Id: lib_refresh.c,v 1.48 2023/05/27 20:13:10 tom Exp $")
 
 NCURSES_EXPORT(int)
 wrefresh(WINDOW *win)
@@ -91,13 +92,21 @@
 
     T((T_CALLED("wnoutrefresh(%p)"), (void *) win));
 
-    /*
-     * This function will break badly if we try to refresh a pad.
-     */
-    if ((win == 0)
-	|| (win->_flags & _ISPAD))
+    if (win == NULL)
 	returnCode(ERR);
 
+    /*
+     * Handle pads as a special case.
+     */
+    if (IS_PAD(win)) {
+	returnCode(pnoutrefresh(win,
+				win->_pad._pad_y,
+				win->_pad._pad_x,
+				win->_pad._pad_top,
+				win->_pad._pad_left,
+				win->_pad._pad_bottom,
+				win->_pad._pad_right));
+    }
 #ifdef TRACE
     if (USE_TRACEF(TRACE_UPDATE)) {
 	_tracedump("...win", win);
@@ -199,7 +208,6 @@
 	    });
 
 	    if_WIDEC({
-		static cchar_t blank = BLANK;
 		int last_dst = begx + ((last_src < win->_maxx)
 				       ? last_src
 				       : win->_maxx);
@@ -245,6 +253,7 @@
 		 */
 		if (fix_left < dst_col || fix_right > last_dst) {
 		    for (j = fix_left; j <= fix_right; ++j) {
+			static cchar_t blank = BLANK;
 			nline->text[j] = blank;
 			CHANGED_CELL(nline, j);
 		    }
diff --git a/ncurses/base/lib_restart.c b/ncurses/base/lib_restart.c
index 5bfb078..0c61cb7 100644
--- a/ncurses/base/lib_restart.c
+++ b/ncurses/base/lib_restart.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2012,2015 Free Software Foundation, Inc.              *
+ * Copyright 2020,2023 Thomas E. Dickey                                     *
+ * Copyright 1998-2012,2015 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -41,7 +42,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_restart.c,v 1.16 2015/06/27 18:12:15 tom Exp $")
+MODULE_ID("$Id: lib_restart.c,v 1.18 2023/04/29 19:01:25 tom Exp $")
 
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(restartterm) (NCURSES_SP_DCLx
@@ -64,31 +65,28 @@
     if (TINFO_SETUP_TERM(&new_term, termp, filenum, errret, FALSE) != OK) {
 	result = ERR;
     } else if (SP_PARM != 0) {
-	int saveecho = SP_PARM->_echo;
-	int savecbreak = SP_PARM->_cbreak;
-	int saveraw = SP_PARM->_raw;
-	int savenl = SP_PARM->_nl;
+	TTY_FLAGS save_flags = SP_PARM->_tty_flags;
 
 #ifdef USE_TERM_DRIVER
 	SP_PARM->_term = new_term;
 #endif
-	if (saveecho) {
+	if (save_flags._echo) {
 	    NCURSES_SP_NAME(echo) (NCURSES_SP_ARG);
 	} else {
 	    NCURSES_SP_NAME(noecho) (NCURSES_SP_ARG);
 	}
 
-	if (savecbreak) {
+	if (save_flags._cbreak) {
 	    NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG);
 	    NCURSES_SP_NAME(noraw) (NCURSES_SP_ARG);
-	} else if (saveraw) {
+	} else if (save_flags._raw) {
 	    NCURSES_SP_NAME(nocbreak) (NCURSES_SP_ARG);
 	    NCURSES_SP_NAME(raw) (NCURSES_SP_ARG);
 	} else {
 	    NCURSES_SP_NAME(nocbreak) (NCURSES_SP_ARG);
 	    NCURSES_SP_NAME(noraw) (NCURSES_SP_ARG);
 	}
-	if (savenl) {
+	if (save_flags._nl) {
 	    NCURSES_SP_NAME(nl) (NCURSES_SP_ARG);
 	} else {
 	    NCURSES_SP_NAME(nonl) (NCURSES_SP_ARG);
diff --git a/ncurses/base/lib_scanw.c b/ncurses/base/lib_scanw.c
index 637aa46..1ed36a5 100644
--- a/ncurses/base/lib_scanw.c
+++ b/ncurses/base/lib_scanw.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2011 Free Software Foundation, Inc.              *
+ * Copyright 2018-2019,2020 Thomas E. Dickey                                *
+ * Copyright 1998-2009,2011 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,21 +41,40 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_scanw.c,v 1.13 2011/10/22 16:31:35 tom Exp $")
+MODULE_ID("$Id: lib_scanw.c,v 1.19 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
-vwscanw(WINDOW *win, NCURSES_CONST char *fmt, va_list argp)
+vwscanw(WINDOW *win, const char *fmt, va_list argp)
 {
     char buf[BUFSIZ];
+    int code = ERR;
 
-    if (wgetnstr(win, buf, (int) sizeof(buf) - 1) == ERR)
-	return (ERR);
+    if (wgetnstr(win, buf, (int) sizeof(buf) - 1) != ERR) {
+	if ((code = vsscanf(buf, fmt, argp)) == EOF) {
+	    code = ERR;
+	}
+    }
 
-    return (vsscanf(buf, fmt, argp));
+    return code;
 }
 
 NCURSES_EXPORT(int)
-scanw(NCURSES_CONST char *fmt,...)
+vw_scanw(WINDOW *win, const char *fmt, va_list argp)
+{
+    char buf[BUFSIZ];
+    int code = ERR;
+
+    if (wgetnstr(win, buf, (int) sizeof(buf) - 1) != ERR) {
+	if ((code = vsscanf(buf, fmt, argp)) == EOF) {
+	    code = ERR;
+	}
+    }
+
+    return code;
+}
+
+NCURSES_EXPORT(int)
+scanw(const char *fmt, ...)
 {
     int code;
     va_list ap;
@@ -62,13 +82,13 @@
     T(("scanw(\"%s\",...) called", fmt));
 
     va_start(ap, fmt);
-    code = vwscanw(stdscr, fmt, ap);
+    code = vw_scanw(stdscr, fmt, ap);
     va_end(ap);
     return (code);
 }
 
 NCURSES_EXPORT(int)
-wscanw(WINDOW *win, NCURSES_CONST char *fmt,...)
+wscanw(WINDOW *win, const char *fmt, ...)
 {
     int code;
     va_list ap;
@@ -76,31 +96,31 @@
     T(("wscanw(%p,\"%s\",...) called", (void *) win, fmt));
 
     va_start(ap, fmt);
-    code = vwscanw(win, fmt, ap);
+    code = vw_scanw(win, fmt, ap);
     va_end(ap);
     return (code);
 }
 
 NCURSES_EXPORT(int)
-mvscanw(int y, int x, NCURSES_CONST char *fmt,...)
+mvscanw(int y, int x, const char *fmt, ...)
 {
     int code;
     va_list ap;
 
     va_start(ap, fmt);
-    code = (move(y, x) == OK) ? vwscanw(stdscr, fmt, ap) : ERR;
+    code = (move(y, x) == OK) ? vw_scanw(stdscr, fmt, ap) : ERR;
     va_end(ap);
     return (code);
 }
 
 NCURSES_EXPORT(int)
-mvwscanw(WINDOW *win, int y, int x, NCURSES_CONST char *fmt,...)
+mvwscanw(WINDOW *win, int y, int x, const char *fmt, ...)
 {
     int code;
     va_list ap;
 
     va_start(ap, fmt);
-    code = (wmove(win, y, x) == OK) ? vwscanw(win, fmt, ap) : ERR;
+    code = (wmove(win, y, x) == OK) ? vw_scanw(win, fmt, ap) : ERR;
     va_end(ap);
     return (code);
 }
diff --git a/ncurses/base/lib_screen.c b/ncurses/base/lib_screen.c
index a03ceec..e2647b5 100644
--- a/ncurses/base/lib_screen.c
+++ b/ncurses/base/lib_screen.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2011,2015 Free Software Foundation, Inc.              *
+ * Copyright 2019-2021,2023 Thomas E. Dickey                                *
+ * Copyright 1998-2017,2018 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -41,7 +42,7 @@
 #define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: lib_screen.c,v 1.77 2015/07/04 22:54:14 tom Exp $")
+MODULE_ID("$Id: lib_screen.c,v 1.105 2023/04/28 20:58:54 tom Exp $")
 
 #define MAX_SIZE 0x3fff		/* 16k is big enough for a window or pad */
 
@@ -51,13 +52,22 @@
 #define L_CURL '{'
 #define R_CURL '}'
 
+#if USE_STRING_HACKS && HAVE_SNPRINTF
+#define ARG_SLIMIT(name) size_t name,
+#else
+#define ARG_SLIMIT(name)	/* nothing */
+#endif
+
+#define CUR_SLIMIT _nc_SLIMIT(limit - (size_t) (target - base))
+#define TOP_SLIMIT _nc_SLIMIT(sizeof(buffer))
+
 /*
- * Use 0x8888 as the magic number for new-format files, since it cannot be
+ * Use 0x888888 as the magic number for new-format files, since it cannot be
  * mistaken for the _cury/_curx pair of 16-bit numbers which start the old
  * format.  It happens to be unused in the file 5.22 database (2015/03/07).
  */
 static const char my_magic[] =
-{'\210', '\210', '\210', '\210'};
+{'\210', '\210', '\210', '\210', 0};
 
 #if NCURSES_EXT_PUTWIN
 typedef enum {
@@ -80,7 +90,6 @@
 typedef struct {
     const char name[17];
     PARAM_TYPE type;
-    size_t size;
     size_t offset;
 } SCR_PARAMS;
 
@@ -110,8 +119,7 @@
 };
 #undef DATA
 
-#define sizeof2(type,name) sizeof(((type *)0)->name)
-#define DATA(name, type) { { #name }, type, sizeof2(WINDOW, name), offsetof(WINDOW, name) }
+#define DATA(name, type) { { #name }, type, offsetof(WINDOW, name) }
 
 static const SCR_PARAMS scr_params[] =
 {
@@ -161,12 +169,12 @@
 read_txt(FILE *fp)
 {
     size_t limit = 1024;
-    size_t used = 0;
     char *result = malloc(limit);
     char *buffer;
 
     if (result != 0) {
 	int ch = 0;
+	size_t used = 0;
 
 	clearerr(fp);
 	result[used] = '\0';
@@ -190,7 +198,7 @@
 
 	if (ch == '\n') {
 	    result[--used] = '\0';
-	    T(("READ:%s", result));
+	    TR(TRACE_IEVENT, ("READ:%s", result));
 	} else if (used == 0) {
 	    free(result);
 	    result = 0;
@@ -204,7 +212,7 @@
 {
     bool found = FALSE;
 
-    T(("decode_attr   '%s'", source));
+    TR(TRACE_IEVENT, ("decode_attr   '%s'", source));
 
     while (*source) {
 	if (source[0] == MARKER && source[1] == L_CURL) {
@@ -262,7 +270,7 @@
     int base = 16;
     const char digits[] = "0123456789abcdef";
 
-    T(("decode_char   '%s'", source));
+    TR(TRACE_IEVENT, ("decode_char   '%s'", source));
     *target = ' ';
     switch (*source) {
     case MARKER:
@@ -319,7 +327,7 @@
     int color = PAIR_NUMBER((int) attr);
     int value;
 
-    T(("decode_chtype '%s'", source));
+    TR(TRACE_IEVENT, ("decode_chtype '%s'", source));
     source = decode_attr(source, &attr, &color);
     source = decode_char(source, &value);
     *target = (ChCharOf(value) | attr | (chtype) COLOR_PAIR(color));
@@ -337,7 +345,7 @@
     int append = 0;
     int value = 0;
 
-    T(("decode_cchar  '%s'", source));
+    TR(TRACE_IEVENT, ("decode_cchar  '%s'", source));
     *target = blank;
 #if NCURSES_EXT_COLORS
     color = fillin->ext_color;
@@ -356,7 +364,7 @@
 	    chars[append] = (wchar_t) value;
 	}
     }
-    setcchar(target, chars, attr, (short) color, NULL);
+    setcchar(target, chars, attr, (short) color, &color);
     return source;
 }
 #endif
@@ -365,9 +373,6 @@
 read_win(WINDOW *win, FILE *fp)
 {
     int code = ERR;
-    char *txt;
-    char *name;
-    char *value;
     size_t n;
     int color;
 #if NCURSES_WIDECHAR
@@ -377,7 +382,10 @@
 
     memset(win, 0, sizeof(WINDOW));
     for (;;) {
-	txt = read_txt(fp);
+	char *name;
+	char *value;
+	char *txt = read_txt(fp);
+
 	if (txt == 0)
 	    break;
 	if (!strcmp(txt, "rows:")) {
@@ -431,14 +439,17 @@
 }
 
 static int
-read_row(char *source, NCURSES_CH_T * prior, NCURSES_CH_T * target, int length)
+read_row(char *source, NCURSES_CH_T *prior, NCURSES_CH_T *target, int length)
 {
     while (*source != '\0' && length > 0) {
 #if NCURSES_WIDECHAR
-	int n, len;
+	int len;
+
 	source = decode_cchar(source, prior, target);
-	len = wcwidth(target->chars[0]);
+	len = _nc_wacs_width(target->chars[0]);
 	if (len > 1) {
+	    int n;
+
 	    SetWidecExt(CHDEREF(target), 0);
 	    for (n = 1; n < len; ++n) {
 		target[n] = target[0];
@@ -490,7 +501,6 @@
 NCURSES_SP_NAME(getwin) (NCURSES_SP_DCLx FILE *filep)
 {
     WINDOW tmp, *nwin;
-    int n;
     bool old_format = FALSE;
 
     T((T_CALLED("getwin(%p)"), (void *) filep));
@@ -503,13 +513,13 @@
      * Read the first 4 bytes to determine first if this is an old-format
      * screen-dump, or new-format.
      */
-    if (read_block(&tmp, 4, filep) < 0) {
+    if (read_block(&tmp, (size_t) 4, filep) < 0) {
 	returnWin(0);
     }
     /*
      * If this is a new-format file, and we do not support it, give up.
      */
-    if (!memcmp(&tmp, my_magic, 4)) {
+    if (!memcmp(&tmp, my_magic, (size_t) 4)) {
 #if NCURSES_EXT_PUTWIN
 	if (read_win(&tmp, filep) < 0)
 #endif
@@ -530,7 +540,7 @@
 	returnWin(0);
     }
 
-    if (tmp._flags & _ISPAD) {
+    if (IS_PAD(&tmp)) {
 	nwin = NCURSES_SP_NAME(newpad) (NCURSES_SP_ARGx
 					tmp._maxy + 1,
 					tmp._maxx + 1);
@@ -546,6 +556,7 @@
      * made sense is probably gone.
      */
     if (nwin != 0) {
+	int n;
 	size_t linesize = sizeof(NCURSES_CH_T) * (size_t) (tmp._maxx + 1);
 
 	nwin->_curx = tmp._curx;
@@ -574,7 +585,7 @@
 	nwin->_regtop = tmp._regtop;
 	nwin->_regbottom = tmp._regbottom;
 
-	if (tmp._flags & _ISPAD)
+	if (IS_PAD(&tmp))
 	    nwin->_pad = tmp._pad;
 
 	if (old_format) {
@@ -588,7 +599,7 @@
 	}
 #if NCURSES_EXT_PUTWIN
 	else {
-	    char *txt;
+	    char *txt = 0;
 	    bool success = TRUE;
 	    NCURSES_CH_T prior = blank;
 
@@ -641,13 +652,20 @@
 
 #if NCURSES_EXT_PUTWIN
 static void
-encode_attr(char *target, attr_t source, attr_t prior)
+encode_attr(char *target, ARG_SLIMIT(limit)
+	    attr_t source,
+	    attr_t prior,
+	    int source_color,
+	    int prior_color)
 {
+#if USE_STRING_HACKS && HAVE_SNPRINTF
+    char *base = target;
+#endif
     source &= ~A_CHARTEXT;
     prior &= ~A_CHARTEXT;
 
     *target = '\0';
-    if (source != prior) {
+    if ((source != prior) || (source_color != prior_color)) {
 	size_t n;
 	bool first = TRUE;
 
@@ -663,14 +681,14 @@
 		} else {
 		    *target++ = '|';
 		}
-		strcpy(target, scr_attrs[n].name);
+		_nc_STRCPY(target, scr_attrs[n].name, limit);
 		target += strlen(target);
 	    }
 	}
-	if ((source & A_COLOR) != (prior & A_COLOR)) {
+	if (source_color != prior_color) {
 	    if (!first)
 		*target++ = '|';
-	    sprintf(target, "C%d", PAIR_NUMBER((int) source));
+	    _nc_SPRINTF(target, CUR_SLIMIT "C%d", source_color);
 	    target += strlen(target);
 	}
 
@@ -680,19 +698,29 @@
 }
 
 static void
-encode_cell(char *target, CARG_CH_T source, CARG_CH_T previous)
+encode_cell(char *target, ARG_SLIMIT(limit) CARG_CH_T source, CARG_CH_T previous)
 {
+#if USE_STRING_HACKS && HAVE_SNPRINTF
+    char *base = target;
+#endif
 #if NCURSES_WIDECHAR
     size_t n;
+    int source_pair = GetPair(*source);
+    int previous_pair = GetPair(*previous);
 
     *target = '\0';
-    if (previous->attr != source->attr) {
-	encode_attr(target, source->attr, previous->attr);
+    if ((previous->attr != source->attr) || (previous_pair != source_pair)) {
+	encode_attr(target, CUR_SLIMIT
+		    source->attr,
+		    previous->attr,
+		    source_pair,
+		    previous_pair);
     }
     target += strlen(target);
 #if NCURSES_EXT_COLORS
     if (previous->ext_color != source->ext_color) {
-	sprintf(target, "%c%cC%d%c", MARKER, L_CURL, source->ext_color, R_CURL);
+	_nc_SPRINTF(target, CUR_SLIMIT
+		    "%c%cC%d%c", MARKER, L_CURL, source->ext_color, R_CURL);
     }
 #endif
     for (n = 0; n < SIZEOF(source->chars); ++n) {
@@ -705,22 +733,23 @@
 	}
 	*target++ = MARKER;
 	if (uch > 0xffff) {
-	    sprintf(target, "U%08x", uch);
+	    _nc_SPRINTF(target, CUR_SLIMIT "U%08x", uch);
 	} else if (uch > 0xff) {
-	    sprintf(target, "u%04x", uch);
+	    _nc_SPRINTF(target, CUR_SLIMIT "u%04x", uch);
 	} else if (uch < 32 || uch >= 127) {
-	    sprintf(target, "%03o", uch & 0xff);
+	    _nc_SPRINTF(target, CUR_SLIMIT "%03o", uch & 0xff);
 	} else {
 	    switch (uch) {
 	    case ' ':
-		strcpy(target, "s");
+		_nc_STRCPY(target, "s", limit);
 		break;
 	    case MARKER:
 		*target++ = MARKER;
 		*target = '\0';
 		break;
 	    default:
-		sprintf(--target, "%c", uch);
+		--target;
+		_nc_SPRINTF(target, CUR_SLIMIT "%c", uch);
 		break;
 	    }
 	}
@@ -731,27 +760,31 @@
 
     *target = '\0';
     if (AttrOfD(previous) != AttrOfD(source)) {
-	encode_attr(target, AttrOfD(source), AttrOfD(previous));
+	encode_attr(target, CUR_SLIMIT
+		    AttrOfD(source),
+		    AttrOfD(previous),
+		    GetPair(source),
+		    GetPair(previous));
     }
     target += strlen(target);
     *target++ = MARKER;
     if (ch < 32 || ch >= 127) {
-	sprintf(target, "%03o", UChar(ch));
+	_nc_SPRINTF(target, CUR_SLIMIT "%03o", UChar(ch));
     } else {
 	switch (ch) {
 	case ' ':
-	    strcpy(target, "s");
+	    _nc_STRCPY(target, "s", limit);
 	    break;
 	case MARKER:
 	    *target++ = MARKER;
 	    *target = '\0';
 	    break;
 	default:
-	    sprintf(--target, "%c", UChar(ch));
+	    --target;
+	    _nc_SPRINTF(target, CUR_SLIMIT "%c", UChar(ch));
 	    break;
 	}
     }
-    target += strlen(target);
 #endif
 }
 #endif
@@ -760,7 +793,6 @@
 putwin(WINDOW *win, FILE *filep)
 {
     int code = ERR;
-    int y;
 
     T((T_CALLED("putwin(%p,%p)"), (void *) win, (void *) filep));
 
@@ -769,6 +801,7 @@
 	const char *version = curses_version();
 	char buffer[1024];
 	NCURSES_CH_T last_cell;
+	int y;
 
 	memset(&last_cell, 0, sizeof(last_cell));
 
@@ -786,43 +819,58 @@
 	    const char *name = scr_params[y].name;
 	    const char *data = (char *) win + scr_params[y].offset;
 	    const void *dp = (const void *) data;
+	    attr_t attr;
 
 	    *buffer = '\0';
-	    if (!strncmp(name, "_pad.", 5) && !(win->_flags & _ISPAD)) {
+	    if (!strncmp(name, "_pad.", (size_t) 5) && !IS_PAD(win)) {
 		continue;
 	    }
 	    switch (scr_params[y].type) {
 	    case pATTR:
-		encode_attr(buffer, (*(const attr_t *) dp) & ~A_CHARTEXT, A_NORMAL);
+		attr = (*(const attr_t *) dp) & ~A_CHARTEXT;
+		encode_attr(buffer, TOP_SLIMIT
+			    (*(const attr_t *) dp) & ~A_CHARTEXT,
+			    A_NORMAL,
+			    COLOR_PAIR((int) attr),
+			    0);
 		break;
 	    case pBOOL:
 		if (!(*(const bool *) data)) {
 		    continue;
 		}
-		strcpy(buffer, name);
+		_nc_STRCPY(buffer, name, sizeof(buffer));
 		name = "flag";
 		break;
 	    case pCHAR:
-		encode_attr(buffer, *(const attr_t *) dp, A_NORMAL);
+		attr = (*(const attr_t *) dp);
+		encode_attr(buffer, TOP_SLIMIT
+			    * (const attr_t *) dp,
+			    A_NORMAL,
+			    COLOR_PAIR((int) attr),
+			    0);
 		break;
 	    case pINT:
 		if (!(*(const int *) dp))
 		    continue;
-		sprintf(buffer, "%d", *(const int *) dp);
+		_nc_SPRINTF(buffer, TOP_SLIMIT
+			    "%d", *(const int *) dp);
 		break;
 	    case pSHORT:
 		if (!(*(const short *) dp))
 		    continue;
-		sprintf(buffer, "%d", *(const short *) dp);
+		_nc_SPRINTF(buffer, TOP_SLIMIT
+			    "%d", *(const short *) dp);
 		break;
 	    case pSIZE:
 		if (!(*(const NCURSES_SIZE_T *) dp))
 		    continue;
-		sprintf(buffer, "%d", *(const NCURSES_SIZE_T *) dp);
+		_nc_SPRINTF(buffer, TOP_SLIMIT
+			    "%d", *(const NCURSES_SIZE_T *) dp);
 		break;
 #if NCURSES_WIDECHAR
 	    case pCCHAR:
-		encode_cell(buffer, (CARG_CH_T) dp, CHREF(last_cell));
+		encode_cell(buffer, TOP_SLIMIT
+			    (CARG_CH_T) dp, CHREF(last_cell));
 		break;
 #endif
 	    }
@@ -845,20 +893,21 @@
 		returnCode(code);
 	    for (x = 0; x <= win->_maxx; x++) {
 #if NCURSES_WIDECHAR
-		int len = wcwidth(data[x].chars[0]);
-		encode_cell(buffer, CHREF(data[x]), CHREF(last_cell));
+		int len = _nc_wacs_width(data[x].chars[0]);
+		encode_cell(buffer, TOP_SLIMIT CHREF(data[x]), CHREF(last_cell));
 		last_cell = data[x];
 		PUTS(buffer);
 		if (len > 1)
 		    x += (len - 1);
 #else
-		encode_cell(buffer, CHREF(data[x]), CHREF(last_cell));
+		encode_cell(buffer, TOP_SLIMIT CHREF(data[x]), CHREF(last_cell));
 		last_cell = data[x];
 		PUTS(buffer);
 #endif
 	    }
 	    PUTS("\n");
 	}
+	code = OK;
     }
 #else
     /*
@@ -869,6 +918,7 @@
      */
     if (win != 0) {
 	size_t len = (size_t) (win->_maxx + 1);
+	int y;
 
 	clearerr(filep);
 	if (fwrite(win, sizeof(WINDOW), (size_t) 1, filep) != 1
@@ -888,6 +938,31 @@
     returnCode(code);
 }
 
+/*
+ * Replace a window covering the whole screen, i.e., newscr or curscr.
+ */
+static WINDOW *
+replace_window(WINDOW *target, FILE *source)
+{
+    WINDOW *result = getwin(source);
+#if NCURSES_EXT_FUNCS
+    if (result != NULL) {
+	if (getmaxx(result) != getmaxx(target)
+	    || getmaxy(result) != getmaxy(target)) {
+	    int code = wresize(result,
+			       1 + getmaxy(target),
+			       1 + getmaxx(target));
+	    if (code != OK) {
+		delwin(result);
+		result = NULL;
+	    }
+	}
+    }
+#endif
+    delwin(target);
+    return result;
+}
+
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(scr_restore) (NCURSES_SP_DCLx const char *file)
 {
@@ -897,9 +972,8 @@
     T((T_CALLED("scr_restore(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file)));
 
     if (_nc_access(file, R_OK) >= 0
-	&& (fp = fopen(file, "rb")) != 0) {
-	delwin(NewScreen(SP_PARM));
-	NewScreen(SP_PARM) = getwin(fp);
+	&& (fp = safe_fopen(file, BIN_R)) != 0) {
+	NewScreen(SP_PARM) = replace_window(NewScreen(SP_PARM), fp);
 #if !USE_REENTRANT
 	newscr = NewScreen(SP_PARM);
 #endif
@@ -928,7 +1002,7 @@
     T((T_CALLED("scr_dump(%s)"), _nc_visbuf(file)));
 
     if (_nc_access(file, W_OK) < 0
-	|| (fp = fopen(file, "wb")) == 0) {
+	|| (fp = safe_fopen(file, BIN_W)) == 0) {
 	result = ERR;
     } else {
 	(void) putwin(newscr, fp);
@@ -941,7 +1015,6 @@
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(scr_init) (NCURSES_SP_DCLx const char *file)
 {
-    FILE *fp = 0;
     int code = ERR;
 
     T((T_CALLED("scr_init(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file)));
@@ -953,10 +1026,11 @@
 	!(exit_ca_mode && non_rev_rmcup)
 #endif
 	) {
+	FILE *fp = 0;
+
 	if (_nc_access(file, R_OK) >= 0
-	    && (fp = fopen(file, "rb")) != 0) {
-	    delwin(CurScreen(SP_PARM));
-	    CurScreen(SP_PARM) = getwin(fp);
+	    && (fp = safe_fopen(file, BIN_R)) != 0) {
+	    CurScreen(SP_PARM) = replace_window(CurScreen(SP_PARM), fp);
 #if !USE_REENTRANT
 	    curscr = CurScreen(SP_PARM);
 #endif
diff --git a/ncurses/base/lib_scroll.c b/ncurses/base/lib_scroll.c
index 8684e25..ecc0ba5 100644
--- a/ncurses/base/lib_scroll.c
+++ b/ncurses/base/lib_scroll.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc.              *
+ * Copyright 2019,2020 Thomas E. Dickey                                     *
+ * Copyright 1998-2010,2011 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -43,7 +44,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_scroll.c,v 1.29 2011/10/22 16:34:50 tom Exp $")
+MODULE_ID("$Id: lib_scroll.c,v 1.32 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(void)
 _nc_scroll_window(WINDOW *win,
@@ -77,11 +78,13 @@
      * setup cost.  So there is no point in trying to be excessively
      * clever -- esr.
      */
+#define BottomLimit(n) ((n) >= 0 && (n) >= top)
+#define TopLimit(n)    ((n) <= win->_maxy && (n) <= bottom)
 
     /* shift n lines downwards */
     if (n < 0) {
 	limit = top - n;
-	for (line = bottom; line >= limit && line >= 0; line--) {
+	for (line = bottom; line >= limit && BottomLimit(line); line--) {
 	    TR(TRACE_MOVE, ("...copying %d to %d", line + n, line));
 	    memcpy(win->_line[line].text,
 		   win->_line[line + n].text,
@@ -89,7 +92,7 @@
 	    if_USE_SCROLL_HINTS(win->_line[line].oldindex =
 				win->_line[line + n].oldindex);
 	}
-	for (line = top; line < limit && line <= win->_maxy; line++) {
+	for (line = top; line < limit && TopLimit(line); line++) {
 	    TR(TRACE_MOVE, ("...filling %d", line));
 	    for (j = 0; j <= win->_maxx; j++)
 		win->_line[line].text[j] = blank;
@@ -100,14 +103,14 @@
     /* shift n lines upwards */
     if (n > 0) {
 	limit = bottom - n;
-	for (line = top; line <= limit && line <= win->_maxy; line++) {
+	for (line = top; line <= limit && TopLimit(line); line++) {
 	    memcpy(win->_line[line].text,
 		   win->_line[line + n].text,
 		   to_copy);
 	    if_USE_SCROLL_HINTS(win->_line[line].oldindex =
 				win->_line[line + n].oldindex);
 	}
-	for (line = bottom; line > limit && line >= 0; line--) {
+	for (line = bottom; line > limit && BottomLimit(line); line--) {
 	    for (j = 0; j <= win->_maxx; j++)
 		win->_line[line].text[j] = blank;
 	    if_USE_SCROLL_HINTS(win->_line[line].oldindex = _NEWINDEX);
diff --git a/ncurses/base/lib_scrollok.c b/ncurses/base/lib_scrollok.c
index 6a698a3..c9462c3 100644
--- a/ncurses/base/lib_scrollok.c
+++ b/ncurses/base/lib_scrollok.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2000,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2000,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,7 +41,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_scrollok.c,v 1.5 2009/10/24 22:35:38 tom Exp $")
+MODULE_ID("$Id: lib_scrollok.c,v 1.6 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 scrollok(WINDOW *win, bool flag)
diff --git a/ncurses/base/lib_scrreg.c b/ncurses/base/lib_scrreg.c
index 546fbc1..5207f6f 100644
--- a/ncurses/base/lib_scrreg.c
+++ b/ncurses/base/lib_scrreg.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2000,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2000,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,7 +41,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_scrreg.c,v 1.11 2009/10/24 22:35:28 tom Exp $")
+MODULE_ID("$Id: lib_scrreg.c,v 1.12 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 wsetscrreg(WINDOW *win, int top, int bottom)
diff --git a/ncurses/base/lib_set_term.c b/ncurses/base/lib_set_term.c
index f787a88..78de859 100644
--- a/ncurses/base/lib_set_term.c
+++ b/ncurses/base/lib_set_term.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2014,2015 Free Software Foundation, Inc.              *
+ * Copyright 2018-2021,2022 Thomas E. Dickey                                *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,14 +41,23 @@
 **
 */
 
+#define NEW_PAIR_INTERNAL 1
+
 #include <curses.priv.h>
 #include <tic.h>
+#include <new_pair.h>
 
-#ifndef CUR
-#define CUR SP_TERMTYPE
+#if USE_GPM_SUPPORT
+#ifdef HAVE_LIBDL
+/* use dynamic loader to avoid linkage dependency */
+#include <dlfcn.h>
+#endif
 #endif
 
-MODULE_ID("$Id: lib_set_term.c,v 1.153 2015/08/07 23:57:58 tom Exp $")
+#undef CUR
+#define CUR SP_TERMTYPE
+
+MODULE_ID("$Id: lib_set_term.c,v 1.184 2022/12/10 21:34:12 tom Exp $")
 
 #ifdef USE_TERM_DRIVER
 #define MaxColors      InfoOf(sp).maxcolors
@@ -134,15 +144,17 @@
 NCURSES_EXPORT(void)
 delscreen(SCREEN *sp)
 {
-    int i;
 
     T((T_CALLED("delscreen(%p)"), (void *) sp));
 
     _nc_lock_global(curses);
     if (delink_screen(sp)) {
+	WINDOWLIST *wl;
+	bool is_current = (sp == CURRENT_SCREEN);
+
 #ifdef USE_SP_RIPOFF
-	ripoff_t *rop;
 	if (safe_ripoff_sp && safe_ripoff_sp != safe_ripoff_stack) {
+	    ripoff_t *rop;
 	    for (rop = safe_ripoff_stack;
 		 rop != safe_ripoff_sp && (rop - safe_ripoff_stack) < N_RIPS;
 		 rop++) {
@@ -154,12 +166,19 @@
 	}
 #endif
 
-	(void) _nc_freewin(CurScreen(sp));
-	(void) _nc_freewin(NewScreen(sp));
-	(void) _nc_freewin(StdScreen(sp));
+	/* delete all of the windows in this screen */
+      rescan:
+	for (each_window(sp, wl)) {
+	    if (_nc_freewin(&(wl->win)) == OK) {
+		goto rescan;
+	    }
+	}
 
 	if (sp->_slk != 0) {
+
 	    if (sp->_slk->ent != 0) {
+		int i;
+
 		for (i = 0; i < sp->_slk->labcnt; ++i) {
 		    FreeIfNeeded(sp->_slk->ent[i].ent_text);
 		    FreeIfNeeded(sp->_slk->ent[i].form_text);
@@ -178,9 +197,11 @@
 
 	FreeIfNeeded(sp->_current_attr);
 
+	_nc_free_ordered_pairs(sp);
 	FreeIfNeeded(sp->_color_table);
 	FreeIfNeeded(sp->_color_pairs);
 
+	FreeIfNeeded(sp->_oldnum_list);
 	FreeIfNeeded(sp->oldhash);
 	FreeIfNeeded(sp->newhash);
 	FreeIfNeeded(sp->hashtab);
@@ -191,6 +212,17 @@
 	NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG);
 	NCURSES_SP_NAME(del_curterm) (NCURSES_SP_ARGx sp->_term);
 	FreeIfNeeded(sp->out_buffer);
+	if (_nc_find_prescr() == sp) {
+	    _nc_forget_prescr();
+	}
+#if USE_GPM_SUPPORT
+#ifdef HAVE_LIBDL
+	if (sp->_dlopen_gpm != 0) {
+	    dlclose(sp->_dlopen_gpm);
+	    sp->_dlopen_gpm = 0;
+	}
+#endif
+#endif /* USE_GPM_SUPPORT */
 	free(sp);
 
 	/*
@@ -198,7 +230,7 @@
 	 * application might try to use (except cur_term, which may have
 	 * multiple references in different screens).
 	 */
-	if (sp == CURRENT_SCREEN) {
+	if (is_current) {
 #if !USE_REENTRANT
 	    curscr = 0;
 	    newscr = 0;
@@ -213,6 +245,8 @@
 		_nc_wacs = 0;
 	    }
 #endif
+	} else {
+	    set_term(CURRENT_SCREEN);
 	}
     }
     _nc_unlock_global(curses);
@@ -259,7 +293,7 @@
     if ((dst = tmp) == 0) {
 	dst = src;
     } else if (value >= 0) {
-	*result = value;
+	*result = (int) value;
     }
     while (*dst != 0 && *dst != ';')
 	dst++;
@@ -284,9 +318,11 @@
 				     int filtered,
 				     int slk_format)
 {
+#ifndef USE_TERM_DRIVER
+    static const TTY null_TTY;	/* all zeros iff uninitialized */
+#endif
     char *env;
     int bottom_stolen = 0;
-    ripoff_t *rop;
     SCREEN *sp;
 #ifndef USE_TERM_DRIVER
     bool support_cookies = USE_XMC_SUPPORT;
@@ -303,11 +339,17 @@
 
     if (!sp) {
 	sp = _nc_alloc_screen_sp();
+	T(("_nc_alloc_screen_sp %p", (void *) sp));
 	*spp = sp;
     }
-    if (!sp
-	|| ((sp->_acs_map = typeCalloc(chtype, ACS_LEN)) == 0)
-	|| ((sp->_screen_acs_map = typeCalloc(bool, ACS_LEN)) == 0)) {
+    if (sp == NULL) {
+	ReturnScreenError();
+    }
+    if ((sp->_acs_map = typeCalloc(chtype, ACS_LEN)) == NULL) {
+	ReturnScreenError();
+    }
+    if ((sp->_screen_acs_map = typeCalloc(bool, ACS_LEN)) == NULL) {
+	free(sp->_acs_map);
 	ReturnScreenError();
     }
 
@@ -331,8 +373,9 @@
     sp->_next_screen = _nc_screen_chain;
     _nc_screen_chain = sp;
 
-    if ((sp->_current_attr = typeCalloc(NCURSES_CH_T, 1)) == 0)
+    if ((sp->_current_attr = typeCalloc(NCURSES_CH_T, 1)) == 0) {
 	returnCode(ERR);
+    }
 #endif
 
     /*
@@ -361,13 +404,19 @@
 #ifdef USE_TERM_DRIVER
 	CallDriver(sp, td_setfilter);
 #else
-	clear_screen = 0;
-	cursor_down = parm_down_cursor = 0;
-	cursor_address = 0;
-	cursor_up = parm_up_cursor = 0;
-	row_address = 0;
+	/* *INDENT-EQLS* */
+	clear_screen     = ABSENT_STRING;
+	cursor_address   = ABSENT_STRING;
+	cursor_down      = ABSENT_STRING;
+	cursor_up        = ABSENT_STRING;
+	parm_down_cursor = ABSENT_STRING;
+	parm_up_cursor   = ABSENT_STRING;
+	row_address      = ABSENT_STRING;
+	cursor_home      = carriage_return;
 
-	cursor_home = carriage_return;
+	if (back_color_erase)
+	    clr_eos = ABSENT_STRING;
+
 #endif
 	T(("filter screensize %dx%d", slines, scolumns));
     }
@@ -376,7 +425,11 @@
     fflush(output);
     setmode(output, O_BINARY);
 #endif
-    NCURSES_SP_NAME(_nc_set_buffer) (NCURSES_SP_ARGx output, TRUE);
+#if defined(EXP_WIN32_DRIVER)
+    T(("setting output mode to binary"));
+    fflush(output);
+    _setmode(fileno(output), _O_BINARY);
+#endif
     sp->_lines = (NCURSES_SIZE_T) slines;
     sp->_lines_avail = (NCURSES_SIZE_T) slines;
     sp->_columns = (NCURSES_SIZE_T) scolumns;
@@ -384,6 +437,10 @@
     fflush(output);
     sp->_ofd = output ? fileno(output) : -1;
     sp->_ofp = output;
+#if defined(EXP_WIN32_DRIVER)
+    if (output)
+	_setmode(fileno(output), _O_BINARY);
+#endif
     sp->out_limit = (size_t) ((2 + slines) * (6 + scolumns));
     if ((sp->out_buffer = malloc(sp->out_limit)) == 0)
 	sp->out_limit = 0;
@@ -419,8 +476,8 @@
     sp->_default_fg = COLOR_WHITE;
     sp->_default_bg = COLOR_BLACK;
 #else
-    sp->_default_fg = C_MASK;
-    sp->_default_bg = C_MASK;
+    sp->_default_fg = COLOR_DEFAULT;
+    sp->_default_bg = COLOR_DEFAULT;
 #endif
 
     /*
@@ -432,9 +489,9 @@
 	char sep1, sep2;
 	int count = sscanf(env, "%d%c%d%c", &fg, &sep1, &bg, &sep2);
 	if (count >= 1) {
-	    sp->_default_fg = ((fg >= 0 && fg < MaxColors) ? fg : C_MASK);
+	    sp->_default_fg = ((fg >= 0 && fg < MaxColors) ? fg : COLOR_DEFAULT);
 	    if (count >= 3) {
-		sp->_default_bg = ((bg >= 0 && bg < MaxColors) ? bg : C_MASK);
+		sp->_default_bg = ((bg >= 0 && bg < MaxColors) ? bg : COLOR_DEFAULT);
 	    }
 	    TR(TRACE_CHARPUT | TRACE_MOVE,
 	       ("from environment assumed fg=%d, bg=%d",
@@ -455,7 +512,7 @@
 	p = extract_fgbg(p, &(sp->_default_fg));
 	p = extract_fgbg(p, &(sp->_default_bg));
 	if (*p)			/* assume rxvt was compiled with xpm support */
-	    p = extract_fgbg(p, &(sp->_default_bg));
+	    extract_fgbg(p, &(sp->_default_bg));
 	TR(TRACE_CHARPUT | TRACE_MOVE, ("decoded fg=%d, bg=%d",
 					sp->_default_fg, sp->_default_bg));
 	if (sp->_default_fg >= MaxColors) {
@@ -627,10 +684,22 @@
     NewScreen(sp)->_clear = TRUE;
     CurScreen(sp)->_clear = FALSE;
 
-    NCURSES_SP_NAME(def_shell_mode) (NCURSES_SP_ARG);
-    NCURSES_SP_NAME(def_prog_mode) (NCURSES_SP_ARG);
+    /*
+     * Get the current tty-modes. setupterm() may already have done this,
+     * unless we use the term-driver.
+     */
+#ifndef USE_TERM_DRIVER
+    if (cur_term != 0 &&
+	!memcmp(&cur_term->Ottyb, &null_TTY, sizeof(TTY)))
+#endif
+    {
+	NCURSES_SP_NAME(def_shell_mode) (NCURSES_SP_ARG);
+	NCURSES_SP_NAME(def_prog_mode) (NCURSES_SP_ARG);
+    }
 
     if (safe_ripoff_sp && safe_ripoff_sp != safe_ripoff_stack) {
+	ripoff_t *rop;
+
 	for (rop = safe_ripoff_stack;
 	     rop != safe_ripoff_sp && (rop - safe_ripoff_stack) < N_RIPS;
 	     rop++) {
@@ -640,6 +709,9 @@
 	       formats (4-4 or 3-2-3) for which there may be some hardware
 	       support. */
 	    if (rop->hook == _nc_slk_initialize) {
+		if (!TerminalOf(sp)) {
+		    continue;
+		}
 		if (!(NumLabels <= 0 || !SLK_STDFMT(slk_format))) {
 		    continue;
 		}
@@ -679,6 +751,7 @@
     }
 
     T(("creating stdscr"));
+    (void) bottom_stolen;
     assert((sp->_lines_avail + sp->_topstolen + bottom_stolen) == slines);
     if ((StdScreen(sp) = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx
 						  sp->_lines_avail,
@@ -724,9 +797,12 @@
 				 int (*init) (WINDOW *, int))
 {
     int code = ERR;
+    TR_FUNC_BFR(1);
 
     START_TRACE();
-    T((T_CALLED("ripoffline(%p,%d,%p)"), (void *) SP_PARM, line, init));
+    T((T_CALLED("ripoffline(%p,%d,%s)"),
+       (void *) SP_PARM, line,
+       TR_FUNC_ARG(0, init)));
 
 #if NCURSES_SP_FUNCS
     if (SP_PARM != 0 && SP_PARM->_prescreen)
@@ -735,12 +811,15 @@
 	if (line == 0) {
 	    code = OK;
 	} else {
-	    if (safe_ripoff_sp == 0)
+	    if (safe_ripoff_sp == 0) {
 		safe_ripoff_sp = safe_ripoff_stack;
+	    }
 	    if (safe_ripoff_sp < safe_ripoff_stack + N_RIPS) {
 		safe_ripoff_sp->line = line;
 		safe_ripoff_sp->hook = init;
 		(safe_ripoff_sp)++;
+		T(("ripped-off %d:%d chunks",
+		   (int) (safe_ripoff_sp - safe_ripoff_stack), N_RIPS));
 		code = OK;
 	    }
 	}
@@ -753,7 +832,15 @@
 NCURSES_EXPORT(int)
 _nc_ripoffline(int line, int (*init) (WINDOW *, int))
 {
-    return NCURSES_SP_NAME(_nc_ripoffline) (CURRENT_SCREEN_PRE, line, init);
+    int rc;
+
+    _nc_init_pthreads();
+    _nc_lock_global(prescreen);
+    START_TRACE();
+    rc = NCURSES_SP_NAME(_nc_ripoffline) (CURRENT_SCREEN_PRE, line, init);
+    _nc_unlock_global(prescreen);
+
+    return rc;
 }
 #endif
 
@@ -772,6 +859,14 @@
 NCURSES_EXPORT(int)
 ripoffline(int line, int (*init) (WINDOW *, int))
 {
-    return NCURSES_SP_NAME(ripoffline) (CURRENT_SCREEN_PRE, line, init);
+    int rc;
+
+    _nc_init_pthreads();
+    _nc_lock_global(prescreen);
+    START_TRACE();
+    rc = NCURSES_SP_NAME(ripoffline) (CURRENT_SCREEN_PRE, line, init);
+    _nc_unlock_global(prescreen);
+
+    return rc;
 }
 #endif
diff --git a/ncurses/base/lib_slk.c b/ncurses/base/lib_slk.c
index 84f17ae..47e57e0 100644
--- a/ncurses/base/lib_slk.c
+++ b/ncurses/base/lib_slk.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc.              *
+ * Copyright 2020,2022 Thomas E. Dickey                                     *
+ * Copyright 1998-2010,2011 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -47,7 +48,7 @@
 #define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: lib_slk.c,v 1.48 2011/03/05 21:21:52 tom Exp $")
+MODULE_ID("$Id: lib_slk.c,v 1.50 2022/08/20 18:29:22 tom Exp $")
 
 #ifdef USE_TERM_DRIVER
 #define NumLabels    InfoOf(SP_PARM).numlabels
@@ -186,8 +187,10 @@
 	|| SP_PARM->_slk->labcnt <= 0
 	|| (SP_PARM->_slk->ent = typeCalloc(slk_ent,
 					    (size_t) SP_PARM->_slk->labcnt))
-	== NULL)
+	== NULL) {
+	free(SP_PARM->_slk->ent);
 	returnCode(slk_failed(NCURSES_SP_ARG));
+    }
 
     max_length = (size_t) SP_PARM->_slk->maxlen;
     for (i = 0; i < SP_PARM->_slk->labcnt; i++) {
diff --git a/ncurses/base/lib_slkatr_set.c b/ncurses/base/lib_slkatr_set.c
index a3132e9..7c5a23a 100644
--- a/ncurses/base/lib_slkatr_set.c
+++ b/ncurses/base/lib_slkatr_set.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2014 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2014,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -38,30 +39,31 @@
  */
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_slkatr_set.c,v 1.15 2014/02/01 22:10:42 tom Exp $")
+MODULE_ID("$Id: lib_slkatr_set.c,v 1.17 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(slk_attr_set) (NCURSES_SP_DCLx
 			       const attr_t attr,
-			       NCURSES_PAIRS_T color_pair_number,
+			       NCURSES_PAIRS_T pair_arg,
 			       void *opts)
 {
     int code = ERR;
+    int color_pair = pair_arg;
 
     T((T_CALLED("slk_attr_set(%p,%s,%d)"),
        (void *) SP_PARM,
        _traceattr(attr),
-       (int) color_pair_number));
+       color_pair));
 
+    set_extended_pair(opts, color_pair);
     if (SP_PARM != 0
 	&& SP_PARM->_slk != 0
-	&& !opts
-	&& color_pair_number >= 0
-	&& color_pair_number < SP_PARM->_pair_limit) {
+	&& color_pair >= 0
+	&& color_pair < SP_PARM->_pair_limit) {
 	TR(TRACE_ATTRS, ("... current %s", _tracech_t(CHREF(SP_PARM->_slk->attr))));
 	SetAttr(SP_PARM->_slk->attr, attr);
-	if (color_pair_number > 0) {
-	    SetPair(SP_PARM->_slk->attr, color_pair_number);
+	if (color_pair > 0) {
+	    SetPair(SP_PARM->_slk->attr, color_pair);
 	}
 	TR(TRACE_ATTRS, ("new attribute is %s", _tracech_t(CHREF(SP_PARM->_slk->attr))));
 	code = OK;
@@ -71,9 +73,9 @@
 
 #if NCURSES_SP_FUNCS
 NCURSES_EXPORT(int)
-slk_attr_set(const attr_t attr, NCURSES_COLOR_T color_pair_number, void *opts)
+slk_attr_set(const attr_t attr, NCURSES_COLOR_T pair_arg, void *opts)
 {
     return NCURSES_SP_NAME(slk_attr_set) (CURRENT_SCREEN, attr,
-					  color_pair_number, opts);
+					  pair_arg, opts);
 }
 #endif
diff --git a/ncurses/base/lib_slkatrof.c b/ncurses/base/lib_slkatrof.c
index bb980ab..2d53ab2 100644
--- a/ncurses/base/lib_slkatrof.c
+++ b/ncurses/base/lib_slkatrof.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2005,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2005,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -38,7 +39,7 @@
  */
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_slkatrof.c,v 1.11 2009/10/24 22:12:21 tom Exp $")
+MODULE_ID("$Id: lib_slkatrof.c,v 1.12 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(slk_attroff) (NCURSES_SP_DCLx const chtype attr)
diff --git a/ncurses/base/lib_slkatron.c b/ncurses/base/lib_slkatron.c
index bc2fb33..accc2f2 100644
--- a/ncurses/base/lib_slkatron.c
+++ b/ncurses/base/lib_slkatron.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2009,2010 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -38,7 +39,7 @@
  */
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_slkatron.c,v 1.12 2010/03/31 23:38:02 tom Exp $")
+MODULE_ID("$Id: lib_slkatron.c,v 1.13 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(slk_attron) (NCURSES_SP_DCLx const chtype attr)
diff --git a/ncurses/base/lib_slkatrset.c b/ncurses/base/lib_slkatrset.c
index 544b8d0..11fa7e6 100644
--- a/ncurses/base/lib_slkatrset.c
+++ b/ncurses/base/lib_slkatrset.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2005,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2005,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -38,7 +39,7 @@
  */
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_slkatrset.c,v 1.10 2009/10/24 22:12:21 tom Exp $")
+MODULE_ID("$Id: lib_slkatrset.c,v 1.11 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(slk_attrset) (NCURSES_SP_DCLx const chtype attr)
diff --git a/ncurses/base/lib_slkattr.c b/ncurses/base/lib_slkattr.c
index bec11e8..af49f3b 100644
--- a/ncurses/base/lib_slkattr.c
+++ b/ncurses/base/lib_slkattr.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2009,2010 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -38,7 +39,7 @@
  */
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_slkattr.c,v 1.11 2010/12/20 01:41:25 tom Exp $")
+MODULE_ID("$Id: lib_slkattr.c,v 1.12 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(attr_t)
 NCURSES_SP_NAME(slk_attr) (NCURSES_SP_DCL0)
diff --git a/ncurses/base/lib_slkclear.c b/ncurses/base/lib_slkclear.c
index 264c8c4..10531e4 100644
--- a/ncurses/base/lib_slkclear.c
+++ b/ncurses/base/lib_slkclear.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2007,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2007,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,7 +41,7 @@
  */
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_slkclear.c,v 1.14 2009/11/07 16:27:05 tom Exp $")
+MODULE_ID("$Id: lib_slkclear.c,v 1.15 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(slk_clear) (NCURSES_SP_DCL0)
diff --git a/ncurses/base/lib_slkcolor.c b/ncurses/base/lib_slkcolor.c
index 2cf9e5d..00d1eaa 100644
--- a/ncurses/base/lib_slkcolor.c
+++ b/ncurses/base/lib_slkcolor.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2014 Free Software Foundation, Inc.              *
+ * Copyright 2018,2020 Thomas E. Dickey                                     *
+ * Copyright 1998-2014,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -38,31 +39,53 @@
  */
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_slkcolor.c,v 1.17 2014/02/01 22:10:42 tom Exp $")
+MODULE_ID("$Id: lib_slkcolor.c,v 1.20 2020/02/02 23:34:34 tom Exp $")
 
-NCURSES_EXPORT(int)
-NCURSES_SP_NAME(slk_color) (NCURSES_SP_DCLx NCURSES_PAIRS_T color_pair_number)
+static int
+_nc_slk_color(SCREEN *sp, int pair_arg)
 {
     int code = ERR;
 
-    T((T_CALLED("slk_color(%p,%d)"), (void *) SP_PARM, (int) color_pair_number));
+    T((T_CALLED("slk_color(%p,%d)"), (void *) sp, pair_arg));
 
-    if (SP_PARM != 0
-	&& SP_PARM->_slk != 0
-	&& color_pair_number >= 0
-	&& color_pair_number < SP_PARM->_pair_limit) {
-	TR(TRACE_ATTRS, ("... current is %s", _tracech_t(CHREF(SP_PARM->_slk->attr))));
-	SetPair(SP_PARM->_slk->attr, color_pair_number);
-	TR(TRACE_ATTRS, ("new attribute is %s", _tracech_t(CHREF(SP_PARM->_slk->attr))));
+    if (sp != 0
+	&& sp->_slk != 0
+	&& pair_arg >= 0
+	&& pair_arg < sp->_pair_limit) {
+	TR(TRACE_ATTRS, ("... current is %s", _tracech_t(CHREF(sp->_slk->attr))));
+	SetPair(sp->_slk->attr, pair_arg);
+	TR(TRACE_ATTRS, ("new attribute is %s", _tracech_t(CHREF(sp->_slk->attr))));
 	code = OK;
     }
     returnCode(code);
 }
 
+NCURSES_EXPORT(int)
+NCURSES_SP_NAME(slk_color) (NCURSES_SP_DCLx NCURSES_PAIRS_T pair_arg)
+{
+    return _nc_slk_color(SP_PARM, pair_arg);
+}
+
 #if NCURSES_SP_FUNCS
 NCURSES_EXPORT(int)
-slk_color(NCURSES_PAIRS_T color_pair_number)
+slk_color(NCURSES_PAIRS_T pair_arg)
 {
-    return NCURSES_SP_NAME(slk_color) (CURRENT_SCREEN, color_pair_number);
+    return NCURSES_SP_NAME(slk_color) (CURRENT_SCREEN, pair_arg);
 }
 #endif
+
+#if NCURSES_EXT_COLORS
+NCURSES_EXPORT(int)
+NCURSES_SP_NAME(extended_slk_color) (NCURSES_SP_DCLx int pair_arg)
+{
+    return _nc_slk_color(SP_PARM, pair_arg);
+}
+
+#if NCURSES_SP_FUNCS
+NCURSES_EXPORT(int)
+extended_slk_color(int pair_arg)
+{
+    return NCURSES_SP_NAME(extended_slk_color) (CURRENT_SCREEN, pair_arg);
+}
+#endif
+#endif
diff --git a/ncurses/base/lib_slkinit.c b/ncurses/base/lib_slkinit.c
index 9cbdfea..318077f 100644
--- a/ncurses/base/lib_slkinit.c
+++ b/ncurses/base/lib_slkinit.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020,2022 Thomas E. Dickey                                     *
+ * Copyright 1998-2009,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,7 +41,7 @@
  */
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_slkinit.c,v 1.13 2009/10/31 00:10:46 tom Exp $")
+MODULE_ID("$Id: lib_slkinit.c,v 1.16 2022/07/09 18:58:58 tom Exp $")
 
 #ifdef USE_SP_RIPOFF
 #define SoftkeyFormat SP_PARM->slk_format
@@ -75,6 +76,14 @@
 NCURSES_EXPORT(int)
 slk_init(int format)
 {
-    return NCURSES_SP_NAME(slk_init) (CURRENT_SCREEN_PRE, format);
+    int rc;
+
+    _nc_init_pthreads();
+    _nc_lock_global(prescreen);
+    START_TRACE();
+    rc = NCURSES_SP_NAME(slk_init) (CURRENT_SCREEN_PRE, format);
+    _nc_unlock_global(prescreen);
+
+    return rc;
 }
 #endif
diff --git a/ncurses/base/lib_slklab.c b/ncurses/base/lib_slklab.c
index d0b2a23..894ff26 100644
--- a/ncurses/base/lib_slklab.c
+++ b/ncurses/base/lib_slklab.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2003,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2003,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,7 +41,7 @@
  */
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_slklab.c,v 1.10 2009/10/24 22:12:21 tom Exp $")
+MODULE_ID("$Id: lib_slklab.c,v 1.11 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(char *)
 NCURSES_SP_NAME(slk_label) (NCURSES_SP_DCLx int n)
diff --git a/ncurses/base/lib_slkrefr.c b/ncurses/base/lib_slkrefr.c
index 382f9c4..7a40624 100644
--- a/ncurses/base/lib_slkrefr.c
+++ b/ncurses/base/lib_slkrefr.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2013,2014 Free Software Foundation, Inc.              *
+ * Copyright 2020,2021 Thomas E. Dickey                                     *
+ * Copyright 1998-2013,2014 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -43,7 +44,7 @@
 #define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: lib_slkrefr.c,v 1.30 2014/03/08 20:32:59 tom Exp $")
+MODULE_ID("$Id: lib_slkrefr.c,v 1.32 2021/09/04 10:54:35 tom Exp $")
 
 #ifdef USE_TERM_DRIVER
 #define NumLabels    InfoOf(SP_PARM).numlabels
@@ -112,7 +113,7 @@
 		    wmove(slk->win, SLK_LINES(fmt) - 1, slk->ent[i].ent_x);
 		    (void) wattrset(slk->win, (int) AttrOf(slk->attr));
 		    waddstr(slk->win, slk->ent[i].form_text);
-		    /* if we simulate SLK's, it's looking much more
+		    /* if we simulate SLK's, it is looking much more
 		       natural to use the current ATTRIBUTE also
 		       for the label window */
 		    (void) wattrset(slk->win, (int) WINDOW_ATTRS(StdScreen(sp)));
diff --git a/ncurses/base/lib_slkset.c b/ncurses/base/lib_slkset.c
index 9091e00..3e777f1 100644
--- a/ncurses/base/lib_slkset.c
+++ b/ncurses/base/lib_slkset.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2011,2012 Free Software Foundation, Inc.              *
+ * Copyright 2019,2020 Thomas E. Dickey                                     *
+ * Copyright 1998-2011,2012 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -44,7 +45,7 @@
 #endif
 #endif
 
-MODULE_ID("$Id: lib_slkset.c,v 1.24 2012/12/08 23:09:25 tom Exp $")
+MODULE_ID("$Id: lib_slkset.c,v 1.26 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(slk_set) (NCURSES_SP_DCLx int i, const char *astr, int format)
@@ -89,9 +90,9 @@
 	mbrtowc(&wc, p, need, &state);
 	if (!iswprint((wint_t) wc))
 	    break;
-	if (wcwidth(wc) + numcols > limit)
+	if (_nc_wacs_width(wc) + numcols > limit)
 	    break;
-	numcols += wcwidth(wc);
+	numcols += _nc_wacs_width(wc);
 	p += need;
     }
     numchrs = (int) (p - str);
diff --git a/ncurses/base/lib_slktouch.c b/ncurses/base/lib_slktouch.c
index ba77fd2..6696a25 100644
--- a/ncurses/base/lib_slktouch.c
+++ b/ncurses/base/lib_slktouch.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2000,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2000,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -38,7 +39,7 @@
  */
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_slktouch.c,v 1.8 2009/10/24 22:12:21 tom Exp $")
+MODULE_ID("$Id: lib_slktouch.c,v 1.9 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(slk_touch) (NCURSES_SP_DCL0)
diff --git a/ncurses/base/lib_touch.c b/ncurses/base/lib_touch.c
index 20ac945..d8d59e1 100644
--- a/ncurses/base/lib_touch.c
+++ b/ncurses/base/lib_touch.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2010,2012 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -43,16 +44,19 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_touch.c,v 1.12 2012/06/09 20:29:33 tom Exp $")
+MODULE_ID("$Id: lib_touch.c,v 1.16 2020/02/02 23:34:34 tom Exp $")
+
+#undef is_linetouched
 
 NCURSES_EXPORT(bool)
 is_linetouched(WINDOW *win, int line)
 {
     T((T_CALLED("is_linetouched(%p,%d)"), (void *) win, line));
 
-    /* XSI doesn't define any error */
-    if (!win || (line > win->_maxy) || (line < 0))
-	returnCode((bool) ERR);
+    /* XSI doesn't define any error, and gcc ultimately made it impossible */
+    if (!win || (line > win->_maxy) || (line < 0)) {
+	returnCode(FALSE);
+    }
 
     returnCode(win->_line[line].firstchar != _NOCHANGE ? TRUE : FALSE);
 }
@@ -60,14 +64,15 @@
 NCURSES_EXPORT(bool)
 is_wintouched(WINDOW *win)
 {
-    int i;
-
     T((T_CALLED("is_wintouched(%p)"), (void *) win));
 
-    if (win)
+    if (win) {
+	int i;
+
 	for (i = 0; i <= win->_maxy; i++)
 	    if (win->_line[i].firstchar != _NOCHANGE)
 		returnCode(TRUE);
+    }
     returnCode(FALSE);
 }
 
diff --git a/ncurses/base/lib_ungetch.c b/ncurses/base/lib_ungetch.c
index 4ee9119..fcbe6f4 100644
--- a/ncurses/base/lib_ungetch.c
+++ b/ncurses/base/lib_ungetch.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2011,2012 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2011,2012 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -42,7 +43,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_ungetch.c,v 1.16 2012/08/04 17:38:53 tom Exp $")
+MODULE_ID("$Id: lib_ungetch.c,v 1.17 2020/02/02 23:34:34 tom Exp $")
 
 #include <fifo_defs.h>
 
diff --git a/ncurses/base/lib_vline.c b/ncurses/base/lib_vline.c
index 2f3148e..ae4af62 100644
--- a/ncurses/base/lib_vline.c
+++ b/ncurses/base/lib_vline.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -29,6 +30,8 @@
 /****************************************************************************
  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
+ *     and: Thomas E. Dickey                        1996-on                 *
+ *     and: Sven Verdoolaege                        2001                    *
  ****************************************************************************/
 
 /*
@@ -40,22 +43,21 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_vline.c,v 1.12 2010/12/19 01:22:58 tom Exp $")
+MODULE_ID("$Id: lib_vline.c,v 1.15 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 wvline(WINDOW *win, chtype ch, int n)
 {
     int code = ERR;
-    int row, col;
-    int end;
 
     T((T_CALLED("wvline(%p,%s,%d)"), (void *) win, _tracechtype(ch), n));
 
     if (win) {
 	NCURSES_CH_T wch;
-	row = win->_cury;
-	col = win->_curx;
-	end = row + n - 1;
+	int row = win->_cury;
+	int col = win->_curx;
+	int end = row + n - 1;
+
 	if (end > win->_maxy)
 	    end = win->_maxy;
 
@@ -67,6 +69,14 @@
 
 	while (end >= row) {
 	    struct ldat *line = &(win->_line[end]);
+#if USE_WIDEC_SUPPORT
+	    if (col > 0 && isWidecExt(line->text[col])) {
+		SetChar2(line->text[col - 1], ' ');
+	    }
+	    if (col < win->_maxx && isWidecExt(line->text[col + 1])) {
+		SetChar2(line->text[col + 1], ' ');
+	    }
+#endif
 	    line->text[col] = wch;
 	    CHANGED_CELL(line, col);
 	    end--;
diff --git a/ncurses/base/lib_wattroff.c b/ncurses/base/lib_wattroff.c
index fff0b39..eac07f0 100644
--- a/ncurses/base/lib_wattroff.c
+++ b/ncurses/base/lib_wattroff.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2006,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2006,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -42,7 +43,7 @@
 #include <curses.priv.h>
 #include <ctype.h>
 
-MODULE_ID("$Id: lib_wattroff.c,v 1.10 2009/10/24 22:36:08 tom Exp $")
+MODULE_ID("$Id: lib_wattroff.c,v 1.11 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 wattr_off(WINDOW *win, attr_t at, void *opts GCC_UNUSED)
diff --git a/ncurses/base/lib_wattron.c b/ncurses/base/lib_wattron.c
index 3806285..906021d 100644
--- a/ncurses/base/lib_wattron.c
+++ b/ncurses/base/lib_wattron.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright 2020,2022 Thomas E. Dickey                                     *
+ * Copyright 1998-2009,2010 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -42,7 +43,7 @@
 #include <curses.priv.h>
 #include <ctype.h>
 
-MODULE_ID("$Id: lib_wattron.c,v 1.11 2010/03/31 23:38:02 tom Exp $")
+MODULE_ID("$Id: lib_wattron.c,v 1.13 2022/04/15 22:34:38 tom Exp $")
 
 NCURSES_EXPORT(int)
 wattr_on(WINDOW *win, attr_t at, void *opts GCC_UNUSED)
@@ -54,8 +55,10 @@
 	   GET_WINDOW_PAIR(win)));
 
 	if_EXT_COLORS({
-	    if (at & A_COLOR)
+	    if (at & A_COLOR) {
 		win->_color = PairNumber(at);
+		set_extended_pair(opts, win->_color);
+	    }
 	});
 	toggle_attr_on(WINDOW_ATTRS(win), at);
 	returnCode(OK);
diff --git a/ncurses/base/lib_winch.c b/ncurses/base/lib_winch.c
index 7e75f85..91253d1 100644
--- a/ncurses/base/lib_winch.c
+++ b/ncurses/base/lib_winch.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2009,2010 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -39,7 +40,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_winch.c,v 1.8 2010/12/19 01:22:58 tom Exp $")
+MODULE_ID("$Id: lib_winch.c,v 1.9 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(chtype)
 winch(WINDOW *win)
diff --git a/ncurses/base/lib_window.c b/ncurses/base/lib_window.c
index 4baa369..5323fbf 100644
--- a/ncurses/base/lib_window.c
+++ b/ncurses/base/lib_window.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright 2020,2021 Thomas E. Dickey                                     *
+ * Copyright 1998-2010,2016 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -39,7 +40,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_window.c,v 1.29 2010/12/19 01:47:22 tom Exp $")
+MODULE_ID("$Id: lib_window.c,v 1.32 2021/10/23 23:06:24 tom Exp $")
 
 NCURSES_EXPORT(void)
 _nc_synchook(WINDOW *win)
@@ -56,7 +57,6 @@
 /* move a derived window */
 {
     WINDOW *orig;
-    int i;
     int rc = ERR;
 
     T((T_CALLED("mvderwin(%p,%d,%d)"), (void *) win, y, x));
@@ -66,6 +66,8 @@
 	&& (x >= 0 && y >= 0)
 	&& (x + getmaxx(win) <= getmaxx(orig))
 	&& (y + getmaxy(win) <= getmaxy(orig))) {
+	int i;
+
 	wsyncup(win);
 	win->_parx = x;
 	win->_pary = y;
@@ -128,7 +130,7 @@
 {
     T((T_CALLED("wsyncdown(%p)"), (void *) win));
 
-    if (win && win->_parent) {
+    if (win != NULL && win->_parent != NULL) {
 	WINDOW *pp = win->_parent;
 	int y;
 
@@ -177,8 +179,6 @@
 /* make an exact duplicate of the given window */
 {
     WINDOW *nwin = 0;
-    size_t linesize;
-    int i;
 
     T((T_CALLED("dupwin(%p)"), (void *) win));
 
@@ -187,7 +187,7 @@
 	SCREEN *sp = _nc_screen_of(win);
 #endif
 	_nc_lock_global(curses);
-	if (win->_flags & _ISPAD) {
+	if (IS_PAD(win)) {
 	    nwin = NCURSES_SP_NAME(newpad) (NCURSES_SP_ARGx
 					    win->_maxy + 1,
 					    win->_maxx + 1);
@@ -200,6 +200,8 @@
 	}
 
 	if (nwin != 0) {
+	    int i;
+	    size_t linesize;
 
 	    nwin->_curx = win->_curx;
 	    nwin->_cury = win->_cury;
@@ -236,7 +238,7 @@
 	    nwin->_regtop = win->_regtop;
 	    nwin->_regbottom = win->_regbottom;
 
-	    if (win->_flags & _ISPAD)
+	    if (IS_PAD(win))
 		nwin->_pad = win->_pad;
 
 	    linesize = (unsigned) (win->_maxx + 1) * sizeof(NCURSES_CH_T);
diff --git a/ncurses/base/nc_panel.c b/ncurses/base/nc_panel.c
index 69b10bc..002f118 100644
--- a/ncurses/base/nc_panel.c
+++ b/ncurses/base/nc_panel.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2000,2009 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2000,2009 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -32,7 +33,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: nc_panel.c,v 1.5 2009/04/11 21:05:10 tom Exp $")
+MODULE_ID("$Id: nc_panel.c,v 1.6 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(struct panelhook *)
 NCURSES_SP_NAME(_nc_panelhook) (NCURSES_SP_DCL0)
diff --git a/ncurses/base/new_pair.c b/ncurses/base/new_pair.c
new file mode 100644
index 0000000..70866c6
--- /dev/null
+++ b/ncurses/base/new_pair.c
@@ -0,0 +1,393 @@
+/****************************************************************************
+ * Copyright 2018-2020,2021 Thomas E. Dickey                                *
+ * Copyright 2017 Free Software Foundation, Inc.                            *
+ *                                                                          *
+ * 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, distribute with modifications, 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 COPYRIGHT HOLDERS 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.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *  Author: Thomas E. Dickey                                                *
+ ****************************************************************************/
+
+/* new_pair.c
+ *
+ * New color-pair functions, alloc_pair and free_pair
+ */
+
+#define NEW_PAIR_INTERNAL 1
+#include <curses.priv.h>
+
+#ifndef CUR
+#define CUR SP_TERMTYPE
+#endif
+
+#ifdef USE_TERM_DRIVER
+#define MaxColors      InfoOf(SP_PARM).maxcolors
+#else
+#define MaxColors      max_colors
+#endif
+
+#if NCURSES_EXT_COLORS
+
+/* fix redefinition versys tic.h */
+#undef entry
+#define entry my_entry
+#undef ENTRY
+#define ENTRY my_ENTRY
+
+#include <search.h>
+
+#endif
+
+MODULE_ID("$Id: new_pair.c,v 1.23 2021/08/16 22:11:26 tom Exp $")
+
+#if NCURSES_EXT_COLORS
+
+#ifdef NEW_PAIR_DEBUG
+
+static int
+prev_len(SCREEN *sp, int pair)
+{
+    int result = 1;
+    int base = pair;
+    colorpair_t *list = sp->_color_pairs;
+    while (list[pair].prev != base) {
+	result++;
+	pair = list[pair].prev;
+    }
+    return result;
+}
+
+static int
+next_len(SCREEN *sp, int pair)
+{
+    int result = 1;
+    int base = pair;
+    colorpair_t *list = sp->_color_pairs;
+    while (list[pair].next != base) {
+	result++;
+	pair = list[pair].next;
+    }
+    return result;
+}
+
+/*
+ * Trace the contents of LRU color-pairs.
+ */
+static void
+dumpit(SCREEN *sp, int pair, const char *tag)
+{
+    colorpair_t *list = sp->_color_pairs;
+    char bigbuf[256 * 20];
+    char *p = bigbuf;
+    int n;
+    size_t have = sizeof(bigbuf);
+
+    _nc_STRCPY(p, tag, have);
+    for (n = 0; n < sp->_pair_alloc; ++n) {
+	if (list[n].mode != cpFREE) {
+	    p += strlen(p);
+	    if ((size_t) (p - bigbuf) + 50 > have)
+		break;
+	    _nc_SPRINTF(p, _nc_SLIMIT(have - (p - bigbuf))
+			" %d%c(%d,%d)",
+			n, n == pair ? '@' : ':', list[n].next, list[n].prev);
+	}
+    }
+    T(("(%d/%d) %ld - %s",
+       next_len(sp, 0),
+       prev_len(sp, 0),
+       strlen(bigbuf), bigbuf));
+
+    if (next_len(sp, 0) != prev_len(sp, 0)) {
+	endwin();
+	ExitProgram(EXIT_FAILURE);
+    }
+}
+#else
+#define dumpit(sp, pair, tag)	/* nothing */
+#endif
+
+static int
+compare_data(const void *a, const void *b)
+{
+    const colorpair_t *p = (const colorpair_t *) a;
+    const colorpair_t *q = (const colorpair_t *) b;
+    return ((p->fg == q->fg)
+	    ? (p->bg - q->bg)
+	    : (p->fg - q->fg));
+}
+
+static int
+_nc_find_color_pair(SCREEN *sp, int fg, int bg)
+{
+    colorpair_t find;
+    int result = -1;
+
+    find.fg = fg;
+    find.bg = bg;
+    if (sp != 0) {
+	void *pp;
+	if ((pp = tfind(&find, &sp->_ordered_pairs, compare_data)) != 0) {
+	    colorpair_t *temp = *(colorpair_t **) pp;
+	    result = (int) (temp - sp->_color_pairs);
+	}
+    }
+    return result;
+}
+
+static void
+delink_color_pair(SCREEN *sp, int pair)
+{
+    colorpair_t *list = sp->_color_pairs;
+    int prev = list[pair].prev;
+    int next = list[pair].next;
+
+    /* delink this from its current location */
+    if (list[prev].next == pair &&
+	list[next].prev == pair) {
+	list[prev].next = next;
+	list[next].prev = prev;
+	dumpit(sp, pair, "delinked");
+    }
+}
+
+/*
+ * Discard all nodes in the fast-index.
+ */
+NCURSES_EXPORT(void)
+_nc_free_ordered_pairs(SCREEN *sp)
+{
+    if (sp && sp->_ordered_pairs && sp->_pair_alloc) {
+	int n;
+	for (n = 0; n < sp->_pair_alloc; ++n) {
+	    tdelete(&sp->_color_pairs[n], &sp->_ordered_pairs, compare_data);
+	}
+    }
+}
+
+/*
+ * Use this call to update the fast-index when modifying an entry in the color
+ * pair table.
+ */
+NCURSES_EXPORT(void)
+_nc_reset_color_pair(SCREEN *sp, int pair, colorpair_t * next)
+{
+    colorpair_t *last;
+
+    if (ValidPair(sp, pair)) {
+	bool used;
+
+	ReservePairs(sp, pair);
+	last = &(sp->_color_pairs[pair]);
+	delink_color_pair(sp, pair);
+	if (last->mode > cpFREE &&
+	    (last->fg != next->fg || last->bg != next->bg)) {
+	    /* remove the old entry from fast index */
+	    tdelete(last, &sp->_ordered_pairs, compare_data);
+	    used = FALSE;
+	} else {
+	    used = (last->mode != cpFREE);
+	}
+	if (!used) {
+	    /* create a new entry in fast index */
+	    *last = *next;
+	    tsearch(last, &sp->_ordered_pairs, compare_data);
+	}
+    }
+}
+
+/*
+ * Use this call to relink the newest pair to the front of the list, keeping
+ * "0" first.
+ */
+NCURSES_EXPORT(void)
+_nc_set_color_pair(SCREEN *sp, int pair, int mode)
+{
+    if (ValidPair(sp, pair)) {
+	colorpair_t *list = sp->_color_pairs;
+	dumpit(sp, pair, "SET_PAIR");
+	list[0].mode = cpKEEP;
+	if (list[pair].mode <= cpFREE)
+	    sp->_pairs_used++;
+	list[pair].mode = mode;
+	if (list[0].next != pair) {
+	    /* link it at the front of the list */
+	    list[pair].next = list[0].next;
+	    list[list[pair].next].prev = pair;
+	    list[pair].prev = 0;
+	    list[0].next = pair;
+	}
+	dumpit(sp, pair, "...after");
+    }
+}
+
+/*
+ * If we reallocate the color-pair array, we have to adjust the fast-index.
+ */
+NCURSES_EXPORT(void)
+_nc_copy_pairs(SCREEN *sp, colorpair_t * target, colorpair_t * source, int length)
+{
+    int n;
+    for (n = 0; n < length; ++n) {
+	void *find = tfind(source + n, &sp->_ordered_pairs, compare_data);
+	if (find != 0) {
+	    tdelete(source + n, &sp->_ordered_pairs, compare_data);
+	    tsearch(target + n, &sp->_ordered_pairs, compare_data);
+	}
+    }
+}
+
+NCURSES_EXPORT(int)
+NCURSES_SP_NAME(alloc_pair) (NCURSES_SP_DCLx int fg, int bg)
+{
+    int pair;
+
+    T((T_CALLED("alloc_pair(%d,%d)"), fg, bg));
+    if (SP_PARM == 0) {
+	pair = -1;
+    } else if ((pair = _nc_find_color_pair(SP_PARM, fg, bg)) < 0) {
+	/*
+	 * Check if all of the slots have been used.  If not, find one and
+	 * use that.
+	 */
+	if (SP_PARM->_pairs_used + 1 < SP_PARM->_pair_limit) {
+	    bool found = FALSE;
+	    int hint = SP_PARM->_recent_pair;
+
+	    /*
+	     * The linear search is done to allow mixing calls to init_pair()
+	     * and alloc_pair().  The former can make gaps...
+	     */
+	    for (pair = hint + 1; pair < SP_PARM->_pair_alloc; pair++) {
+		if (SP_PARM->_color_pairs[pair].mode == cpFREE) {
+		    T(("found gap %d", pair));
+		    found = TRUE;
+		    break;
+		}
+	    }
+	    if (!found && (SP_PARM->_pair_alloc < SP_PARM->_pair_limit)) {
+		pair = SP_PARM->_pair_alloc;
+		ReservePairs(SP_PARM, pair);
+		if (SP_PARM->_color_pairs == 0) {
+		    pair = -1;
+		} else {
+		    found = TRUE;
+		}
+	    }
+	    if (!found && SP_PARM->_color_pairs != NULL) {
+		for (pair = 1; pair <= hint; pair++) {
+		    if (SP_PARM->_color_pairs[pair].mode == cpFREE) {
+			T(("found gap %d", pair));
+			found = TRUE;
+			break;
+		    }
+		}
+	    }
+	    if (found) {
+		SP_PARM->_recent_pair = pair;
+	    } else {
+		pair = ERR;
+	    }
+	} else {
+	    /* reuse the oldest one */
+	    pair = SP_PARM->_color_pairs[0].prev;
+	    T(("reusing %d", pair));
+	}
+
+	if (_nc_init_pair(SP_PARM, pair, fg, bg) == ERR)
+	    pair = ERR;
+    }
+    returnCode(pair);
+}
+
+NCURSES_EXPORT(int)
+NCURSES_SP_NAME(find_pair) (NCURSES_SP_DCLx int fg, int bg)
+{
+    int pair;
+
+    T((T_CALLED("find_pair(%d,%d)"), fg, bg));
+    pair = _nc_find_color_pair(SP_PARM, fg, bg);
+    returnCode(pair);
+}
+
+NCURSES_EXPORT(int)
+NCURSES_SP_NAME(free_pair) (NCURSES_SP_DCLx int pair)
+{
+    int result = ERR;
+    T((T_CALLED("free_pair(%d)"), pair));
+    if (ValidPair(SP_PARM, pair) && pair < SP_PARM->_pair_alloc) {
+	colorpair_t *cp = &(SP_PARM->_color_pairs[pair]);
+	if (pair != 0) {
+	    _nc_change_pair(SP_PARM, pair);
+	    delink_color_pair(SP_PARM, pair);
+	    tdelete(cp, &SP_PARM->_ordered_pairs, compare_data);
+	    cp->mode = cpFREE;
+	    result = OK;
+	    SP_PARM->_pairs_used--;
+	}
+    }
+    returnCode(result);
+}
+
+#if NCURSES_SP_FUNCS
+NCURSES_EXPORT(int)
+alloc_pair(int f, int b)
+{
+    return NCURSES_SP_NAME(alloc_pair) (CURRENT_SCREEN, f, b);
+}
+
+NCURSES_EXPORT(int)
+find_pair(int f, int b)
+{
+    return NCURSES_SP_NAME(find_pair) (CURRENT_SCREEN, f, b);
+}
+
+NCURSES_EXPORT(int)
+free_pair(int pair)
+{
+    return NCURSES_SP_NAME(free_pair) (CURRENT_SCREEN, pair);
+}
+#endif
+
+#if NO_LEAKS
+NCURSES_EXPORT(void)
+_nc_new_pair_leaks(SCREEN *sp)
+{
+    if (sp->_color_pairs) {
+	while (sp->_color_pairs[0].next) {
+	    free_pair(sp->_color_pairs[0].next);
+	}
+    }
+}
+#endif
+
+#else
+void _nc_new_pair(void);
+void
+_nc_new_pair(void)
+{
+}
+#endif /* NCURSES_EXT_COLORS */
diff --git a/ncurses/base/resizeterm.c b/ncurses/base/resizeterm.c
index 1eca279..1a2ddb3 100644
--- a/ncurses/base/resizeterm.c
+++ b/ncurses/base/resizeterm.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2011,2014 Free Software Foundation, Inc.              *
+ * Copyright 2020-2021,2024 Thomas E. Dickey                                *
+ * Copyright 1998-2015,2016 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -45,7 +46,7 @@
 #define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: resizeterm.c,v 1.47 2014/10/13 08:56:49 tom Exp $")
+MODULE_ID("$Id: resizeterm.c,v 1.53 2024/04/20 21:54:14 tom Exp $")
 
 /*
  * If we're trying to be reentrant, do not want any local statics.
@@ -62,6 +63,12 @@
 #define EXTRA_DCLS		/* nothing */
 #endif
 
+#if NCURSES_SP_FUNCS && !defined(USE_SP_WINDOWLIST)
+#define UNUSED_SP  (void) sp
+#else
+#define UNUSED_SP		/* nothing */
+#endif
+
 #ifdef TRACE
 static void
 show_window_sizes(const char *name)
@@ -140,9 +147,10 @@
 ripped_bottom(WINDOW *win)
 {
     int result = 0;
-    ripoff_t *rop;
 
     if (win != 0) {
+	ripoff_t *rop;
+
 #ifdef USE_SP_RIPOFF
 	SCREEN *sp = _nc_screen_of(win);
 #endif
@@ -202,7 +210,7 @@
 }
 
 /*
- * FIXME: must adjust position so it's within the parent!
+ * FIXME: must adjust position so it is within the parent!
  */
 static int
 adjust_window(WINDOW *win, int ToLines, int ToCols, int stolen EXTRA_DCLS)
@@ -276,6 +284,7 @@
     WINDOWLIST *wp;
 
     T((T_CALLED("decrease_size(%p, %d, %d)"), (void *) SP_PARM, ToLines, ToCols));
+    UNUSED_SP;
 
     do {
 	found = FALSE;
@@ -284,7 +293,7 @@
 	for (each_window(SP_PARM, wp)) {
 	    WINDOW *win = &(wp->win);
 
-	    if (!(win->_flags & _ISPAD)) {
+	    if (!IS_PAD(win)) {
 		if (child_depth(win) == depth) {
 		    found = TRUE;
 		    if (adjust_window(win, ToLines, ToCols,
@@ -310,6 +319,7 @@
     WINDOWLIST *wp;
 
     T((T_CALLED("increase_size(%p, %d, %d)"), (void *) SP_PARM, ToLines, ToCols));
+    UNUSED_SP;
 
     do {
 	found = FALSE;
@@ -318,7 +328,7 @@
 	for (each_window(SP_PARM, wp)) {
 	    WINDOW *win = &(wp->win);
 
-	    if (!(win->_flags & _ISPAD)) {
+	    if (!IS_PAD(win)) {
 		if (parent_depth(win) == depth) {
 		    found = TRUE;
 		    if (adjust_window(win, ToLines, ToCols,
@@ -399,8 +409,8 @@
 #ifdef USE_TERM_DRIVER
 	    CallDriver_2(SP_PARM, td_setsize, ToLines, ToCols);
 #else
-	    lines = (NCURSES_SIZE_T) ToLines;
-	    columns = (NCURSES_SIZE_T) ToCols;
+	    lines = (NCURSES_INT2) ToLines;
+	    columns = (NCURSES_INT2) ToCols;
 #endif
 
 	    SP_PARM->_lines_avail = (NCURSES_SIZE_T) (ToLines - was_stolen);
@@ -440,7 +450,7 @@
 NCURSES_EXPORT(int)
 resize_term(int ToLines, int ToCols)
 {
-    int res = ERR;
+    int res;
     _nc_sp_lock_global(curses);
     res = NCURSES_SP_NAME(resize_term) (CURRENT_SCREEN, ToLines, ToCols);
     _nc_sp_unlock_global(curses);
diff --git a/ncurses/base/safe_sprintf.c b/ncurses/base/safe_sprintf.c
index 34abd2f..8816e58 100644
--- a/ncurses/base/safe_sprintf.c
+++ b/ncurses/base/safe_sprintf.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc.              *
+ * Copyright 2018-2021,2023 Thomas E. Dickey                                *
+ * Copyright 1998-2012,2013 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -33,7 +34,7 @@
 #include <curses.priv.h>
 #include <ctype.h>
 
-MODULE_ID("$Id: safe_sprintf.c,v 1.27 2013/01/20 01:04:32 tom Exp $")
+MODULE_ID("$Id: safe_sprintf.c,v 1.37 2023/09/30 10:42:42 tom Exp $")
 
 #if USE_SAFE_SPRINTF
 
@@ -41,7 +42,7 @@
     Flags, Width, Prec, Type, Format
 } PRINTF;
 
-#define VA_INTGR(type) ival = va_arg(ap, type)
+#define VA_INTGR(type) ival = (int) va_arg(ap, type)
 #define VA_FLOAT(type) fval = va_arg(ap, type)
 #define VA_POINT(type) pval = (void *)va_arg(ap, type)
 
@@ -157,9 +158,9 @@
 		    case 's':
 			VA_POINT(char *);
 			if (prec < 0)
-			    prec = strlen(pval);
+			    prec = (int) strlen(pval);
 			if (prec > (int) length) {
-			    length = length + prec;
+			    length = length + (size_t) prec;
 			    buffer = typeRealloc(char, length, buffer);
 			    if (buffer == 0) {
 				free(format);
@@ -222,9 +223,9 @@
 				    const char *fmt,
 				    va_list ap)
 {
-    char *result = 0;
+    char *result = NULL;
 
-    if (fmt != 0) {
+    if (SP_PARM != NULL && fmt != NULL) {
 #if USE_SAFE_SPRINTF
 	va_list ap2;
 	int len;
@@ -234,10 +235,10 @@
 	end_va_copy(ap2);
 
 	if ((int) my_length < len + 1) {
-	    my_length = 2 * (len + 1);
+	    my_length = (size_t) (2 * (len + 1));
 	    my_buffer = typeRealloc(char, my_length, my_buffer);
 	}
-	if (my_buffer != 0) {
+	if (my_buffer != NULL) {
 	    *my_buffer = '\0';
 	    if (len >= 0) {
 		vsprintf(my_buffer, fmt, ap);
@@ -254,21 +255,37 @@
 	    if (screen_columns(SP_PARM) > MyCols)
 		MyCols = screen_columns(SP_PARM);
 	    my_length = (size_t) (MyRows * (MyCols + 1)) + 1;
+	    if (my_length < 80)
+		my_length = 80;
 	    my_buffer = typeRealloc(char, my_length, my_buffer);
 	}
 
-	if (my_buffer != 0) {
+	if (my_buffer != NULL) {
 # if HAVE_VSNPRINTF
-	    vsnprintf(my_buffer, my_length, fmt, ap);	/* GNU extension */
+	    /* SUSv2, 1997 */
+	    int used;
+
+	    do {
+		va_list ap2;
+
+		begin_va_copy(ap2, ap);
+		used = vsnprintf(my_buffer, my_length, fmt, ap2);
+		end_va_copy(ap2);
+		if (used < (int) my_length)
+		    break;
+		my_length = (size_t) ((3 * used) / 2);
+		my_buffer = typeRealloc(char, my_length, my_buffer);
+	    } while (my_buffer != NULL);
 # else
-	    vsprintf(my_buffer, fmt, ap);	/* ANSI */
+	    /* ISO/ANSI C, 1989 */
+	    vsprintf(my_buffer, fmt, ap);
 # endif
 	    result = my_buffer;
 	}
 #endif
-    } else if (my_buffer != 0) {	/* see _nc_freeall() */
+    } else if (my_buffer != NULL) {	/* see _nc_freeall() */
 	free(my_buffer);
-	my_buffer = 0;
+	my_buffer = NULL;
 	my_length = 0;
     }
     return result;
diff --git a/ncurses/base/sigaction.c b/ncurses/base/sigaction.c
index 36442e0..9688c69 100644
--- a/ncurses/base/sigaction.c
+++ b/ncurses/base/sigaction.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2002,2003 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1998-2002,2003 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -35,7 +36,7 @@
 /* This file provides sigaction() emulation using sigvec() */
 /* Use only if this is non POSIX system */
 
-MODULE_ID("$Id: sigaction.c,v 1.14 2003/12/07 01:06:52 tom Exp $")
+MODULE_ID("$Id: sigaction.c,v 1.15 2020/02/02 23:34:34 tom Exp $")
 
 static int
 _nc_sigaction(int sig, sigaction_t * sigact, sigaction_t * osigact)
diff --git a/ncurses/base/tries.c b/ncurses/base/tries.c
index ad85d22..0f8c051 100644
--- a/ncurses/base/tries.c
+++ b/ncurses/base/tries.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ * Copyright 2020,2023 Thomas E. Dickey                                     *
+ * Copyright 1998-2009,2010 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -38,8 +39,9 @@
 */
 
 #include <curses.priv.h>
+#include <tic.h>
 
-MODULE_ID("$Id: tries.c,v 1.30 2010/08/28 21:08:23 tom Exp $")
+MODULE_ID("$Id: tries.c,v 1.32 2023/06/24 15:36:23 tom Exp $")
 
 /*
  * Expand a keycode into the string that it corresponds to, returning null if
@@ -123,7 +125,7 @@
 {
     T((T_CALLED("_nc_remove_string(%p,%s)"), (void *) tree, _nc_visbuf(string)));
 
-    if (string == 0 || *string == 0)
+    if (!VALID_STRING(string) || *string == 0)
 	returnCode(FALSE);
 
     while (*tree != 0) {
diff --git a/ncurses/base/use_window.c b/ncurses/base/use_window.c
index 8eb7339..4893053 100644
--- a/ncurses/base/use_window.c
+++ b/ncurses/base/use_window.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 2007-2008,2009 Free Software Foundation, Inc.              *
+ * Copyright 2018,2020 Thomas E. Dickey                                     *
+ * Copyright 2007-2009,2016 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -32,14 +33,19 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: use_window.c,v 1.9 2009/10/24 22:40:24 tom Exp $")
+MODULE_ID("$Id: use_window.c,v 1.13 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(int)
 use_window(WINDOW *win, NCURSES_WINDOW_CB func, void *data)
 {
     int code = OK;
+    TR_FUNC_BFR(1);
 
-    T((T_CALLED("use_window(%p,%p,%p)"), (void *) win, func, data));
+    T((T_CALLED("use_window(%p,%s,%p)"),
+       (void *) win,
+       TR_FUNC_ARG(0, func),
+       data));
+
     _nc_lock_global(curses);
     code = func(win, data);
     _nc_unlock_global(curses);
diff --git a/ncurses/base/version.c b/ncurses/base/version.c
index ef83967..4d8ee81 100644
--- a/ncurses/base/version.c
+++ b/ncurses/base/version.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1999-2004,2005 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 1999-2004,2005 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -32,7 +33,7 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: version.c,v 1.6 2005/01/02 01:23:54 tom Exp $")
+MODULE_ID("$Id: version.c,v 1.7 2020/02/02 23:34:34 tom Exp $")
 
 NCURSES_EXPORT(const char *)
 curses_version(void)
diff --git a/ncurses/base/vsscanf.c b/ncurses/base/vsscanf.c
index 38c7926..40ee8bb 100644
--- a/ncurses/base/vsscanf.c
+++ b/ncurses/base/vsscanf.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2004,2012 Free Software Foundation, Inc.              *
+ * Copyright 2020,2023 Thomas E. Dickey                                     *
+ * Copyright 1998-2004,2012 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -38,15 +39,12 @@
 
 #if !HAVE_VSSCANF
 
-MODULE_ID("$Id: vsscanf.c,v 1.20 2012/02/22 22:26:58 tom Exp $")
+MODULE_ID("$Id: vsscanf.c,v 1.22 2023/09/23 18:48:57 tom Exp $")
 
 #if !(HAVE_VFSCANF || HAVE__DOSCAN)
 
 #include <ctype.h>
 
-#define L_SQUARE '['
-#define R_SQUARE ']'
-
 typedef enum {
     cUnknown
     ,cError			/* anything that isn't ANSI */
@@ -242,7 +240,7 @@
 		    case sPercent:
 			if (format[n] == '%') {
 			    state = sUnknown;
-			} else if (format[n] == L_SQUARE) {
+			} else if (format[n] == L_BLOCK) {
 			    state = sLeft;
 			} else {
 			    state = sNormal;
@@ -257,7 +255,7 @@
 			}
 			break;
 		    case sRange:
-			if (format[n] == R_SQUARE) {
+			if (format[n] == R_BLOCK) {
 			    state = sFinal;
 			    chunk = cRange;
 			}
diff --git a/ncurses/base/wresize.c b/ncurses/base/wresize.c
index bc6b573..6d5589e 100644
--- a/ncurses/base/wresize.c
+++ b/ncurses/base/wresize.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc.              *
+ * Copyright 2019-2021,2023 Thomas E. Dickey                                *
+ * Copyright 1998-2010,2011 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -33,13 +34,13 @@
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: wresize.c,v 1.35 2011/05/21 18:55:07 tom Exp $")
+MODULE_ID("$Id: wresize.c,v 1.43 2023/10/21 11:13:03 tom Exp $")
 
 static int
 cleanup_lines(struct ldat *data, int length)
 {
     while (--length >= 0)
-	free(data[length].text);
+	FreeAndNull(data[length].text);
     free(data);
     return ERR;
 }
@@ -54,7 +55,7 @@
     WINDOWLIST *wp;
     struct ldat *pline = cmp->_line;
     int row;
-#ifdef USE_SP_WINDOWLIST
+#if NCURSES_SP_FUNCS && defined(USE_SP_WINDOWLIST)
     SCREEN *sp = _nc_screen_of(cmp);
 #endif
 
@@ -65,15 +66,29 @@
 
 	if (tst->_parent == cmp) {
 
-	    if (tst->_pary > cmp->_maxy)
-		tst->_pary = cmp->_maxy;
-	    if (tst->_parx > cmp->_maxx)
-		tst->_parx = cmp->_maxx;
+#define REPAIR1(field, limit) \
+	    if (tst->field > cmp->limit) \
+		tst->field = cmp->limit
 
-	    if (tst->_maxy + tst->_pary > cmp->_maxy)
-		tst->_maxy = (NCURSES_SIZE_T) (cmp->_maxy - tst->_pary);
-	    if (tst->_maxx + tst->_parx > cmp->_maxx)
-		tst->_maxx = (NCURSES_SIZE_T) (cmp->_maxx - tst->_parx);
+	    REPAIR1(_pary, _maxy);
+	    REPAIR1(_parx, _maxx);
+
+#define REPAIR2(field, limit) \
+	    if (tst->limit + tst->field > cmp->limit) \
+		tst->limit = (NCURSES_SIZE_T) (cmp->limit - tst->field)
+
+	    REPAIR2(_pary, _maxy);
+	    REPAIR2(_parx, _maxx);
+
+#define REPAIR3(field, limit) \
+	    if (tst->field > tst->limit) \
+		tst->field = tst->limit
+
+	    REPAIR3(_cury, _maxy);
+	    REPAIR3(_curx, _maxx);
+
+	    REPAIR3(_regtop, _maxy);
+	    REPAIR3(_regbottom, _maxy);
 
 	    for (row = 0; row <= tst->_maxy; ++row) {
 		tst->_line[row].text = &pline[tst->_pary + row].text[tst->_parx];
@@ -120,7 +135,7 @@
 	&& ToCols == size_x)
 	returnCode(OK);
 
-    if ((win->_flags & _SUBWIN)) {
+    if (IS_SUBWIN(win)) {
 	/*
 	 * Check if the new limits will fit into the parent window's size.  If
 	 * not, do not resize.  We could adjust the location of the subwindow,
@@ -154,14 +169,22 @@
 	int end = ToCols;
 	NCURSES_CH_T *s;
 
-	if (!(win->_flags & _SUBWIN)) {
+	if (!IS_SUBWIN(win)) {
 	    if (row <= size_y) {
 		if (ToCols != size_x) {
 		    s = typeMalloc(NCURSES_CH_T, (unsigned) ToCols + 1);
 		    if (s == 0)
 			returnCode(cleanup_lines(new_lines, row));
 		    for (col = 0; col <= ToCols; ++col) {
-			s[col] = (col <= size_x
+			bool valid = (col <= size_x);
+			if_WIDEC({
+			    if (col == ToCols
+				&& col < size_x
+				&& isWidecBase(win->_line[row].text[col])) {
+				valid = FALSE;
+			    }
+			});
+			s[col] = (valid
 				  ? win->_line[row].text[col]
 				  : win->_nc_bkgd);
 		    }
@@ -204,16 +227,16 @@
     if (!(win->_flags & _SUBWIN)) {
 	if (ToCols == size_x) {
 	    for (row = ToLines + 1; row <= size_y; row++) {
-		free(win->_line[row].text);
+		FreeAndNull(win->_line[row].text);
 	    }
 	} else {
 	    for (row = 0; row <= size_y; row++) {
-		free(win->_line[row].text);
+		FreeAndNull(win->_line[row].text);
 	    }
 	}
     }
 
-    free(win->_line);
+    FreeAndNull(win->_line);
     win->_line = new_lines;
 
     /*