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
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"
|
|
|