Index: Makefile.in
--- Makefile.in.orig	2009-09-24 17:03:09 +0200
+++ Makefile.in	2009-09-26 17:15:52 +0200
@@ -1,158 +1,70 @@
-LIBS = -lslang
-LIBTCL = -ltcl8.4
 
-CC = @CC@
-CPP = @CPP@
-CFLAGS = @CFLAGS@
-CPPFLAGS = -D_GNU_SOURCE -I/usr/include/slang @CPPFLAGS@ 
-
-SHLIBFLAGS= -Wl,--version-script,newt.0.52.ver
-VERSION = @VERSION@
-TAG = r$(subst .,-,$(VERSION))
-SONAME = @SONAME@
-
-PYTHONVERS = @PYTHONVERS@
-WHIPTCLSO = @WHIPTCLSO@
-
-PROGS = test whiptail $(WHIPTCLSO) testgrid testtree showchars showkey
-TESTOBJS = test.o testgrid.o testtree.o showchars.o showkey.o
-NDIALOGOBJS = whiptail.o dialogboxes.o
-WHIPTCLOBJS = shared/whiptcl.o shared/dialogboxes.o
-LIBNEWT = libnewt.a
-LIBNEWTSH = libnewt.so.$(VERSION)
-LIBNEWTSONAME = libnewt.so.$(SONAME)
-LIBOBJS = newt.o button.o form.o checkbox.o entry.o label.o listbox.o \
-          scrollbar.o textbox.o scale.o grid.o windows.o buttonbar.o \
-	  checkboxtree.o
-
-SHCFLAGS = -fPIC
-
-prefix = @prefix@
-includedir = @includedir@
-exec_prefix = @exec_prefix@
-libdir = @libdir@
-bindir = @bindir@
-datadir = @datadir@
-mandir = @mandir@
-man1dir = $(mandir)/man1
-pkgconfigdir = $(libdir)/pkgconfig
-
-#--------------------------------------
-
-SOURCES = $(subst .o,.c,$(TESTOBJS) $(NDIALOGOBJS) $(LIBOBJS))
-
-SHAREDDIR = shared
-SHAREDOBJS = $(patsubst %,$(SHAREDDIR)/%, $(LIBOBJS))
-
-ifeq (.depend,$(wildcard .depend))
-TARGET=$(PROGS)
-else
-TARGET=depend $(PROGS)
-endif
-
-all:	$(TARGET) _snackmodule.so
-
-test:	test.o $(LIBNEWT)
-	$(CC) -g -o test test.o $(LIBNEWT) $(LIBS)
-
-testgrid:	testgrid.o $(LIBNEWT)
-	$(CC) -g -o testgrid testgrid.o $(LIBNEWT) $(LIBS)
-
-testtree:	testtree.o $(LIBNEWT)
-	$(CC) -g -o testtree testtree.o $(LIBNEWT) $(LIBS)
-
-showchars:	showchars.o $(LIBNEWT)
-	$(CC) -g -o showchars showchars.o $(LIBNEWT) $(LIBS)
-
-showkey:	showkey.o $(LIBNEWT)
-	$(CC) -g -o showkey showkey.o $(LIBNEWT) $(LIBS)
-
-_snackmodule.so:   snackmodule.c $(LIBNEWTSH)
-	for ver in $(PYTHONVERS) ; do \
-	    	mkdir -p $$ver ;\
-	        $(CC) $(CFLAGS) -I/usr/include/$$ver $(SHCFLAGS) -c -o $$ver/snackmodule.o snackmodule.c ;\
-		$(CC) --shared $(SHCFLAGS) -o $$ver/_snackmodule.so $$ver/snackmodule.o -L .  -lnewt ;\
-	done
-	touch $@
-
-whiptail: $(NDIALOGOBJS) $(LIBNEWTSH)
-	$(CC) -g -o whiptail $(NDIALOGOBJS) -L . -lnewt $(LIBS) -lpopt
-
-whiptcl.so: $(WHIPTCLOBJS) $(LIBNEWTSH)
-	$(CC) -shared $(SHCFLAGS) -o whiptcl.so $(WHIPTCLOBJS) -L . -lnewt  $(LIBTCL) -lpopt
-
-$(LIBNEWT): $(LIBOBJS)
-	ar rv $@ $^
-
-newt.o $(SHAREDDIR)/newt.o: newt.c Makefile
-
-veryclean: clean
-	rm -f .depend
+CC            = @CC@
+CFLAGS        = @CFLAGS@
+CPPFLAGS      = @CPPFLAGS@
+LDFLAGS       = @LDFLAGS@
+LIBS          = -lslang -lpopt -lintl -liconv -lm @LIBS@ 
+RM            = rm -f
+AR            = ar
+RANLIB        = ranlib
+SHTOOL        = sh ./shtool
+
+LIBNEWT       = libnewt.a
+TARGETS       = $(LIB) test whiptail testgrid testtree
+OBJS_LIBNEWT  = newt.o button.o form.o checkbox.o entry.o label.o listbox.o \
+                scrollbar.o textbox.o scale.o grid.o windows.o buttonbar.o \
+                checkboxtree.o
+OBJS_TEST     = test.o
+OBJS_TESTGRID = testgrid.o
+OBJS_TESTTREE = testtree.o
+OBJS_WHIPTAIL = whiptail.o dialogboxes.o
+
+DESTDIR       =
+prefix        = @prefix@
+exec_prefix   = @exec_prefix@
+bindir        = @bindir@
+libdir        = @libdir@
+includedir    = @includedir@
+mandir        = @mandir@
+
+.SUFFIXES: .c .o
+
+.c.o:
+	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+all: $(LIBNEWT) $(TARGETS)
+
+test: $(OBJS_TEST) $(LIBNEWT)
+	$(CC) -o $@ $(OBJS_TEST) $(LIBNEWT) $(LDFLAGS) $(LIBS)
+
+testgrid: $(OBJS_TESTGRID) $(LIBNEWT)
+	$(CC) -o $@ $(OBJS_TESTGRID) $(LIBNEWT) $(LDFLAGS) $(LIBS)
+
+testtree: $(OBJS_TESTTREE) $(LIBNEWT)
+	$(CC) -o $@ $(OBJS_TESTTREE) $(LIBNEWT) $(LDFLAGS) $(LIBS)
+
+whiptail: $(OBJS_WHIPTAIL) $(LIBNEWT)
+	$(CC) -o $@ $(OBJS_WHIPTAIL) $(LIBNEWT) $(LDFLAGS) $(LIBS)
+
+$(LIBNEWT): $(OBJS_LIBNEWT)
+	$(RM) $@
+	$(AR) rc $@ $(OBJS_LIBNEWT)
+	$(RANLIB) $@
 
 clean:
-	rm -f $(PROGS) *.o $(LIBNEWT) core $(LIBNEWTSH)  \
-		$(SHAREDDIR)/*.o *.so* *.pc
-
-depend:
-	$(CPP) $(CFLAGS) $(CPPFLAGS) -M $(SOURCES) > .depend
+	$(RM) $(LIBNEWT) $(TARGETS) *.o
 
-$(SHAREDDIR):
-	mkdir -p $(SHAREDDIR)
+distclean: clean
+	$(RM) config.cache config.status config.log
+	$(RM) Makefile
+
+install: all
+	$(SHTOOL) mkdir -p -m 755 $(DESTDIR)$(bindir)
+	$(SHTOOL) mkdir -p -m 755 $(DESTDIR)$(libdir)
+	$(SHTOOL) mkdir -p -m 755 $(DESTDIR)$(includedir)
+	$(SHTOOL) mkdir -p -m 755 $(DESTDIR)$(mandir)/man1
+	$(SHTOOL) install -c -m 644 newt.h $(DESTDIR)$(includedir)/
+	$(SHTOOL) install -c -m 644 $(LIBNEWT) $(DESTDIR)$(libdir)/
+	$(SHTOOL) install -c -m 755 -s whiptail $(DESTDIR)$(bindir)/
+	$(SHTOOL) install -c -m 644 whiptail.1 $(DESTDIR)$(mandir)/man1/
 
-sharedlib: $(LIBNEWTSH)
-
-$(LIBNEWTSH): $(SHAREDDIR) $(SHAREDOBJS)
-	$(CC) -shared -o $(LIBNEWTSH) $(SHLIBFLAGS) -Wl,-soname,$(LIBNEWTSONAME) $(SHAREDOBJS) $(LIBS)
-	ln -fs $(LIBNEWTSONAME) libnewt.so
-	ln -fs $(LIBNEWTSH) $(LIBNEWTSONAME)
-
-$(SHAREDDIR)/%.o : %.c
-	$(CC) $(SHCFLAGS) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
-
-install: $(LIBNEWT) install-sh whiptail
-	[ -d $(instroot)/$(bindir) ] || install -m 755 -d $(instroot)/$(bindir)
-	[ -d $(instroot)/$(libdir) ] || install -m 755 -d $(instroot)/$(libdir)
-	[ -d $(instroot)/$(includedir) ] || install -m 755 -d $(instroot)/$(includedir)
-	[ -d $(instroot)/$(man1dir) ] || install -m 755 -d $(instroot)/$(man1dir)
-	install -m 644 newt.h $(instroot)/$(includedir)
-	install -m 644 $(LIBNEWT) $(instroot)/$(libdir)
-	install -m 755 whiptail $(instroot)/$(bindir)
-	install -m 644 whiptail.1 $(instroot)/$(man1dir)
-	make -C po datadir=$(instroot)/$(datadir) install
-	install -m 644 -D libnewt.pc $(instroot)/$(pkgconfigdir)/libnewt.pc
-
-install-sh: sharedlib $(WHIPTCLSO) _snackmodule.so
-	[ -d $(instroot)/$(libdir) ] || install -m 755 -d $(instroot)/$(libdir)
-	install -m 755 $(LIBNEWTSH) $(instroot)/$(libdir)
-	ln -sf $(LIBNEWTSONAME) $(instroot)/$(libdir)/libnewt.so
-	ln -sf $(LIBNEWTSH) $(instroot)/$(libdir)/$(LIBNEWTSONAME)
-	[ -n "$(WHIPTCLSO)" ] && install -m 755 whiptcl.so $(instroot)/$(libdir) || :
-	for ver in $(PYTHONVERS) ; do \
-	   [ -d $(instroot)/$(libdir)/$$ver/site-packages ] || install -m 755 -d $(instroot)/$(libdir)/$$ver/site-packages ;\
-	   install -m 755 $$ver/_snackmodule.so $(instroot)/$(libdir)/$$ver/site-packages ;\
-	   install -m 644 snack.py $(instroot)/$(libdir)/$$ver/site-packages ;\
-	done
-
-Makefile: newt.spec
-	echo "You need to rerun ./configure before continuing"
-	@exit 1
-
-create-archive: Makefile
-	@rm -rf /tmp/newt-$(VERSION)
-	@git archive --prefix=newt-$(VERSION)/ $(TAG) | tar x -C /tmp
-	@cd /tmp/newt-$(VERSION) && ./autogen.sh && rm -rf autom4te.cache
-	@cd /tmp; tar czSpf newt-$(VERSION).tar.gz newt-$(VERSION)
-	@rm -rf /tmp/newt-$(VERSION)
-	@cp /tmp/newt-$(VERSION).tar.gz .
-	@rm -f /tmp/newt-$(VERSION).tar.gz
-	@echo " "
-	@echo "The final archive is ./newt-$(VERSION).tar.gz."
-
-tag-archive: Makefile
-	@git tag $(TAG)
-
-archive: tag-archive create-archive
-
-ifeq (.depend,$(wildcard .depend))
-include .depend
-endif
Index: newt.c
--- newt.c.orig	2009-09-24 17:03:09 +0200
+++ newt.c	2009-09-26 15:38:12 +0200
@@ -9,7 +9,9 @@
 #include <sys/types.h>
 #include <termios.h>
 #include <unistd.h>
+#ifdef HAVE_WCHAR
 #include <wchar.h>
+#endif
 
 #ifdef HAVE_ALLOCA_H
 #include <alloca.h>
@@ -156,13 +158,16 @@
 }
 
 int _newt_wstrlen(const char *str, int len) {
+#ifdef HAVE_WCHAR
 	mbstate_t ps;
 	wchar_t tmp;
+#endif
 	int nchars = 0;
 	
 	if (!str) return 0;
 	if (!len) return 0;
 	if (len < 0) len = strlen(str);
+#ifdef HAVE_WCHAR
 	memset(&ps,0,sizeof(mbstate_t));
 	while (len > 0) {
 		int x,y;
@@ -176,6 +181,9 @@
 			  nchars+=y;
 		} else break;
 	}
+#else
+        nchars = len;
+#endif
 	return nchars;
 }
 
@@ -188,19 +196,25 @@
 	char *p = title;
 	int ln;
 	int x = 0,y = 0;
+#ifdef FIXME
 	wchar_t tmp;
 	mbstate_t ps;
 
 	memset(&ps, 0, sizeof(ps));
+#endif
 	ln = strlen(title);
 
 	while (*p) {
+#ifdef FIXME
 		x = mbrtowc(&tmp, p, ln, &ps);
+#endif
 		if (x < 0) { // error
 			*p = '\0';
 			return;
 		}
+#ifdef FIXME
 		y = wcwidth(tmp);
+#endif
 		if (y > chrs) {
 			*p = '\0';
 			return;
Index: shtool
--- /dev/null	2009-09-26 17:15:39 +0200
+++ shtool	2009-09-26 15:38:12 +0200
@@ -0,0 +1,661 @@
+#!/bin/sh
+##
+##  GNU shtool -- The GNU Portable Shell Tool
+##  Copyright (c) 1994-2005 Ralf S. Engelschall <rse@engelschall.com>
+##
+##  See http://www.gnu.org/software/shtool/ for more information.
+##  See ftp://ftp.gnu.org/gnu/shtool/ for latest version.
+##
+##  Version:  2.0.2 (15-Jun-2005)
+##  Contents: 2/19 available modules
+##
+
+##
+##  This program is free software; you can redistribute it and/or modify
+##  it under the terms of the GNU General Public License as published by
+##  the Free Software Foundation; either version 2 of the License, or
+##  (at your option) any later version.
+##
+##  This program is distributed in the hope that it will be useful,
+##  but WITHOUT ANY WARRANTY; without even the implied warranty of
+##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+##  General Public License for more details.
+##
+##  You should have received a copy of the GNU General Public License
+##  along with this program; if not, write to the Free Software
+##  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+##  USA, or contact Ralf S. Engelschall <rse@engelschall.com>.
+##
+##  NOTICE: Given that you include this file verbatim into your own
+##  source tree, you are justified in saying that it remains separate
+##  from your package, and that this way you are simply just using GNU
+##  shtool. So, in this situation, there is no requirement that your
+##  package itself is licensed under the GNU General Public License in
+##  order to take advantage of GNU shtool.
+##
+
+##
+##  Usage: shtool [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]
+##
+##  Available commands:
+##    install    Install a program, script or datafile
+##    mkdir      Make one or more directories
+##
+##  Not available commands (because module was not built-in):
+##    echo       Print string with optional construct expansion
+##    mdate      Pretty-print modification time of a file or dir
+##    table      Pretty-print a field-separated list as a table
+##    prop       Display progress with a running propeller
+##    move       Move files with simultaneous substitution
+##    mkln       Make link with calculation of relative paths
+##    mkshadow   Make a shadow tree through symbolic links
+##    fixperm    Fix file permissions inside a source tree
+##    rotate     Logfile rotation
+##    tarball    Roll distribution tarballs
+##    subst      Apply sed(1) substitution operations
+##    platform   Platform Identification Utility
+##    arx        Extended archive command
+##    slo        Separate linker options by library class
+##    scpp       Sharing C Pre-Processor
+##    version    Maintain a version information file
+##    path       Deal with program paths
+##
+
+if [ $# -eq 0 ]; then
+    echo "$0:Error: invalid command line" 1>&2
+    echo "$0:Hint:  run \`$0 -h' for usage" 1>&2
+    exit 1
+fi
+if [ ".$1" = ".-h" ] || [ ".$1" = ".--help" ]; then
+    echo "This is GNU shtool, version 2.0.2 (15-Jun-2005)"
+    echo "Copyright (c) 1994-2005 Ralf S. Engelschall <rse@engelschall.com>"
+    echo "Report bugs to <bug-shtool@gnu.org>"
+    echo ''
+    echo "Usage: shtool [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]"
+    echo ''
+    echo 'Available global <options>:'
+    echo '  -v, --version   display shtool version information'
+    echo '  -h, --help      display shtool usage help page (this one)'
+    echo '  -d, --debug     display shell trace information'
+    echo '  -r, --recreate  recreate this shtool script via shtoolize'
+    echo ''
+    echo 'Available <cmd-name> [<cmd-options>] [<cmd-args>]:'
+    echo '  install  [-v|--verbose] [-t|--trace] [-d|--mkdir] [-c|--copy]'
+    echo '           [-C|--compare-copy] [-s|--strip] [-m|--mode <mode>]'
+    echo '           [-o|--owner <owner>] [-g|--group <group>] [-e|--exec'
+    echo '           <sed-cmd>] <file> [<file> ...] <path>'
+    echo '  mkdir    [-t|--trace] [-f|--force] [-p|--parents] [-m|--mode'
+    echo '           <mode>] [-o|--owner <owner>] [-g|--group <group>] <dir>'
+    echo '           [<dir> ...]'
+    echo ''
+    echo 'Not available <cmd-name> (because module was not built-in):'
+    echo '  echo     [-n|--newline] [-e|--expand] [<string> ...]'
+    echo '  mdate    [-n|--newline] [-z|--zero] [-s|--shorten] [-d|--digits]'
+    echo '           [-f|--field-sep <str>] [-o|--order <spec>] <path>'
+    echo '  table    [-F|--field-sep <sep>] [-w|--width <width>] [-c|--columns'
+    echo '           <cols>] [-s|--strip <strip>] <str><sep><str>...'
+    echo '  prop     [-p|--prefix <str>]'
+    echo '  move     [-v|--verbose] [-t|--trace] [-e|--expand] [-p|--preserve]'
+    echo '           <src-file> <dst-file>'
+    echo '  mkln     [-t|--trace] [-f|--force] [-s|--symbolic] <src-path>'
+    echo '           [<src-path> ...] <dst-path>'
+    echo '  mkshadow [-v|--verbose] [-t|--trace] [-a|--all] <src-dir> <dst-dir>'
+    echo '  fixperm  [-v|--verbose] [-t|--trace] <path> [<path> ...]'
+    echo '  rotate   [-v|--verbose] [-t|--trace] [-f|--force] [-n|--num-files'
+    echo '           <count>] [-s|--size <size>] [-c|--copy] [-r|--remove]'
+    echo '           [-a|--archive-dir <dir>] [-z|--compress [<tool>:]<level>]'
+    echo '           [-b|--background] [-d|--delay] [-p|--pad <len>] [-m|--mode'
+    echo '           <mode>] [-o|--owner <owner>] [-g|--group <group>] [-M|--migrate'
+    echo '           <cmd>] [-P|--prolog <cmd>] [-E|--epilog <cmd>] <file> [...]'
+    echo '  tarball  [-t|--trace] [-v|--verbose] [-o|--output <tarball>]'
+    echo '           [-c|--compress <prog>] [-d|--directory <dir>] [-u|--user'
+    echo '           <user>] [-g|--group <group>] [-e|--exclude <pattern>]'
+    echo '           <path> [<path> ...]'
+    echo '  subst    [-v|--verbose] [-t|--trace] [-n|--nop] [-w|--warning]'
+    echo '           [-q|--quiet] [-s|--stealth] [-i|--interactive] [-b|--backup'
+    echo '           <ext>] [-e|--exec <cmd>] [-f|--file <cmd-file>] [<file>]'
+    echo '           [...]'
+    echo '  platform [-F|--format <format>] [-S|--sep <string>] [-C|--conc'
+    echo '           <string>] [-L|--lower] [-U|--upper] [-v|--verbose]'
+    echo '           [-c|--concise] [-n|--no-newline] [-t|--type <type>]'
+    echo '           [-V|--version] [-h|--help]'
+    echo '  arx      [-t|--trace] [-C|--command <cmd>] <op> <archive> [<file>'
+    echo '           ...]'
+    echo '  slo      [-p|--prefix <str>] -- -L<dir> -l<lib> [-L<dir> -l<lib>'
+    echo '           ...]'
+    echo '  scpp     [-v|--verbose] [-p|--preserve] [-f|--filter <filter>]'
+    echo '           [-o|--output <ofile>] [-t|--template <tfile>] [-M|--mark'
+    echo '           <mark>] [-D|--define <dname>] [-C|--class <cname>]'
+    echo '           <file> [<file> ...]'
+    echo '  version  [-l|--language <lang>] [-n|--name <name>] [-p|--prefix'
+    echo '           <prefix>] [-s|--set <version>] [-e|--edit] [-i|--increase'
+    echo '           <knob>] [-d|--display <type>] <file>'
+    echo '  path     [-s|--suppress] [-r|--reverse] [-d|--dirname] [-b|--basename]'
+    echo '           [-m|--magic] [-p|--path <path>] <str> [<str> ...]'
+    echo ''
+    exit 0
+fi
+if [ ".$1" = ".-v" ] || [ ".$1" = ".--version" ]; then
+    echo "GNU shtool 2.0.2 (15-Jun-2005)"
+    exit 0
+fi
+if [ ".$1" = ".-r" ] || [ ".$1" = ".--recreate" ]; then
+    shtoolize -oshtool install mkdir
+    exit 0
+fi
+if [ ".$1" = ".-d" ] || [ ".$1" = ".--debug" ]; then
+    shift
+    set -x
+fi
+name=`echo "$0" | sed -e 's;.*/\([^/]*\)$;\1;' -e 's;-sh$;;' -e 's;\.sh$;;'`
+case "$name" in
+    install|mkdir )
+        #   implicit tool command selection
+        tool="$name"
+        ;;
+    * )
+        #   explicit tool command selection
+        tool="$1"
+        shift
+        ;;
+esac
+arg_spec=""
+opt_spec=""
+gen_tmpfile=no
+
+##
+##  DISPATCH INTO SCRIPT PROLOG
+##
+
+case $tool in
+    install )
+        str_tool="install"
+        str_usage="[-v|--verbose] [-t|--trace] [-d|--mkdir] [-c|--copy] [-C|--compare-copy] [-s|--strip] [-m|--mode <mode>] [-o|--owner <owner>] [-g|--group <group>] [-e|--exec <sed-cmd>] <file> [<file> ...] <path>"
+        arg_spec="1+"
+        opt_spec="v.t.d.c.C.s.m:o:g:e+"
+        opt_alias="v:verbose,t:trace,d:mkdir,c:copy,C:compare-copy,s:strip,m:mode,o:owner,g:group,e:exec"
+        opt_v=no
+        opt_t=no
+        opt_d=no
+        opt_c=no
+        opt_C=no
+        opt_s=no
+        opt_m="0755"
+        opt_o=""
+        opt_g=""
+        opt_e=""
+        ;;
+    mkdir )
+        str_tool="mkdir"
+        str_usage="[-t|--trace] [-f|--force] [-p|--parents] [-m|--mode <mode>] [-o|--owner <owner>] [-g|--group <group>] <dir> [<dir> ...]"
+        arg_spec="1+"
+        opt_spec="t.f.p.m:o:g:"
+        opt_alias="t:trace,f:force,p:parents,m:mode,o:owner,g:group"
+        opt_t=no
+        opt_f=no
+        opt_p=no
+        opt_m=""
+        opt_o=""
+        opt_g=""
+        ;;
+    -* )
+        echo "$0:Error: unknown option \`$tool'" 2>&1
+        echo "$0:Hint:  run \`$0 -h' for usage" 2>&1
+        exit 1
+        ;;
+    * )
+        echo "$0:Error: unknown command \`$tool'" 2>&1
+        echo "$0:Hint:  run \`$0 -h' for usage" 2>&1
+        exit 1
+        ;;
+esac
+
+##
+##  COMMON UTILITY CODE
+##
+
+#   commonly used ASCII values
+ASC_TAB="	"
+ASC_NL="
+"
+
+#   determine name of tool
+if [ ".$tool" != . ]; then
+    #   used inside shtool script
+    toolcmd="$0 $tool"
+    toolcmdhelp="shtool $tool"
+    msgprefix="shtool:$tool"
+else
+    #   used as standalone script
+    toolcmd="$0"
+    toolcmdhelp="sh $0"
+    msgprefix="$str_tool"
+fi
+
+#   parse argument specification string
+eval `echo $arg_spec |\
+      sed -e 's/^\([0-9]*\)\([+=]\)/arg_NUMS=\1; arg_MODE=\2/'`
+
+#   parse option specification string
+eval `echo h.$opt_spec |\
+      sed -e 's/\([a-zA-Z0-9]\)\([.:+]\)/opt_MODE_\1=\2;/g'`
+
+#   parse option alias string
+eval `echo h:help,$opt_alias |\
+      sed -e 's/-/_/g' -e 's/\([a-zA-Z0-9]\):\([^,]*\),*/opt_ALIAS_\2=\1;/g'`
+
+#   interate over argument line
+opt_PREV=''
+while [ $# -gt 0 ]; do
+    #   special option stops processing
+    if [ ".$1" = ".--" ]; then
+        shift
+        break
+    fi
+
+    #   determine option and argument
+    opt_ARG_OK=no
+    if [ ".$opt_PREV" != . ]; then
+        #   merge previous seen option with argument
+        opt_OPT="$opt_PREV"
+        opt_ARG="$1"
+        opt_ARG_OK=yes
+        opt_PREV=''
+    else
+        #   split argument into option and argument
+        case "$1" in
+            --[a-zA-Z0-9]*=*)
+                eval `echo "x$1" |\
+                      sed -e 's/^x--\([a-zA-Z0-9-]*\)=\(.*\)$/opt_OPT="\1";opt_ARG="\2"/'`
+                opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'`
+                eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
+                ;;
+            --[a-zA-Z0-9]*)
+                opt_OPT=`echo "x$1" | cut -c4-`
+                opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'`
+                eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
+                opt_ARG=''
+                ;;
+            -[a-zA-Z0-9]*)
+                eval `echo "x$1" |\
+                      sed -e 's/^x-\([a-zA-Z0-9]\)/opt_OPT="\1";/' \
+                          -e 's/";\(.*\)$/"; opt_ARG="\1"/'`
+                ;;
+            -[a-zA-Z0-9])
+                opt_OPT=`echo "x$1" | cut -c3-`
+                opt_ARG=''
+                ;;
+            *)
+                break
+                ;;
+        esac
+    fi
+
+    #   eat up option
+    shift
+
+    #   determine whether option needs an argument
+    eval "opt_MODE=\$opt_MODE_${opt_OPT}"
+    if [ ".$opt_ARG" = . ] && [ ".$opt_ARG_OK" != .yes ]; then
+        if [ ".$opt_MODE" = ".:" ] || [ ".$opt_MODE" = ".+" ]; then
+            opt_PREV="$opt_OPT"
+            continue
+        fi
+    fi
+
+    #   process option
+    case $opt_MODE in
+        '.' )
+            #   boolean option
+            eval "opt_${opt_OPT}=yes"
+            ;;
+        ':' )
+            #   option with argument (multiple occurances override)
+            eval "opt_${opt_OPT}=\"\$opt_ARG\""
+            ;;
+        '+' )
+            #   option with argument (multiple occurances append)
+            eval "opt_${opt_OPT}=\"\$opt_${opt_OPT}\${ASC_NL}\$opt_ARG\""
+            ;;
+        * )
+            echo "$msgprefix:Error: unknown option: \`$opt_OPT'" 1>&2
+            echo "$msgprefix:Hint:  run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2
+            exit 1
+            ;;
+    esac
+done
+if [ ".$opt_PREV" != . ]; then
+    echo "$msgprefix:Error: missing argument to option \`$opt_PREV'" 1>&2
+    echo "$msgprefix:Hint:  run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2
+    exit 1
+fi
+
+#   process help option
+if [ ".$opt_h" = .yes ]; then
+    echo "Usage: $toolcmdhelp $str_usage"
+    exit 0
+fi
+
+#   complain about incorrect number of arguments
+case $arg_MODE in
+    '=' )
+        if [ $# -ne $arg_NUMS ]; then
+            echo "$msgprefix:Error: invalid number of arguments (exactly $arg_NUMS expected)" 1>&2
+            echo "$msgprefix:Hint:  run \`$toolcmd -h' or \`man shtool' for details" 1>&2
+            exit 1
+        fi
+        ;;
+    '+' )
+        if [ $# -lt $arg_NUMS ]; then
+            echo "$msgprefix:Error: invalid number of arguments (at least $arg_NUMS expected)" 1>&2
+            echo "$msgprefix:Hint:  run \`$toolcmd -h' or \`man shtool' for details" 1>&2
+            exit 1
+        fi
+        ;;
+esac
+
+#   establish a temporary file on request
+if [ ".$gen_tmpfile" = .yes ]; then
+    #   create (explicitly) secure temporary directory
+    if [ ".$TMPDIR" != . ]; then
+        tmpdir="$TMPDIR"
+    elif [ ".$TEMPDIR" != . ]; then
+        tmpdir="$TEMPDIR"
+    else
+        tmpdir="/tmp"
+    fi
+    tmpdir="$tmpdir/.shtool.$$"
+    ( umask 077
+      rm -rf "$tmpdir" >/dev/null 2>&1 || true
+      mkdir  "$tmpdir" >/dev/null 2>&1
+      if [ $? -ne 0 ]; then
+          echo "$msgprefix:Error: failed to create temporary directory \`$tmpdir'" 1>&2
+          exit 1
+      fi
+    )
+
+    #   create (implicitly) secure temporary file
+    tmpfile="$tmpdir/shtool.tmp"
+    touch "$tmpfile"
+fi
+
+#   utility function: map string to lower case
+util_lower () {
+    echo "$1" | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'
+}
+
+#   utility function: map string to upper case
+util_upper () {
+    echo "$1" | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+}
+
+#   cleanup procedure
+shtool_exit () {
+    rc="$1"
+    if [ ".$gen_tmpfile" = .yes ]; then
+        rm -rf "$tmpdir" >/dev/null 2>&1 || true
+    fi
+    exit $rc
+}
+
+##
+##  DISPATCH INTO SCRIPT BODY
+##
+
+case $tool in
+
+install )
+    ##
+    ##  install -- Install a program, script or datafile
+    ##  Copyright (c) 1997-2005 Ralf S. Engelschall <rse@engelschall.com>
+    ##
+
+    #   special case: "shtool install -d <dir> [...]" internally
+    #   maps to "shtool mkdir -f -p -m 755 <dir> [...]"
+    if [ "$opt_d" = yes ]; then
+        cmd="$0 mkdir -f -p -m 755"
+        if [ ".$opt_o" != . ]; then
+            cmd="$cmd -o '$opt_o'"
+        fi
+        if [ ".$opt_g" != . ]; then
+            cmd="$cmd -g '$opt_g'"
+        fi
+        if [ ".$opt_v" = .yes ]; then
+            cmd="$cmd -v"
+        fi
+        if [ ".$opt_t" = .yes ]; then
+            cmd="$cmd -t"
+        fi
+        for dir in "$@"; do
+            eval "$cmd $dir" || shtool_exit $?
+        done
+        shtool_exit 0
+    fi
+
+    #   determine source(s) and destination
+    argc=$#
+    srcs=""
+    while [ $# -gt 1 ]; do
+        srcs="$srcs $1"
+        shift
+    done
+    dstpath="$1"
+
+    #   type check for destination
+    dstisdir=0
+    if [ -d $dstpath ]; then
+        dstpath=`echo "$dstpath" | sed -e 's:/$::'`
+        dstisdir=1
+    fi
+
+    #   consistency check for destination
+    if [ $argc -gt 2 ] && [ $dstisdir = 0 ]; then
+        echo "$msgprefix:Error: multiple sources require destination to be directory" 1>&2
+        shtool_exit 1
+    fi
+
+    #   iterate over all source(s)
+    for src in $srcs; do
+        dst=$dstpath
+
+        #   if destination is a directory, append the input filename
+        if [ $dstisdir = 1 ]; then
+            dstfile=`echo "$src" | sed -e 's;.*/\([^/]*\)$;\1;'`
+            dst="$dst/$dstfile"
+        fi
+
+        #   check for correct arguments
+        if [ ".$src" = ".$dst" ]; then
+            echo "$msgprefix:Warning: source and destination are the same - skipped" 1>&2
+            continue
+        fi
+        if [ -d "$src" ]; then
+            echo "$msgprefix:Warning: source \`$src' is a directory - skipped" 1>&2
+            continue
+        fi
+
+        #   make a temp file name in the destination directory
+        dsttmp=`echo $dst |\
+                sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;' -e 's;^$;.;' \
+                    -e "s;\$;/#INST@$$#;"`
+
+        #   verbosity
+        if [ ".$opt_v" = .yes ]; then
+            echo "$src -> $dst" 1>&2
+        fi
+
+        #   copy or move the file name to the temp name
+        #   (because we might be not allowed to change the source)
+        if [ ".$opt_C" = .yes ]; then
+            opt_c=yes
+        fi
+        if [ ".$opt_c" = .yes ]; then
+            if [ ".$opt_t" = .yes ]; then
+                echo "cp $src $dsttmp" 1>&2
+            fi
+            cp $src $dsttmp || shtool_exit $?
+        else
+            if [ ".$opt_t" = .yes ]; then
+                echo "mv $src $dsttmp" 1>&2
+            fi
+            mv $src $dsttmp || shtool_exit $?
+        fi
+
+        #   adjust the target file
+        if [ ".$opt_e" != . ]; then
+            sed='sed'
+            OIFS="$IFS"; IFS="$ASC_NL"; set -- $opt_e; IFS="$OIFS"
+            for e
+            do
+                sed="$sed -e '$e'"
+            done
+            cp $dsttmp $dsttmp.old
+            chmod u+w $dsttmp
+            eval "$sed <$dsttmp.old >$dsttmp" || shtool_exit $?
+            rm -f $dsttmp.old
+        fi
+        if [ ".$opt_s" = .yes ]; then
+            if [ ".$opt_t" = .yes ]; then
+                echo "strip $dsttmp" 1>&2
+            fi
+            strip $dsttmp || shtool_exit $?
+        fi
+        if [ ".$opt_o" != . ]; then
+            if [ ".$opt_t" = .yes ]; then
+                echo "chown $opt_o $dsttmp" 1>&2
+            fi
+            chown $opt_o $dsttmp || shtool_exit $?
+        fi
+        if [ ".$opt_g" != . ]; then
+            if [ ".$opt_t" = .yes ]; then
+                echo "chgrp $opt_g $dsttmp" 1>&2
+            fi
+            chgrp $opt_g $dsttmp || shtool_exit $?
+        fi
+        if [ ".$opt_m" != ".-" ]; then
+            if [ ".$opt_t" = .yes ]; then
+                echo "chmod $opt_m $dsttmp" 1>&2
+            fi
+            chmod $opt_m $dsttmp || shtool_exit $?
+        fi
+
+        #   determine whether to do a quick install
+        #   (has to be done _after_ the strip was already done)
+        quick=no
+        if [ ".$opt_C" = .yes ]; then
+            if [ -r $dst ]; then
+                if cmp -s $src $dst; then
+                    quick=yes
+                fi
+            fi
+        fi
+
+        #   finally, install the file to the real destination
+        if [ $quick = yes ]; then
+            if [ ".$opt_t" = .yes ]; then
+                echo "rm -f $dsttmp" 1>&2
+            fi
+            rm -f $dsttmp
+        else
+            if [ ".$opt_t" = .yes ]; then
+                echo "rm -f $dst && mv $dsttmp $dst" 1>&2
+            fi
+            rm -f $dst && mv $dsttmp $dst
+        fi
+    done
+
+    shtool_exit 0
+    ;;
+
+mkdir )
+    ##
+    ##  mkdir -- Make one or more directories
+    ##  Copyright (c) 1996-2005 Ralf S. Engelschall <rse@engelschall.com>
+    ##
+
+    errstatus=0
+    for p in ${1+"$@"}; do
+        #   if the directory already exists...
+        if [ -d "$p" ]; then
+            if [ ".$opt_f" = .no ] && [ ".$opt_p" = .no ]; then
+                echo "$msgprefix:Error: directory already exists: $p" 1>&2
+                errstatus=1
+                break
+            else
+                continue
+            fi
+        fi
+        #   if the directory has to be created...
+        if [ ".$opt_p" = .no ]; then
+            if [ ".$opt_t" = .yes ]; then
+                echo "mkdir $p" 1>&2
+            fi
+            mkdir $p || errstatus=$?
+            if [ ".$opt_o" != . ]; then
+                if [ ".$opt_t" = .yes ]; then
+                    echo "chown $opt_o $p" 1>&2
+                fi
+                chown $opt_o $p || errstatus=$?
+            fi
+            if [ ".$opt_g" != . ]; then
+                if [ ".$opt_t" = .yes ]; then
+                    echo "chgrp $opt_g $p" 1>&2
+                fi
+                chgrp $opt_g $p || errstatus=$?
+            fi
+            if [ ".$opt_m" != . ]; then
+                if [ ".$opt_t" = .yes ]; then
+                    echo "chmod $opt_m $p" 1>&2
+                fi
+                chmod $opt_m $p || errstatus=$?
+            fi
+        else
+            #   the smart situation
+            set fnord `echo ":$p" |\
+                       sed -e 's/^:\//%/' \
+                           -e 's/^://' \
+                           -e 's/\// /g' \
+                           -e 's/^%/\//'`
+            shift
+            pathcomp=''
+            for d in ${1+"$@"}; do
+                pathcomp="$pathcomp$d"
+                case "$pathcomp" in
+                    -* ) pathcomp="./$pathcomp" ;;
+                esac
+                if [ ! -d "$pathcomp" ]; then
+                    if [ ".$opt_t" = .yes ]; then
+                        echo "mkdir $pathcomp" 1>&2
+                    fi
+                    mkdir $pathcomp || errstatus=$?
+                    if [ ".$opt_o" != . ]; then
+                        if [ ".$opt_t" = .yes ]; then
+                            echo "chown $opt_o $pathcomp" 1>&2
+                        fi
+                        chown $opt_o $pathcomp || errstatus=$?
+                    fi
+                    if [ ".$opt_g" != . ]; then
+                        if [ ".$opt_t" = .yes ]; then
+                            echo "chgrp $opt_g $pathcomp" 1>&2
+                        fi
+                        chgrp $opt_g $pathcomp || errstatus=$?
+                    fi
+                    if [ ".$opt_m" != . ]; then
+                        if [ ".$opt_t" = .yes ]; then
+                            echo "chmod $opt_m $pathcomp" 1>&2
+                        fi
+                        chmod $opt_m $pathcomp || errstatus=$?
+                    fi
+                fi
+                pathcomp="$pathcomp/"
+            done
+        fi
+    done
+
+    shtool_exit $errstatus
+    ;;
+
+esac
+
+shtool_exit 0
+
Index: textbox.c
--- textbox.c.orig	2009-09-24 17:03:09 +0200
+++ textbox.c	2009-09-26 17:19:22 +0200
@@ -4,7 +4,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <wchar.h>
+#ifdef HAVE_WCHAR
 #include <wctype.h>
+#endif
 
 #include "newt.h"
 #include "newt_pr.h"
@@ -171,8 +173,10 @@
     int i;
     int howbad = 0;
     int height = 0;
+#ifdef HAVE_WCHAR
     wchar_t tmp;
     mbstate_t ps;
+#endif
 
     if (resultPtr) {
 	if (width > 1) {
@@ -184,7 +188,9 @@
 	*result = '\0';
     }
 	
+#ifdef HAVE_WCHAR
     memset(&ps,0,sizeof(mbstate_t));
+#endif
     while (*text) {
 	end = strchr(text, '\n');
 	if (!end)
@@ -216,6 +222,7 @@
 	        chptr = text;
 		i = 0;
 		while (1) {
+#ifdef HAVE_WCHAR
 			if ((x=mbrtowc(&tmp,chptr,end-chptr,&ps))<=0)
 				break;
 		        if (spc && !iswspace(tmp))
@@ -232,6 +239,17 @@
 				break;
 			chptr += x;
 			i += w;
+#else
+			if (spc && !isspace(*chptr))
+				spc = 0;
+			else if (!spc && isspace(*chptr)) {
+				spc = 1;
+				spcptr = chptr;
+				w2 = i;
+			}
+			chptr++;
+			i++;
+#endif
 		}
 		howbad += width - w2 + 1;
 #ifdef DEBUG_WRAP		    
@@ -246,9 +264,14 @@
 
 		text = chptr;
 		while (1) {
+#ifdef HAVE_WCHAR
 			if ((x=mbrtowc(&tmp,text,end-text,NULL))<=0)
 				break;
 			if (!iswspace(tmp)) break;
+#else
+                        x = 1;
+			if (!isspace(*text)) break;
+#endif
 			text += x;
 		}
 	    }
Index: tutorial.txt
--- /dev/null	2009-09-26 17:15:39 +0200
+++ tutorial.txt	2009-09-26 15:38:12 +0200
@@ -0,0 +1,1079 @@
+
+Writing Programs Using newtErik Troan, <ewt@redhat.com>
+
+v0.31, 2003-Jan-06
+
+   The newt windowing system is a terminal-based window and widget
+   library designed for writing applications with a simple, but
+   user-friendly, interface. While newt is not intended to provide the
+   rich feature set advanced applications may require, it has proven to
+   be flexible enough for a wide range of applications (most notably, Red
+   Hat's installation process). This tutorial explains the design
+   philosophy behind newt and how to use newt from your programs.
+     _________________________________________________________________
+
+   Table of Contents
+   1. Introduction
+
+        1.1. Background
+        1.2. Designing newt applications
+        1.3. Components
+        1.4. Conventions
+
+   2. Basic Newt Functions
+
+        2.1. Starting and Ending newt Services
+        2.2. Handling Keyboard Input
+        2.3. Drawing on the Root Window
+        2.4. Refreshing the Screen
+        2.5. Other Miscellaneous Functions
+        2.6. Basic newt Example
+
+   3. Windows
+
+        3.1. Creating Windows
+        3.2. Destroying Windows
+
+   4. Components
+
+        4.1. Introduction to Forms
+        4.2. Components
+        4.3. General Component Manipulation
+        4.4. Buttons
+
+              4.4.1. Button Example
+
+        4.5. Labels
+        4.6. Entry Boxes
+        4.7. Checkboxes
+        4.8. Radio Buttons
+        4.9. Scales
+        4.10. Textboxes
+
+              4.10.1. Reflowing Text
+
+        4.11. Scrollbars
+        4.12. Listboxes
+
+              4.12.1. Basic Listboxes
+              4.12.2. Manipulating Listbox Contents
+              4.12.3. Multiple Selections
+
+        4.13. Advanced Forms
+
+              4.13.1. Exiting From Forms
+
+1. Introduction
+
+Newt has a definite design philosophy behind it, and knowing that design
+makes it significantly easier to craft robust newt applications. This
+tutorial documents newt 0.30 --- older versions of newt had annoying
+inconsistencies in it (which writing this tutorial pointed out), which were
+removed while this tutorial was written. The latest version of newt is
+always available from Red Hat.
+     _________________________________________________________________
+
+1.1. Background
+
+Newt was originally designed for use in the install code for Red Hat Linux.
+As this install code runs in an environment with limited resources (most
+importantly limited filesystem space), newt's size was immediately an issue.
+To help minimize its size, the following design decisions were made early in
+its implementation:
+
+     * newt does not use an event-driven architecture.
+     * newt is written in C, not C++. While there has been interest in
+       constructing C++ wrapper classes around the newt API, nothing has
+       yet come of those ideas.
+     * Windows must be created and destroyed as a stack (in other words,
+       all newt windows behave as modal dialogs). This is probably the
+       greatest functionality restriction of newt.
+     * The tty keyboard is the only supported input device.
+     * Many behaviours, such as widget traversal order, are difficult or
+       impossible to change.
+
+   While newt provides a complete API, it does not handle the low-level
+   screen drawing itself. Instead, newt is layered on top of the screen
+   management capabilities of John E. Davis's S-Lang library.
+     _________________________________________________________________
+
+1.2. Designing newt applications
+
+As newt is not event driven and forces modal windows (forcing window order
+to behave like a stack), newt applications tend to look quite like other
+text-mode programs. It is quite straightforward to convert a command line
+program which uses simple user prompts into a newt application. Some of the
+programs run as part of the Red Hat installation process (such as
+Xconfigurator and mouseconfig) were originally written as simple terminal
+mode programs which used line-oriented menus to get input from the user and
+were later converted into newt applications (through a process
+affectionately known as newtering). Such a conversion does not require
+changes to the control flow of most applications. Programming newt is
+dramatically different from writing programs for most other windowing
+systems as newt's API is not event driven. This means that newt applications
+look dramatically different from programs written for event-driven
+architectures such as Motif, gtk, or even Borland's old TurboVision
+libraries. When you're designing your newt program, keep this
+differentiation in mind. As long as you plan your application to call a
+function to get input and then continue (rather then having your program
+called when input is ready), programming with the newt libraries should be
+simple.
+     _________________________________________________________________
+
+1.3. Components
+
+Displayable items in newt are known as components, which are analogous to
+the widgets provided by most Unix widget sets. There are two main types of
+components in newt, forms and everything else. Forms logically group
+components into functional sets. When an application is ready to get input
+from a user, it ``runs a form'', which makes the form active and lets the
+user enter information into the components the form contains. A form may
+contain any other component, including other forms. Using subforms in this
+manner lets the application change the details of how the user tabs between
+components on the form, scroll regions of the screen, and control background
+colors for portions of windows. Every component is of type newtComponent,
+which is an opaque type. It's guaranteed to be a pointer though, which lets
+applications move it through void pointers if the need arises. Variables of
+type newtComponent should never be directly manipulated -- they should only
+be passed to newt functions. As newtComponent variables are pointers,
+remember that they are always passed by value -- if you pass a newtComponent
+to a function which manipulates it, that component is manipulated
+everywhere, not just inside of that function (which is nearly always the
+behaviour you want).
+     _________________________________________________________________
+
+1.4. Conventions
+
+Newt uses a number of conventions to make it easier for programmers to use.
+
+     * All functions which manipulate data structures take the data
+       structure being modified as their first parameter. For example,
+       all of the functions which manipulate forms expect the
+       newtComponent for that form to be the first parameter.
+     * As newt is loosely typed (forcing all of the components into a
+       single variable makes coding easier, but nullifies the value of
+       type checking), newt functions include the name of the type they
+       are manipulating. An example of this is newtFormAddComponent(),
+       which adds a component to a form. Note that the first parameter to
+       this function is a form, as the name would suggest.
+     * When screen coordinates are passed into a function, the x location
+       precedes the y location. To help keep this clear, we'll use the
+       words ``left'' and ``top'' to describe those indicators (with left
+       corresponding to the x position).
+     * When box sizes are passed, the horizontal width precedes the
+       vertical width.
+     * When both a screen location and a box size are being passed, the
+       screen location precedes the box size.
+     * When any component other then a form is created, the first two
+       parameters are always the (left, right) location.
+     * Many functions take a set of flags as the final parameter. These
+       flags may be logically ORed together to pass more then one flag at
+       a time.
+     * Newt uses callback functions to convey certain events to the
+       application. While callbacks differ slightly in their parameters,
+       most of them allow the application to specify an arbitrary
+       argument to be passed to the callback when the callback is
+       invoked. This argument is always a void *, which allows the
+       application great flexibility.
+     _________________________________________________________________
+
+2. Basic Newt Functions
+
+While most newt functions are concerned with widgets or groups of widgets
+(called grids and forms), some parts of the newt API deal with more global
+issues, such as initializing newt or writing to the root window.
+     _________________________________________________________________
+
+2.1. Starting and Ending newt Services
+
+There are three functions which nearly every newt application use. The first
+two are used to initialize the system.
+int newtInit(void);
+void newtCls(void);
+
+newtInit() should be the first function called by every newt program. It
+initializes internal data structures and places the terminal in raw mode.
+Most applications invoke newtCls() immediately after newtInit(), which
+causes the screen to be cleared. It's not necessary to call newtCls() to use
+any of newt's features, but doing so will normally give a much neater
+appearance. When a newt program is ready to exit, it should call
+newtFinished().
+
+int newtFinished(void);
+
+   newtFinished() restores the terminal to its appearance when newtInit()
+   was called (if possible -- on some terminals the cursor will be moved
+   to the bottom, but it won't be possible to remember the original
+   terminal contents) and places the terminal in its original input
+   state. If this function isn't called, the terminal will probably need
+   to be reset with the reset command before it can be used easily.
+     _________________________________________________________________
+
+2.2. Handling Keyboard Input
+
+Normally, newt programs don't read input directly from the user. Instead,
+they let newt read the input and hand it to the program in a semi-digested
+form. Newt does provide a couple of simple functions which give programs (a
+bit of) control over the terminal.
+void newtWaitForKey(void);
+void newtClearKeyBuffer(void);
+
+   The first of these, newtWaitForKey(), doesn't return until a key has
+   been pressed. The keystroke is then ignored. If a key is already in
+   the terminal's buffer, newtWaitForKey() discards a keystroke and
+   returns immediately. newtClearKeyBuffer() discards the contents of the
+   terminal's input buffer without waiting for additional input.
+     _________________________________________________________________
+
+2.3. Drawing on the Root Window
+
+The background of the terminal's display (the part without any windows
+covering it) is known as the root window (it's the parent of all windows,
+just like the system's root directory is the parent of all subdirectories).
+Normally, applications don't use the root window, instead drawing all of
+their text inside of windows (newt doesn't require this though -- widgets
+may be placed directly on the root window without difficulty). It is often
+desirable to display some text, such as a program's name or copyright
+information, on the root window, however. Newt provides two ways of
+displaying text on the root window. These functions may be called at any
+time. They are the only newt functions which are meant to write outside of
+the current window.
+void newtDrawRootText(int left, int top, const char * text);
+
+   This function is straightforward. It displays the string text at the
+   position indicated. If either the left or top is negative, the
+   position is measured from the opposite side of the screen. The final
+   measurement will seem to be off by one though. For example, a top of
+   -1 indicates the last line on the screen, and one of -2 is the line
+   above that. As it's common to use the last line on the screen to
+   display help information, newt includes special support for doing
+   exactly that. The last line on the display is known as the help line,
+   and is treated as a stack. As the value of the help line normally
+   relates to the window currently displayed, using the same structure
+   for window order and the help line is very natural. Two functions are
+   provided to manipulate the help line.
+void newtPushHelpLine(const char * text);
+void newtPopHelpLine(void);
+
+   The first function, newtPushHelpLine(), saves the current help line on
+   a stack (which is independent of the window stack) and displays the
+   new line. If text is NULL, newt's default help line is displayed
+   (which provides basic instructions on using newt). If text is a string
+   of length 0, the help line is cleared. For all other values of text,
+   the passed string is displayed at the bottom, left-hand corner of the
+   display. The space between the end of the displayed string the the
+   right-hand edge of the terminal is cleared. newtPopHelpLine() replaces
+   the current help line with the one it replaced. It's important not to
+   call tt/newtPopHelpLine()/ more then newtPushHelpLine()! Suspending
+   Newt Applications By default, newt programs cannot be suspended by the
+   user (compare this to most Unix programs which can be suspended by
+   pressing the suspend key (normally ^Z). Instead, programs can specify
+   a callback function which gets invoked when the user presses the
+   suspend key.
+typedef void (*newtSuspendCallback)(void);
+
+void newtSetSuspendCallback(newtSuspendCallback cb);
+
+   The suspend function neither expects nor returns any value, and can do
+   whatever it likes to when it is invoked. If no suspend callback is
+   registered, the suspend keystroke is ignored. If the application
+   should suspend and continue like most user applications, the suspend
+   callback needs two other newt functions.
+void newtSuspend(void);
+void newtResume(void);
+
+   newtSuspend() tells newt to return the terminal to its initial state.
+   Once this is done, the application can suspend itself (by sending
+   itself a SIGTSTP, fork a child program, or do whatever else it likes.
+   When it wants to resume using the newt interface, it must call
+   newtResume before doing so. Note that suspend callbacks are not signal
+   handlers. When newtInit() takes over the terminal, it disables the
+   part of the terminal interface which sends the suspend signal.
+   Instead, if newt sees the suspend keystroke during normal input
+   processing, it immediately calls the suspend callback if one has been
+   set. This means that suspending newt applications is not asynchronous.
+     _________________________________________________________________
+
+2.4. Refreshing the Screen
+
+To increase performance, S-Lang only updates the display when it needs to,
+not when the program tells S-Lang to write to the terminal. ``When it needs
+to'' is implemented as ``right before the we wait for the user to press a
+key''. While this allows for optimized screen displays most of the time,
+this optimization makes things difficult for programs which want to display
+progress messages without forcing the user to input characters. Applications
+can force S-Lang to immediately update modified portions of the screen by
+calling newtRefresh.
+
+    1. The program wants to display a progress message, without forcing
+       for the user to enter any characters.
+    2. A misfeature of the program causes part of the screen to be
+       corrupted. Ideally, the program would be fixed, but that may not
+       always be practical.
+     _________________________________________________________________
+
+2.5. Other Miscellaneous Functions
+
+As always, some function defy characterization. Two of newt's general
+function fit this oddball category.
+void newtBell(void);
+void newtGetScreenSize(int * cols, int * rows);
+
+The first sends a beep to the terminal. Depending on the terminal's
+settings, this been may or may not be audible. The second function,
+newtGetScreenSize(), fills in the passed pointers with the current size of
+the terminal.
+     _________________________________________________________________
+
+2.6. Basic newt Example
+
+To help illustrate the functions presented in this section here is a short
+sample newt program which uses many of them. While it doesn't do anything
+interesting, it does show the basic structure of newt programs.
+#include <newt.h>
+#include <stdlib.h>
+
+int main(void) {
+    newtInit();
+    newtCls();
+
+    newtDrawRootText(0, 0, "Some root text");
+    newtDrawRootText(-25, -2, "Root text in the other corner");
+
+    newtPushHelpLine(NULL);
+    newtRefresh();
+    sleep(1);
+
+    newtPushHelpLine("A help line");
+    newtRefresh();
+    sleep(1);
+
+    newtPopHelpLine();
+    newtRefresh();
+    sleep(1);
+
+    newtFinished();
+}
+     _________________________________________________________________
+
+3. Windows
+
+While most newt applications do use windows, newt's window support is
+actually extremely limited. Windows must be destroyed in the opposite of the
+order they were created, and only the topmost window may be active.
+Corollaries to this are:
+
+     * The user may not switch between windows.
+     * Only the top window may be destroyed.
+
+While this is quite a severe limitation, adopting it greatly simplifies both
+writing newt applications and developing newt itself, as it separates newt
+from the world of event-driven programming. However, this tradeoff between
+function and simplicity may make newt unsuitable for some tasks.
+     _________________________________________________________________
+
+3.1. Creating Windows
+
+There are two main ways of opening newt windows: with or without explicit
+sizings. When grids (which will be introduced later in this tutorial) are
+used, a window may be made to just fit the grid. When grids are not used,
+explicit sizing must be given.
+int newtCenteredWindow(int width, int height, const char * title);
+int newtOpenWindow(int left, int top, int width, int height,
+                   const char * title);
+
+The first of these functions open a centered window of the specified size.
+The title is optional -- if it is NULL, then no title is used.
+newtOpenWindow*( is similar, but it requires a specific location for the
+upper left-hand corner of the window.
+     _________________________________________________________________
+
+3.2. Destroying Windows
+
+All windows are destroyed in the same manner, no matter how the windows were
+originally created.
+void newtPopWindow(void);
+
+This function removes the top window from the display, and redraws the
+display areas which the window overwrote.
+     _________________________________________________________________
+
+4. Components
+
+Components are the basic user interface element newt provides. A single
+component may be (for example) a listbox, push button checkbox, a collection
+of other components. Most components are used to display information in a
+window, provide a place for the user to enter data, or a combination of
+these two functions. Forms, however, are a component whose primary purpose
+is not noticed by the user at all. Forms are collections of components (a
+form may contain another form) which logically relate the components to one
+another. Once a form is created and had all of its constituent components
+added to it, applications normally then run the form. This gives control of
+the application to the form, which then lets the user enter data onto the
+form. When the user is done (a number of different events qualify as
+``done''), the form returns control to the part of the application which
+invoked it. The application may then read the information the user provided
+and continue appropriately. All newt components are stored in a common data
+type, a newtComponent (some of the particulars of newtComponents have
+already been mentioned. While this makes it easy for programmers to pass
+components around, it does force them to make sure they don't pass entry
+boxes to routines expecting push buttons, as the compiler can't ensure that
+for them. We start off with a brief introduction to forms. While not
+terribly complete, this introduction is enough to let us illustrate the rest
+of the components with some sample code. We'll then discuss the remainder of
+the components, and end this section with a more exhaustive description of
+forms.
+     _________________________________________________________________
+
+4.1. Introduction to Forms
+
+As we've mentioned, forms are simply collections of components. As only one
+form can be active (or running) at a time, every component which the user
+should be able to access must be on the running form (or on a subform of the
+running form). A form is itself a component, which means forms are stored in
+newtComponent data structures.
+newtComponent newtForm(newtComponent vertBar, const char * help, int flags);
+
+To create a form, call newtForm(). The first parameter is a vertical
+scrollbar which should be associated with the form. For now, that should
+always be NULL (we'll discuss how to create scrolling forms later in this
+section). The second parameter, help, is currently unused and should always
+be NULL. The flags is normally 0, and other values it can take will be
+discussed later. Now that we've waved away the complexity of this function,
+creating a form boils down to simply:
+
+newtComponent myForm;
+
+myForm = newtForm(NULL, NULL, 0);
+
+   After a form is created, components need to be added to it --- after
+   all, an empty form isn't terribly useful. There are two functions
+   which add components to a form.
+void newtFormAddComponent(newtComponent form, newtComponent co);
+void newtFormAddComponents(newtComponent form, ...);
+
+   The first function, newtFormAddComponent(), adds a single component to
+   the form which is passed as the first parameter. The second function
+   is simply a convenience function. After passing the form to
+   newtFormAddComponents(), an arbitrary number of components is then
+   passed, followed by NULL. Every component passed is added to the form.
+   Once a form has been created and components have been added to it,
+   it's time to run the form.
+newtComponent newtRunForm(newtComponent form);
+
+   This function runs the form passed to it, and returns the component
+   which caused the form to stop running. For now, we'll ignore the
+   return value completely. Notice that this function doesn't fit in with
+   newt's normal naming convention. It is an older interface which will
+   not work for all forms. It was left in newt only for legacy
+   applications. It is a simpler interface than the new newtFormRun()
+   though, and is still used quite often as a result. When an application
+   is done with a form, it destroys the form and all of the components
+   the form contains.
+void newtFormDestroy(newtComponent form);
+
+   This function frees the memory resources used by the form and all of
+   the components which have been added to the form (including those
+   components which are on subforms). Once a form has been destroyed,
+   none of the form's components can be used.
+     _________________________________________________________________
+
+4.2. Components
+
+Non-form components are the most important user-interface component for
+users. They determine how users interact with newt and how information is
+presented to them.
+     _________________________________________________________________
+
+4.3. General Component Manipulation
+
+There are a couple of functions which work on more then one type of
+components. The description of each component indicates which (if any) of
+these functions are valid for that particular component.
+typedef void (*newtCallback)(newtComponent, void *);
+
+void newtComponentAddCallback(newtComponent co, newtCallback f, void * data);
+void newtComponentTakesFocus(newtComponent co, int val);
+
+The first registers a callback function for that component. A callback
+function is a function the application provides which newt calls for a
+particular component. Exactly when (if ever) the callback is invoked depends
+on the type of component the callback is attached to, and will be discussed
+for the components which support callbacks. newtComponentTakesFocus() works
+on all components. It allows the application to change which components the
+user is allowed to select as the current component, and hence provide input
+to. Components which do not take focus are skipped over during form
+traversal, but they are displayed on the terminal. Some components should
+never be set to take focus, such as those which display static text.
+     _________________________________________________________________
+
+4.4. Buttons
+
+Nearly all forms contain at least one button. Newt buttons come in two
+flavors, full buttons and compact buttons. Full buttons take up quit a bit
+of screen space, but look much better then the single-row compact buttons.
+Other then their size, both button styles behave identically. Different
+functions are used to create the two types of buttons.
+newtComponent newtButton(int left, int top, const char * text);
+newtComponent newtCompactButton(int left, int top, const char * text);
+
+Both functions take identical parameters. The first two parameters are the
+location of the upper left corner of the button, and the final parameter is
+the text which should be displayed in the button (such as ``Ok'' or
+``Cancel'').
+     _________________________________________________________________
+
+4.4.1. Button Example
+
+Here is a simple example of both full and compact buttons. It also
+illustrates opening and closing windows, as well a simple form.
+#include <newt.h>
+#include <stdlib.h>
+
+void main(void) {
+    newtComponent form, b1, b2;
+    newtInit();
+    newtCls();
+
+    newtOpenWindow(10, 5, 40, 6, "Button Sample");
+
+    b1 = newtButton(10, 1, "Ok");
+    b2 = newtCompactButton(22, 2, "Cancel");
+    form = newtForm(NULL, NULL, 0);
+    newtFormAddComponents(form, b1, b2, NULL);
+
+    newtRunForm(form);
+
+    newtFormDestroy(form);
+    newtFinished();
+}
+     _________________________________________________________________
+
+4.5. Labels
+
+Labels are newt's simplest component. They display some given text and don't
+allow any user input.
+newtComponent newtLabel(int left, int top, const char * text);
+void newtLabelSetText(newtComponent co, const char * text);
+
+Creating a label is just like creating a button; just pass the location of
+the label and the text it should display. Unlike buttons, labels do let the
+application change the text in the label with newtLabelSetText. When the
+label's text is changed, the label automatically redraws itself. It does not
+clear out any old text which may be leftover from the previous time is was
+displayed, however, so be sure that the new text is at least as long as the
+old text.
+     _________________________________________________________________
+
+4.6. Entry Boxes
+
+Entry boxes allow the user to enter a text string into the form which the
+application can later retrieve.
+typedef int (*newtEntryFilter)(newtComponent entry, void * data, int ch,
+                               int cursor);
+
+newtComponent newtEntry(int left, int top, const char * initialValue, int width
+,
+                        char ** resultPtr, int flags);
+void newtEntrySet(newtComponent co, const char * value, int cursorAtEnd);
+char * newtEntryGetValue(newtComponent co);
+void newtEntrySetFilter(newtComponent co, newtEntryFilter filter, void * data);
+
+   newtEntry() creates a new entry box. After the location of the entry
+   box, the initial value for the entry box is passed, which may be NULL
+   if the box should start off empty. Next, the width of the physical box
+   is given. This width may or may not limit the length of the string the
+   user is allowed to enter; that depends on the flags. The resultPtr
+   must be the address of a char *. Until the entry box is destroyed by
+   newtFormDestroy(), that char * will point to the current value of the
+   entry box. It's important that applications make a copy of that value
+   before destroying the form if they need to use it later. The resultPtr
+   may be NULL, in which case the user must use the newtEntryGetValue()
+   function to get the value of the entry box. Entry boxes support a
+   number of flags:
+
+   NEWT_ENTRY_SCROLL
+          If this flag is not specified, the user cannot enter text into
+          the entry box which is wider then the entry box itself. This
+          flag removes this limitation, and lets the user enter data of
+          an arbitrary length.
+
+   NEWT_FLAG_HIDDEN
+          If this flag is specified, the value of the entry box is not
+          displayed. This is useful when the application needs to read a
+          password, for example.
+
+   NEWT_FLAG_RETURNEXIT
+          When this flag is given, the entry box will cause the form to
+          stop running if the user pressed return inside of the entry
+          box. This can provide a nice shortcut for users.
+
+   After an entry box has been created, its contents can be set by
+   newtEntrySet(). After the entry box itself, the new string to place in
+   the entry box is passed. The final parameter, cursorAtEnd, controls
+   where the cursor will appear in the entry box. If it is zero, the
+   cursor remains at its present location; a nonzero value moves the
+   cursor to the end of the entry box's new value. While the simplest way
+   to find the value of an entry box is by using a resultPtr, doing so
+   complicates some applications. newtEntryGetValue() returns a pointer
+   to the string which the entry box currently contains. The returned
+   pointer may not be valid once the user further modifies the entry box,
+   and will not be valid after the entry box has been destroyed, so be
+   sure to save its value in a more permanent location if necessary.
+   Entry boxes allow applications to filter characters as they are
+   entered. This allows programs to ignore characters which are invalid
+   (such as entering a ^ in the middle of a phone number) and provide
+   intelligent aids to the user (such as automatically adding a '.' after
+   the user has typed in the first three numbers in an IP address). When
+   a filter is registered through newtEntrySetFilter(), both the filter
+   itself and an arbitrary void *, which passed to the filter whenever it
+   is invoked, are recorded. This data pointer isn't used for any other
+   purpose, and may be NULL. Entry filters take four arguments.
+
+    1. The entry box which had data entered into it
+    2. The data pointer which was registered along with the filter
+    3. The new character which newt is considering inserting into the
+       entry box
+    4. The current cursor position (0 is the leftmost position)
+
+   The filter returns 0 if the character should be ignored, or the value
+   of the character which should be inserted into the entry box. Filter
+   functions which want to do complex manipulations of the string should
+   use newtEntrySet() to update the entry box and then return 0 to
+   prevent the new character from being inserted. When a callback is
+   attached to a entry box, the callback is invoked whenever the user
+   moves off of the callback and on to another component. Here is a
+   sample program which illustrates the use of both labels and entry
+   boxes.
+#include <newt.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+void main(void) {
+    newtComponent form, label, entry, button;
+    char * entryValue;
+
+    newtInit();
+    newtCls();
+
+    newtOpenWindow(10, 5, 40, 8, "Entry and Label Sample");
+
+    label = newtLabel(1, 1, "Enter a string");
+    entry = newtEntry(16, 1, "sample", 20, &entryValue,
+                      NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
+    button = newtButton(17, 3, "Ok");
+    form = newtForm(NULL, NULL, 0);
+    newtFormAddComponents(form, label, entry, button, NULL);
+
+    newtRunForm(form);
+
+    newtFinished();
+
+    printf("Final string was: %s\n", entryValue);
+
+    /* We cannot destroy the form until after we've used the value
+       from the entry widget. */
+    newtFormDestroy(form);
+}
+     _________________________________________________________________
+
+4.7. Checkboxes
+
+Most widget sets include checkboxes which toggle between two value (checked
+or not checked). Newt checkboxes are more flexible. When the user presses
+the space bar on a checkbox, the checkbox's value changes to the next value
+in an arbitrary sequence (which wraps). Most checkboxes have two items in
+that sequence, checked or not, but newt allows an arbitrary number of value.
+This is useful when the user must pick from a limited number of choices.
+Each item in the sequence is a single character, and the sequence itself is
+represented as a string. The checkbox components displays the character
+which currently represents its value the left of a text label, and returns
+the same character as its current value. The default sequence for checkboxes
+is " *", with ' ' indicating false and '*' true.
+newtComponent newtCheckbox(int left, int top, const char * text, char defValue,
+                           const char * seq, char * result);
+char newtCheckboxGetValue(newtComponent co);
+
+   Like most components, the position of the checkbox is the first thing
+   passed to the function that creates one. The next parameter, text, is
+   the text which is displayed to the right of the area which is checked.
+   The defValue is the initial value for the checkbox, and seq is the
+   sequence which the checkbox should go through (defValue must be in
+   seq. seq may be NULL, in which case " *" is used. The final parameter,
+   result, should point to a character which the checkbox should always
+   record its current value in. If result is NULL, newtCheckboxGetValue()
+   must be used to get the current value of the checkbox.
+   newtCheckboxGetValue() is straightforward, returning the character in
+   the sequence which indicates the current value of the checkbox If a
+   callback is attached to a checkbox, the callback is invoked whenever
+   the checkbox responds to a user's keystroke. The entry box may respond
+   by taking focus or giving up focus, as well as by changing its current
+   value.
+     _________________________________________________________________
+
+4.8. Radio Buttons
+
+Radio buttons look very similar to checkboxes. The key difference between
+the two is that radio buttons are grouped into sets, and exactly one radio
+button in that set may be turned on. If another radio button is selected,
+the button which was selected is automatically deselected.
+newtComponent newtRadiobutton(int left, int top, const char * text,
+                              int isDefault, newtComponent prevButton);
+newtComponent newtRadioGetCurrent(newtComponent setMember);
+
+Each radio button is created by calling newtRadiobutton(). After the
+position of the radio button, the text displayed with the button is passed.
+isDefault should be nonzero if the radio button is to be turned on by
+default. The final parameter, prevMember is used to group radio buttons into
+sets. If prevMember is NULL, the radio button is assigned to a new set. If
+the radio button should belong to a preexisting set, prevMember must be the
+previous radio button added to that set. Discovering which radio button in a
+set is currently selected necessitates newtRadioGetCurrent(). It may be
+passed any radio button in the set you're interested in, and it returns the
+radio button component currently selected. Here is an example of both
+checkboxes and radio buttons.
+
+#include <newt.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+void main(void) {
+    newtComponent form, checkbox, rb[3], button;
+    char cbValue;
+    int i;
+
+    newtInit();
+    newtCls();
+
+    newtOpenWindow(10, 5, 40, 11, "Checkboxes and Radio buttons");
+
+    checkbox = newtCheckbox(1, 1, "A checkbox", ' ', " *X", &cbValue);
+
+    rb[0] = newtRadiobutton(1, 3, "Choice 1", 1, NULL);
+    rb[1] = newtRadiobutton(1, 4, "Choice 2", 0, rb[0]);
+    rb[2] = newtRadiobutton(1, 5, "Choice 3", 0, rb[1]);
+
+    button = newtButton(1, 7, "Ok");
+
+    form = newtForm(NULL, NULL, 0);
+    newtFormAddComponent(form, checkbox);
+    for (i = 0; i < 3; i++)
+        newtFormAddComponent(form, rb[i]);
+    newtFormAddComponent(form, button);
+
+    newtRunForm(form);
+    newtFinished();
+
+    /* We cannot destroy the form until after we've found the current
+       radio button */
+
+    for (i = 0; i < 3; i++)
+        if (newtRadioGetCurrent(rb[0]) == rb[i])
+            printf("radio button picked: %d\n", i);
+    newtFormDestroy(form);
+
+    /* But the checkbox's value is stored locally */
+    printf("checkbox value: '%c'\n", cbValue);
+}
+     _________________________________________________________________
+
+4.9. Scales
+
+It's common for programs to need to display a progress meter on the terminal
+while it performs some length operation (it behaves like an anesthetic). The
+scale component is a simple way of doing this. It displays a horizontal bar
+graph which the application can update as the operation continues.
+newtComponent newtScale(int left, int top, int width, long long fullValue);
+void newtScaleSet(newtComponent co, unsigned long long amount);
+
+When the scale is created with newtScale, it is given the width of the scale
+itself as well as the value which means that the scale should be drawn as
+full. When the position of the scale is set with newtScaleSet(), the scale
+is told the amount of the scale which should be filled in relative to the
+fullAmount. For example, if the application is copying a file, fullValue
+could be the number of bytes in the file, and when the scale is updated
+newtScaleSet() would be passed the number of bytes which have been copied so
+far.
+     _________________________________________________________________
+
+4.10. Textboxes
+
+Textboxes display a block of text on the terminal, and is appropriate for
+display large amounts of text.
+newtComponent newtTextbox(int left, int top, int width, int height, int flags);
+void newtTextboxSetText(newtComponent co, const char * text);
+
+newtTextbox() creates a new textbox, but does not fill it with data. The
+function is passed the location for the textbox on the screen, the width and
+height of the textbox (in characters), and zero or more of the following
+flags:
+
+   NEWT_FLAG_WRAP
+          All text in the textbox should be wrapped to fit the width of
+          the textbox. If this flag is not specified, each newline
+          delimited line in the text is truncated if it is too long to
+          fit. When newt wraps text, it tries not to break lines on
+          spaces or tabs. Literal newline characters are respected, and
+          may be used to force line breaks.
+
+        NEWT_FLAG_SCROLL
+                The text box should be scrollable. When this option is
+                used, the scrollbar which is added increases the width of
+                the area used by the textbox by 2 characters; that is the
+                textbox is 2 characters wider then the width passed to
+                newtTextbox().
+
+          After a textbox has been created, text may be added to it
+          through newtTextboxSetText(), which takes only the textbox and
+          the new text as parameters. If the textbox already contained
+          text, that text is replaced by the new text. The textbox makes
+          its own copy of the passed text, so these is no need to keep
+          the original around unless it's convenient.
+     _________________________________________________________________
+
+4.10.1. Reflowing Text
+
+When applications need to display large amounts of text, it's common not to
+know exactly where the linebreaks should go. While textboxes are quite
+willing to scroll the text, the programmer still must know what width the
+text will look ``best'' at (where ``best'' means most exactly rectangular;
+no lines much shorter or much longer then the rest). This common is
+especially prevalent in internationalized programs, which need to make a
+wide variety of message string look god on a screen. To help with this, newt
+provides routines to reformat text to look good. It tries different widths
+to figure out which one will look ``best'' to the user. As these commons are
+almost always used to format text for textbox components, newt makes it easy
+to construct a textbox with reflowed text.
+char * newtReflowText(char * text, int width, int flexDown, int flexUp,
+                      int * actualWidth, int * actualHeight);
+newtComponent newtTextboxReflowed(int left, int top, char * text, int width,
+                                  int flexDown, int flexUp, int flags);
+int newtTextboxGetNumLines(newtComponent co);
+
+   newtReflowText() reflows the text to a target width of width. The
+   actual width of the longest line in the returned string is between
+   width - flexDown and width + flexUp; the actual maximum line length is
+   chosen to make the displayed check look rectangular. The ints pointed
+   to by actualWidth and actualHeight are set to the width of the longest
+   line and the number of lines in in the returned text, respectively.
+   Either one may be NULL. The return value points to the reflowed text,
+   and is allocated through malloc(). When the reflowed text is being
+   placed in a textbox it may be easier to use newtTextboxReflowed(),
+   which creates a textbox, reflows the text, and places the reflowed
+   text in the listbox. It's parameters consist of the position of the
+   final textbox, the width and flex values for the text (which are
+   identical to the parameters passed to newtReflowText(), and the flags
+   for the textbox (which are the same as the flags for newtTextbox().
+   This function does not let you limit the height of the textbox,
+   however, making limiting it's use to constructing textboxes which
+   don't need to scroll. To find out how tall the textbox created by
+   newtTextboxReflowed() is, use newtTextboxGetNumLines(), which returns
+   the number of lines in the textbox. For textboxes created by
+   newtTextboxReflowed(), this is always the same as the height of the
+   textbox. Here's a simple program which uses a textbox to display a
+   message.
+#include <newt.h>
+#include <stdlib.h>
+
+char message[] = "This is a pretty long message. It will be displayed "
+                 "in a newt textbox, and illustrates how to construct "
+                 "a textbox from arbitrary text which may not have "
+                 "very good line breaks.\n\n"
+                 "Notice how literal \\n characters are respected, and "
+                 "may be used to force line breaks and blank lines.";
+
+void main(void) {
+    newtComponent form, text, button;
+
+    newtInit();
+    newtCls();
+
+    text = newtTextboxReflowed(1, 1, message, 30, 5, 5, 0);
+    button = newtButton(12, newtTextboxGetNumLines(text) + 2, "Ok");
+
+    newtOpenWindow(10, 5, 37,
+                   newtTextboxGetNumLines(text) + 7, "Textboxes");
+
+    form = newtForm(NULL, NULL, 0);
+    newtFormAddComponents(form, text, button, NULL);
+
+    newtRunForm(form);
+    newtFormDestroy(form);
+    newtFinished();
+}
+     _________________________________________________________________
+
+4.11. Scrollbars
+
+Scrollbars (which, currently, are always vertical in newt), may be attached
+to forms to let them contain more data then they have space for. While the
+actual process of making scrolling forms is discussed at the end of this
+section, we'll go ahead and introduce scrollbars now so you'll be ready.
+newtComponent newtVerticalScrollbar(int left, int top, int height,
+                                    int normalColorset, int thumbColorset);
+
+When a scrollbar is created, it is given a position on the screen, a height,
+and two colors. The first color is the color used for drawing the scrollbar,
+and the second color is used for drawing the thumb. This is the only place
+in newt where an application specifically sets colors for a component. It's
+done here to let the colors a scrollbar use match the colors of the
+component the scrollbar is mated too. When a scrollbar is being used with a
+form, normalColorset is often NEWT_COLORSET_WINDOW and thumbColorset
+NEWT_COLORSET_ACTCHECKBOX. Of course, feel free to peruse <newt.h> and pick
+your own colors. As the scrollbar is normally updated by the component it is
+mated with, there is no public interface for moving the thumb.
+     _________________________________________________________________
+
+4.12. Listboxes
+
+Listboxes are the most complicated components newt provides. They can allow
+a single selection or multiple selection, and are easy to update.
+Unfortunately, their API is also the least consistent of newt's components.
+Each entry in a listbox is a ordered pair of the text which should be
+displayed for that item and a key, which is a void * that uniquely
+identifies that listbox item. Many applications pass integers in as keys,
+but using arbitrary pointers makes many applications significantly easier to
+code.
+     _________________________________________________________________
+
+4.12.1. Basic Listboxes
+
+Let's start off by looking at the most important listbox functions.
+newtComponent newtListbox(int left, int top, int height, int flags);
+int newtListboxAppendEntry(newtComponent co, const char * text,
+                           const void * data);
+void * newtListboxGetCurrent(newtComponent co);
+void newtListboxSetWidth(newtComponent co, int width);
+void newtListboxSetCurrent(newtComponent co, int num);
+void newtListboxSetCurrentByKey(newtComponent co, void * key);
+
+   A listbox is created at a certain position and a given height. The
+   height is used for two things. First of all, it is the minimum height
+   the listbox will use. If there are less items in the listbox then the
+   height, suggests the listbox will still take up that minimum amount of
+   space. Secondly, if the listbox is set to be scrollable (by setting
+   the NEWT_FLAG_SCROLL flag, the height is also the maximum height of
+   the listbox. If the listbox may not scroll, it increases its height to
+   display all of its items. The following flags may be used when
+   creating a listbox:
+
+   NEWT_FLAG_SCROLL
+          The listbox should scroll to display all of the items it
+          contains.
+
+   NEWT_FLAG_RETURNEXIT
+          When the user presses return on an item in the list, the form
+          should return.
+
+   NEWT_FLAG_BORDER
+          A frame is drawn around the listbox, which can make it easier
+          to see which listbox has the focus when a form contains
+          multiple listboxes.
+
+   NEWT_FLAG_MULTIPLE
+          By default, a listbox only lets the user select one item in the
+          list at a time. When this flag is specified, they may select
+          multiple items from the list.
+
+   Once a listbox has been created, items are added to it by invoking
+   newtListboxAppendEntry(), which adds new items to the end of the list.
+   In addition to the listbox component, newtListboxAppendEntry() needs
+   both elements of the (text, key) ordered pair. For lists which only
+   allow a single selection, newtListboxGetCurrent() should be used to
+   find out which listbox item is currently selected. It returns the key
+   of the currently selected item. Normally, a listbox is as wide as its
+   widest element, plus space for a scrollbar if the listbox is supposed
+   to have one. To make the listbox any larger then that, use
+   newtListboxSetWidth(), which overrides the natural list of the
+   listbox. Once the width has been set, it's fixed. The listbox will no
+   longer grow to accommodate new entries, so bad things may happen! An
+   application can change the current position of the listbox (where the
+   selection bar is displayed) by calling newtListboxSetCurrent() or
+   newtListboxSetCurrentByKey(). The first sets the current position to
+   the entry number which is passed as the second argument, with 0
+   indicating the first entry. newtListboxSetCurrentByKey() sets the
+   current position to the entry whose key is passed into the function.
+     _________________________________________________________________
+
+4.12.2. Manipulating Listbox Contents
+
+While the contents of many listboxes never need to change, some applications
+need to change the contents of listboxes regularly. Newt includes complete
+support for updating listboxes. These new functions are in addition to
+newtListboxAppendEntry(), which was already discussed.
+void newtListboxSetEntry(newtComponent co, void * key, const char * text);
+int newtListboxInsertEntry(newtComponent co, const char * text,
+                           const void * data, void * key);
+int newtListboxDeleteEntry(newtComponent co, void * key);
+void newtListboxClear(newtComponent co);
+
+   The first of these, newtListboxSetEntry(), updates the text for a key
+   which is already in the listbox. The key specifies which listbox entry
+   should be modified, and text becomes the new text for that entry in
+   the listbox. newtListboxInsertEntry() inserts a new listbox entry
+   after an already existing entry, which is specified by the key
+   parameter. The text and data parameters specify the new entry which
+   should be added. Already-existing entries are removed from a listbox
+   with newtListboxDeleteEntry(). It removes the listbox entry with the
+   specified key. If you want to remove all of the entries from a
+   listbox, use newtListboxClear().
+     _________________________________________________________________
+
+4.12.3. Multiple Selections
+
+When a listbox is created with NEWT_FLAG_MULTIPLE, the user can select
+multiple items from the list. When this option is used, a different set of
+functions must be used to manipulate the listbox selection.
+void newtListboxClearSelection(newtComponent co);
+void **newtListboxGetSelection(newtComponent co, int *numitems);
+void newtListboxSelectItem(newtComponent co, const void * key,
+                           enum newtFlagsSense sense);
+
+The simplest of these is newtListboxClearSelection(), which deselects all of
+the items in the list (listboxes which allow multiple selections also allow
+zero selections). newtListboxGetSelection() returns a pointer to an array
+which contains the keys for all of the items in the listbox currently
+selected. The int pointed to by numitems is set to the number of items
+currently selected (and hence the number of items in the returned array).
+The returned array is dynamically allocated, and must be released through
+free(). newtListboxSelectItem() lets the program select and deselect
+specific listbox entries. The key of the listbox entry is being affected is
+passed, and sense is one of NEWT_FLAGS_RESET, which deselects the entry,
+NEWT_FLAGS_SET, which selects the entry, or NEWT_FLAGS_TOGGLE, which
+reverses the current selection status.
+     _________________________________________________________________
+
+4.13. Advanced Forms
+
+Forms, which tie components together, are quite important in the world of
+newt. While we've already discussed the basics of forms, we've omitted many
+of the details.
+     _________________________________________________________________
+
+4.13.1. Exiting From Forms
+
+Forms return control to the application for a number of reasons:
+
+     * A component can force the form to exit. Buttons do this whenever
+       they are pushed, and other components exit when
+       NEWT_FLAG_RETURNEXIT has been specified.
+     * Applications can setup hot keys which cause the form to exit when
+       they are pressed.
+     * Newt can exit when file descriptors are ready to be read or ready
+       to be written to.
+
+By default, newt forms exit when the F12 key is pressed (F12 is setup as a
+hot key by default). Newt applications should treat F12 as an ``Ok'' button.
+If applications don't want F12 to exit the form, they can specify
+NEWT_FLAG_NOF12 as flag when creating the form with newtForm.
+
+void newtFormAddHotKey(newtComponent co, int key);
+void newtFormWatchFd(newtComponent form, int fd, int fdFlags);
+void newtDrawForm(newtComponent form);
+newtComponent newtFormGetCurrent(newtComponent co);
+void newtFormSetCurrent(newtComponent co, newtComponent subco);
+void newtFormRun(newtComponent co, struct newtExitStruct * es);
+newtComponent newtForm(newtComponent vertBar, const char * help, int flags);
+void newtFormSetBackground(newtComponent co, int color);
+void newtFormSetHeight(newtComponent co, int height);
+void newtFormSetWidth(newtComponent co, int width);
Index: whiptail.c
--- whiptail.c.orig	2009-09-24 17:03:09 +0200
+++ whiptail.c	2009-09-26 15:38:12 +0200
@@ -8,6 +8,7 @@
 #include <unistd.h>
 #include <wchar.h>
 #include <slang.h>
+#include <sys/stat.h>
 
 #include "nls.h"
 #include "dialogboxes.h"
