summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Roxborough <irox@redhat.com>2001-09-08 21:55:17 +0000
committerIan Roxborough <irox@redhat.com>2001-09-08 21:55:17 +0000
commit926d71c5c29102926ff1cf87828cad68a79bce56 (patch)
tree5db22f4f17ca5f8c78ab7fffe45a79a617c3f666
parentb111a96ea19bde1004ecea63c7827a1d4b0b73ef (diff)
downloadgdb-926d71c5c29102926ff1cf87828cad68a79bce56.tar.gz
libgui import for Tcl/Tk8.3 upgradeLIBGUI_TCL_8_3
-rw-r--r--libgui/ChangeLog83
-rw-r--r--libgui/Makefile.in5
-rw-r--r--libgui/TODO29
-rw-r--r--libgui/config.h.in16
-rwxr-xr-xlibgui/configure339
-rw-r--r--libgui/configure.in14
-rw-r--r--libgui/doc/tkTable.html1907
-rw-r--r--libgui/library/Makefile.in18
-rw-r--r--libgui/src/Makefile.in9
-rw-r--r--libgui/src/subcommand.c4
-rw-r--r--libgui/src/tclgetdir.c6
-rw-r--r--libgui/src/tclhelp.c43
-rw-r--r--libgui/src/tclmain.c2
-rw-r--r--libgui/src/tclmsgbox.c18
-rw-r--r--libgui/src/tclsizebox.c4
-rw-r--r--libgui/src/tclwinmode.c4
-rw-r--r--libgui/src/tclwinpath.c4
-rw-r--r--libgui/src/tclwinprint.c8
-rw-r--r--libgui/src/tkCanvEdge.c21
-rw-r--r--libgui/src/tkGraphCanvas.c6
-rw-r--r--libgui/src/tkTable.tcl.h366
-rw-r--r--libgui/src/tkTableCellSort.c400
-rw-r--r--libgui/src/tkTableCmds.c1293
-rw-r--r--libgui/src/tkTableEdit.c683
-rw-r--r--libgui/src/tkTableInitScript.h90
-rw-r--r--libgui/src/tkTablePs.c1299
-rw-r--r--libgui/src/tkTableUtil.c340
-rw-r--r--libgui/src/tkWinPrintCanvas.c14
-rw-r--r--libgui/src/tkWinPrintText.c17
29 files changed, 6844 insertions, 198 deletions
diff --git a/libgui/ChangeLog b/libgui/ChangeLog
index 2a16f91ba45..2651dbcd0a7 100644
--- a/libgui/ChangeLog
+++ b/libgui/ChangeLog
@@ -1,3 +1,86 @@
+2001-08-12 Mo DeJong <mdejong@redhat.com>
+
+ * src/tkCanvEdge.c: Work around Windows gcc problem
+ initializing a static member with a dll imported
+ symbol by assigning the function pointer at runtime.
+ Static initialization works just fine in VC++ but
+ fails when compiling with the Windows version of gcc.
+
+2001-08-03 Mo DeJong <mdejong@redhat.com>
+
+ * src/tclhelp.c (help_display_file_command): Pass int
+ address to Tcl_GetInt instead of an unsigned long to
+ avoid compiler warning.
+
+2001-08-03 Mo DeJong <mdejong@redhat.com>
+
+ * src/subcommand.c:
+ * src/tclgetdir.c:
+ * src/tclhelp.c:
+ * src/tclmain.c:
+ * src/tclmsgbox.c:
+ * src/tclsizebox.c:
+ * src/tclwinmode.c:
+ * src/tclwinpath.c:
+ * src/tclwinprint.c:
+ * src/tkWinPrintCanvas.c:
+ * src/tkWinPrintText.c:
+ Use ckalloc/ckfree instead of Tcl_Alloc/Tcl_Free
+ or malloc/free so that allocations will
+ be marked with file positions when Tcl mem
+ debug is activated.
+
+2001-08-02 Mo DeJong <mdejong@redhat.com>
+
+ * src/tkWinPrintCanvas.c (PrintCanvasCmd):
+ * src/tkWinPrintText.c (PrintTextCmd): Plug
+ memory leak by calling free on memory allocated
+ in PrintCanvasCmd and PrintTextCmd method. Make
+ sure error cases branch to the cleanup code at
+ the end of the method instead of just returning.
+
+2001-08-02 Mo DeJong <mdejong@redhat.com>
+
+ * src/tkWinPrintText.c (DisplayDLineToDrawable): Fix
+ compiler warning by adding missing static modifier
+ to funciton declaration.
+
+2001-08-02 Mo DeJong <mdejong@redhat.com>
+
+ * config.h.in: Regen.
+ * configure: Regen.
+ * configure.in: Don't check for strdup since it
+ is no longer used in libgui.
+ * src/tclhelp.c (help_initialize_command): Replace
+ use of strdup with calls to malloc and strcpy.
+
+2001-08-02 Mo DeJong <mdejong@redhat.com>
+
+ * src/tclhelp.c (help_command_deleted): Free the
+ help_command_data->help_dir member allocated in
+ help_initialize_command.
+
+2001-08-02 Mo DeJong <mdejong@redhat.com>
+
+ * src/tkGraphCanvas.c (GetEdgeNodes): Use ckalloc
+ and strcpy instead of calling strdup() since this
+ memory is deallocated with ckfree() later on.
+
+2001-08-02 Mo DeJong <mdejong@redhat.com>
+
+ * Makefile.in: Regen.
+ * configure: Regen.
+ * configure.in: Check for cross AR using the
+ AC_CHECK_TOOL macro to fix cross compile. Use
+ AC_CHECK_TOOL instead of AC_PROG_RANLIB for
+ ranlib. The ranlib change is not required
+ but it is more correct. Move the call to
+ AC_CANONICAL_HOST up in the file. Don't
+ set or subst ITCL_DIR since it is not used
+ and depends on pre Itcl 3.1 paths.
+ * library/Makefile.in: Regen.
+ * src/Makefile.in: Regen.
+
Fri Sep 17 19:14:15 1999 Andrew Cagney <cagney@b1.cygnus.com>
* src/guitcl.h (cyg_create_warp_pointer_command): Add declaration.
diff --git a/libgui/Makefile.in b/libgui/Makefile.in
index 7a332165274..0a369514dc5 100644
--- a/libgui/Makefile.in
+++ b/libgui/Makefile.in
@@ -59,6 +59,7 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
+AR = @AR@
BFDHDIR = @BFDHDIR@
BFDLIB = @BFDLIB@
CC = @CC@
@@ -84,7 +85,6 @@ ITCLLIB = @ITCLLIB@
ITCLMKIDX = @ITCLMKIDX@
ITCLSH = @ITCLSH@
ITCL_BUILD_LIB_SPEC = @ITCL_BUILD_LIB_SPEC@
-ITCL_DIR = @ITCL_DIR@
ITCL_LIB_FILE = @ITCL_LIB_FILE@
ITCL_LIB_FULL_PATH = @ITCL_LIB_FULL_PATH@
ITCL_SH = @ITCL_SH@
@@ -110,6 +110,7 @@ SIMHDIR = @SIMHDIR@
SIMLIB = @SIMLIB@
TCLCONFIG = @TCLCONFIG@
TCLHDIR = @TCLHDIR@
+TCL_BIN_DIR = @TCL_BIN_DIR@
TCL_BUILD_LIB_SPEC = @TCL_BUILD_LIB_SPEC@
TCL_CFLAGS = @TCL_CFLAGS@
TCL_DEFS = @TCL_DEFS@
@@ -154,7 +155,7 @@ configure.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-TAR = tar
+TAR = gtar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
diff --git a/libgui/TODO b/libgui/TODO
new file mode 100644
index 00000000000..6fd260c183f
--- /dev/null
+++ b/libgui/TODO
@@ -0,0 +1,29 @@
+- should have an intelligent way of mapping color use to color name
+ likewise fonts
+
+- ulset.tcl is not very easy to use
+ should write class to manage menubar
+ this could integrate ulset functionality and also balloon help
+ should look at iwidgets 2.2 again to make sure we
+ aren't gratuitously incompatible
+
+- add more bitmaps/gifs from S-N
+
+- use a real gettext, not the dummy one we have now
+ see if it is possible to use some of the gnu code, for instance
+ xgettext.
+ the runtime code must be written by us; probably just use db
+
+- rewrite the canvas patches as a pure extension
+ the current situation is terrible
+ later, use a different layout algorithm. ISI sucks.
+ See:
+ A Technique for Drawing Directed Graphs
+ Emden R Gansner, Eleftherios Koutsofios, Stephen C. North, and
+ Kiem-Phong Vo
+ IEEE Transactions on Software Engineering Vol 19, No 3
+
+- must have sensible way to track toplevel state and save in database
+
+- a way to make optionmenus which are statically sized to the
+ correct width
diff --git a/libgui/config.h.in b/libgui/config.h.in
index 3154f811749..c3779f19a6a 100644
--- a/libgui/config.h.in
+++ b/libgui/config.h.in
@@ -22,12 +22,6 @@
*/
#undef STACK_DIRECTION
-/* Name of package. */
-#undef PACKAGE
-
-/* Version of package. */
-#undef VERSION
-
/* Define this if <string.h> declares strncasecmp(). */
#undef HAVE_STRNCASECMP_DECL
@@ -46,9 +40,6 @@
/* Define if you have the random function. */
#undef HAVE_RANDOM
-/* Define if you have the strdup function. */
-#undef HAVE_STRDUP
-
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
@@ -75,3 +66,10 @@
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
+
+/* Name of package */
+#undef PACKAGE
+
+/* Version number of package */
+#undef VERSION
+
diff --git a/libgui/configure b/libgui/configure
index f11edd44fc4..e50b9b68c58 100755
--- a/libgui/configure
+++ b/libgui/configure
@@ -826,10 +826,37 @@ fi
MAINT=$MAINTAINER_MODE_TRUE
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:837: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:833: checking for $ac_word" >&5
+echo "configure:860: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -859,7 +886,7 @@ if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:863: checking for $ac_word" >&5
+echo "configure:890: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -910,7 +937,7 @@ fi
# Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:914: checking for $ac_word" >&5
+echo "configure:941: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -942,7 +969,7 @@ fi
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:946: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:973: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -953,12 +980,12 @@ cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext << EOF
-#line 957 "configure"
+#line 984 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
-if { (eval echo configure:962: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:989: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
@@ -984,12 +1011,12 @@ if test $ac_cv_prog_cc_works = no; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:988: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:1015: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:993: checking whether we are using GNU C" >&5
+echo "configure:1020: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -998,7 +1025,7 @@ else
yes;
#endif
EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1002: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1029: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
@@ -1017,7 +1044,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:1021: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:1048: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1049,12 +1076,12 @@ else
fi
echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
-echo "configure:1053: checking for Cygwin environment" >&5
+echo "configure:1080: checking for Cygwin environment" >&5
if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1058 "configure"
+#line 1085 "configure"
#include "confdefs.h"
int main() {
@@ -1065,7 +1092,7 @@ int main() {
return __CYGWIN__;
; return 0; }
EOF
-if { (eval echo configure:1069: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1096: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_cygwin=yes
else
@@ -1082,19 +1109,19 @@ echo "$ac_t""$ac_cv_cygwin" 1>&6
CYGWIN=
test "$ac_cv_cygwin" = yes && CYGWIN=yes
echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
-echo "configure:1086: checking for mingw32 environment" >&5
+echo "configure:1113: checking for mingw32 environment" >&5
if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1091 "configure"
+#line 1118 "configure"
#include "confdefs.h"
int main() {
return __MINGW32__;
; return 0; }
EOF
-if { (eval echo configure:1098: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1125: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_mingw32=yes
else
@@ -1113,7 +1140,7 @@ test "$ac_cv_mingw32" = yes && MINGW32=yes
echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
-echo "configure:1117: checking for executable suffix" >&5
+echo "configure:1144: checking for executable suffix" >&5
if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1123,7 +1150,7 @@ else
rm -f conftest*
echo 'int main () { return 0; }' > conftest.$ac_ext
ac_cv_exeext=
- if { (eval echo configure:1127: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ if { (eval echo configure:1154: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
for file in conftest.*; do
case $file in
*.c | *.o | *.obj | *.ilk | *.pdb) ;;
@@ -1144,13 +1171,13 @@ echo "$ac_t""${ac_cv_exeext}" 1>&6
ac_exeext=$EXEEXT
echo $ac_n "checking for object suffix""... $ac_c" 1>&6
-echo "configure:1148: checking for object suffix" >&5
+echo "configure:1175: checking for object suffix" >&5
if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
rm -f conftest*
echo 'int i = 1;' > conftest.$ac_ext
-if { (eval echo configure:1154: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1181: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
for ac_file in conftest.*; do
case $ac_file in
*.c) ;;
@@ -1191,10 +1218,66 @@ else
INSTALL_LIBGUI_TRUE='#'
INSTALL_LIBGUI_FALSE=
fi
-# Extract the first word of "ranlib", so it can be a program name with args.
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:1223: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+if test $host != $build; then
+ ac_tool_prefix=${host_alias}-
+else
+ ac_tool_prefix=
+fi
+
+# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1249: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_RANLIB"; then
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1198: checking for $ac_word" >&5
+echo "configure:1281: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1221,10 +1304,82 @@ else
echo "$ac_t""no" 1>&6
fi
+else
+ RANLIB=":"
+fi
+fi
+
+# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1316: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+AR="$ac_cv_prog_AR"
+if test -n "$AR"; then
+ echo "$ac_t""$AR" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_AR"; then
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1348: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_AR="ar"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_AR" && ac_cv_prog_AR=":"
+fi
+fi
+AR="$ac_cv_prog_AR"
+if test -n "$AR"; then
+ echo "$ac_t""$AR" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ AR=":"
+fi
+fi
+
# Extract the first word of "itcl_sh", so it can be a program name with args.
set dummy itcl_sh; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1228: checking for $ac_word" >&5
+echo "configure:1383: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_ITCL_SH'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1253,7 +1408,7 @@ fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:1257: checking how to run the C preprocessor" >&5
+echo "configure:1412: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
@@ -1268,13 +1423,13 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
-#line 1272 "configure"
+#line 1427 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1278: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1433: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -1285,13 +1440,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
-#line 1289 "configure"
+#line 1444 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1295: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1450: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -1302,13 +1457,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -nologo -E"
cat > conftest.$ac_ext <<EOF
-#line 1306 "configure"
+#line 1461 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1312: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1467: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -1335,19 +1490,19 @@ echo "$ac_t""$CPP" 1>&6
# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
# for constant arguments. Useless!
echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
-echo "configure:1339: checking for working alloca.h" >&5
+echo "configure:1494: checking for working alloca.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1344 "configure"
+#line 1499 "configure"
#include "confdefs.h"
#include <alloca.h>
int main() {
char *p = alloca(2 * sizeof(int));
; return 0; }
EOF
-if { (eval echo configure:1351: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1506: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_header_alloca_h=yes
else
@@ -1368,12 +1523,12 @@ EOF
fi
echo $ac_n "checking for alloca""... $ac_c" 1>&6
-echo "configure:1372: checking for alloca" >&5
+echo "configure:1527: checking for alloca" >&5
if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1377 "configure"
+#line 1532 "configure"
#include "confdefs.h"
#ifdef __GNUC__
@@ -1401,7 +1556,7 @@ int main() {
char *p = (char *) alloca(1);
; return 0; }
EOF
-if { (eval echo configure:1405: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1560: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_func_alloca_works=yes
else
@@ -1433,12 +1588,12 @@ EOF
echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
-echo "configure:1437: checking whether alloca needs Cray hooks" >&5
+echo "configure:1592: checking whether alloca needs Cray hooks" >&5
if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1442 "configure"
+#line 1597 "configure"
#include "confdefs.h"
#if defined(CRAY) && ! defined(CRAY2)
webecray
@@ -1463,12 +1618,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6
if test $ac_cv_os_cray = yes; then
for ac_func in _getb67 GETB67 getb67; do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1467: checking for $ac_func" >&5
+echo "configure:1622: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1472 "configure"
+#line 1627 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -1491,7 +1646,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:1495: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1650: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -1518,7 +1673,7 @@ done
fi
echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
-echo "configure:1522: checking stack direction for C alloca" >&5
+echo "configure:1677: checking stack direction for C alloca" >&5
if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1526,7 +1681,7 @@ else
ac_cv_c_stack_direction=0
else
cat > conftest.$ac_ext <<EOF
-#line 1530 "configure"
+#line 1685 "configure"
#include "confdefs.h"
find_stack_direction ()
{
@@ -1545,7 +1700,7 @@ main ()
exit (find_stack_direction() < 0);
}
EOF
-if { (eval echo configure:1549: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1704: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_stack_direction=1
else
@@ -1570,17 +1725,17 @@ for ac_hdr in stddef.h stdlib.h getopt.h unistd.h fcntl.h sys/file.h sys/wait.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1574: checking for $ac_hdr" >&5
+echo "configure:1729: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1579 "configure"
+#line 1734 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1584: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1739: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1606,15 +1761,15 @@ else
fi
done
-for ac_func in raise strdup
+for ac_func in raise
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1613: checking for $ac_func" >&5
+echo "configure:1768: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1618 "configure"
+#line 1773 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -1637,7 +1792,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:1641: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1796: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -1695,12 +1850,12 @@ fi
for ac_func in random drand48 rand
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1699: checking for $ac_func" >&5
+echo "configure:1854: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1704 "configure"
+#line 1859 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -1723,7 +1878,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:1727: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1882: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -1749,7 +1904,7 @@ done
cat > conftest.$ac_ext <<EOF
-#line 1753 "configure"
+#line 1908 "configure"
#include "confdefs.h"
#include <string.h>
EOF
@@ -1774,12 +1929,12 @@ fi
echo $ac_n "checking for cygwin32""... $ac_c" 1>&6
-echo "configure:1778: checking for cygwin32" >&5
+echo "configure:1933: checking for cygwin32" >&5
if eval "test \"`echo '$''{'ide_cv_os_cygwin32'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1783 "configure"
+#line 1938 "configure"
#include "confdefs.h"
#ifdef __CYGWIN32__
@@ -1816,7 +1971,7 @@ fi
# Find the init.tcl file.
echo $ac_n "checking for init.tcl""... $ac_c" 1>&6
-echo "configure:1820: checking for init.tcl" >&5
+echo "configure:1975: checking for init.tcl" >&5
if eval "test \"`echo '$''{'ac_cv_c_tcl_libdir'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1851,7 +2006,7 @@ if test "${with_tclconfig+set}" = set; then
fi
echo $ac_n "checking for Tcl configuration script""... $ac_c" 1>&6
-echo "configure:1855: checking for Tcl configuration script" >&5
+echo "configure:2010: checking for Tcl configuration script" >&5
if eval "test \"`echo '$''{'ac_cv_c_tclconfig'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1928,6 +2083,7 @@ fi
+
@@ -1942,7 +2098,7 @@ if test "${with_tkconfig+set}" = set; then
fi
echo $ac_n "checking for Tk configuration script""... $ac_c" 1>&6
-echo "configure:1946: checking for Tk configuration script" >&5
+echo "configure:2102: checking for Tk configuration script" >&5
if eval "test \"`echo '$''{'ac_cv_c_tkconfig'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2022,7 +2178,7 @@ fi
dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
no_tcl=true
echo $ac_n "checking for Tcl headers in the source tree""... $ac_c" 1>&6
-echo "configure:2026: checking for Tcl headers in the source tree" >&5
+echo "configure:2182: checking for Tcl headers in the source tree" >&5
# Check whether --with-tclinclude or --without-tclinclude was given.
if test "${with_tclinclude+set}" = set; then
withval="$with_tclinclude"
@@ -2079,17 +2235,17 @@ if test x"${ac_cv_c_tclh}" = x ; then
echo "$ac_t""none" 1>&6
ac_safe=`echo "tcl.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for tcl.h""... $ac_c" 1>&6
-echo "configure:2083: checking for tcl.h" >&5
+echo "configure:2239: checking for tcl.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2088 "configure"
+#line 2244 "configure"
#include "confdefs.h"
#include <tcl.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2093: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2249: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -2153,7 +2309,7 @@ fi
dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
no_tk=true
echo $ac_n "checking for Tk headers in the source tree""... $ac_c" 1>&6
-echo "configure:2157: checking for Tk headers in the source tree" >&5
+echo "configure:2313: checking for Tk headers in the source tree" >&5
# Check whether --with-tkinclude or --without-tkinclude was given.
if test "${with_tkinclude+set}" = set; then
withval="$with_tkinclude"
@@ -2231,39 +2387,6 @@ fi
-# Make sure we can run config.sub.
-if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
-else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
-fi
-
-echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:2241: checking host system type" >&5
-
-host_alias=$host
-case "$host_alias" in
-NONE)
- case $nonopt in
- NONE)
- if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
- else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
- fi ;;
- *) host_alias=$nonopt ;;
- esac ;;
-esac
-
-host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
-host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
-host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
-host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-echo "$ac_t""$host" 1>&6
-
-case ${host} in
-*cygwin*) ITCL_DIR=itcl/itcl/win ;;
-*) ITCL_DIR=itcl/itcl/unix ;;
-esac
-
-
-
@@ -2432,6 +2555,11 @@ s%@SET_MAKE@%$SET_MAKE%g
s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g
s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g
s%@MAINT@%$MAINT%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
s%@CC@%$CC%g
s%@EXEEXT@%$EXEEXT%g
s%@OBJEXT@%$OBJEXT%g
@@ -2439,7 +2567,13 @@ s%@CROSS_COMPILING_TRUE@%$CROSS_COMPILING_TRUE%g
s%@CROSS_COMPILING_FALSE@%$CROSS_COMPILING_FALSE%g
s%@INSTALL_LIBGUI_TRUE@%$INSTALL_LIBGUI_TRUE%g
s%@INSTALL_LIBGUI_FALSE@%$INSTALL_LIBGUI_FALSE%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
s%@RANLIB@%$RANLIB%g
+s%@AR@%$AR%g
s%@ITCL_SH@%$ITCL_SH%g
s%@CPP@%$CPP%g
s%@ALLOCA@%$ALLOCA%g
@@ -2461,6 +2595,7 @@ s%@TCL_LD_SEARCH_FLAGS@%$TCL_LD_SEARCH_FLAGS%g
s%@TCL_RANLIB@%$TCL_RANLIB%g
s%@TCL_BUILD_LIB_SPEC@%$TCL_BUILD_LIB_SPEC%g
s%@TCL_LIB_SPEC@%$TCL_LIB_SPEC%g
+s%@TCL_BIN_DIR@%$TCL_BIN_DIR%g
s%@TKCONFIG@%$TKCONFIG%g
s%@TK_VERSION@%$TK_VERSION%g
s%@TK_DEFS@%$TK_DEFS%g
@@ -2474,12 +2609,6 @@ s%@TK_BUILD_LIB_SPEC@%$TK_BUILD_LIB_SPEC%g
s%@TK_LIB_SPEC@%$TK_LIB_SPEC%g
s%@TCLHDIR@%$TCLHDIR%g
s%@TKHDIR@%$TKHDIR%g
-s%@host@%$host%g
-s%@host_alias@%$host_alias%g
-s%@host_cpu@%$host_cpu%g
-s%@host_vendor@%$host_vendor%g
-s%@host_os@%$host_os%g
-s%@ITCL_DIR@%$ITCL_DIR%g
s%@TCL_SHARED_TRUE@%$TCL_SHARED_TRUE%g
s%@TCL_SHARED_FALSE@%$TCL_SHARED_FALSE%g
s%@RPATH_ENVVAR@%$RPATH_ENVVAR%g
@@ -2491,7 +2620,7 @@ cat >> $CONFIG_STATUS <<\EOF
# Split the substitutions into bite-sized pieces for seds with
# small command number limits, like on Digital OSF/1 and HP-UX.
-ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_max_sed_cmds=60 # Maximum number of lines to put in a sed script.
ac_file=1 # Number of current file.
ac_beg=1 # First line for current file.
ac_end=$ac_max_sed_cmds # Line after last line for current file.
diff --git a/libgui/configure.in b/libgui/configure.in
index 479663d6732..c6466ce66ff 100644
--- a/libgui/configure.in
+++ b/libgui/configure.in
@@ -4,6 +4,7 @@ AC_INIT(src/subcommand.h)
AM_INIT_AUTOMAKE(libgui, 0.0)
AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
+AC_CANONICAL_HOST
AC_PROG_CC
AC_EXEEXT
AC_OBJEXT
@@ -11,13 +12,14 @@ AC_ARG_ENABLE(install-libgui, \
[ --enable-install-libgui Install libgui.a and library header files])
AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes)
AM_CONDITIONAL(INSTALL_LIBGUI, test x$enable_install_libgui = xyes)
-AC_PROG_RANLIB
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(AR, ar, :)
AC_CHECK_PROG(ITCL_SH, itcl_sh, itcl_sh,
[\$\$here/\$(top_builddir)/../itcl/itcl/unix/itcl_sh\$(EXEEXT)])
AC_FUNC_ALLOCA
AC_HAVE_HEADERS(stddef.h stdlib.h getopt.h unistd.h fcntl.h sys/file.h sys/wait.h string.h strings.h)
-AC_CHECK_FUNCS(raise strdup)
+AC_CHECK_FUNCS(raise)
AC_ARG_ENABLE(ide, [ --enable-ide Enable IDE support],
[case "${enableval}" in
@@ -99,13 +101,6 @@ CYG_AC_PATH_TCLH
# FIXME: consider only doing this if --with-x given.
CYG_AC_PATH_TKH
-dnl what is the path to itclsh?
-AC_CANONICAL_HOST
-case ${host} in
-*cygwin*) ITCL_DIR=itcl/itcl/win ;;
-*) ITCL_DIR=itcl/itcl/unix ;;
-esac
-
AC_SUBST(TCL_DEFS)
AC_SUBST(TK_DEFS)
AC_SUBST(TCLHDIR)
@@ -115,7 +110,6 @@ AC_SUBST(TCL_LIBS)
AC_SUBST(TK_BUILD_LIB_SPEC)
AC_SUBST(TCL_BUILD_LIB_SPEC)
AC_SUBST(TK_LIBS)
-AC_SUBST(ITCL_DIR)
AM_CONDITIONAL(TCL_SHARED, test x$TCL_SHARED_BUILD = x1)
diff --git a/libgui/doc/tkTable.html b/libgui/doc/tkTable.html
new file mode 100644
index 00000000000..e7c65978d75
--- /dev/null
+++ b/libgui/doc/tkTable.html
@@ -0,0 +1,1907 @@
+<!-- manual page source format generated by PolyglotMan v3.0.7, -->
+<!-- available via anonymous ftp from ftp.cs.berkeley.edu:/ucb/people/phelps/tcltk/rman.tar.Z -->
+
+<HTML>
+<HEAD>
+<TITLE>man page(1)</TITLE>
+</HEAD>
+<BODY bgcolor=white>
+<A HREF="#toc">Table of Contents</A><P>
+_________________________________________________________________
+
+<H2><A NAME="sect0" HREF="#toc0"><B>Name</B></A></H2>
+
+<P>
+table - Create and manipulate tables
+
+<H2><A NAME="sect1" HREF="#toc1"><B>Synopsis</B></A></H2>
+
+<P>
+<B>table</B> <I>pathName</I> ?<I>options</I>?
+
+<H2><A NAME="sect2" HREF="#toc2"><B>Standard</B> <B>Options</B></A></H2>
+
+
+<DL>
+
+<DT><B>-anchor</B> </DT></DT>
+<DD> <B>-background</B> <B>-cursor</B>
+</DD>
+
+<DT><B>-exportselection</B> </DT></DT>
+<DD> <B>-font</B> <B>-foreground</B>
+</DD>
+
+<DT><B>-highlightbackground</B> </DT></DT>
+<DD> <B>-highlightcolor</B> <B>-highlightthickness</B>
+</DD>
+
+<DT><B>-insertbackground</B> </DT></DT>
+<DD> <B>-insertborderwidth-insertofftime</B>
+<B>-insertontime</B> <B>-insertwidth</B> <B>-invertselected</B>
+</DD>
+
+<DT><B>-relief</B> </DT></DT>
+<DD> <B>-takefocus</B> <B>-xscrollcommand</B>
+<B>-yscrollcommand</B>
+</DD>
+</DL>
+<P>
+See the <B>options</B> manual entry for details on the standard
+options.
+
+<H2><A NAME="sect3" HREF="#toc3"><B>Widget-specific</B> <B>Options</B></A></H2>
+
+<P>
+Command-Line Name:<B>-autoclear</B><BR>
+
+Database Name: <B>autoClear</B><BR>
+
+Database Class: <B>AutoClear</B>
+<P>
+A boolean value which specifies whether the first
+keypress in a cell will delete whatever text was
+previously there. Defaults to 0.
+<P>
+Command-Line Name:<B>-bordercursor</B><BR>
+
+Database Name: <B>borderCursor</B><BR>
+
+Database Class: <B>Cursor</B>
+<P>
+Specifies the name of the cursor to show when over
+borders, a visual indication that interactive
+resizing is allowed (it is thus affect by the value
+of -resizeborders). Defaults to <I>crosshair</I>.
+<P>
+Command-Line Name:<B>-borderwidth</B> <B>or</B> <B>-bd</B><BR>
+
+Database Name: <B>borderWidth</B><BR>
+
+Database Class: <B>BorderWidth</B>
+<P>
+Specifies a non-negative pixel value or list of
+values indicating the width of the 3-D border to
+draw on interior table cells (if such a border is
+being drawn; the <B>relief</B> option typically determines
+this). If one value is specified, a rectangle of
+this width will be drawn. If two values are specified,
+then only the left and right edges of the
+cell will have borders. If four values are specified,
+then the values correspond to the {left right
+top bottom} edges. This can be overridden by the a
+tag's borderwidth option. It can also be affected
+by the defined <B>-drawmode</B> for the table. Each value
+in the list must have one of the forms acceptable
+to <B>Tk_GetPixels</B>.
+<P>
+Command-Line Name:<B>-browsecommand</B> <B>or</B> <B>-browsecmd</B>
+Database Name: <B>browseCommand</B><BR>
+
+Database Class: <B>BrowseCommand</B>
+<P>
+Specifies a command which will be evaluated anytime
+the active cell changes. It uses the %-substition
+model described in COMMAND SUBSTITUTION below.
+<P>
+Command-Line Name:<B>-cache</B><BR>
+
+Database Name: <B>cache</B><BR>
+
+Database Class: <B>Cache</B>
+<P>
+A boolean value that specifies whether an internal
+cache of the table contents should be kept. This
+greatly enhances speed performance when used with
+<B>-command</B> but uses extra memory. Can maintain state
+when both <B>-command</B> and <B>-variable</B> are empty. The
+cache is automatically flushed whenever the value
+of <B>-cache</B> or <B>-variable</B> changes, otherwise you have
+to explicitly call <B>clear</B> on it. Defaults to off.
+<P>
+Command-Line Name:<B>-colorigin</B><BR>
+
+Database Name: <B>colOrigin</B><BR>
+
+Database Class: <B>Origin</B>
+<P>
+Specifies what column index to interpret as the
+leftmost column in the table. This value is used
+for user indices in the table. Defaults to 0.
+<P>
+Command-Line Name:<B>-cols</B><BR>
+
+Database Name: <B>cols</B><BR>
+
+Database Class: <B>Cols</B>
+<P>
+Number of cols in the table. Defaults to 10.
+<P>
+Command-Line Name:<B>-colseparator</B><BR>
+
+Database Name: <B>colSeparator</B><BR>
+
+Database Class: <B>Separator</B>
+<P>
+Specifies a separator character that will be interpreted
+as the column separator when cutting or
+pasting data in a table. By default, columns are
+separated as elements of a tcl list.
+<P>
+Command-Line Name:<B>-colstretchmode</B><BR>
+
+Database Name: <B>colStretchMode</B><BR>
+
+Database Class: <B>StretchMode</B>
+<P>
+Specifies one of the following stretch modes for
+columns to fill extra allocated window space:
+<B>none</B> Columns will not stretch to fill the
+assigned window space. If the columns are
+too narrow, there will be a blank space at
+the right of the table. This is the
+default.
+<P>
+<B>unset</B> Only columns that do not have a specific
+width set will be stretched.
+
+<DL>
+
+<DT><B>all</B> </DT></DT>
+<DD> All columns will be stretched by the same
+number of pixels to fill the window space
+allocated to the table. This mode can
+interfere with interactive border resizing
+which tries to force column width.
+</DD>
+</DL>
+<P>
+<B>last</B> The last column will be stretched to fill
+the window space allocated to the table.
+<P>
+<B>fill</B> (only valid for <B>-rowstretch</B> currently)
+The table will get more or less columns
+according to the window space allocated to
+the table. This mode has numerous quirks
+and may disappear in the future.
+<P>
+Command-Line Name:<B>-coltagcommand</B><BR>
+
+Database Name: <B>colTagCommand</B><BR>
+
+Database Class: <B>TagCommand</B>
+<P>
+Provides the name of a procedure that will be evaluated
+by the widget to determine the tag to be used
+for a given column. When displaying a cell, the
+table widget will first check to see if a tag has
+been defined using the <B>tag</B> <B>col</B> widget method. If
+no tag is found, it will evaluate the named procedure
+passing the column number in question as the
+sole argument. The procedure is expected to return
+the name of a tag to use, or a null string. Errors
+occuring during the evaluation of the procedure, or
+the return of an invalid tag name are silently
+ignored.
+<P>
+Command-Line Name:<B>-colwidth</B><BR>
+
+Database Name: <B>colWidth</B><BR>
+
+Database Class: <B>ColWidth</B>
+<P>
+Default column width, interpreted as characters in
+the default font when the number is positive, or
+pixels if it is negative. Defaults to 10.
+<P>
+Command-Line Name:<B>-command</B><BR>
+
+Database Name: <B>command</B><BR>
+
+Database Class: <B>Command</B>
+<P>
+Specified a command to use as a procedural
+interface to cell values. If <B>-usecommand</B> is true,
+this command will be used instead of any reference
+to the <B>-variable</B> array. When retrieving cell values,
+the return value of the command is used as the
+value for the cell. It uses the %-substition model
+described in COMMAND SUBSTITUTION below.
+<P>
+Command-Line Name:<B>-drawmode</B><BR>
+
+Database Name: <B>drawMode</B><BR>
+
+Database Class: <B>DrawMode</B>
+<P>
+Sets the table drawing mode to one of the following
+options:
+<P>
+<B>slow</B> The table is drawn to an offscreen pixmap
+using the Tk bordering functions (doublebuffering).
+This means there will be no
+flashing, but this mode is slow for larger
+tables.
+<P>
+<B>compatible</B><BR>
+
+The table is drawn directly to the screen
+using the Tk border functions. It is
+faster, but the screen may flash on update.
+This is the default.
+<P>
+<B>fast</B> The table is drawn directly to the screen
+and the borders are done with fast X calls,
+so they are always one pixel wide only. As
+a side effect, it restricts <B>-borderwidth</B> to
+a range of 0 or 1. This mode provides best
+performance for large tables, but can flash
+on redraw and is not 100% Tk compatible on
+the border mode.
+<P>
+<B>single</B> The table is drawn to the screen as in fast
+mode, but only single pixel lines are drawn
+(not square borders).
+<P>
+Command-Line Name:<B>-flashmode</B><BR>
+
+Database Name: <B>flashMode</B><BR>
+
+Database Class: <B>FlashMode</B>
+<P>
+A boolean value which specifies whether cells
+should flash when their value changes. The table
+tag <B>flash</B> will be applied to these cells for the
+duration specified by <B>-flashtime</B>. Defaults to 0.
+<P>
+Command-Line Name:<B>-flashtime</B><BR>
+
+Database Name: <B>flashTime</B><BR>
+
+Database Class: <B>FlashTime</B>
+<P>
+The amount of time, in 1/4 second increments, for
+which a cell should flash when its value has
+changed. <B>-flashmode</B> must be on. Defaults to 2.
+<P>
+Command-Line Name:<B>-height</B><BR>
+
+Database Name: <B>height</B><BR>
+
+Database Class: <B>Height</B>
+<P>
+Specifies the desired height for the window, in
+rows. If zero or less, then the desired height for
+the window is made just large enough to hold all
+the rows in the table. The height can be further
+limited by <B>-maxheight</B>.
+<P>
+Command-Line Name:<B>-invertselected</B><BR>
+
+Database Name: <B>invertSelected</B><BR>
+
+Database Class: <B>InvertSelected</B>
+<P>
+Specifies whether the foreground and background of
+an item should simply have their values swapped
+instead of merging the <I>sel</I> tag options when the
+cell is selected. Defaults to 0 (merge <I>sel</I> tag).
+<P>
+Command-Line Name:<B>-ipadx</B><BR>
+
+Database Name: <B>ipadX</B><BR>
+
+Database Class: <B>Pad</B>
+<P>
+A pixel value specifying the internal offset X
+padding for text in a cell. This value does not
+grow the size of the cell, it just causes the text
+to be drawn further from the cell border. It only
+affects one side (depending on anchor). Defaults
+to 0. See <B>-padx</B> for an alternate padding style.
+<P>
+Command-Line Name:<B>-ipady</B><BR>
+
+Database Name: <B>ipadY</B><BR>
+
+Database Class: <B>Pad</B>
+<P>
+A pixel value specifying the internal offset Y
+padding for text in a cell. This value does not
+grow the size of the cell, it just causes the text
+to be drawn further from the cell border. It only
+affects one side (depending on anchor). Defaults
+to 0. See <B>-pady</B> for an alternate padding style.
+<P>
+Command-Line Name:<B>-maxheight</B><BR>
+
+Database Name: <B>maxHeight</B><BR>
+
+Database Class: <B>MaxHeight</B>
+<P>
+The max height in pixels that the window will
+request. Defaults to 600.
+<P>
+Command-Line Name:<B>-maxwidth</B><BR>
+
+Database Name: <B>maxWidth</B><BR>
+
+Database Class: <B>MaxWidth</B>
+<P>
+The max width in pixels that the window will
+request. Defaults to 800.
+<P>
+Command-Line Name:<B>-multiline</B><BR>
+
+Database Name: <B>multiline</B><BR>
+
+Database Class: <B>Multiline</B>
+<P>
+Specifies the default setting for the multiline tag
+option. Defaults to 1.
+<P>
+Command-Line Name:<B>-padx</B><BR>
+
+Database Name: <B>padX</B><BR>
+
+Database Class: <B>Pad</B>
+<P>
+A pixel value specifying the offset X padding for a
+cell. This value causes the default size of the
+cell to increase by two times the value (one for
+each side), unless a specific pixel size is chosen
+for the cell with the <B>width</B> command. This will
+force an empty area on the left and right of each
+cell edge. This padding affects all types of data
+in the cell. Defaults to 0. See <B>-ipadx</B> for an
+alternate padding style.
+<P>
+Command-Line Name:<B>-pady</B><BR>
+
+Database Name: <B>padY</B><BR>
+
+Database Class: <B>Pad</B>
+<P>
+A pixel value specifying the offset Y padding for a
+cell. This value causes the default size of the
+cell to increase by two times the value (one for
+each side), unless a specific pixel size is chosen
+for the cell with the <B>height</B> command. This will
+force an empty area on the top and bottom of each
+cell edge. This padding affects all types of data
+in the cell. Defaults to 0. See <B>-ipadx</B> for an
+alternate padding style.
+<P>
+Command-Line Name:<B>-resizeborders</B><BR>
+
+Database Name: <B>resizeBorders</B><BR>
+
+Database Class: <B>ResizeBorders</B>
+<P>
+Specifies what kind of interactive border resizing
+to allow, must be one of row, col, both (default)
+or none.
+<P>
+Command-Line Name:<B>-rowheight</B><BR>
+
+Database Name: <B>rowHeight</B><BR>
+
+Database Class: <B>RowHeight</B>
+<P>
+Default row height, interpreted as lines in the
+default font when the number is positive, or pixels
+if it is negative. Defaults to 1.
+<P>
+Command-Line Name:<B>-roworigin</B><BR>
+
+Database Name: <B>rowOrigin</B><BR>
+
+Database Class: <B>Origin</B>
+<P>
+Specifies what row index to interpret as the topmost
+row in the table. This value is used for user
+indices in the table. Defaults to 0.
+<P>
+Command-Line Name:<B>-rows</B><BR>
+
+Database Name: <B>rows</B><BR>
+
+Database Class: <B>Rows</B>
+<P>
+Number of rows in the table. Defaults to 10.
+<P>
+Command-Line Name:<B>-rowseparator</B><BR>
+
+Database Name: <B>rowSeparator</B><BR>
+
+Database Class: <B>Separator</B>
+<P>
+Specifies a separator character that will be interpreted
+as the row separator when cutting or pasting
+data in a table. By default, rows are separated as
+tcl lists.
+<P>
+Command-Line Name:<B>-rowstretchmode</B><BR>
+
+Database Name: <B>rowStretchMode</B><BR>
+
+Database Class: <B>StretchMode</B>
+<P>
+Specifies the stretch modes for rows to fill extra
+allocated window space. See <B>-colstretchmode</B> for
+valid options.
+<P>
+Command-Line Name:<B>-rowtagcommand</B><BR>
+
+Database Name: <B>rowTagCommand</B><BR>
+
+Database Class: <B>TagCommand</B>
+<P>
+Provides the name of a procedure that can evaluated
+by the widget to determine the tag to be used for a
+given row. The procedure must be defined by the
+user to accept a single argument (the row number),
+and return a tag name or null string. This operates
+in a similar manner as <B>-coltagcommand</B>, except
+that it applies to row tags.
+<P>
+Command-Line Name:<B>-selectioncommand</B> <B>or</B> <B>-selcmd</B>
+Database Name: <B>selectionCommand</B><BR>
+
+Database Class: <B>SelectionCommand</B>
+<P>
+Specifies a command to evaluate when the selection
+is retrieved from a table via the selection mechanism
+(ie: evaluating &laquo;<B>selection</B> <B>get</B>"). The return
+value from this command will become the string
+passed on by the selection mechanism. It uses the
+%-substition model described in COMMAND SUBSTITUTION
+below. If an error occurs, a Tcl background
+error is generated and nothing is returned.
+<P>
+Command-Line Name:<B>-selectmode</B><BR>
+
+Database Name: <B>selectMode</B><BR>
+
+Database Class: <B>SelectMode</B>
+<P>
+Specifies one of several styles for manipulating
+the selection. The value of the option may be
+arbitrary, but the default bindings expect it to be
+either <B>single</B>, <B>browse</B>, <B>multiple</B>, or <B>extended</B>; the
+default value is <B>browse</B>. These styles are like
+those for the Tk listbox, except expanded for 2
+dimensions.
+<P>
+Command-Line Name:<B>-selecttitle</B><BR>
+
+Database Name: <B>selectTitles</B><BR>
+
+Database Class: <B>SelectTitles</B>
+<P>
+Specifies whether title cells should be allowed in
+the selection. Defaults to 0 (disallowed).
+<P>
+Command-Line Name:<B>-selecttype</B><BR>
+
+Database Name: <B>selectType</B><BR>
+
+Database Class: <B>SelectType</B>
+<P>
+Specifies one of several types of selection for the
+table. The value of the option may be one of <B>row</B>,
+<B>col</B>, <B>cell</B>, or <B>both</B> (meaning <B>row</B> <B>&amp;&amp;</B> <B>col</B>); the
+default value is <B>cell</B>. These types define whether
+an entire row/col is affected when a cell's selection
+is changed (set or clear).
+<P>
+Command-Line Name:<B>-sparsearray</B><BR>
+
+Database Name: <B>sparseArray</B><BR>
+
+Database Class: <B>SparseArray</B>
+<P>
+A boolean value that specifies whether an associated
+Tcl array should be kept as a sparse array (1,
+the default) or as a full array (0). If true, then
+cell values that are empty will be deleted from the
+array (taking less memory). If false, then all
+values in the array will be maintained.
+<P>
+Command-Line Name:<B>-state</B><BR>
+
+Database Name: <B>state</B><BR>
+
+Database Class: <B>State</B>
+
+<DL>
+
+<DT>Specifies one of two states for the entry: </DT></DT>
+<DD><B>normal</B>
+or <B>disabled</B>. If the table is disabled then the
+value may not be changed using widget commands and
+no insertion cursor will be displayed, even if the
+input focus is in the widget. Also, all insert or
+delete methods will be ignored. Defaults to <B>normal</B>.
+</DD>
+</DL>
+<P>
+Command-Line Name:<B>-titlecols</B><BR>
+
+Database Name: <B>titleCols</B><BR>
+
+Database Class: <B>TitleCols</B>
+<P>
+Number of columns to use as a title area. Defaults
+to 0.
+<P>
+Command-Line Name:<B>-titlerows</B><BR>
+
+Database Name: <B>titleRows</B><BR>
+
+Database Class: <B>TitleRows</B>
+<P>
+Number of rows to use as a title area. Defaults to
+0.
+<P>
+Command-Line Name:<B>-usecommand</B><BR>
+
+Database Name: <B>useCommand</B><BR>
+
+Database Class: <B>UseCommand</B>
+<P>
+A boolean value which specifies whether to use the
+<B>command</B> option. This value sets itself to zero if
+<B>command</B> is used and returns an error. Defaults to
+1 (will use <B>command</B> if specified).
+<P>
+Command-Line Name:<B>-validate</B><BR>
+
+Database Name: <B>validate</B><BR>
+
+Database Class: <B>Validate</B>
+<P>
+A boolean specifying whether validation should
+occur for the active buffer. Defaults to 0.
+<P>
+Command-Line Name:<B>-validatecommand</B> <B>or</B> <B>-vcmd</B>
+Database Name: <B>validateCommand</B><BR>
+
+Database Class: <B>ValidateCommand</B>
+<P>
+Specifies a command to execute when the active cell
+is edited. This command is expected to return a
+Tcl boolean. If it returns true, then it is
+assumed the new value is OK, otherwise the new
+value is rejected (the edition will not take
+place). Errors in this command are handled in the
+background. It uses the %-substition model
+described in COMMAND SUBSTITUTION below.
+<P>
+Command-Line Name:<B>-variable</B><BR>
+
+Database Name: <B>variable</B><BR>
+
+Database Class: <B>Variable</B>
+<P>
+Global Tcl array variable to attach to the table's
+C array. It will be created if it doesn't already
+exist or is a simple variable. Keys used by the
+table in the array are of the form <I>row</I>,<I>col</I> for
+cells and the special key <I>active</I> which contains the
+value of the active cell buffer. The Tcl array is
+managed as a sparse array (the table doesn't
+require all valid indices have values). No stored
+value for an index is equivalent to the empty
+string, and clearing a cell will remove that index
+from the Tcl array, unless the <B>-sparsearray</B> options
+is set to 0.
+<P>
+Command-Line Name:<B>-width</B><BR>
+
+Database Name: <B>width</B><BR>
+
+Database Class: <B>Width</B>
+<P>
+Specifies the desired width for the window, in
+columns. If zero or less, then the desired width
+for the window is made just large enough to hold
+all the columns in the table. The width can be
+further limited by <B>-maxwidth</B>.
+<P>
+Command-Line Name:<B>-wrap</B><BR>
+
+Database Name: <B>wrap</B><BR>
+
+Database Class: <B>Wrap</B>
+<P>
+Specifies the default wrap value for tags.
+Defaults to 0.<BR>
+
+_________________________________________________________________
+
+<H2><A NAME="sect4" HREF="#toc4"><B>Description</B></A></H2>
+
+<P>
+The <B>table</B> command creates a 2-dimensional grid of cells.
+The table can use a Tcl array variable or Tcl command for
+data storage and retrieval. The widget has an active
+cell, the contents of which can be edited (when the state
+is normal). The widget supports a default style for the
+cells and also multiple <I>tags</I>, which can be used to change
+the style of a row, column or cell (see TAGS for details).
+A cell <I>flash</I> can be set up so that changed cells will
+change color for a specified amount of time ("blink").
+Cells can have embedded images or windows, as described in
+TAGS and &laquo;EMBEDDED WINDOWS&raquo; respectively.
+<P>
+One or more cells may be selected as described below. If
+a table is exporting its selection (see <B>-exportselection</B>
+option), then it will observe the standard X11 protocols
+for handling the selection. See THE SELECTION for
+details.
+<P>
+It is not necessary for all the cells to be displayed in
+the table window at once; commands described below may be
+used to change the view in the window. Tables allow
+scrolling in both directions using the standard <B>-xscrollcommand</B>
+and <B>-yscrollcommand</B> options. They also support
+scanning, as described below.
+<P>
+In order to obtain good performance, the table widget supports
+multiple drawing modes, two of which are fully Tk
+compatible.
+
+<H2><A NAME="sect5" HREF="#toc5"><B>Initialization</B></A></H2>
+
+<P>
+When the <B>table</B> command is loaded into an interpreter, a
+built-in Tcl command, <B>tkTableInit</B>, is evaluated. This
+will search for the appropriate table binding init file to
+load. The directories searched are those in <I>$tcl</I><B>_</B><I>pkgPath</I>,
+both with Tktable(version) appended and without,
+<I>$tk</I><B>_</B><I>library</I> and <I>[pwd]</I> (the current directory). You can
+also define an <I>$env(TK</I><B>_</B><I>TABLE</I><B>_</B><I>LIBRARY)</I> to head this search
+list. By default, the file searched for is called
+<B>tkTable.tcl</B>, but this can be overridden by setting
+<I>$env(TK</I><B>_</B><I>TABLE</I><B>_</B><I>LIBRARY</I><B>_</B><I>FILE)</I>.
+<P>
+This entire init script can be overridden by providing
+your own <B>tkTableInit</B> procedure before the library is
+loaded. Otherwise, the aforementioned
+<I>env(TK</I><B>_</B><I>TABLE</I><B>_</B><I>LIBRARY)</I> variable will be set with the directory
+in which <I>$env(TK</I><B>_</B><I>TABLE</I><B>_</B><I>LIBRARY</I><B>_</B><I>FILE)</I> was found.
+
+<H2><A NAME="sect6" HREF="#toc6"><B>Indices</B></A></H2>
+
+<P>
+Many of the widget commands for tables take one or more
+indices as arguments. An index specifies a particular
+cell of the table, in any of the following ways:
+<P>
+<I>number,number</I><BR>
+
+Specifies the cell as a numerical index of
+row,col which corresponds to the index of the
+associated Tcl array, where <B>-roworigin,-colorigin</B>
+corresponds to the first cell in the
+table (0,0 by default).
+
+<DL>
+
+<DT><B>active</B> </DT></DT>
+<DD> Indicates the cell that has the location cursor.
+It is specified with the <B>activate</B> widget
+command.
+</DD>
+
+<DT><B>anchor</B> </DT></DT>
+<DD> Indicates the anchor point for the selection,
+which is set with the <B>selection</B> <B>anchor</B> widget
+command.
+</DD>
+</DL>
+<P>
+<B>bottomright</B> Indicates the bottom-rightmost cell visible in
+the table.
+
+<DL>
+
+<DT><B>end</B> </DT></DT>
+<DD> Indicates the bottom right cell of the table.
+</DD>
+
+<DT><B>origin</B> </DT></DT>
+<DD> Indicates the top-leftmost editable cell of
+the table, not necessarily in the display.
+This takes into account the user specified
+origin and title area.
+</DD>
+
+<DT><B>topleft</B> </DT></DT>
+<DD> Indicates the top-leftmost editable cell visible
+in the table (this excludes title cells).
+</DD>
+
+<DT><B>@</B><I>x</I><B>,</B><I>y</I> </DT></DT>
+<DD> Indicates the cell that covers the point in
+the table window specified by <I>x</I> and <I>y</I> (in
+pixel coordinates). If no cell covers that
+point, then the closest cell to that point is
+used.
+</DD>
+</DL>
+<P>
+In the widget command descriptions below, arguments named
+<I>index</I>, <I>first</I>, and <I>last</I> always contain text indices in one
+of the above forms.
+
+<H2><A NAME="sect7" HREF="#toc7"><B>Tags</B></A></H2>
+
+<P>
+A tag is a textual string that is associated with zero or
+more rows, columns or cells in a table. Tags may contain
+arbitrary characters, but it is probably best to avoid
+using names which look like indices to reduce coding confusion.
+There may be any number of tags in a table, but
+each row, column or cell can only have one tag associated
+with it at a time. There are several permanent tags in
+each table that can be configured by the user and will
+determine the attributes for special cells:
+
+<DL>
+
+<DT><B>active</B> </DT></DT>
+<DD> This tag is given to the <I>active</I> cell
+</DD>
+
+<DT><B>flash</B> </DT></DT>
+<DD> If flash mode is on, this tag is given to
+any recently edited cells.
+</DD>
+
+<DT><B>sel</B> </DT></DT>
+<DD> This tag is given to any selected cells.
+</DD>
+
+<DT><B>title</B> </DT></DT>
+<DD> This tag is given to any cells in the
+title rows and columns. This tag has
+<B>-state</B> <I>disabled</I> by default.
+</DD>
+</DL>
+<P>
+Tags control the way cells are displayed on the screen.
+Where appropriate, the default for displaying cells is
+determined by the options for the table widget. However,
+display options may be associated with individual tags
+using the ``<I>pathName</I> <B>tag</B> <B>configure</B>'' widget command. If a
+cell, row or column has been tagged, then the display
+options associated with the tag override the default display
+style. The following options are currently supported
+for tags:
+
+<DL>
+
+<DT><B>-anchor</B> <I>anchor</I></DT></DT>
+<DD>
+Anchor for item in the cell space.
+</DD>
+
+<DT><B>-background</B> or <B>-bg</B> <I>color</I></DT></DT>
+<DD>
+Background color of the cell.
+</DD>
+
+<DT><B>-borderwidth</B> or <B>-bd</B> <I>pixelList</I></DT></DT>
+<DD>
+Borderwidth of the cell, of the same format
+for the table, but may also be empty to
+inherit the default table borderwidth value
+(the default).
+</DD>
+
+<DT><B>-font</B> <I>fontName</I></DT></DT>
+<DD>
+Font for text in the cell.
+</DD>
+
+<DT><B>-foreground</B> or <B>-fg</B> <I>color</I></DT></DT>
+<DD>
+Foreground color of the cell.
+</DD>
+
+<DT><B>-justify</B> <I>justify</I></DT></DT>
+<DD>
+How to justify multi-line text in a cell.
+It must be one of <B>left</B>, <B>right</B>, or <B>center</B>.
+</DD>
+
+<DT><B>-image</B> <I>imageName</I></DT></DT>
+<DD>
+An image to display in the cell instead of
+text.
+</DD>
+
+<DT><B>-multiline</B> <I>boolean</I></DT></DT>
+<DD>
+Whether to display text with newlines on
+multiple lines.
+</DD>
+
+<DT><B>-relief</B> <I>relief</I></DT></DT>
+<DD>
+The relief for the cell.
+</DD>
+
+<DT><B>-showtext</B> <I>boolean</I></DT></DT>
+<DD>
+Whether to show the text over an image.
+</DD>
+
+<DT><B>-state</B> <I>state</I></DT></DT>
+<DD>
+The state of the cell, to allow for certain
+cells to be disabled. This prevents the
+cell from being edited by the <I>insert</I> or
+<I>delete</I> methods, but a direct <I>set</I> will not be
+prevented.
+</DD>
+
+<DT><B>-wrap</B> <I>boolean</I></DT></DT>
+<DD>
+Whether characters should wrap in a cell
+that is not wide enough.
+</DD>
+</DL>
+<P>
+A priority order is defined among tags based on creation
+order (first created tag has highest default priority),
+and this order is used in implementing some of the
+tag-related functions described below. When a cell is
+displayed, its properties are determined by the tags which
+are assigned to it. The priority of a tag can be modified
+by the ``<I>pathName</I> <B>tag</B> <B>lower</B>'' and ``<I>pathName</I> <B>tag</B> <B>raise</B>''
+widget commands.
+<P>
+If a cell has several tags associated with it that define
+the same display options (eg - a <B>title</B> cell with specific
+<B>row</B> and <B>cell</B> tags), then the options of the highest priority
+tag are used. If a particular display option hasn't
+been specified for a particular tag, or if it is specified
+as an empty string, then that option will not be used; the
+next-highest-priority tag's option will be used instead.
+If no tag specifies a particular display option, then the
+default style for the widget will be used.
+<P>
+Images are used for display purposes only. Editing in
+that cell will still be enabled and any querying of the
+cell will show the text value of the cell, regardless of
+the value of <B>-showtext</B>.
+
+<H2><A NAME="sect8" HREF="#toc8"><B>Embedded</B> <B>Windows</B></A></H2>
+
+<P>
+There may be any number of embedded windows in a table
+widget (one per cell), and any widget may be used as an
+embedded window (subject to the usual rules for geometry
+management, which require the table window to be the parent
+of the embedded window or a descendant of its parent).
+The embedded window's position on the screen will be
+updated as the table is modified or scrolled, and it will
+be mapped and unmapped as it moves into and out of the
+visible area of the table widget. Each embedded window
+occupies one cell's worth of space in the table widget,
+and it is referred to by the index of the cell in the
+table. Windows associated with the table widget are
+destroyed when the table widget is destroyed.
+<P>
+Windows are used for display purposes only. A value still
+exists for that cell, but will not be shown unless the
+window is deleted in some way. If the window is destroyed
+or lost by the table widget to another geometry manager,
+then any data associated with it is lost (the cell it
+occupied will no longer appear in <B>window</B> <B>names</B>).
+<P>
+When an embedded window is added to a table widget with
+the window configure widget command, several configuration
+options may be associated with it. These options may be
+modified with later calls to the window configure widget
+command. The following options are currently supported:
+
+<DL>
+
+<DT><B>-create</B> <I>script</I></DT></DT>
+<DD>
+NOT CURRENTLY SUPPORTED. Specifies a Tcl
+script that may be evaluated to create the
+window for the annotation. If no -window
+option has been specified for this cell then
+this script will be evaluated when the cell
+is about to be displayed on the screen.
+Script must create a window for the cell and
+return the name of that window as its
+result. If the cell's window should ever be
+deleted, the script will be evaluated again
+the next time the cell is displayed.
+</DD>
+
+<DT><B>-background</B> or <B>-bg</B> <I>color</I></DT></DT>
+<DD>
+Background color of the cell. If not specified,
+it uses the table's default background.
+</DD>
+
+<DT><B>-borderwidth</B> or <B>-bd</B> <I>pixelList</I></DT></DT>
+<DD>
+Borderwidth of the cell, of the same format
+for the table, but may also be empty to
+inherit the default table borderwidth value
+(the default).
+</DD>
+
+<DT><B>-padx</B> <I>pixels</I></DT></DT>
+<DD>
+As defined in the Tk options man page.
+</DD>
+
+<DT><B>-pady</B> <I>pixels</I></DT></DT>
+<DD>
+As defined in the Tk options man page.
+</DD>
+
+<DT><B>-relief</B> <I>relief</I></DT></DT>
+<DD>
+The relief to use for the cell in which the
+window lies. If not specified, it uses the
+table's default relief.
+</DD>
+
+<DT><B>-sticky</B> <I>sticky</I></DT></DT>
+<DD>
+Stickiness of the window inside the cell, as
+defined by the <B>grid</B> command.
+</DD>
+
+<DT><B>-window</B> <I>pathName</I></DT></DT>
+<DD>
+Specifies the name of a window to display in
+the annotation. It must exist before being
+specified here.
+</DD>
+</DL>
+
+<H2><A NAME="sect9" HREF="#toc9"><B>the</B> <B>Selection</B></A></H2>
+
+<P>
+Table selections are available as type STRING. By
+default, the value of the selection will be the values of
+the selected cells in nested Tcl list form where each row
+is a list and each column is an element of a row list.
+You can change the way this value is interpreted by setting
+the <B>-rowseparator</B> and <B>-colseparator</B> options. For
+example, default Excel format would be to set <B>-rowseparator</B>
+to &laquo;\n&raquo; and <B>-colseparator</B> to &laquo;\t". Changing these
+values affects both how the table sends out the selection
+and reads in pasted data, ensuring that the table should
+always be able to cut and paste to itself. It is possible
+to change how pastes are handled by editing the table
+library procedure <B>tk_tablePasteHandler</B>. This might be
+necessary if <B>-selectioncommand</B> is set.
+
+<H2><A NAME="sect10" HREF="#toc10"><B>Row/Col</B> <B>Spanning</B></A></H2>
+
+<P>
+Individual cells can span multiple rows and/or columns.
+This is done via the <B>spans</B> command (see below for exact
+arguments). Cells in the title area that span are not
+permitted to span beyond the title area, and will be constrained
+accordingly. If the title area shrinks during a
+configure, sanity checking will occur to ensure the above.
+You may set spans on regular cells that extend beyond the
+defined row/col area. These spans will not be constrained,
+so that when the defined row/col area expands,
+the span will expand with it.
+<P>
+When setting a span, checks are made as to whether the
+span would overlap an already spanning or hidden cell.
+This is an error and it not allowed. Spans can affect the
+overall speed of table drawing, although not significantly.
+If spans are not used, then there is no performance
+loss.
+<P>
+Cells <I>hidden</I> by spanning cells still have valid data.
+This will be seen during cut and paste operations that
+involve hidden cells, or through direct access by a command
+like <B>get</B> or <B>set</B>.
+<P>
+The drawing properties of spanning cells apply to only the
+visual area of the cell. For example, if a cell is center
+justified over 5 columns, then when viewing any portion of
+those columns, it will appear centered in the visible
+area. The non-visible column area will not be considered
+in the centering calculations.
+
+<H2><A NAME="sect11" HREF="#toc11"><B>Command</B> <B>Substitution</B></A></H2>
+
+<P>
+The various option based commands that the table supports
+all support the familiar Tk %-substitution model (see <B>bind</B>
+for more details). The following %-sequences are recognized
+and substituted by the table widget:
+<P>
+<B>%c</B> For <B>SelectionCommand</B>, it is the maximum number of
+columns in any row in the selection. Otherwise it is
+the column of the triggered cell.
+
+<DL>
+
+<DT><B>%C</B> </DT></DT>
+<DD>A convenience substitution for <I>%r</I>,<I>%c</I>.
+</DD>
+
+<DT><B>%i</B> </DT></DT>
+<DD>For <B>SelectionCommand</B>, it is the total number of cells
+in the selection. For <B>Command</B>, it is 0 for a read
+(get) and 1 for a write (set). Otherwise it is the
+current cursor position in the cell.
+</DD>
+
+<DT><B>%r</B> </DT></DT>
+<DD>For <B>SelectionCommand</B>, it is the number of rows in the
+selection. Otherwise it is the row of the triggered
+cell.
+</DD>
+</DL>
+<P>
+<B>%s</B> For <B>ValidateCommand</B>, it is the current value of the
+cell being validated. For <B>SelectionCommand</B>, it is
+the default value of the selection. For <B>BrowseCommand</B>,
+it is the index of the last active cell. For
+<B>Command</B>, it is empty for reads (get) and the current
+value of the cell for writes (set).
+
+<DL>
+
+<DT><B>%S</B> </DT></DT>
+<DD>For <B>ValidateCommand</B>, it is the potential new value of
+the cell being validated. For <B>BrowseCommand</B>, it is
+the index of the new active cell.
+</DD>
+</DL>
+<P>
+<B>%W</B> The pathname to the window for which the command was
+generated.
+
+<H2><A NAME="sect12" HREF="#toc12"><B>Widget</B> <B>Command</B></A></H2>
+
+<P>
+The <B>table</B> command creates a new Tcl command whose name is
+<I>pathName</I>. This command may be used to invoke various
+operations on the widget. It has the following general
+form:<BR>
+
+<I>pathName</I> <I>option</I> ?<I>arg</I> <I>arg</I> <I>...</I>?<BR>
+
+<I>Option</I> and the <I>arg</I>s determine the exact behavior of the
+command.
+<P>
+The following commands are possible for <B>table</B> widgets:
+<P>
+<I>pathName</I> <B>activate</B> <I>index</I><BR>
+
+Sets the active cell to the one indicated by <I>index</I>.
+<P>
+<I>pathName</I> <B>bbox</B> <I>first</I> ?<I>last</I>?<BR>
+
+It returns the bounding box for the specified cell
+(range) as a 4-tuple of x, y, width and height in
+pixels. It clips the box to the visible portion,
+if any, otherwise an empty string is returned.
+<P>
+<I>pathName</I> <B>border</B> <I>option</I> <I>args</I><BR>
+
+This command is a voodoo hack to implement border
+sizing for tables. This is normally called through
+bindings, with the following as valid options:
+<P>
+<I>pathName</I> <B>border</B> <B>mark</B> <I>x</I> <I>y</I> ?<I>row|col</I>?
+Records <I>x</I> and <I>y</I> and the row and/or column
+border under that point in the table window,
+if any; used in conjunction with later <B>border</B>
+<B>dragto</B> commands. Typically this command
+is associated with a mouse button press in
+the widget. If <I>row</I> or <I>col</I> is not specified,
+it returns a tuple of both border indices
+(an empty item means no border). Otherwise,
+just the specified item is returned.
+<P>
+<I>pathName</I> <B>border</B> <B>dragto</B> <I>x</I> <I>y</I><BR>
+
+This command computes the difference between
+its <I>x</I> and <I>y</I> arguments and the <I>x</I> and <I>y</I> arguments
+to the last <B>border</B> <B>mark</B> command for
+the widget. It then adjusts the previously
+marked border by the difference. This command
+is typically associated with mouse
+motion events in the widget, to produce the
+effect of interactive border resizing.
+<P>
+<I>pathName</I> <B>cget</B> <I>option</I><BR>
+
+Returns the current value of the configuration
+option given by <I>option</I>. <I>Option</I> may have any of the
+values accepted by the <B>table</B> command.
+<P>
+<I>pathName</I> <B>clear</B> <I>option</I> ?<I>first</I>? ?<I>last</I>?<BR>
+
+This command is a convenience routine to clear certain
+state information managed by the table. <I>first</I>
+and <I>last</I> represent valid table indices. If neither
+are specified, then the command operates on the
+whole table. The following options are recognized:
+<P>
+<I>pathName</I> <B>clear</B> <B>cache</B> ?<I>first</I>? ?<I>last</I>?
+Clears the specified section of the cache,
+if the table has been keeping one.
+<P>
+<I>pathName</I> <B>clear</B> <B>sizes</B> ?<I>first</I>? ?<I>last</I>?
+Clears the specified row and column areas of
+specific height/width dimensions. When just
+one index is specified, for example <B>2,0</B>,
+that is interpreted as row 2 <B>and</B> column 0.
+<P>
+<I>pathName</I> <B>clear</B> <B>tags</B> ?<I>first</I>? ?<I>last</I>?
+Clears the specified area of tags (all row,
+column and cell tags).
+<P>
+<I>pathName</I> <B>clear</B> <B>all</B> ?<I>first</I>? ?<I>last</I>?
+Performs all of the above clear functions on
+the specified area.
+<P>
+<I>pathName</I> <B>configure</B> ?<I>option</I>? ?<I>value</I> <I>option</I> <I>value</I> <I>...</I>?
+Query or modify the configuration options of the
+widget. If no <I>option</I> is specified, returns a list
+describing all of the available options for <I>path</I><B>_N</B><I>ame</I>
+(see <B>Tk_ConfigureInfo</B> for information on the
+format of this list). If <I>option</I> is specified with
+no <I>value</I>, then the command returns a list describing
+the one named option (this list will be identical
+to the corresponding sublist of the value
+returned if no <I>option</I> is specified). If one or
+more <I>option-value</I> pairs are specified, then the
+command modifies the given widget option(s) to have
+the given value(s); in this case the command
+returns an empty string. <I>Option</I> may have any of
+the values accepted by the <B>table</B> command.
+<P>
+<I>pathName</I> <B>curselection</B> ?<I>value</I>?<BR>
+
+With no arguments, it returns the sorted indices of
+the currently selected cells. Otherwise it sets
+all the selected cells to the given value. The set
+has no effect if there is no associated Tcl array
+or the state is disabled.
+<P>
+<I>pathName</I> <B>curvalue</B> ?<I>value</I>?<BR>
+
+If no value is given, the value of the cell being
+edited (indexed by <B>active</B>) is returned, else it is
+set to the given value.
+<P>
+<I>pathName</I> <B>delete</B> <I>option</I> <I>arg</I> ?<I>arg</I>?<BR>
+
+This command is used to delete various things in a
+table. It has several forms, depending on the
+<I>option</I>:
+<I>pathName</I> <B>delete</B> <B>active</B> <I>index</I> ?<I>index</I>?
+Deletes text from the active cell. If only
+one index is given, it deletes the character
+after that index, otherwise it deletes from
+the first index to the second. <I>index</I> can be
+a number, <B>insert</B> or <B>end</B>.
+<P>
+<I>pathName</I> <B>delete</B> <B>cols</B> ?<I>switches</I>? <I>index</I> ?<I>count</I>?
+Deletes <I>count</I> cols starting at (and including)
+col <I>index</I>. The <I>index</I> will be constrained
+to the limits of the tables. If
+<I>count</I> is negative, it deletes cols to the
+left. Otherwise it deletes cols to the
+right. <I>count</I> defaults to 1 (meaning just
+the column specified). At the moment, spans
+are not adjusted with this action. Optional
+switches are:
+
+<DL>
+
+<DT><B>-holddimensions</B></DT></DT>
+<DD>
+Causes the table cols to be unaffected
+by the deletion (empty cols
+may appear). By default the dimensions
+are adjusted by <B>count</B>.
+</DD>
+
+<DT><B>-holdselection</B></DT></DT>
+<DD>
+Causes the selection to be maintained
+on the absolute cells values.
+Otherwise, the selection will be
+cleared..
+</DD>
+
+<DT><B>-holdtags</B></DT></DT>
+<DD>
+Causes the tags specified by the <I>tag</I>
+method to not move along with the
+data. Also prevents specific widths
+set by the <I>width</I> method from being
+adjusted. By default, these tags
+are properly adjusted.
+</DD>
+
+<DT><B>-holdwindows</B></DT></DT>
+<DD>
+Causes the embedded windows created
+with the <I>window</I> method to not move
+along with the data. By default,
+these windows are properly adjusted.
+</DD>
+
+<DT><B>-keeptitles</B></DT></DT>
+<DD>
+Prevents title area cells from being
+changed. Otherwise they are treated
+just like regular cells and will
+move as specified.
+</DD>
+
+<DT><B>--</B> </DT></DT>
+<DD> Signifies the end of the switches.
+</DD>
+</DL>
+<P>
+<I>pathName</I> <B>delete</B> <B>rows</B> ?<I>switches</I>? <I>index</I> ?<I>count</I>?
+Deletes <B>count</B> rows starting at (and
+including) row <B>index</B>. If <B>count</B> is negative,
+it deletes rows going up. Otherwise it
+deletes rows going down. The selection will
+be cleared. The switches are the same as
+those for column deletion.
+<P>
+<I>pathName</I> <B>get</B> <I>first</I> ?<I>last</I>?<BR>
+
+Returns the value of the cells specified by the
+table indices <I>first</I> and (optionally) <I>last</I> in a
+list.
+<P>
+<I>pathName</I> <B>height</B> ?<I>row</I>? ?<I>value</I> <I>row</I> <I>value</I> <I>...</I>?
+If no <I>row</I> is specified, returns a list describing
+all rows for which a height has been set. If <B>row</B>
+is specified with no value, it prints out the
+height of that row in characters (positive number)
+or pixels (negative number). If one or more
+<I>row-value</I> pairs are specified, then it sets each
+row to be that height in lines (positive number) or
+pixels (negative number). If <I>value</I> is <I>default</I>,
+then the row uses the default height, specified by
+<B>-rowheight</B>.
+<P>
+<I>pathName</I> <B>hidden</B> ?<I>index</I>? ?<I>index</I> <I>...</I>?<BR>
+
+When called without args, it returns all the <I>hidden</I>
+cells (those cells covered by a spanning cell). If
+one index is specified, it returns the spanning
+cell covering that index, if any. If multiple
+indices are specified, it returns 1 if all indices
+are hidden cells, 0 otherwise.
+<P>
+<I>pathName</I> <B>icursor</B> ?<I>arg</I>?<BR>
+
+With no arguments, prints out the location of the
+insertion cursor in the active cell. With one
+argument, sets the cursor to that point in the
+string. 0 is before the first character, you can
+also use <B>insert</B> or <B>end</B> for the current insertion
+point or the end of the text. If there is no
+active cell, or the cell or table is disabled, this
+will return -1.
+<P>
+<I>pathName</I> <B>index</B> <I>index</I> ?<I>row|col</I>?<BR>
+
+Returns the integer cell coordinate that corresponds
+to <I>index</I> in the form row,col. If <B>row</B> or <B>col</B>
+is specified, then only the row or column index is
+returned.
+<P>
+<I>pathName</I> <B>insert</B> <I>option</I> <I>arg</I> <I>arg</I><BR>
+
+This command is used to into various things into a
+table. It has several forms, depending on the
+<I>option</I>:
+<P>
+<I>pathName</I> <B>insert</B> <B>active</B> <I>index</I> <I>value</I>
+The <I>value</I> is a text string which is inserted
+at the <I>index</I> postion of the active cell.
+The cursor is then positioned after the new
+text. <I>index</I> can be a number, <B>insert</B> or <B>end</B>.
+<P>
+<I>pathName</I> <B>insert</B> <B>cols</B> ?<I>switches</I>? <I>index</I> ?<I>count</I>?
+Inserts <B>count</B> cols starting at col <B>index</B>.
+If <B>count</B> is negative, it inserts before the
+specified col. Otherwise it inserts after
+the specified col. The selection will be
+cleared. The switches are the same as those
+for column deletion.
+<P>
+<I>pathName</I> <B>insert</B> <B>rows</B> ?<I>switches</I>? <I>index</I> ?<I>count</I>?
+Inserts <B>count</B> rows starting at row <B>index</B>.
+If <B>count</B> is negative, it inserts before the
+specified row. Otherwise it inserts after
+the specified row. The selection will be
+cleared. The switches are the same as those
+for column deletion.
+<P>
+<I>pathName</I> <B>reread</B><BR>
+
+Rereads the old contents of the cell back into the
+editing buffer. Useful for a key binding when
+&lt;Escape&gt; is pressed to abort the edit (a default
+binding).
+<P>
+<I>pathName</I> <B>scan</B> <I>option</I> <I>args</I><BR>
+
+This command is used to implement scanning on
+tables. It has two forms, depending on <I>option</I>:
+<P>
+<I>pathName</I> <B>scan</B> <B>mark</B> <I>x</I> <I>y</I><BR>
+
+Records <I>x</I> and <I>y</I> and the current view in the
+table window; used in conjunction with
+later <B>scan</B> <B>dragto</B> commands. Typically this
+command is associated with a mouse button
+press in the widget. It returns an empty
+string.
+<P>
+<I>pathName</I> <B>scan</B> <B>dragto</B> <I>x</I> <I>y</I>.<BR>
+
+This command computes the difference between
+its <I>x</I> and <I>y</I> arguments and the <I>x</I> and <I>y</I> arguments
+to the last <B>scan</B> <B>mark</B> command for the
+widget. It then adjusts the view by 5 times
+the difference in coordinates. This command
+is typically associated with mouse motion
+events in the widget, to produce the effect
+of dragging the list at high speed through
+the window. The return value is an empty
+string.
+<P>
+<I>pathName</I> <B>see</B> <I>index</I><BR>
+
+Adjust the view in the table so that the cell given
+by <I>index</I> is positioned as the cell one off from top
+left (excluding title rows and columns) if the cell
+is not currently visible on the screen. The actual
+cell may be different to keep the screen full.
+<P>
+<I>pathName</I> <B>selection</B> <I>option</I> <I>arg</I><BR>
+
+This command is used to adjust the selection within
+a table. It has several forms, depending on
+<I>option</I>:
+<P>
+<I>pathName</I> <B>selection</B> <B>anchor</B> <I>index</I><BR>
+
+Sets the selection anchor to the cell given
+by <I>index</I>. The selection anchor is the end
+of the selection that is fixed while dragging
+out a selection with the mouse. The
+index <B>anchor</B> may be used to refer to the
+anchor cell.
+<P>
+<I>pathName</I> <B>selection</B> <B>clear</B> <I>first</I> ?<I>last</I>?
+If any of the cells between <I>first</I> and <I>last</I>
+(inclusive) are selected, they are deselected.
+The selection state is not changed
+for cells outside this range. <I>first</I> may be
+specified as <B>all</B> to remove the selection
+from all cells.
+<P>
+<I>pathName</I> <B>selection</B> <B>includes</B> <I>index</I>
+Returns 1 if the cell indicated by <I>index</I> is
+currently selected, 0 if it isn't.
+<P>
+<I>pathName</I> <B>selection</B> <B>set</B> <I>first</I> ?<I>last</I>?
+Selects all of the cells in the range
+between <I>first</I> and <I>last</I>, inclusive, without
+affecting the selection state of cells outside
+that range.
+<P>
+<I>pathName</I> <B>set</B> ?<I>row|col</I>? <I>index</I> ?<I>value</I>? ?<I>index</I> <I>value</I> <I>...</I>?
+Sets the specified index to the associated value.
+Table validation will not be triggered via this
+method. If <B>row</B> or <B>col</B> precedes the list of
+index/value pairs, then the value is assumed to be
+a Tcl list whose values will be split and set into
+the subsequent columns (if <B>row</B> is specified) or
+rows (for <B>col</B>). For example, <B>set</B> <B>row</B> <B>2,3</B> <B>{2,3</B> <B>2,4</B>
+<B>2,5}</B> will set 3 cells, from 2,3 to 2,5. The setting
+of cells is silently bounded by the known
+table dimensions.
+<P>
+<I>pathName</I> <B>spans</B> ?<I>index</I>? ?<I>rows,cols</I> <I>index</I> <I>rows,cols</I> <I>...</I>?
+This command is used to manipulate row/col spans.
+When called with no arguments, all known spans are
+returned as a list of tuples of the form {index
+span}. When called with only the <I>index</I>, the span
+for that <I>index</I> only is returned, if any. Otherwise
+an even number of <I>index</I> <I>rows,cols</I> pairs are used to
+set spans. A span starts at the <I>index</I> and
+continues for the specified number of rows and
+cols. Negative spans are not supported. A span of
+0,0 unsets any span on that cell. See EXAMPLES for
+more info.
+<P>
+<I>pathName</I> <B>tag</B> option ?<I>arg</I> <I>arg</I> <I>...</I>?<BR>
+
+This command is used to manipulate tags. The exact
+behavior of the command depends on the <I>option</I> argument
+that follows the <B>tag</B> argument. <I>cget</I>, <I>cell</I>,
+and <I>row|col</I> complain about unknown tag names. The
+following forms of the command are currently supported:
+<P>
+<I>pathName</I> <B>tag</B> <B>cell</B> <I>tagName</I> <I>?index</I> <I>...?</I>
+With no arguments, prints out the list of
+cells that use the <I>tag</I>. Otherwise it sets
+the specified cells to use the named tag,
+replacing any tag that may have been set
+using this method before. If <I>tagName</I> is {},
+the cells are reset to the default <I>tag</I>.
+Tags added during -*tagcommand evaluation do
+not register here. If <I>tagName</I> does not
+exist, it will be created with the default
+options.
+<P>
+<I>pathName</I> <B>tag</B> <B>cget</B> <I>tagName</I> <I>option</I>
+This command returns the current value of
+the option named <I>option</I> associated with the
+tag given by <I>tagName</I>. <I>Option</I> may have any
+of the values accepted by the <B>tag</B> <B>configure</B>
+widget command.
+<P>
+<I>pathName</I> <B>tag</B> <B>col</B> <I>tagName</I> <I>?col</I> <I>...?</I>
+With no arguments, prints out the list of
+cols that use the <I>tag</I>. Otherwise it sets
+the specified columns to use the named tag,
+replacing any tag that may have been set
+using this method before. If <I>tagName</I> is {},
+the cols are reset to the default <I>tag</I>. Tags
+added during -coltagcommand evaluation do
+not register here. If <I>tagName</I> does not
+exist, it will be created with the default
+options.
+<P>
+<I>pathName</I> <B>tag</B> <B>configure</B> <I>tagName</I> ?<I>option</I>? ?<I>value</I>?
+?<I>option</I> <I>value</I> <I>...</I>?<BR>
+
+This command is similar to the <B>configure</B>
+widget command except that it modifies
+options associated with the tag given by
+<I>tagName</I> instead of modifying options for the
+overall table widget. If no <I>option</I> is specified,
+the command returns a list describing
+all of the available options for <I>tagName</I>
+(see <B>Tk_ConfigureInfo</B> for information on the
+format of this list). If <I>option</I> is specified
+with no <I>value</I>, then the command returns
+a list describing the one named option (this
+list will be identical to the corresponding
+sublist of the value returned if no <I>option</I>
+is specified). If one or more <I>option-value</I>
+pairs are specified, then the command modifies
+the given option(s) to have the given
+value(s) in <I>tagName</I>; in this case the command
+returns an empty string. See TAGS
+above for details on the options available
+for tags.
+<P>
+<I>pathName</I> <B>tag</B> <B>delete</B> <I>tagName</I><BR>
+
+Deletes a tag. No error if the tag does not
+exist.
+<P>
+<I>pathName</I> <B>tag</B> <B>exists</B> <I>tagName</I><BR>
+
+Returns 1 if the named tag exists, 0 otherwise.
+<P>
+<I>pathName</I> <B>tag</B> <B>includes</B> <I>tagName</I> <I>index</I>
+Returns 1 if the specified index has the
+named tag, 0 otherwise.
+<P>
+<I>pathName</I> <B>tag</B> <B>lower</B> <I>tagName</I> ?<I>belowThis</I>?
+Lower the priority of the named tag. If
+<I>belowThis</I> is not specified, then the tag's
+priority is lowered to the bottom, otherwise
+it is lowered to one below <I>belowThis</I>.
+<P>
+<I>pathName</I> <B>tag</B> <B>names</B> ?<I>pattern</I>?<BR>
+
+If no pattern is specified, shows the names
+of all defined tags. Otherwise the <I>pattern</I>
+is used as a glob pattern to show only tags
+matching that pattern. Tag names are
+returned in priority order (highest priority
+tag first).
+<P>
+<I>pathName</I> <B>tag</B> <B>raise</B> <I>tagName</I> ?<I>aboveThis</I>?
+Raise the priority of the named tag. If
+<I>aboveThis</I> is not specified, then the tag's
+priority is raised to the top, otherwise it
+is raised to one above <I>aboveThis</I>.
+<P>
+<I>pathName</I> <B>tag</B> <B>row</B> <I>tagName</I> ?<I>row</I> <I>...</I>?
+With no arguments, prints out the list of
+rows that use the <I>tag</I>. Otherwise it sets
+the specified columns to use the named tag,
+replacing any tag that may have been set
+using this method before. If <I>tagName</I> is {},
+the rows are reset to use the default tag.
+Tags added during -rowtagcommand evaluation
+do not register here. If <I>tagName</I> does not
+exist, it will be created with the default
+options.
+<P>
+<I>pathName</I> <B>validate</B> <I>index</I><BR>
+
+Explicitly validates the specified index based on
+the current <B>-validatecommand</B> and returns 0 or 1
+based on whether the cell was validated.
+<P>
+<I>pathName</I> <B>width</B> ?<I>col</I>? ?<I>value</I> <I>col</I> <I>value</I> <I>...</I>?
+If no <I>col</I> is specified, returns a list describing
+all cols for which a width has been set. If <B>col</B> is
+specified with no value, it prints out the width of
+that col in characters (positive number) or pixels
+(negative number). If one or more <I>col-value</I> pairs
+are specified, then it sets each col to be that
+width in characters (positive number) or pixels
+(negative number). If <I>value</I> is <I>default</I>, then the
+col uses the default width, specified by <B>-colwidth</B>.
+<P>
+<I>pathName</I> <B>window</B> option ?<I>arg</I> <I>arg</I> <I>...</I>?<BR>
+
+This command is used to manipulate embedded windows.
+The exact behavior of the command depends on
+the <I>option</I> argument that follows the <B>window</B> argument.
+The following forms of the command are currently
+supported:
+<P>
+<I>pathName</I> <B>window</B> <B>cget</B> <I>index</I> <I>option</I>
+This command returns the current value of
+the option named <I>option</I> associated with the
+window given by <I>index</I>. <I>Option</I> may have any
+of the values accepted by the <B>window</B> <B>configure</B>
+widget command.
+<P>
+<I>pathName</I> <B>window</B> <B>configure</B> <I>index</I> ?<I>option</I>? ?<I>value</I>?
+?<I>option</I> <I>value</I> <I>...</I>?<BR>
+
+This command is similar to the <B>configure</B>
+widget command except that it modifies
+options associated with the embedded window
+given by <I>index</I> instead of modifying options
+for the overall table widget. If no <I>option</I>
+is specified, the command returns a list
+describing all of the available options for
+<I>index</I> (see <B>Tk_ConfigureInfo</B> for information
+on the format of this list). If <I>option</I> is
+specified with no <I>value</I>, then the command
+returns a list describing the one named
+option (this list will be identical to the
+corresponding sublist of the value returned
+if no <I>option</I> is specified). If one or more
+<I>option-value</I> pairs are specified, then the
+command modifies the given option(s) to have
+the given value(s) in <I>index</I>; in this case
+the command returns an empty string. See
+EMBEDDED WINDOWS above for details on the
+options available for windows.
+<P>
+<I>pathName</I> <B>window</B> <B>delete</B> <I>index</I> ?<I>index</I> <I>...</I>?
+Deletes an embedded window from the table.
+The associated window will also be deleted.
+<P>
+<I>pathName</I> <B>window</B> <B>move</B> <I>indexFrom</I> <I>indexTo</I>
+Moves an embedded window from one cell to
+another. If a window already exists in the
+target cell, it will be deleted.
+<P>
+<I>pathName</I> <B>window</B> <B>names</B> ?<I>pattern</I>?<BR>
+
+If no pattern is specified, shows the cells
+of all embedded windows. Otherwise the <I>pat</I><B>_</B>t<I>ern</I>
+is used as a glob pattern to show only
+cells matching that pattern.
+<P>
+<I>pathName</I> <B>xview</B> <I>args</I><BR>
+
+This command is used to query and change the horizontal
+position of the information in the widget's
+window. It can take any of the following forms:
+<P>
+<I>pathName</I> <B>xview</B><BR>
+
+Returns a list containing two elements.
+Each element is a real fraction between 0
+and 1; together they describe the horizontal
+span that is visible in the window. For
+example, if the first element is .2 and the
+second element is .6, 20% of the table's
+text is off-screen to the left, the middle
+40% is visible in the window, and 40% of the
+text is off-screen to the right. These are
+the same values passed to scrollbars via the
+<B>-xscrollcommand</B> option.
+<P>
+<I>pathName</I> <B>xview</B> <I>index</I><BR>
+
+Adjusts the view in the window so that the
+column given by <I>index</I> is displayed at the
+left edge of the window.
+<P>
+<I>pathName</I> <B>xview</B> <B>moveto</B> <I>fraction</I><BR>
+
+Adjusts the view in the window so that <I>frac</I><B>_</B>t<I>ion</I>
+of the total width of the table text is
+off-screen to the left. <I>fraction</I> must be a
+fraction between 0 and 1.
+<P>
+<I>pathName</I> <B>xview</B> <B>scroll</B> <I>number</I> <I>what</I>
+This command shifts the view in the window
+left or right according to <I>number</I> and <I>what</I>.
+<I>Number</I> must be an integer. <I>What</I> must be
+either <B>units</B> or <B>pages</B> or an abbreviation of
+one of these. If <I>what</I> is <B>units</B>, the view
+adjusts left or right by <I>number</I> character
+units (the width of the <B>0</B> character) on the
+display; if it is <B>pages</B> then the view
+adjusts by <I>number</I> screenfuls. If <I>number</I> is
+negative then characters farther to the left
+become visible; if it is positive then
+characters farther to the right become visible.
+<P>
+<I>pathName</I> <B>yview</B> <I>?args</I>?<BR>
+
+This command is used to query and change the vertical
+position of the text in the widget's window.
+It can take any of the following forms:
+<P>
+<I>pathName</I> <B>yview</B><BR>
+
+Returns a list containing two elements, both
+of which are real fractions between 0 and 1.
+The first element gives the position of the
+table element at the top of the window, relative
+to the table as a whole (0.5 means it
+is halfway through the table, for example).
+The second element gives the position of the
+table element just after the last one in the
+window, relative to the table as a whole.
+These are the same values passed to scrollbars
+via the <B>-yscrollcommand</B> option.
+<P>
+<I>pathName</I> <B>yview</B> <I>index</I><BR>
+
+Adjusts the view in the window so that the
+row given by <I>index</I> is displayed at the top
+of the window.
+<P>
+<I>pathName</I> <B>yview</B> <B>moveto</B> <I>fraction</I><BR>
+
+Adjusts the view in the window so that the
+element given by <I>fraction</I> appears at the top
+of the window. <I>Fraction</I> is a fraction
+between 0 and 1; 0 indicates the first element
+in the table, 0.33 indicates the element
+one-third the way through the table,
+and so on.
+<P>
+<I>pathName</I> <B>yview</B> <B>scroll</B> <I>number</I> <I>what</I>
+This command adjusts the view in the window
+up or down according to <I>number</I> and <I>what</I>.
+<I>Number</I> must be an integer. <I>What</I> must be
+either <B>units</B> or <B>pages</B>. If <I>what</I> is <B>units</B>,
+the view adjusts up or down by <I>number</I> lines;
+if it is <B>pages</B> then the view adjusts by <I>num</I><B>_</B>b<I>er</I>
+screenfuls. If <I>number</I> is negative then
+earlier elements become visible; if it is
+positive then later elements become visible.
+
+<H2><A NAME="sect13" HREF="#toc13"><B>Default</B> <B>Bindings</B></A></H2>
+
+<P>
+The initialization creates class bindings that give the
+following default behaviour:
+
+<DL>
+
+<DT>[1] </DT></DT>
+<DD> Clicking Button-1 in a cell activates that cell.
+Clicking into an already active cell moves the
+insertion cursor to the character nearest the
+mouse.
+</DD>
+
+<DT>[2] </DT></DT>
+<DD> Moving the mouse while Button-1 is pressed will
+stroke out a selection area. Exiting while Button-1
+is pressed causing scanning to occur on the
+table along with selection.
+</DD>
+
+<DT>[3] </DT></DT>
+<DD> Moving the mouse while Button-2 is pressed causes
+scanning to occur without any selection.
+</DD>
+
+<DT>[4] </DT></DT>
+<DD> Home moves the table to have the origin in view.
+</DD>
+
+<DT>[5] </DT></DT>
+<DD> End moves the table to have the <B>end</B> cell in view.
+</DD>
+
+<DT>[6] </DT></DT>
+<DD> Control-Home moves the table to the origin and
+activates that cell.
+</DD>
+
+<DT>[7] </DT></DT>
+<DD> Control-End moves the table to the end and activates
+that cell.
+</DD>
+
+<DT>[8] </DT></DT>
+<DD> Shift-Control-Home extends the selection to the
+origin.
+</DD>
+
+<DT>[9] </DT></DT>
+<DD> Shift-Control-End extends the selection to the end.
+</DD>
+
+<DT>[10] </DT></DT>
+<DD>The left, right, up and down arrows move the active
+cell.
+</DD>
+</DL>
+<P>
+[11] Shift-&lt;arrow&gt; extends the selection in that direction.
+<P>
+[12] Control-leftarrow and Control-rightarrow move the
+insertion cursor within the cell.
+
+<DL>
+
+<DT>[13] </DT></DT>
+<DD>Control-slash selects all the cells.
+</DD>
+</DL>
+<P>
+[14] Control-backslash clears selection from all the
+cells.
+<P>
+[15] Backspace deletes the character before the insertion
+cursor in the active cell.
+<P>
+[16] Delete deletes the character after the insertion
+cursor in the active cell.
+<P>
+[17] Escape rereads the value of the active cell from
+the specified data source, discarding any edits
+that have may been performed on the cell.
+<P>
+[18] Control-a moves the insertion cursor to the beginning
+of the active cell.
+<P>
+[19] Control-e moves the insertion cursor to the end of
+the active cell.
+<P>
+[20] Control-minus and Control-equals decrease and
+increase the width of the column with the active
+cell in it.
+<P>
+[21] Moving the mouse while Button-3 (the right button
+on Windows) is pressed while you are over a border
+will cause interactive resizing of that row and/or
+column to occur, based on the value of <B>-resizeborders</B>.
+<P>
+Some bindings may have slightly different behavior dependent
+on the <B>-selectionmode</B> of the widget.
+<P>
+If the widget is disabled using the <B>-state</B> option, then
+its view can still be adjusted and cells can still be
+selected, but no insertion cursor will be displayed and no
+cell modifications will take place.
+<P>
+The behavior of tables can be changed by defining new
+bindings for individual widgets or by redefining the class
+bindings. The default bindings are either compiled in or
+read from a file expected to correspond to: &laquo;[lindex
+$tcl_pkgPath 0]/Tktable&lt;version&gt;/tkTable.tcl".
+
+<H2><A NAME="sect14" HREF="#toc14"><B>Performance</B> <B>Issues</B></A></H2>
+
+<P>
+The number of rows and columns or a table widget should
+not significantly affect the speed of redraw. Recalculation
+and redraw of table parameters and cells is
+restricted as much as possible.
+<P>
+The display cell with the insert cursor is redrawn each
+time the cursor blinks, which causes a steady stream of
+graphics traffic. Set the <B>-insertofftime</B> option to 0
+avoid this. The use of a <B>-command</B> with the table without
+a cache can cause significant slow-down, as the command is
+called once for each request of a cell value.
+
+<H2><A NAME="sect15" HREF="#toc15"><B>Examples</B></A></H2>
+
+<P>
+Set the topleft title area to be one spanning cell. This
+overestimates both row and column span by one, but the
+command does all the constraining for us.
+$table span [$table cget -roworigin],[$table cget -colorigin] [$table cget -titlerows],[$table cget -titlecols]
+Force a table window refresh (useful for the slight chance
+that a bug in the table is not causing proper refresh):
+$table configure -padx [$table cget -padx]
+
+<H2><A NAME="sect16" HREF="#toc16"><B>Keywords</B></A></H2>
+
+<P>
+table, widget, extension
+<P>
+
+<HR><P>
+<A NAME="toc"><B>Table of Contents</B></A><P>
+<UL>
+<LI><A NAME="toc0" HREF="#sect0">Name</A></LI>
+<LI><A NAME="toc1" HREF="#sect1">Synopsis</A></LI>
+<LI><A NAME="toc2" HREF="#sect2">Standard Options</A></LI>
+<LI><A NAME="toc3" HREF="#sect3">Widget-specific Options</A></LI>
+<LI><A NAME="toc4" HREF="#sect4">Description</A></LI>
+<LI><A NAME="toc5" HREF="#sect5">Initialization</A></LI>
+<LI><A NAME="toc6" HREF="#sect6">Indices</A></LI>
+<LI><A NAME="toc7" HREF="#sect7">Tags</A></LI>
+<LI><A NAME="toc8" HREF="#sect8">Embedded Windows</A></LI>
+<LI><A NAME="toc9" HREF="#sect9">the Selection</A></LI>
+<LI><A NAME="toc10" HREF="#sect10">Row/Col Spanning</A></LI>
+<LI><A NAME="toc11" HREF="#sect11">Command Substitution</A></LI>
+<LI><A NAME="toc12" HREF="#sect12">Widget Command</A></LI>
+<LI><A NAME="toc13" HREF="#sect13">Default Bindings</A></LI>
+<LI><A NAME="toc14" HREF="#sect14">Performance Issues</A></LI>
+<LI><A NAME="toc15" HREF="#sect15">Examples</A></LI>
+<LI><A NAME="toc16" HREF="#sect16">Keywords</A></LI>
+</UL>
+</BODY></HTML>
diff --git a/libgui/library/Makefile.in b/libgui/library/Makefile.in
index 01461dc4f73..025fe879164 100644
--- a/libgui/library/Makefile.in
+++ b/libgui/library/Makefile.in
@@ -59,6 +59,7 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
+AR = @AR@
BFDHDIR = @BFDHDIR@
BFDLIB = @BFDLIB@
CC = @CC@
@@ -84,7 +85,6 @@ ITCLLIB = @ITCLLIB@
ITCLMKIDX = @ITCLMKIDX@
ITCLSH = @ITCLSH@
ITCL_BUILD_LIB_SPEC = @ITCL_BUILD_LIB_SPEC@
-ITCL_DIR = @ITCL_DIR@
ITCL_LIB_FILE = @ITCL_LIB_FILE@
ITCL_LIB_FULL_PATH = @ITCL_LIB_FULL_PATH@
ITK_BUILD_LIB_SPEC = @ITK_BUILD_LIB_SPEC@
@@ -109,6 +109,7 @@ SIMHDIR = @SIMHDIR@
SIMLIB = @SIMLIB@
TCLCONFIG = @TCLCONFIG@
TCLHDIR = @TCLHDIR@
+TCL_BIN_DIR = @TCL_BIN_DIR@
TCL_BUILD_LIB_SPEC = @TCL_BUILD_LIB_SPEC@
TCL_CFLAGS = @TCL_CFLAGS@
TCL_DEFS = @TCL_DEFS@
@@ -155,15 +156,12 @@ PACKAGES = combobox.tcl
guidir = $(datadir)/cygnus/gui
gui_DATA = tclIndex pkgIndex.tcl $(TCL) $(PACKAGES)
-@TCL_SHARED_TRUE@SET_LIB_PATH = \
-@TCL_SHARED_TRUE@$(RPATH_ENVVAR)=$$here/../../tcl/unix:$$here/../../itcl/itcl/unix:$$$(RPATH_ENVVAR); export $(RPATH_ENVVAR);
-@TCL_SHARED_FALSE@SET_LIB_PATH = \
+@TCL_SHARED_TRUE@SET_LIB_PATH = @TCL_SHARED_TRUE@$(RPATH_ENVVAR)=$$here/../../tcl/unix:$$here/../../itcl/itcl/unix:$$$(RPATH_ENVVAR); export $(RPATH_ENVVAR);
+@TCL_SHARED_FALSE@SET_LIB_PATH =
WISH = wish
-@CROSS_COMPILING_TRUE@ITCL_SH = \
-@CROSS_COMPILING_TRUE@itclsh
-@CROSS_COMPILING_FALSE@ITCL_SH = \
-@CROSS_COMPILING_FALSE@$$here/../../itcl/itcl/unix/itclsh$(EXEEXT)
+@CROSS_COMPILING_TRUE@ITCL_SH = @CROSS_COMPILING_TRUE@itclsh
+@CROSS_COMPILING_FALSE@ITCL_SH = @CROSS_COMPILING_FALSE@$$here/../../itcl/itcl/unix/itclsh$(EXEEXT)
ETAGS_ARGS = --lang=none --regex='/[ \t]*\(proc\|method\|itcl_class\)[ \t]+\([^ \t]+\)/\1/' $(TCL) --lang=auto
mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
@@ -176,7 +174,7 @@ DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-TAR = tar
+TAR = gtar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
@@ -322,7 +320,7 @@ tclIndex: $(TCL)
here=`pwd`; \
$(SET_LIB_PATH) \
cd $(srcdir) && \
- echo " auto_mkindex `pwd` $(TCL)" | $(ITCL_SH)
+ echo "auto_mkindex $(LIBGUI_LIBRARY_DIR) $(TCL)" | @ITCL_SH@
pkgIndex.tcl: @MAINT@ $(PACKAGES)
here=`pwd`; \
diff --git a/libgui/src/Makefile.in b/libgui/src/Makefile.in
index 637fa24f5d8..63e73211fdc 100644
--- a/libgui/src/Makefile.in
+++ b/libgui/src/Makefile.in
@@ -60,6 +60,7 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
+AR = @AR@
BFDHDIR = @BFDHDIR@
BFDLIB = @BFDLIB@
CC = @CC@
@@ -85,7 +86,6 @@ ITCLLIB = @ITCLLIB@
ITCLMKIDX = @ITCLMKIDX@
ITCLSH = @ITCLSH@
ITCL_BUILD_LIB_SPEC = @ITCL_BUILD_LIB_SPEC@
-ITCL_DIR = @ITCL_DIR@
ITCL_LIB_FILE = @ITCL_LIB_FILE@
ITCL_LIB_FULL_PATH = @ITCL_LIB_FULL_PATH@
ITCL_SH = @ITCL_SH@
@@ -110,6 +110,7 @@ SIMHDIR = @SIMHDIR@
SIMLIB = @SIMLIB@
TCLCONFIG = @TCLCONFIG@
TCLHDIR = @TCLHDIR@
+TCL_BIN_DIR = @TCL_BIN_DIR@
TCL_BUILD_LIB_SPEC = @TCL_BUILD_LIB_SPEC@
TCL_CFLAGS = @TCL_CFLAGS@
TCL_DEFS = @TCL_DEFS@
@@ -145,8 +146,7 @@ AUTOMAKE_OPTIONS = cygnus
noinst_LIBRARIES = libgui.a
-@INSTALL_LIBGUI_TRUE@include_HEADERS = \
-@INSTALL_LIBGUI_TRUE@\
+@INSTALL_LIBGUI_TRUE@include_HEADERS = @INSTALL_LIBGUI_TRUE@\
@INSTALL_LIBGUI_TRUE@ guitcl.h subcommand.h
TBL_VERSION = 2.1
@@ -198,7 +198,6 @@ tclwinpath.$(OBJEXT) tclmsgbox.$(OBJEXT) tclcursor.$(OBJEXT) \
tkTable.$(OBJEXT) tkTableCmd.$(OBJEXT) tkTableCell.$(OBJEXT) \
tkTableTag.$(OBJEXT) tkTableWin.$(OBJEXT) tkWinPrintText.$(OBJEXT) \
tkWinPrintCanvas.$(OBJEXT) tkWarpPointer.$(OBJEXT)
-AR = ar
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
@@ -210,7 +209,7 @@ DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-TAR = tar
+TAR = gtar
GZIP_ENV = --best
SOURCES = $(libgui_a_SOURCES)
OBJECTS = $(libgui_a_OBJECTS)
diff --git a/libgui/src/subcommand.c b/libgui/src/subcommand.c
index 29e7ea12f18..2ec51d339e6 100644
--- a/libgui/src/subcommand.c
+++ b/libgui/src/subcommand.c
@@ -26,7 +26,7 @@ subcommand_deleted (ClientData cd)
if (data->delete)
(*data->delete) (data->subdata);
- Tcl_Free ((char *) data);
+ ckfree ((char *) data);
}
/* This function implements any Tcl command registered as having
@@ -113,7 +113,7 @@ ide_create_command_with_subcommands (Tcl_Interp *interp, char *name,
}
}
- data = (struct subcommand_clientdata *) Tcl_Alloc (sizeof *data);
+ data = (struct subcommand_clientdata *) ckalloc (sizeof *data);
data->commands = table;
data->subdata = subdata;
data->delete = delete;
diff --git a/libgui/src/tclgetdir.c b/libgui/src/tclgetdir.c
index 7d70aef0012..f3b662f0dec 100644
--- a/libgui/src/tclgetdir.c
+++ b/libgui/src/tclgetdir.c
@@ -237,7 +237,7 @@ get_directory_command (ClientData cd, Tcl_Interp *interp, int argc,
re-eval. This is a lot less efficient, but it doesn't really
matter. */
- new_args = (char **) Tcl_Alloc ((argc + 2) * sizeof (char *));
+ new_args = (char **) ckalloc ((argc + 2) * sizeof (char *));
new_args[0] = "tk_getOpenFile";
new_args[1] = "-choosedir";
@@ -249,8 +249,8 @@ get_directory_command (ClientData cd, Tcl_Interp *interp, int argc,
merge = Tcl_Merge (argc + 2, new_args);
result = Tcl_GlobalEval (interp, merge);
- Tcl_Free (merge);
- Tcl_Free ((char *) new_args);
+ ckfree (merge);
+ ckfree ((char *) new_args);
return result;
}
diff --git a/libgui/src/tclhelp.c b/libgui/src/tclhelp.c
index 199cff77d2e..d3f057a145e 100644
--- a/libgui/src/tclhelp.c
+++ b/libgui/src/tclhelp.c
@@ -109,12 +109,12 @@ help_command_deleted (ClientData cd)
Tcl_DeleteExitHandler (help_command_atexit, cd);
if (hdata->filename != NULL)
- free (hdata->filename);
+ ckfree (hdata->filename);
if (hdata->header_filename != NULL)
- free (hdata->header_filename);
+ ckfree (hdata->header_filename);
if (hdata->hash_initialized)
Tcl_DeleteHashTable (&hdata->topic_hash);
- Tcl_Free ((char *) hdata);
+ ckfree ((char *) hdata);
}
/* Initialize the help system: choose a window, and set up the topic
@@ -223,8 +223,10 @@ help_initialize_command (ClientData cd, Tcl_Interp *interp, int argc,
{
struct help_command_data *hdata = (struct help_command_data *) cd;
- hdata->filename = strdup (argv[2]);
- hdata->header_filename = strdup (argv[3]);
+ hdata->filename = ckalloc (strlen (argv[2]) + 1);
+ strcpy (hdata->filename, argv[2]);
+ hdata->header_filename = ckalloc (strlen (argv[3]) + 1);
+ strcpy (hdata->header_filename, argv[3]);
return TCL_OK;
}
@@ -301,7 +303,8 @@ help_display_file_command (ClientData cd, Tcl_Interp *interp, int argc, char **a
{
struct help_command_data *hdata = (struct help_command_data *) cd;
FILE *e;
- DWORD topic_id = 0; /* default topic id is 0 which brings up the find dialog */
+ int id = 0;
+ DWORD topic_id; /* default topic id is 0 which brings up the find dialog */
/* We call Help initialize just to make sure the window handle is setup */
/* We don't care about the finding the main help file and checking the */
@@ -322,10 +325,11 @@ help_display_file_command (ClientData cd, Tcl_Interp *interp, int argc, char **a
fclose (e);
if (argc > 3)
{
- if ( Tcl_GetInt (interp, argv[3], &topic_id) != TCL_OK )
+ if ( Tcl_GetInt (interp, argv[3], &id) != TCL_OK )
return TCL_ERROR;
}
+ topic_id = (DWORD) id;
if (! WinHelp (hdata->window, argv[2], HELP_CONTEXT, topic_id))
{
char buf[200];
@@ -346,7 +350,7 @@ hdata_initialize ()
{
struct help_command_data *hdata;
- hdata = (struct help_command_data *) Tcl_Alloc (sizeof *hdata);
+ hdata = (struct help_command_data *) ckalloc (sizeof *hdata);
hdata->filename = NULL;
hdata->header_filename = NULL;
@@ -387,14 +391,16 @@ help_command_deleted (ClientData cd)
struct help_command_data *hdata = (struct help_command_data *) cd;
if (hdata->filename != NULL)
- free (hdata->filename);
+ ckfree (hdata->filename);
if (hdata->header_filename != NULL)
- free (hdata->header_filename);
+ ckfree (hdata->header_filename);
+ if (hdata->help_dir != NULL)
+ ckfree (hdata->help_dir);
if (hdata->hash_initialized)
Tcl_DeleteHashTable (&hdata->topic_hash);
if (hdata->memory_block != NULL)
- free (hdata->memory_block);
- Tcl_Free ((char *) hdata);
+ ckfree (hdata->memory_block);
+ ckfree ((char *) hdata);
}
/* Implement the ide_help initialize command. */
@@ -405,9 +411,12 @@ help_initialize_command (ClientData cd, Tcl_Interp *interp, int argc,
{
struct help_command_data *hdata = (struct help_command_data *) cd;
- hdata->filename = strdup (argv[2]);
- hdata->header_filename = strdup (argv[3]);
- hdata->help_dir = strdup (argv[4]);
+ hdata->filename = ckalloc (strlen (argv[2]) + 1);
+ strcpy (hdata->filename, argv[2]);
+ hdata->header_filename = ckalloc (strlen (argv[3]) + 1);
+ strcpy (hdata->header_filename, argv[3]);
+ hdata->help_dir = ckalloc (strlen (argv[4]) + 1);
+ strcpy (hdata->help_dir, argv[4]);
return TCL_OK;
}
@@ -427,7 +436,7 @@ help_initialize (Tcl_Interp *interp, struct help_command_data *hdata)
FILE *e;
char buf[200], *block_start;
- block_start = hdata->memory_block = malloc(6000);
+ block_start = hdata->memory_block = ckalloc(6000);
e = fopen (hdata->header_filename, "r");
if (e == NULL)
@@ -560,7 +569,7 @@ hdata_initialize ()
{
struct help_command_data *hdata;
- hdata = (struct help_command_data *) Tcl_Alloc (sizeof *hdata);
+ hdata = (struct help_command_data *) ckalloc (sizeof *hdata);
hdata->filename = NULL;
hdata->help_dir = NULL;
diff --git a/libgui/src/tclmain.c b/libgui/src/tclmain.c
index 1a962544998..28c2b8eb336 100644
--- a/libgui/src/tclmain.c
+++ b/libgui/src/tclmain.c
@@ -47,7 +47,7 @@ ide_main (int argc, char *argv[], Tcl_AppInitProc *appInitProc)
args = Tcl_Merge (argc - 1, argv + 1);
Tcl_SetVar (interp, "argv", args, TCL_GLOBAL_ONLY);
- Tcl_Free (args);
+ ckfree (args);
sprintf (buf, "%d", argc-1);
Tcl_SetVar (interp, "argc", buf, TCL_GLOBAL_ONLY);
diff --git a/libgui/src/tclmsgbox.c b/libgui/src/tclmsgbox.c
index 8db081fb2a6..918363be0ae 100644
--- a/libgui/src/tclmsgbox.c
+++ b/libgui/src/tclmsgbox.c
@@ -155,7 +155,7 @@ msgbox_wndproc (HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
return DefWindowProc (hwnd, message, wparam, lparam);
/* Queue up a Tcl event. */
- me = (struct msgbox_event *) Tcl_Alloc (sizeof *me);
+ me = (struct msgbox_event *) ckalloc (sizeof *me);
me->header.proc = msgbox_eventproc;
me->md = (struct msgbox_data *) lparam;
Tcl_QueueEvent ((Tcl_Event *) me, TCL_QUEUE_TAIL);
@@ -202,10 +202,10 @@ msgbox_eventproc (Tcl_Event *event, int flags)
/* We are now done with the msgbox_data structure, so we can free
the fields and the structure itself. */
- Tcl_Free (me->md->code);
- Tcl_Free (me->md->message);
- Tcl_Free (me->md->title);
- Tcl_Free ((char *) me->md);
+ ckfree (me->md->code);
+ ckfree (me->md->message);
+ ckfree (me->md->title);
+ ckfree ((char *) me->md);
if (ret != TCL_OK)
Tcl_BackgroundError (me->md->interp);
@@ -401,15 +401,15 @@ msgbox_internal (ClientData clientData, Tcl_Interp *interp, int argc,
msgbox_init ();
- md = (struct msgbox_data *) Tcl_Alloc (sizeof *md);
+ md = (struct msgbox_data *) ckalloc (sizeof *md);
md->interp = interp;
- md->code = Tcl_Alloc (strlen (code) + 1);
+ md->code = ckalloc (strlen (code) + 1);
strcpy (md->code, code);
md->hidden_hwnd = hidden_hwnd;
md->hwnd = hWnd;
- md->message = Tcl_Alloc (strlen (message) + 1);
+ md->message = ckalloc (strlen (message) + 1);
strcpy (md->message, message);
- md->title = Tcl_Alloc (strlen (title) + 1);
+ md->title = ckalloc (strlen (title) + 1);
strcpy (md->title, title);
md->flags = flags | modal;
diff --git a/libgui/src/tclsizebox.c b/libgui/src/tclsizebox.c
index 9a8d30559bf..c10e2e3f9c8 100644
--- a/libgui/src/tclsizebox.c
+++ b/libgui/src/tclsizebox.c
@@ -112,7 +112,7 @@ sizebox_event_proc (ClientData cd, XEvent *event_ptr)
su = (struct sizebox_userdata *) GetWindowLong (hwnd, GWL_USERDATA);
SetWindowLong (hwnd, GWL_USERDATA, 0);
SetWindowLong (hwnd, GWL_WNDPROC, (LONG) su->wndproc);
- Tcl_Free ((char *) su);
+ ckfree ((char *) su);
DestroyWindow (hwnd);
}
}
@@ -149,7 +149,7 @@ sizebox_create (Tk_Window tkwin, Window parent, ClientData cd)
pt.x, pt.y, Tk_Width (tkwin), Tk_Height (tkwin),
parhwnd, NULL, Tk_GetHINSTANCE (), NULL);
- su = (struct sizebox_userdata *) Tcl_Alloc (sizeof *su);
+ su = (struct sizebox_userdata *) ckalloc (sizeof *su);
su->tkwin = tkwin;
su->wndproc = (WNDPROC) GetWindowLong (hwnd, GWL_WNDPROC);
SetWindowLong (hwnd, GWL_USERDATA, (LONG) su);
diff --git a/libgui/src/tclwinmode.c b/libgui/src/tclwinmode.c
index 958d5c9c607..69c6c8082ef 100644
--- a/libgui/src/tclwinmode.c
+++ b/libgui/src/tclwinmode.c
@@ -61,11 +61,11 @@ seterrormode_command (ClientData cd, Tcl_Interp *interp,
{
Tcl_AppendResult (interp, "unrecognized key \"", list[i],
"\"", (char *) NULL);
- Tcl_Free ((char *) list);
+ ckfree ((char *) list);
return TCL_ERROR;
}
}
- Tcl_Free ((char *) list);
+ ckfree ((char *) list);
val = SetErrorMode (val);
diff --git a/libgui/src/tclwinpath.c b/libgui/src/tclwinpath.c
index 2f9d5bdb612..ce75ab0dd7f 100644
--- a/libgui/src/tclwinpath.c
+++ b/libgui/src/tclwinpath.c
@@ -133,7 +133,7 @@ path_posix_to_win32_path_list (ClientData cd, Tcl_Interp *interp, int argc,
char *buf;
size = cygwin32_posix_to_win32_path_list_buf_size (argv[2]);
- buf = Tcl_Alloc (size);
+ buf = ckalloc (size);
cygwin32_posix_to_win32_path_list (argv[2], buf);
Tcl_SetResult (interp, buf, TCL_DYNAMIC);
return TCL_OK;
@@ -149,7 +149,7 @@ path_win32_to_posix_path_list (ClientData cd, Tcl_Interp *interp, int argc,
char *buf;
size = cygwin32_win32_to_posix_path_list_buf_size (argv[2]);
- buf = Tcl_Alloc (size);
+ buf = ckalloc (size);
cygwin32_win32_to_posix_path_list (argv[2], buf);
Tcl_SetResult (interp, buf, TCL_DYNAMIC);
return TCL_OK;
diff --git a/libgui/src/tclwinprint.c b/libgui/src/tclwinprint.c
index 221cc14bf77..02843493511 100644
--- a/libgui/src/tclwinprint.c
+++ b/libgui/src/tclwinprint.c
@@ -126,10 +126,10 @@ winprint_command_deleted (ClientData cd)
{
/* FIXME: I don't know if we are supposed to free the hDevMode
and hDevNames fields. */
- Tcl_Free ((char *) wd->page_setup);
+ ckfree ((char *) wd->page_setup);
}
- Tcl_Free ((char *) wd);
+ ckfree ((char *) wd);
}
/* Implement ide_winprint page_setup. */
@@ -216,7 +216,7 @@ winprint_page_setup_command (ClientData cd, Tcl_Interp *interp, int argc,
}
if (wd->page_setup == NULL)
- wd->page_setup = (PAGESETUPDLG *) Tcl_Alloc (sizeof (PAGESETUPDLG));
+ wd->page_setup = (PAGESETUPDLG *) ckalloc (sizeof (PAGESETUPDLG));
*wd->page_setup = psd;
@@ -916,7 +916,7 @@ ide_create_winprint_command (Tcl_Interp *interp)
{
struct winprint_data *wd;
- wd = (struct winprint_data *) Tcl_Alloc (sizeof *wd);
+ wd = (struct winprint_data *) ckalloc (sizeof *wd);
wd->page_setup = NULL;
wd->aborted = 0;
diff --git a/libgui/src/tkCanvEdge.c b/libgui/src/tkCanvEdge.c
index aa66702d768..a7977f0f904 100644
--- a/libgui/src/tkCanvEdge.c
+++ b/libgui/src/tkCanvEdge.c
@@ -179,8 +179,14 @@ static void TranslateEdge _ANSI_ARGS_((Tk_Canvas canvas,
static Tk_CustomOption arrowShapeOption =
{ ParseArrowShape, PrintArrowShape, (ClientData) NULL};
-static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
- Tk_CanvasTagsPrintProc, (ClientData) NULL};
+/*
+ * The callbacks for tagsOption are initialized in ConfigureEdge()
+ */
+
+static Tk_CustomOption tagsOption =
+{ (Tk_OptionParseProc *) NULL,
+ (Tk_OptionPrintProc *) NULL,
+ (ClientData) NULL};
static Tk_ConfigSpec configSpecs[] = {
{TK_CONFIG_UID, "-arrow", (char *) NULL, (char *) NULL,
@@ -531,6 +537,17 @@ ConfigureEdge(interp, canvas, itemPtr, argc, argv, flags)
tkwin = Tk_CanvasTkwin(canvas);
bgBorder = ((TkCanvas *) canvas)->bgBorder;
+ /*
+ * Init callbacks in tagsOption before accessing configSpecs.
+ * This init can't be done statically when using Windows gcc
+ * since these symbols are imported from the Tk dll.
+ */
+
+ if (tagsOption.parseProc == NULL) {
+ tagsOption.parseProc = Tk_CanvasTagsParseProc;
+ tagsOption.printProc = Tk_CanvasTagsPrintProc;
+ }
+
if (Tk_ConfigureWidget(interp, tkwin,
configSpecs, argc, argv,
(char *) edgePtr, flags) != TCL_OK) {
diff --git a/libgui/src/tkGraphCanvas.c b/libgui/src/tkGraphCanvas.c
index c6ed1e71eef..eff3c6d8540 100644
--- a/libgui/src/tkGraphCanvas.c
+++ b/libgui/src/tkGraphCanvas.c
@@ -259,7 +259,8 @@ GetEdgeNodes(interp,canvasPtr,i,fp,tp)
&argc, &argv) != TCL_OK) {
return TCL_ERROR;
}
- *fp = strdup(argv[4]);
+ *fp = ckalloc (strlen (argv[4]) + 1);
+ strcpy(*fp, argv[4]);
ckfree((char*)argv);
/* Read the to node id of this edge. */
Tk_ConfigureInfo(interp, canvasPtr->tkwin,
@@ -269,7 +270,8 @@ GetEdgeNodes(interp,canvasPtr,i,fp,tp)
&argc, &argv) != TCL_OK) {
return TCL_ERROR;
}
- *tp = strdup(argv[4]);
+ *tp = ckalloc(strlen (argv[4]) + 1);
+ strcpy(*tp, argv[4]);
ckfree((char*)argv);
Tcl_ResetResult(interp);
return TCL_OK;
diff --git a/libgui/src/tkTable.tcl.h b/libgui/src/tkTable.tcl.h
new file mode 100644
index 00000000000..614106e98b5
--- /dev/null
+++ b/libgui/src/tkTable.tcl.h
@@ -0,0 +1,366 @@
+"proc tkTableClipboardKeysyms {copy cut paste} {\n"
+" bind Table <$copy> {tk_tableCopy %W}\n"
+" bind Table <$cut> {tk_tableCut %W}\n"
+" bind Table <$paste> {tk_tablePaste %W}\n"
+"}\n"
+"bind Table <3> {\n"
+" ## You might want to check for row returned if you want to\n"
+" ## restrict the resizing of certain rows\n"
+" %W border mark %x %y\n"
+"}\n"
+"bind Table <B3-Motion> { %W border dragto %x %y }\n"
+"bind Table <1> {\n"
+" if {[winfo exists %W]} {\n"
+" tkTableBeginSelect %W [%W index @%x,%y]\n"
+" focus %W\n"
+" }\n"
+"}\n"
+"bind Table <B1-Motion> {\n"
+" array set tkPriv {x %x y %y}\n"
+" tkTableMotion %W [%W index @%x,%y]\n"
+"}\n"
+"bind Table <Double-1> {\n"
+" # empty\n"
+"}\n"
+"bind Table <ButtonRelease-1> {\n"
+" if {[winfo exists %W]} {\n"
+" tkCancelRepeat\n"
+" %W activate @%x,%y\n"
+" }\n"
+"}\n"
+"bind Table <Shift-1> {tkTableBeginExtend %W [%W index @%x,%y]}\n"
+"bind Table <Control-1> {tkTableBeginToggle %W [%W index @%x,%y]}\n"
+"bind Table <B1-Enter> {tkCancelRepeat}\n"
+"bind Table <B1-Leave> {\n"
+" array set tkPriv {x %x y %y}\n"
+" tkTableAutoScan %W\n"
+"}\n"
+"bind Table <2> {\n"
+" %W scan mark %x %y\n"
+" array set tkPriv {x %x y %y}\n"
+" set tkPriv(mouseMoved) 0\n"
+"}\n"
+"bind Table <B2-Motion> {\n"
+" if {(%x != $tkPriv(x)) || (%y != $tkPriv(y))} { set tkPriv(mouseMoved) 1 }\n"
+" if $tkPriv(mouseMoved) { %W scan dragto %x %y }\n"
+"}\n"
+"bind Table <ButtonRelease-2> {\n"
+" if {!$tkPriv(mouseMoved)} { tk_tablePaste %W [%W index @%x,%y] }\n"
+"}\n"
+"if {[string comp {} [info command event]]} {\n"
+" tkTableClipboardKeysyms <Copy> <Cut> <Paste>\n"
+"} else {\n"
+" tkTableClipboardKeysyms Control-c Control-x Control-v\n"
+"}\n"
+"bind Table <Any-Tab> {\n"
+" # empty to allow Tk focus movement\n"
+"}\n"
+"bind Table <FocusOut> {\n"
+" catch {%W activate active}\n"
+"}\n"
+"bind Table <Shift-Up> {tkTableExtendSelect %W -1 0}\n"
+"bind Table <Shift-Down> {tkTableExtendSelect %W 1 0}\n"
+"bind Table <Shift-Left> {tkTableExtendSelect %W 0 -1}\n"
+"bind Table <Shift-Right> {tkTableExtendSelect %W 0 1}\n"
+"bind Table <Prior> {%W yview scroll -1 pages; %W activate @0,0}\n"
+"bind Table <Next> {%W yview scroll 1 pages; %W activate @0,0}\n"
+"bind Table <Control-Prior> {%W xview scroll -1 pages}\n"
+"bind Table <Control-Next> {%W xview scroll 1 pages}\n"
+"bind Table <Home> {%W see origin}\n"
+"bind Table <End> {%W see end}\n"
+"bind Table <Control-Home> {\n"
+" %W selection clear all\n"
+" %W activate origin\n"
+" %W selection set active\n"
+" %W see active\n"
+"}\n"
+"bind Table <Control-End> {\n"
+" %W selection clear all\n"
+" %W activate end\n"
+" %W selection set active\n"
+" %W see active\n"
+"}\n"
+"bind Table <Shift-Control-Home> {tkTableDataExtend %W origin}\n"
+"bind Table <Shift-Control-End> {tkTableDataExtend %W end}\n"
+"bind Table <Select> {tkTableBeginSelect %W [%W index active]}\n"
+"bind Table <Shift-Select> {tkTableBeginExtend %W [%W index active]}\n"
+"bind Table <Control-slash> {tkTableSelectAll %W}\n"
+"bind Table <Control-backslash> {\n"
+" if {[string match browse [%W cget -selectmode]]} {%W selection clear all}\n"
+"}\n"
+"bind Table <Up> {tkTableMoveCell %W -1 0}\n"
+"bind Table <Down> {tkTableMoveCell %W 1 0}\n"
+"bind Table <Left> {tkTableMoveCell %W 0 -1}\n"
+"bind Table <Right> {tkTableMoveCell %W 0 1}\n"
+"bind Table <Any-KeyPress> {\n"
+" if {[string compare {} %A]} { %W insert active insert %A }\n"
+"}\n"
+"bind Table <BackSpace> {\n"
+" set tkPriv(junk) [%W icursor]\n"
+" if {[string compare {} $tkPriv(junk)] && $tkPriv(junk)} {\n"
+" %W delete active [expr {$tkPriv(junk)-1}]\n"
+" }\n"
+"}\n"
+"bind Table <Delete> {%W delete active insert}\n"
+"bind Table <Escape> {%W reread}\n"
+"bind Table <Return> {\n"
+" %W insert active insert \"\n\"\n"
+"}\n"
+"bind Table <Control-Left> {%W icursor [expr {[%W icursor]-1}]}\n"
+"bind Table <Control-Right> {%W icursor [expr {[%W icursor]+1}]}\n"
+"bind Table <Control-e> {%W icursor end}\n"
+"bind Table <Control-a> {%W icursor 0}\n"
+"bind Table <Control-k> {%W delete active insert end}\n"
+"bind Table <Control-equal> {tkTableChangeWidth %W active 1}\n"
+"bind Table <Control-minus> {tkTableChangeWidth %W active -1}\n"
+"proc tkTableBeginSelect {w el} {\n"
+" global tkPriv\n"
+" if {[scan $el %d,%d r c] != 2} return\n"
+" switch [$w cget -selectmode] {\n"
+" multiple {\n"
+" if {[$w tag includes title $el]} {\n"
+" ## in the title area\n"
+" if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {\n"
+" ## We're in a column header\n"
+" if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {\n"
+" ## We're in the topleft title area\n"
+" set inc topleft\n"
+" set el2 end\n"
+" } else {\n"
+" set inc [$w index topleft row],$c\n"
+" set el2 [$w index end row],$c\n"
+" }\n"
+" } else {\n"
+" ## We're in a row header\n"
+" set inc $r,[$w index topleft col]\n"
+" set el2 $r,[$w index end col]\n"
+" }\n"
+" } else {\n"
+" set inc $el\n"
+" set el2 $el\n"
+" }\n"
+" if [$w selection includes $inc] {\n"
+" $w selection clear $el $el2\n"
+" } else {\n"
+" $w selection set $el $el2\n"
+" }\n"
+" }\n"
+" extended {\n"
+" $w selection clear all\n"
+" if {[$w tag includes title $el]} {\n"
+" if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {\n"
+" ## We're in a column header\n"
+" if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {\n"
+" $w selection set origin end\n"
+" } else {\n"
+" $w selection set $el [$w index end row],$c\n"
+" }\n"
+" } else {\n"
+" ## We're in a row header\n"
+" $w selection set $el $r,[$w index end col]\n"
+" }\n"
+" } else {\n"
+" $w selection set $el\n"
+" }\n"
+" $w selection anchor $el\n"
+" set tkPriv(tablePrev) $el\n"
+" }\n"
+" default {\n"
+" if {![$w tag includes title $el]} {\n"
+" $w selection clear all\n"
+" $w selection set $el\n"
+" set tkPriv(tablePrev) $el\n"
+" }\n"
+" $w selection anchor $el\n"
+" }\n"
+" }\n"
+"}\n"
+"proc tkTableMotion {w el} {\n"
+" global tkPriv\n"
+" if {![info exists tkPriv(tablePrev)]} {\n"
+" set tkPriv(tablePrev) $el\n"
+" return\n"
+" }\n"
+" if {[string match $tkPriv(tablePrev) $el]} return\n"
+" switch [$w cget -selectmode] {\n"
+" browse {\n"
+" $w selection clear all\n"
+" $w selection set $el\n"
+" set tkPriv(tablePrev) $el\n"
+" }\n"
+" extended {\n"
+" scan $tkPriv(tablePrev) %d,%d r c\n"
+" scan $el %d,%d elr elc\n"
+" if {[$w tag includes title $el]} {\n"
+" if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {\n"
+" ## We're in a column header\n"
+" if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {\n"
+" ## We're in the topleft title area\n"
+" $w selection clear anchor end\n"
+" } else {\n"
+" $w selection clear anchor [$w index end row],$c\n"
+" }\n"
+" $w selection set anchor [$w index end row],$elc\n"
+" } else {\n"
+" ## We're in a row header\n"
+" $w selection clear anchor $r,[$w index end col]\n"
+" $w selection set anchor $elr,[$w index end col]\n"
+" }\n"
+" } else {\n"
+" $w selection clear anchor $tkPriv(tablePrev)\n"
+" $w selection set anchor $el\n"
+" }\n"
+" set tkPriv(tablePrev) $el\n"
+" }\n"
+" }\n"
+"}\n"
+"proc tkTableBeginExtend {w el} {\n"
+" if {[string match extended [$w cget -selectmode]] &&\n"
+" [$w selection includes anchor]} {\n"
+" tkTableMotion $w $el\n"
+" }\n"
+"}\n"
+"proc tkTableBeginToggle {w el} {\n"
+" global tkPriv\n"
+" if {[string match extended [$w cget -selectmode]]} {\n"
+" set tkPriv(tablePrev) $el\n"
+" $w selection anchor $el\n"
+" if [$w selection includes $el] {\n"
+" $w selection clear $el\n"
+" } else {\n"
+" $w selection set $el\n"
+" }\n"
+" }\n"
+"}\n"
+"proc tkTableAutoScan {w} {\n"
+" global tkPriv\n"
+" if {![winfo exists $w]} return\n"
+" set x $tkPriv(x)\n"
+" set y $tkPriv(y)\n"
+" if {$y >= [winfo height $w]} {\n"
+" $w yview scroll 1 units\n"
+" } elseif {$y < 0} {\n"
+" $w yview scroll -1 units\n"
+" } elseif {$x >= [winfo width $w]} {\n"
+" $w xview scroll 1 units\n"
+" } elseif {$x < 0} {\n"
+" $w xview scroll -1 units\n"
+" } else {\n"
+" return\n"
+" }\n"
+" tkTableMotion $w [$w index @$x,$y]\n"
+" set tkPriv(afterId) [after 50 tkTableAutoScan $w]\n"
+"}\n"
+"proc tkTableMoveCell {w x y} {\n"
+" global tkPriv\n"
+" if {[catch {$w index active row} r]} return\n"
+" set c [$w index active col]\n"
+" $w activate [incr r $x],[incr c $y]\n"
+" $w see active\n"
+" switch [$w cget -selectmode] {\n"
+" browse {\n"
+" $w selection clear all\n"
+" $w selection set active\n"
+" }\n"
+" extended {\n"
+" $w selection clear all\n"
+" $w selection set active\n"
+" $w selection anchor active\n"
+" set tkPriv(tablePrev) [$w index active]\n"
+" }\n"
+" }\n"
+"}\n"
+"proc tkTableExtendSelect {w x y} {\n"
+" if {[string compare extended [$w cget -selectmode]] ||\n"
+" [catch {$w index active row} r]} return\n"
+" set c [$w index active col]\n"
+" $w activate [incr r $x],[incr c $y]\n"
+" $w see active\n"
+" tkTableMotion $w [$w index active]\n"
+"}\n"
+"proc tkTableDataExtend {w el} {\n"
+" set mode [$w cget -selectmode]\n"
+" if {[string match extended $mode]} {\n"
+" $w activate $el\n"
+" $w see $el\n"
+" if [$w selection includes anchor] {tkTableMotion $w $el}\n"
+" } elseif {[string match multiple $mode]} {\n"
+" $w activate $el\n"
+" $w see $el\n"
+" }\n"
+"}\n"
+"proc tkTableSelectAll {w} {\n"
+" if {[regexp {^(single|browse)$} [$w cget -selectmode]]} {\n"
+" $w selection clear all\n"
+" $w selection set active\n"
+" tkTableHandleType $w [$w index active]\n"
+" } else {\n"
+" $w selection set origin end\n"
+" }\n"
+"}\n"
+"proc tkTableChangeWidth {w i a} {\n"
+" set tmp [$w index $i col]\n"
+" if {[set width [$w width $tmp]] >= 0} {\n"
+" $w width $tmp [incr width $a]\n"
+" } else {\n"
+" $w width $tmp [incr width -$a]\n"
+" }\n"
+"}\n"
+"proc tk_tableCopy w {\n"
+" if {[selection own -displayof $w] == \"$w\"} {\n"
+" clipboard clear -displayof $w\n"
+" catch {clipboard append -displayof $w [selection get -displayof $w]}\n"
+" }\n"
+"}\n"
+"proc tk_tableCut w {\n"
+" if {[selection own -displayof $w] == \"$w\"} {\n"
+" clipboard clear -displayof $w\n"
+" catch {\n"
+" clipboard append -displayof $w [selection get -displayof $w]\n"
+" $w cursel set {}\n"
+" $w selection clear all\n"
+" }\n"
+" }\n"
+"}\n"
+"proc tk_tablePaste {w {cell {}}} {\n"
+" if {[string compare {} $cell]} {\n"
+" if {[catch {selection get -displayof $w} data]} return\n"
+" } else {\n"
+" if {[catch {selection get -displayof $w -selection CLIPBOARD} data]} {\n"
+" return\n"
+" }\n"
+" set cell active\n"
+" }\n"
+" tk_tablePasteHandler $w [$w index $cell] $data\n"
+" if {[$w cget -state] == \"normal\"} {focus $w}\n"
+"}\n"
+"proc tk_tablePasteHandler {w cell data} {\n"
+" set rows [expr {[$w cget -rows]-[$w cget -roworigin]}]\n"
+" set cols [expr {[$w cget -cols]-[$w cget -colorigin]}]\n"
+" set r [$w index $cell row]\n"
+" set c [$w index $cell col]\n"
+" set rsep [$w cget -rowseparator]\n"
+" set csep [$w cget -colseparator]\n"
+" ## Assume separate rows are split by row separator if specified\n"
+" ## If you were to want multi-character row separators, you would need:\n"
+" # regsub -all $rsep $data <newline> data\n"
+" # set data [join $data <newline>]\n"
+" if {[string comp {} $rsep]} { set data [split $data $rsep] }\n"
+" set row $r\n"
+" foreach line $data {\n"
+" if {$row > $rows} break\n"
+" set col $c\n"
+" ## Assume separate cols are split by col separator if specified\n"
+" ## Unless a -separator was specified\n"
+" if {[string comp {} $csep]} { set line [split $line $csep] }\n"
+" ## If you were to want multi-character col separators, you would need:\n"
+" # regsub -all $csep $line <newline> line\n"
+" # set line [join $line <newline>]\n"
+" foreach item $line {\n"
+" if {$col > $cols} break\n"
+" $w set $row,$col $item\n"
+" incr col\n"
+" }\n"
+" incr row\n"
+" }\n"
+"}\n"
diff --git a/libgui/src/tkTableCellSort.c b/libgui/src/tkTableCellSort.c
new file mode 100644
index 00000000000..7afc4d754a1
--- /dev/null
+++ b/libgui/src/tkTableCellSort.c
@@ -0,0 +1,400 @@
+/*
+ * tkTableCell.c --
+ *
+ * This module implements cell sort functions for table
+ * widgets. The MergeSort algorithm and other aux sorting
+ * functions were taken from tclCmdIL.c lsort command:
+
+ * tclCmdIL.c --
+ *
+ * This file contains the top-level command routines for most of
+ * the Tcl built-in commands whose names begin with the letters
+ * I through L. It contains only commands in the generic core
+ * (i.e. those that don't depend much upon UNIX facilities).
+ *
+ * Copyright (c) 1987-1993 The Regents of the University of California.
+ * Copyright (c) 1993-1997 Lucent Technologies.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+
+ *
+ * Copyright (c) 1998-1999 Jeffrey Hobbs
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ */
+
+#include "tkTable.h"
+
+#ifndef UCHAR
+#define UCHAR(c) ((unsigned char) (c))
+#endif
+
+/*
+ * During execution of the "lsort" command, structures of the following
+ * type are used to arrange the objects being sorted into a collection
+ * of linked lists.
+ */
+
+typedef struct SortElement {
+ Tcl_Obj *objPtr; /* Object being sorted. */
+ struct SortElement *nextPtr; /* Next element in the list, or
+ * NULL for end of list. */
+} SortElement;
+
+static int TableSortCompareProc _ANSI_ARGS_((CONST VOID *first,
+ CONST VOID *second));
+static SortElement * MergeSort _ANSI_ARGS_((SortElement *headPt));
+static SortElement * MergeLists _ANSI_ARGS_((SortElement *leftPtr,
+ SortElement *rightPtr));
+static int DictionaryCompare _ANSI_ARGS_((char *left,
+ char *right));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableSortCompareProc --
+ * This procedure is invoked by qsort to determine the proper
+ * ordering between two elements.
+ *
+ * Results:
+ * < 0 means first is "smaller" than "second", > 0 means "first"
+ * is larger than "second", and 0 means they should be treated
+ * as equal.
+ *
+ * Side effects:
+ * None, unless a user-defined comparison command does something
+ * weird.
+ *
+ *----------------------------------------------------------------------
+ */
+static int
+TableSortCompareProc(first, second)
+ CONST VOID *first, *second; /* Elements to be compared. */
+{
+ char *str1 = *((char **) first);
+ char *str2 = *((char **) second);
+
+ return DictionaryCompare(str1, str2);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableCellSort --
+ * Sort a list of table cell elements (of form row,col)
+ *
+ * Results:
+ * Returns the sorted list of elements. Because Tcl_Merge allocs
+ * the space for result, it must later be Tcl_Free'd by caller.
+ *
+ * Side effects:
+ * Behaviour undefined for ill-formed input list of elements.
+ *
+ *----------------------------------------------------------------------
+ */
+char *
+TableCellSort(Table *tablePtr, char *str)
+{
+ int listArgc;
+ char **listArgv;
+ char *result;
+
+ if (Tcl_SplitList(tablePtr->interp, str, &listArgc, &listArgv) != TCL_OK) {
+ return str;
+ }
+ /* Thread safety: qsort is reportedly not thread-safe... */
+ qsort((VOID *) listArgv, (size_t) listArgc, sizeof (char *),
+ TableSortCompareProc);
+ result = Tcl_Merge(listArgc, listArgv);
+ ckfree((char *) listArgv);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictionaryCompare - Not the Unicode version
+ *
+ * This function compares two strings as if they were being used in
+ * an index or card catalog. The case of alphabetic characters is
+ * ignored, except to break ties. Thus "B" comes before "b" but
+ * after "a". Also, integers embedded in the strings compare in
+ * numerical order. In other words, "x10y" comes after "x9y", not
+ * before it as it would when using strcmp().
+ *
+ * Results:
+ * A negative result means that the first element comes before the
+ * second, and a positive result means that the second element
+ * should come first. A result of zero means the two elements
+ * are equal and it doesn't matter which comes first.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictionaryCompare(left, right)
+ char *left, *right; /* The strings to compare */
+{
+ int diff, zeros;
+ int secondaryDiff = 0;
+
+ while (1) {
+ if (isdigit(UCHAR(*right)) && isdigit(UCHAR(*left))) {
+ /*
+ * There are decimal numbers embedded in the two
+ * strings. Compare them as numbers, rather than
+ * strings. If one number has more leading zeros than
+ * the other, the number with more leading zeros sorts
+ * later, but only as a secondary choice.
+ */
+
+ zeros = 0;
+ while ((*right == '0') && (isdigit(UCHAR(right[1])))) {
+ right++;
+ zeros--;
+ }
+ while ((*left == '0') && (isdigit(UCHAR(left[1])))) {
+ left++;
+ zeros++;
+ }
+ if (secondaryDiff == 0) {
+ secondaryDiff = zeros;
+ }
+
+ /*
+ * The code below compares the numbers in the two
+ * strings without ever converting them to integers. It
+ * does this by first comparing the lengths of the
+ * numbers and then comparing the digit values.
+ */
+
+ diff = 0;
+ while (1) {
+ if (diff == 0) {
+ diff = UCHAR(*left) - UCHAR(*right);
+ }
+ right++;
+ left++;
+ if (!isdigit(UCHAR(*right))) {
+ if (isdigit(UCHAR(*left))) {
+ return 1;
+ } else {
+ /*
+ * The two numbers have the same length. See
+ * if their values are different.
+ */
+
+ if (diff != 0) {
+ return diff;
+ }
+ break;
+ }
+ } else if (!isdigit(UCHAR(*left))) {
+ return -1;
+ }
+ }
+ continue;
+ }
+ diff = UCHAR(*left) - UCHAR(*right);
+ if (diff) {
+ if (isupper(UCHAR(*left)) && islower(UCHAR(*right))) {
+ diff = UCHAR(tolower(*left)) - UCHAR(*right);
+ if (diff) {
+ return diff;
+ } else if (secondaryDiff == 0) {
+ secondaryDiff = -1;
+ }
+ } else if (isupper(UCHAR(*right)) && islower(UCHAR(*left))) {
+ diff = UCHAR(*left) - UCHAR(tolower(UCHAR(*right)));
+ if (diff) {
+ return diff;
+ } else if (secondaryDiff == 0) {
+ secondaryDiff = 1;
+ }
+ } else {
+ return diff;
+ }
+ }
+ if (*left == 0) {
+ break;
+ }
+ left++;
+ right++;
+ }
+ if (diff == 0) {
+ diff = secondaryDiff;
+ }
+ return diff;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MergeLists -
+ *
+ * This procedure combines two sorted lists of SortElement structures
+ * into a single sorted list.
+ *
+ * Results:
+ * The unified list of SortElement structures.
+ *
+ * Side effects:
+ * None, unless a user-defined comparison command does something
+ * weird.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static SortElement *
+MergeLists(leftPtr, rightPtr)
+ SortElement *leftPtr; /* First list to be merged; may be
+ * NULL. */
+ SortElement *rightPtr; /* Second list to be merged; may be
+ * NULL. */
+{
+ SortElement *headPtr;
+ SortElement *tailPtr;
+
+ if (leftPtr == NULL) {
+ return rightPtr;
+ }
+ if (rightPtr == NULL) {
+ return leftPtr;
+ }
+ if (DictionaryCompare(Tcl_GetString(leftPtr->objPtr),
+ Tcl_GetString(rightPtr->objPtr)) > 0) {
+ tailPtr = rightPtr;
+ rightPtr = rightPtr->nextPtr;
+ } else {
+ tailPtr = leftPtr;
+ leftPtr = leftPtr->nextPtr;
+ }
+ headPtr = tailPtr;
+ while ((leftPtr != NULL) && (rightPtr != NULL)) {
+ if (DictionaryCompare(Tcl_GetString(leftPtr->objPtr),
+ Tcl_GetString(rightPtr->objPtr)) > 0) {
+ tailPtr->nextPtr = rightPtr;
+ tailPtr = rightPtr;
+ rightPtr = rightPtr->nextPtr;
+ } else {
+ tailPtr->nextPtr = leftPtr;
+ tailPtr = leftPtr;
+ leftPtr = leftPtr->nextPtr;
+ }
+ }
+ if (leftPtr != NULL) {
+ tailPtr->nextPtr = leftPtr;
+ } else {
+ tailPtr->nextPtr = rightPtr;
+ }
+ return headPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MergeSort -
+ *
+ * This procedure sorts a linked list of SortElement structures
+ * use the merge-sort algorithm.
+ *
+ * Results:
+ * A pointer to the head of the list after sorting is returned.
+ *
+ * Side effects:
+ * None, unless a user-defined comparison command does something
+ * weird.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static SortElement *
+MergeSort(headPtr)
+ SortElement *headPtr; /* First element on the list */
+{
+ /*
+ * The subList array below holds pointers to temporary lists built
+ * during the merge sort. Element i of the array holds a list of
+ * length 2**i.
+ */
+
+# define NUM_LISTS 30
+ SortElement *subList[NUM_LISTS];
+ SortElement *elementPtr;
+ int i;
+
+ for(i = 0; i < NUM_LISTS; i++){
+ subList[i] = NULL;
+ }
+ while (headPtr != NULL) {
+ elementPtr = headPtr;
+ headPtr = headPtr->nextPtr;
+ elementPtr->nextPtr = 0;
+ for (i = 0; (i < NUM_LISTS) && (subList[i] != NULL); i++){
+ elementPtr = MergeLists(subList[i], elementPtr);
+ subList[i] = NULL;
+ }
+ if (i >= NUM_LISTS) {
+ i = NUM_LISTS-1;
+ }
+ subList[i] = elementPtr;
+ }
+ elementPtr = NULL;
+ for (i = 0; i < NUM_LISTS; i++){
+ elementPtr = MergeLists(subList[i], elementPtr);
+ }
+ return elementPtr;
+}
+
+#ifndef NO_SORT_CELLS
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableCellSortObj --
+ * Sorts a list of table cell elements (of form row,col) in place
+ *
+ * Results:
+ * Sorts list of elements in place.
+ *
+ * Side effects:
+ * Behaviour undefined for ill-formed input list of elements.
+ *
+ *----------------------------------------------------------------------
+ */
+Tcl_Obj *
+TableCellSortObj(Tcl_Interp *interp, Tcl_Obj *listObjPtr)
+{
+ int length, i;
+ Tcl_Obj *sortedObjPtr, **listObjPtrs;
+ SortElement *elementArray;
+ SortElement *elementPtr;
+
+ if (Tcl_ListObjGetElements(interp, listObjPtr,
+ &length, &listObjPtrs) != TCL_OK) {
+ return NULL;
+ }
+ if (length <= 0) {
+ return listObjPtr;
+ }
+
+ elementArray = (SortElement *) ckalloc(length * sizeof(SortElement));
+ for (i=0; i < length; i++){
+ elementArray[i].objPtr = listObjPtrs[i];
+ elementArray[i].nextPtr = &elementArray[i+1];
+ }
+ elementArray[length-1].nextPtr = NULL;
+ elementPtr = MergeSort(elementArray);
+ sortedObjPtr = Tcl_NewObj();
+ for (; elementPtr != NULL; elementPtr = elementPtr->nextPtr){
+ Tcl_ListObjAppendElement(NULL, sortedObjPtr, elementPtr->objPtr);
+ }
+ ckfree((char*) elementArray);
+
+ return sortedObjPtr;
+}
+#endif
diff --git a/libgui/src/tkTableCmds.c b/libgui/src/tkTableCmds.c
new file mode 100644
index 00000000000..4fc7d3b374a
--- /dev/null
+++ b/libgui/src/tkTableCmds.c
@@ -0,0 +1,1293 @@
+/*
+ * tkTableCmds.c --
+ *
+ * This module implements general commands of a table widget,
+ * based on the major/minor command structure.
+ *
+ * Copyright (c) 1998-2000 Jeffrey Hobbs
+ *
+ * See the file "license.txt" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ */
+
+#include "tkTable.h"
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_ActivateCmd --
+ * This procedure is invoked to process the activate method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_ActivateCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ int result = TCL_OK;
+ int row, col;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ return TCL_ERROR;
+ } else if (TableGetIndexObj(tablePtr, objv[2], &row, &col) != TCL_OK) {
+ return TCL_ERROR;
+ } else {
+ int x, y, w, dummy;
+ char buf1[INDEX_BUFSIZE], buf2[INDEX_BUFSIZE];
+
+ /* convert to valid active index in real coords */
+ row -= tablePtr->rowOffset;
+ col -= tablePtr->colOffset;
+ /* we do this regardless, to avoid cell commit problems */
+ if ((tablePtr->flags & HAS_ACTIVE) &&
+ (tablePtr->flags & TEXT_CHANGED)) {
+ tablePtr->flags &= ~TEXT_CHANGED;
+ TableSetCellValue(tablePtr,
+ tablePtr->activeRow+tablePtr->rowOffset,
+ tablePtr->activeCol+tablePtr->colOffset,
+ tablePtr->activeBuf);
+ }
+ if (row != tablePtr->activeRow || col != tablePtr->activeCol) {
+ if (tablePtr->flags & HAS_ACTIVE) {
+ TableMakeArrayIndex(tablePtr->activeRow+tablePtr->rowOffset,
+ tablePtr->activeCol+tablePtr->colOffset,
+ buf1);
+ } else {
+ buf1[0] = '\0';
+ }
+ tablePtr->flags |= HAS_ACTIVE;
+ tablePtr->flags &= ~ACTIVE_DISABLED;
+ tablePtr->activeRow = row;
+ tablePtr->activeCol = col;
+ if (tablePtr->activeTagPtr != NULL) {
+ ckfree((char *) (tablePtr->activeTagPtr));
+ tablePtr->activeTagPtr = NULL;
+ }
+ TableAdjustActive(tablePtr);
+ TableConfigCursor(tablePtr);
+ if (!(tablePtr->flags & BROWSE_CMD) &&
+ tablePtr->browseCmd != NULL) {
+ Tcl_DString script;
+ tablePtr->flags |= BROWSE_CMD;
+ row = tablePtr->activeRow+tablePtr->rowOffset;
+ col = tablePtr->activeCol+tablePtr->colOffset;
+ TableMakeArrayIndex(row, col, buf2);
+ Tcl_DStringInit(&script);
+ ExpandPercents(tablePtr, tablePtr->browseCmd, row, col,
+ buf1, buf2, tablePtr->icursor, &script, 0);
+ result = Tcl_GlobalEval(interp, Tcl_DStringValue(&script));
+ if (result == TCL_OK || result == TCL_RETURN) {
+ Tcl_ResetResult(interp);
+ }
+ Tcl_DStringFree(&script);
+ tablePtr->flags &= ~BROWSE_CMD;
+ }
+ } else {
+ char *p = Tcl_GetString(objv[2]);
+
+ if ((tablePtr->activeTagPtr != NULL) && *p == '@' &&
+ !(tablePtr->flags & ACTIVE_DISABLED) &&
+ TableCellVCoords(tablePtr, row, col, &x, &y, &w, &dummy, 0)) {
+ /* we are clicking into the same cell
+ * If it was activated with @x,y indexing,
+ * find the closest char */
+ Tk_TextLayout textLayout;
+ TableTag *tagPtr = tablePtr->activeTagPtr;
+
+ /* no error checking because GetIndex did it for us */
+ p++;
+ x = strtol(p, &p, 0) - x - tablePtr->activeX;
+ y = strtol(++p, &p, 0) - y - tablePtr->activeY;
+
+ textLayout = Tk_ComputeTextLayout(tagPtr->tkfont,
+ tablePtr->activeBuf, -1,
+ (tagPtr->wrap) ? w : 0,
+ tagPtr->justify, 0, &dummy, &dummy);
+
+ tablePtr->icursor = Tk_PointToChar(textLayout, x, y);
+ Tk_FreeTextLayout(textLayout);
+ TableRefresh(tablePtr, row, col, CELL|INV_FORCE);
+ }
+ }
+ tablePtr->flags |= HAS_ACTIVE;
+ }
+ return result;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_AdjustCmd --
+ * This procedure is invoked to process the width/height method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_AdjustCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ Tcl_HashEntry *entryPtr;
+ Tcl_HashSearch search;
+ Tcl_HashTable *hashTablePtr;
+ int i, widthType, dummy, value, posn, offset;
+ char buf1[INDEX_BUFSIZE];
+
+ widthType = (*(Tcl_GetString(objv[1])) == 'w');
+ /* changes the width/height of certain selected columns */
+ if (objc != 3 && (objc & 1)) {
+ Tcl_WrongNumArgs(interp, 2, objv, widthType ?
+ "?col? ?width col width ...?" :
+ "?row? ?height row height ...?");
+ return TCL_ERROR;
+ }
+ if (widthType) {
+ hashTablePtr = tablePtr->colWidths;
+ offset = tablePtr->colOffset;
+ } else {
+ hashTablePtr = tablePtr->rowHeights;
+ offset = tablePtr->rowOffset;
+ }
+
+ if (objc == 2) {
+ /* print out all the preset column widths or row heights */
+ entryPtr = Tcl_FirstHashEntry(hashTablePtr, &search);
+ while (entryPtr != NULL) {
+ posn = ((int) Tcl_GetHashKey(hashTablePtr, entryPtr)) + offset;
+ value = (int) Tcl_GetHashValue(entryPtr);
+ sprintf(buf1, "%d %d", posn, value);
+ /* OBJECTIFY */
+ Tcl_AppendElement(interp, buf1);
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ } else if (objc == 3) {
+ /* get the width/height of a particular row/col */
+ if (Tcl_GetIntFromObj(interp, objv[2], &posn) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /* no range check is done, why bother? */
+ posn -= offset;
+ entryPtr = Tcl_FindHashEntry(hashTablePtr, (char *) posn);
+ if (entryPtr != NULL) {
+ Tcl_SetIntObj(Tcl_GetObjResult(interp),
+ (int) Tcl_GetHashValue(entryPtr));
+ } else {
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), widthType ?
+ tablePtr->defColWidth : tablePtr->defRowHeight);
+ }
+ } else {
+ for (i=2; i<objc; i++) {
+ /* set new width|height here */
+ value = -999999;
+ if (Tcl_GetIntFromObj(interp, objv[i++], &posn) != TCL_OK ||
+ (strcmp(Tcl_GetString(objv[i]), "default") &&
+ Tcl_GetIntFromObj(interp, objv[i], &value) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ posn -= offset;
+ if (value == -999999) {
+ /* reset that field */
+ entryPtr = Tcl_FindHashEntry(hashTablePtr, (char *) posn);
+ if (entryPtr != NULL) {
+ Tcl_DeleteHashEntry(entryPtr);
+ }
+ } else {
+ entryPtr = Tcl_CreateHashEntry(hashTablePtr,
+ (char *) posn, &dummy);
+ Tcl_SetHashValue(entryPtr, (ClientData) value);
+ }
+ }
+ TableAdjustParams(tablePtr);
+ /* rerequest geometry */
+ TableGeometryRequest(tablePtr);
+ /*
+ * Invalidate the whole window as TableAdjustParams
+ * will only check to see if the top left cell has moved
+ * FIX: should just move from lowest order visible cell
+ * to edge of window
+ */
+ TableInvalidateAll(tablePtr, 0);
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_BboxCmd --
+ * This procedure is invoked to process the bbox method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_BboxCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ int x, y, w, h, row, col, key;
+ Tcl_Obj *resultPtr;
+
+ /* Returns bounding box of cell(s) */
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "first ?last?");
+ return TCL_ERROR;
+ } else if (TableGetIndexObj(tablePtr, objv[2], &row, &col) == TCL_ERROR ||
+ (objc == 4 &&
+ TableGetIndexObj(tablePtr, objv[3], &x, &y) == TCL_ERROR)) {
+ return TCL_ERROR;
+ }
+
+ resultPtr = Tcl_GetObjResult(interp);
+ if (objc == 3) {
+ row -= tablePtr->rowOffset; col -= tablePtr->colOffset;
+ if (TableCellVCoords(tablePtr, row, col, &x, &y, &w, &h, 0)) {
+ Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewIntObj(x));
+ Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewIntObj(y));
+ Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewIntObj(w));
+ Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewIntObj(h));
+ }
+ return TCL_OK;
+ } else {
+ int r1, c1, r2, c2, minX = 99999, minY = 99999, maxX = 0, maxY = 0;
+
+ row -= tablePtr->rowOffset; col -= tablePtr->colOffset;
+ x -= tablePtr->rowOffset; y -= tablePtr->colOffset;
+ r1 = MIN(row,x); r2 = MAX(row,x);
+ c1 = MIN(col,y); c2 = MAX(col,y);
+ key = 0;
+ for (row = r1; row <= r2; row++) {
+ for (col = c1; col <= c2; col++) {
+ if (TableCellVCoords(tablePtr, row, col, &x, &y, &w, &h, 0)) {
+ /* Get max bounding box */
+ if (x < minX) minX = x;
+ if (y < minY) minY = y;
+ if (x+w > maxX) maxX = x+w;
+ if (y+h > maxY) maxY = y+h;
+ key++;
+ }
+ }
+ }
+ if (key) {
+ Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewIntObj(minX));
+ Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewIntObj(minY));
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewIntObj(maxX-minX));
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewIntObj(maxY-minY));
+ }
+ }
+ return TCL_OK;
+}
+
+static char *bdCmdNames[] = {
+ "mark", "dragto", (char *)NULL
+};
+enum bdCmd {
+ BD_MARK, BD_DRAGTO
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_BorderCmd --
+ * This procedure is invoked to process the bbox method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_BorderCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ Tcl_HashEntry *entryPtr;
+ int x, y, w, h, row, col, key, dummy, value, cmdIndex;
+ char *rc = NULL;
+ Tcl_Obj *objPtr, *resultPtr;
+
+ if (objc < 5 || objc > 6) {
+ Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x y ?row|col?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[2], bdCmdNames,
+ "option", 0, &cmdIndex) != TCL_OK ||
+ Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK ||
+ Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc == 6) {
+ rc = Tcl_GetStringFromObj(objv[5], &w);
+ if ((w < 1) || (strncmp(rc, "row", w) && strncmp(rc, "col", w))) {
+ Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x y ?row|col?");
+ return TCL_ERROR;
+ }
+ }
+
+ resultPtr = Tcl_GetObjResult(interp);
+ switch ((enum bdCmd) cmdIndex) {
+ case BD_MARK:
+ /* Use x && y to determine if we are over a border */
+ value = TableAtBorder(tablePtr, x, y, &row, &col);
+ /* Cache the row && col for use in DRAGTO */
+ tablePtr->scanMarkRow = row;
+ tablePtr->scanMarkCol = col;
+ if (!value) {
+ return TCL_OK;
+ }
+ TableCellCoords(tablePtr, row, col, &x, &y, &dummy, &dummy);
+ tablePtr->scanMarkX = x;
+ tablePtr->scanMarkY = y;
+ if (objc == 5 || *rc == 'r') {
+ if (row < 0) {
+ objPtr = Tcl_NewStringObj("", 0);
+ } else {
+ objPtr = Tcl_NewIntObj(row+tablePtr->rowOffset);
+ }
+ Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
+ }
+ if (objc == 5 || *rc == 'c') {
+ if (col < 0) {
+ objPtr = Tcl_NewStringObj("", 0);
+ } else {
+ objPtr = Tcl_NewIntObj(col+tablePtr->colOffset);
+ }
+ Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
+ }
+ return TCL_OK; /* BORDER MARK */
+
+ case BD_DRAGTO:
+ /* check to see if we want to resize any borders */
+ if (tablePtr->resize == SEL_NONE) { return TCL_OK; }
+ row = tablePtr->scanMarkRow;
+ col = tablePtr->scanMarkCol;
+ TableCellCoords(tablePtr, row, col, &w, &h, &dummy, &dummy);
+ key = 0;
+ if (row >= 0 && (tablePtr->resize & SEL_ROW)) {
+ /* row border was active, move it */
+ value = y-h;
+ if (value < -1) value = -1;
+ if (value != tablePtr->scanMarkY) {
+ entryPtr = Tcl_CreateHashEntry(tablePtr->rowHeights,
+ (char *) row, &dummy);
+ /* -value means rowHeight will be interp'd as pixels, not
+ lines */
+ Tcl_SetHashValue(entryPtr, (ClientData) MIN(0,-value));
+ tablePtr->scanMarkY = value;
+ key++;
+ }
+ }
+ if (col >= 0 && (tablePtr->resize & SEL_COL)) {
+ /* col border was active, move it */
+ value = x-w;
+ if (value < -1) value = -1;
+ if (value != tablePtr->scanMarkX) {
+ entryPtr = Tcl_CreateHashEntry(tablePtr->colWidths,
+ (char *) col, &dummy);
+ /* -value means colWidth will be interp'd as pixels, not
+ chars */
+ Tcl_SetHashValue(entryPtr, (ClientData) MIN(0,-value));
+ tablePtr->scanMarkX = value;
+ key++;
+ }
+ }
+ /* Only if something changed do we want to update */
+ if (key) {
+ TableAdjustParams(tablePtr);
+ /* Only rerequest geometry if the basis is the #rows &| #cols */
+ if (tablePtr->maxReqCols || tablePtr->maxReqRows)
+ TableGeometryRequest(tablePtr);
+ TableInvalidateAll(tablePtr, 0);
+ }
+ return TCL_OK; /* BORDER DRAGTO */
+ }
+ return TCL_OK;
+}
+
+/* clear subcommands */
+static char *clearNames[] = {
+ "all", "cache", "sizes", "tags", (char *)NULL
+};
+enum clearCommand {
+ CLEAR_ALL, CLEAR_CACHE, CLEAR_SIZES, CLEAR_TAGS
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_ClearCmd --
+ * This procedure is invoked to process the clear method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * Cached info can be lost. Returns valid Tcl result.
+ *
+ * Side effects:
+ * Can cause redraw.
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_ClearCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ int cmdIndex, redraw = 0;
+
+ if (objc < 3 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?first? ?last?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[2], clearNames,
+ "clear option", 0, &cmdIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (objc == 3) {
+ if (cmdIndex == CLEAR_TAGS || cmdIndex == CLEAR_ALL) {
+ Tcl_DeleteHashTable(tablePtr->rowStyles);
+ Tcl_DeleteHashTable(tablePtr->colStyles);
+ Tcl_DeleteHashTable(tablePtr->cellStyles);
+ Tcl_DeleteHashTable(tablePtr->flashCells);
+ Tcl_DeleteHashTable(tablePtr->selCells);
+
+ /* style hash tables */
+ Tcl_InitHashTable(tablePtr->rowStyles, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(tablePtr->colStyles, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(tablePtr->cellStyles, TCL_STRING_KEYS);
+
+ /* special style hash tables */
+ Tcl_InitHashTable(tablePtr->flashCells, TCL_STRING_KEYS);
+ Tcl_InitHashTable(tablePtr->selCells, TCL_STRING_KEYS);
+ }
+
+ if (cmdIndex == CLEAR_SIZES || cmdIndex == CLEAR_ALL) {
+ Tcl_DeleteHashTable(tablePtr->colWidths);
+ Tcl_DeleteHashTable(tablePtr->rowHeights);
+
+ /* style hash tables */
+ Tcl_InitHashTable(tablePtr->colWidths, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(tablePtr->rowHeights, TCL_ONE_WORD_KEYS);
+ }
+
+ if (cmdIndex == CLEAR_CACHE || cmdIndex == CLEAR_ALL) {
+ Tcl_DeleteHashTable(tablePtr->cache);
+ Tcl_InitHashTable(tablePtr->cache, TCL_STRING_KEYS);
+ /* If we were caching and we have no other data source,
+ * invalidate all the cells */
+ if (tablePtr->dataSource == DATA_CACHE) {
+ TableGetActiveBuf(tablePtr);
+ }
+ }
+ redraw = 1;
+ } else {
+ int row, col, r1, r2, c1, c2;
+ Tcl_HashEntry *entryPtr;
+ char buf[INDEX_BUFSIZE];
+
+ if (TableGetIndexObj(tablePtr, objv[3], &row, &col) != TCL_OK ||
+ ((objc == 5) &&
+ TableGetIndexObj(tablePtr, objv[4], &r2, &c2) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if (objc == 4) {
+ r1 = r2 = row;
+ c1 = c2 = col;
+ } else {
+ r1 = MIN(row,r2); r2 = MAX(row,r2);
+ c1 = MIN(col,c2); c2 = MAX(col,c2);
+ }
+ for (row = r1; row <= r2; row++) {
+ /* Note that *Styles entries are user based (no offset)
+ * while size entries are 0-based (real) */
+ if ((cmdIndex == CLEAR_TAGS || cmdIndex == CLEAR_ALL) &&
+ (entryPtr = Tcl_FindHashEntry(tablePtr->rowStyles,
+ (char *) row))) {
+ Tcl_DeleteHashEntry(entryPtr);
+ redraw = 1;
+ }
+
+ if ((cmdIndex == CLEAR_SIZES || cmdIndex == CLEAR_ALL) &&
+ (entryPtr = Tcl_FindHashEntry(tablePtr->rowHeights,
+ (char *) row-tablePtr->rowOffset))) {
+ Tcl_DeleteHashEntry(entryPtr);
+ redraw = 1;
+ }
+
+ for (col = c1; col <= c2; col++) {
+ TableMakeArrayIndex(row, col, buf);
+
+ if (cmdIndex == CLEAR_TAGS || cmdIndex == CLEAR_ALL) {
+ if ((row == r1) &&
+ (entryPtr = Tcl_FindHashEntry(tablePtr->colStyles,
+ (char *) col))) {
+ Tcl_DeleteHashEntry(entryPtr);
+ redraw = 1;
+ }
+ if ((entryPtr = Tcl_FindHashEntry(tablePtr->cellStyles,
+ buf))) {
+ Tcl_DeleteHashEntry(entryPtr);
+ redraw = 1;
+ }
+ if ((entryPtr = Tcl_FindHashEntry(tablePtr->flashCells,
+ buf))) {
+ Tcl_DeleteHashEntry(entryPtr);
+ redraw = 1;
+ }
+ if ((entryPtr = Tcl_FindHashEntry(tablePtr->selCells,
+ buf))) {
+ Tcl_DeleteHashEntry(entryPtr);
+ redraw = 1;
+ }
+ }
+
+ if ((cmdIndex == CLEAR_SIZES || cmdIndex == CLEAR_ALL) &&
+ row == r1 &&
+ (entryPtr = Tcl_FindHashEntry(tablePtr->colWidths, (char *)
+ col-tablePtr->colOffset))) {
+ Tcl_DeleteHashEntry(entryPtr);
+ redraw = 1;
+ }
+
+ if ((cmdIndex == CLEAR_CACHE || cmdIndex == CLEAR_ALL) &&
+ (entryPtr = Tcl_FindHashEntry(tablePtr->cache, buf))) {
+ Tcl_DeleteHashEntry(entryPtr);
+ /* if the cache is our data source,
+ * we need to invalidate the cells changed */
+ if ((tablePtr->dataSource == DATA_CACHE) &&
+ (row-tablePtr->rowOffset == tablePtr->activeRow &&
+ col-tablePtr->colOffset == tablePtr->activeCol))
+ TableGetActiveBuf(tablePtr);
+ redraw = 1;
+ }
+ }
+ }
+ }
+ /* This could be more sensitive about what it updates,
+ * but that can actually be a lot more costly in some cases */
+ if (redraw) {
+ if (cmdIndex == CLEAR_SIZES || cmdIndex == CLEAR_ALL) {
+ TableAdjustParams(tablePtr);
+ /* rerequest geometry */
+ TableGeometryRequest(tablePtr);
+ }
+ TableInvalidateAll(tablePtr, 0);
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_CurselectionCmd --
+ * This procedure is invoked to process the bbox method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_CurselectionCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ Tcl_HashEntry *entryPtr;
+ Tcl_HashSearch search;
+ char *value = NULL;
+ int row, col;
+
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?value?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ /* make sure there is a data source to accept a set value */
+ if ((tablePtr->state == STATE_DISABLED) ||
+ (tablePtr->dataSource == DATA_NONE)) {
+ return TCL_OK;
+ }
+ value = Tcl_GetString(objv[2]);
+ for (entryPtr = Tcl_FirstHashEntry(tablePtr->selCells, &search);
+ entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {
+ TableParseArrayIndex(&row, &col,
+ Tcl_GetHashKey(tablePtr->selCells, entryPtr));
+ TableSetCellValue(tablePtr, row, col, value);
+ row -= tablePtr->rowOffset;
+ col -= tablePtr->colOffset;
+ if (row == tablePtr->activeRow && col == tablePtr->activeCol) {
+ TableGetActiveBuf(tablePtr);
+ }
+ TableRefresh(tablePtr, row, col, CELL);
+ }
+ } else {
+ Tcl_Obj *objPtr = Tcl_NewObj();
+
+ for (entryPtr = Tcl_FirstHashEntry(tablePtr->selCells, &search);
+ entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {
+ value = Tcl_GetHashKey(tablePtr->selCells, entryPtr);
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewStringObj(value, -1));
+ }
+ Tcl_SetObjResult(interp, TableCellSortObj(interp, objPtr));
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_CurvalueCmd --
+ * This procedure is invoked to process the curvalue method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_CurvalueCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?<value>?");
+ return TCL_ERROR;
+ } else if (!(tablePtr->flags & HAS_ACTIVE)) {
+ return TCL_OK;
+ }
+
+ if (objc == 3) {
+ char *value;
+ int len;
+
+ value = Tcl_GetStringFromObj(objv[2], &len);
+ if (STREQ(value, tablePtr->activeBuf)) {
+ Tcl_SetObjResult(interp, objv[2]);
+ return TCL_OK;
+ }
+ /* validate potential new active buffer contents
+ * only accept if validation returns acceptance. */
+ if (tablePtr->validate &&
+ TableValidateChange(tablePtr,
+ tablePtr->activeRow+tablePtr->rowOffset,
+ tablePtr->activeCol+tablePtr->colOffset,
+ tablePtr->activeBuf,
+ value, tablePtr->icursor) != TCL_OK) {
+ return TCL_OK;
+ }
+ tablePtr->activeBuf = (char *)ckrealloc(tablePtr->activeBuf, len+1);
+ strcpy(tablePtr->activeBuf, value);
+ /* mark the text as changed */
+ tablePtr->flags |= TEXT_CHANGED;
+ TableSetActiveIndex(tablePtr);
+ /* check for possible adjustment of icursor */
+ TableGetIcursor(tablePtr, "insert", (int *)0);
+ TableRefresh(tablePtr, tablePtr->activeRow, tablePtr->activeCol, CELL);
+ }
+
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), tablePtr->activeBuf, -1);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_GetCmd --
+ * This procedure is invoked to process the bbox method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_GetCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ int result = TCL_OK;
+ int r1, c1, r2, c2, row, col;
+
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "first ?last?");
+ result = TCL_ERROR;
+ } else if (TableGetIndexObj(tablePtr, objv[2], &row, &col) == TCL_ERROR) {
+ result = TCL_ERROR;
+ } else if (objc == 3) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj(TableGetCellValue(tablePtr, row, col), -1));
+ } else if (TableGetIndexObj(tablePtr, objv[3], &r2, &c2) == TCL_ERROR) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_Obj *objPtr = Tcl_NewObj();
+
+ r1 = MIN(row,r2); r2 = MAX(row,r2);
+ c1 = MIN(col,c2); c2 = MAX(col,c2);
+ for ( row = r1; row <= r2; row++ ) {
+ for ( col = c1; col <= c2; col++ ) {
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewStringObj(TableGetCellValue(tablePtr,
+ row, col), -1));
+ }
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ return result;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_ScanCmd --
+ * This procedure is invoked to process the scan method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_ScanCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ int x, y, row, col, cmdIndex;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x y");
+ return TCL_ERROR;
+ } else if (Tcl_GetIndexFromObj(interp, objv[2], bdCmdNames,
+ "option", 0, &cmdIndex) != TCL_OK ||
+ Tcl_GetIntFromObj(interp, objv[3], &x) == TCL_ERROR ||
+ Tcl_GetIntFromObj(interp, objv[4], &y) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ switch ((enum bdCmd) cmdIndex) {
+ case BD_MARK:
+ TableWhatCell(tablePtr, x, y, &row, &col);
+ tablePtr->scanMarkRow = row-tablePtr->topRow;
+ tablePtr->scanMarkCol = col-tablePtr->leftCol;
+ tablePtr->scanMarkX = x;
+ tablePtr->scanMarkY = y;
+ break;
+
+ case BD_DRAGTO: {
+ int oldTop = tablePtr->topRow, oldLeft = tablePtr->leftCol;
+ y += (5*(y-tablePtr->scanMarkY));
+ x += (5*(x-tablePtr->scanMarkX));
+
+ TableWhatCell(tablePtr, x, y, &row, &col);
+
+ /* maintain appropriate real index */
+ tablePtr->topRow = BETWEEN(row-tablePtr->scanMarkRow,
+ tablePtr->titleRows, tablePtr->rows-1);
+ tablePtr->leftCol = BETWEEN(col-tablePtr->scanMarkCol,
+ tablePtr->titleCols, tablePtr->cols-1);
+
+ /* Adjust the table if new top left */
+ if (oldTop != tablePtr->topRow || oldLeft != tablePtr->leftCol) {
+ TableAdjustParams(tablePtr);
+ }
+ break;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_SelAnchorCmd --
+ * This procedure is invoked to process the selection anchor method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_SelAnchorCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ int row, col;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ return TCL_ERROR;
+ } else if (TableGetIndexObj(tablePtr, objv[3], &row, &col) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ tablePtr->flags |= HAS_ANCHOR;
+ /* maintain appropriate real index */
+ if (tablePtr->selectTitles) {
+ tablePtr->anchorRow = BETWEEN(row-tablePtr->rowOffset,
+ 0, tablePtr->rows-1);
+ tablePtr->anchorCol = BETWEEN(col-tablePtr->colOffset,
+ 0, tablePtr->cols-1);
+ } else {
+ tablePtr->anchorRow = BETWEEN(row-tablePtr->rowOffset,
+ tablePtr->titleRows, tablePtr->rows-1);
+ tablePtr->anchorCol = BETWEEN(col-tablePtr->colOffset,
+ tablePtr->titleCols, tablePtr->cols-1);
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_SelClearCmd --
+ * This procedure is invoked to process the selection clear method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_SelClearCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ int result = TCL_OK;
+ char buf1[INDEX_BUFSIZE];
+ int row, col, key, clo=0,chi=0,r1,c1,r2,c2;
+ Tcl_HashEntry *entryPtr;
+
+ if (objc < 4 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "all|<first> ?<last>?");
+ return TCL_ERROR;
+ }
+ if (STREQ(Tcl_GetString(objv[3]), "all")) {
+ Tcl_HashSearch search;
+ for(entryPtr = Tcl_FirstHashEntry(tablePtr->selCells, &search);
+ entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {
+ TableParseArrayIndex(&row, &col,
+ Tcl_GetHashKey(tablePtr->selCells,entryPtr));
+ Tcl_DeleteHashEntry(entryPtr);
+ TableRefresh(tablePtr, row-tablePtr->rowOffset,
+ col-tablePtr->colOffset, CELL);
+ }
+ return TCL_OK;
+ }
+ if (TableGetIndexObj(tablePtr, objv[3], &row, &col) == TCL_ERROR ||
+ (objc==5 &&
+ TableGetIndexObj(tablePtr, objv[4], &r2, &c2) == TCL_ERROR)) {
+ return TCL_ERROR;
+ }
+ key = 0;
+ if (objc == 4) {
+ r1 = r2 = row;
+ c1 = c2 = col;
+ } else {
+ r1 = MIN(row,r2); r2 = MAX(row,r2);
+ c1 = MIN(col,c2); c2 = MAX(col,c2);
+ }
+ switch (tablePtr->selectType) {
+ case SEL_BOTH:
+ clo = c1; chi = c2;
+ c1 = tablePtr->colOffset;
+ c2 = tablePtr->cols-1+c1;
+ key = 1;
+ goto CLEAR_CELLS;
+ CLEAR_BOTH:
+ key = 0;
+ c1 = clo; c2 = chi;
+ case SEL_COL:
+ r1 = tablePtr->rowOffset;
+ r2 = tablePtr->rows-1+r1;
+ break;
+ case SEL_ROW:
+ c1 = tablePtr->colOffset;
+ c2 = tablePtr->cols-1+c1;
+ break;
+ }
+ /* row/col are in user index coords */
+CLEAR_CELLS:
+ for ( row = r1; row <= r2; row++ ) {
+ for ( col = c1; col <= c2; col++ ) {
+ TableMakeArrayIndex(row, col, buf1);
+ entryPtr = Tcl_FindHashEntry(tablePtr->selCells, buf1);
+ if (entryPtr != NULL) {
+ Tcl_DeleteHashEntry(entryPtr);
+ TableRefresh(tablePtr, row-tablePtr->rowOffset,
+ col-tablePtr->colOffset, CELL);
+ }
+ }
+ }
+ if (key) goto CLEAR_BOTH;
+ return result;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_SelIncludesCmd --
+ * This procedure is invoked to process the selection includes method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_SelIncludesCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ int row, col;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ return TCL_ERROR;
+ } else if (TableGetIndexObj(tablePtr, objv[3], &row, &col) == TCL_ERROR) {
+ return TCL_ERROR;
+ } else {
+ char buf[INDEX_BUFSIZE];
+ TableMakeArrayIndex(row, col, buf);
+ Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
+ (Tcl_FindHashEntry(tablePtr->selCells, buf)!=NULL));
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_SelSetCmd --
+ * This procedure is invoked to process the selection set method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_SelSetCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ int row, col, dummy, key;
+ char buf1[INDEX_BUFSIZE];
+ Tcl_HashSearch search;
+ Tcl_HashEntry *entryPtr;
+
+ int clo=0, chi=0, r1, c1, r2, c2, firstRow, firstCol, lastRow, lastCol;
+ if (objc < 4 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "first ?last?");
+ return TCL_ERROR;
+ }
+ if (TableGetIndexObj(tablePtr, objv[3], &row, &col) == TCL_ERROR ||
+ (objc==5 &&
+ TableGetIndexObj(tablePtr, objv[4], &r2, &c2) == TCL_ERROR)) {
+ return TCL_ERROR;
+ }
+ key = 0;
+ lastRow = tablePtr->rows-1+tablePtr->rowOffset;
+ lastCol = tablePtr->cols-1+tablePtr->colOffset;
+ if (tablePtr->selectTitles) {
+ firstRow = tablePtr->rowOffset;
+ firstCol = tablePtr->colOffset;
+ } else {
+ firstRow = tablePtr->titleRows+tablePtr->rowOffset;
+ firstCol = tablePtr->titleCols+tablePtr->colOffset;
+ }
+ /* maintain appropriate user index */
+ CONSTRAIN(row, firstRow, lastRow);
+ CONSTRAIN(col, firstCol, lastCol);
+ if (objc == 4) {
+ r1 = r2 = row;
+ c1 = c2 = col;
+ } else {
+ CONSTRAIN(r2, firstRow, lastRow);
+ CONSTRAIN(c2, firstCol, lastCol);
+ r1 = MIN(row,r2); r2 = MAX(row,r2);
+ c1 = MIN(col,c2); c2 = MAX(col,c2);
+ }
+ switch (tablePtr->selectType) {
+ case SEL_BOTH:
+ if (firstCol > lastCol) c2--; /* No selectable columns in table */
+ if (firstRow > lastRow) r2--; /* No selectable rows in table */
+ clo = c1; chi = c2;
+ c1 = firstCol;
+ c2 = lastCol;
+ key = 1;
+ goto SET_CELLS;
+ SET_BOTH:
+ key = 0;
+ c1 = clo; c2 = chi;
+ case SEL_COL:
+ r1 = firstRow;
+ r2 = lastRow;
+ if (firstCol > lastCol) c2--; /* No selectable columns in table */
+ break;
+ case SEL_ROW:
+ c1 = firstCol;
+ c2 = lastCol;
+ if (firstRow>lastRow) r2--; /* No selectable rows in table */
+ break;
+ }
+SET_CELLS:
+ entryPtr = Tcl_FirstHashEntry(tablePtr->selCells, &search);
+ for ( row = r1; row <= r2; row++ ) {
+ for ( col = c1; col <= c2; col++ ) {
+ TableMakeArrayIndex(row, col, buf1);
+ if (Tcl_FindHashEntry(tablePtr->selCells, buf1) == NULL) {
+ Tcl_CreateHashEntry(tablePtr->selCells, buf1, &dummy);
+ TableRefresh(tablePtr, row-tablePtr->rowOffset,
+ col-tablePtr->colOffset, CELL);
+ }
+ }
+ }
+ if (key) goto SET_BOTH;
+
+ /* Adjust the table for top left, selection on screen etc */
+ TableAdjustParams(tablePtr);
+
+ /* If the table was previously empty and we want to export the
+ * selection, we should grab it now */
+ if (entryPtr == NULL && tablePtr->exportSelection) {
+ Tk_OwnSelection(tablePtr->tkwin, XA_PRIMARY, TableLostSelection,
+ (ClientData) tablePtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_ViewCmd --
+ * This procedure is invoked to process the x|yview method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_ViewCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ int row, col, value;
+ char *xy;
+
+ /* Check xview or yview */
+ if (objc > 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?args?");
+ return TCL_ERROR;
+ }
+ xy = Tcl_GetString(objv[1]);
+
+ if (objc == 2) {
+ Tcl_Obj *resultPtr;
+ int diff, x, y, w, h;
+ double first, last;
+
+ resultPtr = Tcl_GetObjResult(interp);
+ TableGetLastCell(tablePtr, &row, &col);
+ TableCellVCoords(tablePtr, row, col, &x, &y, &w, &h, 0);
+ if (*xy == 'y') {
+ if (row < tablePtr->titleRows) {
+ first = 0;
+ last = 1;
+ } else {
+ diff = tablePtr->rowStarts[tablePtr->titleRows];
+ last = (double) (tablePtr->rowStarts[tablePtr->rows]-diff);
+ first = (tablePtr->rowStarts[tablePtr->topRow]-diff) / last;
+ last = (h+tablePtr->rowStarts[row]-diff) / last;
+ }
+ } else {
+ if (col < tablePtr->titleCols) {
+ first = 0;
+ last = 1;
+ } else {
+ diff = tablePtr->colStarts[tablePtr->titleCols];
+ last = (double) (tablePtr->colStarts[tablePtr->cols]-diff);
+ first = (tablePtr->colStarts[tablePtr->leftCol]-diff) / last;
+ last = (w+tablePtr->colStarts[col]-diff) / last;
+ }
+ }
+ Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewDoubleObj(first));
+ Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewDoubleObj(last));
+ } else {
+ /* cache old topleft to see if it changes */
+ int oldTop = tablePtr->topRow, oldLeft = tablePtr->leftCol;
+
+ if (objc == 3) {
+ if (Tcl_GetIntFromObj(interp, objv[2], &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (*xy == 'y') {
+ tablePtr->topRow = value + tablePtr->titleRows;
+ } else {
+ tablePtr->leftCol = value + tablePtr->titleCols;
+ }
+ } else {
+ int result;
+ double frac;
+#if (TK_MINOR_VERSION > 0) /* 8.1+ */
+ result = Tk_GetScrollInfoObj(interp, objc, objv, &frac, &value);
+#else
+ int i;
+ char **argv = (char **) ckalloc((objc + 1) * sizeof(char *));
+ for (i = 0; i < objc; i++) {
+ argv[i] = Tcl_GetString(objv[i]);
+ }
+ argv[i] = NULL;
+ result = Tk_GetScrollInfo(interp, objc, argv, &frac, &value);
+ ckfree ((char *) argv);
+#endif
+ switch (result) {
+ case TK_SCROLL_ERROR:
+ return TCL_ERROR;
+ case TK_SCROLL_MOVETO:
+ if (frac < 0) frac = 0;
+ if (*xy == 'y') {
+ tablePtr->topRow = (int)(frac*tablePtr->rows)
+ +tablePtr->titleRows;
+ } else {
+ tablePtr->leftCol = (int)(frac*tablePtr->cols)
+ +tablePtr->titleCols;
+ }
+ break;
+ case TK_SCROLL_PAGES:
+ TableGetLastCell(tablePtr, &row, &col);
+ if (*xy == 'y') {
+ tablePtr->topRow += value * (row-tablePtr->topRow+1);
+ } else {
+ tablePtr->leftCol += value * (col-tablePtr->leftCol+1);
+ }
+ break;
+ case TK_SCROLL_UNITS:
+ if (*xy == 'y') {
+ tablePtr->topRow += value;
+ } else {
+ tablePtr->leftCol += value;
+ }
+ break;
+ }
+ }
+ /* maintain appropriate real index */
+ CONSTRAIN(tablePtr->topRow, tablePtr->titleRows, tablePtr->rows-1);
+ CONSTRAIN(tablePtr->leftCol, tablePtr->titleCols, tablePtr->cols-1);
+ /* Do the table adjustment if topRow || leftCol changed */
+ if (oldTop != tablePtr->topRow || oldLeft != tablePtr->leftCol) {
+ TableAdjustParams(tablePtr);
+ }
+ }
+
+ return TCL_OK;
+}
+
+#if 0
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_Cmd --
+ * This procedure is invoked to process the CMD method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_Cmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ int result = TCL_OK;
+
+ return result;
+}
+#endif
diff --git a/libgui/src/tkTableEdit.c b/libgui/src/tkTableEdit.c
new file mode 100644
index 00000000000..3fd6d4879b0
--- /dev/null
+++ b/libgui/src/tkTableEdit.c
@@ -0,0 +1,683 @@
+/*
+ * tkTableEdit.c --
+ *
+ * This module implements editing functions of a table widget.
+ *
+ * Copyright (c) 1998-2000 Jeffrey Hobbs
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#include "tkTable.h"
+
+static void TableModifyRC _ANSI_ARGS_((register Table *tablePtr,
+ int doRows, int movetag,
+ Tcl_HashTable *tagTblPtr, Tcl_HashTable *dimTblPtr,
+ int offset, int from, int to, int lo, int hi,
+ int outOfBounds));
+
+/* insert/delete subcommands */
+static char *modCmdNames[] = {
+ "active", "cols", "rows", (char *)NULL
+};
+enum modCmd {
+ MOD_ACTIVE, MOD_COLS, MOD_ROWS
+};
+
+/* insert/delete row/col switches */
+static char *rcCmdNames[] = {
+ "-keeptitles", "-holddimensions", "-holdselection",
+ "-holdtags", "-holdwindows", "--",
+ (char *) NULL
+};
+enum rcCmd {
+ OPT_TITLES, OPT_DIMS, OPT_SEL,
+ OPT_TAGS, OPT_WINS, OPT_LAST
+};
+
+#define HOLD_TITLES 1<<0
+#define HOLD_DIMS 1<<1
+#define HOLD_TAGS 1<<2
+#define HOLD_WINS 1<<3
+#define HOLD_SEL 1<<4
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_EditCmd --
+ * This procedure is invoked to process the insert/delete method
+ * that corresponds to a table widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_EditCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *) clientData;
+ int doInsert, cmdIndex, first, last;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "option ?switches? arg ?arg?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[2], modCmdNames,
+ "option", 0, &cmdIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ doInsert = (*(Tcl_GetString(objv[1])) == 'i');
+ switch ((enum modCmd) cmdIndex) {
+ case MOD_ACTIVE:
+ if (doInsert) {
+ /* INSERT */
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index string");
+ return TCL_ERROR;
+ }
+ if (TableGetIcursorObj(tablePtr, objv[3], &first) != TCL_OK) {
+ return TCL_ERROR;
+ } else if ((tablePtr->flags & HAS_ACTIVE) &&
+ !(tablePtr->flags & ACTIVE_DISABLED) &&
+ tablePtr->state == STATE_NORMAL) {
+ TableInsertChars(tablePtr, first, Tcl_GetString(objv[4]));
+ }
+ } else {
+ /* DELETE */
+ if (objc > 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "first ?last?");
+ return TCL_ERROR;
+ }
+ if (TableGetIcursorObj(tablePtr, objv[3], &first) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc == 4) {
+ last = first+1;
+ } else if (TableGetIcursorObj(tablePtr, objv[4],
+ &last) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((last >= first) && (tablePtr->flags & HAS_ACTIVE) &&
+ !(tablePtr->flags & ACTIVE_DISABLED) &&
+ tablePtr->state == STATE_NORMAL) {
+ TableDeleteChars(tablePtr, first, last-first);
+ }
+ }
+ break; /* EDIT ACTIVE */
+
+ case MOD_COLS:
+ case MOD_ROWS: {
+ /*
+ * ROW/COL INSERTION/DELETION
+ * FIX: This doesn't handle spans
+ */
+ int i, lo, hi, argsLeft, offset, minkeyoff, doRows;
+ int maxrow, maxcol, maxkey, minkey, flags, count, *dimPtr;
+ Tcl_HashTable *tagTblPtr, *dimTblPtr;
+ Tcl_HashSearch search;
+
+ doRows = (cmdIndex == MOD_ROWS);
+ flags = 0;
+ for (i = 3; i < objc; i++) {
+ if (*(Tcl_GetString(objv[i])) != '-') {
+ break;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[i], rcCmdNames,
+ "switch", 0, &cmdIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (cmdIndex == OPT_LAST) {
+ i++;
+ break;
+ }
+ switch (cmdIndex) {
+ case OPT_TITLES:
+ flags |= HOLD_TITLES;
+ break;
+ case OPT_DIMS:
+ flags |= HOLD_DIMS;
+ break;
+ case OPT_SEL:
+ flags |= HOLD_SEL;
+ break;
+ case OPT_TAGS:
+ flags |= HOLD_TAGS;
+ break;
+ case OPT_WINS:
+ flags |= HOLD_WINS;
+ break;
+ }
+ }
+ argsLeft = objc - i;
+ if (argsLeft < 1 || argsLeft > 2) {
+ Tcl_WrongNumArgs(interp, 3, objv, "?switches? index ?count?");
+ return TCL_ERROR;
+ }
+
+ count = 1;
+ maxcol = tablePtr->cols-1+tablePtr->colOffset;
+ maxrow = tablePtr->rows-1+tablePtr->rowOffset;
+ if (strcmp(Tcl_GetString(objv[i]), "end") == 0) {
+ /* allow "end" to be specified as an index */
+ first = (doRows) ? maxrow : maxcol;
+ } else if (Tcl_GetIntFromObj(interp, objv[i], &first) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (argsLeft == 2 &&
+ Tcl_GetIntFromObj(interp, objv[++i], &count) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (count == 0 || (tablePtr->state == STATE_DISABLED)) {
+ return TCL_OK;
+ }
+
+ if (doRows) {
+ maxkey = maxrow;
+ minkey = tablePtr->rowOffset;
+ minkeyoff = tablePtr->rowOffset+tablePtr->titleRows;
+ offset = tablePtr->rowOffset;
+ tagTblPtr = tablePtr->rowStyles;
+ dimTblPtr = tablePtr->rowHeights;
+ dimPtr = &(tablePtr->rows);
+ lo = tablePtr->colOffset
+ + ((flags & HOLD_TITLES) ? tablePtr->titleCols : 0);
+ hi = maxcol;
+ } else {
+ maxkey = maxcol;
+ minkey = tablePtr->colOffset;
+ minkeyoff = tablePtr->colOffset+tablePtr->titleCols;
+ offset = tablePtr->colOffset;
+ tagTblPtr = tablePtr->colStyles;
+ dimTblPtr = tablePtr->colWidths;
+ dimPtr = &(tablePtr->cols);
+ lo = tablePtr->rowOffset
+ + ((flags & HOLD_TITLES) ? tablePtr->titleRows : 0);
+ hi = maxrow;
+ }
+
+ /* constrain the starting index */
+ if (first > maxkey) {
+ first = maxkey;
+ } else if (first < minkey) {
+ first = minkey;
+ }
+ if (doInsert) {
+ /* +count means insert after index,
+ * -count means insert before index */
+ if (count < 0) {
+ count = -count;
+ } else {
+ first++;
+ }
+ if ((flags & HOLD_TITLES) && (first < minkeyoff)) {
+ count -= minkeyoff-first;
+ if (count <= 0) {
+ return TCL_OK;
+ }
+ first = minkeyoff;
+ }
+ if (!(flags & HOLD_DIMS)) {
+ maxkey += count;
+ *dimPtr += count;
+ }
+ for (i = maxkey; i >= first; i--) {
+ /* move row/col style && width/height here */
+ TableModifyRC(tablePtr, doRows, flags, tagTblPtr, dimTblPtr,
+ offset, i, i-count, lo, hi, ((i-count) < first));
+ }
+ } else {
+ /* (index = i && count = 1) == (index = i && count = -1) */
+ if (count < 0) {
+ /* if the count is negative, make sure that the col count will
+ * delete no greater than the original index */
+ if (first+count < minkey) {
+ if (first-minkey < abs(count)) {
+ /*
+ * In this case, the user is asking to delete more rows
+ * than exist before the minkey, so we have to shrink
+ * the count down to the existing rows up to index.
+ */
+ count = first-minkey;
+ } else {
+ count += first-minkey;
+ }
+ first = minkey;
+ } else {
+ first += count;
+ count = -count;
+ }
+ }
+ if ((flags & HOLD_TITLES) && (first <= minkeyoff)) {
+ count -= minkeyoff-first;
+ if (count <= 0) {
+ return TCL_OK;
+ }
+ first = minkeyoff;
+ }
+ if (count > maxkey-first+1) {
+ count = maxkey-first+1;
+ }
+ if (!(flags & HOLD_DIMS)) {
+ *dimPtr -= count;
+ }
+ for (i = first; i <= maxkey; i++) {
+ TableModifyRC(tablePtr, doRows, flags, tagTblPtr, dimTblPtr,
+ offset, i, i+count, lo, hi, ((i+count) > maxkey));
+ }
+ }
+ if (!(flags & HOLD_SEL) &&
+ Tcl_FirstHashEntry(tablePtr->selCells, &search) != NULL) {
+ /* clear selection - forceful, but effective */
+ Tcl_DeleteHashTable(tablePtr->selCells);
+ Tcl_InitHashTable(tablePtr->selCells, TCL_STRING_KEYS);
+ }
+
+ /*
+ * Make sure that the modified dimension is actually legal
+ * after removing all that stuff.
+ */
+ *dimPtr = MAX(1, *dimPtr);
+
+ TableAdjustParams(tablePtr);
+ /* change the geometry */
+ TableGeometryRequest(tablePtr);
+ /* FIX:
+ * This has to handle when the previous rows/cols resize because
+ * of the *stretchmode. InvalidateAll does that, but could be
+ * more efficient.
+ */
+ TableInvalidateAll(tablePtr, 0);
+ break;
+ }
+
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableDeleteChars --
+ * Remove one or more characters from an table widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory gets freed, the table gets modified and (eventually)
+ * redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TableDeleteChars(tablePtr, index, count)
+ register Table *tablePtr; /* Table widget to modify. */
+ int index; /* Index of first character to delete. */
+ int count; /* How many characters to delete. */
+{
+#ifdef TCL_UTF_MAX
+ int byteIndex, byteCount, newByteCount, numBytes, numChars;
+ char *new, *string;
+
+ string = tablePtr->activeBuf;
+ numBytes = strlen(string);
+ numChars = Tcl_NumUtfChars(string, numBytes);
+ if ((index + count) > numChars) {
+ count = numChars - index;
+ }
+ if (count <= 0) {
+ return;
+ }
+
+ byteIndex = Tcl_UtfAtIndex(string, index) - string;
+ byteCount = Tcl_UtfAtIndex(string + byteIndex, count)
+ - (string + byteIndex);
+
+ newByteCount = numBytes + 1 - byteCount;
+ new = (char *) ckalloc((unsigned) newByteCount);
+ memcpy(new, string, (size_t) byteIndex);
+ strcpy(new + byteIndex, string + byteIndex + byteCount);
+#else
+ int oldlen;
+ char *new;
+
+ /* this gets the length of the string, as well as ensuring that
+ * the cursor isn't beyond the end char */
+ TableGetIcursor(tablePtr, "end", &oldlen);
+
+ if ((index+count) > oldlen)
+ count = oldlen-index;
+ if (count <= 0)
+ return;
+
+ new = (char *) ckalloc((unsigned)(oldlen-count+1));
+ strncpy(new, tablePtr->activeBuf, (size_t) index);
+ strcpy(new+index, tablePtr->activeBuf+index+count);
+ /* make sure this string is null terminated */
+ new[oldlen-count] = '\0';
+#endif
+ /* This prevents deletes on BREAK or validation error. */
+ if (tablePtr->validate &&
+ TableValidateChange(tablePtr, tablePtr->activeRow+tablePtr->rowOffset,
+ tablePtr->activeCol+tablePtr->colOffset,
+ tablePtr->activeBuf, new, index) != TCL_OK) {
+ ckfree(new);
+ return;
+ }
+
+ ckfree(tablePtr->activeBuf);
+ tablePtr->activeBuf = new;
+
+ /* mark the text as changed */
+ tablePtr->flags |= TEXT_CHANGED;
+
+ if (tablePtr->icursor >= index) {
+ if (tablePtr->icursor >= (index+count)) {
+ tablePtr->icursor -= count;
+ } else {
+ tablePtr->icursor = index;
+ }
+ }
+
+ TableSetActiveIndex(tablePtr);
+
+ TableRefresh(tablePtr, tablePtr->activeRow, tablePtr->activeCol, CELL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableInsertChars --
+ * Add new characters to the active cell of a table widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * New information gets added to tablePtr; it will be redisplayed
+ * soon, but not necessarily immediately.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TableInsertChars(tablePtr, index, value)
+ register Table *tablePtr; /* Table that is to get the new elements. */
+ int index; /* Add the new elements before this element. */
+ char *value; /* New characters to add (NULL-terminated
+ * string). */
+{
+#ifdef TCL_UTF_MAX
+ int oldlen, byteIndex, byteCount;
+ char *new, *string;
+
+ byteCount = strlen(value);
+ if (byteCount == 0) {
+ return;
+ }
+
+ /* Is this an autoclear and this is the first update */
+ /* Note that this clears without validating */
+ if (tablePtr->autoClear && !(tablePtr->flags & TEXT_CHANGED)) {
+ /* set the buffer to be empty */
+ tablePtr->activeBuf = (char *)ckrealloc(tablePtr->activeBuf, 1);
+ tablePtr->activeBuf[0] = '\0';
+ /* the insert position now has to be 0 */
+ index = 0;
+ tablePtr->icursor = 0;
+ }
+
+ string = tablePtr->activeBuf;
+ byteIndex = Tcl_UtfAtIndex(string, index) - string;
+
+ oldlen = strlen(string);
+ new = (char *) ckalloc((unsigned)(oldlen + byteCount + 1));
+ memcpy(new, string, (size_t) byteIndex);
+ strcpy(new + byteIndex, value);
+ strcpy(new + byteIndex + byteCount, string + byteIndex);
+
+ /* validate potential new active buffer */
+ /* This prevents inserts on either BREAK or validation error. */
+ if (tablePtr->validate &&
+ TableValidateChange(tablePtr, tablePtr->activeRow+tablePtr->rowOffset,
+ tablePtr->activeCol+tablePtr->colOffset,
+ tablePtr->activeBuf, new, byteIndex) != TCL_OK) {
+ ckfree(new);
+ return;
+ }
+
+ /*
+ * The following construction is used because inserting improperly
+ * formed UTF-8 sequences between other improperly formed UTF-8
+ * sequences could result in actually forming valid UTF-8 sequences;
+ * the number of characters added may not be Tcl_NumUtfChars(string, -1),
+ * because of context. The actual number of characters added is how
+ * many characters were are in the string now minus the number that
+ * used to be there.
+ */
+
+ if (tablePtr->icursor >= index) {
+ tablePtr->icursor += Tcl_NumUtfChars(new, oldlen+byteCount)
+ - Tcl_NumUtfChars(tablePtr->activeBuf, oldlen);
+ }
+
+ ckfree(string);
+ tablePtr->activeBuf = new;
+
+#else
+ int oldlen, newlen;
+ char *new;
+
+ newlen = strlen(value);
+ if (newlen == 0) return;
+
+ /* Is this an autoclear and this is the first update */
+ /* Note that this clears without validating */
+ if (tablePtr->autoClear && !(tablePtr->flags & TEXT_CHANGED)) {
+ /* set the buffer to be empty */
+ tablePtr->activeBuf = (char *)ckrealloc(tablePtr->activeBuf, 1);
+ tablePtr->activeBuf[0] = '\0';
+ /* the insert position now has to be 0 */
+ index = 0;
+ }
+ oldlen = strlen(tablePtr->activeBuf);
+ /* get the buffer to at least the right length */
+ new = (char *) ckalloc((unsigned)(oldlen+newlen+1));
+ strncpy(new, tablePtr->activeBuf, (size_t) index);
+ strcpy(new+index, value);
+ strcpy(new+index+newlen, (tablePtr->activeBuf)+index);
+ /* make sure this string is null terminated */
+ new[oldlen+newlen] = '\0';
+
+ /* validate potential new active buffer */
+ /* This prevents inserts on either BREAK or validation error. */
+ if (tablePtr->validate &&
+ TableValidateChange(tablePtr, tablePtr->activeRow+tablePtr->rowOffset,
+ tablePtr->activeCol+tablePtr->colOffset,
+ tablePtr->activeBuf, new, index) != TCL_OK) {
+ ckfree(new);
+ return;
+ }
+ ckfree(tablePtr->activeBuf);
+ tablePtr->activeBuf = new;
+
+ if (tablePtr->icursor >= index) {
+ tablePtr->icursor += newlen;
+ }
+#endif
+
+ /* mark the text as changed */
+ tablePtr->flags |= TEXT_CHANGED;
+
+ TableSetActiveIndex(tablePtr);
+
+ TableRefresh(tablePtr, tablePtr->activeRow, tablePtr->activeCol, CELL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableModifyRC --
+ * Helper function that does the core work of moving rows/cols
+ * and associated tags.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Moves cell data and possibly tag data
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+TableModifyRC(tablePtr, doRows, flags, tagTblPtr, dimTblPtr,
+ offset, from, to, lo, hi, outOfBounds)
+ Table *tablePtr; /* Information about text widget. */
+ int doRows; /* rows (1) or cols (0) */
+ int flags; /* flags indicating what to move */
+ Tcl_HashTable *tagTblPtr, *dimTblPtr; /* Pointers to the row/col tags
+ * and width/height tags */
+ int offset; /* appropriate offset */
+ int from, to; /* the from and to row/col */
+ int lo, hi; /* the lo and hi col/row */
+ int outOfBounds; /* the boundary check for shifting items */
+{
+ int j, new;
+ char buf[INDEX_BUFSIZE], buf1[INDEX_BUFSIZE];
+ Tcl_HashEntry *entryPtr, *newPtr;
+ TableEmbWindow *ewPtr;
+
+ /*
+ * move row/col style && width/height here
+ * If -holdtags is specified, we don't move the user-set widths/heights
+ * of the absolute rows/columns, otherwise we enter here to move the
+ * dimensions appropriately
+ */
+ if (!(flags & HOLD_TAGS)) {
+ entryPtr = Tcl_FindHashEntry(tagTblPtr, (char *)from);
+ if (entryPtr != NULL) {
+ Tcl_DeleteHashEntry(entryPtr);
+ }
+ entryPtr = Tcl_FindHashEntry(dimTblPtr, (char *)from-offset);
+ if (entryPtr != NULL) {
+ Tcl_DeleteHashEntry(entryPtr);
+ }
+ if (!outOfBounds) {
+ entryPtr = Tcl_FindHashEntry(tagTblPtr, (char *)to);
+ if (entryPtr != NULL) {
+ newPtr = Tcl_CreateHashEntry(tagTblPtr, (char *)from, &new);
+ Tcl_SetHashValue(newPtr, Tcl_GetHashValue(entryPtr));
+ Tcl_DeleteHashEntry(entryPtr);
+ }
+ entryPtr = Tcl_FindHashEntry(dimTblPtr, (char *)to-offset);
+ if (entryPtr != NULL) {
+ newPtr = Tcl_CreateHashEntry(dimTblPtr, (char *)from-offset,
+ &new);
+ Tcl_SetHashValue(newPtr, Tcl_GetHashValue(entryPtr));
+ Tcl_DeleteHashEntry(entryPtr);
+ }
+ }
+ }
+ for (j = lo; j <= hi; j++) {
+ if (doRows /* rows */) {
+ TableMakeArrayIndex(from, j, buf);
+ TableMakeArrayIndex(to, j, buf1);
+ TableMoveCellValue(tablePtr, to, j, buf1, from, j, buf,
+ outOfBounds);
+ } else {
+ TableMakeArrayIndex(j, from, buf);
+ TableMakeArrayIndex(j, to, buf1);
+ TableMoveCellValue(tablePtr, j, to, buf1, j, from, buf,
+ outOfBounds);
+ }
+ /*
+ * If -holdselection is specified, we leave the selected cells in the
+ * absolute cell values, otherwise we enter here to move the
+ * selection appropriately
+ */
+ if (!(flags & HOLD_SEL)) {
+ entryPtr = Tcl_FindHashEntry(tablePtr->selCells, buf);
+ if (entryPtr != NULL) {
+ Tcl_DeleteHashEntry(entryPtr);
+ }
+ if (!outOfBounds) {
+ entryPtr = Tcl_FindHashEntry(tablePtr->selCells, buf1);
+ if (entryPtr != NULL) {
+ Tcl_CreateHashEntry(tablePtr->selCells, buf, &new);
+ Tcl_DeleteHashEntry(entryPtr);
+ }
+ }
+ }
+ /*
+ * If -holdtags is specified, we leave the tags in the
+ * absolute cell values, otherwise we enter here to move the
+ * tags appropriately
+ */
+ if (!(flags & HOLD_TAGS)) {
+ entryPtr = Tcl_FindHashEntry(tablePtr->cellStyles, buf);
+ if (entryPtr != NULL) {
+ Tcl_DeleteHashEntry(entryPtr);
+ }
+ if (!outOfBounds) {
+ entryPtr = Tcl_FindHashEntry(tablePtr->cellStyles, buf1);
+ if (entryPtr != NULL) {
+ newPtr = Tcl_CreateHashEntry(tablePtr->cellStyles, buf,
+ &new);
+ Tcl_SetHashValue(newPtr, Tcl_GetHashValue(entryPtr));
+ Tcl_DeleteHashEntry(entryPtr);
+ }
+ }
+ }
+ /*
+ * If -holdwindows is specified, we leave the windows in the
+ * absolute cell values, otherwise we enter here to move the
+ * windows appropriately
+ */
+ if (!(flags & HOLD_WINS)) {
+ /*
+ * Delete whatever window might be in our destination
+ */
+ Table_WinDelete(tablePtr, buf);
+ if (!outOfBounds) {
+ /*
+ * buf1 is where the window is
+ * buf is where we want it to be
+ *
+ * This is an adaptation of Table_WinMove, which we can't
+ * use because we are intermediately fiddling with boundaries
+ */
+ entryPtr = Tcl_FindHashEntry(tablePtr->winTable, buf1);
+ if (entryPtr != NULL) {
+ /*
+ * If there was a window in our source,
+ * get the window pointer to move it
+ */
+ ewPtr = (TableEmbWindow *) Tcl_GetHashValue(entryPtr);
+ /* and free the old hash table entry */
+ Tcl_DeleteHashEntry(entryPtr);
+
+ entryPtr = Tcl_CreateHashEntry(tablePtr->winTable, buf,
+ &new);
+ /*
+ * We needn't check if a window was in buf, since the
+ * Table_WinDelete above should guarantee that no window
+ * is there. Just set the new entry's value.
+ */
+ Tcl_SetHashValue(entryPtr, (ClientData) ewPtr);
+ ewPtr->hPtr = entryPtr;
+ }
+ }
+ }
+ }
+}
diff --git a/libgui/src/tkTableInitScript.h b/libgui/src/tkTableInitScript.h
new file mode 100644
index 00000000000..1084717757b
--- /dev/null
+++ b/libgui/src/tkTableInitScript.h
@@ -0,0 +1,90 @@
+/*
+ * tkTableInitScript.h --
+ *
+ * This file contains common init script for tkTable
+ *
+ * Copyright (c) 1998 Jeffrey Hobbs
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+/*
+ * The following string is the startup script executed when the table is
+ * loaded. It looks on disk in several different directories for a script
+ * "TBL_RUNTIME" (as defined in Makefile) that is compatible with this
+ * version of tkTable. The sourced script has all key bindings defined.
+ */
+
+static char tkTableInitScript[] = "if {[info proc tkTableInit]==\"\"} {\n\
+ proc tkTableInit {} {\n\
+ global tk_library tcl_pkgPath errorInfo env\n\
+ rename tkTableInit {}\n\
+ set errors {}\n\
+ if {![info exists env(TK_TABLE_LIBRARY_FILE)]} {\n\
+ set env(TK_TABLE_LIBRARY_FILE) " TBL_RUNTIME "\n\
+ }\n\
+ if {[info exists env(TK_TABLE_LIBRARY)]} {\n\
+ lappend dirs $env(TK_TABLE_LIBRARY)\n\
+ }\n\
+ lappend dirs " TBL_RUNTIME_DIR "\n\
+ if {[info exists tcl_pkgPath]} {\n\
+ foreach i $tcl_pkgPath {\n\
+ lappend dirs [file join $i Tktable" TBL_VERSION "] \\\n\
+ [file join $i Tktable] $i\n\
+ }\n\
+ }\n\
+ lappend dirs $tk_library [pwd]\n\
+ foreach i $dirs {\n\
+ set try [file join $i $env(TK_TABLE_LIBRARY_FILE)]\n\
+ if {[file exists $try]} {\n\
+ if {![catch {uplevel #0 [list source $try]} msg]} {\n\
+ set env(TK_TABLE_LIBRARY) $i\n\
+ return\n\
+ } else {\n\
+ append errors \"$try: $msg\n$errorInfo\n\"\n\
+ }\n\
+ }\n\
+ }\n"
+#ifdef NO_EMBEDDED_RUNTIME
+" set msg \"Can't find a $env(TK_TABLE_LIBRARY_FILE) in the following directories: \n\"\n\
+ append msg \" $dirs\n\n$errors\n\n\"\n\
+ append msg \"This probably means that TkTable wasn't installed properly.\"\n\
+ return -code error $msg\n"
+#else
+" set env(TK_TABLE_LIBRARY) EMBEDDED_RUNTIME\n"
+# ifdef MAC_TCL
+" source -rsrc tkTable"
+# else
+" uplevel #0 {"
+# include "tkTable.tcl.h"
+" }"
+# endif
+#endif
+" }\n\
+}\n\
+tkTableInit";
+
+/*
+ * The init script can't make certain calls in a safe interpreter,
+ * so we always have to use the embedded runtime for it
+ */
+static char tkTableSafeInitScript[] = "if {[info proc tkTableInit]==\"\"} {\n\
+ proc tkTableInit {} {\n\
+ set env(TK_TABLE_LIBRARY) EMBEDDED_RUNTIME\n"
+#ifdef NO_EMBEDDED_RUNTIME
+" append msg \"tkTable requires embedded runtime to be compiled for\"\n\
+ append msg \" use in safe interpreters\"\n\
+ return -code error $msg\n"
+#endif
+# ifdef MAC_TCL
+" source -rsrc tkTable"
+# else
+" uplevel #0 {"
+# include "tkTable.tcl.h"
+" }"
+# endif
+" }\n\
+}\n\
+tkTableInit";
+
diff --git a/libgui/src/tkTablePs.c b/libgui/src/tkTablePs.c
new file mode 100644
index 00000000000..018f0791ec3
--- /dev/null
+++ b/libgui/src/tkTablePs.c
@@ -0,0 +1,1299 @@
+/*
+ * tkTablePs.c --
+ *
+ * This module implements postscript output for table widgets.
+ * Based off of Tk8.1a2 tkCanvPs.c.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * changes 1998 Copyright (c) 1998 Jeffrey Hobbs
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ */
+
+#include "tkTable.h"
+
+/* This is for Tcl_DStringAppendAll */
+#if defined(__STDC__) || defined(HAS_STDARG)
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifndef TCL_INTEGER_SPACE
+/* This appears in 8.1 */
+#define TCL_INTEGER_SPACE 24
+#endif
+
+/*
+ * One of the following structures is created to keep track of Postscript
+ * output being generated. It consists mostly of information provided on
+ * the widget command line.
+ */
+
+typedef struct TkPostscriptInfo {
+ int x, y, width, height; /* Area to print, in table pixel
+ * coordinates. */
+ int x2, y2; /* x+width and y+height. */
+ char *pageXString; /* String value of "-pagex" option or NULL. */
+ char *pageYString; /* String value of "-pagey" option or NULL. */
+ double pageX, pageY; /* Postscript coordinates (in points)
+ * corresponding to pageXString and
+ * pageYString. Don't forget that y-values
+ * grow upwards for Postscript! */
+ char *pageWidthString; /* Printed width of output. */
+ char *pageHeightString; /* Printed height of output. */
+ double scale; /* Scale factor for conversion: each pixel
+ * maps into this many points. */
+ Tk_Anchor pageAnchor; /* How to anchor bbox on Postscript page. */
+ int rotate; /* Non-zero means output should be rotated
+ * on page (landscape mode). */
+ char *fontVar; /* If non-NULL, gives name of global variable
+ * containing font mapping information.
+ * Malloc'ed. */
+ char *colorVar; /* If non-NULL, give name of global variable
+ * containing color mapping information.
+ * Malloc'ed. */
+ char *colorMode; /* Mode for handling colors: "monochrome",
+ * "gray", or "color". Malloc'ed. */
+ int colorLevel; /* Numeric value corresponding to colorMode:
+ * 0 for mono, 1 for gray, 2 for color. */
+ char *fileName; /* Name of file in which to write Postscript;
+ * NULL means return Postscript info as
+ * result. Malloc'ed. */
+ char *channelName; /* If -channel is specified, the name of
+ * the channel to use. */
+ Tcl_Channel chan; /* Open channel corresponding to fileName. */
+ Tcl_HashTable fontTable; /* Hash table containing names of all font
+ * families used in output. The hash table
+ * values are not used. */
+ char *first, *last; /* table indices to start and end at */
+} TkPostscriptInfo;
+
+/*
+ * The table below provides a template that's used to process arguments
+ * to the table "postscript" command and fill in TkPostscriptInfo
+ * structures.
+ */
+
+static Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_STRING, "-colormap", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, colorVar), 0},
+ {TK_CONFIG_STRING, "-colormode", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, colorMode), 0},
+ {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, fileName), 0},
+ {TK_CONFIG_STRING, "-channel", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, channelName), 0},
+ {TK_CONFIG_STRING, "-first", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, first), 0},
+ {TK_CONFIG_STRING, "-fontmap", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, fontVar), 0},
+ {TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, height), 0},
+ {TK_CONFIG_STRING, "-last", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, last), 0},
+ {TK_CONFIG_ANCHOR, "-pageanchor", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, pageAnchor), 0},
+ {TK_CONFIG_STRING, "-pageheight", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, pageHeightString), 0},
+ {TK_CONFIG_STRING, "-pagewidth", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, pageWidthString), 0},
+ {TK_CONFIG_STRING, "-pagex", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, pageXString), 0},
+ {TK_CONFIG_STRING, "-pagey", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, pageYString), 0},
+ {TK_CONFIG_BOOLEAN, "-rotate", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, rotate), 0},
+ {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, width), 0},
+ {TK_CONFIG_PIXELS, "-x", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, x), 0},
+ {TK_CONFIG_PIXELS, "-y", (char *) NULL, (char *) NULL, "",
+ Tk_Offset(TkPostscriptInfo, y), 0},
+ {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, 0}
+};
+
+/*
+ * The prolog data. Generated by str2c from prolog.ps
+ * This was split in small chunks by str2c because
+ * some C compiler have limitations on the size of static strings.
+ * (str2c is a small tcl script in tcl's tool directory (source release))
+ */
+/*
+ * This is a stripped down version of that found in tkCanvPs.c of Tk8.1a2.
+ * Comments, and stuff pertaining to stipples and other unused entities
+ * have been removed
+ */
+static CONST char * CONST prolog[]= {
+ /* Start of part 1 */
+ "%%BeginProlog\n\
+50 dict begin\n\
+\n\
+% This is standard prolog for Postscript generated by Tk's table widget.\n\
+% Based of standard prolog for Tk's canvas widget.\n\
+\n\
+% INITIALIZING VARIABLES\n\
+\n\
+/baseline 0 def\n\
+/height 0 def\n\
+/justify 0 def\n\
+/cellHeight 0 def\n\
+/cellWidth 0 def\n\
+/spacing 0 def\n\
+/strings 0 def\n\
+/xoffset 0 def\n\
+/yoffset 0 def\n\
+/x 0 def\n\
+/y 0 def\n\
+\n\
+% Define the array ISOLatin1Encoding, if it isn't already present.\n\
+\n\
+systemdict /ISOLatin1Encoding known not {\n\
+ /ISOLatin1Encoding [\n\
+ /space /space /space /space /space /space /space /space\n\
+ /space /space /space /space /space /space /space /space\n\
+ /space /space /space /space /space /space /space /space\n\
+ /space /space /space /space /space /space /space /space\n\
+ /space /exclam /quotedbl /numbersign /dollar /percent /ampersand\n\
+ /quoteright\n\
+ /parenleft /parenright /asterisk /plus /comma /minus /period /slash\n\
+ /zero /one /two /three /four /five /six /seven\n\
+ /eight /nine /colon /semicolon /less /equal /greater /question\n\
+ /at /A /B /C /D /E /F /G\n\
+ /H /I /J /K /L /M /N /O\n\
+ /P /Q /R /S /T /U /V /W\n\
+ /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore\n\
+ /quoteleft /a /b /c /d /e /f /g\n\
+ /h /i /j /k /l /m /n /o\n\
+ /p /q /r /s /t /u /v /w\n\
+ /x /y /z /braceleft /bar /braceright /asciitilde /space\n\
+ /space /space /space /space /space /space /space /space\n\
+ /space /space /space /space /space /space /space /space\n\
+ /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent\n\
+ /dieresis /space /ring /cedilla /space /hungarumlaut /ogonek /caron\n\
+ /space /exclamdown /cent /sterling /currency /yen /brokenbar /section\n\
+ /dieresis /copyright /ordfem",
+
+ "inine /guillemotleft /logicalnot /hyphen\n\
+ /registered /macron\n\
+ /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph\n\
+ /periodcentered\n\
+ /cedillar /onesuperior /ordmasculine /guillemotright /onequarter\n\
+ /onehalf /threequarters /questiondown\n\
+ /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla\n\
+ /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex\n\
+ /Idieresis\n\
+ /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply\n\
+ /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn\n\
+ /germandbls\n\
+ /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla\n\
+ /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex\n\
+ /idieresis\n\
+ /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide\n\
+ /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn\n\
+ /ydieresis\n\
+ ] def\n\
+} if\n",
+
+ "\n\
+% font ISOEncode font\n\
+% This procedure changes the encoding of a font from the default\n\
+% Postscript encoding to ISOLatin1. It's typically invoked just\n\
+% before invoking \"setfont\". The body of this procedure comes from\n\
+% Section 5.6.1 of the Postscript book.\n\
+\n\
+/ISOEncode {\n\
+ dup length dict begin\n\
+ {1 index /FID ne {def} {pop pop} ifelse} forall\n\
+ /Encoding ISOLatin1Encoding def\n\
+ currentdict\n\
+ end\n\
+\n\
+ % I'm not sure why it's necessary to use \"definefont\" on this new\n\
+ % font, but it seems to be important; just use the name \"Temporary\"\n\
+ % for the font.\n\
+\n\
+ /Temporary exch definefont\n\
+} bind def\n\
+\n\
+% -- AdjustColor --\n\
+% Given a color value already set for output by the caller, adjusts\n\
+% that value to a grayscale or mono value if requested by the CL variable.\n\
+\n\
+/AdjustColor {\n\
+ setrgbcolor\n\
+ CL 2 lt {\n\
+ currentgray\n\
+ CL 0 eq {\n\
+ .5 lt {0} {1} ifelse\n\
+ } if\n\
+ setgray\n\
+ } if\n\
+} bind def\n\
+\n\
+% pointSize fontName SetFont\n\
+% The ISOEncode shouldn't be done to Symbol fonts...\n\
+/SetFont {\n\
+ findfont exch scalefont ISOEncode setfont\n\
+} def\n\
+\n",
+
+ "% x y strings spacing xoffset yoffset justify ... DrawText --\n\
+% This procedure does all of the real work of drawing text. The\n\
+% color and font must already have been set by the caller, and the\n\
+% following arguments must be on the stack:\n\
+%\n\
+% x, y - Coordinates at which to draw text.\n\
+% strings - An array of strings, one for each line of the text item,\n\
+% in order from top to bottom.\n\
+% spacing - Spacing between lines.\n\
+% xoffset - Horizontal offset for text bbox relative to x and y: 0 for\n\
+% nw/w/sw anchor, -0.5 for n/center/s, and -1.0 for ne/e/se.\n\
+% yoffset - Vertical offset for text bbox relative to x and y: 0 for\n\
+% nw/n/ne anchor, +0.5 for w/center/e, and +1.0 for sw/s/se.\n\
+% justify - 0 for left justification, 0.5 for center, 1 for right justify.\n\
+% cellWidth - width for this cell\n\
+% cellHeight - height for this cell\n\
+%\n\
+% Also, when this procedure is invoked, the color and font must already\n\
+% have been set for the text.\n\
+\n",
+
+ "/DrawCellText {\n\
+ /cellHeight exch def\n\
+ /cellWidth exch def\n\
+ /justify exch def\n\
+ /yoffset exch def\n\
+ /xoffset exch def\n\
+ /spacing exch def\n\
+ /strings exch def\n\
+ /y exch def\n\
+ /x exch def\n\
+\n\
+ % Compute the baseline offset and the actual font height.\n\
+\n\
+ 0 0 moveto (TXygqPZ) false charpath\n\
+ pathbbox dup /baseline exch def\n\
+ exch pop exch sub /height exch def pop\n\
+ newpath\n\
+\n\
+ % Translate coordinates first so that the origin is at the upper-left\n\
+ % corner of the text's bounding box. Remember that x and y for\n\
+ % positioning are still on the stack.\n\
+\n\
+ col0 x sub row0 y sub translate\n\
+ cellWidth xoffset mul\n\
+ strings length 1 sub spacing mul height add yoffset mul translate\n\
+\n\
+ % Now use the baseline and justification information to translate so\n\
+ % that the origin is at the baseline and positioning point for the\n\
+ % first line of text.\n\
+\n\
+ justify cellWidth mul baseline neg translate\n\
+\n\
+ % Iterate over each of the lines to output it. For each line,\n\
+ % compute its width again so it can be properly justified, then\n\
+ % display it.\n\
+\n\
+ strings {\n\
+ dup stringwidth pop\n\
+ justify neg mul 0 moveto\n\
+ show\n\
+ 0 spacing neg translate\n\
+ } forall\n\
+} bind def\n\
+\n",
+
+ "%\n\
+% x, y - Coordinates at which to draw text.\n\
+% strings - An array of strings, one for each line of the text item,\n\
+% in order from top to bottom.\n\
+% spacing - Spacing between lines.\n\
+% xoffset - Horizontal offset for text bbox relative to x and y: 0 for\n\
+% nw/w/sw anchor, -0.5 for n/center/s, and -1.0 for ne/e/se.\n\
+% yoffset - Vertical offset for text bbox relative to x and y: 0 for\n\
+% nw/n/ne anchor, +0.5 for w/center/e, and +1.0 for sw/s/se.\n\
+% justify - 0 for left justification, 0.5 for center, 1 for right justify.\n\
+% cellWidth - width for this cell\n\
+% cellHeight - height for this cell\n\
+%\n\
+% Also, when this procedure is invoked, the color and font must already\n\
+% have been set for the text.\n\
+\n\
+/DrawCellTextOld {\n\
+ /cellHeight exch def\n\
+ /cellWidth exch def\n\
+ /justify exch def\n\
+ /yoffset exch def\n\
+ /xoffset exch def\n\
+ /spacing exch def\n\
+ /strings exch def\n\
+\n\
+ % Compute the baseline offset and the actual font height.\n\
+\n\
+ 0 0 moveto (TXygqPZ) false charpath\n\
+ pathbbox dup /baseline exch def\n\
+ exch pop exch sub /height exch def pop\n\
+ newpath\n\
+\n\
+ % Translate coordinates first so that the origin is at the upper-left\n\
+ % corner of the text's bounding box. Remember that x and y for\n\
+ % positioning are still on the stack.\n\
+\n\
+ translate\n\
+ cellWidth xoffset mul\n\
+ strings length 1 sub spacing mul height add yoffset mul translate\n\
+\n\
+ % Now use the baseline and justification information to translate so\n\
+ % that the origin is at the baseline and positioning point for the\n\
+ % first line of text.\n\
+\n\
+ justify cellWidth mul baseline neg translate\n\
+\n\
+ % Iterate over each of the lines to output it. For each line,\n\
+ % compute its width again so it can be properly justified, then\n\
+ % display it.\n\
+\n\
+ strings {\n\
+ dup stringwidth pop\n\
+ justify neg mul 0 moveto\n\
+ show\n\
+ 0 spacing neg translate\n\
+ } forall\n\
+} bind def\n\
+\n\
+%%EndProlog\n\
+",
+ /* End of part 5 */
+
+ NULL /* End of data marker */
+};
+
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static int GetPostscriptPoints _ANSI_ARGS_((Tcl_Interp *interp,
+ char *string, double *doublePtr));
+int Tk_TablePsFont _ANSI_ARGS_((Tcl_Interp *interp,
+ Table *tablePtr, Tk_Font tkfont));
+int Tk_TablePsColor _ANSI_ARGS_((Tcl_Interp *interp,
+ Table *tablePtr, XColor *colorPtr));
+static int TextToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
+ Table *tablePtr, TableTag *tagPtr, int tagX, int tagY,
+ int width, int height, int row, int col,
+ Tk_TextLayout textLayout));
+
+/*
+ * Tcl could really use some more convenience routines...
+ * This is just Tcl_DStringAppend for multiple lines, including
+ * the full text of each line
+ */
+void
+Tcl_DStringAppendAll TCL_VARARGS_DEF(Tcl_DString *, arg1)
+{
+ va_list argList;
+ Tcl_DString *dstringPtr;
+ char *string;
+
+ dstringPtr = TCL_VARARGS_START(Tcl_DString *, arg1, argList);
+ while ((string = va_arg(argList, char *)) != NULL) {
+ Tcl_DStringAppend(dstringPtr, string, -1);
+ }
+ va_end(argList);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_PostscriptCmd --
+ *
+ * This procedure is invoked to process the "postscript" options
+ * of the widget command for table widgets. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+int
+Table_PostscriptCmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Information about table widget. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of argument objects. */
+ Tcl_Obj *CONST objv[];
+{
+#ifdef _WIN32
+ /*
+ * At the moment, it just doesn't like this code...
+ */
+ return TCL_OK;
+#else
+ register Table *tablePtr = (Table *) clientData;
+ TkPostscriptInfo psInfo, *oldInfoPtr;
+ int result;
+ int row, col, firstRow, firstCol, lastRow, lastCol;
+ /* dimensions of first and last cell to output */
+ int x0, y0, w0, h0, xn, yn, wn, hn;
+ int x, y, w, h, i;
+#define STRING_LENGTH 400
+ char string[STRING_LENGTH+1], *p, **argv;
+ size_t length;
+ int deltaX = 0, deltaY = 0; /* Offset of lower-left corner of area to
+ * be marked up, measured in table units
+ * from the positioning point on the page
+ * (reflects anchor position). Initial
+ * values needed only to stop compiler
+ * warnings. */
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hPtr;
+ CONST char * CONST *chunk;
+ Tk_TextLayout textLayout = NULL;
+ char *value;
+ int rowHeight, total, *colWidths, iW, iH;
+ TableTag *tagPtr, *colPtr, *rowPtr, *titlePtr;
+ Tcl_DString postscript, buffer;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?option value ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ *----------------------------------------------------------------
+ * Initialize the data structure describing Postscript generation,
+ * then process all the arguments to fill the data structure in.
+ *----------------------------------------------------------------
+ */
+
+ Tcl_DStringInit(&postscript);
+ Tcl_DStringInit(&buffer);
+ oldInfoPtr = tablePtr->psInfoPtr;
+ tablePtr->psInfoPtr = &psInfo;
+ /* This is where in the window that we start printing from */
+ psInfo.x = 0;
+ psInfo.y = 0;
+ psInfo.width = -1;
+ psInfo.height = -1;
+ psInfo.pageXString = NULL;
+ psInfo.pageYString = NULL;
+ psInfo.pageX = 72*4.25;
+ psInfo.pageY = 72*5.5;
+ psInfo.pageWidthString = NULL;
+ psInfo.pageHeightString = NULL;
+ psInfo.scale = 1.0;
+ psInfo.pageAnchor = TK_ANCHOR_CENTER;
+ psInfo.rotate = 0;
+ psInfo.fontVar = NULL;
+ psInfo.colorVar = NULL;
+ psInfo.colorMode = NULL;
+ psInfo.colorLevel = 0;
+ psInfo.fileName = NULL;
+ psInfo.channelName = NULL;
+ psInfo.chan = NULL;
+ psInfo.first = NULL;
+ psInfo.last = NULL;
+ Tcl_InitHashTable(&psInfo.fontTable, TCL_STRING_KEYS);
+
+ /*
+ * The magic StringifyObjects
+ */
+ argv = (char **) ckalloc((objc + 1) * sizeof(char *));
+ for (i = 0; i < objc; i++)
+ argv[i] = Tcl_GetString(objv[i]);
+ argv[i] = NULL;
+
+ result = Tk_ConfigureWidget(interp, tablePtr->tkwin, configSpecs,
+ objc-2, argv+2, (char *) &psInfo,
+ TK_CONFIG_ARGV_ONLY);
+ if (result != TCL_OK) {
+ goto cleanup;
+ }
+
+ if (psInfo.first == NULL) {
+ firstRow = 0;
+ firstCol = 0;
+ } else if (TableGetIndex(tablePtr, psInfo.first, &firstRow, &firstCol)
+ != TCL_OK) {
+ result = TCL_ERROR;
+ goto cleanup;
+ }
+ if (psInfo.last == NULL) {
+ lastRow = tablePtr->rows-1;
+ lastCol = tablePtr->cols-1;
+ } else if (TableGetIndex(tablePtr, psInfo.last, &lastRow, &lastCol)
+ != TCL_OK) {
+ result = TCL_ERROR;
+ goto cleanup;
+ }
+
+ if (psInfo.fileName != NULL) {
+ /* Check that -file and -channel are not both specified. */
+ if (psInfo.channelName != NULL) {
+ Tcl_AppendResult(interp, "can't specify both -file",
+ " and -channel", (char *) NULL);
+ result = TCL_ERROR;
+ goto cleanup;
+ }
+
+ /*
+ * Check that we are not in a safe interpreter. If we are, disallow
+ * the -file specification.
+ */
+ if (Tcl_IsSafe(interp)) {
+ Tcl_AppendResult(interp, "can't specify -file in a",
+ " safe interpreter", (char *) NULL);
+ result = TCL_ERROR;
+ goto cleanup;
+ }
+
+ p = Tcl_TranslateFileName(interp, psInfo.fileName, &buffer);
+ if (p == NULL) {
+ result = TCL_ERROR;
+ goto cleanup;
+ }
+ psInfo.chan = Tcl_OpenFileChannel(interp, p, "w", 0666);
+ Tcl_DStringFree(&buffer);
+ Tcl_DStringInit(&buffer);
+ if (psInfo.chan == NULL) {
+ result = TCL_ERROR;
+ goto cleanup;
+ }
+ }
+
+ if (psInfo.channelName != NULL) {
+ int mode;
+ /*
+ * Check that the channel is found in this interpreter and that it
+ * is open for writing.
+ */
+ psInfo.chan = Tcl_GetChannel(interp, psInfo.channelName, &mode);
+ if (psInfo.chan == (Tcl_Channel) NULL) {
+ result = TCL_ERROR;
+ goto cleanup;
+ }
+ if ((mode & TCL_WRITABLE) == 0) {
+ Tcl_AppendResult(interp, "channel \"", psInfo.channelName,
+ "\" wasn't opened for writing", (char *) NULL);
+ result = TCL_ERROR;
+ goto cleanup;
+ }
+ }
+
+ if (psInfo.colorMode == NULL) {
+ psInfo.colorLevel = 2;
+ } else {
+ length = strlen(psInfo.colorMode);
+ if (strncmp(psInfo.colorMode, "monochrome", length) == 0) {
+ psInfo.colorLevel = 0;
+ } else if (strncmp(psInfo.colorMode, "gray", length) == 0) {
+ psInfo.colorLevel = 1;
+ } else if (strncmp(psInfo.colorMode, "color", length) == 0) {
+ psInfo.colorLevel = 2;
+ } else {
+ Tcl_AppendResult(interp, "bad color mode \"", psInfo.colorMode,
+ "\": must be monochrome, gray or color", (char *) NULL);
+ goto cleanup;
+ }
+ }
+
+ TableCellCoords(tablePtr, firstRow, firstCol, &x0, &y0, &w0, &h0);
+ TableCellCoords(tablePtr, lastRow, lastCol, &xn, &yn, &wn, &hn);
+ psInfo.x = x0;
+ psInfo.y = y0;
+ if (psInfo.width == -1) {
+ psInfo.width = xn+wn;
+ }
+ if (psInfo.height == -1) {
+ psInfo.height = yn+hn;
+ }
+ psInfo.x2 = psInfo.x + psInfo.width;
+ psInfo.y2 = psInfo.y + psInfo.height;
+
+ if (psInfo.pageXString != NULL) {
+ if (GetPostscriptPoints(interp, psInfo.pageXString,
+ &psInfo.pageX) != TCL_OK) {
+ goto cleanup;
+ }
+ }
+ if (psInfo.pageYString != NULL) {
+ if (GetPostscriptPoints(interp, psInfo.pageYString,
+ &psInfo.pageY) != TCL_OK) {
+ goto cleanup;
+ }
+ }
+ if (psInfo.pageWidthString != NULL) {
+ if (GetPostscriptPoints(interp, psInfo.pageWidthString,
+ &psInfo.scale) != TCL_OK) {
+ goto cleanup;
+ }
+ psInfo.scale /= psInfo.width;
+ } else if (psInfo.pageHeightString != NULL) {
+ if (GetPostscriptPoints(interp, psInfo.pageHeightString,
+ &psInfo.scale) != TCL_OK) {
+ goto cleanup;
+ }
+ psInfo.scale /= psInfo.height;
+ } else {
+ psInfo.scale = (72.0/25.4)*WidthMMOfScreen(Tk_Screen(tablePtr->tkwin))
+ / WidthOfScreen(Tk_Screen(tablePtr->tkwin));
+ }
+ switch (psInfo.pageAnchor) {
+ case TK_ANCHOR_NW:
+ case TK_ANCHOR_W:
+ case TK_ANCHOR_SW:
+ deltaX = 0;
+ break;
+ case TK_ANCHOR_N:
+ case TK_ANCHOR_CENTER:
+ case TK_ANCHOR_S:
+ deltaX = -psInfo.width/2;
+ break;
+ case TK_ANCHOR_NE:
+ case TK_ANCHOR_E:
+ case TK_ANCHOR_SE:
+ deltaX = -psInfo.width;
+ break;
+ }
+ switch (psInfo.pageAnchor) {
+ case TK_ANCHOR_NW:
+ case TK_ANCHOR_N:
+ case TK_ANCHOR_NE:
+ deltaY = - psInfo.height;
+ break;
+ case TK_ANCHOR_W:
+ case TK_ANCHOR_CENTER:
+ case TK_ANCHOR_E:
+ deltaY = -psInfo.height/2;
+ break;
+ case TK_ANCHOR_SW:
+ case TK_ANCHOR_S:
+ case TK_ANCHOR_SE:
+ deltaY = 0;
+ break;
+ }
+
+ /*
+ *--------------------------------------------------------
+ * Make a PREPASS over all of the tags
+ * to collect information about all the fonts in use, so that
+ * we can output font information in the proper form required
+ * by the Document Structuring Conventions.
+ *--------------------------------------------------------
+ */
+
+ Tk_TablePsFont(interp, tablePtr, tablePtr->defaultTag.tkfont);
+ Tcl_ResetResult(interp);
+ for (hPtr = Tcl_FirstHashEntry(tablePtr->tagTable, &search);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ tagPtr = (TableTag *) Tcl_GetHashValue(hPtr);
+ if (tagPtr->tkfont != NULL) {
+ Tk_TablePsFont(interp, tablePtr, tagPtr->tkfont);
+ }
+ }
+ Tcl_ResetResult(interp);
+
+ /*
+ *--------------------------------------------------------
+ * Generate the header and prolog for the Postscript.
+ *--------------------------------------------------------
+ */
+
+ sprintf(string, " %d,%d => %d,%d\n", firstRow, firstCol, lastRow, lastCol);
+ Tcl_DStringAppendAll(&postscript,
+ "%!PS-Adobe-3.0 EPSF-3.0\n",
+ "%%Creator: Tk Table Widget ", TBL_VERSION, "\n",
+ "%%Title: Window ",
+ Tk_PathName(tablePtr->tkwin), string,
+ "%%BoundingBox: ",
+ (char *) NULL);
+ if (!psInfo.rotate) {
+ sprintf(string, "%d %d %d %d\n",
+ (int) (psInfo.pageX + psInfo.scale*deltaX),
+ (int) (psInfo.pageY + psInfo.scale*deltaY),
+ (int) (psInfo.pageX + psInfo.scale*(deltaX + psInfo.width)
+ + 1.0),
+ (int) (psInfo.pageY + psInfo.scale*(deltaY + psInfo.height)
+ + 1.0));
+ } else {
+ sprintf(string, "%d %d %d %d\n",
+ (int) (psInfo.pageX - psInfo.scale*(deltaY + psInfo.height)),
+ (int) (psInfo.pageY + psInfo.scale*deltaX),
+ (int) (psInfo.pageX - psInfo.scale*deltaY + 1.0),
+ (int) (psInfo.pageY + psInfo.scale*(deltaX + psInfo.width)
+ + 1.0));
+ }
+ Tcl_DStringAppendAll(&postscript, string,
+ "%%Pages: 1\n%%DocumentData: Clean7Bit\n",
+ "%%Orientation: ",
+ psInfo.rotate?"Landscape\n":"Portrait\n",
+ (char *) NULL);
+ p = "%%DocumentNeededResources: font ";
+ for (hPtr = Tcl_FirstHashEntry(&psInfo.fontTable, &search);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ sprintf(string, "%s%s\n", p, Tcl_GetHashKey(&psInfo.fontTable, hPtr));
+ Tcl_DStringAppend(&postscript, string, -1);
+ p = "%%+ font ";
+ }
+ Tcl_DStringAppend(&postscript, "%%EndComments\n\n", -1);
+
+ /*
+ * Insert the prolog
+ */
+ for (chunk=prolog; *chunk; chunk++) {
+ Tcl_DStringAppend(&postscript, *chunk, -1);
+ }
+
+ if (psInfo.chan != NULL) {
+ Tcl_Write(psInfo.chan, Tcl_DStringValue(&postscript), -1);
+ Tcl_DStringFree(&postscript);
+ Tcl_DStringInit(&postscript);
+ }
+
+ /*
+ * Document setup: set the color level and include fonts.
+ * This is where we start using &postscript
+ */
+
+ sprintf(string, "/CL %d def\n", psInfo.colorLevel);
+ Tcl_DStringAppendAll(&postscript, "%%BeginSetup\n", string, (char *) NULL);
+ for (hPtr = Tcl_FirstHashEntry(&psInfo.fontTable, &search);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ sprintf(string, "%s%s\n", "%%IncludeResource: font ",
+ Tcl_GetHashKey(&psInfo.fontTable, hPtr));
+ Tcl_DStringAppend(&postscript, string, -1);
+ }
+ Tcl_DStringAppend(&postscript, "%%EndSetup\n\n", -1);
+
+ /*
+ * Page setup: move to page positioning point, rotate if
+ * needed, set scale factor, offset for proper anchor position,
+ * and set clip region.
+ */
+
+ sprintf(string, "%.1f %.1f translate\n",
+ psInfo.pageX, psInfo.pageY);
+ Tcl_DStringAppendAll(&postscript, "%%Page: 1 1\nsave\n",
+ string, psInfo.rotate?"90 rotate\n":"",
+ (char *) NULL);
+ sprintf(string, "%.4g %.4g scale\n%d %d translate\n",
+ psInfo.scale, psInfo.scale, deltaX - psInfo.x, deltaY);
+ Tcl_DStringAppend(&postscript, string, -1);
+ sprintf(string, "%d %.15g moveto %d %.15g lineto %d %.15g lineto %d %.15g",
+ psInfo.x, (double) psInfo.y2-psInfo.y,
+ psInfo.x2,(double) psInfo.y2-psInfo.y,
+ psInfo.x2, 0.0, psInfo.x, 0.0);
+ Tcl_DStringAppend(&postscript, string, -1);
+ Tcl_DStringAppend(&postscript, " lineto closepath clip newpath\n", -1);
+ if (psInfo.chan != NULL) {
+ Tcl_Write(psInfo.chan, Tcl_DStringValue(&postscript), -1);
+ Tcl_DStringFree(&postscript);
+ Tcl_DStringInit(&postscript);
+ }
+
+ /*
+ * Go through each cell, calculating full desired height
+ */
+ result = TCL_OK;
+
+ hPtr = Tcl_FindHashEntry(tablePtr->tagTable, "title");
+ titlePtr = (TableTag *) Tcl_GetHashValue(hPtr);
+
+ total = 0;
+ colWidths = (int *) ckalloc((lastCol-firstCol) * sizeof(int));
+ for (col = 0; col <= lastCol-firstCol; col++) colWidths[col] = 0;
+ Tcl_DStringAppend(&buffer, "gsave\n", -1);
+ for (row = firstRow; row <= lastRow; row++) {
+ rowHeight = 0;
+ rowPtr = FindRowColTag(tablePtr, row+tablePtr->rowOffset, ROW);
+ for (col = firstCol; col <= lastCol; col++) {
+ /* get the coordinates for the cell */
+ TableCellCoords(tablePtr, row, col, &x, &y, &w, &h);
+ if ((x >= psInfo.x2) || (x+w < psInfo.x) ||
+ (y >= psInfo.y2) || (y+h < psInfo.y)) {
+ continue;
+ }
+
+ if (row == tablePtr->activeRow && col == tablePtr->activeCol) {
+ value = tablePtr->activeBuf;
+ } else {
+ value = TableGetCellValue(tablePtr, row+tablePtr->rowOffset,
+ col+tablePtr->colOffset);
+ }
+ if (!strlen(value)) {
+ continue;
+ }
+
+ /* Create the tag here */
+ tagPtr = TableNewTag();
+ /* First, merge in the default tag */
+ TableMergeTag(tagPtr, &(tablePtr->defaultTag));
+
+ colPtr = FindRowColTag(tablePtr, col+tablePtr->colOffset, COL);
+ if (colPtr != (TableTag *) NULL) TableMergeTag(tagPtr, colPtr);
+ if (rowPtr != (TableTag *) NULL) TableMergeTag(tagPtr, rowPtr);
+ /* Am I in the titles */
+ if (row < tablePtr->topRow || col < tablePtr->leftCol) {
+ TableMergeTag(tagPtr, titlePtr);
+ }
+ /* Does this have a cell tag */
+ TableMakeArrayIndex(row+tablePtr->rowOffset,
+ col+tablePtr->colOffset, string);
+ hPtr = Tcl_FindHashEntry(tablePtr->cellStyles, string);
+ if (hPtr != NULL) {
+ TableMergeTag(tagPtr, (TableTag *) Tcl_GetHashValue(hPtr));
+ }
+
+ /*
+ * the use of -1 instead of Tcl_NumUtfChars means we don't
+ * pass NULLs to postscript
+ */
+ textLayout = Tk_ComputeTextLayout(tagPtr->tkfont, value, -1,
+ (tagPtr->wrap>0) ? w : 0,
+ tagPtr->justify,
+ (tagPtr->multiline>0) ? 0 :
+ TK_IGNORE_NEWLINES, &iW, &iH);
+
+ rowHeight = MAX(rowHeight, iH);
+ colWidths[col-firstCol] = MAX(colWidths[col-firstCol], iW);
+
+ result = TextToPostscript(interp, tablePtr, tagPtr,
+ x, y, iW, iH, row, col, textLayout);
+ Tk_FreeTextLayout(textLayout);
+ if (result != TCL_OK) {
+ char msg[64 + TCL_INTEGER_SPACE];
+
+ sprintf(msg, "\n (generating Postscript for cell %s)",
+ string);
+ Tcl_AddErrorInfo(interp, msg);
+ goto cleanup;
+ }
+ Tcl_DStringAppend(&buffer, Tcl_GetStringResult(interp), -1);
+ }
+ sprintf(string, "/row%d %d def\n",
+ row, tablePtr->psInfoPtr->y2 - total);
+ Tcl_DStringAppend(&postscript, string, -1);
+ total += rowHeight + 2*tablePtr->defaultTag.bd;
+ }
+ Tcl_DStringAppend(&buffer, "grestore\n", -1);
+ sprintf(string, "/row%d %d def\n", row, tablePtr->psInfoPtr->y2 - total);
+ Tcl_DStringAppend(&postscript, string, -1);
+
+ total = tablePtr->defaultTag.bd;
+ for (col = firstCol; col <= lastCol; col++) {
+ sprintf(string, "/col%d %d def\n", col, total);
+ Tcl_DStringAppend(&postscript, string, -1);
+ total += colWidths[col-firstCol] + 2*tablePtr->defaultTag.bd;
+ }
+ sprintf(string, "/col%d %d def\n", col, total);
+ Tcl_DStringAppend(&postscript, string, -1);
+
+ Tcl_DStringAppend(&postscript, Tcl_DStringValue(&buffer), -1);
+
+ /*
+ * Output to channel at the end of it all
+ * This should more incremental, but that can't be avoided in order
+ * to post-define width/height of the cols/rows
+ */
+ if (psInfo.chan != NULL) {
+ Tcl_Write(psInfo.chan, Tcl_DStringValue(&postscript), -1);
+ Tcl_DStringFree(&postscript);
+ Tcl_DStringInit(&postscript);
+ }
+
+ /*
+ *---------------------------------------------------------------------
+ * Output page-end information, such as commands to print the page
+ * and document trailer stuff.
+ *---------------------------------------------------------------------
+ */
+
+ Tcl_DStringAppend(&postscript,
+ "restore showpage\n\n%%Trailer\nend\n%%EOF\n", -1);
+ if (psInfo.chan != NULL) {
+ Tcl_Write(psInfo.chan, Tcl_DStringValue(&postscript), -1);
+ Tcl_DStringFree(&postscript);
+ Tcl_DStringInit(&postscript);
+ }
+
+ /*
+ * Clean up psInfo to release malloc'ed stuff.
+ */
+
+cleanup:
+ ckfree((char *) argv);
+ Tcl_DStringResult(interp, &postscript);
+ Tcl_DStringFree(&postscript);
+ Tcl_DStringFree(&buffer);
+ if (psInfo.first != NULL) {
+ ckfree(psInfo.first);
+ }
+ if (psInfo.last != NULL) {
+ ckfree(psInfo.last);
+ }
+ if (psInfo.pageXString != NULL) {
+ ckfree(psInfo.pageXString);
+ }
+ if (psInfo.pageYString != NULL) {
+ ckfree(psInfo.pageYString);
+ }
+ if (psInfo.pageWidthString != NULL) {
+ ckfree(psInfo.pageWidthString);
+ }
+ if (psInfo.pageHeightString != NULL) {
+ ckfree(psInfo.pageHeightString);
+ }
+ if (psInfo.fontVar != NULL) {
+ ckfree(psInfo.fontVar);
+ }
+ if (psInfo.colorVar != NULL) {
+ ckfree(psInfo.colorVar);
+ }
+ if (psInfo.colorMode != NULL) {
+ ckfree(psInfo.colorMode);
+ }
+ if (psInfo.fileName != NULL) {
+ ckfree(psInfo.fileName);
+ }
+ if ((psInfo.chan != NULL) && (psInfo.channelName == NULL)) {
+ Tcl_Close(interp, psInfo.chan);
+ }
+ if (psInfo.channelName != NULL) {
+ ckfree(psInfo.channelName);
+ }
+ Tcl_DeleteHashTable(&psInfo.fontTable);
+ tablePtr->psInfoPtr = oldInfoPtr;
+ return result;
+#endif
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_TablePsColor --
+ *
+ * This procedure is called by individual table items when
+ * they want to set a color value for output. Given information
+ * about an X color, this procedure will generate Postscript
+ * commands to set up an appropriate color in Postscript.
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs
+ * then an error message will be left in the interp's result.
+ * If no error occurs, then additional Postscript will be
+ * appended to the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_TablePsColor(interp, tablePtr, colorPtr)
+ Tcl_Interp *interp; /* Interpreter for returning Postscript
+ * or error message. */
+ Table *tablePtr; /* Information about table. */
+ XColor *colorPtr; /* Information about color. */
+{
+ TkPostscriptInfo *psInfoPtr = tablePtr->psInfoPtr;
+ int tmp;
+ double red, green, blue;
+ char string[200];
+
+ /*
+ * If there is a color map defined, then look up the color's name
+ * in the map and use the Postscript commands found there, if there
+ * are any.
+ */
+
+ if (psInfoPtr->colorVar != NULL) {
+ char *cmdString;
+
+ cmdString = Tcl_GetVar2(interp, psInfoPtr->colorVar,
+ Tk_NameOfColor(colorPtr), 0);
+ if (cmdString != NULL) {
+ Tcl_AppendResult(interp, cmdString, "\n", (char *) NULL);
+ return TCL_OK;
+ }
+ }
+
+ /*
+ * No color map entry for this color. Grab the color's intensities
+ * and output Postscript commands for them. Special note: X uses
+ * a range of 0-65535 for intensities, but most displays only use
+ * a range of 0-255, which maps to (0, 256, 512, ... 65280) in the
+ * X scale. This means that there's no way to get perfect white,
+ * since the highest intensity is only 65280 out of 65535. To
+ * work around this problem, rescale the X intensity to a 0-255
+ * scale and use that as the basis for the Postscript colors. This
+ * scheme still won't work if the display only uses 4 bits per color,
+ * but most diplays use at least 8 bits.
+ */
+
+ tmp = colorPtr->red;
+ red = ((double) (tmp >> 8))/255.0;
+ tmp = colorPtr->green;
+ green = ((double) (tmp >> 8))/255.0;
+ tmp = colorPtr->blue;
+ blue = ((double) (tmp >> 8))/255.0;
+ sprintf(string, "%.3f %.3f %.3f AdjustColor\n",
+ red, green, blue);
+ Tcl_AppendResult(interp, string, (char *) NULL);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_TablePsFont --
+ *
+ * This procedure is called by individual table items when
+ * they want to output text. Given information about an X
+ * font, this procedure will generate Postscript commands
+ * to set up an appropriate font in Postscript.
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs
+ * then an error message will be left in the interp's result.
+ * If no error occurs, then additional Postscript will be
+ * appended to the interp's result.
+ *
+ * Side effects:
+ * The Postscript font name is entered into psInfoPtr->fontTable
+ * if it wasn't already there.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_TablePsFont(interp, tablePtr, tkfont)
+ Tcl_Interp *interp; /* Interpreter for returning Postscript
+ * or error message. */
+ Table *tablePtr; /* Information about table. */
+ Tk_Font tkfont; /* Information about font in which text
+ * is to be printed. */
+{
+ TkPostscriptInfo *psInfoPtr = tablePtr->psInfoPtr;
+ char *end;
+ char pointString[TCL_INTEGER_SPACE];
+ Tcl_DString ds;
+ int i, points;
+
+ /*
+ * First, look up the font's name in the font map, if there is one.
+ * If there is an entry for this font, it consists of a list
+ * containing font name and size. Use this information.
+ */
+
+ Tcl_DStringInit(&ds);
+
+ if (psInfoPtr->fontVar != NULL) {
+ char *list, **argv;
+ int objc;
+ double size;
+ char *name;
+
+ name = Tk_NameOfFont(tkfont);
+ list = Tcl_GetVar2(interp, psInfoPtr->fontVar, name, 0);
+ if (list != NULL) {
+ if (Tcl_SplitList(interp, list, &objc, &argv) != TCL_OK) {
+ badMapEntry:
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad font map entry for \"", name,
+ "\": \"", list, "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (objc != 2) {
+ goto badMapEntry;
+ }
+ size = strtod(argv[1], &end);
+ if ((size <= 0) || (*end != 0)) {
+ goto badMapEntry;
+ }
+
+ Tcl_DStringAppend(&ds, argv[0], -1);
+ points = (int) size;
+
+ ckfree((char *) argv);
+ goto findfont;
+ }
+ }
+
+ points = Tk_PostscriptFontName(tkfont, &ds);
+
+findfont:
+ sprintf(pointString, "%d", points);
+ Tcl_AppendResult(interp, pointString, " /", Tcl_DStringValue(&ds),
+ " SetFont\n", (char *) NULL);
+ Tcl_CreateHashEntry(&psInfoPtr->fontTable, Tcl_DStringValue(&ds), &i);
+ Tcl_DStringFree(&ds);
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetPostscriptPoints --
+ *
+ * Given a string, returns the number of Postscript points
+ * corresponding to that string.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If
+ * TCL_OK is returned, then everything went well and the
+ * screen distance is stored at *doublePtr; otherwise
+ * TCL_ERROR is returned and an error message is left in
+ * the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+GetPostscriptPoints(interp, string, doublePtr)
+ Tcl_Interp *interp; /* Use this for error reporting. */
+ char *string; /* String describing a screen distance. */
+ double *doublePtr; /* Place to store converted result. */
+{
+ char *end;
+ double d;
+
+ d = strtod(string, &end);
+ if (end == string) {
+ error:
+ Tcl_AppendResult(interp, "bad distance \"", string,
+ "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+#define UCHAR(c) ((unsigned char) (c))
+ while ((*end != '\0') && isspace(UCHAR(*end))) {
+ end++;
+ }
+ switch (*end) {
+ case 'c':
+ d *= 72.0/2.54;
+ end++;
+ break;
+ case 'i':
+ d *= 72.0;
+ end++;
+ break;
+ case 'm':
+ d *= 72.0/25.4;
+ end++;
+ break;
+ case 0:
+ break;
+ case 'p':
+ end++;
+ break;
+ default:
+ goto error;
+ }
+ while ((*end != '\0') && isspace(UCHAR(*end))) {
+ end++;
+ }
+ if (*end != 0) {
+ goto error;
+ }
+ *doublePtr = d;
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TextToPostscript --
+ *
+ * This procedure is called to generate Postscript for
+ * text items.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error
+ * occurs in generating Postscript then an error message is
+ * left in the interp's result, replacing whatever used
+ * to be there. If no error occurs, then Postscript for the
+ * item is appended to the result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+TextToPostscript(interp, tablePtr, tagPtr, tagX, tagY, width, height,
+ row, col, textLayout)
+ Tcl_Interp *interp; /* Leave Postscript or error message here. */
+ Table *tablePtr; /* Information about overall canvas. */
+ TableTag *tagPtr; /* */
+ int tagX, tagY; /* */
+ int width, height; /* */
+ int row, col; /* */
+ Tk_TextLayout textLayout; /* */
+{
+ int x, y;
+ Tk_FontMetrics fm;
+ char *justify;
+ char buffer[500];
+ Tk_3DBorder fg = tagPtr->fg;
+
+ if (fg == NULL) {
+ fg = tablePtr->defaultTag.fg;
+ }
+
+ if (Tk_TablePsFont(interp, tablePtr, tagPtr->tkfont) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tk_TablePsColor(interp, tablePtr, Tk_3DBorderColor(fg)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ sprintf(buffer, "%% %.15g %.15g [\n", (tagX+width)/2.0,
+ tablePtr->psInfoPtr->y2 - ((tagY+height)/2.0));
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ sprintf(buffer, "col%d row%d [\n", col, row);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+
+ Tk_TextLayoutToPostscript(interp, textLayout);
+
+ x = 0; y = 0; justify = NULL; /* lint. */
+ switch (tagPtr->anchor) {
+ case TK_ANCHOR_NW: x = 0; y = 0; break;
+ case TK_ANCHOR_N: x = 1; y = 0; break;
+ case TK_ANCHOR_NE: x = 2; y = 0; break;
+ case TK_ANCHOR_E: x = 2; y = 1; break;
+ case TK_ANCHOR_SE: x = 2; y = 2; break;
+ case TK_ANCHOR_S: x = 1; y = 2; break;
+ case TK_ANCHOR_SW: x = 0; y = 2; break;
+ case TK_ANCHOR_W: x = 0; y = 1; break;
+ case TK_ANCHOR_CENTER: x = 1; y = 1; break;
+ }
+ switch (tagPtr->justify) {
+ case TK_JUSTIFY_RIGHT: justify = "1"; break;
+ case TK_JUSTIFY_CENTER: justify = "0.5";break;
+ case TK_JUSTIFY_LEFT: justify = "0";
+ }
+
+ Tk_GetFontMetrics(tagPtr->tkfont, &fm);
+ sprintf(buffer, "] %d %g %g %s %d %d DrawCellText\n",
+ fm.linespace, (x / -2.0), (y / 2.0), justify,
+ width, height);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+
+ return TCL_OK;
+}
diff --git a/libgui/src/tkTableUtil.c b/libgui/src/tkTableUtil.c
new file mode 100644
index 00000000000..29e2f143456
--- /dev/null
+++ b/libgui/src/tkTableUtil.c
@@ -0,0 +1,340 @@
+/*
+ * tkTableUtil.c --
+ *
+ * This module contains utility functions for table widgets.
+ *
+ * Copyright (c) 2000 Jeffrey Hobbs
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#include "tkTable.h"
+
+static char * Cmd_GetName _ANSI_ARGS_((const Cmd_Struct *cmds, int val));
+static int Cmd_GetValue _ANSI_ARGS_((const Cmd_Struct *cmds,
+ const char *arg));
+static void Cmd_GetError _ANSI_ARGS_((Tcl_Interp *interp,
+ const Cmd_Struct *cmds, const char *arg));
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableOptionBdSet --
+ *
+ * This routine configures the borderwidth value for a tag.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * It may adjust the tag struct values of bd[0..4] and borders.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TableOptionBdSet(clientData, interp, tkwin, value, widgRec, offset)
+ ClientData clientData; /* Type of struct being set. */
+ Tcl_Interp *interp; /* Used for reporting errors. */
+ Tk_Window tkwin; /* Window containing table widget. */
+ char *value; /* Value of option. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+{
+ char **borderStr;
+ int *bordersPtr, *bdPtr;
+ int type = (int) clientData;
+ int result = TCL_OK;
+ int argc;
+ char **argv;
+
+
+ if ((type == BD_TABLE) && (value[0] == '\0')) {
+ /*
+ * NULL strings aren't allowed for the table global -bd
+ */
+ Tcl_AppendResult(interp, "borderwidth value may not be empty",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if ((type == BD_TABLE) || (type == BD_TABLE_TAG)) {
+ TableTag *tagPtr = (TableTag *) (widgRec + offset);
+ borderStr = &(tagPtr->borderStr);
+ bordersPtr = &(tagPtr->borders);
+ bdPtr = tagPtr->bd;
+ } else if (type == BD_TABLE_WIN) {
+ TableEmbWindow *tagPtr = (TableEmbWindow *) widgRec;
+ borderStr = &(tagPtr->borderStr);
+ bordersPtr = &(tagPtr->borders);
+ bdPtr = tagPtr->bd;
+ } else {
+ panic("invalid type given to TableOptionBdSet\n");
+ return TCL_ERROR; /* lint */
+ }
+
+ result = Tcl_SplitList(interp, value, &argc, &argv);
+ if (result == TCL_OK) {
+ int i, bd[4];
+
+ if (((type == BD_TABLE) && (argc == 0)) || (argc == 3) || (argc > 4)) {
+ Tcl_AppendResult(interp,
+ "1, 2 or 4 values must be specified for borderwidth",
+ (char *) NULL);
+ result = TCL_ERROR;
+ } else {
+ /*
+ * We use the shadow bd array first, in case we have an error
+ * parsing arguments half way through.
+ */
+ for (i = 0; i < argc; i++) {
+ if (Tk_GetPixels(interp, tkwin, argv[i], &(bd[i])) != TCL_OK) {
+ result = TCL_ERROR;
+ break;
+ }
+ }
+ /*
+ * If everything is OK, store the parsed and given values for
+ * easy retrieval.
+ */
+ if (result == TCL_OK) {
+ for (i = 0; i < argc; i++) {
+ bdPtr[i] = MAX(0, bd[i]);
+ }
+ if (*borderStr) {
+ ckfree(*borderStr);
+ }
+ if (value) {
+ *borderStr = (char *) ckalloc(strlen(value) + 1);
+ strcpy(*borderStr, value);
+ } else {
+ *borderStr = NULL;
+ }
+ *bordersPtr = argc;
+ }
+ }
+ ckfree ((char *) argv);
+ }
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableOptionBdGet --
+ *
+ * Results:
+ * Value of the -bd option.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+TableOptionBdGet(clientData, tkwin, widgRec, offset, freeProcPtr)
+ ClientData clientData; /* Type of struct being set. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+ Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
+ * information about how to reclaim
+ * storage for return string. */
+{
+ register int type = (int) clientData;
+
+ if (type == BD_TABLE) {
+ return ((TableTag *) (widgRec + offset))->borderStr;
+ } else if (type == BD_TABLE_TAG) {
+ return ((TableTag *) widgRec)->borderStr;
+ } else if (type == BD_TABLE_WIN) {
+ return ((TableEmbWindow *) widgRec)->borderStr;
+ } else {
+ panic("invalid type given to TableOptionBdSet\n");
+ return NULL; /* lint */
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableTagConfigureBd --
+ * This routine configures the border values based on a tag.
+ * The previous value of the bd string (oldValue) is assumed to
+ * be a valid value for this tag.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * It may adjust the value used by -bd.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TableTagConfigureBd(Table *tablePtr, TableTag *tagPtr,
+ char *oldValue, int nullOK)
+{
+ int i, argc, result = TCL_OK;
+ char **argv;
+
+ /*
+ * First check to see if the value really changed.
+ */
+ if (strcmp(tagPtr->borderStr ? tagPtr->borderStr : "",
+ oldValue ? oldValue : "") == 0) {
+ return TCL_OK;
+ }
+
+ tagPtr->borders = 0;
+ if (!nullOK && ((tagPtr->borderStr == NULL)
+ || (*(tagPtr->borderStr) == '\0'))) {
+ /*
+ * NULL strings aren't allowed for this tag
+ */
+ result = TCL_ERROR;
+ } else if (tagPtr->borderStr) {
+ result = Tcl_SplitList(tablePtr->interp, tagPtr->borderStr,
+ &argc, &argv);
+ if (result == TCL_OK) {
+ if ((!nullOK && (argc == 0)) || (argc == 3) || (argc > 4)) {
+ Tcl_SetResult(tablePtr->interp,
+ "1, 2 or 4 values must be specified to -borderwidth",
+ TCL_STATIC);
+ result = TCL_ERROR;
+ } else {
+ for (i = 0; i < argc; i++) {
+ if (Tk_GetPixels(tablePtr->interp, tablePtr->tkwin,
+ argv[i], &(tagPtr->bd[i])) != TCL_OK) {
+ result = TCL_ERROR;
+ break;
+ }
+ tagPtr->bd[i] = MAX(0, tagPtr->bd[i]);
+ }
+ tagPtr->borders = argc;
+ }
+ ckfree ((char *) argv);
+ }
+ }
+
+ if (result != TCL_OK) {
+ if (tagPtr->borderStr) {
+ ckfree ((char *) tagPtr->borderStr);
+ }
+ if (oldValue != NULL) {
+ size_t length = strlen(oldValue) + 1;
+ /*
+ * We are making the assumption that oldValue is correct.
+ * We have to reparse in case the bad new value had a couple
+ * of correct args before failing on a bad pixel value.
+ */
+ Tcl_SplitList(tablePtr->interp, oldValue, &argc, &argv);
+ for (i = 0; i < argc; i++) {
+ Tk_GetPixels(tablePtr->interp, tablePtr->tkwin,
+ argv[i], &(tagPtr->bd[i]));
+ }
+ ckfree ((char *) argv);
+ tagPtr->borders = argc;
+ tagPtr->borderStr = (char *) ckalloc(length);
+ memcpy(tagPtr->borderStr, oldValue, length);
+ } else {
+ tagPtr->borders = 0;
+ tagPtr->borderStr = (char *) NULL;
+ }
+ }
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Cmd_OptionSet --
+ *
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Cmd_OptionSet(ClientData clientData, Tcl_Interp *interp,
+ Tk_Window unused, char *value, char *widgRec, int offset)
+{
+ Cmd_Struct *p = (Cmd_Struct *)clientData;
+ int mode = Cmd_GetValue(p,value);
+ if (!mode) {
+ Cmd_GetError(interp,p,value);
+ return TCL_ERROR;
+ }
+ *((int*)(widgRec+offset)) = mode;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Cmd_OptionGet --
+ *
+ *
+ * Results:
+ * Value of the option.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Cmd_OptionGet(ClientData clientData, Tk_Window unused,
+ char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
+{
+ Cmd_Struct *p = (Cmd_Struct *)clientData;
+ int mode = *((int*)(widgRec+offset));
+ return Cmd_GetName(p,mode);
+}
+
+/*
+ * simple Cmd_Struct lookup functions
+ */
+
+char *
+Cmd_GetName(const Cmd_Struct *cmds, int val)
+{
+ for(;cmds->name && cmds->name[0];cmds++) {
+ if (cmds->value==val) return cmds->name;
+ }
+ return NULL;
+}
+
+int
+Cmd_GetValue(const Cmd_Struct *cmds, const char *arg)
+{
+ unsigned int len = strlen(arg);
+ for(;cmds->name && cmds->name[0];cmds++) {
+ if (!strncmp(cmds->name, arg, len)) return cmds->value;
+ }
+ return 0;
+}
+
+void
+Cmd_GetError(Tcl_Interp *interp, const Cmd_Struct *cmds, const char *arg)
+{
+ int i;
+ Tcl_AppendResult(interp, "bad option \"", arg, "\" must be ", (char *) 0);
+ for(i=0;cmds->name && cmds->name[0];cmds++,i++) {
+ Tcl_AppendResult(interp, (i?", ":""), cmds->name, (char *) 0);
+ }
+}
diff --git a/libgui/src/tkWinPrintCanvas.c b/libgui/src/tkWinPrintCanvas.c
index 5b7bc41830a..029c6687f52 100644
--- a/libgui/src/tkWinPrintCanvas.c
+++ b/libgui/src/tkWinPrintCanvas.c
@@ -52,20 +52,20 @@ PrintCanvasCmd(clientData, interp, argc, argv)
int tiles_wide,tiles_high;
int tile_y, tile_x;
int screenX1, screenX2, screenY1, screenY2, width, height;
- DOCINFO *lpdi = malloc(sizeof(DOCINFO));
+ DOCINFO *lpdi = (DOCINFO *) ckalloc(sizeof(DOCINFO));
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " canvas \"",
(char *) NULL);
- return TCL_ERROR;
+ goto error;
}
/* The second arg is the canvas widget */
if (!Tcl_GetCommandInfo(interp, argv[1], &canvCmd)) {
Tcl_AppendResult(interp, "couldn't get canvas information for \"",
argv[1], "\"", (char *) NULL);
- return TCL_ERROR;
+ goto error;
}
memset(&dm,0,sizeof(DEVMODE));
@@ -74,7 +74,7 @@ PrintCanvasCmd(clientData, interp, argc, argv)
memset(lpdi,0,sizeof(DOCINFO));
lpdi->cbSize=sizeof(DOCINFO);
- lpdi->lpszDocName=malloc(255);
+ lpdi->lpszDocName= (LPCSTR) ckalloc(255);
sprintf((char*)lpdi->lpszDocName,"SN - Printing\0");
lpdi->lpszOutput=NULL;
@@ -164,8 +164,12 @@ PrintCanvasCmd(clientData, interp, argc, argv)
EndDoc(pd.hDC);
done:
+ ckfree ((char*) lpdi->lpszDocName);
+ ckfree ((char*) lpdi);
return TCL_OK;
- error:
+error:
+ ckfree ((char*) lpdi->lpszDocName);
+ ckfree ((char*) lpdi);
return TCL_ERROR;
}
diff --git a/libgui/src/tkWinPrintText.c b/libgui/src/tkWinPrintText.c
index a9ffd36bfb9..88ed8b8884d 100644
--- a/libgui/src/tkWinPrintText.c
+++ b/libgui/src/tkWinPrintText.c
@@ -212,7 +212,8 @@ typedef struct TextStyle {
-void DisplayDLineToDrawable(TkText *textPtr, DLine *dlPtr, DLine *prevPtr, TkWinDrawable *drawable);
+static void
+DisplayDLineToDrawable(TkText *textPtr, DLine *dlPtr, DLine *prevPtr, TkWinDrawable *drawable);
/*
*--------------------------------------------------------------
@@ -248,7 +249,7 @@ PrintTextCmd(clientData, interp, argc, argv)
Pixmap pixmap;
int bottomY = 0; /* Initialization needed only to stop
* compiler warnings. */
- DOCINFO *lpdi = malloc(sizeof(DOCINFO));
+ DOCINFO *lpdi = (DOCINFO *) ckalloc(sizeof(DOCINFO));
TkTextIndex first, last;
int numLines;
HDC hDCpixmap;
@@ -272,7 +273,7 @@ PrintTextCmd(clientData, interp, argc, argv)
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " text \"",
(char *) NULL);
- return TCL_ERROR;
+ goto error;
}
/*
@@ -281,7 +282,7 @@ PrintTextCmd(clientData, interp, argc, argv)
if (!Tcl_GetCommandInfo(interp, argv[1], &textCmd)) {
Tcl_AppendResult(interp, "couldn't get text information for \"",
argv[1], "\"", (char *) NULL);
- return TCL_ERROR;
+ goto error;
}
memset(&dm,0,sizeof(DEVMODE));
@@ -290,7 +291,7 @@ PrintTextCmd(clientData, interp, argc, argv)
memset(lpdi,0,sizeof(DOCINFO));
lpdi->cbSize=sizeof(DOCINFO);
- lpdi->lpszDocName=malloc(255);
+ lpdi->lpszDocName = (LPCSTR) ckalloc(255);
sprintf((char*)lpdi->lpszDocName,"SN - Printing\0");
lpdi->lpszOutput=NULL;
@@ -445,8 +446,12 @@ PrintTextCmd(clientData, interp, argc, argv)
textPtr->dInfoPtr->flags|=DINFO_OUT_OF_DATE;
done:
+ ckfree ((char*) lpdi->lpszDocName);
+ ckfree ((char*) lpdi);
return TCL_OK;
- error:
+error:
+ ckfree ((char*) lpdi->lpszDocName);
+ ckfree ((char*) lpdi);
return TCL_ERROR;
}