Base version of ncurses-5.7 library
diff --git a/ncurses/tinfo/MKcaptab.awk b/ncurses/tinfo/MKcaptab.awk
new file mode 100644
index 0000000..56d3d17
--- /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 100755
index 0000000..98c04e8
--- /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 0000000..b9ba636
--- /dev/null
+++ b/ncurses/tinfo/MKcodes.awk
@@ -0,0 +1,164 @@
+##############################################################################
+# 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.                                                             #
+##############################################################################
+# $Id: MKcodes.awk,v 1.5 2008/06/28 23:13:25 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  "#if NO_LEAKS"
+		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  "#endif"
+		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 0000000..9feab35
--- /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 0000000..14017b0
--- /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 0000000..7e50744
--- /dev/null
+++ b/ncurses/tinfo/MKnames.awk
@@ -0,0 +1,186 @@
+##############################################################################
+# 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.                                                             #
+##############################################################################
+# $Id: MKnames.awk,v 1.20 2008/10/11 21:07:56 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] = (NCURSES_CONST char *) _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  "#if NO_LEAKS"
+		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  "#endif"
+		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 0000000..14c4220
--- /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 0000000..ce8ccda
--- /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 0000000..455d142
--- /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 0000000..4638e99
--- /dev/null
+++ b/ncurses/tinfo/alloc_entry.c
@@ -0,0 +1,299 @@
+/****************************************************************************
+ * 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                 *
+ ****************************************************************************/
+
+/*
+ * 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.48 2008/08/16 16:25:31 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 / sizeof(short)];
+    int 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);
+    }
+
+    assert(tp->term_names >= stringbuf);
+    n = (unsigned) (tp->term_names - stringbuf);
+    for_each_string(i, &(ep->tterm)) {
+	if (i < SIZEOF(offsets)) {
+	    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 (i < SIZEOF(offsets)) {
+	    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 = (unsigned) NUM_EXT_NAMES(tp)) != 0) {
+	    if (n < SIZEOF(offsets)) {
+		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] = (char) mergebool;
+	}
+    }
+
+    for_each_number(i, from) {
+	if (to->Numbers[i] != CANCELLED_NUMERIC) {
+	    short 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 0000000..b2b06d1
--- /dev/null
+++ b/ncurses/tinfo/alloc_ttype.c
@@ -0,0 +1,506 @@
+/****************************************************************************
+ * 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.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *  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.17 2008/10/12 16:12:00 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 if ((k = _nc_find_ext_name(from, to->ext_Names[j],
+					      STRING)) >= 0) {
+		if (_nc_del_ext_name(to, name, NUMBER)
+		    || _nc_del_ext_name(to, name, BOOLEAN)) {
+		    k = _nc_ins_ext_name(to, name, STRING);
+		    to->Strings[k] = CANCELLED_STRING;
+		} else {
+		    j++;
+		}
+	    } 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 0000000..93300c1
--- /dev/null
+++ b/ncurses/tinfo/captoinfo.c
@@ -0,0 +1,852 @@
+/****************************************************************************
+ * 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                 *
+ ****************************************************************************/
+
+/*
+ *	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.52 2008/08/16 19:24:51 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 = (unsigned char) (*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 = (unsigned char) (*sp);
+	    len = 2;
+	    break;
+	}
+	break;
+    case '^':
+	c = (*++sp & 0x1f);
+	len = 2;
+	break;
+    default:
+	c = (unsigned char) (*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 == '%') */
+
+	/*
+	 * 'str' always points to the end of what was scanned in this step,
+	 * but that may not be the end of the string.
+	 */
+	assert(str != 0);
+	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 0000000..56c362a
--- /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 0000000..6e79a92
--- /dev/null
+++ b/ncurses/tinfo/comp_expand.c
@@ -0,0 +1,192 @@
+/****************************************************************************
+ * 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: 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.20 2008/08/16 19:29:42 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 : "\0\0";
+    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++] = (char) 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++] = (char) ch;
+	} else if (REALPRINT(str)
+		   && (ch != ','
+		       && ch != ':'
+		       && !(ch == '!' && !tic_format)
+		       && ch != '^'))
+	    buffer[bufp++] = (char) 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 0000000..b7fbd06
--- /dev/null
+++ b/ncurses/tinfo/comp_hash.c
@@ -0,0 +1,370 @@
+/****************************************************************************
+ * 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                 *
+ ****************************************************************************/
+
+/*
+ *	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.36 2008/08/16 17:06:53 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)
+{
+    short 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 */
+		    assert(s > buffer + 1);
+		    s[-1] = '\0';
+		    buffer++;
+		}
+		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
+	|| name_table == 0
+	|| hash_table == 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 = (int) 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 += (int) 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");
+
+    free(hash_table);
+    return EXIT_SUCCESS;
+}
+#endif
diff --git a/ncurses/tinfo/comp_parse.c b/ncurses/tinfo/comp_parse.c
new file mode 100644
index 0000000..3325a0d
--- /dev/null
+++ b/ncurses/tinfo/comp_parse.c
@@ -0,0 +1,491 @@
+/****************************************************************************
+ * 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                 *
+ ****************************************************************************/
+
+/*
+ *	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.69 2008/08/16 21:58:16 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;
+    unsigned i;
+    int 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 0000000..5ad750f
--- /dev/null
+++ b/ncurses/tinfo/comp_scan.c
@@ -0,0 +1,944 @@
+/****************************************************************************
+ * 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                 *
+ ****************************************************************************/
+
+/*
+ *	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.83 2008/08/16 19:22:55 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);
+		    bufstart = result;
+		}
+		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;
+}
+
+#define TOK_BUF_SIZE MAX_ENTRY_SIZE
+
+#define OkToAdd() \
+	((tok_ptr - tok_buf) < (TOK_BUF_SIZE - 2))
+
+#define AddCh(ch) \
+	*tok_ptr++ = (char) ch; \
+	*tok_ptr = '\0'
+
+/*
+ *	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 *tok_buf;
+
+    char *after_list;
+    char *after_name;
+    char *numchk;
+    char *tok_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 (tok_buf != 0) {
+	    if (_nc_curr_token.tk_name == tok_buf)
+		_nc_curr_token.tk_name = 0;
+	    FreeAndNull(tok_buf);
+	}
+	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 (tok_buf == 0)
+	    tok_buf = typeMalloc(char, TOK_BUF_SIZE);
+
+#ifdef TRACE
+	old_line = _nc_curr_line;
+	old_col = _nc_curr_col;
+#endif
+	tok_ptr = tok_buf;
+	AddCh(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 = tok_ptr;
+		    if (after_name == 0)
+			after_name = tok_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);
+
+		if (OkToAdd()) {
+		    AddCh(ch);
+		} else {
+		    ch = EOF;
+		    break;
+		}
+	    }
+	    *tok_ptr = '\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 (--tok_ptr;
+		     iswhite(*tok_ptr) || *tok_ptr == ',';
+		     tok_ptr--)
+		    continue;
+		tok_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(tok_buf);
+		*after_name = (char) 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 = tok_buf + strlen(tok_buf);
+		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 = tok_buf; 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 = tok_buf;
+	    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;
+		    }
+		}
+		if (OkToAdd()) {
+		    AddCh(ch);
+		} else {
+		    ch = EOF;
+		    break;
+		}
+	    }
+
+	    *tok_ptr++ = '\0';	/* separate name/value in buffer */
+	    switch (ch) {
+	    case ',':
+	    case ':':
+		if (ch != separator)
+		    _nc_err_abort("Separator inconsistent with syntax");
+		_nc_curr_token.tk_name = tok_buf;
+		type = BOOLEAN;
+		break;
+	    case '@':
+		if ((ch = next_char()) != separator && !silent)
+		    _nc_warning("Missing separator after `%s', have %s",
+				tok_buf, unctrl((chtype) ch));
+		_nc_curr_token.tk_name = tok_buf;
+		type = CANCEL;
+		break;
+
+	    case '#':
+		found = 0;
+		while (isalnum(ch = next_char())) {
+		    numbuf[found++] = (char) 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'", tok_buf);
+		    if ((*numchk != '\0') || (ch != separator))
+			_nc_warning("Missing separator");
+		}
+		_nc_curr_token.tk_name = tok_buf;
+		_nc_curr_token.tk_valnumber = number;
+		type = NUMBER;
+		break;
+
+	    case '=':
+		ch = _nc_trans_string(tok_ptr, tok_buf + TOK_BUF_SIZE);
+		if (!silent && ch != separator)
+		    _nc_warning("Missing separator");
+		_nc_curr_token.tk_name = tok_buf;
+		_nc_curr_token.tk_valstring = tok_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)) {
+	    if (c != EOF) {
+		while ((c = next_char()) != separator && c != EOF) {
+		    ;
+		}
+		ch = c;
+	    }
+	    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((char) 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 0000000..fdc2bb0
--- /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 0000000..fe2a009
--- /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 0000000..cf2a833
--- /dev/null
+++ b/ncurses/tinfo/entries.c
@@ -0,0 +1,145 @@
+/****************************************************************************
+ * Copyright (c) 2006-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                                                *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+
+#include <ctype.h>
+
+#include <tic.h>
+#include <term_entry.h>
+
+MODULE_ID("$Id: entries.c,v 1.8 2008/09/27 13:11:10 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)
+{
+#if NO_LEAKS
+    char *s;
+#endif
+
+    T((T_CALLED("_nc_free_tinfo()")));
+#if NO_LEAKS
+    _nc_free_tparm();
+    _nc_tgetent_leaks();
+    _nc_free_entries(_nc_head);
+    _nc_get_type(0);
+    _nc_first_name(0);
+    _nc_keyname_leaks();
+#if BROKEN_LINKER || USE_REENTRANT
+    _nc_names_leaks();
+    _nc_codes_leaks();
+    FreeIfNeeded(_nc_prescreen.real_acs_map);
+#endif
+
+    if ((s = _nc_home_terminfo()) != 0)
+	free(s);
+#endif /* NO_LEAKS */
+    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 0000000..fa0fff1
--- /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 0000000..a90cc08
--- /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 0000000..3fc04ea
--- /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 0000000..4521c4a
--- /dev/null
+++ b/ncurses/tinfo/home_terminfo.c
@@ -0,0 +1,67 @@
+/****************************************************************************
+ * 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: 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.11 2008/08/03 23:43:11 tom Exp $")
+
+/* 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) {
+		unsigned want = (strlen(home) + sizeof(PRIVATE_INFO));
+		MyBuffer = typeMalloc(char, want);
+		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 0000000..2f6fe4f
--- /dev/null
+++ b/ncurses/tinfo/init_keytry.c
@@ -0,0 +1,117 @@
+/****************************************************************************
+ * 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.12 2008/05/24 21:44:51 tom Exp $")
+
+/*
+**      _nc_init_keytry()
+**
+**      Construct the try for the current terminal's keypad keys.
+**
+*/
+
+/*
+ * Internal entrypoints use SCREEN* parameter to obtain capabilities rather
+ * than cur_term.
+ */
+#undef CUR
+#define CUR (sp->_term)->type.
+
+#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 0000000..919e472
--- /dev/null
+++ b/ncurses/tinfo/lib_acs.c
@@ -0,0 +1,194 @@
+/****************************************************************************
+ * 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                 *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+#include <term.h>		/* ena_acs, acs_chars */
+
+MODULE_ID("$Id: lib_acs.c,v 1.36 2008/08/16 19:22:55 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;
+	    if (SP)
+		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++] = (char) 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 0000000..b9cdfda
--- /dev/null
+++ b/ncurses/tinfo/lib_baudrate.c
@@ -0,0 +1,238 @@
+/****************************************************************************
+ * 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_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.27 2008/06/28 15:19:24 tom 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 (!isatty(fileno(SP ? SP->_ofp : stdout))
+	&& getenv("BAUDRATE") != 0) {
+	int ret;
+	if ((ret = _nc_getenv_num("BAUDRATE")) <= 0)
+	    ret = 9600;
+	ospeed = _nc_ospeed(ret);
+	returnCode(ret);
+    }
+#endif
+
+    if (cur_term != 0) {
+#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
+	cur_term->_baudrate = result;
+    } else {
+	result = ERR;
+    }
+
+    returnCode(result);
+}
diff --git a/ncurses/tinfo/lib_cur_term.c b/ncurses/tinfo/lib_cur_term.c
new file mode 100644
index 0000000..626578d
--- /dev/null
+++ b/ncurses/tinfo/lib_cur_term.c
@@ -0,0 +1,105 @@
+/****************************************************************************
+ * Copyright (c) 1998-2003,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 <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.18 2008/08/16 19:22:55 tom Exp $")
+
+#undef CUR
+#define CUR termp->type.
+
+#if BROKEN_LINKER || USE_REENTRANT
+NCURSES_EXPORT(TERMINAL *)
+NCURSES_PUBLIC_VAR(cur_term) (void)
+{
+    return (SP != 0 && SP->_term != 0) ? SP->_term : _nc_prescreen._cur_term;
+}
+#else
+NCURSES_EXPORT_VAR(TERMINAL *) cur_term = 0;
+#endif
+
+NCURSES_EXPORT(TERMINAL *)
+set_curterm(TERMINAL * termp)
+{
+    TERMINAL *oldterm;
+
+    T((T_CALLED("set_curterm(%p)"), termp));
+
+    _nc_lock_global(curses);
+    oldterm = cur_term;
+    if (SP)
+	SP->_term = termp;
+#if BROKEN_LINKER || USE_REENTRANT
+    _nc_prescreen._cur_term = termp;
+#else
+    cur_term = termp;
+#endif
+    if (termp != 0) {
+	ospeed = _nc_ospeed(termp->_baudrate);
+	if (termp->type.Strings) {
+	    PC = (char) ((pad_char != NULL) ? pad_char[0] : 0);
+	}
+    }
+    _nc_unlock_global(curses);
+
+    T((T_RETURN("%p"), oldterm));
+    return (oldterm);
+}
+
+NCURSES_EXPORT(int)
+del_curterm(TERMINAL * termp)
+{
+    int rc = ERR;
+
+    T((T_CALLED("del_curterm(%p)"), termp));
+
+    _nc_lock_global(curses);
+    if (termp != 0) {
+	_nc_free_termtype(&(termp->type));
+	FreeIfNeeded(termp->_termname);
+	free(termp);
+	if (termp == cur_term)
+	    set_curterm(0);
+	rc = OK;
+    }
+    _nc_unlock_global(curses);
+
+    returnCode(rc);
+}
diff --git a/ncurses/tinfo/lib_data.c b/ncurses/tinfo/lib_data.c
new file mode 100644
index 0000000..e84209d
--- /dev/null
+++ b/ncurses/tinfo/lib_data.c
@@ -0,0 +1,332 @@
+/****************************************************************************
+ * 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.52 2008/08/23 22:16:15 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 */
+
+    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_curses */
+    PTHREAD_MUTEX_INITIALIZER,	/* mutex_tst_tracef */
+    PTHREAD_MUTEX_INITIALIZER,	/* mutex_tracef */
+    0,				/* nested_tracef */
+    0,				/* use_pthreads */
+#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 NCURSES_NO_PADDING
+    FALSE,			/* flag to set if padding disabled  */
+#endif
+#if BROKEN_LINKER || USE_REENTRANT
+    NULL,			/* real_acs_map */
+    0,				/* LINES */
+    0,				/* COLS */
+    0,				/* cur_term */
+#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_curses);
+	_nc_mutex_init(&_nc_globals.mutex_tst_tracef);
+	_nc_mutex_init(&_nc_globals.mutex_tracef);
+    }
+}
+
+NCURSES_EXPORT(void)
+_nc_init_pthreads(void)
+{
+    if (_nc_use_pthreads)
+	return;
+# if USE_WEAK_SYMBOLS
+    if ((pthread_mutex_init) == 0)
+	return;
+    if ((pthread_mutex_lock) == 0)
+	return;
+    if ((pthread_mutex_unlock) == 0)
+	return;
+    if ((pthread_mutex_trylock) == 0)
+	return;
+    if ((pthread_mutexattr_settype) == 0)
+	return;
+# endif
+    _nc_use_pthreads = 1;
+    init_global_mutexes();
+}
+
+/*
+ * 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;
+
+    if (_nc_use_pthreads) {
+	pthread_mutexattr_init(&recattr);
+	pthread_mutexattr_settype(&recattr, PTHREAD_MUTEX_RECURSIVE);
+	pthread_mutex_init(obj, &recattr);
+    }
+}
+
+NCURSES_EXPORT(int)
+_nc_mutex_lock(pthread_mutex_t * obj)
+{
+    if (_nc_use_pthreads == 0)
+	return 0;
+    return pthread_mutex_lock(obj);
+}
+
+NCURSES_EXPORT(int)
+_nc_mutex_trylock(pthread_mutex_t * obj)
+{
+    if (_nc_use_pthreads == 0)
+	return 0;
+    return pthread_mutex_trylock(obj);
+}
+
+NCURSES_EXPORT(int)
+_nc_mutex_unlock(pthread_mutex_t * obj)
+{
+    if (_nc_use_pthreads == 0)
+	return 0;
+    return pthread_mutex_unlock(obj);
+}
+
+#if USE_WEAK_SYMBOLS
+/*
+ * NB: sigprocmask(2) is global but pthread_sigmask(3p)
+ * only for the calling thread.
+ */
+NCURSES_EXPORT(int)
+_nc_sigprocmask(int how, const sigset_t * newmask, sigset_t * oldmask)
+{
+    if ((pthread_sigmask))
+	return pthread_sigmask(how, newmask, oldmask);
+    else
+	return sigprocmask(how, newmask, oldmask);
+}
+#endif
+#endif /* USE_PTHREADS */
diff --git a/ncurses/tinfo/lib_has_cap.c b/ncurses/tinfo/lib_has_cap.c
new file mode 100644
index 0000000..0dc66bd
--- /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 0000000..89dc1e8
--- /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 0000000..1301ee5
--- /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 0000000..417b3b4
--- /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 0000000..f3b1485
--- /dev/null
+++ b/ncurses/tinfo/lib_options.c
@@ -0,0 +1,327 @@
+/****************************************************************************
+ * 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.58 2008/08/16 21:20:48 Werner.Fink Exp $")
+
+static int _nc_curs_set(SCREEN *, int);
+static int _nc_meta(SCREEN *, bool);
+
+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;
+
+    /* Ok, we stay relaxed and don't signal an error if win is NULL */
+    T((T_CALLED("meta(%p,%d)"), win, flag));
+    result = _nc_meta(SP, flag);
+    returnCode(result);
+}
+
+/* curs_set() moved here to narrow the kernel interface */
+
+NCURSES_EXPORT(int)
+curs_set(int vis)
+{
+    int result;
+
+    T((T_CALLED("curs_set(%d)"), vis));
+    result = _nc_curs_set(SP, vis);
+    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 */
+
+/*
+ * Internal entrypoints use SCREEN* parameter to obtain capabilities rather
+ * than cur_term.
+ */
+#undef CUR
+#define CUR (sp->_term)->type.
+
+static int
+_nc_putp(const char *name GCC_UNUSED, const char *value)
+{
+    int rc = ERR;
+
+    if (value) {
+	TPUTS_TRACE(name);
+	rc = putp(value);
+    }
+    return rc;
+}
+
+static int
+_nc_putp_flush(const char *name, const char *value)
+{
+    int rc = _nc_putp(name, value);
+    if (rc != ERR) {
+	_nc_flush();
+    }
+    return rc;
+}
+
+/* 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)
+{
+    int rc = ERR;
+
+    if (sp != 0) {
+#ifdef USE_PTHREADS
+	/*
+	 * We might have this situation in a multithreaded application that
+	 * has wgetch() reading in more than one thread.  putp() and below
+	 * may use SP explicitly.
+	 */
+	if (_nc_use_pthreads && sp != SP) {
+	    SCREEN *save_sp;
+
+	    /* cannot use use_screen(), since that is not in tinfo library */
+	    _nc_lock_global(curses);
+	    save_sp = SP;
+	    _nc_set_screen(sp);
+	    rc = _nc_keypad(sp, flag);
+	    _nc_set_screen(save_sp);
+	    _nc_unlock_global(curses);
+	} else
+#endif
+	{
+	    if (flag) {
+		(void) _nc_putp_flush("keypad_xmit", keypad_xmit);
+	    } else if (!flag && keypad_local) {
+		(void) _nc_putp_flush("keypad_local", keypad_local);
+	    }
+
+	    if (flag && !sp->_tried) {
+		_nc_init_keytry(sp);
+		sp->_tried = TRUE;
+	    }
+	    sp->_keypad_on = flag;
+	    rc = OK;
+	}
+    }
+    return (rc);
+}
+
+static int
+_nc_curs_set(SCREEN *sp, 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 {
+	    switch (vis) {
+	    case 2:
+		result = _nc_putp_flush("cursor_visible", cursor_visible);
+		break;
+	    case 1:
+		result = _nc_putp_flush("cursor_normal", cursor_normal);
+		break;
+	    case 0:
+		result = _nc_putp_flush("cursor_invisible", cursor_invisible);
+		break;
+	    }
+	    if (result != ERR)
+		result = (cursor == -1 ? 1 : cursor);
+	    sp->_cursor = vis;
+	}
+    }
+    returnCode(result);
+}
+
+static int
+_nc_meta(SCREEN *sp, bool flag)
+{
+    int result = ERR;
+
+    /* Ok, we stay relaxed and don't signal an error if win is NULL */
+
+    if (SP != 0) {
+	SP->_use_meta = flag;
+
+	if (flag) {
+	    _nc_putp("meta_on", meta_on);
+	} else {
+	    _nc_putp("meta_off", meta_off);
+	}
+	result = OK;
+    }
+    return result;
+}
diff --git a/ncurses/tinfo/lib_print.c b/ncurses/tinfo/lib_print.c
new file mode 100644
index 0000000..975b46d
--- /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 0000000..58e7188
--- /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 0000000..8cfaf12
--- /dev/null
+++ b/ncurses/tinfo/lib_setup.c
@@ -0,0 +1,631 @@
+/****************************************************************************
+ * 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.111 2008/08/03 22:42:33 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
+
+/*
+ * Reduce explicit use of "cur_term" global variable.
+ */
+#undef CUR
+#define CUR termp->type.
+
+/*
+ * 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 *)
+_nc_ptr_Lines(void)
+{
+    return ptrLines();
+}
+NCURSES_EXPORT(int)
+NCURSES_PUBLIC_VAR(LINES) (void)
+{
+    return *_nc_ptr_Lines();
+}
+NCURSES_EXPORT(int *)
+_nc_ptr_Cols(void)
+{
+    return ptrCols();
+}
+NCURSES_EXPORT(int)
+NCURSES_PUBLIC_VAR(COLS) (void)
+{
+    return *_nc_ptr_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 */
+{
+    TERMINAL *termp = cur_term;
+    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)
+{
+    TERMINAL *termp = cur_term;
+    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(TERMINAL * termp)
+{
+    unsigned i;
+    char CC;
+    char proto;
+    char *tmp;
+
+    if ((tmp = getenv("CC")) != 0) {
+	if ((CC = *tmp) != 0) {
+	    proto = *command_character;
+
+	    for_each_string(i, &(termp->type)) {
+		for (tmp = termp->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(TERMINAL * termp)
+{
+    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)
+{
+    TERMINAL *termp;
+    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
+	&& (termp = cur_term) != 0
+	&& termp->Filedes == Filedes
+	&& termp->_termname != 0
+	&& !strcmp(termp->_termname, tname)
+	&& _nc_name_match(termp->type.term_names, tname, "|")) {
+	T(("reusing existing terminal information and mode-settings"));
+    } else {
+
+	termp = typeCalloc(TERMINAL, 1);
+
+	if (termp == 0) {
+	    ret_error0(TGETENT_ERR,
+		       "Not enough memory to create terminal structure.\n");
+	}
+#if USE_DATABASE || USE_TERMCAP
+	status = grab_entry(tname, &termp->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) {
+		termp->type = *fallback;
+		status = TGETENT_YES;
+	    }
+	}
+
+	if (status != TGETENT_YES) {
+	    del_curterm(termp);
+	    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);
+	    }
+	}
+#if !USE_REENTRANT
+	strncpy(ttytype, termp->type.term_names, NAMESIZE - 1);
+	ttytype[NAMESIZE - 1] = '\0';
+#endif
+
+	termp->Filedes = Filedes;
+	termp->_termname = strdup(tname);
+
+	set_curterm(termp);
+
+	if (command_character && getenv("CC"))
+	    do_prototype(termp);
+
+	/*
+	 * 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.
+     */
+    _nc_get_screensize(SP, ptrLines(), ptrCols());
+
+    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 0000000..2d245ff
--- /dev/null
+++ b/ncurses/tinfo/lib_termcap.c
@@ -0,0 +1,291 @@
+/****************************************************************************
+ * 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                 *
+ *                                                                          *
+ * 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.63 2008/08/16 19:22:55 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 = (char) !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;
+
+	SetNoPadding(SP);
+	(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 0000000..713d0be
--- /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 0000000..e07f464
--- /dev/null
+++ b/ncurses/tinfo/lib_tgoto.c
@@ -0,0 +1,203 @@
+/****************************************************************************
+ * Copyright (c) 2000-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: Thomas E. Dickey                                                *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+
+#include <ctype.h>
+#include <termcap.h>
+
+MODULE_ID("$Id: lib_tgoto.c,v 1.13 2008/08/16 19:29:32 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++] = (char) *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 0000000..df460f9
--- /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 0000000..ba2a840
--- /dev/null
+++ b/ncurses/tinfo/lib_tparm.c
@@ -0,0 +1,795 @@
+/****************************************************************************
+ * 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                                       *
+ ****************************************************************************/
+
+/*
+ *	tparm.c
+ *
+ */
+
+#include <curses.priv.h>
+
+#include <ctype.h>
+#include <term.h>
+#include <tic.h>
+
+MODULE_ID("$Id: lib_tparm.c,v 1.76 2008/08/16 19:22:55 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)++] = (char) 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--) {
+	    if (p_is_s[i])
+		spush(p_is_s[i]);
+	    else
+		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 0000000..a8b7276
--- /dev/null
+++ b/ncurses/tinfo/lib_tputs.c
@@ -0,0 +1,275 @@
+/****************************************************************************
+ * 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                 *
+ ****************************************************************************/
+
+/*
+ *	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.66 2008/06/28 13:12:15 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 */
+
+#if NCURSES_NO_PADDING
+NCURSES_EXPORT(void)
+_nc_set_no_padding(SCREEN *sp)
+{
+    bool no_padding = (getenv("NCURSES_NO_PADDING") != 0);
+
+    if (sp)
+	sp->_no_padding = no_padding;
+    else
+	_nc_prescreen._no_padding = no_padding;
+
+    TR(TRACE_CHARPUT | TRACE_MOVE, ("padding will%s be used",
+				    GetNoPadding(sp) ? " not" : ""));
+}
+#endif
+
+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
+	    && !GetNoPadding(SP)
+#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 0000000..a2b38a3
--- /dev/null
+++ b/ncurses/tinfo/lib_ttyflags.c
@@ -0,0 +1,220 @@
+/****************************************************************************
+ * 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.18 2008/08/03 22:10:44 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 ? cur_term->Filedes : -1,
+			_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 ? cur_term->Filedes : -1,
+			_nc_trace_ttymode(buf)));
+    }
+    return (result);
+}
+
+NCURSES_EXPORT(int)
+def_shell_mode(void)
+{
+    int rc = ERR;
+
+    T((T_CALLED("def_shell_mode()")));
+
+    if (cur_term != 0) {
+	/*
+	 * If XTABS was on, remove the tab and backtab capabilities.
+	 */
+	if (_nc_get_tty_mode(&cur_term->Ottyb) == OK) {
+#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
+	    rc = OK;
+	}
+    }
+    returnCode(rc);
+}
+
+NCURSES_EXPORT(int)
+def_prog_mode(void)
+{
+    int rc = ERR;
+
+    T((T_CALLED("def_prog_mode()")));
+
+    if (cur_term != 0) {
+	/*
+	 * Turn off the XTABS bit in the tty structure if it was on.
+	 */
+	if (_nc_get_tty_mode(&cur_term->Nttyb) == OK) {
+#ifdef TERMIOS
+	    cur_term->Nttyb.c_oflag &= ~OFLAGS_TABS;
+#else
+	    cur_term->Nttyb.sg_flags &= ~XTABS;
+#endif
+	    rc = OK;
+	}
+    }
+    returnCode(rc);
+}
+
+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 0000000..c084f87
--- /dev/null
+++ b/ncurses/tinfo/make_keys.c
@@ -0,0 +1,148 @@
+/****************************************************************************
+ * 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: Thomas E. Dickey                    1997-on                     *
+ ****************************************************************************/
+
+/*
+ * 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.14 2008/08/03 21:57:22 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[256];
+    char to[256];
+    int maxlen = 16;
+    int scanned;
+
+    while (fgets(buffer, sizeof(buffer), ifp) != 0) {
+	if (*buffer == '#')
+	    continue;
+
+	to[sizeof(to) - 1] = '\0';
+	from[sizeof(from) - 1] = '\0';
+
+	scanned = sscanf(buffer, "%255s %255s", to, from);
+	if (scanned == 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 0000000..d576901
--- /dev/null
+++ b/ncurses/tinfo/name_match.c
@@ -0,0 +1,111 @@
+/****************************************************************************
+ * Copyright (c) 1999-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                    1999-on                     *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+#include <term.h>
+#include <tic.h>
+
+MODULE_ID("$Id: name_match.c,v 1.17 2008/08/03 19:49:33 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);
+    } else
+#endif
+    {
+	if (FirstName == 0)
+	    FirstName = typeMalloc(char, MAX_NAME_SIZE + 1);
+
+	if (FirstName != 0) {
+	    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 0000000..cf7a5f4
--- /dev/null
+++ b/ncurses/tinfo/parse_entry.c
@@ -0,0 +1,997 @@
+/****************************************************************************
+ * 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                 *
+ ****************************************************************************/
+
+/*
+ *	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.69 2008/08/16 21:52:03 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);
+
+    if (entryp->tterm.str_table == 0)
+	return (ERR);
+
+    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.
+		 */
+
+		if (token_type == NUMBER
+		    && !strcmp("ma", _nc_curr_token.tk_name)) {
+		    /* tell max_attributes from arrow_key_map */
+		    entry_ptr = _nc_find_type_entry("ma", NUMBER,
+						    _nc_get_table(_nc_syntax
+								  != 0));
+		    assert(entry_ptr != 0);
+
+		} else if (token_type == STRING
+			   && !strcmp("MT", _nc_curr_token.tk_name)) {
+		    /* map terminfo's string MT to MT */
+		    entry_ptr = _nc_find_type_entry("MT", STRING,
+						    _nc_get_table(_nc_syntax
+								  != 0));
+		    assert(entry_ptr != 0);
+
+		} else if (token_type == BOOLEAN
+			   && entry_ptr->nte_type == STRING) {
+		    /* treat strings without following "=" as empty strings */
+		    token_type = STRING;
+		} else {
+		    /* we couldn't recover; skip this token */
+		    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((char) ((_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;
+	    unsigned 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] = (char) code;
+	temp[1] = (char) 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->from && 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 0000000..b4ea61c
--- /dev/null
+++ b/ncurses/tinfo/read_entry.c
@@ -0,0 +1,546 @@
+/****************************************************************************
+ * 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                 *
+ ****************************************************************************/
+
+/*
+ *	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.102 2008/08/03 19:33:04 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 ((int) 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 (ext_str_count >= (MAX_ENTRY_SIZE * 2))
+		  return (TGETENT_NO);
+	    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 0000000..d94d1a4
--- /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 0000000..ba910e8
--- /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 0000000..78cd2ef
--- /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 0000000..80c8f77
--- /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 0000000..6c3b12f
--- /dev/null
+++ b/ncurses/tinfo/use_screen.c
@@ -0,0 +1,58 @@
+/****************************************************************************
+ * 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.6 2008/06/07 19:16:56 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(curses);
+    save_SP = SP;
+    set_term(screen);
+
+    code = func(screen, data);
+
+    set_term(save_SP);
+    _nc_unlock_global(curses);
+    returnCode(code);
+}
diff --git a/ncurses/tinfo/write_entry.c b/ncurses/tinfo/write_entry.c
new file mode 100644
index 0000000..b53bb21
--- /dev/null
+++ b/ncurses/tinfo/write_entry.c
@@ -0,0 +1,785 @@
+/****************************************************************************
+ * 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                 *
+ ****************************************************************************/
+
+/*
+ *	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.72 2008/08/03 19:24:00 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;
+
+    assert(strlen(tp->term_names) != 0);
+    assert(strlen(tp->term_names) < sizeof(name_list));
+
+    (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++;
+	assert(ptr < buffer + sizeof(buffer) - 1);
+	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]), (int) 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));
+
+	if (tp->ext_Strings >= SIZEOF(offsets))
+	    return (ERR);
+
+	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;
+}