aboutsummaryrefslogtreecommitdiff
path: root/ncurses/tinfo
diff options
context:
space:
mode:
Diffstat (limited to 'ncurses/tinfo')
-rw-r--r--ncurses/tinfo/MKcaptab.awk94
-rw-r--r--ncurses/tinfo/MKcaptab.sh149
-rw-r--r--ncurses/tinfo/MKcodes.awk161
-rwxr-xr-xncurses/tinfo/MKfallback.sh129
-rwxr-xr-xncurses/tinfo/MKkeys_list.sh62
-rw-r--r--ncurses/tinfo/MKnames.awk183
-rw-r--r--ncurses/tinfo/README36
-rw-r--r--ncurses/tinfo/access.c176
-rw-r--r--ncurses/tinfo/add_tries.c120
-rw-r--r--ncurses/tinfo/alloc_entry.c289
-rw-r--r--ncurses/tinfo/alloc_ttype.c495
-rw-r--r--ncurses/tinfo/captoinfo.c847
-rw-r--r--ncurses/tinfo/comp_error.c153
-rw-r--r--ncurses/tinfo/comp_expand.c192
-rw-r--r--ncurses/tinfo/comp_hash.c366
-rw-r--r--ncurses/tinfo/comp_parse.c490
-rw-r--r--ncurses/tinfo/comp_scan.c915
-rw-r--r--ncurses/tinfo/db_iterator.c225
-rw-r--r--ncurses/tinfo/doalloc.c75
-rw-r--r--ncurses/tinfo/entries.c144
-rw-r--r--ncurses/tinfo/free_ttype.c77
-rw-r--r--ncurses/tinfo/getenv_num.c56
-rw-r--r--ncurses/tinfo/hashed_db.c260
-rw-r--r--ncurses/tinfo/home_terminfo.c69
-rw-r--r--ncurses/tinfo/init_keytry.c110
-rw-r--r--ncurses/tinfo/lib_acs.c193
-rw-r--r--ncurses/tinfo/lib_baudrate.c235
-rw-r--r--ncurses/tinfo/lib_cur_term.c76
-rw-r--r--ncurses/tinfo/lib_data.c294
-rw-r--r--ncurses/tinfo/lib_has_cap.c65
-rw-r--r--ncurses/tinfo/lib_kernel.c154
-rw-r--r--ncurses/tinfo/lib_longname.c57
-rw-r--r--ncurses/tinfo/lib_napms.c74
-rw-r--r--ncurses/tinfo/lib_options.c270
-rw-r--r--ncurses/tinfo/lib_print.c92
-rw-r--r--ncurses/tinfo/lib_raw.c296
-rw-r--r--ncurses/tinfo/lib_setup.c618
-rw-r--r--ncurses/tinfo/lib_termcap.c290
-rw-r--r--ncurses/tinfo/lib_termname.c44
-rw-r--r--ncurses/tinfo/lib_tgoto.c203
-rw-r--r--ncurses/tinfo/lib_ti.c103
-rw-r--r--ncurses/tinfo/lib_tparm.c791
-rw-r--r--ncurses/tinfo/lib_tputs.c258
-rw-r--r--ncurses/tinfo/lib_ttyflags.c210
-rw-r--r--ncurses/tinfo/make_keys.c142
-rw-r--r--ncurses/tinfo/name_match.c108
-rw-r--r--ncurses/tinfo/parse_entry.c991
-rw-r--r--ncurses/tinfo/read_entry.c544
-rw-r--r--ncurses/tinfo/read_termcap.c1174
-rw-r--r--ncurses/tinfo/setbuf.c150
-rw-r--r--ncurses/tinfo/strings.c142
-rw-r--r--ncurses/tinfo/trim_sgr0.c326
-rw-r--r--ncurses/tinfo/use_screen.c60
-rw-r--r--ncurses/tinfo/write_entry.c773
54 files changed, 14606 insertions, 0 deletions
diff --git a/ncurses/tinfo/MKcaptab.awk b/ncurses/tinfo/MKcaptab.awk
new file mode 100644
index 000000000000..56d3d17754d1
--- /dev/null
+++ b/ncurses/tinfo/MKcaptab.awk
@@ -0,0 +1,94 @@
+##############################################################################
+# Copyright (c) 1998-2006,2007 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. #
+##############################################################################
+# $Id: MKcaptab.awk,v 1.20 2007/08/12 00:26:15 tom Exp $
+function add_string(text) {
+ if (text != "IGNORE") {
+ offsets[num_strings] = offset;
+ offset = offset + length(text) + 1;
+ printf "%s\\0", text;
+ } else {
+ offsets[num_strings] = -1;
+ }
+ num_strings = num_strings + 1;
+ if ((num_strings % 3) == 0) {
+ printf "\\\n";
+ }
+ return offsets[num_strings - 1];
+}
+BEGIN {
+ first = 1;
+ num_aliases = 0;
+ num_strings = 0;
+ offset = 0;
+}
+
+/^[^#]/ {
+ if (first) {
+ printf "/* generated by MKcaptab.awk %s(%d) */\n", tablename, bigstrings;
+ print ""
+ if (bigstrings) {
+ printf "static struct alias *_nc_%s_table = 0;\n", tablename;
+ print "";
+ printf "static const char %s_text[] = \"\\\n", tablename;
+ } else {
+ printf "static const struct alias _nc_%s_table[] =\n", tablename;
+ printf "{\n";
+ }
+ first = 0;
+ }
+ if ($1 == tablename) {
+ if ($3 == "IGNORE") {
+ to = "(char *)NULL";
+ } else {
+ to = "\"" $3 "\"";
+ }
+ if (bigstrings) {
+ c1 = add_string($2);
+ c2 = add_string($3);
+ c3 = add_string($4);
+ aliases[num_aliases] = sprintf("\t{%5d, %5d, %5d},\t /* %s */", c1, c2, c3, $5);
+ num_aliases = num_aliases + 1;
+ } else {
+ printf "\t{\"%s\", %s, \"%s\"},\t /* %s */\n", $2, to, $4, $5;
+ }
+ }
+ }
+END {
+ if (bigstrings) {
+ printf "\";\n\n";
+ printf "static const alias_table_data %s_data[] = {\n", tablename;
+ for (n = 0; n < num_aliases; ++n) {
+ printf "%s\n", aliases[n];
+ }
+ printf "};\n\n";
+ } else {
+ printf "\t{(char *)NULL, (char *)NULL, (char *)NULL}\n";
+ printf "};\n\n";
+ }
+ }
+# vile:sw=4:
diff --git a/ncurses/tinfo/MKcaptab.sh b/ncurses/tinfo/MKcaptab.sh
new file mode 100644
index 000000000000..98c04e884309
--- /dev/null
+++ b/ncurses/tinfo/MKcaptab.sh
@@ -0,0 +1,149 @@
+#!/bin/sh
+##############################################################################
+# Copyright (c) 2007 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. #
+##############################################################################
+# $Id: MKcaptab.sh,v 1.8 2007/08/12 13:13:51 tom Exp $
+AWK=${1-awk}
+OPT1=${2-0}
+OPT2=${3-tinfo/MKcaptab.awk}
+DATA=${4-../include/Caps}
+
+cat <<'EOF'
+/*
+ * comp_captab.c -- The names of the capabilities indexed via a hash
+ * table for the compiler.
+ *
+ */
+
+#include <curses.priv.h>
+#include <tic.h>
+#include <hashsize.h>
+
+EOF
+
+./make_hash 1 info $OPT1 <$DATA
+./make_hash 3 cap $OPT1 <$DATA
+
+$AWK -f $OPT2 bigstrings=$OPT1 tablename=capalias <$DATA
+
+$AWK -f $OPT2 bigstrings=$OPT1 tablename=infoalias <$DATA
+
+cat <<EOF
+
+#if $OPT1
+static void
+next_string(const char *strings, unsigned *offset)
+{
+ *offset += strlen(strings + *offset) + 1;
+}
+
+static const struct name_table_entry *
+_nc_build_names(struct name_table_entry **actual,
+ const name_table_data *source,
+ const char *strings)
+{
+ if (*actual == 0) {
+ *actual = typeCalloc(struct name_table_entry, CAPTABSIZE);
+ if (*actual != 0) {
+ unsigned n;
+ unsigned len = 0;
+ for (n = 0; n < CAPTABSIZE; ++n) {
+ (*actual)[n].nte_name = strings + len;
+ (*actual)[n].nte_type = source[n].nte_type;
+ (*actual)[n].nte_index = source[n].nte_index;
+ (*actual)[n].nte_link = source[n].nte_link;
+ next_string(strings, &len);
+ }
+ }
+ }
+ return *actual;
+}
+
+#define add_alias(field) \\
+ if (source[n].field >= 0) { \\
+ (*actual)[n].field = strings + source[n].field; \\
+ }
+
+static const struct alias *
+_nc_build_alias(struct alias **actual,
+ const alias_table_data *source,
+ const char *strings,
+ unsigned tablesize)
+{
+ if (*actual == 0) {
+ *actual = typeCalloc(struct alias, tablesize + 1);
+ if (*actual != 0) {
+ unsigned n;
+ for (n = 0; n < tablesize; ++n) {
+ add_alias(from);
+ add_alias(to);
+ add_alias(source);
+ }
+ }
+ }
+ return *actual;
+}
+
+#define build_names(root) _nc_build_names(&_nc_##root##_table, \\
+ root##_names_data, \\
+ root##_names_text)
+#define build_alias(root) _nc_build_alias(&_nc_##root##alias_table, \\
+ root##alias_data, \\
+ root##alias_text, \\
+ SIZEOF(root##alias_data))
+#else
+#define build_names(root) _nc_ ## root ## _table
+#define build_alias(root) _nc_ ## root ## alias_table
+#endif
+
+NCURSES_EXPORT(const struct name_table_entry *) _nc_get_table (bool termcap)
+{
+ return termcap ? build_names(cap) : build_names(info) ;
+}
+
+NCURSES_EXPORT(const short *) _nc_get_hash_table (bool termcap)
+{
+ return termcap ? _nc_cap_hash_table: _nc_info_hash_table ;
+}
+
+NCURSES_EXPORT(const struct alias *) _nc_get_alias_table (bool termcap)
+{
+ return termcap ? build_alias(cap) : build_alias(info) ;
+}
+
+#if NO_LEAKS
+NCURSES_EXPORT(void) _nc_comp_captab_leaks(void)
+{
+#if $OPT1
+ FreeIfNeeded(_nc_cap_table);
+ FreeIfNeeded(_nc_info_table);
+ FreeIfNeeded(_nc_capalias_table);
+ FreeIfNeeded(_nc_infoalias_table);
+#endif
+}
+#endif /* NO_LEAKS */
+EOF
diff --git a/ncurses/tinfo/MKcodes.awk b/ncurses/tinfo/MKcodes.awk
new file mode 100644
index 000000000000..db8ad5541841
--- /dev/null
+++ b/ncurses/tinfo/MKcodes.awk
@@ -0,0 +1,161 @@
+##############################################################################
+# Copyright (c) 1998-2006,2007 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. #
+##############################################################################
+# $Id: MKcodes.awk,v 1.4 2007/11/03 20:24:15 tom Exp $
+function large_item(value) {
+ result = sprintf("%d,", offset);
+ offset = offset + length(value) + 1;
+ offcol = offcol + length(result) + 2;
+ if (offcol > 70) {
+ result = result "\n";
+ offcol = 0;
+ } else {
+ result = result " ";
+ }
+ bigstr = bigstr sprintf("\"%s\\0\" ", value);
+ bigcol = bigcol + length(value) + 5;
+ if (bigcol > 70) {
+ bigstr = bigstr "\\\n";
+ bigcol = 0;
+ }
+ return result;
+}
+
+function small_item(value) {
+ return sprintf("\t\t\"%s\",\n", value);
+}
+
+function print_strings(name,value) {
+ printf "DCL(%s) = {\n", name
+ print value
+ print "\t\t(NCURSES_CONST char *)0,"
+ print "};"
+ print ""
+}
+
+function print_offsets(name,value) {
+ printf "static const short _nc_offset_%s[] = {\n", name
+ printf "%s", value
+ print "};"
+ print ""
+ printf "static NCURSES_CONST char ** ptr_%s = 0;\n", name
+ print ""
+}
+
+BEGIN {
+ print "/* This file was generated by MKcodes.awk */"
+ print ""
+ print "#include <curses.priv.h>"
+ print ""
+ print "#define IT NCURSES_CONST char * const"
+ print ""
+ offset = 0;
+ offcol = 0;
+ bigcol = 0;
+ }
+
+$1 ~ /^#/ {next;}
+
+$1 == "SKIPWARN" {next;}
+
+$3 == "bool" {
+ small_boolcodes = small_boolcodes small_item($4);
+ large_boolcodes = large_boolcodes large_item($4);
+ }
+
+$3 == "num" {
+ small_numcodes = small_numcodes small_item($4);
+ large_numcodes = large_numcodes large_item($4);
+ }
+
+$3 == "str" {
+ small_strcodes = small_strcodes small_item($4);
+ large_strcodes = large_strcodes large_item($4);
+ }
+
+END {
+ print ""
+ print "#if BROKEN_LINKER || USE_REENTRANT"
+ print ""
+ print "#include <term.h>"
+ print ""
+ if (bigstrings) {
+ printf "static const char _nc_code_blob[] = \n"
+ printf "%s;\n", bigstr;
+ print_offsets("boolcodes", large_boolcodes);
+ print_offsets("numcodes", large_numcodes);
+ print_offsets("strcodes", large_strcodes);
+ print ""
+ print "static IT *"
+ print "alloc_array(NCURSES_CONST char ***value, const short *offsets, unsigned size)"
+ print "{"
+ print " if (*value == 0) {"
+ print " if ((*value = typeCalloc(NCURSES_CONST char *, size + 1)) != 0) {"
+ print " unsigned n;"
+ print " for (n = 0; n < size; ++n) {"
+ print " (*value)[n] = _nc_code_blob + offsets[n];"
+ print " }"
+ print " }"
+ print " }"
+ print " return *value;"
+ print "}"
+ print ""
+ print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API _nc_##it(void) { return alloc_array(&ptr_##it, _nc_offset_##it, SIZEOF(_nc_offset_##it)); }"
+ } else {
+ print "#define DCL(it) static IT data##it[]"
+ print ""
+ print_strings("boolcodes", small_boolcodes);
+ print_strings("numcodes", small_numcodes);
+ print_strings("strcodes", small_strcodes);
+ print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API _nc_##it(void) { return data##it; }"
+ }
+ print ""
+ print "FIX(boolcodes)"
+ print "FIX(numcodes)"
+ print "FIX(strcodes)"
+ print ""
+ print "#define FREE_FIX(it) if (ptr_##it) { FreeAndNull(ptr_##it); }"
+ print ""
+ print "NCURSES_EXPORT(void)"
+ print "_nc_codes_leaks(void)"
+ print "{"
+ if (bigstrings) {
+ print "FREE_FIX(boolcodes)"
+ print "FREE_FIX(numcodes)"
+ print "FREE_FIX(strcodes)"
+ }
+ print "}"
+ print "#else"
+ print ""
+ print "#define DCL(it) NCURSES_EXPORT_VAR(IT) it[]"
+ print ""
+ print_strings("boolcodes", small_boolcodes);
+ print_strings("numcodes", small_numcodes);
+ print_strings("strcodes", small_strcodes);
+ print ""
+ print "#endif /* BROKEN_LINKER */"
+ }
diff --git a/ncurses/tinfo/MKfallback.sh b/ncurses/tinfo/MKfallback.sh
new file mode 100755
index 000000000000..9feab3507cc0
--- /dev/null
+++ b/ncurses/tinfo/MKfallback.sh
@@ -0,0 +1,129 @@
+#!/bin/sh
+##############################################################################
+# Copyright (c) 1998-2001,2006 Free Software Foundation, Inc. #
+# #
+# Permission is hereby granted, free of charge, to any person obtaining a #
+# copy of this software and associated documentation files (the "Software"), #
+# 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. #
+##############################################################################
+# $Id: MKfallback.sh,v 1.13 2006/07/15 16:54:20 tom Exp $
+#
+# MKfallback.sh -- create fallback table for entry reads
+#
+# This script generates source code for a custom version of read_entry.c
+# that (instead of reading capabilities for an argument terminal type
+# from an on-disk terminfo tree) tries to match the type with one of a
+# specified list of types generated in.
+#
+
+terminfo_dir=$1
+shift
+
+terminfo_src=$1
+shift
+
+if test $# != 0 ; then
+ tmp_info=tmp_info
+ echo creating temporary terminfo directory... >&2
+
+ TERMINFO=`pwd`/$tmp_info
+ export TERMINFO
+
+ TERMINFO_DIRS=$TERMINFO:$terminfo_dir
+ export TERMINFO_DIRS
+
+ tic -x $terminfo_src >&2
+else
+ tmp_info=
+fi
+
+cat <<EOF
+/*
+ * DO NOT EDIT THIS FILE BY HAND! It is generated by MKfallback.sh.
+ */
+
+#include <curses.priv.h>
+#include <term.h>
+
+EOF
+
+if [ "$*" ]
+then
+ cat <<EOF
+#include <tic.h>
+
+/* fallback entries for: $* */
+EOF
+ for x in $*
+ do
+ echo "/* $x */"
+ infocmp -E $x
+ done
+
+ cat <<EOF
+static const TERMTYPE fallbacks[$#] =
+{
+EOF
+ comma=""
+ for x in $*
+ do
+ echo "$comma /* $x */"
+ infocmp -e $x
+ comma=","
+ done
+
+ cat <<EOF
+};
+
+EOF
+fi
+
+cat <<EOF
+NCURSES_EXPORT(const TERMTYPE *) _nc_fallback (const char *name GCC_UNUSED)
+{
+EOF
+
+if [ "$*" ]
+then
+ cat <<EOF
+ const TERMTYPE *tp;
+
+ for (tp = fallbacks;
+ tp < fallbacks + sizeof(fallbacks)/sizeof(TERMTYPE);
+ tp++)
+ if (_nc_name_match(tp->term_names, name, "|"))
+ return(tp);
+EOF
+else
+ echo " /* the fallback list is empty */";
+fi
+
+cat <<EOF
+ return((TERMTYPE *)0);
+}
+EOF
+
+if test -n "$tmp_info" ; then
+ echo removing temporary terminfo directory... >&2
+ rm -rf $tmp_info
+fi
diff --git a/ncurses/tinfo/MKkeys_list.sh b/ncurses/tinfo/MKkeys_list.sh
new file mode 100755
index 000000000000..14017b016896
--- /dev/null
+++ b/ncurses/tinfo/MKkeys_list.sh
@@ -0,0 +1,62 @@
+#! /bin/sh
+# $Id: MKkeys_list.sh,v 1.4 2003/10/25 16:19:54 tom Exp $
+##############################################################################
+# Copyright (c) 2001,2003 Free Software Foundation, Inc. #
+# #
+# Permission is hereby granted, free of charge, to any person obtaining a #
+# copy of this software and associated documentation files (the "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. #
+##############################################################################
+#
+# MKkey_defs.sh -- generate list of function-keys for terminfo database
+#
+# Author: Thomas E. Dickey 2001
+#
+# Extract function-key names from the Caps file
+#
+: ${AWK-awk}
+DATA=${1-../../include/Caps}
+
+data=data$$
+trap 'rm -f $data' 0 1 2 5 15
+sed -e 's/[ ][ ]*/ /g' < $DATA >$data
+
+cat <<EOF
+# These definitions were generated by $0 $DATA
+KEY_BREAK
+KEY_SRESET
+KEY_RESET
+KEY_RESIZE
+EOF
+
+${AWK-awk} <$data '
+/^#/ {next;}
+/^capalias/ {next;}
+/^infoalias/ {next;}
+
+$5 != "-" {
+ if (substr($5, 1, 4) == "KEY_" ) {
+ printf "%s %s\n", $5, $1
+ }
+}
+'
diff --git a/ncurses/tinfo/MKnames.awk b/ncurses/tinfo/MKnames.awk
new file mode 100644
index 000000000000..93e682c2d28d
--- /dev/null
+++ b/ncurses/tinfo/MKnames.awk
@@ -0,0 +1,183 @@
+##############################################################################
+# Copyright (c) 2007 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. #
+##############################################################################
+# $Id: MKnames.awk,v 1.18 2007/11/03 20:24:15 tom Exp $
+function large_item(value) {
+ result = sprintf("%d,", offset);
+ offset = offset + length(value) + 1;
+ offcol = offcol + length(result) + 2;
+ if (offcol > 70) {
+ result = result "\n";
+ offcol = 0;
+ } else {
+ result = result " ";
+ }
+ bigstr = bigstr sprintf("\"%s\\0\" ", value);
+ bigcol = bigcol + length(value) + 5;
+ if (bigcol > 70) {
+ bigstr = bigstr "\\\n";
+ bigcol = 0;
+ }
+ return result;
+}
+
+function small_item(value) {
+ return sprintf("\t\t\"%s\",\n", value);
+}
+
+function print_strings(name,value) {
+ printf "DCL(%s) = {\n", name
+ print value
+ print "\t\t(NCURSES_CONST char *)0,"
+ print "};"
+ print ""
+}
+
+function print_offsets(name,value) {
+ printf "static const short _nc_offset_%s[] = {\n", name
+ printf "%s", value
+ print "};"
+ print ""
+ printf "static NCURSES_CONST char ** ptr_%s = 0;\n", name
+ print ""
+}
+
+BEGIN {
+ print "/* This file was generated by MKnames.awk */"
+ print ""
+ print "#include <curses.priv.h>"
+ print ""
+ print "#define IT NCURSES_CONST char * const"
+ print ""
+ offset = 0;
+ offcol = 0;
+ bigcol = 0;
+ }
+
+$1 ~ /^#/ {next;}
+
+$1 == "SKIPWARN" {next;}
+
+$3 == "bool" {
+ small_boolnames = small_boolnames small_item($2);
+ large_boolnames = large_boolnames large_item($2);
+ small_boolfnames = small_boolfnames small_item($1);
+ large_boolfnames = large_boolfnames large_item($1);
+ }
+
+$3 == "num" {
+ small_numnames = small_numnames small_item($2);
+ large_numnames = large_numnames large_item($2);
+ small_numfnames = small_numfnames small_item($1);
+ large_numfnames = large_numfnames large_item($1);
+ }
+
+$3 == "str" {
+ small_strnames = small_strnames small_item($2);
+ large_strnames = large_strnames large_item($2);
+ small_strfnames = small_strfnames small_item($1);
+ large_strfnames = large_strfnames large_item($1);
+ }
+
+END {
+ print ""
+ print "#if BROKEN_LINKER || USE_REENTRANT"
+ print ""
+ print "#include <term.h>"
+ print ""
+ if (bigstrings) {
+ printf "static const char _nc_name_blob[] = \n"
+ printf "%s;\n", bigstr;
+ print_offsets("boolfnames", large_boolfnames);
+ print_offsets("boolnames", large_boolnames);
+ print_offsets("numfnames", large_numfnames);
+ print_offsets("numnames", large_numnames);
+ print_offsets("strfnames", large_strfnames);
+ print_offsets("strnames", large_strnames);
+ print ""
+ print "static IT *"
+ print "alloc_array(NCURSES_CONST char ***value, const short *offsets, unsigned size)"
+ print "{"
+ print " if (*value == 0) {"
+ print " if ((*value = typeCalloc(NCURSES_CONST char *, size + 1)) != 0) {"
+ print " unsigned n;"
+ print " for (n = 0; n < size; ++n) {"
+ print " (*value)[n] = _nc_name_blob + offsets[n];"
+ print " }"
+ print " }"
+ print " }"
+ print " return *value;"
+ print "}"
+ print ""
+ print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API _nc_##it(void) { return alloc_array(&ptr_##it, _nc_offset_##it, SIZEOF(_nc_offset_##it)); }"
+ } else {
+ print "#define DCL(it) static IT data##it[]"
+ print ""
+ print_strings("boolnames", small_boolnames);
+ print_strings("boolfnames", small_boolfnames);
+ print_strings("numnames", small_numnames);
+ print_strings("numfnames", small_numfnames);
+ print_strings("strnames", small_strnames);
+ print_strings("strfnames", small_strfnames);
+ print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API _nc_##it(void) { return data##it; }"
+ }
+ print ""
+ print "FIX(boolnames)"
+ print "FIX(boolfnames)"
+ print "FIX(numnames)"
+ print "FIX(numfnames)"
+ print "FIX(strnames)"
+ print "FIX(strfnames)"
+ print ""
+ print ""
+ print "#define FREE_FIX(it) if (ptr_##it) { FreeAndNull(ptr_##it); }"
+ print ""
+ print "NCURSES_EXPORT(void)"
+ print "_nc_names_leaks(void)"
+ print "{"
+ if (bigstrings) {
+ print "FREE_FIX(boolnames)"
+ print "FREE_FIX(boolfnames)"
+ print "FREE_FIX(numnames)"
+ print "FREE_FIX(numfnames)"
+ print "FREE_FIX(strnames)"
+ print "FREE_FIX(strfnames)"
+ }
+ print "}"
+ print "#else"
+ print ""
+ print "#define DCL(it) NCURSES_EXPORT_VAR(IT) it[]"
+ print ""
+ print_strings("boolnames", small_boolnames);
+ print_strings("boolfnames", small_boolfnames);
+ print_strings("numnames", small_numnames);
+ print_strings("numfnames", small_numfnames);
+ print_strings("strnames", small_strnames);
+ print_strings("strfnames", small_strfnames);
+ print ""
+ print "#endif /* BROKEN_LINKER */"
+ }
diff --git a/ncurses/tinfo/README b/ncurses/tinfo/README
new file mode 100644
index 000000000000..14c4220c4431
--- /dev/null
+++ b/ncurses/tinfo/README
@@ -0,0 +1,36 @@
+-------------------------------------------------------------------------------
+-- Copyright (c) 1998,2006 Free Software Foundation, Inc. --
+-- --
+-- Permission is hereby granted, free of charge, to any person obtaining a --
+-- copy of this software and associated documentation files (the --
+-- "Software"), 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. --
+-------------------------------------------------------------------------------
+-- $Id: README,v 1.2 2006/04/22 22:19:37 tom Exp $
+-------------------------------------------------------------------------------
+
+The files in this directory (tinfo) are those that support the terminfo
+database and interfaces for ncurses. The terminfo library can be built
+separately, as a lower-level library for ncurses, but usually is bundled.
+
+In addition to the standard documented interfaces, ncurses uses internal
+functions which reside in tinfo to satisfy linkage requirements.
diff --git a/ncurses/tinfo/access.c b/ncurses/tinfo/access.c
new file mode 100644
index 000000000000..ce8ccdac53f6
--- /dev/null
+++ b/ncurses/tinfo/access.c
@@ -0,0 +1,176 @@
+/****************************************************************************
+ * Copyright (c) 1998-2006,2007 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 <curses.priv.h>
+
+#include <ctype.h>
+#include <sys/stat.h>
+
+#include <tic.h>
+#include <nc_alloc.h>
+
+MODULE_ID("$Id: access.c,v 1.14 2007/11/18 00:57:53 tom Exp $")
+
+#define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c))
+
+NCURSES_EXPORT(char *)
+_nc_rootname(char *path)
+{
+ char *result = _nc_basename(path);
+#if !MIXEDCASE_FILENAMES || defined(PROG_EXT)
+ static char *temp;
+ char *s;
+
+ temp = strdup(result);
+ result = temp;
+#if !MIXEDCASE_FILENAMES
+ for (s = result; *s != '\0'; ++s) {
+ *s = LOWERCASE(*s);
+ }
+#endif
+#if defined(PROG_EXT)
+ if ((s = strrchr(result, '.')) != 0) {
+ if (!strcmp(s, PROG_EXT))
+ *s = '\0';
+ }
+#endif
+#endif
+ return result;
+}
+
+/*
+ * Check if a string appears to be an absolute pathname.
+ */
+NCURSES_EXPORT(bool)
+_nc_is_abs_path(const char *path)
+{
+#if defined(__EMX__) || defined(__DJGPP__)
+#define is_pathname(s) ((((s) != 0) && ((s)[0] == '/')) \
+ || (((s)[0] != 0) && ((s)[1] == ':')))
+#else
+#define is_pathname(s) ((s) != 0 && (s)[0] == '/')
+#endif
+ return is_pathname(path);
+}
+
+/*
+ * Return index of the basename
+ */
+NCURSES_EXPORT(unsigned)
+_nc_pathlast(const char *path)
+{
+ const char *test = strrchr(path, '/');
+#ifdef __EMX__
+ if (test == 0)
+ test = strrchr(path, '\\');
+#endif
+ if (test == 0)
+ test = path;
+ else
+ test++;
+ return (test - path);
+}
+
+NCURSES_EXPORT(char *)
+_nc_basename(char *path)
+{
+ return path + _nc_pathlast(path);
+}
+
+NCURSES_EXPORT(int)
+_nc_access(const char *path, int mode)
+{
+ if (access(path, mode) < 0) {
+ if ((mode & W_OK) != 0
+ && errno == ENOENT
+ && strlen(path) < PATH_MAX) {
+ char head[PATH_MAX];
+ char *leaf = _nc_basename(strcpy(head, path));
+
+ if (leaf == 0)
+ leaf = head;
+ *leaf = '\0';
+ if (head == leaf)
+ (void) strcpy(head, ".");
+
+ return access(head, R_OK | W_OK | X_OK);
+ }
+ return -1;
+ }
+ return 0;
+}
+
+NCURSES_EXPORT(bool)
+_nc_is_dir_path(const char *path)
+{
+ bool result = FALSE;
+ struct stat sb;
+
+ if (stat(path, &sb) == 0
+ && (sb.st_mode & S_IFMT) == S_IFDIR) {
+ result = TRUE;
+ }
+ return result;
+}
+
+NCURSES_EXPORT(bool)
+_nc_is_file_path(const char *path)
+{
+ bool result = FALSE;
+ struct stat sb;
+
+ if (stat(path, &sb) == 0
+ && (sb.st_mode & S_IFMT) == S_IFREG) {
+ result = TRUE;
+ }
+ return result;
+}
+
+#ifndef USE_ROOT_ENVIRON
+/*
+ * Returns true if we allow application to use environment variables that are
+ * used for searching lists of directories, etc.
+ */
+NCURSES_EXPORT(int)
+_nc_env_access(void)
+{
+#if HAVE_ISSETUGID
+ if (issetugid())
+ return FALSE;
+#elif HAVE_GETEUID && HAVE_GETEGID
+ if (getuid() != geteuid()
+ || getgid() != getegid())
+ return FALSE;
+#endif
+ return getuid() != 0 && geteuid() != 0; /* ...finally, disallow root */
+}
+#endif
diff --git a/ncurses/tinfo/add_tries.c b/ncurses/tinfo/add_tries.c
new file mode 100644
index 000000000000..455d142edc8e
--- /dev/null
+++ b/ncurses/tinfo/add_tries.c
@@ -0,0 +1,120 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), 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 1998-on *
+ ****************************************************************************/
+
+/*
+** add_tries.c
+**
+** Add keycode/string to tries-tree.
+**
+*/
+
+#include <curses.priv.h>
+
+MODULE_ID("$Id: add_tries.c,v 1.8 2006/12/30 23:15:26 tom Exp $")
+
+#define SET_TRY(dst,src) if ((dst->ch = *src++) == 128) dst->ch = '\0'
+#define CMP_TRY(a,b) ((a)? (a == b) : (b == 128))
+
+NCURSES_EXPORT(int)
+_nc_add_to_try(TRIES ** tree, const char *str, unsigned code)
+{
+ TRIES *ptr, *savedptr;
+ unsigned const char *txt = (unsigned const char *) str;
+
+ T((T_CALLED("_nc_add_to_try(%p, %s, %u)"), *tree, _nc_visbuf(str), code));
+ if (txt == 0 || *txt == '\0' || code == 0)
+ returnCode(ERR);
+
+ if ((*tree) != 0) {
+ ptr = savedptr = (*tree);
+
+ for (;;) {
+ unsigned char cmp = *txt;
+
+ while (!CMP_TRY(ptr->ch, cmp)
+ && ptr->sibling != 0)
+ ptr = ptr->sibling;
+
+ if (CMP_TRY(ptr->ch, cmp)) {
+ if (*(++txt) == '\0') {
+ ptr->value = code;
+ returnCode(OK);
+ }
+ if (ptr->child != 0)
+ ptr = ptr->child;
+ else
+ break;
+ } else {
+ if ((ptr->sibling = typeCalloc(TRIES, 1)) == 0) {
+ returnCode(ERR);
+ }
+
+ savedptr = ptr = ptr->sibling;
+ SET_TRY(ptr, txt);
+ ptr->value = 0;
+
+ break;
+ }
+ } /* end for (;;) */
+ } else { /* (*tree) == 0 :: First sequence to be added */
+ savedptr = ptr = (*tree) = typeCalloc(TRIES, 1);
+
+ if (ptr == 0) {
+ returnCode(ERR);
+ }
+
+ SET_TRY(ptr, txt);
+ ptr->value = 0;
+ }
+
+ /* at this point, we are adding to the try. ptr->child == 0 */
+
+ while (*txt) {
+ ptr->child = typeCalloc(TRIES, 1);
+
+ ptr = ptr->child;
+
+ if (ptr == 0) {
+ while ((ptr = savedptr) != 0) {
+ savedptr = ptr->child;
+ free(ptr);
+ }
+ returnCode(ERR);
+ }
+
+ SET_TRY(ptr, txt);
+ ptr->value = 0;
+ }
+
+ ptr->value = code;
+ returnCode(OK);
+}
diff --git a/ncurses/tinfo/alloc_entry.c b/ncurses/tinfo/alloc_entry.c
new file mode 100644
index 000000000000..1496752f1956
--- /dev/null
+++ b/ncurses/tinfo/alloc_entry.c
@@ -0,0 +1,289 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ ****************************************************************************/
+
+/*
+ * alloc_entry.c -- allocation functions for terminfo entries
+ *
+ * _nc_copy_entry()
+ * _nc_init_entry()
+ * _nc_merge_entry()
+ * _nc_save_str()
+ * _nc_wrap_entry()
+ *
+ */
+
+#include <curses.priv.h>
+
+#include <tic.h>
+#include <term_entry.h>
+
+MODULE_ID("$Id: alloc_entry.c,v 1.47 2006/12/16 19:06:58 tom Exp $")
+
+#define ABSENT_OFFSET -1
+#define CANCELLED_OFFSET -2
+
+#define MAX_STRTAB 4096 /* documented maximum entry size */
+
+static char *stringbuf; /* buffer for string capabilities */
+static size_t next_free; /* next free character in stringbuf */
+
+NCURSES_EXPORT(void)
+_nc_init_entry(TERMTYPE *const tp)
+/* initialize a terminal type data block */
+{
+ unsigned i;
+
+#if NO_LEAKS
+ if (tp == 0 && stringbuf != 0) {
+ FreeAndNull(stringbuf);
+ return;
+ }
+#endif
+
+ if (stringbuf == 0)
+ stringbuf = (char *) malloc(MAX_STRTAB);
+
+#if NCURSES_XNAMES
+ tp->num_Booleans = BOOLCOUNT;
+ tp->num_Numbers = NUMCOUNT;
+ tp->num_Strings = STRCOUNT;
+ tp->ext_Booleans = 0;
+ tp->ext_Numbers = 0;
+ tp->ext_Strings = 0;
+#endif
+ if (tp->Booleans == 0)
+ tp->Booleans = typeMalloc(NCURSES_SBOOL, BOOLCOUNT);
+ if (tp->Numbers == 0)
+ tp->Numbers = typeMalloc(short, NUMCOUNT);
+ if (tp->Strings == 0)
+ tp->Strings = typeMalloc(char *, STRCOUNT);
+
+ for_each_boolean(i, tp)
+ tp->Booleans[i] = FALSE;
+
+ for_each_number(i, tp)
+ tp->Numbers[i] = ABSENT_NUMERIC;
+
+ for_each_string(i, tp)
+ tp->Strings[i] = ABSENT_STRING;
+
+ next_free = 0;
+}
+
+NCURSES_EXPORT(ENTRY *)
+_nc_copy_entry(ENTRY * oldp)
+{
+ ENTRY *newp = typeCalloc(ENTRY, 1);
+
+ if (newp != 0) {
+ *newp = *oldp;
+ _nc_copy_termtype(&(newp->tterm), &(oldp->tterm));
+ }
+ return newp;
+}
+
+/* save a copy of string in the string buffer */
+NCURSES_EXPORT(char *)
+_nc_save_str(const char *const string)
+{
+ char *result = 0;
+ size_t old_next_free = next_free;
+ size_t len = strlen(string) + 1;
+
+ if (len == 1 && next_free != 0) {
+ /*
+ * Cheat a little by making an empty string point to the end of the
+ * previous string.
+ */
+ if (next_free < MAX_STRTAB) {
+ result = (stringbuf + next_free - 1);
+ }
+ } else if (next_free + len < MAX_STRTAB) {
+ strcpy(&stringbuf[next_free], string);
+ DEBUG(7, ("Saved string %s", _nc_visbuf(string)));
+ DEBUG(7, ("at location %d", (int) next_free));
+ next_free += len;
+ result = (stringbuf + old_next_free);
+ } else {
+ _nc_warning("Too much data, some is lost");
+ }
+ return result;
+}
+
+NCURSES_EXPORT(void)
+_nc_wrap_entry(ENTRY * const ep, bool copy_strings)
+/* copy the string parts to allocated storage, preserving pointers to it */
+{
+ int offsets[MAX_ENTRY_SIZE / 2], useoffsets[MAX_USES];
+ unsigned i, n;
+ unsigned nuses = ep->nuses;
+ TERMTYPE *tp = &(ep->tterm);
+
+ if (copy_strings) {
+ next_free = 0; /* clear static storage */
+
+ /* copy term_names, Strings, uses */
+ tp->term_names = _nc_save_str(tp->term_names);
+ for_each_string(i, tp) {
+ if (tp->Strings[i] != ABSENT_STRING &&
+ tp->Strings[i] != CANCELLED_STRING) {
+ tp->Strings[i] = _nc_save_str(tp->Strings[i]);
+ }
+ }
+
+ for (i = 0; i < nuses; i++) {
+ if (ep->uses[i].name == 0) {
+ ep->uses[i].name = _nc_save_str(ep->uses[i].name);
+ }
+ }
+
+ free(tp->str_table);
+ }
+
+ n = tp->term_names - stringbuf;
+ for_each_string(i, &(ep->tterm)) {
+ if (tp->Strings[i] == ABSENT_STRING)
+ offsets[i] = ABSENT_OFFSET;
+ else if (tp->Strings[i] == CANCELLED_STRING)
+ offsets[i] = CANCELLED_OFFSET;
+ else
+ offsets[i] = tp->Strings[i] - stringbuf;
+ }
+
+ for (i = 0; i < nuses; i++) {
+ if (ep->uses[i].name == 0)
+ useoffsets[i] = ABSENT_OFFSET;
+ else
+ useoffsets[i] = ep->uses[i].name - stringbuf;
+ }
+
+ if ((tp->str_table = typeMalloc(char, next_free)) == (char *) 0)
+ _nc_err_abort(MSG_NO_MEMORY);
+ (void) memcpy(tp->str_table, stringbuf, next_free);
+
+ tp->term_names = tp->str_table + n;
+ for_each_string(i, &(ep->tterm)) {
+ if (offsets[i] == ABSENT_OFFSET)
+ tp->Strings[i] = ABSENT_STRING;
+ else if (offsets[i] == CANCELLED_OFFSET)
+ tp->Strings[i] = CANCELLED_STRING;
+ else
+ tp->Strings[i] = tp->str_table + offsets[i];
+ }
+
+#if NCURSES_XNAMES
+ if (!copy_strings) {
+ if ((n = NUM_EXT_NAMES(tp)) != 0) {
+ unsigned length = 0;
+ for (i = 0; i < n; i++) {
+ length += strlen(tp->ext_Names[i]) + 1;
+ offsets[i] = tp->ext_Names[i] - stringbuf;
+ }
+ if ((tp->ext_str_table = typeMalloc(char, length)) == 0)
+ _nc_err_abort(MSG_NO_MEMORY);
+ for (i = 0, length = 0; i < n; i++) {
+ tp->ext_Names[i] = tp->ext_str_table + length;
+ strcpy(tp->ext_Names[i], stringbuf + offsets[i]);
+ length += strlen(tp->ext_Names[i]) + 1;
+ }
+ }
+ }
+#endif
+
+ for (i = 0; i < nuses; i++) {
+ if (useoffsets[i] == ABSENT_OFFSET)
+ ep->uses[i].name = 0;
+ else
+ ep->uses[i].name = (tp->str_table + useoffsets[i]);
+ }
+}
+
+NCURSES_EXPORT(void)
+_nc_merge_entry(TERMTYPE *const to, TERMTYPE *const from)
+/* merge capabilities from `from' entry into `to' entry */
+{
+ unsigned i;
+
+#if NCURSES_XNAMES
+ _nc_align_termtype(to, from);
+#endif
+ for_each_boolean(i, from) {
+ if (to->Booleans[i] != (char) CANCELLED_BOOLEAN) {
+ int mergebool = from->Booleans[i];
+
+ if (mergebool == CANCELLED_BOOLEAN)
+ to->Booleans[i] = FALSE;
+ else if (mergebool == TRUE)
+ to->Booleans[i] = mergebool;
+ }
+ }
+
+ for_each_number(i, from) {
+ if (to->Numbers[i] != CANCELLED_NUMERIC) {
+ int mergenum = from->Numbers[i];
+
+ if (mergenum == CANCELLED_NUMERIC)
+ to->Numbers[i] = ABSENT_NUMERIC;
+ else if (mergenum != ABSENT_NUMERIC)
+ to->Numbers[i] = mergenum;
+ }
+ }
+
+ /*
+ * Note: the copies of strings this makes don't have their own
+ * storage. This is OK right now, but will be a problem if we
+ * we ever want to deallocate entries.
+ */
+ for_each_string(i, from) {
+ if (to->Strings[i] != CANCELLED_STRING) {
+ char *mergestring = from->Strings[i];
+
+ if (mergestring == CANCELLED_STRING)
+ to->Strings[i] = ABSENT_STRING;
+ else if (mergestring != ABSENT_STRING)
+ to->Strings[i] = mergestring;
+ }
+ }
+}
+
+#if NO_LEAKS
+NCURSES_EXPORT(void)
+_nc_alloc_entry_leaks(void)
+{
+ if (stringbuf != 0) {
+ FreeAndNull(stringbuf);
+ }
+ next_free = 0;
+}
+#endif
diff --git a/ncurses/tinfo/alloc_ttype.c b/ncurses/tinfo/alloc_ttype.c
new file mode 100644
index 000000000000..9f31ed3ffab7
--- /dev/null
+++ b/ncurses/tinfo/alloc_ttype.c
@@ -0,0 +1,495 @@
+/****************************************************************************
+ * Copyright (c) 1999-2003,2006 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), 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 <dickey@clark.net> 1999-on *
+ ****************************************************************************/
+
+/*
+ * align_ttype.c -- functions for TERMTYPE
+ *
+ * _nc_align_termtype()
+ * _nc_copy_termtype()
+ *
+ */
+
+#include <curses.priv.h>
+
+#include <tic.h>
+#include <term_entry.h>
+
+MODULE_ID("$Id: alloc_ttype.c,v 1.16 2006/07/08 19:18:38 tom Exp $")
+
+#if NCURSES_XNAMES
+/*
+ * Merge the a/b lists into dst. Both a/b are sorted (see _nc_extend_names()),
+ * so we do not have to worry about order dependencies.
+ */
+static int
+merge_names(char **dst, char **a, int na, char **b, int nb)
+{
+ int n = 0;
+ while (na > 0 && nb > 0) {
+ int cmp = strcmp(*a, *b);
+ if (cmp < 0) {
+ dst[n++] = *a++;
+ na--;
+ } else if (cmp > 0) {
+ dst[n++] = *b++;
+ nb--;
+ } else if (cmp == 0) {
+ dst[n++] = *a;
+ a++, b++;
+ na--, nb--;
+ }
+ }
+ while (na-- > 0) {
+ dst[n++] = *a++;
+ }
+ while (nb-- > 0) {
+ dst[n++] = *b++;
+ }
+ DEBUG(4, ("merge_names -> %d", n));
+ return n;
+}
+
+static bool
+find_name(char **table, int length, char *name)
+{
+ while (length-- > 0) {
+ if (!strcmp(*table++, name)) {
+ DEBUG(4, ("found name '%s'", name));
+ return TRUE;
+ }
+ }
+ DEBUG(4, ("did not find name '%s'", name));
+ return FALSE;
+}
+
+static void
+realign_data(TERMTYPE *to, char **ext_Names,
+ int ext_Booleans,
+ int ext_Numbers,
+ int ext_Strings)
+{
+ int n, m, base;
+ int limit = (to->ext_Booleans + to->ext_Numbers + to->ext_Strings);
+
+ if (to->ext_Booleans != ext_Booleans) {
+ to->num_Booleans += (ext_Booleans - to->ext_Booleans);
+ to->Booleans = typeRealloc(NCURSES_SBOOL, to->num_Booleans, to->Booleans);
+ for (n = to->ext_Booleans - 1,
+ m = ext_Booleans - 1,
+ base = to->num_Booleans - (m + 1); m >= 0; m--) {
+ if (find_name(to->ext_Names, limit, ext_Names[m])) {
+ to->Booleans[base + m] = to->Booleans[base + n--];
+ } else {
+ to->Booleans[base + m] = FALSE;
+ }
+ }
+ to->ext_Booleans = ext_Booleans;
+ }
+ if (to->ext_Numbers != ext_Numbers) {
+ to->num_Numbers += (ext_Numbers - to->ext_Numbers);
+ to->Numbers = typeRealloc(short, to->num_Numbers, to->Numbers);
+ for (n = to->ext_Numbers - 1,
+ m = ext_Numbers - 1,
+ base = to->num_Numbers - (m + 1); m >= 0; m--) {
+ if (find_name(to->ext_Names, limit, ext_Names[m + ext_Booleans])) {
+ to->Numbers[base + m] = to->Numbers[base + n--];
+ } else {
+ to->Numbers[base + m] = ABSENT_NUMERIC;
+ }
+ }
+ to->ext_Numbers = ext_Numbers;
+ }
+ if (to->ext_Strings != ext_Strings) {
+ to->num_Strings += (ext_Strings - to->ext_Strings);
+ to->Strings = typeRealloc(char *, to->num_Strings, to->Strings);
+ for (n = to->ext_Strings - 1,
+ m = ext_Strings - 1,
+ base = to->num_Strings - (m + 1); m >= 0; m--) {
+ if (find_name(to->ext_Names, limit, ext_Names[m + ext_Booleans + ext_Numbers])) {
+ to->Strings[base + m] = to->Strings[base + n--];
+ } else {
+ to->Strings[base + m] = ABSENT_STRING;
+ }
+ }
+ to->ext_Strings = ext_Strings;
+ }
+}
+
+/*
+ * Returns the first index in ext_Names[] for the given token-type
+ */
+static int
+_nc_first_ext_name(TERMTYPE *tp, int token_type)
+{
+ int first;
+
+ switch (token_type) {
+ case BOOLEAN:
+ first = 0;
+ break;
+ case NUMBER:
+ first = tp->ext_Booleans;
+ break;
+ case STRING:
+ first = tp->ext_Booleans + tp->ext_Numbers;
+ break;
+ default:
+ first = 0;
+ break;
+ }
+ return first;
+}
+
+/*
+ * Returns the last index in ext_Names[] for the given token-type
+ */
+static int
+_nc_last_ext_name(TERMTYPE *tp, int token_type)
+{
+ int last;
+
+ switch (token_type) {
+ case BOOLEAN:
+ last = tp->ext_Booleans;
+ break;
+ case NUMBER:
+ last = tp->ext_Booleans + tp->ext_Numbers;
+ break;
+ default:
+ case STRING:
+ last = NUM_EXT_NAMES(tp);
+ break;
+ }
+ return last;
+}
+
+/*
+ * Lookup an entry from extended-names, returning -1 if not found
+ */
+static int
+_nc_find_ext_name(TERMTYPE *tp, char *name, int token_type)
+{
+ unsigned j;
+ unsigned first = _nc_first_ext_name(tp, token_type);
+ unsigned last = _nc_last_ext_name(tp, token_type);
+
+ for (j = first; j < last; j++) {
+ if (!strcmp(name, tp->ext_Names[j])) {
+ return j;
+ }
+ }
+ return -1;
+}
+
+/*
+ * Translate an index into ext_Names[] into the corresponding index into data
+ * (e.g., Booleans[]).
+ */
+static int
+_nc_ext_data_index(TERMTYPE *tp, int n, int token_type)
+{
+ switch (token_type) {
+ case BOOLEAN:
+ n += (tp->num_Booleans - tp->ext_Booleans);
+ break;
+ case NUMBER:
+ n += (tp->num_Numbers - tp->ext_Numbers)
+ - (tp->ext_Booleans);
+ break;
+ default:
+ case STRING:
+ n += (tp->num_Strings - tp->ext_Strings)
+ - (tp->ext_Booleans + tp->ext_Numbers);
+ }
+ return n;
+}
+
+/*
+ * Adjust tables to remove (not free) an extended name and its corresponding
+ * data.
+ */
+static bool
+_nc_del_ext_name(TERMTYPE *tp, char *name, int token_type)
+{
+ int j;
+ int first, last;
+
+ if ((first = _nc_find_ext_name(tp, name, token_type)) >= 0) {
+ last = NUM_EXT_NAMES(tp) - 1;
+ for (j = first; j < last; j++) {
+ tp->ext_Names[j] = tp->ext_Names[j + 1];
+ }
+ first = _nc_ext_data_index(tp, first, token_type);
+ switch (token_type) {
+ case BOOLEAN:
+ last = tp->num_Booleans - 1;
+ for (j = first; j < last; j++)
+ tp->Booleans[j] = tp->Booleans[j + 1];
+ tp->ext_Booleans -= 1;
+ tp->num_Booleans -= 1;
+ break;
+ case NUMBER:
+ last = tp->num_Numbers - 1;
+ for (j = first; j < last; j++)
+ tp->Numbers[j] = tp->Numbers[j + 1];
+ tp->ext_Numbers -= 1;
+ tp->num_Numbers -= 1;
+ break;
+ case STRING:
+ last = tp->num_Strings - 1;
+ for (j = first; j < last; j++)
+ tp->Strings[j] = tp->Strings[j + 1];
+ tp->ext_Strings -= 1;
+ tp->num_Strings -= 1;
+ break;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Adjust tables to insert an extended name, making room for new data. The
+ * index into the corresponding data array is returned.
+ */
+static int
+_nc_ins_ext_name(TERMTYPE *tp, char *name, int token_type)
+{
+ unsigned first = _nc_first_ext_name(tp, token_type);
+ unsigned last = _nc_last_ext_name(tp, token_type);
+ unsigned total = NUM_EXT_NAMES(tp) + 1;
+ unsigned j, k;
+
+ for (j = first; j < last; j++) {
+ int cmp = strcmp(name, tp->ext_Names[j]);
+ if (cmp == 0)
+ /* already present */
+ return _nc_ext_data_index(tp, (int) j, token_type);
+ if (cmp < 0) {
+ break;
+ }
+ }
+
+ tp->ext_Names = typeRealloc(char *, total, tp->ext_Names);
+ for (k = total - 1; k > j; k--)
+ tp->ext_Names[k] = tp->ext_Names[k - 1];
+ tp->ext_Names[j] = name;
+ j = _nc_ext_data_index(tp, (int) j, token_type);
+
+ switch (token_type) {
+ case BOOLEAN:
+ tp->ext_Booleans += 1;
+ tp->num_Booleans += 1;
+ tp->Booleans = typeRealloc(NCURSES_SBOOL, tp->num_Booleans, tp->Booleans);
+ for (k = tp->num_Booleans - 1; k > j; k--)
+ tp->Booleans[k] = tp->Booleans[k - 1];
+ break;
+ case NUMBER:
+ tp->ext_Numbers += 1;
+ tp->num_Numbers += 1;
+ tp->Numbers = typeRealloc(short, tp->num_Numbers, tp->Numbers);
+ for (k = tp->num_Numbers - 1; k > j; k--)
+ tp->Numbers[k] = tp->Numbers[k - 1];
+ break;
+ case STRING:
+ tp->ext_Strings += 1;
+ tp->num_Strings += 1;
+ tp->Strings = typeRealloc(char *, tp->num_Strings, tp->Strings);
+ for (k = tp->num_Strings - 1; k > j; k--)
+ tp->Strings[k] = tp->Strings[k - 1];
+ break;
+ }
+ return j;
+}
+
+/*
+ * Look for strings that are marked cancelled, which happen to be the same name
+ * as a boolean or number. We'll get this as a special case when we get a
+ * cancellation of a name that is inherited from another entry.
+ */
+static void
+adjust_cancels(TERMTYPE *to, TERMTYPE *from)
+{
+ int first = to->ext_Booleans + to->ext_Numbers;
+ int last = first + to->ext_Strings;
+ int j, k;
+
+ for (j = first; j < last;) {
+ char *name = to->ext_Names[j];
+ unsigned j_str = to->num_Strings - first - to->ext_Strings;
+
+ if (to->Strings[j + j_str] == CANCELLED_STRING) {
+ if ((k = _nc_find_ext_name(from, to->ext_Names[j], BOOLEAN)) >= 0) {
+ if (_nc_del_ext_name(to, name, STRING)
+ || _nc_del_ext_name(to, name, NUMBER)) {
+ k = _nc_ins_ext_name(to, name, BOOLEAN);
+ to->Booleans[k] = FALSE;
+ } else {
+ j++;
+ }
+ } else if ((k = _nc_find_ext_name(from, to->ext_Names[j],
+ NUMBER)) >= 0) {
+ if (_nc_del_ext_name(to, name, STRING)
+ || _nc_del_ext_name(to, name, BOOLEAN)) {
+ k = _nc_ins_ext_name(to, name, NUMBER);
+ to->Numbers[k] = CANCELLED_NUMERIC;
+ } else {
+ j++;
+ }
+ }
+ } else {
+ j++;
+ }
+ }
+}
+
+NCURSES_EXPORT(void)
+_nc_align_termtype(TERMTYPE *to, TERMTYPE *from)
+{
+ int na = NUM_EXT_NAMES(to);
+ int nb = NUM_EXT_NAMES(from);
+ int n;
+ bool same;
+ char **ext_Names;
+ int ext_Booleans, ext_Numbers, ext_Strings;
+ bool used_ext_Names = FALSE;
+
+ DEBUG(2, ("align_termtype to(%d:%s), from(%d:%s)", na, to->term_names,
+ nb, from->term_names));
+
+ if (na != 0 || nb != 0) {
+ if ((na == nb) /* check if the arrays are equivalent */
+ &&(to->ext_Booleans == from->ext_Booleans)
+ && (to->ext_Numbers == from->ext_Numbers)
+ && (to->ext_Strings == from->ext_Strings)) {
+ for (n = 0, same = TRUE; n < na; n++) {
+ if (strcmp(to->ext_Names[n], from->ext_Names[n])) {
+ same = FALSE;
+ break;
+ }
+ }
+ if (same)
+ return;
+ }
+ /*
+ * This is where we pay for having a simple extension representation.
+ * Allocate a new ext_Names array and merge the two ext_Names arrays
+ * into it, updating to's counts for booleans, etc. Fortunately we do
+ * this only for the terminfo compiler (tic) and comparer (infocmp).
+ */
+ ext_Names = typeMalloc(char *, na + nb);
+
+ if (to->ext_Strings && (from->ext_Booleans + from->ext_Numbers))
+ adjust_cancels(to, from);
+
+ if (from->ext_Strings && (to->ext_Booleans + to->ext_Numbers))
+ adjust_cancels(from, to);
+
+ ext_Booleans = merge_names(ext_Names,
+ to->ext_Names,
+ to->ext_Booleans,
+ from->ext_Names,
+ from->ext_Booleans);
+ ext_Numbers = merge_names(ext_Names + ext_Booleans,
+ to->ext_Names
+ + to->ext_Booleans,
+ to->ext_Numbers,
+ from->ext_Names
+ + from->ext_Booleans,
+ from->ext_Numbers);
+ ext_Strings = merge_names(ext_Names + ext_Numbers + ext_Booleans,
+ to->ext_Names
+ + to->ext_Booleans
+ + to->ext_Numbers,
+ to->ext_Strings,
+ from->ext_Names
+ + from->ext_Booleans
+ + from->ext_Numbers,
+ from->ext_Strings);
+ /*
+ * Now we must reallocate the Booleans, etc., to allow the data to be
+ * overlaid.
+ */
+ if (na != (ext_Booleans + ext_Numbers + ext_Strings)) {
+ realign_data(to, ext_Names, ext_Booleans, ext_Numbers, ext_Strings);
+ FreeIfNeeded(to->ext_Names);
+ to->ext_Names = ext_Names;
+ DEBUG(2, ("realigned %d extended names for '%s' (to)",
+ NUM_EXT_NAMES(to), to->term_names));
+ used_ext_Names = TRUE;
+ }
+ if (nb != (ext_Booleans + ext_Numbers + ext_Strings)) {
+ nb = (ext_Booleans + ext_Numbers + ext_Strings);
+ realign_data(from, ext_Names, ext_Booleans, ext_Numbers, ext_Strings);
+ from->ext_Names = typeRealloc(char *, nb, from->ext_Names);
+ memcpy(from->ext_Names, ext_Names, sizeof(char *) * nb);
+ DEBUG(2, ("realigned %d extended names for '%s' (from)",
+ NUM_EXT_NAMES(from), from->term_names));
+ }
+ if (!used_ext_Names)
+ free(ext_Names);
+ }
+}
+#endif
+
+NCURSES_EXPORT(void)
+_nc_copy_termtype(TERMTYPE *dst, TERMTYPE *src)
+{
+ unsigned i;
+
+ *dst = *src; /* ...to copy the sizes and string-tables */
+ dst->Booleans = typeMalloc(NCURSES_SBOOL, NUM_BOOLEANS(dst));
+ dst->Numbers = typeMalloc(short, NUM_NUMBERS(dst));
+ dst->Strings = typeMalloc(char *, NUM_STRINGS(dst));
+
+ /* FIXME: use memcpy for these and similar loops */
+ for_each_boolean(i, dst)
+ dst->Booleans[i] = src->Booleans[i];
+ for_each_number(i, dst)
+ dst->Numbers[i] = src->Numbers[i];
+ for_each_string(i, dst)
+ dst->Strings[i] = src->Strings[i];
+
+ /* FIXME: we probably should also copy str_table and ext_str_table,
+ * but tic and infocmp are not written to exploit that (yet).
+ */
+
+#if NCURSES_XNAMES
+ if ((i = NUM_EXT_NAMES(src)) != 0) {
+ dst->ext_Names = typeMalloc(char *, i);
+ memcpy(dst->ext_Names, src->ext_Names, i * sizeof(char *));
+ } else {
+ dst->ext_Names = 0;
+ }
+#endif
+
+}
diff --git a/ncurses/tinfo/captoinfo.c b/ncurses/tinfo/captoinfo.c
new file mode 100644
index 000000000000..0e3baa845693
--- /dev/null
+++ b/ncurses/tinfo/captoinfo.c
@@ -0,0 +1,847 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ ****************************************************************************/
+
+/*
+ * captoinfo.c --- conversion between termcap and terminfo formats
+ *
+ * The captoinfo() code was swiped from Ross Ridge's mytinfo package,
+ * adapted to fit ncurses by Eric S. Raymond <esr@snark.thyrsus.com>.
+ *
+ * There is just one entry point:
+ *
+ * char *_nc_captoinfo(n, s, parameterized)
+ *
+ * Convert value s for termcap string capability named n into terminfo
+ * format.
+ *
+ * This code recognizes all the standard 4.4BSD %-escapes:
+ *
+ * %% output `%'
+ * %d output value as in printf %d
+ * %2 output value as in printf %2d
+ * %3 output value as in printf %3d
+ * %. output value as in printf %c
+ * %+x add x to value, then do %.
+ * %>xy if value > x then add y, no output
+ * %r reverse order of two parameters, no output
+ * %i increment by one, no output
+ * %n exclusive-or all parameters with 0140 (Datamedia 2500)
+ * %B BCD (16*(value/10)) + (value%10), no output
+ * %D Reverse coding (value - 2*(value%16)), no output (Delta Data).
+ *
+ * Also, %02 and %03 are accepted as synonyms for %2 and %3.
+ *
+ * Besides all the standard termcap escapes, this translator understands
+ * the following extended escapes:
+ *
+ * used by GNU Emacs termcap libraries
+ * %a[+*-/=][cp]x GNU arithmetic.
+ * %m xor the first two parameters by 0177
+ * %b backup to previous parameter
+ * %f skip this parameter
+ *
+ * used by the University of Waterloo (MFCF) termcap libraries
+ * %-x subtract parameter FROM char x and output it as a char
+ * %ax add the character x to parameter
+ *
+ * If #define WATERLOO is on, also enable these translations:
+ *
+ * %sx subtract parameter FROM the character x
+ *
+ * By default, this Waterloo translations are not compiled in, because
+ * the Waterloo %s conflicts with the way terminfo uses %s in strings for
+ * function programming.
+ *
+ * Note the two definitions of %a: the GNU definition is translated if the
+ * characters after the 'a' are valid for it, otherwise the UW definition
+ * is translated.
+ */
+
+#include <curses.priv.h>
+
+#include <ctype.h>
+#include <tic.h>
+
+MODULE_ID("$Id: captoinfo.c,v 1.49 2006/12/16 19:16:53 tom Exp $")
+
+#define MAX_PUSHED 16 /* max # args we can push onto the stack */
+
+static int stack[MAX_PUSHED]; /* the stack */
+static int stackptr; /* the next empty place on the stack */
+static int onstack; /* the top of stack */
+static int seenm; /* seen a %m */
+static int seenn; /* seen a %n */
+static int seenr; /* seen a %r */
+static int param; /* current parameter */
+static char *dp; /* pointer to end of the converted string */
+
+static char *my_string;
+static size_t my_length;
+
+static char *
+init_string(void)
+/* initialize 'my_string', 'my_length' */
+{
+ if (my_string == 0)
+ my_string = typeMalloc(char, my_length = 256);
+ if (my_string == 0)
+ _nc_err_abort(MSG_NO_MEMORY);
+
+ *my_string = '\0';
+ return my_string;
+}
+
+static char *
+save_string(char *d, const char *const s)
+{
+ size_t have = (d - my_string);
+ size_t need = have + strlen(s) + 2;
+ if (need > my_length) {
+ my_string = (char *) realloc(my_string, my_length = (need + need));
+ if (my_string == 0)
+ _nc_err_abort(MSG_NO_MEMORY);
+ d = my_string + have;
+ }
+ (void) strcpy(d, s);
+ return d + strlen(d);
+}
+
+static NCURSES_INLINE char *
+save_char(char *s, int c)
+{
+ static char temp[2];
+ temp[0] = (char) c;
+ return save_string(s, temp);
+}
+
+static void
+push(void)
+/* push onstack on to the stack */
+{
+ if (stackptr > MAX_PUSHED)
+ _nc_warning("string too complex to convert");
+ else
+ stack[stackptr++] = onstack;
+}
+
+static void
+pop(void)
+/* pop the top of the stack into onstack */
+{
+ if (stackptr == 0) {
+ if (onstack == 0)
+ _nc_warning("I'm confused");
+ else
+ onstack = 0;
+ } else
+ onstack = stack[--stackptr];
+ param++;
+}
+
+static int
+cvtchar(register const char *sp)
+/* convert a character to a terminfo push */
+{
+ unsigned char c = 0;
+ int len;
+
+ switch (*sp) {
+ case '\\':
+ switch (*++sp) {
+ case '\'':
+ case '$':
+ case '\\':
+ case '%':
+ c = *sp;
+ len = 2;
+ break;
+ case '\0':
+ c = '\\';
+ len = 1;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ len = 1;
+ while (isdigit(UChar(*sp))) {
+ c = 8 * c + (*sp++ - '0');
+ len++;
+ }
+ break;
+ default:
+ c = *sp;
+ len = 2;
+ break;
+ }
+ break;
+ case '^':
+ c = (*++sp & 0x1f);
+ len = 2;
+ break;
+ default:
+ c = *sp;
+ len = 1;
+ }
+ if (isgraph(c) && c != ',' && c != '\'' && c != '\\' && c != ':') {
+ dp = save_string(dp, "%\'");
+ dp = save_char(dp, c);
+ dp = save_char(dp, '\'');
+ } else {
+ dp = save_string(dp, "%{");
+ if (c > 99)
+ dp = save_char(dp, c / 100 + '0');
+ if (c > 9)
+ dp = save_char(dp, ((int) (c / 10)) % 10 + '0');
+ dp = save_char(dp, c % 10 + '0');
+ dp = save_char(dp, '}');
+ }
+ return len;
+}
+
+static void
+getparm(int parm, int n)
+/* push n copies of param on the terminfo stack if not already there */
+{
+ if (seenr) {
+ if (parm == 1)
+ parm = 2;
+ else if (parm == 2)
+ parm = 1;
+ }
+ if (onstack == parm) {
+ if (n > 1) {
+ _nc_warning("string may not be optimal");
+ dp = save_string(dp, "%Pa");
+ while (n--) {
+ dp = save_string(dp, "%ga");
+ }
+ }
+ return;
+ }
+ if (onstack != 0)
+ push();
+
+ onstack = parm;
+
+ while (n--) {
+ dp = save_string(dp, "%p");
+ dp = save_char(dp, '0' + parm);
+ }
+
+ if (seenn && parm < 3) {
+ dp = save_string(dp, "%{96}%^");
+ }
+
+ if (seenm && parm < 3) {
+ dp = save_string(dp, "%{127}%^");
+ }
+}
+
+/*
+ * Convert a termcap string to terminfo format.
+ * 'cap' is the relevant terminfo capability index.
+ * 's' is the string value of the capability.
+ * 'parameterized' tells what type of translations to do:
+ * % translations if 1
+ * pad translations if >=0
+ */
+NCURSES_EXPORT(char *)
+_nc_captoinfo(const char *cap, const char *s, int const parameterized)
+{
+ const char *capstart;
+
+ stackptr = 0;
+ onstack = 0;
+ seenm = 0;
+ seenn = 0;
+ seenr = 0;
+ param = 1;
+
+ dp = init_string();
+
+ /* skip the initial padding (if we haven't been told not to) */
+ capstart = 0;
+ if (s == 0)
+ s = "";
+ if (parameterized >= 0 && isdigit(UChar(*s)))
+ for (capstart = s;; s++)
+ if (!(isdigit(UChar(*s)) || *s == '*' || *s == '.'))
+ break;
+
+ while (*s != '\0') {
+ switch (*s) {
+ case '%':
+ s++;
+ if (parameterized < 1) {
+ dp = save_char(dp, '%');
+ break;
+ }
+ switch (*s++) {
+ case '%':
+ dp = save_char(dp, '%');
+ break;
+ case 'r':
+ if (seenr++ == 1) {
+ _nc_warning("saw %%r twice in %s", cap);
+ }
+ break;
+ case 'm':
+ if (seenm++ == 1) {
+ _nc_warning("saw %%m twice in %s", cap);
+ }
+ break;
+ case 'n':
+ if (seenn++ == 1) {
+ _nc_warning("saw %%n twice in %s", cap);
+ }
+ break;
+ case 'i':
+ dp = save_string(dp, "%i");
+ break;
+ case '6':
+ case 'B':
+ getparm(param, 1);
+ dp = save_string(dp, "%{10}%/%{16}%*");
+ getparm(param, 1);
+ dp = save_string(dp, "%{10}%m%+");
+ break;
+ case '8':
+ case 'D':
+ getparm(param, 2);
+ dp = save_string(dp, "%{2}%*%-");
+ break;
+ case '>':
+ getparm(param, 2);
+ /* %?%{x}%>%t%{y}%+%; */
+ dp = save_string(dp, "%?");
+ s += cvtchar(s);
+ dp = save_string(dp, "%>%t");
+ s += cvtchar(s);
+ dp = save_string(dp, "%+%;");
+ break;
+ case 'a':
+ if ((*s == '=' || *s == '+' || *s == '-'
+ || *s == '*' || *s == '/')
+ && (s[1] == 'p' || s[1] == 'c')
+ && s[2] != '\0') {
+ int l;
+ l = 2;
+ if (*s != '=')
+ getparm(param, 1);
+ if (s[1] == 'p') {
+ getparm(param + s[2] - '@', 1);
+ if (param != onstack) {
+ pop();
+ param--;
+ }
+ l++;
+ } else
+ l += cvtchar(s + 2);
+ switch (*s) {
+ case '+':
+ dp = save_string(dp, "%+");
+ break;
+ case '-':
+ dp = save_string(dp, "%-");
+ break;
+ case '*':
+ dp = save_string(dp, "%*");
+ break;
+ case '/':
+ dp = save_string(dp, "%/");
+ break;
+ case '=':
+ if (seenr) {
+ if (param == 1)
+ onstack = 2;
+ else if (param == 2)
+ onstack = 1;
+ else
+ onstack = param;
+ } else
+ onstack = param;
+ break;
+ }
+ s += l;
+ break;
+ }
+ getparm(param, 1);
+ s += cvtchar(s);
+ dp = save_string(dp, "%+");
+ break;
+ case '+':
+ getparm(param, 1);
+ s += cvtchar(s);
+ dp = save_string(dp, "%+%c");
+ pop();
+ break;
+ case 's':
+#ifdef WATERLOO
+ s += cvtchar(s);
+ getparm(param, 1);
+ dp = save_string(dp, "%-");
+#else
+ getparm(param, 1);
+ dp = save_string(dp, "%s");
+ pop();
+#endif /* WATERLOO */
+ break;
+ case '-':
+ s += cvtchar(s);
+ getparm(param, 1);
+ dp = save_string(dp, "%-%c");
+ pop();
+ break;
+ case '.':
+ getparm(param, 1);
+ dp = save_string(dp, "%c");
+ pop();
+ break;
+ case '0': /* not clear any of the historical termcaps did this */
+ if (*s == '3')
+ goto see03;
+ else if (*s != '2')
+ goto invalid;
+ /* FALLTHRU */
+ case '2':
+ getparm(param, 1);
+ dp = save_string(dp, "%2d");
+ pop();
+ break;
+ case '3':
+ see03:
+ getparm(param, 1);
+ dp = save_string(dp, "%3d");
+ pop();
+ break;
+ case 'd':
+ getparm(param, 1);
+ dp = save_string(dp, "%d");
+ pop();
+ break;
+ case 'f':
+ param++;
+ break;
+ case 'b':
+ param--;
+ break;
+ case '\\':
+ dp = save_string(dp, "%\\");
+ break;
+ default:
+ invalid:
+ dp = save_char(dp, '%');
+ s--;
+ _nc_warning("unknown %% code %s (%#x) in %s",
+ unctrl((chtype) *s), UChar(*s), cap);
+ break;
+ }
+ break;
+#ifdef REVISIBILIZE
+ case '\\':
+ dp = save_char(dp, *s++);
+ dp = save_char(dp, *s++);
+ break;
+ case '\n':
+ dp = save_string(dp, "\\n");
+ s++;
+ break;
+ case '\t':
+ dp = save_string(dp, "\\t");
+ s++;
+ break;
+ case '\r':
+ dp = save_string(dp, "\\r");
+ s++;
+ break;
+ case '\200':
+ dp = save_string(dp, "\\0");
+ s++;
+ break;
+ case '\f':
+ dp = save_string(dp, "\\f");
+ s++;
+ break;
+ case '\b':
+ dp = save_string(dp, "\\b");
+ s++;
+ break;
+ case ' ':
+ dp = save_string(dp, "\\s");
+ s++;
+ break;
+ case '^':
+ dp = save_string(dp, "\\^");
+ s++;
+ break;
+ case ':':
+ dp = save_string(dp, "\\:");
+ s++;
+ break;
+ case ',':
+ dp = save_string(dp, "\\,");
+ s++;
+ break;
+ default:
+ if (*s == '\033') {
+ dp = save_string(dp, "\\E");
+ s++;
+ } else if (*s > 0 && *s < 32) {
+ dp = save_char(dp, '^');
+ dp = save_char(dp, *s + '@');
+ s++;
+ } else if (*s <= 0 || *s >= 127) {
+ dp = save_char(dp, '\\');
+ dp = save_char(dp, ((*s & 0300) >> 6) + '0');
+ dp = save_char(dp, ((*s & 0070) >> 3) + '0');
+ dp = save_char(dp, (*s & 0007) + '0');
+ s++;
+ } else
+ dp = save_char(dp, *s++);
+ break;
+#else
+ default:
+ dp = save_char(dp, *s++);
+ break;
+#endif
+ }
+ }
+
+ /*
+ * Now, if we stripped off some leading padding, add it at the end
+ * of the string as mandatory padding.
+ */
+ if (capstart) {
+ dp = save_string(dp, "$<");
+ for (s = capstart;; s++)
+ if (isdigit(UChar(*s)) || *s == '*' || *s == '.')
+ dp = save_char(dp, *s);
+ else
+ break;
+ dp = save_string(dp, "/>");
+ }
+
+ (void) save_char(dp, '\0');
+ return (my_string);
+}
+
+/*
+ * Check for an expression that corresponds to "%B" (BCD):
+ * (parameter / 10) * 16 + (parameter % 10)
+ */
+static int
+bcd_expression(const char *str)
+{
+ /* leave this non-const for HPUX */
+ static char fmt[] = "%%p%c%%{10}%%/%%{16}%%*%%p%c%%{10}%%m%%+";
+ int len = 0;
+ char ch1, ch2;
+
+ if (sscanf(str, fmt, &ch1, &ch2) == 2
+ && isdigit(UChar(ch1))
+ && isdigit(UChar(ch2))
+ && (ch1 == ch2)) {
+ len = 28;
+#ifndef NDEBUG
+ {
+ char buffer[80];
+ int tst;
+ sprintf(buffer, fmt, ch1, ch2);
+ tst = strlen(buffer) - 1;
+ assert(len == tst);
+ }
+#endif
+ }
+ return len;
+}
+
+static char *
+save_tc_char(char *bufptr, int c1)
+{
+ char temp[80];
+
+ if (is7bits(c1) && isprint(c1)) {
+ if (c1 == ':' || c1 == '\\')
+ bufptr = save_char(bufptr, '\\');
+ bufptr = save_char(bufptr, c1);
+ } else {
+ if (c1 == (c1 & 0x1f)) /* iscntrl() returns T on 255 */
+ (void) strcpy(temp, unctrl((chtype) c1));
+ else
+ (void) sprintf(temp, "\\%03o", c1);
+ bufptr = save_string(bufptr, temp);
+ }
+ return bufptr;
+}
+
+static char *
+save_tc_inequality(char *bufptr, int c1, int c2)
+{
+ bufptr = save_string(bufptr, "%>");
+ bufptr = save_tc_char(bufptr, c1);
+ bufptr = save_tc_char(bufptr, c2);
+ return bufptr;
+}
+
+/*
+ * Here are the capabilities infotocap assumes it can translate to:
+ *
+ * %% output `%'
+ * %d output value as in printf %d
+ * %2 output value as in printf %2d
+ * %3 output value as in printf %3d
+ * %. output value as in printf %c
+ * %+c add character c to value, then do %.
+ * %>xy if value > x then add y, no output
+ * %r reverse order of two parameters, no output
+ * %i increment by one, no output
+ * %n exclusive-or all parameters with 0140 (Datamedia 2500)
+ * %B BCD (16*(value/10)) + (value%10), no output
+ * %D Reverse coding (value - 2*(value%16)), no output (Delta Data).
+ * %m exclusive-or all parameters with 0177 (not in 4.4BSD)
+ */
+
+/*
+ * Convert a terminfo string to termcap format. Parameters are as in
+ * _nc_captoinfo().
+ */
+NCURSES_EXPORT(char *)
+_nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameterized)
+{
+ int seenone = 0, seentwo = 0, saw_m = 0, saw_n = 0;
+ const char *padding;
+ const char *trimmed = 0;
+ char ch1 = 0, ch2 = 0;
+ char *bufptr = init_string();
+ int len;
+ bool syntax_error = FALSE;
+
+ /* we may have to move some trailing mandatory padding up front */
+ padding = str + strlen(str) - 1;
+ if (padding > str && *padding == '>' && *--padding == '/') {
+ --padding;
+ while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*')
+ padding--;
+ if (padding > str && *padding == '<' && *--padding == '$')
+ trimmed = padding;
+ padding += 2;
+
+ while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*')
+ bufptr = save_char(bufptr, *padding++);
+ }
+
+ for (; *str && str != trimmed; str++) {
+ int c1, c2;
+ char *cp = 0;
+
+ if (str[0] == '\\' && (str[1] == '^' || str[1] == ',')) {
+ bufptr = save_char(bufptr, *++str);
+ } else if (str[0] == '$' && str[1] == '<') { /* discard padding */
+ str += 2;
+ while (isdigit(UChar(*str))
+ || *str == '.'
+ || *str == '*'
+ || *str == '/'
+ || *str == '>')
+ str++;
+ --str;
+ } else if (str[0] == '%' && str[1] == '%') { /* escaped '%' */
+ bufptr = save_string(bufptr, "%%");
+ ++str;
+ } else if (*str != '%' || (parameterized < 1)) {
+ bufptr = save_char(bufptr, *str);
+ } else if (sscanf(str, "%%?%%{%d}%%>%%t%%{%d}%%+%%;", &c1, &c2) == 2) {
+ str = strchr(str, ';');
+ bufptr = save_tc_inequality(bufptr, c1, c2);
+ } else if (sscanf(str, "%%?%%{%d}%%>%%t%%'%c'%%+%%;", &c1, &ch2) == 2) {
+ str = strchr(str, ';');
+ bufptr = save_tc_inequality(bufptr, c1, c2);
+ } else if (sscanf(str, "%%?%%'%c'%%>%%t%%{%d}%%+%%;", &ch1, &c2) == 2) {
+ str = strchr(str, ';');
+ bufptr = save_tc_inequality(bufptr, c1, c2);
+ } else if (sscanf(str, "%%?%%'%c'%%>%%t%%'%c'%%+%%;", &ch1, &ch2) == 2) {
+ str = strchr(str, ';');
+ bufptr = save_tc_inequality(bufptr, c1, c2);
+ } else if ((len = bcd_expression(str)) != 0) {
+ str += len;
+ bufptr = save_string(bufptr, "%B");
+ } else if ((sscanf(str, "%%{%d}%%+%%c", &c1) == 1
+ || sscanf(str, "%%'%c'%%+%%c", &ch1) == 1)
+ && (cp = strchr(str, '+'))) {
+ str = cp + 2;
+ bufptr = save_string(bufptr, "%+");
+
+ if (ch1)
+ c1 = ch1;
+ bufptr = save_tc_char(bufptr, c1);
+ }
+ /* FIXME: this "works" for 'delta' */
+ else if (strncmp(str, "%{2}%*%-", 8) == 0) {
+ str += 7;
+ bufptr = save_string(bufptr, "%D");
+ } else if (strncmp(str, "%{96}%^", 7) == 0) {
+ str += 6;
+ if (saw_m++ == 0) {
+ bufptr = save_string(bufptr, "%n");
+ }
+ } else if (strncmp(str, "%{127}%^", 8) == 0) {
+ str += 7;
+ if (saw_n++ == 0) {
+ bufptr = save_string(bufptr, "%m");
+ }
+ } else { /* cm-style format element */
+ str++;
+ switch (*str) {
+ case '%':
+ bufptr = save_char(bufptr, '%');
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ bufptr = save_char(bufptr, '%');
+ while (isdigit(UChar(*str)))
+ bufptr = save_char(bufptr, *str++);
+ if (strchr("doxX.", *str)) {
+ if (*str != 'd') /* termcap doesn't have octal, hex */
+ return 0;
+ }
+ break;
+
+ case 'd':
+ bufptr = save_string(bufptr, "%d");
+ break;
+
+ case 'c':
+ bufptr = save_string(bufptr, "%.");
+ break;
+
+ /*
+ * %s isn't in termcap, but it's convenient to pass it through
+ * so we can represent things like terminfo pfkey strings in
+ * termcap notation.
+ */
+ case 's':
+ bufptr = save_string(bufptr, "%s");
+ break;
+
+ case 'p':
+ str++;
+ if (*str == '1')
+ seenone = 1;
+ else if (*str == '2') {
+ if (!seenone && !seentwo) {
+ bufptr = save_string(bufptr, "%r");
+ seentwo++;
+ }
+ } else if (*str >= '3')
+ return (0);
+ break;
+
+ case 'i':
+ bufptr = save_string(bufptr, "%i");
+ break;
+
+ default:
+ bufptr = save_char(bufptr, *str);
+ syntax_error = TRUE;
+ break;
+ } /* endswitch (*str) */
+ } /* endelse (*str == '%') */
+
+ if (*str == '\0')
+ break;
+
+ } /* endwhile (*str) */
+
+ return (syntax_error ? NULL : my_string);
+}
+
+#ifdef MAIN
+
+int curr_line;
+
+int
+main(int argc, char *argv[])
+{
+ int c, tc = FALSE;
+
+ while ((c = getopt(argc, argv, "c")) != EOF)
+ switch (c) {
+ case 'c':
+ tc = TRUE;
+ break;
+ }
+
+ curr_line = 0;
+ for (;;) {
+ char buf[BUFSIZ];
+
+ ++curr_line;
+ if (fgets(buf, sizeof(buf), stdin) == 0)
+ break;
+ buf[strlen(buf) - 1] = '\0';
+ _nc_set_source(buf);
+
+ if (tc) {
+ char *cp = _nc_infotocap("to termcap", buf, 1);
+
+ if (cp)
+ (void) fputs(cp, stdout);
+ } else
+ (void) fputs(_nc_captoinfo("to terminfo", buf, 1), stdout);
+ (void) putchar('\n');
+ }
+ return (0);
+}
+#endif /* MAIN */
+
+#if NO_LEAKS
+NCURSES_EXPORT(void)
+_nc_captoinfo_leaks(void)
+{
+ if (my_string != 0) {
+ FreeAndNull(my_string);
+ }
+ my_length = 0;
+}
+#endif
diff --git a/ncurses/tinfo/comp_error.c b/ncurses/tinfo/comp_error.c
new file mode 100644
index 000000000000..56c362a4f7dd
--- /dev/null
+++ b/ncurses/tinfo/comp_error.c
@@ -0,0 +1,153 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2007 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ ****************************************************************************/
+
+/*
+ * comp_error.c -- Error message routines
+ *
+ */
+
+#include <curses.priv.h>
+
+#include <tic.h>
+
+MODULE_ID("$Id: comp_error.c,v 1.31 2007/04/21 23:38:32 tom Exp $")
+
+NCURSES_EXPORT_VAR(bool) _nc_suppress_warnings = FALSE;
+NCURSES_EXPORT_VAR(int) _nc_curr_line = 0; /* current line # in input */
+NCURSES_EXPORT_VAR(int) _nc_curr_col = 0; /* current column # in input */
+
+#define SourceName _nc_globals.comp_sourcename
+#define TermType _nc_globals.comp_termtype
+
+NCURSES_EXPORT(const char *)
+_nc_get_source(void)
+{
+ return SourceName;
+}
+
+NCURSES_EXPORT(void)
+_nc_set_source(const char *const name)
+{
+ SourceName = name;
+}
+
+NCURSES_EXPORT(void)
+_nc_set_type(const char *const name)
+{
+ if (TermType == 0)
+ TermType = typeMalloc(char, MAX_NAME_SIZE + 1);
+ if (TermType != 0) {
+ TermType[0] = '\0';
+ if (name)
+ strncat(TermType, name, MAX_NAME_SIZE);
+ }
+}
+
+NCURSES_EXPORT(void)
+_nc_get_type(char *name)
+{
+#if NO_LEAKS
+ if (name == 0 && TermType != 0) {
+ FreeAndNull(TermType);
+ return;
+ }
+#endif
+ if (name != 0)
+ strcpy(name, TermType != 0 ? TermType : "");
+}
+
+static NCURSES_INLINE void
+where_is_problem(void)
+{
+ fprintf(stderr, "\"%s\"", SourceName ? SourceName : "?");
+ if (_nc_curr_line >= 0)
+ fprintf(stderr, ", line %d", _nc_curr_line);
+ if (_nc_curr_col >= 0)
+ fprintf(stderr, ", col %d", _nc_curr_col);
+ if (TermType != 0 && TermType[0] != '\0')
+ fprintf(stderr, ", terminal '%s'", TermType);
+ fputc(':', stderr);
+ fputc(' ', stderr);
+}
+
+NCURSES_EXPORT(void)
+_nc_warning(const char *const fmt,...)
+{
+ va_list argp;
+
+ if (_nc_suppress_warnings)
+ return;
+
+ where_is_problem();
+ va_start(argp, fmt);
+ vfprintf(stderr, fmt, argp);
+ fprintf(stderr, "\n");
+ va_end(argp);
+}
+
+NCURSES_EXPORT(void)
+_nc_err_abort(const char *const fmt,...)
+{
+ va_list argp;
+
+ where_is_problem();
+ va_start(argp, fmt);
+ vfprintf(stderr, fmt, argp);
+ fprintf(stderr, "\n");
+ va_end(argp);
+ exit(EXIT_FAILURE);
+}
+
+NCURSES_EXPORT(void)
+_nc_syserr_abort(const char *const fmt,...)
+{
+ va_list argp;
+
+ where_is_problem();
+ va_start(argp, fmt);
+ vfprintf(stderr, fmt, argp);
+ fprintf(stderr, "\n");
+ va_end(argp);
+
+ /* If we're debugging, try to show where the problem occurred - this
+ * will dump core.
+ */
+#if defined(TRACE) || !defined(NDEBUG)
+ abort();
+#else
+ /* Dumping core in production code is not a good idea.
+ */
+ exit(EXIT_FAILURE);
+#endif
+}
diff --git a/ncurses/tinfo/comp_expand.c b/ncurses/tinfo/comp_expand.c
new file mode 100644
index 000000000000..ef419d84cd2c
--- /dev/null
+++ b/ncurses/tinfo/comp_expand.c
@@ -0,0 +1,192 @@
+/****************************************************************************
+ * Copyright (c) 1998-2001,2006 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), 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 <dickey@clark.net> 1998 *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+
+#include <ctype.h>
+#include <tic.h>
+
+MODULE_ID("$Id: comp_expand.c,v 1.18 2006/06/17 19:37:14 tom Exp $")
+
+static int
+trailing_spaces(const char *src)
+{
+ while (*src == ' ')
+ src++;
+ return *src == 0;
+}
+
+/* this deals with differences over whether 0x7f and 0x80..0x9f are controls */
+#define REALCTL(s) (UChar(*(s)) < 127 && iscntrl(UChar(*(s))))
+#define REALPRINT(s) (UChar(*(s)) < 127 && isprint(UChar(*(s))))
+
+NCURSES_EXPORT(char *)
+_nc_tic_expand(const char *srcp, bool tic_format, int numbers)
+{
+ static char *buffer;
+ static size_t length;
+
+ int bufp;
+ const char *str = VALID_STRING(srcp) ? srcp : "";
+ bool islong = (strlen(str) > 3);
+ size_t need = (2 + strlen(str)) * 4;
+ int ch;
+
+#if NO_LEAKS
+ if (srcp == 0) {
+ if (buffer != 0) {
+ FreeAndNull(buffer);
+ length = 0;
+ }
+ return 0;
+ }
+#endif
+ if (buffer == 0 || need > length) {
+ if ((buffer = typeRealloc(char, length = need, buffer)) == 0)
+ return 0;
+ }
+
+ bufp = 0;
+ while ((ch = UChar(*str)) != 0) {
+ if (ch == '%' && REALPRINT(str + 1)) {
+ buffer[bufp++] = *str++;
+ /*
+ * Though the character literals are more compact, most
+ * terminal descriptions use numbers and are not easy
+ * to read in character-literal form.
+ */
+ switch (numbers) {
+ case -1:
+ if (str[0] == S_QUOTE
+ && str[1] != '\\'
+ && REALPRINT(str + 1)
+ && str[2] == S_QUOTE) {
+ sprintf(buffer + bufp, "{%d}", str[1]);
+ bufp += strlen(buffer + bufp);
+ str += 2;
+ } else {
+ buffer[bufp++] = *str;
+ }
+ break;
+ /*
+ * If we have a "%{number}", try to translate it into
+ * a "%'char'" form, since that will run a little faster
+ * when we're interpreting it. Also, having one form
+ * for the constant makes it simpler to compare terminal
+ * descriptions.
+ */
+ case 1:
+ if (str[0] == L_BRACE
+ && isdigit(UChar(str[1]))) {
+ char *dst = 0;
+ long value = strtol(str + 1, &dst, 0);
+ if (dst != 0
+ && *dst == R_BRACE
+ && value < 127
+ && value != '\\' /* FIXME */
+ && isprint((int) value)) {
+ ch = (int) value;
+ buffer[bufp++] = S_QUOTE;
+ if (ch == '\\'
+ || ch == S_QUOTE)
+ buffer[bufp++] = '\\';
+ buffer[bufp++] = ch;
+ buffer[bufp++] = S_QUOTE;
+ str = dst;
+ } else {
+ buffer[bufp++] = *str;
+ }
+ } else {
+ buffer[bufp++] = *str;
+ }
+ break;
+ default:
+ buffer[bufp++] = *str;
+ break;
+ }
+ } else if (ch == 128) {
+ buffer[bufp++] = '\\';
+ buffer[bufp++] = '0';
+ } else if (ch == '\033') {
+ buffer[bufp++] = '\\';
+ buffer[bufp++] = 'E';
+ } else if (ch == '\\' && tic_format && (str == srcp || str[-1] != '^')) {
+ buffer[bufp++] = '\\';
+ buffer[bufp++] = '\\';
+ } else if (ch == ' ' && tic_format && (str == srcp ||
+ trailing_spaces(str))) {
+ buffer[bufp++] = '\\';
+ buffer[bufp++] = 's';
+ } else if ((ch == ',' || ch == ':' || ch == '^') && tic_format) {
+ buffer[bufp++] = '\\';
+ buffer[bufp++] = ch;
+ } else if (REALPRINT(str)
+ && (ch != ','
+ && ch != ':'
+ && !(ch == '!' && !tic_format)
+ && ch != '^'))
+ buffer[bufp++] = ch;
+#if 0 /* FIXME: this would be more readable (in fact the whole 'islong' logic should be removed) */
+ else if (ch == '\b') {
+ buffer[bufp++] = '\\';
+ buffer[bufp++] = 'b';
+ } else if (ch == '\f') {
+ buffer[bufp++] = '\\';
+ buffer[bufp++] = 'f';
+ } else if (ch == '\t' && islong) {
+ buffer[bufp++] = '\\';
+ buffer[bufp++] = 't';
+ }
+#endif
+ else if (ch == '\r' && (islong || (strlen(srcp) > 2 && str[1] == '\0'))) {
+ buffer[bufp++] = '\\';
+ buffer[bufp++] = 'r';
+ } else if (ch == '\n' && islong) {
+ buffer[bufp++] = '\\';
+ buffer[bufp++] = 'n';
+ }
+#define UnCtl(c) ((c) + '@')
+ else if (REALCTL(str) && ch != '\\'
+ && (!islong || isdigit(UChar(str[1])))) {
+ (void) sprintf(&buffer[bufp], "^%c", UnCtl(ch));
+ bufp += 2;
+ } else {
+ (void) sprintf(&buffer[bufp], "\\%03o", ch);
+ bufp += 4;
+ }
+
+ str++;
+ }
+
+ buffer[bufp] = '\0';
+ return (buffer);
+}
diff --git a/ncurses/tinfo/comp_hash.c b/ncurses/tinfo/comp_hash.c
new file mode 100644
index 000000000000..8b85eee6ced8
--- /dev/null
+++ b/ncurses/tinfo/comp_hash.c
@@ -0,0 +1,366 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2007 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ ****************************************************************************/
+
+/*
+ * comp_hash.c --- Routines to deal with the hashtable of capability
+ * names.
+ *
+ */
+
+#define USE_TERMLIB 1
+#include <curses.priv.h>
+
+#include <tic.h>
+#include <hashsize.h>
+
+#ifdef MAIN_PROGRAM
+#include <ctype.h>
+#undef DEBUG
+#define DEBUG(level, params) /*nothing */
+#endif
+
+MODULE_ID("$Id: comp_hash.c,v 1.33 2007/08/18 21:42:25 tom Exp $")
+
+static int hash_function(const char *);
+
+/*
+ * _nc_make_hash_table()
+ *
+ * Takes the entries in table[] and hashes them into hash_table[]
+ * by name. There are CAPTABSIZE entries in table[] and HASHTABSIZE
+ * slots in hash_table[].
+ *
+ */
+
+#ifdef MAIN_PROGRAM
+
+#undef MODULE_ID
+#define MODULE_ID(id) /*nothing */
+#include <tinfo/doalloc.c>
+
+static void
+_nc_make_hash_table(struct name_table_entry *table,
+ short *hash_table)
+{
+ int i;
+ int hashvalue;
+ int collisions = 0;
+
+ for (i = 0; i < HASHTABSIZE; i++) {
+ hash_table[i] = -1;
+ }
+ for (i = 0; i < CAPTABSIZE; i++) {
+ hashvalue = hash_function(table[i].nte_name);
+
+ if (hash_table[hashvalue] >= 0)
+ collisions++;
+
+ if (hash_table[hashvalue] != 0)
+ table[i].nte_link = hash_table[hashvalue];
+ hash_table[hashvalue] = i;
+ }
+
+ DEBUG(4, ("Hash table complete: %d collisions out of %d entries",
+ collisions, CAPTABSIZE));
+}
+#endif
+
+/*
+ * int hash_function(string)
+ *
+ * Computes the hashing function on the given string.
+ *
+ * The current hash function is the sum of each consectutive pair
+ * of characters, taken as two-byte integers, mod HASHTABSIZE.
+ *
+ */
+
+static int
+hash_function(const char *string)
+{
+ long sum = 0;
+
+ DEBUG(9, ("hashing %s", string));
+ while (*string) {
+ sum += (long) (*string + (*(string + 1) << 8));
+ string++;
+ }
+
+ DEBUG(9, ("sum is %ld", sum));
+ return (int) (sum % HASHTABSIZE);
+}
+
+/*
+ * struct name_table_entry *
+ * find_entry(string)
+ *
+ * Finds the entry for the given string in the hash table if present.
+ * Returns a pointer to the entry in the table or 0 if not found.
+ *
+ */
+
+#ifndef MAIN_PROGRAM
+NCURSES_EXPORT(struct name_table_entry const *)
+_nc_find_entry(const char *string,
+ const short *hash_table)
+{
+ int hashvalue;
+ struct name_table_entry const *ptr = 0;
+ struct name_table_entry const *real_table;
+
+ hashvalue = hash_function(string);
+
+ if (hash_table[hashvalue] >= 0) {
+ real_table = _nc_get_table(hash_table != _nc_get_hash_table(FALSE));
+ ptr = real_table + hash_table[hashvalue];
+ while (strcmp(ptr->nte_name, string) != 0) {
+ if (ptr->nte_link < 0)
+ return 0;
+ ptr = real_table + (ptr->nte_link + hash_table[HASHTABSIZE]);
+ }
+ }
+
+ return (ptr);
+}
+
+/*
+ * struct name_table_entry *
+ * find_type_entry(string, type, table)
+ *
+ * Finds the first entry for the given name with the given type in the
+ * given table if present (as distinct from find_entry, which finds the
+ * the last entry regardless of type). You can use this if you detect
+ * a name clash. It's slower, though. Returns a pointer to the entry
+ * in the table or 0 if not found.
+ */
+
+NCURSES_EXPORT(struct name_table_entry const *)
+_nc_find_type_entry(const char *string,
+ int type,
+ const struct name_table_entry *table)
+{
+ struct name_table_entry const *ptr;
+
+ for (ptr = table; ptr < table + CAPTABSIZE; ptr++) {
+ if (ptr->nte_type == type && strcmp(string, ptr->nte_name) == 0)
+ return (ptr);
+ }
+
+ return ((struct name_table_entry *) NULL);
+}
+#endif
+
+#ifdef MAIN_PROGRAM
+/*
+ * This filter reads from standard input a list of tab-delimited columns,
+ * (e.g., from Caps.filtered) computes the hash-value of a specified column and
+ * writes the hashed tables to standard output.
+ *
+ * By compiling the hash table at build time, we're able to make the entire
+ * set of terminfo and termcap tables readonly (and also provide some runtime
+ * performance enhancement).
+ */
+
+#define MAX_COLUMNS BUFSIZ /* this _has_ to be worst-case */
+
+static char **
+parse_columns(char *buffer)
+{
+ static char **list;
+
+ int col = 0;
+
+ if (list == 0 && (list = typeCalloc(char *, MAX_COLUMNS)) == 0)
+ return (0);
+
+ if (*buffer != '#') {
+ while (*buffer != '\0') {
+ char *s;
+ for (s = buffer; (*s != '\0') && !isspace(UChar(*s)); s++)
+ /*EMPTY */ ;
+ if (s != buffer) {
+ char mark = *s;
+ *s = '\0';
+ if ((s - buffer) > 1
+ && (*buffer == '"')
+ && (s[-1] == '"')) { /* strip the quotes */
+ buffer++;
+ s[-1] = '\0';
+ }
+ list[col] = buffer;
+ col++;
+ if (mark == '\0')
+ break;
+ while (*++s && isspace(UChar(*s)))
+ /*EMPTY */ ;
+ buffer = s;
+ } else
+ break;
+ }
+ }
+ return col ? list : 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct name_table_entry *name_table = typeCalloc(struct
+ name_table_entry, CAPTABSIZE);
+ short *hash_table = typeCalloc(short, HASHTABSIZE);
+ const char *root_name = "";
+ int column = 0;
+ int bigstring = 0;
+ int n;
+ char buffer[BUFSIZ];
+
+ static const char *typenames[] =
+ {"BOOLEAN", "NUMBER", "STRING"};
+
+ short BoolCount = 0;
+ short NumCount = 0;
+ short StrCount = 0;
+
+ /* The first argument is the column-number (starting with 0).
+ * The second is the root name of the tables to generate.
+ */
+ if (argc <= 3
+ || (column = atoi(argv[1])) <= 0
+ || (column >= MAX_COLUMNS)
+ || *(root_name = argv[2]) == 0
+ || (bigstring = atoi(argv[3])) < 0) {
+ fprintf(stderr, "usage: make_hash column root_name bigstring\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * Read the table into our arrays.
+ */
+ for (n = 0; (n < CAPTABSIZE) && fgets(buffer, BUFSIZ, stdin);) {
+ char **list, *nlp = strchr(buffer, '\n');
+ if (nlp)
+ *nlp = '\0';
+ list = parse_columns(buffer);
+ if (list == 0) /* blank or comment */
+ continue;
+ name_table[n].nte_link = -1; /* end-of-hash */
+ name_table[n].nte_name = strdup(list[column]);
+ if (!strcmp(list[2], "bool")) {
+ name_table[n].nte_type = BOOLEAN;
+ name_table[n].nte_index = BoolCount++;
+ } else if (!strcmp(list[2], "num")) {
+ name_table[n].nte_type = NUMBER;
+ name_table[n].nte_index = NumCount++;
+ } else if (!strcmp(list[2], "str")) {
+ name_table[n].nte_type = STRING;
+ name_table[n].nte_index = StrCount++;
+ } else {
+ fprintf(stderr, "Unknown type: %s\n", list[2]);
+ exit(EXIT_FAILURE);
+ }
+ n++;
+ }
+ _nc_make_hash_table(name_table, hash_table);
+
+ /*
+ * Write the compiled tables to standard output
+ */
+ if (bigstring) {
+ int len = 0;
+ int nxt;
+
+ printf("static const char %s_names_text[] = \\\n", root_name);
+ for (n = 0; n < CAPTABSIZE; n++) {
+ nxt = strlen(name_table[n].nte_name) + 5;
+ if (nxt + len > 72) {
+ printf("\\\n");
+ len = 0;
+ }
+ printf("\"%s\\0\" ", name_table[n].nte_name);
+ len += nxt;
+ }
+ printf(";\n\n");
+
+ len = 0;
+ printf("static name_table_data const %s_names_data[] =\n",
+ root_name);
+ printf("{\n");
+ for (n = 0; n < CAPTABSIZE; n++) {
+ printf("\t{ %15d,\t%10s,\t%3d, %3d }%c\n",
+ len,
+ typenames[name_table[n].nte_type],
+ name_table[n].nte_index,
+ name_table[n].nte_link,
+ n < CAPTABSIZE - 1 ? ',' : ' ');
+ len += strlen(name_table[n].nte_name) + 1;
+ }
+ printf("};\n\n");
+ printf("static struct name_table_entry *_nc_%s_table = 0;\n\n", root_name);
+ } else {
+
+ printf("static struct name_table_entry %s _nc_%s_table[] =\n",
+ bigstring ? "" : "const",
+ root_name);
+ printf("{\n");
+ for (n = 0; n < CAPTABSIZE; n++) {
+ sprintf(buffer, "\"%s\"",
+ name_table[n].nte_name);
+ printf("\t{ %15s,\t%10s,\t%3d, %3d }%c\n",
+ buffer,
+ typenames[name_table[n].nte_type],
+ name_table[n].nte_index,
+ name_table[n].nte_link,
+ n < CAPTABSIZE - 1 ? ',' : ' ');
+ }
+ printf("};\n\n");
+ }
+
+ printf("static const short _nc_%s_hash_table[%d] =\n",
+ root_name,
+ HASHTABSIZE + 1);
+ printf("{\n");
+ for (n = 0; n < HASHTABSIZE; n++) {
+ printf("\t%3d,\n", hash_table[n]);
+ }
+ printf("\t0\t/* base-of-table */\n");
+ printf("};\n\n");
+
+ printf("#if (BOOLCOUNT!=%d)||(NUMCOUNT!=%d)||(STRCOUNT!=%d)\n",
+ BoolCount, NumCount, StrCount);
+ printf("#error\t--> term.h and comp_captab.c disagree about the <--\n");
+ printf("#error\t--> numbers of booleans, numbers and/or strings <--\n");
+ printf("#endif\n\n");
+
+ return EXIT_SUCCESS;
+}
+#endif
diff --git a/ncurses/tinfo/comp_parse.c b/ncurses/tinfo/comp_parse.c
new file mode 100644
index 000000000000..aa60047b0aad
--- /dev/null
+++ b/ncurses/tinfo/comp_parse.c
@@ -0,0 +1,490 @@
+/****************************************************************************
+ * Copyright (c) 1998-2006,2007 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ ****************************************************************************/
+
+/*
+ * comp_parse.c -- parser driver loop and use handling.
+ *
+ * _nc_read_entry_source(FILE *, literal, bool, bool (*hook)())
+ * _nc_resolve_uses2(void)
+ * _nc_free_entries(void)
+ *
+ * Use this code by calling _nc_read_entry_source() on as many source
+ * files as you like (either terminfo or termcap syntax). If you
+ * want use-resolution, call _nc_resolve_uses2(). To free the list
+ * storage, do _nc_free_entries().
+ *
+ */
+
+#include <curses.priv.h>
+
+#include <ctype.h>
+
+#include <tic.h>
+#include <term_entry.h>
+
+MODULE_ID("$Id: comp_parse.c,v 1.68 2007/11/03 20:41:46 tom Exp $")
+
+static void sanity_check2(TERMTYPE *, bool);
+NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype2) (TERMTYPE *, bool) = sanity_check2;
+
+/* obsolete: 20040705 */
+static void sanity_check(TERMTYPE *);
+NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype) (TERMTYPE *) = sanity_check;
+
+static void
+enqueue(ENTRY * ep)
+/* add an entry to the in-core list */
+{
+ ENTRY *newp = _nc_copy_entry(ep);
+
+ if (newp == 0)
+ _nc_err_abort(MSG_NO_MEMORY);
+
+ newp->last = _nc_tail;
+ _nc_tail = newp;
+
+ newp->next = 0;
+ if (newp->last)
+ newp->last->next = newp;
+}
+
+static char *
+force_bar(char *dst, char *src)
+{
+ if (strchr(src, '|') == 0) {
+ size_t len = strlen(src);
+ if (len > MAX_NAME_SIZE)
+ len = MAX_NAME_SIZE;
+ (void) strncpy(dst, src, len);
+ (void) strcpy(dst + len, "|");
+ src = dst;
+ }
+ return src;
+}
+
+NCURSES_EXPORT(bool)
+_nc_entry_match(char *n1, char *n2)
+/* do any of the aliases in a pair of terminal names match? */
+{
+ char *pstart, *qstart, *pend, *qend;
+ char nc1[MAX_NAME_SIZE + 2], nc2[MAX_NAME_SIZE + 2];
+
+ n1 = force_bar(nc1, n1);
+ n2 = force_bar(nc2, n2);
+
+ for (pstart = n1; (pend = strchr(pstart, '|')); pstart = pend + 1)
+ for (qstart = n2; (qend = strchr(qstart, '|')); qstart = qend + 1)
+ if ((pend - pstart == qend - qstart)
+ && memcmp(pstart, qstart, (size_t) (pend - pstart)) == 0)
+ return (TRUE);
+
+ return (FALSE);
+}
+
+/****************************************************************************
+ *
+ * Entry compiler and resolution logic
+ *
+ ****************************************************************************/
+
+NCURSES_EXPORT(void)
+_nc_read_entry_source(FILE *fp, char *buf,
+ int literal, bool silent,
+ bool(*hook) (ENTRY *))
+/* slurp all entries in the given file into core */
+{
+ ENTRY thisentry;
+ bool oldsuppress = _nc_suppress_warnings;
+ int immediate = 0;
+
+ if (silent)
+ _nc_suppress_warnings = TRUE; /* shut the lexer up, too */
+
+ _nc_reset_input(fp, buf);
+ for (;;) {
+ memset(&thisentry, 0, sizeof(thisentry));
+ if (_nc_parse_entry(&thisentry, literal, silent) == ERR)
+ break;
+ if (!isalnum(UChar(thisentry.tterm.term_names[0])))
+ _nc_err_abort("terminal names must start with letter or digit");
+
+ /*
+ * This can be used for immediate compilation of entries with no "use="
+ * references to disk. That avoids consuming a lot of memory when the
+ * resolution code could fetch entries off disk.
+ */
+ if (hook != NULLHOOK && (*hook) (&thisentry)) {
+ immediate++;
+ } else {
+ enqueue(&thisentry);
+ /*
+ * The enqueued entry is copied with _nc_copy_termtype(), so we can
+ * free some of the data from thisentry, i.e., the arrays.
+ */
+ FreeIfNeeded(thisentry.tterm.Booleans);
+ FreeIfNeeded(thisentry.tterm.Numbers);
+ FreeIfNeeded(thisentry.tterm.Strings);
+#if NCURSES_XNAMES
+ FreeIfNeeded(thisentry.tterm.ext_Names);
+#endif
+ }
+ }
+
+ if (_nc_tail) {
+ /* set up the head pointer */
+ for (_nc_head = _nc_tail; _nc_head->last; _nc_head = _nc_head->last)
+ continue;
+
+ DEBUG(1, ("head = %s", _nc_head->tterm.term_names));
+ DEBUG(1, ("tail = %s", _nc_tail->tterm.term_names));
+ }
+#ifdef TRACE
+ else if (!immediate)
+ DEBUG(1, ("no entries parsed"));
+#endif
+
+ _nc_suppress_warnings = oldsuppress;
+}
+
+NCURSES_EXPORT(int)
+_nc_resolve_uses2(bool fullresolve, bool literal)
+/* try to resolve all use capabilities */
+{
+ ENTRY *qp, *rp, *lastread = 0;
+ bool keepgoing;
+ int i, unresolved, total_unresolved, multiples;
+
+ DEBUG(2, ("RESOLUTION BEGINNING"));
+
+ /*
+ * Check for multiple occurrences of the same name.
+ */
+ multiples = 0;
+ for_entry_list(qp) {
+ int matchcount = 0;
+
+ for_entry_list(rp) {
+ if (qp > rp
+ && _nc_entry_match(qp->tterm.term_names, rp->tterm.term_names)) {
+ matchcount++;
+ if (matchcount == 1) {
+ (void) fprintf(stderr, "Name collision between %s",
+ _nc_first_name(qp->tterm.term_names));
+ multiples++;
+ }
+ if (matchcount >= 1)
+ (void) fprintf(stderr, " %s", _nc_first_name(rp->tterm.term_names));
+ }
+ }
+ if (matchcount >= 1)
+ (void) putc('\n', stderr);
+ }
+ if (multiples > 0)
+ return (FALSE);
+
+ DEBUG(2, ("NO MULTIPLE NAME OCCURRENCES"));
+
+ /*
+ * First resolution stage: compute link pointers corresponding to names.
+ */
+ total_unresolved = 0;
+ _nc_curr_col = -1;
+ for_entry_list(qp) {
+ unresolved = 0;
+ for (i = 0; i < qp->nuses; i++) {
+ bool foundit;
+ char *child = _nc_first_name(qp->tterm.term_names);
+ char *lookfor = qp->uses[i].name;
+ long lookline = qp->uses[i].line;
+
+ foundit = FALSE;
+
+ _nc_set_type(child);
+
+ /* first, try to resolve from in-core records */
+ for_entry_list(rp) {
+ if (rp != qp
+ && _nc_name_match(rp->tterm.term_names, lookfor, "|")) {
+ DEBUG(2, ("%s: resolving use=%s (in core)",
+ child, lookfor));
+
+ qp->uses[i].link = rp;
+ foundit = TRUE;
+ }
+ }
+
+ /* if that didn't work, try to merge in a compiled entry */
+ if (!foundit) {
+ TERMTYPE thisterm;
+ char filename[PATH_MAX];
+
+ memset(&thisterm, 0, sizeof(thisterm));
+ if (_nc_read_entry(lookfor, filename, &thisterm) == 1) {
+ DEBUG(2, ("%s: resolving use=%s (compiled)",
+ child, lookfor));
+
+ rp = typeMalloc(ENTRY, 1);
+ if (rp == 0)
+ _nc_err_abort(MSG_NO_MEMORY);
+ rp->tterm = thisterm;
+ rp->nuses = 0;
+ rp->next = lastread;
+ lastread = rp;
+
+ qp->uses[i].link = rp;
+ foundit = TRUE;
+ }
+ }
+
+ /* no good, mark this one unresolvable and complain */
+ if (!foundit) {
+ unresolved++;
+ total_unresolved++;
+
+ _nc_curr_line = lookline;
+ _nc_warning("resolution of use=%s failed", lookfor);
+ qp->uses[i].link = 0;
+ }
+ }
+ }
+ if (total_unresolved) {
+ /* free entries read in off disk */
+ _nc_free_entries(lastread);
+ return (FALSE);
+ }
+
+ DEBUG(2, ("NAME RESOLUTION COMPLETED OK"));
+
+ /*
+ * OK, at this point all (char *) references in `name' members
+ * have been successfully converted to (ENTRY *) pointers in
+ * `link' members. Time to do the actual merges.
+ */
+ if (fullresolve) {
+ do {
+ TERMTYPE merged;
+
+ keepgoing = FALSE;
+
+ for_entry_list(qp) {
+ if (qp->nuses > 0) {
+ DEBUG(2, ("%s: attempting merge",
+ _nc_first_name(qp->tterm.term_names)));
+ /*
+ * If any of the use entries we're looking for is
+ * incomplete, punt. We'll catch this entry on a
+ * subsequent pass.
+ */
+ for (i = 0; i < qp->nuses; i++)
+ if (qp->uses[i].link->nuses) {
+ DEBUG(2, ("%s: use entry %d unresolved",
+ _nc_first_name(qp->tterm.term_names), i));
+ goto incomplete;
+ }
+
+ /*
+ * First, make sure there is no garbage in the
+ * merge block. As a side effect, copy into
+ * the merged entry the name field and string
+ * table pointer.
+ */
+ _nc_copy_termtype(&merged, &(qp->tterm));
+
+ /*
+ * Now merge in each use entry in the proper
+ * (reverse) order.
+ */
+ for (; qp->nuses; qp->nuses--)
+ _nc_merge_entry(&merged,
+ &qp->uses[qp->nuses - 1].link->tterm);
+
+ /*
+ * Now merge in the original entry.
+ */
+ _nc_merge_entry(&merged, &qp->tterm);
+
+ /*
+ * Replace the original entry with the merged one.
+ */
+ FreeIfNeeded(qp->tterm.Booleans);
+ FreeIfNeeded(qp->tterm.Numbers);
+ FreeIfNeeded(qp->tterm.Strings);
+#if NCURSES_XNAMES
+ FreeIfNeeded(qp->tterm.ext_Names);
+#endif
+ qp->tterm = merged;
+ _nc_wrap_entry(qp, TRUE);
+
+ /*
+ * We know every entry is resolvable because name resolution
+ * didn't bomb. So go back for another pass.
+ */
+ /* FALLTHRU */
+ incomplete:
+ keepgoing = TRUE;
+ }
+ }
+ } while
+ (keepgoing);
+
+ DEBUG(2, ("MERGES COMPLETED OK"));
+ }
+
+ /*
+ * We'd like to free entries read in off disk at this point, but can't.
+ * The merge_entry() code doesn't copy the strings in the use entries,
+ * it just aliases them. If this ever changes, do a
+ * free_entries(lastread) here.
+ */
+
+ DEBUG(2, ("RESOLUTION FINISHED"));
+
+ if (fullresolve)
+ if (_nc_check_termtype != 0) {
+ _nc_curr_col = -1;
+ for_entry_list(qp) {
+ _nc_curr_line = qp->startline;
+ _nc_set_type(_nc_first_name(qp->tterm.term_names));
+ _nc_check_termtype2(&qp->tterm, literal);
+ }
+ DEBUG(2, ("SANITY CHECK FINISHED"));
+ }
+
+ return (TRUE);
+}
+
+/* obsolete: 20040705 */
+NCURSES_EXPORT(int)
+_nc_resolve_uses(bool fullresolve)
+{
+ return _nc_resolve_uses2(fullresolve, FALSE);
+}
+
+/*
+ * This bit of legerdemain turns all the terminfo variable names into
+ * references to locations in the arrays Booleans, Numbers, and Strings ---
+ * precisely what's needed.
+ */
+
+#undef CUR
+#define CUR tp->
+
+static void
+sanity_check2(TERMTYPE *tp, bool literal)
+{
+ if (!PRESENT(exit_attribute_mode)) {
+#ifdef __UNUSED__ /* this casts too wide a net */
+ bool terminal_entry = !strchr(tp->term_names, '+');
+ if (terminal_entry &&
+ (PRESENT(set_attributes)
+ || PRESENT(enter_standout_mode)
+ || PRESENT(enter_underline_mode)
+ || PRESENT(enter_blink_mode)
+ || PRESENT(enter_bold_mode)
+ || PRESENT(enter_dim_mode)
+ || PRESENT(enter_secure_mode)
+ || PRESENT(enter_protected_mode)
+ || PRESENT(enter_reverse_mode)))
+ _nc_warning("no exit_attribute_mode");
+#endif /* __UNUSED__ */
+ PAIRED(enter_standout_mode, exit_standout_mode);
+ PAIRED(enter_underline_mode, exit_underline_mode);
+ }
+
+ /* we do this check/fix in postprocess_termcap(), but some packagers
+ * prefer to bypass it...
+ */
+ if (!literal) {
+ if (acs_chars == 0
+ && enter_alt_charset_mode != 0
+ && exit_alt_charset_mode != 0)
+ acs_chars = strdup(VT_ACSC);
+ ANDMISSING(enter_alt_charset_mode, acs_chars);
+ ANDMISSING(exit_alt_charset_mode, acs_chars);
+ }
+
+ /* listed in structure-member order of first argument */
+ PAIRED(enter_alt_charset_mode, exit_alt_charset_mode);
+ ANDMISSING(enter_blink_mode, exit_attribute_mode);
+ ANDMISSING(enter_bold_mode, exit_attribute_mode);
+ PAIRED(exit_ca_mode, enter_ca_mode);
+ PAIRED(enter_delete_mode, exit_delete_mode);
+ ANDMISSING(enter_dim_mode, exit_attribute_mode);
+ PAIRED(enter_insert_mode, exit_insert_mode);
+ ANDMISSING(enter_secure_mode, exit_attribute_mode);
+ ANDMISSING(enter_protected_mode, exit_attribute_mode);
+ ANDMISSING(enter_reverse_mode, exit_attribute_mode);
+ PAIRED(from_status_line, to_status_line);
+ PAIRED(meta_off, meta_on);
+
+ PAIRED(prtr_on, prtr_off);
+ PAIRED(save_cursor, restore_cursor);
+ PAIRED(enter_xon_mode, exit_xon_mode);
+ PAIRED(enter_am_mode, exit_am_mode);
+ ANDMISSING(label_off, label_on);
+#ifdef remove_clock
+ PAIRED(display_clock, remove_clock);
+#endif
+ ANDMISSING(set_color_pair, initialize_pair);
+}
+
+/* obsolete: 20040705 */
+static void
+sanity_check(TERMTYPE *tp)
+{
+ sanity_check2(tp, FALSE);
+}
+
+#if NO_LEAKS
+NCURSES_EXPORT(void)
+_nc_leaks_tic(void)
+{
+ _nc_alloc_entry_leaks();
+ _nc_captoinfo_leaks();
+ _nc_comp_captab_leaks();
+ _nc_comp_scan_leaks();
+#if BROKEN_LINKER || USE_REENTRANT
+ _nc_names_leaks();
+ _nc_codes_leaks();
+#endif
+ _nc_tic_expand(0, FALSE, 0);
+}
+
+NCURSES_EXPORT(void)
+_nc_free_tic(int code)
+{
+ _nc_leaks_tic();
+ _nc_free_tinfo(code);
+}
+#endif
diff --git a/ncurses/tinfo/comp_scan.c b/ncurses/tinfo/comp_scan.c
new file mode 100644
index 000000000000..e937f7eb5ada
--- /dev/null
+++ b/ncurses/tinfo/comp_scan.c
@@ -0,0 +1,915 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996 on *
+ ****************************************************************************/
+
+/*
+ * comp_scan.c --- Lexical scanner for terminfo compiler.
+ *
+ * _nc_reset_input()
+ * _nc_get_token()
+ * _nc_panic_mode()
+ * int _nc_syntax;
+ * int _nc_curr_line;
+ * long _nc_curr_file_pos;
+ * long _nc_comment_start;
+ * long _nc_comment_end;
+ */
+
+#include <curses.priv.h>
+
+#include <ctype.h>
+#include <term_entry.h>
+#include <tic.h>
+
+MODULE_ID("$Id: comp_scan.c,v 1.78 2006/12/16 19:17:01 tom Exp $")
+
+/*
+ * Maximum length of string capability we'll accept before raising an error.
+ * Yes, there is a real capability in /etc/termcap this long, an "is".
+ */
+#define MAXCAPLEN 600
+
+#define iswhite(ch) (ch == ' ' || ch == '\t')
+
+NCURSES_EXPORT_VAR(int)
+_nc_syntax = 0; /* termcap or terminfo? */
+NCURSES_EXPORT_VAR(long)
+_nc_curr_file_pos = 0; /* file offset of current line */
+NCURSES_EXPORT_VAR(long)
+_nc_comment_start = 0; /* start of comment range before name */
+NCURSES_EXPORT_VAR(long)
+_nc_comment_end = 0; /* end of comment range before name */
+NCURSES_EXPORT_VAR(long)
+_nc_start_line = 0; /* start line of current entry */
+
+NCURSES_EXPORT_VAR(struct token)
+_nc_curr_token =
+{
+ 0, 0, 0
+};
+
+/*****************************************************************************
+ *
+ * Token-grabbing machinery
+ *
+ *****************************************************************************/
+
+static bool first_column; /* See 'next_char()' below */
+static bool had_newline;
+static char separator; /* capability separator */
+static int pushtype; /* type of pushback token */
+static char *pushname;
+
+#if NCURSES_EXT_FUNCS
+NCURSES_EXPORT_VAR(bool)
+_nc_disable_period = FALSE; /* used by tic -a option */
+#endif
+
+/*****************************************************************************
+ *
+ * Character-stream handling
+ *
+ *****************************************************************************/
+
+#define LEXBUFSIZ 1024
+
+static char *bufptr; /* otherwise, the input buffer pointer */
+static char *bufstart; /* start of buffer so we can compute offsets */
+static FILE *yyin; /* scanner's input file descriptor */
+
+/*
+ * _nc_reset_input()
+ *
+ * Resets the input-reading routines. Used on initialization,
+ * or after a seek has been done. Exactly one argument must be
+ * non-null.
+ */
+
+NCURSES_EXPORT(void)
+_nc_reset_input(FILE *fp, char *buf)
+{
+ pushtype = NO_PUSHBACK;
+ if (pushname != 0)
+ pushname[0] = '\0';
+ yyin = fp;
+ bufstart = bufptr = buf;
+ _nc_curr_file_pos = 0L;
+ if (fp != 0)
+ _nc_curr_line = 0;
+ _nc_curr_col = 0;
+}
+
+/*
+ * int last_char()
+ *
+ * Returns the final nonblank character on the current input buffer
+ */
+static int
+last_char(void)
+{
+ size_t len = strlen(bufptr);
+ while (len--) {
+ if (!isspace(UChar(bufptr[len])))
+ return bufptr[len];
+ }
+ return 0;
+}
+
+/*
+ * int next_char()
+ *
+ * Returns the next character in the input stream. Comments and leading
+ * white space are stripped.
+ *
+ * The global state variable 'firstcolumn' is set TRUE if the character
+ * returned is from the first column of the input line.
+ *
+ * The global variable _nc_curr_line is incremented for each new line.
+ * The global variable _nc_curr_file_pos is set to the file offset of the
+ * beginning of each line.
+ */
+
+static int
+next_char(void)
+{
+ static char *result;
+ static size_t allocated;
+ int the_char;
+
+ if (!yyin) {
+ if (result != 0) {
+ FreeAndNull(result);
+ FreeAndNull(pushname);
+ allocated = 0;
+ }
+ /*
+ * An string with an embedded null will truncate the input. This is
+ * intentional (we don't read binary files here).
+ */
+ if (bufptr == 0 || *bufptr == '\0')
+ return (EOF);
+ if (*bufptr == '\n') {
+ _nc_curr_line++;
+ _nc_curr_col = 0;
+ } else if (*bufptr == '\t') {
+ _nc_curr_col = (_nc_curr_col | 7);
+ }
+ } else if (!bufptr || !*bufptr) {
+ /*
+ * In theory this could be recoded to do its I/O one character at a
+ * time, saving the buffer space. In practice, this turns out to be
+ * quite hard to get completely right. Try it and see. If you
+ * succeed, don't forget to hack push_back() correspondingly.
+ */
+ size_t used;
+ size_t len;
+
+ do {
+ bufstart = 0;
+ used = 0;
+ do {
+ if (used + (LEXBUFSIZ / 4) >= allocated) {
+ allocated += (allocated + LEXBUFSIZ);
+ result = typeRealloc(char, allocated, result);
+ if (result == 0)
+ return (EOF);
+ }
+ if (used == 0)
+ _nc_curr_file_pos = ftell(yyin);
+
+ if (fgets(result + used, (int) (allocated - used), yyin) != 0) {
+ bufstart = result;
+ if (used == 0) {
+ _nc_curr_line++;
+ _nc_curr_col = 0;
+ }
+ } else {
+ if (used != 0)
+ strcat(result, "\n");
+ }
+ if ((bufptr = bufstart) != 0) {
+ used = strlen(bufptr);
+ while (iswhite(*bufptr)) {
+ if (*bufptr == '\t') {
+ _nc_curr_col = (_nc_curr_col | 7) + 1;
+ } else {
+ _nc_curr_col++;
+ }
+ bufptr++;
+ }
+
+ /*
+ * Treat a trailing <cr><lf> the same as a <newline> so we
+ * can read files on OS/2, etc.
+ */
+ if ((len = strlen(bufptr)) > 1) {
+ if (bufptr[len - 1] == '\n'
+ && bufptr[len - 2] == '\r') {
+ len--;
+ bufptr[len - 1] = '\n';
+ bufptr[len] = '\0';
+ }
+ }
+ } else {
+ return (EOF);
+ }
+ } while (bufptr[len - 1] != '\n'); /* complete a line */
+ } while (result[0] == '#'); /* ignore comments */
+ } else if (*bufptr == '\t') {
+ _nc_curr_col = (_nc_curr_col | 7);
+ }
+
+ first_column = (bufptr == bufstart);
+ if (first_column)
+ had_newline = FALSE;
+
+ _nc_curr_col++;
+ the_char = *bufptr++;
+ return UChar(the_char);
+}
+
+static void
+push_back(char c)
+/* push a character back onto the input stream */
+{
+ if (bufptr == bufstart)
+ _nc_syserr_abort("Can't backspace off beginning of line");
+ *--bufptr = c;
+ _nc_curr_col--;
+}
+
+static long
+stream_pos(void)
+/* return our current character position in the input stream */
+{
+ return (yyin ? ftell(yyin) : (bufptr ? bufptr - bufstart : 0));
+}
+
+static bool
+end_of_stream(void)
+/* are we at end of input? */
+{
+ return ((yyin ? feof(yyin) : (bufptr && *bufptr == '\0'))
+ ? TRUE : FALSE);
+}
+
+/* Assume we may be looking at a termcap-style continuation */
+static NCURSES_INLINE int
+eat_escaped_newline(int ch)
+{
+ if (ch == '\\')
+ while ((ch = next_char()) == '\n' || iswhite(ch))
+ continue;
+ return ch;
+}
+
+/*
+ * int
+ * get_token()
+ *
+ * Scans the input for the next token, storing the specifics in the
+ * global structure 'curr_token' and returning one of the following:
+ *
+ * NAMES A line beginning in column 1. 'name'
+ * will be set to point to everything up to but
+ * not including the first separator on the line.
+ * BOOLEAN An entry consisting of a name followed by
+ * a separator. 'name' will be set to point to
+ * the name of the capability.
+ * NUMBER An entry of the form
+ * name#digits,
+ * 'name' will be set to point to the capability
+ * name and 'valnumber' to the number given.
+ * STRING An entry of the form
+ * name=characters,
+ * 'name' is set to the capability name and
+ * 'valstring' to the string of characters, with
+ * input translations done.
+ * CANCEL An entry of the form
+ * name@,
+ * 'name' is set to the capability name and
+ * 'valnumber' to -1.
+ * EOF The end of the file has been reached.
+ *
+ * A `separator' is either a comma or a semicolon, depending on whether
+ * we are in termcap or terminfo mode.
+ *
+ */
+
+NCURSES_EXPORT(int)
+_nc_get_token(bool silent)
+{
+ static const char terminfo_punct[] = "@%&*!#";
+ static char *buffer;
+
+ char *after_list;
+ char *after_name;
+ char *numchk;
+ char *ptr;
+ char *s;
+ char numbuf[80];
+ int ch;
+ int dot_flag = FALSE;
+ int type;
+ long number;
+ long token_start;
+ unsigned found;
+#ifdef TRACE
+ int old_line;
+ int old_col;
+#endif
+
+ if (pushtype != NO_PUSHBACK) {
+ int retval = pushtype;
+
+ _nc_set_type(pushname != 0 ? pushname : "");
+ DEBUG(3, ("pushed-back token: `%s', class %d",
+ _nc_curr_token.tk_name, pushtype));
+
+ pushtype = NO_PUSHBACK;
+ if (pushname != 0)
+ pushname[0] = '\0';
+
+ /* currtok wasn't altered by _nc_push_token() */
+ return (retval);
+ }
+
+ if (end_of_stream()) {
+ yyin = 0;
+ next_char(); /* frees its allocated memory */
+ if (buffer != 0) {
+ if (_nc_curr_token.tk_name == buffer)
+ _nc_curr_token.tk_name = 0;
+ FreeAndNull(buffer);
+ }
+ return (EOF);
+ }
+
+ start_token:
+ token_start = stream_pos();
+ while ((ch = next_char()) == '\n' || iswhite(ch)) {
+ if (ch == '\n')
+ had_newline = TRUE;
+ continue;
+ }
+
+ ch = eat_escaped_newline(ch);
+
+#ifdef TRACE
+ old_line = _nc_curr_line;
+ old_col = _nc_curr_col;
+#endif
+ if (ch == EOF)
+ type = EOF;
+ else {
+ /* if this is a termcap entry, skip a leading separator */
+ if (separator == ':' && ch == ':')
+ ch = next_char();
+
+ if (ch == '.'
+#if NCURSES_EXT_FUNCS
+ && !_nc_disable_period
+#endif
+ ) {
+ dot_flag = TRUE;
+ DEBUG(8, ("dot-flag set"));
+
+ while ((ch = next_char()) == '.' || iswhite(ch))
+ continue;
+ }
+
+ if (ch == EOF) {
+ type = EOF;
+ goto end_of_token;
+ }
+
+ /* have to make some punctuation chars legal for terminfo */
+ if (!isalnum(UChar(ch))
+#if NCURSES_EXT_FUNCS
+ && !(ch == '.' && _nc_disable_period)
+#endif
+ && !strchr(terminfo_punct, (char) ch)) {
+ if (!silent)
+ _nc_warning("Illegal character (expected alphanumeric or %s) - '%s'",
+ terminfo_punct, unctrl((chtype) ch));
+ _nc_panic_mode(separator);
+ goto start_token;
+ }
+
+ if (buffer == 0)
+ buffer = typeMalloc(char, MAX_ENTRY_SIZE);
+
+#ifdef TRACE
+ old_line = _nc_curr_line;
+ old_col = _nc_curr_col;
+#endif
+ ptr = buffer;
+ *(ptr++) = ch;
+
+ if (first_column) {
+ _nc_comment_start = token_start;
+ _nc_comment_end = _nc_curr_file_pos;
+ _nc_start_line = _nc_curr_line;
+
+ _nc_syntax = ERR;
+ after_name = 0;
+ after_list = 0;
+ while ((ch = next_char()) != '\n') {
+ if (ch == EOF) {
+ _nc_err_abort(MSG_NO_INPUTS);
+ } else if (ch == '|') {
+ after_list = ptr;
+ if (after_name == 0)
+ after_name = ptr;
+ } else if (ch == ':' && last_char() != ',') {
+ _nc_syntax = SYN_TERMCAP;
+ separator = ':';
+ break;
+ } else if (ch == ',') {
+ _nc_syntax = SYN_TERMINFO;
+ separator = ',';
+ /*
+ * If we did not see a '|', then we found a name with no
+ * aliases or description.
+ */
+ if (after_name == 0)
+ break;
+ /*
+ * If we see a comma, we assume this is terminfo unless we
+ * subsequently run into a colon. But we don't stop
+ * looking for a colon until hitting a newline. This
+ * allows commas to be embedded in description fields of
+ * either syntax.
+ */
+ } else
+ ch = eat_escaped_newline(ch);
+
+ *ptr++ = ch;
+ }
+ ptr[0] = '\0';
+ if (_nc_syntax == ERR) {
+ /*
+ * Grrr...what we ought to do here is barf, complaining that
+ * the entry is malformed. But because a couple of name fields
+ * in the 8.2 termcap file end with |\, we just have to assume
+ * it's termcap syntax.
+ */
+ _nc_syntax = SYN_TERMCAP;
+ separator = ':';
+ } else if (_nc_syntax == SYN_TERMINFO) {
+ /* throw away trailing /, *$/ */
+ for (--ptr; iswhite(*ptr) || *ptr == ','; ptr--)
+ continue;
+ ptr[1] = '\0';
+ }
+
+ /*
+ * This is the soonest we have the terminal name fetched. Set up
+ * for following warning messages. If there's no '|', then there
+ * is no description.
+ */
+ if (after_name != 0) {
+ ch = *after_name;
+ *after_name = '\0';
+ _nc_set_type(buffer);
+ *after_name = ch;
+ }
+
+ /*
+ * Compute the boundary between the aliases and the description
+ * field for syntax-checking purposes.
+ */
+ if (after_list != 0) {
+ if (!silent) {
+ if (*after_list == '\0')
+ _nc_warning("empty longname field");
+ else if (strchr(after_list, ' ') == 0)
+ _nc_warning("older tic versions may treat the description field as an alias");
+ }
+ } else {
+ after_list = buffer + strlen(buffer);
+ DEBUG(1, ("missing description"));
+ }
+
+ /*
+ * Whitespace in a name field other than the long name can confuse
+ * rdist and some termcap tools. Slashes are a no-no. Other
+ * special characters can be dangerous due to shell expansion.
+ */
+ for (s = buffer; s < after_list; ++s) {
+ if (isspace(UChar(*s))) {
+ if (!silent)
+ _nc_warning("whitespace in name or alias field");
+ break;
+ } else if (*s == '/') {
+ if (!silent)
+ _nc_warning("slashes aren't allowed in names or aliases");
+ break;
+ } else if (strchr("$[]!*?", *s)) {
+ if (!silent)
+ _nc_warning("dubious character `%c' in name or alias field", *s);
+ break;
+ }
+ }
+
+ _nc_curr_token.tk_name = buffer;
+ type = NAMES;
+ } else {
+ if (had_newline && _nc_syntax == SYN_TERMCAP) {
+ _nc_warning("Missing backslash before newline");
+ had_newline = FALSE;
+ }
+ while ((ch = next_char()) != EOF) {
+ if (!isalnum(UChar(ch))) {
+ if (_nc_syntax == SYN_TERMINFO) {
+ if (ch != '_')
+ break;
+ } else { /* allow ';' for "k;" */
+ if (ch != ';')
+ break;
+ }
+ }
+ *(ptr++) = ch;
+ }
+
+ *ptr++ = '\0';
+ switch (ch) {
+ case ',':
+ case ':':
+ if (ch != separator)
+ _nc_err_abort("Separator inconsistent with syntax");
+ _nc_curr_token.tk_name = buffer;
+ type = BOOLEAN;
+ break;
+ case '@':
+ if ((ch = next_char()) != separator && !silent)
+ _nc_warning("Missing separator after `%s', have %s",
+ buffer, unctrl((chtype) ch));
+ _nc_curr_token.tk_name = buffer;
+ type = CANCEL;
+ break;
+
+ case '#':
+ found = 0;
+ while (isalnum(ch = next_char())) {
+ numbuf[found++] = ch;
+ if (found >= sizeof(numbuf) - 1)
+ break;
+ }
+ numbuf[found] = '\0';
+ number = strtol(numbuf, &numchk, 0);
+ if (!silent) {
+ if (numchk == numbuf)
+ _nc_warning("no value given for `%s'", buffer);
+ if ((*numchk != '\0') || (ch != separator))
+ _nc_warning("Missing separator");
+ }
+ _nc_curr_token.tk_name = buffer;
+ _nc_curr_token.tk_valnumber = number;
+ type = NUMBER;
+ break;
+
+ case '=':
+ ch = _nc_trans_string(ptr, buffer + MAX_ENTRY_SIZE);
+ if (!silent && ch != separator)
+ _nc_warning("Missing separator");
+ _nc_curr_token.tk_name = buffer;
+ _nc_curr_token.tk_valstring = ptr;
+ type = STRING;
+ break;
+
+ case EOF:
+ type = EOF;
+ break;
+ default:
+ /* just to get rid of the compiler warning */
+ type = UNDEF;
+ if (!silent)
+ _nc_warning("Illegal character - '%s'", unctrl((chtype) ch));
+ }
+ } /* end else (first_column == FALSE) */
+ } /* end else (ch != EOF) */
+
+ end_of_token:
+
+#ifdef TRACE
+ if (dot_flag == TRUE)
+ DEBUG(8, ("Commented out "));
+
+ if (_nc_tracing >= DEBUG_LEVEL(8)) {
+ _tracef("parsed %d.%d to %d.%d",
+ old_line, old_col,
+ _nc_curr_line, _nc_curr_col);
+ }
+ if (_nc_tracing >= DEBUG_LEVEL(7)) {
+ switch (type) {
+ case BOOLEAN:
+ _tracef("Token: Boolean; name='%s'",
+ _nc_curr_token.tk_name);
+ break;
+
+ case NUMBER:
+ _tracef("Token: Number; name='%s', value=%d",
+ _nc_curr_token.tk_name,
+ _nc_curr_token.tk_valnumber);
+ break;
+
+ case STRING:
+ _tracef("Token: String; name='%s', value=%s",
+ _nc_curr_token.tk_name,
+ _nc_visbuf(_nc_curr_token.tk_valstring));
+ break;
+
+ case CANCEL:
+ _tracef("Token: Cancel; name='%s'",
+ _nc_curr_token.tk_name);
+ break;
+
+ case NAMES:
+
+ _tracef("Token: Names; value='%s'",
+ _nc_curr_token.tk_name);
+ break;
+
+ case EOF:
+ _tracef("Token: End of file");
+ break;
+
+ default:
+ _nc_warning("Bad token type");
+ }
+ }
+#endif
+
+ if (dot_flag == TRUE) /* if commented out, use the next one */
+ type = _nc_get_token(silent);
+
+ DEBUG(3, ("token: `%s', class %d",
+ ((_nc_curr_token.tk_name != 0)
+ ? _nc_curr_token.tk_name
+ : "<null>"),
+ type));
+
+ return (type);
+}
+
+/*
+ * char
+ * trans_string(ptr)
+ *
+ * Reads characters using next_char() until encountering a separator, nl,
+ * or end-of-file. The returned value is the character which caused
+ * reading to stop. The following translations are done on the input:
+ *
+ * ^X goes to ctrl-X (i.e. X & 037)
+ * {\E,\n,\r,\b,\t,\f} go to
+ * {ESCAPE,newline,carriage-return,backspace,tab,formfeed}
+ * {\^,\\} go to {carat,backslash}
+ * \ddd (for ddd = up to three octal digits) goes to the character ddd
+ *
+ * \e == \E
+ * \0 == \200
+ *
+ */
+
+NCURSES_EXPORT(int)
+_nc_trans_string(char *ptr, char *last)
+{
+ int count = 0;
+ int number = 0;
+ int i, c;
+ chtype ch, last_ch = '\0';
+ bool ignored = FALSE;
+ bool long_warning = FALSE;
+
+ while ((ch = c = next_char()) != (chtype) separator && c != EOF) {
+ if (ptr == (last - 1))
+ break;
+ if ((_nc_syntax == SYN_TERMCAP) && c == '\n')
+ break;
+ if (ch == '^' && last_ch != '%') {
+ ch = c = next_char();
+ if (c == EOF)
+ _nc_err_abort(MSG_NO_INPUTS);
+
+ if (!(is7bits(ch) && isprint(ch))) {
+ _nc_warning("Illegal ^ character - '%s'", unctrl(ch));
+ }
+ if (ch == '?') {
+ *(ptr++) = '\177';
+ if (_nc_tracing)
+ _nc_warning("Allow ^? as synonym for \\177");
+ } else {
+ if ((ch &= 037) == 0)
+ ch = 128;
+ *(ptr++) = (char) (ch);
+ }
+ } else if (ch == '\\') {
+ ch = c = next_char();
+ if (c == EOF)
+ _nc_err_abort(MSG_NO_INPUTS);
+
+ if (ch >= '0' && ch <= '7') {
+ number = ch - '0';
+ for (i = 0; i < 2; i++) {
+ ch = c = next_char();
+ if (c == EOF)
+ _nc_err_abort(MSG_NO_INPUTS);
+
+ if (c < '0' || c > '7') {
+ if (isdigit(c)) {
+ _nc_warning("Non-octal digit `%c' in \\ sequence", c);
+ /* allow the digit; it'll do less harm */
+ } else {
+ push_back((char) c);
+ break;
+ }
+ }
+
+ number = number * 8 + c - '0';
+ }
+
+ if (number == 0)
+ number = 0200;
+ *(ptr++) = (char) number;
+ } else {
+ switch (c) {
+ case 'E':
+ case 'e':
+ *(ptr++) = '\033';
+ break;
+
+ case 'a':
+ *(ptr++) = '\007';
+ break;
+
+ case 'l':
+ case 'n':
+ *(ptr++) = '\n';
+ break;
+
+ case 'r':
+ *(ptr++) = '\r';
+ break;
+
+ case 'b':
+ *(ptr++) = '\010';
+ break;
+
+ case 's':
+ *(ptr++) = ' ';
+ break;
+
+ case 'f':
+ *(ptr++) = '\014';
+ break;
+
+ case 't':
+ *(ptr++) = '\t';
+ break;
+
+ case '\\':
+ *(ptr++) = '\\';
+ break;
+
+ case '^':
+ *(ptr++) = '^';
+ break;
+
+ case ',':
+ *(ptr++) = ',';
+ break;
+
+ case ':':
+ *(ptr++) = ':';
+ break;
+
+ case '\n':
+ continue;
+
+ default:
+ _nc_warning("Illegal character '%s' in \\ sequence",
+ unctrl(ch));
+ /* FALLTHRU */
+ case '|':
+ *(ptr++) = (char) ch;
+ } /* endswitch (ch) */
+ } /* endelse (ch < '0' || ch > '7') */
+ }
+ /* end else if (ch == '\\') */
+ else if (ch == '\n' && (_nc_syntax == SYN_TERMINFO)) {
+ /*
+ * Newlines embedded in a terminfo string are ignored, provided
+ * that the next line begins with whitespace.
+ */
+ ignored = TRUE;
+ } else {
+ *(ptr++) = (char) ch;
+ }
+
+ if (!ignored) {
+ if (_nc_curr_col <= 1) {
+ push_back(ch);
+ ch = '\n';
+ break;
+ }
+ last_ch = ch;
+ count++;
+ }
+ ignored = FALSE;
+
+ if (count > MAXCAPLEN && !long_warning) {
+ _nc_warning("Very long string found. Missing separator?");
+ long_warning = TRUE;
+ }
+ } /* end while */
+
+ *ptr = '\0';
+
+ return (ch);
+}
+
+/*
+ * _nc_push_token()
+ *
+ * Push a token of given type so that it will be reread by the next
+ * get_token() call.
+ */
+
+NCURSES_EXPORT(void)
+_nc_push_token(int tokclass)
+{
+ /*
+ * This implementation is kind of bogus, it will fail if we ever do more
+ * than one pushback at a time between get_token() calls. It relies on the
+ * fact that _nc_curr_token is static storage that nothing but
+ * _nc_get_token() touches.
+ */
+ pushtype = tokclass;
+ if (pushname == 0)
+ pushname = typeMalloc(char, MAX_NAME_SIZE + 1);
+ _nc_get_type(pushname);
+
+ DEBUG(3, ("pushing token: `%s', class %d",
+ ((_nc_curr_token.tk_name != 0)
+ ? _nc_curr_token.tk_name
+ : "<null>"),
+ pushtype));
+}
+
+/*
+ * Panic mode error recovery - skip everything until a "ch" is found.
+ */
+NCURSES_EXPORT(void)
+_nc_panic_mode(char ch)
+{
+ int c;
+
+ for (;;) {
+ c = next_char();
+ if (c == ch)
+ return;
+ if (c == EOF)
+ return;
+ }
+}
+
+#if NO_LEAKS
+NCURSES_EXPORT(void)
+_nc_comp_scan_leaks(void)
+{
+ if (pushname != 0) {
+ FreeAndNull(pushname);
+ }
+}
+#endif
diff --git a/ncurses/tinfo/db_iterator.c b/ncurses/tinfo/db_iterator.c
new file mode 100644
index 000000000000..fdc2bb09eadc
--- /dev/null
+++ b/ncurses/tinfo/db_iterator.c
@@ -0,0 +1,225 @@
+/****************************************************************************
+ * Copyright (c) 2006,2007 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 *
+ ****************************************************************************/
+
+/*
+ * Iterators for terminal databases.
+ */
+
+#include <curses.priv.h>
+
+#include <tic.h>
+
+MODULE_ID("$Id: db_iterator.c,v 1.6 2007/04/22 00:00:26 tom Exp $")
+
+#define HaveTicDirectory _nc_globals.have_tic_directory
+#define KeepTicDirectory _nc_globals.keep_tic_directory
+#define TicDirectory _nc_globals.tic_directory
+
+/*
+ * Record the "official" location of the terminfo directory, according to
+ * the place where we're writing to, or the normal default, if not.
+ */
+NCURSES_EXPORT(const char *)
+_nc_tic_dir(const char *path)
+{
+ if (!KeepTicDirectory) {
+ if (path != 0) {
+ TicDirectory = path;
+ HaveTicDirectory = TRUE;
+ } else if (!HaveTicDirectory && use_terminfo_vars()) {
+ char *envp;
+ if ((envp = getenv("TERMINFO")) != 0)
+ return _nc_tic_dir(envp);
+ }
+ }
+ return TicDirectory;
+}
+
+/*
+ * Special fix to prevent the terminfo directory from being moved after tic
+ * has chdir'd to it. If we let it be changed, then if $TERMINFO has a
+ * relative path, we'll lose track of the actual directory.
+ */
+NCURSES_EXPORT(void)
+_nc_keep_tic_dir(const char *path)
+{
+ _nc_tic_dir(path);
+ KeepTicDirectory = TRUE;
+}
+
+/*
+ * Process the list of :-separated directories, looking for the terminal type.
+ * We don't use strtok because it does not show us empty tokens.
+ */
+#define ThisDbList _nc_globals.dbi_list
+#define ThisDbSize _nc_globals.dbi_size
+
+/*
+ * Cleanup.
+ */
+NCURSES_EXPORT(void)
+_nc_last_db(void)
+{
+ if (ThisDbList != 0) {
+ FreeAndNull(ThisDbList);
+ }
+ ThisDbSize = 0;
+}
+
+/* The TERMINFO_DIRS value, if defined by the configure script, begins with a
+ * ":", which will be interpreted as TERMINFO.
+ */
+static const char *
+next_list_item(const char *source, int *offset)
+{
+ if (source != 0) {
+ FreeIfNeeded(ThisDbList);
+ ThisDbList = strdup(source);
+ ThisDbSize = strlen(source);
+ }
+
+ if (ThisDbList != 0 && ThisDbSize && *offset < ThisDbSize) {
+ static char system_db[] = TERMINFO;
+ char *result = ThisDbList + *offset;
+ char *marker = strchr(result, NCURSES_PATHSEP);
+
+ /*
+ * Put a null on the marker if a separator was found. Set the offset
+ * to the next position after the marker so we can call this function
+ * again, using the data at the offset.
+ */
+ if (marker == 0) {
+ *offset += strlen(result) + 1;
+ marker = result + *offset;
+ } else {
+ *marker++ = 0;
+ *offset = marker - ThisDbList;
+ }
+ if (*result == 0 && result != (ThisDbList + ThisDbSize))
+ result = system_db;
+ return result;
+ }
+ return 0;
+}
+
+#define NEXT_DBD(var, offset) next_list_item((*offset == 0) ? var : 0, offset)
+
+/*
+ * This is a simple iterator which allows the caller to step through the
+ * possible locations for a terminfo directory. ncurses uses this to find
+ * terminfo files to read.
+ */
+NCURSES_EXPORT(const char *)
+_nc_next_db(DBDIRS * state, int *offset)
+{
+ const char *result;
+ char *envp;
+
+ while (*state < dbdLAST) {
+ DBDIRS next = (DBDIRS) ((int) (*state) + 1);
+
+ result = 0;
+
+ switch (*state) {
+ case dbdTIC:
+ if (HaveTicDirectory)
+ result = _nc_tic_dir(0);
+ break;
+#if USE_DATABASE
+ case dbdEnvOnce:
+ if (use_terminfo_vars()) {
+ if ((envp = getenv("TERMINFO")) != 0)
+ result = _nc_tic_dir(envp);
+ }
+ break;
+ case dbdHome:
+ if (use_terminfo_vars()) {
+ result = _nc_home_terminfo();
+ }
+ break;
+ case dbdEnvList:
+ if (use_terminfo_vars()) {
+ if ((result = NEXT_DBD(getenv("TERMINFO_DIRS"), offset)) != 0)
+ next = *state;
+ }
+ break;
+ case dbdCfgList:
+#ifdef TERMINFO_DIRS
+ if ((result = NEXT_DBD(TERMINFO_DIRS, offset)) != 0)
+ next = *state;
+#endif
+ break;
+ case dbdCfgOnce:
+#ifndef TERMINFO_DIRS
+ result = TERMINFO;
+#endif
+ break;
+#endif /* USE_DATABASE */
+#if USE_TERMCAP
+ case dbdEnvOnce2:
+ if (use_terminfo_vars()) {
+ if ((envp = getenv("TERMCAP")) != 0)
+ result = _nc_tic_dir(envp);
+ }
+ break;
+ case dbdEnvList2:
+ if (use_terminfo_vars()) {
+ if ((result = NEXT_DBD(getenv("TERMPATH"), offset)) != 0)
+ next = *state;
+ }
+ break;
+ case dbdCfgList2:
+ if ((result = NEXT_DBD(TERMPATH, offset)) != 0)
+ next = *state;
+ break;
+#endif /* USE_TERMCAP */
+ case dbdLAST:
+ break;
+ }
+ if (*state != next) {
+ *state = next;
+ *offset = 0;
+ _nc_last_db();
+ }
+ if (result != 0) {
+ return result;
+ }
+ }
+ return 0;
+}
+
+NCURSES_EXPORT(void)
+_nc_first_db(DBDIRS * state, int *offset)
+{
+ *state = dbdTIC;
+ *offset = 0;
+}
diff --git a/ncurses/tinfo/doalloc.c b/ncurses/tinfo/doalloc.c
new file mode 100644
index 000000000000..fe2a009d19b4
--- /dev/null
+++ b/ncurses/tinfo/doalloc.c
@@ -0,0 +1,75 @@
+/****************************************************************************
+ * Copyright (c) 1998,2000 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 <dickey@clark.net> 1998 *
+ ****************************************************************************/
+
+/*
+ * Wrapper for malloc/realloc. Standard implementations allow realloc with
+ * a null pointer, but older libraries may not (e.g., SunOS).
+ *
+ * Also if realloc fails, we discard the old memory to avoid leaks.
+ */
+
+#include <curses.priv.h>
+
+MODULE_ID("$Id: doalloc.c,v 1.8 2002/08/31 21:48:11 Philippe.Blain Exp $")
+
+NCURSES_EXPORT(void *)
+_nc_doalloc(void *oldp, size_t amount)
+{
+ void *newp;
+
+ if (oldp != 0) {
+ if ((newp = realloc(oldp, amount)) == 0) {
+ free(oldp);
+ errno = ENOMEM; /* just in case 'free' reset */
+ }
+ } else {
+ newp = malloc(amount);
+ }
+ return newp;
+}
+
+#if !HAVE_STRDUP
+NCURSES_EXPORT(char *)
+_nc_strdup(const char *src)
+{
+ char *dst;
+ if (src != 0) {
+ dst = typeMalloc(char, strlen(src) + 1);
+ if (dst != 0) {
+ (void) strcpy(dst, src);
+ }
+ } else {
+ dst = 0;
+ }
+ return dst;
+}
+#endif
diff --git a/ncurses/tinfo/entries.c b/ncurses/tinfo/entries.c
new file mode 100644
index 000000000000..8b63f0d8965c
--- /dev/null
+++ b/ncurses/tinfo/entries.c
@@ -0,0 +1,144 @@
+/****************************************************************************
+ * Copyright (c) 2006,2007 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 <curses.priv.h>
+
+#include <ctype.h>
+
+#include <tic.h>
+#include <term_entry.h>
+
+MODULE_ID("$Id: entries.c,v 1.4 2007/11/03 21:00:27 tom Exp $")
+
+/****************************************************************************
+ *
+ * Entry queue handling
+ *
+ ****************************************************************************/
+/*
+ * The entry list is a doubly linked list with NULLs terminating the lists:
+ *
+ * --------- --------- ---------
+ * | | | | | | offset
+ * |-------| |-------| |-------|
+ * | ----+-->| ----+-->| NULL | next
+ * |-------| |-------| |-------|
+ * | NULL |<--+---- |<--+---- | last
+ * --------- --------- ---------
+ * ^ ^
+ * | |
+ * | |
+ * _nc_head _nc_tail
+ */
+
+NCURSES_EXPORT_VAR(ENTRY *) _nc_head = 0;
+NCURSES_EXPORT_VAR(ENTRY *) _nc_tail = 0;
+
+NCURSES_EXPORT(void)
+_nc_free_entry(ENTRY * headp, TERMTYPE *tterm)
+/* free the allocated storage consumed by the given list entry */
+{
+ ENTRY *ep;
+
+ if ((ep = _nc_delink_entry(headp, tterm)) != 0) {
+ free(ep);
+ }
+}
+
+NCURSES_EXPORT(void)
+_nc_free_entries(ENTRY * headp)
+/* free the allocated storage consumed by list entries */
+{
+ (void) headp; /* unused - _nc_head is altered here! */
+
+ while (_nc_head != 0) {
+ _nc_free_termtype(&(_nc_head->tterm));
+ }
+}
+
+NCURSES_EXPORT(ENTRY *)
+_nc_delink_entry(ENTRY * headp, TERMTYPE *tterm)
+/* delink the allocated storage for the given list entry */
+{
+ ENTRY *ep, *last;
+
+ for (last = 0, ep = headp; ep != 0; last = ep, ep = ep->next) {
+ if (&(ep->tterm) == tterm) {
+ if (last != 0) {
+ last->next = ep->next;
+ }
+ if (ep == _nc_head) {
+ _nc_head = ep->next;
+ }
+ if (ep == _nc_tail) {
+ _nc_tail = last;
+ }
+ break;
+ }
+ }
+ return ep;
+}
+
+NCURSES_EXPORT(void)
+_nc_leaks_tinfo(void)
+{
+ char *s;
+
+ T((T_CALLED("_nc_free_tinfo()")));
+#if NO_LEAKS
+ _nc_free_tparm();
+ _nc_tgetent_leaks();
+#endif
+ _nc_free_entries(_nc_head);
+ _nc_get_type(0);
+ _nc_first_name(0);
+#if NO_LEAKS
+ _nc_keyname_leaks();
+#endif
+#if BROKEN_LINKER || USE_REENTRANT
+ _nc_names_leaks();
+ _nc_codes_leaks();
+#endif
+
+ if ((s = _nc_home_terminfo()) != 0)
+ free(s);
+ returnVoid;
+}
+
+#if NO_LEAKS
+NCURSES_EXPORT(void)
+_nc_free_tinfo(int code)
+{
+ _nc_leaks_tinfo();
+ exit(code);
+}
+#endif
diff --git a/ncurses/tinfo/free_ttype.c b/ncurses/tinfo/free_ttype.c
new file mode 100644
index 000000000000..fa0fff1b83fb
--- /dev/null
+++ b/ncurses/tinfo/free_ttype.c
@@ -0,0 +1,77 @@
+/****************************************************************************
+ * Copyright (c) 1999-2005,2006 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), 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 1999-on *
+ ****************************************************************************/
+
+/*
+ * free_ttype.c -- allocation functions for TERMTYPE
+ *
+ * _nc_free_termtype()
+ * use_extended_names()
+ *
+ */
+
+#include <curses.priv.h>
+
+#include <tic.h>
+#include <term_entry.h>
+
+MODULE_ID("$Id: free_ttype.c,v 1.13 2006/06/25 10:46:02 tom Exp $")
+
+NCURSES_EXPORT(void)
+_nc_free_termtype(TERMTYPE *ptr)
+{
+ T(("_nc_free_termtype(%s)", ptr->term_names));
+
+ FreeIfNeeded(ptr->str_table);
+ FreeIfNeeded(ptr->Booleans);
+ FreeIfNeeded(ptr->Numbers);
+ FreeIfNeeded(ptr->Strings);
+#if NCURSES_XNAMES
+ FreeIfNeeded(ptr->ext_str_table);
+ FreeIfNeeded(ptr->ext_Names);
+#endif
+ memset(ptr, 0, sizeof(TERMTYPE));
+ _nc_free_entry(_nc_head, ptr);
+}
+
+#if NCURSES_XNAMES
+NCURSES_EXPORT_VAR(bool) _nc_user_definable = TRUE;
+
+NCURSES_EXPORT(int)
+use_extended_names(bool flag)
+{
+ int oldflag = _nc_user_definable;
+
+ T((T_CALLED("use_extended_names(%d)"), flag));
+ _nc_user_definable = flag;
+ returnBool(oldflag);
+}
+#endif
diff --git a/ncurses/tinfo/getenv_num.c b/ncurses/tinfo/getenv_num.c
new file mode 100644
index 000000000000..a90cc08d297c
--- /dev/null
+++ b/ncurses/tinfo/getenv_num.c
@@ -0,0 +1,56 @@
+/****************************************************************************
+ * Copyright (c) 1998,2000 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 <dickey@clark.net> 1998 *
+ ****************************************************************************/
+
+/*
+ * getenv_num.c -- obtain a number from the environment
+ */
+
+#include <curses.priv.h>
+
+MODULE_ID("$Id: getenv_num.c,v 1.3 2000/12/10 02:55:07 tom Exp $")
+
+NCURSES_EXPORT(int)
+_nc_getenv_num(const char *name)
+{
+ char *dst = 0;
+ char *src = getenv(name);
+ long value;
+
+ if ((src == 0)
+ || (value = strtol(src, &dst, 0)) < 0
+ || (dst == src)
+ || (*dst != '\0')
+ || (int) value < value)
+ value = -1;
+
+ return (int) value;
+}
diff --git a/ncurses/tinfo/hashed_db.c b/ncurses/tinfo/hashed_db.c
new file mode 100644
index 000000000000..3fc04eae3cca
--- /dev/null
+++ b/ncurses/tinfo/hashed_db.c
@@ -0,0 +1,260 @@
+/****************************************************************************
+ * Copyright (c) 2006 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), 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 2006 *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+#include <tic.h>
+#include <hashed_db.h>
+
+#if USE_HASHED_DB
+
+MODULE_ID("$Id: hashed_db.c,v 1.13 2006/08/19 19:48:38 tom Exp $")
+
+#if HASHED_DB_API >= 2
+static DBC *cursor;
+#endif
+
+/*
+ * Open the database.
+ */
+NCURSES_EXPORT(DB *)
+_nc_db_open(const char *path, bool modify)
+{
+ DB *result = 0;
+
+#if HASHED_DB_API >= 4
+ db_create(&result, NULL, 0);
+ result->open(result,
+ NULL,
+ path,
+ NULL,
+ DB_HASH,
+ modify ? DB_CREATE : DB_RDONLY,
+ 0644);
+#elif HASHED_DB_API >= 3
+ db_create(&result, NULL, 0);
+ result->open(result,
+ path,
+ NULL,
+ DB_HASH,
+ modify ? DB_CREATE : DB_RDONLY,
+ 0644);
+#elif HASHED_DB_API >= 2
+ int code;
+
+ if ((code = db_open(path,
+ DB_HASH,
+ modify ? DB_CREATE : DB_RDONLY,
+ 0644,
+ (DB_ENV *) 0,
+ (DB_INFO *) 0,
+ &result)) != 0) {
+ T(("cannot open %s: %s", path, strerror(code)));
+ result = 0;
+ } else {
+ T(("opened %s", path));
+ }
+#else
+ result = dbopen(path,
+ modify ? (O_CREAT | O_RDWR) : O_RDONLY,
+ 0644,
+ DB_HASH,
+ NULL);
+ if (result != 0) {
+ T(("opened %s", path));
+ }
+#endif
+ return result;
+}
+
+/*
+ * Close the database. Do not attempt to use the 'db' handle after this call.
+ */
+NCURSES_EXPORT(int)
+_nc_db_close(DB * db)
+{
+ int result;
+
+#if HASHED_DB_API >= 2
+ result = db->close(db, 0);
+#else
+ result = db->close(db);
+#endif
+ return result;
+}
+
+/*
+ * Write a record to the database.
+ *
+ * Returns 0 on success.
+ *
+ * FIXME: the FreeBSD cap_mkdb program assumes the database could have
+ * duplicates. There appears to be no good reason for that (review/fix).
+ */
+NCURSES_EXPORT(int)
+_nc_db_put(DB * db, DBT * key, DBT * data)
+{
+ int result;
+#if HASHED_DB_API >= 2
+ /* remove any pre-existing value, since we do not want duplicates */
+ (void) db->del(db, NULL, key, 0);
+ result = db->put(db, NULL, key, data, DB_NOOVERWRITE);
+#else
+ result = db->put(db, key, data, R_NOOVERWRITE);
+#endif
+ return result;
+}
+
+/*
+ * Read a record from the database.
+ *
+ * Returns 0 on success.
+ */
+NCURSES_EXPORT(int)
+_nc_db_get(DB * db, DBT * key, DBT * data)
+{
+ int result;
+
+ memset(data, 0, sizeof(*data));
+#if HASHED_DB_API >= 2
+ result = db->get(db, NULL, key, data, 0);
+#else
+ result = db->get(db, key, data, 0);
+#endif
+ return result;
+}
+
+/*
+ * Read the first record from the database, ignoring order.
+ *
+ * Returns 0 on success.
+ */
+NCURSES_EXPORT(int)
+_nc_db_first(DB * db, DBT * key, DBT * data)
+{
+ int result;
+
+ memset(key, 0, sizeof(*key));
+ memset(data, 0, sizeof(*data));
+#if HASHED_DB_API >= 2
+ if ((result = db->cursor(db, NULL, &cursor, 0)) == 0) {
+ result = cursor->c_get(cursor, key, data, DB_FIRST);
+ }
+#else
+ result = db->seq(db, key, data, 0);
+#endif
+ return result;
+}
+
+/*
+ * Read the next record from the database, ignoring order.
+ *
+ * Returns 0 on success.
+ */
+NCURSES_EXPORT(int)
+_nc_db_next(DB * db, DBT * key, DBT * data)
+{
+ int result;
+
+#if HASHED_DB_API >= 2
+ (void) db;
+ if (cursor != 0) {
+ result = cursor->c_get(cursor, key, data, DB_NEXT);
+ } else {
+ result = -1;
+ }
+#else
+ result = db->seq(db, key, data, 0);
+#endif
+ return result;
+}
+
+/*
+ * Check if a record is a terminfo index record. Index records are those that
+ * contain only an alias pointing to a list of aliases.
+ */
+NCURSES_EXPORT(bool)
+_nc_db_have_index(DBT * key, DBT * data, char **buffer, int *size)
+{
+ bool result = FALSE;
+ int used = data->size - 1;
+ char *have = (char *) data->data;
+
+ (void) key;
+ if (*have++ == 2) {
+ result = TRUE;
+ }
+ /*
+ * Update params in any case for consistency with _nc_db_have_data().
+ */
+ *buffer = have;
+ *size = used;
+ return result;
+}
+
+/*
+ * Check if a record is the terminfo data record. Ignore index records, e.g.,
+ * those that contain only an alias pointing to a list of aliases.
+ */
+NCURSES_EXPORT(bool)
+_nc_db_have_data(DBT * key, DBT * data, char **buffer, int *size)
+{
+ bool result = FALSE;
+ int used = data->size - 1;
+ char *have = (char *) data->data;
+
+ if (*have++ == 0) {
+ if (data->size > key->size
+ && IS_TIC_MAGIC(have)) {
+ result = TRUE;
+ }
+ }
+ /*
+ * Update params in any case to make it simple to follow a index record
+ * to the data record.
+ */
+ *buffer = have;
+ *size = used;
+ return result;
+}
+
+#else
+
+extern
+NCURSES_EXPORT(void)
+_nc_hashed_db(void);
+
+NCURSES_EXPORT(void)
+_nc_hashed_db(void)
+{
+}
+
+#endif /* USE_HASHED_DB */
diff --git a/ncurses/tinfo/home_terminfo.c b/ncurses/tinfo/home_terminfo.c
new file mode 100644
index 000000000000..92c26705a016
--- /dev/null
+++ b/ncurses/tinfo/home_terminfo.c
@@ -0,0 +1,69 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2007 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 *
+ ****************************************************************************/
+
+/*
+ * home_terminfo.c -- return the $HOME/.terminfo string, expanded
+ */
+
+#include <curses.priv.h>
+#include <tic.h>
+
+MODULE_ID("$Id: home_terminfo.c,v 1.10 2007/04/21 23:11:53 tom Exp $")
+
+#define my_length (strlen(home) + sizeof(PRIVATE_INFO))
+
+/* ncurses extension...fall back on user's private directory */
+
+#define MyBuffer _nc_globals.home_terminfo
+
+NCURSES_EXPORT(char *)
+_nc_home_terminfo(void)
+{
+ char *result = 0;
+#if USE_HOME_TERMINFO
+ char *home;
+
+ if (use_terminfo_vars()) {
+ if (MyBuffer == 0) {
+ if ((home = getenv("HOME")) != 0
+ && my_length <= PATH_MAX) {
+ MyBuffer = typeMalloc(char, my_length);
+ if (MyBuffer == 0)
+ _nc_err_abort(MSG_NO_MEMORY);
+ (void) sprintf(MyBuffer, PRIVATE_INFO, home);
+ }
+ }
+ result = MyBuffer;
+ }
+#endif
+ return result;
+}
diff --git a/ncurses/tinfo/init_keytry.c b/ncurses/tinfo/init_keytry.c
new file mode 100644
index 000000000000..d30d3ed16a87
--- /dev/null
+++ b/ncurses/tinfo/init_keytry.c
@@ -0,0 +1,110 @@
+/****************************************************************************
+ * Copyright (c) 1999-2006,2008 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. *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+
+#include <term.h>
+/* keypad_xmit, keypad_local, meta_on, meta_off */
+/* cursor_visible,cursor_normal,cursor_invisible */
+
+#include <tic.h> /* struct tinfo_fkeys */
+
+#include <term_entry.h>
+
+MODULE_ID("$Id: init_keytry.c,v 1.11 2008/05/03 23:09:15 tom Exp $")
+
+/*
+** _nc_init_keytry()
+**
+** Construct the try for the current terminal's keypad keys.
+**
+*/
+
+#if BROKEN_LINKER
+#undef _nc_tinfo_fkeys
+#endif
+
+/* LINT_PREPRO
+#if 0*/
+#include <init_keytry.h>
+/* LINT_PREPRO
+#endif*/
+
+#if BROKEN_LINKER
+const struct tinfo_fkeys *
+_nc_tinfo_fkeysf(void)
+{
+ return _nc_tinfo_fkeys;
+}
+#endif
+
+NCURSES_EXPORT(void)
+_nc_init_keytry(SCREEN *sp)
+{
+ size_t n;
+
+ /* The sp->_keytry value is initialized in newterm(), where the sp
+ * structure is created, because we can not tell where keypad() or
+ * mouse_activate() (which will call keyok()) are first called.
+ */
+
+ if (sp != 0) {
+ for (n = 0; _nc_tinfo_fkeys[n].code; n++) {
+ if (_nc_tinfo_fkeys[n].offset < STRCOUNT) {
+ (void) _nc_add_to_try(&(sp->_keytry),
+ CUR Strings[_nc_tinfo_fkeys[n].offset],
+ _nc_tinfo_fkeys[n].code);
+ }
+ }
+#if NCURSES_XNAMES
+ /*
+ * Add any of the extended strings to the tries if their name begins
+ * with 'k', i.e., they follow the convention of other terminfo key
+ * names.
+ */
+ {
+ TERMTYPE *tp = &(sp->_term->type);
+ for (n = STRCOUNT; n < NUM_STRINGS(tp); ++n) {
+ const char *name = ExtStrname(tp, n, strnames);
+ char *value = tp->Strings[n];
+ if (name != 0
+ && *name == 'k'
+ && value != 0
+ && key_defined(value) == 0) {
+ (void) _nc_add_to_try(&(sp->_keytry),
+ value,
+ n - STRCOUNT + KEY_MAX);
+ }
+ }
+ }
+#endif
+#ifdef TRACE
+ _nc_trace_tries(sp->_keytry);
+#endif
+ }
+}
diff --git a/ncurses/tinfo/lib_acs.c b/ncurses/tinfo/lib_acs.c
new file mode 100644
index 000000000000..6a24285460b3
--- /dev/null
+++ b/ncurses/tinfo/lib_acs.c
@@ -0,0 +1,193 @@
+/****************************************************************************
+ * Copyright (c) 1998-2006,2007 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+#include <term.h> /* ena_acs, acs_chars */
+
+MODULE_ID("$Id: lib_acs.c,v 1.34 2007/09/29 20:37:13 tom Exp $")
+
+#if BROKEN_LINKER || USE_REENTRANT
+#define MyBuffer _nc_prescreen.real_acs_map
+NCURSES_EXPORT_VAR(chtype *)
+_nc_acs_map(void)
+{
+ if (MyBuffer == 0)
+ MyBuffer = typeCalloc(chtype, ACS_LEN);
+ return MyBuffer;
+}
+#undef MyBuffer
+#else
+NCURSES_EXPORT_VAR(chtype) acs_map[ACS_LEN] =
+{
+ 0
+};
+#endif
+
+NCURSES_EXPORT(void)
+_nc_init_acs(void)
+{
+ chtype *fake_map = acs_map;
+ chtype *real_map = SP != 0 ? SP->_acs_map : fake_map;
+ int j;
+
+ T(("initializing ACS map"));
+
+ /*
+ * If we're using this from curses (rather than terminfo), we are storing
+ * the mapping information in the SCREEN struct so we can decide how to
+ * render it.
+ */
+ if (real_map != fake_map) {
+ for (j = 1; j < ACS_LEN; ++j) {
+ real_map[j] = 0;
+ fake_map[j] = A_ALTCHARSET | j;
+ SP->_screen_acs_map[j] = FALSE;
+ }
+ } else {
+ for (j = 1; j < ACS_LEN; ++j) {
+ real_map[j] = 0;
+ }
+ }
+
+ /*
+ * Initializations for a UNIX-like multi-terminal environment. Use
+ * ASCII chars and count on the terminfo description to do better.
+ */
+ real_map['l'] = '+'; /* should be upper left corner */
+ real_map['m'] = '+'; /* should be lower left corner */
+ real_map['k'] = '+'; /* should be upper right corner */
+ real_map['j'] = '+'; /* should be lower right corner */
+ real_map['u'] = '+'; /* should be tee pointing left */
+ real_map['t'] = '+'; /* should be tee pointing right */
+ real_map['v'] = '+'; /* should be tee pointing up */
+ real_map['w'] = '+'; /* should be tee pointing down */
+ real_map['q'] = '-'; /* should be horizontal line */
+ real_map['x'] = '|'; /* should be vertical line */
+ real_map['n'] = '+'; /* should be large plus or crossover */
+ real_map['o'] = '~'; /* should be scan line 1 */
+ real_map['s'] = '_'; /* should be scan line 9 */
+ real_map['`'] = '+'; /* should be diamond */
+ real_map['a'] = ':'; /* should be checker board (stipple) */
+ real_map['f'] = '\''; /* should be degree symbol */
+ real_map['g'] = '#'; /* should be plus/minus */
+ real_map['~'] = 'o'; /* should be bullet */
+ real_map[','] = '<'; /* should be arrow pointing left */
+ real_map['+'] = '>'; /* should be arrow pointing right */
+ real_map['.'] = 'v'; /* should be arrow pointing down */
+ real_map['-'] = '^'; /* should be arrow pointing up */
+ real_map['h'] = '#'; /* should be board of squares */
+ real_map['i'] = '#'; /* should be lantern symbol */
+ real_map['0'] = '#'; /* should be solid square block */
+ /* these defaults were invented for ncurses */
+ real_map['p'] = '-'; /* should be scan line 3 */
+ real_map['r'] = '-'; /* should be scan line 7 */
+ real_map['y'] = '<'; /* should be less-than-or-equal-to */
+ real_map['z'] = '>'; /* should be greater-than-or-equal-to */
+ real_map['{'] = '*'; /* should be greek pi */
+ real_map['|'] = '!'; /* should be not-equal */
+ real_map['}'] = 'f'; /* should be pound-sterling symbol */
+
+ if (ena_acs != NULL) {
+ TPUTS_TRACE("ena_acs");
+ putp(ena_acs);
+ }
+#if NCURSES_EXT_FUNCS
+ /*
+ * Linux console "supports" the "PC ROM" character set by the coincidence
+ * that smpch/rmpch and smacs/rmacs have the same values. ncurses has
+ * no codepage support (see SCO Merge for an example). Outside of the
+ * values defined in acsc, there are no definitions for the "PC ROM"
+ * character set (assumed by some applications to be codepage 437), but we
+ * allow those applications to use those codepoints.
+ *
+ * test/blue.c uses this feature.
+ */
+#define PCH_KLUDGE(a,b) (a != 0 && b != 0 && !strcmp(a,b))
+ if (PCH_KLUDGE(enter_pc_charset_mode, enter_alt_charset_mode) &&
+ PCH_KLUDGE(exit_pc_charset_mode, exit_alt_charset_mode)) {
+ size_t i;
+ for (i = 1; i < ACS_LEN; ++i) {
+ if (real_map[i] == 0) {
+ real_map[i] = i;
+ if (real_map != fake_map) {
+ if (SP != 0)
+ SP->_screen_acs_map[i] = TRUE;
+ }
+ }
+ }
+ }
+#endif
+
+ if (acs_chars != NULL) {
+ size_t i = 0;
+ size_t length = strlen(acs_chars);
+
+ while (i + 1 < length) {
+ if (acs_chars[i] != 0 && UChar(acs_chars[i]) < ACS_LEN) {
+ real_map[UChar(acs_chars[i])] = UChar(acs_chars[i + 1]) | A_ALTCHARSET;
+ if (SP != 0)
+ SP->_screen_acs_map[UChar(acs_chars[i])] = TRUE;
+ }
+ i += 2;
+ }
+ }
+#ifdef TRACE
+ /* Show the equivalent mapping, noting if it does not match the
+ * given attribute, whether by re-ordering or duplication.
+ */
+ if (USE_TRACEF(TRACE_CALLS)) {
+ size_t n, m;
+ char show[ACS_LEN * 2 + 1];
+ for (n = 1, m = 0; n < ACS_LEN; n++) {
+ if (real_map[n] != 0) {
+ show[m++] = (char) n;
+ show[m++] = ChCharOf(real_map[n]);
+ }
+ }
+ show[m] = 0;
+ if (acs_chars == NULL || strcmp(acs_chars, show))
+ _tracef("%s acs_chars %s",
+ (acs_chars == NULL) ? "NULL" : "READ",
+ _nc_visbuf(acs_chars));
+ _tracef("%s acs_chars %s",
+ (acs_chars == NULL)
+ ? "NULL"
+ : (strcmp(acs_chars, show)
+ ? "DIFF"
+ : "SAME"),
+ _nc_visbuf(show));
+ _nc_unlock_global(tracef);
+ }
+#endif /* TRACE */
+}
diff --git a/ncurses/tinfo/lib_baudrate.c b/ncurses/tinfo/lib_baudrate.c
new file mode 100644
index 000000000000..4070160da393
--- /dev/null
+++ b/ncurses/tinfo/lib_baudrate.c
@@ -0,0 +1,235 @@
+/****************************************************************************
+ * Copyright (c) 1998-2006,2007 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ ****************************************************************************/
+
+/*
+ * lib_baudrate.c
+ *
+ */
+
+#include <curses.priv.h>
+#include <term.h> /* cur_term, pad_char */
+#include <termcap.h> /* ospeed */
+#if defined(__FreeBSD__)
+#include <sys/param.h>
+#endif
+
+/*
+ * These systems use similar header files, which define B1200 as 1200, etc.,
+ * but can be overridden by defining USE_OLD_TTY so B1200 is 9, which makes all
+ * of the indices up to B115200 fit nicely in a 'short', allowing us to retain
+ * ospeed's type for compatibility.
+ */
+#if (defined(__FreeBSD__) && (__FreeBSD_version < 700000)) || defined(__NetBSD__) || defined(__OpenBSD__)
+#undef B0
+#undef B50
+#undef B75
+#undef B110
+#undef B134
+#undef B150
+#undef B200
+#undef B300
+#undef B600
+#undef B1200
+#undef B1800
+#undef B2400
+#undef B4800
+#undef B9600
+#undef B19200
+#undef EXTA
+#undef B38400
+#undef EXTB
+#undef B57600
+#undef B115200
+#undef B230400
+#undef B460800
+#undef B921600
+#define USE_OLD_TTY
+#include <sys/ttydev.h>
+#else
+#undef USE_OLD_TTY
+#endif /* USE_OLD_TTY */
+
+MODULE_ID("$Id: lib_baudrate.c,v 1.25 2007/10/20 15:00:41 Rong-En.Fan Exp $")
+
+/*
+ * int
+ * baudrate()
+ *
+ * Returns the current terminal's baud rate.
+ *
+ */
+
+struct speed {
+ int s; /* value for 'ospeed' is an index */
+ int sp; /* the actual speed */
+};
+
+static struct speed const speeds[] =
+{
+ {B0, 0},
+ {B50, 50},
+ {B75, 75},
+ {B110, 110},
+ {B134, 134},
+ {B150, 150},
+ {B200, 200},
+ {B300, 300},
+ {B600, 600},
+ {B1200, 1200},
+ {B1800, 1800},
+ {B2400, 2400},
+ {B4800, 4800},
+ {B9600, 9600},
+#ifdef B19200
+ {B19200, 19200},
+#else
+#ifdef EXTA
+ {EXTA, 19200},
+#endif
+#endif
+#ifdef B38400
+ {B38400, 38400},
+#else
+#ifdef EXTB
+ {EXTB, 38400},
+#endif
+#endif
+#ifdef B57600
+ {B57600, 57600},
+#endif
+#ifdef B115200
+ {B115200, 115200},
+#endif
+#ifdef B230400
+ {B230400, 230400},
+#endif
+#ifdef B460800
+ {B460800, 460800},
+#endif
+#ifdef B921600
+ {B921600, 921600},
+#endif
+};
+
+NCURSES_EXPORT(int)
+_nc_baudrate(int OSpeed)
+{
+#if !USE_REENTRANT
+ static int last_OSpeed;
+ static int last_baudrate;
+#endif
+
+ int result = ERR;
+ unsigned i;
+
+#if !USE_REENTRANT
+ if (OSpeed == last_OSpeed) {
+ result = last_baudrate;
+ }
+#endif
+ if (result == ERR) {
+ if (OSpeed >= 0) {
+ for (i = 0; i < SIZEOF(speeds); i++) {
+ if (speeds[i].s == OSpeed) {
+ result = speeds[i].sp;
+ break;
+ }
+ }
+ }
+#if !USE_REENTRANT
+ if (OSpeed == last_OSpeed) {
+ last_OSpeed = OSpeed;
+ last_baudrate = result;
+ }
+#endif
+ }
+ return (result);
+}
+
+NCURSES_EXPORT(int)
+_nc_ospeed(int BaudRate)
+{
+ int result = 1;
+ unsigned i;
+
+ if (BaudRate >= 0) {
+ for (i = 0; i < SIZEOF(speeds); i++) {
+ if (speeds[i].sp == BaudRate) {
+ result = speeds[i].s;
+ break;
+ }
+ }
+ }
+ return (result);
+}
+
+NCURSES_EXPORT(int)
+baudrate(void)
+{
+ int result;
+
+ T((T_CALLED("baudrate()")));
+
+ /*
+ * In debugging, allow the environment symbol to override when we're
+ * redirecting to a file, so we can construct repeatable test-cases
+ * that take into account costs that depend on baudrate.
+ */
+#ifdef TRACE
+ if (SP && !isatty(fileno(SP->_ofp))
+ && getenv("BAUDRATE") != 0) {
+ int ret;
+ if ((ret = _nc_getenv_num("BAUDRATE")) <= 0)
+ ret = 9600;
+ ospeed = _nc_ospeed(ret);
+ returnCode(ret);
+ }
+#endif
+
+#ifdef USE_OLD_TTY
+ result = cfgetospeed(&cur_term->Nttyb);
+ ospeed = _nc_ospeed(result);
+#else /* !USE_OLD_TTY */
+#ifdef TERMIOS
+ ospeed = cfgetospeed(&cur_term->Nttyb);
+#else
+ ospeed = cur_term->Nttyb.sg_ospeed;
+#endif
+ result = _nc_baudrate(ospeed);
+#endif
+ if (cur_term != 0)
+ cur_term->_baudrate = result;
+
+ returnCode(result);
+}
diff --git a/ncurses/tinfo/lib_cur_term.c b/ncurses/tinfo/lib_cur_term.c
new file mode 100644
index 000000000000..8fccc2f88d08
--- /dev/null
+++ b/ncurses/tinfo/lib_cur_term.c
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * Copyright (c) 1998-2000,2003 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "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 <dickey@clark.net> 1997 *
+ ****************************************************************************/
+/*
+ * Module that "owns" the 'cur_term' variable:
+ *
+ * TERMINAL *set_curterm(TERMINAL *)
+ * int del_curterm(TERMINAL *)
+ */
+
+#include <curses.priv.h>
+#include <term_entry.h> /* TTY, cur_term */
+#include <termcap.h> /* ospeed */
+
+MODULE_ID("$Id: lib_cur_term.c,v 1.13 2003/12/27 18:21:30 tom Exp $")
+
+NCURSES_EXPORT_VAR(TERMINAL *) cur_term = 0;
+
+NCURSES_EXPORT(TERMINAL *)
+set_curterm(TERMINAL * termp)
+{
+ TERMINAL *oldterm = cur_term;
+
+ T((T_CALLED("set_curterm(%p)"), termp));
+
+ if ((cur_term = termp) != 0) {
+ ospeed = _nc_ospeed(cur_term->_baudrate);
+ PC = (pad_char != NULL) ? pad_char[0] : 0;
+ }
+ T((T_RETURN("%p"), oldterm));
+ return (oldterm);
+}
+
+NCURSES_EXPORT(int)
+del_curterm(TERMINAL * termp)
+{
+ T((T_CALLED("del_curterm(%p)"), termp));
+
+ if (termp != 0) {
+ _nc_free_termtype(&(termp->type));
+ FreeIfNeeded(termp->_termname);
+ free(termp);
+ if (termp == cur_term)
+ cur_term = 0;
+ returnCode(OK);
+ }
+ returnCode(ERR);
+}
diff --git a/ncurses/tinfo/lib_data.c b/ncurses/tinfo/lib_data.c
new file mode 100644
index 000000000000..ba37e5dc8c49
--- /dev/null
+++ b/ncurses/tinfo/lib_data.c
@@ -0,0 +1,294 @@
+/****************************************************************************
+ * Copyright (c) 1998-2007,2008 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ ****************************************************************************/
+
+/*
+** lib_data.c
+**
+** Common data that may/may not be allocated, but is referenced globally
+**
+*/
+
+#include <curses.priv.h>
+
+MODULE_ID("$Id: lib_data.c,v 1.43 2008/03/29 21:16:49 tom Exp $")
+
+/*
+ * OS/2's native linker complains if we don't initialize public data when
+ * constructing a dll (reported by J.J.G.Ripoll).
+ */
+#if USE_REENTRANT
+NCURSES_EXPORT(WINDOW *)
+NCURSES_PUBLIC_VAR(stdscr) (void)
+{
+ return SP ? SP->_stdscr : 0;
+}
+NCURSES_EXPORT(WINDOW *)
+NCURSES_PUBLIC_VAR(curscr) (void)
+{
+ return SP ? SP->_curscr : 0;
+}
+NCURSES_EXPORT(WINDOW *)
+NCURSES_PUBLIC_VAR(newscr) (void)
+{
+ return SP ? SP->_newscr : 0;
+}
+#else
+NCURSES_EXPORT_VAR(WINDOW *) stdscr = 0;
+NCURSES_EXPORT_VAR(WINDOW *) curscr = 0;
+NCURSES_EXPORT_VAR(WINDOW *) newscr = 0;
+#endif
+
+NCURSES_EXPORT_VAR(SCREEN *) _nc_screen_chain = 0;
+
+/*
+ * The variable 'SP' will be defined as a function on systems that cannot link
+ * data-only modules, since it is used in a lot of places within ncurses and we
+ * cannot guarantee that any application will use any particular function. We
+ * put the WINDOW variables in this module, because it appears that any
+ * application that uses them will also use 'SP'.
+ *
+ * This module intentionally does not reference other ncurses modules, to avoid
+ * module coupling that increases the size of the executable.
+ */
+#if BROKEN_LINKER
+static SCREEN *my_screen;
+
+NCURSES_EXPORT(SCREEN *)
+_nc_screen(void)
+{
+ return my_screen;
+}
+
+NCURSES_EXPORT(int)
+_nc_alloc_screen(void)
+{
+ return ((my_screen = typeCalloc(SCREEN, 1)) != 0);
+}
+
+NCURSES_EXPORT(void)
+_nc_set_screen(SCREEN *sp)
+{
+ my_screen = sp;
+}
+
+#else
+NCURSES_EXPORT_VAR(SCREEN *) SP = NULL; /* Some linkers require initialized data... */
+#endif
+/* *INDENT-OFF* */
+#define CHARS_0s { '\0' }
+
+#define TGETENT_0 { 0L, FALSE, NULL, NULL, NULL }
+#define TGETENT_0s { TGETENT_0, TGETENT_0, TGETENT_0, TGETENT_0 }
+
+NCURSES_EXPORT_VAR(NCURSES_GLOBALS) _nc_globals = {
+ 0, /* have_sigwinch */
+ 0, /* cleanup_nested */
+
+ FALSE, /* init_signals */
+ FALSE, /* init_screen */
+
+ NULL, /* comp_sourcename */
+ NULL, /* comp_termtype */
+
+ FALSE, /* have_tic_directory */
+ FALSE, /* keep_tic_directory */
+ TERMINFO, /* tic_directory */
+
+ NULL, /* dbi_list */
+ 0, /* dbi_size */
+
+ NULL, /* first_name */
+ NULL, /* keyname_table */
+
+ 0, /* slk_format */
+
+ NULL, /* safeprint_buf */
+ 0, /* safeprint_used */
+
+ TGETENT_0s, /* tgetent_cache */
+ 0, /* tgetent_index */
+ 0, /* tgetent_sequence */
+
+ 0, /* _nc_windowlist */
+
+#if USE_HOME_TERMINFO
+ NULL, /* home_terminfo */
+#endif
+
+#if !USE_SAFE_SPRINTF
+ 0, /* safeprint_cols */
+ 0, /* safeprint_rows */
+#endif
+
+#ifdef TRACE
+ FALSE, /* init_trace */
+ CHARS_0s, /* trace_fname */
+ 0, /* trace_level */
+ NULL, /* trace_fp */
+
+ NULL, /* tracearg_buf */
+ 0, /* tracearg_used */
+
+ NULL, /* tracebuf_ptr */
+ 0, /* tracebuf_used */
+
+ CHARS_0s, /* tracechr_buf */
+
+ NULL, /* tracedmp_buf */
+ 0, /* tracedmp_used */
+
+ CHARS_0s, /* tracemse_buf */
+
+ NULL, /* tracetry_buf */
+ 0, /* tracetry_used */
+
+ { CHARS_0s, CHARS_0s }, /* traceatr_color_buf */
+ 0, /* traceatr_color_sel */
+ -1, /* traceatr_color_last */
+
+#endif /* TRACE */
+#ifdef USE_PTHREADS
+ PTHREAD_MUTEX_INITIALIZER, /* mutex_set_SP */
+ PTHREAD_MUTEX_INITIALIZER, /* mutex_use_screen */
+ PTHREAD_MUTEX_INITIALIZER, /* mutex_use_window */
+ PTHREAD_MUTEX_INITIALIZER, /* mutex_windowlist */
+ PTHREAD_MUTEX_INITIALIZER, /* mutex_tst_tracef */
+ PTHREAD_MUTEX_INITIALIZER, /* mutex_tracef */
+ 0, /* nested_tracef */
+#endif
+};
+
+#define STACK_FRAME_0 { { 0 }, 0 }
+#define STACK_FRAME_0s { STACK_FRAME_0 }
+#define NUM_VARS_0s { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+
+#define RIPOFF_0 { 0,0,0 }
+#define RIPOFF_0s { RIPOFF_0 }
+
+NCURSES_EXPORT_VAR(NCURSES_PRESCREEN) _nc_prescreen = {
+ TRUE, /* use_env */
+ FALSE, /* filter_mode */
+ A_NORMAL, /* previous_attr */
+ RIPOFF_0s, /* ripoff */
+ NULL, /* rsp */
+ { /* tparm_state */
+#ifdef TRACE
+ NULL, /* tname */
+#endif
+ NULL, /* tparam_base */
+
+ STACK_FRAME_0s, /* stack */
+ 0, /* stack_ptr */
+
+ NULL, /* out_buff */
+ 0, /* out_size */
+ 0, /* out_used */
+
+ NULL, /* fmt_buff */
+ 0, /* fmt_size */
+
+ NUM_VARS_0s, /* dynamic_var */
+ NUM_VARS_0s, /* static_vars */
+ },
+ NULL, /* saved_tty */
+#if BROKEN_LINKER || USE_REENTRANT
+ NULL, /* real_acs_map */
+ 0, /* LINES */
+ 0, /* COLS */
+#ifdef TRACE
+ 0L, /* _outchars */
+ NULL, /* _tputs_trace */
+#endif
+#endif
+};
+/* *INDENT-ON* */
+
+/******************************************************************************/
+#ifdef USE_PTHREADS
+static void
+init_global_mutexes(void)
+{
+ static bool initialized = FALSE;
+
+ if (!initialized) {
+ initialized = TRUE;
+ _nc_mutex_init(&_nc_globals.mutex_set_SP);
+ _nc_mutex_init(&_nc_globals.mutex_use_screen);
+ _nc_mutex_init(&_nc_globals.mutex_use_window);
+ _nc_mutex_init(&_nc_globals.mutex_windowlist);
+ _nc_mutex_init(&_nc_globals.mutex_tst_tracef);
+ _nc_mutex_init(&_nc_globals.mutex_tracef);
+ }
+}
+
+/*
+ * Use recursive mutexes if we have them - they're part of Unix98.
+ * For the cases where we do not, _nc_mutex_trylock() is used to avoid a
+ * deadlock, at the expense of memory leaks and unexpected failures that
+ * may not be handled by typical clients.
+ *
+ * FIXME - need configure check for PTHREAD_MUTEX_RECURSIVE, define it to
+ * PTHREAD_MUTEX_NORMAL if not supported.
+ */
+NCURSES_EXPORT(void)
+_nc_mutex_init(pthread_mutex_t * obj)
+{
+ pthread_mutexattr_t recattr;
+
+ memset(&recattr, 0, sizeof(recattr));
+ pthread_mutexattr_settype(&recattr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(obj, &recattr);
+}
+
+NCURSES_EXPORT(int)
+_nc_mutex_lock(pthread_mutex_t * obj)
+{
+ init_global_mutexes();
+ return pthread_mutex_lock(obj);
+}
+
+NCURSES_EXPORT(int)
+_nc_mutex_trylock(pthread_mutex_t * obj)
+{
+ init_global_mutexes();
+ return pthread_mutex_trylock(obj);
+}
+
+NCURSES_EXPORT(int)
+_nc_mutex_unlock(pthread_mutex_t * obj)
+{
+ init_global_mutexes();
+ return pthread_mutex_unlock(obj);
+}
+#endif /* USE_PTHREADS */
diff --git a/ncurses/tinfo/lib_has_cap.c b/ncurses/tinfo/lib_has_cap.c
new file mode 100644
index 000000000000..0dc66bd9b918
--- /dev/null
+++ b/ncurses/tinfo/lib_has_cap.c
@@ -0,0 +1,65 @@
+/****************************************************************************
+ * Copyright (c) 1998-2000,2003 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-2003 *
+ ****************************************************************************/
+
+/*
+** lib_has_cap.c
+**
+** The routines to query terminal capabilities
+**
+*/
+
+#include <curses.priv.h>
+
+#include <term.h>
+
+MODULE_ID("$Id: lib_has_cap.c,v 1.4 2003/10/25 19:43:55 tom Exp $")
+
+NCURSES_EXPORT(bool)
+has_ic(void)
+{
+ T((T_CALLED("has_ic()")));
+ returnCode(cur_term &&
+ (insert_character || parm_ich
+ || (enter_insert_mode && exit_insert_mode))
+ && (delete_character || parm_dch));
+}
+
+NCURSES_EXPORT(bool)
+has_il(void)
+{
+ T((T_CALLED("has_il()")));
+ returnCode(cur_term
+ && (insert_line || parm_insert_line)
+ && (delete_line || parm_delete_line));
+}
diff --git a/ncurses/tinfo/lib_kernel.c b/ncurses/tinfo/lib_kernel.c
new file mode 100644
index 000000000000..89dc1e80ea8e
--- /dev/null
+++ b/ncurses/tinfo/lib_kernel.c
@@ -0,0 +1,154 @@
+/****************************************************************************
+ * Copyright (c) 1998-2003,2004 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 2002 *
+ ****************************************************************************/
+
+/*
+ * lib_kernel.c
+ *
+ * Misc. low-level routines:
+ * erasechar()
+ * killchar()
+ * flushinp()
+ *
+ * The baudrate() and delay_output() functions could logically live here,
+ * but are in other modules to reduce the static-link size of programs
+ * that use only these facilities.
+ */
+
+#include <curses.priv.h>
+#include <term.h> /* cur_term */
+
+MODULE_ID("$Id: lib_kernel.c,v 1.24 2004/05/08 17:11:21 tom Exp $")
+
+static int
+_nc_vdisable(void)
+{
+ int value = -1;
+#if defined(_POSIX_VDISABLE) && HAVE_UNISTD_H
+ value = _POSIX_VDISABLE;
+#endif
+#if defined(_PC_VDISABLE)
+ if (value == -1) {
+ value = fpathconf(0, _PC_VDISABLE);
+ if (value == -1) {
+ value = 0377;
+ }
+ }
+#elif defined(VDISABLE)
+ if (value == -1)
+ value = VDISABLE;
+#endif
+ return value;
+}
+
+/*
+ * erasechar()
+ *
+ * Return erase character as given in cur_term->Ottyb.
+ *
+ */
+
+NCURSES_EXPORT(char)
+erasechar(void)
+{
+ int result = ERR;
+ T((T_CALLED("erasechar()")));
+
+ if (cur_term != 0) {
+#ifdef TERMIOS
+ result = cur_term->Ottyb.c_cc[VERASE];
+ if (result == _nc_vdisable())
+ result = ERR;
+#else
+ result = cur_term->Ottyb.sg_erase;
+#endif
+ }
+ returnCode(result);
+}
+
+/*
+ * killchar()
+ *
+ * Return kill character as given in cur_term->Ottyb.
+ *
+ */
+
+NCURSES_EXPORT(char)
+killchar(void)
+{
+ int result = ERR;
+ T((T_CALLED("killchar()")));
+
+ if (cur_term != 0) {
+#ifdef TERMIOS
+ result = cur_term->Ottyb.c_cc[VKILL];
+ if (result == _nc_vdisable())
+ result = ERR;
+#else
+ result = cur_term->Ottyb.sg_kill;
+#endif
+ }
+ returnCode(result);
+}
+
+/*
+ * flushinp()
+ *
+ * Flush any input on cur_term->Filedes
+ *
+ */
+
+NCURSES_EXPORT(int)
+flushinp(void)
+{
+ T((T_CALLED("flushinp()")));
+
+ if (cur_term != 0) {
+#ifdef TERMIOS
+ tcflush(cur_term->Filedes, TCIFLUSH);
+#else
+ errno = 0;
+ do {
+ ioctl(cur_term->Filedes, TIOCFLUSH, 0);
+ } while
+ (errno == EINTR);
+#endif
+ if (SP) {
+ SP->_fifohead = -1;
+ SP->_fifotail = 0;
+ SP->_fifopeek = 0;
+ }
+ returnCode(OK);
+ }
+ returnCode(ERR);
+}
diff --git a/ncurses/tinfo/lib_longname.c b/ncurses/tinfo/lib_longname.c
new file mode 100644
index 000000000000..1301ee516944
--- /dev/null
+++ b/ncurses/tinfo/lib_longname.c
@@ -0,0 +1,57 @@
+/****************************************************************************
+ * Copyright (c) 1998,2000 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ ****************************************************************************/
+
+/*
+** lib_longname.c
+**
+** The routine longname().
+**
+*/
+
+#include <curses.priv.h>
+
+MODULE_ID("$Id: lib_longname.c,v 1.9 2000/12/10 02:55:07 tom Exp $")
+
+NCURSES_EXPORT(char *)
+longname(void)
+{
+ char *ptr;
+
+ T((T_CALLED("longname()")));
+
+ for (ptr = ttytype + strlen(ttytype); ptr > ttytype; ptr--)
+ if (*ptr == '|')
+ returnPtr(ptr + 1);
+
+ returnPtr(ttytype);
+}
diff --git a/ncurses/tinfo/lib_napms.c b/ncurses/tinfo/lib_napms.c
new file mode 100644
index 000000000000..417b3b4b4dbc
--- /dev/null
+++ b/ncurses/tinfo/lib_napms.c
@@ -0,0 +1,74 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2008 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ ****************************************************************************/
+
+/*
+ * lib_napms.c
+ *
+ * The routine napms.
+ *
+ * (This file was originally written by Eric Raymond; however except for
+ * comments, none of the original code remains - T.Dickey).
+ */
+
+#include <curses.priv.h>
+
+#if HAVE_NANOSLEEP
+#include <time.h>
+#if HAVE_SYS_TIME_H
+#include <sys/time.h> /* needed for MacOS X DP3 */
+#endif
+#endif
+
+MODULE_ID("$Id: lib_napms.c,v 1.17 2008/05/03 21:34:13 tom Exp $")
+
+NCURSES_EXPORT(int)
+napms(int ms)
+{
+ T((T_CALLED("napms(%d)"), ms));
+
+#if HAVE_NANOSLEEP
+ {
+ struct timespec request, remaining;
+ request.tv_sec = ms / 1000;
+ request.tv_nsec = (ms % 1000) * 1000000;
+ while (nanosleep(&request, &remaining) == -1
+ && errno == EINTR) {
+ request = remaining;
+ }
+ }
+#else
+ _nc_timed_wait(0, 0, ms, (int *) 0 EVENTLIST_2nd(0));
+#endif
+
+ returnCode(OK);
+}
diff --git a/ncurses/tinfo/lib_options.c b/ncurses/tinfo/lib_options.c
new file mode 100644
index 000000000000..98aae24baacb
--- /dev/null
+++ b/ncurses/tinfo/lib_options.c
@@ -0,0 +1,270 @@
+/****************************************************************************
+ * Copyright (c) 1998-2006,2008 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ ****************************************************************************/
+
+/*
+** lib_options.c
+**
+** The routines to handle option setting.
+**
+*/
+
+#include <curses.priv.h>
+
+#include <term.h>
+
+MODULE_ID("$Id: lib_options.c,v 1.52 2008/05/03 23:09:20 tom Exp $")
+
+NCURSES_EXPORT(int)
+idlok(WINDOW *win, bool flag)
+{
+ T((T_CALLED("idlok(%p,%d)"), win, flag));
+
+ if (win) {
+ _nc_idlok = win->_idlok = (flag && (has_il() || change_scroll_region));
+ returnCode(OK);
+ } else
+ returnCode(ERR);
+}
+
+NCURSES_EXPORT(void)
+idcok(WINDOW *win, bool flag)
+{
+ T((T_CALLED("idcok(%p,%d)"), win, flag));
+
+ if (win)
+ _nc_idcok = win->_idcok = (flag && has_ic());
+
+ returnVoid;
+}
+
+NCURSES_EXPORT(int)
+halfdelay(int t)
+{
+ T((T_CALLED("halfdelay(%d)"), t));
+
+ if (t < 1 || t > 255 || SP == 0)
+ returnCode(ERR);
+
+ cbreak();
+ SP->_cbreak = t + 1;
+ returnCode(OK);
+}
+
+NCURSES_EXPORT(int)
+nodelay(WINDOW *win, bool flag)
+{
+ T((T_CALLED("nodelay(%p,%d)"), win, flag));
+
+ if (win) {
+ if (flag == TRUE)
+ win->_delay = 0;
+ else
+ win->_delay = -1;
+ returnCode(OK);
+ } else
+ returnCode(ERR);
+}
+
+NCURSES_EXPORT(int)
+notimeout(WINDOW *win, bool f)
+{
+ T((T_CALLED("notimeout(%p,%d)"), win, f));
+
+ if (win) {
+ win->_notimeout = f;
+ returnCode(OK);
+ } else
+ returnCode(ERR);
+}
+
+NCURSES_EXPORT(void)
+wtimeout(WINDOW *win, int delay)
+{
+ T((T_CALLED("wtimeout(%p,%d)"), win, delay));
+
+ if (win) {
+ win->_delay = delay;
+ }
+ returnVoid;
+}
+
+NCURSES_EXPORT(int)
+keypad(WINDOW *win, bool flag)
+{
+ T((T_CALLED("keypad(%p,%d)"), win, flag));
+
+ if (win) {
+ win->_use_keypad = flag;
+ returnCode(_nc_keypad(SP, flag));
+ } else
+ returnCode(ERR);
+}
+
+NCURSES_EXPORT(int)
+meta(WINDOW *win GCC_UNUSED, bool flag)
+{
+ int result = ERR;
+
+ /* Ok, we stay relaxed and don't signal an error if win is NULL */
+ T((T_CALLED("meta(%p,%d)"), win, flag));
+
+ if (SP != 0) {
+ SP->_use_meta = flag;
+
+ if (flag && meta_on) {
+ TPUTS_TRACE("meta_on");
+ putp(meta_on);
+ } else if (!flag && meta_off) {
+ TPUTS_TRACE("meta_off");
+ putp(meta_off);
+ }
+ result = OK;
+ }
+ returnCode(result);
+}
+
+/* curs_set() moved here to narrow the kernel interface */
+
+NCURSES_EXPORT(int)
+curs_set(int vis)
+{
+ int result = ERR;
+
+ T((T_CALLED("curs_set(%d)"), vis));
+ if (SP != 0 && vis >= 0 && vis <= 2) {
+ int cursor = SP->_cursor;
+
+ if (vis == cursor) {
+ result = cursor;
+ } else {
+ result = (cursor == -1 ? 1 : cursor);
+ switch (vis) {
+ case 2:
+ if (cursor_visible) {
+ TPUTS_TRACE("cursor_visible");
+ putp(cursor_visible);
+ } else
+ result = ERR;
+ break;
+ case 1:
+ if (cursor_normal) {
+ TPUTS_TRACE("cursor_normal");
+ putp(cursor_normal);
+ } else
+ result = ERR;
+ break;
+ case 0:
+ if (cursor_invisible) {
+ TPUTS_TRACE("cursor_invisible");
+ putp(cursor_invisible);
+ } else
+ result = ERR;
+ break;
+ }
+ SP->_cursor = vis;
+ _nc_flush();
+ }
+ }
+ returnCode(result);
+}
+
+NCURSES_EXPORT(int)
+typeahead(int fd)
+{
+ T((T_CALLED("typeahead(%d)"), fd));
+ if (SP != 0) {
+ SP->_checkfd = fd;
+ returnCode(OK);
+ } else {
+ returnCode(ERR);
+ }
+}
+
+/*
+** has_key()
+**
+** Return TRUE if the current terminal has the given key
+**
+*/
+
+#if NCURSES_EXT_FUNCS
+static int
+has_key_internal(int keycode, TRIES * tp)
+{
+ if (tp == 0)
+ return (FALSE);
+ else if (tp->value == keycode)
+ return (TRUE);
+ else
+ return (has_key_internal(keycode, tp->child)
+ || has_key_internal(keycode, tp->sibling));
+}
+
+NCURSES_EXPORT(int)
+has_key(int keycode)
+{
+ T((T_CALLED("has_key(%d)"), keycode));
+ returnCode(SP != 0 ? has_key_internal(keycode, SP->_keytry) : FALSE);
+}
+#endif /* NCURSES_EXT_FUNCS */
+
+/* Turn the keypad on/off
+ *
+ * Note: we flush the output because changing this mode causes some terminals
+ * to emit different escape sequences for cursor and keypad keys. If we don't
+ * flush, then the next wgetch may get the escape sequence that corresponds to
+ * the terminal state _before_ switching modes.
+ */
+NCURSES_EXPORT(int)
+_nc_keypad(SCREEN *sp, bool flag)
+{
+ if (flag && keypad_xmit) {
+ TPUTS_TRACE("keypad_xmit");
+ putp(keypad_xmit);
+ _nc_flush();
+ } else if (!flag && keypad_local) {
+ TPUTS_TRACE("keypad_local");
+ putp(keypad_local);
+ _nc_flush();
+ }
+
+ if (sp != 0) {
+ if (flag && !sp->_tried) {
+ _nc_init_keytry(sp);
+ sp->_tried = TRUE;
+ }
+ sp->_keypad_on = flag;
+ }
+ return (OK);
+}
diff --git a/ncurses/tinfo/lib_print.c b/ncurses/tinfo/lib_print.c
new file mode 100644
index 000000000000..975b46d85773
--- /dev/null
+++ b/ncurses/tinfo/lib_print.c
@@ -0,0 +1,92 @@
+/****************************************************************************
+ * Copyright (c) 1998-2002,2006 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+
+#include <term.h>
+
+MODULE_ID("$Id: lib_print.c,v 1.16 2006/11/26 00:26:34 tom Exp $")
+
+NCURSES_EXPORT(int)
+mcprint(char *data, int len)
+/* ship binary character data to the printer via mc4/mc5/mc5p */
+{
+ char *mybuf, *switchon;
+ size_t onsize, offsize, res;
+
+ errno = 0;
+ if (!cur_term || (!prtr_non && (!prtr_on || !prtr_off))) {
+ errno = ENODEV;
+ return (ERR);
+ }
+
+ if (prtr_non) {
+ switchon = TPARM_1(prtr_non, len);
+ onsize = strlen(switchon);
+ offsize = 0;
+ } else {
+ switchon = prtr_on;
+ onsize = strlen(prtr_on);
+ offsize = strlen(prtr_off);
+ }
+
+ if (switchon == 0
+ || (mybuf = typeMalloc(char, onsize + len + offsize + 1)) == 0) {
+ errno = ENOMEM;
+ return (ERR);
+ }
+
+ (void) strcpy(mybuf, switchon);
+ memcpy(mybuf + onsize, data, (unsigned) len);
+ if (offsize)
+ (void) strcpy(mybuf + onsize + len, prtr_off);
+
+ /*
+ * We're relying on the atomicity of UNIX writes here. The
+ * danger is that output from a refresh() might get interspersed
+ * with the printer data after the write call returns but before the
+ * data has actually been shipped to the terminal. If the write(2)
+ * operation is truly atomic we're protected from this.
+ */
+ res = write(cur_term->Filedes, mybuf, onsize + len + offsize);
+
+ /*
+ * By giving up our scheduler slot here we increase the odds that the
+ * kernel will ship the contiguous clist items from the last write
+ * immediately.
+ */
+ (void) sleep(0);
+
+ free(mybuf);
+ return (res);
+}
diff --git a/ncurses/tinfo/lib_raw.c b/ncurses/tinfo/lib_raw.c
new file mode 100644
index 000000000000..58e71889af12
--- /dev/null
+++ b/ncurses/tinfo/lib_raw.c
@@ -0,0 +1,296 @@
+/****************************************************************************
+ * Copyright (c) 1998-2002,2007 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1998 on *
+ ****************************************************************************/
+
+/*
+ * raw.c
+ *
+ * Routines:
+ * raw()
+ * cbreak()
+ * noraw()
+ * nocbreak()
+ * qiflush()
+ * noqiflush()
+ * intrflush()
+ *
+ */
+
+#include <curses.priv.h>
+#include <term.h> /* cur_term */
+
+MODULE_ID("$Id: lib_raw.c,v 1.14 2007/09/29 21:50:22 tom Exp $")
+
+#if SVR4_TERMIO && !defined(_POSIX_SOURCE)
+#define _POSIX_SOURCE
+#endif
+
+#if HAVE_SYS_TERMIO_H
+#include <sys/termio.h> /* needed for ISC */
+#endif
+
+#ifdef __EMX__
+#include <io.h>
+#define _nc_setmode(mode) setmode(SP->_ifd, mode)
+#else
+#define _nc_setmode(mode) /* nothing */
+#endif
+
+#define COOKED_INPUT (IXON|BRKINT|PARMRK)
+
+#ifdef TRACE
+#define BEFORE(N) if (USE_TRACEF(TRACE_BITS)) _nc_locked_tracef("%s before bits: %s", N, _nc_tracebits())
+#define AFTER(N) if (USE_TRACEF(TRACE_BITS)) _nc_locked_tracef("%s after bits: %s", N, _nc_tracebits())
+#else
+#define BEFORE(s)
+#define AFTER(s)
+#endif /* TRACE */
+
+NCURSES_EXPORT(int)
+raw(void)
+{
+ int result = ERR;
+
+ T((T_CALLED("raw()")));
+
+ if (SP != 0 && cur_term != 0) {
+ TTY buf;
+
+ BEFORE("raw");
+ _nc_setmode(O_BINARY);
+
+ buf = cur_term->Nttyb;
+#ifdef TERMIOS
+ buf.c_lflag &= ~(ICANON | ISIG | IEXTEN);
+ buf.c_iflag &= ~(COOKED_INPUT);
+ buf.c_cc[VMIN] = 1;
+ buf.c_cc[VTIME] = 0;
+#else
+ buf.sg_flags |= RAW;
+#endif
+ if ((result = _nc_set_tty_mode(&buf)) == OK) {
+ SP->_raw = TRUE;
+ SP->_cbreak = 1;
+ cur_term->Nttyb = buf;
+ }
+ AFTER("raw");
+ }
+ returnCode(result);
+}
+
+NCURSES_EXPORT(int)
+cbreak(void)
+{
+ int result = ERR;
+
+ T((T_CALLED("cbreak()")));
+
+ if (SP != 0 && cur_term != 0) {
+ TTY buf;
+
+ BEFORE("cbreak");
+ _nc_setmode(O_BINARY);
+
+ buf = cur_term->Nttyb;
+#ifdef TERMIOS
+ buf.c_lflag &= ~ICANON;
+ buf.c_iflag &= ~ICRNL;
+ buf.c_lflag |= ISIG;
+ buf.c_cc[VMIN] = 1;
+ buf.c_cc[VTIME] = 0;
+#else
+ buf.sg_flags |= CBREAK;
+#endif
+ if ((result = _nc_set_tty_mode(&buf)) == OK) {
+ SP->_cbreak = 1;
+ cur_term->Nttyb = buf;
+ }
+ AFTER("cbreak");
+ }
+ returnCode(result);
+}
+
+/*
+ * Note:
+ * this implementation may be wrong. See the comment under intrflush().
+ */
+NCURSES_EXPORT(void)
+qiflush(void)
+{
+ int result = ERR;
+
+ T((T_CALLED("qiflush()")));
+
+ if (cur_term != 0) {
+ TTY buf;
+
+ BEFORE("qiflush");
+ buf = cur_term->Nttyb;
+#ifdef TERMIOS
+ buf.c_lflag &= ~(NOFLSH);
+ result = _nc_set_tty_mode(&buf);
+#else
+ /* FIXME */
+#endif
+ if (result == OK)
+ cur_term->Nttyb = buf;
+ AFTER("qiflush");
+ }
+ returnVoid;
+}
+
+NCURSES_EXPORT(int)
+noraw(void)
+{
+ int result = ERR;
+
+ T((T_CALLED("noraw()")));
+
+ if (SP != 0 && cur_term != 0) {
+ TTY buf;
+
+ BEFORE("noraw");
+ _nc_setmode(O_TEXT);
+
+ buf = cur_term->Nttyb;
+#ifdef TERMIOS
+ buf.c_lflag |= ISIG | ICANON |
+ (cur_term->Ottyb.c_lflag & IEXTEN);
+ buf.c_iflag |= COOKED_INPUT;
+#else
+ buf.sg_flags &= ~(RAW | CBREAK);
+#endif
+ if ((result = _nc_set_tty_mode(&buf)) == OK) {
+ SP->_raw = FALSE;
+ SP->_cbreak = 0;
+ cur_term->Nttyb = buf;
+ }
+ AFTER("noraw");
+ }
+ returnCode(result);
+}
+
+NCURSES_EXPORT(int)
+nocbreak(void)
+{
+ int result = ERR;
+
+ T((T_CALLED("nocbreak()")));
+
+ if (SP != 0 && cur_term != 0) {
+ TTY buf;
+
+ BEFORE("nocbreak");
+ _nc_setmode(O_TEXT);
+
+ buf = cur_term->Nttyb;
+#ifdef TERMIOS
+ buf.c_lflag |= ICANON;
+ buf.c_iflag |= ICRNL;
+#else
+ buf.sg_flags &= ~CBREAK;
+#endif
+ if ((result = _nc_set_tty_mode(&buf)) == OK) {
+ SP->_cbreak = 0;
+ cur_term->Nttyb = buf;
+ }
+ AFTER("nocbreak");
+ }
+ returnCode(result);
+}
+
+/*
+ * Note:
+ * this implementation may be wrong. See the comment under intrflush().
+ */
+NCURSES_EXPORT(void)
+noqiflush(void)
+{
+ int result = ERR;
+
+ T((T_CALLED("noqiflush()")));
+
+ if (cur_term != 0) {
+ TTY buf;
+
+ BEFORE("noqiflush");
+ buf = cur_term->Nttyb;
+#ifdef TERMIOS
+ buf.c_lflag |= NOFLSH;
+ result = _nc_set_tty_mode(&buf);
+#else
+ /* FIXME */
+#endif
+ if (result == OK) {
+ cur_term->Nttyb = buf;
+ }
+ AFTER("noqiflush");
+ }
+ returnVoid;
+}
+
+/*
+ * This call does the same thing as the qiflush()/noqiflush() pair. We know
+ * for certain that SVr3 intrflush() tweaks the NOFLSH bit; on the other hand,
+ * the match (in the SVr4 man pages) between the language describing NOFLSH in
+ * termio(7) and the language describing qiflush()/noqiflush() in
+ * curs_inopts(3x) is too exact to be coincidence.
+ */
+NCURSES_EXPORT(int)
+intrflush(WINDOW *win GCC_UNUSED, bool flag)
+{
+ int result = ERR;
+
+ T((T_CALLED("intrflush(%d)"), flag));
+
+ if (cur_term != 0) {
+ TTY buf;
+
+ BEFORE("intrflush");
+ buf = cur_term->Nttyb;
+#ifdef TERMIOS
+ if (flag)
+ buf.c_lflag &= ~(NOFLSH);
+ else
+ buf.c_lflag |= (NOFLSH);
+ result = _nc_set_tty_mode(&buf);
+#else
+ /* FIXME */
+#endif
+ if (result == OK) {
+ cur_term->Nttyb = buf;
+ }
+ AFTER("intrflush");
+ }
+ returnCode(result);
+}
diff --git a/ncurses/tinfo/lib_setup.c b/ncurses/tinfo/lib_setup.c
new file mode 100644
index 000000000000..08cb783c5942
--- /dev/null
+++ b/ncurses/tinfo/lib_setup.c
@@ -0,0 +1,618 @@
+/****************************************************************************
+ * Copyright (c) 1998-2007,2008 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ ****************************************************************************/
+
+/*
+ * Terminal setup routines common to termcap and terminfo:
+ *
+ * use_env(bool)
+ * setupterm(char *, int, int *)
+ */
+
+#include <curses.priv.h>
+#include <tic.h> /* for MAX_NAME_SIZE */
+#include <term_entry.h>
+
+#if SVR4_TERMIO && !defined(_POSIX_SOURCE)
+#define _POSIX_SOURCE
+#endif
+
+#if HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#include <term.h> /* lines, columns, cur_term */
+
+MODULE_ID("$Id: lib_setup.c,v 1.105 2008/05/03 22:41:42 tom Exp $")
+
+/****************************************************************************
+ *
+ * Terminal size computation
+ *
+ ****************************************************************************/
+
+#if HAVE_SIZECHANGE
+# if !defined(sun) || !TERMIOS
+# if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+# endif
+# endif
+#endif
+
+#if NEED_PTEM_H
+ /* On SCO, they neglected to define struct winsize in termios.h -- it's only
+ * in termio.h and ptem.h (the former conflicts with other definitions).
+ */
+# include <sys/stream.h>
+# include <sys/ptem.h>
+#endif
+
+#if HAVE_LANGINFO_CODESET
+#include <langinfo.h>
+#endif
+
+/*
+ * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS,
+ * Solaris, IRIX) define TIOCGWINSZ and struct winsize.
+ */
+#ifdef TIOCGSIZE
+# define IOCTL_WINSIZE TIOCGSIZE
+# define STRUCT_WINSIZE struct ttysize
+# define WINSIZE_ROWS(n) (int)n.ts_lines
+# define WINSIZE_COLS(n) (int)n.ts_cols
+#else
+# ifdef TIOCGWINSZ
+# define IOCTL_WINSIZE TIOCGWINSZ
+# define STRUCT_WINSIZE struct winsize
+# define WINSIZE_ROWS(n) (int)n.ws_row
+# define WINSIZE_COLS(n) (int)n.ws_col
+# endif
+#endif
+
+/*
+ * Wrap global variables in this module.
+ */
+#if USE_REENTRANT
+NCURSES_EXPORT(char *)
+NCURSES_PUBLIC_VAR(ttytype) (void)
+{
+ static char empty[] = "";
+ return cur_term ? cur_term->type.term_names : empty;
+}
+NCURSES_EXPORT(int)
+NCURSES_PUBLIC_VAR(LINES) (void)
+{
+ return (SP ? SP->_LINES : _nc_prescreen._LINES);
+}
+NCURSES_EXPORT(int)
+NCURSES_PUBLIC_VAR(COLS) (void)
+{
+ return SP ? SP->_COLS : _nc_prescreen._COLS;
+}
+NCURSES_EXPORT(int)
+NCURSES_PUBLIC_VAR(TABSIZE) (void)
+{
+ return SP ? SP->_TABSIZE : 8;
+}
+#else
+NCURSES_EXPORT_VAR(char) ttytype[NAMESIZE] = "";
+NCURSES_EXPORT_VAR(int) LINES = 0;
+NCURSES_EXPORT_VAR(int) COLS = 0;
+NCURSES_EXPORT_VAR(int) TABSIZE = 0;
+#endif
+
+#if NCURSES_EXT_FUNCS
+NCURSES_EXPORT(int)
+set_tabsize(int value)
+{
+ int code = OK;
+#if USE_REENTRANT
+ if (SP) {
+ SP->_TABSIZE = value;
+ } else {
+ code = ERR;
+ }
+#else
+ TABSIZE = value;
+#endif
+ return code;
+}
+#endif
+
+#if USE_SIGWINCH
+/*
+ * If we have a pending SIGWINCH, set the flag in each screen.
+ */
+NCURSES_EXPORT(int)
+_nc_handle_sigwinch(SCREEN *sp)
+{
+ SCREEN *scan;
+
+ if (_nc_globals.have_sigwinch) {
+ _nc_globals.have_sigwinch = 0;
+
+ for (each_screen(scan)) {
+ scan->_sig_winch = TRUE;
+ }
+ }
+
+ return (sp ? sp->_sig_winch : 0);
+}
+
+#endif
+
+NCURSES_EXPORT(void)
+use_env(bool f)
+{
+ T((T_CALLED("use_env()")));
+ _nc_prescreen.use_env = f;
+ returnVoid;
+}
+
+NCURSES_EXPORT(void)
+_nc_get_screensize(SCREEN *sp, int *linep, int *colp)
+/* Obtain lines/columns values from the environment and/or terminfo entry */
+{
+ int my_tabsize;
+
+ /* figure out the size of the screen */
+ T(("screen size: terminfo lines = %d columns = %d", lines, columns));
+
+ if (!_nc_prescreen.use_env) {
+ *linep = (int) lines;
+ *colp = (int) columns;
+ } else { /* usually want to query LINES and COLUMNS from environment */
+ int value;
+
+ *linep = *colp = 0;
+
+ /* first, look for environment variables */
+ if ((value = _nc_getenv_num("LINES")) > 0) {
+ *linep = value;
+ }
+ if ((value = _nc_getenv_num("COLUMNS")) > 0) {
+ *colp = value;
+ }
+ T(("screen size: environment LINES = %d COLUMNS = %d", *linep, *colp));
+
+#ifdef __EMX__
+ if (*linep <= 0 || *colp <= 0) {
+ int screendata[2];
+ _scrsize(screendata);
+ *colp = screendata[0];
+ *linep = screendata[1];
+ T(("EMX screen size: environment LINES = %d COLUMNS = %d",
+ *linep, *colp));
+ }
+#endif
+#if HAVE_SIZECHANGE
+ /* if that didn't work, maybe we can try asking the OS */
+ if (*linep <= 0 || *colp <= 0) {
+ if (isatty(cur_term->Filedes)) {
+ STRUCT_WINSIZE size;
+
+ errno = 0;
+ do {
+ if (ioctl(cur_term->Filedes, IOCTL_WINSIZE, &size) < 0
+ && errno != EINTR)
+ goto failure;
+ } while
+ (errno == EINTR);
+
+ /*
+ * Solaris lets users override either dimension with an
+ * environment variable.
+ */
+ if (*linep <= 0)
+ *linep = (sp != 0 && sp->_filtered) ? 1 : WINSIZE_ROWS(size);
+ if (*colp <= 0)
+ *colp = WINSIZE_COLS(size);
+ }
+ /* FALLTHRU */
+ failure:;
+ }
+#endif /* HAVE_SIZECHANGE */
+
+ /* if we can't get dynamic info about the size, use static */
+ if (*linep <= 0) {
+ *linep = (int) lines;
+ }
+ if (*colp <= 0) {
+ *colp = (int) columns;
+ }
+
+ /* the ultimate fallback, assume fixed 24x80 size */
+ if (*linep <= 0) {
+ *linep = 24;
+ }
+ if (*colp <= 0) {
+ *colp = 80;
+ }
+
+ /*
+ * Put the derived values back in the screen-size caps, so
+ * tigetnum() and tgetnum() will do the right thing.
+ */
+ lines = (short) (*linep);
+ columns = (short) (*colp);
+ }
+
+ T(("screen size is %dx%d", *linep, *colp));
+
+ if (VALID_NUMERIC(init_tabs))
+ my_tabsize = (int) init_tabs;
+ else
+ my_tabsize = 8;
+
+#if USE_REENTRANT
+ if (sp != 0)
+ sp->_TABSIZE = my_tabsize;
+#else
+ TABSIZE = my_tabsize;
+#endif
+ T(("TABSIZE = %d", TABSIZE));
+}
+
+#if USE_SIZECHANGE
+NCURSES_EXPORT(void)
+_nc_update_screensize(SCREEN *sp)
+{
+ int old_lines = lines;
+ int new_lines;
+ int old_cols = columns;
+ int new_cols;
+
+ _nc_get_screensize(sp, &new_lines, &new_cols);
+
+ /*
+ * See is_term_resized() and resizeterm().
+ * We're doing it this way because those functions belong to the upper
+ * ncurses library, while this resides in the lower terminfo library.
+ */
+ if (sp != 0
+ && sp->_resize != 0) {
+ if ((new_lines != old_lines) || (new_cols != old_cols))
+ sp->_resize(new_lines, new_cols);
+ sp->_sig_winch = FALSE;
+ }
+}
+#endif
+
+/****************************************************************************
+ *
+ * Terminal setup
+ *
+ ****************************************************************************/
+
+#define ret_error(code, fmt, arg) if (errret) {\
+ *errret = code;\
+ returnCode(ERR);\
+ } else {\
+ fprintf(stderr, fmt, arg);\
+ exit(EXIT_FAILURE);\
+ }
+
+#define ret_error0(code, msg) if (errret) {\
+ *errret = code;\
+ returnCode(ERR);\
+ } else {\
+ fprintf(stderr, msg);\
+ exit(EXIT_FAILURE);\
+ }
+
+#if USE_DATABASE || USE_TERMCAP
+/*
+ * Return 1 if entry found, 0 if not found, -1 if database not accessible,
+ * just like tgetent().
+ */
+static int
+grab_entry(const char *const tn, TERMTYPE *const tp)
+{
+ char filename[PATH_MAX];
+ int status = _nc_read_entry(tn, filename, tp);
+
+ /*
+ * If we have an entry, force all of the cancelled strings to null
+ * pointers so we don't have to test them in the rest of the library.
+ * (The terminfo compiler bypasses this logic, since it must know if
+ * a string is cancelled, for merging entries).
+ */
+ if (status == TGETENT_YES) {
+ unsigned n;
+ for_each_boolean(n, tp) {
+ if (!VALID_BOOLEAN(tp->Booleans[n]))
+ tp->Booleans[n] = FALSE;
+ }
+ for_each_string(n, tp) {
+ if (tp->Strings[n] == CANCELLED_STRING)
+ tp->Strings[n] = ABSENT_STRING;
+ }
+ }
+ return (status);
+}
+#endif
+
+/*
+** do_prototype()
+**
+** Take the real command character out of the CC environment variable
+** and substitute it in for the prototype given in 'command_character'.
+*/
+static void
+do_prototype(void)
+{
+ int i;
+ char CC;
+ char proto;
+ char *tmp;
+
+ tmp = getenv("CC");
+ CC = *tmp;
+ proto = *command_character;
+
+ for_each_string(i, &(cur_term->type)) {
+ for (tmp = cur_term->type.Strings[i]; *tmp; tmp++) {
+ if (*tmp == proto)
+ *tmp = CC;
+ }
+ }
+}
+
+/*
+ * Find the locale which is in effect.
+ */
+NCURSES_EXPORT(char *)
+_nc_get_locale(void)
+{
+ char *env;
+#if HAVE_LOCALE_H
+ /*
+ * This is preferable to using getenv() since it ensures that we are using
+ * the locale which was actually initialized by the application.
+ */
+ env = setlocale(LC_CTYPE, 0);
+#else
+ if (((env = getenv("LC_ALL")) != 0 && *env != '\0')
+ || ((env = getenv("LC_CTYPE")) != 0 && *env != '\0')
+ || ((env = getenv("LANG")) != 0 && *env != '\0')) {
+ ;
+ }
+#endif
+ T(("_nc_get_locale %s", _nc_visbuf(env)));
+ return env;
+}
+
+/*
+ * Check if we are running in a UTF-8 locale.
+ */
+NCURSES_EXPORT(int)
+_nc_unicode_locale(void)
+{
+ int result = 0;
+#if HAVE_LANGINFO_CODESET
+ char *env = nl_langinfo(CODESET);
+ result = !strcmp(env, "UTF-8");
+ T(("_nc_unicode_locale(%s) ->%d", env, result));
+#else
+ char *env = _nc_get_locale();
+ if (env != 0) {
+ if (strstr(env, ".UTF-8") != 0) {
+ result = 1;
+ T(("_nc_unicode_locale(%s) ->%d", env, result));
+ }
+ }
+#endif
+ return result;
+}
+
+#define CONTROL_N(s) ((s) != 0 && strstr(s, "\016") != 0)
+#define CONTROL_O(s) ((s) != 0 && strstr(s, "\017") != 0)
+
+/*
+ * Check for known broken cases where a UTF-8 locale breaks the alternate
+ * character set.
+ */
+NCURSES_EXPORT(int)
+_nc_locale_breaks_acs(void)
+{
+ char *env;
+
+ if ((env = getenv("NCURSES_NO_UTF8_ACS")) != 0) {
+ return atoi(env);
+ } else if ((env = getenv("TERM")) != 0) {
+ if (strstr(env, "linux"))
+ return 1; /* always broken */
+ if (strstr(env, "screen") != 0
+ && ((env = getenv("TERMCAP")) != 0
+ && strstr(env, "screen") != 0)
+ && strstr(env, "hhII00") != 0) {
+ if (CONTROL_N(enter_alt_charset_mode) ||
+ CONTROL_O(enter_alt_charset_mode) ||
+ CONTROL_N(set_attributes) ||
+ CONTROL_O(set_attributes))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * This entrypoint is called from tgetent() to allow a special case of reusing
+ * the same TERMINAL data (see comment).
+ */
+NCURSES_EXPORT(int)
+_nc_setupterm(NCURSES_CONST char *tname, int Filedes, int *errret, bool reuse)
+{
+ int status;
+
+ START_TRACE();
+ T((T_CALLED("setupterm(%s,%d,%p)"), _nc_visbuf(tname), Filedes, errret));
+
+ if (tname == 0) {
+ tname = getenv("TERM");
+ if (tname == 0 || *tname == '\0') {
+ ret_error0(TGETENT_ERR, "TERM environment variable not set.\n");
+ }
+ }
+
+ if (strlen(tname) > MAX_NAME_SIZE) {
+ ret_error(TGETENT_ERR,
+ "TERM environment must be <= %d characters.\n",
+ MAX_NAME_SIZE);
+ }
+
+ T(("your terminal name is %s", tname));
+
+ /*
+ * Allow output redirection. This is what SVr3 does. If stdout is
+ * directed to a file, screen updates go to standard error.
+ */
+ if (Filedes == STDOUT_FILENO && !isatty(Filedes))
+ Filedes = STDERR_FILENO;
+
+ /*
+ * Check if we have already initialized to use this terminal. If so, we
+ * do not need to re-read the terminfo entry, or obtain TTY settings.
+ *
+ * This is an improvement on SVr4 curses. If an application mixes curses
+ * and termcap calls, it may call both initscr and tgetent. This is not
+ * really a good thing to do, but can happen if someone tries using ncurses
+ * with the readline library. The problem we are fixing is that when
+ * tgetent calls setupterm, the resulting Ottyb struct in cur_term is
+ * zeroed. A subsequent call to endwin uses the zeroed terminal settings
+ * rather than the ones saved in initscr. So we check if cur_term appears
+ * to contain terminal settings for the same output file as our current
+ * call - and copy those terminal settings. (SVr4 curses does not do this,
+ * however applications that are working around the problem will still work
+ * properly with this feature).
+ */
+ if (reuse
+ && cur_term != 0
+ && cur_term->Filedes == Filedes
+ && cur_term->_termname != 0
+ && !strcmp(cur_term->_termname, tname)
+ && _nc_name_match(cur_term->type.term_names, tname, "|")) {
+ T(("reusing existing terminal information and mode-settings"));
+ } else {
+ TERMINAL *term_ptr;
+
+ term_ptr = typeCalloc(TERMINAL, 1);
+
+ if (term_ptr == 0) {
+ ret_error0(TGETENT_ERR,
+ "Not enough memory to create terminal structure.\n");
+ }
+#if USE_DATABASE || USE_TERMCAP
+ status = grab_entry(tname, &term_ptr->type);
+#else
+ status = TGETENT_NO;
+#endif
+
+ /* try fallback list if entry on disk */
+ if (status != TGETENT_YES) {
+ const TERMTYPE *fallback = _nc_fallback(tname);
+
+ if (fallback) {
+ term_ptr->type = *fallback;
+ status = TGETENT_YES;
+ }
+ }
+
+ if (status != TGETENT_YES) {
+ del_curterm(term_ptr);
+ if (status == TGETENT_ERR) {
+ ret_error0(status, "terminals database is inaccessible\n");
+ } else if (status == TGETENT_NO) {
+ ret_error(status, "'%s': unknown terminal type.\n", tname);
+ }
+ }
+
+ set_curterm(term_ptr);
+
+ if (command_character && getenv("CC"))
+ do_prototype();
+
+#if !USE_REENTRANT
+ strncpy(ttytype, cur_term->type.term_names, NAMESIZE - 1);
+ ttytype[NAMESIZE - 1] = '\0';
+#endif
+
+ cur_term->Filedes = Filedes;
+ cur_term->_termname = strdup(tname);
+
+ /*
+ * If an application calls setupterm() rather than initscr() or
+ * newterm(), we will not have the def_prog_mode() call in
+ * _nc_setupscreen(). Do it now anyway, so we can initialize the
+ * baudrate.
+ */
+ if (isatty(Filedes)) {
+ def_prog_mode();
+ baudrate();
+ }
+ }
+
+ /*
+ * We should always check the screensize, just in case.
+ */
+#if USE_REENTRANT
+ _nc_get_screensize(SP,
+ SP ? &(SP->_LINES) : &(_nc_prescreen._LINES),
+ SP ? &(SP->_COLS) : &(_nc_prescreen._COLS));
+#else
+ _nc_get_screensize(SP, &LINES, &COLS);
+#endif
+
+ if (errret)
+ *errret = TGETENT_YES;
+
+ if (generic_type) {
+ ret_error(TGETENT_NO, "'%s': I need something more specific.\n", tname);
+ }
+ if (hard_copy) {
+ ret_error(TGETENT_YES, "'%s': I can't handle hardcopy terminals.\n", tname);
+ }
+ returnCode(OK);
+}
+
+/*
+ * setupterm(termname, Filedes, errret)
+ *
+ * Find and read the appropriate object file for the terminal
+ * Make cur_term point to the structure.
+ */
+NCURSES_EXPORT(int)
+setupterm(NCURSES_CONST char *tname, int Filedes, int *errret)
+{
+ return _nc_setupterm(tname, Filedes, errret, FALSE);
+}
diff --git a/ncurses/tinfo/lib_termcap.c b/ncurses/tinfo/lib_termcap.c
new file mode 100644
index 000000000000..ff97eea920f8
--- /dev/null
+++ b/ncurses/tinfo/lib_termcap.c
@@ -0,0 +1,290 @@
+/****************************************************************************
+ * Copyright (c) 1998-2006,2007 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ * *
+ * some of the code in here was contributed by: *
+ * Magnus Bengtsson, d6mbeng@dtek.chalmers.se (Nov'93) *
+ * (but it has changed a lot) *
+ ****************************************************************************/
+
+#define __INTERNAL_CAPS_VISIBLE
+#include <curses.priv.h>
+
+#include <termcap.h>
+#include <tic.h>
+#include <ctype.h>
+
+#include <term_entry.h>
+
+MODULE_ID("$Id: lib_termcap.c,v 1.61 2007/06/02 19:36:03 tom Exp $")
+
+NCURSES_EXPORT_VAR(char *) UP = 0;
+NCURSES_EXPORT_VAR(char *) BC = 0;
+
+#define MyCache _nc_globals.tgetent_cache
+#define CacheInx _nc_globals.tgetent_index
+#define CacheSeq _nc_globals.tgetent_sequence
+
+#define FIX_SGR0 MyCache[CacheInx].fix_sgr0
+#define LAST_TRM MyCache[CacheInx].last_term
+#define LAST_BUF MyCache[CacheInx].last_bufp
+#define LAST_USE MyCache[CacheInx].last_used
+#define LAST_SEQ MyCache[CacheInx].sequence
+
+/***************************************************************************
+ *
+ * tgetent(bufp, term)
+ *
+ * In termcap, this function reads in the entry for terminal `term' into the
+ * buffer pointed to by bufp. It must be called before any of the functions
+ * below are called.
+ * In this terminfo emulation, tgetent() simply calls setupterm() (which
+ * does a bit more than tgetent() in termcap does), and returns its return
+ * value (1 if successful, 0 if no terminal with the given name could be
+ * found, or -1 if no terminal descriptions have been installed on the
+ * system). The bufp argument is ignored.
+ *
+ ***************************************************************************/
+
+NCURSES_EXPORT(int)
+tgetent(char *bufp, const char *name)
+{
+ int errcode;
+ int n;
+ bool found_cache = FALSE;
+
+ START_TRACE();
+ T((T_CALLED("tgetent()")));
+
+ _nc_setupterm((NCURSES_CONST char *) name, STDOUT_FILENO, &errcode, TRUE);
+
+ /*
+ * In general we cannot tell if the fixed sgr0 is still used by the
+ * caller, but if tgetent() is called with the same buffer, that is
+ * good enough, since the previous data would be invalidated by the
+ * current call.
+ *
+ * bufp may be a null pointer, e.g., GNU termcap. That allocates data,
+ * which is good until the next tgetent() call. The conventional termcap
+ * is inconvenient because of the fixed buffer size, but because it uses
+ * caller-supplied buffers, can have multiple terminal descriptions in
+ * use at a given time.
+ */
+ for (n = 0; n < TGETENT_MAX; ++n) {
+ bool same_result = (MyCache[n].last_used && MyCache[n].last_bufp == bufp);
+ if (same_result) {
+ CacheInx = n;
+ if (FIX_SGR0 != 0) {
+ FreeAndNull(FIX_SGR0);
+ }
+ /*
+ * Also free the terminfo data that we loaded (much bigger leak).
+ */
+ if (LAST_TRM != 0 && LAST_TRM != cur_term) {
+ TERMINAL *trm = LAST_TRM;
+ del_curterm(LAST_TRM);
+ for (CacheInx = 0; CacheInx < TGETENT_MAX; ++CacheInx)
+ if (LAST_TRM == trm)
+ LAST_TRM = 0;
+ CacheInx = n;
+ }
+ found_cache = TRUE;
+ break;
+ }
+ }
+ if (!found_cache) {
+ int best = 0;
+
+ for (CacheInx = 0; CacheInx < TGETENT_MAX; ++CacheInx) {
+ if (LAST_SEQ < MyCache[best].sequence) {
+ best = CacheInx;
+ }
+ }
+ CacheInx = best;
+ }
+ LAST_TRM = cur_term;
+ LAST_SEQ = ++CacheSeq;
+
+ PC = 0;
+ UP = 0;
+ BC = 0;
+ FIX_SGR0 = 0; /* don't free it - application may still use */
+
+ if (errcode == 1) {
+
+ if (cursor_left)
+ if ((backspaces_with_bs = !strcmp(cursor_left, "\b")) == 0)
+ backspace_if_not_bs = cursor_left;
+
+ /* we're required to export these */
+ if (pad_char != NULL)
+ PC = pad_char[0];
+ if (cursor_up != NULL)
+ UP = cursor_up;
+ if (backspace_if_not_bs != NULL)
+ BC = backspace_if_not_bs;
+
+ if ((FIX_SGR0 = _nc_trim_sgr0(&(cur_term->type))) != 0) {
+ if (!strcmp(FIX_SGR0, exit_attribute_mode)) {
+ if (FIX_SGR0 != exit_attribute_mode) {
+ free(FIX_SGR0);
+ }
+ FIX_SGR0 = 0;
+ }
+ }
+ LAST_BUF = bufp;
+ LAST_USE = TRUE;
+
+ (void) baudrate(); /* sets ospeed as a side-effect */
+
+/* LINT_PREPRO
+#if 0*/
+#include <capdefaults.c>
+/* LINT_PREPRO
+#endif*/
+
+ }
+ returnCode(errcode);
+}
+
+/***************************************************************************
+ *
+ * tgetflag(str)
+ *
+ * Look up boolean termcap capability str and return its value (TRUE=1 if
+ * present, FALSE=0 if not).
+ *
+ ***************************************************************************/
+
+NCURSES_EXPORT(int)
+tgetflag(NCURSES_CONST char *id)
+{
+ unsigned i;
+
+ T((T_CALLED("tgetflag(%s)"), id));
+ if (cur_term != 0) {
+ TERMTYPE *tp = &(cur_term->type);
+ for_each_boolean(i, tp) {
+ const char *capname = ExtBoolname(tp, i, boolcodes);
+ if (!strncmp(id, capname, 2)) {
+ /* setupterm forces invalid booleans to false */
+ returnCode(tp->Booleans[i]);
+ }
+ }
+ }
+ returnCode(0); /* Solaris does this */
+}
+
+/***************************************************************************
+ *
+ * tgetnum(str)
+ *
+ * Look up numeric termcap capability str and return its value, or -1 if
+ * not given.
+ *
+ ***************************************************************************/
+
+NCURSES_EXPORT(int)
+tgetnum(NCURSES_CONST char *id)
+{
+ unsigned i;
+
+ T((T_CALLED("tgetnum(%s)"), id));
+ if (cur_term != 0) {
+ TERMTYPE *tp = &(cur_term->type);
+ for_each_number(i, tp) {
+ const char *capname = ExtNumname(tp, i, numcodes);
+ if (!strncmp(id, capname, 2)) {
+ if (!VALID_NUMERIC(tp->Numbers[i]))
+ returnCode(ABSENT_NUMERIC);
+ returnCode(tp->Numbers[i]);
+ }
+ }
+ }
+ returnCode(ABSENT_NUMERIC);
+}
+
+/***************************************************************************
+ *
+ * tgetstr(str, area)
+ *
+ * Look up string termcap capability str and return a pointer to its value,
+ * or NULL if not given.
+ *
+ ***************************************************************************/
+
+NCURSES_EXPORT(char *)
+tgetstr(NCURSES_CONST char *id, char **area)
+{
+ unsigned i;
+ char *result = NULL;
+
+ T((T_CALLED("tgetstr(%s,%p)"), id, area));
+ if (cur_term != 0) {
+ TERMTYPE *tp = &(cur_term->type);
+ for_each_string(i, tp) {
+ const char *capname = ExtStrname(tp, i, strcodes);
+ if (!strncmp(id, capname, 2)) {
+ result = tp->Strings[i];
+ TR(TRACE_DATABASE, ("found match : %s", _nc_visbuf(result)));
+ /* setupterm forces canceled strings to null */
+ if (VALID_STRING(result)) {
+ if (result == exit_attribute_mode
+ && FIX_SGR0 != 0) {
+ result = FIX_SGR0;
+ TR(TRACE_DATABASE, ("altered to : %s", _nc_visbuf(result)));
+ }
+ if (area != 0
+ && *area != 0) {
+ (void) strcpy(*area, result);
+ result = *area;
+ *area += strlen(*area) + 1;
+ }
+ }
+ break;
+ }
+ }
+ }
+ returnPtr(result);
+}
+
+#if NO_LEAKS
+NCURSES_EXPORT(void)
+_nc_tgetent_leaks(void)
+{
+ for (CacheInx = 0; CacheInx < TGETENT_MAX; ++CacheInx) {
+ FreeIfNeeded(FIX_SGR0);
+ if (LAST_TRM != 0)
+ del_curterm(LAST_TRM);
+ }
+}
+#endif
diff --git a/ncurses/tinfo/lib_termname.c b/ncurses/tinfo/lib_termname.c
new file mode 100644
index 000000000000..713d0be8c360
--- /dev/null
+++ b/ncurses/tinfo/lib_termname.c
@@ -0,0 +1,44 @@
+/****************************************************************************
+ * Copyright (c) 1998-2001,2003 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "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. *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+
+MODULE_ID("$Id: lib_termname.c,v 1.8 2003/12/27 18:23:01 tom Exp $")
+
+NCURSES_EXPORT(char *)
+termname(void)
+{
+ char *name = 0;
+
+ T((T_CALLED("termname()")));
+
+ if (cur_term != 0)
+ name = cur_term->_termname;
+
+ returnPtr(name);
+}
diff --git a/ncurses/tinfo/lib_tgoto.c b/ncurses/tinfo/lib_tgoto.c
new file mode 100644
index 000000000000..37553f712394
--- /dev/null
+++ b/ncurses/tinfo/lib_tgoto.c
@@ -0,0 +1,203 @@
+/****************************************************************************
+ * Copyright (c) 2000-2003,2006 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), 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 <curses.priv.h>
+
+#include <ctype.h>
+#include <termcap.h>
+
+MODULE_ID("$Id: lib_tgoto.c,v 1.12 2006/11/26 00:26:24 tom Exp $")
+
+#if !PURE_TERMINFO
+static bool
+is_termcap(const char *string)
+{
+ bool result = TRUE;
+
+ if (string == 0 || *string == '\0') {
+ result = FALSE; /* tparm() handles empty strings */
+ } else {
+ while ((*string != '\0') && result) {
+ if (*string == '%') {
+ switch (*++string) {
+ case 'p':
+ result = FALSE;
+ break;
+ case '\0':
+ string--;
+ break;
+ }
+ } else if (string[0] == '$' && string[1] == '<') {
+ result = FALSE;
+ }
+ string++;
+ }
+ }
+ return result;
+}
+
+static char *
+tgoto_internal(const char *string, int x, int y)
+{
+ static char *result;
+ static size_t length;
+
+ int swap_arg;
+ int param[3];
+ size_t used = 0;
+ size_t need = 10;
+ int *value = param;
+ bool need_BC = FALSE;
+
+ if (BC)
+ need += strlen(BC);
+
+ param[0] = y;
+ param[1] = x;
+ param[2] = 0;
+
+ while (*string != 0) {
+ if ((used + need) > length) {
+ length += (used + need);
+ if ((result = typeRealloc(char, length, result)) == 0) {
+ length = 0;
+ break;
+ }
+ }
+ if (*string == '%') {
+ const char *fmt = 0;
+
+ switch (*++string) {
+ case '\0':
+ string--;
+ break;
+ case 'd':
+ fmt = "%d";
+ break;
+ case '2':
+ fmt = "%02d";
+ *value %= 100;
+ break;
+ case '3':
+ fmt = "%03d";
+ *value %= 1000;
+ break;
+ case '+':
+ *value += UChar(*++string);
+ /* FALLTHRU */
+ case '.':
+ /*
+ * Guard against tputs() seeing a truncated string. The
+ * termcap documentation refers to a similar fixup for \n
+ * and \r, but I don't see that it could work -TD
+ */
+ if (*value == 0) {
+ if (BC != 0) {
+ *value += 1;
+ need_BC = TRUE;
+ } else {
+ *value = 0200; /* tputs will treat this as \0 */
+ }
+ }
+ result[used++] = *value++;
+ break;
+ case '%':
+ result[used++] = *string;
+ break;
+ case 'r':
+ swap_arg = param[0];
+ param[0] = param[1];
+ param[1] = swap_arg;
+ break;
+ case 'i':
+ param[0] += 1;
+ param[1] += 1;
+ break;
+ case '>':
+ if (*value > string[1])
+ *value += string[2];
+ string += 2;
+ break;
+ case 'n': /* Datamedia 2500 */
+ param[0] ^= 0140;
+ param[1] ^= 0140;
+ break;
+ case 'B': /* BCD */
+ *value = 16 * (*value / 10) + (*value % 10);
+ break;
+ case 'D': /* Reverse coding (Delta Data) */
+ *value -= 2 * (*value % 16);
+ break;
+ }
+ if (fmt != 0) {
+ sprintf(result + used, fmt, *value++);
+ used += strlen(result + used);
+ fmt = 0;
+ }
+ if (value - param > 2) {
+ value = param + 2;
+ *value = 0;
+ }
+ } else {
+ result[used++] = *string;
+ }
+ string++;
+ }
+ if (result != 0) {
+ if (need_BC) {
+ strcpy(result + used, BC);
+ used += strlen(BC);
+ }
+ result[used] = '\0';
+ }
+ return result;
+}
+#endif
+
+/*
+ * Retained solely for upward compatibility. Note the intentional reversing of
+ * the last two arguments when invoking tparm().
+ */
+NCURSES_EXPORT(char *)
+tgoto(const char *string, int x, int y)
+{
+ char *result;
+
+ T((T_CALLED("tgoto(%s, %d, %d)"), _nc_visbuf(string), x, y));
+#if !PURE_TERMINFO
+ if (is_termcap(string))
+ result = tgoto_internal(string, x, y);
+ else
+#endif
+ result = TPARM_2((NCURSES_CONST char *) string, y, x);
+ returnPtr(result);
+}
diff --git a/ncurses/tinfo/lib_ti.c b/ncurses/tinfo/lib_ti.c
new file mode 100644
index 000000000000..df460f953ea7
--- /dev/null
+++ b/ncurses/tinfo/lib_ti.c
@@ -0,0 +1,103 @@
+/****************************************************************************
+ * Copyright (c) 1998-2000,2003 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+
+#include <term_entry.h>
+#include <tic.h>
+
+MODULE_ID("$Id: lib_ti.c,v 1.23 2003/05/24 21:10:28 tom Exp $")
+
+NCURSES_EXPORT(int)
+tigetflag(NCURSES_CONST char *str)
+{
+ unsigned i;
+
+ T((T_CALLED("tigetflag(%s)"), str));
+
+ if (cur_term != 0) {
+ TERMTYPE *tp = &(cur_term->type);
+ for_each_boolean(i, tp) {
+ const char *capname = ExtBoolname(tp, i, boolnames);
+ if (!strcmp(str, capname)) {
+ /* setupterm forces invalid booleans to false */
+ returnCode(tp->Booleans[i]);
+ }
+ }
+ }
+
+ returnCode(ABSENT_BOOLEAN);
+}
+
+NCURSES_EXPORT(int)
+tigetnum(NCURSES_CONST char *str)
+{
+ unsigned i;
+
+ T((T_CALLED("tigetnum(%s)"), str));
+
+ if (cur_term != 0) {
+ TERMTYPE *tp = &(cur_term->type);
+ for_each_number(i, tp) {
+ const char *capname = ExtNumname(tp, i, numnames);
+ if (!strcmp(str, capname)) {
+ if (!VALID_NUMERIC(tp->Numbers[i]))
+ returnCode(ABSENT_NUMERIC);
+ returnCode(tp->Numbers[i]);
+ }
+ }
+ }
+
+ returnCode(CANCELLED_NUMERIC); /* Solaris returns a -1 instead */
+}
+
+NCURSES_EXPORT(char *)
+tigetstr(NCURSES_CONST char *str)
+{
+ unsigned i;
+
+ T((T_CALLED("tigetstr(%s)"), str));
+
+ if (cur_term != 0) {
+ TERMTYPE *tp = &(cur_term->type);
+ for_each_string(i, tp) {
+ const char *capname = ExtStrname(tp, i, strnames);
+ if (!strcmp(str, capname)) {
+ /* setupterm forces cancelled strings to null */
+ returnPtr(tp->Strings[i]);
+ }
+ }
+ }
+
+ returnPtr(CANCELLED_STRING);
+}
diff --git a/ncurses/tinfo/lib_tparm.c b/ncurses/tinfo/lib_tparm.c
new file mode 100644
index 000000000000..d11fcf80cfbf
--- /dev/null
+++ b/ncurses/tinfo/lib_tparm.c
@@ -0,0 +1,791 @@
+/****************************************************************************
+ * Copyright (c) 1998-2006,2007 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey, 1996 on *
+ ****************************************************************************/
+
+/*
+ * tparm.c
+ *
+ */
+
+#include <curses.priv.h>
+
+#include <ctype.h>
+#include <term.h>
+#include <tic.h>
+
+MODULE_ID("$Id: lib_tparm.c,v 1.74 2007/09/29 20:37:13 tom Exp $")
+
+/*
+ * char *
+ * tparm(string, ...)
+ *
+ * Substitute the given parameters into the given string by the following
+ * rules (taken from terminfo(5)):
+ *
+ * Cursor addressing and other strings requiring parame-
+ * ters in the terminal are described by a parameterized string
+ * capability, with like escapes %x in it. For example, to
+ * address the cursor, the cup capability is given, using two
+ * parameters: the row and column to address to. (Rows and
+ * columns are numbered from zero and refer to the physical
+ * screen visible to the user, not to any unseen memory.) If
+ * the terminal has memory relative cursor addressing, that can
+ * be indicated by
+ *
+ * The parameter mechanism uses a stack and special %
+ * codes to manipulate it. Typically a sequence will push one
+ * of the parameters onto the stack and then print it in some
+ * format. Often more complex operations are necessary.
+ *
+ * The % encodings have the following meanings:
+ *
+ * %% outputs `%'
+ * %c print pop() like %c in printf()
+ * %s print pop() like %s in printf()
+ * %[[:]flags][width[.precision]][doxXs]
+ * as in printf, flags are [-+#] and space
+ * The ':' is used to avoid making %+ or %-
+ * patterns (see below).
+ *
+ * %p[1-9] push ith parm
+ * %P[a-z] set dynamic variable [a-z] to pop()
+ * %g[a-z] get dynamic variable [a-z] and push it
+ * %P[A-Z] set static variable [A-Z] to pop()
+ * %g[A-Z] get static variable [A-Z] and push it
+ * %l push strlen(pop)
+ * %'c' push char constant c
+ * %{nn} push integer constant nn
+ *
+ * %+ %- %* %/ %m
+ * arithmetic (%m is mod): push(pop() op pop())
+ * %& %| %^ bit operations: push(pop() op pop())
+ * %= %> %< logical operations: push(pop() op pop())
+ * %A %O logical and & or operations for conditionals
+ * %! %~ unary operations push(op pop())
+ * %i add 1 to first two parms (for ANSI terminals)
+ *
+ * %? expr %t thenpart %e elsepart %;
+ * if-then-else, %e elsepart is optional.
+ * else-if's are possible ala Algol 68:
+ * %? c1 %t b1 %e c2 %t b2 %e c3 %t b3 %e c4 %t b4 %e b5 %;
+ *
+ * For those of the above operators which are binary and not commutative,
+ * the stack works in the usual way, with
+ * %gx %gy %m
+ * resulting in x mod y, not the reverse.
+ */
+
+NCURSES_EXPORT_VAR(int) _nc_tparm_err = 0;
+
+#define TPS(var) _nc_prescreen.tparm_state.var
+
+#if NO_LEAKS
+NCURSES_EXPORT(void)
+_nc_free_tparm(void)
+{
+ if (TPS(out_buff) != 0) {
+ FreeAndNull(TPS(out_buff));
+ TPS(out_size) = 0;
+ TPS(out_used) = 0;
+ FreeAndNull(TPS(fmt_buff));
+ TPS(fmt_size) = 0;
+ }
+}
+#endif
+
+static NCURSES_INLINE void
+get_space(size_t need)
+{
+ need += TPS(out_used);
+ if (need > TPS(out_size)) {
+ TPS(out_size) = need * 2;
+ TPS(out_buff) = typeRealloc(char, TPS(out_size), TPS(out_buff));
+ if (TPS(out_buff) == 0)
+ _nc_err_abort(MSG_NO_MEMORY);
+ }
+}
+
+static NCURSES_INLINE void
+save_text(const char *fmt, const char *s, int len)
+{
+ size_t s_len = strlen(s);
+ if (len > (int) s_len)
+ s_len = len;
+
+ get_space(s_len + 1);
+
+ (void) sprintf(TPS(out_buff) + TPS(out_used), fmt, s);
+ TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used));
+}
+
+static NCURSES_INLINE void
+save_number(const char *fmt, int number, int len)
+{
+ if (len < 30)
+ len = 30; /* actually log10(MAX_INT)+1 */
+
+ get_space((unsigned) len + 1);
+
+ (void) sprintf(TPS(out_buff) + TPS(out_used), fmt, number);
+ TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used));
+}
+
+static NCURSES_INLINE void
+save_char(int c)
+{
+ if (c == 0)
+ c = 0200;
+ get_space(1);
+ TPS(out_buff)[TPS(out_used)++] = c;
+}
+
+static NCURSES_INLINE void
+npush(int x)
+{
+ if (TPS(stack_ptr) < STACKSIZE) {
+ TPS(stack)[TPS(stack_ptr)].num_type = TRUE;
+ TPS(stack)[TPS(stack_ptr)].data.num = x;
+ TPS(stack_ptr)++;
+ } else {
+ DEBUG(2, ("npush: stack overflow: %s", _nc_visbuf(TPS(tparam_base))));
+ _nc_tparm_err++;
+ }
+}
+
+static NCURSES_INLINE int
+npop(void)
+{
+ int result = 0;
+ if (TPS(stack_ptr) > 0) {
+ TPS(stack_ptr)--;
+ if (TPS(stack)[TPS(stack_ptr)].num_type)
+ result = TPS(stack)[TPS(stack_ptr)].data.num;
+ } else {
+ DEBUG(2, ("npop: stack underflow: %s", _nc_visbuf(TPS(tparam_base))));
+ _nc_tparm_err++;
+ }
+ return result;
+}
+
+static NCURSES_INLINE void
+spush(char *x)
+{
+ if (TPS(stack_ptr) < STACKSIZE) {
+ TPS(stack)[TPS(stack_ptr)].num_type = FALSE;
+ TPS(stack)[TPS(stack_ptr)].data.str = x;
+ TPS(stack_ptr)++;
+ } else {
+ DEBUG(2, ("spush: stack overflow: %s", _nc_visbuf(TPS(tparam_base))));
+ _nc_tparm_err++;
+ }
+}
+
+static NCURSES_INLINE char *
+spop(void)
+{
+ static char dummy[] = ""; /* avoid const-cast */
+ char *result = dummy;
+ if (TPS(stack_ptr) > 0) {
+ TPS(stack_ptr)--;
+ if (!TPS(stack)[TPS(stack_ptr)].num_type
+ && TPS(stack)[TPS(stack_ptr)].data.str != 0)
+ result = TPS(stack)[TPS(stack_ptr)].data.str;
+ } else {
+ DEBUG(2, ("spop: stack underflow: %s", _nc_visbuf(TPS(tparam_base))));
+ _nc_tparm_err++;
+ }
+ return result;
+}
+
+static NCURSES_INLINE const char *
+parse_format(const char *s, char *format, int *len)
+{
+ *len = 0;
+ if (format != 0) {
+ bool done = FALSE;
+ bool allowminus = FALSE;
+ bool dot = FALSE;
+ bool err = FALSE;
+ char *fmt = format;
+ int my_width = 0;
+ int my_prec = 0;
+ int value = 0;
+
+ *len = 0;
+ *format++ = '%';
+ while (*s != '\0' && !done) {
+ switch (*s) {
+ case 'c': /* FALLTHRU */
+ case 'd': /* FALLTHRU */
+ case 'o': /* FALLTHRU */
+ case 'x': /* FALLTHRU */
+ case 'X': /* FALLTHRU */
+ case 's':
+ *format++ = *s;
+ done = TRUE;
+ break;
+ case '.':
+ *format++ = *s++;
+ if (dot) {
+ err = TRUE;
+ } else { /* value before '.' is the width */
+ dot = TRUE;
+ my_width = value;
+ }
+ value = 0;
+ break;
+ case '#':
+ *format++ = *s++;
+ break;
+ case ' ':
+ *format++ = *s++;
+ break;
+ case ':':
+ s++;
+ allowminus = TRUE;
+ break;
+ case '-':
+ if (allowminus) {
+ *format++ = *s++;
+ } else {
+ done = TRUE;
+ }
+ break;
+ default:
+ if (isdigit(UChar(*s))) {
+ value = (value * 10) + (*s - '0');
+ if (value > 10000)
+ err = TRUE;
+ *format++ = *s++;
+ } else {
+ done = TRUE;
+ }
+ }
+ }
+
+ /*
+ * If we found an error, ignore (and remove) the flags.
+ */
+ if (err) {
+ my_width = my_prec = value = 0;
+ format = fmt;
+ *format++ = '%';
+ *format++ = *s;
+ }
+
+ /*
+ * Any value after '.' is the precision. If we did not see '.', then
+ * the value is the width.
+ */
+ if (dot)
+ my_prec = value;
+ else
+ my_width = value;
+
+ *format = '\0';
+ /* return maximum string length in print */
+ *len = (my_width > my_prec) ? my_width : my_prec;
+ }
+ return s;
+}
+
+#define isUPPER(c) ((c) >= 'A' && (c) <= 'Z')
+#define isLOWER(c) ((c) >= 'a' && (c) <= 'z')
+
+/*
+ * Analyze the string to see how many parameters we need from the varargs list,
+ * and what their types are. We will only accept string parameters if they
+ * appear as a %l or %s format following an explicit parameter reference (e.g.,
+ * %p2%s). All other parameters are numbers.
+ *
+ * 'number' counts coarsely the number of pop's we see in the string, and
+ * 'popcount' shows the highest parameter number in the string. We would like
+ * to simply use the latter count, but if we are reading termcap strings, there
+ * may be cases that we cannot see the explicit parameter numbers.
+ */
+NCURSES_EXPORT(int)
+_nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount)
+{
+ size_t len2;
+ int i;
+ int lastpop = -1;
+ int len;
+ int number = 0;
+ const char *cp = string;
+ static char dummy[] = "";
+
+ if (cp == 0)
+ return 0;
+
+ if ((len2 = strlen(cp)) > TPS(fmt_size)) {
+ TPS(fmt_size) = len2 + TPS(fmt_size) + 2;
+ TPS(fmt_buff) = typeRealloc(char, TPS(fmt_size), TPS(fmt_buff));
+ if (TPS(fmt_buff) == 0)
+ return 0;
+ }
+
+ memset(p_is_s, 0, sizeof(p_is_s[0]) * NUM_PARM);
+ *popcount = 0;
+
+ while ((cp - string) < (int) len2) {
+ if (*cp == '%') {
+ cp++;
+ cp = parse_format(cp, TPS(fmt_buff), &len);
+ switch (*cp) {
+ default:
+ break;
+
+ case 'd': /* FALLTHRU */
+ case 'o': /* FALLTHRU */
+ case 'x': /* FALLTHRU */
+ case 'X': /* FALLTHRU */
+ case 'c': /* FALLTHRU */
+ if (lastpop <= 0)
+ number++;
+ lastpop = -1;
+ break;
+
+ case 'l':
+ case 's':
+ if (lastpop > 0)
+ p_is_s[lastpop - 1] = dummy;
+ ++number;
+ break;
+
+ case 'p':
+ cp++;
+ i = (UChar(*cp) - '0');
+ if (i >= 0 && i <= NUM_PARM) {
+ lastpop = i;
+ if (lastpop > *popcount)
+ *popcount = lastpop;
+ }
+ break;
+
+ case 'P':
+ ++number;
+ ++cp;
+ break;
+
+ case 'g':
+ cp++;
+ break;
+
+ case S_QUOTE:
+ cp += 2;
+ lastpop = -1;
+ break;
+
+ case L_BRACE:
+ cp++;
+ while (isdigit(UChar(*cp))) {
+ cp++;
+ }
+ break;
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case 'm':
+ case 'A':
+ case 'O':
+ case '&':
+ case '|':
+ case '^':
+ case '=':
+ case '<':
+ case '>':
+ lastpop = -1;
+ number += 2;
+ break;
+
+ case '!':
+ case '~':
+ lastpop = -1;
+ ++number;
+ break;
+
+ case 'i':
+ /* will add 1 to first (usually two) parameters */
+ break;
+ }
+ }
+ if (*cp != '\0')
+ cp++;
+ }
+
+ if (number > NUM_PARM)
+ number = NUM_PARM;
+ return number;
+}
+
+static NCURSES_INLINE char *
+tparam_internal(const char *string, va_list ap)
+{
+ char *p_is_s[NUM_PARM];
+ TPARM_ARG param[NUM_PARM];
+ int popcount;
+ int number;
+ int len;
+ int level;
+ int x, y;
+ int i;
+ const char *cp = string;
+ size_t len2;
+
+ if (cp == NULL)
+ return NULL;
+
+ TPS(out_used) = 0;
+ len2 = strlen(cp);
+
+ /*
+ * Find the highest parameter-number referred to in the format string.
+ * Use this value to limit the number of arguments copied from the
+ * variable-length argument list.
+ */
+ number = _nc_tparm_analyze(cp, p_is_s, &popcount);
+ if (TPS(fmt_buff) == 0)
+ return NULL;
+
+ for (i = 0; i < max(popcount, number); i++) {
+ /*
+ * A few caps (such as plab_norm) have string-valued parms.
+ * We'll have to assume that the caller knows the difference, since
+ * a char* and an int may not be the same size on the stack. The
+ * normal prototype for this uses 9 long's, which is consistent with
+ * our va_arg() usage.
+ */
+ if (p_is_s[i] != 0) {
+ p_is_s[i] = va_arg(ap, char *);
+ } else {
+ param[i] = va_arg(ap, TPARM_ARG);
+ }
+ }
+
+ /*
+ * This is a termcap compatibility hack. If there are no explicit pop
+ * operations in the string, load the stack in such a way that
+ * successive pops will grab successive parameters. That will make
+ * the expansion of (for example) \E[%d;%dH work correctly in termcap
+ * style, which means tparam() will expand termcap strings OK.
+ */
+ TPS(stack_ptr) = 0;
+ if (popcount == 0) {
+ popcount = number;
+ for (i = number - 1; i >= 0; i--)
+ npush(param[i]);
+ }
+#ifdef TRACE
+ if (USE_TRACEF(TRACE_CALLS)) {
+ for (i = 0; i < popcount; i++) {
+ if (p_is_s[i] != 0)
+ save_text(", %s", _nc_visbuf(p_is_s[i]), 0);
+ else
+ save_number(", %d", param[i], 0);
+ }
+ _tracef(T_CALLED("%s(%s%s)"), TPS(tname), _nc_visbuf(cp), TPS(out_buff));
+ TPS(out_used) = 0;
+ _nc_unlock_global(tracef);
+ }
+#endif /* TRACE */
+
+ while ((cp - string) < (int) len2) {
+ if (*cp != '%') {
+ save_char(UChar(*cp));
+ } else {
+ TPS(tparam_base) = cp++;
+ cp = parse_format(cp, TPS(fmt_buff), &len);
+ switch (*cp) {
+ default:
+ break;
+ case '%':
+ save_char('%');
+ break;
+
+ case 'd': /* FALLTHRU */
+ case 'o': /* FALLTHRU */
+ case 'x': /* FALLTHRU */
+ case 'X': /* FALLTHRU */
+ save_number(TPS(fmt_buff), npop(), len);
+ break;
+
+ case 'c': /* FALLTHRU */
+ save_char(npop());
+ break;
+
+ case 'l':
+ save_number("%d", (int) strlen(spop()), 0);
+ break;
+
+ case 's':
+ save_text(TPS(fmt_buff), spop(), len);
+ break;
+
+ case 'p':
+ cp++;
+ i = (UChar(*cp) - '1');
+ if (i >= 0 && i < NUM_PARM) {
+ if (p_is_s[i])
+ spush(p_is_s[i]);
+ else
+ npush(param[i]);
+ }
+ break;
+
+ case 'P':
+ cp++;
+ if (isUPPER(*cp)) {
+ i = (UChar(*cp) - 'A');
+ TPS(static_vars)[i] = npop();
+ } else if (isLOWER(*cp)) {
+ i = (UChar(*cp) - 'a');
+ TPS(dynamic_var)[i] = npop();
+ }
+ break;
+
+ case 'g':
+ cp++;
+ if (isUPPER(*cp)) {
+ i = (UChar(*cp) - 'A');
+ npush(TPS(static_vars)[i]);
+ } else if (isLOWER(*cp)) {
+ i = (UChar(*cp) - 'a');
+ npush(TPS(dynamic_var)[i]);
+ }
+ break;
+
+ case S_QUOTE:
+ cp++;
+ npush(UChar(*cp));
+ cp++;
+ break;
+
+ case L_BRACE:
+ number = 0;
+ cp++;
+ while (isdigit(UChar(*cp))) {
+ number = (number * 10) + (UChar(*cp) - '0');
+ cp++;
+ }
+ npush(number);
+ break;
+
+ case '+':
+ npush(npop() + npop());
+ break;
+
+ case '-':
+ y = npop();
+ x = npop();
+ npush(x - y);
+ break;
+
+ case '*':
+ npush(npop() * npop());
+ break;
+
+ case '/':
+ y = npop();
+ x = npop();
+ npush(y ? (x / y) : 0);
+ break;
+
+ case 'm':
+ y = npop();
+ x = npop();
+ npush(y ? (x % y) : 0);
+ break;
+
+ case 'A':
+ npush(npop() && npop());
+ break;
+
+ case 'O':
+ npush(npop() || npop());
+ break;
+
+ case '&':
+ npush(npop() & npop());
+ break;
+
+ case '|':
+ npush(npop() | npop());
+ break;
+
+ case '^':
+ npush(npop() ^ npop());
+ break;
+
+ case '=':
+ y = npop();
+ x = npop();
+ npush(x == y);
+ break;
+
+ case '<':
+ y = npop();
+ x = npop();
+ npush(x < y);
+ break;
+
+ case '>':
+ y = npop();
+ x = npop();
+ npush(x > y);
+ break;
+
+ case '!':
+ npush(!npop());
+ break;
+
+ case '~':
+ npush(~npop());
+ break;
+
+ case 'i':
+ if (p_is_s[0] == 0)
+ param[0]++;
+ if (p_is_s[1] == 0)
+ param[1]++;
+ break;
+
+ case '?':
+ break;
+
+ case 't':
+ x = npop();
+ if (!x) {
+ /* scan forward for %e or %; at level zero */
+ cp++;
+ level = 0;
+ while (*cp) {
+ if (*cp == '%') {
+ cp++;
+ if (*cp == '?')
+ level++;
+ else if (*cp == ';') {
+ if (level > 0)
+ level--;
+ else
+ break;
+ } else if (*cp == 'e' && level == 0)
+ break;
+ }
+
+ if (*cp)
+ cp++;
+ }
+ }
+ break;
+
+ case 'e':
+ /* scan forward for a %; at level zero */
+ cp++;
+ level = 0;
+ while (*cp) {
+ if (*cp == '%') {
+ cp++;
+ if (*cp == '?')
+ level++;
+ else if (*cp == ';') {
+ if (level > 0)
+ level--;
+ else
+ break;
+ }
+ }
+
+ if (*cp)
+ cp++;
+ }
+ break;
+
+ case ';':
+ break;
+
+ } /* endswitch (*cp) */
+ } /* endelse (*cp == '%') */
+
+ if (*cp == '\0')
+ break;
+
+ cp++;
+ } /* endwhile (*cp) */
+
+ get_space(1);
+ TPS(out_buff)[TPS(out_used)] = '\0';
+
+ T((T_RETURN("%s"), _nc_visbuf(TPS(out_buff))));
+ return (TPS(out_buff));
+}
+
+#if NCURSES_TPARM_VARARGS
+#define tparm_varargs tparm
+#else
+#define tparm_proto tparm
+#endif
+
+NCURSES_EXPORT(char *)
+tparm_varargs(NCURSES_CONST char *string,...)
+{
+ va_list ap;
+ char *result;
+
+ _nc_tparm_err = 0;
+ va_start(ap, string);
+#ifdef TRACE
+ TPS(tname) = "tparm";
+#endif /* TRACE */
+ result = tparam_internal(string, ap);
+ va_end(ap);
+ return result;
+}
+
+#if !NCURSES_TPARM_VARARGS
+NCURSES_EXPORT(char *)
+tparm_proto(NCURSES_CONST char *string,
+ TPARM_ARG a1,
+ TPARM_ARG a2,
+ TPARM_ARG a3,
+ TPARM_ARG a4,
+ TPARM_ARG a5,
+ TPARM_ARG a6,
+ TPARM_ARG a7,
+ TPARM_ARG a8,
+ TPARM_ARG a9)
+{
+ return tparm_varargs(string, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+}
+#endif /* NCURSES_TPARM_VARARGS */
diff --git a/ncurses/tinfo/lib_tputs.c b/ncurses/tinfo/lib_tputs.c
new file mode 100644
index 000000000000..aab3351905ce
--- /dev/null
+++ b/ncurses/tinfo/lib_tputs.c
@@ -0,0 +1,258 @@
+/****************************************************************************
+ * Copyright (c) 1998-2003,2007 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ ****************************************************************************/
+
+/*
+ * tputs.c
+ * delay_output()
+ * _nc_outch()
+ * tputs()
+ *
+ */
+
+#include <curses.priv.h>
+#include <ctype.h>
+#include <term.h> /* padding_baud_rate, xon_xoff */
+#include <termcap.h> /* ospeed */
+#include <tic.h>
+
+MODULE_ID("$Id: lib_tputs.c,v 1.64 2007/09/29 20:37:13 tom Exp $")
+
+NCURSES_EXPORT_VAR(char) PC = 0; /* used by termcap library */
+NCURSES_EXPORT_VAR(NCURSES_OSPEED) ospeed = 0; /* used by termcap library */
+
+NCURSES_EXPORT_VAR(int) _nc_nulls_sent = 0; /* used by 'tack' program */
+
+static int (*my_outch) (int c) = _nc_outch;
+
+NCURSES_EXPORT(int)
+delay_output(int ms)
+{
+ T((T_CALLED("delay_output(%d)"), ms));
+
+ if (no_pad_char) {
+ _nc_flush();
+ napms(ms);
+ } else {
+ register int nullcount;
+
+ nullcount = (ms * _nc_baudrate(ospeed)) / (BAUDBYTE * 1000);
+ for (_nc_nulls_sent += nullcount; nullcount > 0; nullcount--)
+ my_outch(PC);
+ if (my_outch == _nc_outch)
+ _nc_flush();
+ }
+
+ returnCode(OK);
+}
+
+NCURSES_EXPORT(void)
+_nc_flush(void)
+{
+ (void) fflush(NC_OUTPUT);
+}
+
+NCURSES_EXPORT(int)
+_nc_outch(int ch)
+{
+ COUNT_OUTCHARS(1);
+
+ if (SP != 0
+ && SP->_cleanup) {
+ char tmp = ch;
+ /*
+ * POSIX says write() is safe in a signal handler, but the
+ * buffered I/O is not.
+ */
+ write(fileno(NC_OUTPUT), &tmp, 1);
+ } else {
+ putc(ch, NC_OUTPUT);
+ }
+ return OK;
+}
+
+NCURSES_EXPORT(int)
+putp(const char *string)
+{
+ return tputs(string, 1, _nc_outch);
+}
+
+NCURSES_EXPORT(int)
+tputs(const char *string, int affcnt, int (*outc) (int))
+{
+ bool always_delay;
+ bool normal_delay;
+ int number;
+#if BSD_TPUTS
+ int trailpad;
+#endif /* BSD_TPUTS */
+
+#ifdef TRACE
+ char addrbuf[32];
+
+ if (USE_TRACEF(TRACE_TPUTS)) {
+ if (outc == _nc_outch)
+ (void) strcpy(addrbuf, "_nc_outch");
+ else
+ (void) sprintf(addrbuf, "%p", outc);
+ if (_nc_tputs_trace) {
+ _tracef("tputs(%s = %s, %d, %s) called", _nc_tputs_trace,
+ _nc_visbuf(string), affcnt, addrbuf);
+ } else {
+ _tracef("tputs(%s, %d, %s) called", _nc_visbuf(string), affcnt, addrbuf);
+ }
+ TPUTS_TRACE(NULL);
+ _nc_unlock_global(tracef);
+ }
+#endif /* TRACE */
+
+ if (!VALID_STRING(string))
+ return ERR;
+
+ if (cur_term == 0) {
+ always_delay = FALSE;
+ normal_delay = TRUE;
+ } else {
+ always_delay = (string == bell) || (string == flash_screen);
+ normal_delay =
+ !xon_xoff
+ && padding_baud_rate
+#if NCURSES_NO_PADDING
+ && (SP == 0 || !(SP->_no_padding))
+#endif
+ && (_nc_baudrate(ospeed) >= padding_baud_rate);
+ }
+
+#if BSD_TPUTS
+ /*
+ * This ugly kluge deals with the fact that some ancient BSD programs
+ * (like nethack) actually do the likes of tputs("50") to get delays.
+ */
+ trailpad = 0;
+ if (isdigit(UChar(*string))) {
+ while (isdigit(UChar(*string))) {
+ trailpad = trailpad * 10 + (*string - '0');
+ string++;
+ }
+ trailpad *= 10;
+ if (*string == '.') {
+ string++;
+ if (isdigit(UChar(*string))) {
+ trailpad += (*string - '0');
+ string++;
+ }
+ while (isdigit(UChar(*string)))
+ string++;
+ }
+
+ if (*string == '*') {
+ trailpad *= affcnt;
+ string++;
+ }
+ }
+#endif /* BSD_TPUTS */
+
+ my_outch = outc; /* redirect delay_output() */
+ while (*string) {
+ if (*string != '$')
+ (*outc) (*string);
+ else {
+ string++;
+ if (*string != '<') {
+ (*outc) ('$');
+ if (*string)
+ (*outc) (*string);
+ } else {
+ bool mandatory;
+
+ string++;
+ if ((!isdigit(UChar(*string)) && *string != '.')
+ || !strchr(string, '>')) {
+ (*outc) ('$');
+ (*outc) ('<');
+ continue;
+ }
+
+ number = 0;
+ while (isdigit(UChar(*string))) {
+ number = number * 10 + (*string - '0');
+ string++;
+ }
+ number *= 10;
+ if (*string == '.') {
+ string++;
+ if (isdigit(UChar(*string))) {
+ number += (*string - '0');
+ string++;
+ }
+ while (isdigit(UChar(*string)))
+ string++;
+ }
+
+ mandatory = FALSE;
+ while (*string == '*' || *string == '/') {
+ if (*string == '*') {
+ number *= affcnt;
+ string++;
+ } else { /* if (*string == '/') */
+ mandatory = TRUE;
+ string++;
+ }
+ }
+
+ if (number > 0
+ && (always_delay
+ || normal_delay
+ || mandatory))
+ delay_output(number / 10);
+
+ } /* endelse (*string == '<') */
+ } /* endelse (*string == '$') */
+
+ if (*string == '\0')
+ break;
+
+ string++;
+ }
+
+#if BSD_TPUTS
+ /*
+ * Emit any BSD-style prefix padding that we've accumulated now.
+ */
+ if (trailpad > 0
+ && (always_delay || normal_delay))
+ delay_output(trailpad / 10);
+#endif /* BSD_TPUTS */
+
+ my_outch = _nc_outch;
+ return OK;
+}
diff --git a/ncurses/tinfo/lib_ttyflags.c b/ncurses/tinfo/lib_ttyflags.c
new file mode 100644
index 000000000000..2cb9fd67b4dd
--- /dev/null
+++ b/ncurses/tinfo/lib_ttyflags.c
@@ -0,0 +1,210 @@
+/****************************************************************************
+ * Copyright (c) 1998-2007,2008 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. *
+ ****************************************************************************/
+
+/*
+ * def_prog_mode()
+ * def_shell_mode()
+ * reset_prog_mode()
+ * reset_shell_mode()
+ * savetty()
+ * resetty()
+ */
+
+#include <curses.priv.h>
+#include <term.h> /* cur_term */
+
+MODULE_ID("$Id: lib_ttyflags.c,v 1.16 2008/05/03 22:39:03 tom Exp $")
+
+NCURSES_EXPORT(int)
+_nc_get_tty_mode(TTY * buf)
+{
+ int result = OK;
+
+ if (buf == 0) {
+ result = ERR;
+ } else {
+ if (cur_term == 0) {
+ result = ERR;
+ } else {
+ for (;;) {
+ if (GET_TTY(cur_term->Filedes, buf) != 0) {
+ if (errno == EINTR)
+ continue;
+ result = ERR;
+ }
+ break;
+ }
+ }
+
+ if (result == ERR)
+ memset(buf, 0, sizeof(*buf));
+
+ TR(TRACE_BITS, ("_nc_get_tty_mode(%d): %s",
+ cur_term->Filedes, _nc_trace_ttymode(buf)));
+ }
+ return (result);
+}
+
+NCURSES_EXPORT(int)
+_nc_set_tty_mode(TTY * buf)
+{
+ int result = OK;
+
+ if (buf == 0) {
+ result = ERR;
+ } else {
+ if (cur_term == 0) {
+ result = ERR;
+ } else {
+ for (;;) {
+ if (SET_TTY(cur_term->Filedes, buf) != 0) {
+ if (errno == EINTR)
+ continue;
+ if ((errno == ENOTTY) && (SP != 0))
+ SP->_notty = TRUE;
+ result = ERR;
+ }
+ break;
+ }
+ }
+ TR(TRACE_BITS, ("_nc_set_tty_mode(%d): %s",
+ cur_term->Filedes, _nc_trace_ttymode(buf)));
+ }
+ return (result);
+}
+
+NCURSES_EXPORT(int)
+def_shell_mode(void)
+{
+ T((T_CALLED("def_shell_mode()")));
+
+ /*
+ * If XTABS was on, remove the tab and backtab capabilities.
+ */
+
+ if (_nc_get_tty_mode(&cur_term->Ottyb) != OK)
+ returnCode(ERR);
+#ifdef TERMIOS
+ if (cur_term->Ottyb.c_oflag & OFLAGS_TABS)
+ tab = back_tab = NULL;
+#else
+ if (cur_term->Ottyb.sg_flags & XTABS)
+ tab = back_tab = NULL;
+#endif
+ returnCode(OK);
+}
+
+NCURSES_EXPORT(int)
+def_prog_mode(void)
+{
+ T((T_CALLED("def_prog_mode()")));
+
+ /*
+ * Turn off the XTABS bit in the tty structure if it was on.
+ */
+
+ if (_nc_get_tty_mode(&cur_term->Nttyb) != OK)
+ returnCode(ERR);
+#ifdef TERMIOS
+ cur_term->Nttyb.c_oflag &= ~OFLAGS_TABS;
+#else
+ cur_term->Nttyb.sg_flags &= ~XTABS;
+#endif
+ returnCode(OK);
+}
+
+NCURSES_EXPORT(int)
+reset_prog_mode(void)
+{
+ T((T_CALLED("reset_prog_mode()")));
+
+ if (cur_term != 0) {
+ if (_nc_set_tty_mode(&cur_term->Nttyb) == OK) {
+ if (SP) {
+ if (SP->_keypad_on)
+ _nc_keypad(SP, TRUE);
+ NC_BUFFERED(TRUE);
+ }
+ returnCode(OK);
+ }
+ }
+ returnCode(ERR);
+}
+
+NCURSES_EXPORT(int)
+reset_shell_mode(void)
+{
+ T((T_CALLED("reset_shell_mode()")));
+
+ if (cur_term != 0) {
+ if (SP) {
+ _nc_keypad(SP, FALSE);
+ _nc_flush();
+ NC_BUFFERED(FALSE);
+ }
+ returnCode(_nc_set_tty_mode(&cur_term->Ottyb));
+ }
+ returnCode(ERR);
+}
+
+static TTY *
+saved_tty(void)
+{
+ TTY *result = 0;
+
+ if (SP != 0) {
+ result = &(SP->_saved_tty);
+ } else {
+ if (_nc_prescreen.saved_tty == 0) {
+ _nc_prescreen.saved_tty = typeCalloc(TTY, 1);
+ }
+ result = _nc_prescreen.saved_tty;
+ }
+ return result;
+}
+
+/*
+** savetty() and resetty()
+**
+*/
+
+NCURSES_EXPORT(int)
+savetty(void)
+{
+ T((T_CALLED("savetty()")));
+
+ returnCode(_nc_get_tty_mode(saved_tty()));
+}
+
+NCURSES_EXPORT(int)
+resetty(void)
+{
+ T((T_CALLED("resetty()")));
+
+ returnCode(_nc_set_tty_mode(saved_tty()));
+}
diff --git a/ncurses/tinfo/make_keys.c b/ncurses/tinfo/make_keys.c
new file mode 100644
index 000000000000..00367185a45c
--- /dev/null
+++ b/ncurses/tinfo/make_keys.c
@@ -0,0 +1,142 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2007 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 <dickey@clark.net> 1997 *
+ ****************************************************************************/
+
+/*
+ * This replaces an awk script which translated keys.list into keys.tries by
+ * making the output show the indices into the TERMTYPE Strings array. Doing
+ * it that way lets us cut down on the size of the init_keytry() function.
+ */
+
+#define USE_TERMLIB 1
+#include <curses.priv.h>
+
+MODULE_ID("$Id: make_keys.c,v 1.13 2007/01/07 00:00:14 tom Exp $")
+
+#include <names.c>
+
+#define UNKNOWN (SIZEOF(strnames) + SIZEOF(strfnames))
+
+static size_t
+lookup(const char *name)
+{
+ size_t n;
+ bool found = FALSE;
+ for (n = 0; strnames[n] != 0; n++) {
+ if (!strcmp(name, strnames[n])) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found) {
+ for (n = 0; strfnames[n] != 0; n++) {
+ if (!strcmp(name, strfnames[n])) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ return found ? n : UNKNOWN;
+}
+
+static void
+make_keys(FILE *ifp, FILE *ofp)
+{
+ char buffer[BUFSIZ];
+ char from[BUFSIZ];
+ char to[BUFSIZ];
+ int maxlen = 16;
+
+ while (fgets(buffer, sizeof(buffer), ifp) != 0) {
+ if (*buffer == '#')
+ continue;
+ if (sscanf(buffer, "%s %s", to, from) == 2) {
+ int code = lookup(from);
+ if (code == UNKNOWN)
+ continue;
+ if ((int) strlen(from) > maxlen)
+ maxlen = strlen(from);
+ fprintf(ofp, "\t{ %4d, %-*.*s },\t/* %s */\n",
+ code,
+ maxlen, maxlen,
+ to,
+ from);
+ }
+ }
+}
+
+static void
+write_list(FILE *ofp, const char **list)
+{
+ while (*list != 0)
+ fprintf(ofp, "%s\n", *list++);
+}
+
+int
+main(int argc, char *argv[])
+{
+ static const char *prefix[] =
+ {
+ "#ifndef NCU_KEYS_H",
+ "#define NCU_KEYS_H 1",
+ "",
+ "/* This file was generated by MAKE_KEYS */",
+ "",
+ "#if BROKEN_LINKER",
+ "static",
+ "#endif",
+ "const struct tinfo_fkeys _nc_tinfo_fkeys[] = {",
+ 0
+ };
+ static const char *suffix[] =
+ {
+ "\t{ 0, 0} };",
+ "",
+ "#endif /* NCU_KEYS_H */",
+ 0
+ };
+
+ write_list(stdout, prefix);
+ if (argc > 1) {
+ int n;
+ for (n = 1; n < argc; n++) {
+ FILE *fp = fopen(argv[n], "r");
+ if (fp != 0) {
+ make_keys(fp, stdout);
+ fclose(fp);
+ }
+ }
+ } else {
+ make_keys(stdin, stdout);
+ }
+ write_list(stdout, suffix);
+ return EXIT_SUCCESS;
+}
diff --git a/ncurses/tinfo/name_match.c b/ncurses/tinfo/name_match.c
new file mode 100644
index 000000000000..c8d728faa7c4
--- /dev/null
+++ b/ncurses/tinfo/name_match.c
@@ -0,0 +1,108 @@
+/****************************************************************************
+ * Copyright (c) 1999-2005,2007 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 <dickey@clark.net> 1999 *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+#include <term.h>
+#include <tic.h>
+
+MODULE_ID("$Id: name_match.c,v 1.16 2007/04/21 21:28:13 tom Exp $")
+
+/*
+ * _nc_first_name(char *names)
+ *
+ * Extract the primary name from a compiled entry.
+ */
+#define FirstName _nc_globals.first_name
+
+NCURSES_EXPORT(char *)
+_nc_first_name(const char *const sp)
+/* get the first name from the given name list */
+{
+ unsigned n;
+
+#if NO_LEAKS
+ if (sp == 0) {
+ if (FirstName != 0)
+ FreeAndNull(FirstName);
+ return 0;
+ }
+#endif
+
+ if (FirstName == 0)
+ FirstName = typeMalloc(char, MAX_NAME_SIZE + 1);
+ for (n = 0; n < MAX_NAME_SIZE; n++) {
+ if ((FirstName[n] = sp[n]) == '\0'
+ || (FirstName[n] == '|'))
+ break;
+ }
+ FirstName[n] = '\0';
+ return (FirstName);
+}
+
+/*
+ * int _nc_name_match(namelist, name, delim)
+ *
+ * Is the given name matched in namelist?
+ */
+
+NCURSES_EXPORT(int)
+_nc_name_match(const char *const namelst, const char *const name, const char *const delim)
+{
+ const char *s, *d, *t;
+ int code, found;
+
+ if ((s = namelst) != 0) {
+ while (*s != '\0') {
+ for (d = name; *d != '\0'; d++) {
+ if (*s != *d)
+ break;
+ s++;
+ }
+ found = FALSE;
+ for (code = TRUE; *s != '\0'; code = FALSE, s++) {
+ for (t = delim; *t != '\0'; t++) {
+ if (*s == *t) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found)
+ break;
+ }
+ if (code && *d == '\0')
+ return code;
+ if (*s++ == 0)
+ break;
+ }
+ }
+ return FALSE;
+}
diff --git a/ncurses/tinfo/parse_entry.c b/ncurses/tinfo/parse_entry.c
new file mode 100644
index 000000000000..375ce8ff9957
--- /dev/null
+++ b/ncurses/tinfo/parse_entry.c
@@ -0,0 +1,991 @@
+/****************************************************************************
+ * Copyright (c) 1998-2006,2007 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ ****************************************************************************/
+
+/*
+ * parse_entry.c -- compile one terminfo or termcap entry
+ *
+ * Get an exact in-core representation of an entry. Don't
+ * try to resolve use or tc capabilities, that is someone
+ * else's job. Depends on the lexical analyzer to get tokens
+ * from the input stream.
+ */
+
+#define __INTERNAL_CAPS_VISIBLE
+#include <curses.priv.h>
+
+#include <ctype.h>
+#include <tic.h>
+#include <term_entry.h>
+
+MODULE_ID("$Id: parse_entry.c,v 1.65 2007/08/11 16:19:02 tom Exp $")
+
+#ifdef LINT
+static short const parametrized[] =
+{0};
+#else
+#include <parametrized.h>
+#endif
+
+static void postprocess_termcap(TERMTYPE *, bool);
+static void postprocess_terminfo(TERMTYPE *);
+static struct name_table_entry const *lookup_fullname(const char *name);
+
+#if NCURSES_XNAMES
+
+static struct name_table_entry const *
+_nc_extend_names(ENTRY * entryp, char *name, int token_type)
+{
+ static struct name_table_entry temp;
+ TERMTYPE *tp = &(entryp->tterm);
+ unsigned offset = 0;
+ unsigned actual;
+ unsigned tindex;
+ unsigned first, last, n;
+ bool found;
+
+ switch (token_type) {
+ case BOOLEAN:
+ first = 0;
+ last = tp->ext_Booleans;
+ offset = tp->ext_Booleans;
+ tindex = tp->num_Booleans;
+ break;
+ case NUMBER:
+ first = tp->ext_Booleans;
+ last = tp->ext_Numbers + first;
+ offset = tp->ext_Booleans + tp->ext_Numbers;
+ tindex = tp->num_Numbers;
+ break;
+ case STRING:
+ first = tp->ext_Booleans + tp->ext_Numbers;
+ last = tp->ext_Strings + first;
+ offset = tp->ext_Booleans + tp->ext_Numbers + tp->ext_Strings;
+ tindex = tp->num_Strings;
+ break;
+ case CANCEL:
+ actual = NUM_EXT_NAMES(tp);
+ for (n = 0; n < actual; n++) {
+ if (!strcmp(name, tp->ext_Names[n])) {
+ if (n > (unsigned) (tp->ext_Booleans + tp->ext_Numbers)) {
+ token_type = STRING;
+ } else if (n > tp->ext_Booleans) {
+ token_type = NUMBER;
+ } else {
+ token_type = BOOLEAN;
+ }
+ return _nc_extend_names(entryp, name, token_type);
+ }
+ }
+ /* Well, we are given a cancel for a name that we don't recognize */
+ return _nc_extend_names(entryp, name, STRING);
+ default:
+ return 0;
+ }
+
+ /* Adjust the 'offset' (insertion-point) to keep the lists of extended
+ * names sorted.
+ */
+ for (n = first, found = FALSE; n < last; n++) {
+ int cmp = strcmp(tp->ext_Names[n], name);
+ if (cmp == 0)
+ found = TRUE;
+ if (cmp >= 0) {
+ offset = n;
+ tindex = n - first;
+ switch (token_type) {
+ case BOOLEAN:
+ tindex += BOOLCOUNT;
+ break;
+ case NUMBER:
+ tindex += NUMCOUNT;
+ break;
+ case STRING:
+ tindex += STRCOUNT;
+ break;
+ }
+ break;
+ }
+ }
+ if (!found) {
+ switch (token_type) {
+ case BOOLEAN:
+ tp->ext_Booleans += 1;
+ tp->num_Booleans += 1;
+ tp->Booleans = typeRealloc(NCURSES_SBOOL, tp->num_Booleans, tp->Booleans);
+ for (last = tp->num_Booleans - 1; last > tindex; last--)
+ tp->Booleans[last] = tp->Booleans[last - 1];
+ break;
+ case NUMBER:
+ tp->ext_Numbers += 1;
+ tp->num_Numbers += 1;
+ tp->Numbers = typeRealloc(short, tp->num_Numbers, tp->Numbers);
+ for (last = tp->num_Numbers - 1; last > tindex; last--)
+ tp->Numbers[last] = tp->Numbers[last - 1];
+ break;
+ case STRING:
+ tp->ext_Strings += 1;
+ tp->num_Strings += 1;
+ tp->Strings = typeRealloc(char *, tp->num_Strings, tp->Strings);
+ for (last = tp->num_Strings - 1; last > tindex; last--)
+ tp->Strings[last] = tp->Strings[last - 1];
+ break;
+ }
+ actual = NUM_EXT_NAMES(tp);
+ tp->ext_Names = typeRealloc(char *, actual, tp->ext_Names);
+ while (--actual > offset)
+ tp->ext_Names[actual] = tp->ext_Names[actual - 1];
+ tp->ext_Names[offset] = _nc_save_str(name);
+ }
+
+ temp.nte_name = tp->ext_Names[offset];
+ temp.nte_type = token_type;
+ temp.nte_index = tindex;
+ temp.nte_link = -1;
+
+ return &temp;
+}
+#endif /* NCURSES_XNAMES */
+
+/*
+ * int
+ * _nc_parse_entry(entry, literal, silent)
+ *
+ * Compile one entry. Doesn't try to resolve use or tc capabilities.
+ *
+ * found-forward-use = FALSE
+ * re-initialise internal arrays
+ * get_token();
+ * if the token was not a name in column 1, complain and die
+ * save names in entry's string table
+ * while (get_token() is not EOF and not NAMES)
+ * check for existence and type-correctness
+ * enter cap into structure
+ * if STRING
+ * save string in entry's string table
+ * push back token
+ */
+
+#define BAD_TC_USAGE if (!bad_tc_usage) \
+ { bad_tc_usage = TRUE; \
+ _nc_warning("Legacy termcap allows only a trailing tc= clause"); }
+
+NCURSES_EXPORT(int)
+_nc_parse_entry(struct entry *entryp, int literal, bool silent)
+{
+ int token_type;
+ struct name_table_entry const *entry_ptr;
+ char *ptr, *base;
+ bool bad_tc_usage = FALSE;
+
+ token_type = _nc_get_token(silent);
+
+ if (token_type == EOF)
+ return (EOF);
+ if (token_type != NAMES)
+ _nc_err_abort("Entry does not start with terminal names in column one");
+
+ _nc_init_entry(&entryp->tterm);
+
+ entryp->cstart = _nc_comment_start;
+ entryp->cend = _nc_comment_end;
+ entryp->startline = _nc_start_line;
+ DEBUG(2, ("Comment range is %ld to %ld", entryp->cstart, entryp->cend));
+
+ /*
+ * Strip off the 2-character termcap name, if present. Originally termcap
+ * used that as an indexing aid. We can retain 2-character terminfo names,
+ * but note that they would be lost if we translate to/from termcap. This
+ * feature is supposedly obsolete since "newer" BSD implementations do not
+ * use it; however our reference for this feature is SunOS 4.x, which
+ * implemented it. Note that the resulting terminal type was never the
+ * 2-character name, but was instead the first alias after that.
+ */
+ ptr = _nc_curr_token.tk_name;
+ if (_nc_syntax == SYN_TERMCAP
+#if NCURSES_XNAMES
+ && !_nc_user_definable
+#endif
+ ) {
+ if (ptr[2] == '|') {
+ ptr += 3;
+ _nc_curr_token.tk_name[2] = '\0';
+ }
+ }
+
+ entryp->tterm.str_table = entryp->tterm.term_names = _nc_save_str(ptr);
+
+ DEBUG(1, ("Starting '%s'", ptr));
+
+ /*
+ * We do this because the one-token lookahead in the parse loop
+ * results in the terminal type getting prematurely set to correspond
+ * to that of the next entry.
+ */
+ _nc_set_type(_nc_first_name(entryp->tterm.term_names));
+
+ /* check for overly-long names and aliases */
+ for (base = entryp->tterm.term_names; (ptr = strchr(base, '|')) != 0;
+ base = ptr + 1) {
+ if (ptr - base > MAX_ALIAS) {
+ _nc_warning("%s `%.*s' may be too long",
+ (base == entryp->tterm.term_names)
+ ? "primary name"
+ : "alias",
+ (int) (ptr - base), base);
+ }
+ }
+
+ entryp->nuses = 0;
+
+ for (token_type = _nc_get_token(silent);
+ token_type != EOF && token_type != NAMES;
+ token_type = _nc_get_token(silent)) {
+ bool is_use = (strcmp(_nc_curr_token.tk_name, "use") == 0);
+ bool is_tc = !is_use && (strcmp(_nc_curr_token.tk_name, "tc") == 0);
+ if (is_use || is_tc) {
+ entryp->uses[entryp->nuses].name = _nc_save_str(_nc_curr_token.tk_valstring);
+ entryp->uses[entryp->nuses].line = _nc_curr_line;
+ entryp->nuses++;
+ if (entryp->nuses > 1 && is_tc) {
+ BAD_TC_USAGE
+ }
+ } else {
+ /* normal token lookup */
+ entry_ptr = _nc_find_entry(_nc_curr_token.tk_name,
+ _nc_get_hash_table(_nc_syntax));
+
+ /*
+ * Our kluge to handle aliasing. The reason it's done
+ * this ugly way, with a linear search, is so the hashing
+ * machinery doesn't have to be made really complicated
+ * (also we get better warnings this way). No point in
+ * making this case fast, aliased caps aren't common now
+ * and will get rarer.
+ */
+ if (entry_ptr == NOTFOUND) {
+ const struct alias *ap;
+
+ if (_nc_syntax == SYN_TERMCAP) {
+ if (entryp->nuses != 0) {
+ BAD_TC_USAGE
+ }
+ for (ap = _nc_get_alias_table(TRUE); ap->from; ap++)
+ if (strcmp(ap->from, _nc_curr_token.tk_name) == 0) {
+ if (ap->to == (char *) 0) {
+ _nc_warning("%s (%s termcap extension) ignored",
+ ap->from, ap->source);
+ goto nexttok;
+ }
+
+ entry_ptr = _nc_find_entry(ap->to,
+ _nc_get_hash_table(TRUE));
+ if (entry_ptr && !silent)
+ _nc_warning("%s (%s termcap extension) aliased to %s",
+ ap->from, ap->source, ap->to);
+ break;
+ }
+ } else { /* if (_nc_syntax == SYN_TERMINFO) */
+ for (ap = _nc_get_alias_table(FALSE); ap->from; ap++)
+ if (strcmp(ap->from, _nc_curr_token.tk_name) == 0) {
+ if (ap->to == (char *) 0) {
+ _nc_warning("%s (%s terminfo extension) ignored",
+ ap->from, ap->source);
+ goto nexttok;
+ }
+
+ entry_ptr = _nc_find_entry(ap->to,
+ _nc_get_hash_table(FALSE));
+ if (entry_ptr && !silent)
+ _nc_warning("%s (%s terminfo extension) aliased to %s",
+ ap->from, ap->source, ap->to);
+ break;
+ }
+
+ if (entry_ptr == NOTFOUND) {
+ entry_ptr = lookup_fullname(_nc_curr_token.tk_name);
+ }
+ }
+ }
+#if NCURSES_XNAMES
+ /*
+ * If we have extended-names active, we will automatically
+ * define a name based on its context.
+ */
+ if (entry_ptr == NOTFOUND
+ && _nc_user_definable
+ && (entry_ptr = _nc_extend_names(entryp,
+ _nc_curr_token.tk_name,
+ token_type)) != 0) {
+ if (_nc_tracing >= DEBUG_LEVEL(1))
+ _nc_warning("extended capability '%s'", _nc_curr_token.tk_name);
+ }
+#endif /* NCURSES_XNAMES */
+
+ /* can't find this cap name, not even as an alias */
+ if (entry_ptr == NOTFOUND) {
+ if (!silent)
+ _nc_warning("unknown capability '%s'",
+ _nc_curr_token.tk_name);
+ continue;
+ }
+
+ /* deal with bad type/value combinations. */
+ if (token_type != CANCEL && entry_ptr->nte_type != token_type) {
+ /*
+ * Nasty special cases here handle situations in which type
+ * information can resolve name clashes. Normal lookup
+ * finds the last instance in the capability table of a
+ * given name, regardless of type. find_type_entry looks
+ * for a first matching instance with given type. So as
+ * long as all ambiguous names occur in pairs of distinct
+ * type, this will do the job.
+ */
+
+ /* tell max_attributes from arrow_key_map */
+ if (token_type == NUMBER
+ && !strcmp("ma", _nc_curr_token.tk_name)) {
+ entry_ptr = _nc_find_type_entry("ma", NUMBER,
+ _nc_get_table(_nc_syntax
+ != 0));
+
+ /* map terminfo's string MT to MT */
+ } else if (token_type == STRING
+ && !strcmp("MT", _nc_curr_token.tk_name)) {
+ entry_ptr = _nc_find_type_entry("MT", STRING,
+ _nc_get_table(_nc_syntax
+ != 0));
+
+ /* treat strings without following "=" as empty strings */
+ } else if (token_type == BOOLEAN
+ && entry_ptr->nte_type == STRING) {
+ token_type = STRING;
+ /* we couldn't recover; skip this token */
+ } else {
+ if (!silent) {
+ const char *type_name;
+ switch (entry_ptr->nte_type) {
+ case BOOLEAN:
+ type_name = "boolean";
+ break;
+ case STRING:
+ type_name = "string";
+ break;
+ case NUMBER:
+ type_name = "numeric";
+ break;
+ default:
+ type_name = "unknown";
+ break;
+ }
+ _nc_warning("wrong type used for %s capability '%s'",
+ type_name, _nc_curr_token.tk_name);
+ }
+ continue;
+ }
+ }
+
+ /* now we know that the type/value combination is OK */
+ switch (token_type) {
+ case CANCEL:
+ switch (entry_ptr->nte_type) {
+ case BOOLEAN:
+ entryp->tterm.Booleans[entry_ptr->nte_index] = CANCELLED_BOOLEAN;
+ break;
+
+ case NUMBER:
+ entryp->tterm.Numbers[entry_ptr->nte_index] = CANCELLED_NUMERIC;
+ break;
+
+ case STRING:
+ entryp->tterm.Strings[entry_ptr->nte_index] = CANCELLED_STRING;
+ break;
+ }
+ break;
+
+ case BOOLEAN:
+ entryp->tterm.Booleans[entry_ptr->nte_index] = TRUE;
+ break;
+
+ case NUMBER:
+ entryp->tterm.Numbers[entry_ptr->nte_index] =
+ _nc_curr_token.tk_valnumber;
+ break;
+
+ case STRING:
+ ptr = _nc_curr_token.tk_valstring;
+ if (_nc_syntax == SYN_TERMCAP)
+ ptr = _nc_captoinfo(_nc_curr_token.tk_name,
+ ptr,
+ parametrized[entry_ptr->nte_index]);
+ entryp->tterm.Strings[entry_ptr->nte_index] = _nc_save_str(ptr);
+ break;
+
+ default:
+ if (!silent)
+ _nc_warning("unknown token type");
+ _nc_panic_mode((_nc_syntax == SYN_TERMCAP) ? ':' : ',');
+ continue;
+ }
+ } /* end else cur_token.name != "use" */
+ nexttok:
+ continue; /* cannot have a label w/o statement */
+ } /* endwhile (not EOF and not NAMES) */
+
+ _nc_push_token(token_type);
+ _nc_set_type(_nc_first_name(entryp->tterm.term_names));
+
+ /*
+ * Try to deduce as much as possible from extension capabilities
+ * (this includes obsolete BSD capabilities). Sigh...it would be more
+ * space-efficient to call this after use resolution, but it has
+ * to be done before entry allocation is wrapped up.
+ */
+ if (!literal) {
+ if (_nc_syntax == SYN_TERMCAP) {
+ bool has_base_entry = FALSE;
+ int i;
+
+ /*
+ * Don't insert defaults if this is a `+' entry meant only
+ * for inclusion in other entries (not sure termcap ever
+ * had these, actually).
+ */
+ if (strchr(entryp->tterm.term_names, '+'))
+ has_base_entry = TRUE;
+ else
+ /*
+ * Otherwise, look for a base entry that will already
+ * have picked up defaults via translation.
+ */
+ for (i = 0; i < entryp->nuses; i++)
+ if (!strchr((char *) entryp->uses[i].name, '+'))
+ has_base_entry = TRUE;
+
+ postprocess_termcap(&entryp->tterm, has_base_entry);
+ } else
+ postprocess_terminfo(&entryp->tterm);
+ }
+ _nc_wrap_entry(entryp, FALSE);
+
+ return (OK);
+}
+
+NCURSES_EXPORT(int)
+_nc_capcmp(const char *s, const char *t)
+/* compare two string capabilities, stripping out padding */
+{
+ if (!s && !t)
+ return (0);
+ else if (!s || !t)
+ return (1);
+
+ for (;;) {
+ if (s[0] == '$' && s[1] == '<') {
+ for (s += 2;; s++)
+ if (!(isdigit(UChar(*s))
+ || *s == '.'
+ || *s == '*'
+ || *s == '/'
+ || *s == '>'))
+ break;
+ }
+
+ if (t[0] == '$' && t[1] == '<') {
+ for (t += 2;; t++)
+ if (!(isdigit(UChar(*t))
+ || *t == '.'
+ || *t == '*'
+ || *t == '/'
+ || *t == '>'))
+ break;
+ }
+
+ /* we've now pushed s and t past any padding they were pointing at */
+
+ if (*s == '\0' && *t == '\0')
+ return (0);
+
+ if (*s != *t)
+ return (*t - *s);
+
+ /* else *s == *t but one is not NUL, so continue */
+ s++, t++;
+ }
+}
+
+static void
+append_acs0(string_desc * dst, int code, int src)
+{
+ if (src != 0) {
+ char temp[3];
+ temp[0] = code;
+ temp[1] = src;
+ temp[2] = 0;
+ _nc_safe_strcat(dst, temp);
+ }
+}
+
+static void
+append_acs(string_desc * dst, int code, char *src)
+{
+ if (src != 0 && strlen(src) == 1) {
+ append_acs0(dst, code, *src);
+ }
+}
+
+/*
+ * The ko capability, if present, consists of a comma-separated capability
+ * list. For each capability, we may assume there is a keycap that sends the
+ * string which is the value of that capability.
+ */
+typedef struct {
+ const char *from;
+ const char *to;
+} assoc;
+static assoc const ko_xlate[] =
+{
+ {"al", "kil1"}, /* insert line key -> KEY_IL */
+ {"bt", "kcbt"}, /* back tab -> KEY_BTAB */
+ {"cd", "ked"}, /* clear-to-eos key -> KEY_EOL */
+ {"ce", "kel"}, /* clear-to-eol key -> KEY_EOS */
+ {"cl", "kclr"}, /* clear key -> KEY_CLEAR */
+ {"ct", "tbc"}, /* clear all tabs -> KEY_CATAB */
+ {"dc", "kdch1"}, /* delete char -> KEY_DC */
+ {"dl", "kdl1"}, /* delete line -> KEY_DL */
+ {"do", "kcud1"}, /* down key -> KEY_DOWN */
+ {"ei", "krmir"}, /* exit insert key -> KEY_EIC */
+ {"ho", "khome"}, /* home key -> KEY_HOME */
+ {"ic", "kich1"}, /* insert char key -> KEY_IC */
+ {"im", "kIC"}, /* insert-mode key -> KEY_SIC */
+ {"le", "kcub1"}, /* le key -> KEY_LEFT */
+ {"nd", "kcuf1"}, /* nd key -> KEY_RIGHT */
+ {"nl", "kent"}, /* new line key -> KEY_ENTER */
+ {"st", "khts"}, /* set-tab key -> KEY_STAB */
+ {"ta", CANCELLED_STRING},
+ {"up", "kcuu1"}, /* up-arrow key -> KEY_UP */
+ {(char *) 0, (char *) 0},
+};
+
+/*
+ * This routine fills in string caps that either had defaults under
+ * termcap or can be manufactured from obsolete termcap capabilities.
+ * It was lifted from Ross Ridge's mytinfo package.
+ */
+
+static const char C_CR[] = "\r";
+static const char C_LF[] = "\n";
+static const char C_BS[] = "\b";
+static const char C_HT[] = "\t";
+
+/*
+ * Note that WANTED and PRESENT are not simple inverses! If a capability
+ * has been explicitly cancelled, it's not considered WANTED.
+ */
+#define WANTED(s) ((s) == ABSENT_STRING)
+#define PRESENT(s) (((s) != ABSENT_STRING) && ((s) != CANCELLED_STRING))
+
+/*
+ * This bit of legerdemain turns all the terminfo variable names into
+ * references to locations in the arrays Booleans, Numbers, and Strings ---
+ * precisely what's needed.
+ */
+
+#undef CUR
+#define CUR tp->
+
+static void
+postprocess_termcap(TERMTYPE *tp, bool has_base)
+{
+ char buf[MAX_LINE * 2 + 2];
+ string_desc result;
+
+ /*
+ * TERMCAP DEFAULTS AND OBSOLETE-CAPABILITY TRANSLATIONS
+ *
+ * This first part of the code is the functional inverse of the
+ * fragment in capdefaults.c.
+ * ----------------------------------------------------------------------
+ */
+
+ /* if there was a tc entry, assume we picked up defaults via that */
+ if (!has_base) {
+ if (WANTED(init_3string) && termcap_init2)
+ init_3string = _nc_save_str(termcap_init2);
+
+ if (WANTED(reset_2string) && termcap_reset)
+ reset_2string = _nc_save_str(termcap_reset);
+
+ if (WANTED(carriage_return)) {
+ if (carriage_return_delay > 0) {
+ sprintf(buf, "%s$<%d>", C_CR, carriage_return_delay);
+ carriage_return = _nc_save_str(buf);
+ } else
+ carriage_return = _nc_save_str(C_CR);
+ }
+ if (WANTED(cursor_left)) {
+ if (backspace_delay > 0) {
+ sprintf(buf, "%s$<%d>", C_BS, backspace_delay);
+ cursor_left = _nc_save_str(buf);
+ } else if (backspaces_with_bs == 1)
+ cursor_left = _nc_save_str(C_BS);
+ else if (PRESENT(backspace_if_not_bs))
+ cursor_left = backspace_if_not_bs;
+ }
+ /* vi doesn't use "do", but it does seems to use nl (or '\n') instead */
+ if (WANTED(cursor_down)) {
+ if (PRESENT(linefeed_if_not_lf))
+ cursor_down = linefeed_if_not_lf;
+ else if (linefeed_is_newline != 1) {
+ if (new_line_delay > 0) {
+ sprintf(buf, "%s$<%d>", C_LF, new_line_delay);
+ cursor_down = _nc_save_str(buf);
+ } else
+ cursor_down = _nc_save_str(C_LF);
+ }
+ }
+ if (WANTED(scroll_forward) && crt_no_scrolling != 1) {
+ if (PRESENT(linefeed_if_not_lf))
+ cursor_down = linefeed_if_not_lf;
+ else if (linefeed_is_newline != 1) {
+ if (new_line_delay > 0) {
+ sprintf(buf, "%s$<%d>", C_LF, new_line_delay);
+ scroll_forward = _nc_save_str(buf);
+ } else
+ scroll_forward = _nc_save_str(C_LF);
+ }
+ }
+ if (WANTED(newline)) {
+ if (linefeed_is_newline == 1) {
+ if (new_line_delay > 0) {
+ sprintf(buf, "%s$<%d>", C_LF, new_line_delay);
+ newline = _nc_save_str(buf);
+ } else
+ newline = _nc_save_str(C_LF);
+ } else if (PRESENT(carriage_return) && PRESENT(scroll_forward)) {
+ _nc_str_init(&result, buf, sizeof(buf));
+ if (_nc_safe_strcat(&result, carriage_return)
+ && _nc_safe_strcat(&result, scroll_forward))
+ newline = _nc_save_str(buf);
+ } else if (PRESENT(carriage_return) && PRESENT(cursor_down)) {
+ _nc_str_init(&result, buf, sizeof(buf));
+ if (_nc_safe_strcat(&result, carriage_return)
+ && _nc_safe_strcat(&result, cursor_down))
+ newline = _nc_save_str(buf);
+ }
+ }
+ }
+
+ /*
+ * Inverse of capdefaults.c code ends here.
+ * ----------------------------------------------------------------------
+ *
+ * TERMCAP-TO TERMINFO MAPPINGS FOR SOURCE TRANSLATION
+ *
+ * These translations will *not* be inverted by tgetent().
+ */
+
+ if (!has_base) {
+ /*
+ * We wait until now to decide if we've got a working cr because even
+ * one that doesn't work can be used for newline. Unfortunately the
+ * space allocated for it is wasted.
+ */
+ if (return_does_clr_eol == 1 || no_correctly_working_cr == 1)
+ carriage_return = ABSENT_STRING;
+
+ /*
+ * Supposedly most termcap entries have ta now and '\t' is no longer a
+ * default, but it doesn't seem to be true...
+ */
+ if (WANTED(tab)) {
+ if (horizontal_tab_delay > 0) {
+ sprintf(buf, "%s$<%d>", C_HT, horizontal_tab_delay);
+ tab = _nc_save_str(buf);
+ } else
+ tab = _nc_save_str(C_HT);
+ }
+ if (init_tabs == ABSENT_NUMERIC && has_hardware_tabs == TRUE)
+ init_tabs = 8;
+
+ /*
+ * Assume we can beep with ^G unless we're given bl@.
+ */
+ if (WANTED(bell))
+ bell = _nc_save_str("\007");
+ }
+
+ /*
+ * Translate the old termcap :pt: capability to it#8 + ht=\t
+ */
+ if (has_hardware_tabs == TRUE) {
+ if (init_tabs != 8 && init_tabs != ABSENT_NUMERIC)
+ _nc_warning("hardware tabs with a width other than 8: %d", init_tabs);
+ else {
+ if (tab && _nc_capcmp(tab, C_HT))
+ _nc_warning("hardware tabs with a non-^I tab string %s",
+ _nc_visbuf(tab));
+ else {
+ if (WANTED(tab))
+ tab = _nc_save_str(C_HT);
+ init_tabs = 8;
+ }
+ }
+ }
+ /*
+ * Now translate the ko capability, if there is one. This
+ * isn't from mytinfo...
+ */
+ if (PRESENT(other_non_function_keys)) {
+ char *base = other_non_function_keys;
+ char *bp, *cp, *dp;
+ struct name_table_entry const *from_ptr;
+ struct name_table_entry const *to_ptr;
+ assoc const *ap;
+ char buf2[MAX_TERMINFO_LENGTH];
+ bool foundim;
+
+ /* we're going to use this for a special case later */
+ dp = strchr(other_non_function_keys, 'i');
+ foundim = (dp != 0) && (dp[1] == 'm');
+
+ /* look at each comma-separated capability in the ko string... */
+ for (base = other_non_function_keys;
+ (cp = strchr(base, ',')) != 0;
+ base = cp + 1) {
+ size_t len = cp - base;
+
+ for (ap = ko_xlate; ap->from; ap++)
+ if (len == strlen(ap->from)
+ && strncmp(ap->from, base, len) == 0)
+ break;
+ if (!ap->to) {
+ _nc_warning("unknown capability `%.*s' in ko string",
+ (int) len, base);
+ continue;
+ } else if (ap->to == CANCELLED_STRING) /* ignore it */
+ continue;
+
+ /* now we know we found a match in ko_table, so... */
+
+ from_ptr = _nc_find_entry(ap->from, _nc_get_hash_table(TRUE));
+ to_ptr = _nc_find_entry(ap->to, _nc_get_hash_table(FALSE));
+
+ if (!from_ptr || !to_ptr) /* should never happen! */
+ _nc_err_abort("ko translation table is invalid, I give up");
+
+ if (WANTED(tp->Strings[from_ptr->nte_index])) {
+ _nc_warning("no value for ko capability %s", ap->from);
+ continue;
+ }
+
+ if (tp->Strings[to_ptr->nte_index]) {
+ /* There's no point in warning about it if it's the same
+ * string; that's just an inefficiency.
+ */
+ if (strcmp(
+ tp->Strings[from_ptr->nte_index],
+ tp->Strings[to_ptr->nte_index]) != 0)
+ _nc_warning("%s (%s) already has an explicit value %s, ignoring ko",
+ ap->to, ap->from,
+ _nc_visbuf(tp->Strings[to_ptr->nte_index]));
+ continue;
+ }
+
+ /*
+ * The magic moment -- copy the mapped key string over,
+ * stripping out padding.
+ */
+ for (dp = buf2, bp = tp->Strings[from_ptr->nte_index]; *bp; bp++) {
+ if (bp[0] == '$' && bp[1] == '<') {
+ while (*bp && *bp != '>') {
+ ++bp;
+ }
+ } else
+ *dp++ = *bp;
+ }
+ *dp++ = '\0';
+
+ tp->Strings[to_ptr->nte_index] = _nc_save_str(buf2);
+ }
+
+ /*
+ * Note: ko=im and ko=ic both want to grab the `Insert'
+ * keycap. There's a kich1 but no ksmir, so the ic capability
+ * got mapped to kich1 and im to kIC to avoid a collision.
+ * If the description has im but not ic, hack kIC back to kich1.
+ */
+ if (foundim && WANTED(key_ic) && key_sic) {
+ key_ic = key_sic;
+ key_sic = ABSENT_STRING;
+ }
+ }
+
+ if (!has_base) {
+ if (!hard_copy) {
+ if (WANTED(key_backspace))
+ key_backspace = _nc_save_str(C_BS);
+ if (WANTED(key_left))
+ key_left = _nc_save_str(C_BS);
+ if (WANTED(key_down))
+ key_down = _nc_save_str(C_LF);
+ }
+ }
+
+ /*
+ * Translate XENIX forms characters.
+ */
+ if (PRESENT(acs_ulcorner) ||
+ PRESENT(acs_llcorner) ||
+ PRESENT(acs_urcorner) ||
+ PRESENT(acs_lrcorner) ||
+ PRESENT(acs_ltee) ||
+ PRESENT(acs_rtee) ||
+ PRESENT(acs_btee) ||
+ PRESENT(acs_ttee) ||
+ PRESENT(acs_hline) ||
+ PRESENT(acs_vline) ||
+ PRESENT(acs_plus)) {
+ char buf2[MAX_TERMCAP_LENGTH];
+
+ _nc_str_init(&result, buf2, sizeof(buf2));
+ _nc_safe_strcat(&result, acs_chars);
+
+ append_acs(&result, 'j', acs_lrcorner);
+ append_acs(&result, 'k', acs_urcorner);
+ append_acs(&result, 'l', acs_ulcorner);
+ append_acs(&result, 'm', acs_llcorner);
+ append_acs(&result, 'n', acs_plus);
+ append_acs(&result, 'q', acs_hline);
+ append_acs(&result, 't', acs_ltee);
+ append_acs(&result, 'u', acs_rtee);
+ append_acs(&result, 'v', acs_btee);
+ append_acs(&result, 'w', acs_ttee);
+ append_acs(&result, 'x', acs_vline);
+
+ if (buf2[0]) {
+ acs_chars = _nc_save_str(buf2);
+ _nc_warning("acsc string synthesized from XENIX capabilities");
+ }
+ } else if (acs_chars == 0
+ && enter_alt_charset_mode != 0
+ && exit_alt_charset_mode != 0) {
+ acs_chars = _nc_save_str(VT_ACSC);
+ }
+}
+
+static void
+postprocess_terminfo(TERMTYPE *tp)
+{
+ /*
+ * TERMINFO-TO-TERMINFO MAPPINGS FOR SOURCE TRANSLATION
+ * ----------------------------------------------------------------------
+ */
+
+ /*
+ * Translate AIX forms characters.
+ */
+ if (PRESENT(box_chars_1)) {
+ char buf2[MAX_TERMCAP_LENGTH];
+ string_desc result;
+
+ _nc_str_init(&result, buf2, sizeof(buf2));
+ _nc_safe_strcat(&result, acs_chars);
+
+ append_acs0(&result, 'l', box_chars_1[0]); /* ACS_ULCORNER */
+ append_acs0(&result, 'q', box_chars_1[1]); /* ACS_HLINE */
+ append_acs0(&result, 'k', box_chars_1[2]); /* ACS_URCORNER */
+ append_acs0(&result, 'x', box_chars_1[3]); /* ACS_VLINE */
+ append_acs0(&result, 'j', box_chars_1[4]); /* ACS_LRCORNER */
+ append_acs0(&result, 'm', box_chars_1[5]); /* ACS_LLCORNER */
+ append_acs0(&result, 'w', box_chars_1[6]); /* ACS_TTEE */
+ append_acs0(&result, 'u', box_chars_1[7]); /* ACS_RTEE */
+ append_acs0(&result, 'v', box_chars_1[8]); /* ACS_BTEE */
+ append_acs0(&result, 't', box_chars_1[9]); /* ACS_LTEE */
+ append_acs0(&result, 'n', box_chars_1[10]); /* ACS_PLUS */
+
+ if (buf2[0]) {
+ acs_chars = _nc_save_str(buf2);
+ _nc_warning("acsc string synthesized from AIX capabilities");
+ box_chars_1 = ABSENT_STRING;
+ }
+ }
+ /*
+ * ----------------------------------------------------------------------
+ */
+}
+
+/*
+ * Do a linear search through the terminfo tables to find a given full-name.
+ * We don't expect to do this often, so there's no hashing function.
+ *
+ * In effect, this scans through the 3 lists of full-names, and looks them
+ * up in _nc_info_table, which is organized so that the nte_index fields are
+ * sorted, but the nte_type fields are not necessarily grouped together.
+ */
+static struct name_table_entry const *
+lookup_fullname(const char *find)
+{
+ int state = -1;
+
+ for (;;) {
+ int count = 0;
+ NCURSES_CONST char *const *names;
+
+ switch (++state) {
+ case BOOLEAN:
+ names = boolfnames;
+ break;
+ case STRING:
+ names = strfnames;
+ break;
+ case NUMBER:
+ names = numfnames;
+ break;
+ default:
+ return NOTFOUND;
+ }
+
+ for (count = 0; names[count] != 0; count++) {
+ if (!strcmp(names[count], find)) {
+ struct name_table_entry const *entry_ptr = _nc_get_table(FALSE);
+ while (entry_ptr->nte_type != state
+ || entry_ptr->nte_index != count)
+ entry_ptr++;
+ return entry_ptr;
+ }
+ }
+ }
+}
+
+/* parse_entry.c ends here */
diff --git a/ncurses/tinfo/read_entry.c b/ncurses/tinfo/read_entry.c
new file mode 100644
index 000000000000..6a050ee78e66
--- /dev/null
+++ b/ncurses/tinfo/read_entry.c
@@ -0,0 +1,544 @@
+/****************************************************************************
+ * Copyright (c) 1998-2006,2007 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ ****************************************************************************/
+
+/*
+ * read_entry.c -- Routine for reading in a compiled terminfo file
+ */
+
+#include <curses.priv.h>
+#include <hashed_db.h>
+
+#include <tic.h>
+#include <term_entry.h>
+
+MODULE_ID("$Id: read_entry.c,v 1.100 2007/11/17 23:56:50 tom Exp $")
+
+#define TYPE_CALLOC(type,elts) typeCalloc(type, (unsigned)(elts))
+
+#if USE_DATABASE
+static void
+convert_shorts(char *buf, short *Numbers, int count)
+{
+ int i;
+ for (i = 0; i < count; i++) {
+ if (IS_NEG1(buf + 2 * i))
+ Numbers[i] = ABSENT_NUMERIC;
+ else if (IS_NEG2(buf + 2 * i))
+ Numbers[i] = CANCELLED_NUMERIC;
+ else
+ Numbers[i] = LOW_MSB(buf + 2 * i);
+ TR(TRACE_DATABASE, ("get Numbers[%d]=%d", i, Numbers[i]));
+ }
+}
+
+static void
+convert_strings(char *buf, char **Strings, int count, int size, char *table)
+{
+ int i;
+ char *p;
+
+ for (i = 0; i < count; i++) {
+ if (IS_NEG1(buf + 2 * i)) {
+ Strings[i] = ABSENT_STRING;
+ } else if (IS_NEG2(buf + 2 * i)) {
+ Strings[i] = CANCELLED_STRING;
+ } else if (LOW_MSB(buf + 2 * i) > size) {
+ Strings[i] = ABSENT_STRING;
+ } else {
+ Strings[i] = (LOW_MSB(buf + 2 * i) + table);
+ TR(TRACE_DATABASE, ("Strings[%d] = %s", i, _nc_visbuf(Strings[i])));
+ }
+
+ /* make sure all strings are NUL terminated */
+ if (VALID_STRING(Strings[i])) {
+ for (p = Strings[i]; p <= table + size; p++)
+ if (*p == '\0')
+ break;
+ /* if there is no NUL, ignore the string */
+ if (p > table + size)
+ Strings[i] = ABSENT_STRING;
+ }
+ }
+}
+
+static int
+fake_read(char *src, int *offset, int limit, char *dst, unsigned want)
+{
+ int have = (limit - *offset);
+
+ if (have > 0) {
+ if ((int) want > have)
+ want = have;
+ memcpy(dst, src + *offset, want);
+ *offset += want;
+ } else {
+ want = 0;
+ }
+ return (int) want;
+}
+
+#define Read(buf, count) fake_read(buffer, &offset, limit, buf, count)
+
+#define read_shorts(buf, count) \
+ (Read(buf, (unsigned) (count)*2) == (int) (count)*2)
+
+#define even_boundary(value) \
+ if ((value) % 2 != 0) Read(buf, 1)
+
+NCURSES_EXPORT(int)
+_nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit)
+/* return 1 if read, 0 if not found or garbled */
+{
+ int offset = 0;
+ int name_size, bool_count, num_count, str_count, str_size;
+ int i;
+ char buf[MAX_ENTRY_SIZE + 1];
+ char *string_table;
+ unsigned want, have;
+
+ TR(TRACE_DATABASE, ("READ termtype header @%d", offset));
+
+ memset(ptr, 0, sizeof(*ptr));
+
+ /* grab the header */
+ if (!read_shorts(buf, 6)
+ || !IS_TIC_MAGIC(buf)) {
+ return (TGETENT_NO);
+ }
+
+ name_size = LOW_MSB(buf + 2);
+ bool_count = LOW_MSB(buf + 4);
+ num_count = LOW_MSB(buf + 6);
+ str_count = LOW_MSB(buf + 8);
+ str_size = LOW_MSB(buf + 10);
+
+ TR(TRACE_DATABASE,
+ ("TERMTYPE name_size=%d, bool=%d/%d, num=%d/%d str=%d/%d(%d)",
+ name_size, bool_count, BOOLCOUNT, num_count, NUMCOUNT,
+ str_count, STRCOUNT, str_size));
+ if (name_size < 0
+ || bool_count < 0
+ || num_count < 0
+ || str_count < 0
+ || str_size < 0) {
+ return (TGETENT_NO);
+ }
+
+ want = str_size + name_size + 1;
+ if (str_size) {
+ /* try to allocate space for the string table */
+ if (str_count * 2 >= (int) sizeof(buf)
+ || (string_table = typeMalloc(char, want)) == 0) {
+ return (TGETENT_NO);
+ }
+ } else {
+ str_count = 0;
+ if ((string_table = typeMalloc(char, want)) == 0) {
+ return (TGETENT_NO);
+ }
+ }
+
+ /* grab the name (a null-terminated string) */
+ want = min(MAX_NAME_SIZE, (unsigned) name_size);
+ ptr->str_table = string_table;
+ ptr->term_names = string_table;
+ if ((have = Read(ptr->term_names, want)) != want) {
+ memset(ptr->term_names + have, 0, want - have);
+ }
+ ptr->term_names[want] = '\0';
+ string_table += (want + 1);
+
+ if (have > MAX_NAME_SIZE)
+ offset = (have - MAX_NAME_SIZE);
+
+ /* grab the booleans */
+ if ((ptr->Booleans = TYPE_CALLOC(NCURSES_SBOOL,
+ max(BOOLCOUNT, bool_count))) == 0
+ || Read(ptr->Booleans, (unsigned) bool_count) < bool_count) {
+ return (TGETENT_NO);
+ }
+
+ /*
+ * If booleans end on an odd byte, skip it. The machine they
+ * originally wrote terminfo on must have been a 16-bit
+ * word-oriented machine that would trap out if you tried a
+ * word access off a 2-byte boundary.
+ */
+ even_boundary(name_size + bool_count);
+
+ /* grab the numbers */
+ if ((ptr->Numbers = TYPE_CALLOC(short, max(NUMCOUNT, num_count))) == 0
+ || !read_shorts(buf, num_count)) {
+ return (TGETENT_NO);
+ }
+ convert_shorts(buf, ptr->Numbers, num_count);
+
+ if ((ptr->Strings = TYPE_CALLOC(char *, max(STRCOUNT, str_count))) == 0)
+ return (TGETENT_NO);
+
+ if (str_count) {
+ /* grab the string offsets */
+ if (!read_shorts(buf, str_count)) {
+ return (TGETENT_NO);
+ }
+ /* finally, grab the string table itself */
+ if (Read(string_table, (unsigned) str_size) != str_size)
+ return (TGETENT_NO);
+ convert_strings(buf, ptr->Strings, str_count, str_size, string_table);
+ }
+#if NCURSES_XNAMES
+
+ ptr->num_Booleans = BOOLCOUNT;
+ ptr->num_Numbers = NUMCOUNT;
+ ptr->num_Strings = STRCOUNT;
+
+ /*
+ * Read extended entries, if any, after the normal end of terminfo data.
+ */
+ even_boundary(str_size);
+ TR(TRACE_DATABASE, ("READ extended_header @%d", offset));
+ if (_nc_user_definable && read_shorts(buf, 5)) {
+ int ext_bool_count = LOW_MSB(buf + 0);
+ int ext_num_count = LOW_MSB(buf + 2);
+ int ext_str_count = LOW_MSB(buf + 4);
+ int ext_str_size = LOW_MSB(buf + 6);
+ int ext_str_limit = LOW_MSB(buf + 8);
+ unsigned need = (ext_bool_count + ext_num_count + ext_str_count);
+ int base = 0;
+
+ if (need >= sizeof(buf)
+ || ext_str_size >= (int) sizeof(buf)
+ || ext_str_limit >= (int) sizeof(buf)
+ || ext_bool_count < 0
+ || ext_num_count < 0
+ || ext_str_count < 0
+ || ext_str_size < 0
+ || ext_str_limit < 0)
+ return (TGETENT_NO);
+
+ ptr->num_Booleans = BOOLCOUNT + ext_bool_count;
+ ptr->num_Numbers = NUMCOUNT + ext_num_count;
+ ptr->num_Strings = STRCOUNT + ext_str_count;
+
+ ptr->Booleans = typeRealloc(NCURSES_SBOOL, ptr->num_Booleans, ptr->Booleans);
+ ptr->Numbers = typeRealloc(short, ptr->num_Numbers, ptr->Numbers);
+ ptr->Strings = typeRealloc(char *, ptr->num_Strings, ptr->Strings);
+
+ TR(TRACE_DATABASE, ("extended header is %d/%d/%d(%d:%d)",
+ ext_bool_count, ext_num_count, ext_str_count,
+ ext_str_size, ext_str_limit));
+
+ TR(TRACE_DATABASE, ("READ %d extended-booleans @%d",
+ ext_bool_count, offset));
+ if ((ptr->ext_Booleans = ext_bool_count) != 0) {
+ if (Read(ptr->Booleans + BOOLCOUNT, (unsigned)
+ ext_bool_count) != ext_bool_count)
+ return (TGETENT_NO);
+ }
+ even_boundary(ext_bool_count);
+
+ TR(TRACE_DATABASE, ("READ %d extended-numbers @%d",
+ ext_num_count, offset));
+ if ((ptr->ext_Numbers = ext_num_count) != 0) {
+ if (!read_shorts(buf, ext_num_count))
+ return (TGETENT_NO);
+ TR(TRACE_DATABASE, ("Before converting extended-numbers"));
+ convert_shorts(buf, ptr->Numbers + NUMCOUNT, ext_num_count);
+ }
+
+ TR(TRACE_DATABASE, ("READ extended-offsets @%d", offset));
+ if ((ext_str_count || need)
+ && !read_shorts(buf, ext_str_count + need))
+ return (TGETENT_NO);
+
+ TR(TRACE_DATABASE, ("READ %d bytes of extended-strings @%d",
+ ext_str_limit, offset));
+
+ if (ext_str_limit) {
+ if ((ptr->ext_str_table = typeMalloc(char, ext_str_limit)) == 0)
+ return (TGETENT_NO);
+ if (Read(ptr->ext_str_table, (unsigned) ext_str_limit) != ext_str_limit)
+ return (TGETENT_NO);
+ TR(TRACE_DATABASE, ("first extended-string is %s", _nc_visbuf(ptr->ext_str_table)));
+ }
+
+ if ((ptr->ext_Strings = ext_str_count) != 0) {
+ TR(TRACE_DATABASE,
+ ("Before computing extended-string capabilities str_count=%d, ext_str_count=%d",
+ str_count, ext_str_count));
+ convert_strings(buf, ptr->Strings + str_count, ext_str_count,
+ ext_str_limit, ptr->ext_str_table);
+ for (i = ext_str_count - 1; i >= 0; i--) {
+ TR(TRACE_DATABASE, ("MOVE from [%d:%d] %s",
+ i, i + str_count,
+ _nc_visbuf(ptr->Strings[i + str_count])));
+ ptr->Strings[i + STRCOUNT] = ptr->Strings[i + str_count];
+ if (VALID_STRING(ptr->Strings[i + STRCOUNT]))
+ base += (strlen(ptr->Strings[i + STRCOUNT]) + 1);
+ TR(TRACE_DATABASE, ("... to [%d] %s",
+ i + STRCOUNT,
+ _nc_visbuf(ptr->Strings[i + STRCOUNT])));
+ }
+ }
+
+ if (need) {
+ if ((ptr->ext_Names = TYPE_CALLOC(char *, need)) == 0)
+ return (TGETENT_NO);
+ TR(TRACE_DATABASE,
+ ("ext_NAMES starting @%d in extended_strings, first = %s",
+ base, _nc_visbuf(ptr->ext_str_table + base)));
+ convert_strings(buf + (2 * ext_str_count),
+ ptr->ext_Names,
+ (int) need,
+ ext_str_limit, ptr->ext_str_table + base);
+ }
+
+ T(("...done reading terminfo bool %d(%d) num %d(%d) str %d(%d)",
+ ptr->num_Booleans, ptr->ext_Booleans,
+ ptr->num_Numbers, ptr->ext_Numbers,
+ ptr->num_Strings, ptr->ext_Strings));
+
+ TR(TRACE_DATABASE, ("extend: num_Booleans:%d", ptr->num_Booleans));
+ } else
+#endif /* NCURSES_XNAMES */
+ {
+ T(("...done reading terminfo bool %d num %d str %d",
+ bool_count, num_count, str_count));
+#if NCURSES_XNAMES
+ TR(TRACE_DATABASE, ("normal: num_Booleans:%d", ptr->num_Booleans));
+#endif
+ }
+
+ for (i = bool_count; i < BOOLCOUNT; i++)
+ ptr->Booleans[i] = FALSE;
+ for (i = num_count; i < NUMCOUNT; i++)
+ ptr->Numbers[i] = ABSENT_NUMERIC;
+ for (i = str_count; i < STRCOUNT; i++)
+ ptr->Strings[i] = ABSENT_STRING;
+
+ return (TGETENT_YES);
+}
+
+/*
+ * int
+ * _nc_read_file_entry(filename, ptr)
+ *
+ * Read the compiled terminfo entry in the given file into the
+ * structure pointed to by ptr, allocating space for the string
+ * table.
+ */
+NCURSES_EXPORT(int)
+_nc_read_file_entry(const char *const filename, TERMTYPE *ptr)
+/* return 1 if read, 0 if not found or garbled */
+{
+ int code, fd = -1;
+ int limit;
+ char buffer[MAX_ENTRY_SIZE + 1];
+
+ if (_nc_access(filename, R_OK) < 0
+ || (fd = open(filename, O_RDONLY | O_BINARY)) < 0) {
+ T(("cannot open terminfo %s (errno=%d)", filename, errno));
+ code = TGETENT_NO;
+ } else {
+ if ((limit = read(fd, buffer, sizeof(buffer))) > 0) {
+
+ T(("read terminfo %s", filename));
+ if ((code = _nc_read_termtype(ptr, buffer, limit)) == TGETENT_NO) {
+ _nc_free_termtype(ptr);
+ }
+ } else {
+ code = TGETENT_NO;
+ }
+ close(fd);
+ }
+
+ return (code);
+}
+
+/*
+ * Build a terminfo pathname and try to read the data. Returns TGETENT_YES on
+ * success, TGETENT_NO on failure.
+ */
+static int
+_nc_read_tic_entry(char *filename,
+ unsigned limit,
+ const char *const path,
+ const char *name,
+ TERMTYPE *const tp)
+{
+ int result = TGETENT_NO;
+
+ /*
+ * If we are looking in a directory, assume the entry is a file under that,
+ * according to the normal rules.
+ *
+ * FIXME - add caseless-filename fixup.
+ */
+ if (_nc_is_dir_path(path)) {
+ unsigned need = 4 + strlen(path) + strlen(name);
+
+ if (need <= limit) {
+ (void) sprintf(filename, "%s/" LEAF_FMT "/%s", path, *name, name);
+ result = _nc_read_file_entry(filename, tp);
+ }
+ }
+#if USE_HASHED_DB
+ else {
+ static const char suffix[] = DBM_SUFFIX;
+ DB *capdbp;
+ unsigned lens = sizeof(suffix) - 1;
+ unsigned size = strlen(path);
+ unsigned need = lens + size;
+
+ if (need <= limit) {
+ if (size >= lens
+ && !strcmp(path + size - lens, suffix))
+ (void) strcpy(filename, path);
+ else
+ (void) sprintf(filename, "%s%s", path, suffix);
+
+ /*
+ * It would be nice to optimize the dbopen/close activity, as
+ * done in the cgetent implementation for tc= clauses. However,
+ * since we support multiple database locations, we cannot do
+ * that.
+ */
+ if ((capdbp = _nc_db_open(filename, FALSE)) != 0) {
+ DBT key, data;
+ int reccnt = 0;
+ char *save = strdup(name);
+
+ memset(&key, 0, sizeof(key));
+ key.data = save;
+ key.size = strlen(save);
+
+ /*
+ * This lookup could return termcap data, which we do not want.
+ * We are looking for compiled (binary) terminfo data.
+ *
+ * cgetent uses a two-level lookup. On the first it uses the
+ * given name to return a record containing only the aliases
+ * for an entry. On the second (using that list of aliases as
+ * a key), it returns the content of the terminal description.
+ * We expect second lookup to return data beginning with the
+ * same set of aliases.
+ *
+ * For compiled terminfo, the list of aliases in the second
+ * case will be null-terminated. A termcap entry will not be,
+ * and will run on into the description. So we can easily
+ * distinguish between the two (source/binary) by checking the
+ * lengths.
+ */
+ while (_nc_db_get(capdbp, &key, &data) == 0) {
+ int used = data.size - 1;
+ char *have = (char *) data.data;
+
+ if (*have++ == 0) {
+ if (data.size > key.size
+ && IS_TIC_MAGIC(have)) {
+ result = _nc_read_termtype(tp, have, used);
+ if (result == TGETENT_NO) {
+ _nc_free_termtype(tp);
+ }
+ }
+ break;
+ }
+
+ /*
+ * Just in case we have a corrupt database, do not waste
+ * time with it.
+ */
+ if (++reccnt >= 3)
+ break;
+
+ /*
+ * Prepare for the second level.
+ */
+ key.data = have;
+ key.size = used;
+ }
+
+ _nc_db_close(capdbp);
+ free(save);
+ }
+ }
+ }
+#endif
+ return result;
+}
+#endif /* USE_DATABASE */
+
+/*
+ * _nc_read_entry(char *name, char *filename, TERMTYPE *tp)
+ *
+ * Find and read the compiled entry for a given terminal type,
+ * if it exists. We take pains here to make sure no combination
+ * of environment variables and terminal type name can be used to
+ * overrun the file buffer.
+ */
+
+NCURSES_EXPORT(int)
+_nc_read_entry(const char *const name, char *const filename, TERMTYPE *const tp)
+{
+ int code = TGETENT_NO;
+
+ if (strlen(name) == 0
+ || strcmp(name, ".") == 0
+ || strcmp(name, "..") == 0
+ || _nc_pathlast(name) != 0
+ || strchr(name, NCURSES_PATHSEP) != 0) {
+ T(("illegal or missing entry name '%s'", name));
+ } else {
+#if USE_DATABASE
+ DBDIRS state = dbdTIC;
+ int offset = 0;
+ const char *path;
+
+ while ((path = _nc_next_db(&state, &offset)) != 0) {
+ code = _nc_read_tic_entry(filename, PATH_MAX, path, name, tp);
+ if (code == TGETENT_YES) {
+ _nc_last_db();
+ break;
+ }
+ }
+#endif
+#if USE_TERMCAP
+ if (code != TGETENT_YES) {
+ code = _nc_read_termcap_entry(name, tp);
+ sprintf(filename, "%.*s", PATH_MAX - 1, _nc_get_source());
+ }
+#endif
+ }
+ return code;
+}
diff --git a/ncurses/tinfo/read_termcap.c b/ncurses/tinfo/read_termcap.c
new file mode 100644
index 000000000000..d94d1a42466d
--- /dev/null
+++ b/ncurses/tinfo/read_termcap.c
@@ -0,0 +1,1174 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ ****************************************************************************/
+
+/*
+ * Termcap compatibility support
+ *
+ * If your OS integrator didn't install a terminfo database, you can call
+ * _nc_read_termcap_entry() to support reading and translating capabilities
+ * from the system termcap file. This is a kludge; it will bulk up and slow
+ * down every program that uses ncurses, and translated termcap entries cannot
+ * use full terminfo capabilities. Don't use it unless you absolutely have to;
+ * instead, get your system people to run tic(1) from root on the terminfo
+ * master included with ncurses to translate it into a terminfo database.
+ *
+ * If USE_GETCAP is enabled, we use what is effectively a copy of the 4.4BSD
+ * getcap code to fetch entries. There are disadvantages to this; mainly that
+ * getcap(3) does its own resolution, meaning that entries read in in this way
+ * can't reference the terminfo tree. The only thing it buys is faster startup
+ * time, getcap(3) is much faster than our tic parser.
+ */
+
+#include <curses.priv.h>
+
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <tic.h>
+#include <term_entry.h>
+
+MODULE_ID("$Id: read_termcap.c,v 1.71 2006/07/29 12:06:51 tom Exp $")
+
+#if !PURE_TERMINFO
+
+#define TC_SUCCESS 0
+#define TC_NOT_FOUND -1
+#define TC_SYS_ERR -2
+#define TC_REF_LOOP -3
+#define TC_UNRESOLVED -4 /* this is not returned by BSD cgetent */
+
+static NCURSES_CONST char *
+get_termpath(void)
+{
+ NCURSES_CONST char *result;
+
+ if (!use_terminfo_vars() || (result = getenv("TERMPATH")) == 0)
+ result = TERMPATH;
+ T(("TERMPATH is %s", result));
+ return result;
+}
+
+#if USE_GETCAP
+
+#if HAVE_BSD_CGETENT
+#define _nc_cgetcap cgetcap
+#define _nc_cgetent(buf, oline, db_array, name) cgetent(buf, db_array, name)
+#define _nc_cgetmatch cgetmatch
+#define _nc_cgetset cgetset
+#else
+static int _nc_cgetmatch(char *, const char *);
+static int _nc_getent(char **, unsigned *, int *, int, char **, int, const char
+ *, int, char *);
+static int _nc_nfcmp(const char *, char *);
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Casey Leedom of Lawrence Livermore National Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgment:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* static char sccsid[] = "@(#)getcap.c 8.3 (Berkeley) 3/25/94"; */
+
+#define BFRAG 1024
+#define BSIZE 1024
+#define MAX_RECURSION 32 /* maximum getent recursion */
+
+static size_t topreclen; /* toprec length */
+static char *toprec; /* Additional record specified by cgetset() */
+static int gottoprec; /* Flag indicating retrieval of toprecord */
+
+/*
+ * Cgetset() allows the addition of a user specified buffer to be added to the
+ * database array, in effect "pushing" the buffer on top of the virtual
+ * database. 0 is returned on success, -1 on failure.
+ */
+static int
+_nc_cgetset(const char *ent)
+{
+ if (ent == 0) {
+ FreeIfNeeded(toprec);
+ toprec = 0;
+ topreclen = 0;
+ return (0);
+ }
+ topreclen = strlen(ent);
+ if ((toprec = typeMalloc(char, topreclen + 1)) == 0) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ gottoprec = 0;
+ (void) strcpy(toprec, ent);
+ return (0);
+}
+
+/*
+ * Cgetcap searches the capability record buf for the capability cap with type
+ * `type'. A pointer to the value of cap is returned on success, 0 if the
+ * requested capability couldn't be found.
+ *
+ * Specifying a type of ':' means that nothing should follow cap (:cap:). In
+ * this case a pointer to the terminating ':' or NUL will be returned if cap is
+ * found.
+ *
+ * If (cap, '@') or (cap, terminator, '@') is found before (cap, terminator)
+ * return 0.
+ */
+static char *
+_nc_cgetcap(char *buf, const char *cap, int type)
+{
+ register const char *cp;
+ register char *bp;
+
+ bp = buf;
+ for (;;) {
+ /*
+ * Skip past the current capability field - it's either the
+ * name field if this is the first time through the loop, or
+ * the remainder of a field whose name failed to match cap.
+ */
+ for (;;) {
+ if (*bp == '\0')
+ return (0);
+ else if (*bp++ == ':')
+ break;
+ }
+
+ /*
+ * Try to match (cap, type) in buf.
+ */
+ for (cp = cap; *cp == *bp && *bp != '\0'; cp++, bp++)
+ continue;
+ if (*cp != '\0')
+ continue;
+ if (*bp == '@')
+ return (0);
+ if (type == ':') {
+ if (*bp != '\0' && *bp != ':')
+ continue;
+ return (bp);
+ }
+ if (*bp != type)
+ continue;
+ bp++;
+ return (*bp == '@' ? 0 : bp);
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * Cgetent extracts the capability record name from the NULL terminated file
+ * array db_array and returns a pointer to a malloc'd copy of it in buf. Buf
+ * must be retained through all subsequent calls to cgetcap, cgetnum, cgetflag,
+ * and cgetstr, but may then be freed.
+ *
+ * Returns:
+ *
+ * positive # on success (i.e., the index in db_array)
+ * TC_NOT_FOUND if the requested record couldn't be found
+ * TC_SYS_ERR if a system error was encountered (e.g.,couldn't open a file)
+ * TC_REF_LOOP if a potential reference loop is detected
+ * TC_UNRESOLVED if we had too many recurrences to resolve
+ */
+static int
+_nc_cgetent(char **buf, int *oline, char **db_array, const char *name)
+{
+ unsigned dummy;
+
+ return (_nc_getent(buf, &dummy, oline, 0, db_array, -1, name, 0, 0));
+}
+
+/*
+ * Getent implements the functions of cgetent. If fd is non-negative,
+ * *db_array has already been opened and fd is the open file descriptor. We
+ * do this to save time and avoid using up file descriptors for tc=
+ * recursions.
+ *
+ * Getent returns the same success/failure codes as cgetent. On success, a
+ * pointer to a malloc'd capability record with all tc= capabilities fully
+ * expanded and its length (not including trailing ASCII NUL) are left in
+ * *cap and *len.
+ *
+ * Basic algorithm:
+ * + Allocate memory incrementally as needed in chunks of size BFRAG
+ * for capability buffer.
+ * + Recurse for each tc=name and interpolate result. Stop when all
+ * names interpolated, a name can't be found, or depth exceeds
+ * MAX_RECURSION.
+ */
+#define DOALLOC(size) typeRealloc(char, size, record)
+static int
+_nc_getent(
+ char **cap, /* termcap-content */
+ unsigned *len, /* length, needed for recursion */
+ int *beginning, /* line-number at match */
+ int in_array, /* index in 'db_array[] */
+ char **db_array, /* list of files to search */
+ int fd,
+ const char *name,
+ int depth,
+ char *nfield)
+{
+ register char *r_end, *rp;
+ int myfd = FALSE;
+ char *record = 0;
+ int tc_not_resolved;
+ int current;
+ int lineno;
+
+ /*
+ * Return with ``loop detected'' error if we've recurred more than
+ * MAX_RECURSION times.
+ */
+ if (depth > MAX_RECURSION)
+ return (TC_REF_LOOP);
+
+ /*
+ * Check if we have a top record from cgetset().
+ */
+ if (depth == 0 && toprec != 0 && _nc_cgetmatch(toprec, name) == 0) {
+ if ((record = DOALLOC(topreclen + BFRAG)) == 0) {
+ errno = ENOMEM;
+ return (TC_SYS_ERR);
+ }
+ (void) strcpy(record, toprec);
+ rp = record + topreclen + 1;
+ r_end = rp + BFRAG;
+ current = in_array;
+ } else {
+ int foundit;
+
+ /*
+ * Allocate first chunk of memory.
+ */
+ if ((record = DOALLOC(BFRAG)) == 0) {
+ errno = ENOMEM;
+ return (TC_SYS_ERR);
+ }
+ rp = r_end = record + BFRAG;
+ foundit = FALSE;
+
+ /*
+ * Loop through database array until finding the record.
+ */
+ for (current = in_array; db_array[current] != 0; current++) {
+ int eof = FALSE;
+
+ /*
+ * Open database if not already open.
+ */
+ if (fd >= 0) {
+ (void) lseek(fd, (off_t) 0, SEEK_SET);
+ } else if ((_nc_access(db_array[current], R_OK) < 0)
+ || (fd = open(db_array[current], O_RDONLY, 0)) < 0) {
+ /* No error on unfound file. */
+ if (errno == ENOENT)
+ continue;
+ free(record);
+ return (TC_SYS_ERR);
+ } else {
+ myfd = TRUE;
+ }
+ lineno = 0;
+
+ /*
+ * Find the requested capability record ...
+ */
+ {
+ char buf[2048];
+ register char *b_end = buf;
+ register char *bp = buf;
+ register int c;
+
+ /*
+ * Loop invariants:
+ * There is always room for one more character in record.
+ * R_end always points just past end of record.
+ * Rp always points just past last character in record.
+ * B_end always points just past last character in buf.
+ * Bp always points at next character in buf.
+ */
+
+ for (;;) {
+ int first = lineno + 1;
+
+ /*
+ * Read in a line implementing (\, newline)
+ * line continuation.
+ */
+ rp = record;
+ for (;;) {
+ if (bp >= b_end) {
+ int n;
+
+ n = read(fd, buf, sizeof(buf));
+ if (n <= 0) {
+ if (myfd)
+ (void) close(fd);
+ if (n < 0) {
+ free(record);
+ return (TC_SYS_ERR);
+ }
+ fd = -1;
+ eof = TRUE;
+ break;
+ }
+ b_end = buf + n;
+ bp = buf;
+ }
+
+ c = *bp++;
+ if (c == '\n') {
+ lineno++;
+ if (rp == record || *(rp - 1) != '\\')
+ break;
+ }
+ *rp++ = c;
+
+ /*
+ * Enforce loop invariant: if no room
+ * left in record buffer, try to get
+ * some more.
+ */
+ if (rp >= r_end) {
+ unsigned pos;
+ size_t newsize;
+
+ pos = rp - record;
+ newsize = r_end - record + BFRAG;
+ record = DOALLOC(newsize);
+ if (record == 0) {
+ if (myfd)
+ (void) close(fd);
+ errno = ENOMEM;
+ return (TC_SYS_ERR);
+ }
+ r_end = record + newsize;
+ rp = record + pos;
+ }
+ }
+ /* loop invariant lets us do this */
+ *rp++ = '\0';
+
+ /*
+ * If encountered eof check next file.
+ */
+ if (eof)
+ break;
+
+ /*
+ * Toss blank lines and comments.
+ */
+ if (*record == '\0' || *record == '#')
+ continue;
+
+ /*
+ * See if this is the record we want ...
+ */
+ if (_nc_cgetmatch(record, name) == 0
+ && (nfield == 0
+ || !_nc_nfcmp(nfield, record))) {
+ foundit = TRUE;
+ *beginning = first;
+ break; /* found it! */
+ }
+ }
+ }
+ if (foundit)
+ break;
+ }
+
+ if (!foundit)
+ return (TC_NOT_FOUND);
+ }
+
+ /*
+ * Got the capability record, but now we have to expand all tc=name
+ * references in it ...
+ */
+ {
+ register char *newicap, *s;
+ register int newilen;
+ unsigned ilen;
+ int diff, iret, tclen, oline;
+ char *icap, *scan, *tc, *tcstart, *tcend;
+
+ /*
+ * Loop invariants:
+ * There is room for one more character in record.
+ * R_end points just past end of record.
+ * Rp points just past last character in record.
+ * Scan points at remainder of record that needs to be
+ * scanned for tc=name constructs.
+ */
+ scan = record;
+ tc_not_resolved = FALSE;
+ for (;;) {
+ if ((tc = _nc_cgetcap(scan, "tc", '=')) == 0)
+ break;
+
+ /*
+ * Find end of tc=name and stomp on the trailing `:'
+ * (if present) so we can use it to call ourselves.
+ */
+ s = tc;
+ while (*s != '\0') {
+ if (*s++ == ':') {
+ *(s - 1) = '\0';
+ break;
+ }
+ }
+ tcstart = tc - 3;
+ tclen = s - tcstart;
+ tcend = s;
+
+ iret = _nc_getent(&icap, &ilen, &oline, current, db_array, fd,
+ tc, depth + 1, 0);
+ newicap = icap; /* Put into a register. */
+ newilen = ilen;
+ if (iret != TC_SUCCESS) {
+ /* an error */
+ if (iret < TC_NOT_FOUND) {
+ if (myfd)
+ (void) close(fd);
+ free(record);
+ return (iret);
+ }
+ if (iret == TC_UNRESOLVED)
+ tc_not_resolved = TRUE;
+ /* couldn't resolve tc */
+ if (iret == TC_NOT_FOUND) {
+ *(s - 1) = ':';
+ scan = s - 1;
+ tc_not_resolved = TRUE;
+ continue;
+ }
+ }
+
+ /* not interested in name field of tc'ed record */
+ s = newicap;
+ while (*s != '\0' && *s++ != ':') ;
+ newilen -= s - newicap;
+ newicap = s;
+
+ /* make sure interpolated record is `:'-terminated */
+ s += newilen;
+ if (*(s - 1) != ':') {
+ *s = ':'; /* overwrite NUL with : */
+ newilen++;
+ }
+
+ /*
+ * Make sure there's enough room to insert the
+ * new record.
+ */
+ diff = newilen - tclen;
+ if (diff >= r_end - rp) {
+ unsigned pos, tcpos, tcposend;
+ size_t newsize;
+
+ pos = rp - record;
+ newsize = r_end - record + diff + BFRAG;
+ tcpos = tcstart - record;
+ tcposend = tcend - record;
+ record = DOALLOC(newsize);
+ if (record == 0) {
+ if (myfd)
+ (void) close(fd);
+ free(icap);
+ errno = ENOMEM;
+ return (TC_SYS_ERR);
+ }
+ r_end = record + newsize;
+ rp = record + pos;
+ tcstart = record + tcpos;
+ tcend = record + tcposend;
+ }
+
+ /*
+ * Insert tc'ed record into our record.
+ */
+ s = tcstart + newilen;
+ memmove(s, tcend, (size_t) (rp - tcend));
+ memmove(tcstart, newicap, (size_t) newilen);
+ rp += diff;
+ free(icap);
+
+ /*
+ * Start scan on `:' so next cgetcap works properly
+ * (cgetcap always skips first field).
+ */
+ scan = s - 1;
+ }
+ }
+
+ /*
+ * Close file (if we opened it), give back any extra memory, and
+ * return capability, length and success.
+ */
+ if (myfd)
+ (void) close(fd);
+ *len = rp - record - 1; /* don't count NUL */
+ if (r_end > rp) {
+ if ((record = DOALLOC((size_t) (rp - record))) == 0) {
+ errno = ENOMEM;
+ return (TC_SYS_ERR);
+ }
+ }
+
+ *cap = record;
+ if (tc_not_resolved)
+ return (TC_UNRESOLVED);
+ return (current);
+}
+
+/*
+ * Cgetmatch will return 0 if name is one of the names of the capability
+ * record buf, -1 if not.
+ */
+static int
+_nc_cgetmatch(char *buf, const char *name)
+{
+ register const char *np;
+ register char *bp;
+
+ /*
+ * Start search at beginning of record.
+ */
+ bp = buf;
+ for (;;) {
+ /*
+ * Try to match a record name.
+ */
+ np = name;
+ for (;;) {
+ if (*np == '\0') {
+ if (*bp == '|' || *bp == ':' || *bp == '\0')
+ return (0);
+ else
+ break;
+ } else if (*bp++ != *np++) {
+ break;
+ }
+ }
+
+ /*
+ * Match failed, skip to next name in record.
+ */
+ bp--; /* a '|' or ':' may have stopped the match */
+ for (;;) {
+ if (*bp == '\0' || *bp == ':')
+ return (-1); /* match failed totally */
+ else if (*bp++ == '|')
+ break; /* found next name */
+ }
+ }
+}
+
+/*
+ * Compare name field of record.
+ */
+static int
+_nc_nfcmp(const char *nf, char *rec)
+{
+ char *cp, tmp;
+ int ret;
+
+ for (cp = rec; *cp != ':'; cp++) ;
+
+ tmp = *(cp + 1);
+ *(cp + 1) = '\0';
+ ret = strcmp(nf, rec);
+ *(cp + 1) = tmp;
+
+ return (ret);
+}
+#endif /* HAVE_BSD_CGETENT */
+
+/*
+ * Since ncurses provides its own 'tgetent()', we cannot use the native one.
+ * So we reproduce the logic to get down to cgetent() -- or our cut-down
+ * version of that -- to circumvent the problem of configuring against the
+ * termcap library.
+ */
+#define USE_BSD_TGETENT 1
+
+#if USE_BSD_TGETENT
+/*
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgment:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* static char sccsid[] = "@(#)termcap.c 8.1 (Berkeley) 6/4/93" */
+
+#define PBUFSIZ 512 /* max length of filename path */
+#define PVECSIZ 32 /* max number of names in path */
+#define TBUFSIZ (2048*2)
+
+static char *tbuf;
+
+/*
+ * On entry, srcp points to a non ':' character which is the beginning of the
+ * token, if any. We'll try to return a string that doesn't end with a ':'.
+ */
+static char *
+get_tc_token(char **srcp, int *endp)
+{
+ int ch;
+ bool found = FALSE;
+ char *s, *base;
+ char *tok = 0;
+
+ *endp = TRUE;
+ for (s = base = *srcp; *s != '\0';) {
+ ch = *s++;
+ if (ch == '\\') {
+ if (*s == '\0') {
+ break;
+ } else if (*s++ == '\n') {
+ while (isspace(UChar(*s)))
+ s++;
+ } else {
+ found = TRUE;
+ }
+ } else if (ch == ':') {
+ if (found) {
+ tok = base;
+ s[-1] = '\0';
+ *srcp = s;
+ *endp = FALSE;
+ break;
+ }
+ base = s;
+ } else if (isgraph(UChar(ch))) {
+ found = TRUE;
+ }
+ }
+
+ /* malformed entry may end without a ':' */
+ if (tok == 0 && found) {
+ tok = base;
+ }
+
+ return tok;
+}
+
+static char *
+copy_tc_token(char *dst, const char *src, size_t len)
+{
+ int ch;
+
+ while ((ch = *src++) != '\0') {
+ if (ch == '\\' && *src == '\n') {
+ while (isspace(UChar(*src)))
+ src++;
+ continue;
+ }
+ if (--len == 0) {
+ dst = 0;
+ break;
+ }
+ *dst++ = ch;
+ }
+ return dst;
+}
+
+/*
+ * Get an entry for terminal name in buffer bp from the termcap file.
+ */
+static int
+_nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name)
+{
+ static char *the_source;
+
+ register char *p;
+ register char *cp;
+ char *dummy = NULL;
+ char **fname;
+ char *home;
+ int i;
+ char pathbuf[PBUFSIZ]; /* holds raw path of filenames */
+ char *pathvec[PVECSIZ]; /* to point to names in pathbuf */
+ char **pvec; /* holds usable tail of path vector */
+ NCURSES_CONST char *termpath;
+ string_desc desc;
+
+ fname = pathvec;
+ pvec = pathvec;
+ tbuf = bp;
+ p = pathbuf;
+ cp = use_terminfo_vars()? getenv("TERMCAP") : NULL;
+
+ /*
+ * TERMCAP can have one of two things in it. It can be the name of a file
+ * to use instead of /etc/termcap. In this case it better start with a
+ * "/". Or it can be an entry to use so we don't have to read the file.
+ * In this case it has to already have the newlines crunched out. If
+ * TERMCAP does not hold a file name then a path of names is searched
+ * instead. The path is found in the TERMPATH variable, or becomes
+ * "$HOME/.termcap /etc/termcap" if no TERMPATH exists.
+ */
+ _nc_str_init(&desc, pathbuf, sizeof(pathbuf));
+ if (cp == NULL) {
+ _nc_safe_strcpy(&desc, get_termpath());
+ } else if (!_nc_is_abs_path(cp)) { /* TERMCAP holds an entry */
+ if ((termpath = get_termpath()) != 0) {
+ _nc_safe_strcat(&desc, termpath);
+ } else {
+ char temp[PBUFSIZ];
+ temp[0] = 0;
+ if ((home = getenv("HOME")) != 0 && *home != '\0'
+ && strchr(home, ' ') == 0
+ && strlen(home) < sizeof(temp) - 10) { /* setup path */
+ sprintf(temp, "%s/", home); /* $HOME first */
+ }
+ /* if no $HOME look in current directory */
+ strcat(temp, ".termcap");
+ _nc_safe_strcat(&desc, temp);
+ _nc_safe_strcat(&desc, " ");
+ _nc_safe_strcat(&desc, get_termpath());
+ }
+ } else { /* user-defined name in TERMCAP */
+ _nc_safe_strcat(&desc, cp); /* still can be tokenized */
+ }
+
+ *fname++ = pathbuf; /* tokenize path into vector of names */
+ while (*++p) {
+ if (*p == ' ' || *p == NCURSES_PATHSEP) {
+ *p = '\0';
+ while (*++p)
+ if (*p != ' ' && *p != NCURSES_PATHSEP)
+ break;
+ if (*p == '\0')
+ break;
+ *fname++ = p;
+ if (fname >= pathvec + PVECSIZ) {
+ fname--;
+ break;
+ }
+ }
+ }
+ *fname = 0; /* mark end of vector */
+ if (_nc_is_abs_path(cp)) {
+ if (_nc_cgetset(cp) < 0) {
+ return (TC_SYS_ERR);
+ }
+ }
+
+ i = _nc_cgetent(&dummy, lineno, pathvec, name);
+
+ /* ncurses' termcap-parsing routines cannot handle multiple adjacent
+ * empty fields, and mistakenly use the last valid cap entry instead of
+ * the first (breaks tc= includes)
+ */
+ if (i >= 0) {
+ char *pd, *ps, *tok;
+ int endflag = FALSE;
+ char *list[1023];
+ size_t n, count = 0;
+
+ pd = bp;
+ ps = dummy;
+ while (!endflag && (tok = get_tc_token(&ps, &endflag)) != 0) {
+ bool ignore = FALSE;
+
+ for (n = 1; n < count; n++) {
+ char *s = list[n];
+ if (s[0] == tok[0]
+ && s[1] == tok[1]) {
+ ignore = TRUE;
+ break;
+ }
+ }
+ if (ignore != TRUE) {
+ list[count++] = tok;
+ pd = copy_tc_token(pd, tok, TBUFSIZ - (2 + pd - bp));
+ if (pd == 0) {
+ i = -1;
+ break;
+ }
+ *pd++ = ':';
+ *pd = '\0';
+ }
+ }
+ }
+
+ FreeIfNeeded(dummy);
+ FreeIfNeeded(the_source);
+ the_source = 0;
+
+ /* This is not related to the BSD cgetent(), but to fake up a suitable
+ * filename for ncurses' error reporting. (If we are not using BSD
+ * cgetent, then it is the actual filename).
+ */
+ if (i >= 0) {
+#if HAVE_BSD_CGETENT
+ char temp[PATH_MAX];
+
+ _nc_str_init(&desc, temp, sizeof(temp));
+ _nc_safe_strcpy(&desc, pathvec[i]);
+ _nc_safe_strcat(&desc, ".db");
+ if (_nc_access(temp, R_OK) == 0) {
+ _nc_safe_strcpy(&desc, pathvec[i]);
+ }
+ if ((the_source = strdup(temp)) != 0)
+ *sourcename = the_source;
+#else
+ if ((the_source = strdup(pathvec[i])) != 0)
+ *sourcename = the_source;
+#endif
+ }
+
+ return (i);
+}
+#endif /* USE_BSD_TGETENT */
+#endif /* USE_GETCAP */
+
+#define MAXPATHS 32
+
+/*
+ * Add a filename to the list in 'termpaths[]', checking that we really have
+ * a right to open the file.
+ */
+#if !USE_GETCAP
+static int
+add_tc(char *termpaths[], char *path, int count)
+{
+ char *save = strchr(path, NCURSES_PATHSEP);
+ if (save != 0)
+ *save = '\0';
+ if (count < MAXPATHS
+ && _nc_access(path, R_OK) == 0) {
+ termpaths[count++] = path;
+ T(("Adding termpath %s", path));
+ }
+ termpaths[count] = 0;
+ if (save != 0)
+ *save = NCURSES_PATHSEP;
+ return count;
+}
+#define ADD_TC(path, count) filecount = add_tc(termpaths, path, count)
+#endif /* !USE_GETCAP */
+
+NCURSES_EXPORT(int)
+_nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp)
+{
+ int found = TGETENT_NO;
+ ENTRY *ep;
+#if USE_GETCAP_CACHE
+ char cwd_buf[PATH_MAX];
+#endif
+#if USE_GETCAP
+ char *p, tc[TBUFSIZ];
+ int status;
+ static char *source;
+ static int lineno;
+
+ T(("read termcap entry for %s", tn));
+
+ if (strlen(tn) == 0
+ || strcmp(tn, ".") == 0
+ || strcmp(tn, "..") == 0
+ || _nc_pathlast(tn) != 0) {
+ T(("illegal or missing entry name '%s'", tn));
+ return TGETENT_NO;
+ }
+
+ if (use_terminfo_vars() && (p = getenv("TERMCAP")) != 0
+ && !_nc_is_abs_path(p) && _nc_name_match(p, tn, "|:")) {
+ /* TERMCAP holds a termcap entry */
+ strncpy(tc, p, sizeof(tc) - 1);
+ tc[sizeof(tc) - 1] = '\0';
+ _nc_set_source("TERMCAP");
+ } else {
+ /* we're using getcap(3) */
+ if ((status = _nc_tgetent(tc, &source, &lineno, tn)) < 0)
+ return (status == TC_NOT_FOUND ? TGETENT_NO : TGETENT_ERR);
+
+ _nc_curr_line = lineno;
+ _nc_set_source(source);
+ }
+ _nc_read_entry_source((FILE *) 0, tc, FALSE, FALSE, NULLHOOK);
+#else
+ /*
+ * Here is what the 4.4BSD termcap(3) page prescribes:
+ *
+ * It will look in the environment for a TERMCAP variable. If found, and
+ * the value does not begin with a slash, and the terminal type name is the
+ * same as the environment string TERM, the TERMCAP string is used instead
+ * of reading a termcap file. If it does begin with a slash, the string is
+ * used as a path name of the termcap file to search. If TERMCAP does not
+ * begin with a slash and name is different from TERM, tgetent() searches
+ * the files $HOME/.termcap and /usr/share/misc/termcap, in that order,
+ * unless the environment variable TERMPATH exists, in which case it
+ * specifies a list of file pathnames (separated by spaces or colons) to be
+ * searched instead.
+ *
+ * It goes on to state:
+ *
+ * Whenever multiple files are searched and a tc field occurs in the
+ * requested entry, the entry it names must be found in the same file or
+ * one of the succeeding files.
+ *
+ * However, this restriction is relaxed in ncurses; tc references to
+ * previous files are permitted.
+ *
+ * This routine returns 1 if an entry is found, 0 if not found, and -1 if
+ * the database is not accessible.
+ */
+ FILE *fp;
+ char *tc, *termpaths[MAXPATHS];
+ int filecount = 0;
+ int j, k;
+ bool use_buffer = FALSE;
+ bool normal = TRUE;
+ char tc_buf[1024];
+ char pathbuf[PATH_MAX];
+ char *copied = 0;
+ char *cp;
+ struct stat test_stat[MAXPATHS];
+
+ termpaths[filecount] = 0;
+ if (use_terminfo_vars() && (tc = getenv("TERMCAP")) != 0) {
+ if (_nc_is_abs_path(tc)) { /* interpret as a filename */
+ ADD_TC(tc, 0);
+ normal = FALSE;
+ } else if (_nc_name_match(tc, tn, "|:")) { /* treat as a capability file */
+ use_buffer = TRUE;
+ (void) sprintf(tc_buf, "%.*s\n", (int) sizeof(tc_buf) - 2, tc);
+ normal = FALSE;
+ }
+ }
+
+ if (normal) { /* normal case */
+ char envhome[PATH_MAX], *h;
+
+ copied = strdup(get_termpath());
+ for (cp = copied; *cp; cp++) {
+ if (*cp == NCURSES_PATHSEP)
+ *cp = '\0';
+ else if (cp == copied || cp[-1] == '\0') {
+ ADD_TC(cp, filecount);
+ }
+ }
+
+#define PRIVATE_CAP "%s/.termcap"
+
+ if (use_terminfo_vars() && (h = getenv("HOME")) != NULL && *h != '\0'
+ && (strlen(h) + sizeof(PRIVATE_CAP)) < PATH_MAX) {
+ /* user's .termcap, if any, should override it */
+ (void) strcpy(envhome, h);
+ (void) sprintf(pathbuf, PRIVATE_CAP, envhome);
+ ADD_TC(pathbuf, filecount);
+ }
+ }
+
+ /*
+ * Probably /etc/termcap is a symlink to /usr/share/misc/termcap.
+ * Avoid reading the same file twice.
+ */
+#if HAVE_LINK
+ for (j = 0; j < filecount; j++) {
+ bool omit = FALSE;
+ if (stat(termpaths[j], &test_stat[j]) != 0
+ || (test_stat[j].st_mode & S_IFMT) != S_IFREG) {
+ omit = TRUE;
+ } else {
+ for (k = 0; k < j; k++) {
+ if (test_stat[k].st_dev == test_stat[j].st_dev
+ && test_stat[k].st_ino == test_stat[j].st_ino) {
+ omit = TRUE;
+ break;
+ }
+ }
+ }
+ if (omit) {
+ T(("Path %s is a duplicate", termpaths[j]));
+ for (k = j + 1; k < filecount; k++) {
+ termpaths[k - 1] = termpaths[k];
+ test_stat[k - 1] = test_stat[k];
+ }
+ --filecount;
+ --j;
+ }
+ }
+#endif
+
+ /* parse the sources */
+ if (use_buffer) {
+ _nc_set_source("TERMCAP");
+
+ /*
+ * We don't suppress warning messages here. The presumption is
+ * that since it's just a single entry, they won't be a pain.
+ */
+ _nc_read_entry_source((FILE *) 0, tc_buf, FALSE, FALSE, NULLHOOK);
+ } else {
+ int i;
+
+ for (i = 0; i < filecount; i++) {
+
+ T(("Looking for %s in %s", tn, termpaths[i]));
+ if (_nc_access(termpaths[i], R_OK) == 0
+ && (fp = fopen(termpaths[i], "r")) != (FILE *) 0) {
+ _nc_set_source(termpaths[i]);
+
+ /*
+ * Suppress warning messages. Otherwise you get 400 lines of
+ * crap from archaic termcap files as ncurses complains about
+ * all the obsolete capabilities.
+ */
+ _nc_read_entry_source(fp, (char *) 0, FALSE, TRUE, NULLHOOK);
+
+ (void) fclose(fp);
+ }
+ }
+ }
+ if (copied != 0)
+ free(copied);
+#endif /* USE_GETCAP */
+
+ if (_nc_head == 0)
+ return (TGETENT_ERR);
+
+ /* resolve all use references */
+ _nc_resolve_uses2(TRUE, FALSE);
+
+ /* find a terminal matching tn, if we can */
+#if USE_GETCAP_CACHE
+ if (getcwd(cwd_buf, sizeof(cwd_buf)) != 0) {
+ _nc_set_writedir((char *) 0); /* note: this does a chdir */
+#endif
+ for_entry_list(ep) {
+ if (_nc_name_match(ep->tterm.term_names, tn, "|:")) {
+ /*
+ * Make a local copy of the terminal capabilities, delinked
+ * from the list.
+ */
+ *tp = ep->tterm;
+ _nc_delink_entry(_nc_head, &(ep->tterm));
+ free(ep);
+
+ /*
+ * OK, now try to write the type to user's terminfo directory.
+ * Next time he loads this, it will come through terminfo.
+ *
+ * Advantage: Second and subsequent fetches of this entry will
+ * be very fast.
+ *
+ * Disadvantage: After the first time a termcap type is loaded
+ * by its user, editing it in the /etc/termcap file, or in
+ * TERMCAP, or in a local ~/.termcap, will be ineffective
+ * unless the terminfo entry is explicitly removed.
+ */
+#if USE_GETCAP_CACHE
+ (void) _nc_write_entry(tp);
+#endif
+ found = TGETENT_YES;
+ break;
+ }
+ }
+#if USE_GETCAP_CACHE
+ chdir(cwd_buf);
+ }
+#endif
+
+ return (found);
+}
+#else
+extern
+NCURSES_EXPORT(void)
+_nc_read_termcap(void);
+NCURSES_EXPORT(void)
+_nc_read_termcap(void)
+{
+}
+#endif /* PURE_TERMINFO */
diff --git a/ncurses/tinfo/setbuf.c b/ncurses/tinfo/setbuf.c
new file mode 100644
index 000000000000..ba910e8983a4
--- /dev/null
+++ b/ncurses/tinfo/setbuf.c
@@ -0,0 +1,150 @@
+/****************************************************************************
+ * Copyright (c) 1998-2003,2007 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ ****************************************************************************/
+
+/*
+** setbuf.c
+**
+** Support for set_term(), reset_shell_mode(), reset_prog_mode().
+**
+*/
+
+#include <curses.priv.h>
+
+MODULE_ID("$Id: setbuf.c,v 1.13 2007/05/12 19:04:02 tom Exp $")
+
+/*
+ * If the output file descriptor is connected to a tty (the typical case) it
+ * will probably be line-buffered. Keith Bostic pointed out that we don't want
+ * this; it hoses people running over networks by forcing out a bunch of small
+ * packets instead of one big one, so screen updates on ptys look jerky.
+ * Restore block buffering to prevent this minor lossage.
+ *
+ * The buffer size is a compromise. Ideally we'd like a buffer that can hold
+ * the maximum possible update size (the whole screen plus cup commands to
+ * change lines as it's painted). On a 66-line xterm this can become
+ * excessive. So we min it with the amount of data we think we can get through
+ * two Ethernet packets (maximum packet size - 100 for TCP/IP overhead).
+ *
+ * Why two ethernet packets? It used to be one, on the theory that said
+ * packets define the maximum size of atomic update. But that's less than the
+ * 2000 chars on a 25 x 80 screen, and we don't want local updates to flicker
+ * either. Two packet lengths will handle up to a 35 x 80 screen.
+ *
+ * The magic '6' is the estimated length of the end-of-line cup sequence to go
+ * to the next line. It's generous. We used to mess with the buffering in
+ * init_mvcur() after cost computation, but that lost the sequences emitted by
+ * init_acs() in setupscreen().
+ *
+ * "The setvbuf function may be used only after the stream pointed to by stream
+ * has been associated with an open file and before any other operation is
+ * performed on the stream." (ISO 7.9.5.6.)
+ *
+ * Grrrr...
+ *
+ * On a lighter note, many implementations do in fact allow an application to
+ * reset the buffering after it has been written to. We try to do this because
+ * otherwise we leave stdout in buffered mode after endwin() is called. (This
+ * also happens with SVr4 curses).
+ *
+ * There are pros/cons:
+ *
+ * con:
+ * There is no guarantee that we can reestablish buffering once we've
+ * dropped it.
+ *
+ * We _may_ lose data if the implementation does not coordinate this with
+ * fflush.
+ *
+ * pro:
+ * An implementation is more likely to refuse to change the buffering than
+ * to do it in one of the ways mentioned above.
+ *
+ * The alternative is to have the application try to change buffering
+ * itself, which is certainly no improvement.
+ *
+ * Just in case it does not work well on a particular system, the calls to
+ * change buffering are all via the macro NC_BUFFERED. Some implementations
+ * do indeed get confused by changing setbuf on/off, and will overrun the
+ * buffer. So we disable this by default (there may yet be a workaround).
+ */
+NCURSES_EXPORT(void)
+_nc_set_buffer(FILE *ofp, bool buffered)
+{
+ /* optional optimization hack -- do before any output to ofp */
+#if HAVE_SETVBUF || HAVE_SETBUFFER
+ if (SP->_buffered != buffered) {
+ unsigned buf_len;
+ char *buf_ptr;
+
+ if (getenv("NCURSES_NO_SETBUF") != 0)
+ return;
+
+ fflush(ofp);
+#ifdef __DJGPP__
+ setmode(ofp, O_BINARY);
+#endif
+ if (buffered != 0) {
+ buf_len = min(LINES * (COLS + 6), 2800);
+ if ((buf_ptr = SP->_setbuf) == 0) {
+ if ((buf_ptr = typeMalloc(char, buf_len)) == NULL)
+ return;
+ SP->_setbuf = buf_ptr;
+ /* Don't try to free this! */
+ }
+#if !USE_SETBUF_0
+ else
+ return;
+#endif
+ } else {
+#if !USE_SETBUF_0
+ return;
+#else
+ buf_len = 0;
+ buf_ptr = 0;
+#endif
+ }
+
+#if HAVE_SETVBUF
+#ifdef SETVBUF_REVERSED /* pre-svr3? */
+ (void) setvbuf(ofp, buf_ptr, buf_len, buf_len ? _IOFBF : _IOLBF);
+#else
+ (void) setvbuf(ofp, buf_ptr, buf_len ? _IOFBF : _IOLBF, buf_len);
+#endif
+#elif HAVE_SETBUFFER
+ (void) setbuffer(ofp, buf_ptr, (int) buf_len);
+#endif
+
+ SP->_buffered = buffered;
+ }
+#endif /* HAVE_SETVBUF || HAVE_SETBUFFER */
+}
diff --git a/ncurses/tinfo/strings.c b/ncurses/tinfo/strings.c
new file mode 100644
index 000000000000..78cd2ef4f5f5
--- /dev/null
+++ b/ncurses/tinfo/strings.c
@@ -0,0 +1,142 @@
+/****************************************************************************
+ * Copyright (c) 2000-2003,2007 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 *
+ ****************************************************************************/
+
+/*
+** lib_mvcur.c
+**/
+
+#include <curses.priv.h>
+
+MODULE_ID("$Id: strings.c,v 1.6 2007/08/11 17:12:17 tom Exp $")
+
+/****************************************************************************
+ * Useful string functions (especially for mvcur)
+ ****************************************************************************/
+
+#if !HAVE_STRSTR
+NCURSES_EXPORT(char *)
+_nc_strstr(const char *haystack, const char *needle)
+{
+ size_t len1 = strlen(haystack);
+ size_t len2 = strlen(needle);
+ char *result = 0;
+
+ while ((len1 != 0) && (len1-- >= len2)) {
+ if (!strncmp(haystack, needle, len2)) {
+ result = (char *) haystack;
+ break;
+ }
+ haystack++;
+ }
+ return result;
+}
+#endif
+
+/*
+ * Initialize the descriptor so we can append to it. Note that 'src' may
+ * be a null pointer (see _nc_str_null), so the corresponding strcat and
+ * strcpy calls have to allow for this.
+ */
+NCURSES_EXPORT(string_desc *)
+_nc_str_init(string_desc * dst, char *src, size_t len)
+{
+ if (dst != 0) {
+ dst->s_head = src;
+ dst->s_tail = src;
+ dst->s_size = len - 1;
+ dst->s_init = dst->s_size;
+ if (src != 0)
+ *src = 0;
+ }
+ return dst;
+}
+
+/*
+ * Initialize the descriptor for only tracking the amount of memory used.
+ */
+NCURSES_EXPORT(string_desc *)
+_nc_str_null(string_desc * dst, size_t len)
+{
+ return _nc_str_init(dst, 0, len);
+}
+
+/*
+ * Copy a descriptor
+ */
+NCURSES_EXPORT(string_desc *)
+_nc_str_copy(string_desc * dst, string_desc * src)
+{
+ *dst = *src;
+ return dst;
+}
+
+/*
+ * Replaces strcat into a fixed buffer, returning false on failure.
+ */
+NCURSES_EXPORT(bool)
+_nc_safe_strcat(string_desc * dst, const char *src)
+{
+ if (src != 0) {
+ size_t len = strlen(src);
+
+ if (len < dst->s_size) {
+ if (dst->s_tail != 0) {
+ strcpy(dst->s_tail, src);
+ dst->s_tail += len;
+ }
+ dst->s_size -= len;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*
+ * Replaces strcpy into a fixed buffer, returning false on failure.
+ */
+NCURSES_EXPORT(bool)
+_nc_safe_strcpy(string_desc * dst, const char *src)
+{
+ if (src != 0) {
+ size_t len = strlen(src);
+
+ if (len < dst->s_size) {
+ if (dst->s_head != 0) {
+ strcpy(dst->s_head, src);
+ dst->s_tail = dst->s_head + len;
+ }
+ dst->s_size = dst->s_init - len;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
diff --git a/ncurses/tinfo/trim_sgr0.c b/ncurses/tinfo/trim_sgr0.c
new file mode 100644
index 000000000000..80c8f77fbebe
--- /dev/null
+++ b/ncurses/tinfo/trim_sgr0.c
@@ -0,0 +1,326 @@
+/****************************************************************************
+ * Copyright (c) 2005-2006,2007 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 Dickey *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+
+#include <ctype.h>
+
+#include <tic.h>
+#include <term_entry.h>
+
+MODULE_ID("$Id: trim_sgr0.c,v 1.8 2007/04/07 17:14:11 tom Exp $")
+
+#undef CUR
+#define CUR tp->
+
+#define CSI 233
+#define ESC 033 /* ^[ */
+#define L_BRACK '['
+
+static char *
+set_attribute_9(TERMTYPE *tp, int flag)
+{
+ const char *result;
+
+ if ((result = tparm(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, flag)) == 0)
+ result = "";
+ return strdup(result);
+}
+
+static int
+is_csi(const char *s)
+{
+ if (UChar(s[0]) == CSI)
+ return 1;
+ else if (s[0] == ESC && s[1] == L_BRACK)
+ return 2;
+ return 0;
+}
+
+static char *
+skip_zero(char *s)
+{
+ if (s[0] == '0') {
+ if (s[1] == ';')
+ s += 2;
+ else if (isalpha(UChar(s[1])))
+ s += 1;
+ }
+ return s;
+}
+
+static const char *
+skip_delay(const char *s)
+{
+ if (s[0] == '$' && s[1] == '<') {
+ s += 2;
+ while (isdigit(UChar(*s)) || *s == '/')
+ ++s;
+ if (*s == '>')
+ ++s;
+ }
+ return s;
+}
+
+/*
+ * Improve similar_sgr a little by moving the attr-string from the beginning
+ * to the end of the s-string.
+ */
+static bool
+rewrite_sgr(char *s, char *attr)
+{
+ if (PRESENT(s)) {
+ if (PRESENT(attr)) {
+ unsigned len_s = strlen(s);
+ unsigned len_a = strlen(attr);
+
+ if (len_s > len_a && !strncmp(attr, s, len_a)) {
+ unsigned n;
+ TR(TRACE_DATABASE, ("rewrite:\n\t%s", s));
+ for (n = 0; n < len_s - len_a; ++n) {
+ s[n] = s[n + len_a];
+ }
+ strcpy(s + n, attr);
+ TR(TRACE_DATABASE, ("to:\n\t%s", s));
+ }
+ }
+ return TRUE;
+ }
+ return FALSE; /* oops */
+}
+
+static bool
+similar_sgr(char *a, char *b)
+{
+ bool result = FALSE;
+ int csi_a = is_csi(a);
+ int csi_b = is_csi(b);
+ unsigned len_a;
+ unsigned len_b;
+
+ TR(TRACE_DATABASE, ("similar_sgr:\n\t%s\n\t%s",
+ _nc_visbuf2(1, a),
+ _nc_visbuf2(2, b)));
+ if (csi_a != 0 && csi_b != 0 && csi_a == csi_b) {
+ a += csi_a;
+ b += csi_b;
+ if (*a != *b) {
+ a = skip_zero(a);
+ b = skip_zero(b);
+ }
+ }
+ len_a = strlen(a);
+ len_b = strlen(b);
+ if (len_a && len_b) {
+ if (len_a > len_b)
+ result = (strncmp(a, b, len_b) == 0);
+ else
+ result = (strncmp(a, b, len_a) == 0);
+ }
+ TR(TRACE_DATABASE, ("...similar_sgr: %d\n\t%s\n\t%s", result,
+ _nc_visbuf2(1, a),
+ _nc_visbuf2(2, b)));
+ return result;
+}
+
+static unsigned
+chop_out(char *string, unsigned i, unsigned j)
+{
+ TR(TRACE_DATABASE, ("chop_out %d..%d from %s", i, j, _nc_visbuf(string)));
+ while (string[j] != '\0') {
+ string[i++] = string[j++];
+ }
+ string[i] = '\0';
+ return i;
+}
+
+/*
+ * Compare, ignoring delays. Some of the delay values are inconsistent, and
+ * we do not want to be stopped by that.
+ *
+ * Returns the number of chars from 'full' that we matched. If any mismatch
+ * occurs, return zero.
+ */
+static int
+compare_part(const char *part, const char *full)
+{
+ const char *next_part;
+ const char *next_full;
+ int used_full = 0;
+ int used_delay = 0;
+
+ while (*part != 0) {
+ if (*part != *full) {
+ used_full = 0;
+ break;
+ }
+
+ /*
+ * Adjust the return-value to allow the rare case of
+ * string<delay>string
+ * to remove the whole piece. The most common case is a delay at the
+ * end of the string. The adjusted string will retain the delay, which
+ * is conservative.
+ */
+ if (used_delay != 0) {
+ used_full += used_delay;
+ used_delay = 0;
+ }
+ if (*part == '$' && *full == '$') {
+ next_part = skip_delay(part);
+ next_full = skip_delay(full);
+ if (next_part != part && next_full != full) {
+ used_delay += (next_full - full);
+ full = next_full;
+ part = next_part;
+ continue;
+ }
+ }
+ ++used_full;
+ ++part;
+ ++full;
+ }
+ return used_full;
+}
+
+/*
+ * While 'sgr0' is the "same" as termcap 'me', there is a compatibility issue.
+ * The sgr/sgr0 capabilities include setting/clearing alternate character set
+ * mode. A termcap application cannot use sgr, so sgr0 strings that reset
+ * alternate character set mode will be misinterpreted. Here, we remove those
+ * from the more common ISO/ANSI/VT100 entries, which have sgr0 agreeing with
+ * sgr.
+ *
+ * This function returns the modified sgr0 if it can be modified, a null if
+ * an error occurs, or the original sgr0 if no change is needed.
+ */
+NCURSES_EXPORT(char *)
+_nc_trim_sgr0(TERMTYPE *tp)
+{
+ char *result = exit_attribute_mode;
+
+ T((T_CALLED("_nc_trim_sgr0()")));
+
+ if (PRESENT(exit_attribute_mode)
+ && PRESENT(set_attributes)) {
+ bool found = FALSE;
+ char *on = set_attribute_9(tp, 1);
+ char *off = set_attribute_9(tp, 0);
+ char *end = strdup(exit_attribute_mode);
+ char *tmp;
+ size_t i, j, k;
+
+ TR(TRACE_DATABASE, ("checking if we can trim sgr0 based on sgr"));
+ TR(TRACE_DATABASE, ("sgr0 %s", _nc_visbuf(end)));
+ TR(TRACE_DATABASE, ("sgr(9:off) %s", _nc_visbuf(off)));
+ TR(TRACE_DATABASE, ("sgr(9:on) %s", _nc_visbuf(on)));
+
+ if (!rewrite_sgr(on, enter_alt_charset_mode)
+ || !rewrite_sgr(off, exit_alt_charset_mode)
+ || !rewrite_sgr(end, exit_alt_charset_mode)) {
+ FreeIfNeeded(off);
+ } else if (similar_sgr(off, end)
+ && !similar_sgr(off, on)) {
+ TR(TRACE_DATABASE, ("adjusting sgr(9:off) : %s", _nc_visbuf(off)));
+ result = off;
+ /*
+ * If rmacs is a substring of sgr(0), remove that chunk.
+ */
+ if (exit_alt_charset_mode != 0) {
+ TR(TRACE_DATABASE, ("scan for rmacs %s", _nc_visbuf(exit_alt_charset_mode)));
+ j = strlen(off);
+ k = strlen(exit_alt_charset_mode);
+ if (j > k) {
+ for (i = 0; i <= (j - k); ++i) {
+ int k2 = compare_part(exit_alt_charset_mode, off + i);
+ if (k2 != 0) {
+ found = TRUE;
+ chop_out(off, i, i + k2);
+ break;
+ }
+ }
+ }
+ }
+ /*
+ * SGR 10 would reset to normal font.
+ */
+ if (!found) {
+ if ((i = is_csi(off)) != 0
+ && off[strlen(off) - 1] == 'm') {
+ TR(TRACE_DATABASE, ("looking for SGR 10 in %s",
+ _nc_visbuf(off)));
+ tmp = skip_zero(off + i);
+ if (tmp[0] == '1'
+ && skip_zero(tmp + 1) != tmp + 1) {
+ i = tmp - off;
+ if (off[i - 1] == ';')
+ i--;
+ j = skip_zero(tmp + 1) - off;
+ i = chop_out(off, i, j);
+ found = TRUE;
+ }
+ }
+ }
+ if (!found
+ && (tmp = strstr(end, off)) != 0
+ && strcmp(end, off) != 0) {
+ i = tmp - end;
+ j = strlen(off);
+ tmp = strdup(end);
+ chop_out(tmp, i, j);
+ free(off);
+ result = tmp;
+ }
+ TR(TRACE_DATABASE, ("...adjusted sgr0 : %s", _nc_visbuf(result)));
+ if (!strcmp(result, exit_attribute_mode)) {
+ TR(TRACE_DATABASE, ("...same result, discard"));
+ free(result);
+ result = exit_attribute_mode;
+ }
+ } else {
+ /*
+ * Either the sgr does not reference alternate character set,
+ * or it is incorrect. That's too hard to decide right now.
+ */
+ free(off);
+ }
+ FreeIfNeeded(end);
+ FreeIfNeeded(on);
+ } else {
+ /*
+ * Possibly some applications are confused if sgr0 contains rmacs,
+ * but that would be a different bug report -TD
+ */
+ }
+
+ returnPtr(result);
+}
diff --git a/ncurses/tinfo/use_screen.c b/ncurses/tinfo/use_screen.c
new file mode 100644
index 000000000000..a4f34c0e4520
--- /dev/null
+++ b/ncurses/tinfo/use_screen.c
@@ -0,0 +1,60 @@
+/****************************************************************************
+ * Copyright (c) 2007,2008 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 2007 *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+
+MODULE_ID("$Id: use_screen.c,v 1.4 2008/03/29 21:19:58 tom Exp $")
+
+NCURSES_EXPORT(int)
+use_screen(SCREEN *screen, NCURSES_SCREEN_CB func, void *data)
+{
+ SCREEN *save_SP;
+ int code = OK;
+
+ T((T_CALLED("use_screen(%p,%p,%p)"), screen, func, data));
+
+ /*
+ * FIXME - add a flag so a given thread can check if _it_ has already
+ * recurred through this point, return an error if so.
+ */
+ _nc_lock_global(use_screen);
+ save_SP = SP;
+ set_term(screen);
+
+ code = func(screen, data);
+
+ set_term(save_SP);
+ _nc_unlock_global(use_screen);
+ returnCode(code);
+
+ return 0;
+}
diff --git a/ncurses/tinfo/write_entry.c b/ncurses/tinfo/write_entry.c
new file mode 100644
index 000000000000..05027e0021a2
--- /dev/null
+++ b/ncurses/tinfo/write_entry.c
@@ -0,0 +1,773 @@
+/****************************************************************************
+ * Copyright (c) 1998-2006,2007 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
+ ****************************************************************************/
+
+/*
+ * write_entry.c -- write a terminfo structure onto the file system
+ */
+
+#include <curses.priv.h>
+#include <hashed_db.h>
+
+#include <sys/stat.h>
+
+#include <tic.h>
+#include <term_entry.h>
+
+#ifndef S_ISDIR
+#define S_ISDIR(mode) ((mode & S_IFMT) == S_IFDIR)
+#endif
+
+#if 1
+#define TRACE_OUT(p) DEBUG(2, p)
+#else
+#define TRACE_OUT(p) /*nothing */
+#endif
+
+MODULE_ID("$Id: write_entry.c,v 1.70 2007/11/17 23:38:28 tom Exp $")
+
+static int total_written;
+
+static int make_db_root(const char *);
+static int write_object(TERMTYPE *, char *, unsigned *, unsigned);
+
+#if !USE_HASHED_DB
+static void
+write_file(char *filename, TERMTYPE *tp)
+{
+ char buffer[MAX_ENTRY_SIZE];
+ unsigned limit = sizeof(buffer);
+ unsigned offset = 0;
+
+ FILE *fp = (_nc_access(filename, W_OK) == 0) ? fopen(filename, "wb") : 0;
+ if (fp == 0) {
+ perror(filename);
+ _nc_syserr_abort("can't open %s/%s", _nc_tic_dir(0), filename);
+ }
+ DEBUG(1, ("Created %s", filename));
+
+ if (write_object(tp, buffer, &offset, limit) == ERR
+ || fwrite(buffer, sizeof(char), offset, fp) != offset) {
+ _nc_syserr_abort("error writing %s/%s", _nc_tic_dir(0), filename);
+ }
+
+ fclose(fp);
+}
+
+/*
+ * Check for access rights to destination directories
+ * Create any directories which don't exist.
+ *
+ * Note: there's no reason to return the result of make_db_root(), since
+ * this function is called only in instances where that has to succeed.
+ */
+static void
+check_writeable(int code)
+{
+ static const char dirnames[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+ static bool verified[sizeof(dirnames)];
+
+ char dir[sizeof(LEAF_FMT)];
+ char *s = 0;
+
+ if (code == 0 || (s = strchr(dirnames, code)) == 0)
+ _nc_err_abort("Illegal terminfo subdirectory \"" LEAF_FMT "\"", code);
+
+ if (verified[s - dirnames])
+ return;
+
+ sprintf(dir, LEAF_FMT, code);
+ if (make_db_root(dir) < 0) {
+ _nc_err_abort("%s/%s: permission denied", _nc_tic_dir(0), dir);
+ }
+
+ verified[s - dirnames] = TRUE;
+}
+#endif /* !USE_HASHED_DB */
+
+static int
+make_db_path(char *dst, const char *src, unsigned limit)
+{
+ int rc = -1;
+ const char *top = _nc_tic_dir(0);
+
+ if (src == top || _nc_is_abs_path(src)) {
+ if (strlen(src) + 1 <= limit) {
+ (void) strcpy(dst, src);
+ rc = 0;
+ }
+ } else {
+ if (strlen(top) + strlen(src) + 2 <= limit) {
+ (void) sprintf(dst, "%s/%s", top, src);
+ rc = 0;
+ }
+ }
+#if USE_HASHED_DB
+ if (rc == 0) {
+ if (_nc_is_dir_path(dst)) {
+ rc = -1;
+ } else {
+ unsigned have = strlen(dst);
+ if (have > 3 && strcmp(dst + have - 3, DBM_SUFFIX)) {
+ if (have + 3 <= limit)
+ strcat(dst, DBM_SUFFIX);
+ else
+ rc = -1;
+ }
+ }
+ }
+#endif
+ return rc;
+}
+
+/*
+ * Make a database-root if it doesn't exist.
+ */
+static int
+make_db_root(const char *path)
+{
+ int rc;
+ char fullpath[PATH_MAX];
+
+ if ((rc = make_db_path(fullpath, path, sizeof(fullpath))) == 0) {
+#if USE_HASHED_DB
+ DB *capdbp;
+
+ if ((capdbp = _nc_db_open(fullpath, TRUE)) == NULL)
+ rc = -1;
+ else if (_nc_db_close(capdbp) < 0)
+ rc = -1;
+#else
+ struct stat statbuf;
+
+ if ((rc = stat(path, &statbuf)) < 0) {
+ rc = mkdir(path, 0777);
+ } else if (_nc_access(path, R_OK | W_OK | X_OK) < 0) {
+ rc = -1; /* permission denied */
+ } else if (!(S_ISDIR(statbuf.st_mode))) {
+ rc = -1; /* not a directory */
+ }
+#endif
+ }
+ return rc;
+}
+
+/*
+ * Set the write directory for compiled entries.
+ */
+NCURSES_EXPORT(void)
+_nc_set_writedir(char *dir)
+{
+ const char *destination;
+ char actual[PATH_MAX];
+
+ if (dir == 0
+ && use_terminfo_vars())
+ dir = getenv("TERMINFO");
+
+ if (dir != 0)
+ (void) _nc_tic_dir(dir);
+
+ destination = _nc_tic_dir(0);
+ if (make_db_root(destination) < 0) {
+ char *home = _nc_home_terminfo();
+
+ if (home != 0) {
+ destination = home;
+ if (make_db_root(destination) < 0)
+ _nc_err_abort("%s: permission denied (errno %d)",
+ destination, errno);
+ }
+ }
+
+ /*
+ * Note: because of this code, this logic should be exercised
+ * *once only* per run.
+ */
+#if USE_HASHED_DB
+ make_db_path(actual, destination, sizeof(actual));
+#else
+ if (chdir(_nc_tic_dir(destination)) < 0
+ || getcwd(actual, sizeof(actual)) == 0)
+ _nc_err_abort("%s: not a directory", destination);
+#endif
+ _nc_keep_tic_dir(strdup(actual));
+}
+
+/*
+ * Save the compiled version of a description in the filesystem.
+ *
+ * make a copy of the name-list
+ * break it up into first-name and all-but-last-name
+ * creat(first-name)
+ * write object information to first-name
+ * close(first-name)
+ * for each name in all-but-last-name
+ * link to first-name
+ *
+ * Using 'time()' to obtain a reference for file timestamps is unreliable,
+ * e.g., with NFS, because the filesystem may have a different time
+ * reference. We check for pre-existence of links by latching the first
+ * timestamp from a file that we create.
+ *
+ * The _nc_warning() calls will report a correct line number only if
+ * _nc_curr_line is properly set before the write_entry() call.
+ */
+
+NCURSES_EXPORT(void)
+_nc_write_entry(TERMTYPE *const tp)
+{
+#if USE_HASHED_DB
+
+ char buffer[MAX_ENTRY_SIZE + 1];
+ unsigned limit = sizeof(buffer);
+ unsigned offset = 0;
+
+#else /* !USE_HASHED_DB */
+
+ struct stat statbuf;
+ char filename[PATH_MAX];
+ char linkname[PATH_MAX];
+#if USE_SYMLINKS
+ char symlinkname[PATH_MAX];
+#if !HAVE_LINK
+#undef HAVE_LINK
+#define HAVE_LINK 1
+#endif
+#endif /* USE_SYMLINKS */
+
+ static int call_count;
+ static time_t start_time; /* time at start of writes */
+
+#endif /* USE_HASHED_DB */
+
+ char name_list[MAX_TERMINFO_LENGTH];
+ char *first_name, *other_names;
+ char *ptr;
+
+ (void) strcpy(name_list, tp->term_names);
+ DEBUG(7, ("Name list = '%s'", name_list));
+
+ first_name = name_list;
+
+ ptr = &name_list[strlen(name_list) - 1];
+ other_names = ptr + 1;
+
+ while (ptr > name_list && *ptr != '|')
+ ptr--;
+
+ if (ptr != name_list) {
+ *ptr = '\0';
+
+ for (ptr = name_list; *ptr != '\0' && *ptr != '|'; ptr++)
+ continue;
+
+ if (*ptr == '\0')
+ other_names = ptr;
+ else {
+ *ptr = '\0';
+ other_names = ptr + 1;
+ }
+ }
+
+ DEBUG(7, ("First name = '%s'", first_name));
+ DEBUG(7, ("Other names = '%s'", other_names));
+
+ _nc_set_type(first_name);
+
+#if USE_HASHED_DB
+ if (write_object(tp, buffer + 1, &offset, limit - 1) != ERR) {
+ DB *capdb = _nc_db_open(_nc_tic_dir(0), TRUE);
+ DBT key, data;
+
+ if (capdb != 0) {
+ buffer[0] = 0;
+
+ memset(&key, 0, sizeof(key));
+ key.data = tp->term_names;
+ key.size = strlen(tp->term_names);
+
+ memset(&data, 0, sizeof(data));
+ data.data = buffer;
+ data.size = offset + 1;
+
+ _nc_db_put(capdb, &key, &data);
+
+ buffer[0] = 2;
+
+ key.data = name_list;
+ key.size = strlen(name_list);
+
+ strcpy(buffer + 1, tp->term_names);
+ data.size = strlen(tp->term_names) + 1;
+
+ _nc_db_put(capdb, &key, &data);
+
+ while (*other_names != '\0') {
+ ptr = other_names++;
+ while (*other_names != '|' && *other_names != '\0')
+ other_names++;
+
+ if (*other_names != '\0')
+ *(other_names++) = '\0';
+
+ key.data = ptr;
+ key.size = strlen(ptr);
+
+ _nc_db_put(capdb, &key, &data);
+ }
+ _nc_db_close(capdb);
+ }
+ }
+#else /* !USE_HASHED_DB */
+ if (call_count++ == 0) {
+ start_time = 0;
+ }
+
+ if (strlen(first_name) > sizeof(filename) - 3)
+ _nc_warning("terminal name too long.");
+
+ sprintf(filename, LEAF_FMT "/%s", first_name[0], first_name);
+
+ /*
+ * Has this primary name been written since the first call to
+ * write_entry()? If so, the newer write will step on the older,
+ * so warn the user.
+ */
+ if (start_time > 0 &&
+ stat(filename, &statbuf) >= 0
+ && statbuf.st_mtime >= start_time) {
+ _nc_warning("name multiply defined.");
+ }
+
+ check_writeable(first_name[0]);
+ write_file(filename, tp);
+
+ if (start_time == 0) {
+ if (stat(filename, &statbuf) < 0
+ || (start_time = statbuf.st_mtime) == 0) {
+ _nc_syserr_abort("error obtaining time from %s/%s",
+ _nc_tic_dir(0), filename);
+ }
+ }
+ while (*other_names != '\0') {
+ ptr = other_names++;
+ while (*other_names != '|' && *other_names != '\0')
+ other_names++;
+
+ if (*other_names != '\0')
+ *(other_names++) = '\0';
+
+ if (strlen(ptr) > sizeof(linkname) - 3) {
+ _nc_warning("terminal alias %s too long.", ptr);
+ continue;
+ }
+ if (strchr(ptr, '/') != 0) {
+ _nc_warning("cannot link alias %s.", ptr);
+ continue;
+ }
+
+ check_writeable(ptr[0]);
+ sprintf(linkname, LEAF_FMT "/%s", ptr[0], ptr);
+
+ if (strcmp(filename, linkname) == 0) {
+ _nc_warning("self-synonym ignored");
+ } else if (stat(linkname, &statbuf) >= 0 &&
+ statbuf.st_mtime < start_time) {
+ _nc_warning("alias %s multiply defined.", ptr);
+ } else if (_nc_access(linkname, W_OK) == 0)
+#if HAVE_LINK
+ {
+ int code;
+#if USE_SYMLINKS
+ strcpy(symlinkname, "../");
+ strncat(symlinkname, filename, sizeof(symlinkname) - 4);
+ symlinkname[sizeof(symlinkname) - 1] = '\0';
+#endif /* USE_SYMLINKS */
+#if HAVE_REMOVE
+ code = remove(linkname);
+#else
+ code = unlink(linkname);
+#endif
+ if (code != 0 && errno == ENOENT)
+ code = 0;
+#if USE_SYMLINKS
+ if (symlink(symlinkname, linkname) < 0)
+#else
+ if (link(filename, linkname) < 0)
+#endif /* USE_SYMLINKS */
+ {
+ /*
+ * If there wasn't anything there, and we cannot
+ * link to the target because it is the same as the
+ * target, then the source must be on a filesystem
+ * that uses caseless filenames, such as Win32, etc.
+ */
+ if (code == 0 && errno == EEXIST)
+ _nc_warning("can't link %s to %s", filename, linkname);
+ else if (code == 0 && (errno == EPERM || errno == ENOENT))
+ write_file(linkname, tp);
+ else {
+#if MIXEDCASE_FILENAMES
+ _nc_syserr_abort("can't link %s to %s", filename, linkname);
+#else
+ _nc_warning("can't link %s to %s (errno=%d)", filename,
+ linkname, errno);
+#endif
+ }
+ } else {
+ DEBUG(1, ("Linked %s", linkname));
+ }
+ }
+#else /* just make copies */
+ write_file(linkname, tp);
+#endif /* HAVE_LINK */
+ }
+#endif /* USE_HASHED_DB */
+}
+
+static unsigned
+fake_write(char *dst,
+ unsigned *offset,
+ unsigned limit,
+ char *src,
+ unsigned want,
+ unsigned size)
+{
+ int have = (limit - *offset);
+
+ want *= size;
+ if (have > 0) {
+ if ((int) want > have)
+ want = have;
+ memcpy(dst + *offset, src, want);
+ *offset += want;
+ } else {
+ want = 0;
+ }
+ return (int) (want / size);
+}
+
+#define Write(buf, size, count) fake_write(buffer, offset, limit, (char *) buf, count, size)
+
+#undef LITTLE_ENDIAN /* BSD/OS defines this as a feature macro */
+#define HI(x) ((x) / 256)
+#define LO(x) ((x) % 256)
+#define LITTLE_ENDIAN(p, x) (p)[0] = LO(x), (p)[1] = HI(x)
+
+#define WRITE_STRING(str) (Write(str, sizeof(char), strlen(str) + 1) == strlen(str) + 1)
+
+static int
+compute_offsets(char **Strings, unsigned strmax, short *offsets)
+{
+ size_t nextfree = 0;
+ unsigned i;
+
+ for (i = 0; i < strmax; i++) {
+ if (Strings[i] == ABSENT_STRING) {
+ offsets[i] = -1;
+ } else if (Strings[i] == CANCELLED_STRING) {
+ offsets[i] = -2;
+ } else {
+ offsets[i] = nextfree;
+ nextfree += strlen(Strings[i]) + 1;
+ TRACE_OUT(("put Strings[%d]=%s(%d)", (int) i,
+ _nc_visbuf(Strings[i]), nextfree));
+ }
+ }
+ return nextfree;
+}
+
+static void
+convert_shorts(unsigned char *buf, short *Numbers, unsigned count)
+{
+ unsigned i;
+ for (i = 0; i < count; i++) {
+ if (Numbers[i] == ABSENT_NUMERIC) { /* HI/LO won't work */
+ buf[2 * i] = buf[2 * i + 1] = 0377;
+ } else if (Numbers[i] == CANCELLED_NUMERIC) { /* HI/LO won't work */
+ buf[2 * i] = 0376;
+ buf[2 * i + 1] = 0377;
+ } else {
+ LITTLE_ENDIAN(buf + 2 * i, Numbers[i]);
+ TRACE_OUT(("put Numbers[%d]=%d", i, Numbers[i]));
+ }
+ }
+}
+
+#define even_boundary(value) \
+ ((value) % 2 != 0 && Write(&zero, sizeof(char), 1) != 1)
+
+#if NCURSES_XNAMES
+static unsigned
+extended_Booleans(TERMTYPE *tp)
+{
+ unsigned short result = 0;
+ unsigned short i;
+
+ for (i = 0; i < tp->ext_Booleans; ++i) {
+ if (tp->Booleans[BOOLCOUNT + i] == TRUE)
+ result = (i + 1);
+ }
+ return result;
+}
+
+static unsigned
+extended_Numbers(TERMTYPE *tp)
+{
+ unsigned short result = 0;
+ unsigned short i;
+
+ for (i = 0; i < tp->ext_Numbers; ++i) {
+ if (tp->Numbers[NUMCOUNT + i] != ABSENT_NUMERIC)
+ result = (i + 1);
+ }
+ return result;
+}
+
+static unsigned
+extended_Strings(TERMTYPE *tp)
+{
+ unsigned short result = 0;
+ unsigned short i;
+
+ for (i = 0; i < tp->ext_Strings; ++i) {
+ if (tp->Strings[STRCOUNT + i] != ABSENT_STRING)
+ result = (i + 1);
+ }
+ return result;
+}
+
+/*
+ * _nc_align_termtype() will extend entries that are referenced in a use=
+ * clause - discard the unneeded data.
+ */
+static bool
+extended_object(TERMTYPE *tp)
+{
+ bool result = FALSE;
+
+ if (_nc_user_definable) {
+ result = ((extended_Booleans(tp)
+ + extended_Numbers(tp)
+ + extended_Strings(tp)) != 0);
+ }
+ return result;
+}
+#endif
+
+static int
+write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit)
+{
+ char *namelist;
+ size_t namelen, boolmax, nummax, strmax;
+ char zero = '\0';
+ size_t i;
+ short nextfree;
+ short offsets[MAX_ENTRY_SIZE / 2];
+ unsigned char buf[MAX_ENTRY_SIZE];
+ unsigned last_bool = BOOLWRITE;
+ unsigned last_num = NUMWRITE;
+ unsigned last_str = STRWRITE;
+
+#if NCURSES_XNAMES
+ /*
+ * Normally we limit the list of values to exclude the "obsolete"
+ * capabilities. However, if we are accepting extended names, add
+ * these as well, since they are used for supporting translation
+ * to/from termcap.
+ */
+ if (_nc_user_definable) {
+ last_bool = BOOLCOUNT;
+ last_num = NUMCOUNT;
+ last_str = STRCOUNT;
+ }
+#endif
+
+ namelist = tp->term_names;
+ namelen = strlen(namelist) + 1;
+
+ boolmax = 0;
+ for (i = 0; i < last_bool; i++) {
+ if (tp->Booleans[i] == TRUE)
+ boolmax = i + 1;
+ }
+
+ nummax = 0;
+ for (i = 0; i < last_num; i++) {
+ if (tp->Numbers[i] != ABSENT_NUMERIC)
+ nummax = i + 1;
+ }
+
+ strmax = 0;
+ for (i = 0; i < last_str; i++) {
+ if (tp->Strings[i] != ABSENT_STRING)
+ strmax = i + 1;
+ }
+
+ nextfree = compute_offsets(tp->Strings, strmax, offsets);
+
+ /* fill in the header */
+ LITTLE_ENDIAN(buf, MAGIC);
+ LITTLE_ENDIAN(buf + 2, min(namelen, MAX_NAME_SIZE + 1));
+ LITTLE_ENDIAN(buf + 4, boolmax);
+ LITTLE_ENDIAN(buf + 6, nummax);
+ LITTLE_ENDIAN(buf + 8, strmax);
+ LITTLE_ENDIAN(buf + 10, nextfree);
+
+ /* write out the header */
+ TRACE_OUT(("Header of %s @%d", namelist, *offset));
+ if (Write(buf, 12, 1) != 1
+ || Write(namelist, sizeof(char), namelen) != namelen)
+ return (ERR);
+
+ for (i = 0; i < boolmax; i++)
+ if (tp->Booleans[i] == TRUE)
+ buf[i] = TRUE;
+ else
+ buf[i] = FALSE;
+ if (Write(buf, sizeof(char), boolmax) != boolmax)
+ return (ERR);
+
+ if (even_boundary(namelen + boolmax))
+ return (ERR);
+
+ TRACE_OUT(("Numerics begin at %04x", *offset));
+
+ /* the numerics */
+ convert_shorts(buf, tp->Numbers, nummax);
+ if (Write(buf, 2, nummax) != nummax)
+ return (ERR);
+
+ TRACE_OUT(("String offsets begin at %04x", *offset));
+
+ /* the string offsets */
+ convert_shorts(buf, offsets, strmax);
+ if (Write(buf, 2, strmax) != strmax)
+ return (ERR);
+
+ TRACE_OUT(("String table begins at %04x", *offset));
+
+ /* the strings */
+ for (i = 0; i < strmax; i++)
+ if (VALID_STRING(tp->Strings[i]))
+ if (!WRITE_STRING(tp->Strings[i]))
+ return (ERR);
+
+#if NCURSES_XNAMES
+ if (extended_object(tp)) {
+ unsigned extcnt = NUM_EXT_NAMES(tp);
+
+ if (even_boundary(nextfree))
+ return (ERR);
+
+ nextfree = compute_offsets(tp->Strings + STRCOUNT, tp->ext_Strings, offsets);
+ TRACE_OUT(("after extended string capabilities, nextfree=%d", nextfree));
+ nextfree += compute_offsets(tp->ext_Names, extcnt, offsets + tp->ext_Strings);
+ TRACE_OUT(("after extended capnames, nextfree=%d", nextfree));
+ strmax = tp->ext_Strings + extcnt;
+
+ /*
+ * Write the extended header
+ */
+ LITTLE_ENDIAN(buf + 0, tp->ext_Booleans);
+ LITTLE_ENDIAN(buf + 2, tp->ext_Numbers);
+ LITTLE_ENDIAN(buf + 4, tp->ext_Strings);
+ LITTLE_ENDIAN(buf + 6, strmax);
+ LITTLE_ENDIAN(buf + 8, nextfree);
+ TRACE_OUT(("WRITE extended-header @%d", *offset));
+ if (Write(buf, 10, 1) != 1)
+ return (ERR);
+
+ TRACE_OUT(("WRITE %d booleans @%d", tp->ext_Booleans, *offset));
+ if (tp->ext_Booleans
+ && Write(tp->Booleans + BOOLCOUNT, sizeof(char),
+ tp->ext_Booleans) != tp->ext_Booleans)
+ return (ERR);
+
+ if (even_boundary(tp->ext_Booleans))
+ return (ERR);
+
+ TRACE_OUT(("WRITE %d numbers @%d", tp->ext_Numbers, *offset));
+ if (tp->ext_Numbers) {
+ convert_shorts(buf, tp->Numbers + NUMCOUNT, tp->ext_Numbers);
+ if (Write(buf, 2, tp->ext_Numbers) != tp->ext_Numbers)
+ return (ERR);
+ }
+
+ /*
+ * Convert the offsets for the ext_Strings and ext_Names tables,
+ * in that order.
+ */
+ convert_shorts(buf, offsets, strmax);
+ TRACE_OUT(("WRITE offsets @%d", *offset));
+ if (Write(buf, 2, strmax) != strmax)
+ return (ERR);
+
+ /*
+ * Write the string table after the offset tables so we do not
+ * have to do anything about alignment.
+ */
+ for (i = 0; i < tp->ext_Strings; i++) {
+ if (VALID_STRING(tp->Strings[i + STRCOUNT])) {
+ TRACE_OUT(("WRITE ext_Strings[%d]=%s", (int) i,
+ _nc_visbuf(tp->Strings[i + STRCOUNT])));
+ if (!WRITE_STRING(tp->Strings[i + STRCOUNT]))
+ return (ERR);
+ }
+ }
+
+ /*
+ * Write the extended names
+ */
+ for (i = 0; i < extcnt; i++) {
+ TRACE_OUT(("WRITE ext_Names[%d]=%s", (int) i, tp->ext_Names[i]));
+ if (!WRITE_STRING(tp->ext_Names[i]))
+ return (ERR);
+ }
+
+ }
+#endif /* NCURSES_XNAMES */
+
+ total_written++;
+ return (OK);
+}
+
+/*
+ * Returns the total number of entries written by this process
+ */
+NCURSES_EXPORT(int)
+_nc_tic_written(void)
+{
+ return total_written;
+}