You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2127 lines
84 KiB

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"