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/progs/MKtermsort.sh b/progs/MKtermsort.sh
index 9f5db27..4e58c50 100755
--- a/progs/MKtermsort.sh
+++ b/progs/MKtermsort.sh
@@ -1,10 +1,11 @@
 #!/bin/sh
-# $Id: MKtermsort.sh,v 1.11 2015/07/04 23:59:54 tom Exp $
+# $Id: MKtermsort.sh,v 1.17 2022/02/05 20:39:41 tom Exp $
 #
 # MKtermsort.sh -- generate indirection vectors for the various sort methods
 #
 ##############################################################################
-# Copyright (c) 1998-2008,2015 Free Software Foundation, Inc.                #
+# Copyright 2020-2021,2022 Thomas E. Dickey                                  #
+# Copyright 1998-2015,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"), #
@@ -46,15 +47,26 @@
 DATA=${2-../include/Caps}
 
 data=data$$
-trap 'rm -f $data' 1 2 5 15
-sed -e 's/[	][	]*/	/g' < $DATA >$data
+trap 'rm -f $data; exit 1' 1 2 3 15
+sed -e 's/[	][	]*/	/g' < "$DATA" >$data
 DATA=$data
 
-echo "/*";
-echo " * termsort.c --- sort order arrays for use by infocmp.";
-echo " *";
-echo " * Note: this file is generated using MKtermsort.sh, do not edit by hand.";
-echo " */";
+cat <<EOF
+/*
+ * termsort.h --- sort order arrays for use by infocmp.
+ *
+ * Note: this file is generated using MKtermsort.sh, do not edit by hand.
+ */
+#ifndef _TERMSORT_H
+#define _TERMSORT_H 1
+#include <curses.h>
+
+#ifndef DUMP_ENTRY_H
+typedef unsigned PredType;
+typedef unsigned PredIdx;
+#endif
+
+EOF
 
 echo "static const PredIdx bool_terminfo_sort[] = {";
 $AWK <$DATA '
@@ -164,7 +176,11 @@
 $3 == "str" && substr($7, 1, 1) == "Y"        {print "\tTRUE,\t/* ", $2, " */"; valid = count++; }
 END { printf "#define OK_str_from_termcap %d\n", valid; }
 '
-echo "};";
-echo "";
+
+cat <<EOF
+};
+
+#endif /* _TERMSORT_H */
+EOF
 
 rm -f $data
diff --git a/progs/Makefile b/progs/Makefile
deleted file mode 100644
index d402903..0000000
--- a/progs/Makefile
+++ /dev/null
@@ -1,592 +0,0 @@
-# $Id: Makefile.in,v 1.95 2015/08/05 09:24:06 tom Exp $
-##############################################################################
-# Copyright (c) 1998-2014,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 "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 1996-on
-#
-# Makefile for ncurses source code.
-#
-# This makes the ncurses utility programs.
-#
-# The variable 'srcdir' refers to the source-distribution, and can be set with
-# the configure script by "--srcdir=DIR".
-#
-# The rules are organized to produce the libraries for the configured models,
-# and the programs with the configured default model.
-
-# turn off _all_ suffix rules; we'll generate our own
-.SUFFIXES:
-
-SHELL		= /bin/sh
-
-THIS		= Makefile
-
-CF_MFLAGS 	= 
-
-
-x		= 
-o		= .o
-
-MODEL		= ../objects
-DESTDIR		= 
-top_srcdir	= ..
-srcdir		= .
-prefix		= /system
-exec_prefix	= ${prefix}
-bindir		= ${exec_prefix}/bin
-libdir		= ${exec_prefix}/lib
-includedir	= ${prefix}/include
-datarootdir	= ${prefix}/share
-datadir		= ${datarootdir}
-includesubdir	= /ncurses
-
-INCLUDEDIR	= $(DESTDIR)$(includedir)$(includesubdir)
-
-PACKAGE		= ncurses
-
-LIBTOOL		= 
-LIBTOOL_OPTS	= 
-LIBTOOL_CLEAN	= 
-LIBTOOL_COMPILE	= 
-LIBTOOL_LINK	= ${CC}
-LIBTOOL_INSTALL	= 
-LIBTOOL_UNINSTALL = 
-
-INSTALL		= /usr/bin/install -c
-INSTALL_PROG	= ${INSTALL}
-transform	= s,x,x,
-
-AWK		= mawk
-LN_S		= ln -s -f
-
-CTAGS		= 
-ETAGS		= 
-
-CC		= /home/shade/dev/cm/13/prebuilts/clang/linux-x86/host/3.6/bin/clang
-CPP		= /home/shade/dev/cm/13/prebuilts/clang/linux-x86/host/3.6/bin/clang -E
-CFLAGS		= -target arm-linux-androideabi -I/home/shade/dev/cm/13/bionic/libc/include -I/home/shade/dev/cm/13/bionic/libc/kernel/uapi -I/home/shade/dev/cm/13/bionic/libc/arch-arm/include -I/home/shade/dev/cm/13/bionic/libc/kernel/uapi/asm-arm --sysroot=/home/shade/dev/cm/13/prebuilts/ndk/current/platforms/android-21/arch-arm -L/home/shade/dev/cm/13/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/lib/gcc/arm-linux-androideabi/4.9.x-google/armv7-a -I/home/shade/dev/cm/13/bionic/libm/include -I/home/shade/dev/cm/13/bionic/libm/include/arm -I/home/shade/dev/cm/13/external/libselinux/include -I/home/shade/dev/cm/13/system/core/include -I/home/shade/dev/cm/13/bionic/libc/dns/include -I.  --param max-inline-insns-single=1200
-
-INCDIR		= $(top_srcdir)/include
-CPPFLAGS	= -DHAVE_CONFIG_H -I. -I../include   -D_XOPEN_SOURCE=500 -D_FILE_OFFSET_BITS=64  -DNDEBUG
-
-CCFLAGS		= $(CPPFLAGS) $(CFLAGS)
-
-CFLAGS_LIBTOOL	= $(CCFLAGS)
-CFLAGS_NORMAL	= $(CCFLAGS)
-CFLAGS_DEBUG	= $(CCFLAGS) -g -DTRACE
-CFLAGS_PROFILE	= $(CCFLAGS) -pg
-CFLAGS_SHARED	= $(CCFLAGS) -fPIC
-
-CFLAGS_DEFAULT	= $(CFLAGS_NORMAL)
-
-REL_VERSION	= 6.0
-ABI_VERSION	= 6
-LOCAL_LIBDIR	= /home/shade/dev/cm/13/external/libncurses/lib
-
-LD		= arm-linux-androideabi-ld
-LINK		=  $(LIBTOOL_LINK)
-LDFLAGS		=  -L/home/shade/dev/cm/13/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/lib/gcc/arm-linux-androideabi/4.9.x-google/armv7-a -L/home/shade/dev/cm/13/out/target/product/bacon/system/lib -lc -lselinux -lcutils
-RPATH_LIST	= ${libdir}
-
-LDFLAGS_LIBTOOL	= $(LDFLAGS) $(CFLAGS_LIBTOOL)
-LDFLAGS_NORMAL	= $(LDFLAGS) $(CFLAGS_NORMAL)
-LDFLAGS_DEBUG	= $(LDFLAGS) $(CFLAGS_DEBUG)
-LDFLAGS_PROFILE	= $(LDFLAGS) $(CFLAGS_PROFILE)
-LDFLAGS_SHARED	= $(LDFLAGS) $(CFLAGS_SHARED) 
-
-LDFLAGS_DEFAULT	= $(LDFLAGS_NORMAL)
-
-LIBS_TIC	= -L../lib  -lncurses -lncurses   
-LDFLAGS_TIC	= -L../lib $(LDFLAGS_NORMAL) $(LIBS_TIC)
-
-LIBS_TINFO	=  -lncurses   
-LDFLAGS_TINFO	= -L../lib $(LDFLAGS_NORMAL) $(LIBS_TINFO)
-
-LINT		= lint
-LINT_OPTS	= 
-LINT_LIBS	= -lncurses 
-
-AUTO_SRC = \
-	termsort.c \
-	transform.h
-
-# tic relies on direct access to the terminfo database
-GET_PROGS = infocmp$x clear$x tabs$x tput$x tset$x toe$x
-PUT_PROGS =  tic$x
-PROGS = $(PUT_PROGS) $(GET_PROGS)
-
-# Default library, for linking applications
-DEPS_CURSES = ../lib/libncurses.a
-
-HEADER_DEPS	= \
-	../include/curses.h \
-	$(INCDIR)/term_entry.h \
-	$(INCDIR)/tic.h \
-	$(INCDIR)/nc_alloc.h
-
-################################################################################
-all:		$(AUTO_SRC) $(PROGS)
-
-sources:	$(AUTO_SRC)
-
-install: 	$(AUTO_SRC) install.progs
-uninstall: uninstall.progs
-
-# this line simplifies the configure-script
-libs \
-install.libs \
-uninstall.libs:
-
-TRANSFORM = sed 's/$x$$//'|sed '$(transform)'|sed 's/$$/$x/'
-
-# transformed names for installing files
-actual_captoinfo = `echo captoinfo$x| $(TRANSFORM)`
-actual_clear     = `echo clear$x|     $(TRANSFORM)`
-actual_infocmp   = `echo infocmp$x|   $(TRANSFORM)`
-actual_infotocap = `echo infotocap$x| $(TRANSFORM)`
-actual_init      = `echo init$x|      $(TRANSFORM)`
-actual_reset     = `echo reset$x|     $(TRANSFORM)`
-actual_tabs      = `echo tabs$x|      $(TRANSFORM)`
-actual_tic       = `echo tic$x|       $(TRANSFORM)`
-actual_toe       = `echo toe$x|       $(TRANSFORM)`
-actual_tput      = `echo tput$x|      $(TRANSFORM)`
-actual_tset      = `echo tset$x|      $(TRANSFORM)`
-
-# transformed names for comparing at runtime
-define_captoinfo = `echo captoinfo|   $(TRANSFORM)`
-define_infotocap = `echo infotocap|   $(TRANSFORM)`
-define_init      = `echo init|        $(TRANSFORM)`
-define_reset     = `echo reset|       $(TRANSFORM)`
-
-transform.h :
-	echo "#ifndef __TRANSFORM_H"					>$@
-	echo "#define __TRANSFORM_H 1"					>>$@
-	echo "#include <progs.priv.h>"					>>$@
-	echo "extern bool same_program(const char *, const char *);"	>>$@
-	-$(SHELL) -c 'if test -n "$x" ; then echo "#define SUFFIX_IGNORED \"$x\"">>$@; fi'
-	echo "#define PROG_CAPTOINFO \"$(define_captoinfo)\""		>>$@
-	echo "#define PROG_INFOTOCAP \"$(define_infotocap)\""		>>$@
-	echo "#define PROG_RESET     \"$(define_reset)\""		>>$@
-	echo "#define PROG_INIT      \"$(define_init)\""		>>$@
-	echo "#endif /* __TRANSFORM_H */"				>>$@
-
-install.progs: $(AUTO_SRC) $(PROGS) $(DESTDIR)$(bindir)
-	$(LIBTOOL_INSTALL) $(INSTALL_PROG) tic$x     $(DESTDIR)$(bindir)/$(actual_tic)
-	$(LIBTOOL_INSTALL) $(INSTALL_PROG) toe$x     $(DESTDIR)$(bindir)/$(actual_toe)
-	@echo "linking $(actual_infotocap) to $(actual_tic)"
-	-@rm -f $(DESTDIR)$(bindir)/$(actual_infotocap)
-	(cd $(DESTDIR)$(bindir) && $(LN_S) $(actual_tic) $(actual_infotocap))
-	@echo "linking $(actual_captoinfo) to $(actual_tic)"
-	-@rm -f $(DESTDIR)$(bindir)/$(actual_captoinfo)
-	(cd $(DESTDIR)$(bindir) && $(LN_S) $(actual_tic) $(actual_captoinfo))
-	$(LIBTOOL_INSTALL) $(INSTALL_PROG) infocmp$x $(DESTDIR)$(bindir)/$(actual_infocmp)
-	$(LIBTOOL_INSTALL) $(INSTALL_PROG) clear$x   $(DESTDIR)$(bindir)/$(actual_clear)
-	$(LIBTOOL_INSTALL) $(INSTALL_PROG) tabs$x    $(DESTDIR)$(bindir)/$(actual_tabs)
-	$(LIBTOOL_INSTALL) $(INSTALL_PROG) tput$x    $(DESTDIR)$(bindir)/$(actual_tput)
-	$(LIBTOOL_INSTALL) $(INSTALL_PROG) tset$x    $(DESTDIR)$(bindir)/$(actual_tset)
-	@echo "linking $(actual_reset) to $(actual_tset)"
-	-@rm -f $(DESTDIR)$(bindir)/$(actual_reset)
-	(cd $(DESTDIR)$(bindir) && $(LN_S) $(actual_tset) $(actual_reset))
-
-uninstall.progs:
-	-@$(LIBTOOL_CLEAN) rm -f $(DESTDIR)$(bindir)/$(actual_tic)
-	-@$(LIBTOOL_CLEAN) rm -f $(DESTDIR)$(bindir)/$(actual_toe)
-	-@rm -f $(DESTDIR)$(bindir)/$(actual_captoinfo)
-	-@rm -f $(DESTDIR)$(bindir)/$(actual_infotocap)
-	-@$(LIBTOOL_CLEAN) rm -f $(DESTDIR)$(bindir)/$(actual_infocmp)
-	-@$(LIBTOOL_CLEAN) rm -f $(DESTDIR)$(bindir)/$(actual_clear)
-	-@$(LIBTOOL_CLEAN) rm -f $(DESTDIR)$(bindir)/$(actual_tabs)
-	-@$(LIBTOOL_CLEAN) rm -f $(DESTDIR)$(bindir)/$(actual_tput)
-	-@$(LIBTOOL_CLEAN) rm -f $(DESTDIR)$(bindir)/$(actual_tset)
-	-@rm -f $(DESTDIR)$(bindir)/$(actual_reset)
-
-$(DESTDIR)$(bindir) :
-	mkdir -p $@
-
-#
-# Utilities normally built by make all start here
-#
-
-DEPS_TIC = \
-	$(MODEL)/tic$o \
-	$(MODEL)/dump_entry$o \
-	$(MODEL)/tparm_type$o \
-	$(MODEL)/transform$o
-
-tic$x: $(DEPS_TIC) $(DEPS_CURSES) transform.h
-	 $(LINK) $(DEPS_TIC) $(LDFLAGS_TIC) -o $@
-
-DEPS_TOE = \
-	$(MODEL)/toe$o
-
-toe$x: $(DEPS_TOE) $(DEPS_CURSES)
-	 $(LINK) $(DEPS_TOE) $(LDFLAGS_TIC) -o $@
-
-DEPS_CLEAR = \
-	$(MODEL)/clear$o
-
-clear$x: $(DEPS_CLEAR) $(DEPS_CURSES)
-	 $(LINK) $(DEPS_CLEAR) $(LDFLAGS_TINFO) -o $@
-
-DEPS_TABS = \
-	$(MODEL)/tabs$o
-
-tabs$x: $(DEPS_TABS) $(DEPS_TABS)
-	 $(LINK) $(DEPS_TABS) $(LDFLAGS_TINFO) -o $@
-
-DEPS_TPUT = \
-	$(MODEL)/tput$o \
-	$(MODEL)/tparm_type$o \
-	$(MODEL)/transform$o
-
-tput$x: $(DEPS_TPUT) $(DEPS_CURSES) transform.h
-	 $(LINK) $(DEPS_TPUT) $(LDFLAGS_TINFO) -o $@
-
-DEPS_INFOCMP = \
-	$(MODEL)/infocmp$o \
-	$(MODEL)/dump_entry$o
-
-infocmp$x: $(DEPS_INFOCMP) $(DEPS_CURSES)
-	 $(LINK) $(DEPS_INFOCMP) $(LDFLAGS_TIC) -o $@
-
-DEPS_TSET = \
-	$(MODEL)/tset$o \
-	$(MODEL)/transform$o
-
-tset$x: $(DEPS_TSET) $(DEPS_CURSES) transform.h
-	 $(LINK) $(DEPS_TSET) $(LDFLAGS_TINFO) -o $@
-
-termsort.c: $(srcdir)/MKtermsort.sh
-	$(SHELL) $(srcdir)/MKtermsort.sh $(AWK) $(srcdir)/../include/Caps >$@
-
-#
-# Utility productions start here
-#
-
-tags:
-	$(CTAGS) *.[ch]
-
-#TAGS:
-#	$(ETAGS) *.[ch]
-
-mostlyclean ::
-	-rm -f core tags TAGS *~ *.bak *.i *.ln *.atac trace
-
-clean :: mostlyclean
-	-$(SHELL) -c "if test -n '$x' ; then $(MAKE) clean x=''; fi"
-	-rm -f $(AUTO_SRC)
-	-rm -f $(PROGS)
-	-rm -rf .libs *.dSYM
-
-distclean :: clean
-	-rm -f Makefile
-
-realclean :: distclean
-
-# These rules are used to allow "make -n" to work on a clean directory-tree
-../include/hashsize.h \
-../include/parametrized.h \
-../include/term.h :
-	cd ../include; $(MAKE) $(CF_MFLAGS)
-$(DEPS_CURSES) :
-	cd ../ncurses; $(MAKE) $(CF_MFLAGS)
-
-lint:
-	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/tic.c     $(srcdir)/dump_entry.c $(LINT_LIBS)
-	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/toe.c     $(srcdir)/dump_entry.c $(LINT_LIBS)
-	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/clear.c                          $(LINT_LIBS)
-	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/infocmp.c $(srcdir)/dump_entry.c $(LINT_LIBS)
-	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/tabs.c                           $(LINT_LIBS)
-	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/tput.c                           $(LINT_LIBS)
-	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/tset.c    $(srcdir)/dump_entry.c $(LINT_LIBS)
-
-###############################################################################
-# The remainder of this file is automatically generated during configuration
-###############################################################################
-
-# Generated by CF_LIB_RULES
-resulting.map: 
-	sed  -e "s/NCURSES\([WT]\+\)\?_/NCURSES\16_/g" -e "/deprecated in ABI6/d" <  >$@
-
-clean::
-	rm -f resulting.map
-
-# generated by mk-0th.awk
-#   libname:    progs
-#   subsets:    ticlib+termlib+ext_tinfo+base+ext_funcs
-
-.SUFFIXES: .c .cc .h .i .ii
-.c.i :
-	$(CPP) $(CPPFLAGS) $< >$@
-.cc.ii :
-	$(CPP) $(CPPFLAGS) $< >$@
-.h.i :
-	$(CPP) $(CPPFLAGS) $< >$@
-
-C_SRC = \
-	$(srcdir)/clear.c \
-	$(srcdir)/tic.c \
-	$(srcdir)/toe.c \
-	$(srcdir)/dump_entry.c \
-	$(srcdir)/infocmp.c \
-	$(srcdir)/tabs.c \
-	$(srcdir)/tparm_type.c \
-	$(srcdir)/tput.c \
-	$(srcdir)/tset.c \
-	$(srcdir)/transform.c
-
-lintlib :
-	@echo no action needed
-
-# generated by mk-1st.awk (subset=ticlib+termlib+ext_tinfo+base+ext_funcs)
-#  name:          progs
-#  traces:        DEBUG
-#  MODEL:         NORMAL
-#  CXX_MODEL:     NORMAL
-#  model:         objects
-#  prefix:        lib
-#  suffix:        .a
-#  subset:        ticlib+termlib+ext_tinfo+base+ext_funcs
-#  driver:        no
-#  ShlibVer:      rel
-#  ShlibVerInfix: no
-#  SymLink:       ln -s -f
-#  TermlibRoot:   ncurses
-#  TermlibSuffix: .a
-#  ReLink:        no
-#  DoLinks:       yes
-#  rmSoLocs:      no
-#  ldconfig:      :
-#  overwrite:     no
-#  depend:        ../include/ncurses_cfg.h ./progs.priv.h
-#  host:          arm-unknown-linux-androideabi
-
-NORMAL_OBJS = \
-	../objects/clear$o \
-	../objects/tic$o \
-	../objects/toe$o \
-	../objects/dump_entry$o \
-	../objects/infocmp$o \
-	../objects/tabs$o \
-	../objects/tparm_type$o \
-	../objects/tput$o \
-	../objects/tset$o \
-	../objects/transform$o
-
-$(NORMAL_OBJS) : ../include/ncurses_cfg.h ./progs.priv.h
-
-mostlyclean::
-	-rm -f $(NORMAL_OBJS)
-
-clean ::
-	-rm -f $(NORMAL_OBJS)
-
-# generated by mk-2nd.awk
-#   model:      objects
-#   MODEL:      NORMAL
-#   echo:       yes
-#   subset:     ticlib+termlib+ext_tinfo+base+ext_funcs
-#   crenames:   yes
-#   cxxrenames: 
-#   traces:     DEBUG
-#   srcdir:     .
-
-../objects/clear$o :	$(srcdir)/clear.c \
-			$(HEADER_DEPS)
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_NORMAL) -c ../progs/clear.c -o ../objects/clear$o
-
-../objects/tic$o :	$(srcdir)/tic.c \
-			$(HEADER_DEPS) \
-			transform.h \
-			$(srcdir)/dump_entry.h \
-			$(srcdir)/tparm_type.h
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_NORMAL) -c ../progs/tic.c -o ../objects/tic$o
-
-../objects/toe$o :	$(srcdir)/toe.c \
-			$(HEADER_DEPS) \
-			$(INCDIR)/hashed_db.h
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_NORMAL) -c ../progs/toe.c -o ../objects/toe$o
-
-../objects/dump_entry$o :	$(srcdir)/dump_entry.c \
-			$(HEADER_DEPS) \
-			$(srcdir)/dump_entry.h \
-			../include/parametrized.h \
-			$(INCDIR)/capdefaults.c \
-			termsort.c
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_NORMAL) -c ../progs/dump_entry.c -o ../objects/dump_entry$o
-
-../objects/infocmp$o :	$(srcdir)/infocmp.c \
-			$(HEADER_DEPS) \
-			$(srcdir)/dump_entry.h
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_NORMAL) -c ../progs/infocmp.c -o ../objects/infocmp$o
-
-../objects/tabs$o :	$(srcdir)/tabs.c \
-			$(HEADER_DEPS)
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_NORMAL) -c ../progs/tabs.c -o ../objects/tabs$o
-
-../objects/tparm_type$o :	$(srcdir)/tparm_type.c \
-			$(HEADER_DEPS) \
-			$(srcdir)/tparm_type.h
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_NORMAL) -c ../progs/tparm_type.c -o ../objects/tparm_type$o
-
-../objects/tput$o :	$(srcdir)/tput.c \
-			$(HEADER_DEPS) \
-			transform.h \
-			$(srcdir)/dump_entry.h \
-			$(srcdir)/tparm_type.h \
-			termsort.c
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_NORMAL) -c ../progs/tput.c -o ../objects/tput$o
-
-../objects/tset$o :	$(srcdir)/tset.c \
-			$(HEADER_DEPS) \
-			transform.h \
-			$(srcdir)/dump_entry.h \
-			../include/termcap.h
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_NORMAL) -c ../progs/tset.c -o ../objects/tset$o
-
-../objects/transform$o :	$(srcdir)/transform.c \
-			$(HEADER_DEPS) \
-			transform.h
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_NORMAL) -c ../progs/transform.c -o ../objects/transform$o
-
-
-# generated by mk-1st.awk (subset=ticlib+termlib+ext_tinfo+base+ext_funcs)
-#  name:          progs
-#  traces:        DEBUG
-#  MODEL:         DEBUG
-#  CXX_MODEL:     DEBUG
-#  model:         obj_g
-#  prefix:        lib
-#  suffix:        _g.a
-#  subset:        ticlib+termlib+ext_tinfo+base+ext_funcs
-#  driver:        no
-#  ShlibVer:      rel
-#  ShlibVerInfix: no
-#  SymLink:       ln -s -f
-#  TermlibRoot:   ncurses
-#  TermlibSuffix: .a
-#  ReLink:        no
-#  DoLinks:       yes
-#  rmSoLocs:      no
-#  ldconfig:      :
-#  overwrite:     no
-#  depend:        ../include/ncurses_cfg.h ./progs.priv.h
-#  host:          arm-unknown-linux-androideabi
-
-DEBUG_OBJS = \
-	../obj_g/clear$o \
-	../obj_g/tic$o \
-	../obj_g/toe$o \
-	../obj_g/dump_entry$o \
-	../obj_g/infocmp$o \
-	../obj_g/tabs$o \
-	../obj_g/tparm_type$o \
-	../obj_g/tput$o \
-	../obj_g/tset$o \
-	../obj_g/transform$o
-
-$(DEBUG_OBJS) : ../include/ncurses_cfg.h ./progs.priv.h
-
-mostlyclean::
-	-rm -f $(DEBUG_OBJS)
-
-clean ::
-	-rm -f $(DEBUG_OBJS)
-
-# generated by mk-2nd.awk
-#   model:      obj_g
-#   MODEL:      DEBUG
-#   echo:       yes
-#   subset:     ticlib+termlib+ext_tinfo+base+ext_funcs
-#   crenames:   yes
-#   cxxrenames: 
-#   traces:     DEBUG
-#   srcdir:     .
-
-../obj_g/clear$o :	$(srcdir)/clear.c \
-			$(HEADER_DEPS)
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_DEBUG) -c ../progs/clear.c -o ../obj_g/clear$o
-
-../obj_g/tic$o :	$(srcdir)/tic.c \
-			$(HEADER_DEPS) \
-			transform.h \
-			$(srcdir)/dump_entry.h \
-			$(srcdir)/tparm_type.h
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_DEBUG) -c ../progs/tic.c -o ../obj_g/tic$o
-
-../obj_g/toe$o :	$(srcdir)/toe.c \
-			$(HEADER_DEPS) \
-			$(INCDIR)/hashed_db.h
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_DEBUG) -c ../progs/toe.c -o ../obj_g/toe$o
-
-../obj_g/dump_entry$o :	$(srcdir)/dump_entry.c \
-			$(HEADER_DEPS) \
-			$(srcdir)/dump_entry.h \
-			../include/parametrized.h \
-			$(INCDIR)/capdefaults.c \
-			termsort.c
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_DEBUG) -c ../progs/dump_entry.c -o ../obj_g/dump_entry$o
-
-../obj_g/infocmp$o :	$(srcdir)/infocmp.c \
-			$(HEADER_DEPS) \
-			$(srcdir)/dump_entry.h
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_DEBUG) -c ../progs/infocmp.c -o ../obj_g/infocmp$o
-
-../obj_g/tabs$o :	$(srcdir)/tabs.c \
-			$(HEADER_DEPS)
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_DEBUG) -c ../progs/tabs.c -o ../obj_g/tabs$o
-
-../obj_g/tparm_type$o :	$(srcdir)/tparm_type.c \
-			$(HEADER_DEPS) \
-			$(srcdir)/tparm_type.h
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_DEBUG) -c ../progs/tparm_type.c -o ../obj_g/tparm_type$o
-
-../obj_g/tput$o :	$(srcdir)/tput.c \
-			$(HEADER_DEPS) \
-			transform.h \
-			$(srcdir)/dump_entry.h \
-			$(srcdir)/tparm_type.h \
-			termsort.c
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_DEBUG) -c ../progs/tput.c -o ../obj_g/tput$o
-
-../obj_g/tset$o :	$(srcdir)/tset.c \
-			$(HEADER_DEPS) \
-			transform.h \
-			$(srcdir)/dump_entry.h \
-			../include/termcap.h
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_DEBUG) -c ../progs/tset.c -o ../obj_g/tset$o
-
-../obj_g/transform$o :	$(srcdir)/transform.c \
-			$(HEADER_DEPS) \
-			transform.h
-	$(LIBTOOL_COMPILE) $(CC) $(CFLAGS_DEBUG) -c ../progs/transform.c -o ../obj_g/transform$o
-
-depend : ${AUTO_SRC}
-	makedepend -- ${CPPFLAGS} -- ${C_SRC}
-
-# DO NOT DELETE THIS LINE -- make depend depends on it.
diff --git a/progs/Makefile.in b/progs/Makefile.in
index 663a5a0..218e64e 100644
--- a/progs/Makefile.in
+++ b/progs/Makefile.in
@@ -1,6 +1,7 @@
-# $Id: Makefile.in,v 1.95 2015/08/05 09:24:06 tom Exp $
+# $Id: Makefile.in,v 1.115 2024/04/08 18:33:54 tom Exp $
 ##############################################################################
-# Copyright (c) 1998-2014,2015 Free Software Foundation, Inc.                #
+# Copyright 2020-2021,2024 Thomas E. Dickey                                  #
+# Copyright 1998-2016,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 "Software"), #
@@ -46,7 +47,7 @@
 VPATH		= @srcdir@
 THIS		= Makefile
 
-CF_MFLAGS 	= @cf_cv_makeflags@
+TOP_MFLAGS	= @cf_cv_makeflags@ DESTDIR="$(DESTDIR)" RPATH_LIST="$(RPATH_LIST)"
 @SET_MAKE@
 
 x		= @EXEEXT@
@@ -78,7 +79,7 @@
 LIBTOOL_UNINSTALL = @LIB_UNINSTALL@
 
 INSTALL		= @INSTALL@
-INSTALL_PROG	= @INSTALL_PROGRAM@
+INSTALL_PROG	= @INSTALL_PROGRAM@ @INSTALL_OPT_S@
 transform	= @program_transform_name@
 
 AWK		= @AWK@
@@ -89,17 +90,18 @@
 
 CC		= @CC@
 CPP		= @CPP@
-CFLAGS		= @CFLAGS@
+CFLAGS		= @CFLAGS@ @EXTRA_CFLAGS@
 
 INCDIR		= $(top_srcdir)/include
-CPPFLAGS	= -DHAVE_CONFIG_H @CPPFLAGS@
+NCUDIR		= $(top_srcdir)/ncurses
+CPPFLAGS	= -DHAVE_CONFIG_H -I../progs -I../ncurses -I$(top_srcdir)/ncurses @CPPFLAGS@
 
 CCFLAGS		= $(CPPFLAGS) $(CFLAGS)
 
 CFLAGS_LIBTOOL	= $(CCFLAGS)
-CFLAGS_NORMAL	= $(CCFLAGS)
-CFLAGS_DEBUG	= $(CCFLAGS) @CC_G_OPT@ -DTRACE
-CFLAGS_PROFILE	= $(CCFLAGS) -pg
+CFLAGS_NORMAL	= $(CCFLAGS) -DNCURSES_STATIC
+CFLAGS_DEBUG	= $(CCFLAGS) -DNCURSES_STATIC @CC_G_OPT@ -DTRACE
+CFLAGS_PROFILE	= $(CCFLAGS) -DNCURSES_STATIC -pg
 CFLAGS_SHARED	= $(CCFLAGS) @CC_SHARED_OPTS@
 
 CFLAGS_DEFAULT	= $(CFLAGS_@DFT_UPR_MODEL@)
@@ -132,7 +134,7 @@
 LINT_LIBS	= -lncurses @LIBS@
 
 AUTO_SRC = \
-	termsort.c \
+	termsort.h \
 	transform.h
 
 # tic relies on direct access to the terminfo database
@@ -144,12 +146,43 @@
 DEPS_CURSES = ../lib/@LIB_PREFIX@ncurses@DFT_DEP_SUFFIX@
 
 HEADER_DEPS	= \
-	../include/curses.h \
+	$(INCDIR)/nc_access.h \
+	$(INCDIR)/nc_alloc.h \
+	$(INCDIR)/nc_panel.h \
+	$(INCDIR)/nc_string.h \
+	$(INCDIR)/nc_termios.h \
+	$(INCDIR)/nc_tparm.h \
 	$(INCDIR)/term_entry.h \
 	$(INCDIR)/tic.h \
-	$(INCDIR)/nc_alloc.h
+	$(NCUDIR)/curses.priv.h \
+	$(NCUDIR)/new_pair.h \
+	$(NCUDIR)/term.priv.h \
+	$(srcdir)/progs.priv.h \
+	../include/curses.h \
+	../include/ncurses_cfg.h \
+	../include/ncurses_def.h \
+	../include/ncurses_dll.h \
+	../include/term.h \
+	../include/unctrl.h
 
 ################################################################################
+
+@MAKE_PHONY@.PHONY :	all
+@MAKE_PHONY@.PHONY :	check
+@MAKE_PHONY@.PHONY :	clean
+@MAKE_PHONY@.PHONY :	distclean
+@MAKE_PHONY@.PHONY :	install
+@MAKE_PHONY@.PHONY :	install.libs
+@MAKE_PHONY@.PHONY :	install.progs
+@MAKE_PHONY@.PHONY :	libs
+@MAKE_PHONY@.PHONY :	lint
+@MAKE_PHONY@.PHONY :	mostlyclean
+@MAKE_PHONY@.PHONY :	realclean
+@MAKE_PHONY@.PHONY :	sources
+@MAKE_PHONY@.PHONY :	uninstall
+@MAKE_PHONY@.PHONY :	uninstall.libs
+@MAKE_PHONY@.PHONY :	uninstall.progs
+
 all:		$(AUTO_SRC) $(PROGS)
 
 sources:	$(AUTO_SRC)
@@ -179,6 +212,7 @@
 
 # transformed names for comparing at runtime
 define_captoinfo = `echo captoinfo|   $(TRANSFORM)`
+define_clear     = `echo clear|       $(TRANSFORM)`
 define_infotocap = `echo infotocap|   $(TRANSFORM)`
 define_init      = `echo init|        $(TRANSFORM)`
 define_reset     = `echo reset|       $(TRANSFORM)`
@@ -191,6 +225,7 @@
 	-$(SHELL) -c 'if test -n "$x" ; then echo "#define SUFFIX_IGNORED \"$x\"">>$@; fi'
 	echo "#define PROG_CAPTOINFO \"$(define_captoinfo)\""		>>$@
 	echo "#define PROG_INFOTOCAP \"$(define_infotocap)\""		>>$@
+	echo "#define PROG_CLEAR     \"$(define_clear)\""		>>$@
 	echo "#define PROG_RESET     \"$(define_reset)\""		>>$@
 	echo "#define PROG_INIT      \"$(define_init)\""		>>$@
 	echo "#endif /* __TRANSFORM_H */"				>>$@
@@ -200,10 +235,10 @@
 @MAKE_TERMINFO@	$(LIBTOOL_INSTALL) $(INSTALL_PROG) toe$x     $(DESTDIR)$(bindir)/$(actual_toe)
 @MAKE_TERMINFO@	@echo "linking $(actual_infotocap) to $(actual_tic)"
 @MAKE_TERMINFO@	-@rm -f $(DESTDIR)$(bindir)/$(actual_infotocap)
-@MAKE_TERMINFO@	(cd $(DESTDIR)$(bindir) && $(LN_S) $(actual_tic) $(actual_infotocap))
+@MAKE_TERMINFO@	( cd $(DESTDIR)$(bindir) && $(LN_S) $(actual_tic) $(actual_infotocap) )
 @MAKE_TERMINFO@	@echo "linking $(actual_captoinfo) to $(actual_tic)"
 @MAKE_TERMINFO@	-@rm -f $(DESTDIR)$(bindir)/$(actual_captoinfo)
-@MAKE_TERMINFO@	(cd $(DESTDIR)$(bindir) && $(LN_S) $(actual_tic) $(actual_captoinfo))
+@MAKE_TERMINFO@	( cd $(DESTDIR)$(bindir) && $(LN_S) $(actual_tic) $(actual_captoinfo) )
 	$(LIBTOOL_INSTALL) $(INSTALL_PROG) infocmp$x $(DESTDIR)$(bindir)/$(actual_infocmp)
 	$(LIBTOOL_INSTALL) $(INSTALL_PROG) clear$x   $(DESTDIR)$(bindir)/$(actual_clear)
 	$(LIBTOOL_INSTALL) $(INSTALL_PROG) tabs$x    $(DESTDIR)$(bindir)/$(actual_tabs)
@@ -211,7 +246,7 @@
 	$(LIBTOOL_INSTALL) $(INSTALL_PROG) tset$x    $(DESTDIR)$(bindir)/$(actual_tset)
 	@echo "linking $(actual_reset) to $(actual_tset)"
 	-@rm -f $(DESTDIR)$(bindir)/$(actual_reset)
-	(cd $(DESTDIR)$(bindir) && $(LN_S) $(actual_tset) $(actual_reset))
+	( cd $(DESTDIR)$(bindir) && $(LN_S) $(actual_tset) $(actual_reset) )
 
 uninstall.progs:
 @MAKE_TERMINFO@	-@$(LIBTOOL_CLEAN) rm -f $(DESTDIR)$(bindir)/$(actual_tic)
@@ -248,21 +283,27 @@
 	@ECHO_LD@ $(LINK) $(DEPS_TOE) $(LDFLAGS_TIC) -o $@
 
 DEPS_CLEAR = \
-	$(MODEL)/clear$o
+	$(MODEL)/clear$o \
+	$(MODEL)/clear_cmd$o \
+	$(MODEL)/tty_settings$o
 
 clear$x: $(DEPS_CLEAR) $(DEPS_CURSES)
 	@ECHO_LD@ $(LINK) $(DEPS_CLEAR) $(LDFLAGS_TINFO) -o $@
 
 DEPS_TABS = \
-	$(MODEL)/tabs$o
+	$(MODEL)/tabs$o \
+	$(MODEL)/tty_settings$o
 
 tabs$x: $(DEPS_TABS) $(DEPS_TABS)
 	@ECHO_LD@ $(LINK) $(DEPS_TABS) $(LDFLAGS_TINFO) -o $@
 
 DEPS_TPUT = \
 	$(MODEL)/tput$o \
+	$(MODEL)/clear_cmd$o \
+	$(MODEL)/reset_cmd$o \
 	$(MODEL)/tparm_type$o \
-	$(MODEL)/transform$o
+	$(MODEL)/transform$o \
+	$(MODEL)/tty_settings$o
 
 tput$x: $(DEPS_TPUT) $(DEPS_CURSES) transform.h
 	@ECHO_LD@ $(LINK) $(DEPS_TPUT) $(LDFLAGS_TINFO) -o $@
@@ -276,12 +317,14 @@
 
 DEPS_TSET = \
 	$(MODEL)/tset$o \
-	$(MODEL)/transform$o
+	$(MODEL)/reset_cmd$o \
+	$(MODEL)/transform$o \
+	$(MODEL)/tty_settings$o
 
 tset$x: $(DEPS_TSET) $(DEPS_CURSES) transform.h
 	@ECHO_LD@ $(LINK) $(DEPS_TSET) $(LDFLAGS_TINFO) -o $@
 
-termsort.c: $(srcdir)/MKtermsort.sh
+termsort.h: $(srcdir)/MKtermsort.sh
 	$(SHELL) $(srcdir)/MKtermsort.sh $(AWK) $(srcdir)/../include/@TERMINFO_CAPS@ >$@
 
 #
@@ -312,18 +355,29 @@
 ../include/hashsize.h \
 ../include/parametrized.h \
 ../include/term.h :
-	cd ../include; $(MAKE) $(CF_MFLAGS)
+	( cd ../include && $(MAKE) $(TOP_MFLAGS) )
 $(DEPS_CURSES) :
-	cd ../ncurses; $(MAKE) $(CF_MFLAGS)
+	( cd ../ncurses && $(MAKE) $(TOP_MFLAGS) )
 
 lint:
 @MAKE_TERMINFO@	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/tic.c     $(srcdir)/dump_entry.c $(LINT_LIBS)
-@MAKE_TERMINFO@	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/toe.c     $(srcdir)/dump_entry.c $(LINT_LIBS)
+@MAKE_TERMINFO@	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/toe.c                    $(LINT_LIBS)
 	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/clear.c                          $(LINT_LIBS)
 	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/infocmp.c $(srcdir)/dump_entry.c $(LINT_LIBS)
 	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/tabs.c                           $(LINT_LIBS)
 	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/tput.c                           $(LINT_LIBS)
-	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/tset.c    $(srcdir)/dump_entry.c $(LINT_LIBS)
+	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/tset.c                           $(LINT_LIBS)
+
+# Verify that each header-file can be compiled without including another.
+check:
+	@$(SHELL) -c "for header in *.h;\
+		do \
+			echo \"** testing \$${header}\" ; \
+			echo \"#include <\$${header}>\" >headers.c; \
+			echo \"int main(void) { return 0; }\" >>headers.c; \
+			$(CC) -c $(CFLAGS) $(CPPFLAGS) headers.c; \
+		done"
+	-@rm -f headers.*
 
 ###############################################################################
 # The remainder of this file is automatically generated during configuration
diff --git a/progs/capconvert b/progs/capconvert
index eb382e0..4b5b321 100755
--- a/progs/capconvert
+++ b/progs/capconvert
@@ -1,6 +1,7 @@
 #!/bin/sh
 ##############################################################################
-# Copyright (c) 1998-2006,2011 Free Software Foundation, Inc.                #
+# Copyright 2019-2021,2022 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 "Software"), #
@@ -26,7 +27,7 @@
 # use or other dealings in this Software without prior written               #
 # authorization.                                                             #
 ##############################################################################
-# $Id: capconvert,v 1.5 2011/11/12 23:28:07 Robert.Millan Exp $
+# $Id: capconvert,v 1.12 2022/07/16 21:00:27 tom Exp $
 #
 # capconvert -- automated conversion from termcap to terminfo
 #
@@ -46,7 +47,7 @@
 	echo "TERMINFO is already defined in your environment.  This means"
 	echo "you already have a local terminfo tree, so you do not need any"
 	echo "conversion."
-	if test ! -d $TERMINFO ; then
+	if test ! -d "$TERMINFO" ; then
 		echo "Caution: TERMINFO does not point to a directory!"
 	fi
 	exit;
@@ -61,7 +62,7 @@
 	/usr/local/lib/terminfo \
 	/usr/local/share/terminfo
 do
-	if test -d $p ; then
+	if test -d "$p" ; then
 		terminfo=yes
 		break
 	fi
@@ -94,7 +95,7 @@
 fi
 echo "";
 
-# Check if test -x works (it's not portable, but useful)
+# Check if test -x works (it is not portable, but useful)
 OPT="-x"
 TMP=test$$; touch $TMP && chmod 755 $TMP
 if test $OPT $TMP ; then
@@ -110,13 +111,13 @@
 IFS="${IFS= 	}"; save_ifs="$IFS"; IFS="${IFS}:"
 for x in $PATH .
 do
-	if test $OPT $x/tic
+	if test "$OPT" "$x"/tic
 	then
 		TIC=$x/tic
 		break
 	fi
 done
-IFS="$ac_save_ifs"
+IFS="$save_ifs"
 
 if test -n "$TIC"
 then
@@ -139,7 +140,7 @@
 #
 
 # Make the user a terminfo directory
-if test -d $HOME/.terminfo
+if test -d "$HOME"/.terminfo
 then
 	echo "It appears you already have a private terminfo directory"
 	echo "at $HOME/.terminfo; this seems odd, because TERMINFO"
@@ -149,7 +150,7 @@
 	exit;
 else
 	echo "I am creating your private terminfo directory at $HOME/.terminfo"
-	mkdir $HOME/.terminfo
+	mkdir "$HOME"/.terminfo
 	# Ensure that that's where tic's compilation results.
 	# This isn't strictly necessary with a 1.9.7 or later tic.
 	TERMINFO="$HOME/.terminfo"; export TERMINFO
@@ -164,8 +165,8 @@
 else
 	# Ooops...looks like we're running from somewhere other than the
 	# progs directory of an ncurses source tree.
-	master=`find $HOME -name "*terminfo.src" -print`
-	mcount=`echo $master | wc -l`
+	master=`find "$HOME" -name "*terminfo.src" -print`
+	mcount=`find "$HOME" -name "*terminfo.src" | wc -l`
 	case $mcount in
 	0)
 		echo "I can not find a terminfo source file anywhere under your home directory."
@@ -179,16 +180,16 @@
 		echo "I am going to assume this is the terminfo source included with"
 		echo "the ncurses distribution.  If this assumption is wrong, please"
 		echo "interrupt me now!  OK to continue?"
-		read ans;
+		read answer;
 	;;
 	2)
 		echo "I see more than one possible terminfo source.  Here they are:"
-		echo $master | sed "/^/s//	/";
+		echo "$master" | sed "/^/s//	/";
 		while :
 		do
 			echo "Please tell me which one to use:"
 			read master;
-			if test -f $master
+			if test -f "$master"
 			then
 				break
 			else
@@ -205,14 +206,15 @@
 #
 # Kluge alert: we compile terminfo.src in two pieces because a lot of machines
 # with < 16MB RAM choke on tic's core-hog habits.
-trap "rm -f tsplit$$.*" 0 1 2 5 15
-sed -n $master \
+trap 'rm -f tsplit$$.*; exit 1' 1 2 3 15
+trap 'rm -f tsplit$$.*' 0
+sed -n "$master" \
 	-e '1,/SPLIT HERE/w 'tsplit$$.01 \
 	-e '/SPLIT HERE/,$w 'tsplit$$.02 \
 	2>/dev/null
-for x in tsplit$$.*; do eval $TIC $x; done
+for x in tsplit$$.*; do eval $TIC "$x"; done
 rm tsplit$$.*
-trap 0 1 2 5 15
+trap EXIT INT QUIT TERM HUP
 #
 echo "You now have a private tree under $HOME/.terminfo;"
 echo "the ncurses library will automatically read from it,"
@@ -226,32 +228,32 @@
 
 # OK, here comes the nasty case...user has a TERMCAP.  Instead of
 # trying to follow all the convolutions of the relationship between
-# TERM and TERMCAP (partly because it's too painful, and partly because
+# TERM and TERMCAP (partly because it is too painful, and partly because
 # we don't actually know what TERM will be nor even if it always has
 # the same value for this user) we do the following three steps...
 
-if test -f $HOME/.termcap
+if test -f "$HOME"/.termcap
 then
-	echo 'I see you have a $HOME/.termcap file.  I will compile that.'
-	eval $TIC $HOME/.termcap
+	echo "I see you have a \$HOME/.termcap file.  I will compile that."
+	eval $TIC "$HOME"/.termcap
 	echo "Done."
 	echo "Note that editing $HOME/.termcap will no longer change the data curses sees."
 elif test -f "$TERMCAP"
 then
 	echo "Your TERMCAP names the file $TERMCAP.  I will compile that."
-	eval $TIC $TERMCAP
+	eval $TIC "$TERMCAP"
 	echo "Done."
 	echo "Note that editing $TERMCAP will no longer change the data curses sees."
 else
 	echo "Your TERMCAP value appears to be an entry in termcap format."
 	echo "I will compile it."
-	echo $TERMCAP >myterm$$
+	echo "$TERMCAP" >myterm$$
 	eval $TIC myterm$$
 	rm myterm$$
 	echo "Done."
 	echo "Note that editing TERMCAP will no longer change the data curses sees."
 fi
-echo "To do that, decompile the terminal decription you want with infocmp(1),"
+echo "To do that, decompile the terminal description you want with infocmp(1),"
 echo "edit to taste, and recompile using tic(1)."
 
 # capconvert ends here
diff --git a/progs/clear b/progs/clear
deleted file mode 100755
index 1839a55..0000000
--- a/progs/clear
+++ /dev/null
Binary files differ
diff --git a/progs/clear.c b/progs/clear.c
index 4ac503e..97cb0f3 100644
--- a/progs/clear.c
+++ b/progs/clear.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2007,2013 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            *
@@ -37,14 +38,29 @@
  */
 
 #define USE_LIBTINFO
-#include <progs.priv.h>
+#include <clear_cmd.h>
+#include <tty_settings.h>
 
-MODULE_ID("$Id: clear.c,v 1.13 2013/06/22 22:20:54 tom Exp $")
+MODULE_ID("$Id: clear.c,v 1.24 2021/03/20 18:23:14 tom Exp $")
 
-static int
-putch(int c)
+const char *_nc_progname = "clear";
+
+static GCC_NORETURN void
+usage(void)
 {
-    return putchar(c);
+#define KEEP(s) s "\n"
+    static const char msg[] =
+    {
+	KEEP("")
+	KEEP("Options:")
+	KEEP("  -T TERM     use this instead of $TERM")
+	KEEP("  -V          print curses-version")
+	KEEP("  -x          do not try to clear scrollback")
+    };
+#undef KEEP
+    (void) fprintf(stderr, "Usage: %s [options]\n", _nc_progname);
+    fputs(msg, stderr);
+    ExitProgram(EXIT_FAILURE);
 }
 
 int
@@ -52,16 +68,41 @@
 	int argc GCC_UNUSED,
 	char *argv[]GCC_UNUSED)
 {
-    char *E3;
+    TTY tty_settings;
+    int fd;
+    int c;
+    char *term;
+    bool opt_x = FALSE;		/* clear scrollback if possible */
 
-    setupterm((char *) 0, STDOUT_FILENO, (int *) 0);
+    _nc_progname = _nc_rootname(argv[0]);
+    term = getenv("TERM");
 
-    /* Clear the scrollback buffer if possible. */
-    E3 = tigetstr("E3");
-    if (E3)
-	(void) tputs(E3, lines > 0 ? lines : 1, putch);
+    while ((c = getopt(argc, argv, "T:Vx")) != -1) {
+	switch (c) {
+	case 'T':
+	    use_env(FALSE);
+	    use_tioctl(TRUE);
+	    term = optarg;
+	    break;
+	case 'V':
+	    puts(curses_version());
+	    ExitProgram(EXIT_SUCCESS);
+	case 'x':		/* do not try to clear scrollback */
+	    opt_x = TRUE;
+	    break;
+	default:
+	    usage();
+	    /* NOTREACHED */
+	}
+    }
+    if (optind < argc)
+	usage();
 
-    ExitProgram((tputs(clear_screen, lines > 0 ? lines : 1, putch) == ERR)
+    fd = save_tty_settings(&tty_settings, FALSE);
+
+    setupterm(term, fd, (int *) 0);
+
+    ExitProgram((clear_cmd(opt_x) == ERR)
 		? EXIT_FAILURE
 		: EXIT_SUCCESS);
 }
diff --git a/progs/clear.sh b/progs/clear.sh
index f26112b..1d899f1 100755
--- a/progs/clear.sh
+++ b/progs/clear.sh
@@ -1,6 +1,7 @@
 #!/bin/sh
 ##############################################################################
-# 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 "Software"), #
diff --git a/progs/clear_cmd.c b/progs/clear_cmd.c
new file mode 100644
index 0000000..3d80515
--- /dev/null
+++ b/progs/clear_cmd.c
@@ -0,0 +1,60 @@
+/****************************************************************************
+ * Copyright 2018,2020 Thomas E. Dickey                                     *
+ * Copyright 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"), 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                                                *
+ ****************************************************************************/
+
+/*
+ * clear.c --  clears the terminal's screen
+ */
+
+#define USE_LIBTINFO
+#include <clear_cmd.h>
+
+MODULE_ID("$Id: clear_cmd.c,v 1.5 2020/02/02 23:34:34 tom Exp $")
+
+static int
+putch(int c)
+{
+    return putchar(c);
+}
+
+int
+clear_cmd(bool legacy)
+{
+    int retval = tputs(clear_screen, lines > 0 ? lines : 1, putch);
+    if (!legacy) {
+	/* Clear the scrollback buffer if possible. */
+	char *E3 = tigetstr("E3");
+	if (E3)
+	    (void) tputs(E3, lines > 0 ? lines : 1, putch);
+    }
+    return retval;
+}
diff --git a/progs/clear_cmd.h b/progs/clear_cmd.h
new file mode 100644
index 0000000..b1de814
--- /dev/null
+++ b/progs/clear_cmd.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 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"), 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                                                *
+ ****************************************************************************/
+
+/*
+ * $Id: clear_cmd.h,v 1.3 2020/02/02 23:34:34 tom Exp $
+ *
+ * Utility functions for clearing terminal.
+ */
+#ifndef CLEAR_CMD_H
+#define CLEAR_CMD_H 1
+
+#include <progs.priv.h>
+extern int clear_cmd(bool);
+
+#endif /* CLEAR_CMD_H */
diff --git a/progs/dump_entry.c b/progs/dump_entry.c
index d59a925..be332d2 100644
--- a/progs/dump_entry.c
+++ b/progs/dump_entry.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2014,2015 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            *
@@ -35,17 +36,18 @@
 #define __INTERNAL_CAPS_VISIBLE
 #include <progs.priv.h>
 
-#include "dump_entry.h"
-#include "termsort.c"		/* this C file is generated */
+#include <dump_entry.h>
+#include <termsort.h>		/* this C file is generated */
 #include <parametrized.h>	/* so is this */
 
-MODULE_ID("$Id: dump_entry.c,v 1.118 2015/07/07 08:06:39 Werner.Fink Exp $")
+MODULE_ID("$Id: dump_entry.c,v 1.196 2023/05/27 20:13:10 tom Exp $")
 
-#define INDENT			8
 #define DISCARD(string) string = ABSENT_STRING
 #define PRINTF (void) printf
+#define WRAPPED 32
 
 #define OkIndex(index,array) ((int)(index) >= 0 && (int)(index) < (int) SIZEOF(array))
+#define TcOutput() (outform == F_TERMCAP || outform == F_TCONVERR)
 
 typedef struct {
     char *text;
@@ -61,7 +63,10 @@
 static int column;		/* current column, limited by 'width' */
 static int oldcol;		/* last value of column before wrap */
 static bool pretty;		/* true if we format if-then-else strings */
+static bool wrapped;		/* true if we wrap too-long strings */
+static bool did_wrap;		/* true if last wrap_concat did wrapping */
 static bool checking;		/* true if we are checking for tic */
+static int quickdump;		/* true if we are dumping compiled data */
 
 static char *save_sgr;
 
@@ -75,11 +80,12 @@
 static NCURSES_CONST char *const *str_names;
 
 static const char *separator = "", *trailer = "";
+static int indent = 8;
 
 /* cover various ports and variants of terminfo */
 #define V_ALLCAPS	0	/* all capabilities (SVr4, XSI, ncurses) */
 #define V_SVR1		1	/* SVR1, Ultrix */
-#define V_HPUX		2	/* HP/UX */
+#define V_HPUX		2	/* HP-UX */
 #define V_AIX		3	/* AIX */
 #define V_BSD		4	/* BSD */
 
@@ -89,7 +95,7 @@
 #define OBSOLETE(n) (n[0] == 'O' && n[1] == 'T')
 #endif
 
-#define isObsolete(f,n) ((f == F_TERMINFO || f == F_VARIABLE) && OBSOLETE(n))
+#define isObsolete(f,n) ((f == F_TERMINFO || f == F_VARIABLE) && (sortmode != S_VARIABLE) && OBSOLETE(n))
 
 #if NCURSES_XNAMES
 #define BoolIndirect(j) ((j >= BOOLCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : bool_indirect[j]))
@@ -101,9 +107,7 @@
 #define StrIndirect(j)  ((sortmode == S_NOSORT) ? (j) : str_indirect[j])
 #endif
 
-static void failed(const char *) GCC_NORETURN;
-
-static void
+static GCC_NORETURN void
 failed(const char *s)
 {
     perror(s);
@@ -120,7 +124,7 @@
 	if (dst->text == 0)
 	    failed("strncpy_DYN");
     }
-    (void) strncpy(dst->text + dst->used, src, need);
+    _nc_STRNCPY(dst->text + dst->used, src, need + 1);
     dst->used += need;
     dst->text[dst->used] = 0;
 }
@@ -189,17 +193,23 @@
 dump_init(const char *version,
 	  int mode,
 	  int sort,
+	  bool wrap_strings,
 	  int twidth,
 	  int theight,
 	  unsigned traceval,
 	  bool formatted,
-	  bool check)
+	  bool check,
+	  int quick)
 /* set up for entry display */
 {
     width = twidth;
     height = theight;
     pretty = formatted;
+    wrapped = wrap_strings;
     checking = check;
+    quickdump = (quick & 3);
+
+    did_wrap = (width <= 0);
 
     /* versions */
     if (version == 0)
@@ -244,6 +254,7 @@
 	trailer = "\\\n\t:";
 	break;
     }
+    indent = 8;
 
     /* implement sort modes */
     switch (sortmode = sort) {
@@ -287,7 +298,7 @@
 		       _nc_progname, width, tversion, outform);
 }
 
-static TERMTYPE *cur_type;
+static TERMTYPE2 *cur_type;
 
 static int
 dump_predicate(PredType type, PredIdx idx)
@@ -310,7 +321,7 @@
     return (FALSE);		/* pacify compiler */
 }
 
-static void set_obsolete_termcaps(TERMTYPE *tp);
+static void set_obsolete_termcaps(TERMTYPE2 *tp);
 
 /* is this the index of a function key string? */
 #define FNKEY(i) \
@@ -413,22 +424,257 @@
     oldcol = column;
     trim_trailing();
     strcpy_DYN(&outbuf, trailer);
-    column = INDENT;
+    column = indent;
+}
+
+static int
+op_length(const char *src, int offset)
+{
+    int result = 0;
+
+    if (offset > 0 && src[offset - 1] == '\\') {
+	result = 0;
+    } else {
+	int ch;
+
+	result++;		/* for '%' mark */
+	ch = src[offset + result];
+	if (TcOutput()) {
+	    if (ch == '>') {
+		result += 3;
+	    } else if (ch == '+') {
+		result += 2;
+	    } else {
+		result++;
+	    }
+	} else if (ch == '\'') {
+	    result += 3;
+	} else if (ch == L_CURL[0]) {
+	    int n = result;
+	    while ((ch = src[offset + n]) != '\0') {
+		if (ch == R_CURL[0]) {
+		    result = ++n;
+		    break;
+		}
+		n++;
+	    }
+	} else if (strchr("pPg", ch) != 0) {
+	    result += 2;
+	} else {
+	    result++;		/* ordinary operator */
+	}
+    }
+    return result;
+}
+
+/*
+ * When wrapping too-long strings, avoid splitting a backslash sequence, or
+ * a terminfo '%' operator.  That will leave things a little ragged, but avoids
+ * a stray backslash at the end of the line, as well as making the result a
+ * little more readable.
+ */
+static int
+find_split(const char *src, int step, int size)
+{
+    int result = size;
+
+    if (size > 0) {
+	/* check if that would split a backslash-sequence */
+	int mark = size;
+	int n;
+
+	for (n = size - 1; n > 0; --n) {
+	    int ch = UChar(src[step + n]);
+	    if (ch == '\\') {
+		if (n > 0 && src[step + n - 1] == ch)
+		    --n;
+		mark = n;
+		break;
+	    } else if (!isalnum(ch)) {
+		break;
+	    }
+	}
+	if (mark < size) {
+	    result = mark;
+	} else {
+	    /* check if that would split a backslash-sequence */
+	    for (n = size - 1; n > 0; --n) {
+		int ch = UChar(src[step + n]);
+		if (ch == '%') {
+		    int need = op_length(src, step + n);
+		    if ((n + need) > size) {
+			mark = n;
+		    }
+		    break;
+		}
+	    }
+	    if (mark < size) {
+		result = mark;
+	    }
+	}
+    }
+    return result;
+}
+
+/*
+ * If we are going to wrap lines, we cannot leave literal spaces because that
+ * would be ambiguous if we split on that space.
+ */
+static char *
+fill_spaces(const char *src)
+{
+    const char *fill = "\\s";
+    size_t need = strlen(src);
+    size_t size = strlen(fill);
+    char *result = 0;
+    int pass;
+    size_t s, d;
+    for (pass = 0; pass < 2; ++pass) {
+	for (s = d = 0; src[s] != '\0'; ++s) {
+	    if (src[s] == ' ') {
+		if (pass) {
+		    _nc_STRCPY(&result[d], fill, need + 1 - d);
+		    d += size;
+		} else {
+		    need += size;
+		}
+	    } else {
+		if (pass) {
+		    result[d++] = src[s];
+		} else {
+		    ++d;
+		}
+	    }
+	}
+	if (pass) {
+	    result[d] = '\0';
+	} else {
+	    result = calloc(need + 1, sizeof(char));
+	    if (result == 0)
+		failed("fill_spaces");
+	}
+    }
+    return result;
+}
+
+typedef enum {
+    wOFF = 0
+    ,w1ST = 1
+    ,w2ND = 2
+    ,wEND = 4
+    ,wERR = 8
+} WRAPMODE;
+
+#define wrap_1ST(mode) ((mode)&w1ST)
+#define wrap_END(mode) ((mode)&wEND)
+#define wrap_ERR(mode) ((mode)&wERR)
+
+static void
+wrap_concat(const char *src, int need, unsigned mode)
+{
+    int gaps = (int) strlen(separator);
+    int want = gaps + need;
+
+    did_wrap = (width <= 0);
+    if (wrap_1ST(mode)
+	&& column > indent
+	&& column + want > width) {
+	force_wrap();
+    }
+    if ((wrap_END(mode) && !wrap_ERR(mode)) &&
+	wrapped &&
+	(width >= 0) &&
+	(column + want) > width) {
+	int step = 0;
+	int used = width > WRAPPED ? width : WRAPPED;
+	int base = 0;
+	char *p, align[9];
+	const char *my_t = trailer;
+	char *fill = fill_spaces(src);
+	int last = (int) strlen(fill);
+
+	need = last;
+
+	if (TcOutput())
+	    trailer = "\\\n\t ";
+
+	if (!TcOutput() && (p = strchr(fill, '=')) != 0) {
+	    base = (int) (p + 1 - fill);
+	    if (base > 8)
+		base = 8;
+	    _nc_SPRINTF(align, _nc_SLIMIT(align) "%*s", base, " ");
+	} else if (column > 8) {
+	    base = column - 8;
+	    if (base > 8)
+		base = 8;
+	    _nc_SPRINTF(align, _nc_SLIMIT(align) "%*s", base, " ");
+	} else {
+	    align[base] = '\0';
+	}
+	/* "pretty" overrides wrapping if it already split the line */
+	if (!pretty || strchr(fill, '\n') == 0) {
+	    int tag = 0;
+
+	    if (TcOutput() && outbuf.used && !wrap_1ST(mode)) {
+		tag = 3;
+	    }
+
+	    while ((column + (need + gaps)) > used) {
+		int size = used - tag;
+		if (step) {
+		    strcpy_DYN(&outbuf, align);
+		    size -= base;
+		}
+		if (size > (last - step)) {
+		    size = (last - step);
+		}
+		size = find_split(fill, step, size);
+		strncpy_DYN(&outbuf, fill + step, (size_t) size);
+		step += size;
+		need -= size;
+		if (need > 0) {
+		    force_wrap();
+		    did_wrap = TRUE;
+		    tag = 0;
+		}
+	    }
+	}
+	if (need > 0) {
+	    if (step)
+		strcpy_DYN(&outbuf, align);
+	    strcpy_DYN(&outbuf, fill + step);
+	}
+	if (wrap_END(mode))
+	    strcpy_DYN(&outbuf, separator);
+	trailer = my_t;
+	force_wrap();
+
+	free(fill);
+    } else {
+	strcpy_DYN(&outbuf, src);
+	if (wrap_END(mode))
+	    strcpy_DYN(&outbuf, separator);
+	column += (int) strlen(src);
+    }
 }
 
 static void
-wrap_concat(const char *src)
+wrap_concat1(const char *src)
 {
-    size_t need = strlen(src);
-    size_t want = strlen(separator) + need;
+    int need = (int) strlen(src);
+    wrap_concat(src, need, w1ST | wEND);
+}
 
-    if (column > INDENT
-	&& column + (int) want > width) {
-	force_wrap();
-    }
-    strcpy_DYN(&outbuf, src);
-    strcpy_DYN(&outbuf, separator);
-    column += (int) need;
+static void
+wrap_concat3(const char *name, const char *eqls, const char *value)
+{
+    int nlen = (int) strlen(name);
+    int elen = (int) strlen(eqls);
+    int vlen = (int) strlen(value);
+
+    wrap_concat(name, nlen + elen + vlen, w1ST);
+    wrap_concat(eqls, elen + vlen, w2ND);
+    wrap_concat(value, vlen, wEND);
 }
 
 #define IGNORE_SEP_TRAIL(first,last,sep_trail) \
@@ -474,8 +720,35 @@
 	strncpy_DYN(buffer, "\t", (size_t) 1);
 }
 
+/*
+ * Check if the current line which was begun consists only of a tab and the
+ * given leading text.
+ */
+static bool
+leading_DYN(DYNBUF * buffer, const char *leading)
+{
+    bool result = FALSE;
+    size_t need = strlen(leading);
+    if (buffer->used > need) {
+	need = buffer->used - need;
+	if (!strcmp(buffer->text + need, leading)) {
+	    result = TRUE;
+	    while (--need != 0) {
+		if (buffer->text[need] == '\n') {
+		    break;
+		}
+		if (buffer->text[need] != '\t') {
+		    result = FALSE;
+		    break;
+		}
+	    }
+	}
+    }
+    return result;
+}
+
 bool
-has_params(const char *src)
+has_params(const char *src, bool formatting)
 {
     bool result = FALSE;
     int len = (int) strlen(src);
@@ -493,19 +766,27 @@
 	}
     }
     if (!ifthen) {
-	result = ((len > 50) && params);
+	if (formatting) {
+	    result = ((len > 50) && params);
+	} else {
+	    result = params;
+	}
     }
     return result;
 }
 
 static char *
-fmt_complex(TERMTYPE *tterm, const char *capability, char *src, int level)
+fmt_complex(TERMTYPE2 *tterm, const char *capability, char *src, int level)
 {
     bool percent = FALSE;
-    bool params = has_params(src);
+    bool params = has_params(src, TRUE);
 
     while (*src != '\0') {
 	switch (*src) {
+	case '^':
+	    percent = FALSE;
+	    strncpy_DYN(&tmpbuf, src++, (size_t) 1);
+	    break;
 	case '\\':
 	    percent = FALSE;
 	    strncpy_DYN(&tmpbuf, src++, (size_t) 1);
@@ -525,7 +806,7 @@
 		    strncpy_DYN(&tmpbuf, "%", (size_t) 1);
 		    strncpy_DYN(&tmpbuf, src, (size_t) 1);
 		    src++;
-		    params = has_params(src);
+		    params = has_params(src, TRUE);
 		    if (!params && *src != '\0' && *src != '%') {
 			strncpy_DYN(&tmpbuf, "\n", (size_t) 1);
 			indent_DYN(&tmpbuf, level + 1);
@@ -573,12 +854,11 @@
 	    }
 	    break;
 	case 'p':
-	    if (percent && params) {
+	    if (percent && params && !leading_DYN(&tmpbuf, "%")) {
 		tmpbuf.text[tmpbuf.used - 1] = '\n';
 		indent_DYN(&tmpbuf, level + 1);
 		strncpy_DYN(&tmpbuf, "%", (size_t) 1);
 	    }
-	    params = FALSE;
 	    percent = FALSE;
 	    break;
 	case ' ':
@@ -594,11 +874,38 @@
     return src;
 }
 
+/*
+ * Make "large" numbers a little easier to read by showing them in hexadecimal
+ * if they are "close" to a power of two.
+ */
+static const char *
+number_format(int value)
+{
+    const char *result = "%d";
+
+    if ((outform != F_TERMCAP) && (value > 255)) {
+	unsigned long lv = (unsigned long) value;
+	int bits = sizeof(unsigned long) * 8;
+	int nn;
+
+	for (nn = 8; nn < bits; ++nn) {
+	    unsigned long mm;
+
+	    mm = 1UL << nn;
+	    if ((mm - 16) <= lv && (mm + 16) > lv) {
+		result = "%#x";
+		break;
+	    }
+	}
+    }
+    return result;
+}
+
 #define SAME_CAP(n,cap) (&tterm->Strings[n] == &cap)
 #define EXTRA_CAP 20
 
 int
-fmt_entry(TERMTYPE *tterm,
+fmt_entry(TERMTYPE2 *tterm,
 	  PredFunc pred,
 	  int content_only,
 	  int suppress_untranslatable,
@@ -607,7 +914,6 @@
 {
     PredIdx i, j;
     char buffer[MAX_TERMINFO_LENGTH + EXTRA_CAP];
-    char *capability;
     NCURSES_CONST char *name;
     int predval, len;
     PredIdx num_bools = 0;
@@ -615,9 +921,8 @@
     PredIdx num_strings = 0;
     bool outcount = 0;
 
-#define WRAP_CONCAT	\
-	wrap_concat(buffer); \
-	outcount = TRUE
+#define WRAP_CONCAT1(s)		wrap_concat1(s); outcount = TRUE
+#define WRAP_CONCAT		WRAP_CONCAT1(buffer)
 
     len = 12;			/* terminfo file-header */
 
@@ -628,7 +933,7 @@
 
     strcpy_DYN(&outbuf, 0);
     if (content_only) {
-	column = INDENT;	/* FIXME: workaround to prevent empty lines */
+	column = indent;	/* workaround to prevent empty lines */
     } else {
 	strcpy_DYN(&outbuf, tterm->term_names);
 
@@ -671,7 +976,7 @@
 	}
     }
 
-    if (column != INDENT && height > 1)
+    if (column != indent && height > 1)
 	force_wrap();
 
     for_each_number(j, tterm) {
@@ -690,8 +995,13 @@
 		_nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
 			    "%s@", name);
 	    } else {
+		size_t nn;
 		_nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
-			    "%s#%d", name, tterm->Numbers[i]);
+			    "%s#", name);
+		nn = strlen(buffer);
+		_nc_SPRINTF(buffer + nn, _nc_SLIMIT(sizeof(buffer) - nn)
+			    number_format(tterm->Numbers[i]),
+			    tterm->Numbers[i]);
 		if (i + 1 > num_values)
 		    num_values = i + 1;
 	    }
@@ -699,7 +1009,7 @@
 	}
     }
 
-    if (column != INDENT && height > 1)
+    if (column != indent && height > 1)
 	force_wrap();
 
     len += (int) (num_bools
@@ -711,18 +1021,19 @@
 #undef CUR
 #define CUR tterm->
     if (outform == F_TERMCAP) {
-	if (termcap_reset != ABSENT_STRING) {
-	    if (init_3string != ABSENT_STRING
+	if (VALID_STRING(termcap_reset)) {
+	    if (VALID_STRING(init_3string)
 		&& !strcmp(init_3string, termcap_reset))
 		DISCARD(init_3string);
 
-	    if (reset_2string != ABSENT_STRING
+	    if (VALID_STRING(reset_2string)
 		&& !strcmp(reset_2string, termcap_reset))
 		DISCARD(reset_2string);
 	}
     }
 
     for_each_string(j, tterm) {
+	char *capability;
 	i = StrIndirect(j);
 	name = ExtStrname(tterm, (int) i, str_names);
 	assert(strlen(name) < sizeof(buffer) - EXTRA_CAP);
@@ -776,9 +1087,9 @@
 		    set_attributes = save_sgr;
 
 		    trimmed_sgr0 = _nc_trim_sgr0(tterm);
-		    if (strcmp(capability, trimmed_sgr0))
+		    if (strcmp(capability, trimmed_sgr0)) {
 			capability = trimmed_sgr0;
-		    else {
+		    } else {
 			if (trimmed_sgr0 != exit_attribute_mode)
 			    free(trimmed_sgr0);
 		    }
@@ -792,7 +1103,7 @@
 	buffer[0] = '\0';
 
 	if (predval != FAIL) {
-	    if (capability != ABSENT_STRING
+	    if (VALID_STRING(capability)
 		&& i + 1 > num_strings)
 		num_strings = i + 1;
 
@@ -800,14 +1111,13 @@
 		_nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
 			    "%s@", name);
 		WRAP_CONCAT;
-	    } else if (outform == F_TERMCAP || outform == F_TCONVERR) {
+	    } else if (TcOutput()) {
 		char *srccap = _nc_tic_expand(capability, TRUE, numbers);
-		int params = (((i < (int) SIZEOF(parametrized)) &&
-			       (i < STRCOUNT))
+		int params = ((i < (int) SIZEOF(parametrized))
 			      ? parametrized[i]
 			      : ((*srccap == 'k')
 				 ? 0
-				 : has_params(srccap)));
+				 : has_params(srccap, FALSE)));
 		char *cv = _nc_infotocap(name, srccap, params);
 
 		if (cv == 0) {
@@ -815,28 +1125,45 @@
 			_nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
 				    "%s=!!! %s WILL NOT CONVERT !!!",
 				    name, srccap);
+			WRAP_CONCAT;
 		    } else if (suppress_untranslatable) {
 			continue;
 		    } else {
 			char *s = srccap, *d = buffer;
-			_nc_SPRINTF(d, _nc_SLIMIT(sizeof(buffer)) "..%s=", name);
-			d += strlen(d);
+			int need = 3 + (int) strlen(name);
 			while ((*d = *s++) != 0) {
+			    if ((d - buffer + 2) >= (int) sizeof(buffer)) {
+				fprintf(stderr,
+					"%s: value for %s is too long\n",
+					_nc_progname,
+					name);
+				*d = '\0';
+				break;
+			    }
 			    if (*d == ':') {
 				*d++ = '\\';
 				*d = ':';
 			    } else if (*d == '\\') {
-				*++d = *s++;
+				if ((*++d = *s++) == '\0')
+				    break;
 			    }
 			    d++;
+			    *d = '\0';
 			}
+			need += (int) (d - buffer);
+			wrap_concat("..", need, w1ST | wERR);
+			need -= 2;
+			wrap_concat(name, need, wOFF | wERR);
+			need -= (int) strlen(name);
+			wrap_concat("=", need, w2ND | wERR);
+			need -= 1;
+			wrap_concat(buffer, need, wEND | wERR);
+			outcount = TRUE;
 		    }
 		} else {
-		    _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
-				"%s=%s", name, cv);
+		    wrap_concat3(name, "=", cv);
 		}
 		len += (int) strlen(capability) + 1;
-		WRAP_CONCAT;
 	    } else {
 		char *src = _nc_tic_expand(capability,
 					   outform == F_TERMINFO, numbers);
@@ -852,13 +1179,11 @@
 		    strcpy_DYN(&tmpbuf, src);
 		}
 		len += (int) strlen(capability) + 1;
-		wrap_concat(tmpbuf.text);
-		outcount = TRUE;
+		WRAP_CONCAT1(tmpbuf.text);
 	    }
 	}
 	/* e.g., trimmed_sgr0 */
-	if (capability != ABSENT_STRING &&
-	    capability != CANCELLED_STRING &&
+	if (VALID_STRING(capability) &&
 	    capability != tterm->Strings[i])
 	    free(capability);
     }
@@ -947,9 +1272,11 @@
     if (outcount) {
 	bool trimmed = FALSE;
 	j = (PredIdx) outbuf.used;
-	if (j >= 2
-	    && outbuf.text[j - 1] == '\t'
-	    && outbuf.text[j - 2] == '\n') {
+	if (wrapped && did_wrap) {
+	    /* EMPTY */ ;
+	} else if (j >= 2
+		   && outbuf.text[j - 1] == '\t'
+		   && outbuf.text[j - 2] == '\n') {
 	    outbuf.used -= 2;
 	    trimmed = TRUE;
 	} else if (j >= 4
@@ -984,7 +1311,7 @@
 }
 
 static bool
-kill_string(TERMTYPE *tterm, char *cap)
+kill_string(TERMTYPE2 *tterm, const char *const cap)
 {
     unsigned n;
     for (n = 0; n < NUM_STRINGS(tterm); ++n) {
@@ -997,7 +1324,7 @@
 }
 
 static char *
-find_string(TERMTYPE *tterm, char *name)
+find_string(TERMTYPE2 *tterm, char *name)
 {
     PredIdx n;
     for (n = 0; n < NUM_STRINGS(tterm); ++n) {
@@ -1018,16 +1345,18 @@
  * make it smaller.
  */
 static int
-kill_labels(TERMTYPE *tterm, int target)
+kill_labels(TERMTYPE2 *tterm, int target)
 {
     int n;
     int result = 0;
-    char *cap;
-    char name[10];
+    char name[20];
 
     for (n = 0; n <= 10; ++n) {
+	char *cap;
+
 	_nc_SPRINTF(name, _nc_SLIMIT(sizeof(name)) "lf%d", n);
-	if ((cap = find_string(tterm, name)) != ABSENT_STRING
+	cap = find_string(tterm, name);
+	if (VALID_STRING(cap)
 	    && kill_string(tterm, cap)) {
 	    target -= (int) (strlen(cap) + 5);
 	    ++result;
@@ -1043,16 +1372,18 @@
  * make it smaller.
  */
 static int
-kill_fkeys(TERMTYPE *tterm, int target)
+kill_fkeys(TERMTYPE2 *tterm, int target)
 {
     int n;
     int result = 0;
-    char *cap;
-    char name[10];
+    char name[20];
 
     for (n = 60; n >= 0; --n) {
+	char *cap;
+
 	_nc_SPRINTF(name, _nc_SLIMIT(sizeof(name)) "kf%d", n);
-	if ((cap = find_string(tterm, name)) != ABSENT_STRING
+	cap = find_string(tterm, name);
+	if (VALID_STRING(cap)
 	    && kill_string(tterm, cap)) {
 	    target -= (int) (strlen(cap) + 5);
 	    ++result;
@@ -1074,9 +1405,9 @@
 {
     bool result = TRUE;
 
-    if (mapping != ABSENT_STRING) {
+    if (VALID_STRING(mapping)) {
 	int n = 0;
-	while (mapping[n] != '\0') {
+	while (mapping[n] != '\0' && mapping[n + 1] != '\0') {
 	    if (isLine(mapping[n]) &&
 		mapping[n] != mapping[n + 1]) {
 		result = FALSE;
@@ -1097,7 +1428,7 @@
 #define SHOW_WHY PRINTF
 
 static bool
-purged_acs(TERMTYPE *tterm)
+purged_acs(TERMTYPE2 *tterm)
 {
     bool result = FALSE;
 
@@ -1112,22 +1443,103 @@
     return result;
 }
 
+static void
+encode_b64(char *target, char *source, unsigned state, int *saved)
+{
+    /* RFC-4648 */
+    static const char data[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    "abcdefghijklmnopqrstuvwxyz"
+    "0123456789" "-_";
+    int ch = UChar(source[state]);
+
+    switch (state % 3) {
+    case 0:
+	*target++ = data[(ch >> 2) & 077];
+	*saved = (ch << 4);
+	break;
+    case 1:
+	*target++ = data[((ch >> 4) | *saved) & 077];
+	*saved = (ch << 2);
+	break;
+    case 2:
+	*target++ = data[((ch >> 6) | *saved) & 077];
+	*target++ = data[ch & 077];
+	*saved = 0;
+	break;
+    }
+    *target = '\0';
+}
+
 /*
  * Dump a single entry.
  */
 void
-dump_entry(TERMTYPE *tterm,
+dump_entry(TERMTYPE2 *tterm,
 	   int suppress_untranslatable,
 	   int limited,
 	   int numbers,
 	   PredFunc pred)
 {
-    TERMTYPE save_tterm;
-    int len, critlen;
+    TERMTYPE2 save_tterm;
+    int critlen;
     const char *legend;
     bool infodump;
 
-    if (outform == F_TERMCAP || outform == F_TCONVERR) {
+    if (quickdump) {
+	char bigbuf[65536];
+	unsigned offset = 0;
+
+	separator = "";
+	trailer = "\n";
+	indent = 0;
+
+	if (_nc_write_object(tterm, bigbuf, &offset, sizeof(bigbuf)) == OK) {
+	    char numbuf[80];
+	    unsigned n;
+
+	    if (quickdump & 1) {
+		if (outbuf.used)
+		    wrap_concat1("\n");
+		wrap_concat1("hex:");
+		for (n = 0; n < offset; ++n) {
+		    _nc_SPRINTF(numbuf, _nc_SLIMIT(sizeof(numbuf))
+				"%02X", UChar(bigbuf[n]));
+		    wrap_concat1(numbuf);
+		}
+	    }
+	    if (quickdump & 2) {
+		static char padding[] =
+		{0, 0};
+		int value = 0;
+
+		if (outbuf.used)
+		    wrap_concat1("\n");
+		wrap_concat1("b64:");
+		for (n = 0; n < offset; ++n) {
+		    encode_b64(numbuf, bigbuf, n, &value);
+		    wrap_concat1(numbuf);
+		}
+		switch (n % 3) {
+		case 0:
+		    break;
+		case 1:
+		    encode_b64(numbuf, padding, 1, &value);
+		    wrap_concat1(numbuf);
+		    wrap_concat1("==");
+		    break;
+		case 2:
+		    encode_b64(numbuf, padding, 1, &value);
+		    wrap_concat1(numbuf);
+		    wrap_concat1("=");
+		    break;
+		}
+	    }
+	}
+	return;
+    }
+
+    if (TcOutput()) {
 	critlen = MAX_TERMCAP_LENGTH;
 	legend = "older termcap";
 	infodump = FALSE;
@@ -1141,6 +1553,7 @@
     save_sgr = set_attributes;
 
     if ((FMT_ENTRY() > critlen)
+	&& TcOutput()
 	&& limited) {
 
 	save_tterm = *tterm;
@@ -1151,7 +1564,7 @@
 	}
 	if (FMT_ENTRY() > critlen) {
 	    /*
-	     * We pick on sgr because it's a nice long string capability that
+	     * We pick on sgr because it is a nice long string capability that
 	     * is really just an optimization hack.  Another good candidate is
 	     * acsc since it is both long and unused by BSD termcap.
 	     */
@@ -1196,6 +1609,7 @@
 	    }
 	    if (!changed || (FMT_ENTRY() > critlen)) {
 		int oldversion = tversion;
+		int len;
 
 		tversion = V_BSD;
 		SHOW_WHY("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n",
@@ -1216,7 +1630,8 @@
 		}
 		if (len > critlen) {
 		    (void) fprintf(stderr,
-				   "warning: %s entry is %d bytes long\n",
+				   "%s: %s entry is %d bytes long\n",
+				   _nc_progname,
 				   _nc_first_name(tterm->term_names),
 				   len);
 		    SHOW_WHY("# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n",
@@ -1237,16 +1652,26 @@
 }
 
 void
-dump_uses(const char *name, bool infodump)
+dump_uses(const char *value, bool infodump)
 /* dump "use=" clauses in the appropriate format */
 {
-    char buffer[MAX_TERMINFO_LENGTH];
+    char buffer[MAX_TERMINFO_LENGTH + EXTRA_CAP];
+    int limit = (VALID_STRING(value) ? (int) strlen(value) : 0);
+    const char *cap = infodump ? "use" : "tc";
 
-    if (outform == F_TERMCAP || outform == F_TCONVERR)
+    if (TcOutput())
 	trim_trailing();
+    if (limit == 0) {
+	_nc_warning("empty \"%s\" field", cap);
+	value = "";
+    } else if (limit > MAX_ALIAS) {
+	_nc_warning("\"%s\" field too long (%d), limit to %d",
+		    cap, limit, MAX_ALIAS);
+	limit = MAX_ALIAS;
+    }
     _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
-		"%s%s", infodump ? "use=" : "tc=", name);
-    wrap_concat(buffer);
+		"%s=%.*s", cap, limit, value);
+    wrap_concat1(buffer);
 }
 
 int
@@ -1256,7 +1681,7 @@
      * Trim any remaining whitespace.
      */
     if (outbuf.used != 0) {
-	bool infodump = (outform != F_TERMCAP && outform != F_TCONVERR);
+	bool infodump = !TcOutput();
 	char delim = (char) (infodump ? ',' : ':');
 	int j;
 
@@ -1268,7 +1693,7 @@
 		outbuf.used = (size_t) j;
 	    } else if (!infodump && ch == '\\') {
 		outbuf.used = (size_t) j;
-	    } else if (ch == delim && (j == 0 || outbuf.text[j - 1] != '\\')) {
+	    } else if (ch == delim && (outbuf.text[j - 1] != '\\')) {
 		outbuf.used = (size_t) (j + 1);
 	    } else {
 		break;
@@ -1276,14 +1701,16 @@
 	}
 	outbuf.text[outbuf.used] = '\0';
     }
-    (void) fputs(outbuf.text, stdout);
-    putchar('\n');
+    if (outbuf.text != 0) {
+	(void) fputs(outbuf.text, stdout);
+	putchar('\n');
+    }
     return (int) outbuf.used;
 }
 
 void
 compare_entry(PredHook hook,
-	      TERMTYPE *tp GCC_UNUSED,
+	      TERMTYPE2 *tp GCC_UNUSED,
 	      bool quiet)
 /* compare two entries */
 {
@@ -1342,7 +1769,7 @@
 #define CUR tp->
 
 static void
-set_obsolete_termcaps(TERMTYPE *tp)
+set_obsolete_termcaps(TERMTYPE2 *tp)
 {
 #include "capdefaults.c"
 }
@@ -1352,12 +1779,11 @@
  * unique.
  */
 void
-repair_acsc(TERMTYPE *tp)
+repair_acsc(TERMTYPE2 *tp)
 {
     if (VALID_STRING(acs_chars)) {
-	size_t n, m;
+	size_t n;
 	char mapped[256];
-	char extra = 0;
 	unsigned source;
 	unsigned target;
 	bool fix_needed = FALSE;
@@ -1372,7 +1798,11 @@
 	    if (acs_chars[n + 1])
 		n++;
 	}
+
 	if (fix_needed) {
+	    size_t m;
+	    char extra = 0;
+
 	    memset(mapped, 0, sizeof(mapped));
 	    for (n = 0; acs_chars[n] != 0; n++) {
 		source = UChar(acs_chars[n]);
diff --git a/progs/dump_entry.h b/progs/dump_entry.h
index 8b1ebd2..39e856f 100644
--- a/progs/dump_entry.h
+++ b/progs/dump_entry.h
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2014,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            *
@@ -33,7 +34,7 @@
  ****************************************************************************/
 
 /*
- * $Id: dump_entry.h,v 1.35 2015/05/27 00:56:54 tom Exp $
+ * $Id: dump_entry.h,v 1.44 2021/04/18 19:56:09 tom Exp $
  *
  * Dump control definitions and variables
  */
@@ -41,6 +42,11 @@
 #ifndef DUMP_ENTRY_H
 #define DUMP_ENTRY_H 1
 
+#define NCURSES_OPAQUE    0
+#define NCURSES_INTERNALS 1
+#include <curses.h>
+#include <term.h>
+
 /* capability output formats */
 #define F_TERMINFO	0	/* use terminfo names */
 #define F_VARIABLE	1	/* use C variable names */
@@ -61,20 +67,27 @@
 #define CMP_STRING	2	/* comparison on strings */
 #define CMP_USE		3	/* comparison on use capabilities */
 
+#ifndef _TERMSORT_H
 typedef unsigned PredType;
 typedef unsigned PredIdx;
+#endif
+
 typedef int (*PredFunc) (PredType, PredIdx);
 typedef void (*PredHook) (PredType, PredIdx, const char *);
 
 extern NCURSES_CONST char *nametrans(const char *);
-extern bool has_params(const char *src);
-extern int fmt_entry(TERMTYPE *, PredFunc, int, int, int, int);
+extern bool has_params(const char *, bool);
+extern int fmt_entry(TERMTYPE2 *, PredFunc, int, int, int, int);
 extern int show_entry(void);
-extern void compare_entry(PredHook, TERMTYPE *, bool);
-extern void dump_entry(TERMTYPE *, int, int, int, PredFunc);
-extern void dump_init(const char *, int, int, int, int, unsigned, bool, bool);
+extern void compare_entry(PredHook, TERMTYPE2 *, bool);
+extern void dump_entry(TERMTYPE2 *, int, int, int, PredFunc);
+extern void dump_init(const char *, int, int, bool, int, int, unsigned, bool,
+		      bool, int);
 extern void dump_uses(const char *, bool);
-extern void repair_acsc(TERMTYPE *tp);
+extern void repair_acsc(TERMTYPE2 *tp);
+
+#define L_CURL "{"
+#define R_CURL "}"
 
 #define FAIL	-1
 
diff --git a/progs/infocmp b/progs/infocmp
deleted file mode 100755
index 8d0bc80..0000000
--- a/progs/infocmp
+++ /dev/null
Binary files differ
diff --git a/progs/infocmp.c b/progs/infocmp.c
index d3fdc52..7932203 100644
--- a/progs/infocmp.c
+++ b/progs/infocmp.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2014,2015 Free Software Foundation, Inc.              *
+ * Copyright 2020-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            *
@@ -42,10 +43,7 @@
 
 #include <dump_entry.h>
 
-MODULE_ID("$Id: infocmp.c,v 1.133 2015/05/27 00:57:41 tom Exp $")
-
-#define L_CURL "{"
-#define R_CURL "}"
+MODULE_ID("$Id: infocmp.c,v 1.163 2023/12/16 17:27:47 tom Exp $")
 
 #define MAX_STRING	1024	/* maximum formatted string */
 
@@ -96,7 +94,7 @@
 static ENTERED *entered;
 
 #undef ExitProgram
-static void ExitProgram(int code) GCC_NORETURN;
+static GCC_NORETURN void ExitProgram(int code);
 /* prototype is to get gcc to accept the noreturn attribute */
 static void
 ExitProgram(int code)
@@ -126,17 +124,46 @@
     ExitProgram(EXIT_FAILURE);
 }
 
-static char *
-canonical_name(char *ptr, char *buf)
+static void
+canonical_name(char *source, char *target)
 /* extract the terminal type's primary name */
 {
-    char *bp;
+    int limit = NAMESIZE;
 
-    _nc_STRCPY(buf, ptr, NAMESIZE);
-    if ((bp = strchr(buf, '|')) != 0)
-	*bp = '\0';
+    while (--limit > 0) {
+	char ch = *source++;
+	if (ch == '|')
+	    break;
+	*target++ = ch;
+    }
+    *target = '\0';
+}
 
-    return (buf);
+static bool
+no_boolean(int value)
+{
+    bool result = (value == ABSENT_BOOLEAN);
+    if (!strcmp(s_absent, s_cancel))
+	result = !VALID_BOOLEAN(value);
+    return result;
+}
+
+static bool
+no_numeric(int value)
+{
+    bool result = (value == ABSENT_NUMERIC);
+    if (!strcmp(s_absent, s_cancel))
+	result = !VALID_NUMERIC(value);
+    return result;
+}
+
+static bool
+no_string(const char *const value)
+{
+    bool result = (value == ABSENT_STRING);
+    if (!strcmp(s_absent, s_cancel))
+	result = !VALID_STRING(value);
+    return result;
 }
 
 /***************************************************************************
@@ -160,10 +187,21 @@
 	return (_nc_capcmp(s, t));
 }
 
+/*
+ * Predicate function to use for "use=" decompilation.
+ *
+ * Return value is used in fmt_entry:
+ *   FAIL  show nothing for this capability.
+ *   FALSE show cancel for booleans (a compromise)
+ *   TRUE  show capability
+ *
+ * The only difference between FALSE/TRUE returns is in the treatment of
+ * booleans.
+ */
 static int
 use_predicate(unsigned type, PredIdx idx)
-/* predicate function to use for use decompilation */
 {
+    int result = FAIL;
     ENTRY *ep;
 
     switch (type) {
@@ -182,16 +220,18 @@
 	     * unlike numbers and strings, whose cancelled/absent state is
 	     * recorded in the terminfo database.
 	     */
-	    for (ep = &entries[1]; ep < entries + termcount; ep++)
-		if (ep->tterm.Booleans[idx] == TRUE) {
-		    is_set = entries[0].tterm.Booleans[idx];
-		    break;
+	    if (idx < NUM_BOOLEANS(&(entries[0].tterm))) {
+		for (ep = &entries[1]; ep < entries + termcount; ep++) {
+		    if (idx < NUM_BOOLEANS(&(ep->tterm))
+			&& (is_set = ep->tterm.Booleans[idx])) {
+			break;
+		    }
 		}
-	    if (is_set != entries[0].tterm.Booleans[idx])
-		return (!is_set);
-	    else
-		return (FAIL);
+		if (is_set != entries[0].tterm.Booleans[idx])
+		    result = (!is_set);
+	    }
 	}
+	break;
 
     case NUMBER:
 	{
@@ -202,45 +242,56 @@
 	     * capability gets the first non-default value found
 	     * in the sequence of use entries'.
 	     */
-	    for (ep = &entries[1]; ep < entries + termcount; ep++)
-		if (VALID_NUMERIC(ep->tterm.Numbers[idx])) {
-		    value = ep->tterm.Numbers[idx];
-		    break;
-		}
+	    if (idx < NUM_NUMBERS(&(entries[0].tterm))) {
+		for (ep = &entries[1]; ep < entries + termcount; ep++)
+		    if (idx < NUM_NUMBERS(&(ep->tterm))
+			&& VALID_NUMERIC(ep->tterm.Numbers[idx])) {
+			value = ep->tterm.Numbers[idx];
+			break;
+		    }
 
-	    if (value != entries[0].tterm.Numbers[idx])
-		return (value != ABSENT_NUMERIC);
-	    else
-		return (FAIL);
+		if (value != entries[0].tterm.Numbers[idx])
+		    result = (value != ABSENT_NUMERIC);
+	    }
 	}
+	break;
 
     case STRING:
 	{
-	    char *termstr, *usestr = ABSENT_STRING;
-
-	    termstr = entries[0].tterm.Strings[idx];
+	    char *termstr = entries[0].tterm.Strings[idx];
+	    char *usestr = ABSENT_STRING;
 
 	    /*
 	     * We take the semantics of multiple uses to be 'each
 	     * capability gets the first non-default value found
 	     * in the sequence of use entries'.
 	     */
-	    for (ep = &entries[1]; ep < entries + termcount; ep++)
-		if (ep->tterm.Strings[idx]) {
-		    usestr = ep->tterm.Strings[idx];
-		    break;
-		}
+	    if (idx < NUM_STRINGS(&(entries[0].tterm))) {
+		for (ep = &entries[1]; ep < entries + termcount; ep++)
+		    if (idx < NUM_STRINGS(&(ep->tterm))
+			&& ep->tterm.Strings[idx]) {
+			usestr = ep->tterm.Strings[idx];
+			break;
+		    }
 
-	    if (usestr == ABSENT_STRING && termstr == ABSENT_STRING)
-		return (FAIL);
-	    else if (!usestr || !termstr || capcmp(idx, usestr, termstr))
-		return (TRUE);
-	    else
-		return (FAIL);
+		if (usestr == CANCELLED_STRING && termstr == ABSENT_STRING)
+		    result = (FAIL);
+		else if (usestr == CANCELLED_STRING && termstr == CANCELLED_STRING)
+		    result = (TRUE);
+		else if (usestr == ABSENT_STRING && termstr == ABSENT_STRING)
+		    result = (FAIL);
+		else if (!usestr || !termstr || capcmp(idx, usestr, termstr))
+		    result = (TRUE);
+	    }
 	}
+	break;
+
+    default:
+	result = FALSE;
+	break;
     }
 
-    return (FALSE);		/* pacify compiler */
+    return (result);
 }
 
 static bool
@@ -271,7 +322,7 @@
 }
 
 static bool
-entryeq(TERMTYPE *t1, TERMTYPE *t2)
+entryeq(TERMTYPE2 *t1, TERMTYPE2 *t2)
 /* are two entries equivalent? */
 {
     unsigned i;
@@ -297,16 +348,17 @@
 print_uses(ENTRY * ep, FILE *fp)
 /* print an entry's use references */
 {
-    unsigned i;
-
-    if (!ep->nuses)
+    if (!ep->nuses) {
 	fputs("NULL", fp);
-    else
+    } else {
+	unsigned i;
+
 	for (i = 0; i < ep->nuses; i++) {
 	    fputs(ep->uses[i].name, fp);
 	    if (i < ep->nuses - 1)
 		fputs(" ", fp);
 	}
+    }
 }
 
 static const char *
@@ -329,7 +381,7 @@
 
 static void
 dump_numeric(int val, char *buf)
-/* display the value of a boolean capability */
+/* display the value of a numeric capability */
 {
     switch (val) {
     case ABSENT_NUMERIC:
@@ -393,7 +445,7 @@
 
 /*
  * ncurses stores two types of non-standard capabilities:
- * a) capabilities listed past the "STOP-HERE" comment in the Caps file. 
+ * a) capabilities listed past the "STOP-HERE" comment in the Caps file.
  *    These are used in the terminfo source file to provide data for termcaps,
  *    e.g., when there is no equivalent capability in terminfo, as well as for
  *    widely-used non-standard capabilities.
@@ -437,7 +489,7 @@
 	switch (compare) {
 	case C_DIFFERENCE:
 	    b2 = next_entry->Booleans[idx];
-	    if (!(b1 == ABSENT_BOOLEAN && b2 == ABSENT_BOOLEAN) && b1 != b2)
+	    if (!(no_boolean(b1) && no_boolean(b2)) && (b1 != b2))
 		(void) printf("\t%s: %s%s%s.\n",
 			      name,
 			      dump_boolean(b1),
@@ -485,7 +537,7 @@
 	switch (compare) {
 	case C_DIFFERENCE:
 	    n2 = next_entry->Numbers[idx];
-	    if (!((n1 == ABSENT_NUMERIC && n2 == ABSENT_NUMERIC)) && n1 != n2) {
+	    if (!(no_numeric(n1) && no_numeric(n2)) && n1 != n2) {
 		dump_numeric(n1, buf1);
 		dump_numeric(n2, buf2);
 		(void) printf("\t%s: %s, %s.\n", name, buf1, buf2);
@@ -533,7 +585,7 @@
 	switch (compare) {
 	case C_DIFFERENCE:
 	    s2 = next_entry->Strings[idx];
-	    if (capcmp(idx, s1, s2)) {
+	    if (!(no_string(s1) && no_string(s2)) && capcmp(idx, s1, s2)) {
 		dump_string(s1, buf1);
 		dump_string(s2, buf2);
 		if (strcmp(buf1, buf2))
@@ -786,7 +838,7 @@
 }
 
 static void
-analyze_string(const char *name, const char *cap, TERMTYPE *tp)
+analyze_string(const char *name, const char *cap, TERMTYPE2 *tp)
 {
     char buf2[MAX_TERMINFO_LENGTH];
     const char *sp;
@@ -810,6 +862,8 @@
 	    char *cp = tp->Strings[i];
 
 	    /* don't use function-key capabilities */
+	    if (strnames[i] == NULL)
+		continue;
 	    if (strnames[i][0] == 'k' && strnames[i][1] == 'f')
 		continue;
 
@@ -817,7 +871,7 @@
 		cp[0] != '\0' &&
 		cp != cap) {
 		len = strlen(cp);
-		(void) strncpy(buf2, sp, len);
+		_nc_STRNCPY(buf2, sp, len);
 		buf2[len] = '\0';
 
 		if (_nc_capcmp(cp, buf2))
@@ -873,9 +927,8 @@
 			? "ECMA+"
 			: "ECMA-"),
 		       sizeof(buf2));
-	    (void) strncpy(buf3, sp + csi, len);
+	    _nc_STRNCPY(buf3, sp + csi, len);
 	    buf3[len] = '\0';
-	    len += (size_t) csi + 1;
 
 	    expansion = lookup_params(std_modes, buf2, buf3);
 	}
@@ -894,9 +947,8 @@
 			? "DEC+"
 			: "DEC-"),
 		       sizeof(buf2));
-	    (void) strncpy(buf3, sp + csi + 1, len);
+	    _nc_STRNCPY(buf3, sp + csi + 1, len);
 	    buf3[len] = '\0';
-	    len += (size_t) csi + 2;
 
 	    expansion = lookup_params(private_modes, buf2, buf3);
 	}
@@ -910,7 +962,7 @@
 	    && sp[next] == 'm') {
 
 	    _nc_STRCPY(buf2, "SGR:", sizeof(buf2));
-	    (void) strncpy(buf3, sp + csi, len);
+	    _nc_STRNCPY(buf3, sp + csi, len);
 	    buf3[len] = '\0';
 	    len += (size_t) csi + 1;
 
@@ -989,7 +1041,8 @@
     int i, n;
 
     memset(heads, 0, sizeof(heads));
-    dump_init((char *) 0, F_LITERAL, S_TERMINFO, 0, 65535, itrace, FALSE, FALSE);
+    dump_init((char *) 0, F_LITERAL, S_TERMINFO,
+	      FALSE, 0, 65535, itrace, FALSE, FALSE, FALSE);
 
     for (n = 0; n < argc && n < MAXCOMPARE; n++) {
 	if (freopen(argv[n], "r", stdin) == 0)
@@ -1103,8 +1156,8 @@
 	    if (entryeq(&qp->tterm, &rp->tterm) && useeq(qp, rp)) {
 		char name1[NAMESIZE], name2[NAMESIZE];
 
-		(void) canonical_name(qp->tterm.term_names, name1);
-		(void) canonical_name(rp->tterm.term_names, name2);
+		canonical_name(qp->tterm.term_names, name1);
+		canonical_name(rp->tterm.term_names, name2);
 
 		(void) printf("%s = %s\n", name1, name2);
 	    }
@@ -1132,8 +1185,8 @@
 		entries[0] = *qp;
 		entries[1] = *rp;
 
-		(void) canonical_name(qp->tterm.term_names, name1);
-		(void) canonical_name(rp->tterm.term_names, name2);
+		canonical_name(qp->tterm.term_names, name1);
+		canonical_name(rp->tterm.term_names, name2);
 
 		switch (compare) {
 		case C_DIFFERENCE:
@@ -1168,35 +1221,38 @@
 	DATA("Options:")
     };
 #undef DATA
+    /* length is given here so the compiler can make everything readonly */
 #define DATA(s) s
-    static const char options[][45] =
+    static const char options[][46] =
     {
 	"  -0    print single-row"
 	,"  -1    print single-column"
-	,"  -K    use termcap-names and BSD syntax"
 	,"  -C    use termcap-names"
+	,"  -D    print database locations"
+	,"  -E    format output as C tables"
 	,"  -F    compare terminfo-files"
+	,"  -G    format %{number} to %'char'"
 	,"  -I    use terminfo-names"
+	,"  -K    use termcap-names and BSD syntax"
 	,"  -L    use long names"
 	,"  -R subset (see manpage)"
 	,"  -T    eliminate size limits (test)"
 	,"  -U    do not post-process entries"
-	,"  -D    print database locations"
 	,"  -V    print version"
+	,"  -W    wrap long strings per -w[n]"
 #if NCURSES_XNAMES
 	,"  -a    with -F, list commented-out caps"
 #endif
 	,"  -c    list common capabilities"
 	,"  -d    list different capabilities"
 	,"  -e    format output for C initializer"
-	,"  -E    format output as C tables"
 	,"  -f    with -1, format complex strings"
-	,"  -G    format %{number} to %'char'"
 	,"  -g    format %'char' to %{number}"
 	,"  -i    analyze initialization/reset"
 	,"  -l    output terminfo names"
 	,"  -n    list capabilities in neither"
 	,"  -p    ignore padding specifiers"
+	,"  -Q number  dump compiled description"
 	,"  -q    brief listing, removes headers"
 	,"  -r    with -C, output in termcap form"
 	,"  -r    with -F, resolve use-references"
@@ -1267,7 +1323,7 @@
 
 /* dump C initializers for the terminal type */
 static void
-dump_initializers(TERMTYPE *term)
+dump_initializers(TERMTYPE2 *term)
 {
     unsigned n;
     const char *str = 0;
@@ -1276,9 +1332,9 @@
 	   name_initializer("alias"), entries->tterm.term_names);
 
     for_each_string(n, term) {
-	char buf[MAX_STRING], *sp, *tp;
-
 	if (VALID_STRING(term->Strings[n])) {
+	    char buf[MAX_STRING], *sp, *tp;
+
 	    tp = buf;
 #define TP_LIMIT	((MAX_STRING - 5) - (size_t)(tp - buf))
 	    *tp++ = '"';
@@ -1391,7 +1447,7 @@
 
 /* dump C initializers for the terminal type */
 static void
-dump_termtype(TERMTYPE *term)
+dump_termtype(TERMTYPE2 *term)
 {
     (void) printf("\t%s\n\t\t%s,\n", L_CURL, name_initializer("alias"));
     (void) printf("\t\t(char *)0,\t/* pointer to string table */\n");
@@ -1481,6 +1537,8 @@
 
 #if NO_LEAKS
 #define MAIN_LEAKS() \
+    _nc_free_termtype2(&entries[0].tterm); \
+    _nc_free_termtype2(&entries[1].tterm); \
     free(myargv); \
     free(tfile); \
     free(tname)
@@ -1500,12 +1558,14 @@
     char **myargv;
 
     char *firstdir, *restdir;
-    int c, i, len;
+    int c;
     bool formatted = FALSE;
     bool filecompare = FALSE;
     int initdump = 0;
     bool init_analyze = FALSE;
     bool suppress_untranslatable = FALSE;
+    int quickdump = 0;
+    bool wrap_strings = FALSE;
 
     /* where is the terminfo database location going to default to? */
     restdir = firstdir = 0;
@@ -1527,7 +1587,7 @@
 
     while ((c = getopt(argc,
 		       argv,
-		       "01A:aB:CcDdEeFfGgIiKLlnpqR:rs:TtUuVv:w:x")) != -1) {
+		       "01A:aB:CcDdEeFfGgIiKLlnpQ:qR:rs:TtUuVv:Ww:x")) != -1) {
 	switch (c) {
 	case '0':
 	    mwidth = 65535;
@@ -1628,6 +1688,10 @@
 	    ignorepads = TRUE;
 	    break;
 
+	case 'Q':
+	    quickdump = optarg_to_number();
+	    break;
+
 	case 'q':
 	    quiet = TRUE;
 	    s_absent = "-";
@@ -1685,7 +1749,11 @@
 
 	case 'v':
 	    itrace = (unsigned) optarg_to_number();
-	    set_trace_level(itrace);
+	    use_verbosity(itrace);
+	    break;
+
+	case 'W':
+	    wrap_strings = TRUE;
 	    break;
 
 	case 'w':
@@ -1750,8 +1818,9 @@
     }
 
     /* set up for display */
-    dump_init(tversion, outform, sortmode, mwidth, mheight, itrace,
-	      formatted, FALSE);
+    dump_init(tversion, outform, sortmode,
+	      wrap_strings, mwidth, mheight, itrace,
+	      formatted, FALSE, quickdump);
 
     if (!filecompare) {
 	/* grab the entries */
@@ -1795,9 +1864,9 @@
 				   _nc_progname,
 				   tname[termcount]);
 
-		status = _nc_read_entry(tname[termcount],
-					tfile[termcount],
-					&entries[termcount].tterm);
+		status = _nc_read_entry2(tname[termcount],
+					 tfile[termcount],
+					 &entries[termcount].tterm);
 	    }
 
 	    if (status <= 0) {
@@ -1813,8 +1882,16 @@
 	}
 
 #if NCURSES_XNAMES
-	if (termcount > 1)
-	    _nc_align_termtype(&entries[0].tterm, &entries[1].tterm);
+	if (termcount > 1) {
+	    /*
+	     * User-defined capabilities in different terminal descriptions
+	     * may have the same name/type but different indices.  Line up
+	     * the names to use comparable indices.  We may have more than two
+	     * entries to compare when processing the "-u" option.
+	     */
+	    for (c = 1; c < termcount; ++c)
+		_nc_align_termtype(&entries[c].tterm, &entries[0].tterm);
+	}
 #endif
 
 	/* dump as C initializer for the terminal type */
@@ -1841,6 +1918,8 @@
 	    analyze_string("rmkx", keypad_local, &entries[0].tterm);
 #undef CUR
 	} else {
+	    int i;
+	    int len;
 
 	    /*
 	     * Here's where the real work gets done
@@ -1852,8 +1931,10 @@
 				   "%s: about to dump %s\n",
 				   _nc_progname,
 				   tname[0]);
-		(void) printf("#\tReconstructed via infocmp from file: %s\n",
-			      tfile[0]);
+		if (!quiet)
+		    (void)
+			printf("#\tReconstructed via infocmp from file: %s\n",
+			       tfile[0]);
 		dump_entry(&entries[0].tterm,
 			   suppress_untranslatable,
 			   limited,
diff --git a/progs/modules b/progs/modules
index c09d2a6..349061f 100644
--- a/progs/modules
+++ b/progs/modules
@@ -1,7 +1,8 @@
-# $Id: modules,v 1.18 2014/05/21 17:01:28 tom Exp $
+# $Id: modules,v 1.25 2021/04/18 17:21:03 tom Exp $
 # Program modules (some are in ncurses lib!)
 ##############################################################################
-# Copyright (c) 1998-2010,2014 Free Software Foundation, Inc.                #
+# Copyright 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 "Software"), #
@@ -32,15 +33,18 @@
 #
 
 @ base
-clear		progs		$(srcdir)	$(HEADER_DEPS)
+clear		progs		$(srcdir)	$(HEADER_DEPS) tty_settings.h
 tic		progs		$(srcdir)	$(HEADER_DEPS) transform.h $(srcdir)/dump_entry.h $(srcdir)/tparm_type.h
 toe		progs		$(srcdir)	$(HEADER_DEPS)             $(INCDIR)/hashed_db.h
-dump_entry	progs		$(srcdir)	$(HEADER_DEPS)             $(srcdir)/dump_entry.h ../include/parametrized.h $(INCDIR)/capdefaults.c termsort.c
+clear_cmd	progs		$(srcdir)	$(HEADER_DEPS) clear_cmd.h
+dump_entry	progs		$(srcdir)	$(HEADER_DEPS)             $(srcdir)/dump_entry.h ../include/parametrized.h $(INCDIR)/capdefaults.c termsort.h
 infocmp		progs		$(srcdir)	$(HEADER_DEPS)             $(srcdir)/dump_entry.h
+reset_cmd	progs		$(srcdir)	$(HEADER_DEPS) reset_cmd.h tty_settings.h
 tabs		progs		$(srcdir)	$(HEADER_DEPS)
 tparm_type	progs		$(srcdir)	$(HEADER_DEPS)             $(srcdir)/tparm_type.h
-tput		progs		$(srcdir)	$(HEADER_DEPS) transform.h $(srcdir)/dump_entry.h $(srcdir)/tparm_type.h termsort.c
-tset		progs		$(srcdir)	$(HEADER_DEPS) transform.h $(srcdir)/dump_entry.h ../include/termcap.h
+tput		progs		$(srcdir)	$(HEADER_DEPS) transform.h $(srcdir)/tparm_type.h reset_cmd.h tty_settings.h
+tset		progs		$(srcdir)	$(HEADER_DEPS) transform.h ../include/termcap.h reset_cmd.h  tty_settings.h
 transform	progs		$(srcdir)	$(HEADER_DEPS) transform.h
+tty_settings	progs		$(srcdir)	$(HEADER_DEPS) tty_settings.h
 
 # vile:makemode
diff --git a/progs/progs.priv.h b/progs/progs.priv.h
index 786fe55..fea18b8 100644
--- a/progs/progs.priv.h
+++ b/progs/progs.priv.h
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2014,2015 Free Software Foundation, Inc.              *
+ * Copyright 2019-2022,2024 Thomas E. Dickey                                *
+ * Copyright 1998-2015,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            *
@@ -30,7 +31,7 @@
  *  Author: Thomas E. Dickey                    1997-on                     *
  ****************************************************************************/
 /*
- * $Id: progs.priv.h,v 1.41 2015/05/23 23:53:55 tom Exp $
+ * $Id: progs.priv.h,v 1.62 2024/04/08 17:28:28 tom Exp $
  *
  *	progs.priv.h
  *
@@ -40,32 +41,9 @@
 #ifndef PROGS_PRIV_H
 #define PROGS_PRIV_H 1
 
-#include <ncurses_cfg.h>
+#include <curses.priv.h>
 
-#if USE_RCS_IDS
-#define MODULE_ID(id) static const char Ident[] = id;
-#else
-#define MODULE_ID(id)		/*nothing */
-#endif
-
-#include <stdlib.h>
 #include <ctype.h>
-#include <string.h>
-#include <sys/types.h>
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#if HAVE_SYS_BSDTYPES_H
-#include <sys/bsdtypes.h>	/* needed for ISC */
-#endif
-
-#if HAVE_LIMITS_H
-# include <limits.h>
-#elif HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
 
 #if HAVE_DIRENT_H
 # include <dirent.h>
@@ -93,21 +71,6 @@
 # endif
 #endif
 
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-#  include <stdint.h>
-# endif
-#endif
-
-#include <assert.h>
-#include <errno.h>
-
-#if DECL_ERRNO
-extern int errno;
-#endif
-
 #if HAVE_GETOPT_H
 #include <getopt.h>
 #elif !defined(HAVE_GETOPT_HEADER)
@@ -118,81 +81,22 @@
 extern int optind;
 #endif /* HAVE_GETOPT_H */
 
-#include <curses.h>
-#include <term_entry.h>
-#include <nc_termios.h>
 #include <tic.h>
-#include <nc_tparm.h>
 
-#include <nc_string.h>
-#include <nc_alloc.h>
 #if HAVE_NC_FREEALL
 #undef ExitProgram
 #ifdef USE_LIBTINFO
-#define ExitProgram(code) _nc_free_tinfo(code)
+#define ExitProgram(code) exit_terminfo(code)
 #else
 #define ExitProgram(code) _nc_free_tic(code)
 #endif
 #endif
 
-#if defined(__GNUC__) && defined(_FORTIFY_SOURCE)
-#define IGNORE_RC(func) errno = (int) func
-#else
-#define IGNORE_RC(func) (void) func
-#endif /* gcc workarounds */
-
-/* usually in <unistd.h> */
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO 1
-#endif
-
-#ifndef STDERR_FILENO
-#define STDERR_FILENO 2
-#endif
-
-#ifndef EXIT_SUCCESS
-#define EXIT_SUCCESS 0
-#endif
-
-#ifndef EXIT_FAILURE
-#define EXIT_FAILURE 1
-#endif
-
-#ifndef R_OK
-#define	R_OK	4		/* Test for readable.  */
-#endif
-
-#ifndef W_OK
-#define	W_OK	2		/* Test for writable.  */
-#endif
-
-#ifndef X_OK
-#define	X_OK	1		/* Test for executable.  */
-#endif
-
-#ifndef F_OK
-#define	F_OK	0		/* Test for existence.  */
-#endif
-
-/* usually in <unistd.h> */
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO 1
-#endif
-
-#ifndef STDERR_FILENO
-#define STDERR_FILENO 2
-#endif
-
-/* may be in limits.h, included from various places */
-#ifndef PATH_MAX
-# if defined(_POSIX_PATH_MAX)
-#  define PATH_MAX _POSIX_PATH_MAX
-# elif defined(MAXPATHLEN)
-#  define PATH_MAX MAXPATHLEN
-# else
-#  define PATH_MAX 255		/* the Posix minimum pathsize */
-# endif
-#endif
+/* error-returns for tput */
+#define ErrUsage	2
+#define ErrTermType	3
+#define ErrCapName	4
+#define ErrSystem(n)	(4 + (n))
 
 /* We use isascii only to guard against use of 7-bit ctype tables in the
  * isprint test in infocmp.
@@ -206,8 +110,28 @@
 # endif
 #endif
 
-#define UChar(c)    ((unsigned char)(c))
+#define VtoTrace(opt) (unsigned) ((opt > 0) ? opt : (opt == 0))
 
-#define SIZEOF(v) (sizeof(v)/sizeof(v[0]))
+/*
+ * If configured for tracing, the debug- and trace-output are merged together
+ * in the trace file for "upper" levels of the verbose option.
+ */
+#ifdef TRACE
+#define use_verbosity(level) do { \
+ 		set_trace_level(level); \
+		if (_nc_tracing > DEBUG_LEVEL(2)) \
+		    _nc_tracing |= TRACE_MAXIMUM; \
+		else if (_nc_tracing == DEBUG_LEVEL(2)) \
+		    _nc_tracing |= TRACE_ORDINARY; \
+		if (level >= 2) \
+		    curses_trace(_nc_tracing); \
+	} while (0)
+#else
+#define use_verbosity(level) do { set_trace_level(level); } while (0)
+#endif
+
+#ifndef CUR
+#define CUR ((TERMTYPE *)(cur_term))->
+#endif
 
 #endif /* PROGS_PRIV_H */
diff --git a/progs/reset_cmd.c b/progs/reset_cmd.c
new file mode 100644
index 0000000..6ae3b67
--- /dev/null
+++ b/progs/reset_cmd.c
@@ -0,0 +1,697 @@
+/****************************************************************************
+ * Copyright 2019-2023,2024 Thomas E. Dickey                                *
+ * Copyright 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"), 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                                                *
+ ****************************************************************************/
+
+#include <reset_cmd.h>
+#include <tty_settings.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#if HAVE_SIZECHANGE
+# if !defined(sun) || !TERMIOS
+#  if HAVE_SYS_IOCTL_H
+#   include <sys/ioctl.h>
+#  endif
+# endif
+#endif
+
+#if NEED_PTEM_H
+/* they neglected to define struct winsize in termios.h -- it is only
+   in termio.h	*/
+#include <sys/stream.h>
+#include <sys/ptem.h>
+#endif
+
+MODULE_ID("$Id: reset_cmd.c,v 1.37 2024/04/08 17:29:34 tom Exp $")
+
+/*
+ * SCO defines TIOCGSIZE and the corresponding struct.  Other systems (SunOS,
+ * Solaris, IRIX) define TIOCGWINSZ and struct winsize.
+ */
+#ifdef TIOCGSIZE
+# define IOCTL_GET_WINSIZE TIOCGSIZE
+# define IOCTL_SET_WINSIZE TIOCSSIZE
+# define STRUCT_WINSIZE struct ttysize
+# define WINSIZE_ROWS(n) n.ts_lines
+# define WINSIZE_COLS(n) n.ts_cols
+#else
+# ifdef TIOCGWINSZ
+#  define IOCTL_GET_WINSIZE TIOCGWINSZ
+#  define IOCTL_SET_WINSIZE TIOCSWINSZ
+#  define STRUCT_WINSIZE struct winsize
+#  define WINSIZE_ROWS(n) n.ws_row
+#  define WINSIZE_COLS(n) n.ws_col
+# endif
+#endif
+
+#define set_flags(target, mask)    target |= mask
+#define clear_flags(target, mask)  target &= ~((unsigned)(mask))
+
+static FILE *my_file;
+
+static bool use_reset = FALSE;	/* invoked as reset */
+static bool use_init = FALSE;	/* invoked as init */
+
+static GCC_NORETURN void
+failed(const char *msg)
+{
+    int code = errno;
+
+    (void) fprintf(stderr, "%s: %s: %s\n", _nc_progname, msg, strerror(code));
+    restore_tty_settings();
+    (void) fprintf(my_file, "\n");
+    fflush(my_file);
+    ExitProgram(ErrSystem(code));
+    /* NOTREACHED */
+}
+
+static bool
+cat_file(char *file)
+{
+    FILE *fp;
+    size_t nr;
+    char buf[BUFSIZ];
+    bool sent = FALSE;
+
+    if (file != 0) {
+	if ((fp = safe_fopen(file, "r")) == 0)
+	    failed(file);
+
+	while ((nr = fread(buf, sizeof(char), sizeof(buf), fp)) != 0) {
+	    if (fwrite(buf, sizeof(char), nr, my_file) != nr) {
+		failed(file);
+	    }
+	    sent = TRUE;
+	}
+	fclose(fp);
+    }
+    return sent;
+}
+
+static int
+out_char(int c)
+{
+    return putc(c, my_file);
+}
+
+/**************************************************************************
+ * Mode-setting logic
+ **************************************************************************/
+
+/* some BSD systems have these built in, some systems are missing
+ * one or more definitions. The safest solution is to override unless the
+ * commonly-altered ones are defined.
+ */
+#if !(defined(CERASE) && defined(CINTR) && defined(CKILL) && defined(CQUIT))
+#undef CEOF
+#undef CERASE
+#undef CINTR
+#undef CKILL
+#undef CLNEXT
+#undef CRPRNT
+#undef CQUIT
+#undef CSTART
+#undef CSTOP
+#undef CSUSP
+#endif
+
+/* control-character defaults */
+#ifndef CEOF
+#define CEOF	CTRL('D')
+#endif
+#ifndef CERASE
+#define CERASE	CTRL('H')
+#endif
+#ifndef CINTR
+#define CINTR	127		/* ^? */
+#endif
+#ifndef CKILL
+#define CKILL	CTRL('U')
+#endif
+#ifndef CLNEXT
+#define CLNEXT  CTRL('v')
+#endif
+#ifndef CRPRNT
+#define CRPRNT  CTRL('r')
+#endif
+#ifndef CQUIT
+#define CQUIT	CTRL('\\')
+#endif
+#ifndef CSTART
+#define CSTART	CTRL('Q')
+#endif
+#ifndef CSTOP
+#define CSTOP	CTRL('S')
+#endif
+#ifndef CSUSP
+#define CSUSP	CTRL('Z')
+#endif
+
+#if defined(_POSIX_VDISABLE)
+#define DISABLED(val)   (((_POSIX_VDISABLE != -1) \
+		       && ((val) == _POSIX_VDISABLE)) \
+		      || ((val) <= 0))
+#else
+#define DISABLED(val)   ((int)(val) <= 0)
+#endif
+
+#define CHK(val, dft)   (unsigned char) (DISABLED(val) ? dft : val)
+
+#define reset_char(item, value) \
+    tty_settings->c_cc[item] = CHK(tty_settings->c_cc[item], value)
+
+/*
+ * Simplify ifdefs
+ */
+#ifndef BSDLY
+#define BSDLY 0
+#endif
+#ifndef CRDLY
+#define CRDLY 0
+#endif
+#ifndef ECHOCTL
+#define ECHOCTL 0
+#endif
+#ifndef ECHOKE
+#define ECHOKE 0
+#endif
+#ifndef ECHOPRT
+#define ECHOPRT 0
+#endif
+#ifndef FFDLY
+#define FFDLY 0
+#endif
+#ifndef IMAXBEL
+#define IMAXBEL 0
+#endif
+#ifndef IUCLC
+#define IUCLC 0
+#endif
+#ifndef IXANY
+#define IXANY 0
+#endif
+#ifndef NLDLY
+#define NLDLY 0
+#endif
+#ifndef OCRNL
+#define OCRNL 0
+#endif
+#ifndef OFDEL
+#define OFDEL 0
+#endif
+#ifndef OFILL
+#define OFILL 0
+#endif
+#ifndef OLCUC
+#define OLCUC 0
+#endif
+#ifndef ONLCR
+#define ONLCR 0
+#endif
+#ifndef ONLRET
+#define ONLRET 0
+#endif
+#ifndef ONOCR
+#define ONOCR 0
+#endif
+#ifndef OXTABS
+#define OXTABS 0
+#endif
+#ifndef TAB3
+#define TAB3 0
+#endif
+#ifndef TABDLY
+#define TABDLY 0
+#endif
+#ifndef TOSTOP
+#define TOSTOP 0
+#endif
+#ifndef VTDLY
+#define VTDLY 0
+#endif
+#ifndef XCASE
+#define XCASE 0
+#endif
+
+/*
+ * Reset the terminal mode bits to a sensible state.  Very useful after
+ * a child program dies in raw mode.
+ */
+void
+reset_tty_settings(int fd, TTY * tty_settings, int noset)
+{
+    unsigned mask;
+#ifdef TIOCMGET
+    int modem_bits;
+#endif
+
+    GET_TTY(fd, tty_settings);
+
+#ifdef TERMIOS
+#if defined(VDISCARD) && defined(CDISCARD)
+    reset_char(VDISCARD, CDISCARD);
+#endif
+    reset_char(VEOF, CEOF);
+    reset_char(VERASE, CERASE);
+#if defined(VERASE2) && defined(CERASE2)
+    reset_char(VERASE2, CERASE2);
+#endif
+#if defined(VFLUSH) && defined(CFLUSH)
+    reset_char(VFLUSH, CFLUSH);
+#endif
+    reset_char(VINTR, CINTR);
+    reset_char(VKILL, CKILL);
+#if defined(VLNEXT) && defined(CLNEXT)
+    reset_char(VLNEXT, CLNEXT);
+#endif
+    reset_char(VQUIT, CQUIT);
+#if defined(VREPRINT) && defined(CRPRNT)
+    reset_char(VREPRINT, CRPRNT);
+#endif
+#if defined(VSTART) && defined(CSTART)
+    reset_char(VSTART, CSTART);
+#endif
+#if defined(VSTOP) && defined(CSTOP)
+    reset_char(VSTOP, CSTOP);
+#endif
+#if defined(VSUSP) && defined(CSUSP)
+    reset_char(VSUSP, CSUSP);
+#endif
+#if defined(VWERASE) && defined(CWERASE)
+    reset_char(VWERASE, CWERASE);
+#endif
+
+    clear_flags(tty_settings->c_iflag, (IGNBRK
+					| PARMRK
+					| INPCK
+					| ISTRIP
+					| INLCR
+					| IGNCR
+					| IUCLC
+					| IXANY
+					| IXOFF));
+
+    set_flags(tty_settings->c_iflag, (BRKINT
+				      | IGNPAR
+				      | ICRNL
+				      | IXON
+				      | IMAXBEL));
+
+    clear_flags(tty_settings->c_oflag, (0
+					| OLCUC
+					| OCRNL
+					| ONOCR
+					| ONLRET
+					| OFILL
+					| OFDEL
+					| NLDLY
+					| CRDLY
+					| TABDLY
+					| BSDLY
+					| VTDLY
+					| FFDLY));
+
+    set_flags(tty_settings->c_oflag, (OPOST
+				      | ONLCR));
+
+    mask = (CSIZE | CSTOPB | PARENB | PARODD);
+#ifdef TIOCMGET
+    /* leave clocal alone if this appears to use a modem */
+    if (ioctl(fd, TIOCMGET, &modem_bits) == -1)
+	mask |= CLOCAL;
+#else
+    /* cannot check - use the behavior from tset */
+    mask |= CLOCAL;
+#endif
+    clear_flags(tty_settings->c_cflag, mask);
+
+    set_flags(tty_settings->c_cflag, (CS8 | CREAD));
+    clear_flags(tty_settings->c_lflag, (ECHONL
+					| NOFLSH
+					| TOSTOP
+					| ECHOPRT
+					| XCASE));
+
+    set_flags(tty_settings->c_lflag, (ISIG
+				      | ICANON
+				      | ECHO
+				      | ECHOE
+				      | ECHOK
+				      | ECHOCTL
+				      | ECHOKE));
+#endif /* TERMIOS */
+
+    if (!noset) {
+	SET_TTY(fd, tty_settings);
+    }
+}
+
+/*
+ * Returns a "good" value for the erase character.  This is loosely based on
+ * the BSD4.4 logic.
+ */
+static int
+default_erase(void)
+{
+    int result;
+
+    if (over_strike
+	&& VALID_STRING(key_backspace)
+	&& strlen(key_backspace) == 1) {
+	result = key_backspace[0];
+    } else {
+	result = CERASE;
+    }
+
+    return result;
+}
+
+/*
+ * Update the values of the erase, interrupt, and kill characters in the TTY
+ * parameter.
+ *
+ * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase
+ * characters if they're unset, or if we specify them as options.  This differs
+ * from BSD 4.4 tset, which always sets erase.
+ */
+void
+set_control_chars(TTY * tty_settings, int my_erase, int my_intr, int my_kill)
+{
+#if defined(EXP_WIN32_DRIVER)
+    /* noop */
+    (void) tty_settings;
+    (void) my_erase;
+    (void) my_intr;
+    (void) my_kill;
+#else
+    if (DISABLED(tty_settings->c_cc[VERASE]) || my_erase >= 0) {
+	tty_settings->c_cc[VERASE] = UChar((my_erase >= 0)
+					   ? my_erase
+					   : default_erase());
+    }
+
+    if (DISABLED(tty_settings->c_cc[VINTR]) || my_intr >= 0) {
+	tty_settings->c_cc[VINTR] = UChar((my_intr >= 0)
+					  ? my_intr
+					  : CINTR);
+    }
+
+    if (DISABLED(tty_settings->c_cc[VKILL]) || my_kill >= 0) {
+	tty_settings->c_cc[VKILL] = UChar((my_kill >= 0)
+					  ? my_kill
+					  : CKILL);
+    }
+#endif
+}
+
+/*
+ * Set up various conversions in the TTY parameter, including parity, tabs,
+ * returns, echo, and case, according to the termcap entry.
+ */
+void
+set_conversions(TTY * tty_settings)
+{
+#if defined(EXP_WIN32_DRIVER)
+    /* FIXME */
+#else
+    set_flags(tty_settings->c_oflag, ONLCR);
+    set_flags(tty_settings->c_iflag, ICRNL);
+    set_flags(tty_settings->c_lflag, ECHO);
+    set_flags(tty_settings->c_oflag, OXTABS);
+
+    /* test used to be tgetflag("NL") */
+    if (VALID_STRING(newline) && newline[0] == '\n' && !newline[1]) {
+	/* Newline, not linefeed. */
+	clear_flags(tty_settings->c_oflag, ONLCR);
+	clear_flags(tty_settings->c_iflag, ICRNL);
+    }
+#if OXTABS
+    /* test used to be tgetflag("pt") */
+    if (VALID_STRING(set_tab) && VALID_STRING(clear_all_tabs))
+	clear_flags(tty_settings->c_oflag, OXTABS);
+#endif /* OXTABS */
+    set_flags(tty_settings->c_lflag, (ECHOE | ECHOK));
+#endif
+}
+
+static bool
+sent_string(const char *s)
+{
+    bool sent = FALSE;
+    if (VALID_STRING(s)) {
+	tputs(s, 0, out_char);
+	sent = TRUE;
+    }
+    return sent;
+}
+
+static bool
+to_left_margin(void)
+{
+    if (VALID_STRING(carriage_return)) {
+	sent_string(carriage_return);
+    } else {
+	out_char('\r');
+    }
+    return TRUE;
+}
+
+/*
+ * Set the hardware tabs on the terminal, using the 'ct' (clear all tabs),
+ * 'st' (set one tab) and 'ch' (horizontal cursor addressing) capabilities.
+ * This is done before 'if' and 'is', so they can recover in case of error.
+ *
+ * Return TRUE if we set any tab stops, FALSE if not.
+ */
+static bool
+reset_tabstops(int wide)
+{
+    if ((init_tabs != 8)
+	&& VALID_NUMERIC(init_tabs)
+	&& VALID_STRING(set_tab)
+	&& VALID_STRING(clear_all_tabs)) {
+	int c;
+
+	to_left_margin();
+	tputs(clear_all_tabs, 0, out_char);
+	if (init_tabs > 1) {
+	    if (init_tabs > wide)
+		init_tabs = (short) wide;
+	    for (c = init_tabs; c < wide; c += init_tabs) {
+		fprintf(my_file, "%*s", init_tabs, " ");
+		tputs(set_tab, 0, out_char);
+	    }
+	    to_left_margin();
+	}
+	return (TRUE);
+    }
+    return (FALSE);
+}
+
+/* Output startup string. */
+bool
+send_init_strings(int fd GCC_UNUSED, TTY * old_settings)
+{
+    int i;
+    bool need_flush = FALSE;
+
+    (void) old_settings;
+#if TAB3
+    if (old_settings != 0 &&
+	old_settings->c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
+	old_settings->c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
+	SET_TTY(fd, old_settings);
+    }
+#endif
+    if (use_reset || use_init) {
+	if (VALID_STRING(init_prog)) {
+	    IGNORE_RC(system(init_prog));
+	}
+
+	need_flush |= sent_string((use_reset && (reset_1string != 0))
+				  ? reset_1string
+				  : init_1string);
+
+	need_flush |= sent_string((use_reset && (reset_2string != 0))
+				  ? reset_2string
+				  : init_2string);
+
+	if (VALID_STRING(clear_margins)) {
+	    need_flush |= sent_string(clear_margins);
+	}
+#if defined(set_lr_margin)
+	else if (VALID_STRING(set_lr_margin)) {
+	    need_flush |= sent_string(TIPARM_2(set_lr_margin, 0, columns - 1));
+	}
+#endif
+#if defined(set_left_margin_parm) && defined(set_right_margin_parm)
+	else if (VALID_STRING(set_left_margin_parm)
+		 && VALID_STRING(set_right_margin_parm)) {
+	    need_flush |= sent_string(TIPARM_1(set_left_margin_parm, 0));
+	    need_flush |= sent_string(TIPARM_1(set_right_margin_parm,
+					       columns - 1));
+	}
+#endif
+	else if (VALID_STRING(set_left_margin)
+		 && VALID_STRING(set_right_margin)) {
+	    need_flush |= to_left_margin();
+	    need_flush |= sent_string(set_left_margin);
+	    if (VALID_STRING(parm_right_cursor)) {
+		need_flush |= sent_string(TIPARM_1(parm_right_cursor,
+						   columns - 1));
+	    } else {
+		for (i = 0; i < columns - 1; i++) {
+		    out_char(' ');
+		    need_flush = TRUE;
+		}
+	    }
+	    need_flush |= sent_string(set_right_margin);
+	    need_flush |= to_left_margin();
+	}
+
+	need_flush |= reset_tabstops(columns);
+
+	need_flush |= cat_file((use_reset && reset_file) ? reset_file : init_file);
+
+	need_flush |= sent_string((use_reset && (reset_3string != 0))
+				  ? reset_3string
+				  : init_3string);
+    }
+
+    return need_flush;
+}
+
+/*
+ * Tell the user if a control key has been changed from the default value.
+ */
+static void
+show_tty_change(TTY * old_settings,
+		TTY * new_settings,
+		const char *name,
+		int which,
+		unsigned def)
+{
+    unsigned older = 0, newer = 0;
+    char *p;
+
+#if defined(EXP_WIN32_DRIVER)
+    /* noop */
+    (void) old_settings;
+    (void) new_settings;
+    (void) name;
+    (void) which;
+    (void) def;
+#else
+    newer = new_settings->c_cc[which];
+    older = old_settings->c_cc[which];
+
+    if (older == newer && older == def)
+	return;
+#endif
+    (void) fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to");
+
+    if (DISABLED(newer)) {
+	(void) fprintf(stderr, "undef.\n");
+	/*
+	 * Check 'delete' before 'backspace', since the key_backspace value
+	 * is ambiguous.
+	 */
+    } else if (newer == 0177) {
+	(void) fprintf(stderr, "delete.\n");
+    } else if ((p = key_backspace) != 0
+	       && newer == (unsigned char) p[0]
+	       && p[1] == '\0') {
+	(void) fprintf(stderr, "backspace.\n");
+    } else if (newer < 040) {
+	newer ^= 0100;
+	(void) fprintf(stderr, "control-%c (^%c).\n", UChar(newer), UChar(newer));
+    } else
+	(void) fprintf(stderr, "%c.\n", UChar(newer));
+}
+
+/**************************************************************************
+ * Miscellaneous.
+ **************************************************************************/
+
+void
+reset_start(FILE *fp, bool is_reset, bool is_init)
+{
+    my_file = fp;
+    use_reset = is_reset;
+    use_init = is_init;
+}
+
+void
+reset_flush(void)
+{
+    if (my_file != 0)
+	fflush(my_file);
+}
+
+void
+print_tty_chars(TTY * old_settings, TTY * new_settings)
+{
+#if defined(EXP_WIN32_DRIVER)
+    /* noop */
+#else
+    show_tty_change(old_settings, new_settings, "Erase", VERASE, CERASE);
+    show_tty_change(old_settings, new_settings, "Kill", VKILL, CKILL);
+    show_tty_change(old_settings, new_settings, "Interrupt", VINTR, CINTR);
+#endif
+}
+
+#if HAVE_SIZECHANGE
+/*
+ * Set window size if not set already, but update our copy of the values if the
+ * size was set.
+ */
+void
+set_window_size(int fd, NCURSES_INT2 *high, NCURSES_INT2 *wide)
+{
+    STRUCT_WINSIZE win;
+    (void) ioctl(fd, IOCTL_GET_WINSIZE, &win);
+    if (WINSIZE_ROWS(win) == 0 &&
+	WINSIZE_COLS(win) == 0) {
+	if (*high > 0 && *wide > 0) {
+	    WINSIZE_ROWS(win) = (unsigned short) *high;
+	    WINSIZE_COLS(win) = (unsigned short) *wide;
+	    (void) ioctl(fd, IOCTL_SET_WINSIZE, &win);
+	}
+    } else if (WINSIZE_ROWS(win) > 0 &&
+	       WINSIZE_COLS(win) > 0) {
+	*high = (short) WINSIZE_ROWS(win);
+	*wide = (short) WINSIZE_COLS(win);
+    }
+}
+#endif
diff --git a/progs/reset_cmd.h b/progs/reset_cmd.h
new file mode 100644
index 0000000..43aee28
--- /dev/null
+++ b/progs/reset_cmd.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+ * Copyright 2020-2021,2024 Thomas E. Dickey                                *
+ * Copyright 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            *
+ * "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                                                 *
+ ****************************************************************************/
+
+/*
+ * $Id: reset_cmd.h,v 1.11 2024/04/08 17:29:34 tom Exp $
+ *
+ * Utility functions for resetting terminal.
+ */
+#ifndef RESET_CMD_H
+#define RESET_CMD_H 1
+/* *INDENT-OFF* */
+
+#define USE_LIBTINFO
+#define __INTERNAL_CAPS_VISIBLE	/* we need to see has_hardware_tabs */
+#include <progs.priv.h>
+
+#undef CTRL
+#define CTRL(x)	((x) & 0x1f)
+
+extern bool send_init_strings(int /* fd */, TTY * /* old_settings */);
+extern void print_tty_chars(TTY * /* old_settings */, TTY * /* new_settings */);
+extern void reset_flush(void);
+extern void reset_start(FILE * /* fp */, bool /* is_reset */, bool /* is_init */ );
+extern void reset_tty_settings(int /* fd */, TTY * /* tty_settings */, int /* noset */);
+extern void set_control_chars(TTY * /* tty_settings */, int /* erase */, int /* intr */, int /* kill */);
+extern void set_conversions(TTY * /* tty_settings */);
+
+#if HAVE_SIZECHANGE
+extern void set_window_size(int /* fd */, NCURSES_INT2 * /* high */, NCURSES_INT2 * /* wide */);
+#endif
+
+extern const char *_nc_progname;
+
+/* *INDENT-ON* */
+
+#endif /* RESET_CMD_H */
diff --git a/progs/tabs b/progs/tabs
deleted file mode 100755
index 868b2d9..0000000
--- a/progs/tabs
+++ /dev/null
Binary files differ
diff --git a/progs/tabs.c b/progs/tabs.c
index 9974c33..a630b04 100644
--- a/progs/tabs.c
+++ b/progs/tabs.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 2008-2013,2015 Free Software Foundation, Inc.              *
+ * Copyright 2020-2022,2023 Thomas E. Dickey                                *
+ * Copyright 2008-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,12 +37,13 @@
 
 #define USE_LIBTINFO
 #include <progs.priv.h>
+#include <tty_settings.h>
 
-MODULE_ID("$Id: tabs.c,v 1.37 2015/07/04 21:14:42 tom Exp $")
+MODULE_ID("$Id: tabs.c,v 1.53 2023/11/04 20:46:09 tom Exp $")
 
-static void usage(void) GCC_NORETURN;
+static GCC_NORETURN void usage(void);
 
-static char *prg_name;
+const char *_nc_progname;
 static int max_cols;
 
 static void
@@ -57,14 +59,44 @@
     return putchar(c);
 }
 
+static char *
+skip_csi(char *value)
+{
+    if (UChar(*value) == 0x9b)
+	++value;
+    else if (!strncmp(value, "\033[", 2))
+	value += 2;
+    return value;
+}
+
+/*
+ * If the terminal uses ANSI clear_all_tabs, then it is not necessary to first
+ * move to the left margin before clearing tabs.
+ */
+static bool
+ansi_clear_tabs(void)
+{
+    bool result = FALSE;
+    if (VALID_STRING(clear_all_tabs)) {
+	char *param = skip_csi(clear_all_tabs);
+	if (!strcmp(param, "3g"))
+	    result = TRUE;
+    }
+    return result;
+}
+
 static void
 do_tabs(int *tab_list)
 {
     int last = 1;
     int stop;
+    bool first = TRUE;
 
-    putchar('\r');
     while ((stop = *tab_list++) > 0) {
+	if (first) {
+	    first = FALSE;
+	    putchar('\r');
+	}
 	if (last < stop) {
 	    while (last++ < stop) {
 		if (last > max_cols)
@@ -73,7 +105,7 @@
 	    }
 	}
 	if (stop <= max_cols) {
-	    tputs(tparm(set_tab, stop), 1, putch);
+	    tputs(set_tab, 1, putch);
 	    last = stop;
 	} else {
 	    break;
@@ -82,8 +114,13 @@
     putchar('\r');
 }
 
+/*
+ * Decode a list of tab-stops from a string, returning an array of integers.
+ * If the margin is positive (because the terminal does not support margins),
+ * work around this by adding the margin to the decoded values.
+ */
 static int *
-decode_tabs(const char *tab_list)
+decode_tabs(const char *tab_list, int margin)
 {
     int *result = typeCalloc(int, strlen(tab_list) + (unsigned) max_cols);
     int n = 0;
@@ -91,19 +128,24 @@
     int prior = 0;
     int ch;
 
-    if (result == 0)
+    if (result == NULL)
 	failed("decode_tabs");
 
+    if (margin < 0)
+	margin = 0;
+
     while ((ch = *tab_list++) != '\0') {
 	if (isdigit(UChar(ch))) {
 	    value *= 10;
 	    value += (ch - '0');
+	    if (value > max_cols)
+		value = max_cols;
 	} else if (ch == ',') {
-	    result[n] = value + prior;
+	    result[n] = value + prior + margin;
 	    if (n > 0 && result[n] <= result[n - 1]) {
 		fprintf(stderr,
 			"%s: tab-stops are not in increasing order: %d %d\n",
-			prg_name, value, result[n - 1]);
+			_nc_progname, value, result[n - 1]);
 		free(result);
 		result = 0;
 		break;
@@ -125,7 +167,7 @@
 	    int step = value;
 	    value = 1;
 	    while (n < max_cols - 1) {
-		result[n++] = value;
+		result[n++] = value + margin;
 		value += step;
 	    }
 	}
@@ -133,7 +175,7 @@
 	/*
 	 * Add the last value, if any.
 	 */
-	result[n++] = value + prior;
+	result[n++] = value + prior + margin;
 	result[n] = 0;
     }
 
@@ -141,10 +183,9 @@
 }
 
 static void
-print_ruler(int *tab_list)
+print_ruler(const int *const tab_list, const char *new_line)
 {
     int last = 0;
-    int stop;
     int n;
 
     /* first print a readable ruler */
@@ -158,11 +199,12 @@
 		     : (ch + 'A' - 10)));
 	printf("%.*s", ((max_cols - n) > 10) ? 10 : (max_cols - n), buffer);
     }
-    putchar('\n');
+    printf("%s", new_line);
 
     /* now, print '*' for each stop */
     for (n = 0, last = 0; (tab_list[n] > 0) && (last < max_cols); ++n) {
-	stop = tab_list[n];
+	int stop = tab_list[n];
+
 	while (++last < stop) {
 	    if (last <= max_cols) {
 		putchar('-');
@@ -179,7 +221,7 @@
     }
     while (++last <= max_cols)
 	putchar('-');
-    putchar('\n');
+    printf("%s", new_line);
 }
 
 /*
@@ -187,7 +229,7 @@
  * ruler.
  */
 static void
-write_tabs(int *tab_list)
+write_tabs(int *tab_list, const char *new_line)
 {
     int stop;
 
@@ -197,7 +239,7 @@
     /* also show a tab _past_ the stops */
     if (stop < max_cols)
 	fputs("\t+", stdout);
-    putchar('\n');
+    fputs(new_line, stdout);
 }
 
 /*
@@ -208,11 +250,11 @@
 trimmed_tab_list(const char *source)
 {
     char *result = strdup(source);
-    int ch, j, k, last;
-
     if (result != 0) {
+	int j, k, last;
+
 	for (j = k = last = 0; result[j] != 0; ++j) {
-	    ch = UChar(result[j]);
+	    int ch = UChar(result[j]);
 	    if (isspace(ch)) {
 		if (last == '\0') {
 		    continue;
@@ -293,6 +335,66 @@
 }
 
 /*
+ * If the terminal supports it, (re)set the left margin and return true.
+ * Otherwise, return false.
+ */
+static bool
+do_set_margin(int margin, bool no_op)
+{
+    bool result = FALSE;
+
+    if (margin == 0) {		/* 0 is special case for resetting */
+	if (VALID_STRING(clear_margins)) {
+	    result = TRUE;
+	    if (!no_op)
+		tputs(clear_margins, 1, putch);
+	}
+    } else if (margin-- < 0) {	/* margin will be 0-based from here on */
+	result = TRUE;
+    } else if (VALID_STRING(set_left_margin)) {
+	result = TRUE;
+	if (!no_op) {
+	    /*
+	     * assuming we're on the first column of the line, move the cursor
+	     * to the column at which we will set a margin.
+	     */
+	    if (VALID_STRING(column_address)) {
+		tputs(TIPARM_1(column_address, margin), 1, putch);
+	    } else if (margin >= 1) {
+		if (VALID_STRING(parm_right_cursor)) {
+		    tputs(TIPARM_1(parm_right_cursor, margin), 1, putch);
+		} else {
+		    while (margin-- > 0)
+			putch(' ');
+		}
+	    }
+	    tputs(set_left_margin, 1, putch);
+	}
+    }
+#if defined(set_left_margin_parm) && defined(set_right_margin_parm)
+    else if (VALID_STRING(set_left_margin_parm)) {
+	result = TRUE;
+	if (!no_op) {
+	    if (VALID_STRING(set_right_margin_parm)) {
+		tputs(TIPARM_1(set_left_margin_parm, margin), 1, putch);
+	    } else {
+		tputs(TIPARM_2(set_left_margin_parm, margin, max_cols), 1, putch);
+	    }
+	}
+    }
+#endif
+#if defined(set_lr_margin)
+    else if (VALID_STRING(set_lr_margin)) {
+	result = TRUE;
+	if (!no_op) {
+	    tputs(TIPARM_2(set_lr_margin, margin, max_cols), 1, putch);
+	}
+    }
+#endif
+    return result;
+}
+
+/*
  * Check for illegal characters in the tab-list.
  */
 static bool
@@ -302,24 +404,25 @@
 
     if (tab_list != 0 && *tab_list != '\0') {
 	if (comma_is_needed(tab_list)) {
-	    int n, ch;
+	    int n;
+
 	    for (n = 0; tab_list[n] != '\0'; ++n) {
-		ch = UChar(tab_list[n]);
+		int ch = UChar(tab_list[n]);
+
 		if (!(isdigit(ch) || ch == ',' || ch == '+')) {
 		    fprintf(stderr,
 			    "%s: unexpected character found '%c'\n",
-			    prg_name, ch);
+			    _nc_progname, ch);
 		    result = FALSE;
 		    break;
 		}
 	    }
 	} else {
-	    fprintf(stderr, "%s: trailing comma found '%s'\n", prg_name, tab_list);
+	    fprintf(stderr, "%s: trailing comma found '%s'\n", _nc_progname, tab_list);
 	    result = FALSE;
 	}
     } else {
-	fprintf(stderr, "%s: no tab-list given\n", prg_name);
-	result = FALSE;
+	/* if no list given, default to "tabs -8" */
     }
     return result;
 }
@@ -377,12 +480,17 @@
     int rc = EXIT_FAILURE;
     bool debug = FALSE;
     bool no_op = FALSE;
+    bool change_tty = FALSE;
     int n, ch;
     NCURSES_CONST char *term_name = 0;
     char *append = 0;
     const char *tab_list = 0;
+    const char *new_line = "\n";
+    int margin = -1;
+    TTY tty_settings;
+    int fd;
 
-    prg_name = _nc_rootname(argv[0]);
+    _nc_progname = _nc_rootname(argv[0]);
 
     if ((term_name = getenv("TERM")) == 0)
 	term_name = "ansi+tabs";
@@ -453,7 +561,7 @@
 		    if (*++option != '\0') {
 			term_name = option;
 		    } else {
-			term_name = argv[n++];
+			term_name = argv[n];
 			option--;
 		    }
 		    option += ((int) strlen(option)) - 1;
@@ -475,7 +583,10 @@
 	    }
 	    break;
 	case '+':
-	    while ((ch = *++option) != '\0') {
+	    if ((ch = *++option) != '\0') {
+		int digits = 0;
+		int number = 0;
+
 		switch (ch) {
 		case 'm':
 		    /*
@@ -483,6 +594,17 @@
 		     * att510d implements smgl, which is needed to support
 		     * this option.
 		     */
+		    while ((ch = *++option) != '\0') {
+			if (isdigit(UChar(ch))) {
+			    ++digits;
+			    number = number * 10 + (ch - '0');
+			} else {
+			    usage();
+			}
+		    }
+		    if (digits == 0)
+			number = 10;
+		    margin = number;
 		    break;
 		default:
 		    /* special case of relative stops separated by spaces? */
@@ -506,37 +628,78 @@
 	}
     }
 
-    setupterm(term_name, STDOUT_FILENO, (int *) 0);
+    fd = save_tty_settings(&tty_settings, FALSE);
+
+    setupterm(term_name, fd, (int *) 0);
 
     max_cols = (columns > 0) ? columns : 80;
+    if (margin > 0)
+	max_cols -= margin;
 
     if (!VALID_STRING(clear_all_tabs)) {
 	fprintf(stderr,
 		"%s: terminal type '%s' cannot reset tabs\n",
-		prg_name, term_name);
+		_nc_progname, term_name);
     } else if (!VALID_STRING(set_tab)) {
 	fprintf(stderr,
 		"%s: terminal type '%s' cannot set tabs\n",
-		prg_name, term_name);
+		_nc_progname, term_name);
     } else if (legal_tab_list(tab_list)) {
-	int *list = decode_tabs(tab_list);
+	int *list;
 
-	if (!no_op)
+	if (tab_list == NULL)
+	    tab_list = add_to_tab_list(&append, "8");
+
+	if (!no_op) {
+#if defined(TERMIOS) && defined(OCRNL)
+	    /* set tty modes to -ocrnl to allow \r */
+	    if (isatty(STDOUT_FILENO)) {
+		TTY new_settings = tty_settings;
+		new_settings.c_oflag &= (unsigned) ~OCRNL;
+		update_tty_settings(&tty_settings, &new_settings);
+		change_tty = TRUE;
+		new_line = "\r\n";
+	    }
+#endif
+
+	    if (!ansi_clear_tabs())
+		putch('\r');
 	    tputs(clear_all_tabs, 1, putch);
+	}
+
+	if (margin >= 0) {
+	    putch('\r');
+	    if (margin > 0) {
+		/* reset existing margin before setting margin, to reduce
+		 * problems moving left of the current margin.
+		 */
+		if (do_set_margin(0, no_op))
+		    putch('\r');
+	    }
+	    if (do_set_margin(margin, no_op))
+		margin = -1;
+	}
+
+	list = decode_tabs(tab_list, margin);
 
 	if (list != 0) {
 	    if (!no_op)
 		do_tabs(list);
 	    if (debug) {
 		fflush(stderr);
-		printf("tabs %s\n", tab_list);
-		print_ruler(list);
-		write_tabs(list);
+		printf("tabs %s%s", tab_list, new_line);
+		print_ruler(list, new_line);
+		write_tabs(list, new_line);
 	    }
 	    free(list);
 	} else if (debug) {
 	    fflush(stderr);
-	    printf("tabs %s\n", tab_list);
+	    printf("tabs %s%s", tab_list, new_line);
+	}
+	if (!no_op) {
+	    if (change_tty) {
+		restore_tty_settings();
+	    }
 	}
 	rc = EXIT_SUCCESS;
     }
diff --git a/progs/termsort.c b/progs/termsort.c
deleted file mode 100644
index eae285e..0000000
--- a/progs/termsort.c
+++ /dev/null
@@ -1,2166 +0,0 @@
-/*
- * termsort.c --- sort order arrays for use by infocmp.
- *
- * Note: this file is generated using MKtermsort.sh, do not edit by hand.
- */
-static const PredIdx bool_terminfo_sort[] = {
-	 40 ,	/*  OTMT  */
-	 41 ,	/*  OTNL  */
-	 37 ,	/*  OTbs  */
-	 39 ,	/*  OTnc  */
-	 38 ,	/*  OTns  */
-	 42 ,	/*  OTpt  */
-	 43 ,	/*  OTxr  */
-	 1 ,	/*  am  */
-	 28 ,	/*  bce  */
-	 0 ,	/*  bw  */
-	 27 ,	/*  ccc  */
-	 23 ,	/*  chts  */
-	 35 ,	/*  cpix  */
-	 31 ,	/*  crxm  */
-	 11 ,	/*  da  */
-	 32 ,	/*  daisy  */
-	 12 ,	/*  db  */
-	 5 ,	/*  eo  */
-	 16 ,	/*  eslok  */
-	 6 ,	/*  gn  */
-	 7 ,	/*  hc  */
-	 29 ,	/*  hls  */
-	 9 ,	/*  hs  */
-	 18 ,	/*  hz  */
-	 10 ,	/*  in  */
-	 8 ,	/*  km  */
-	 36 ,	/*  lpix  */
-	 22 ,	/*  mc5i  */
-	 13 ,	/*  mir  */
-	 14 ,	/*  msgr  */
-	 26 ,	/*  ndscr  */
-	 25 ,	/*  npc  */
-	 24 ,	/*  nrrmc  */
-	 21 ,	/*  nxon  */
-	 15 ,	/*  os  */
-	 34 ,	/*  sam  */
-	 19 ,	/*  ul  */
-	 4 ,	/*  xenl  */
-	 3 ,	/*  xhp  */
-	 30 ,	/*  xhpa  */
-	 20 ,	/*  xon  */
-	 2 ,	/*  xsb  */
-	 17 ,	/*  xt  */
-	 33 ,	/*  xvpa  */
-};
-
-static const PredIdx num_terminfo_sort[] = {
-	 36 ,	/*  OTdB  */
-	 34 ,	/*  OTdC  */
-	 35 ,	/*  OTdN  */
-	 37 ,	/*  OTdT  */
-	 38 ,	/*  OTkn  */
-	 33 ,	/*  OTug  */
-	 31 ,	/*  bitwin  */
-	 32 ,	/*  bitype  */
-	 30 ,	/*  btns  */
-	 16 ,	/*  bufsz  */
-	 13 ,	/*  colors  */
-	 0 ,	/*  cols  */
-	 28 ,	/*  cps  */
-	 1 ,	/*  it  */
-	 9 ,	/*  lh  */
-	 2 ,	/*  lines  */
-	 3 ,	/*  lm  */
-	 10 ,	/*  lw  */
-	 11 ,	/*  ma  */
-	 19 ,	/*  maddr  */
-	 21 ,	/*  mcs  */
-	 20 ,	/*  mjump  */
-	 22 ,	/*  mls  */
-	 15 ,	/*  ncv  */
-	 8 ,	/*  nlab  */
-	 23 ,	/*  npins  */
-	 24 ,	/*  orc  */
-	 26 ,	/*  orhi  */
-	 25 ,	/*  orl  */
-	 27 ,	/*  orvi  */
-	 14 ,	/*  pairs  */
-	 5 ,	/*  pb  */
-	 18 ,	/*  spinh  */
-	 17 ,	/*  spinv  */
-	 6 ,	/*  vt  */
-	 29 ,	/*  widcs  */
-	 12 ,	/*  wnum  */
-	 7 ,	/*  wsl  */
-	 4 ,	/*  xmc  */
-};
-
-static const PredIdx str_terminfo_sort[] = {
-	 402 ,	/*  OTG1  */
-	 400 ,	/*  OTG2  */
-	 401 ,	/*  OTG3  */
-	 403 ,	/*  OTG4  */
-	 410 ,	/*  OTGC  */
-	 407 ,	/*  OTGD  */
-	 408 ,	/*  OTGH  */
-	 405 ,	/*  OTGL  */
-	 404 ,	/*  OTGR  */
-	 406 ,	/*  OTGU  */
-	 409 ,	/*  OTGV  */
-	 397 ,	/*  OTbc  */
-	 394 ,	/*  OTi2  */
-	 398 ,	/*  OTko  */
-	 399 ,	/*  OTma  */
-	 396 ,	/*  OTnl  */
-	 395 ,	/*  OTrs  */
-	 146 ,	/*  acsc  */
-	 1 ,	/*  bel  */
-	 372 ,	/*  bicr  */
-	 371 ,	/*  binel  */
-	 370 ,	/*  birep  */
-	 26 ,	/*  blink  */
-	 27 ,	/*  bold  */
-	 413 ,	/*  box1  */
-	 0 ,	/*  cbt  */
-	 306 ,	/*  chr  */
-	 13 ,	/*  civis  */
-	 5 ,	/*  clear  */
-	 9 ,	/*  cmdch  */
-	 16 ,	/*  cnorm  */
-	 373 ,	/*  colornm  */
-	 304 ,	/*  cpi  */
-	 2 ,	/*  cr  */
-	 363 ,	/*  csin  */
-	 354 ,	/*  csnm  */
-	 3 ,	/*  csr  */
-	 111 ,	/*  cub  */
-	 14 ,	/*  cub1  */
-	 107 ,	/*  cud  */
-	 11 ,	/*  cud1  */
-	 112 ,	/*  cuf  */
-	 17 ,	/*  cuf1  */
-	 10 ,	/*  cup  */
-	 114 ,	/*  cuu  */
-	 19 ,	/*  cuu1  */
-	 307 ,	/*  cvr  */
-	 20 ,	/*  cvvis  */
-	 277 ,	/*  cwin  */
-	 105 ,	/*  dch  */
-	 21 ,	/*  dch1  */
-	 275 ,	/*  dclk  */
-	 374 ,	/*  defbi  */
-	 308 ,	/*  defc  */
-	 362 ,	/*  devt  */
-	 280 ,	/*  dial  */
-	 30 ,	/*  dim  */
-	 378 ,	/*  dispc  */
-	 106 ,	/*  dl  */
-	 22 ,	/*  dl1  */
-	 352 ,	/*  docr  */
-	 23 ,	/*  dsl  */
-	 37 ,	/*  ech  */
-	 7 ,	/*  ed  */
-	 386 ,	/*  ehhlm  */
-	 6 ,	/*  el  */
-	 269 ,	/*  el1  */
-	 387 ,	/*  elhlm  */
-	 388 ,	/*  elohlm  */
-	 155 ,	/*  enacs  */
-	 375 ,	/*  endbi  */
-	 389 ,	/*  erhlm  */
-	 390 ,	/*  ethlm  */
-	 391 ,	/*  evhlm  */
-	 46 ,	/*  ff  */
-	 45 ,	/*  flash  */
-	 273 ,	/*  fln  */
-	 47 ,	/*  fsl  */
-	 358 ,	/*  getm  */
-	 24 ,	/*  hd  */
-	 12 ,	/*  home  */
-	 284 ,	/*  hook  */
-	 8 ,	/*  hpa  */
-	 134 ,	/*  ht  */
-	 132 ,	/*  hts  */
-	 137 ,	/*  hu  */
-	 279 ,	/*  hup  */
-	 108 ,	/*  ich  */
-	 52 ,	/*  ich1  */
-	 51 ,	/*  if  */
-	 110 ,	/*  il  */
-	 53 ,	/*  il1  */
-	 129 ,	/*  ind  */
-	 109 ,	/*  indn  */
-	 299 ,	/*  initc  */
-	 300 ,	/*  initp  */
-	 32 ,	/*  invis  */
-	 54 ,	/*  ip  */
-	 138 ,	/*  iprog  */
-	 48 ,	/*  is1  */
-	 49 ,	/*  is2  */
-	 50 ,	/*  is3  */
-	 186 ,	/*  kBEG  */
-	 187 ,	/*  kCAN  */
-	 188 ,	/*  kCMD  */
-	 189 ,	/*  kCPY  */
-	 190 ,	/*  kCRT  */
-	 191 ,	/*  kDC  */
-	 192 ,	/*  kDL  */
-	 194 ,	/*  kEND  */
-	 195 ,	/*  kEOL  */
-	 196 ,	/*  kEXT  */
-	 197 ,	/*  kFND  */
-	 198 ,	/*  kHLP  */
-	 199 ,	/*  kHOM  */
-	 200 ,	/*  kIC  */
-	 201 ,	/*  kLFT  */
-	 203 ,	/*  kMOV  */
-	 202 ,	/*  kMSG  */
-	 204 ,	/*  kNXT  */
-	 205 ,	/*  kOPT  */
-	 207 ,	/*  kPRT  */
-	 206 ,	/*  kPRV  */
-	 208 ,	/*  kRDO  */
-	 211 ,	/*  kRES  */
-	 210 ,	/*  kRIT  */
-	 209 ,	/*  kRPL  */
-	 212 ,	/*  kSAV  */
-	 213 ,	/*  kSPD  */
-	 214 ,	/*  kUND  */
-	 139 ,	/*  ka1  */
-	 140 ,	/*  ka3  */
-	 141 ,	/*  kb2  */
-	 158 ,	/*  kbeg  */
-	 55 ,	/*  kbs  */
-	 142 ,	/*  kc1  */
-	 143 ,	/*  kc3  */
-	 159 ,	/*  kcan  */
-	 148 ,	/*  kcbt  */
-	 160 ,	/*  kclo  */
-	 57 ,	/*  kclr  */
-	 161 ,	/*  kcmd  */
-	 162 ,	/*  kcpy  */
-	 163 ,	/*  kcrt  */
-	 58 ,	/*  kctab  */
-	 79 ,	/*  kcub1  */
-	 61 ,	/*  kcud1  */
-	 83 ,	/*  kcuf1  */
-	 87 ,	/*  kcuu1  */
-	 59 ,	/*  kdch1  */
-	 60 ,	/*  kdl1  */
-	 64 ,	/*  ked  */
-	 63 ,	/*  kel  */
-	 164 ,	/*  kend  */
-	 165 ,	/*  kent  */
-	 166 ,	/*  kext  */
-	 65 ,	/*  kf0  */
-	 66 ,	/*  kf1  */
-	 67 ,	/*  kf10  */
-	 216 ,	/*  kf11  */
-	 217 ,	/*  kf12  */
-	 218 ,	/*  kf13  */
-	 219 ,	/*  kf14  */
-	 220 ,	/*  kf15  */
-	 221 ,	/*  kf16  */
-	 222 ,	/*  kf17  */
-	 223 ,	/*  kf18  */
-	 224 ,	/*  kf19  */
-	 68 ,	/*  kf2  */
-	 225 ,	/*  kf20  */
-	 226 ,	/*  kf21  */
-	 227 ,	/*  kf22  */
-	 228 ,	/*  kf23  */
-	 229 ,	/*  kf24  */
-	 230 ,	/*  kf25  */
-	 231 ,	/*  kf26  */
-	 232 ,	/*  kf27  */
-	 233 ,	/*  kf28  */
-	 234 ,	/*  kf29  */
-	 69 ,	/*  kf3  */
-	 235 ,	/*  kf30  */
-	 236 ,	/*  kf31  */
-	 237 ,	/*  kf32  */
-	 238 ,	/*  kf33  */
-	 239 ,	/*  kf34  */
-	 240 ,	/*  kf35  */
-	 241 ,	/*  kf36  */
-	 242 ,	/*  kf37  */
-	 243 ,	/*  kf38  */
-	 244 ,	/*  kf39  */
-	 70 ,	/*  kf4  */
-	 245 ,	/*  kf40  */
-	 246 ,	/*  kf41  */
-	 247 ,	/*  kf42  */
-	 248 ,	/*  kf43  */
-	 249 ,	/*  kf44  */
-	 250 ,	/*  kf45  */
-	 251 ,	/*  kf46  */
-	 252 ,	/*  kf47  */
-	 253 ,	/*  kf48  */
-	 254 ,	/*  kf49  */
-	 71 ,	/*  kf5  */
-	 255 ,	/*  kf50  */
-	 256 ,	/*  kf51  */
-	 257 ,	/*  kf52  */
-	 258 ,	/*  kf53  */
-	 259 ,	/*  kf54  */
-	 260 ,	/*  kf55  */
-	 261 ,	/*  kf56  */
-	 262 ,	/*  kf57  */
-	 263 ,	/*  kf58  */
-	 264 ,	/*  kf59  */
-	 72 ,	/*  kf6  */
-	 265 ,	/*  kf60  */
-	 266 ,	/*  kf61  */
-	 267 ,	/*  kf62  */
-	 268 ,	/*  kf63  */
-	 73 ,	/*  kf7  */
-	 74 ,	/*  kf8  */
-	 75 ,	/*  kf9  */
-	 167 ,	/*  kfnd  */
-	 168 ,	/*  khlp  */
-	 76 ,	/*  khome  */
-	 86 ,	/*  khts  */
-	 77 ,	/*  kich1  */
-	 78 ,	/*  kil1  */
-	 84 ,	/*  kind  */
-	 80 ,	/*  kll  */
-	 355 ,	/*  kmous  */
-	 171 ,	/*  kmov  */
-	 169 ,	/*  kmrk  */
-	 170 ,	/*  kmsg  */
-	 81 ,	/*  knp  */
-	 172 ,	/*  knxt  */
-	 173 ,	/*  kopn  */
-	 174 ,	/*  kopt  */
-	 82 ,	/*  kpp  */
-	 176 ,	/*  kprt  */
-	 175 ,	/*  kprv  */
-	 177 ,	/*  krdo  */
-	 178 ,	/*  kref  */
-	 182 ,	/*  kres  */
-	 179 ,	/*  krfr  */
-	 85 ,	/*  kri  */
-	 62 ,	/*  krmir  */
-	 180 ,	/*  krpl  */
-	 181 ,	/*  krst  */
-	 183 ,	/*  ksav  */
-	 193 ,	/*  kslt  */
-	 184 ,	/*  kspd  */
-	 56 ,	/*  ktbc  */
-	 185 ,	/*  kund  */
-	 90 ,	/*  lf0  */
-	 91 ,	/*  lf1  */
-	 92 ,	/*  lf10  */
-	 93 ,	/*  lf2  */
-	 94 ,	/*  lf3  */
-	 95 ,	/*  lf4  */
-	 96 ,	/*  lf5  */
-	 97 ,	/*  lf6  */
-	 98 ,	/*  lf7  */
-	 99 ,	/*  lf8  */
-	 100 ,	/*  lf9  */
-	 18 ,	/*  ll  */
-	 305 ,	/*  lpi  */
-	 118 ,	/*  mc0  */
-	 119 ,	/*  mc4  */
-	 120 ,	/*  mc5  */
-	 144 ,	/*  mc5p  */
-	 336 ,	/*  mcub  */
-	 330 ,	/*  mcub1  */
-	 335 ,	/*  mcud  */
-	 329 ,	/*  mcud1  */
-	 337 ,	/*  mcuf  */
-	 331 ,	/*  mcuf1  */
-	 338 ,	/*  mcuu  */
-	 333 ,	/*  mcuu1  */
-	 411 ,	/*  meml  */
-	 412 ,	/*  memu  */
-	 270 ,	/*  mgc  */
-	 328 ,	/*  mhpa  */
-	 356 ,	/*  minfo  */
-	 15 ,	/*  mrcup  */
-	 332 ,	/*  mvpa  */
-	 103 ,	/*  nel  */
-	 298 ,	/*  oc  */
-	 297 ,	/*  op  */
-	 104 ,	/*  pad  */
-	 285 ,	/*  pause  */
-	 383 ,	/*  pctrm  */
-	 115 ,	/*  pfkey  */
-	 116 ,	/*  pfloc  */
-	 117 ,	/*  pfx  */
-	 361 ,	/*  pfxl  */
-	 147 ,	/*  pln  */
-	 334 ,	/*  porder  */
-	 33 ,	/*  prot  */
-	 283 ,	/*  pulse  */
-	 281 ,	/*  qdial  */
-	 348 ,	/*  rbim  */
-	 126 ,	/*  rc  */
-	 349 ,	/*  rcsd  */
-	 121 ,	/*  rep  */
-	 357 ,	/*  reqmp  */
-	 34 ,	/*  rev  */
-	 125 ,	/*  rf  */
-	 215 ,	/*  rfi  */
-	 130 ,	/*  ri  */
-	 113 ,	/*  rin  */
-	 321 ,	/*  ritm  */
-	 322 ,	/*  rlm  */
-	 38 ,	/*  rmacs  */
-	 152 ,	/*  rmam  */
-	 276 ,	/*  rmclk  */
-	 40 ,	/*  rmcup  */
-	 41 ,	/*  rmdc  */
-	 323 ,	/*  rmicm  */
-	 42 ,	/*  rmir  */
-	 88 ,	/*  rmkx  */
-	 157 ,	/*  rmln  */
-	 101 ,	/*  rmm  */
-	 145 ,	/*  rmp  */
-	 380 ,	/*  rmpch  */
-	 382 ,	/*  rmsc  */
-	 43 ,	/*  rmso  */
-	 44 ,	/*  rmul  */
-	 150 ,	/*  rmxon  */
-	 122 ,	/*  rs1  */
-	 123 ,	/*  rs2  */
-	 124 ,	/*  rs3  */
-	 324 ,	/*  rshm  */
-	 325 ,	/*  rsubm  */
-	 326 ,	/*  rsupm  */
-	 327 ,	/*  rum  */
-	 320 ,	/*  rwidm  */
-	 364 ,	/*  s0ds  */
-	 365 ,	/*  s1ds  */
-	 366 ,	/*  s2ds  */
-	 367 ,	/*  s3ds  */
-	 346 ,	/*  sbim  */
-	 128 ,	/*  sc  */
-	 385 ,	/*  scesa  */
-	 384 ,	/*  scesc  */
-	 274 ,	/*  sclk  */
-	 301 ,	/*  scp  */
-	 339 ,	/*  scs  */
-	 347 ,	/*  scsd  */
-	 310 ,	/*  sdrfq  */
-	 360 ,	/*  setab  */
-	 359 ,	/*  setaf  */
-	 303 ,	/*  setb  */
-	 376 ,	/*  setcolor  */
-	 302 ,	/*  setf  */
-	 131 ,	/*  sgr  */
-	 39 ,	/*  sgr0  */
-	 392 ,	/*  sgr1  */
-	 311 ,	/*  sitm  */
-	 393 ,	/*  slength  */
-	 377 ,	/*  slines  */
-	 312 ,	/*  slm  */
-	 25 ,	/*  smacs  */
-	 151 ,	/*  smam  */
-	 28 ,	/*  smcup  */
-	 29 ,	/*  smdc  */
-	 340 ,	/*  smgb  */
-	 341 ,	/*  smgbp  */
-	 271 ,	/*  smgl  */
-	 342 ,	/*  smglp  */
-	 368 ,	/*  smglr  */
-	 272 ,	/*  smgr  */
-	 343 ,	/*  smgrp  */
-	 344 ,	/*  smgt  */
-	 369 ,	/*  smgtb  */
-	 345 ,	/*  smgtp  */
-	 313 ,	/*  smicm  */
-	 31 ,	/*  smir  */
-	 89 ,	/*  smkx  */
-	 156 ,	/*  smln  */
-	 102 ,	/*  smm  */
-	 379 ,	/*  smpch  */
-	 381 ,	/*  smsc  */
-	 35 ,	/*  smso  */
-	 36 ,	/*  smul  */
-	 149 ,	/*  smxon  */
-	 314 ,	/*  snlq  */
-	 315 ,	/*  snrmq  */
-	 316 ,	/*  sshm  */
-	 317 ,	/*  ssubm  */
-	 318 ,	/*  ssupm  */
-	 350 ,	/*  subcs  */
-	 319 ,	/*  sum  */
-	 351 ,	/*  supcs  */
-	 309 ,	/*  swidm  */
-	 4 ,	/*  tbc  */
-	 282 ,	/*  tone  */
-	 135 ,	/*  tsl  */
-	 287 ,	/*  u0  */
-	 288 ,	/*  u1  */
-	 289 ,	/*  u2  */
-	 290 ,	/*  u3  */
-	 291 ,	/*  u4  */
-	 292 ,	/*  u5  */
-	 293 ,	/*  u6  */
-	 294 ,	/*  u7  */
-	 295 ,	/*  u8  */
-	 296 ,	/*  u9  */
-	 136 ,	/*  uc  */
-	 127 ,	/*  vpa  */
-	 286 ,	/*  wait  */
-	 133 ,	/*  wind  */
-	 278 ,	/*  wingo  */
-	 154 ,	/*  xoffc  */
-	 153 ,	/*  xonc  */
-	 353 ,	/*  zerom  */
-};
-
-static const PredIdx bool_variable_sort[] = {
-	 0 ,	/*  auto_left_margin  */
-	 1 ,	/*  auto_right_margin  */
-	 28 ,	/*  back_color_erase  */
-	 37 ,	/*  backspaces_with_bs  */
-	 27 ,	/*  can_change  */
-	 3 ,	/*  ceol_standout_glitch  */
-	 30 ,	/*  col_addr_glitch  */
-	 35 ,	/*  cpi_changes_res  */
-	 31 ,	/*  cr_cancels_micro_mode  */
-	 38 ,	/*  crt_no_scrolling  */
-	 17 ,	/*  dest_tabs_magic_smso  */
-	 4 ,	/*  eat_newline_glitch  */
-	 5 ,	/*  erase_overstrike  */
-	 6 ,	/*  generic_type  */
-	 40 ,	/*  gnu_has_meta_key  */
-	 7 ,	/*  hard_copy  */
-	 23 ,	/*  hard_cursor  */
-	 42 ,	/*  has_hardware_tabs  */
-	 8 ,	/*  has_meta_key  */
-	 32 ,	/*  has_print_wheel  */
-	 9 ,	/*  has_status_line  */
-	 29 ,	/*  hue_lightness_saturation  */
-	 10 ,	/*  insert_null_glitch  */
-	 41 ,	/*  linefeed_is_newline  */
-	 36 ,	/*  lpi_changes_res  */
-	 11 ,	/*  memory_above  */
-	 12 ,	/*  memory_below  */
-	 13 ,	/*  move_insert_mode  */
-	 14 ,	/*  move_standout_mode  */
-	 21 ,	/*  needs_xon_xoff  */
-	 39 ,	/*  no_correctly_working_cr  */
-	 2 ,	/*  no_esc_ctlc  */
-	 25 ,	/*  no_pad_char  */
-	 26 ,	/*  non_dest_scroll_region  */
-	 24 ,	/*  non_rev_rmcup  */
-	 15 ,	/*  over_strike  */
-	 22 ,	/*  prtr_silent  */
-	 43 ,	/*  return_does_clr_eol  */
-	 33 ,	/*  row_addr_glitch  */
-	 34 ,	/*  semi_auto_right_margin  */
-	 16 ,	/*  status_line_esc_ok  */
-	 18 ,	/*  tilde_glitch  */
-	 19 ,	/*  transparent_underline  */
-	 20 ,	/*  xon_xoff  */
-};
-
-static const PredIdx num_variable_sort[] = {
-	 36 ,	/*  backspace_delay  */
-	 31 ,	/*  bit_image_entwining  */
-	 32 ,	/*  bit_image_type  */
-	 16 ,	/*  buffer_capacity  */
-	 30 ,	/*  buttons  */
-	 34 ,	/*  carriage_return_delay  */
-	 0 ,	/*  columns  */
-	 18 ,	/*  dot_horz_spacing  */
-	 17 ,	/*  dot_vert_spacing  */
-	 37 ,	/*  horizontal_tab_delay  */
-	 1 ,	/*  init_tabs  */
-	 9 ,	/*  label_height  */
-	 10 ,	/*  label_width  */
-	 2 ,	/*  lines  */
-	 3 ,	/*  lines_of_memory  */
-	 4 ,	/*  magic_cookie_glitch  */
-	 33 ,	/*  magic_cookie_glitch_ul  */
-	 11 ,	/*  max_attributes  */
-	 13 ,	/*  max_colors  */
-	 19 ,	/*  max_micro_address  */
-	 20 ,	/*  max_micro_jump  */
-	 14 ,	/*  max_pairs  */
-	 12 ,	/*  maximum_windows  */
-	 21 ,	/*  micro_col_size  */
-	 22 ,	/*  micro_line_size  */
-	 35 ,	/*  new_line_delay  */
-	 15 ,	/*  no_color_video  */
-	 8 ,	/*  num_labels  */
-	 38 ,	/*  number_of_function_keys  */
-	 23 ,	/*  number_of_pins  */
-	 24 ,	/*  output_res_char  */
-	 26 ,	/*  output_res_horz_inch  */
-	 25 ,	/*  output_res_line  */
-	 27 ,	/*  output_res_vert_inch  */
-	 5 ,	/*  padding_baud_rate  */
-	 28 ,	/*  print_rate  */
-	 6 ,	/*  virtual_terminal  */
-	 29 ,	/*  wide_char_size  */
-	 7 ,	/*  width_status_line  */
-};
-
-static const PredIdx str_variable_sort[] = {
-	 406 ,	/*  acs_btee  */
-	 146 ,	/*  acs_chars  */
-	 408 ,	/*  acs_hline  */
-	 401 ,	/*  acs_llcorner  */
-	 403 ,	/*  acs_lrcorner  */
-	 404 ,	/*  acs_ltee  */
-	 410 ,	/*  acs_plus  */
-	 405 ,	/*  acs_rtee  */
-	 407 ,	/*  acs_ttee  */
-	 400 ,	/*  acs_ulcorner  */
-	 402 ,	/*  acs_urcorner  */
-	 409 ,	/*  acs_vline  */
-	 385 ,	/*  alt_scancode_esc  */
-	 399 ,	/*  arrow_key_map  */
-	 0 ,	/*  back_tab  */
-	 397 ,	/*  backspace_if_not_bs  */
-	 1 ,	/*  bell  */
-	 372 ,	/*  bit_image_carriage_return  */
-	 371 ,	/*  bit_image_newline  */
-	 370 ,	/*  bit_image_repeat  */
-	 413 ,	/*  box_chars_1  */
-	 2 ,	/*  carriage_return  */
-	 304 ,	/*  change_char_pitch  */
-	 305 ,	/*  change_line_pitch  */
-	 306 ,	/*  change_res_horz  */
-	 307 ,	/*  change_res_vert  */
-	 3 ,	/*  change_scroll_region  */
-	 145 ,	/*  char_padding  */
-	 354 ,	/*  char_set_names  */
-	 4 ,	/*  clear_all_tabs  */
-	 270 ,	/*  clear_margins  */
-	 5 ,	/*  clear_screen  */
-	 269 ,	/*  clr_bol  */
-	 6 ,	/*  clr_eol  */
-	 7 ,	/*  clr_eos  */
-	 363 ,	/*  code_set_init  */
-	 373 ,	/*  color_names  */
-	 8 ,	/*  column_address  */
-	 9 ,	/*  command_character  */
-	 277 ,	/*  create_window  */
-	 10 ,	/*  cursor_address  */
-	 11 ,	/*  cursor_down  */
-	 12 ,	/*  cursor_home  */
-	 13 ,	/*  cursor_invisible  */
-	 14 ,	/*  cursor_left  */
-	 15 ,	/*  cursor_mem_address  */
-	 16 ,	/*  cursor_normal  */
-	 17 ,	/*  cursor_right  */
-	 18 ,	/*  cursor_to_ll  */
-	 19 ,	/*  cursor_up  */
-	 20 ,	/*  cursor_visible  */
-	 374 ,	/*  define_bit_image_region  */
-	 308 ,	/*  define_char  */
-	 21 ,	/*  delete_character  */
-	 22 ,	/*  delete_line  */
-	 362 ,	/*  device_type  */
-	 280 ,	/*  dial_phone  */
-	 23 ,	/*  dis_status_line  */
-	 275 ,	/*  display_clock  */
-	 378 ,	/*  display_pc_char  */
-	 24 ,	/*  down_half_line  */
-	 155 ,	/*  ena_acs  */
-	 375 ,	/*  end_bit_image_region  */
-	 25 ,	/*  enter_alt_charset_mode  */
-	 151 ,	/*  enter_am_mode  */
-	 26 ,	/*  enter_blink_mode  */
-	 27 ,	/*  enter_bold_mode  */
-	 28 ,	/*  enter_ca_mode  */
-	 29 ,	/*  enter_delete_mode  */
-	 30 ,	/*  enter_dim_mode  */
-	 309 ,	/*  enter_doublewide_mode  */
-	 310 ,	/*  enter_draft_quality  */
-	 386 ,	/*  enter_horizontal_hl_mode  */
-	 31 ,	/*  enter_insert_mode  */
-	 311 ,	/*  enter_italics_mode  */
-	 387 ,	/*  enter_left_hl_mode  */
-	 312 ,	/*  enter_leftward_mode  */
-	 388 ,	/*  enter_low_hl_mode  */
-	 313 ,	/*  enter_micro_mode  */
-	 314 ,	/*  enter_near_letter_quality  */
-	 315 ,	/*  enter_normal_quality  */
-	 379 ,	/*  enter_pc_charset_mode  */
-	 33 ,	/*  enter_protected_mode  */
-	 34 ,	/*  enter_reverse_mode  */
-	 389 ,	/*  enter_right_hl_mode  */
-	 381 ,	/*  enter_scancode_mode  */
-	 32 ,	/*  enter_secure_mode  */
-	 316 ,	/*  enter_shadow_mode  */
-	 35 ,	/*  enter_standout_mode  */
-	 317 ,	/*  enter_subscript_mode  */
-	 318 ,	/*  enter_superscript_mode  */
-	 390 ,	/*  enter_top_hl_mode  */
-	 36 ,	/*  enter_underline_mode  */
-	 319 ,	/*  enter_upward_mode  */
-	 391 ,	/*  enter_vertical_hl_mode  */
-	 149 ,	/*  enter_xon_mode  */
-	 37 ,	/*  erase_chars  */
-	 38 ,	/*  exit_alt_charset_mode  */
-	 152 ,	/*  exit_am_mode  */
-	 39 ,	/*  exit_attribute_mode  */
-	 40 ,	/*  exit_ca_mode  */
-	 41 ,	/*  exit_delete_mode  */
-	 320 ,	/*  exit_doublewide_mode  */
-	 42 ,	/*  exit_insert_mode  */
-	 321 ,	/*  exit_italics_mode  */
-	 322 ,	/*  exit_leftward_mode  */
-	 323 ,	/*  exit_micro_mode  */
-	 380 ,	/*  exit_pc_charset_mode  */
-	 382 ,	/*  exit_scancode_mode  */
-	 324 ,	/*  exit_shadow_mode  */
-	 43 ,	/*  exit_standout_mode  */
-	 325 ,	/*  exit_subscript_mode  */
-	 326 ,	/*  exit_superscript_mode  */
-	 44 ,	/*  exit_underline_mode  */
-	 327 ,	/*  exit_upward_mode  */
-	 150 ,	/*  exit_xon_mode  */
-	 285 ,	/*  fixed_pause  */
-	 284 ,	/*  flash_hook  */
-	 45 ,	/*  flash_screen  */
-	 46 ,	/*  form_feed  */
-	 47 ,	/*  from_status_line  */
-	 358 ,	/*  get_mouse  */
-	 278 ,	/*  goto_window  */
-	 279 ,	/*  hangup  */
-	 48 ,	/*  init_1string  */
-	 49 ,	/*  init_2string  */
-	 50 ,	/*  init_3string  */
-	 51 ,	/*  init_file  */
-	 138 ,	/*  init_prog  */
-	 299 ,	/*  initialize_color  */
-	 300 ,	/*  initialize_pair  */
-	 52 ,	/*  insert_character  */
-	 53 ,	/*  insert_line  */
-	 54 ,	/*  insert_padding  */
-	 139 ,	/*  key_a1  */
-	 140 ,	/*  key_a3  */
-	 141 ,	/*  key_b2  */
-	 55 ,	/*  key_backspace  */
-	 158 ,	/*  key_beg  */
-	 148 ,	/*  key_btab  */
-	 142 ,	/*  key_c1  */
-	 143 ,	/*  key_c3  */
-	 159 ,	/*  key_cancel  */
-	 56 ,	/*  key_catab  */
-	 57 ,	/*  key_clear  */
-	 160 ,	/*  key_close  */
-	 161 ,	/*  key_command  */
-	 162 ,	/*  key_copy  */
-	 163 ,	/*  key_create  */
-	 58 ,	/*  key_ctab  */
-	 59 ,	/*  key_dc  */
-	 60 ,	/*  key_dl  */
-	 61 ,	/*  key_down  */
-	 62 ,	/*  key_eic  */
-	 164 ,	/*  key_end  */
-	 165 ,	/*  key_enter  */
-	 63 ,	/*  key_eol  */
-	 64 ,	/*  key_eos  */
-	 166 ,	/*  key_exit  */
-	 65 ,	/*  key_f0  */
-	 66 ,	/*  key_f1  */
-	 67 ,	/*  key_f10  */
-	 216 ,	/*  key_f11  */
-	 217 ,	/*  key_f12  */
-	 218 ,	/*  key_f13  */
-	 219 ,	/*  key_f14  */
-	 220 ,	/*  key_f15  */
-	 221 ,	/*  key_f16  */
-	 222 ,	/*  key_f17  */
-	 223 ,	/*  key_f18  */
-	 224 ,	/*  key_f19  */
-	 68 ,	/*  key_f2  */
-	 225 ,	/*  key_f20  */
-	 226 ,	/*  key_f21  */
-	 227 ,	/*  key_f22  */
-	 228 ,	/*  key_f23  */
-	 229 ,	/*  key_f24  */
-	 230 ,	/*  key_f25  */
-	 231 ,	/*  key_f26  */
-	 232 ,	/*  key_f27  */
-	 233 ,	/*  key_f28  */
-	 234 ,	/*  key_f29  */
-	 69 ,	/*  key_f3  */
-	 235 ,	/*  key_f30  */
-	 236 ,	/*  key_f31  */
-	 237 ,	/*  key_f32  */
-	 238 ,	/*  key_f33  */
-	 239 ,	/*  key_f34  */
-	 240 ,	/*  key_f35  */
-	 241 ,	/*  key_f36  */
-	 242 ,	/*  key_f37  */
-	 243 ,	/*  key_f38  */
-	 244 ,	/*  key_f39  */
-	 70 ,	/*  key_f4  */
-	 245 ,	/*  key_f40  */
-	 246 ,	/*  key_f41  */
-	 247 ,	/*  key_f42  */
-	 248 ,	/*  key_f43  */
-	 249 ,	/*  key_f44  */
-	 250 ,	/*  key_f45  */
-	 251 ,	/*  key_f46  */
-	 252 ,	/*  key_f47  */
-	 253 ,	/*  key_f48  */
-	 254 ,	/*  key_f49  */
-	 71 ,	/*  key_f5  */
-	 255 ,	/*  key_f50  */
-	 256 ,	/*  key_f51  */
-	 257 ,	/*  key_f52  */
-	 258 ,	/*  key_f53  */
-	 259 ,	/*  key_f54  */
-	 260 ,	/*  key_f55  */
-	 261 ,	/*  key_f56  */
-	 262 ,	/*  key_f57  */
-	 263 ,	/*  key_f58  */
-	 264 ,	/*  key_f59  */
-	 72 ,	/*  key_f6  */
-	 265 ,	/*  key_f60  */
-	 266 ,	/*  key_f61  */
-	 267 ,	/*  key_f62  */
-	 268 ,	/*  key_f63  */
-	 73 ,	/*  key_f7  */
-	 74 ,	/*  key_f8  */
-	 75 ,	/*  key_f9  */
-	 167 ,	/*  key_find  */
-	 168 ,	/*  key_help  */
-	 76 ,	/*  key_home  */
-	 77 ,	/*  key_ic  */
-	 78 ,	/*  key_il  */
-	 79 ,	/*  key_left  */
-	 80 ,	/*  key_ll  */
-	 169 ,	/*  key_mark  */
-	 170 ,	/*  key_message  */
-	 355 ,	/*  key_mouse  */
-	 171 ,	/*  key_move  */
-	 172 ,	/*  key_next  */
-	 81 ,	/*  key_npage  */
-	 173 ,	/*  key_open  */
-	 174 ,	/*  key_options  */
-	 82 ,	/*  key_ppage  */
-	 175 ,	/*  key_previous  */
-	 176 ,	/*  key_print  */
-	 177 ,	/*  key_redo  */
-	 178 ,	/*  key_reference  */
-	 179 ,	/*  key_refresh  */
-	 180 ,	/*  key_replace  */
-	 181 ,	/*  key_restart  */
-	 182 ,	/*  key_resume  */
-	 83 ,	/*  key_right  */
-	 183 ,	/*  key_save  */
-	 186 ,	/*  key_sbeg  */
-	 187 ,	/*  key_scancel  */
-	 188 ,	/*  key_scommand  */
-	 189 ,	/*  key_scopy  */
-	 190 ,	/*  key_screate  */
-	 191 ,	/*  key_sdc  */
-	 192 ,	/*  key_sdl  */
-	 193 ,	/*  key_select  */
-	 194 ,	/*  key_send  */
-	 195 ,	/*  key_seol  */
-	 196 ,	/*  key_sexit  */
-	 84 ,	/*  key_sf  */
-	 197 ,	/*  key_sfind  */
-	 198 ,	/*  key_shelp  */
-	 199 ,	/*  key_shome  */
-	 200 ,	/*  key_sic  */
-	 201 ,	/*  key_sleft  */
-	 202 ,	/*  key_smessage  */
-	 203 ,	/*  key_smove  */
-	 204 ,	/*  key_snext  */
-	 205 ,	/*  key_soptions  */
-	 206 ,	/*  key_sprevious  */
-	 207 ,	/*  key_sprint  */
-	 85 ,	/*  key_sr  */
-	 208 ,	/*  key_sredo  */
-	 209 ,	/*  key_sreplace  */
-	 210 ,	/*  key_sright  */
-	 211 ,	/*  key_srsume  */
-	 212 ,	/*  key_ssave  */
-	 213 ,	/*  key_ssuspend  */
-	 86 ,	/*  key_stab  */
-	 214 ,	/*  key_sundo  */
-	 184 ,	/*  key_suspend  */
-	 185 ,	/*  key_undo  */
-	 87 ,	/*  key_up  */
-	 88 ,	/*  keypad_local  */
-	 89 ,	/*  keypad_xmit  */
-	 90 ,	/*  lab_f0  */
-	 91 ,	/*  lab_f1  */
-	 92 ,	/*  lab_f10  */
-	 93 ,	/*  lab_f2  */
-	 94 ,	/*  lab_f3  */
-	 95 ,	/*  lab_f4  */
-	 96 ,	/*  lab_f5  */
-	 97 ,	/*  lab_f6  */
-	 98 ,	/*  lab_f7  */
-	 99 ,	/*  lab_f8  */
-	 100 ,	/*  lab_f9  */
-	 273 ,	/*  label_format  */
-	 157 ,	/*  label_off  */
-	 156 ,	/*  label_on  */
-	 396 ,	/*  linefeed_if_not_lf  */
-	 411 ,	/*  memory_lock  */
-	 412 ,	/*  memory_unlock  */
-	 101 ,	/*  meta_off  */
-	 102 ,	/*  meta_on  */
-	 328 ,	/*  micro_column_address  */
-	 329 ,	/*  micro_down  */
-	 330 ,	/*  micro_left  */
-	 331 ,	/*  micro_right  */
-	 332 ,	/*  micro_row_address  */
-	 333 ,	/*  micro_up  */
-	 356 ,	/*  mouse_info  */
-	 103 ,	/*  newline  */
-	 334 ,	/*  order_of_pins  */
-	 298 ,	/*  orig_colors  */
-	 297 ,	/*  orig_pair  */
-	 398 ,	/*  other_non_function_keys  */
-	 104 ,	/*  pad_char  */
-	 105 ,	/*  parm_dch  */
-	 106 ,	/*  parm_delete_line  */
-	 107 ,	/*  parm_down_cursor  */
-	 335 ,	/*  parm_down_micro  */
-	 108 ,	/*  parm_ich  */
-	 109 ,	/*  parm_index  */
-	 110 ,	/*  parm_insert_line  */
-	 111 ,	/*  parm_left_cursor  */
-	 336 ,	/*  parm_left_micro  */
-	 112 ,	/*  parm_right_cursor  */
-	 337 ,	/*  parm_right_micro  */
-	 113 ,	/*  parm_rindex  */
-	 114 ,	/*  parm_up_cursor  */
-	 338 ,	/*  parm_up_micro  */
-	 383 ,	/*  pc_term_options  */
-	 115 ,	/*  pkey_key  */
-	 116 ,	/*  pkey_local  */
-	 361 ,	/*  pkey_plab  */
-	 117 ,	/*  pkey_xmit  */
-	 147 ,	/*  plab_norm  */
-	 118 ,	/*  print_screen  */
-	 144 ,	/*  prtr_non  */
-	 119 ,	/*  prtr_off  */
-	 120 ,	/*  prtr_on  */
-	 283 ,	/*  pulse  */
-	 281 ,	/*  quick_dial  */
-	 276 ,	/*  remove_clock  */
-	 121 ,	/*  repeat_char  */
-	 215 ,	/*  req_for_input  */
-	 357 ,	/*  req_mouse_pos  */
-	 122 ,	/*  reset_1string  */
-	 123 ,	/*  reset_2string  */
-	 124 ,	/*  reset_3string  */
-	 125 ,	/*  reset_file  */
-	 126 ,	/*  restore_cursor  */
-	 127 ,	/*  row_address  */
-	 128 ,	/*  save_cursor  */
-	 384 ,	/*  scancode_escape  */
-	 129 ,	/*  scroll_forward  */
-	 130 ,	/*  scroll_reverse  */
-	 339 ,	/*  select_char_set  */
-	 364 ,	/*  set0_des_seq  */
-	 365 ,	/*  set1_des_seq  */
-	 366 ,	/*  set2_des_seq  */
-	 367 ,	/*  set3_des_seq  */
-	 392 ,	/*  set_a_attributes  */
-	 360 ,	/*  set_a_background  */
-	 359 ,	/*  set_a_foreground  */
-	 131 ,	/*  set_attributes  */
-	 303 ,	/*  set_background  */
-	 340 ,	/*  set_bottom_margin  */
-	 341 ,	/*  set_bottom_margin_parm  */
-	 274 ,	/*  set_clock  */
-	 376 ,	/*  set_color_band  */
-	 301 ,	/*  set_color_pair  */
-	 302 ,	/*  set_foreground  */
-	 271 ,	/*  set_left_margin  */
-	 342 ,	/*  set_left_margin_parm  */
-	 368 ,	/*  set_lr_margin  */
-	 377 ,	/*  set_page_length  */
-	 393 ,	/*  set_pglen_inch  */
-	 272 ,	/*  set_right_margin  */
-	 343 ,	/*  set_right_margin_parm  */
-	 132 ,	/*  set_tab  */
-	 369 ,	/*  set_tb_margin  */
-	 344 ,	/*  set_top_margin  */
-	 345 ,	/*  set_top_margin_parm  */
-	 133 ,	/*  set_window  */
-	 346 ,	/*  start_bit_image  */
-	 347 ,	/*  start_char_set_def  */
-	 348 ,	/*  stop_bit_image  */
-	 349 ,	/*  stop_char_set_def  */
-	 350 ,	/*  subscript_characters  */
-	 351 ,	/*  superscript_characters  */
-	 134 ,	/*  tab  */
-	 394 ,	/*  termcap_init2  */
-	 395 ,	/*  termcap_reset  */
-	 352 ,	/*  these_cause_cr  */
-	 135 ,	/*  to_status_line  */
-	 282 ,	/*  tone  */
-	 136 ,	/*  underline_char  */
-	 137 ,	/*  up_half_line  */
-	 287 ,	/*  user0  */
-	 288 ,	/*  user1  */
-	 289 ,	/*  user2  */
-	 290 ,	/*  user3  */
-	 291 ,	/*  user4  */
-	 292 ,	/*  user5  */
-	 293 ,	/*  user6  */
-	 294 ,	/*  user7  */
-	 295 ,	/*  user8  */
-	 296 ,	/*  user9  */
-	 286 ,	/*  wait_tone  */
-	 154 ,	/*  xoff_character  */
-	 153 ,	/*  xon_character  */
-	 353 ,	/*  zero_motion  */
-};
-
-static const PredIdx bool_termcap_sort[] = {
-	 22 ,	/*  5i  */
-	 23 ,	/*  HC  */
-	 40 ,	/*  MT  */
-	 26 ,	/*  ND  */
-	 41 ,	/*  NL  */
-	 25 ,	/*  NP  */
-	 24 ,	/*  NR  */
-	 30 ,	/*  YA  */
-	 31 ,	/*  YB  */
-	 32 ,	/*  YC  */
-	 33 ,	/*  YD  */
-	 34 ,	/*  YE  */
-	 35 ,	/*  YF  */
-	 36 ,	/*  YG  */
-	 1 ,	/*  am  */
-	 37 ,	/*  bs  */
-	 0 ,	/*  bw  */
-	 27 ,	/*  cc  */
-	 11 ,	/*  da  */
-	 12 ,	/*  db  */
-	 5 ,	/*  eo  */
-	 16 ,	/*  es  */
-	 6 ,	/*  gn  */
-	 7 ,	/*  hc  */
-	 29 ,	/*  hl  */
-	 9 ,	/*  hs  */
-	 18 ,	/*  hz  */
-	 10 ,	/*  in  */
-	 8 ,	/*  km  */
-	 13 ,	/*  mi  */
-	 14 ,	/*  ms  */
-	 39 ,	/*  nc  */
-	 38 ,	/*  ns  */
-	 21 ,	/*  nx  */
-	 15 ,	/*  os  */
-	 42 ,	/*  pt  */
-	 19 ,	/*  ul  */
-	 28 ,	/*  ut  */
-	 2 ,	/*  xb  */
-	 4 ,	/*  xn  */
-	 20 ,	/*  xo  */
-	 43 ,	/*  xr  */
-	 3 ,	/*  xs  */
-	 17 ,	/*  xt  */
-};
-
-static const PredIdx num_termcap_sort[] = {
-	 30 ,	/*  BT  */
-	 13 ,	/*  Co  */
-	 12 ,	/*  MW  */
-	 15 ,	/*  NC  */
-	 8 ,	/*  Nl  */
-	 16 ,	/*  Ya  */
-	 17 ,	/*  Yb  */
-	 18 ,	/*  Yc  */
-	 19 ,	/*  Yd  */
-	 20 ,	/*  Ye  */
-	 21 ,	/*  Yf  */
-	 22 ,	/*  Yg  */
-	 23 ,	/*  Yh  */
-	 24 ,	/*  Yi  */
-	 25 ,	/*  Yj  */
-	 26 ,	/*  Yk  */
-	 27 ,	/*  Yl  */
-	 28 ,	/*  Ym  */
-	 29 ,	/*  Yn  */
-	 31 ,	/*  Yo  */
-	 32 ,	/*  Yp  */
-	 0 ,	/*  co  */
-	 36 ,	/*  dB  */
-	 34 ,	/*  dC  */
-	 35 ,	/*  dN  */
-	 37 ,	/*  dT  */
-	 1 ,	/*  it  */
-	 38 ,	/*  kn  */
-	 9 ,	/*  lh  */
-	 2 ,	/*  li  */
-	 3 ,	/*  lm  */
-	 10 ,	/*  lw  */
-	 11 ,	/*  ma  */
-	 14 ,	/*  pa  */
-	 5 ,	/*  pb  */
-	 4 ,	/*  sg  */
-	 33 ,	/*  ug  */
-	 6 ,	/*  vt  */
-	 7 ,	/*  ws  */
-};
-
-static const PredIdx str_termcap_sort[] = {
-	 212 ,	/*  !1  */
-	 213 ,	/*  !2  */
-	 214 ,	/*  !3  */
-	 198 ,	/*  #1  */
-	 199 ,	/*  #2  */
-	 200 ,	/*  #3  */
-	 201 ,	/*  #4  */
-	 177 ,	/*  %0  */
-	 168 ,	/*  %1  */
-	 169 ,	/*  %2  */
-	 170 ,	/*  %3  */
-	 171 ,	/*  %4  */
-	 172 ,	/*  %5  */
-	 173 ,	/*  %6  */
-	 174 ,	/*  %7  */
-	 175 ,	/*  %8  */
-	 176 ,	/*  %9  */
-	 202 ,	/*  %a  */
-	 203 ,	/*  %b  */
-	 204 ,	/*  %c  */
-	 205 ,	/*  %d  */
-	 206 ,	/*  %e  */
-	 207 ,	/*  %f  */
-	 208 ,	/*  %g  */
-	 209 ,	/*  %h  */
-	 210 ,	/*  %i  */
-	 211 ,	/*  %j  */
-	 187 ,	/*  &0  */
-	 178 ,	/*  &1  */
-	 179 ,	/*  &2  */
-	 180 ,	/*  &3  */
-	 181 ,	/*  &4  */
-	 182 ,	/*  &5  */
-	 183 ,	/*  &6  */
-	 184 ,	/*  &7  */
-	 185 ,	/*  &8  */
-	 186 ,	/*  &9  */
-	 197 ,	/*  *0  */
-	 188 ,	/*  *1  */
-	 189 ,	/*  *2  */
-	 190 ,	/*  *3  */
-	 191 ,	/*  *4  */
-	 192 ,	/*  *5  */
-	 193 ,	/*  *6  */
-	 194 ,	/*  *7  */
-	 195 ,	/*  *8  */
-	 196 ,	/*  *9  */
-	 167 ,	/*  @0  */
-	 158 ,	/*  @1  */
-	 159 ,	/*  @2  */
-	 160 ,	/*  @3  */
-	 161 ,	/*  @4  */
-	 162 ,	/*  @5  */
-	 163 ,	/*  @6  */
-	 164 ,	/*  @7  */
-	 165 ,	/*  @8  */
-	 166 ,	/*  @9  */
-	 360 ,	/*  AB  */
-	 359 ,	/*  AF  */
-	 110 ,	/*  AL  */
-	 9 ,	/*  CC  */
-	 15 ,	/*  CM  */
-	 277 ,	/*  CW  */
-	 105 ,	/*  DC  */
-	 280 ,	/*  DI  */
-	 275 ,	/*  DK  */
-	 106 ,	/*  DL  */
-	 107 ,	/*  DO  */
-	 216 ,	/*  F1  */
-	 217 ,	/*  F2  */
-	 218 ,	/*  F3  */
-	 219 ,	/*  F4  */
-	 220 ,	/*  F5  */
-	 221 ,	/*  F6  */
-	 222 ,	/*  F7  */
-	 223 ,	/*  F8  */
-	 224 ,	/*  F9  */
-	 225 ,	/*  FA  */
-	 226 ,	/*  FB  */
-	 227 ,	/*  FC  */
-	 228 ,	/*  FD  */
-	 229 ,	/*  FE  */
-	 230 ,	/*  FF  */
-	 231 ,	/*  FG  */
-	 232 ,	/*  FH  */
-	 233 ,	/*  FI  */
-	 234 ,	/*  FJ  */
-	 235 ,	/*  FK  */
-	 236 ,	/*  FL  */
-	 237 ,	/*  FM  */
-	 238 ,	/*  FN  */
-	 239 ,	/*  FO  */
-	 240 ,	/*  FP  */
-	 241 ,	/*  FQ  */
-	 242 ,	/*  FR  */
-	 243 ,	/*  FS  */
-	 244 ,	/*  FT  */
-	 245 ,	/*  FU  */
-	 246 ,	/*  FV  */
-	 247 ,	/*  FW  */
-	 248 ,	/*  FX  */
-	 249 ,	/*  FY  */
-	 250 ,	/*  FZ  */
-	 251 ,	/*  Fa  */
-	 252 ,	/*  Fb  */
-	 253 ,	/*  Fc  */
-	 254 ,	/*  Fd  */
-	 255 ,	/*  Fe  */
-	 256 ,	/*  Ff  */
-	 257 ,	/*  Fg  */
-	 258 ,	/*  Fh  */
-	 259 ,	/*  Fi  */
-	 260 ,	/*  Fj  */
-	 261 ,	/*  Fk  */
-	 262 ,	/*  Fl  */
-	 263 ,	/*  Fm  */
-	 264 ,	/*  Fn  */
-	 265 ,	/*  Fo  */
-	 266 ,	/*  Fp  */
-	 267 ,	/*  Fq  */
-	 268 ,	/*  Fr  */
-	 402 ,	/*  G1  */
-	 400 ,	/*  G2  */
-	 401 ,	/*  G3  */
-	 403 ,	/*  G4  */
-	 410 ,	/*  GC  */
-	 407 ,	/*  GD  */
-	 408 ,	/*  GH  */
-	 405 ,	/*  GL  */
-	 404 ,	/*  GR  */
-	 406 ,	/*  GU  */
-	 409 ,	/*  GV  */
-	 358 ,	/*  Gm  */
-	 279 ,	/*  HU  */
-	 108 ,	/*  IC  */
-	 299 ,	/*  Ic  */
-	 300 ,	/*  Ip  */
-	 139 ,	/*  K1  */
-	 141 ,	/*  K2  */
-	 140 ,	/*  K3  */
-	 142 ,	/*  K4  */
-	 143 ,	/*  K5  */
-	 355 ,	/*  Km  */
-	 111 ,	/*  LE  */
-	 157 ,	/*  LF  */
-	 156 ,	/*  LO  */
-	 273 ,	/*  Lf  */
-	 270 ,	/*  MC  */
-	 271 ,	/*  ML  */
-	 368 ,	/*  ML  */
-	 272 ,	/*  MR  */
-	 369 ,	/*  MT  */
-	 356 ,	/*  Mi  */
-	 285 ,	/*  PA  */
-	 283 ,	/*  PU  */
-	 281 ,	/*  QD  */
-	 152 ,	/*  RA  */
-	 276 ,	/*  RC  */
-	 215 ,	/*  RF  */
-	 112 ,	/*  RI  */
-	 357 ,	/*  RQ  */
-	 150 ,	/*  RX  */
-	 378 ,	/*  S1  */
-	 379 ,	/*  S2  */
-	 380 ,	/*  S3  */
-	 381 ,	/*  S4  */
-	 382 ,	/*  S5  */
-	 383 ,	/*  S6  */
-	 384 ,	/*  S7  */
-	 385 ,	/*  S8  */
-	 151 ,	/*  SA  */
-	 274 ,	/*  SC  */
-	 109 ,	/*  SF  */
-	 113 ,	/*  SR  */
-	 149 ,	/*  SX  */
-	 303 ,	/*  Sb  */
-	 302 ,	/*  Sf  */
-	 282 ,	/*  TO  */
-	 114 ,	/*  UP  */
-	 286 ,	/*  WA  */
-	 278 ,	/*  WG  */
-	 154 ,	/*  XF  */
-	 153 ,	/*  XN  */
-	 386 ,	/*  Xh  */
-	 387 ,	/*  Xl  */
-	 388 ,	/*  Xo  */
-	 389 ,	/*  Xr  */
-	 390 ,	/*  Xt  */
-	 391 ,	/*  Xv  */
-	 370 ,	/*  Xy  */
-	 393 ,	/*  YI  */
-	 377 ,	/*  YZ  */
-	 372 ,	/*  Yv  */
-	 373 ,	/*  Yw  */
-	 374 ,	/*  Yx  */
-	 375 ,	/*  Yy  */
-	 376 ,	/*  Yz  */
-	 304 ,	/*  ZA  */
-	 305 ,	/*  ZB  */
-	 306 ,	/*  ZC  */
-	 307 ,	/*  ZD  */
-	 308 ,	/*  ZE  */
-	 309 ,	/*  ZF  */
-	 310 ,	/*  ZG  */
-	 311 ,	/*  ZH  */
-	 312 ,	/*  ZI  */
-	 313 ,	/*  ZJ  */
-	 314 ,	/*  ZK  */
-	 315 ,	/*  ZL  */
-	 316 ,	/*  ZM  */
-	 317 ,	/*  ZN  */
-	 318 ,	/*  ZO  */
-	 319 ,	/*  ZP  */
-	 320 ,	/*  ZQ  */
-	 321 ,	/*  ZR  */
-	 322 ,	/*  ZS  */
-	 323 ,	/*  ZT  */
-	 324 ,	/*  ZU  */
-	 325 ,	/*  ZV  */
-	 326 ,	/*  ZW  */
-	 327 ,	/*  ZX  */
-	 328 ,	/*  ZY  */
-	 329 ,	/*  ZZ  */
-	 330 ,	/*  Za  */
-	 331 ,	/*  Zb  */
-	 332 ,	/*  Zc  */
-	 333 ,	/*  Zd  */
-	 334 ,	/*  Ze  */
-	 335 ,	/*  Zf  */
-	 336 ,	/*  Zg  */
-	 337 ,	/*  Zh  */
-	 338 ,	/*  Zi  */
-	 339 ,	/*  Zj  */
-	 340 ,	/*  Zk  */
-	 341 ,	/*  Zl  */
-	 342 ,	/*  Zm  */
-	 343 ,	/*  Zn  */
-	 344 ,	/*  Zo  */
-	 345 ,	/*  Zp  */
-	 346 ,	/*  Zq  */
-	 347 ,	/*  Zr  */
-	 348 ,	/*  Zs  */
-	 349 ,	/*  Zt  */
-	 350 ,	/*  Zu  */
-	 351 ,	/*  Zv  */
-	 352 ,	/*  Zw  */
-	 353 ,	/*  Zx  */
-	 354 ,	/*  Zy  */
-	 371 ,	/*  Zz  */
-	 146 ,	/*  ac  */
-	 38 ,	/*  ae  */
-	 53 ,	/*  al  */
-	 25 ,	/*  as  */
-	 397 ,	/*  bc  */
-	 1 ,	/*  bl  */
-	 0 ,	/*  bt  */
-	 413 ,	/*  bx  */
-	 269 ,	/*  cb  */
-	 7 ,	/*  cd  */
-	 6 ,	/*  ce  */
-	 8 ,	/*  ch  */
-	 363 ,	/*  ci  */
-	 5 ,	/*  cl  */
-	 10 ,	/*  cm  */
-	 2 ,	/*  cr  */
-	 3 ,	/*  cs  */
-	 4 ,	/*  ct  */
-	 127 ,	/*  cv  */
-	 21 ,	/*  dc  */
-	 22 ,	/*  dl  */
-	 29 ,	/*  dm  */
-	 11 ,	/*  do  */
-	 23 ,	/*  ds  */
-	 362 ,	/*  dv  */
-	 155 ,	/*  eA  */
-	 37 ,	/*  ec  */
-	 41 ,	/*  ed  */
-	 42 ,	/*  ei  */
-	 46 ,	/*  ff  */
-	 284 ,	/*  fh  */
-	 47 ,	/*  fs  */
-	 24 ,	/*  hd  */
-	 12 ,	/*  ho  */
-	 137 ,	/*  hu  */
-	 48 ,	/*  i1  */
-	 394 ,	/*  i2  */
-	 50 ,	/*  i3  */
-	 138 ,	/*  iP  */
-	 52 ,	/*  ic  */
-	 51 ,	/*  if  */
-	 31 ,	/*  im  */
-	 54 ,	/*  ip  */
-	 49 ,	/*  is  */
-	 65 ,	/*  k0  */
-	 66 ,	/*  k1  */
-	 68 ,	/*  k2  */
-	 69 ,	/*  k3  */
-	 70 ,	/*  k4  */
-	 71 ,	/*  k5  */
-	 72 ,	/*  k6  */
-	 73 ,	/*  k7  */
-	 74 ,	/*  k8  */
-	 75 ,	/*  k9  */
-	 67 ,	/*  k;  */
-	 78 ,	/*  kA  */
-	 148 ,	/*  kB  */
-	 57 ,	/*  kC  */
-	 59 ,	/*  kD  */
-	 63 ,	/*  kE  */
-	 84 ,	/*  kF  */
-	 80 ,	/*  kH  */
-	 77 ,	/*  kI  */
-	 60 ,	/*  kL  */
-	 62 ,	/*  kM  */
-	 81 ,	/*  kN  */
-	 82 ,	/*  kP  */
-	 85 ,	/*  kR  */
-	 64 ,	/*  kS  */
-	 86 ,	/*  kT  */
-	 56 ,	/*  ka  */
-	 55 ,	/*  kb  */
-	 61 ,	/*  kd  */
-	 88 ,	/*  ke  */
-	 76 ,	/*  kh  */
-	 79 ,	/*  kl  */
-	 398 ,	/*  ko  */
-	 83 ,	/*  kr  */
-	 89 ,	/*  ks  */
-	 58 ,	/*  kt  */
-	 87 ,	/*  ku  */
-	 90 ,	/*  l0  */
-	 91 ,	/*  l1  */
-	 93 ,	/*  l2  */
-	 94 ,	/*  l3  */
-	 95 ,	/*  l4  */
-	 96 ,	/*  l5  */
-	 97 ,	/*  l6  */
-	 98 ,	/*  l7  */
-	 99 ,	/*  l8  */
-	 100 ,	/*  l9  */
-	 92 ,	/*  la  */
-	 14 ,	/*  le  */
-	 18 ,	/*  ll  */
-	 399 ,	/*  ma  */
-	 26 ,	/*  mb  */
-	 27 ,	/*  md  */
-	 39 ,	/*  me  */
-	 30 ,	/*  mh  */
-	 32 ,	/*  mk  */
-	 411 ,	/*  ml  */
-	 102 ,	/*  mm  */
-	 101 ,	/*  mo  */
-	 33 ,	/*  mp  */
-	 34 ,	/*  mr  */
-	 412 ,	/*  mu  */
-	 17 ,	/*  nd  */
-	 396 ,	/*  nl  */
-	 103 ,	/*  nw  */
-	 298 ,	/*  oc  */
-	 297 ,	/*  op  */
-	 144 ,	/*  pO  */
-	 104 ,	/*  pc  */
-	 119 ,	/*  pf  */
-	 115 ,	/*  pk  */
-	 116 ,	/*  pl  */
-	 147 ,	/*  pn  */
-	 120 ,	/*  po  */
-	 118 ,	/*  ps  */
-	 117 ,	/*  px  */
-	 122 ,	/*  r1  */
-	 123 ,	/*  r2  */
-	 124 ,	/*  r3  */
-	 145 ,	/*  rP  */
-	 126 ,	/*  rc  */
-	 125 ,	/*  rf  */
-	 121 ,	/*  rp  */
-	 395 ,	/*  rs  */
-	 364 ,	/*  s0  */
-	 365 ,	/*  s1  */
-	 366 ,	/*  s2  */
-	 367 ,	/*  s3  */
-	 392 ,	/*  sA  */
-	 131 ,	/*  sa  */
-	 128 ,	/*  sc  */
-	 43 ,	/*  se  */
-	 129 ,	/*  sf  */
-	 35 ,	/*  so  */
-	 301 ,	/*  sp  */
-	 130 ,	/*  sr  */
-	 132 ,	/*  st  */
-	 134 ,	/*  ta  */
-	 40 ,	/*  te  */
-	 28 ,	/*  ti  */
-	 135 ,	/*  ts  */
-	 287 ,	/*  u0  */
-	 288 ,	/*  u1  */
-	 289 ,	/*  u2  */
-	 290 ,	/*  u3  */
-	 291 ,	/*  u4  */
-	 292 ,	/*  u5  */
-	 293 ,	/*  u6  */
-	 294 ,	/*  u7  */
-	 295 ,	/*  u8  */
-	 296 ,	/*  u9  */
-	 136 ,	/*  uc  */
-	 44 ,	/*  ue  */
-	 19 ,	/*  up  */
-	 36 ,	/*  us  */
-	 45 ,	/*  vb  */
-	 16 ,	/*  ve  */
-	 13 ,	/*  vi  */
-	 20 ,	/*  vs  */
-	 133 ,	/*  wi  */
-	 361 ,	/*  xl  */
-};
-
-static const bool bool_from_termcap[] = {
-	TRUE,	/*  bw  */
-	TRUE,	/*  am  */
-	TRUE,	/*  xsb  */
-	TRUE,	/*  xhp  */
-	TRUE,	/*  xenl  */
-	TRUE,	/*  eo  */
-	TRUE,	/*  gn  */
-	TRUE,	/*  hc  */
-	TRUE,	/*  km  */
-	TRUE,	/*  hs  */
-	TRUE,	/*  in  */
-	TRUE,	/*  da  */
-	TRUE,	/*  db  */
-	TRUE,	/*  mir  */
-	TRUE,	/*  msgr  */
-	TRUE,	/*  os  */
-	TRUE,	/*  eslok  */
-	TRUE,	/*  xt  */
-	TRUE,	/*  hz  */
-	TRUE,	/*  ul  */
-	TRUE,	/*  xon  */
-	FALSE,	/*  nxon  */
-	FALSE,	/*  mc5i  */
-	FALSE,	/*  chts  */
-	FALSE,	/*  nrrmc  */
-	FALSE,	/*  npc  */
-	FALSE,	/*  ndscr  */
-	FALSE,	/*  ccc  */
-	FALSE,	/*  bce  */
-	FALSE,	/*  hls  */
-	FALSE,	/*  xhpa  */
-	FALSE,	/*  crxm  */
-	FALSE,	/*  daisy  */
-	FALSE,	/*  xvpa  */
-	FALSE,	/*  sam  */
-	FALSE,	/*  cpix  */
-	FALSE,	/*  lpix  */
-	TRUE,	/*  OTbs  */
-	TRUE,	/*  OTns  */
-	TRUE,	/*  OTnc  */
-	FALSE,	/*  OTMT  */
-	TRUE,	/*  OTNL  */
-	TRUE,	/*  OTpt  */
-	TRUE,	/*  OTxr  */
-#define OK_bool_from_termcap 43
-};
-
-static const bool num_from_termcap[] = {
-	TRUE,	/*  cols  */
-	TRUE,	/*  it  */
-	TRUE,	/*  lines  */
-	TRUE,	/*  lm  */
-	TRUE,	/*  xmc  */
-	TRUE,	/*  pb  */
-	TRUE,	/*  vt  */
-	TRUE,	/*  wsl  */
-	FALSE,	/*  nlab  */
-	FALSE,	/*  lh  */
-	FALSE,	/*  lw  */
-	TRUE,	/*  ma  */
-	FALSE,	/*  wnum  */
-	FALSE,	/*  colors  */
-	FALSE,	/*  pairs  */
-	FALSE,	/*  ncv  */
-	FALSE,	/*  bufsz  */
-	FALSE,	/*  spinv  */
-	FALSE,	/*  spinh  */
-	FALSE,	/*  maddr  */
-	FALSE,	/*  mjump  */
-	FALSE,	/*  mcs  */
-	FALSE,	/*  mls  */
-	FALSE,	/*  npins  */
-	FALSE,	/*  orc  */
-	FALSE,	/*  orl  */
-	FALSE,	/*  orhi  */
-	FALSE,	/*  orvi  */
-	FALSE,	/*  cps  */
-	FALSE,	/*  widcs  */
-	FALSE,	/*  btns  */
-	FALSE,	/*  bitwin  */
-	FALSE,	/*  bitype  */
-	TRUE,	/*  OTug  */
-	TRUE,	/*  OTdC  */
-	TRUE,	/*  OTdN  */
-	TRUE,	/*  OTdB  */
-	TRUE,	/*  OTdT  */
-	FALSE,	/*  OTkn  */
-#define OK_num_from_termcap 37
-};
-
-static const bool str_from_termcap[] = {
-	TRUE,	/*  cbt  */
-	TRUE,	/*  bel  */
-	TRUE,	/*  cr  */
-	TRUE,	/*  csr  */
-	TRUE,	/*  tbc  */
-	TRUE,	/*  clear  */
-	TRUE,	/*  el  */
-	TRUE,	/*  ed  */
-	FALSE,	/*  hpa  */
-	TRUE,	/*  cmdch  */
-	TRUE,	/*  cup  */
-	TRUE,	/*  cud1  */
-	TRUE,	/*  home  */
-	TRUE,	/*  civis  */
-	TRUE,	/*  cub1  */
-	TRUE,	/*  mrcup  */
-	TRUE,	/*  cnorm  */
-	TRUE,	/*  cuf1  */
-	TRUE,	/*  ll  */
-	TRUE,	/*  cuu1  */
-	TRUE,	/*  cvvis  */
-	TRUE,	/*  dch1  */
-	TRUE,	/*  dl1  */
-	TRUE,	/*  dsl  */
-	TRUE,	/*  hd  */
-	TRUE,	/*  smacs  */
-	TRUE,	/*  blink  */
-	TRUE,	/*  bold  */
-	TRUE,	/*  smcup  */
-	TRUE,	/*  smdc  */
-	TRUE,	/*  dim  */
-	TRUE,	/*  smir  */
-	FALSE,	/*  invis  */
-	FALSE,	/*  prot  */
-	TRUE,	/*  rev  */
-	TRUE,	/*  smso  */
-	TRUE,	/*  smul  */
-	TRUE,	/*  ech  */
-	TRUE,	/*  rmacs  */
-	TRUE,	/*  sgr0  */
-	TRUE,	/*  rmcup  */
-	TRUE,	/*  rmdc  */
-	TRUE,	/*  rmir  */
-	TRUE,	/*  rmso  */
-	TRUE,	/*  rmul  */
-	TRUE,	/*  flash  */
-	TRUE,	/*  ff  */
-	TRUE,	/*  fsl  */
-	TRUE,	/*  is1  */
-	TRUE,	/*  is2  */
-	TRUE,	/*  is3  */
-	TRUE,	/*  if  */
-	TRUE,	/*  ich1  */
-	TRUE,	/*  il1  */
-	TRUE,	/*  ip  */
-	TRUE,	/*  kbs  */
-	FALSE,	/*  ktbc  */
-	FALSE,	/*  kclr  */
-	FALSE,	/*  kctab  */
-	TRUE,	/*  kdch1  */
-	FALSE,	/*  kdl1  */
-	TRUE,	/*  kcud1  */
-	FALSE,	/*  krmir  */
-	FALSE,	/*  kel  */
-	FALSE,	/*  ked  */
-	TRUE,	/*  kf0  */
-	TRUE,	/*  kf1  */
-	FALSE,	/*  kf10  */
-	TRUE,	/*  kf2  */
-	TRUE,	/*  kf3  */
-	TRUE,	/*  kf4  */
-	TRUE,	/*  kf5  */
-	TRUE,	/*  kf6  */
-	TRUE,	/*  kf7  */
-	TRUE,	/*  kf8  */
-	TRUE,	/*  kf9  */
-	TRUE,	/*  khome  */
-	TRUE,	/*  kich1  */
-	FALSE,	/*  kil1  */
-	TRUE,	/*  kcub1  */
-	TRUE,	/*  kll  */
-	TRUE,	/*  knp  */
-	TRUE,	/*  kpp  */
-	TRUE,	/*  kcuf1  */
-	FALSE,	/*  kind  */
-	FALSE,	/*  kri  */
-	FALSE,	/*  khts  */
-	TRUE,	/*  kcuu1  */
-	TRUE,	/*  rmkx  */
-	TRUE,	/*  smkx  */
-	FALSE,	/*  lf0  */
-	FALSE,	/*  lf1  */
-	FALSE,	/*  lf10  */
-	FALSE,	/*  lf2  */
-	FALSE,	/*  lf3  */
-	FALSE,	/*  lf4  */
-	FALSE,	/*  lf5  */
-	FALSE,	/*  lf6  */
-	FALSE,	/*  lf7  */
-	FALSE,	/*  lf8  */
-	FALSE,	/*  lf9  */
-	TRUE,	/*  rmm  */
-	TRUE,	/*  smm  */
-	TRUE,	/*  nel  */
-	TRUE,	/*  pad  */
-	TRUE,	/*  dch  */
-	TRUE,	/*  dl  */
-	TRUE,	/*  cud  */
-	TRUE,	/*  ich  */
-	TRUE,	/*  indn  */
-	TRUE,	/*  il  */
-	TRUE,	/*  cub  */
-	TRUE,	/*  cuf  */
-	TRUE,	/*  rin  */
-	TRUE,	/*  cuu  */
-	FALSE,	/*  pfkey  */
-	FALSE,	/*  pfloc  */
-	FALSE,	/*  pfx  */
-	FALSE,	/*  mc0  */
-	FALSE,	/*  mc4  */
-	FALSE,	/*  mc5  */
-	TRUE,	/*  rep  */
-	FALSE,	/*  rs1  */
-	FALSE,	/*  rs2  */
-	FALSE,	/*  rs3  */
-	FALSE,	/*  rf  */
-	TRUE,	/*  rc  */
-	FALSE,	/*  vpa  */
-	TRUE,	/*  sc  */
-	TRUE,	/*  ind  */
-	TRUE,	/*  ri  */
-	TRUE,	/*  sgr  */
-	TRUE,	/*  hts  */
-	FALSE,	/*  wind  */
-	TRUE,	/*  ht  */
-	TRUE,	/*  tsl  */
-	TRUE,	/*  uc  */
-	TRUE,	/*  hu  */
-	FALSE,	/*  iprog  */
-	TRUE,	/*  ka1  */
-	TRUE,	/*  ka3  */
-	TRUE,	/*  kb2  */
-	TRUE,	/*  kc1  */
-	TRUE,	/*  kc3  */
-	FALSE,	/*  mc5p  */
-	FALSE,	/*  rmp  */
-	FALSE,	/*  acsc  */
-	FALSE,	/*  pln  */
-	FALSE,	/*  kcbt  */
-	FALSE,	/*  smxon  */
-	FALSE,	/*  rmxon  */
-	FALSE,	/*  smam  */
-	FALSE,	/*  rmam  */
-	FALSE,	/*  xonc  */
-	FALSE,	/*  xoffc  */
-	FALSE,	/*  enacs  */
-	FALSE,	/*  smln  */
-	FALSE,	/*  rmln  */
-	FALSE,	/*  kbeg  */
-	FALSE,	/*  kcan  */
-	FALSE,	/*  kclo  */
-	FALSE,	/*  kcmd  */
-	FALSE,	/*  kcpy  */
-	FALSE,	/*  kcrt  */
-	FALSE,	/*  kend  */
-	FALSE,	/*  kent  */
-	FALSE,	/*  kext  */
-	FALSE,	/*  kfnd  */
-	FALSE,	/*  khlp  */
-	FALSE,	/*  kmrk  */
-	FALSE,	/*  kmsg  */
-	FALSE,	/*  kmov  */
-	FALSE,	/*  knxt  */
-	FALSE,	/*  kopn  */
-	FALSE,	/*  kopt  */
-	FALSE,	/*  kprv  */
-	FALSE,	/*  kprt  */
-	FALSE,	/*  krdo  */
-	FALSE,	/*  kref  */
-	FALSE,	/*  krfr  */
-	FALSE,	/*  krpl  */
-	FALSE,	/*  krst  */
-	FALSE,	/*  kres  */
-	FALSE,	/*  ksav  */
-	FALSE,	/*  kspd  */
-	FALSE,	/*  kund  */
-	FALSE,	/*  kBEG  */
-	FALSE,	/*  kCAN  */
-	FALSE,	/*  kCMD  */
-	FALSE,	/*  kCPY  */
-	FALSE,	/*  kCRT  */
-	FALSE,	/*  kDC  */
-	FALSE,	/*  kDL  */
-	FALSE,	/*  kslt  */
-	FALSE,	/*  kEND  */
-	FALSE,	/*  kEOL  */
-	FALSE,	/*  kEXT  */
-	FALSE,	/*  kFND  */
-	FALSE,	/*  kHLP  */
-	FALSE,	/*  kHOM  */
-	FALSE,	/*  kIC  */
-	FALSE,	/*  kLFT  */
-	FALSE,	/*  kMSG  */
-	FALSE,	/*  kMOV  */
-	FALSE,	/*  kNXT  */
-	FALSE,	/*  kOPT  */
-	FALSE,	/*  kPRV  */
-	FALSE,	/*  kPRT  */
-	FALSE,	/*  kRDO  */
-	FALSE,	/*  kRPL  */
-	FALSE,	/*  kRIT  */
-	FALSE,	/*  kRES  */
-	FALSE,	/*  kSAV  */
-	FALSE,	/*  kSPD  */
-	FALSE,	/*  kUND  */
-	FALSE,	/*  rfi  */
-	FALSE,	/*  kf11  */
-	FALSE,	/*  kf12  */
-	FALSE,	/*  kf13  */
-	FALSE,	/*  kf14  */
-	FALSE,	/*  kf15  */
-	FALSE,	/*  kf16  */
-	FALSE,	/*  kf17  */
-	FALSE,	/*  kf18  */
-	FALSE,	/*  kf19  */
-	FALSE,	/*  kf20  */
-	FALSE,	/*  kf21  */
-	FALSE,	/*  kf22  */
-	FALSE,	/*  kf23  */
-	FALSE,	/*  kf24  */
-	FALSE,	/*  kf25  */
-	FALSE,	/*  kf26  */
-	FALSE,	/*  kf27  */
-	FALSE,	/*  kf28  */
-	FALSE,	/*  kf29  */
-	FALSE,	/*  kf30  */
-	FALSE,	/*  kf31  */
-	FALSE,	/*  kf32  */
-	FALSE,	/*  kf33  */
-	FALSE,	/*  kf34  */
-	FALSE,	/*  kf35  */
-	FALSE,	/*  kf36  */
-	FALSE,	/*  kf37  */
-	FALSE,	/*  kf38  */
-	FALSE,	/*  kf39  */
-	FALSE,	/*  kf40  */
-	FALSE,	/*  kf41  */
-	FALSE,	/*  kf42  */
-	FALSE,	/*  kf43  */
-	FALSE,	/*  kf44  */
-	FALSE,	/*  kf45  */
-	FALSE,	/*  kf46  */
-	FALSE,	/*  kf47  */
-	FALSE,	/*  kf48  */
-	FALSE,	/*  kf49  */
-	FALSE,	/*  kf50  */
-	FALSE,	/*  kf51  */
-	FALSE,	/*  kf52  */
-	FALSE,	/*  kf53  */
-	FALSE,	/*  kf54  */
-	FALSE,	/*  kf55  */
-	FALSE,	/*  kf56  */
-	FALSE,	/*  kf57  */
-	FALSE,	/*  kf58  */
-	FALSE,	/*  kf59  */
-	FALSE,	/*  kf60  */
-	FALSE,	/*  kf61  */
-	FALSE,	/*  kf62  */
-	FALSE,	/*  kf63  */
-	FALSE,	/*  el1  */
-	FALSE,	/*  mgc  */
-	FALSE,	/*  smgl  */
-	FALSE,	/*  smgr  */
-	FALSE,	/*  fln  */
-	FALSE,	/*  sclk  */
-	FALSE,	/*  dclk  */
-	FALSE,	/*  rmclk  */
-	FALSE,	/*  cwin  */
-	FALSE,	/*  wingo  */
-	FALSE,	/*  hup  */
-	FALSE,	/*  dial  */
-	FALSE,	/*  qdial  */
-	FALSE,	/*  tone  */
-	FALSE,	/*  pulse  */
-	FALSE,	/*  hook  */
-	FALSE,	/*  pause  */
-	FALSE,	/*  wait  */
-	FALSE,	/*  u0  */
-	FALSE,	/*  u1  */
-	FALSE,	/*  u2  */
-	FALSE,	/*  u3  */
-	FALSE,	/*  u4  */
-	FALSE,	/*  u5  */
-	FALSE,	/*  u6  */
-	FALSE,	/*  u7  */
-	FALSE,	/*  u8  */
-	FALSE,	/*  u9  */
-	FALSE,	/*  op  */
-	FALSE,	/*  oc  */
-	FALSE,	/*  initc  */
-	FALSE,	/*  initp  */
-	FALSE,	/*  scp  */
-	FALSE,	/*  setf  */
-	FALSE,	/*  setb  */
-	FALSE,	/*  cpi  */
-	FALSE,	/*  lpi  */
-	FALSE,	/*  chr  */
-	FALSE,	/*  cvr  */
-	FALSE,	/*  defc  */
-	FALSE,	/*  swidm  */
-	FALSE,	/*  sdrfq  */
-	FALSE,	/*  sitm  */
-	FALSE,	/*  slm  */
-	FALSE,	/*  smicm  */
-	FALSE,	/*  snlq  */
-	FALSE,	/*  snrmq  */
-	FALSE,	/*  sshm  */
-	FALSE,	/*  ssubm  */
-	FALSE,	/*  ssupm  */
-	FALSE,	/*  sum  */
-	FALSE,	/*  rwidm  */
-	FALSE,	/*  ritm  */
-	FALSE,	/*  rlm  */
-	FALSE,	/*  rmicm  */
-	FALSE,	/*  rshm  */
-	FALSE,	/*  rsubm  */
-	FALSE,	/*  rsupm  */
-	FALSE,	/*  rum  */
-	FALSE,	/*  mhpa  */
-	FALSE,	/*  mcud1  */
-	FALSE,	/*  mcub1  */
-	FALSE,	/*  mcuf1  */
-	FALSE,	/*  mvpa  */
-	FALSE,	/*  mcuu1  */
-	FALSE,	/*  porder  */
-	FALSE,	/*  mcud  */
-	FALSE,	/*  mcub  */
-	FALSE,	/*  mcuf  */
-	FALSE,	/*  mcuu  */
-	FALSE,	/*  scs  */
-	FALSE,	/*  smgb  */
-	FALSE,	/*  smgbp  */
-	FALSE,	/*  smglp  */
-	FALSE,	/*  smgrp  */
-	FALSE,	/*  smgt  */
-	FALSE,	/*  smgtp  */
-	FALSE,	/*  sbim  */
-	FALSE,	/*  scsd  */
-	FALSE,	/*  rbim  */
-	FALSE,	/*  rcsd  */
-	FALSE,	/*  subcs  */
-	FALSE,	/*  supcs  */
-	FALSE,	/*  docr  */
-	FALSE,	/*  zerom  */
-	FALSE,	/*  csnm  */
-	FALSE,	/*  kmous  */
-	FALSE,	/*  minfo  */
-	FALSE,	/*  reqmp  */
-	FALSE,	/*  getm  */
-	FALSE,	/*  setaf  */
-	FALSE,	/*  setab  */
-	FALSE,	/*  pfxl  */
-	FALSE,	/*  devt  */
-	FALSE,	/*  csin  */
-	FALSE,	/*  s0ds  */
-	FALSE,	/*  s1ds  */
-	FALSE,	/*  s2ds  */
-	FALSE,	/*  s3ds  */
-	FALSE,	/*  smglr  */
-	FALSE,	/*  smgtb  */
-	FALSE,	/*  birep  */
-	FALSE,	/*  binel  */
-	FALSE,	/*  bicr  */
-	FALSE,	/*  colornm  */
-	FALSE,	/*  defbi  */
-	FALSE,	/*  endbi  */
-	FALSE,	/*  setcolor  */
-	FALSE,	/*  slines  */
-	FALSE,	/*  dispc  */
-	FALSE,	/*  smpch  */
-	FALSE,	/*  rmpch  */
-	FALSE,	/*  smsc  */
-	FALSE,	/*  rmsc  */
-	FALSE,	/*  pctrm  */
-	FALSE,	/*  scesc  */
-	FALSE,	/*  scesa  */
-	FALSE,	/*  ehhlm  */
-	FALSE,	/*  elhlm  */
-	FALSE,	/*  elohlm  */
-	FALSE,	/*  erhlm  */
-	FALSE,	/*  ethlm  */
-	FALSE,	/*  evhlm  */
-	FALSE,	/*  sgr1  */
-	FALSE,	/*  slength  */
-	TRUE,	/*  OTi2  */
-	TRUE,	/*  OTrs  */
-	TRUE,	/*  OTnl  */
-	TRUE,	/*  OTbc  */
-	FALSE,	/*  OTko  */
-	TRUE,	/*  OTma  */
-	FALSE,	/*  OTG2  */
-	FALSE,	/*  OTG3  */
-	FALSE,	/*  OTG1  */
-	FALSE,	/*  OTG4  */
-	FALSE,	/*  OTGR  */
-	FALSE,	/*  OTGL  */
-	FALSE,	/*  OTGU  */
-	FALSE,	/*  OTGD  */
-	FALSE,	/*  OTGH  */
-	FALSE,	/*  OTGV  */
-	FALSE,	/*  OTGC  */
-	FALSE,	/*  meml  */
-	FALSE,	/*  memu  */
-	FALSE,	/*  pln  */
-	FALSE,	/*  smln  */
-	FALSE,	/*  rmln  */
-	FALSE,	/*  kf11  */
-	FALSE,	/*  kf12  */
-	FALSE,	/*  kf13  */
-	FALSE,	/*  kf14  */
-	FALSE,	/*  kf15  */
-	FALSE,	/*  kf16  */
-	FALSE,	/*  kf17  */
-	FALSE,	/*  kf18  */
-	FALSE,	/*  kf19  */
-	FALSE,	/*  kf20  */
-	FALSE,	/*  kf21  */
-	FALSE,	/*  kf22  */
-	FALSE,	/*  kf23  */
-	FALSE,	/*  kf24  */
-	FALSE,	/*  kf25  */
-	FALSE,	/*  kf26  */
-	FALSE,	/*  kf27  */
-	FALSE,	/*  kf28  */
-	FALSE,	/*  kf29  */
-	FALSE,	/*  kf30  */
-	FALSE,	/*  kf31  */
-	FALSE,	/*  kf32  */
-	FALSE,	/*  kf33  */
-	FALSE,	/*  kf34  */
-	FALSE,	/*  kf35  */
-	FALSE,	/*  kf36  */
-	FALSE,	/*  kf37  */
-	FALSE,	/*  kf38  */
-	FALSE,	/*  kf39  */
-	FALSE,	/*  kf40  */
-	FALSE,	/*  kf41  */
-	FALSE,	/*  kf42  */
-	FALSE,	/*  kf43  */
-	FALSE,	/*  kf44  */
-	FALSE,	/*  kf45  */
-	FALSE,	/*  kf46  */
-	FALSE,	/*  kf47  */
-	FALSE,	/*  kf48  */
-	FALSE,	/*  kf49  */
-	FALSE,	/*  kf50  */
-	FALSE,	/*  kf51  */
-	FALSE,	/*  kf52  */
-	FALSE,	/*  kf53  */
-	FALSE,	/*  kf54  */
-	FALSE,	/*  kf55  */
-	FALSE,	/*  kf56  */
-	FALSE,	/*  kf57  */
-	FALSE,	/*  kf58  */
-	FALSE,	/*  kf59  */
-	FALSE,	/*  kf60  */
-	FALSE,	/*  kf61  */
-	FALSE,	/*  kf62  */
-	FALSE,	/*  kf63  */
-	FALSE,	/*  box1  */
-	FALSE,	/*  box2  */
-	FALSE,	/*  batt1  */
-	FALSE,	/*  batt2  */
-	FALSE,	/*  colb0  */
-	FALSE,	/*  colb1  */
-	FALSE,	/*  colb2  */
-	FALSE,	/*  colb3  */
-	FALSE,	/*  colb4  */
-	FALSE,	/*  colb5  */
-	FALSE,	/*  colb6  */
-	FALSE,	/*  colb7  */
-	FALSE,	/*  colf0  */
-	FALSE,	/*  colf1  */
-	FALSE,	/*  colf2  */
-	FALSE,	/*  colf3  */
-	FALSE,	/*  colf4  */
-	FALSE,	/*  colf5  */
-	FALSE,	/*  colf6  */
-	FALSE,	/*  colf7  */
-	FALSE,	/*  font0  */
-	FALSE,	/*  font1  */
-	FALSE,	/*  font2  */
-	FALSE,	/*  font3  */
-	FALSE,	/*  font4  */
-	FALSE,	/*  font5  */
-	FALSE,	/*  font6  */
-	FALSE,	/*  font7  */
-	FALSE,	/*  kbtab  */
-	FALSE,	/*  kdo  */
-	FALSE,	/*  kcmd  */
-	FALSE,	/*  kcpn  */
-	FALSE,	/*  kend  */
-	FALSE,	/*  khlp  */
-	FALSE,	/*  knl  */
-	FALSE,	/*  knpn  */
-	FALSE,	/*  kppn  */
-	FALSE,	/*  kppn  */
-	FALSE,	/*  kquit  */
-	FALSE,	/*  ksel  */
-	FALSE,	/*  kscl  */
-	FALSE,	/*  kscr  */
-	FALSE,	/*  ktab  */
-	FALSE,	/*  kmpf1  */
-	FALSE,	/*  kmpt1  */
-	FALSE,	/*  kmpf2  */
-	FALSE,	/*  kmpt2  */
-	FALSE,	/*  kmpf3  */
-	FALSE,	/*  kmpt3  */
-	FALSE,	/*  kmpf4  */
-	FALSE,	/*  kmpt4  */
-	FALSE,	/*  kmpf5  */
-	FALSE,	/*  kmpt5  */
-	FALSE,	/*  apstr  */
-	FALSE,	/*  kmpf6  */
-	FALSE,	/*  kmpt6  */
-	FALSE,	/*  kmpf7  */
-	FALSE,	/*  kmpt7  */
-	FALSE,	/*  kmpf8  */
-	FALSE,	/*  kmpt8  */
-	FALSE,	/*  kmpf9  */
-	FALSE,	/*  kmpt9  */
-	FALSE,	/*  ksf1  */
-	FALSE,	/*  ksf2  */
-	FALSE,	/*  ksf3  */
-	FALSE,	/*  ksf4  */
-	FALSE,	/*  ksf5  */
-	FALSE,	/*  ksf6  */
-	FALSE,	/*  ksf7  */
-	FALSE,	/*  ksf8  */
-	FALSE,	/*  ksf9  */
-	FALSE,	/*  ksf10  */
-	FALSE,	/*  kf11  */
-	FALSE,	/*  kf12  */
-	FALSE,	/*  kact  */
-	FALSE,	/*  topl  */
-	FALSE,	/*  btml  */
-	FALSE,	/*  rvert  */
-	FALSE,	/*  lvert  */
-#define OK_str_from_termcap 399
-};
-
diff --git a/progs/tic b/progs/tic
deleted file mode 100755
index 81ea0d2..0000000
--- a/progs/tic
+++ /dev/null
Binary files differ
diff --git a/progs/tic.c b/progs/tic.c
index 10cc4d2..fc77b34 100644
--- a/progs/tic.c
+++ b/progs/tic.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2014,2015 Free Software Foundation, Inc.              *
+ * Copyright 2018-2023,2024 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            *
@@ -48,7 +49,7 @@
 #include <parametrized.h>
 #include <transform.h>
 
-MODULE_ID("$Id: tic.c,v 1.211 2015/07/04 21:12:41 tom Exp $")
+MODULE_ID("$Id: tic.c,v 1.325 2024/03/02 19:33:22 tom Exp $")
 
 #define STDIN_NAME "<stdin>"
 
@@ -59,11 +60,16 @@
 static bool capdump = FALSE;	/* running as infotocap? */
 static bool infodump = FALSE;	/* running as captoinfo? */
 static bool showsummary = FALSE;
+static unsigned debug_level;
 static char **namelst = 0;
 static const char *to_remove;
 
-static void (*save_check_termtype) (TERMTYPE *, bool);
-static void check_termtype(TERMTYPE *tt, bool);
+#if NCURSES_XNAMES
+static bool using_extensions = FALSE;
+#endif
+
+static void (*save_check_termtype) (TERMTYPE2 *, bool);
+static void check_termtype(TERMTYPE2 *tt, bool);
 
 static const char usage_string[] = "\
 [-e names] \
@@ -110,14 +116,15 @@
 static void
 cleanup(void)
 {
-    int rc;
-
 #if NO_LEAKS
     free_namelist(namelst);
+    _nc_leaks_dump_entry();
 #endif
     if (tmp_fp != 0)
 	fclose(tmp_fp);
     if (to_remove != 0) {
+	int rc;
+
 #if HAVE_REMOVE
 	rc = remove(to_remove);
 #else
@@ -142,6 +149,7 @@
     static const char options_string[] =
     {
 	DATA("Options:")
+	DATA("  -0         format translation output all capabilities on one line")
 	DATA("  -1         format translation output one capability per line")
 #if NCURSES_XNAMES
 	DATA("  -a         retain commented-out capabilities (sets -x also)")
@@ -158,6 +166,8 @@
 	DATA("  -L         translate entries to full terminfo source form")
 	DATA("  -N         disable smart defaults for source translation")
 	DATA("  -o<dir>    set output directory for compiled entry writes")
+	DATA("  -Q[n]      dump compiled description")
+	DATA("  -q    brief listing, removes headers")
 	DATA("  -R<name>   restrict translation to given terminfo/termcap version")
 	DATA("  -r         force resolution of all use entries in source translation")
 	DATA("  -s         print summary statistics")
@@ -167,6 +177,7 @@
 #endif
 	DATA("  -U         suppress post-processing of entries")
 	DATA("  -V         print version")
+	DATA("  -W         wrap long strings according to -w[n] option")
 	DATA("  -v[n]      set verbosity level")
 	DATA("  -w[n]      set format width for translation output")
 #if NCURSES_XNAMES
@@ -208,7 +219,8 @@
 	    while ((ch = *t++) != 0) {
 		*d++ = (char) ch;
 		if (ch == '\\') {
-		    *d++ = *t++;
+		    if ((*d++ = *t++) == '\0')
+			break;
 		} else if ((ch == '%')
 			   && (*t == L_BRACE)) {
 		    char *v = 0;
@@ -292,15 +304,17 @@
 /* emit a comment char, translating terminfo names to termcap names */
 {
     static bool in_name = FALSE;
-    static size_t have, used;
-    static char *namebuf, *suffix;
+    static size_t used;
 
     if (in_name) {
+	static size_t have;
+	static char *namebuf, *suffix;
+
 	if (used + 1 >= have) {
 	    have += 132;
-	    if ((namebuf = typeRealloc(char, have, namebuf)) == 0)
+	    if ((namebuf = typeRealloc(char, have, namebuf)) == NULL)
 		  failed("put_translate namebuf");
-	    if ((suffix = typeRealloc(char, have, suffix)) == 0)
+	    if ((suffix = typeRealloc(char, have, suffix)) == NULL)
 		  failed("put_translate suffix");
 	}
 	if (c == '\n' || c == '@') {
@@ -359,12 +373,10 @@
 	src++;
 
     if (*src != '\0') {
-	size_t len;
-
 	if ((dst = strdup(src)) == NULL) {
 	    failed("strdup");
 	} else {
-	    len = strlen(dst);
+	    size_t len = strlen(dst);
 	    while (--len != 0 && isspace(UChar(dst[len])))
 		dst[len] = '\0';
 	}
@@ -388,7 +400,7 @@
     }
 #else
     if (tmpnam(filename) != 0)
-	result = fopen(filename, "w");
+	result = safe_fopen(filename, "w");
 #endif
     return result;
 }
@@ -398,15 +410,15 @@
 {
     char my_altfile[PATH_MAX];
     FILE *result = 0;
-    FILE *target = 0;
+    FILE *target;
     int ch;
 
-    if (alt_file == 0)
+    if (alt_file == NULL)
 	alt_file = my_altfile;
 
-    if (source == 0) {
+    if (source == NULL) {
 	failed("copy_input (source)");
-    } else if ((target = open_tempfile(alt_file)) == 0) {
+    } else if ((target = open_tempfile(alt_file)) == NULL) {
 	failed("copy_input (target)");
     } else {
 	clearerr(source);
@@ -430,7 +442,7 @@
 	 * the one that we were writing on before starting to read from the
 	 * second stream.
 	 */
-	result = fopen(alt_file, "r+");
+	result = safe_fopen(alt_file, "r+");
 	fclose(target);
 	to_remove = strdup(alt_file);
     }
@@ -446,18 +458,21 @@
 
     if (!strcmp(filename, "-")) {
 	fp = copy_input(stdin, STDIN_NAME, alt_file);
-    } else if (stat(filename, &sb) < 0) {
-	fprintf(stderr, "%s: %s %s\n", _nc_progname, filename, strerror(errno));
+    } else if (stat(filename, &sb) == -1) {
+	fprintf(stderr, "%s: cannot open '%s': %s\n", _nc_progname,
+		filename, strerror(errno));
 	ExitProgram(EXIT_FAILURE);
     } else if ((mode = (sb.st_mode & S_IFMT)) == S_IFDIR
 	       || (mode != S_IFREG && mode != S_IFCHR && mode != S_IFIFO)) {
-	fprintf(stderr, "%s: %s is not a file\n", _nc_progname, filename);
+	fprintf(stderr, "%s: cannot open '%s'; it is not a file\n",
+		_nc_progname, filename);
 	ExitProgram(EXIT_FAILURE);
     } else {
-	fp = fopen(filename, "r");
+	fp = safe_fopen(filename, "r");
 
-	if (fp == 0) {
-	    fprintf(stderr, "%s: Can't open %s\n", _nc_progname, filename);
+	if (fp == NULL) {
+	    fprintf(stderr, "%s: cannot open '%s': %s\n", _nc_progname,
+		    filename, strerror(errno));
 	    ExitProgram(EXIT_FAILURE);
 	}
 	if (mode != S_IFREG) {
@@ -465,7 +480,8 @@
 		FILE *fp2 = copy_input(fp, filename, alt_file);
 		fp = fp2;
 	    } else {
-		fprintf(stderr, "%s: %s is not a file\n", _nc_progname, filename);
+		fprintf(stderr, "%s: cannot open '%s'; it is not a"
+			" file\n", _nc_progname, filename);
 		ExitProgram(EXIT_FAILURE);
 	    }
 	}
@@ -483,7 +499,7 @@
     unsigned pass, n, nn;
     char buffer[BUFSIZ];
 
-    if (src == 0) {
+    if (src == NULL) {
 	/* EMPTY */ ;
     } else if (strchr(src, '/') != 0) {		/* a filename */
 	FILE *fp = open_input(src, (char *) 0);
@@ -500,7 +516,7 @@
 		}
 	    }
 	    if (pass == 1) {
-		if ((dst = typeCalloc(char *, nn + 1)) == 0)
+		if ((dst = typeCalloc(char *, nn + 1)) == NULL)
 		      failed("make_namelist");
 		rewind(fp);
 	    }
@@ -524,7 +540,7 @@
 		    break;
 	    }
 	    if (pass == 1) {
-		if ((dst = typeCalloc(char *, nn + 1)) == 0)
+		if ((dst = typeCalloc(char *, nn + 1)) == NULL)
 		      failed("make_namelist");
 	    }
 	}
@@ -542,9 +558,10 @@
 /* does entry in needle list match |-separated field in haystack? */
 {
     bool code = FALSE;
-    size_t n;
 
     if (needle != 0) {
+	size_t n;
+
 	for (n = 0; needle[n] != 0; n++) {
 	    if (_nc_name_match(haystack, needle[n], "|")) {
 		code = TRUE;
@@ -565,7 +582,7 @@
     size_t need = strlen(nominal) + sizeof(suffix);
     char *result = malloc(need);
 
-    if (result == 0)
+    if (result == NULL)
 	failed("valid_db_path");
     _nc_STRCPY(result, nominal, need);
     if (strcmp(result + need - sizeof(suffix), suffix)) {
@@ -630,8 +647,8 @@
     char *result;
     const char *tried = 0;
 
-    if (outdir == 0) {
-	outdir = _nc_tic_dir(0);
+    if (outdir == NULL) {
+	outdir = _nc_tic_dir(NULL);
     }
     if ((result = valid_db_path(outdir)) != 0) {
 	printf("%s\n", result);
@@ -659,15 +676,17 @@
     }
 }
 
-#define VtoTrace(opt) (unsigned) ((opt > 0) ? opt : (opt == 0))
+static void
+add_digit(int *target, int source)
+{
+    *target = (*target * 10) + (source - '0');
+}
 
 int
 main(int argc, char *argv[])
 {
     char my_tmpname[PATH_MAX];
-    char my_altfile[PATH_MAX];
     int v_opt = -1;
-    unsigned debug_level;
     int smart_defaults = TRUE;
     char *termcap;
     ENTRY *qp;
@@ -685,10 +704,13 @@
     bool forceresolve = FALSE;	/* force resolution */
     bool limited = TRUE;
     char *tversion = (char *) NULL;
-    const char *source_file = "terminfo";
+    const char *source_file;
     char *outdir = (char *) NULL;
     bool check_only = FALSE;
     bool suppress_untranslatable = FALSE;
+    int quickdump = 0;
+    bool quiet = FALSE;
+    bool wrap_strings = FALSE;
 
     log_fp = stderr;
 
@@ -704,7 +726,8 @@
 	sortmode = S_TERMCAP;
     }
 #if NCURSES_XNAMES
-    use_extended_names(FALSE);
+    /* set this directly to avoid interaction with -v and -D options */
+    _nc_user_definable = FALSE;
 #endif
     _nc_strict_bsd = 0;
 
@@ -714,14 +737,17 @@
      * be optional.
      */
     while ((this_opt = getopt(argc, argv,
-			      "0123456789CDIKLNR:TUVace:fGgo:rstvwx")) != -1) {
+			      "0123456789CDIKLNQR:TUVWace:fGgo:qrstvwx")) != -1) {
 	if (isdigit(this_opt)) {
 	    switch (last_opt) {
+	    case 'Q':
+		add_digit(&quickdump, this_opt);
+		break;
 	    case 'v':
-		v_opt = (v_opt * 10) + (this_opt - '0');
+		add_digit(&v_opt, this_opt);
 		break;
 	    case 'w':
-		width = (width * 10) + (this_opt - '0');
+		add_digit(&width, this_opt);
 		break;
 	    default:
 		switch (this_opt) {
@@ -754,7 +780,7 @@
 	    break;
 	case 'D':
 	    debug_level = VtoTrace(v_opt);
-	    set_trace_level(debug_level);
+	    use_verbosity(debug_level);
 	    show_databases(outdir);
 	    ExitProgram(EXIT_SUCCESS);
 	    break;
@@ -772,6 +798,9 @@
 	    smart_defaults = FALSE;
 	    literal = TRUE;
 	    break;
+	case 'Q':
+	    quickdump = 0;
+	    break;
 	case 'R':
 	    tversion = optarg;
 	    break;
@@ -784,6 +813,9 @@
 	case 'V':
 	    puts(curses_version());
 	    ExitProgram(EXIT_SUCCESS);
+	case 'W':
+	    wrap_strings = TRUE;
+	    break;
 	case 'c':
 	    check_only = TRUE;
 	    break;
@@ -802,6 +834,9 @@
 	case 'o':
 	    outdir = optarg;
 	    break;
+	case 'q':
+	    quiet = TRUE;
+	    break;
 	case 'r':
 	    forceresolve = TRUE;
 	    break;
@@ -823,7 +858,7 @@
 	    _nc_disable_period = TRUE;
 	    /* FALLTHRU */
 	case 'x':
-	    use_extended_names(TRUE);
+	    using_extensions = TRUE;
 	    break;
 #endif
 	default:
@@ -832,8 +867,23 @@
 	last_opt = this_opt;
     }
 
+    /*
+     * If the -v option is set, it may override the $NCURSES_TRACE environment
+     * variable, e.g., for -v3 and up.
+     */
     debug_level = VtoTrace(v_opt);
-    set_trace_level(debug_level);
+    use_verbosity(debug_level);
+
+    /*
+     * Do this after setting debug_level, since the function calls START_TRACE,
+     * which uses the $NCURSES_TRACE environment variable if _nc_tracing bits
+     * for tracing are zero.
+     */
+#if NCURSES_XNAMES
+    if (using_extensions) {
+	use_extended_names(TRUE);
+    }
+#endif
 
     if (_nc_tracing) {
 	save_check_termtype = _nc_check_termtype2;
@@ -846,7 +896,7 @@
      * One problem with immedhook is it means we can't do -e.  Problem
      * is that we can't guarantee that for each terminal listed, all the
      * terminals it depends on will have been kept in core for reference
-     * resolution -- in fact it's certain the primitive types at the end
+     * resolution -- in fact it is certain the primitive types at the end
      * of reference chains *won't* be in core unless they were explicitly
      * in the select list themselves.
      */
@@ -900,7 +950,8 @@
 	}
     }
 
-    if (tmp_fp == 0) {
+    if (tmp_fp == NULL) {
+	char my_altfile[PATH_MAX];
 	tmp_fp = open_input(source_file, my_altfile);
 	if (!strcmp(source_file, "-")) {
 	    source_file = STDIN_NAME;
@@ -909,15 +960,18 @@
 
     if (infodump || check_only) {
 	dump_init(tversion,
-		  smart_defaults
-		  ? outform
-		  : F_LITERAL,
-		  sortmode, width, height, debug_level, formatted ||
-		  check_only, check_only);
+		  (smart_defaults
+		   ? outform
+		   : F_LITERAL),
+		  sortmode,
+		  wrap_strings, width, height,
+		  debug_level, formatted || check_only, check_only, quickdump);
     } else if (capdump) {
 	dump_init(tversion,
 		  outform,
-		  sortmode, width, height, debug_level, FALSE, FALSE);
+		  sortmode,
+		  wrap_strings, width, height,
+		  debug_level, FALSE, FALSE, FALSE);
     }
 
     /* parse entries out of the source file */
@@ -947,7 +1001,8 @@
 
 		if (len > (infodump ? MAX_TERMINFO_LENGTH : MAX_TERMCAP_LENGTH))
 		    (void) fprintf(stderr,
-				   "warning: resolved %s entry is %d bytes long\n",
+				   "%s: resolved %s entry is %d bytes long\n",
+				   _nc_progname,
 				   _nc_first_name(qp->tterm.term_names),
 				   len);
 	    }
@@ -988,12 +1043,18 @@
 		    /* this is in case infotocap() generates warnings */
 		    _nc_set_type(_nc_first_name(qp->tterm.term_names));
 
-		    (void) fseek(tmp_fp, qp->cstart, SEEK_SET);
-		    while (j-- > 0) {
-			if (infodump)
-			    (void) putchar(fgetc(tmp_fp));
-			else
-			    put_translate(fgetc(tmp_fp));
+		    if (!quiet) {
+			(void) fseek(tmp_fp, qp->cstart, SEEK_SET);
+			while (j-- > 0) {
+			    int ch = fgetc(tmp_fp);
+			    if (ch == EOF || ferror(tmp_fp)) {
+				break;
+			    } else if (infodump) {
+				(void) putchar(ch);
+			    } else {
+				put_translate(ch);
+			    }
+			}
 		    }
 
 		    repair_acsc(&qp->tterm);
@@ -1006,7 +1067,7 @@
 			printf("# length=%d\n", len);
 		}
 	    }
-	    if (!namelst && _nc_tail) {
+	    if (!namelst && _nc_tail && !quiet) {
 		int c, oldc = '\0';
 		bool in_comment = FALSE;
 		bool trailing_comment = FALSE;
@@ -1039,7 +1100,7 @@
 	if (total != 0)
 	    fprintf(log_fp, "%d entries written to %s\n",
 		    total,
-		    _nc_tic_dir((char *) 0));
+		    _nc_tic_dir(NULL));
 	else
 	    fprintf(log_fp, "No entries written\n");
     }
@@ -1058,8 +1119,52 @@
  * Check if the alternate character-set capabilities are consistent.
  */
 static void
-check_acs(TERMTYPE *tp)
+check_acs(TERMTYPE2 *tp)
 {
+    int vt100_smacs = 0;
+    int vt100_rmacs = 0;
+    int vt100_enacs = 0;
+
+    /*
+     * ena_acs is not always necessary, but if it is present, the enter/exit
+     * capabilities should be.
+     */
+    ANDMISSING(ena_acs, enter_alt_charset_mode);
+    ANDMISSING(ena_acs, exit_alt_charset_mode);
+    PAIRED(exit_alt_charset_mode, exit_alt_charset_mode);
+
+    /*
+     * vt100-like is frequently used, but perhaps ena_acs is missing, etc.
+     */
+    if (VALID_STRING(enter_alt_charset_mode)) {
+	vt100_smacs = (!strcmp("\033(0", enter_alt_charset_mode)
+		       ? 2
+		       : (!strcmp("\016", enter_alt_charset_mode)
+			  ? 1
+			  : 0));
+    }
+    if (VALID_STRING(exit_alt_charset_mode)) {
+	vt100_rmacs = (!strcmp("\033(B", exit_alt_charset_mode)
+		       ? 2
+		       : (!strcmp("\017", exit_alt_charset_mode)
+			  ? 1
+			  : 0));
+    }
+    if (VALID_STRING(ena_acs)) {
+	vt100_enacs = (!strcmp("\033(B\033)0", ena_acs)
+		       ? 2
+		       : 0);
+    }
+    if (vt100_rmacs && vt100_smacs && (vt100_rmacs != vt100_smacs)) {
+	_nc_warning("rmacs/smacs are inconsistent");
+    }
+    if ((vt100_rmacs == 2) && (vt100_smacs == 2) && vt100_enacs) {
+	_nc_warning("rmacs/smacs make enacs redundant");
+    }
+    if ((vt100_rmacs == 1) && (vt100_smacs == 1) && !vt100_enacs) {
+	_nc_warning("VT100-style rmacs/smacs require enacs");
+    }
+
     if (VALID_STRING(acs_chars)) {
 	const char *boxes = "lmkjtuvwqxn";
 	char mapped[256];
@@ -1068,6 +1173,7 @@
 	char *q;
 
 	memset(mapped, 0, sizeof(mapped));
+	memset(missing, 0, sizeof(missing));
 	for (p = acs_chars; *p != '\0'; p += 2) {
 	    if (p[1] == '\0') {
 		_nc_warning("acsc has odd number of characters");
@@ -1094,14 +1200,45 @@
     }
 }
 
+static char *
+safe_strdup(const char *value)
+{
+    if (value == NULL)
+	value = "";
+    return strdup(value);
+}
+
+static bool
+same_color(NCURSES_CONST char *oldcap, NCURSES_CONST char *newcap, int limit)
+{
+    bool result = FALSE;
+    if (limit > 16)
+	limit = 16;
+    if (limit >= 8) {
+	int n;
+	int same;
+	for (n = same = 0; n < limit; ++n) {
+	    char *oldvalue = safe_strdup(TIPARM_1(oldcap, n));
+	    char *newvalue = safe_strdup(TIPARM_1(newcap, n));
+	    same += !strcmp(oldvalue, newvalue);
+	    free(oldvalue);
+	    free(newvalue);
+	}
+	result = (same == limit);
+    }
+    return result;
+}
+
 /*
  * Check if the color capabilities are consistent
  */
 static void
-check_colors(TERMTYPE *tp)
+check_colors(TERMTYPE2 *tp)
 {
+    char *value;
+
     if ((max_colors > 0) != (max_pairs > 0)
-	|| ((max_colors > max_pairs) && (initialize_pair == 0)))
+	|| ((max_colors > max_pairs) && !VALID_STRING(initialize_pair)))
 	_nc_warning("inconsistent values for max_colors (%d) and max_pairs (%d)",
 		    max_colors, max_pairs);
 
@@ -1110,21 +1247,29 @@
     PAIRED(set_color_pair, initialize_pair);
 
     if (VALID_STRING(set_foreground)
-	&& VALID_STRING(set_a_foreground)
-	&& !_nc_capcmp(set_foreground, set_a_foreground))
-	_nc_warning("expected setf/setaf to be different");
+	&& VALID_STRING(set_a_foreground)) {
+	if (!_nc_capcmp(set_foreground, set_a_foreground)) {
+	    _nc_warning("expected setf/setaf to be different");
+	} else if (same_color(set_foreground, set_a_foreground, max_colors)) {
+	    _nc_warning("setf/setaf are equivalent");
+	}
+    }
 
     if (VALID_STRING(set_background)
-	&& VALID_STRING(set_a_background)
-	&& !_nc_capcmp(set_background, set_a_background))
-	_nc_warning("expected setb/setab to be different");
+	&& VALID_STRING(set_a_background)) {
+	if (!_nc_capcmp(set_background, set_a_background)) {
+	    _nc_warning("expected setb/setab to be different");
+	} else if (same_color(set_background, set_a_background, max_colors)) {
+	    _nc_warning("setb/setab are equivalent");
+	}
+    }
 
     /* see: has_colors() */
     if (VALID_NUMERIC(max_colors) && VALID_NUMERIC(max_pairs)
-	&& (((set_foreground != NULL)
-	     && (set_background != NULL))
-	    || ((set_a_foreground != NULL)
-		&& (set_a_background != NULL))
+	&& ((VALID_STRING(set_foreground)
+	     && VALID_STRING(set_background))
+	    || (VALID_STRING(set_a_foreground)
+		&& VALID_STRING(set_a_background))
 	    || set_color_pair)) {
 	if (!VALID_STRING(orig_pair) && !VALID_STRING(orig_colors))
 	    _nc_warning("expected either op/oc string for resetting colors");
@@ -1140,6 +1285,28 @@
 	    _nc_warning("expected ccc because initc is given");
 	}
     }
+    value = tigetstr("RGB");
+    if (VALID_STRING(value)) {
+	int r, g, b;
+	char bad;
+	int code = sscanf(value, "%d/%d/%d%c", &r, &g, &b, &bad);
+	if (code != 3 || r <= 0 || g <= 0 || b <= 0) {
+	    _nc_warning("unexpected value for RGB capability: %s", value);
+	}
+    }
+}
+
+static int
+csi_length(const char *value)
+{
+    int result = 0;
+
+    if (value[0] == '\033' && value[1] == '[') {
+	result = 2;
+    } else if (UChar(value[0]) == 0x9a) {
+	result = 1;
+    }
+    return result;
 }
 
 static char
@@ -1160,13 +1327,12 @@
 static long
 keypad_index(const char *string)
 {
-    char *test;
-    const char *list = "PQRSwxymtuvlqrsPpn";	/* app-keypad except "Enter" */
     int ch;
     long result = -1;
 
     if ((ch = keypad_final(string)) != '\0') {
-	test = (strchr) (list, ch);
+	const char *list = "PQRSwxymtuvlqrsPpn";	/* app-keypad except "Enter" */
+	char *test = (strchr) (list, ch);
 	if (test != 0)
 	    result = (long) (test - list);
     }
@@ -1183,35 +1349,24 @@
 check_ansi_cursor(char *list[4])
 {
     int j, k;
-    int want;
-    size_t prefix = 0;
-    size_t suffix;
     bool skip[4];
     bool repeated = FALSE;
 
     for (j = 0; j < 4; ++j) {
 	skip[j] = FALSE;
 	for (k = 0; k < j; ++k) {
-	    if (j != k
-		&& !strcmp(list[j], list[k])) {
+	    if (!strcmp(list[j], list[k])) {
 		char *value = _nc_tic_expand(list[k], TRUE, 0);
-		_nc_warning("repeated cursor control %s\n", value);
+		_nc_warning("repeated cursor control %s", value);
 		repeated = TRUE;
 	    }
 	}
     }
     if (!repeated) {
 	char *up = list[1];
+	size_t prefix = (size_t) csi_length(up);
+	size_t suffix;
 
-	if (UChar(up[0]) == '\033') {
-	    if (up[1] == '[') {
-		prefix = 2;
-	    } else {
-		prefix = 1;
-	    }
-	} else if (UChar(up[0]) == UChar('\233')) {
-	    prefix = 1;
-	}
 	if (prefix) {
 	    suffix = prefix;
 	    while (up[suffix] && isdigit(UChar(up[suffix])))
@@ -1225,23 +1380,25 @@
 		skip[2] = TRUE;
 
 	    for (j = 0; j < 4; ++j) {
+		int want;
+
 		if (skip[j] || strlen(list[j]) == 1)
 		    continue;
 		if (memcmp(list[j], up, prefix)) {
 		    char *value = _nc_tic_expand(list[j], TRUE, 0);
-		    _nc_warning("inconsistent prefix for %s\n", value);
+		    _nc_warning("inconsistent prefix for %s", value);
 		    continue;
 		}
 		if (strlen(list[j]) < suffix) {
 		    char *value = _nc_tic_expand(list[j], TRUE, 0);
-		    _nc_warning("inconsistent length for %s, expected %d\n",
+		    _nc_warning("inconsistent length for %s, expected %d",
 				value, (int) suffix + 1);
 		    continue;
 		}
 		want = "BADC"[j];
 		if (list[j][suffix] != want) {
 		    char *value = _nc_tic_expand(list[j], TRUE, 0);
-		    _nc_warning("inconsistent suffix for %s, expected %c, have %c\n",
+		    _nc_warning("inconsistent suffix for %s, expected %c, have %c",
 				value, want, list[j][suffix]);
 		}
 	    }
@@ -1253,7 +1410,7 @@
 #define UNEXPECTED(name) if (PRESENT(name)) _nc_warning("unexpected " #name ", for %s", why)
 
 static void
-check_noaddress(TERMTYPE *tp, const char *why)
+check_noaddress(TERMTYPE2 *tp, const char *why)
 {
     UNEXPECTED(column_address);
     UNEXPECTED(cursor_address);
@@ -1265,7 +1422,7 @@
 }
 
 static void
-check_cursor(TERMTYPE *tp)
+check_cursor(TERMTYPE2 *tp)
 {
     int count;
     char *list[4];
@@ -1274,7 +1431,7 @@
 	check_noaddress(tp, "hard_copy");
     } else if (generic_type) {
 	check_noaddress(tp, "generic_type");
-    } else if (strchr(tp->term_names, '+') == 0) {
+    } else if (strchr(tp->term_names, '+') == NULL) {
 	int y = 0;
 	int x = 0;
 	if (PRESENT(column_address))
@@ -1384,7 +1541,7 @@
  * is mapped inconsistently.
  */
 static void
-check_keypad(TERMTYPE *tp)
+check_keypad(TERMTYPE2 *tp)
 {
     char show[80];
 
@@ -1396,9 +1553,7 @@
 	char final[MAX_KP + 1];
 	long list[MAX_KP];
 	int increase = 0;
-	int j, k, kk;
-	long last;
-	long test;
+	int j;
 
 	final[0] = keypad_final(key_a1);
 	final[1] = keypad_final(key_a3);
@@ -1431,10 +1586,17 @@
 		++increase;
 	    }
 	}
+
 	if (increase != (MAX_KP - 1)) {
+	    long last;
+
 	    show[0] = '\0';
 
 	    for (j = 0, last = -1; j < MAX_KP; ++j) {
+		int k;
+		int kk;
+		long test;
+
 		for (k = 0, kk = -1, test = 100; k < 5; ++k) {
 		    if (list[k] > last &&
 			list[k] < test) {
@@ -1494,31 +1656,57 @@
 }
 
 static void
-check_printer(TERMTYPE *tp)
+check_printer(TERMTYPE2 *tp)
 {
+    (void) tp;
+#if defined(enter_doublewide_mode) && defined(exit_doublewide_mode)
     PAIRED(enter_doublewide_mode, exit_doublewide_mode);
+#endif
+#if defined(enter_italics_mode) && defined(exit_italics_mode)
     PAIRED(enter_italics_mode, exit_italics_mode);
+#endif
+#if defined(enter_leftward_mode) && defined(exit_leftward_mode)
     PAIRED(enter_leftward_mode, exit_leftward_mode);
+#endif
+#if defined(enter_micro_mode) && defined(exit_micro_mode)
     PAIRED(enter_micro_mode, exit_micro_mode);
+#endif
+#if defined(enter_shadow_mode) && defined(exit_shadow_mode)
     PAIRED(enter_shadow_mode, exit_shadow_mode);
+#endif
+#if defined(enter_subscript_mode) && defined(exit_subscript_mode)
     PAIRED(enter_subscript_mode, exit_subscript_mode);
+#endif
+#if defined(enter_superscript_mode) && defined(exit_superscript_mode)
     PAIRED(enter_superscript_mode, exit_superscript_mode);
+#endif
+#if defined(enter_upward_mode) && defined(exit_upward_mode)
     PAIRED(enter_upward_mode, exit_upward_mode);
+#endif
 
+#if defined(start_char_set_def) && defined(stop_char_set_def)
     ANDMISSING(start_char_set_def, stop_char_set_def);
+#endif
 
-    /* if we have a parameterized form, then the non-parameterized is easy */
-    ANDMISSING(set_bottom_margin_parm, set_bottom_margin);
-    ANDMISSING(set_left_margin_parm, set_left_margin);
-    ANDMISSING(set_right_margin_parm, set_right_margin);
-    ANDMISSING(set_top_margin_parm, set_top_margin);
-
+    /*
+     * If we have a parameterized form, then the non-parameterized is easy.
+     * note: parameterized/non-parameterized margin settings are unrelated.
+     */
+#if defined(parm_down_micro) && defined(micro_down)
     ANDMISSING(parm_down_micro, micro_down);
+#endif
+#if defined(parm_left_micro) && defined(micro_left)
     ANDMISSING(parm_left_micro, micro_left);
+#endif
+#if defined(parm_right_micro) && defined(micro_right)
     ANDMISSING(parm_right_micro, micro_right);
+#endif
+#if defined(parm_up_micro) && defined(micro_up)
     ANDMISSING(parm_up_micro, micro_up);
+#endif
 }
 
+#if NCURSES_XNAMES
 static bool
 uses_SGR_39_49(const char *value)
 {
@@ -1530,16 +1718,19 @@
  * Check consistency of termcap extensions related to "screen".
  */
 static void
-check_screen(TERMTYPE *tp)
+check_screen(TERMTYPE2 *tp)
 {
-#if NCURSES_XNAMES
     if (_nc_user_definable) {
 	int have_XT = tigetflag("XT");
 	int have_XM = tigetflag("XM");
 	int have_bce = back_color_erase;
 	bool have_kmouse = FALSE;
 	bool use_sgr_39_49 = FALSE;
+	const char *name_39_49 = "orig_pair or orig_colors";
 	char *name = _nc_first_name(tp->term_names);
+	bool is_screen = !strncmp(name, "screen", 6);
+	bool screen_base = (is_screen
+			    && strchr(name, '.') == NULL);
 
 	if (!VALID_BOOLEAN(have_bce)) {
 	    have_bce = FALSE;
@@ -1553,39 +1744,55 @@
 	if (VALID_STRING(key_mouse)) {
 	    have_kmouse = !strcmp("\033[M", key_mouse);
 	}
-	if (VALID_STRING(orig_colors)) {
-	    use_sgr_39_49 = uses_SGR_39_49(orig_colors);
-	} else if (VALID_STRING(orig_pair)) {
-	    use_sgr_39_49 = uses_SGR_39_49(orig_pair);
+	if (have_bce) {
+	    if (VALID_STRING(orig_pair)) {
+		name_39_49 = "orig_pair";
+		use_sgr_39_49 = uses_SGR_39_49(orig_pair);
+	    }
+	    if (!use_sgr_39_49 && VALID_STRING(orig_colors)) {
+		name_39_49 = "orig_colors";
+		use_sgr_39_49 = uses_SGR_39_49(orig_colors);
+	    }
 	}
 
 	if (have_XM && have_XT) {
-	    _nc_warning("Screen's XT capability conflicts with XM");
-	} else if (have_XT
-		   && strstr(name, "screen") != 0
-		   && strchr(name, '.') != 0) {
-	    _nc_warning("Screen's \"screen\" entries should not have XT set");
+	    _nc_warning("screen's XT capability conflicts with XM");
+	} else if (have_XT && screen_base) {
+	    _nc_warning("screen's \"screen\" entries should not have XT set");
 	} else if (have_XT) {
-	    if (!have_kmouse && have_bce) {
+	    char *s;
+
+	    if (!have_kmouse && is_screen) {
 		if (VALID_STRING(key_mouse)) {
-		    _nc_warning("Value of kmous inconsistent with screen's usage");
+		    _nc_warning("value of kmous inconsistent with screen's usage");
 		} else {
-		    _nc_warning("Expected kmous capability with XT");
+		    _nc_warning("expected kmous capability with XT");
 		}
 	    }
-	    if (!have_bce && max_colors > 0)
-		_nc_warning("Expected bce capability with XT");
-	    if (!use_sgr_39_49 && have_bce && max_colors > 0)
-		_nc_warning("Expected orig_colors capability with XT to have 39/49 parameters");
-	    if (VALID_STRING(to_status_line))
+	    if (max_colors > 0) {
+		if (!have_bce) {
+		    _nc_warning("expected bce capability with XT");
+		} else if (!use_sgr_39_49) {
+		    _nc_warning("expected %s capability with XT "
+				"to have 39/49 parameters", name_39_49);
+		}
+	    }
+	    if (VALID_STRING(to_status_line)
+		&& (s = strchr(to_status_line, ';')) != NULL
+		&& *++s == '\0')
 		_nc_warning("\"tsl\" capability is redundant, given XT");
 	} else {
-	    if (have_kmouse && !have_XM)
-		_nc_warning("Expected XT to be set, given kmous");
+	    if (have_kmouse
+		&& !have_XM
+		&& !screen_base && strchr(name, '+') == NULL) {
+		_nc_warning("expected XT to be set, given kmous");
+	    }
 	}
     }
-#endif
 }
+#else
+#define check_screen(tp)	/* nothing */
+#endif
 
 /*
  * Returns the expected number of parameters for the given capability.
@@ -1665,7 +1872,6 @@
 	DATA( "wingo",		1 ),
     };
     /* *INDENT-ON* */
-
 #undef DATA
 
     unsigned n;
@@ -1682,26 +1888,133 @@
 }
 
 /*
+ * Check for user-capabilities that happen to be used in ncurses' terminal
+ * database.
+ */
+#if NCURSES_XNAMES
+static struct user_table_entry const *
+lookup_user_capability(const char *name)
+{
+    struct user_table_entry const *result = 0;
+    if (*name != 'k') {
+	result = _nc_find_user_entry(name);
+    }
+    return result;
+}
+#endif
+
+/*
+ * If a given name is likely to be a user-capability, return the number of
+ * parameters it would be used with.  If not, return -1.
+ *
+ * ncurses assumes that u6 could be used for getting the cursor-position, but
+ * that is not implemented.  Make a special case for that, to quiet needless
+ * warnings.
+ *
+ * The other string-capability extensions (see terminfo.src) which could have
+ * parameters such as "Ss", "%u", are not used by ncurses.  But we check those
+ * anyway, to validate the terminfo database.
+ */
+static int
+is_user_capability(const char *name)
+{
+    int result = -1;
+    if (name[0] == 'u' &&
+	(name[1] >= '0' && name[1] <= '9') &&
+	name[2] == '\0') {
+	result = (name[1] == '6') ? 2 : 0;
+    }
+#if NCURSES_XNAMES
+    else if (using_extensions) {
+	struct user_table_entry const *p = lookup_user_capability(name);
+	if (p != 0) {
+	    result = (int) p->ute_argc;
+	}
+    }
+#endif
+    return result;
+}
+
+static bool
+line_capability(const char *name)
+{
+    bool result = FALSE;
+    static const char *table[] =
+    {
+	"csr",			/* change_scroll_region          */
+	"clear",		/* clear_screen                  */
+	"ed",			/* clr_eos                       */
+	"cwin",			/* create_window                 */
+	"cup",			/* cursor_address                */
+	"cud1",			/* cursor_down                   */
+	"home",			/* cursor_home                   */
+	"mrcup",		/* cursor_mem_address            */
+	"ll",			/* cursor_to_ll                  */
+	"cuu1",			/* cursor_up                     */
+	"dl1",			/* delete_line                   */
+	"hd",			/* down_half_line                */
+	"flash",		/* flash_screen                  */
+	"ff",			/* form_feed                     */
+	"il1",			/* insert_line                   */
+	"nel",			/* newline                       */
+	"dl",			/* parm_delete_line              */
+	"cud",			/* parm_down_cursor              */
+	"indn",			/* parm_index                    */
+	"il",			/* parm_insert_line              */
+	"rin",			/* parm_rindex                   */
+	"cuu",			/* parm_up_cursor                */
+	"mc0",			/* print_screen                  */
+	"vpa",			/* row_address                   */
+	"ind",			/* scroll_forward                */
+	"ri",			/* scroll_reverse                */
+	"hu",			/* up_half_line                  */
+    };
+    size_t n;
+    for (n = 0; n < SIZEOF(table); ++n) {
+	if (!strcmp(name, table[n])) {
+	    result = TRUE;
+	    break;
+	}
+    }
+    return result;
+}
+
+/*
  * Make a quick sanity check for the parameters which are used in the given
  * strings.  If there are no "%p" tokens, then there should be no other "%"
  * markers.
  */
 static void
-check_params(TERMTYPE *tp, const char *name, char *value)
+check_params(TERMTYPE2 *tp, const char *name, const char *value, int extended)
 {
     int expected = expected_params(name);
     int actual = 0;
     int n;
-    bool params[NUM_PARM];
-    char *s = value;
+    bool params[1 + NUM_PARM];
+    const char *s = value;
 
+#ifdef set_left_margin_parm
+    if (!strcmp(name, "smgrp")
+	&& !VALID_STRING(set_left_margin_parm))
+	expected = 2;
+#endif
+#ifdef set_right_margin_parm
+    if (!strcmp(name, "smglp")
+	&& !VALID_STRING(set_right_margin_parm))
+	expected = 2;
+#endif
 #ifdef set_top_margin_parm
     if (!strcmp(name, "smgbp")
-	&& set_top_margin_parm == 0)
+	&& !VALID_STRING(set_top_margin_parm))
+	expected = 2;
+#endif
+#ifdef set_bottom_margin_parm
+    if (!strcmp(name, "smgtp")
+	&& !VALID_STRING(set_bottom_margin_parm))
 	expected = 2;
 #endif
 
-    for (n = 0; n < NUM_PARM; n++)
+    for (n = 0; n <= NUM_PARM; n++)
 	params[n] = FALSE;
 
     while (*s != 0) {
@@ -1724,6 +2037,22 @@
 	s++;
     }
 
+#if NCURSES_XNAMES
+    if (extended) {
+	int check = is_user_capability(name);
+	if (check != actual && (check >= 0 && actual >= 0)) {
+	    _nc_warning("extended %s capability has %d parameters, expected %d",
+			name, actual, check);
+	} else if (debug_level > 1) {
+	    _nc_warning("extended %s capability has %d parameters, as expected",
+			name, actual);
+	}
+	expected = actual;
+    }
+#else
+    (void) extended;
+#endif
+
     if (params[0]) {
 	_nc_warning("%s refers to parameter 0 (%%p0), which is not allowed", name);
     }
@@ -1737,6 +2066,175 @@
 		_nc_warning("%s omits parameter %d", name, n);
 	}
     }
+
+    /*
+     * Counting "%p" markers does not account for termcap expressions which
+     * may not have been fully translated.  Also, tparm does its own analysis.
+     * Report differences here.
+     */
+    _nc_reset_tparm(NULL);
+    if (actual >= 0) {
+	char *p_is_s[NUM_PARM];
+	int popcount;
+	int analyzed = _nc_tparm_analyze(NULL, value, p_is_s, &popcount);
+	if (analyzed < popcount) {
+	    analyzed = popcount;
+	}
+	if (actual != analyzed && expected != analyzed) {
+#if NCURSES_XNAMES
+	    int user_cap = is_user_capability(name);
+	    if ((user_cap == analyzed) && using_extensions) {
+		;		/* ignore */
+	    } else if (user_cap >= 0) {
+		_nc_warning("tparm will use %d parameters for %s, expected %d",
+			    analyzed, name, user_cap);
+	    } else
+#endif
+	    {
+		_nc_warning("tparm analyzed %d parameters for %s, expected %d",
+			    analyzed, name, actual);
+	    }
+	} else if (expected > 0
+		   && actual == expected
+		   && guess_tparm_type(expected, p_is_s) == Numbers) {
+	    int limit = 1;
+
+	    if (!strcmp(name, "setf")
+		|| !strcmp(name, "setb")
+		|| !strcmp(name, "setaf")
+		|| !strcmp(name, "setab")) {
+		if ((limit = max_colors) > 256)
+		    limit = 256;
+	    } else if (line_capability(name)) {
+		limit = 24;
+	    } else if (is_user_capability(name) < 0) {
+		limit = 80;
+	    }
+	    for (n = 0; n < limit; ++n) {
+		_nc_reset_tparm(NULL);
+		(void) TPARM_9(value, n, n, n, n, n, n, n, n, n);
+		if (_nc_tparm_err) {
+		    _nc_warning("problem%s in tparm(%s, %d, ...)",
+				(_nc_tparm_err == 1) ? "" : "s",
+				name, n);
+		    if (debug_level < 2)
+			break;
+		}
+	    }
+	}
+    }
+}
+
+/*
+ * Check for DEC VT100 private mode for reverse video.
+ */
+static const char *
+skip_DECSCNM(const char *value, int *flag)
+{
+    *flag = -1;
+    if (value != 0) {
+	int skip = csi_length(value);
+	if (skip > 0 &&
+	    value[skip++] == '?' &&
+	    value[skip++] == '5') {
+	    if (value[skip] == 'h') {
+		*flag = 1;
+	    } else if (value[skip] == 'l') {
+		*flag = 0;
+	    }
+	    value += skip + 1;
+	}
+    }
+    return value;
+}
+
+static void
+check_delays(TERMTYPE2 *tp, const char *name, const char *value)
+{
+    const char *p, *q;
+    const char *first = 0;
+    const char *last = 0;
+
+    for (p = value; *p != '\0'; ++p) {
+	if (p[0] == '$' && p[1] == '<') {
+	    const char *base = p + 2;
+	    const char *mark = 0;
+	    bool mixed = FALSE;
+	    int proportional = 0;
+	    int mandatory = 0;
+
+	    first = p;
+
+	    for (q = base; *q != '\0'; ++q) {
+		if (*q == '>') {
+		    if (mark == NULL)
+			mark = q;
+		    break;
+		} else if (*q == '*' || *q == '/') {
+		    if (*q == '*')
+			++proportional;
+		    if (*q == '/')
+			++mandatory;
+		    if (mark == NULL)
+			mark = q;
+		} else if (!(isalnum(UChar(*q)) || strchr("+-.", *q) != 0)) {
+		    break;
+		} else if (proportional || mandatory) {
+		    mixed = TRUE;
+		}
+	    }
+	    last = *q ? (q + 1) : q;
+	    if (*q != '\0') {
+		float check_f;
+		char check_c;
+		int rc = sscanf(base, "%f%c", &check_f, &check_c);
+		if ((rc != 2) || (mark != NULL && (check_c != *mark)) || mixed) {
+		    _nc_warning("syntax error in %s delay '%.*s'", name,
+				(int) (q - base), base);
+		} else if (*name == 'k') {
+		    _nc_warning("function-key %s has delay", name);
+		} else if (proportional && !line_capability(name)) {
+		    _nc_warning("non-line capability using proportional delay: %s", name);
+		} else if (!xon_xoff &&
+			   !mandatory &&
+			   strchr(_nc_first_name(tp->term_names), '+') == NULL) {
+		    _nc_warning("%s in %s is used since no xon/xoff",
+				(proportional
+				 ? "proportional delay"
+				 : "delay"),
+				name);
+		}
+	    } else {
+		p = q - 1;	/* restart scan */
+	    }
+	}
+    }
+
+    if (!strcmp(name, "flash") ||
+	!strcmp(name, "beep")) {
+
+	if (first != 0) {
+	    if (first == value || *last == 0) {
+		/*
+		 * Delay is on one end or the other.
+		 */
+		_nc_warning("expected delay embedded within %s", name);
+	    }
+	} else {
+	    int flag;
+
+	    /*
+	     * Check for missing delay when using VT100 reverse-video.
+	     * A real VT100 might not need this, but terminal emulators do.
+	     */
+	    if ((p = skip_DECSCNM(value, &flag)) != 0 &&
+		flag > 0 &&
+		skip_DECSCNM(p, &flag) != 0 &&
+		flag == 0) {
+		_nc_warning("expected a delay in %s", name);
+	    }
+	}
+    }
 }
 
 static char *
@@ -1750,25 +2248,60 @@
     char *result;
     char blob[NUM_PARM * 10];
     char *next = blob;
+    TParams expect;
+    TParams actual;
+    int nparam;
 
     *next++ = '\0';
     for (k = 1; k <= NUM_PARM; k++) {
 	numbers[k] = count;
-	sprintf(next, "XYZ%d", count);
+	_nc_SPRINTF(next,
+		    _nc_SLIMIT(sizeof(blob) - (size_t) (next - blob))
+		    "XYZ%d", count);
 	strings[k] = next;
 	next += strlen(next) + 1;
     }
 
-    switch (tparm_type(name)) {
+    _nc_reset_tparm(NULL);
+    expect = tparm_type(name);
+    nparam = _nc_tparm_analyze(NULL, value, p_is_s, &ignored);
+    actual = guess_tparm_type(nparam, p_is_s);
+
+    if (expect != actual) {
+	_nc_warning("%s has mismatched parameters", name);
+	actual = Other;
+    }
+
+    _nc_reset_tparm(NULL);
+    switch (actual) {
+    case Str:
+	result = TPARM_1(value, strings[1]);
+	break;
     case Num_Str:
 	result = TPARM_2(value, numbers[1], strings[2]);
 	break;
+    case Str_Str:
+	result = TPARM_2(value, strings[1], strings[2]);
+	break;
     case Num_Str_Str:
 	result = TPARM_3(value, numbers[1], strings[2], strings[3]);
 	break;
     case Numbers:
+#define myParam(n) numbers[n]
+	result = TIPARM_9(value,
+			  myParam(1),
+			  myParam(2),
+			  myParam(3),
+			  myParam(4),
+			  myParam(5),
+			  myParam(6),
+			  myParam(7),
+			  myParam(8),
+			  myParam(9));
+#undef myParam
+	break;
+    case Other:
     default:
-	(void) _nc_tparm_analyze(value, p_is_s, &ignored);
 #define myParam(n) (p_is_s[n - 1] != 0 ? ((TPARM_ARG) strings[n]) : numbers[n])
 	result = TPARM_9(value,
 			 myParam(1),
@@ -1780,9 +2313,10 @@
 			 myParam(7),
 			 myParam(8),
 			 myParam(9));
+#undef myParam
 	break;
     }
-    return result;
+    return strdup(result);
 }
 
 #define IsDelay(ch) ((ch) == '.' || isdigit(UChar(ch)))
@@ -1809,7 +2343,7 @@
 	}
     }
     while (*src == '*' || *src == '/') {
-	if (always == 0 && *src == '/')
+	if (always == NULL && *src == '/')
 	    break;
 	if (*src++ == '*') {
 	    star = 1;
@@ -1907,57 +2441,65 @@
  * Check terminfo to termcap translation.
  */
 static void
-check_infotocap(TERMTYPE *tp, int i, const char *value)
+check_infotocap(TERMTYPE2 *tp, int i, const char *value)
 {
     const char *name = ExtStrname(tp, i, strnames);
-    int params = (((i < (int) SIZEOF(parametrized)) &&
-		   (i < STRCOUNT))
-		  ? parametrized[i]
-		  : ((*value == 'k')
-		     ? 0
-		     : has_params(value)));
-    int to_char = 0;
-    char *ti_value;
-    char *tc_value;
-    bool embedded;
+    char *ti_value = NULL;
 
-    if ((ti_value = _nc_tic_expand(value, TRUE, to_char)) == ABSENT_STRING) {
+    assert(SIZEOF(parametrized) == STRCOUNT);
+    if (!VALID_STRING(value) || (ti_value = strdup(value)) == NULL) {
 	_nc_warning("tic-expansion of %s failed", name);
-    } else if ((tc_value = _nc_infotocap(name, ti_value, params)) == ABSENT_STRING) {
-	_nc_warning("tic-conversion of %s failed", name);
-    } else if (params > 0) {
-	int limit = 5;
-	int count;
-	bool first = TRUE;
+    } else {
+	char *tc_value;
+	bool embedded;
+	int params = ((i < (int) SIZEOF(parametrized))
+		      ? parametrized[i]
+		      : ((*value == 'k')
+			 ? 0
+			 : has_params(value, FALSE)));
 
-	if (!strcmp(name, "setf")
-	    || !strcmp(name, "setb")
-	    || !strcmp(name, "setaf")
-	    || !strcmp(name, "setab")) {
-	    limit = max_colors;
-	}
-	for (count = 0; count < limit; ++count) {
-	    char *ti_check = check_1_infotocap(name, ti_value, count);
-	    char *tc_check = check_1_infotocap(name, tc_value, count);
+	if ((tc_value = _nc_infotocap(name, ti_value, params)) == ABSENT_STRING) {
+	    _nc_warning("tic-conversion of %s failed", name);
+	} else if (params > 0) {
+	    int limit = 5;
+	    int count;
+	    bool first = TRUE;
 
-	    if (strcmp(ti_check, tc_check)) {
-		if (first) {
-		    fprintf(stderr, "check_infotocap(%s)\n", name);
-		    fprintf(stderr, "...ti '%s'\n", ti_value);
-		    fprintf(stderr, "...tc '%s'\n", tc_value);
-		    first = FALSE;
+	    if (!strcmp(name, "setf")
+		|| !strcmp(name, "setb")
+		|| !strcmp(name, "setaf")
+		|| !strcmp(name, "setab")) {
+		if ((limit = max_colors) > 256)
+		    limit = 256;
+	    }
+	    for (count = 0; count < limit; ++count) {
+		char *ti_check = check_1_infotocap(name, ti_value, count);
+		char *tc_check = check_1_infotocap(name, tc_value, count);
+
+		if (strcmp(ti_check, tc_check)) {
+		    if (first) {
+			fprintf(stderr, "check_infotocap(%s)\n", name);
+			fprintf(stderr, "...ti '%s'\n", _nc_visbuf2(0, ti_value));
+			fprintf(stderr, "...tc '%s'\n", _nc_visbuf2(0, tc_value));
+			first = FALSE;
+		    }
+		    _nc_warning("tparm-conversion of %s(%d) differs between\n\tterminfo %s\n\ttermcap  %s",
+				name, count,
+				_nc_visbuf2(0, ti_check),
+				_nc_visbuf2(1, tc_check));
 		}
-		_nc_warning("tparm-conversion of %s(%d) differs between\n\tterminfo %s\n\ttermcap  %s",
-			    name, count, ti_check, tc_check);
+		free(ti_check);
+		free(tc_check);
+	    }
+	} else if (params == 0 && !same_ti_tc(ti_value, tc_value, &embedded)) {
+	    if (embedded) {
+		_nc_warning("termcap equivalent of %s cannot use embedded delay", name);
+	    } else {
+		_nc_warning("tic-conversion of %s changed value\n\tfrom %s\n\tto   %s",
+			    name, ti_value, tc_value);
 	    }
 	}
-    } else if (params == 0 && !same_ti_tc(ti_value, tc_value, &embedded)) {
-	if (embedded) {
-	    _nc_warning("termcap equivalent of %s cannot use embedded delay", name);
-	} else {
-	    _nc_warning("tic-conversion of %s changed value\n\tfrom %s\n\tto   %s",
-			name, ti_value, tc_value);
-	}
+	free(ti_value);
     }
 }
 
@@ -2006,6 +2548,23 @@
     return s;
 }
 
+#define DATA(name) { #name }
+static const char sgr_names[][11] =
+{
+    DATA(none),
+    DATA(standout),
+    DATA(underline),
+    DATA(reverse),
+    DATA(blink),
+    DATA(dim),
+    DATA(bold),
+    DATA(invis),
+    DATA(protect),
+    DATA(altcharset),
+    ""
+};
+#undef DATA
+
 /*
  * An sgr string may contain several settings other than the one we're
  * interested in, essentially sgr0 + rmacs + whatever.  As long as the
@@ -2015,21 +2574,6 @@
 static bool
 similar_sgr(int num, char *a, char *b)
 {
-#define DATA(name) { #name }
-    static const char names[][11] =
-    {
-	DATA(none),
-	DATA(standout),
-	DATA(underline),
-	DATA(reverse),
-	DATA(blink),
-	DATA(dim),
-	DATA(bold),
-	DATA(invis),
-	DATA(protect),
-	DATA(altcharset),
-    };
-#undef DATA
     char *base_a = a;
     char *base_b = b;
     int delaying = 0;
@@ -2037,12 +2581,14 @@
     while (*b != 0) {
 	while (*a != *b) {
 	    if (*a == 0) {
-		if (b[0] == '$'
-		    && b[1] == '<') {
-		    _nc_warning("Did not find delay %s", _nc_visbuf(b));
+		if (num < 0) {
+		    ;
+		} else if (b[0] == '$'
+			   && b[1] == '<') {
+		    _nc_warning("did not find delay %s", _nc_visbuf(b));
 		} else {
 		    _nc_warning("checking sgr(%s) %s\n\tcompare to %s\n\tunmatched %s",
-				names[num], _nc_visbuf2(1, base_a),
+				sgr_names[num], _nc_visbuf2(1, base_a),
 				_nc_visbuf2(2, base_b),
 				_nc_visbuf2(3, b));
 		}
@@ -2077,22 +2623,29 @@
     return ((num != 0) || (*a == 0));
 }
 
+static void
+check_tparm_err(int num)
+{
+    if (_nc_tparm_err)
+	_nc_warning("tparam error in sgr(%d): %s", num, sgr_names[num]);
+}
+
 static char *
-check_sgr(TERMTYPE *tp, char *zero, int num, char *cap, const char *name)
+check_sgr(TERMTYPE2 *tp, char *zero, int num, char *cap, const char *name)
 {
     char *test;
 
     _nc_tparm_err = 0;
-    test = TPARM_9(set_attributes,
-		   num == 1,
-		   num == 2,
-		   num == 3,
-		   num == 4,
-		   num == 5,
-		   num == 6,
-		   num == 7,
-		   num == 8,
-		   num == 9);
+    test = TIPARM_9(set_attributes,
+		    num == 1,
+		    num == 2,
+		    num == 3,
+		    num == 4,
+		    num == 5,
+		    num == 6,
+		    num == 7,
+		    num == 8,
+		    num == 9);
     if (test != 0) {
 	if (PRESENT(cap)) {
 	    if (!similar_sgr(num, test, cap)) {
@@ -2107,8 +2660,7 @@
     } else if (PRESENT(cap)) {
 	_nc_warning("sgr(%d) missing, but %s present", num, name);
     }
-    if (_nc_tparm_err)
-	_nc_warning("stack error in sgr(%d) string", num);
+    check_tparm_err(num);
     return test;
 }
 
@@ -2144,14 +2696,14 @@
 } NAME_VALUE;
 
 static NAME_VALUE *
-get_fkey_list(TERMTYPE *tp)
+get_fkey_list(TERMTYPE2 *tp)
 {
     NAME_VALUE *result = typeMalloc(NAME_VALUE, NUM_STRINGS(tp) + 1);
     const struct tinfo_fkeys *all_fkeys = _nc_tinfo_fkeys;
     int used = 0;
-    int j;
+    unsigned j;
 
-    if (result == 0)
+    if (result == NULL)
 	failed("get_fkey_list");
 
     for (j = 0; all_fkeys[j].code; j++) {
@@ -2165,7 +2717,7 @@
     }
 #if NCURSES_XNAMES
     for (j = STRCOUNT; j < NUM_STRINGS(tp); ++j) {
-	const char *name = ExtStrname(tp, j, strnames);
+	const char *name = ExtStrname(tp, (int) j, strnames);
 	if (*name == 'k') {
 	    result[used].keycode = -1;
 	    result[used].name = name;
@@ -2195,32 +2747,38 @@
  * last one assigned).
  */
 static void
-check_conflict(TERMTYPE *tp)
+check_conflict(TERMTYPE2 *tp)
 {
-    bool conflict = FALSE;
-    unsigned j, k;
-
     if (!(_nc_syntax == SYN_TERMCAP && capdump)) {
 	char *check = calloc((size_t) (NUM_STRINGS(tp) + 1), sizeof(char));
 	NAME_VALUE *given = get_fkey_list(tp);
+	unsigned j, k;
+	bool conflict = FALSE;
 
-	if (check == 0)
-	    failed("check_termtype");
+	if (check == NULL)
+	    failed("check_conflict");
 
 	for (j = 0; given[j].keycode; ++j) {
 	    const char *a = given[j].value;
 	    bool first = TRUE;
 
+	    if (!VALID_STRING(a))
+		continue;
+
 	    for (k = j + 1; given[k].keycode; k++) {
 		const char *b = given[k].value;
+
+		if (!VALID_STRING(b))
+		    continue;
 		if (check[k])
 		    continue;
+
 		if (!_nc_capcmp(a, b)) {
 		    check[j] = 1;
 		    check[k] = 1;
 		    if (first) {
 			if (!conflict) {
-			    _nc_warning("Conflicting key definitions (using the last)");
+			    _nc_warning("conflicting key definitions (using the last)");
 			    conflict = TRUE;
 			}
 			fprintf(stderr, "...");
@@ -2237,16 +2795,405 @@
 	    if (!first)
 		fprintf(stderr, "\n");
 	}
+#if NCURSES_XNAMES
+	if (using_extensions) {
+	    /* *INDENT-OFF* */
+	    static struct {
+		const char *xcurses;
+		const char *shifted;
+	    } table[] = {
+		{ "kDC",  NULL },
+		{ "kDN",  "kind" },
+		{ "kEND", NULL },
+		{ "kHOM", NULL },
+		{ "kLFT", NULL },
+		{ "kNXT", NULL },
+		{ "kPRV", NULL },
+		{ "kRIT", NULL },
+		{ "kUP",  "kri" },
+		{ NULL,   NULL },
+	    };
+	    /* *INDENT-ON* */
+	    /*
+	     * SVr4 curses defines the "xcurses" names listed above except for
+	     * the special cases in the "shifted" column.  When using these
+	     * names for xterm's extensions, that was confusing, and resulted
+	     * in adding extended capabilities with "2" (shift) suffix.  This
+	     * check warns about unnecessary use of extensions for this quirk.
+	     */
+	    for (j = 0; given[j].keycode; ++j) {
+		const char *find = given[j].name;
+		int value;
+		char ch;
+
+		if (!VALID_STRING(given[j].value))
+		    continue;
+
+		for (k = 0; table[k].xcurses; ++k) {
+		    const char *test = table[k].xcurses;
+		    size_t size = strlen(test);
+
+		    if (!strncmp(find, test, size) && strcmp(find, test)) {
+			switch (sscanf(find + size, "%d%c", &value, &ch)) {
+			case 1:
+			    if (value == 2) {
+				_nc_warning("expected '%s' rather than '%s'",
+					    (table[k].shifted
+					     ? table[k].shifted
+					     : test), find);
+			    } else if (value < 2 || value > 15) {
+				_nc_warning("expected numeric 2..15 '%s'", find);
+			    }
+			    break;
+			default:
+			    _nc_warning("expected numeric suffix for '%s'", find);
+			    break;
+			}
+			break;
+		    }
+		}
+	    }
+	}
+#endif
 	free(given);
 	free(check);
     }
 }
 
+/*
+ * Exiting a video mode should not duplicate sgr0
+ */
+static void
+check_exit_attribute(const char *name, char *test, char *trimmed, char *untrimmed)
+{
+    if (VALID_STRING(test) && (trimmed != 0)) {
+	if (similar_sgr(-1, trimmed, test) ||
+	    similar_sgr(-1, untrimmed, test)) {
+	    _nc_warning("%s matches exit_attribute_mode", name);
+	}
+    }
+}
+
+/*
+ * Returns true if the string looks like a standard SGR string.
+ */
+static bool
+is_sgr_string(char *value)
+{
+    bool result = FALSE;
+
+    if (VALID_STRING(value)) {
+	int skip = csi_length(value);
+
+	if (skip) {
+	    int ch;
+
+	    result = TRUE;
+	    value += skip;
+	    while ((ch = UChar(*value++)) != '\0') {
+		if (isdigit(ch) || ch == ';') {
+		    ;
+		} else if (ch == 'm' && *value == '\0') {
+		    ;
+		} else {
+		    result = FALSE;
+		    break;
+		}
+	    }
+	}
+    }
+    return result;
+}
+
+/*
+ * Check if the given capability contains a given SGR attribute.
+ */
+static void
+check_sgr_param(TERMTYPE2 *tp, int code, const char *name, char *value)
+{
+    if (VALID_STRING(value)) {
+	int ncv = ((code != 0) ? (1 << (code - 1)) : 0);
+	char *test = tgoto(value, 0, 0);
+	if (is_sgr_string(test)) {
+	    int param = 0;
+	    int count = 0;
+	    int skips = 0;
+	    int color = (value == set_a_foreground ||
+			 value == set_a_background ||
+			 value == set_foreground ||
+			 value == set_background);
+	    while (*test != 0) {
+		if (isdigit(UChar(*test))) {
+		    param = 10 * param + (*test - '0');
+		    ++count;
+		} else {
+		    if (count) {
+			/*
+			 * Avoid unnecessary warning for xterm 256color codes.
+			 */
+			if (color && (param == 38 || param == 48))
+			    skips = 3;
+			if ((skips-- <= 0) && (param == code))
+			    break;
+		    }
+		    count = 0;
+		    param = 0;
+		}
+		++test;
+	    }
+	    if (count != 0 && param == code) {
+		if (code == 0 ||
+		    no_color_video < 0 ||
+		    !(no_color_video & ncv)) {
+		    _nc_warning("\"%s\" SGR-attribute used in %s",
+				sgr_names[code],
+				name);
+		}
+	    }
+	}
+    }
+}
+
+#if NCURSES_XNAMES
+static int
+standard_type(const char *name)
+{
+    int result = -1;
+    const struct name_table_entry *np;
+
+    if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0) {
+	result = np->nte_type;
+    }
+    return result;
+}
+
+static const char *
+name_of_type(int type)
+{
+    const char *result = "unknown";
+    switch (type) {
+    case BOOLEAN:
+	result = "boolean";
+	break;
+    case NUMBER:
+	result = "number";
+	break;
+    case STRING:
+	result = "string";
+	break;
+    }
+    return result;
+}
+
+static void
+check_user_capability_type(const char *name, int actual)
+{
+    if (lookup_user_capability(name) == 0) {
+	int expected = standard_type(name);
+	if (expected >= 0) {
+	    _nc_warning("expected %s to be %s, but actually %s",
+			name,
+			name_of_type(actual),
+			name_of_type(expected)
+		);
+	} else if (*name != 'k') {
+	    _nc_warning("undocumented %s capability %s",
+			name_of_type(actual),
+			name);
+	}
+    }
+}
+#endif
+
+#define IN_DELAY "0123456789*/."
+
+static bool
+check_ANSI_cap(const char *value, int nparams, char final)
+{
+    bool result = FALSE;
+    if (VALID_STRING(value) && csi_length(value) > 0) {
+	char *p_is_s[NUM_PARM];
+	int popcount;
+	int analyzed = _nc_tparm_analyze(NULL, value, p_is_s, &popcount);
+	if (analyzed < popcount) {
+	    analyzed = popcount;
+	}
+	if (analyzed == nparams) {
+	    bool numbers = TRUE;
+	    int p;
+	    for (p = 0; p < nparams; ++p) {
+		if (p_is_s[p]) {
+		    numbers = FALSE;
+		    break;
+		}
+	    }
+	    if (numbers) {
+		int in_delay = 0;
+		p = (int) strlen(value);
+		while (p-- > 0) {
+		    char ch = value[p];
+		    if (ch == final) {
+			result = TRUE;
+			break;
+		    }
+		    switch (in_delay) {
+		    case 0:
+			if (ch == '>')
+			    in_delay = 1;
+			break;
+		    case 1:
+			if (strchr(IN_DELAY, value[p]) != NULL)
+			    break;
+			if (ch != '<')
+			    p = 0;
+			in_delay = 2;
+			break;
+		    case 2:
+			if (ch != '$')
+			    p = 0;
+			in_delay = 0;
+			break;
+		    }
+		}
+	    }
+	}
+    }
+    return result;
+}
+
+static const char *
+skip_Delay(const char *value)
+{
+    const char *result = value;
+
+    if (*value == '$') {
+	++result;
+	if (*result++ == '<') {
+	    while (strchr(IN_DELAY, *result) != NULL)
+		++result;
+	    if (*result++ != '>') {
+		result = value;
+	    }
+	} else {
+	    result = value;
+	}
+    }
+    return result;
+}
+
+static bool
+isValidString(const char *value, const char *expect)
+{
+    bool result = FALSE;
+    if (VALID_STRING(value)) {
+	if (!strcmp(value, expect))
+	    result = TRUE;
+    }
+    return result;
+}
+
+static bool
+isValidEscape(const char *value, const char *expect)
+{
+    bool result = FALSE;
+    if (VALID_STRING(value)) {
+	if (*value == '\033') {
+	    size_t need = strlen(expect);
+	    size_t have = strlen(value) - 1;
+	    if (have >= need && !strncmp(value + 1, expect, need)) {
+		if (*skip_Delay(value + need + 1) == '\0') {
+		    result = TRUE;
+		}
+	    }
+	}
+    }
+    return result;
+}
+
+static int
+guess_ANSI_VTxx(TERMTYPE2 *tp)
+{
+    int result = -1;
+    int checks = 0;
+
+    /* VT100s have scrolling region, but ANSI (ECMA-48) does not specify */
+    if (check_ANSI_cap(change_scroll_region, 2, 'r') &&
+	(isValidEscape(scroll_forward, "D") ||
+	 isValidString(scroll_forward, "\n") ||
+	 isValidEscape(scroll_forward, "6")) &&
+	(isValidEscape(scroll_reverse, "M") ||
+	 isValidEscape(scroll_reverse, "9"))) {
+	checks |= 2;
+    }
+    if (check_ANSI_cap(cursor_address, 2, 'H') &&
+	check_ANSI_cap(cursor_up, 0, 'A') &&
+	(check_ANSI_cap(cursor_down, 0, 'B') ||
+	 isValidString(cursor_down, "\n")) &&
+	check_ANSI_cap(cursor_right, 0, 'C') &&
+	(check_ANSI_cap(cursor_left, 0, 'D') ||
+	 isValidString(cursor_left, "\b")) &&
+	check_ANSI_cap(clr_eos, 0, 'J') &&
+	check_ANSI_cap(clr_bol, 0, 'K') &&
+	check_ANSI_cap(clr_eol, 0, 'K')) {
+	checks |= 1;
+    }
+    if (checks == 3)
+	result = 1;
+    if (checks == 1)
+	result = 0;
+    return result;
+}
+
+/*
+ * u6/u7 and u8/u9 are query/response extensions which most terminals support.
+ * In particular, any ECMA-48 terminal should support these, though the details
+ * for u9 are implementation dependent.
+ */
+#if defined(user6) && defined(user7) && defined(user8) && defined(user9)
+static void
+check_user_6789(TERMTYPE2 *tp)
+{
+    /*
+     * Check if the terminal is known to not 
+     */
+#define NO_QUERY(longname,shortname) \
+	if (PRESENT(longname)) _nc_warning(#shortname " is not supported")
+    if (tigetflag("NQ") > 0) {
+	NO_QUERY(user6, u6);
+	NO_QUERY(user7, u7);
+	NO_QUERY(user8, u8);
+	NO_QUERY(user9, u9);
+	return;
+    }
+
+    PAIRED(user6, user7);
+    PAIRED(user8, user9);
+
+    if (strchr(tp->term_names, '+') != NULL)
+	return;
+
+    switch (guess_ANSI_VTxx(tp)) {
+    case 1:
+	if (!PRESENT(user8)) {
+	    _nc_warning("expected u8/u9 for device-attributes");
+	}
+	/* FALLTHRU */
+    case 0:
+	if (!PRESENT(user6)) {
+	    _nc_warning("expected u6/u7 for cursor-position");
+	}
+	break;
+    }
+}
+#else
+#define check_user_6789(tp)	/* nothing */
+#endif
+
 /* other sanity-checks (things that we don't want in the normal
  * logic that reads a terminfo entry)
  */
 static void
-check_termtype(TERMTYPE *tp, bool literal)
+check_termtype(TERMTYPE2 *tp, bool literal)
 {
     unsigned j;
 
@@ -2255,12 +3202,34 @@
     for_each_string(j, tp) {
 	char *a = tp->Strings[j];
 	if (VALID_STRING(a)) {
-	    check_params(tp, ExtStrname(tp, (int) j, strnames), a);
+	    const char *name = ExtStrname(tp, (int) j, strnames);
+	    /*
+	     * If we expect parameters, or if there might be parameters,
+	     * check for consistent number of parameters.
+	     */
+	    if (j >= SIZEOF(parametrized) ||
+		is_user_capability(name) >= 0 ||
+		parametrized[j] > 0) {
+		check_params(tp, name, a, (j >= STRCOUNT));
+	    }
+	    check_delays(tp, ExtStrname(tp, (int) j, strnames), a);
 	    if (capdump) {
 		check_infotocap(tp, (int) j, a);
 	    }
 	}
     }
+#if NCURSES_XNAMES
+    /* in extended mode, verify that each extension is expected type */
+    for_each_ext_boolean(j, tp) {
+	check_user_capability_type(ExtBoolname(tp, (int) j, strnames), BOOLEAN);
+    }
+    for_each_ext_number(j, tp) {
+	check_user_capability_type(ExtNumname(tp, (int) j, strnames), NUMBER);
+    }
+    for_each_ext_string(j, tp) {
+	check_user_capability_type(ExtStrname(tp, (int) j, strnames), STRING);
+    }
+#endif /* NCURSES_XNAMES */
 
     check_acs(tp);
     check_colors(tp);
@@ -2268,6 +3237,13 @@
     check_keypad(tp);
     check_printer(tp);
     check_screen(tp);
+    check_user_6789(tp);
+
+    /*
+     * These are probably both or none.
+     */
+    PAIRED(parm_index, parm_rindex);
+    PAIRED(parm_ich, parm_dch);
 
     /*
      * These may be mismatched because the terminal description relies on
@@ -2300,10 +3276,9 @@
 	if (PRESENT(exit_attribute_mode)) {
 	    zero = strdup(CHECK_SGR(0, exit_attribute_mode));
 	} else {
-	    zero = strdup(TPARM_9(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+	    zero = strdup(TIPARM_9(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, 0));
 	}
-	if (_nc_tparm_err)
-	    _nc_warning("stack error in sgr(0) string");
+	check_tparm_err(0);
 
 	if (zero != 0) {
 	    CHECK_SGR(1, enter_standout_mode);
@@ -2324,11 +3299,11 @@
 	if (_nc_syntax == SYN_TERMINFO)
 	    _nc_warning("missing sgr string");
     }
-
+#define CHECK_SGR0(name) check_exit_attribute(#name, name, check_sgr0, exit_attribute_mode)
     if (PRESENT(exit_attribute_mode)) {
 	char *check_sgr0 = _nc_trim_sgr0(tp);
 
-	if (check_sgr0 == 0 || *check_sgr0 == '\0') {
+	if (check_sgr0 == NULL || *check_sgr0 == '\0') {
 	    _nc_warning("trimmed sgr0 is empty");
 	} else {
 	    show_where(2);
@@ -2343,10 +3318,22 @@
 		       _nc_visbuf(exit_attribute_mode)));
 	    }
 	}
+#if defined(exit_italics_mode)
+	CHECK_SGR0(exit_italics_mode);
+#endif
+	CHECK_SGR0(exit_standout_mode);
+	CHECK_SGR0(exit_underline_mode);
 	if (check_sgr0 != exit_attribute_mode) {
 	    free(check_sgr0);
 	}
     }
+#define CHECK_SGR_PARAM(code, name) check_sgr_param(tp, (int)code, #name, name)
+    for (j = 0; *sgr_names[j] != '\0'; ++j) {
+	CHECK_SGR_PARAM(j, set_a_foreground);
+	CHECK_SGR_PARAM(j, set_a_background);
+	CHECK_SGR_PARAM(j, set_foreground);
+	CHECK_SGR_PARAM(j, set_background);
+    }
 #ifdef TRACE
     show_where(2);
     if (!auto_right_margin) {
@@ -2372,7 +3359,7 @@
      * ncurses handles it.
      */
     if ((PRESENT(enter_insert_mode) || PRESENT(exit_insert_mode))
-	&& PRESENT(parm_ich)) {
+	&& PRESENT(insert_character)) {
 	_nc_warning("non-curses applications may be confused by ich1 with smir/rmir");
     }
 
diff --git a/progs/toe b/progs/toe
deleted file mode 100755
index cda6cfe..0000000
--- a/progs/toe
+++ /dev/null
Binary files differ
diff --git a/progs/toe.c b/progs/toe.c
index 0d299b4..ecbfd53 100644
--- a/progs/toe.c
+++ b/progs/toe.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc.              *
+ * Copyright 2018-2022,2023 Thomas E. Dickey                                *
+ * Copyright 1998-2013,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 <hashed_db.h>
 #endif
 
-MODULE_ID("$Id: toe.c,v 1.74 2013/12/15 01:08:28 tom Exp $")
+MODULE_ID("$Id: toe.c,v 1.89 2023/07/01 17:04:46 tom Exp $")
 
 #define isDotname(name) (!strcmp(name, ".") || !strcmp(name, ".."))
 
@@ -63,7 +64,7 @@
 
 #if NO_LEAKS
 #undef ExitProgram
-static void ExitProgram(int code) GCC_NORETURN;
+static GCC_NORETURN void ExitProgram(int code);
 static void
 ExitProgram(int code)
 {
@@ -72,7 +73,7 @@
 }
 #endif
 
-static void failed(const char *) GCC_NORETURN;
+static GCC_NORETURN void failed(const char *);
 
 static void
 failed(const char *msg)
@@ -126,12 +127,15 @@
 static void
 show_termdata(int eargc, char **eargv)
 {
-    int j, k;
-    size_t n;
-
     if (use_termdata) {
+	size_t n;
+
 	if (eargc > 1) {
+	    int j;
+
 	    for (j = 0; j < eargc; ++j) {
+		int k;
+
 		for (k = 0; k <= j; ++k) {
 		    printf("--");
 		}
@@ -142,14 +146,20 @@
 	if (use_termdata > 1)
 	    qsort(ptr_termdata, use_termdata, sizeof(TERMDATA), compare_termdata);
 	for (n = 0; n < use_termdata; ++n) {
+	    int nk = -1;
 
 	    /*
 	     * If there is more than one database, show how they differ.
 	     */
 	    if (eargc > 1) {
 		unsigned long check = 0;
-		k = 0;
+		int k = 0;
 		for (;;) {
+		    char mark = ((check == 0
+				  || (check != ptr_termdata[n].checksum))
+				 ? '*'
+				 : '+');
+
 		    for (; k < ptr_termdata[n].db_index; ++k) {
 			printf("--");
 		    }
@@ -159,11 +169,10 @@
 		     * from the first entry's checksum, print "*". Otherwise
 		     * it looks enough like a duplicate to print "+".
 		     */
-		    printf("%c-", ((check == 0
-				    || (check != ptr_termdata[n].checksum))
-				   ? '*'
-				   : '+'));
+		    printf("%c-", mark);
 		    check = ptr_termdata[n].checksum;
+		    if (mark == '*' && nk < 0)
+			nk = (int) n;
 
 		    ++k;
 		    if ((n + 1) >= use_termdata
@@ -178,10 +187,12 @@
 		}
 		printf(":\t");
 	    }
+	    if (nk < 0)
+		nk = (int) n;
 
 	    (void) printf("%-10s\t%s\n",
 			  ptr_termdata[n].term_name,
-			  ptr_termdata[n].description);
+			  ptr_termdata[nk].description);
 	}
     }
 }
@@ -241,7 +252,9 @@
 	    && !strcmp(src + size - lens, suffix)) {
 	    _nc_STRCPY(dst, src, PATH_MAX);
 	} else {
-	    _nc_SPRINTF(dst, _nc_SLIMIT(PATH_MAX) "%s%s", src, suffix);
+	    _nc_SPRINTF(dst, _nc_SLIMIT(PATH_MAX) "%.*s%s",
+			(int) (PATH_MAX - sizeof(suffix)),
+			src, suffix);
 	}
 	result = TRUE;
     }
@@ -252,10 +265,10 @@
 typedef void (DescHook) (int /* db_index */ ,
 			 int /* db_limit */ ,
 			 const char * /* term_name */ ,
-			 TERMTYPE * /* term */ );
+			 TERMTYPE2 * /* term */ );
 
 static const char *
-term_description(TERMTYPE *tp)
+term_description(TERMTYPE2 *tp)
 {
     const char *desc;
 
@@ -270,7 +283,7 @@
 
 /* display a description for the type */
 static void
-deschook(int db_index, int db_limit, const char *term_name, TERMTYPE *tp)
+deschook(int db_index, int db_limit, const char *term_name, TERMTYPE2 *tp)
 {
     (void) db_index;
     (void) db_limit;
@@ -294,7 +307,7 @@
 }
 
 static unsigned long
-checksum_of(TERMTYPE *tp)
+checksum_of(TERMTYPE2 *tp)
 {
     unsigned long result = string_sum(tp->term_names);
     unsigned i;
@@ -313,7 +326,7 @@
 
 /* collect data, to sort before display */
 static void
-sorthook(int db_index, int db_limit, const char *term_name, TERMTYPE *tp)
+sorthook(int db_index, int db_limit, const char *term_name, TERMTYPE2 *tp)
 {
     TERMDATA *data = new_termdata();
 
@@ -324,10 +337,30 @@
 }
 
 #if NCURSES_USE_TERMCAP
+/*
+ * Check if the buffer contents are printable ASCII, ensuring that we do not
+ * accidentally pick up incompatible binary content from a hashed database.
+ */
+static bool
+is_termcap(char *buffer)
+{
+    bool result = TRUE;
+    while (*buffer != '\0') {
+	int ch = UChar(*buffer++);
+	if (ch == '\t')
+	    continue;
+	if (ch < ' ' || ch > '~') {
+	    result = FALSE;
+	    break;
+	}
+    }
+    return result;
+}
+
 static void
 show_termcap(int db_index, int db_limit, char *buffer, DescHook hook)
 {
-    TERMTYPE data;
+    TERMTYPE2 data;
     char *next = strchr(buffer, ':');
     char *last;
     char *list = buffer;
@@ -424,7 +457,7 @@
 		}
 		while ((entry = readdir(entrydir)) != 0) {
 		    char *name_2;
-		    TERMTYPE lterm;
+		    TERMTYPE2 lterm;
 		    char *cn;
 		    int status;
 
@@ -440,11 +473,8 @@
 			(void) fprintf(stderr,
 				       "%s: couldn't open terminfo file %s.\n",
 				       _nc_progname, name_2);
-			free(cwd_buf);
 			free(name_2);
-			closedir(entrydir);
-			closedir(termdir);
-			return (EXIT_FAILURE);
+			continue;
 		    }
 
 		    /* only visit things once, by primary name */
@@ -453,7 +483,7 @@
 			/* apply the selected hook function */
 			hook(i, eargc, cn, &lterm);
 		    }
-		    _nc_free_termtype(&lterm);
+		    _nc_free_termtype2(&lterm);
 		    free(name_2);
 		}
 		closedir(entrydir);
@@ -478,7 +508,7 @@
 
 		    code = _nc_db_first(capdbp, &key, &data);
 		    while (code == 0) {
-			TERMTYPE lterm;
+			TERMTYPE2 lterm;
 			int used;
 			char *have;
 			char *cn;
@@ -489,7 +519,7 @@
 				cn = _nc_first_name(lterm.term_names);
 				/* apply the selected hook function */
 				hook(i, eargc, cn, &lterm);
-				_nc_free_termtype(&lterm);
+				_nc_free_termtype2(&lterm);
 			    }
 			}
 			code = _nc_db_next(capdbp, &key, &data);
@@ -500,8 +530,8 @@
 		}
 	    }
 	}
-#endif
-#endif
+#endif /* USE_HASHED_DB */
+#endif /* NCURSES_USE_DATABASE */
 #if NCURSES_USE_TERMCAP
 #if HAVE_BSD_CGETENT
 	{
@@ -515,11 +545,13 @@
 	    db_array[1] = 0;
 
 	    if (cgetfirst(&buffer, db_array) > 0) {
-		show_termcap(i, eargc, buffer, hook);
-		free(buffer);
-		while (cgetnext(&buffer, db_array) > 0) {
+		if (is_termcap(buffer)) {
 		    show_termcap(i, eargc, buffer, hook);
 		    free(buffer);
+		    while (cgetnext(&buffer, db_array) > 0) {
+			show_termcap(i, eargc, buffer, hook);
+			free(buffer);
+		    }
 		}
 		cgetclose();
 		continue;
@@ -534,11 +566,13 @@
 	    if (verbosity)
 		(void) printf("#\n#%s:\n#\n", eargv[i]);
 
-	    if ((fp = fopen(eargv[i], "r")) != 0) {
+	    if ((fp = safe_fopen(eargv[i], "r")) != 0) {
 		while (fgets(buffer, sizeof(buffer), fp) != 0) {
+		    if (!is_termcap(buffer))
+			break;
 		    if (*buffer == '#')
 			continue;
-		    if (isspace(*buffer))
+		    if (isspace(UChar(*buffer)))
 			continue;
 		    show_termcap(i, eargc, buffer, hook);
 		}
@@ -572,7 +606,6 @@
     bool invert_dependencies = FALSE;
     bool header = FALSE;
     char *report_file = 0;
-    unsigned i;
     int code;
     int this_opt, last_opt = '?';
     unsigned v_opt = 0;
@@ -625,7 +658,7 @@
 	    usage();
 	}
     }
-    set_trace_level(v_opt);
+    use_verbosity(v_opt);
 
     if (report_file != 0) {
 	if (freopen(report_file, "r", stdin) == 0) {
@@ -660,11 +693,13 @@
     /* maybe we want a reverse-dependency listing? */
     if (invert_dependencies) {
 	ENTRY *qp, *rp;
-	int matchcount;
 
 	for_entry_list(qp) {
-	    matchcount = 0;
+	    int matchcount = 0;
+
 	    for_entry_list(rp) {
+		unsigned i;
+
 		if (rp->nuses == 0)
 		    continue;
 
@@ -694,15 +729,17 @@
 	DBDIRS state;
 	int offset;
 	int pass;
-	const char *path;
 	char **eargv = 0;
 
 	code = EXIT_FAILURE;
 	for (pass = 0; pass < 2; ++pass) {
 	    size_t count = 0;
+	    const char *path;
 
 	    _nc_first_db(&state, &offset);
 	    while ((path = _nc_next_db(&state, &offset)) != 0) {
+		if (quick_prefix(path))
+		    continue;
 		if (pass) {
 		    eargv[count] = strmalloc(path);
 		}
@@ -728,7 +765,8 @@
 	    failed("eargv");
 	_nc_first_db(&state, &offset);
 	if ((path = _nc_next_db(&state, &offset)) != 0) {
-	    eargv[count++] = strmalloc(path);
+	    if (!quick_prefix(path))
+		eargv[count++] = strmalloc(path);
 	}
 
 	code = typelist((int) count, eargv, header, hook);
diff --git a/progs/tparm_type.c b/progs/tparm_type.c
index 125e43c..4fed96a 100644
--- a/progs/tparm_type.c
+++ b/progs/tparm_type.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2013,2015 Free Software Foundation, Inc.              *
+ * Copyright 2020,2023 Thomas E. Dickey                                     *
+ * Copyright 2014,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            *
@@ -32,7 +33,7 @@
 
 #include <tparm_type.h>
 
-MODULE_ID("$Id: tparm_type.c,v 1.2 2015/04/04 15:01:13 tom Exp $")
+MODULE_ID("$Id: tparm_type.c,v 1.5 2023/04/08 15:57:01 tom Exp $")
 
 /*
  * Lookup the type of call we should make to tparm().  This ignores the actual
@@ -46,6 +47,7 @@
     	{code, {longname} }, \
 	{code, {ti} }, \
 	{code, {tc} }
+#define XD(code, onlyname) TD(code, onlyname, onlyname, onlyname)
     TParams result = Numbers;
     /* *INDENT-OFF* */
     static const struct {
@@ -57,6 +59,10 @@
 	TD(Num_Str,	"pkey_xmit",	"pfx",		"px"),
 	TD(Num_Str,	"plab_norm",	"pln",		"pn"),
 	TD(Num_Str_Str, "pkey_plab",	"pfxl",		"xl"),
+#if NCURSES_XNAMES
+	XD(Str,		"Cs"),
+	XD(Str_Str,	"Ms"),
+#endif
     };
     /* *INDENT-ON* */
 
@@ -69,3 +75,35 @@
     }
     return result;
 }
+
+TParams
+guess_tparm_type(int nparam, char **p_is_s)
+{
+    TParams result = Other;
+    switch (nparam) {
+    case 0:
+    case 1:
+	if (!p_is_s[0])
+	    result = Numbers;
+	if (p_is_s[0])
+	    result = Str;
+	break;
+    case 2:
+	if (!p_is_s[0] && !p_is_s[1])
+	    result = Numbers;
+	if (!p_is_s[0] && p_is_s[1])
+	    result = Num_Str;
+	if (p_is_s[0] && p_is_s[1])
+	    result = Str_Str;
+	break;
+    case 3:
+	if (!p_is_s[0] && !p_is_s[1] && !p_is_s[2])
+	    result = Numbers;
+	if (!p_is_s[0] && p_is_s[1] && p_is_s[2])
+	    result = Num_Str_Str;
+	break;
+    default:
+	break;
+    }
+    return result;
+}
diff --git a/progs/tparm_type.h b/progs/tparm_type.h
index d143168..2f7bd07 100644
--- a/progs/tparm_type.h
+++ b/progs/tparm_type.h
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 2014 Free Software Foundation, Inc.                        *
+ * Copyright 2020,2023 Thomas E. Dickey                                     *
+ * Copyright 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            *
@@ -31,7 +32,7 @@
  ****************************************************************************/
 
 /*
- * $Id: tparm_type.h,v 1.1 2014/05/21 16:57:56 tom Exp $
+ * $Id: tparm_type.h,v 1.4 2023/04/08 15:41:20 tom Exp $
  *
  * determine expected/actual number of parameters to setup for tparm
  */
@@ -42,11 +43,15 @@
 #include <progs.priv.h>
 
 typedef enum {
-    Numbers = 0
+    Other = -1
+    ,Numbers = 0
+    ,Str
     ,Num_Str
     ,Num_Str_Str
+    ,Str_Str
 } TParams;
 
 extern TParams tparm_type(const char *name);
+extern TParams guess_tparm_type(int nparam, char **p_is_s);
 
 #endif /* TPARM_TYPE_H */
diff --git a/progs/tput b/progs/tput
deleted file mode 100755
index 6367b8a..0000000
--- a/progs/tput
+++ /dev/null
Binary files differ
diff --git a/progs/tput.c b/progs/tput.c
index f25cbaf..f9321b6 100644
--- a/progs/tput.c
+++ b/progs/tput.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            *
@@ -40,48 +41,92 @@
  */
 
 #include <tparm_type.h>
+#include <clear_cmd.h>
+#include <reset_cmd.h>
 
-#if !PURE_TERMINFO
-#include <dump_entry.h>
-#include <termsort.c>
-#endif
 #include <transform.h>
+#include <tty_settings.h>
 
-MODULE_ID("$Id: tput.c,v 1.51 2015/05/23 23:42:55 tom Exp $")
+MODULE_ID("$Id: tput.c,v 1.104 2024/04/20 22:20:51 tom Exp $")
 
 #define PUTS(s)		fputs(s, stdout)
-#define PUTCHAR(c)	putchar(c)
-#define FLUSH		fflush(stdout)
 
-static char *prg_name;
+const char *_nc_progname = "tput";
+
+static bool opt_v = FALSE;	/* quiet, do not show warnings */
+static bool opt_x = FALSE;	/* clear scrollback if possible */
+
 static bool is_init = FALSE;
 static bool is_reset = FALSE;
+static bool is_clear = FALSE;
 
-static void
-quit(int status, const char *fmt,...)
+static GCC_NORETURN void
+quit(int status, const char *fmt, ...)
 {
     va_list argp;
 
     va_start(argp, fmt);
-    fprintf(stderr, "%s: ", prg_name);
+    fprintf(stderr, "%s: ", _nc_progname);
     vfprintf(stderr, fmt, argp);
     fprintf(stderr, "\n");
     va_end(argp);
     ExitProgram(status);
 }
 
-static void
-usage(void)
+static GCC_NORETURN void
+usage(const char *optstring)
 {
-    fprintf(stderr, "usage: %s [-V] [-S] [-T term] capname\n", prg_name);
-    ExitProgram(EXIT_FAILURE);
+#define KEEP(s) s "\n"
+    static const char msg[] =
+    {
+	KEEP("")
+	KEEP("Options:")
+	KEEP("  -S <<       read commands from standard input")
+	KEEP("  -T TERM     use this instead of $TERM")
+	KEEP("  -V          print curses-version")
+	KEEP("  -v          verbose, show warnings")
+	KEEP("  -x          do not try to clear scrollback")
+	KEEP("")
+	KEEP("Commands:")
+	KEEP("  clear       clear the screen")
+	KEEP("  init        initialize the terminal")
+	KEEP("  reset       reinitialize the terminal")
+	KEEP("  capname     unlike clear/init/reset, print value for capability \"capname\"")
+    };
+#undef KEEP
+    (void) fprintf(stderr, "Usage: %s [options] [command]\n", _nc_progname);
+    if (optstring != NULL) {
+	const char *s = msg;
+	while (*s != '\0') {
+	    fputc(UChar(*s), stderr);
+	    if (!strncmp(s, "  -", 3)) {
+		if (strchr(optstring, s[3]) == NULL)
+		    s = strchr(s, '\n') + 1;
+	    } else if (!strncmp(s, "\n\nC", 3))
+		break;
+	    ++s;
+	}
+    } else {
+	fputs(msg, stderr);
+    }
+    ExitProgram(ErrUsage);
 }
 
-static void
-check_aliases(const char *name)
+static char *
+check_aliases(char *name, bool program)
 {
-    is_init = same_program(name, PROG_INIT);
-    is_reset = same_program(name, PROG_RESET);
+    static char my_init[] = "init";
+    static char my_reset[] = "reset";
+    static char my_clear[] = "clear";
+
+    char *result = name;
+    if ((is_init = same_program(name, program ? PROG_INIT : my_init)))
+	result = my_init;
+    if ((is_reset = same_program(name, program ? PROG_RESET : my_reset)))
+	result = my_reset;
+    if ((is_clear = same_program(name, program ? PROG_CLEAR : my_clear)))
+	result = my_clear;
+    return result;
 }
 
 static int
@@ -103,121 +148,54 @@
     return result;
 }
 
+/*
+ * Returns nonzero on error.
+ */
 static int
-tput(int argc, char *argv[])
+tput_cmd(int fd, TTY * settings, int argc, char **argv, int *used)
 {
     NCURSES_CONST char *name;
     char *s;
-    int i, j, c;
     int status;
-    FILE *f;
 #if !PURE_TERMINFO
     bool termcap = FALSE;
 #endif
 
-    if ((name = argv[0]) == 0)
-	name = "";
-    check_aliases(name);
+    name = check_aliases(argv[0], FALSE);
+    *used = 1;
     if (is_reset || is_init) {
-	if (init_prog != 0) {
-	    IGNORE_RC(system(init_prog));
-	}
-	FLUSH;
+	TTY oldmode = *settings;
 
-	if (is_reset && reset_1string != 0) {
-	    PUTS(reset_1string);
-	} else if (init_1string != 0) {
-	    PUTS(init_1string);
-	}
-	FLUSH;
+	int terasechar = -1;	/* new erase character */
+	int intrchar = -1;	/* new interrupt character */
+	int tkillchar = -1;	/* new kill character */
 
-	if (is_reset && reset_2string != 0) {
-	    PUTS(reset_2string);
-	} else if (init_2string != 0) {
-	    PUTS(init_2string);
+	if (is_reset) {
+	    reset_start(stdout, TRUE, FALSE);
+	    reset_tty_settings(fd, settings, FALSE);
+	} else {
+	    reset_start(stdout, FALSE, TRUE);
 	}
-	FLUSH;
 
-#ifdef set_lr_margin
-	if (set_lr_margin != 0) {
-	    PUTS(TPARM_2(set_lr_margin, 0, columns - 1));
-	} else
+#if HAVE_SIZECHANGE
+	{
+	    NCURSES_INT2 my_rows = lines;
+	    NCURSES_INT2 my_cols = columns;
+	    set_window_size(fd, &my_rows, &my_cols);
+	    lines = my_rows;
+	    columns = my_cols;
+	}
+#else
+	(void) fd;
 #endif
-#ifdef set_left_margin_parm
-	    if (set_left_margin_parm != 0
-		&& set_right_margin_parm != 0) {
-	    PUTS(TPARM_1(set_left_margin_parm, 0));
-	    PUTS(TPARM_1(set_right_margin_parm, columns - 1));
-	} else
-#endif
-	    if (clear_margins != 0
-		&& set_left_margin != 0
-		&& set_right_margin != 0) {
-	    PUTS(clear_margins);
-	    if (carriage_return != 0) {
-		PUTS(carriage_return);
-	    } else {
-		PUTCHAR('\r');
-	    }
-	    PUTS(set_left_margin);
-	    if (parm_right_cursor) {
-		PUTS(TPARM_1(parm_right_cursor, columns - 1));
-	    } else {
-		for (i = 0; i < columns - 1; i++) {
-		    PUTCHAR(' ');
-		}
-	    }
-	    PUTS(set_right_margin);
-	    if (carriage_return != 0) {
-		PUTS(carriage_return);
-	    } else {
-		PUTCHAR('\r');
-	    }
-	}
-	FLUSH;
+	set_control_chars(settings, terasechar, intrchar, tkillchar);
+	set_conversions(settings);
 
-	if (init_tabs != 8) {
-	    if (clear_all_tabs != 0 && set_tab != 0) {
-		for (i = 0; i < columns - 1; i += 8) {
-		    if (parm_right_cursor) {
-			PUTS(TPARM_1(parm_right_cursor, 8));
-		    } else {
-			for (j = 0; j < 8; j++)
-			    PUTCHAR(' ');
-		    }
-		    PUTS(set_tab);
-		}
-		FLUSH;
-	    }
+	if (send_init_strings(fd, &oldmode)) {
+	    reset_flush();
 	}
 
-	if (is_reset && reset_file != 0) {
-	    f = fopen(reset_file, "r");
-	    if (f == 0) {
-		quit(4 + errno, "Can't open reset_file: '%s'", reset_file);
-	    }
-	    while ((c = fgetc(f)) != EOF) {
-		PUTCHAR(c);
-	    }
-	    fclose(f);
-	} else if (init_file != 0) {
-	    f = fopen(init_file, "r");
-	    if (f == 0) {
-		quit(4 + errno, "Can't open init_file: '%s'", init_file);
-	    }
-	    while ((c = fgetc(f)) != EOF) {
-		PUTCHAR(c);
-	    }
-	    fclose(f);
-	}
-	FLUSH;
-
-	if (is_reset && reset_3string != 0) {
-	    PUTS(reset_3string);
-	} else if (init_3string != 0) {
-	    PUTS(init_3string);
-	}
-	FLUSH;
+	update_tty_settings(&oldmode, settings);
 	return 0;
     }
 
@@ -228,7 +206,9 @@
 #if !PURE_TERMINFO
   retry:
 #endif
-    if ((status = tigetflag(name)) != -1) {
+    if (strcmp(name, "clear") == 0) {
+	return (clear_cmd(opt_x) == ERR) ? ErrUsage : 0;
+    } else if ((status = tigetflag(name)) != -1) {
 	return exit_code(BOOLEAN, status);
     } else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) {
 	(void) printf("%d\n", status);
@@ -242,39 +222,40 @@
 	    if ((np = _nc_find_entry(name, _nc_get_hash_table(termcap))) != 0) {
 		switch (np->nte_type) {
 		case BOOLEAN:
-		    if (bool_from_termcap[np->nte_index])
-			name = boolnames[np->nte_index];
+		    name = boolnames[np->nte_index];
 		    break;
 
 		case NUMBER:
-		    if (num_from_termcap[np->nte_index])
-			name = numnames[np->nte_index];
+		    name = numnames[np->nte_index];
 		    break;
 
 		case STRING:
-		    if (str_from_termcap[np->nte_index])
-			name = strnames[np->nte_index];
+		    name = strnames[np->nte_index];
 		    break;
 		}
 		goto retry;
 	    }
 	}
 #endif
-	quit(4, "unknown terminfo capability '%s'", name);
-    } else if (s != ABSENT_STRING) {
+	quit(ErrCapName, "unknown terminfo capability '%s'", name);
+    } else if (VALID_STRING(s)) {
 	if (argc > 1) {
 	    int k;
-	    int ignored;
+	    int narg;
+	    int analyzed;
+	    int provided;
+	    int popcount;
 	    long numbers[1 + NUM_PARM];
 	    char *strings[1 + NUM_PARM];
 	    char *p_is_s[NUM_PARM];
+	    TParams paramType;
 
 	    /* Nasty hack time. The tparm function needs to see numeric
 	     * parameters as numbers, not as pointers to their string
 	     * representations
 	     */
 
-	    for (k = 1; k < argc; k++) {
+	    for (k = 1; (k < argc) && (k <= NUM_PARM); k++) {
 		char *tmp = 0;
 		strings[k] = argv[k];
 		numbers[k] = strtol(argv[k], &tmp, 0);
@@ -286,16 +267,81 @@
 		strings[k] = 0;
 	    }
 
-	    switch (tparm_type(name)) {
+	    paramType = tparm_type(name);
+#if NCURSES_XNAMES
+	    /*
+	     * If the capability is an extended one, analyze the string.
+	     */
+	    if (paramType == Numbers) {
+		struct name_table_entry const *entry_ptr;
+		entry_ptr = _nc_find_type_entry(name, STRING, FALSE);
+		if (entry_ptr == NULL) {
+		    paramType = Other;
+		}
+	    }
+#endif
+
+	    popcount = 0;
+	    _nc_reset_tparm(NULL);
+	    /*
+	     * Count the number of numeric parameters which are provided.
+	     */
+	    provided = 0;
+	    for (narg = 1; narg < argc; ++narg) {
+		char *ending = NULL;
+		long check = strtol(argv[narg], &ending, 0);
+		if (check < 0 || ending == argv[narg] || *ending != '\0')
+		    break;
+		provided = narg;
+	    }
+	    switch (paramType) {
+	    case Str:
+		s = TPARM_1(s, strings[1]);
+		analyzed = 1;
+		if (provided == 0 && argc >= 1)
+		    provided++;
+		break;
+	    case Str_Str:
+		s = TPARM_2(s, strings[1], strings[2]);
+		analyzed = 2;
+		if (provided == 0 && argc >= 1)
+		    provided++;
+		if (provided == 1 && argc >= 2)
+		    provided++;
+		break;
 	    case Num_Str:
 		s = TPARM_2(s, numbers[1], strings[2]);
+		analyzed = 2;
+		if (provided == 1 && argc >= 2)
+		    provided++;
 		break;
 	    case Num_Str_Str:
 		s = TPARM_3(s, numbers[1], strings[2], strings[3]);
+		analyzed = 3;
+		if (provided == 1 && argc >= 2)
+		    provided++;
+		if (provided == 2 && argc >= 3)
+		    provided++;
 		break;
 	    case Numbers:
+		analyzed = _nc_tparm_analyze(NULL, s, p_is_s, &popcount);
+#define myParam(n) numbers[n]
+		s = TIPARM_9(s,
+			     myParam(1),
+			     myParam(2),
+			     myParam(3),
+			     myParam(4),
+			     myParam(5),
+			     myParam(6),
+			     myParam(7),
+			     myParam(8),
+			     myParam(9));
+#undef myParam
+		break;
+	    case Other:
+		/* FALLTHRU */
 	    default:
-		(void) _nc_tparm_analyze(s, p_is_s, &ignored);
+		analyzed = _nc_tparm_analyze(NULL, s, p_is_s, &popcount);
 #define myParam(n) (p_is_s[n - 1] != 0 ? ((TPARM_ARG) strings[n]) : numbers[n])
 		s = TPARM_9(s,
 			    myParam(1),
@@ -307,8 +353,19 @@
 			    myParam(7),
 			    myParam(8),
 			    myParam(9));
+#undef myParam
 		break;
 	    }
+	    if (analyzed < popcount) {
+		analyzed = popcount;
+	    }
+	    if (opt_v && (analyzed != provided)) {
+		fprintf(stderr, "%s: %s parameters for \"%s\"\n",
+			_nc_progname,
+			(analyzed < provided ? "extra" : "missing"),
+			argv[0]);
+	    }
+	    *used += provided;
 	}
 
 	/* use putp() in order to perform padding */
@@ -327,78 +384,122 @@
     int c;
     char buf[BUFSIZ];
     int result = 0;
+    int fd;
+    int used;
+    TTY old_settings;
+    TTY tty_settings;
+    bool is_alias;
+    bool need_tty;
 
-    check_aliases(prg_name = _nc_rootname(argv[0]));
+    _nc_progname = check_aliases(_nc_rootname(argv[0]), TRUE);
+    is_alias = (is_clear || is_reset || is_init);
 
     term = getenv("TERM");
 
-    while ((c = getopt(argc, argv, "ST:V")) != -1) {
+    while ((c = getopt(argc, argv, is_alias ? "T:Vvx" : "ST:Vvx")) != -1) {
 	switch (c) {
 	case 'S':
 	    cmdline = FALSE;
 	    break;
 	case 'T':
 	    use_env(FALSE);
+	    use_tioctl(TRUE);
 	    term = optarg;
 	    break;
 	case 'V':
 	    puts(curses_version());
 	    ExitProgram(EXIT_SUCCESS);
+	case 'v':		/* verbose */
+	    opt_v = TRUE;
+	    break;
+	case 'x':		/* do not try to clear scrollback */
+	    opt_x = TRUE;
+	    break;
 	default:
-	    usage();
+	    usage(is_alias ? "TVx" : NULL);
 	    /* NOTREACHED */
 	}
     }
 
+    need_tty = ((is_reset || is_init) ||
+		(optind < argc &&
+		 (!strcmp(argv[optind], "reset") ||
+		  !strcmp(argv[optind], "init"))));
+
     /*
      * Modify the argument list to omit the options we processed.
      */
-    if (is_reset || is_init) {
+    if (is_alias) {
 	if (optind-- < argc) {
 	    argc -= optind;
 	    argv += optind;
 	}
-	argv[0] = prg_name;
+	argv[0] = strdup(_nc_progname);
     } else {
 	argc -= optind;
 	argv += optind;
     }
 
     if (term == 0 || *term == '\0')
-	quit(2, "No value for $TERM and no -T specified");
+	quit(ErrUsage, "No value for $TERM and no -T specified");
 
-    if (setupterm(term, STDOUT_FILENO, &errret) != OK && errret <= 0)
-	quit(3, "unknown terminal \"%s\"", term);
+    fd = save_tty_settings(&tty_settings, need_tty);
+    old_settings = tty_settings;
+
+    if (setupterm(term, fd, &errret) != OK && errret <= 0)
+	quit(ErrTermType, "unknown terminal \"%s\"", term);
 
     if (cmdline) {
-	if ((argc <= 0) && !is_reset && !is_init)
-	    usage();
-	ExitProgram(tput(argc, argv));
+	int code = 0;
+	if ((argc <= 0) && !is_alias)
+	    usage(NULL);
+	while (argc > 0) {
+	    tty_settings = old_settings;
+	    code = tput_cmd(fd, &tty_settings, argc, argv, &used);
+	    if (code != 0)
+		break;
+	    argc -= used;
+	    argv += used;
+	}
+	ExitProgram(code);
     }
 
     while (fgets(buf, sizeof(buf), stdin) != 0) {
-	char *argvec[16];	/* command, 9 parms, null, & slop */
+	size_t need = strlen(buf);
+	char **argvec = typeCalloc(char *, need + 1);
+	char **argnow;
 	int argnum = 0;
 	char *cp;
 
-	/* crack the argument list into a dope vector */
+	if (argvec == NULL) {
+	    quit(ErrSystem(1), strerror(errno));
+	}
+
+	/* split the buffer into tokens */
 	for (cp = buf; *cp; cp++) {
 	    if (isspace(UChar(*cp))) {
 		*cp = '\0';
-	    } else if (cp == buf || cp[-1] == 0) {
+	    } else if (cp == buf || cp[-1] == '\0') {
 		argvec[argnum++] = cp;
-		if (argnum >= (int) SIZEOF(argvec) - 1)
+		if (argnum >= (int) need)
 		    break;
 	    }
 	}
-	argvec[argnum] = 0;
 
-	if (argnum != 0
-	    && tput(argnum, argvec) != 0) {
-	    if (result == 0)
-		result = 4;	/* will return value >4 */
-	    ++result;
+	argnow = argvec;
+	while (argnum > 0) {
+	    int code;
+	    tty_settings = old_settings;
+	    code = tput_cmd(fd, &tty_settings, argnum, argnow, &used);
+	    if (code != 0) {
+		if (result == 0)
+		    result = ErrSystem(0);	/* will return value >4 */
+		++result;
+	    }
+	    argnum -= used;
+	    argnow += used;
 	}
+	free(argvec);
     }
 
     ExitProgram(result);
diff --git a/progs/transform.c b/progs/transform.c
index c0557f0..67caf2d 100644
--- a/progs/transform.c
+++ b/progs/transform.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 2009-2010,2011 Free Software Foundation, Inc.              *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 2009-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            *
@@ -34,7 +35,7 @@
 
 #include <transform.h>
 
-MODULE_ID("$Id: transform.c,v 1.3 2011/05/14 22:41:17 tom Exp $")
+MODULE_ID("$Id: transform.c,v 1.4 2020/02/02 23:34:34 tom Exp $")
 
 #ifdef SUFFIX_IGNORED
 static void
diff --git a/progs/transform.h b/progs/transform.h
deleted file mode 100644
index 708938f..0000000
--- a/progs/transform.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __TRANSFORM_H
-#define __TRANSFORM_H 1
-#include <progs.priv.h>
-extern bool same_program(const char *, const char *);
-#define PROG_CAPTOINFO "captoinfo"
-#define PROG_INFOTOCAP "infotocap"
-#define PROG_RESET     "reset"
-#define PROG_INIT      "init"
-#endif /* __TRANSFORM_H */
diff --git a/progs/tset b/progs/tset
deleted file mode 100755
index 1e1473c..0000000
--- a/progs/tset
+++ /dev/null
Binary files differ
diff --git a/progs/tset.c b/progs/tset.c
index 9a05b3d..69f4aba 100644
--- a/progs/tset.c
+++ b/progs/tset.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2013,2015 Free Software Foundation, Inc.              *
+ * Copyright 2020-2021,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            *
@@ -85,92 +86,30 @@
  * SUCH DAMAGE.
  */
 
-#define USE_LIBTINFO
-#define __INTERNAL_CAPS_VISIBLE	/* we need to see has_hardware_tabs */
-#include <progs.priv.h>
-
-#include <errno.h>
-#include <stdio.h>
+#include <reset_cmd.h>
 #include <termcap.h>
-#include <fcntl.h>
+#include <transform.h>
+#include <tty_settings.h>
 
-#if HAVE_GETTTYNAM && HAVE_TTYENT_H
+#if HAVE_GETTTYNAM
 #include <ttyent.h>
 #endif
 #ifdef NeXT
 char *ttyname(int fd);
 #endif
 
-#if HAVE_SIZECHANGE
-# if !defined(sun) || !TERMIOS
-#  if HAVE_SYS_IOCTL_H
-#   include <sys/ioctl.h>
-#  endif
-# endif
-#endif
-
-#if NEED_PTEM_H
-/* they neglected to define struct winsize in termios.h -- it's only
-   in termio.h	*/
-#include <sys/stream.h>
-#include <sys/ptem.h>
-#endif
-
-#include <dump_entry.h>
-#include <transform.h>
-
-MODULE_ID("$Id: tset.c,v 1.96 2015/04/12 15:36:06 tom Exp $")
-
-/*
- * SCO defines TIOCGSIZE and the corresponding struct.  Other systems (SunOS,
- * Solaris, IRIX) define TIOCGWINSZ and struct winsize.
- */
-#ifdef TIOCGSIZE
-# define IOCTL_GET_WINSIZE TIOCGSIZE
-# define IOCTL_SET_WINSIZE TIOCSSIZE
-# define STRUCT_WINSIZE struct ttysize
-# define WINSIZE_ROWS(n) n.ts_lines
-# define WINSIZE_COLS(n) n.ts_cols
-#else
-# ifdef TIOCGWINSZ
-#  define IOCTL_GET_WINSIZE TIOCGWINSZ
-#  define IOCTL_SET_WINSIZE TIOCSWINSZ
-#  define STRUCT_WINSIZE struct winsize
-#  define WINSIZE_ROWS(n) n.ws_row
-#  define WINSIZE_COLS(n) n.ws_col
-# endif
-#endif
+MODULE_ID("$Id: tset.c,v 1.135 2024/04/20 22:20:41 tom Exp $")
 
 #ifndef environ
 extern char **environ;
 #endif
 
-#undef CTRL
-#define CTRL(x)	((x) & 0x1f)
-
-static void failed(const char *) GCC_NORETURN;
-static void exit_error(void) GCC_NORETURN;
-static void err(const char *,...) GCC_NORETURN;
-
 const char *_nc_progname = "tset";
 
-static TTY mode, oldmode, original;
-
-static bool opt_c;		/* set control-chars */
-static bool opt_w;		/* set window-size */
-
-static bool can_restore = FALSE;
-static bool isreset = FALSE;	/* invoked as reset */
-static int terasechar = -1;	/* new erase character */
-static int intrchar = -1;	/* new interrupt character */
-static int tkillchar = -1;	/* new kill character */
-
-#if HAVE_SIZECHANGE
-static int tlines, tcolumns;	/* window size */
-#endif
-
 #define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c))
 
+static GCC_NORETURN void exit_error(void);
+
 static int
 CaselessCmp(const char *a, const char *b)
 {				/* strcasecmp isn't portable */
@@ -183,19 +122,18 @@
     return LOWERCASE(*a) - LOWERCASE(*b);
 }
 
-static void
+static GCC_NORETURN void
 exit_error(void)
 {
-    if (can_restore)
-	SET_TTY(STDERR_FILENO, &original);
+    restore_tty_settings();
     (void) fprintf(stderr, "\n");
     fflush(stderr);
     ExitProgram(EXIT_FAILURE);
     /* NOTREACHED */
 }
 
-static void
-err(const char *fmt,...)
+static GCC_NORETURN void
+err(const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
@@ -206,7 +144,7 @@
     /* NOTREACHED */
 }
 
-static void
+static GCC_NORETURN void
 failed(const char *msg)
 {
     char temp[BUFSIZ];
@@ -218,39 +156,17 @@
     } else {
 	_nc_STRCPY(temp, "tset: ", sizeof(temp));
     }
-    perror(strncat(temp, msg, sizeof(temp) - strlen(temp) - 2));
+    _nc_STRNCAT(temp, msg, sizeof(temp), sizeof(temp) - strlen(temp) - 2);
+    perror(temp);
     exit_error();
     /* NOTREACHED */
 }
 
-static void
-cat(char *file)
-{
-    FILE *fp;
-    size_t nr;
-    char buf[BUFSIZ];
-
-    if ((fp = fopen(file, "r")) == 0)
-	failed(file);
-
-    while ((nr = fread(buf, sizeof(char), sizeof(buf), fp)) != 0)
-	if (fwrite(buf, sizeof(char), nr, stderr) != nr)
-	      failed("write to stderr");
-    fclose(fp);
-}
-
-static int
-outc(int c)
-{
-    return putc(c, stderr);
-}
-
 /* Prompt the user for a terminal type. */
 static const char *
 askuser(const char *dflt)
 {
     static char answer[256];
-    char *p;
 
     /* We can get recalled; if so, don't continue uselessly. */
     clearerr(stdin);
@@ -259,7 +175,10 @@
 	exit_error();
 	/* NOTREACHED */
     }
+
     for (;;) {
+	char *p;
+
 	if (dflt)
 	    (void) fprintf(stderr, "Terminal type? [%s] ", dflt);
 	else
@@ -310,10 +229,16 @@
 #define DATA(name,value) { { name }, value }
 
 typedef struct speeds {
-    const char string[7];
+    const char string[8];
     int speed;
 } SPEEDS;
 
+#if defined(EXP_WIN32_DRIVER)
+static const SPEEDS speeds[] =
+{
+    {"0", 0}
+};
+#else
 static const SPEEDS speeds[] =
 {
     DATA("0", B0),
@@ -361,17 +286,60 @@
 #ifdef B57600
     DATA("57600", B57600),
 #endif
+#ifdef B76800
+    DATA("76800", B57600),
+#endif
 #ifdef B115200
     DATA("115200", B115200),
 #endif
+#ifdef B153600
+    DATA("153600", B153600),
+#endif
 #ifdef B230400
     DATA("230400", B230400),
 #endif
+#ifdef B307200
+    DATA("307200", B307200),
+#endif
 #ifdef B460800
     DATA("460800", B460800),
 #endif
+#ifdef B500000
+    DATA("500000", B500000),
+#endif
+#ifdef B576000
+    DATA("576000", B576000),
+#endif
+#ifdef B921600
+    DATA("921600", B921600),
+#endif
+#ifdef B1000000
+    DATA("1000000", B1000000),
+#endif
+#ifdef B1152000
+    DATA("1152000", B1152000),
+#endif
+#ifdef B1500000
+    DATA("1500000", B1500000),
+#endif
+#ifdef B2000000
+    DATA("2000000", B2000000),
+#endif
+#ifdef B2500000
+    DATA("2500000", B2500000),
+#endif
+#ifdef B3000000
+    DATA("3000000", B3000000),
+#endif
+#ifdef B3500000
+    DATA("3500000", B3500000),
+#endif
+#ifdef B4000000
+    DATA("4000000", B4000000),
+#endif
 };
 #undef DATA
+#endif
 
 static int
 tbaudrate(char *rate)
@@ -384,6 +352,10 @@
 	++rate;
 
     for (n = 0; n < SIZEOF(speeds); ++n) {
+	if (n > 0 && (speeds[n].speed <= speeds[n - 1].speed)) {
+	    /* if the speeds are not increasing, likely a numeric overflow */
+	    break;
+	}
 	if (!CaselessCmp(rate, speeds[n].string)) {
 	    sp = speeds + n;
 	    break;
@@ -568,17 +540,21 @@
  * its termcap entry.
  */
 static const char *
-get_termcap_entry(char *userarg)
+get_termcap_entry(int fd, char *userarg)
 {
     int errret;
     char *p;
     const char *ttype;
+#if HAVE_PATH_TTYS
 #if HAVE_GETTTYNAM
     struct ttyent *t;
 #else
     FILE *fp;
 #endif
     char *ttypath;
+#endif /* HAVE_PATH_TTYS */
+
+    (void) fd;
 
     if (userarg) {
 	ttype = userarg;
@@ -589,7 +565,8 @@
     if ((ttype = getenv("TERM")) != 0)
 	goto map;
 
-    if ((ttypath = ttyname(STDERR_FILENO)) != 0) {
+#if HAVE_PATH_TTYS
+    if ((ttypath = ttyname(fd)) != 0) {
 	p = _nc_basename(ttypath);
 #if HAVE_GETTTYNAM
 	/*
@@ -626,6 +603,7 @@
 	}
 #endif /* HAVE_GETTTYNAM */
     }
+#endif /* HAVE_PATH_TTYS */
 
     /* If still undefined, use "unknown". */
     ttype = "unknown";
@@ -664,7 +642,7 @@
 	    ttype = askuser(0);
     }
     /* Find the terminfo entry.  If it doesn't exist, ask the user. */
-    while (setupterm((NCURSES_CONST char *) ttype, STDOUT_FILENO, &errret)
+    while (setupterm((NCURSES_CONST char *) ttype, fd, &errret)
 	   != OK) {
 	if (errret == 0) {
 	    (void) fprintf(stderr, "%s: unknown terminal type %s\n",
@@ -686,453 +664,11 @@
 
 /**************************************************************************
  *
- * Mode-setting logic
- *
- **************************************************************************/
-
-/* some BSD systems have these built in, some systems are missing
- * one or more definitions. The safest solution is to override unless the
- * commonly-altered ones are defined.
- */
-#if !(defined(CERASE) && defined(CINTR) && defined(CKILL) && defined(CQUIT))
-#undef CEOF
-#undef CERASE
-#undef CINTR
-#undef CKILL
-#undef CLNEXT
-#undef CRPRNT
-#undef CQUIT
-#undef CSTART
-#undef CSTOP
-#undef CSUSP
-#endif
-
-/* control-character defaults */
-#ifndef CEOF
-#define CEOF	CTRL('D')
-#endif
-#ifndef CERASE
-#define CERASE	CTRL('H')
-#endif
-#ifndef CINTR
-#define CINTR	127		/* ^? */
-#endif
-#ifndef CKILL
-#define CKILL	CTRL('U')
-#endif
-#ifndef CLNEXT
-#define CLNEXT  CTRL('v')
-#endif
-#ifndef CRPRNT
-#define CRPRNT  CTRL('r')
-#endif
-#ifndef CQUIT
-#define CQUIT	CTRL('\\')
-#endif
-#ifndef CSTART
-#define CSTART	CTRL('Q')
-#endif
-#ifndef CSTOP
-#define CSTOP	CTRL('S')
-#endif
-#ifndef CSUSP
-#define CSUSP	CTRL('Z')
-#endif
-
-#if defined(_POSIX_VDISABLE)
-#define DISABLED(val)   (((_POSIX_VDISABLE != -1) \
-		       && ((val) == _POSIX_VDISABLE)) \
-		      || ((val) <= 0))
-#else
-#define DISABLED(val)   ((int)(val) <= 0)
-#endif
-
-#define CHK(val, dft)   (unsigned char) (DISABLED(val) ? dft : val)
-
-static bool set_tabs(void);
-
-/*
- * Reset the terminal mode bits to a sensible state.  Very useful after
- * a child program dies in raw mode.
- */
-static void
-reset_mode(void)
-{
-#ifdef TERMIOS
-    tcgetattr(STDERR_FILENO, &mode);
-#else
-    stty(STDERR_FILENO, &mode);
-#endif
-
-#ifdef TERMIOS
-#if defined(VDISCARD) && defined(CDISCARD)
-    mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD);
-#endif
-    mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF);
-    mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE);
-#if defined(VFLUSH) && defined(CFLUSH)
-    mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH);
-#endif
-    mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR);
-    mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL);
-#if defined(VLNEXT) && defined(CLNEXT)
-    mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT);
-#endif
-    mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT);
-#if defined(VREPRINT) && defined(CRPRNT)
-    mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT);
-#endif
-#if defined(VSTART) && defined(CSTART)
-    mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART);
-#endif
-#if defined(VSTOP) && defined(CSTOP)
-    mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP);
-#endif
-#if defined(VSUSP) && defined(CSUSP)
-    mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP);
-#endif
-#if defined(VWERASE) && defined(CWERASE)
-    mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
-#endif
-
-    mode.c_iflag &= ~((unsigned) (IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
-#ifdef IUCLC
-				  | IUCLC
-#endif
-#ifdef IXANY
-				  | IXANY
-#endif
-				  | IXOFF));
-
-    mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
-#ifdef IMAXBEL
-		     | IMAXBEL
-#endif
-	);
-
-    mode.c_oflag &= ~((unsigned) (0
-#ifdef OLCUC
-				  | OLCUC
-#endif
-#ifdef OCRNL
-				  | OCRNL
-#endif
-#ifdef ONOCR
-				  | ONOCR
-#endif
-#ifdef ONLRET
-				  | ONLRET
-#endif
-#ifdef OFILL
-				  | OFILL
-#endif
-#ifdef OFDEL
-				  | OFDEL
-#endif
-#ifdef NLDLY
-				  | NLDLY
-#endif
-#ifdef CRDLY
-				  | CRDLY
-#endif
-#ifdef TABDLY
-				  | TABDLY
-#endif
-#ifdef BSDLY
-				  | BSDLY
-#endif
-#ifdef VTDLY
-				  | VTDLY
-#endif
-#ifdef FFDLY
-				  | FFDLY
-#endif
-		      ));
-
-    mode.c_oflag |= (OPOST
-#ifdef ONLCR
-		     | ONLCR
-#endif
-	);
-
-    mode.c_cflag &= ~((unsigned) (CSIZE | CSTOPB | PARENB | PARODD | CLOCAL));
-    mode.c_cflag |= (CS8 | CREAD);
-    mode.c_lflag &= ~((unsigned) (ECHONL | NOFLSH
-#ifdef TOSTOP
-				  | TOSTOP
-#endif
-#ifdef ECHOPTR
-				  | ECHOPRT
-#endif
-#ifdef XCASE
-				  | XCASE
-#endif
-		      ));
-
-    mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
-#ifdef ECHOCTL
-		     | ECHOCTL
-#endif
-#ifdef ECHOKE
-		     | ECHOKE
-#endif
-	);
-#endif
-
-    SET_TTY(STDERR_FILENO, &mode);
-}
-
-/*
- * Returns a "good" value for the erase character.  This is loosely based on
- * the BSD4.4 logic.
- */
-#ifdef TERMIOS
-static int
-default_erase(void)
-{
-    int result;
-
-    if (over_strike
-	&& key_backspace != 0
-	&& strlen(key_backspace) == 1)
-	result = key_backspace[0];
-    else
-	result = CERASE;
-
-    return result;
-}
-#endif
-
-/*
- * Update the values of the erase, interrupt, and kill characters in 'mode'.
- *
- * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase
- * characters if they're unset, or if we specify them as options.  This differs
- * from BSD 4.4 tset, which always sets erase.
- */
-static void
-set_control_chars(void)
-{
-#ifdef TERMIOS
-    if (DISABLED(mode.c_cc[VERASE]) || terasechar >= 0) {
-	mode.c_cc[VERASE] = UChar((terasechar >= 0)
-				  ? terasechar
-				  : default_erase());
-    }
-
-    if (DISABLED(mode.c_cc[VINTR]) || intrchar >= 0) {
-	mode.c_cc[VINTR] = UChar((intrchar >= 0)
-				 ? intrchar
-				 : CINTR);
-    }
-
-    if (DISABLED(mode.c_cc[VKILL]) || tkillchar >= 0) {
-	mode.c_cc[VKILL] = UChar((tkillchar >= 0)
-				 ? tkillchar
-				 : CKILL);
-    }
-#endif
-}
-
-/*
- * Set up various conversions in 'mode', including parity, tabs, returns,
- * echo, and case, according to the termcap entry.  If the program we're
- * running was named with a leading upper-case character, map external
- * uppercase to internal lowercase.
- */
-static void
-set_conversions(void)
-{
-#ifdef __OBSOLETE__
-    /*
-     * Conversion logic for some *really* ancient terminal glitches,
-     * not supported in terminfo.  Left here for succeeding generations
-     * to marvel at.
-     */
-    if (tgetflag("UC")) {
-#ifdef IUCLC
-	mode.c_iflag |= IUCLC;
-	mode.c_oflag |= OLCUC;
-#endif
-    } else if (tgetflag("LC")) {
-#ifdef IUCLC
-	mode.c_iflag &= ~IUCLC;
-	mode.c_oflag &= ~OLCUC;
-#endif
-    }
-    mode.c_iflag &= ~(PARMRK | INPCK);
-    mode.c_lflag |= ICANON;
-    if (tgetflag("EP")) {
-	mode.c_cflag |= PARENB;
-	mode.c_cflag &= ~PARODD;
-    }
-    if (tgetflag("OP")) {
-	mode.c_cflag |= PARENB;
-	mode.c_cflag |= PARODD;
-    }
-#endif /* __OBSOLETE__ */
-
-#ifdef TERMIOS
-#ifdef ONLCR
-    mode.c_oflag |= ONLCR;
-#endif
-    mode.c_iflag |= ICRNL;
-    mode.c_lflag |= ECHO;
-#ifdef OXTABS
-    mode.c_oflag |= OXTABS;
-#endif /* OXTABS */
-
-    /* test used to be tgetflag("NL") */
-    if (newline != (char *) 0 && newline[0] == '\n' && !newline[1]) {
-	/* Newline, not linefeed. */
-#ifdef ONLCR
-	mode.c_oflag &= ~((unsigned) ONLCR);
-#endif
-	mode.c_iflag &= ~((unsigned) ICRNL);
-    }
-#ifdef __OBSOLETE__
-    if (tgetflag("HD"))		/* Half duplex. */
-	mode.c_lflag &= ~ECHO;
-#endif /* __OBSOLETE__ */
-#ifdef OXTABS
-    /* test used to be tgetflag("pt") */
-    if (has_hardware_tabs)	/* Print tabs. */
-	mode.c_oflag &= ~OXTABS;
-#endif /* OXTABS */
-    mode.c_lflag |= (ECHOE | ECHOK);
-#endif
-}
-
-/* Output startup string. */
-static void
-set_init(void)
-{
-    char *p;
-    bool settle;
-
-#ifdef __OBSOLETE__
-    if (pad_char != (char *) 0)	/* Get/set pad character. */
-	PC = pad_char[0];
-#endif /* OBSOLETE */
-
-#ifdef TAB3
-    if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
-	oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
-	SET_TTY(STDERR_FILENO, &oldmode);
-    }
-#endif
-    settle = set_tabs();
-
-    if (isreset) {
-	if ((p = reset_1string) != 0) {
-	    tputs(p, 0, outc);
-	    settle = TRUE;
-	}
-	if ((p = reset_2string) != 0) {
-	    tputs(p, 0, outc);
-	    settle = TRUE;
-	}
-	/* What about rf, rs3, as per terminfo man page? */
-	/* also might be nice to send rmacs, rmul, rmm */
-	if ((p = reset_file) != 0
-	    || (p = init_file) != 0) {
-	    cat(p);
-	    settle = TRUE;
-	}
-    }
-
-    if (settle) {
-	(void) putc('\r', stderr);
-	(void) fflush(stderr);
-	(void) napms(1000);	/* Settle the terminal. */
-    }
-}
-
-/*
- * Set the hardware tabs on the terminal, using the ct (clear all tabs),
- * st (set one tab) and ch (horizontal cursor addressing) capabilities.
- * This is done before if and is, so they can patch in case we blow this.
- * Return TRUE if we set any tab stops, FALSE if not.
- */
-static bool
-set_tabs(void)
-{
-    if (set_tab && clear_all_tabs) {
-	int c;
-	int lim =
-#if HAVE_SIZECHANGE
-	tcolumns
-#else
-	columns
-#endif
-	 ;
-
-	(void) putc('\r', stderr);	/* Force to left margin. */
-	tputs(clear_all_tabs, 0, outc);
-
-	for (c = 8; c < lim; c += 8) {
-	    /* Get to the right column.  In BSD tset, this
-	     * used to try a bunch of half-clever things
-	     * with cup and hpa, for an average saving of
-	     * somewhat less than two character times per
-	     * tab stop, less than .01 sec at 2400cps. We
-	     * lost all this cruft because it seemed to be
-	     * introducing some odd bugs.
-	     * -----------12345678----------- */
-	    (void) fputs("        ", stderr);
-	    tputs(set_tab, 0, outc);
-	}
-	putc('\r', stderr);
-	return (TRUE);
-    }
-    return (FALSE);
-}
-
-/**************************************************************************
- *
  * Main sequence
  *
  **************************************************************************/
 
 /*
- * Tell the user if a control key has been changed from the default value.
- */
-#ifdef TERMIOS
-static void
-report(const char *name, int which, unsigned def)
-{
-    unsigned older, newer;
-    char *p;
-
-    newer = mode.c_cc[which];
-    older = oldmode.c_cc[which];
-
-    if (older == newer && older == def)
-	return;
-
-    (void) fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to");
-
-    if (DISABLED(newer))
-	(void) fprintf(stderr, "undef.\n");
-    /*
-     * Check 'delete' before 'backspace', since the key_backspace value
-     * is ambiguous.
-     */
-    else if (newer == 0177)
-	(void) fprintf(stderr, "delete.\n");
-    else if ((p = key_backspace) != 0
-	     && newer == (unsigned char) p[0]
-	     && p[1] == '\0')
-	(void) fprintf(stderr, "backspace.\n");
-    else if (newer < 040) {
-	newer ^= 0100;
-	(void) fprintf(stderr, "control-%c (^%c).\n", UChar(newer), UChar(newer));
-    } else
-	(void) fprintf(stderr, "%c.\n", UChar(newer));
-}
-#endif
-
-/*
  * Convert the obsolete argument forms into something that getopt can handle.
  * This means that -e, -i and -k get default arguments supplied for them.
  */
@@ -1167,29 +703,58 @@
 }
 
 static void
+print_shell_commands(const char *ttype)
+{
+    const char *p;
+    int len;
+    char *var;
+    char *leaf;
+    /*
+     * Figure out what shell we're using.  A hack, we look for an
+     * environmental variable SHELL ending in "csh".
+     */
+    if ((var = getenv("SHELL")) != 0
+	&& ((len = (int) strlen(leaf = _nc_basename(var))) >= 3)
+	&& !strcmp(leaf + len - 3, "csh"))
+	p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
+    else
+	p = "TERM=%s;\n";
+    (void) printf(p, ttype);
+}
+
+static void
 usage(void)
 {
-#define DATA(s) s "\n"
+#define SKIP(s)			/* nothing */
+#define KEEP(s) s "\n"
     static const char msg[] =
     {
-	DATA("")
-	DATA("Options:")
-	DATA("  -c          set control characters")
-	DATA("  -e ch       erase character")
-	DATA("  -I          no initialization strings")
-	DATA("  -i ch       interrupt character")
-	DATA("  -k ch       kill character")
-	DATA("  -m mapping  map identifier to type")
-	DATA("  -Q          do not output control key settings")
-	DATA("  -r          display term on stderr")
-	DATA("  -s          output TERM set command")
-	DATA("  -V          print curses-version")
-	DATA("  -w          set window-size")
+	KEEP("")
+	KEEP("Options:")
+	SKIP("  -a arpanet  (obsolete)")
+	KEEP("  -c          set control characters")
+	SKIP("  -d dialup   (obsolete)")
+	KEEP("  -e ch       erase character")
+	KEEP("  -I          no initialization strings")
+	KEEP("  -i ch       interrupt character")
+	KEEP("  -k ch       kill character")
+	KEEP("  -m mapping  map identifier to type")
+	SKIP("  -p plugboard (obsolete)")
+	KEEP("  -Q          do not output control key settings")
+	KEEP("  -q          display term only, do no changes")
+	KEEP("  -r          display term on stderr")
+	SKIP("  -S          (obsolete)")
+	KEEP("  -s          output TERM set command")
+	KEEP("  -V          print curses-version")
+	KEEP("  -w          set window-size")
+	KEEP("")
+	KEEP("If neither -c/-w are given, both are assumed.")
     };
-#undef DATA
+#undef KEEP
+#undef SKIP
     (void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname);
     fputs(msg, stderr);
-    exit_error();
+    ExitProgram(EXIT_FAILURE);
     /* NOTREACHED */
 }
 
@@ -1205,12 +770,19 @@
 main(int argc, char **argv)
 {
     int ch, noinit, noset, quiet, Sflag, sflag, showterm;
-    const char *p;
     const char *ttype;
+    int terasechar = -1;	/* new erase character */
+    int intrchar = -1;		/* new interrupt character */
+    int tkillchar = -1;		/* new kill character */
+    int my_fd;
+    bool opt_c = FALSE;		/* set control-chars */
+    bool opt_w = FALSE;		/* set window-size */
+    TTY mode, oldmode;
 
+    _nc_progname = _nc_rootname(*argv);
     obsolete(argv);
     noinit = noset = quiet = Sflag = sflag = showterm = 0;
-    while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:np:qQSrsVw")) != -1) {
+    while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:p:qQrSsVw")) != -1) {
 	switch (ch) {
 	case 'c':		/* set control-chars */
 	    opt_c = TRUE;
@@ -1236,8 +808,6 @@
 	case 'm':		/* map identifier to type */
 	    add_mapping(0, optarg);
 	    break;
-	case 'n':		/* OBSOLETE: set new tty driver */
-	    break;
 	case 'p':		/* OBSOLETE: map identifier to type */
 	    add_mapping("plugboard", optarg);
 	    break;
@@ -1268,7 +838,6 @@
 	}
     }
 
-    _nc_progname = _nc_rootname(*argv);
     argc -= optind;
     argv += optind;
 
@@ -1278,94 +847,74 @@
     if (!opt_c && !opt_w)
 	opt_c = opt_w = TRUE;
 
-    if (GET_TTY(STDERR_FILENO, &mode) < 0)
-	failed("standard error");
-    can_restore = TRUE;
-    original = oldmode = mode;
+    my_fd = save_tty_settings(&mode, TRUE);
+    oldmode = mode;
 #ifdef TERMIOS
     ospeed = (NCURSES_OSPEED) cfgetospeed(&mode);
+#elif defined(EXP_WIN32_DRIVER)
+    ospeed = 0;
 #else
     ospeed = (NCURSES_OSPEED) mode.sg_ospeed;
 #endif
 
     if (same_program(_nc_progname, PROG_RESET)) {
-	isreset = TRUE;
-	reset_mode();
+	reset_start(stderr, TRUE, FALSE);
+	reset_tty_settings(my_fd, &mode, noset);
+    } else {
+	reset_start(stderr, FALSE, TRUE);
     }
 
-    (void) get_termcap_entry(*argv);
+    ttype = get_termcap_entry(my_fd, *argv);
 
     if (!noset) {
 #if HAVE_SIZECHANGE
-	tcolumns = columns;
-	tlines = lines;
-
 	if (opt_w) {
-	    STRUCT_WINSIZE win;
-	    /* Set window size if not set already */
-	    (void) ioctl(STDERR_FILENO, IOCTL_GET_WINSIZE, &win);
-	    if (WINSIZE_ROWS(win) == 0 &&
-		WINSIZE_COLS(win) == 0 &&
-		tlines > 0 && tcolumns > 0) {
-		WINSIZE_ROWS(win) = (unsigned short) tlines;
-		WINSIZE_COLS(win) = (unsigned short) tcolumns;
-		(void) ioctl(STDERR_FILENO, IOCTL_SET_WINSIZE, &win);
-	    }
+	    NCURSES_INT2 my_rows = lines;
+	    NCURSES_INT2 my_cols = columns;
+	    set_window_size(my_fd, &my_rows, &my_cols);
+	    lines = my_rows;
+	    columns = my_cols;
 	}
 #endif
 	if (opt_c) {
-	    set_control_chars();
-	    set_conversions();
+	    set_control_chars(&mode, terasechar, intrchar, tkillchar);
+	    set_conversions(&mode);
 
-	    if (!noinit)
-		set_init();
+	    if (!noinit) {
+		if (send_init_strings(my_fd, &oldmode)) {
+		    const char *name;
 
-	    /* Set the modes if they've changed. */
-	    if (memcmp(&mode, &oldmode, sizeof(mode))) {
-		SET_TTY(STDERR_FILENO, &mode);
+		    (void) putc('\r', stderr);
+		    (void) fflush(stderr);
+		    if (IsRealTty(my_fd, name)) {
+			(void) napms(1000);	/* Settle the terminal. */
+		    }
+		}
 	    }
+
+	    update_tty_settings(&oldmode, &mode);
 	}
     }
 
-    /* Get the terminal name from the entry. */
-    ttype = _nc_first_name(cur_term->type.term_names);
-
-    if (noset)
+    if (noset) {
 	(void) printf("%s\n", ttype);
-    else {
+    } else {
 	if (showterm)
 	    (void) fprintf(stderr, "Terminal type is %s.\n", ttype);
 	/*
 	 * If erase, kill and interrupt characters could have been
 	 * modified and not -Q, display the changes.
 	 */
-#ifdef TERMIOS
 	if (!quiet) {
-	    report("Erase", VERASE, CERASE);
-	    report("Kill", VKILL, CKILL);
-	    report("Interrupt", VINTR, CINTR);
+	    print_tty_chars(&oldmode, &mode);
 	}
-#endif
     }
 
     if (Sflag)
 	err("The -S option is not supported under terminfo.");
 
     if (sflag) {
-	int len;
-	char *var;
-	char *leaf;
-	/*
-	 * Figure out what shell we're using.  A hack, we look for an
-	 * environmental variable SHELL ending in "csh".
-	 */
-	if ((var = getenv("SHELL")) != 0
-	    && ((len = (int) strlen(leaf = _nc_basename(var))) >= 3)
-	    && !strcmp(leaf + len - 3, "csh"))
-	    p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
-	else
-	    p = "TERM=%s;\n";
-	(void) printf(p, ttype);
+	print_shell_commands(ttype);
     }
 
     ExitProgram(EXIT_SUCCESS);
diff --git a/progs/tty_settings.c b/progs/tty_settings.c
new file mode 100644
index 0000000..a9eb8cd
--- /dev/null
+++ b/progs/tty_settings.c
@@ -0,0 +1,107 @@
+/****************************************************************************
+ * Copyright 2020,2021 Thomas E. Dickey                                     *
+ * Copyright 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"), 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                                                *
+ ****************************************************************************/
+
+#define USE_LIBTINFO
+#include <tty_settings.h>
+
+#include <fcntl.h>
+
+MODULE_ID("$Id: tty_settings.c,v 1.7 2021/10/08 23:53:32 tom Exp $")
+
+static int my_fd;
+static TTY original_settings;
+static bool can_restore = FALSE;
+
+static void
+failed(const char *msg)
+{
+    int code = errno;
+
+    (void) fprintf(stderr, "%s: %s: %s\n", _nc_progname, msg, strerror(code));
+    restore_tty_settings();
+    (void) fprintf(stderr, "\n");
+    ExitProgram(ErrSystem(code));
+    /* NOTREACHED */
+}
+
+static bool
+get_tty_settings(int fd, TTY * tty_settings)
+{
+    bool success = TRUE;
+    my_fd = fd;
+    if (fd < 0 || GET_TTY(my_fd, tty_settings) < 0) {
+	success = FALSE;
+    }
+    return success;
+}
+
+/*
+ * Open a file descriptor on the current terminal, to obtain its settings.
+ * stderr is less likely to be redirected than stdout; try that first.
+ */
+int
+save_tty_settings(TTY * tty_settings, bool need_tty)
+{
+    if (!get_tty_settings(STDERR_FILENO, tty_settings) &&
+	!get_tty_settings(STDOUT_FILENO, tty_settings) &&
+	!get_tty_settings(STDIN_FILENO, tty_settings)) {
+	if (need_tty) {
+	    int fd = open("/dev/tty", O_RDWR);
+	    if (!get_tty_settings(fd, tty_settings)) {
+		failed("terminal attributes");
+	    }
+	} else {
+	    my_fd = fileno(stdout);
+	}
+    } else {
+	can_restore = TRUE;
+	original_settings = *tty_settings;
+    }
+    return my_fd;
+}
+
+void
+restore_tty_settings(void)
+{
+    if (can_restore)
+	SET_TTY(my_fd, &original_settings);
+}
+
+/* Set the modes if they've changed. */
+void
+update_tty_settings(TTY * old_settings, TTY * new_settings)
+{
+    if (memcmp(new_settings, old_settings, sizeof(TTY))) {
+	SET_TTY(my_fd, new_settings);
+    }
+}
diff --git a/progs/tty_settings.h b/progs/tty_settings.h
new file mode 100644
index 0000000..bd3bcdb
--- /dev/null
+++ b/progs/tty_settings.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 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"), 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                                                 *
+ ****************************************************************************/
+
+/*
+ * $Id: tty_settings.h,v 1.3 2020/02/02 23:34:34 tom Exp $
+ *
+ * Utility functions for saving/restoring terminal settings.
+ */
+#ifndef TTY_SETTINGS_H
+#define TTY_SETTINGS_H 1
+/* *INDENT-OFF* */
+
+#include <progs.priv.h>
+
+extern int save_tty_settings(TTY * /* tty_settings */, bool /* need_tty */ );
+extern void restore_tty_settings(void);
+extern void update_tty_settings(TTY * /* old_settings */, TTY * /* new_settings */ );
+
+/* *INDENT-ON* */
+
+#endif /* TTY_SETTINGS_H */