aboutsummaryrefslogtreecommitdiff
path: root/progs
diff options
context:
space:
mode:
authorBaptiste Daroussin <bapt@FreeBSD.org>2020-02-07 08:36:41 +0000
committerBaptiste Daroussin <bapt@FreeBSD.org>2020-02-07 08:36:41 +0000
commitf0179cb6083cc92e5947ae56e6a0a5c5328aead0 (patch)
treebcee0ba9c2149b71f0bfc036df1e61e3105bf980 /progs
parentcea297eb34d2361e79529034397465068ae34ecd (diff)
downloadsrc-f0179cb6083cc92e5947ae56e6a0a5c5328aead0.tar.gz
src-f0179cb6083cc92e5947ae56e6a0a5c5328aead0.zip
Vendor import ncurses 6.1-20200118vendor/ncurses/6.1-20200118
Notes
Notes: svn path=/vendor/ncurses/dist/; revision=357645 svn path=/vendor/ncurses/6.1-20200118/; revision=357646; tag=vendor/ncurses/6.1-20200118
Diffstat (limited to 'progs')
-rwxr-xr-xprogs/MKtermsort.sh24
-rw-r--r--progs/Makefile.in41
-rwxr-xr-xprogs/capconvert12
-rw-r--r--progs/clear.c66
-rw-r--r--progs/clear_cmd.c59
-rw-r--r--progs/clear_cmd.h44
-rw-r--r--progs/dump_entry.c570
-rw-r--r--progs/dump_entry.h24
-rw-r--r--progs/infocmp.c269
-rw-r--r--progs/modules16
-rw-r--r--progs/progs.priv.h37
-rw-r--r--progs/reset_cmd.c634
-rw-r--r--progs/reset_cmd.h65
-rw-r--r--progs/tabs.c83
-rw-r--r--progs/tic.c1363
-rw-r--r--progs/toe.c38
-rw-r--r--progs/tparm_type.c71
-rw-r--r--progs/tparm_type.h52
-rw-r--r--progs/tput.c268
-rw-r--r--progs/tset.c828
-rw-r--r--progs/tty_settings.c104
-rw-r--r--progs/tty_settings.h50
22 files changed, 3395 insertions, 1323 deletions
diff --git a/progs/MKtermsort.sh b/progs/MKtermsort.sh
index 2247f14ef2e8..60aaaedf7325 100755
--- a/progs/MKtermsort.sh
+++ b/progs/MKtermsort.sh
@@ -1,10 +1,10 @@
#!/bin/sh
-# $Id: MKtermsort.sh,v 1.10 2008/07/12 20:22:54 tom Exp $
+# $Id: MKtermsort.sh,v 1.12 2017/08/12 12:22:06 tom Exp $
#
# MKtermsort.sh -- generate indirection vectors for the various sort methods
#
##############################################################################
-# Copyright (c) 1998-2003,2008 Free Software Foundation, Inc. #
+# Copyright (c) 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,7 +46,7 @@ AWK=${1-awk}
DATA=${2-../include/Caps}
data=data$$
-trap 'rm -f $data' 1 2 5 15
+trap 'rm -f $data' 1 2 3 15
sed -e 's/[ ][ ]*/ /g' < $DATA >$data
DATA=$data
@@ -139,24 +139,30 @@ echo "";
echo "static const bool bool_from_termcap[] = {";
$AWK <$DATA '
-$3 == "bool" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */";}
-$3 == "bool" && substr($7, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */";}
+BEGIN { count = 0; valid = 0; }
+$3 == "bool" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */"; count++; }
+$3 == "bool" && substr($7, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */"; valid = count++; }
+END { printf "#define OK_bool_from_termcap %d\n", valid; }
'
echo "};";
echo "";
echo "static const bool num_from_termcap[] = {";
$AWK <$DATA '
-$3 == "num" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */";}
-$3 == "num" && substr($7, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */";}
+BEGIN { count = 0; valid = 0; }
+$3 == "num" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */"; count++; }
+$3 == "num" && substr($7, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */"; valid = count++; }
+END { printf "#define OK_num_from_termcap %d\n", valid; }
'
echo "};";
echo "";
echo "static const bool str_from_termcap[] = {";
$AWK <$DATA '
-$3 == "str" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */";}
-$3 == "str" && substr($7, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */";}
+BEGIN { count = 0; valid = 0; }
+$3 == "str" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */"; count++; }
+$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 "";
diff --git a/progs/Makefile.in b/progs/Makefile.in
index a9161b16cbca..b55057d88ef9 100644
--- a/progs/Makefile.in
+++ b/progs/Makefile.in
@@ -1,6 +1,6 @@
-# $Id: Makefile.in,v 1.90 2013/08/04 20:23:20 tom Exp $
+# $Id: Makefile.in,v 1.102 2018/01/15 19:28:45 tom Exp $
##############################################################################
-# Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. #
+# Copyright (c) 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"), #
@@ -42,7 +42,7 @@
# turn off _all_ suffix rules; we'll generate our own
.SUFFIXES:
-SHELL = /bin/sh
+SHELL = @SHELL@
VPATH = @srcdir@
THIS = Makefile
@@ -67,7 +67,10 @@ includesubdir = @includesubdir@
INCLUDEDIR = $(DESTDIR)$(includedir)$(includesubdir)
+PACKAGE = @PACKAGE@
+
LIBTOOL = @LIBTOOL@
+LIBTOOL_OPTS = @LIBTOOL_OPTS@
LIBTOOL_CLEAN = @LIB_CLEAN@
LIBTOOL_COMPILE = @LIB_COMPILE@
LIBTOOL_LINK = @LIB_LINK@
@@ -75,7 +78,7 @@ LIBTOOL_INSTALL = @LIB_INSTALL@
LIBTOOL_UNINSTALL = @LIB_UNINSTALL@
INSTALL = @INSTALL@
-INSTALL_PROG = @INSTALL_PROGRAM@
+INSTALL_PROG = @INSTALL_PROGRAM@ @INSTALL_OPT_S@
transform = @program_transform_name@
AWK = @AWK@
@@ -89,7 +92,7 @@ CPP = @CPP@
CFLAGS = @CFLAGS@
INCDIR = $(top_srcdir)/include
-CPPFLAGS = -I../progs -I$(srcdir) -DHAVE_CONFIG_H @CPPFLAGS@
+CPPFLAGS = -DHAVE_CONFIG_H -I../progs @CPPFLAGS@
CCFLAGS = $(CPPFLAGS) $(CFLAGS)
@@ -176,6 +179,7 @@ actual_tset = `echo tset$x| $(TRANSFORM)`
# 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)`
@@ -185,9 +189,10 @@ transform.h :
echo "#define __TRANSFORM_H 1" >>$@
echo "#include <progs.priv.h>" >>$@
echo "extern bool same_program(const char *, const char *);" >>$@
- -sh -c 'if test -n "$x" ; then echo "#define SUFFIX_IGNORED \"$x\"">>$@; fi'
+ -$(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 */" >>$@
@@ -232,6 +237,7 @@ $(DESTDIR)$(bindir) :
DEPS_TIC = \
$(MODEL)/tic$o \
$(MODEL)/dump_entry$o \
+ $(MODEL)/tparm_type$o \
$(MODEL)/transform$o
tic$x: $(DEPS_TIC) $(DEPS_CURSES) transform.h
@@ -244,20 +250,27 @@ toe$x: $(DEPS_TOE) $(DEPS_CURSES)
@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)/transform$o
+ $(MODEL)/clear_cmd$o \
+ $(MODEL)/reset_cmd$o \
+ $(MODEL)/tparm_type$o \
+ $(MODEL)/transform$o \
+ $(MODEL)/tty_settings$o
tput$x: $(DEPS_TPUT) $(DEPS_CURSES) transform.h
@ECHO_LD@ $(LINK) $(DEPS_TPUT) $(LDFLAGS_TINFO) -o $@
@@ -271,13 +284,15 @@ infocmp$x: $(DEPS_INFOCMP) $(DEPS_CURSES)
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
- sh $(srcdir)/MKtermsort.sh $(AWK) $(srcdir)/../include/@TERMINFO_CAPS@ >$@
+ $(SHELL) $(srcdir)/MKtermsort.sh $(AWK) $(srcdir)/../include/@TERMINFO_CAPS@ >$@
#
# Utility productions start here
@@ -293,10 +308,10 @@ mostlyclean ::
-rm -f core tags TAGS *~ *.bak *.i *.ln *.atac trace
clean :: mostlyclean
- -sh -c "if test -n '$x' ; then $(MAKE) clean x=''; fi"
+ -$(SHELL) -c "if test -n '$x' ; then $(MAKE) clean x=''; fi"
-rm -f $(AUTO_SRC)
-rm -f $(PROGS)
- -rm -rf .libs
+ -rm -rf .libs *.dSYM
distclean :: clean
-rm -f Makefile
diff --git a/progs/capconvert b/progs/capconvert
index eb382e0bc86c..a3535bd4a570 100755
--- a/progs/capconvert
+++ b/progs/capconvert
@@ -1,6 +1,6 @@
#!/bin/sh
##############################################################################
-# Copyright (c) 1998-2006,2011 Free Software Foundation, Inc. #
+# Copyright (c) 1998-2019,2020 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 +26,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.8 2020/01/18 17:02:38 tom Exp $
#
# capconvert -- automated conversion from termcap to terminfo
#
@@ -179,7 +179,7 @@ else
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:"
@@ -205,14 +205,14 @@ echo "OK, now I will make your private terminfo tree. This may take a bit..."
#
# 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
+trap "rm -f tsplit$$.*" EXIT INT QUIT TERM HUP
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
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,"
@@ -251,7 +251,7 @@ else
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.c b/progs/clear.c
index 4ac503ed3641..2ffdf9530948 100644
--- a/progs/clear.c
+++ b/progs/clear.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2007,2013 Free Software Foundation, Inc. *
+ * Copyright (c) 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 +37,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.22 2017/10/07 21:48:32 tom Exp $")
-static int
-putch(int c)
+const char *_nc_progname = "clear";
+
+static 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 +67,41 @@ main(
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 */
+
+ _nc_progname = _nc_rootname(argv[0]);
+ term = getenv("TERM");
+
+ 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();
- setupterm((char *) 0, STDOUT_FILENO, (int *) 0);
+ fd = save_tty_settings(&tty_settings, FALSE);
- /* Clear the scrollback buffer if possible. */
- E3 = tigetstr("E3");
- if (E3)
- (void) tputs(E3, lines > 0 ? lines : 1, putch);
+ setupterm(term, fd, (int *) 0);
- ExitProgram((tputs(clear_screen, lines > 0 ? lines : 1, putch) == ERR)
+ ExitProgram((clear_cmd(opt_x) == ERR)
? EXIT_FAILURE
: EXIT_SUCCESS);
}
diff --git a/progs/clear_cmd.c b/progs/clear_cmd.c
new file mode 100644
index 000000000000..ef404a444d6e
--- /dev/null
+++ b/progs/clear_cmd.c
@@ -0,0 +1,59 @@
+/****************************************************************************
+ * Copyright (c) 2016-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 *
+ * "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.4 2018/08/04 18:43:22 Nicholas.Marriott 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 000000000000..7ccd44c8c8fb
--- /dev/null
+++ b/progs/clear_cmd.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+ * Copyright (c) 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.2 2017/08/19 13:37:38 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 65de9f9bc1f1..8a47084a28bf 100644
--- a/progs/dump_entry.c
+++ b/progs/dump_entry.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2018,2019 Free Software Foundation, Inc. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the *
@@ -39,13 +39,14 @@
#include "termsort.c" /* this C file is generated */
#include <parametrized.h> /* so is this */
-MODULE_ID("$Id: dump_entry.c,v 1.111 2013/12/15 01:05:20 tom Exp $")
+MODULE_ID("$Id: dump_entry.c,v 1.175 2019/10/12 15:59:07 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,6 +62,10 @@ static int height = 65535; /* max number of lines for listings */
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;
@@ -74,6 +79,7 @@ static NCURSES_CONST char *const *num_names;
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) */
@@ -88,7 +94,7 @@ static const char *separator = "", *trailer = "";
#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]))
@@ -119,7 +125,7 @@ strncpy_DYN(DYNBUF * dst, const char *src, size_t need)
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;
}
@@ -155,17 +161,17 @@ _nc_leaks_dump_entry(void)
#endif
#define NameTrans(check,result) \
- if (OkIndex(np->nte_index, check) \
+ if ((np->nte_index <= OK_ ## check) \
&& check[np->nte_index]) \
return (result[np->nte_index])
NCURSES_CONST char *
nametrans(const char *name)
-/* translate a capability name from termcap to terminfo */
+/* translate a capability name to termcap from terminfo */
{
const struct name_table_entry *np;
- if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0)
+ if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0) {
switch (np->nte_type) {
case BOOLEAN:
NameTrans(bool_from_termcap, boolcodes);
@@ -179,6 +185,7 @@ nametrans(const char *name)
NameTrans(str_from_termcap, strcodes);
break;
}
+ }
return (0);
}
@@ -187,15 +194,23 @@ void
dump_init(const char *version,
int mode,
int sort,
+ bool wrap_strings,
int twidth,
int theight,
unsigned traceval,
- bool formatted)
+ bool formatted,
+ 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)
@@ -240,6 +255,7 @@ dump_init(const char *version,
trailer = "\\\n\t:";
break;
}
+ indent = 8;
/* implement sort modes */
switch (sortmode = sort) {
@@ -283,7 +299,7 @@ dump_init(const char *version,
_nc_progname, width, tversion, outform);
}
-static TERMTYPE *cur_type;
+static TERMTYPE2 *cur_type;
static int
dump_predicate(PredType type, PredIdx idx)
@@ -306,7 +322,7 @@ dump_predicate(PredType type, PredIdx idx)
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) \
@@ -409,22 +425,254 @@ force_wrap(void)
oldcol = column;
trim_trailing();
strcpy_DYN(&outbuf, trailer);
- column = INDENT;
+ column = indent;
}
-static void
-wrap_concat(const char *src)
+static int
+op_length(const char *src, int offset)
+{
+ int result = 0;
+ int ch;
+ if (offset > 0 && src[offset - 1] == '\\') {
+ result = 0;
+ } else {
+ 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;
+ int n;
+ if (size > 0) {
+ /* check if that would split a backslash-sequence */
+ int mark = size;
+ 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 want = strlen(separator) + need;
+ size_t size = strlen(fill);
+ char *result = 0;
+ int pass;
+ int 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 += (int) size;
+ } else {
+ need += size;
+ }
+ } else {
+ if (pass) {
+ result[d++] = src[s];
+ } else {
+ ++d;
+ }
+ }
+ }
+ if (pass) {
+ result[d] = '\0';
+ } else {
+ result = malloc(need + 1);
+ 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 size;
+ 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;
+ }
- if (column > INDENT
- && column + (int) want > width) {
+ while ((column + (need + gaps)) > used) {
+ 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);
}
- strcpy_DYN(&outbuf, src);
- strcpy_DYN(&outbuf, separator);
- column += (int) need;
+}
+
+static void
+wrap_concat1(const char *src)
+{
+ int need = (int) strlen(src);
+ wrap_concat(src, need, w1ST | wEND);
+}
+
+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) \
@@ -470,7 +718,34 @@ indent_DYN(DYNBUF * buffer, int level)
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)
{
bool result = FALSE;
@@ -495,13 +770,17 @@ has_params(const char *src)
}
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);
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);
@@ -537,9 +816,10 @@ fmt_complex(TERMTYPE *tterm, const char *capability, char *src, int level)
indent_DYN(&tmpbuf, level + 1);
}
} else if (level == 1) {
- _nc_warning("%s: %%%c without %%? in %s",
- _nc_first_name(tterm->term_names),
- *src, capability);
+ if (checking)
+ _nc_warning("%s: %%%c without %%? in %s",
+ _nc_first_name(tterm->term_names),
+ *src, capability);
}
}
continue;
@@ -561,13 +841,14 @@ fmt_complex(TERMTYPE *tterm, const char *capability, char *src, int level)
}
return src;
}
- _nc_warning("%s: %%; without %%? in %s",
- _nc_first_name(tterm->term_names),
- capability);
+ if (checking)
+ _nc_warning("%s: %%; without %%? in %s",
+ _nc_first_name(tterm->term_names),
+ capability);
}
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);
@@ -588,11 +869,35 @@ fmt_complex(TERMTYPE *tterm, const char *capability, char *src, int level)
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;
+ unsigned long mm;
+ int bits = sizeof(unsigned long) * 8;
+ int nn;
+ for (nn = 8; nn < bits; ++nn) {
+ 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,
@@ -609,9 +914,8 @@ fmt_entry(TERMTYPE *tterm,
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 */
@@ -622,7 +926,7 @@ fmt_entry(TERMTYPE *tterm,
strcpy_DYN(&outbuf, 0);
if (content_only) {
- column = INDENT; /* FIXME: workaround to prevent empty lines */
+ column = indent; /* FIXME: workaround to prevent empty lines */
} else {
strcpy_DYN(&outbuf, tterm->term_names);
@@ -665,7 +969,7 @@ fmt_entry(TERMTYPE *tterm,
}
}
- if (column != INDENT && height > 1)
+ if (column != indent && height > 1)
force_wrap();
for_each_number(j, tterm) {
@@ -684,8 +988,13 @@ fmt_entry(TERMTYPE *tterm,
_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;
}
@@ -693,7 +1002,7 @@ fmt_entry(TERMTYPE *tterm,
}
}
- if (column != INDENT && height > 1)
+ if (column != indent && height > 1)
force_wrap();
len += (int) (num_bools
@@ -705,12 +1014,12 @@ fmt_entry(TERMTYPE *tterm,
#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);
}
@@ -770,8 +1079,12 @@ fmt_entry(TERMTYPE *tterm,
set_attributes = save_sgr;
trimmed_sgr0 = _nc_trim_sgr0(tterm);
- if (strcmp(capability, trimmed_sgr0))
+ if (strcmp(capability, trimmed_sgr0)) {
capability = trimmed_sgr0;
+ } else {
+ if (trimmed_sgr0 != exit_attribute_mode)
+ free(trimmed_sgr0);
+ }
set_attributes = my_sgr;
}
@@ -782,7 +1095,7 @@ fmt_entry(TERMTYPE *tterm,
buffer[0] = '\0';
if (predval != FAIL) {
- if (capability != ABSENT_STRING
+ if (VALID_STRING(capability)
&& i + 1 > num_strings)
num_strings = i + 1;
@@ -790,11 +1103,13 @@ fmt_entry(TERMTYPE *tterm,
_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))
? parametrized[i]
- : 0);
- char *srccap = _nc_tic_expand(capability, TRUE, numbers);
+ : ((*srccap == 'k')
+ ? 0
+ : has_params(srccap)));
char *cv = _nc_infotocap(name, srccap, params);
if (cv == 0) {
@@ -802,28 +1117,45 @@ fmt_entry(TERMTYPE *tterm,
_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 + 1) >= (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);
@@ -839,13 +1171,11 @@ fmt_entry(TERMTYPE *tterm,
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);
}
@@ -934,9 +1264,11 @@ fmt_entry(TERMTYPE *tterm,
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
@@ -971,7 +1303,7 @@ fmt_entry(TERMTYPE *tterm,
}
static bool
-kill_string(TERMTYPE *tterm, char *cap)
+kill_string(TERMTYPE2 *tterm, char *cap)
{
unsigned n;
for (n = 0; n < NUM_STRINGS(tterm); ++n) {
@@ -984,7 +1316,7 @@ kill_string(TERMTYPE *tterm, char *cap)
}
static char *
-find_string(TERMTYPE *tterm, char *name)
+find_string(TERMTYPE2 *tterm, char *name)
{
PredIdx n;
for (n = 0; n < NUM_STRINGS(tterm); ++n) {
@@ -1005,7 +1337,7 @@ find_string(TERMTYPE *tterm, char *name)
* make it smaller.
*/
static int
-kill_labels(TERMTYPE *tterm, int target)
+kill_labels(TERMTYPE2 *tterm, int target)
{
int n;
int result = 0;
@@ -1014,7 +1346,8 @@ kill_labels(TERMTYPE *tterm, int target)
for (n = 0; n <= 10; ++n) {
_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;
@@ -1030,7 +1363,7 @@ kill_labels(TERMTYPE *tterm, int target)
* make it smaller.
*/
static int
-kill_fkeys(TERMTYPE *tterm, int target)
+kill_fkeys(TERMTYPE2 *tterm, int target)
{
int n;
int result = 0;
@@ -1039,7 +1372,8 @@ kill_fkeys(TERMTYPE *tterm, int target)
for (n = 60; n >= 0; --n) {
_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;
@@ -1061,9 +1395,9 @@ one_one_mapping(const char *mapping)
{
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;
@@ -1084,7 +1418,7 @@ one_one_mapping(const char *mapping)
#define SHOW_WHY PRINTF
static bool
-purged_acs(TERMTYPE *tterm)
+purged_acs(TERMTYPE2 *tterm)
{
bool result = FALSE;
@@ -1099,22 +1433,99 @@ purged_acs(TERMTYPE *tterm)
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;
+ TERMTYPE2 save_tterm;
int len, critlen;
const char *legend;
bool infodump;
- if (outform == F_TERMCAP || outform == F_TCONVERR) {
+ if (quickdump) {
+ char bigbuf[65536];
+ unsigned n;
+ unsigned offset = 0;
+ separator = "";
+ trailer = "\n";
+ indent = 0;
+ if (_nc_write_object(tterm, bigbuf, &offset, sizeof(bigbuf)) == OK) {
+ char numbuf[80];
+ 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;
@@ -1203,7 +1614,8 @@ dump_entry(TERMTYPE *tterm,
}
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",
@@ -1229,11 +1641,11 @@ dump_uses(const char *name, bool infodump)
{
char buffer[MAX_TERMINFO_LENGTH];
- if (outform == F_TERMCAP || outform == F_TCONVERR)
+ if (TcOutput())
trim_trailing();
_nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
"%s%s", infodump ? "use=" : "tc=", name);
- wrap_concat(buffer);
+ wrap_concat1(buffer);
}
int
@@ -1243,7 +1655,7 @@ show_entry(void)
* 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;
@@ -1263,14 +1675,16 @@ show_entry(void)
}
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 */
{
@@ -1329,7 +1743,7 @@ compare_entry(PredHook hook,
#define CUR tp->
static void
-set_obsolete_termcaps(TERMTYPE *tp)
+set_obsolete_termcaps(TERMTYPE2 *tp)
{
#include "capdefaults.c"
}
@@ -1339,7 +1753,7 @@ set_obsolete_termcaps(TERMTYPE *tp)
* unique.
*/
void
-repair_acsc(TERMTYPE *tp)
+repair_acsc(TERMTYPE2 *tp)
{
if (VALID_STRING(acs_chars)) {
size_t n, m;
diff --git a/progs/dump_entry.h b/progs/dump_entry.h
index cb2a44fe7d4f..1d0b01d8acbe 100644
--- a/progs/dump_entry.h
+++ b/progs/dump_entry.h
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2011,2013 Free Software Foundation, Inc. *
+ * Copyright (c) 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 *
@@ -33,7 +33,7 @@
****************************************************************************/
/*
- * $Id: dump_entry.h,v 1.33 2013/12/15 01:08:03 tom Exp $
+ * $Id: dump_entry.h,v 1.41 2018/05/26 15:22:30 tom Exp $
*
* Dump control definitions and variables
*/
@@ -41,6 +41,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 */
@@ -67,13 +72,18 @@ typedef int (*PredFunc) (PredType, PredIdx);
typedef void (*PredHook) (PredType, PredIdx, const char *);
extern NCURSES_CONST char *nametrans(const char *);
-extern int fmt_entry(TERMTYPE *, PredFunc, int, int, int, int);
+extern bool has_params(const char *src);
+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);
+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.c b/progs/infocmp.c
index 587cbc3449be..82c48419a047 100644
--- a/progs/infocmp.c
+++ b/progs/infocmp.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2013,2014 Free Software Foundation, Inc. *
+ * Copyright (c) 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 +42,7 @@
#include <dump_entry.h>
-MODULE_ID("$Id: infocmp.c,v 1.129 2014/02/01 22:11:03 tom Exp $")
-
-#define L_CURL "{"
-#define R_CURL "}"
+MODULE_ID("$Id: infocmp.c,v 1.143 2017/04/05 09:27:51 tom Exp $")
#define MAX_STRING 1024 /* maximum formatted string */
@@ -139,6 +136,33 @@ canonical_name(char *ptr, char *buf)
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(char *value)
+{
+ bool result = (value == ABSENT_STRING);
+ if (!strcmp(s_absent, s_cancel))
+ result = !VALID_STRING(value);
+ return result;
+}
+
/***************************************************************************
*
* Predicates for dump function
@@ -271,7 +295,7 @@ useeq(ENTRY * e1, ENTRY * e2)
}
static bool
-entryeq(TERMTYPE *t1, TERMTYPE *t2)
+entryeq(TERMTYPE2 *t1, TERMTYPE2 *t2)
/* are two entries equivalent? */
{
unsigned i;
@@ -329,7 +353,7 @@ dump_boolean(int val)
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:
@@ -437,7 +461,7 @@ compare_predicate(PredType type, PredIdx idx, const char *name)
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 +509,7 @@ compare_predicate(PredType type, PredIdx idx, const char *name)
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 +557,7 @@ compare_predicate(PredType type, PredIdx idx, const char *name)
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))
@@ -631,99 +655,104 @@ compare_predicate(PredType type, PredIdx idx, const char *name)
*
***************************************************************************/
+#define DATA(from, to) { { from }, { to } }
+#define DATAX() DATA("", "")
+
typedef struct {
- const char *from;
- const char *to;
+ const char from[4];
+ const char to[12];
} assoc;
static const assoc std_caps[] =
{
/* these are specified by X.364 and iBCS2 */
- {"\033c", "RIS"}, /* full reset */
- {"\0337", "SC"}, /* save cursor */
- {"\0338", "RC"}, /* restore cursor */
- {"\033[r", "RSR"}, /* not an X.364 mnemonic */
- {"\033[m", "SGR0"}, /* not an X.364 mnemonic */
- {"\033[2J", "ED2"}, /* clear page */
+ DATA("\033c", "RIS"), /* full reset */
+ DATA("\0337", "SC"), /* save cursor */
+ DATA("\0338", "RC"), /* restore cursor */
+ DATA("\033[r", "RSR"), /* not an X.364 mnemonic */
+ DATA("\033[m", "SGR0"), /* not an X.364 mnemonic */
+ DATA("\033[2J", "ED2"), /* clear page */
/* this group is specified by ISO 2022 */
- {"\033(0", "ISO DEC G0"}, /* enable DEC graphics for G0 */
- {"\033(A", "ISO UK G0"}, /* enable UK chars for G0 */
- {"\033(B", "ISO US G0"}, /* enable US chars for G0 */
- {"\033)0", "ISO DEC G1"}, /* enable DEC graphics for G1 */
- {"\033)A", "ISO UK G1"}, /* enable UK chars for G1 */
- {"\033)B", "ISO US G1"}, /* enable US chars for G1 */
+ DATA("\033(0", "ISO DEC G0"), /* enable DEC graphics for G0 */
+ DATA("\033(A", "ISO UK G0"), /* enable UK chars for G0 */
+ DATA("\033(B", "ISO US G0"), /* enable US chars for G0 */
+ DATA("\033)0", "ISO DEC G1"), /* enable DEC graphics for G1 */
+ DATA("\033)A", "ISO UK G1"), /* enable UK chars for G1 */
+ DATA("\033)B", "ISO US G1"), /* enable US chars for G1 */
/* these are DEC private controls widely supported by emulators */
- {"\033=", "DECPAM"}, /* application keypad mode */
- {"\033>", "DECPNM"}, /* normal keypad mode */
- {"\033<", "DECANSI"}, /* enter ANSI mode */
- {"\033[!p", "DECSTR"}, /* soft reset */
- {"\033 F", "S7C1T"}, /* 7-bit controls */
+ DATA("\033=", "DECPAM"), /* application keypad mode */
+ DATA("\033>", "DECPNM"), /* normal keypad mode */
+ DATA("\033<", "DECANSI"), /* enter ANSI mode */
+ DATA("\033[!p", "DECSTR"), /* soft reset */
+ DATA("\033 F", "S7C1T"), /* 7-bit controls */
- {(char *) 0, (char *) 0}
+ DATAX()
};
static const assoc std_modes[] =
/* ECMA \E[ ... [hl] modes recognized by many emulators */
{
- {"2", "AM"}, /* keyboard action mode */
- {"4", "IRM"}, /* insert/replace mode */
- {"12", "SRM"}, /* send/receive mode */
- {"20", "LNM"}, /* linefeed mode */
- {(char *) 0, (char *) 0}
+ DATA("2", "AM"), /* keyboard action mode */
+ DATA("4", "IRM"), /* insert/replace mode */
+ DATA("12", "SRM"), /* send/receive mode */
+ DATA("20", "LNM"), /* linefeed mode */
+ DATAX()
};
static const assoc private_modes[] =
/* DEC \E[ ... [hl] modes recognized by many emulators */
{
- {"1", "CKM"}, /* application cursor keys */
- {"2", "ANM"}, /* set VT52 mode */
- {"3", "COLM"}, /* 132-column mode */
- {"4", "SCLM"}, /* smooth scroll */
- {"5", "SCNM"}, /* reverse video mode */
- {"6", "OM"}, /* origin mode */
- {"7", "AWM"}, /* wraparound mode */
- {"8", "ARM"}, /* auto-repeat mode */
- {(char *) 0, (char *) 0}
+ DATA("1", "CKM"), /* application cursor keys */
+ DATA("2", "ANM"), /* set VT52 mode */
+ DATA("3", "COLM"), /* 132-column mode */
+ DATA("4", "SCLM"), /* smooth scroll */
+ DATA("5", "SCNM"), /* reverse video mode */
+ DATA("6", "OM"), /* origin mode */
+ DATA("7", "AWM"), /* wraparound mode */
+ DATA("8", "ARM"), /* auto-repeat mode */
+ DATAX()
};
static const assoc ecma_highlights[] =
/* recognize ECMA attribute sequences */
{
- {"0", "NORMAL"}, /* normal */
- {"1", "+BOLD"}, /* bold on */
- {"2", "+DIM"}, /* dim on */
- {"3", "+ITALIC"}, /* italic on */
- {"4", "+UNDERLINE"}, /* underline on */
- {"5", "+BLINK"}, /* blink on */
- {"6", "+FASTBLINK"}, /* fastblink on */
- {"7", "+REVERSE"}, /* reverse on */
- {"8", "+INVISIBLE"}, /* invisible on */
- {"9", "+DELETED"}, /* deleted on */
- {"10", "MAIN-FONT"}, /* select primary font */
- {"11", "ALT-FONT-1"}, /* select alternate font 1 */
- {"12", "ALT-FONT-2"}, /* select alternate font 2 */
- {"13", "ALT-FONT-3"}, /* select alternate font 3 */
- {"14", "ALT-FONT-4"}, /* select alternate font 4 */
- {"15", "ALT-FONT-5"}, /* select alternate font 5 */
- {"16", "ALT-FONT-6"}, /* select alternate font 6 */
- {"17", "ALT-FONT-7"}, /* select alternate font 7 */
- {"18", "ALT-FONT-1"}, /* select alternate font 1 */
- {"19", "ALT-FONT-1"}, /* select alternate font 1 */
- {"20", "FRAKTUR"}, /* Fraktur font */
- {"21", "DOUBLEUNDER"}, /* double underline */
- {"22", "-DIM"}, /* dim off */
- {"23", "-ITALIC"}, /* italic off */
- {"24", "-UNDERLINE"}, /* underline off */
- {"25", "-BLINK"}, /* blink off */
- {"26", "-FASTBLINK"}, /* fastblink off */
- {"27", "-REVERSE"}, /* reverse off */
- {"28", "-INVISIBLE"}, /* invisible off */
- {"29", "-DELETED"}, /* deleted off */
- {(char *) 0, (char *) 0}
+ DATA("0", "NORMAL"), /* normal */
+ DATA("1", "+BOLD"), /* bold on */
+ DATA("2", "+DIM"), /* dim on */
+ DATA("3", "+ITALIC"), /* italic on */
+ DATA("4", "+UNDERLINE"), /* underline on */
+ DATA("5", "+BLINK"), /* blink on */
+ DATA("6", "+FASTBLINK"), /* fastblink on */
+ DATA("7", "+REVERSE"), /* reverse on */
+ DATA("8", "+INVISIBLE"), /* invisible on */
+ DATA("9", "+DELETED"), /* deleted on */
+ DATA("10", "MAIN-FONT"), /* select primary font */
+ DATA("11", "ALT-FONT-1"), /* select alternate font 1 */
+ DATA("12", "ALT-FONT-2"), /* select alternate font 2 */
+ DATA("13", "ALT-FONT-3"), /* select alternate font 3 */
+ DATA("14", "ALT-FONT-4"), /* select alternate font 4 */
+ DATA("15", "ALT-FONT-5"), /* select alternate font 5 */
+ DATA("16", "ALT-FONT-6"), /* select alternate font 6 */
+ DATA("17", "ALT-FONT-7"), /* select alternate font 7 */
+ DATA("18", "ALT-FONT-1"), /* select alternate font 1 */
+ DATA("19", "ALT-FONT-1"), /* select alternate font 1 */
+ DATA("20", "FRAKTUR"), /* Fraktur font */
+ DATA("21", "DOUBLEUNDER"), /* double underline */
+ DATA("22", "-DIM"), /* dim off */
+ DATA("23", "-ITALIC"), /* italic off */
+ DATA("24", "-UNDERLINE"), /* underline off */
+ DATA("25", "-BLINK"), /* blink off */
+ DATA("26", "-FASTBLINK"), /* fastblink off */
+ DATA("27", "-REVERSE"), /* reverse off */
+ DATA("28", "-INVISIBLE"), /* invisible off */
+ DATA("29", "-DELETED"), /* deleted off */
+ DATAX()
};
+#undef DATA
+
static int
skip_csi(const char *cap)
{
@@ -757,7 +786,7 @@ lookup_params(const assoc * table, char *dst, char *src)
do {
bool found = FALSE;
- for (ap = table; ap->from; ap++) {
+ for (ap = table; ap->from[0]; ap++) {
size_t tlen = strlen(ap->from);
if (same_param(ap->from, ep, tlen)) {
@@ -781,7 +810,7 @@ lookup_params(const assoc * table, char *dst, char *src)
}
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;
@@ -812,7 +841,7 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp)
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))
@@ -839,7 +868,7 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp)
/* now check the standard capabilities */
if (!expansion) {
csi = skip_csi(sp);
- for (ap = std_caps; ap->from; ap++) {
+ for (ap = std_caps; ap->from[0]; ap++) {
size_t adj = (size_t) (csi ? 2 : 0);
len = strlen(ap->from);
@@ -868,7 +897,7 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp)
? "ECMA+"
: "ECMA-"),
sizeof(buf2));
- (void) strncpy(buf3, sp + csi, len);
+ _nc_STRNCPY(buf3, sp + csi, len);
buf3[len] = '\0';
len += (size_t) csi + 1;
@@ -889,7 +918,7 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp)
? "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;
@@ -905,7 +934,7 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp)
&& 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;
@@ -984,7 +1013,8 @@ file_comparison(int argc, char *argv[])
int i, n;
memset(heads, 0, sizeof(heads));
- dump_init((char *) 0, F_LITERAL, S_TERMINFO, 0, 65535, itrace, 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)
@@ -1155,37 +1185,45 @@ file_comparison(int argc, char *argv[])
static void
usage(void)
{
- static const char *tbl[] =
+#define DATA(s) s "\n"
+ static const char head[] =
+ {
+ DATA("Usage: infocmp [options] [-A directory] [-B directory] [termname...]")
+ DATA("")
+ DATA("Options:")
+ };
+#undef DATA
+#define DATA(s) s
+ static const char options[][45] =
{
- "Usage: infocmp [options] [-A directory] [-B directory] [termname...]"
- ,""
- ,"Options:"
- ," -0 print single-row"
+ " -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 eliminate post-processing of entries"
- ," -D print database locations"
+ ," -U do not post-process entries"
," -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"
@@ -1197,20 +1235,21 @@ usage(void)
," -v number (verbose)"
," -w number (width)"
#if NCURSES_XNAMES
- ," -x treat unknown capabilities as user-defined"
+ ," -x unknown capabilities are user-defined"
#endif
};
- const size_t first = 3;
- const size_t last = SIZEOF(tbl);
- const size_t left = (last - first + 1) / 2 + first;
+#undef DATA
+ const size_t last = SIZEOF(options);
+ const size_t left = (last + 1) / 2;
size_t n;
+ fputs(head, stderr);
for (n = 0; n < left; n++) {
- size_t m = (n < first) ? last : n + left - first;
+ size_t m = n + left;
if (m < last)
- fprintf(stderr, "%-40.40s%s\n", tbl[n], tbl[m]);
+ fprintf(stderr, "%-40.40s%s\n", options[n], options[m]);
else
- fprintf(stderr, "%s\n", tbl[n]);
+ fprintf(stderr, "%s\n", options[n]);
}
ExitProgram(EXIT_FAILURE);
}
@@ -1255,7 +1294,7 @@ string_variable(const char *type)
/* dump C initializers for the terminal type */
static void
-dump_initializers(TERMTYPE *term)
+dump_initializers(TERMTYPE2 *term)
{
unsigned n;
const char *str = 0;
@@ -1379,7 +1418,7 @@ dump_initializers(TERMTYPE *term)
/* 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");
@@ -1494,6 +1533,8 @@ main(int argc, char *argv[])
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;
@@ -1515,7 +1556,7 @@ main(int argc, char *argv[])
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;
@@ -1616,6 +1657,10 @@ main(int argc, char *argv[])
ignorepads = TRUE;
break;
+ case 'Q':
+ quickdump = optarg_to_number();
+ break;
+
case 'q':
quiet = TRUE;
s_absent = "-";
@@ -1676,6 +1721,10 @@ main(int argc, char *argv[])
set_trace_level(itrace);
break;
+ case 'W':
+ wrap_strings = TRUE;
+ break;
+
case 'w':
mwidth = optarg_to_number();
break;
@@ -1738,7 +1787,9 @@ main(int argc, char *argv[])
}
/* set up for display */
- dump_init(tversion, outform, sortmode, mwidth, mheight, itrace, formatted);
+ dump_init(tversion, outform, sortmode,
+ wrap_strings, mwidth, mheight, itrace,
+ formatted, FALSE, quickdump);
if (!filecompare) {
/* grab the entries */
@@ -1782,7 +1833,7 @@ main(int argc, char *argv[])
_nc_progname,
tname[termcount]);
- status = _nc_read_entry(tname[termcount],
+ status = _nc_read_entry2(tname[termcount],
tfile[termcount],
&entries[termcount].tterm);
}
@@ -1824,6 +1875,8 @@ main(int argc, char *argv[])
analyze_string("rs3", reset_3string, &entries[0].tterm);
analyze_string("smcup", enter_ca_mode, &entries[0].tterm);
analyze_string("rmcup", exit_ca_mode, &entries[0].tterm);
+ analyze_string("smkx", keypad_xmit, &entries[0].tterm);
+ analyze_string("rmkx", keypad_local, &entries[0].tterm);
#undef CUR
} else {
@@ -1837,8 +1890,10 @@ main(int argc, char *argv[])
"%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 55d7a9fb9694..dc7d61cf4a74 100644
--- a/progs/modules
+++ b/progs/modules
@@ -1,7 +1,7 @@
-# $Id: modules,v 1.17 2010/01/23 17:47:23 tom Exp $
+# $Id: modules,v 1.21 2016/12/24 17:33:59 tom Exp $
# Program modules (some are in ncurses lib!)
##############################################################################
-# Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. #
+# Copyright (c) 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,14 +32,18 @@
#
@ base
-clear progs $(srcdir) $(HEADER_DEPS)
-tic progs $(srcdir) $(HEADER_DEPS) transform.h $(srcdir)/dump_entry.h
+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
+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.c
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)
-tput progs $(srcdir) $(HEADER_DEPS) transform.h $(srcdir)/dump_entry.h termsort.c
-tset progs $(srcdir) $(HEADER_DEPS) transform.h $(srcdir)/dump_entry.h ../include/termcap.h
+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 reset_cmd.h tty_settings.h
+tset progs $(srcdir) $(HEADER_DEPS) transform.h $(srcdir)/dump_entry.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 3ead89f85d20..da34790275f3 100644
--- a/progs/progs.priv.h
+++ b/progs/progs.priv.h
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2011,2012 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2017,2019 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,13 +30,16 @@
* Author: Thomas E. Dickey 1997-on *
****************************************************************************/
/*
- * $Id: progs.priv.h,v 1.39 2012/02/22 22:11:27 tom Exp $
+ * $Id: progs.priv.h,v 1.47 2019/12/14 23:53:12 tom Exp $
*
* progs.priv.h
*
* Header file for curses utility programs
*/
+#ifndef PROGS_PRIV_H
+#define PROGS_PRIV_H 1
+
#include <ncurses_cfg.h>
#if USE_RCS_IDS
@@ -115,6 +118,9 @@ extern char *optarg;
extern int optind;
#endif /* HAVE_GETOPT_H */
+#define NCURSES_INTERNALS 1
+#define NCURSES_OPAQUE 0
+
#include <curses.h>
#include <term_entry.h>
#include <nc_termios.h>
@@ -123,15 +129,30 @@ extern int optind;
#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
+#define VtoTrace(opt) (unsigned) ((opt > 0) ? opt : (opt == 0))
+
+/* error-returns for tput */
+#define ErrUsage 2
+#define ErrTermType 3
+#define ErrCapName 4
+#define ErrSystem(n) (4 + (n))
+
+#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
@@ -200,3 +221,13 @@ extern int optind;
#define UChar(c) ((unsigned char)(c))
#define SIZEOF(v) (sizeof(v)/sizeof(v[0]))
+
+#define NCURSES_EXT_NUMBERS (NCURSES_EXT_COLORS && HAVE_INIT_EXTENDED_COLOR)
+
+#if NCURSES_EXT_NUMBERS
+#else
+#define _nc_free_termtype2(t) _nc_free_termtype(t)
+#define _nc_read_entry2(n,f,t) _nc_read_entry(n,f,t)
+#endif
+
+#endif /* PROGS_PRIV_H */
diff --git a/progs/reset_cmd.c b/progs/reset_cmd.c
new file mode 100644
index 000000000000..28829e72fe25
--- /dev/null
+++ b/progs/reset_cmd.c
@@ -0,0 +1,634 @@
+/****************************************************************************
+ * Copyright (c) 2016-2017,2019 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's only
+ in termio.h */
+#include <sys/stream.h>
+#include <sys/ptem.h>
+#endif
+
+MODULE_ID("$Id: reset_cmd.c,v 1.18 2019/07/13 21:35:13 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
+
+static FILE *my_file;
+
+static bool use_reset = FALSE; /* invoked as reset */
+static bool use_init = FALSE; /* invoked as init */
+
+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(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 = 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)
+
+/*
+ * 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)
+{
+ 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(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
+
+ tty_settings->c_iflag &= ~((unsigned) (IGNBRK
+ | PARMRK
+ | INPCK
+ | ISTRIP
+ | INLCR
+ | IGNCR
+#ifdef IUCLC
+ | IUCLC
+#endif
+#ifdef IXANY
+ | IXANY
+#endif
+ | IXOFF));
+
+ tty_settings->c_iflag |= (BRKINT
+ | IGNPAR
+ | ICRNL
+ | IXON
+#ifdef IMAXBEL
+ | IMAXBEL
+#endif
+ );
+
+ tty_settings->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
+ ));
+
+ tty_settings->c_oflag |= (OPOST
+#ifdef ONLCR
+ | ONLCR
+#endif
+ );
+
+ tty_settings->c_cflag &= ~((unsigned) (CSIZE
+ | CSTOPB
+ | PARENB
+ | PARODD
+ | CLOCAL));
+ tty_settings->c_cflag |= (CS8 | CREAD);
+ tty_settings->c_lflag &= ~((unsigned) (ECHONL
+ | NOFLSH
+#ifdef TOSTOP
+ | TOSTOP
+#endif
+#ifdef ECHOPTR
+ | ECHOPRT
+#endif
+#ifdef XCASE
+ | XCASE
+#endif
+ ));
+
+ tty_settings->c_lflag |= (ISIG
+ | ICANON
+ | ECHO
+ | ECHOE
+ | ECHOK
+#ifdef ECHOCTL
+ | ECHOCTL
+#endif
+#ifdef ECHOKE
+ | ECHOKE
+#endif
+ );
+#endif
+
+ 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 (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);
+ }
+}
+
+/*
+ * 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)
+{
+#ifdef ONLCR
+ tty_settings->c_oflag |= ONLCR;
+#endif
+ tty_settings->c_iflag |= ICRNL;
+ tty_settings->c_lflag |= ECHO;
+#ifdef OXTABS
+ tty_settings->c_oflag |= OXTABS;
+#endif /* OXTABS */
+
+ /* test used to be tgetflag("NL") */
+ if (VALID_STRING(newline) && newline[0] == '\n' && !newline[1]) {
+ /* Newline, not linefeed. */
+#ifdef ONLCR
+ tty_settings->c_oflag &= ~((unsigned) ONLCR);
+#endif
+ tty_settings->c_iflag &= ~((unsigned) ICRNL);
+ }
+#ifdef OXTABS
+ /* test used to be tgetflag("pt") */
+ if (VALID_STRING(set_tab) && VALID_STRING(clear_all_tabs))
+ tty_settings->c_oflag &= ~OXTABS;
+#endif /* OXTABS */
+ tty_settings->c_lflag |= (ECHOE | ECHOK);
+}
+
+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;
+#ifdef 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);
+ } else
+#if defined(set_lr_margin)
+ if (VALID_STRING(set_lr_margin)) {
+ need_flush |= sent_string(TPARM_2(set_lr_margin, 0,
+ columns - 1));
+ } else
+#endif
+#if defined(set_left_margin_parm) && defined(set_right_margin_parm)
+ if (VALID_STRING(set_left_margin_parm)
+ && VALID_STRING(set_right_margin_parm)) {
+ need_flush |= sent_string(TPARM_1(set_left_margin_parm, 0));
+ need_flush |= sent_string(TPARM_1(set_right_margin_parm,
+ columns - 1));
+ } else
+#endif
+ 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(TPARM_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, newer;
+ char *p;
+
+ newer = new_settings->c_cc[which];
+ older = old_settings->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));
+}
+
+/**************************************************************************
+ * 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)
+{
+ 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);
+}
+
+#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, short *high, short *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 000000000000..f5426eb8d04b
--- /dev/null
+++ b/progs/reset_cmd.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+ * Copyright (c) 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.7 2016/12/24 18:08:48 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 */);
+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 */, short * /* high */, short * /* wide */);
+#endif
+
+extern const char *_nc_progname;
+
+/* *INDENT-ON* */
+
+#endif /* RESET_CMD_H */
diff --git a/progs/tabs.c b/progs/tabs.c
index 7ed3007549d8..01325c329cb9 100644
--- a/progs/tabs.c
+++ b/progs/tabs.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 2008-2012,2013 Free Software Foundation, Inc. *
+ * Copyright (c) 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 +36,13 @@
#define USE_LIBTINFO
#include <progs.priv.h>
+#include <tty_settings.h>
-MODULE_ID("$Id: tabs.c,v 1.34 2013/06/11 08:18:27 tom Exp $")
+MODULE_ID("$Id: tabs.c,v 1.41 2017/10/12 22:42:08 tom Exp $")
static void usage(void) GCC_NORETURN;
-static char *prg_name;
+const char *_nc_progname;
static int max_cols;
static void
@@ -79,7 +80,7 @@ do_tabs(int *tab_list)
break;
}
}
- putchar('\n');
+ putchar('\r');
}
static int *
@@ -103,7 +104,7 @@ decode_tabs(const char *tab_list)
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;
@@ -288,6 +289,7 @@ add_to_tab_list(char **append, const char *value)
*append = result;
}
+ free(copied);
return result;
}
@@ -307,17 +309,17 @@ legal_tab_list(const char *tab_list)
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);
+ fprintf(stderr, "%s: no tab-list given\n", _nc_progname);
result = FALSE;
}
return result;
@@ -338,36 +340,35 @@ skip_list(char *value)
static void
usage(void)
{
- static const char *msg[] =
+#define DATA(s) s "\n"
+ static const char msg[] =
{
- "Usage: tabs [options] [tabstop-list]"
- ,""
- ,"Options:"
- ," -0 reset tabs"
- ," -8 set tabs to standard interval"
- ," -a Assembler, IBM S/370, first format"
- ," -a2 Assembler, IBM S/370, second format"
- ," -c COBOL, normal format"
- ," -c2 COBOL compact format"
- ," -c3 COBOL compact format extended"
- ," -d debug (show ruler with expected/actual tab positions)"
- ," -f FORTRAN"
- ," -n no-op (do not modify terminal settings)"
- ," -p PL/I"
- ," -s SNOBOL"
- ," -u UNIVAC 1100 Assembler"
- ," -T name use terminal type 'name'"
- ," -V print version"
- ,""
- ,"A tabstop-list is an ordered list of column numbers, e.g., 1,11,21"
- ,"or 1,+10,+10 which is the same."
+ DATA("Usage: tabs [options] [tabstop-list]")
+ DATA("")
+ DATA("Options:")
+ DATA(" -0 reset tabs")
+ DATA(" -8 set tabs to standard interval")
+ DATA(" -a Assembler, IBM S/370, first format")
+ DATA(" -a2 Assembler, IBM S/370, second format")
+ DATA(" -c COBOL, normal format")
+ DATA(" -c2 COBOL compact format")
+ DATA(" -c3 COBOL compact format extended")
+ DATA(" -d debug (show ruler with expected/actual tab positions)")
+ DATA(" -f FORTRAN")
+ DATA(" -n no-op (do not modify terminal settings)")
+ DATA(" -p PL/I")
+ DATA(" -s SNOBOL")
+ DATA(" -u UNIVAC 1100 Assembler")
+ DATA(" -T name use terminal type 'name'")
+ DATA(" -V print version")
+ DATA("")
+ DATA("A tabstop-list is an ordered list of column numbers, e.g., 1,11,21")
+ DATA("or 1,+10,+10 which is the same.")
};
- unsigned n;
+#undef DATA
fflush(stdout);
- for (n = 0; n < SIZEOF(msg); ++n) {
- fprintf(stderr, "%s\n", msg[n]);
- }
+ fputs(msg, stderr);
ExitProgram(EXIT_FAILURE);
}
@@ -381,8 +382,12 @@ main(int argc, char *argv[])
NCURSES_CONST char *term_name = 0;
char *append = 0;
const char *tab_list = 0;
+ TTY tty_settings;
+ int fd;
+
+ _nc_progname = _nc_rootname(argv[0]);
- prg_name = _nc_rootname(argv[0]);
+ fd = save_tty_settings(&tty_settings, FALSE);
if ((term_name = getenv("TERM")) == 0)
term_name = "ansi+tabs";
@@ -453,7 +458,7 @@ main(int argc, char *argv[])
if (*++option != '\0') {
term_name = option;
} else {
- term_name = argv[n++];
+ term_name = argv[n];
option--;
}
option += ((int) strlen(option)) - 1;
@@ -506,18 +511,18 @@ main(int argc, char *argv[])
}
}
- setupterm(term_name, STDOUT_FILENO, (int *) 0);
+ setupterm(term_name, fd, (int *) 0);
max_cols = (columns > 0) ? columns : 80;
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);
diff --git a/progs/tic.c b/progs/tic.c
index fef78ee0745e..c66a4ef4cdb9 100644
--- a/progs/tic.c
+++ b/progs/tic.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2018,2019 Free Software Foundation, Inc. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the *
@@ -43,10 +43,12 @@
#include <sys/stat.h>
#include <dump_entry.h>
+#include <tparm_type.h>
#include <hashed_db.h>
+#include <parametrized.h>
#include <transform.h>
-MODULE_ID("$Id: tic.c,v 1.189 2013/11/16 19:58:09 tom Exp $")
+MODULE_ID("$Id: tic.c,v 1.281 2019/11/09 18:51:36 tom Exp $")
#define STDIN_NAME "<stdin>"
@@ -57,11 +59,16 @@ static FILE *tmp_fp;
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] \
@@ -112,6 +119,7 @@ cleanup(void)
#if NO_LEAKS
free_namelist(namelst);
+ _nc_leaks_dump_entry();
#endif
if (tmp_fp != 0)
fclose(tmp_fp);
@@ -136,50 +144,52 @@ failed(const char *msg)
static void
usage(void)
{
- static const char *const tbl[] =
+#define DATA(s) s "\n"
+ static const char options_string[] =
{
- "Options:",
- " -1 format translation output one capability per line",
+ DATA("Options:")
+ DATA(" -0 format translation output all capabilities on one line")
+ DATA(" -1 format translation output one capability per line")
#if NCURSES_XNAMES
- " -a retain commented-out capabilities (sets -x also)",
+ DATA(" -a retain commented-out capabilities (sets -x also)")
#endif
- " -K translate entries to termcap source form with BSD syntax",
- " -C translate entries to termcap source form",
- " -D print list of tic's database locations (first must be writable)",
- " -c check only, validate input without compiling or translating",
- " -e<names> translate/compile only entries named by comma-separated list",
- " -f format complex strings for readability",
- " -G format %{number} to %'char'",
- " -g format %'char' to %{number}",
- " -I translate entries to terminfo source form",
- " -L translate entries to full terminfo source form",
- " -N disable smart defaults for source translation",
- " -o<dir> set output directory for compiled entry writes",
- " -R<name> restrict translation to given terminfo/termcap version",
- " -r force resolution of all use entries in source translation",
- " -s print summary statistics",
- " -T remove size-restrictions on compiled description",
+ DATA(" -C translate entries to termcap source form")
+ DATA(" -D print list of tic's database locations (first must be writable)")
+ DATA(" -c check only, validate input without compiling or translating")
+ DATA(" -e<names> translate/compile only entries named by comma-separated list")
+ DATA(" -f format complex strings for readability")
+ DATA(" -G format %{number} to %'char'")
+ DATA(" -g format %'char' to %{number}")
+ DATA(" -I translate entries to terminfo source form")
+ DATA(" -K translate entries to termcap source form with BSD syntax")
+ 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")
+ DATA(" -T remove size-restrictions on compiled description")
#if NCURSES_XNAMES
- " -t suppress commented-out capabilities",
+ DATA(" -t suppress commented-out capabilities")
#endif
- " -U suppress post-processing of entries",
- " -V print version",
- " -v[n] set verbosity level",
- " -w[n] set format width for translation output",
+ 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
- " -x treat unknown capabilities as user-defined",
+ DATA(" -x treat unknown capabilities as user-defined")
#endif
- "",
- "Parameters:",
- " <file> file to translate or compile"
+ DATA("")
+ DATA("Parameters:")
+ DATA(" <file> file to translate or compile")
};
- size_t j;
+#undef DATA
fprintf(stderr, "Usage: %s %s\n", _nc_progname, usage_string);
- for (j = 0; j < SIZEOF(tbl); j++) {
- fputs(tbl[j], stderr);
- putc('\n', stderr);
- }
+ fputs(options_string, stderr);
ExitProgram(EXIT_FAILURE);
}
@@ -208,7 +218,8 @@ write_it(ENTRY * ep)
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;
@@ -450,7 +461,7 @@ open_input(const char *filename, char *alt_file)
fprintf(stderr, "%s: %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_IFREG && mode != S_IFCHR && mode != S_IFIFO)) {
fprintf(stderr, "%s: %s is not a file\n", _nc_progname, filename);
ExitProgram(EXIT_FAILURE);
} else {
@@ -659,7 +670,11 @@ show_databases(const char *outdir)
}
}
-#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[])
@@ -667,7 +682,6 @@ 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;
@@ -689,6 +703,9 @@ main(int argc, char *argv[])
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;
@@ -714,14 +731,17 @@ main(int argc, char *argv[])
* 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) {
@@ -772,6 +792,9 @@ main(int argc, char *argv[])
smart_defaults = FALSE;
literal = TRUE;
break;
+ case 'Q':
+ quickdump = 0;
+ break;
case 'R':
tversion = optarg;
break;
@@ -784,6 +807,9 @@ main(int argc, char *argv[])
case 'V':
puts(curses_version());
ExitProgram(EXIT_SUCCESS);
+ case 'W':
+ wrap_strings = TRUE;
+ break;
case 'c':
check_only = TRUE;
break;
@@ -802,6 +828,9 @@ main(int argc, char *argv[])
case 'o':
outdir = optarg;
break;
+ case 'q':
+ quiet = TRUE;
+ break;
case 'r':
forceresolve = TRUE;
break;
@@ -824,6 +853,7 @@ main(int argc, char *argv[])
/* FALLTHRU */
case 'x':
use_extended_names(TRUE);
+ using_extensions = TRUE;
break;
#endif
default:
@@ -907,16 +937,20 @@ main(int argc, char *argv[])
}
}
- if (infodump) {
+ if (infodump || check_only) {
dump_init(tversion,
- smart_defaults
- ? outform
- : F_LITERAL,
- sortmode, width, height, debug_level, formatted);
+ (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);
+ sortmode,
+ wrap_strings, width, height,
+ debug_level, FALSE, FALSE, FALSE);
}
/* parse entries out of the source file */
@@ -939,14 +973,15 @@ main(int argc, char *argv[])
}
/* length check */
- if (check_only && (capdump || infodump)) {
+ if (check_only && limited && (capdump || infodump)) {
for_entry_list(qp) {
if (matches(namelst, qp->tterm.term_names)) {
int len = fmt_entry(&qp->tterm, NULL, FALSE, TRUE, infodump, numbers);
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);
}
@@ -954,7 +989,21 @@ main(int argc, char *argv[])
}
/* write or dump all entries */
- if (!check_only) {
+ if (check_only) {
+ /* this is in case infotocap() generates warnings */
+ _nc_curr_col = _nc_curr_line = -1;
+
+ for_entry_list(qp) {
+ if (matches(namelst, qp->tterm.term_names)) {
+ /* this is in case infotocap() generates warnings */
+ _nc_set_type(_nc_first_name(qp->tterm.term_names));
+ _nc_curr_line = (int) qp->startline;
+ repair_acsc(&qp->tterm);
+ dump_entry(&qp->tterm, suppress_untranslatable,
+ limited, numbers, NULL);
+ }
+ }
+ } else {
if (!infodump && !capdump) {
_nc_set_writedir(outdir);
for_entry_list(qp) {
@@ -973,12 +1022,18 @@ main(int argc, char *argv[])
/* 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);
@@ -991,7 +1046,7 @@ main(int argc, char *argv[])
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;
@@ -1043,8 +1098,52 @@ main(int argc, char *argv[])
* 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];
@@ -1079,12 +1178,35 @@ check_acs(TERMTYPE *tp)
}
}
+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 = strdup(TPARM_1(oldcap, n));
+ char *newvalue = strdup(TPARM_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)))
_nc_warning("inconsistent values for max_colors (%d) and max_pairs (%d)",
@@ -1095,25 +1217,66 @@ check_colors(TERMTYPE *tp)
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");
}
+ if (can_change) {
+ if (!VALID_STRING(initialize_pair) &&
+ !VALID_STRING(initialize_color)) {
+ _nc_warning("expected initc or initp because ccc is given");
+ }
+ } else {
+ if (VALID_STRING(initialize_pair) ||
+ VALID_STRING(initialize_color)) {
+ _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
@@ -1158,7 +1321,6 @@ check_ansi_cursor(char *list[4])
{
int j, k;
int want;
- size_t prefix = 0;
size_t suffix;
bool skip[4];
bool repeated = FALSE;
@@ -1176,16 +1338,8 @@ check_ansi_cursor(char *list[4])
}
if (!repeated) {
char *up = list[1];
+ size_t prefix = (size_t) csi_length(up);
- 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])))
@@ -1227,7 +1381,7 @@ check_ansi_cursor(char *list[4])
#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);
@@ -1239,7 +1393,7 @@ check_noaddress(TERMTYPE *tp, const char *why)
}
static void
-check_cursor(TERMTYPE *tp)
+check_cursor(TERMTYPE2 *tp)
{
int count;
char *list[4];
@@ -1358,7 +1512,7 @@ check_cursor(TERMTYPE *tp)
* is mapped inconsistently.
*/
static void
-check_keypad(TERMTYPE *tp)
+check_keypad(TERMTYPE2 *tp)
{
char show[80];
@@ -1468,31 +1622,67 @@ check_keypad(TERMTYPE *tp)
}
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 */
+#if defined(set_bottom_margin_parm) && defined(set_bottom_margin)
ANDMISSING(set_bottom_margin_parm, set_bottom_margin);
+#endif
+#if defined(set_left_margin_parm) && defined(set_left_margin)
ANDMISSING(set_left_margin_parm, set_left_margin);
+#endif
+#if defined(set_right_margin_parm) && defined(set_right_margin)
ANDMISSING(set_right_margin_parm, set_right_margin);
+#endif
+#if defined(set_top_margin_parm) && defined(set_top_margin)
ANDMISSING(set_top_margin_parm, set_top_margin);
+#endif
+#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)
{
@@ -1504,9 +1694,8 @@ uses_SGR_39_49(const char *value)
* 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");
@@ -1514,6 +1703,9 @@ check_screen(TERMTYPE *tp)
bool have_kmouse = FALSE;
bool use_sgr_39_49 = FALSE;
char *name = _nc_first_name(tp->term_names);
+ bool is_screen = !strncmp(name, "screen", 6);
+ bool screen_base = (is_screen
+ && strchr(name, '.') == 0);
if (!VALID_BOOLEAN(have_bce)) {
have_bce = FALSE;
@@ -1534,32 +1726,35 @@ check_screen(TERMTYPE *tp)
}
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) {
+ 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");
+ _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");
+ _nc_warning("expected orig_colors capability with XT to have 39/49 parameters");
if (VALID_STRING(to_status_line))
_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, '+') == 0) {
+ _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.
@@ -1567,78 +1762,81 @@ check_screen(TERMTYPE *tp)
static int
expected_params(const char *name)
{
+#define DATA(name,count) { { name }, count }
/* *INDENT-OFF* */
static const struct {
- const char *name;
+ const char name[9];
int count;
} table[] = {
- { "S0", 1 }, /* 'screen' extension */
- { "birep", 2 },
- { "chr", 1 },
- { "colornm", 1 },
- { "cpi", 1 },
- { "csnm", 1 },
- { "csr", 2 },
- { "cub", 1 },
- { "cud", 1 },
- { "cuf", 1 },
- { "cup", 2 },
- { "cuu", 1 },
- { "cvr", 1 },
- { "cwin", 5 },
- { "dch", 1 },
- { "defc", 3 },
- { "dial", 1 },
- { "dispc", 1 },
- { "dl", 1 },
- { "ech", 1 },
- { "getm", 1 },
- { "hpa", 1 },
- { "ich", 1 },
- { "il", 1 },
- { "indn", 1 },
- { "initc", 4 },
- { "initp", 7 },
- { "lpi", 1 },
- { "mc5p", 1 },
- { "mrcup", 2 },
- { "mvpa", 1 },
- { "pfkey", 2 },
- { "pfloc", 2 },
- { "pfx", 2 },
- { "pfxl", 3 },
- { "pln", 2 },
- { "qdial", 1 },
- { "rcsd", 1 },
- { "rep", 2 },
- { "rin", 1 },
- { "sclk", 3 },
- { "scp", 1 },
- { "scs", 1 },
- { "scsd", 2 },
- { "setab", 1 },
- { "setaf", 1 },
- { "setb", 1 },
- { "setcolor", 1 },
- { "setf", 1 },
- { "sgr", 9 },
- { "sgr1", 6 },
- { "slength", 1 },
- { "slines", 1 },
- { "smgbp", 1 }, /* 2 if smgtp is not given */
- { "smglp", 1 },
- { "smglr", 2 },
- { "smgrp", 1 },
- { "smgtb", 2 },
- { "smgtp", 1 },
- { "tsl", 1 },
- { "u6", -1 },
- { "vpa", 1 },
- { "wind", 4 },
- { "wingo", 1 },
+ DATA( "S0", 1 ), /* 'screen' extension */
+ DATA( "birep", 2 ),
+ DATA( "chr", 1 ),
+ DATA( "colornm", 1 ),
+ DATA( "cpi", 1 ),
+ DATA( "csnm", 1 ),
+ DATA( "csr", 2 ),
+ DATA( "cub", 1 ),
+ DATA( "cud", 1 ),
+ DATA( "cuf", 1 ),
+ DATA( "cup", 2 ),
+ DATA( "cuu", 1 ),
+ DATA( "cvr", 1 ),
+ DATA( "cwin", 5 ),
+ DATA( "dch", 1 ),
+ DATA( "defc", 3 ),
+ DATA( "dial", 1 ),
+ DATA( "dispc", 1 ),
+ DATA( "dl", 1 ),
+ DATA( "ech", 1 ),
+ DATA( "getm", 1 ),
+ DATA( "hpa", 1 ),
+ DATA( "ich", 1 ),
+ DATA( "il", 1 ),
+ DATA( "indn", 1 ),
+ DATA( "initc", 4 ),
+ DATA( "initp", 7 ),
+ DATA( "lpi", 1 ),
+ DATA( "mc5p", 1 ),
+ DATA( "mrcup", 2 ),
+ DATA( "mvpa", 1 ),
+ DATA( "pfkey", 2 ),
+ DATA( "pfloc", 2 ),
+ DATA( "pfx", 2 ),
+ DATA( "pfxl", 3 ),
+ DATA( "pln", 2 ),
+ DATA( "qdial", 1 ),
+ DATA( "rcsd", 1 ),
+ DATA( "rep", 2 ),
+ DATA( "rin", 1 ),
+ DATA( "sclk", 3 ),
+ DATA( "scp", 1 ),
+ DATA( "scs", 1 ),
+ DATA( "scsd", 2 ),
+ DATA( "setab", 1 ),
+ DATA( "setaf", 1 ),
+ DATA( "setb", 1 ),
+ DATA( "setcolor", 1 ),
+ DATA( "setf", 1 ),
+ DATA( "sgr", 9 ),
+ DATA( "sgr1", 6 ),
+ DATA( "slength", 1 ),
+ DATA( "slines", 1 ),
+ DATA( "smgbp", 1 ), /* 2 if smgtp is not given */
+ DATA( "smglp", 1 ),
+ DATA( "smglr", 2 ),
+ DATA( "smgrp", 1 ),
+ DATA( "smgtb", 2 ),
+ DATA( "smgtp", 1 ),
+ DATA( "tsl", 1 ),
+ DATA( "u6", -1 ),
+ DATA( "vpa", 1 ),
+ DATA( "wind", 4 ),
+ DATA( "wingo", 1 ),
};
/* *INDENT-ON* */
+#undef DATA
+
unsigned n;
int result = 0; /* function-keys, etc., use none */
@@ -1653,17 +1851,65 @@ expected_params(const char *name)
}
/*
+ * 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;
+}
+
+/*
* 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, char *value, int extended)
{
int expected = expected_params(name);
int actual = 0;
int n;
- bool params[10];
+ bool params[NUM_PARM];
char *s = value;
#ifdef set_top_margin_parm
@@ -1672,7 +1918,7 @@ check_params(TERMTYPE *tp, const char *name, char *value)
expected = 2;
#endif
- for (n = 0; n < 10; n++)
+ for (n = 0; n < NUM_PARM; n++)
params[n] = FALSE;
while (*s != 0) {
@@ -1695,6 +1941,22 @@ check_params(TERMTYPE *tp, const char *name, char *value)
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);
}
@@ -1708,6 +1970,422 @@ check_params(TERMTYPE *tp, const char *name, char *value)
_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.
+ */
+ if (actual >= 0) {
+ char *p_is_s[NUM_PARM];
+ int popcount;
+ int analyzed = _nc_tparm_analyze(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);
+ }
+ }
+ }
+}
+
+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;
+}
+
+/*
+ * 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 maybe = TRUE;
+ bool mixed = FALSE;
+ int proportional = 0;
+ int mandatory = 0;
+
+ first = p;
+
+ for (q = base; *q != '\0'; ++q) {
+ if (*q == '>') {
+ if (mark == 0)
+ mark = q;
+ break;
+ } else if (*q == '*' || *q == '/') {
+ if (*q == '*')
+ ++proportional;
+ if (*q == '/')
+ ++mandatory;
+ if (mark == 0)
+ mark = q;
+ } else if (!(isalnum(UChar(*q)) || strchr("+-.", *q) != 0)) {
+ maybe = FALSE;
+ break;
+ } else if (proportional || mandatory) {
+ mixed = TRUE;
+ }
+ }
+ last = *q ? (q + 1) : q;
+ if (*q == '\0') {
+ maybe = FALSE; /* just an isolated "$<" */
+ } else if (maybe) {
+ float check_f;
+ char check_c;
+ int rc = sscanf(base, "%f%c", &check_f, &check_c);
+ if ((rc != 2) || (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), '+') == 0) {
+ _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 &&
+ (q = skip_DECSCNM(p, &flag)) != 0 &&
+ flag == 0) {
+ _nc_warning("expected a delay in %s", name);
+ }
+ }
+ }
+}
+
+static char *
+check_1_infotocap(const char *name, NCURSES_CONST char *value, int count)
+{
+ int k;
+ int ignored;
+ long numbers[1 + NUM_PARM];
+ char *strings[1 + NUM_PARM];
+ char *p_is_s[NUM_PARM];
+ char *result;
+ char blob[NUM_PARM * 10];
+ char *next = blob;
+
+ *next++ = '\0';
+ for (k = 1; k <= NUM_PARM; k++) {
+ numbers[k] = 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)) {
+ case Num_Str:
+ result = TPARM_2(value, numbers[1], strings[2]);
+ break;
+ case Num_Str_Str:
+ result = TPARM_3(value, numbers[1], strings[2], strings[3]);
+ break;
+ case Numbers:
+ 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),
+ myParam(2),
+ myParam(3),
+ myParam(4),
+ myParam(5),
+ myParam(6),
+ myParam(7),
+ myParam(8),
+ myParam(9));
+ break;
+ }
+ return strdup(result);
+}
+
+#define IsDelay(ch) ((ch) == '.' || isdigit(UChar(ch)))
+
+static const char *
+parse_delay_value(const char *src, double *delays, int *always)
+{
+ int star = 0;
+
+ *delays = 0.0;
+ if (always)
+ *always = 0;
+
+ while (isdigit(UChar(*src))) {
+ (*delays) = (*delays) * 10 + (*src++ - '0');
+ }
+ if (*src == '.') {
+ int gotdot = 1;
+
+ ++src;
+ while (isdigit(UChar(*src))) {
+ gotdot *= 10;
+ (*delays) += (*src++ - '0') / gotdot;
+ }
+ }
+ while (*src == '*' || *src == '/') {
+ if (always == 0 && *src == '/')
+ break;
+ if (*src++ == '*') {
+ star = 1;
+ } else {
+ *always = 1;
+ }
+ }
+ if (star)
+ *delays = -(*delays);
+ return src;
+}
+
+static const char *
+parse_ti_delay(const char *ti, double *delays)
+{
+ *delays = 0.0;
+ while (*ti != '\0') {
+ if (*ti == '\\') {
+ ++ti;
+ }
+ if (ti[0] == '$'
+ && ti[1] == '<'
+ && IsDelay(UChar(ti[2]))) {
+ int ignored;
+ const char *last = parse_delay_value(ti + 2, delays, &ignored);
+ if (*last == '>') {
+ ti = last;
+ }
+ } else {
+ ++ti;
+ }
+ }
+ return ti;
+}
+
+static const char *
+parse_tc_delay(const char *tc, double *delays)
+{
+ return parse_delay_value(tc, delays, (int *) 0);
+}
+
+/*
+ * Compare terminfo- and termcap-strings, factoring out delays.
+ */
+static bool
+same_ti_tc(const char *ti, const char *tc, bool * embedded)
+{
+ bool same = TRUE;
+ double ti_delay = 0.0;
+ double tc_delay = 0.0;
+ const char *ti_last;
+
+ *embedded = FALSE;
+ ti_last = parse_ti_delay(ti, &ti_delay);
+ tc = parse_tc_delay(tc, &tc_delay);
+
+ while ((ti < ti_last) && *tc) {
+ if (*ti == '\\' && ispunct(UChar(ti[1]))) {
+ ++ti;
+ if ((*ti == '^') && !strncmp(tc, "\\136", 4)) {
+ ti += 1;
+ tc += 4;
+ continue;
+ }
+ } else if (ti[0] == '$' && ti[1] == '<') {
+ double no_delay;
+ const char *ss = parse_ti_delay(ti, &no_delay);
+ if (ss != ti) {
+ *embedded = TRUE;
+ ti = ss;
+ continue;
+ }
+ }
+ if (*tc == '\\' && ispunct(UChar(tc[1]))) {
+ ++tc;
+ }
+ if (*ti++ != *tc++) {
+ same = FALSE;
+ break;
+ }
+ }
+
+ if (*embedded) {
+ if (same) {
+ same = FALSE;
+ } else {
+ *embedded = FALSE; /* report only one problem */
+ }
+ }
+
+ return same;
+}
+
+/*
+ * Check terminfo to termcap translation.
+ */
+static void
+check_infotocap(TERMTYPE2 *tp, int i, const char *value)
+{
+ const char *name = ExtStrname(tp, i, strnames);
+ int params = ((i < (int) SIZEOF(parametrized))
+ ? parametrized[i]
+ : ((*value == 'k')
+ ? 0
+ : has_params(value)));
+ int to_char = 0;
+ char *ti_value;
+ char *tc_value;
+ bool embedded;
+
+ assert(SIZEOF(parametrized) == STRCOUNT);
+ if ((ti_value = _nc_tic_expand(value, TRUE, to_char)) == ABSENT_STRING) {
+ _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;
+
+ if (!strcmp(name, "setf")
+ || !strcmp(name, "setb")
+ || !strcmp(name, "setaf")
+ || !strcmp(name, "setab")) {
+ if ((limit = max_colors) > 16)
+ limit = 16;
+ }
+ 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", ti_value);
+ fprintf(stderr, "...tc '%s'\n", tc_value);
+ first = FALSE;
+ }
+ _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);
+ }
+ }
}
static char *
@@ -1755,6 +2433,23 @@ ignore_delays(char *s)
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
@@ -1764,19 +2459,6 @@ ignore_delays(char *s)
static bool
similar_sgr(int num, char *a, char *b)
{
- static const char *names[] =
- {
- "none"
- ,"standout"
- ,"underline"
- ,"reverse"
- ,"blink"
- ,"dim"
- ,"bold"
- ,"invis"
- ,"protect"
- ,"altcharset"
- };
char *base_a = a;
char *base_b = b;
int delaying = 0;
@@ -1784,12 +2466,14 @@ similar_sgr(int num, char *a, char *b)
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));
}
@@ -1825,7 +2509,7 @@ similar_sgr(int num, char *a, char *b)
}
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;
@@ -1891,12 +2575,12 @@ typedef struct {
} 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)
failed("get_fkey_list");
@@ -1912,7 +2596,7 @@ get_fkey_list(TERMTYPE *tp)
}
#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;
@@ -1936,41 +2620,45 @@ show_fkey_name(NAME_VALUE * data)
}
}
-/* other sanity-checks (things that we don't want in the normal
- * logic that reads a terminfo entry)
+/*
+ * A terminal entry may contain more than one keycode assigned to a given
+ * string (e.g., KEY_END and KEY_LL). But curses will only return one (the
+ * last one assigned).
*/
static void
-check_termtype(TERMTYPE *tp, bool literal)
+check_conflict(TERMTYPE2 *tp)
{
bool conflict = FALSE;
unsigned j, k;
- /*
- * A terminal entry may contain more than one keycode assigned to
- * a given string (e.g., KEY_END and KEY_LL). But curses will only
- * return one (the last one assigned).
- */
if (!(_nc_syntax == SYN_TERMCAP && capdump)) {
char *check = calloc((size_t) (NUM_STRINGS(tp) + 1), sizeof(char));
NAME_VALUE *given = get_fkey_list(tp);
if (check == 0)
- failed("check_termtype");
+ 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, "...");
@@ -1987,15 +2675,258 @@ check_termtype(TERMTYPE *tp, bool literal)
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
+
+/* other sanity-checks (things that we don't want in the normal
+ * logic that reads a terminfo entry)
+ */
+static void
+check_termtype(TERMTYPE2 *tp, bool literal)
+{
+ unsigned j;
+
+ check_conflict(tp);
for_each_string(j, tp) {
char *a = tp->Strings[j];
- if (VALID_STRING(a))
- check_params(tp, ExtStrname(tp, (int) j, strnames), a);
+ if (VALID_STRING(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);
@@ -2005,6 +2936,12 @@ check_termtype(TERMTYPE *tp, bool literal)
check_screen(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
* restoring the cursor visibility by resetting it.
*/
@@ -2059,7 +2996,7 @@ check_termtype(TERMTYPE *tp, bool literal)
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);
@@ -2072,13 +3009,27 @@ check_termtype(TERMTYPE *tp, bool literal)
("will trim sgr0\n\toriginal sgr0=%s\n\ttrimmed sgr0=%s",
_nc_visbuf2(1, exit_attribute_mode),
_nc_visbuf2(2, check_sgr0)));
- free(check_sgr0);
} else {
DEBUG(2,
("will not trim sgr0\n\toriginal sgr0=%s",
_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);
@@ -2105,7 +3056,7 @@ check_termtype(TERMTYPE *tp, bool literal)
* 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.c b/progs/toe.c
index 0d299b457dfb..7b9f79ad6d8d 100644
--- a/progs/toe.c
+++ b/progs/toe.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. *
+ * Copyright (c) 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 *
@@ -44,7 +44,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.78 2018/11/17 22:41:46 tom Exp $")
#define isDotname(name) (!strcmp(name, ".") || !strcmp(name, ".."))
@@ -252,10 +252,10 @@ make_db_name(char *dst, const char *src, unsigned limit)
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 +270,7 @@ term_description(TERMTYPE *tp)
/* 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 +294,7 @@ string_sum(const char *value)
}
static unsigned long
-checksum_of(TERMTYPE *tp)
+checksum_of(TERMTYPE2 *tp)
{
unsigned long result = string_sum(tp->term_names);
unsigned i;
@@ -313,7 +313,7 @@ checksum_of(TERMTYPE *tp)
/* 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();
@@ -327,7 +327,7 @@ sorthook(int db_index, int db_limit, const char *term_name, TERMTYPE *tp)
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 +424,7 @@ typelist(int eargc, char *eargv[],
}
while ((entry = readdir(entrydir)) != 0) {
char *name_2;
- TERMTYPE lterm;
+ TERMTYPE2 lterm;
char *cn;
int status;
@@ -440,11 +440,8 @@ typelist(int eargc, char *eargv[],
(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 +450,7 @@ typelist(int eargc, char *eargv[],
/* 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 +475,7 @@ typelist(int eargc, char *eargv[],
code = _nc_db_first(capdbp, &key, &data);
while (code == 0) {
- TERMTYPE lterm;
+ TERMTYPE2 lterm;
int used;
char *have;
char *cn;
@@ -489,7 +486,7 @@ typelist(int eargc, char *eargv[],
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 +497,8 @@ typelist(int eargc, char *eargv[],
}
}
}
-#endif
-#endif
+#endif /* USE_HASHED_DB */
+#endif /* NCURSES_USE_DATABASE */
#if NCURSES_USE_TERMCAP
#if HAVE_BSD_CGETENT
{
@@ -703,6 +700,8 @@ main(int argc, char *argv[])
_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 +727,8 @@ main(int argc, char *argv[])
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
new file mode 100644
index 000000000000..125e43c26179
--- /dev/null
+++ b/progs/tparm_type.c
@@ -0,0 +1,71 @@
+/****************************************************************************
+ * Copyright (c) 1998-2013,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 *
+ ****************************************************************************/
+
+#include <tparm_type.h>
+
+MODULE_ID("$Id: tparm_type.c,v 1.2 2015/04/04 15:01:13 tom Exp $")
+
+/*
+ * Lookup the type of call we should make to tparm(). This ignores the actual
+ * terminfo capability (bad, because it is not extensible), but makes this
+ * code portable to platforms where sizeof(int) != sizeof(char *).
+ */
+TParams
+tparm_type(const char *name)
+{
+#define TD(code, longname, ti, tc) \
+ {code, {longname} }, \
+ {code, {ti} }, \
+ {code, {tc} }
+ TParams result = Numbers;
+ /* *INDENT-OFF* */
+ static const struct {
+ TParams code;
+ const char name[12];
+ } table[] = {
+ TD(Num_Str, "pkey_key", "pfkey", "pk"),
+ TD(Num_Str, "pkey_local", "pfloc", "pl"),
+ TD(Num_Str, "pkey_xmit", "pfx", "px"),
+ TD(Num_Str, "plab_norm", "pln", "pn"),
+ TD(Num_Str_Str, "pkey_plab", "pfxl", "xl"),
+ };
+ /* *INDENT-ON* */
+
+ unsigned n;
+ for (n = 0; n < SIZEOF(table); n++) {
+ if (!strcmp(name, table[n].name)) {
+ result = table[n].code;
+ break;
+ }
+ }
+ return result;
+}
diff --git a/progs/tparm_type.h b/progs/tparm_type.h
new file mode 100644
index 000000000000..d1431683ad45
--- /dev/null
+++ b/progs/tparm_type.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+ * Copyright (c) 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 *
+ * "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: tparm_type.h,v 1.1 2014/05/21 16:57:56 tom Exp $
+ *
+ * determine expected/actual number of parameters to setup for tparm
+ */
+#ifndef TPARM_TYPE_H
+#define TPARM_TYPE_H 1
+
+#define USE_LIBTINFO
+#include <progs.priv.h>
+
+typedef enum {
+ Numbers = 0
+ ,Num_Str
+ ,Num_Str_Str
+} TParams;
+
+extern TParams tparm_type(const char *name);
+
+#endif /* TPARM_TYPE_H */
diff --git a/progs/tput.c b/progs/tput.c
index 6652d3450a2d..da90dcf07be2 100644
--- a/progs/tput.c
+++ b/progs/tput.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2018,2019 Free Software Foundation, Inc. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the *
@@ -29,6 +29,7 @@
/****************************************************************************
* Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
* and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
****************************************************************************/
/*
@@ -38,30 +39,27 @@
* Ross Ridge's mytinfo package.
*/
-#define USE_LIBTINFO
-#include <progs.priv.h>
+#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.49 2013/09/28 20:57:25 tom Exp $")
+MODULE_ID("$Id: tput.c,v 1.80 2019/07/28 18:18:41 tom Exp $")
#define PUTS(s) fputs(s, stdout)
-#define PUTCHAR(c) putchar(c)
-#define FLUSH fflush(stdout)
-typedef enum {
- Numbers = 0
- ,Num_Str
- ,Num_Str_Str
-} TParams;
+const char *_nc_progname = "tput";
static char *prg_name;
static bool is_init = FALSE;
static bool is_reset = FALSE;
+static bool is_clear = FALSE;
static void
quit(int status, const char *fmt,...)
@@ -79,47 +77,42 @@ quit(int status, const char *fmt,...)
static void
usage(void)
{
- 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(" -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", prg_name);
+ 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);
-}
-
-/*
- * Lookup the type of call we should make to tparm(). This ignores the actual
- * terminfo capability (bad, because it is not extensible), but makes this
- * code portable to platforms where sizeof(int) != sizeof(char *).
- */
-static TParams
-tparm_type(const char *name)
-{
-#define TD(code, longname, ti, tc) {code,longname},{code,ti},{code,tc}
- TParams result = Numbers;
- /* *INDENT-OFF* */
- static const struct {
- TParams code;
- const char *name;
- } table[] = {
- TD(Num_Str, "pkey_key", "pfkey", "pk"),
- TD(Num_Str, "pkey_local", "pfloc", "pl"),
- TD(Num_Str, "pkey_xmit", "pfx", "px"),
- TD(Num_Str, "plab_norm", "pln", "pn"),
- TD(Num_Str_Str, "pkey_plab", "pfxl", "xl"),
- };
- /* *INDENT-ON* */
-
- unsigned n;
- for (n = 0; n < SIZEOF(table); n++) {
- if (!strcmp(name, table[n].name)) {
- result = table[n].code;
- break;
- }
- }
+ 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;
}
@@ -142,121 +135,46 @@ exit_code(int token, int value)
return result;
}
+/*
+ * Returns nonzero on error.
+ */
static int
-tput(int argc, char *argv[])
+tput_cmd(int fd, TTY * saved_settings, bool opt_x, int argc, char *argv[])
{
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);
if (is_reset || is_init) {
- if (init_prog != 0) {
- system(init_prog);
- }
- FLUSH;
+ TTY oldmode;
- 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, saved_settings);
+ } 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
+ set_window_size(fd, &lines, &columns);
+#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;
-
- 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;
- }
+ set_control_chars(saved_settings, terasechar, intrchar, tkillchar);
+ set_conversions(saved_settings);
+ 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, saved_settings);
return 0;
}
@@ -267,7 +185,9 @@ tput(int argc, char *argv[])
#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);
@@ -281,26 +201,23 @@ tput(int argc, char *argv[])
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;
@@ -313,7 +230,7 @@ tput(int argc, char *argv[])
* 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);
@@ -366,33 +283,48 @@ main(int argc, char **argv)
int c;
char buf[BUFSIZ];
int result = 0;
+ int fd;
+ TTY tty_settings;
+ bool opt_x = FALSE; /* clear scrollback if possible */
+ bool is_alias;
+ bool need_tty;
- check_aliases(prg_name = _nc_rootname(argv[0]));
+ prg_name = check_aliases(_nc_rootname(argv[0]), TRUE);
term = getenv("TERM");
- while ((c = getopt(argc, argv, "ST:V")) != -1) {
+ while ((c = getopt(argc, argv, "ST:Vx")) != -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 'x': /* do not try to clear scrollback */
+ opt_x = TRUE;
+ break;
default:
usage();
/* NOTREACHED */
}
}
+ is_alias = (is_clear || is_reset || is_init);
+ 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;
@@ -404,15 +336,17 @@ main(int argc, char **argv)
}
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");
+
+ fd = save_tty_settings(&tty_settings, need_tty);
- if (setupterm(term, STDOUT_FILENO, &errret) != OK && errret <= 0)
- quit(3, "unknown terminal \"%s\"", term);
+ if (setupterm(term, fd, &errret) != OK && errret <= 0)
+ quit(ErrTermType, "unknown terminal \"%s\"", term);
if (cmdline) {
- if ((argc <= 0) && !is_reset && !is_init)
+ if ((argc <= 0) && !is_alias)
usage();
- ExitProgram(tput(argc, argv));
+ ExitProgram(tput_cmd(fd, &tty_settings, opt_x, argc, argv));
}
while (fgets(buf, sizeof(buf), stdin) != 0) {
@@ -433,9 +367,9 @@ main(int argc, char **argv)
argvec[argnum] = 0;
if (argnum != 0
- && tput(argnum, argvec) != 0) {
+ && tput_cmd(fd, &tty_settings, opt_x, argnum, argvec) != 0) {
if (result == 0)
- result = 4; /* will return value >4 */
+ result = ErrSystem(0); /* will return value >4 */
++result;
}
}
diff --git a/progs/tset.c b/progs/tset.c
index f01acd721091..10696e9da2d9 100644
--- a/progs/tset.c
+++ b/progs/tset.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. *
+ * Copyright (c) 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,14 +85,10 @@
* 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
#include <ttyent.h>
@@ -101,76 +97,18 @@
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.93 2013/12/15 01:05:56 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.120 2017/10/08 00:01:29 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 void exit_error(void) GCC_NORETURN;
+
static int
CaselessCmp(const char *a, const char *b)
{ /* strcasecmp isn't portable */
@@ -186,8 +124,7 @@ CaselessCmp(const char *a, const char *b)
static void
exit_error(void)
{
- if (can_restore)
- SET_TTY(STDERR_FILENO, &original);
+ restore_tty_settings();
(void) fprintf(stderr, "\n");
fflush(stderr);
ExitProgram(EXIT_FAILURE);
@@ -218,33 +155,12 @@ failed(const char *msg)
} 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)
@@ -307,87 +223,135 @@ typedef struct map {
static MAP *cur, *maplist;
+#define DATA(name,value) { { name }, value }
+
typedef struct speeds {
- const char *string;
+ const char string[7];
int speed;
} SPEEDS;
static const SPEEDS speeds[] =
{
- {"0", B0},
- {"50", B50},
- {"75", B75},
- {"110", B110},
- {"134", B134},
- {"134.5", B134},
- {"150", B150},
- {"200", B200},
- {"300", B300},
- {"600", B600},
- {"1200", B1200},
- {"1800", B1800},
- {"2400", B2400},
- {"4800", B4800},
- {"9600", B9600},
+ DATA("0", B0),
+ DATA("50", B50),
+ DATA("75", B75),
+ DATA("110", B110),
+ DATA("134", B134),
+ DATA("134.5", B134),
+ DATA("150", B150),
+ DATA("200", B200),
+ DATA("300", B300),
+ DATA("600", B600),
+ DATA("1200", B1200),
+ DATA("1800", B1800),
+ DATA("2400", B2400),
+ DATA("4800", B4800),
+ DATA("9600", B9600),
/* sgttyb may define up to this point */
#ifdef B19200
- {"19200", B19200},
+ DATA("19200", B19200),
#endif
#ifdef B38400
- {"38400", B38400},
+ DATA("38400", B38400),
#endif
#ifdef B19200
- {"19200", B19200},
+ DATA("19200", B19200),
#endif
#ifdef B38400
- {"38400", B38400},
+ DATA("38400", B38400),
#endif
#ifdef B19200
- {"19200", B19200},
+ DATA("19200", B19200),
#else
#ifdef EXTA
- {"19200", EXTA},
+ DATA("19200", EXTA),
#endif
#endif
#ifdef B38400
- {"38400", B38400},
+ DATA("38400", B38400),
#else
#ifdef EXTB
- {"38400", EXTB},
+ DATA("38400", EXTB),
#endif
#endif
#ifdef B57600
- {"57600", B57600},
+ DATA("57600", B57600),
+#endif
+#ifdef B76800
+ DATA("76800", B57600),
#endif
#ifdef B115200
- {"115200", B115200},
+ DATA("115200", B115200),
+#endif
+#ifdef B153600
+ DATA("153600", B153600),
#endif
#ifdef B230400
- {"230400", B230400},
+ DATA("230400", B230400),
+#endif
+#ifdef B307200
+ DATA("307200", B307200),
#endif
#ifdef B460800
- {"460800", 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
- {(char *) 0, 0}
};
+#undef DATA
static int
tbaudrate(char *rate)
{
- const SPEEDS *sp;
- int found = FALSE;
+ const SPEEDS *sp = 0;
+ size_t n;
/* The baudrate number can be preceded by a 'B', which is ignored. */
if (*rate == 'B')
++rate;
- for (sp = speeds; sp->string; ++sp) {
- if (!CaselessCmp(rate, sp->string)) {
- found = TRUE;
+ 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;
}
}
- if (!found)
+ if (sp == 0)
err("unknown baud rate %s", rate);
return (sp->speed);
}
@@ -566,7 +530,7 @@ mapped(const char *type)
* its termcap entry.
*/
static const char *
-get_termcap_entry(char *userarg)
+get_termcap_entry(int fd, char *userarg)
{
int errret;
char *p;
@@ -578,6 +542,8 @@ get_termcap_entry(char *userarg)
#endif
char *ttypath;
+ (void) fd;
+
if (userarg) {
ttype = userarg;
goto found;
@@ -587,7 +553,7 @@ get_termcap_entry(char *userarg)
if ((ttype = getenv("TERM")) != 0)
goto map;
- if ((ttypath = ttyname(STDERR_FILENO)) != 0) {
+ if ((ttypath = ttyname(fd)) != 0) {
p = _nc_basename(ttypath);
#if HAVE_GETTTYNAM
/*
@@ -662,7 +628,7 @@ get_termcap_entry(char *userarg)
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",
@@ -684,453 +650,11 @@ get_termcap_entry(char *userarg)
/**************************************************************************
*
- * 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) (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.
*/
@@ -1165,29 +689,58 @@ obsolete(char **argv)
}
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)
{
- static const char *tbl[] =
+#define SKIP(s) /* nothing */
+#define KEEP(s) s "\n"
+ static const char msg[] =
{
- ""
- ,"Options:"
- ," -c set control characters"
- ," -e ch erase character"
- ," -I no initialization strings"
- ," -i ch interrupt character"
- ," -k ch kill character"
- ," -m mapping map identifier to type"
- ," -Q do not output control key settings"
- ," -r display term on stderr"
- ," -s output TERM set command"
- ," -V print curses-version"
- ," -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.")
};
- unsigned n;
+#undef KEEP
+#undef SKIP
(void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname);
- for (n = 0; n < sizeof(tbl) / sizeof(tbl[0]); ++n)
- fprintf(stderr, "%s\n", tbl[n]);
- exit_error();
+ fputs(msg, stderr);
+ ExitProgram(EXIT_FAILURE);
/* NOTREACHED */
}
@@ -1203,12 +756,19 @@ int
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;
+
+ my_fd = STDERR_FILENO;
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;
@@ -1234,8 +794,6 @@ main(int argc, char **argv)
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;
@@ -1276,10 +834,8 @@ main(int argc, char **argv)
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);
#else
@@ -1287,83 +843,55 @@ main(int argc, char **argv)
#endif
if (same_program(_nc_progname, PROG_RESET)) {
- isreset = TRUE;
- reset_mode();
+ reset_start(stderr, TRUE, FALSE);
+ reset_tty_settings(my_fd, &mode);
+ } 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) = tlines;
- WINSIZE_COLS(win) = tcolumns;
- (void) ioctl(STDERR_FILENO, IOCTL_SET_WINSIZE, &win);
- }
+ set_window_size(my_fd, &lines, &columns);
}
#endif
if (opt_c) {
- set_control_chars();
- set_conversions();
-
- if (!noinit)
- set_init();
-
- /* Set the modes if they've changed. */
- if (memcmp(&mode, &oldmode, sizeof(mode))) {
- SET_TTY(STDERR_FILENO, &mode);
+ set_control_chars(&mode, terasechar, intrchar, tkillchar);
+ set_conversions(&mode);
+
+ if (!noinit) {
+ if (send_init_strings(my_fd, &oldmode)) {
+ (void) putc('\r', stderr);
+ (void) fflush(stderr);
+ (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 000000000000..23daefa07ac8
--- /dev/null
+++ b/progs/tty_settings.c
@@ -0,0 +1,104 @@
+/****************************************************************************
+ * Copyright (c) 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.5 2017/10/07 20:55:57 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) &&
+ !get_tty_settings(open("/dev/tty", O_RDWR), tty_settings)) {
+ if (need_tty) {
+ 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 000000000000..b0731078a3d4
--- /dev/null
+++ b/progs/tty_settings.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+ * Copyright (c) 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.2 2017/10/07 19:11:31 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 */