diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2019-01-07 21:33:12 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2019-01-07 21:33:12 (GMT) |
commit | 9d9bd29f4c4f54a064f2cf2ab7f51244a235839d (patch) | |
tree | 26340b4567650fefdb4a915b41db5b993546741c | |
parent | 1c463eec511ffd93b99d7de57821c018bbfc0b24 (diff) | |
parent | add018f8b224a906e0c85e0740919e68d15f6854 (diff) | |
download | blt-9d9bd29f4c4f54a064f2cf2ab7f51244a235839d.zip blt-9d9bd29f4c4f54a064f2cf2ab7f51244a235839d.tar.gz blt-9d9bd29f4c4f54a064f2cf2ab7f51244a235839d.tar.bz2 |
Merge commit 'add018f8b224a906e0c85e0740919e68d15f6854' as 'tktable'
50 files changed, 38706 insertions, 0 deletions
diff --git a/tktable/.gitignore b/tktable/.gitignore new file mode 100644 index 0000000..f805e81 --- /dev/null +++ b/tktable/.gitignore @@ -0,0 +1,33 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su diff --git a/tktable/ChangeLog b/tktable/ChangeLog new file mode 100755 index 0000000..3b95bec --- /dev/null +++ b/tktable/ChangeLog @@ -0,0 +1,1705 @@ +2016-01-12 waj + + * upgraded TEA to 3.9 + * numerous compiler fixes for 64bit + +2008-11-14 Jeff Hobbs <jeffh@ActiveState.com> + + **** 2.10 TAGGED FOR RELEASE **** + + * generic/tkTable.c: Set NO_XSETCLIP universally as Tk 8.5/Xft + seems to ignore XSetClipRectangles. This may slow things down a + little, but draws correctly. [Bug 1805350] + + * UPGRADING.txt (removed): no longer need this old v1 upgrade doc. + + * README.txt: remove refs to mac classic stuff, update notes + + * configure, configure.in, tclconfig/tcl.m4: Update to TEA 3.7 + * tests/tkTable.test, unix/tktable.spec, generic/version.h: + * demos/loadtable.tcl: Update version to 2.10 + * Makefile.in: update dist target, include library/tktable.py + + * demos/tktable.py: note that this version is outdated + * library/tktable.py (NEW): Added new version of tktable wrapper + for Python/Tkinter from GPolo. Not 100% compatible with previous + version. [Patch 2244167] + + * generic/tkTableTag.c (Table_TagCmd): remove interp->result set + work-around for old bug as i->result is no longer exposed in 8.6. + + * generic/tkTable.c: Use safe Tcl_SetObjResult instead of trying + * generic/tkTableCell.c: to set existing objResult value. + * generic/tkTableCmds.c: + +2006-07-10 Jeff Hobbs <jeffh@ActiveState.com> + + * license.txt (bourbon_ware): Be less restrictive in the + bourbon_ware clause. + +2006-01-25 Jeff Hobbs <jeffh@ActiveState.com> + + * configure.in, configure, tclconfig/tcl.m4: update to TEA 3.5 + +2006-01-22 Jeff Hobbs <jeffh@ActiveState.com> + + * tclconfig/tcl.m4, configure: update to TEA 3.4 interim + +2005-12-13 Jeff Hobbs <jeffh@ActiveState.com> + + * generic/tkTableCmds.c (Table_ActivateCmd): remove potential + undefined behavior warning. + +2005-12-02 Jeff Hobbs <jeffh@ActiveState.com> + + * tclconfig/tcl.m4, configure.in, configure: update to TEA 3.4 + +2005-05-11 Jeff Hobbs <jeffh@ActiveState.com> + + * Makefile.in (html): switch to groff to fix botched html output. + * doc/tkTable.html: regen [Bug 1198478] + * doc/tkTable.n: use '' around \\ items. + +2005-03-18 Jeff Hobbs <jeffh@ActiveState.com> + + * Makefile.in (AR): use @AR@, improve html doc target + * configure, configure.in, tclconfig/tcl.m4: TEA 3.2 patch update + + * doc/tkTable.n, doc/kTable.html: doc cleanup + +2005-02-01 Jeff Hobbs <jeffh@ActiveState.com> + + * configure, configure.in, tclconfig/tcl.m4: update to TEA 3.2 + +2004-11-18 Jeff Hobbs <jeffh@ActiveState.com> + + * library/tkTable.tcl (::tk::table::SelectAll): remove invalid ref + to HandleType proc. [Bug 1068874] (ade) + +2004-07-22 Jeff Hobbs <jeffh@ActiveState.com> + + **** 2.9 TAGGED FOR RELEASE **** + + * configure, tclconfig/tcl.m4: update tcl.m4 TEA_PATH_X that adds + Aqua build recognition and TEA_WINDOWINGSYSTEM variable. + +2004-07-20 Jeff Hobbs <jeffh@ActiveState.com> + + * generic/version.h, unix/tktable.spec: updated for v2.9 + * demos/loadtable.tcl, tests/tkTable.test: + + * Makefile.in, configure.in, configure, tclconfig/tcl.m4: update + to TEA 3.1, use CFLAGS instead of EXTRA_CFLAGS and bump the + version number of Tktable to 2.9. + + * generic/tkTable.h: add #include <ctype.h> + + * generic/tkTableCell.c (TableGetCellValue, TableSetCellValue): + Do faster cache checks when DATA_CACHE is the only data source. + In fallback from command that errors to array var, retrieve array + value immediately on current get|set request. + When setting the value with cache and array sources, don't do the + caching branch as the array trace will do that already. + (TableMoveCellValue): Do the efficient cache value management when + cache is the only data source, otherwise the regular fallback has + all the necessary checks. [Bug #919872] + + * generic/tkTable.c (TableVarProc): allow setting NULL value in + cache hash from array trace. + +2004-06-10 Jeff Hobbs <jeffh@ActiveState.com> + + * generic/tkTableWin.c (EmbWinDisplay): make min window displayed + have width/height 1 pixel min (was 3px) + + * generic/tkTable.c (TableDisplay): Don't draw when we don't have + the space for it. [Bug 747038] + + * doc/tkTable.html, doc/tkTable.n: improve docs to note + requirement of specifying a data source. [Bug 963204] + +2004-02-17 Jeff Hobbs <jeffh@ActiveState.com> + + * generic/tkTableCmds.c (Table_ActivateCmd): test implementation + of an "unactivate" ($table activate "") command to remove the + active cell. (becroft) + +2004-02-13 Jeff Hobbs <jeffh@ActiveState.com> + + * library/tkTable.tcl (::tk::table::Button1): account for what + resizeborders are set when selecting cell [Bug 876320] (ferenc) + (<Prior> <Next>): activate topleft, not @0,0 (accounts for title + rows) [Bug 879347] (ferenc) + +2003-12-10 Jeff Hobbs <jeffh@ActiveState.com> + + * Makefile.in: updated to TEA3 spec + * configure: + * configure.in: + * generic/tkTable.c: + * generic/tkTableInitScript.h: + * generic/version.h: + * mac/mac_tkTable.r: + * tclconfig/tcl.m4: + + * win/makefile.vc: minor updates, probably still out of date + + * tclconfig/ChangeLog (removed): not necessary + + * generic/tkTable.c: added Tk_ClassProcs and TableWorldChanged + proc if built against 8.4 + + * generic/tkTable.h: add 8.4 ifdef, remove ANSI_ARGS usage + +2003-07-16 Jeff Hobbs <jeffh@ActiveState.com> + + * doc/tkTable.n: add note about -window "" behavior + +2003-04-10 Jeff Hobbs <jeffh@ActiveState.com> + + * configure: regen + * tclconfig/tcl.m4: updated + + * library/tkTable.tcl (BeginExtend): avoid error in tables that + have no anchor index yet. (renshaw) + +2003-04-09 Jeff Hobbs <jeffh@ActiveState.com> + + * configure: regen + * tclconfig/tcl.m4: Updated to newest tcl.m4, (WinCE support) + + * demos/loadtable.tcl: redefine 'puts' on Windows CE + + * generic/tkTable.c (TableDisplay): correctly copy clipwindow area + for NO_XSETCLIP case and use that when UNDER_CE as well. Also add + support for drawing ellipsis in NO_XSETCLIP case. + Comment out OffsetClipRgn call - it was a noop. + +2003-04-04 Andreas Kupries <andreask@activestate.com> + + * configure.in: + * tclconfig/tcl.m4: Updated to newest tcl.m4, regenerated + configure's. + +2003-02-24 Jeff Hobbs <jeffh@ActiveState.com> + + * generic/tkTable.c (TableDisplay): do not use buffer pixmap for + slow -drawmode on Win32 because we aren't clipping it correctly. + +2003-01-30 Jeff Hobbs <jeffh@ActiveState.com> + + * Makefile.in: remove use of nested $(PACKAGE) to enable building + on older, cruftier make versions + + * doc/tkTable.n: add -ellipsis tag /global option which + * tests/tkTable.test: takes a char string (ie: "...") to display + * generic/tkTableTag.c: as an ellipsis. These will only be shown + * generic/tkTable.h: on non-wrapping, non-multiline cells. + * generic/tkTable.c: + +2002-12-10 Jeff Hobbs <jeffh@ActiveState.com> + + * tests/tkTable.test: + * generic/tkTableCell.c (TableGetCellValue): make caching allows + NULLs throughout to save mem. + Do not call Tcl_FreeResult as it will be freed before the next + result is set, and causes us to lose large results. [Bug #651685] + +2002-10-16 Jeff Hobbs <jeffh@ActiveState.com> + + **** 2.8 TAGGED FOR RELEASE **** + + * Makefile.in: updated dist target to get changed fileset. + + * generic/tkTableEdit.c (Table_EditCmd): Ensure that embedded + widgets being moved offscreen get unmapped. [Bug #551325] + + * generic/tkTableCell.c (TableAtBorder): refine border detection + in the midst of spanned cells. [Patch #544117] (duxbury) + + * doc/tkTable.n: + * doc/tkTable.html: + * tests/tkTable.test: + * generic/tkTable.c: Add global -justify option. [Bug #623557] + + * generic/tkTableTag.c: more CONST84 casting fixes. + Allowing setting of tag relief to "". [Bug #233619] + + * generic/tkTable.h: + * generic/tkTableUtil.c: + * generic/tkTableWin.c: more CONST84 casting fixes. + + * library/tkTable.tcl: Add <FocusOut> as a default auto-commit + event. [Bug #611132] + (::tk::table::Motion): abort "extended" arm if the anchor cell + isn't defined. [Bug #604470] + +2002-10-15 Jeff Hobbs <jeffh@ActiveState.com> + + * tclconfig/tcl.m4: + * configure: + * configure.in: move the CFLAGS definition into TEA_MAKE_LIB + and make it pick up the env CFLAGS at configure time. + +2002-10-15 Andreas Kupries <andreask@pliers.activestate.com> + + * configure.in: Changed to propagate an initial CFLAGS value to + the final definition. A TEA condition (SHARED_BUILD == 1) + squashed it, causing it the build system to loose the + +DAportable we specify for the AS PA-RISC2.2 build host. This is + a problem for _all_ TEA and TEA 2 based configure files. + +2002-10-09 Jeff Hobbs <jeffh@ActiveState.com> + + * configure: + * configure.in: move TEA_PATH_X below TEA_CONFIG_CFLAGS as it can + mess with the configure results. + + * unix/tktable.spec (new): RPM spec file. (fontaine) + + * demos/tktable.py: added a contributed tktable wrapper for + Python/Tkinter from Klaus Roethemeyer. + +2002-09-27 Jeff Hobbs <jeffh@ActiveState.com> + + * Makefile.in: correct tkTable.tcl.h target to work with FreeBSD's + default make. + +2002-09-25 Jeff Hobbs <jeffh@ActiveState.com> + + * generic/tkTable.c: + * generic/tkTable.h: added support for building on OS X (steffen) + +2002-06-21 Jeff Hobbs <jeffh@ActiveState.com> + + * Makefile.in: call cygpath on INCLUDES $(srcdir)/generic. + + * tests/all.tcl: minor cleanup + + * tests/tkTable.test (table-30.1): + * generic/tkTableEdit.c (Table_EditCmd): fixed problem where row + insertion could segfault. [Bug #487747] + +2002-04-11 Jeff Hobbs <jeffh@ActiveState.com> + + * tclconfig/tcl.m4: + * configure: Enabled COFF as well as CV style debug info with + --enable-symbols to allow Dr. Watson users to see function info. + More info on debugging levels can be obtained at: + http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp + +2002-04-03 Jeff Hobbs <jeffh@ActiveState.com> + + * Makefile.in: improved use of DESTDIR in install targets. + Removed need for installdirs target. + Broke TCLSH_PROG into TCLSH_ENV and TCLSH_PROG with TCLSH var and + added comments about TCLSH_ENV. + Added default shell and gdb targets. + + * tclconfig/tcl.m4: + * configure: + * configure.in: updated to new TEA base that: prefixes all macros + with TEA_* instead of SC_*; adds TEA_PREFIX, which defaults the + prefix and exec_prefix values to what Tcl used; adds + TEA_SETUP_COMPILER, which handles basic compiler / support program + checks and simplifies the configure.in. Turn on --enable-threads + by default and do sanity checking as well. + +2002-04-02 Jeff Hobbs <jeffh@ActiveState.com> + + * configure: regened + * configure.in: added user32.lib to LIBS for Windows + * tclconfig/tcl.m4: updated from TEA sample + +2002-03-27 Jeff Hobbs <jeffh@ActiveState.com> + + * Makefile.in (WISH_PROG): moved and updated env var definitions + to have wish work from build dir. Removed TCL_EXTRA_CFLAGS, + TCL_LD_FLAGS, TCL_SHLIB_LD_LIBS, TCL_DBGX, TCL_STUB_LIB_FILE, + TCL_STUB_LIB_SPEC as they aren't needed (configure acquires all + that info for us). TCL_LIBS is also not needed, but left in as a + reference to the libs Tcl used. + + * configure: regen based on updated tclconfig/tcl.m4 + * configure.in: moved the SHLIB_LD_LIBS magic into + tclconfig/tcl.m4 and noted where users can modify (SHLIB_LD_)LIBS. + * tclconfig/tcl.m4: updated from sample to be more independent of + *Config.sh. + + * unix/Makefile.in (removed): + * unix/configure.in (removed): + * unix/configure (removed): + * unix/install-sh (removed): removed old makefile files to force + use of new toplevel TEA 2002 configure/make. + +2002-03-21 Jeff Hobbs <jeffh@ActiveState.com> + + * tests/tkTable.test: more icursor tests + * generic/tkTable.c (TableWidgetObjCmd): corrected placing the + icursor and retaining the position. + +2002-03-20 Jeff Hobbs <jeffh@ActiveState.com> + + * generic/tkTable.c: + * generic/tkTable.h: + * generic/tkTableCmds.c: + * generic/tkTableUtil.c: cleaned up several areas where cache data + was not getting freed. [Bug #532447] (bloisi) + +2002-03-19 Jeff Hobbs <jeffh@ActiveState.com> + + * tests/tkTable.test: added tag configure tests + + * generic/tkTableTag.c (Table_TagCmd): work-around for bug in + Tk_ConfigureValue that sets interp->result to NULL. [Bug #522882] + + * generic/tkTable.c (TableDisplay): when building with threads on + WIN32, use NO_XSETCLIP instead of direct DC hacks because Tk + doesn't use CS_CLASSDC on threaded builds. + (Tktable_Init) Corrected to use BUILD_Tktable for EXTERN changes. + + * configure: + * configure.in: use double-eval to substitute DBGX var for + ${PACKAGE}_LIB_FILE. + + * Makefile.in: cleaned up install target + +2002-03-13 Jeff Hobbs <jeffh@ActiveState.com> + + * demos/loadtable.tcl: + * tests/tkTable.test: adapted load to new configure style where + unix gets the 'lib' suffix for the library. + + * tclconfig/ChangeLog: + * tclconfig/README.txt: + * tclconfig/install-sh: + * tclconfig/tcl.m4: + * README.txt: + * Makefile.in: + * aclocal.m4: + * configure: + * configure.in: introduction of next-gen TEA based config files. + The unix/ configure files should no longer be used. + + * generic/tkTable.c: + * generic/tkTableCell.c: + * generic/tkTableCellSort.c: + * generic/tkTableCmds.c: + * generic/tkTableEdit.c: + * generic/tkTableTag.c: + * generic/tkTableUtil.c: + * generic/tkTableWin.c: + * generic/tkTable.h: introduced CONST84 define for compatibility + with new 8.4 CONST-ed headers and older headers and fixed up + sources where necessary. + + * generic/tkTableInitScript.h: + * generic/tkTable.c: + * generic/version.h: + * mac/mac_tkTable.r: + * win/makefile.vc: changed TBL_VERSION to VERSION, upped to 2.8. + Added Win64 build support to makefile.vc + +2002-03-07 Jeff Hobbs <jeffh@ActiveState.com> + + * library/tkTable.tcl (tk_tablePasteHandler): "string comp" fixed + to "string compare" [Bug #500449] + +2002-01-16 Jeff Hobbs <jeffh@ActiveState.com> + + * generic/tkTable.c (TableWidgetObjCmd): corrected dangerous + caching of resultPtr that could lead to segfault. + +2001-08-24 Jeff Hobbs <jeffh@ActiveState.com> + + * README.txt: corrected outdated notes. [Bug #455116] (kriehbel) + +2001-08-23 Jeff Hobbs <jeffh@ActiveState.com> + + * unix/Makefile.in (tkTable.tcl.h): corrected target to sed \'s + properly in the .tcl file. + + * library/tkTable.tcl: added the ability to select borders with + button 1. (backe) The user can turn off this ability by calling + [set ::tk::table::Priv(borderB1) 0] in their code. button 3 is + still active for selecting borders as well. + fixed a couple references to work on Mac/Tk. (steffen) + + * mac/mac_tkTable_prefix.h: + * mac/mac_tkTable.r: corrected Mac build. (steffen) + + * doc/tkTable.html: regen'd + * doc/tkTable.n: Clarified that any <row>,<col> index + specification will always return a valid cell. [Bug #450397] + Corrected what 'units' scrolls. [Bug #448837] + + * mac/mac_tkTable.mcp: removed in favor of XML project file + * mac/mac_tkTable.mcp.xml: XML CodeWarrior project file for the + mac. (steffen) + +2001-07-18 Jeff Hobbs <jeffh@ActiveState.com> + + * generic/tkTable.c (TableDestroy): freed cached values in destroy. + +2001-06-30 Jeff Hobbs <jeffh@ActiveState.com> + + **** 2.7 RELEASE **** + + * generic/tkTable.h: added STREQ #def to replace strcmp(a,b) == 0 + * generic/tkTable.c: + * generic/tkTableTag.c: made use of STREQ #define. + Redid tag merging to make use of only one allocated tag. + + * doc/tkTable.html: + * doc/tkTable.n: updated docs with feature change info + + * tests/tkTable.test: added more tests + + * generic/tkTableCmds.c (Table_ActivateCmd): made table refresh + when moving the cursor in the active cell. + +2001-06-24 Jeff Hobbs <jeffh@ActiveState.com> + + * generic/tkTableTag.c (Table_TagCmd): corrected patch for Patch + #423332 that does prevent excess refresh in the simple case. + +2001-06-23 Jeff Hobbs <jeffh@ActiveState.com> + + * generic/tkTable.c (TableConfigure): corrected possible crash + during configure when switching array vars and changed name of + 'restrict' var to something that is not a reserved word. (berggren) + + * library/tkTable.tcl: support for future UTF8_STRING selection on + unix. + + * generic/tkTable.c: + * generic/tkTable.h: + * generic/tkTableTag.c: added support for priorities in tags. + There are new 'tag lower' and 'tag raise' methods. This may lead + to different view characteristics because the default priority + order is creation order, starting with flash, active, sel, title, + followed by whatever the user creates. The old order was fixed at + flash, active, sel, <celltag>, title, <rowtag>, <coltag> + **** POTENTIAL INCOMPATABILITY **** + + * tests/tkTable.test: makings of an initial test suite + + * generic/tkTableCmds.c (Table_CurvalueCmd): removed extra curvalue + in error message. + +2001-06-22 Jeff Hobbs <jeffh@ActiveState.com> + + * generic/tkTableTag.c (Table_TagCmd): made adding tags to + cell/row/col create the tag if it didn't exist. This was + previously an error. + + * generic/tkTable.c (TableDisplay): changed use of NO_XSETCLIP to + only operate on Macintosh, added new Windows code that is the + equivalent of XSetClipRectangles. (teske) + Removed XFillRectangle function that was there for support with + 8.1 (nobody should use 8.1 anymore). + (TableDisplay): Corrected clearing of the area beyond the last + cell to not be incorrect when there is a span on the last cell. + (TableAdjustParams): handle possible div-by-zero for scrollbar + calculations. (christian brunner) + + * generic/tkTable.h: added TableMoveCellValue decl. + * generic/tkTableEdit.c (TableModifyRC): made use of + TableMoveCellValue. + * generic/tkTableCell.c (TableSetCellValue): fixed mem leak in + -cache option. + (TableMoveCellValue): new function to support possible speedier + movement of cells when caching is being used. (michael teske) + + * generic/tkTableCell.c (TableCellCoords): corrected + rowspan/colspan dimension calculation for title cells. + (Table_SetCmd): correct possible abuse in setting result object + pointer. + + * README.txt: updated links + + * win/makefile.vc (pkgIndex.tcl): + * unix/Makefile.in (pkgIndex.tcl): made 8.2 the required base for + the stubs version + + * generic/tkTableCmds.c (Table_GetCmd): fixed potential crash from + abusing object pointer. (jonas hodges) Bug #230701 + + * generic/tkTableTag.c (Table_TagCmd): fix possible hang situation + by preventing refresh when setting the same tag on a cell/row/col. + (Michael Shulz) + +2001-03-28 Jeff Hobbs <jeffh@ActiveState.com> + + * generic/tkTable.h: change 'char *new' -> 'char *newVal' to not + stump C++ compilers + +2000-10-19 Jeff Hobbs <jeff at hobbs org> + + * tests/all.tcl: new file + * tests/tkTable.test: copied listbox.test in to serve as a base + for tests on the table widget. Conversion still needs to be done. + + * generic/tkTableCmds.c: #if 0'd stub function Table_Cmd + + * generic/tkTable.h: + * generic/tkTable.c: corrected headers, made TableConfigure static + +2000-08-30 Jeff Hobbs <hobbs@scriptics.com> + + * generic/tkTable.h: + * generic/tkTableWin.c (EmbWinConfigure): + * generic/tkTableTag.c (Table_TagCmd): + * generic/tkTable.c (TableConfigure): changed -borderwidth to use + TK_CONFIG_CUSTOM functions for option parsing. + + * win/makefile.vc: + * unix/Makefile.in: updated for added/removed source files + + * generic/cmd.c (removed): + * generic/mm.h (removed): + * generic/tkTableUtil.c (new): moved the few used Cmd_* functions + into tkTableUtil.c (Cmd_Struct moved to tkTable.h), removing the + need for the other accessory files. + + * unix/configure: + * unix/configure.in (uname check): added support for systems where + uname has no -p option (ie HP). + +2000-08-21 Jeff Hobbs <hobbs@scriptics.com> + + * generic/tkTable.c (TableConfigure): added check for NULL + oldBorders during configure. + +2000-08-18 Jeff Hobbs <hobbs@scriptics.com> + + * generic/tkTable.c: changed the -ipad* defaults to 0, to go along + with the -pad* defaults. For users looking for backwards + compatability with 2.5 padding, add: + option add *Table.ipadX 2 + option add *Table.ipadY 1 + Users will likely find that -pad* is more intuitive though. + **** POTENTIAL INCOMPATABILITY **** + + * doc/tkTable.html: + * doc/tkTable.n: updated docs to reflect new -(i)pad* definitions + and enhanced -bd behavior. + + * generic/tkTable.c (TableCursorEvent, TableConfigCursor): reduced + unnecessary redraws when the cursor was in a non-editable cell. + +2000-08-17 Jeff Hobbs <hobbs@scriptics.com> + + * generic/tkTable.c: enhanced -borderwidth option to support + per-edge configuration of borderwith. -bd now takes a list of + pixel sizes, 1, 2 or 4 in length. 1 is traditional, 2 specifies + just the left and right border sizes (to emulate a multicolumn + listbox), and 4 specifies {left right top bottom} for ultimate + control. Tags may override the default. + Also redid the handling of -(i)pad[xy]. Swapped the basic meaning + (-pad* from v2.5 should now be -ipad* in 2.7). -pad* now enforces + absolute empty padding for cells, expanding the default size. + Embedded windows can override the -pad* value. See docs for more. + **** POTENTIAL INCOMPATABILITY **** + + * generic/tkTable.h: removed use of INLINE, added new border style + support to structures. + + * generic/tkTableCell.c (TableAtBorder): made it aware of the new + configurable border style. It bases its calculations off the + default border width(s). Also did lots of comment cleanup. + + * generic/tkTableWin.c (EmbWinDisplay): changed interpretation of + -pad* for windows to be per side (instead of overall). This is + more intuitive. Added support of new border styles. + + * generic/tkTableTag.c: Added new border style control per tag. + New TableGetTagBorders function to determine border values based + on input. Lots of comment/code cleanup. + + * generic/tkTableEdit.c (Table_EditCmd): corrected code to ensure + that when rows where deleted, rows/cols would not fall below 1, + the minimum dimension size (otherwise "bad things" happen). + (Table_EditCmd): corrected problem when specifying a negative + count deleting more rows than exist before the specified index. + + * unix/Makefile.in ($(DLL)): corrected ld build line to not use + SHLIB_CFLAGS, instead adding TK_LD_SEARCH_FLAGS. (virden) + +2000-08-10 Jeff Hobbs <hobbs@scriptics.com> + + * unix/Makefile.in: cleaned up Makefile to correctly use the right + flags for building with stubs support. + + * generic/version.h: bumped version to 2.7 + + * generic/tkTable.h: added ipadX, ipadY to table struct. + * generic/tkTable.c (TableConfigure): removed code setting + forceUpdate to 1 for any configure options. + (TableAdjustParams): added -ipdax/-ipday, giving them the meaning + that -pad* was extended to use in 2.6. -pad* are as they were in + 2.5, and -ipad* does the extended cell padding for 2.7+. See docs + for details. + (TableEventProc): removed xexpose.count check that would delay + necessary invalidate calls. (Wangnick) + + * library/tkTable.tcl: added ::tk::table::BackSpace proc instead + of inlined event binding, taking out \ at eol that confused the + tcl2c converter when inlining the tkTable.tcl.h runtime. + +2000-08-02 Jeff Hobbs <hobbs@scriptics.com> + + 2.6 RELEASE + + * unix/Makefile.in: added bindist and cleanall targets, and + cleared up the use of some variables to allow for correct building + of the tktable library across platforms (including AIX). + The distclean target no longer removes the generated html doc. + * unix/configure: + * unix/configure.in: added check of available compression program + and SYSID for Unix make bindist target. Also cleaned up the use + of some other variables. + + * generic/tkTable.c (TableConfigCursor, TableCursorEvent) + (TableFlashEvent, TableEventProc): + * generic/tkTableEdit.c (TableDeleteChars, TableInsertChars): + * generic/tkTableCmds.c (Table_CurvalueCmd): removed INV_FORCE + from TableRefresh call. This means more refreshes are delayed. + + * generic/tkTable.c (BUILD_tkTable): corrected EXTERN def'n of + Init funcs. + +2000-08-01 Jeff Hobbs <hobbs@scriptics.com> + + * library/tkTable.tcl: rewritten to use ::tk::table namespace + + * generic/tkTable.h: added CONSTRAIN and BETWEEN macros to simply + some MIN/MAX cases. + * generic/tkTable.c: + * generic/tkTableCell.c: + * generic/tkTableCmds.c: updated to use CONSTRAIN/BETWEEN instead + of MIN(MAX()). + + * generic/tkTable.c (TableRefresh): changed to not do anything + when coords < 0 are passed in (like asking to refresh non-existent + active cell). + (TableEventProc): added (likely redundant) check for xexpose.count + == 0 before redisplaying in Expose case. (Halpin) + + * generic/tkTable.c (XFillRectangle): added compat XFillRectangle + to make up for lack of one in Tk8.1. (Nijtmans) + (TableAdjustParams): Made -padx and -pady actually work as + intended for each cell. This actually affects the default size + for a table, as more spacing is given to each cell by default. + Use -padx/y to control this. (Lennard, Hobbs) + (TableDisplay): removed extra call to TableCellCoords (leftover + from NO_SPANS). (Deich) + + * generic/tkTableCmds.c (Table_SelSetCmd): Corrected the selection + of title cells when only title cells are available. (Brutti) + + * library/tkTable.tcl (tkTableChangeWidth): changed -$a to + [expr {-$a}]. (Dubiner) + (tkTableBeginSelect): Changed behavior for extended selectmode to + select in the topleft title area when appropriate. (Dubiner) + (tkTableSelectAll): Changed behavior to select *all* cells + (including title cells) when -selecttitles is 1. + + * demos/loadtable.tcl: corrected to search better in new directory + structure. + +2000-03-22 Jeff Hobbs <hobbs@scriptics.com> + + * */*: complete restructure of tktable sources + * CHANGES.txt: moved to ChangeLog, will now use ChangeLog format + +########################################################################## +## TkTable CHANGES +## +## Newest changes at the top of the file. +## Release dates between "****"s. +## +## changes by Hobbs COPYRIGHT 1996-1997 Jeffrey Hobbs, CADIX International +## changes by Hobbs COPYRIGHT 1998-2000 Jeffrey Hobbs +## jeff at hobbs org +## +# * tkTable v0.55-1.x includes additions contributed by: +# * tmoore@spatial.ca (Tom Moore) +# * sebastian.wangnick@eurocontrol.de (Sebastian Wangnick) +# * paulf@lamont.ldgo.columbia.edu +# * peter@bj-ig.de (Peter Brueckner) +# * jeff at hobbs org (Jeffrey Hobbs) +# * ellson@lucent.com (John Ellson) +## +## Mac support provided by Chuck Houpt (choupt@als.com). (v2.3+) +## +########################################################################## + +**** v2.6alpha 29 February 2000 **** + +Fixed row/col insertion/deletion to correctly handle embedded windows. +(fix in part by albrecht@DAnalyse.de) + +Added stubs support to makefile. + +Added support for safe init script (requires embedded runtime) to +be used in safe interpreters. + +Fixed bug in Table_BorderCmd on passing the 6th arg (the optional +row|col). (rickm@vsl.com) + +Added -holdselection arg to row/col insert/delete. (Paolo.Brutti@tlsoft.it) + +Added -DNO_SORT_CELLS ... + +Created tkTableCellSort.c with cell sorting routines. Redid ... + +Fixed bug in tk_tableCut due to change in curselection syntax. + +Fixed missing comma in tkTableEdit.c:32 (Brutti) + +**** v2.5 31 May 1999 **** + +Fixed row/col insertion/deletion to move embedded windows, added +-holdwindows option and Table_Win(Delete|Move). + +Removed -rows/-cols switch to insert/delete row/col, as it could +cause very odd behavioral problems. + +Removed ckfree/ckalloc's between a quick delete/init of a hash table. + +Upgraded ExpandPercents for UTF awareness. + +Changed "tag cell|row|col" to complain when the tag is unknown. + +Fixed bug in UTF char length handling (actually due to change in +the Tk API from 8.1beta to final) for active cell. + +fixed bug where scanMark* weren't properly initialized. + +Changed icursor method to always return an int, being -1 if there +really isn't a valid cursor in the active cell (ie - it's disabled). + +Converted table widget to mostly Tcl_Obj in/output. +Reorganized a lot of code in the process. + +**** v2.4 10 December 1998 **** + +Changed exit handler to not be used (unless -DUSE_EXIT_HANDLER is specified). + +Changed distribution directory name to go with new 'make distrib'. + +Changed TableUndisplay to properly handle unmapping embedded windows +in title areas. Added TableTrueCell for this. + +Changed EmbWinUnmapNow to always call Tk_UnmapWindow. + +Changed cell border drawing so that any 1-pixel border would use the +fast drawing mode (except for when single drawmode is set). + +Changed borderWidth to be a tag-definable value. + +Removed used of borderWidth in border resize cmd calculations. + +Modified various C and Tcl procs to support spanning cells. + +Changed ckfree(value) to Tcl_Free(value) in TableFetchSelection. + +Streamlined use of NO_XSETCLIP, improved boundary checking for +determining whether the cell needs clipping at all. + +Fixed bug in drawing with NO_XSETCLIP to copy the area from the source +window to the clip window, draw on it, then copy it back. Before the +clip window was drawn on clean, losing what might be important stuff in +the source (like an image). + +Added row/col spanning. This involved a lot of code changes, mostly +in tkTableCell.c, mostly #ifndef'ed with NO_SPANS. See docs for behavior. +Added 'spans' and 'hidden' command. + +Fixed bug in TableAtBorder that was messing up certain border cases. + +Added delta error of 1 pixel to the B1-Motion routine, so that the mouse +must move more than a pixel for the tkTableMotion routine to kick in. + +Fixed tkTableBeginToggle to handle Control-B1 properly. (rickm@vsl.com) + +Fixed seg fault in Table_BorderCmd when called with too few args +(reported by rbansal@ltcm.com). + +Added TableGeometryRequest to TableModifyRC to update a table's +geometry according to the new row/col size. + +Fixed EmbWinDelete to clean up properly (it wouldn't clean up if there +wasn't a window associated with the tag). + +Removed unused type arg from TableModifyRCaux. + +Fixed EmbWinRemove to actually remove all info about the window from +the table (as advertised). + *** BEHAVIORAL CHANGE *** + +Fixed "window delete ..." to actually delete the window entry. + +Fixed flashing so that it will flash if any valid data source is +being used (before only the Tcl array source caused flashes). + +Removed deprecated 'flush' command. [.t flush ...] is equivalent +to [.t clear cache ...]. + +Improved TableUndisplay to really work within the proper seen +constraints. (rickm@vsl.com) + +Removed dependency on source for Windows (only for the XSync call). +Should now be able to compile against a binary installed version of wish. + +Use of EXTERN and EXPORT reworked to follow 8.0.3 guidelines. EXPORT +was dropped, meaning that compiling for older versions of the Borland +compiler is not possible. + +Changed use of "$*.h" in Makefile.in to "$@" - some makes seemed to +choke on the proper interpretation of $* (notably HP-UX). + +Added "-fg SELECT_FG" to the default sel tag definition. + +Swapped proto define of Tcl_DStringAppendAll with actual header. + +Fixed #endif SPANS syntax error in Makefile. + +Changed #define CELL from (ROW|COL) to it's own significant bit (this +is used by TableRefresh). + +Added -sparsearray option to allow the user to choose whether the +table treats associated arrays as "sparse", deleting the empty +elements (default), or whether every element set is kept. + +Fixed demos/spreadsheet.tcl to start column labeling with "A". + +Changed Tcl_StaticPackage call in tkAppInit.c to include +SafeInit function. + +Added "empty" bindings to tkTable.tcl to prevent the magic Alt-"menu" +bindings from inserting chars into the table as well. + +**** v2.3 23 July 1998 **** + +Moved the 'set' command into tkTableCell.c and extended it to +understand full row/col setting with Tcl lists. + +Created tkTableInitScript.h to mirror the spirit of tclInitScript.h. +The user can now define a tkTableInit to be eval'ed at load time +that finds the appropriate tkTable.tcl file. Also added env support +for these locations. + +Changed version.in to version.h, a file that is both readable in C +(for the Mac build) and by make (for Unix/Windows). + +Changed TableDisplay #ifdef's to be more specific (NO_XSETCLIP). +Expecting XSetClipRectangles to be available in Tk8.0.3 for Win, +and maybe also in the future for Mac. + +Attempted row/col spanning with limited success. Half functional +code left in for reference, delimited by #ifdef SPANS/#endif. + +Changed TableCellCoords to no longer do bounds checking on row/col. + +Changed several more instances of TableCellCoords/TableInvalidate +to TableRefresh. + +Fixed bug in table insertion/deletion concerning the calculation of +the minkey (minimum valid row/col to insert/delete) when titles were +allowed to be moved. + +Mac support courtesy Chuck Houpt (choupt@als.com). + +**** v2.2 10 July 1998 **** + +Undid caching of activeLayout in favor of activeTagPtr because I was +abusing the nature of the token returned by Tk_ComputeTextLayout, +causing amazingly odd cores. + +Changed TableGetLastCell definition to fix scrollbar bug. (Brutti) + +Changed "#if (TK_MINOR_VERSION > 0)" to "#ifdef TCL_UTF_MAX" to +remove the ambiguity of purpose (for UTF code). + +Fixed bug in TableInsertChars that mangled the purpose of -autoclear, +as well as confusing icursor index when using it. + +**** v2.1 2 July 1998 **** + +Updated man pages, generated new HTML file. + +Reworked directory structure, updated makefiles. + +Removed -batchmode. It was pretty useless, and potentially confusing. + **** POTENTIAL INCOMPATIBILITY **** + +Fixed bug for Tk8.1a2 Unicode display in TableDisplay where the length +of the display string was not calculated correctly. + +Fixed background area redraw bug in Windows. Reworked to take out the +#ifdef WIN32 code without too much compromise. + +Added TableRefresh command that subsumes many CellVCoords/Invalidate +call combos. + +Adjusted TableWhatCell to what it was in v1.82, and made fix in +TableDisplay for bounds to prevent <=0 invalidWidth|Height. + +Added clear command, subsumes flush command, plus adds features. + +Made some cleanup from DestroyNotify repetitive in TableDestroy. + +Added MapNotify event handler to ensure that changes to the table +made when iconified will still cause an update. + +Changed "single" and "fast" drawmodes to not set -bd 1 as a side +effect, but instead to force 0..1 to allow for fast drawing without +any borders. Skipped border drawing case statement when -bd is 0. + +Changed "tag cell ..." to only invalidate for redraw when the affected +cell is visible. + +Added check for NULL tablePtr->tkwin in TableCellVCoords. Could +cause problems where it was used to replace TableCellCoords. + +Fixed bug in TableFetchSelection that truncated the string returned +by -selectioncommand to the length of the original string. Also +fixed mem leak (didn't free all DStrings in an error), and changed +it so that a background error is triggered if there is a problem +with the -selectioncommand. + +Fixed bug in TableDisplay where last row, if one pixel hi, wouldn't +get redrawn properly. + +Changed default fonts to those used for entry widgets. + **** POTENTIAL INCOMPATIBILITY **** + +Added UTF char (Unicode) support, based on 8.1a2 tkEntry.c. Had +to be conditionalized because it doesn't exist in 8.0. + +Added -multiline option for tags to allow old one-line text only, +Reworked tag options so that tag values that aren't ever set won't +affect other tags. + +Fixed seg fault bug in CMD_ACTIVATE when Tk_PointToChar could be called +on double-click, but TableDisplay hadn't yet been called (because it is +waiting for idle) which is required to set tablePtr->activeLayout +properly. Also fixed mem leak with old activeLayout not being freed when +it changed. + +Speed improvement - changed from using Tk_GetGC/Tk_FreeGC to XCreateGc/ +XChangeGC/XFreeGC. Since it was highly unlikely that the caching +provided in the Tk routines would ever benefit us, moving to direct +X calls and manipulating just one GC should be faster. + +**** v2.00 24 April 1998 **** + +Update man pages, generated new HTML version. + +Added "single" drawing mode, and made "single" and "fast" both set +-borderwidth to 1 as a side effect. + +Fixed seg fault on Windows involving large numbers of rows. Unsure +exactly what fixed it, but the problem disappeared amidst all the +changes since v1.82... + +Updated tkAppInit.c to Tk8.1 version. + +Added ifdef for Win32 default colors. + +Since we can now have multi-line cells, changed -rowheight and height +to work the same as -colwidth and width did (+ nums for size in line, +- for sizes in pixels). + **** POTENTIAL INCOMPATIBILITY **** + +Added new "make static" option for making a static library. + +Reworked scrollbar calcs again based on pixels. Fixes all funny off by +half a cell problems. Also prevents scrolling when only title areas are +visible (those are, by design, not scrollable). + +Changed stretching to stretch the last row/col for any stretchmode but +"none", to prevent empty space from appearing. + +Fixed interpretation of CellVCoords to return 1 on slightly visible +cells (now only a 1 pixel square size is required to be considered +visible - used to be 1/4 the desired cell size). + +Added support to allow the second click into the active cell to select +the nearest character. + +Changed <Return> binding to work with multi-line cells. + **** POTENTIAL INCOMPATIBILITY **** + +*** Undid 60.06.98 - bad fix +Fixed bug in TableWhatCell that caused the returned cell to be one more +than expected when the edge was passed in. +*** + +Made TableVarProc not cause an Invalidate call if it was +triggered by SetActiveIndex. + +Changed around some function names for sense of modularity (preparing +better C API). + +Commented all procedures in tkTable.c. + +Broke up tkTable.c into constituent files. + +Added support for embedded windows via "window" submethod. + +Fixed quirk in xscrollbar that would make it appear as it all was +in view when the last column was only partially visible. (Brutti) + +Changed several CellCoord calls to CellVCoord calls to only invalidate +if necessary. + +Reworked merging of tags and determination of active cell. State +disabled cells no longer receive the "active" look, although they +are still indexed as active. + +New -selecttitles option, removed prohibition of selecting title areas. + **** POTENTIAL INCOMPATIBILITY **** + +Removed all KANJI, IMP and TK4 #ifdef code. tkTable development now +focused 100% on Tk8+. Also removed Itcl stuff since itcl for Tcl8 +should be different. + **** INCOMPATIBILITY FOR TK4/KANJI/ITCL USERS **** + +**** v1.82 3 April 1998 **** + +Update man pages, generated new HTML version. + +Fixed bug in row start location calculation, reorg'ed some code +for row stretch fill mode. + +Simplified caching of col tags for display. + +Changed code that referenced interp->result to use accessor functions. + +Fixed problem where flat reliefs would be eliminated because they +were assumed to be undefined (TK_RELIEF_FLAT changed in Tk8.1). + +Added -bordercursor and -resizeborders option, added PointerMotionMask +to event handler, moving the tkTableCheckBorder event into C. Should +be much more efficient. + **** POTENTIAL INCOMPATIBILITY **** + +Changed "$(COMPILE.c)" to "$(CC) $(CFLAGS) $(CPPFLAGS) -c" in Makefile.in. +Should be equivalent, but some make's don't understand. + +Change border dragging routines for column to support pixel movement. + +Fixed problem with column widths and row heights being shifted improperly +during row/col deletion (didn't account for - row/col offset). + +Updated tkTable.itcl to same versions as tkTable.tcl (ignored over +several revisions). + +Fixed binding bug in tkTable.tcl for <Control-(Left|Right)>. (Becker) + +changed TableModifyRC to be more selective about what is invalidated +for redraw. (Brutti) + +made 'title' tag have -state disabled by default (an oversight from +the addition of -state tag option in 1.80). + +**** v1.81 March 20 1998 **** + +added support for exact pixel dimensions for column width by using +negative numbers, also supported in -colwidth. Changed width|height +to support 'default' key instead of assuming negative number means default. + **** POTENTIAL INCOMPATIBILITY **** + +added -state tag option (cheap hack, must be improved). + +changed handling of -state table option. (Ellson) + +added -invertselected option. (Brutti) + +added FocusOut binding to commit cell on FocusOut events. + +made the cell commit changes anytime "activate" is called, regardless +of whether the active cell was moved or not. + +"tag cell|col|row|includes tagName" no longer return an error if the tag name +is unknown (just returns empty string, or 0 for "includes"). Only "tag cget" +complains about unknown tag names. + **** POTENTIAL INCOMPATIBILITY **** + +Improved makefiles. (patches courtesy Dukhovni) + +Fixed bug in tkTable.itcl (improperly handled backslash). + +Fix for 8.0 w/ plus/dash patch (Ellson). + +Fixed minor -Wall complaints. + +Changed the way row/col tags were determined to be on a cell. (JMH) + +Made title tag have lower priority than a cell tag. + +Fixed bug where the last table row/col would be deleted when table -state was +disabled (should be a no op). + +**** v1.8 May 28 1997 **** (changes hobbs) + +Moved the instantiation of the tk*Uid variables from the DLLEntryPoint +into the *Init functions for those not compiling this as a DLL. + +Fixed bug where "active" index for an array might not update properly after +the table changes arrays if the previous array's cell had the same value +for the active cell. + +Updated Windows makefile.vc (still far from perfect). + +Fixed calculation error where WhatCell would look for the bottomright +cell a few pixels off (didn't account for highlightWidth). + +Fixed numerous places where cells weren't being invalidated (to be +redrawn) but should have been. + +Fixed bug in curvalue that didn't mark the active text as changed which +would cause editions to be lost when the active cell changed. + +Changed default font for Tk8 from "Helvetica 12" to just "Helvetica" because +the 12 was a tweaking large font on my Sol2.5 machine. + +Renamed -width to -colwidth and -height to -rowheight, replaced with +different interpretation such that -width, -height set the viewable +# of cols, rows (a la listbox or text widget). + **** POTENTIAL INCOMPATIBILITY **** + +Made default title foreground white for better readability. + +Fixed INF/divide by zero possible error for scrollbars when no editable +cells are in view. Possible funky behavior still exists when no editable +cells are available (for selection). + +Fixed possible access violation where TableInvalidate would be called +after the tkwin had been destroyed. + +Enhancement ideas from Pawel Gorazda <pawel.gorazda@solidex.com.pl>: + * Added TCL_DEFS to TCL_CFLAGS in Makefile.in + * Make "tag cell tagName" list cells for the special tags + * new "tag includes" method for finding if a cell has a specific tag + * changed selection to not change selection (do nothing) when + the user clicks on a title cell + **** BEHAVIORAL CHANGE **** + +Fixed missing 'q' in tkTable.itcl + +Fixed interaction with -command to only blow up when an error occurs, +not for return/break/ok. + +Changed tkTableCheckBorder to use crosshair instead of fleur because of +complaint of lack of fleur cursor on WinNT. + +Added internal caching with -cache option and flush method for speed +improvements. + +Changed "sel clear all" to use old iterated method of clearing selection +for people who use "sel clear all" in Motion events and such. + +**** v1.7 Apr 11 1997 **** (changes hobbs) + +Changed instances of clearing selection to delete and reinit the +sel hash table instead of going through each entry. + +Updated docs and added demo and basic spreadsheet class for [incr Tcl]. + +Changed default selectmode to browse, same as listbox. + **** POTENTIAL INCOMPATIBLITY **** + +Added forceUpdate arg to TableConfigure to make sure that necessary +parameters will be adjusted at instantiation. + +Changed TableSetCellValue to *unset* empty valued indices instead of +setting them to "". + +Introduced support for row/col insertion/deletion with numerous options. + +Fixed geometry bug that didn't account for highlightWidth in GeometryRequest. + +Added selecttype option to alter the way selection is handled. + +Added padx and pady configuration options. + +Some changes to Makefile.in to get better behavior out of it. + +Changed "see" to ensure cell is fully visible by adding param to +TableCellVCoords. + +Added support for [incr Tcl] (tested against v2.2). + +Fixed TableGetIndex to properly account for row/colOffset > 0. Also +adjusted constraining of user index in TableGetIndex. + +**** v1.6 Feb 7 1997 **** (changes hobbs) + +Fixed x && y offset bug for SLOW drawmode (reported by Michael Johnson). + +Now whenever you move from a cell where an edit has occured, it will +save that edition. You can always use <Escape> (reread) to get the +old value back before you move the cell. + **** BEHAVIORAL CHANGE **** + +Fixed the bug where inserting characters with autoclear off didn't set +TEXT_CHANGED properly, so you could move without a cell registering the +change (reported by Eric Dolce). + +**** v1.5 Feb 6 1997 **** (changes hobbs) + +Fixed xview/yview scroll page/units problems. + +Fixed TableConfigure error return problems. + +Fixed font display problem for Tk8 (stupid reference error). + +Fixed "set" && "curselection" to understand need for command OR array +existence. + +Fixed conceptual bug in -command %-substitution - there was no way to +get the write value! Redefined %s/S value for -command. + **** POTENTIAL INCOMPATIBLITY **** + +Fixed bug in "see" method reported by PHIL SMITH <pjsmith@netins.net>. +It did the opposite of what it should, caused by the change from +TableCellHidden to TableCellVCoords. + +Optimized TableDisplay. offsetX, offsetY were useless because they were +always subtracted from x && y (so why not do it once... doh!). + +Removed CheckTagCmd and inlined some code. This optimizes certain things +(there was no reason to cache row tags, just move the lookup code!). + +changed TableSetCellValue to not use GetVar, thus a write always occurs, +even if the value is the same. This prevents a read trace from triggering, +but now a write trace will always trigger. + +**** v1.4 Feb 2 1997 **** (changes hobbs) + +Changed default unix font to medium weight (from bold). + +Updated "bbox" method to allow range. + +Added auto-resizable border code with new "border" method, TableAtBorder +function and new Table bindings. + +Changed TableCellHidden to TableCellVCoords & extended it. Now understands +highlightWidth variation and clips area to actual visible coords. + +Added code in TableConfigure to prevent spurious redisplays of the +entire table for any config request. + +fixed index bug where "ROW,COL<extrajunk>" translated to "ROW,COL" and +a couple other similar interpretive bugs. + +fixed potential segfault in unsetting "active" element of attached array. + +changed min()/max() to MIN()/MAX() - avoids Windoze warning. + +changed textCurPosn to icursor. + +greatly simplified KANJI interoperability by making activeBuf a regular +char *, changing a few interfaces, and some other stuff. This reduced +the number of KANJI #ifdef's significantly. + +added -command and -usecommand options. + +**** v1.3 Jan 28 1997 **** (changes hobbs) + +Included precompiled Win95/Tk8.0a2 DLL. + +Fixed several compiler warning problems. + +Moved header code to its own header file. + +Fixed some potential mem leaks. + +Added Windows support. HACK ALERT! Without an XSetClipRectangles, an +extra Drawable is used for WIN32. There may be a better way to do this. +If so, make me a patch. + +Data struct / Cmd name changes to avoid any conflict when compiling older +version of Table with newer version in same executable. + +Added -image option to tags. + +Removed NO_TOP_LEFT ifdef'ed code. Topleft should be showing. + +**** v1.2 Jan 18 1997 **** (changes hobbs) + +Updated man page and HTML help page. + +Added TableCellSort to sort a row,col properly. + +Added arg for curvalue method to set the current active buffer. + +Added validation mechanism, validate method and -validate, -validatecommand +options. See docs for details. + +Added "active" key element to traced Tcl array for table. This holds +the activeBuf value of the table. + +Change arrayVar configuration in TableConfigure to only trigger if +the arrayVar actually changed. + +Moved inserting/deleting in active cell to separate functions and +bullet-proofed the code. + +Removed TableFlashConfigure. Not used since "flash" became permanent tag. + +Changed TableSetCellValue to only set the variable if the value +has changed. This will prevent spurious flashing. + +Removed Roland King's COPYRIGHT, replaced with acknowledgements. +This code represents a 90% rewrite of his original code. + +Added -O as default CFLAGS in Makefile.in, along with HP cc note. + +Fixed bug with cursor at position 0 for KANJI (appears to be a bug +in TkWSTextExtents). + +Get/Set variable overhaul to ensure that everything works correctly +for KANJI support (without compile warnings). + +Changed TableBufLengthen to a #define which uses ckrealloc. + +Removed -rowfirstmode and its use in code. It actually didn't work for +many functions and indices would be incorrectly returned. + **** POTENTIAL INCOMPATIBLITY **** + +Fixed handling of arrayVar to accept vars with funny chars (including spaces). + +Added "see active" to tkTableMoveCell. + +Changed calculation of hidden cell to require at least 3/4 of +the cell to be off the screen. + +Cleaned up, optimized lots of code. Cleaned up some memory leaks. + +Removed undocumented "setlist" functionality - it was never used +and I deemed it extraneous. + +Numerous name changes in tkTable.tcl (conforming to standards). Also +added full row/col selection capability && cut/copy/paste functionality. + **** POTENTIAL INCOMPATIBLITY **** + +Changed ".table get ..." to return items in the same way as that +of listbox (only affects handling of spaced values being returned). + **** POTENTIAL INCOMPATIBLITY **** + +Changed Table_GetIndex to TableGetIndex (it was the only _ func). + +Optimized calling of TableAdjustParams in [xy]view and scan dragto +as well as TAP code. + +Removed useless selectionOn C var and "select" index. + **** POTENTIAL INCOMPATIBLITY **** + +Changed the [xy]scrollcmd to receive Tk4+ style args (2 doubles +instead of 4 ints). + +Fixed problems with [xy]view and scan. Might not be perfect yet. +Removed boundary command as it reiterates [yx]view and index, +added "bottomright" special index. Change of code example: + .table bound bottom => .table index bottomright row|col + **** POTENTIAL INCOMPATIBLITY **** + +Fixed problem with cursor not disappearing on focus out. + +Added -browsecommand option for monitoring active cell movement. + +Added selection handler and -rowseparator, -colseparator, +-selectioncommand, -exportselection options. + +Fixed problem with changing var to a simple variable. + +Fixed problems with compiling for KANJI, now seems to work again. + +Fixed highlight border bug. (bruecker) + +Fixed typo that prevented IMP from working. + +**** v1.1 Dec 30 1996 **** (changes hobbs) + +Updated code to handle Tk8 font mechanism. Now works with Tk8. + +Added Tktable_SafeInit procedure so it could be loaded into a safe +interpreter. + +Integrated Bruecker's (peter@bj-ig.de) changes to 0.63: + - Moved IMP-Code to one place, needs testing. + - Some changes to TableCreate and TableDestroy: + Hashtables ever needed are created in Create + so no tests in configure and later needed. + - Removed GcCache (will be placed in TableDisplay) + - Repaired Focus-Code little bug remains in the right + and bottom of HL-Frame. + +Updated README to reflect file name changes. + +Changed tkAppInit.c to reflect tk4.2 appinit. + +Changed Makefile.in to support get X_INCLUDES right. + +**** v1.0 Dec 19 1996 **** (changes hobbs) + +BUMPED VERSION TO 1.0 for initial (re)release. + +Updated man pages, in particular documenting bindings. + +Updated tkTable.tcl to use origin where appropriate. + +Added origin index. + +Added extra arg to insert/delete to specify what is really being +inserted/deleted to/from. + +Corrected insert/delete/icursor to not do edit the active cell if +it has not been set yet. + +Fixed TableScanTo. + +Enabled the display of the topleft title cells. + +Fixed cursor constraint for oversized fonts in a row. + +**** v0.63 Dec 18 96 **** (changes hobbs) + +Removed TableSetCell from tkTable.tcl, rearranged bindings as well. + +Rewrote checkTagCmd, fixed spurious return values. + +Reordered trigger path for Table_GetIndex. + +Fixed see to not be forceful, but to only move if necessary, and to +use the +1,+1 offset from topleft (more like centering). + +Added topleft index. + +ellson patch: + Fixed package require in Makefile.in and demo files + Moved Table_GetIndex to avoid implicit declaration warning. + +Changed how "anchor" was indexed internally. + +Fixed cursor showing in an active cell of width 0. + +Removed check for bounds in SEL_CLEAR (SEL_SET did it for us). + +**** v0.62 Dec 18 96 **** (changes hobbs) + +Updated man pages. + +Removed "#ifdef KANJI0" code (it was useless). + +Added in use of the active tag (it was previously ignored). + +Removed restriction on see method that kept the active cell in the view. + +Changed xview/yview/scan methods to not adjust selRow/Col. + +Changed code to use active cell as active, rather then sel cell. + +Made "flash" tag have higher display priority than "sel". + +Added pattern match support for "tag names". + +Added "tag exists" and "tag cget" submethods. + +Changed "tag celltag" to use Table_GetIndex instead of sscanf + +**** v0.61 patch Dec 14 96 **** (ellson@lucent.com) + +Change "tag celltag" to use index form of cell address,"x,y" instead of list +form "{x y}" + +Add back support for zero width columns and zero height rows. + +Added installation of tkTable.tcl in + [lindex $tcl_pkgPath 0]/Tktable/tkTable.tcl +(0.61 was using the built-in copy of tkTable.tcl so the lack of +installation wasn't noticed. Perhaps we don't need the built-in +version???) I put the runtime script in this directory to make it +trivial to generate binary distributions of the widget consisting of +a single Tktable directory that is just dropped into lib/. + +Added a make target for tablewish (not normally needed with dynamic loading +but sometimes handy for debugging) + +Corrected package name (Wasn't loading from tkcon Interp->Packages menu. +Package name should start with capital letter to match Init entry point.) + +Added configure code to automatically discover --prefix from existing +tclsh installation. Installation is now simply: + ./configure + make install + +**** v0.61 Dec 13 96 **** (all changes jhobbs except noted) + +Updated, corrected, expanded man pages. + +Updated internal code comments, fixed result strings. + +Fixed see problem (reported by Jean-Paul). + +Removed getwidth && getheight and rewrote width && height to be more +flexible and subsume the previous methods. + +Changed flashtime to really be a number representing 1/4 sec and +changed the default to 3 (750ms). Added "flash" as a permanent tag +(like "title", "active", and "sel"). Added options: + -flashmode + -flashtime + +Changed "Title" tag to "title". Why cap it? + +Reformatted most code to fit in 80 cols. + +Fixed activate index offset bug. + +Changed -*title options to -title*. The original version was too +misleading as to its purpose. + +Added fixes from ellson@lucent.com. + test.tcl updates + SIGSEV bug from improper argc count + +Added some changes from peter@bj-ig.de. + New stretch modes LAST && FILL + Highlight/Focus fixes + More options instead of methods + +Improved curselection code. + +added the following options: + -autoclear replaces editmode method + -state replaces editmode method + -insert* from Tk entry, manipulate cursor style + -batchmode replaces batch method + +Changed the dynamic load path for tkTable.tcl from +"$tk_library/tkTable/tkTable.tcl" to "$tk_library/tkTable.tcl". + +**** v0.60 Dec 10 96 **** (all changes jhobbs) +OPTIONS: + +Altered man pages to properly reflect what options are handled (there +were numerous extra, plus many missing). + +changed -procrowtag => -rowtagcommand +changed -proccoltag => -coltagcommand + +Added -bd synonym + +Fixed all internal coding for readability, concise representation + +changed -cursorbg => -insertbackground + +METHODS: + +Fixed lack of break in CMD_*STRETCH + +removed whatcell: code change: + .table whatcell x y => .table index @x,y + +removed whereis, changed to bbox: code change: + .table whereis row col => .table bbox <index> +This needs to be improved to take multiple indices. + +removed toprow && leftcol, added boundary: code change: + .table leftcol|toprow|bottomrow|rightcol ?rowOrCol? + => + .table boundary left|right|top|bottom ?rowOrCol? +rowOrCol can only be specified for top|left, as appropriate (though +a bug in the code didn't check properly). + +removed [rc]index: code change: + .table [rc]index <index> => .table index <index> row|col + +changed get so (1) it works and (2) it returns values more like the +listbox command + +removed setcell. This has been subsumed by the improved selection method. +code likeness: + .table setcell => .table index select + OR => .table curselection + .table setcell 4 2 => .table selection set 4,2 +The "index select" is there for 100% compatibility, but curselection is +what should be used to properly represent all selected cells. + +MISC: + +fixed parse_command to handle full non-ambiguous method names + +updated man pages to include all methods/options in Tk4 style. + +reordered a lot of code to be in "alphabetical" order. + +**** v0.56 Nov 96 **** + - merged changes from tkSpread from Jeffrey Hobbs <hobbs> + - added support for Japanization patch + - added multi-node select support + - removed -underline option for tags + - included default bindings in loadable library + +**** v0.5 Oct 96 **** + - merged changes from Peter Brueckner <peter@peter.bj-ig.de> + - takefocus + - highlight border + - "gcc -Wall -pedantic" cleanup + - updated for tcl7.6/tk4.2 + - autoconf + - only one c-file + +**** v0.4p8 **** + - added patch from wangnick@orthogon.de to make tkTable accept -rows 0 + - added patch from tmoore@pnfi.forestry.ca for handling of bad + array indexes + - added patch from tmoore@pnfi.forestry.ca to add rowTagProc and + colTagProc + - added patch from ellson@lucent.com to support cget so that + tkTable can be used with the dragdrop extension by + fellowsd@cs.man.ac.uk (Donal K. Fellows). + +version 0.3 --> version 0.4 +--------------------------- +tk4.1 and tk4.0 compatability (ellson@lucent.com) + - dynamically loadable library (SunOS 4.1.3 only so far) + - changed BISQUE to GRAY + - statically included TableInit.tcl into dynamic library + - fixed various compiler warnings + (now none with tk4.1, but still one with tk4.0) + - upgraded tkAppInit.c + - changed a few names: library: libtktable.so.0.4 + entry point: Tktable_Init + extended wish: tablewish + +version 0.2 --> version 0.3 +--------------------------- +Upgraded to tk4.0 (Paul Friberg) + +version 0.1 --> version 0.2 +--------------------------- +Changed the tag code to apply the effects of multiple tags to a cell. + +Fixed a bug with the flash code which forgot to delete the flash when +a table was deleted + +Fixed a bug which meant that row, column and cell tag changes didn't +update to the screen immediately when there was a row or column offset. + +Fixed the anchor code which was adding/subtracting a pixel from the +string in certain circumstances + +Fixed a cursor movement bug which caused the same cell to appear twice +when the cursor was moved + +Thanks particularly to Lou Salkind for pointing out some of the above +and suggesting fixes. + + diff --git a/tktable/Makefile.in b/tktable/Makefile.in new file mode 100644 index 0000000..36e30a5 --- /dev/null +++ b/tktable/Makefile.in @@ -0,0 +1,467 @@ +# Makefile.in -- +# +# This file is a Makefile for Sample TEA Extension. If it has the name +# "Makefile.in" then it is a template for a Makefile; to generate the +# actual Makefile, run "./configure", which is a configuration script +# generated by the "autoconf" program (constructs like "@foo@" will get +# replaced in the actual Makefile. +# +# Copyright (c) 1999 Scriptics Corporation. +# Copyright (c) 2002-2005 ActiveState Corporation. +# +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. + +#======================================================================== +# Add additional lines to handle any additional AC_SUBST cases that +# have been added in a customized configure script. +#======================================================================== + +#SAMPLE_NEW_VAR = @SAMPLE_NEW_VAR@ + +#======================================================================== +# Nothing of the variables below this line should need to be changed. +# Please check the TARGETS section below to make sure the make targets +# are correct. +#======================================================================== + +#======================================================================== +# The names of the source files is defined in the configure script. +# The object files are used for linking into the final library. +# This will be used when a dist target is added to the Makefile. +# It is not important to specify the directory, as long as it is the +# $(srcdir) or in the generic, win or unix subdirectory. +#======================================================================== + +PKG_SOURCES = @PKG_SOURCES@ +PKG_OBJECTS = @PKG_OBJECTS@ + +PKG_STUB_SOURCES = @PKG_STUB_SOURCES@ +PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@ + +#======================================================================== +# PKG_TCL_SOURCES identifies Tcl runtime files that are associated with +# this package that need to be installed, if any. +#======================================================================== + +PKG_TCL_SOURCES = @PKG_TCL_SOURCES@ + +#======================================================================== +# This is a list of public header files to be installed, if any. +#======================================================================== + +PKG_HEADERS = @PKG_HEADERS@ + +#======================================================================== +# "PKG_LIB_FILE" refers to the library (dynamic or static as per +# configuration options) composed of the named objects. +#======================================================================== + +PKG_LIB_FILE = @PKG_LIB_FILE@ +PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@ + +lib_BINARIES = $(PKG_LIB_FILE) +BINARIES = tkTable.tcl.h $(lib_BINARIES) + +SHELL = @SHELL@ + +srcdir = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +libdir = @libdir@ +includedir = @includedir@ +datarootdir = @datarootdir@ +datadir = @datadir@ +mandir = @mandir@ + +DESTDIR = + +PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION) +pkgdatadir = $(datadir)/$(PKG_DIR) +pkglibdir = $(libdir)/$(PKG_DIR) +pkgincludedir = $(includedir)/$(PKG_DIR) + +top_builddir = @abs_top_builddir@ + +INSTALL_OPTIONS = +INSTALL = @INSTALL@ $(INSTALL_OPTIONS) +INSTALL_DATA_DIR = ${INSTALL} -d -m 755 +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_LIBRARY = ${INSTALL_DATA} + +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +CC = @CC@ +CFLAGS_DEFAULT = @CFLAGS_DEFAULT@ +CFLAGS_WARNING = @CFLAGS_WARNING@ +EXEEXT = @EXEEXT@ +LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@ +MAKE_LIB = @MAKE_LIB@ +MAKE_SHARED_LIB = @MAKE_SHARED_LIB@ +MAKE_STATIC_LIB = @MAKE_STATIC_LIB@ +MAKE_STUB_LIB = @MAKE_STUB_LIB@ +OBJEXT = @OBJEXT@ +RANLIB = @RANLIB@ +RANLIB_STUB = @RANLIB_STUB@ +SHLIB_CFLAGS = @SHLIB_CFLAGS@ +SHLIB_LD = @SHLIB_LD@ +SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ +STLIB_LD = @STLIB_LD@ +#TCL_DEFS = @TCL_DEFS@ +TCL_BIN_DIR = @TCL_BIN_DIR@ +TCL_SRC_DIR = @TCL_SRC_DIR@ +#TK_BIN_DIR = @TK_BIN_DIR@ +#TK_SRC_DIR = @TK_SRC_DIR@ + +# Not used, but retained for reference of what libs Tcl required +#TCL_LIBS = @TCL_LIBS@ + +#======================================================================== +# TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our +# package without installing. The other environment variables allow us +# to test against an uninstalled Tcl. Add special env vars that you +# require for testing here (like TCLX_LIBRARY). +#======================================================================== + +EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR) +#EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR) +TCLLIBPATH = $(top_builddir) +TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` +PKG_ENV = @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ + PATH="$(EXTRA_PATH):$(PATH)" \ + TCLLIBPATH="$(TCLLIBPATH)" + +TCLSH_PROG = @TCLSH_PROG@ +TCLSH = $(TCLSH_ENV) $(PKG_ENV) $(TCLSH_PROG) + +#WISH_ENV = TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library` +#WISH_PROG = @WISH_PROG@ +#WISH = $(TCLSH_ENV) $(WISH_ENV) $(PKG_ENV) $(WISH_PROG) + +SHARED_BUILD = @SHARED_BUILD@ + +#INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ +INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@ + +PKG_CFLAGS = @PKG_CFLAGS@ + +# TCL_DEFS is not strictly need here, but if you remove it, then you +# must make sure that configure.ac checks for the necessary components +# that your library may use. TCL_DEFS can actually be a problem if +# you do not compile with a similar machine setup as the Tcl core was +# compiled with. +#DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS) +DEFS = @DEFS@ $(PKG_CFLAGS) \ + -DTBL_COMMAND=\"table\" \ + -DTBL_RUNTIME=\"tkTable.tcl\" \ + -DTBL_RUNTIME_DIR=\"$(pkglibdir)\" + +# Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile +CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl +CLEANFILES = @CLEANFILES@ + +CPPFLAGS = @CPPFLAGS@ +LIBS = @PKG_LIBS@ @LIBS@ +AR = @AR@ +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) \ + $(CFLAGS_DEFAULT) $(CFLAGS_WARNING) $(SHLIB_CFLAGS) $(CFLAGS) + +GDB = gdb +VALGRIND = valgrind +VALGRINDARGS = --tool=memcheck --num-callers=8 --leak-resolution=high \ + --leak-check=yes --show-reachable=yes -v + +.SUFFIXES: .c .$(OBJEXT) + +#======================================================================== +# Start of user-definable TARGETS section +#======================================================================== + +#======================================================================== +# TEA TARGETS. Please note that the "libraries:" target refers to platform +# independent files, and the "binaries:" target includes executable programs and +# platform-dependent libraries. Modify these targets so that they install +# the various pieces of your package. The make and install rules +# for the BINARIES that you specified above have already been done. +#======================================================================== + +all: binaries libraries doc + +#======================================================================== +# The binaries target builds executable programs, Windows .dll's, unix +# shared/static libraries, and any other platform-dependent files. +# The list of targets to build for "binaries:" is specified at the top +# of the Makefile, in the "BINARIES" variable. +#======================================================================== + +binaries: $(BINARIES) + +libraries: + +#======================================================================== +# Your doc target should differentiate from doc builds (by the developer) +# and doc installs (see install-doc), which just install the docs on the +# end user machine when building from source. +#======================================================================== + +doc: + @echo "If you have documentation to create, place the commands to" + @echo "build the docs in the 'doc:' target. For example:" + @echo " xml2nroff sample.xml > sample.n" + @echo " xml2html sample.xml > sample.html" + +install: all install-binaries install-libraries install-doc + +install-binaries: binaries install-lib-binaries install-bin-binaries + +#======================================================================== +# This rule installs platform-independent files, such as header files. +# The list=...; for p in $$list handles the empty list case x-platform. +#======================================================================== + +install-libraries: libraries + @$(INSTALL_DATA_DIR) $(DESTDIR)$(includedir) + @echo "Installing header files in $(DESTDIR)$(includedir)" + @list='$(PKG_HEADERS)'; for i in $$list; do \ + echo "Installing $(srcdir)/$$i" ; \ + $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \ + done; + +#======================================================================== +# Install documentation. Unix manpages should go in the $(mandir) +# directory. +#======================================================================== + +install-doc: doc + @$(INSTALL_DATA_DIR) $(DESTDIR)$(mandir)/mann + @echo "Installing documentation in $(DESTDIR)$(mandir)" + @list='$(srcdir)/doc/*.n'; for i in $$list; do \ + echo "Installing $$i"; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \ + done + +test: binaries libraries + $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \ + -load "package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \ + [list load `@CYGPATH@ $(PKG_LIB_FILE)` $(PACKAGE_NAME)]" + +shell: binaries libraries + @$(TCLSH) $(SCRIPT) + +gdb: + $(TCLSH_ENV) $(PKG_ENV) $(GDB) $(TCLSH_PROG) $(SCRIPT) + +gdb-test: binaries libraries + $(TCLSH_ENV) $(PKG_ENV) $(GDB) \ + --args $(TCLSH_PROG) `@CYGPATH@ $(srcdir)/tests/all.tcl` \ + $(TESTFLAGS) -singleproc 1 \ + -load "package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \ + [list load `@CYGPATH@ $(PKG_LIB_FILE)` $(PACKAGE_NAME)]" + +valgrind: binaries libraries + $(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) \ + `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) + +valgrindshell: binaries libraries + $(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT) + +depend: + +#======================================================================== +# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable +# mentioned above. That will ensure that this target is built when you +# run "make binaries". +# +# The $(PKG_OBJECTS) objects are created and linked into the final +# library. In most cases these object files will correspond to the +# source files above. +#======================================================================== + +$(PKG_LIB_FILE): $(PKG_OBJECTS) + -rm -f $(PKG_LIB_FILE) + ${MAKE_LIB} + $(RANLIB) $(PKG_LIB_FILE) + +$(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS) + -rm -f $(PKG_STUB_LIB_FILE) + ${MAKE_STUB_LIB} + $(RANLIB_STUB) $(PKG_STUB_LIB_FILE) + +#======================================================================== +# We need to enumerate the list of .c to .o lines here. +# +# In the following lines, $(srcdir) refers to the toplevel directory +# containing your extension. If your sources are in a subdirectory, +# you will have to modify the paths to reflect this: +# +# sample.$(OBJEXT): $(srcdir)/generic/sample.c +# $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@ +# +# Setting the VPATH variable to a list of paths will cause the makefile +# to look into these paths when resolving .c to .obj dependencies. +# As necessary, add $(srcdir):$(srcdir)/compat:.... +#======================================================================== + +VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win:$(srcdir)/macosx + +# I would prefer to use $< over $?, but FreeBSD's can't handle it, and +# with only one prereq, $? is sufficient +tkTable.tcl.h: $(srcdir)/library/tkTable.tcl + sed -e '/^\#/d' -e '/^$$/d' -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' < `@CYGPATH@ $?` > '$@' || { rm -f $@; exit 1; } + +.c.@OBJEXT@: + $(COMPILE) -c `@CYGPATH@ $<` -o $@ + +#======================================================================== +# Distribution creation +# You may need to tweak this target to make it work correctly. +#======================================================================== + +#COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar +COMPRESS = tar zcvf $(PKG_DIR).tar.gz $(PKG_DIR) +DIST_ROOT = /tmp/dist +DIST_DIR = $(DIST_ROOT)/$(PKG_DIR) + +DIST_INSTALL_DATA = CPPROG='cp -p' $(INSTALL) -m 644 +DIST_INSTALL_SCRIPT = CPPROG='cp -p' $(INSTALL) -m 755 + +dist-clean: + rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.* + +dist: dist-clean + $(INSTALL_DATA_DIR) $(DIST_DIR) + + # TEA files + $(DIST_INSTALL_DATA) $(srcdir)/Makefile.in \ + $(srcdir)/aclocal.m4 $(srcdir)/configure.ac \ + $(DIST_DIR)/ + $(DIST_INSTALL_SCRIPT) $(srcdir)/configure $(DIST_DIR)/ + + $(INSTALL_DATA_DIR) $(DIST_DIR)/tclconfig + $(DIST_INSTALL_DATA) $(srcdir)/tclconfig/README.txt \ + $(srcdir)/tclconfig/tcl.m4 $(srcdir)/tclconfig/install-sh \ + $(DIST_DIR)/tclconfig/ + + # Extension files + $(DIST_INSTALL_DATA) \ + $(srcdir)/ChangeLog \ + $(srcdir)/README.sha \ + $(srcdir)/license.terms \ + $(srcdir)/README \ + $(srcdir)/pkgIndex.tcl.in \ + $(DIST_DIR)/ + + list='demos doc generic library mac tests unix win'; \ + for p in $$list; do \ + if test -d $(srcdir)/$$p ; then \ + $(INSTALL_DATA_DIR) $(DIST_DIR)/$$p; \ + $(DIST_INSTALL_DATA) $(srcdir)/$$p/* $(DIST_DIR)/$$p/; \ + fi; \ + done + + (cd $(DIST_ROOT); $(COMPRESS);) + +#======================================================================== +# End of user-definable section +#======================================================================== + +#======================================================================== +# Don't modify the file to clean here. Instead, set the "CLEANFILES" +# variable in configure.ac +#======================================================================== + +clean: + -test -z "$(BINARIES)" || rm -f $(BINARIES) + -rm -f *.$(OBJEXT) core *.core + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean: clean + -rm -f *.tab.c + -rm -f $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log config.status + +#======================================================================== +# Install binary object libraries. On Windows this includes both .dll and +# .lib files. Because the .lib files are not explicitly listed anywhere, +# we need to deduce their existence from the .dll file of the same name. +# Library files go into the lib directory. +# In addition, this will generate the pkgIndex.tcl +# file in the install location (assuming it can find a usable tclsh shell) +# +# You should not have to modify this target. +#======================================================================== + +install-lib-binaries: binaries + @$(INSTALL_DATA_DIR) $(DESTDIR)$(pkglibdir) + @list='$(lib_BINARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \ + $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p; \ + ext=`echo $$p|sed -e "s/.*\.//"`; \ + if test "x$$ext" = "xdll"; then \ + lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \ + if test -f $$lib; then \ + echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \ + $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \ + fi; \ + fi; \ + fi; \ + done + @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ + if test -f $(srcdir)/$$p; then \ + destp=`basename $$p`; \ + echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \ + fi; \ + done + @if test "x$(SHARED_BUILD)" = "x1"; then \ + echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \ + $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \ + fi + $(INSTALL_DATA) tktableConfig.sh $(DESTDIR)$(libdir) + +#======================================================================== +# Install binary executables (e.g. .exe files and dependent .dll files) +# This is for files that must go in the bin directory (located next to +# wish and tclsh), like dependent .dll files on Windows. +# +# You should not have to modify this target, except to define bin_BINARIES +# above if necessary. +#======================================================================== + +install-bin-binaries: binaries + @$(INSTALL_DATA_DIR) $(DESTDIR)$(bindir) + @list='$(bin_BINARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \ + fi; \ + done + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +uninstall-binaries: + list='$(lib_BINARIES)'; for p in $$list; do \ + rm -f $(DESTDIR)$(pkglibdir)/$$p; \ + done + list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ + p=`basename $$p`; \ + rm -f $(DESTDIR)$(pkglibdir)/$$p; \ + done + list='$(bin_BINARIES)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/$$p; \ + done + +.PHONY: all binaries clean depend distclean doc install libraries test +.PHONY: gdb gdb-test valgrind valgrindshell + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tktable/README.blt b/tktable/README.blt new file mode 100644 index 0000000..ced2559 --- /dev/null +++ b/tktable/README.blt @@ -0,0 +1,20 @@ +If tkTable is used at the same time as BLT then there are two name +conflicts to be aware of. + +BLT also has a table.n man page. TkTable's man page will still be +available as tkTable.n. + +BLT also has a "table" command. The table command of the last +extension loaded will be in effect. If you need to use both table +commands then eval "rename table blttable" after loading blt and +before loading tkTable, or perhaps "rename table tkTable" if you +load the tkTable extension first. + +In general this shouldn't be a problem as long as you load tkTable +last. The BLT "table" command facilities have been subsumed by the +Tk "grid" command (available in Tk4.1+), so the BLT table should +only be used in legacy code. + +Alternatively, if you want both or have another "table" command, +then change the TBL_COMMAND macro in the makefile before compiling, +and it tkTable will define your named command for the table widget. diff --git a/tktable/README.md b/tktable/README.md new file mode 100644 index 0000000..6774296 --- /dev/null +++ b/tktable/README.md @@ -0,0 +1,2 @@ +# tktable +TKTable Widget. Tcl/Tk 8.5/8.6 TEA compatible. Full support for MacOSX and Windows. Based on Tktable version 2.10 by Jeffrey Hobbs. diff --git a/tktable/README.txt b/tktable/README.txt new file mode 100755 index 0000000..d857716 --- /dev/null +++ b/tktable/README.txt @@ -0,0 +1,149 @@ +/* + * Conceptually based on Tk3 table widget by Roland King (rols@lehman.com) + * + * see ChangeLog file for details + * + * current maintainer: jeff at hobbs org + * + * Copyright 1997-2002, Jeffrey Hobbs (jeff@hobbs.org) + */ + + ************************************* + The Tk Table Widget Version 2.0+ + ************************************* + +INTRODUCTION + +TkTable is a table/matrix widget extension to tk/tcl. +The basic features of the widget are: + + * multi-line cells + * support for embedded windows (one per cell) + * row & column spanning + * variable width columns / height rows (interactively resizable) + * row and column titles + * multiple data sources ((Tcl array || Tcl command) &| internal caching) + * supports standard Tk reliefs, fonts, colors, etc. + * x/y scrollbar support + * 'tag' styles per row, column or cell to change visual appearance + * in-cell editing - returns value back to data source + * support for disabled (read-only) tables or cells (via tags) + * multiple selection modes, with "active" cell + * multiple drawing modes to get optimal performance for larger tables + * optional 'flashes' when things update + * cell validation support + * Works everywhere Tk does (including Windows and Mac!) + * Unicode support (Tk8.1+) + +FINDING THE WIDGET + +0. The newest version is most likely found at: + http://tktable.sourceforge.net/ + http://www.purl.org/net/hobbs/tcl/capp/ + +BUILDING AND INSTALLING THE WIDGET + +1. Uncompress and unpack the distribution + + ON UNIX and OS X: + gzip -cd Tktable<version>.tar.gz | tar xf - + + ON WINDOWS: + use something like WinZip to unpack the archive. + + ON MACINTOSH: + use StuffIt Expander to unstuff the archive. + + This will create a subdirectory tkTable<version> with all the files in it. + +2. Configure + + ON UNIX and OS X: + cd Tktable<version> + ./configure + + tkTable uses information left in tkConfig.sh when you built tk. This + file will be found in $exec_prefix/lib/. You might set the --prefix and + --exec-prefix options of configure if you don't want the default + (/usr/local). If building on multiple unix platforms, the following is + recommended to isolate build conflicts: + mkdir <builddir>/<platform> + cd !$ + /path/to/Tktable<version>/configure + + ON WINDOWS: + + Version 2.8 added support for building in the cygwin environment on + Windows based on TEA (http://www.tcl.tk/doc/tea/). You can retrieve + cygwin from: + http://sources.redhat.com/cygwin/ + + Inside the cygwin environment, you build the same as on Unix. + + Otherwise, hack makefile.vc until it works and compile. It has problems + executing wish from a path with a space in it, but the DLL builds just + fine. A DLL should be available where you found this archive. + +3. Make and Install + + ON UNIX< OS X or WINDOWS (with cygwin): + make + make test (OPTIONAL) + make demo (OPTIONAL) + make install + + ON WINDOWS (makefile.vc): + nmake -f makefile.vc + nmake -f makefile.vc test (OPTIONAL) + nmake -f makefile.vc install + + tkTable is built to comply to the latest tcl package conventions. + There is also a specific "make static" for those who need it. + +4. Use it + + Start a regular wish interpreter, 'load' the library, and use the table. + There are a few test scripts in the demos directory which you can source. + +5. Read the documentation + + There is a Unix manpage and HTML translation provided in the doc/ + subdirectory. These describe the table widget's features and commands + in depth. If something is confusing, just to try it out. + +6. Python users + + There is a library/tktable.py wrapper for use with Python/Tkinter. + +THINGS TO WATCH OUT FOR + +Packing + The table tries not to allocate huge chunks of screen real estate if + you ask it for a lot of rows and columns. You can always stretch out + the frame or explicitly tell it how big it can be. If you want to + stretch the table, remember to pack it with fill both and expand on, + or with grid, give it -sticky news and configure the grid row and column + for some weighting. + +Array + The array elements for the table are of the form array(2,3) etc. Make + sure there are no spaces around the ','. Negative indices are allowed. + +Editing + If you can't edit, remember that the focus model in tk is explicit, so + you need to click on the table or give it the focus command. Just + having a selected cell is not the same thing as being able to edit. + You also need the editing cursor. If you can't get the cursor, make + sure that you actually have a variable assigned to the table, and that + the "state" of the cell is not disabled. + +COMMENTS, BUGS, etc. + +* Please can you send comments and bug reports to the current maintainer + and their best will be done to address them. A mailing list for + tktable discussion is tktable-users@lists.sourceforge.net. + +* If you find a bug, a short piece of Tcl that exercises it would be very + useful, or even better, compile with debugging and specify where it + crashed in that short piece of Tcl. Use the SourceForge site to check + for known bugs or submit new ones. diff --git a/tktable/TODO.txt b/tktable/TODO.txt new file mode 100644 index 0000000..38b79c3 --- /dev/null +++ b/tktable/TODO.txt @@ -0,0 +1,63 @@ +## TODO LIST +## +## updated 1 June 1999, jeff at hobbs org +## +## Any information in here may be out of date. For up-to-date info see: +## http://tktable.sourceforge.net/ +## + +These are recommendations, not all of the same priority, and not +all necessarily will be implemented. If you see something you +feel is important, email me and say so. Very democratic. + +* some sort of textbbox command that will return the size of the + text in a cell, to allow for perfect cell sizing. + +* anchor title areas in different parts of the screen + +* -rowstretchmode fill ignores initial # of rows, or config requests for more. +* interpret 0 rows/cols to be FILL +* add -colstretchmode fill +* scratch stretchmode "fill" in favor of "dynamic" which would monitor + the max extent of row/col (difficult) + +* fix selection routines to properly handle title area movement + +* support smooth scrolling of rows/cols + +* add ability to index by tagname +* overhaul tag mechanism (include way to query for tags on a cell, add + priority) + +* add internal sort procedures +pathName sort -row {the list of rows we want to sort | all} + -col {the list of cols we use for sorting} + -master row,col + -command _command_to_use_ + -type {for each column specifies the type of sort: + ascii | dictionary | integer | real } + -order {for each column specify the order of sort: + increasing | decreasing | none } + +* row/column swap (maybe only in terms of visual remapping) + += BBBB U U GGG SSS +== B B U U G S +==- B BB U U G GGG SSS +== B B U U G G S += BBBB UUU GGGG SSS + +MINOR: + +Windows: With "-colstretchmode last", the scrollbar behaves oddly in + handling the space for the last cell properly when moving the + main part of the scrollbar with the mouse. This seems to be + that even though the scrollbar receives the "set 0.6xxx 1", + the scrollbar immediately jumps back to what the mouse says, + although this isn't a problem in X... + +Windows: when moving windows in "Show Window While Dragging" mode, + the column titles don't refresh properly. + +Windows: When using bitmaps in cells, they occasionally don't redraw + correctly. The work-around is to use -drawmode slow. diff --git a/tktable/aclocal.m4 b/tktable/aclocal.m4 new file mode 100644 index 0000000..0b05739 --- /dev/null +++ b/tktable/aclocal.m4 @@ -0,0 +1,9 @@ +# +# Include the TEA standard macro set +# + +builtin(include,tclconfig/tcl.m4) + +# +# Add here whatever m4 macros you want to define for your package +# diff --git a/tktable/configure b/tktable/configure new file mode 100755 index 0000000..6cd4508 --- /dev/null +++ b/tktable/configure @@ -0,0 +1,10087 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for tktable 2.10. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 </dev/null +exec 6>&1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='tktable' +PACKAGE_TARNAME='tktable' +PACKAGE_VERSION='2.10' +PACKAGE_STRING='tktable 2.10' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='LTLIBOBJS +LIBOBJS +PATCHLEVEL +MINOR_VERSION +MAJOR_VERSION +tktable_STUB_LIB_PATH +tktable_BUILD_STUB_LIB_PATH +tktable_STUB_LIB_SPEC +tktable_BUILD_STUB_LIB_SPEC +tktable_LIB_SPEC +tktable_BUILD_LIB_SPEC +WISH_PROG +TCLSH_PROG +VC_MANIFEST_EMBED_EXE +VC_MANIFEST_EMBED_DLL +RANLIB_STUB +MAKE_STUB_LIB +MAKE_STATIC_LIB +MAKE_SHARED_LIB +MAKE_LIB +TCL_DBGX +LDFLAGS_DEFAULT +CFLAGS_DEFAULT +LD_LIBRARY_PATH_VAR +SHLIB_CFLAGS +SHLIB_LD_LIBS +SHLIB_LD +STLIB_LD +CFLAGS_WARNING +CFLAGS_OPTIMIZE +CFLAGS_DEBUG +RC +CELIB_DIR +AR +STUBS_BUILD +SHARED_BUILD +TCL_THREADS +XMKMF +TK_INCLUDES +TCL_INCLUDES +PKG_OBJECTS +PKG_SOURCES +EGREP +GREP +RANLIB +SET_MAKE +CPP +TK_XINCLUDES +TK_LIBS +TK_STUB_LIB_SPEC +TK_STUB_LIB_FLAG +TK_STUB_LIB_FILE +TK_LIB_SPEC +TK_LIB_FLAG +TK_LIB_FILE +TK_SRC_DIR +TK_BIN_DIR +TK_VERSION +TCL_SHLIB_LD_LIBS +TCL_LD_FLAGS +TCL_EXTRA_CFLAGS +TCL_DEFS +TCL_LIBS +CLEANFILES +OBJEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +TCL_STUB_LIB_SPEC +TCL_STUB_LIB_FLAG +TCL_STUB_LIB_FILE +TCL_LIB_SPEC +TCL_LIB_FLAG +TCL_LIB_FILE +TCL_SRC_DIR +TCL_BIN_DIR +TCL_PATCH_LEVEL +TCL_VERSION +INSTALL_LIBRARY +INSTALL_SCRIPT +INSTALL_PROGRAM +INSTALL_DATA +INSTALL_DATA_DIR +INSTALL +PKG_CFLAGS +PKG_LIBS +PKG_INCLUDES +PKG_HEADERS +PKG_TCL_SOURCES +PKG_STUB_OBJECTS +PKG_STUB_SOURCES +PKG_STUB_LIB_FILE +PKG_LIB_FILE +EXEEXT +CYGPATH +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_tcl +with_tk +with_tclinclude +with_tkinclude +with_x +enable_threads +enable_shared +enable_stubs +enable_64bit +enable_64bit_vis +enable_rpath +enable_wince +with_celib +enable_symbols +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +XMKMF' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures tktable 2.10 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/tktable] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of tktable 2.10:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-threads build with threads (default: on) + --enable-shared build and link with shared libraries (default: on) + --enable-stubs build and link with stub libraries. Always true for + shared builds (default: on) + --enable-64bit enable 64bit support (default: off) + --enable-64bit-vis enable 64bit Sparc VIS support (default: off) + --disable-rpath disable rpath support (default: on) + --enable-wince enable Win/CE support (where applicable) + --enable-symbols build with debugging symbols (default: off) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-tcl directory containing tcl configuration + (tclConfig.sh) + --with-tk directory containing tk configuration (tkConfig.sh) + --with-tclinclude directory containing the public Tcl header files + --with-tkinclude directory containing the public Tk header files + --with-x use the X Window System + --with-celib=DIR use Windows/CE support library from DIR + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + LIBS libraries to pass to the linker, e.g. -l<library> + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if + you have headers in a nonstandard directory <include dir> + CPP C preprocessor + XMKMF Path to xmkmf, Makefile generator for X Window System + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +tktable configure 2.10 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case <limits.h> declares $2. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by tktable $as_me 2.10, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +#-------------------------------------------------------------------- +# Call TEA_INIT as the first TEA_ macro to set up initial vars. +# This will define a ${TEA_PLATFORM} variable == "unix" or "windows" +# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. +#-------------------------------------------------------------------- + + + TEA_VERSION="3.13" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking TEA configuration" >&5 +$as_echo_n "checking TEA configuration... " >&6; } + if test x"${PACKAGE_NAME}" = x ; then + as_fn_error $? " +The PACKAGE_NAME variable must be defined by your TEA configure.ac" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok (TEA ${TEA_VERSION})" >&5 +$as_echo "ok (TEA ${TEA_VERSION})" >&6; } + + # If the user did not set CFLAGS, set it now to keep macros + # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". + if test "${CFLAGS+set}" != "set" ; then + CFLAGS="" + fi + + case "`uname -s`" in + *win32*|*WIN32*|*MINGW32_*|*MINGW64_*) + # Extract the first word of "cygpath", so it can be a program name with args. +set dummy cygpath; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CYGPATH+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CYGPATH"; then + ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CYGPATH="cygpath -m" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" +fi +fi +CYGPATH=$ac_cv_prog_CYGPATH +if test -n "$CYGPATH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 +$as_echo "$CYGPATH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + EXEEXT=".exe" + TEA_PLATFORM="windows" + ;; + *CYGWIN_*) + EXEEXT=".exe" + # CYGPATH and TEA_PLATFORM are determined later in LOAD_TCLCONFIG + ;; + *) + CYGPATH=echo + # Maybe we are cross-compiling.... + case ${host_alias} in + *mingw32*) + EXEEXT=".exe" + TEA_PLATFORM="windows" + ;; + *) + EXEEXT="" + TEA_PLATFORM="unix" + ;; + esac + ;; + esac + + # Check if exec_prefix is set. If not use fall back to prefix. + # Note when adjusted, so that TEA_PREFIX can correct for this. + # This is needed for recursive configures, since autoconf propagates + # $prefix, but not $exec_prefix (doh!). + if test x$exec_prefix = xNONE ; then + exec_prefix_default=yes + exec_prefix=$prefix + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&5 +$as_echo "$as_me: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&6;} + + + + + # This package name must be replaced statically for AC_SUBST to work + + # Substitute STUB_LIB_FILE in case package creates a stub library too. + + + # We AC_SUBST these here to ensure they are subst'ed, + # in case the user doesn't call TEA_ADD_... + + + + + + + + + # Configure the installer. + + INSTALL='$(SHELL) $(srcdir)/tclconfig/install-sh -c' + INSTALL_DATA_DIR='${INSTALL} -d -m 755' + INSTALL_DATA='${INSTALL} -m 644' + INSTALL_PROGRAM='${INSTALL} -m 755' + INSTALL_SCRIPT='${INSTALL} -m 755' + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5 +$as_echo_n "checking system version... " >&6; } +if ${tcl_cv_sys_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + + # TEA specific: + if test "${TEA_PLATFORM}" = "windows" ; then + tcl_cv_sys_version=windows + else + tcl_cv_sys_version=`uname -s`-`uname -r` + if test "$?" -ne 0 ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 +$as_echo "$as_me: WARNING: can't find uname command" >&2;} + tcl_cv_sys_version=unknown + else + if test "`uname -s`" = "AIX" ; then + tcl_cv_sys_version=AIX-`uname -v`.`uname -r` + fi + fi + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 +$as_echo "$tcl_cv_sys_version" >&6; } + system=$tcl_cv_sys_version + + case $system in + HP-UX-*) INSTALL_LIBRARY='${INSTALL} -m 755' ;; + *) INSTALL_LIBRARY='${INSTALL} -m 644' ;; + esac + + + + + + + + + + +ac_aux_dir= +for ac_dir in tclconfig "$srcdir"/tclconfig; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in tclconfig \"$srcdir\"/tclconfig" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +#-------------------------------------------------------------------- +# Load the tclConfig.sh file +#-------------------------------------------------------------------- + + + + # + # Ok, lets find the tcl configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tcl + # + + if test x"${no_tcl}" = x ; then + # we reset no_tcl in case something fails here + no_tcl=true + +# Check whether --with-tcl was given. +if test "${with_tcl+set}" = set; then : + withval=$with_tcl; with_tclconfig="${withval}" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5 +$as_echo_n "checking for Tcl configuration... " >&6; } + if ${ac_cv_c_tclconfig+:} false; then : + $as_echo_n "(cached) " >&6 +else + + + # First check to see if --with-tcl was specified. + if test x"${with_tclconfig}" != x ; then + case "${with_tclconfig}" in + */tclConfig.sh ) + if test -f "${with_tclconfig}"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5 +$as_echo "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;} + with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tclconfig}/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" + else + as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5 + fi + fi + + # then check for a private Tcl installation + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ../tcl \ + `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \ + ../../tcl \ + `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \ + ../../../tcl \ + `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks/Tcl.framework 2>/dev/null` \ + `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Network/Library/Frameworks/Tcl.framework 2>/dev/null` \ + `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Tcl.framework 2>/dev/null` \ + ; do + if test -f "$i/Tcl.framework/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" + break + fi + done + fi + + # TEA specific: on Windows, check in common installation locations + if test "${TEA_PLATFORM}" = "windows" \ + -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d C:/Tcl/lib 2>/dev/null` \ + `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/pkg/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + `ls -d /usr/lib/tcl8.6 2>/dev/null` \ + `ls -d /usr/lib/tcl8.5 2>/dev/null` \ + `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ + `ls -d /usr/local/lib/tcl8.5 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ${srcdir}/../tcl \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + +fi + + + if test x"${ac_cv_c_tclconfig}" = x ; then + TCL_BIN_DIR="# no Tcl configs found" + as_fn_error $? "Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" "$LINENO" 5 + else + no_tcl= + TCL_BIN_DIR="${ac_cv_c_tclconfig}" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5 +$as_echo "found ${TCL_BIN_DIR}/tclConfig.sh" >&6; } + fi + fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdio.h> +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5 +$as_echo_n "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... " >&6; } + + if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5 +$as_echo "loading" >&6; } + . "${TCL_BIN_DIR}/tclConfig.sh" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 +$as_echo "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; } + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" + eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" + + # If the TCL_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TCL_LIB_SPEC will be set to the value + # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC + # instead of TCL_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" + TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" + TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tcl.framework installed in an arbitrary location. + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then + for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ + "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then + TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" + break + fi + done + fi + if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then + TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" + TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" + eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" + eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" + eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking platform" >&5 +$as_echo_n "checking platform... " >&6; } + hold_cc=$CC; CC="$TCL_CC" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + #ifdef _WIN32 + #error win32 + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + TEA_PLATFORM="unix" + CYGPATH=echo + +else + + TEA_PLATFORM="windows" + # Extract the first word of "cygpath", so it can be a program name with args. +set dummy cygpath; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CYGPATH+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CYGPATH"; then + ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CYGPATH="cygpath -m" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" +fi +fi +CYGPATH=$ac_cv_prog_CYGPATH +if test -n "$CYGPATH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 +$as_echo "$CYGPATH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CC=$hold_cc + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEA_PLATFORM" >&5 +$as_echo "$TEA_PLATFORM" >&6; } + + # The BUILD_$pkg is to define the correct extern storage class + # handling when making this package + +cat >>confdefs.h <<_ACEOF +#define BUILD_${PACKAGE_NAME} /**/ +_ACEOF + + # Do this here as we have fully defined TEA_PLATFORM now + if test "${TEA_PLATFORM}" = "windows" ; then + EXEEXT=".exe" + CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" + fi + + # TEA specific: + + + + + + + + +#-------------------------------------------------------------------- +# Load the tkConfig.sh file if necessary (Tk extension) +#-------------------------------------------------------------------- + + + # + # Ok, lets find the tk configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tk + # + + if test x"${no_tk}" = x ; then + # we reset no_tk in case something fails here + no_tk=true + +# Check whether --with-tk was given. +if test "${with_tk+set}" = set; then : + withval=$with_tk; with_tkconfig="${withval}" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tk configuration" >&5 +$as_echo_n "checking for Tk configuration... " >&6; } + if ${ac_cv_c_tkconfig+:} false; then : + $as_echo_n "(cached) " >&6 +else + + + # First check to see if --with-tkconfig was specified. + if test x"${with_tkconfig}" != x ; then + case "${with_tkconfig}" in + */tkConfig.sh ) + if test -f "${with_tkconfig}"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself" >&5 +$as_echo "$as_me: WARNING: --with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself" >&2;} + with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tkconfig}/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`" + else + as_fn_error $? "${with_tkconfig} directory doesn't contain tkConfig.sh" "$LINENO" 5 + fi + fi + + # then check for a private Tk library + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in \ + ../tk \ + `ls -dr ../tk[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../tk[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../tk[8-9].[0-9]* 2>/dev/null` \ + ../../tk \ + `ls -dr ../../tk[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../tk[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../tk[8-9].[0-9]* 2>/dev/null` \ + ../../../tk \ + `ls -dr ../../../tk[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../../tk[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../../tk[8-9].[0-9]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks/Tcl.framework 2>/dev/null` \ + `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Network/Library/Frameworks/Tcl.framework 2>/dev/null` \ + `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Tcl.framework 2>/dev/null` \ + ; do + if test -f "$i/Tk.framework/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/pkg/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + `ls -d /usr/lib/tk8.6 2>/dev/null` \ + `ls -d /usr/lib/tk8.5 2>/dev/null` \ + `ls -d /usr/local/lib/tk8.6 2>/dev/null` \ + `ls -d /usr/local/lib/tk8.5 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tk8.6 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tk8.5 2>/dev/null` \ + ; do + if test -f "$i/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # TEA specific: on Windows, check in common installation locations + if test "${TEA_PLATFORM}" = "windows" \ + -a x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d C:/Tcl/lib 2>/dev/null` \ + `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ + ; do + if test -f "$i/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in \ + ${srcdir}/../tk \ + `ls -dr ${srcdir}/../tk[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tk[8-9].[0-9] 2>/dev/null` \ + `ls -dr ${srcdir}/../tk[8-9].[0-9]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + +fi + + + if test x"${ac_cv_c_tkconfig}" = x ; then + TK_BIN_DIR="# no Tk configs found" + as_fn_error $? "Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh" "$LINENO" 5 + else + no_tk= + TK_BIN_DIR="${ac_cv_c_tkconfig}" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found ${TK_BIN_DIR}/tkConfig.sh" >&5 +$as_echo "found ${TK_BIN_DIR}/tkConfig.sh" >&6; } + fi + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of ${TK_BIN_DIR}/tkConfig.sh" >&5 +$as_echo_n "checking for existence of ${TK_BIN_DIR}/tkConfig.sh... " >&6; } + + if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5 +$as_echo "loading" >&6; } + . "${TK_BIN_DIR}/tkConfig.sh" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: could not find ${TK_BIN_DIR}/tkConfig.sh" >&5 +$as_echo "could not find ${TK_BIN_DIR}/tkConfig.sh" >&6; } + fi + + # eval is required to do the TK_DBGX substitution + eval "TK_LIB_FILE=\"${TK_LIB_FILE}\"" + eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\"" + + # If the TK_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TK_LIB_SPEC will be set to the value + # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC + # instead of TK_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TK_BIN_DIR}/Makefile" ; then + TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}" + TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}" + TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tk was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tk.framework installed in an arbitrary location. + case ${TK_DEFS} in + *TK_FRAMEWORK*) + if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then + for i in "`cd "${TK_BIN_DIR}"; pwd`" \ + "`cd "${TK_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then + TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}" + break + fi + done + fi + if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then + TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}" + TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TK_DBGX substitution + eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\"" + eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\"" + eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\"" + eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\"" + + # TEA specific: Ensure windowingsystem is defined + if test "${TEA_PLATFORM}" = "unix" ; then + case ${TK_DEFS} in + *MAC_OSX_TK*) + +$as_echo "#define MAC_OSX_TK 1" >>confdefs.h + + TEA_WINDOWINGSYSTEM="aqua" + ;; + *) + TEA_WINDOWINGSYSTEM="x11" + ;; + esac + elif test "${TEA_PLATFORM}" = "windows" ; then + TEA_WINDOWINGSYSTEM="win32" + fi + + + + + + + + + + + + + + # TEA specific: + + + + +#----------------------------------------------------------------------- +# Handle the --prefix=... option by defaulting to what Tcl gave. +# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. +#----------------------------------------------------------------------- + + + if test "${prefix}" = "NONE"; then + prefix_default=yes + if test x"${TCL_PREFIX}" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&5 +$as_echo "$as_me: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&6;} + prefix=${TCL_PREFIX} + else + { $as_echo "$as_me:${as_lineno-$LINENO}: --prefix defaulting to /usr/local" >&5 +$as_echo "$as_me: --prefix defaulting to /usr/local" >&6;} + prefix=/usr/local + fi + fi + if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ + -o x"${exec_prefix_default}" = x"yes" ; then + if test x"${TCL_EXEC_PREFIX}" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&5 +$as_echo "$as_me: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&6;} + exec_prefix=${TCL_EXEC_PREFIX} + else + { $as_echo "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to ${prefix}" >&5 +$as_echo "$as_me: --exec-prefix defaulting to ${prefix}" >&6;} + exec_prefix=$prefix + fi + fi + + +#----------------------------------------------------------------------- +# Standard compiler checks. +# This sets up CC by using the CC env var, or looks for gcc otherwise. +# This also calls AC_PROG_CC and a few others to create the basic setup +# necessary to compile executables. +#----------------------------------------------------------------------- + + + # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) + # in this macro, they need to go into TEA_SETUP_COMPILER instead. + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + #-------------------------------------------------------------------- + # Checks to see if the make program sets the $MAKE variable. + #-------------------------------------------------------------------- + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + + + #-------------------------------------------------------------------- + # Find ranlib + #-------------------------------------------------------------------- + + if test -n "$ac_tool_prefix"; then + # 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + + #-------------------------------------------------------------------- + # Determines the correct binary file extension (.o, .obj, .exe etc.) + #-------------------------------------------------------------------- + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. + + + #------------------------------------------------------------------------ + # If we're using GCC, see if the compiler understands -pipe. If so, use it. + # It makes compiling go faster. (This is only a performance feature.) + #------------------------------------------------------------------------ + + if test -z "$no_pipe" -a -n "$GCC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe" >&5 +$as_echo_n "checking if the compiler understands -pipe... " >&6; } +if ${tcl_cv_cc_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_cc_pipe=yes +else + tcl_cv_cc_pipe=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe" >&5 +$as_echo "$tcl_cv_cc_pipe" >&6; } + if test $tcl_cv_cc_pipe = yes; then + CFLAGS="$CFLAGS -pipe" + fi + fi + + #-------------------------------------------------------------------- + # Common compiler flag setup + #-------------------------------------------------------------------- + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <sys/param.h> + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <sys/param.h> + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <limits.h> + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <limits.h> + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + + +#----------------------------------------------------------------------- +# __CHANGE__ +# Specify the C source files to compile in TEA_ADD_SOURCES, +# public headers that need to be installed in TEA_ADD_HEADERS, +# stub library C source files to compile in TEA_ADD_STUB_SOURCES, +# and runtime Tcl library files in TEA_ADD_TCL_SOURCES. +# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS +# and PKG_TCL_SOURCES. +#----------------------------------------------------------------------- + + + vars="tkTable.c tkTableWin.c tkTableTag.c tkTableEdit.c + tkTableCell.c tkTableCellSort.c tkTableCmds.c tkTableUtil.c" + for i in $vars; do + case $i in + \$*) + # allow $-var names + PKG_SOURCES="$PKG_SOURCES $i" + PKG_OBJECTS="$PKG_OBJECTS $i" + ;; + *) + # check for existence - allows for generic/win/unix VPATH + # To add more dirs here (like 'src'), you have to update VPATH + # in Makefile.in as well + if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ + -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ + -a ! -f "${srcdir}/macosx/$i" \ + ; then + as_fn_error $? "could not find source file '$i'" "$LINENO" 5 + fi + PKG_SOURCES="$PKG_SOURCES $i" + # this assumes it is in a VPATH dir + i=`basename $i` + # handle user calling this before or after TEA_SETUP_COMPILER + if test x"${OBJEXT}" != x ; then + j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" + else + j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" + fi + PKG_OBJECTS="$PKG_OBJECTS $j" + ;; + esac + done + + + + + vars="" + for i in $vars; do + # check for existence, be strict because it is installed + if test ! -f "${srcdir}/$i" ; then + as_fn_error $? "could not find header file '${srcdir}/$i'" "$LINENO" 5 + fi + PKG_HEADERS="$PKG_HEADERS $i" + done + + + + vars="-I. -I${srcdir}/generic" + for i in $vars; do + PKG_INCLUDES="$PKG_INCLUDES $i" + done + + + + vars="" + for i in $vars; do + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then + # Convert foo.lib to -lfoo for GCC. No-op if not *.lib + i=`echo "$i" | sed -e 's/^\([^-].*\)\.lib$/-l\1/i'` + fi + PKG_LIBS="$PKG_LIBS $i" + done + + + + PKG_CFLAGS="$PKG_CFLAGS " + + + + vars="" + for i in $vars; do + # check for existence - allows for generic/win/unix VPATH + if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ + -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ + -a ! -f "${srcdir}/macosx/$i" \ + ; then + as_fn_error $? "could not find stub source file '$i'" "$LINENO" 5 + fi + PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i" + # this assumes it is in a VPATH dir + i=`basename $i` + # handle user calling this before or after TEA_SETUP_COMPILER + if test x"${OBJEXT}" != x ; then + j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" + else + j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" + fi + PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j" + done + + + + + vars="library/tkTable.tcl library/tktable.py" + for i in $vars; do + # check for existence, be strict because it is installed + if test ! -f "${srcdir}/$i" ; then + as_fn_error $? "could not find tcl source file '${srcdir}/$i'" "$LINENO" 5 + fi + PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" + done + + + +#-------------------------------------------------------------------- +# __CHANGE__ +# +# You can add more files to clean if your extension creates any extra +# files by extending CLEANFILES. +# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure +# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. +# +# A few miscellaneous platform-specific items: +# TEA_ADD_* any platform specific compiler/build info here. +#-------------------------------------------------------------------- + +#CLEANFILES="$CLEANFILES pkgIndex.tcl" +if test "${TEA_PLATFORM}" = "windows" ; then + # Ensure no empty if clauses + : + #TEA_ADD_SOURCES([win/winFile.c]) + #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"]) +else + # Ensure no empty else clauses + : + #TEA_ADD_SOURCES([unix/unixFile.c]) + #TEA_ADD_LIBS([-lsuperfly]) +fi + +#-------------------------------------------------------------------- +# __CHANGE__ +# Choose which headers you need. Extension authors should try very +# hard to only rely on the Tcl public header files. Internal headers +# contain private data structures and are subject to change without +# notice. +# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG +#-------------------------------------------------------------------- + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl public headers" >&5 +$as_echo_n "checking for Tcl public headers... " >&6; } + + +# Check whether --with-tclinclude was given. +if test "${with_tclinclude+set}" = set; then : + withval=$with_tclinclude; with_tclinclude=${withval} +fi + + + if ${ac_cv_c_tclh+:} false; then : + $as_echo_n "(cached) " >&6 +else + + # Use the value from --with-tclinclude, if it was given + + if test x"${with_tclinclude}" != x ; then + if test -f "${with_tclinclude}/tcl.h" ; then + ac_cv_c_tclh=${with_tclinclude} + else + as_fn_error $? "${with_tclinclude} directory does not contain tcl.h" "$LINENO" 5 + fi + else + list="" + if test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use + # the framework's Headers directory + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" + ;; + esac + fi + + # Look in the source dir only if Tcl is not installed, + # and in that situation, look there before installed locations. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" + fi + + # Check order: pkg --prefix location, Tcl's --prefix location, + # relative to directory of tclConfig.sh. + + eval "temp_includedir=${includedir}" + list="$list \ + `ls -d ${temp_includedir} 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" + if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then + list="$list /usr/local/include /usr/include" + if test x"${TCL_INCLUDE_SPEC}" != x ; then + d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` + list="$list `ls -d ${d} 2>/dev/null`" + fi + fi + for i in $list ; do + if test -f "$i/tcl.h" ; then + ac_cv_c_tclh=$i + break + fi + done + fi + +fi + + + # Print a message based on how we determined the include path + + if test x"${ac_cv_c_tclh}" = x ; then + as_fn_error $? "tcl.h not found. Please specify its location with --with-tclinclude" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_cv_c_tclh}" >&5 +$as_echo "${ac_cv_c_tclh}" >&6; } + fi + + # Convert to a native path and substitute into the output files. + + INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` + + TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + + +#TEA_PRIVATE_TCL_HEADERS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tk public headers" >&5 +$as_echo_n "checking for Tk public headers... " >&6; } + + +# Check whether --with-tkinclude was given. +if test "${with_tkinclude+set}" = set; then : + withval=$with_tkinclude; with_tkinclude=${withval} +fi + + + if ${ac_cv_c_tkh+:} false; then : + $as_echo_n "(cached) " >&6 +else + + # Use the value from --with-tkinclude, if it was given + + if test x"${with_tkinclude}" != x ; then + if test -f "${with_tkinclude}/tk.h" ; then + ac_cv_c_tkh=${with_tkinclude} + else + as_fn_error $? "${with_tkinclude} directory does not contain tk.h" "$LINENO" 5 + fi + else + list="" + if test "`uname -s`" = "Darwin"; then + # If Tk was built as a framework, attempt to use + # the framework's Headers directory. + case ${TK_DEFS} in + *TK_FRAMEWORK*) + list="`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`" + ;; + esac + fi + + # Look in the source dir only if Tk is not installed, + # and in that situation, look there before installed locations. + if test -f "${TK_BIN_DIR}/Makefile" ; then + list="$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`" + fi + + # Check order: pkg --prefix location, Tk's --prefix location, + # relative to directory of tkConfig.sh, Tcl's --prefix location, + # relative to directory of tclConfig.sh. + + eval "temp_includedir=${includedir}" + list="$list \ + `ls -d ${temp_includedir} 2>/dev/null` \ + `ls -d ${TK_PREFIX}/include 2>/dev/null` \ + `ls -d ${TK_BIN_DIR}/../include 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" + if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then + list="$list /usr/local/include /usr/include" + if test x"${TK_INCLUDE_SPEC}" != x ; then + d=`echo "${TK_INCLUDE_SPEC}" | sed -e 's/^-I//'` + list="$list `ls -d ${d} 2>/dev/null`" + fi + fi + for i in $list ; do + if test -f "$i/tk.h" ; then + ac_cv_c_tkh=$i + break + fi + done + fi + +fi + + + # Print a message based on how we determined the include path + + if test x"${ac_cv_c_tkh}" = x ; then + as_fn_error $? "tk.h not found. Please specify its location with --with-tkinclude" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_cv_c_tkh}" >&5 +$as_echo "${ac_cv_c_tkh}" >&6; } + fi + + # Convert to a native path and substitute into the output files. + + INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}` + + TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + + + if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then + # On Windows and Aqua, we need the X compat headers + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X11 header files" >&5 +$as_echo_n "checking for X11 header files... " >&6; } + if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then + INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`" + TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${INCLUDE_DIR_NATIVE}" >&5 +$as_echo "${INCLUDE_DIR_NATIVE}" >&6; } + fi + +#TEA_PRIVATE_TK_HEADERS + + if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5 +$as_echo_n "checking for X... " >&6; } + + +# Check whether --with-x was given. +if test "${with_x+set}" = set; then : + withval=$with_x; +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + case $x_includes,$x_libraries in #( + *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( + *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then : + $as_echo_n "(cached) " >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -f -r conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + cat >Imakefile <<'_ACEOF' +incroot: + @echo incroot='${INCROOT}' +usrlibdir: + @echo usrlibdir='${USRLIBDIR}' +libdir: + @echo libdir='${LIBDIR}' +_ACEOF + if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. + for ac_var in incroot usrlibdir libdir; do + eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" + done + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl dylib la dll; do + if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && + test -f "$ac_im_libdir/libX11.$ac_extension"; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ac_x_includes= ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /usr/lib64 | /lib | /lib64) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -f -r conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R7/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R7 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R7/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R7 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Xlib.h. + # First, try using that file with no special directory specified. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <X11/Xlib.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # We can compile using X headers with no special include directory. +ac_x_includes= +else + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Xlib.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lX11 $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <X11/Xlib.h> +int +main () +{ +XrmInitialize () + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + LIBS=$ac_save_LIBS +for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl dylib la dll; do + if test -r "$ac_dir/libX11.$ac_extension"; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +case $ac_x_includes,$ac_x_libraries in #( + no,* | *,no | *\'*) + # Didn't find X, or a directory has "'" in its name. + ac_cv_have_x="have_x=no";; #( + *) + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$ac_x_includes'\ + ac_x_libraries='$ac_x_libraries'" +esac +fi +;; #( + *) have_x=yes;; + esac + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 +$as_echo "$have_x" >&6; } + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$x_includes'\ + ac_x_libraries='$x_libraries'" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 +$as_echo "libraries $x_libraries, headers $x_includes" >&6; } +fi + + not_really_there="" + if test "$no_x" = ""; then + if test "$x_includes" = ""; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <X11/Xlib.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + not_really_there="yes" +fi +rm -f conftest.err conftest.i conftest.$ac_ext + else + if test ! -r $x_includes/X11/Xlib.h; then + not_really_there="yes" + fi + fi + fi + if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X11 header files" >&5 +$as_echo_n "checking for X11 header files... " >&6; } + found_xincludes="no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <X11/Xlib.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + found_xincludes="yes" +else + found_xincludes="no" +fi +rm -f conftest.err conftest.i conftest.$ac_ext + if test "$found_xincludes" = "no"; then + dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include" + for i in $dirs ; do + if test -r $i/X11/Xlib.h; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $i" >&5 +$as_echo "$i" >&6; } + XINCLUDES=" -I$i" + found_xincludes="yes" + break + fi + done + fi + else + if test "$x_includes" != ""; then + XINCLUDES="-I$x_includes" + found_xincludes="yes" + fi + fi + if test "$found_xincludes" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: couldn't find any!" >&5 +$as_echo "couldn't find any!" >&6; } + fi + + if test "$no_x" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X11 libraries" >&5 +$as_echo_n "checking for X11 libraries... " >&6; } + XLIBSW=nope + dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib" + for i in $dirs ; do + if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $i" >&5 +$as_echo "$i" >&6; } + XLIBSW="-L$i -lX11" + x_libraries="$i" + break + fi + done + else + if test "$x_libraries" = ""; then + XLIBSW=-lX11 + else + XLIBSW="-L$x_libraries -lX11" + fi + fi + if test "$XLIBSW" = nope ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XCreateWindow in -lXwindow" >&5 +$as_echo_n "checking for XCreateWindow in -lXwindow... " >&6; } +if ${ac_cv_lib_Xwindow_XCreateWindow+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXwindow $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XCreateWindow (); +int +main () +{ +return XCreateWindow (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_Xwindow_XCreateWindow=yes +else + ac_cv_lib_Xwindow_XCreateWindow=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xwindow_XCreateWindow" >&5 +$as_echo "$ac_cv_lib_Xwindow_XCreateWindow" >&6; } +if test "x$ac_cv_lib_Xwindow_XCreateWindow" = xyes; then : + XLIBSW=-lXwindow +fi + + fi + if test "$XLIBSW" = nope ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: could not find any! Using -lX11." >&5 +$as_echo "could not find any! Using -lX11." >&6; } + XLIBSW=-lX11 + fi + # TEA specific: + if test x"${XLIBSW}" != x ; then + PKG_LIBS="${PKG_LIBS} ${XLIBSW}" + fi + + fi + + +#-------------------------------------------------------------------- +# Check whether --enable-threads or --disable-threads was given. +# This auto-enables if Tcl was compiled threaded. +#-------------------------------------------------------------------- + + + # Check whether --enable-threads was given. +if test "${enable_threads+set}" = set; then : + enableval=$enable_threads; tcl_ok=$enableval +else + tcl_ok=yes +fi + + + if test "${enable_threads+set}" = set; then + enableval="$enable_threads" + tcl_ok=$enableval + else + tcl_ok=yes + fi + + if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then + TCL_THREADS=1 + + if test "${TEA_PLATFORM}" != "windows" ; then + # We are always OK on Windows, so check what this platform wants: + + # USE_THREAD_ALLOC tells us to try the special thread-based + # allocator that significantly reduces lock contention + +$as_echo "#define USE_THREAD_ALLOC 1" >>confdefs.h + + +$as_echo "#define _REENTRANT 1" >>confdefs.h + + if test "`uname -s`" = "SunOS" ; then + +$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + fi + +$as_echo "#define _THREAD_SAFE 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5 +$as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_init (); +int +main () +{ +return pthread_mutex_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_pthread_mutex_init=yes +else + ac_cv_lib_pthread_pthread_mutex_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; } +if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then : + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "no"; then + # Check a little harder for __pthread_mutex_init in the same + # library, as some systems hide it there until pthread.h is + # defined. We could alternatively do an AC_TRY_COMPILE with + # pthread.h, but that will work with libpthread really doesn't + # exist, like AIX 4.2. [Bug: 4359] + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5 +$as_echo_n "checking for __pthread_mutex_init in -lpthread... " >&6; } +if ${ac_cv_lib_pthread___pthread_mutex_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __pthread_mutex_init (); +int +main () +{ +return __pthread_mutex_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread___pthread_mutex_init=yes +else + ac_cv_lib_pthread___pthread_mutex_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5 +$as_echo "$ac_cv_lib_pthread___pthread_mutex_init" >&6; } +if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes; then : + tcl_ok=yes +else + tcl_ok=no +fi + + fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthread" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5 +$as_echo_n "checking for pthread_mutex_init in -lpthreads... " >&6; } +if ${ac_cv_lib_pthreads_pthread_mutex_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthreads $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_init (); +int +main () +{ +return pthread_mutex_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthreads_pthread_mutex_init=yes +else + ac_cv_lib_pthreads_pthread_mutex_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5 +$as_echo "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; } +if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes; then : + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthreads" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5 +$as_echo_n "checking for pthread_mutex_init in -lc... " >&6; } +if ${ac_cv_lib_c_pthread_mutex_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_init (); +int +main () +{ +return pthread_mutex_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_c_pthread_mutex_init=yes +else + ac_cv_lib_c_pthread_mutex_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5 +$as_echo "$ac_cv_lib_c_pthread_mutex_init" >&6; } +if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes; then : + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5 +$as_echo_n "checking for pthread_mutex_init in -lc_r... " >&6; } +if ${ac_cv_lib_c_r_pthread_mutex_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc_r $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_init (); +int +main () +{ +return pthread_mutex_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_c_r_pthread_mutex_init=yes +else + ac_cv_lib_c_r_pthread_mutex_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5 +$as_echo "$ac_cv_lib_c_r_pthread_mutex_init" >&6; } +if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes; then : + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -pthread" + else + TCL_THREADS=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&5 +$as_echo "$as_me: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&2;} + fi + fi + fi + fi + fi + else + TCL_THREADS=0 + fi + # Do checking message here to not mess up interleaved configure output + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for building with threads" >&5 +$as_echo_n "checking for building with threads... " >&6; } + if test "${TCL_THREADS}" = 1; then + +$as_echo "#define TCL_THREADS 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5 +$as_echo "yes (default)" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + # TCL_THREADS sanity checking. See if our request for building with + # threads is the same as the way Tcl was built. If not, warn the user. + case ${TCL_DEFS} in + *THREADS=1*) + if test "${TCL_THREADS}" = "0"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: + Building ${PACKAGE_NAME} without threads enabled, but building against Tcl + that IS thread-enabled. It is recommended to use --enable-threads." >&5 +$as_echo "$as_me: WARNING: + Building ${PACKAGE_NAME} without threads enabled, but building against Tcl + that IS thread-enabled. It is recommended to use --enable-threads." >&2;} + fi + ;; + esac + + + +#-------------------------------------------------------------------- +# The statement below defines a collection of symbols related to +# building as a shared library instead of a static library. +#-------------------------------------------------------------------- + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5 +$as_echo_n "checking how to build libraries... " >&6; } + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; shared_ok=$enableval +else + shared_ok=yes +fi + + + if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + shared_ok=$enableval + else + shared_ok=yes + fi + + # Check whether --enable-stubs was given. +if test "${enable_stubs+set}" = set; then : + enableval=$enable_stubs; stubs_ok=$enableval +else + stubs_ok=yes +fi + + + if test "${enable_stubs+set}" = set; then + enableval="$enable_stubs" + stubs_ok=$enableval + else + stubs_ok=yes + fi + + # Stubs are always enabled for shared builds + if test "$shared_ok" = "yes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: shared" >&5 +$as_echo "shared" >&6; } + SHARED_BUILD=1 + STUBS_BUILD=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5 +$as_echo "static" >&6; } + SHARED_BUILD=0 + +$as_echo "#define STATIC_BUILD 1" >>confdefs.h + + if test "$stubs_ok" = "yes" ; then + STUBS_BUILD=1 + else + STUBS_BUILD=0 + fi + fi + if test "${STUBS_BUILD}" = "1" ; then + +$as_echo "#define USE_TCL_STUBS 1" >>confdefs.h + + +$as_echo "#define USE_TCLOO_STUBS 1" >>confdefs.h + + if test "${TEA_WINDOWINGSYSTEM}" != ""; then + +$as_echo "#define USE_TK_STUBS 1" >>confdefs.h + + fi + fi + + + + + +#-------------------------------------------------------------------- +# This macro figures out what flags to use with the compiler/linker +# when building shared/static debug/optimized objects. This information +# can be taken from the tclConfig.sh file, but this figures it all out. +#-------------------------------------------------------------------- + +if test -n "$ac_tool_prefix"; then + # 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + + + + # Step 0.a: Enable 64 bit support? + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5 +$as_echo_n "checking if 64bit support is requested... " >&6; } + # Check whether --enable-64bit was given. +if test "${enable_64bit+set}" = set; then : + enableval=$enable_64bit; do64bit=$enableval +else + do64bit=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5 +$as_echo "$do64bit" >&6; } + + # Step 0.b: Enable Solaris 64 bit VIS support? + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested" >&5 +$as_echo_n "checking if 64bit Sparc VIS support is requested... " >&6; } + # Check whether --enable-64bit-vis was given. +if test "${enable_64bit_vis+set}" = set; then : + enableval=$enable_64bit_vis; do64bitVIS=$enableval +else + do64bitVIS=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bitVIS" >&5 +$as_echo "$do64bitVIS" >&6; } + # Force 64bit on with VIS + if test "$do64bitVIS" = "yes"; then : + do64bit=yes +fi + + # Step 0.c: Check if visibility support is available. Do this here so + # that platform specific alternatives can be used below if this fails. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \"hidden\"" >&5 +$as_echo_n "checking if compiler supports visibility \"hidden\"... " >&6; } +if ${tcl_cv_cc_visibility_hidden+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + extern __attribute__((__visibility__("hidden"))) void f(void); + void f(void) {} +int +main () +{ +f(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_cc_visibility_hidden=yes +else + tcl_cv_cc_visibility_hidden=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden" >&5 +$as_echo "$tcl_cv_cc_visibility_hidden" >&6; } + if test $tcl_cv_cc_visibility_hidden = yes; then : + + +$as_echo "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h + + +$as_echo "#define HAVE_HIDDEN 1" >>confdefs.h + + +fi + + # Step 0.d: Disable -rpath support? + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if rpath support is requested" >&5 +$as_echo_n "checking if rpath support is requested... " >&6; } + # Check whether --enable-rpath was given. +if test "${enable_rpath+set}" = set; then : + enableval=$enable_rpath; doRpath=$enableval +else + doRpath=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doRpath" >&5 +$as_echo "$doRpath" >&6; } + + # TEA specific: Cross-compiling options for Windows/CE builds? + + if test "${TEA_PLATFORM}" = windows; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Windows/CE build is requested" >&5 +$as_echo_n "checking if Windows/CE build is requested... " >&6; } + # Check whether --enable-wince was given. +if test "${enable_wince+set}" = set; then : + enableval=$enable_wince; doWince=$enableval +else + doWince=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doWince" >&5 +$as_echo "$doWince" >&6; } + +fi + + # Set the variable "system" to hold the name and version number + # for the system. + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5 +$as_echo_n "checking system version... " >&6; } +if ${tcl_cv_sys_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + + # TEA specific: + if test "${TEA_PLATFORM}" = "windows" ; then + tcl_cv_sys_version=windows + else + tcl_cv_sys_version=`uname -s`-`uname -r` + if test "$?" -ne 0 ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 +$as_echo "$as_me: WARNING: can't find uname command" >&2;} + tcl_cv_sys_version=unknown + else + if test "`uname -s`" = "AIX" ; then + tcl_cv_sys_version=AIX-`uname -v`.`uname -r` + fi + fi + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 +$as_echo "$tcl_cv_sys_version" >&6; } + system=$tcl_cv_sys_version + + + # Require ranlib early so we can override it in special cases below. + + + + # Set configuration options based on system name and version. + # This is similar to Tcl's unix/tcl.m4 except that we've added a + # "windows" case and removed some core-only vars. + + do64bit_ok=no + # default to '{$LIBS}' and set to "" on per-platform necessary basis + SHLIB_LD_LIBS='${LIBS}' + # When ld needs options to work in 64-bit mode, put them in + # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] + # is disabled by the user. [Bug 1016796] + LDFLAGS_ARCH="" + UNSHARED_LIB_SUFFIX="" + # TEA specific: use PACKAGE_VERSION instead of VERSION + TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' + ECHO_VERSION='`echo ${PACKAGE_VERSION}`' + TCL_LIB_VERSIONS_OK=ok + CFLAGS_DEBUG=-g + if test "$GCC" = yes; then : + + CFLAGS_OPTIMIZE=-O2 + CFLAGS_WARNING="-Wall" + +else + + CFLAGS_OPTIMIZE=-O + CFLAGS_WARNING="" + +fi + if test -n "$ac_tool_prefix"; then + # 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + + STLIB_LD='${AR} cr' + LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" + if test "x$SHLIB_VERSION" = x; then : + SHLIB_VERSION="" +else + SHLIB_VERSION=".$SHLIB_VERSION" +fi + case $system in + # TEA specific: + windows) + # This is a 2-stage check to make sure we have the 64-bit SDK + # We have to know where the SDK is installed. + # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs + # MACHINE is IX86 for LINK, but this is used by the manifest, + # which requires x86|amd64|ia64. + MACHINE="X86" + if test "$do64bit" != "no" ; then + if test "x${MSSDK}x" = "xx" ; then + MSSDK="C:/Progra~1/Microsoft Platform SDK" + fi + MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'` + PATH64="" + case "$do64bit" in + amd64|x64|yes) + MACHINE="AMD64" ; # default to AMD64 64-bit build + PATH64="${MSSDK}/Bin/Win64/x86/AMD64" + ;; + ia64) + MACHINE="IA64" + PATH64="${MSSDK}/Bin/Win64" + ;; + esac + if test "$GCC" != "yes" -a ! -d "${PATH64}" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&5 +$as_echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ensure latest Platform SDK is installed" >&5 +$as_echo "$as_me: WARNING: Ensure latest Platform SDK is installed" >&2;} + do64bit="no" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using 64-bit $MACHINE mode" >&5 +$as_echo " Using 64-bit $MACHINE mode" >&6; } + do64bit_ok="yes" + fi + fi + + if test "$doWince" != "no" ; then + if test "$do64bit" != "no" ; then + as_fn_error $? "Windows/CE and 64-bit builds incompatible" "$LINENO" 5 + fi + if test "$GCC" = "yes" ; then + as_fn_error $? "Windows/CE and GCC builds incompatible" "$LINENO" 5 + fi + + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-celib + + if test x"${no_celib}" = x ; then + # we reset no_celib in case something fails here + no_celib=true + +# Check whether --with-celib was given. +if test "${with_celib+set}" = set; then : + withval=$with_celib; with_celibconfig=${withval} +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Windows/CE celib directory" >&5 +$as_echo_n "checking for Windows/CE celib directory... " >&6; } + if ${ac_cv_c_celibconfig+:} false; then : + $as_echo_n "(cached) " >&6 +else + + # First check to see if --with-celibconfig was specified. + if test x"${with_celibconfig}" != x ; then + if test -d "${with_celibconfig}/inc" ; then + ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)` + else + as_fn_error $? "${with_celibconfig} directory doesn't contain inc directory" "$LINENO" 5 + fi + fi + + # then check for a celib library + if test x"${ac_cv_c_celibconfig}" = x ; then + for i in \ + ../celib-palm-3.0 \ + ../celib \ + ../../celib-palm-3.0 \ + ../../celib \ + `ls -dr ../celib-*3.[0-9]* 2>/dev/null` \ + ${srcdir}/../celib-palm-3.0 \ + ${srcdir}/../celib \ + `ls -dr ${srcdir}/../celib-*3.[0-9]* 2>/dev/null` \ + ; do + if test -d "$i/inc" ; then + ac_cv_c_celibconfig=`(cd $i; pwd)` + break + fi + done + fi + +fi + + if test x"${ac_cv_c_celibconfig}" = x ; then + as_fn_error $? "Cannot find celib support library directory" "$LINENO" 5 + else + no_celib= + CELIB_DIR=${ac_cv_c_celibconfig} + CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found $CELIB_DIR" >&5 +$as_echo "found $CELIB_DIR" >&6; } + fi + fi + + # Set defaults for common evc4/PPC2003 setup + # Currently Tcl requires 300+, possibly 420+ for sockets + CEVERSION=420; # could be 211 300 301 400 420 ... + TARGETCPU=ARMV4; # could be ARMV4 ARM MIPS SH3 X86 ... + ARCH=ARM; # could be ARM MIPS X86EM ... + PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002" + if test "$doWince" != "yes"; then + # If !yes then the user specified something + # Reset ARCH to allow user to skip specifying it + ARCH= + eval `echo $doWince | awk -F, '{ \ + if (length($1)) { printf "CEVERSION=\"%s\"\n", $1; \ + if ($1 < 400) { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \ + if (length($2)) { printf "TARGETCPU=\"%s\"\n", toupper($2) }; \ + if (length($3)) { printf "ARCH=\"%s\"\n", toupper($3) }; \ + if (length($4)) { printf "PLATFORM=\"%s\"\n", $4 }; \ + }'` + if test "x${ARCH}" = "x" ; then + ARCH=$TARGETCPU; + fi + fi + OSVERSION=WCE$CEVERSION; + if test "x${WCEROOT}" = "x" ; then + WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0" + if test ! -d "${WCEROOT}" ; then + WCEROOT="C:/Program Files/Microsoft eMbedded Tools" + fi + fi + if test "x${SDKROOT}" = "x" ; then + SDKROOT="C:/Program Files/Windows CE Tools" + if test ! -d "${SDKROOT}" ; then + SDKROOT="C:/Windows CE Tools" + fi + fi + WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'` + SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'` + if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \ + -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then + as_fn_error $? "could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" "$LINENO" 5 + doWince="no" + else + # We could PATH_NOSPACE these, but that's not important, + # as long as we quote them when used. + CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include" + if test -d "${CEINCLUDE}/${TARGETCPU}" ; then + CEINCLUDE="${CEINCLUDE}/${TARGETCPU}" + fi + CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" + fi + fi + + if test "$GCC" != "yes" ; then + if test "${SHARED_BUILD}" = "0" ; then + runtime=-MT + else + runtime=-MD + fi + case "x`echo \${VisualStudioVersion}`" in + x1[4-9]*) + lflags="${lflags} -nodefaultlib:libucrt.lib" + + vars="ucrt.lib" + for i in $vars; do + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then + # Convert foo.lib to -lfoo for GCC. No-op if not *.lib + i=`echo "$i" | sed -e 's/^\([^-].*\)\.lib$/-l\1/i'` + fi + PKG_LIBS="$PKG_LIBS $i" + done + + + ;; + *) + ;; + esac + + if test "$do64bit" != "no" ; then + # All this magic is necessary for the Win64 SDK RC1 - hobbs + CC="\"${PATH64}/cl.exe\"" + CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\"" + RC="\"${MSSDK}/bin/rc.exe\"" + lflags="${lflags} -nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\"" + LINKBIN="\"${PATH64}/link.exe\"" + CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" + CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" + # Avoid 'unresolved external symbol __security_cookie' + # errors, c.f. http://support.microsoft.com/?id=894573 + + vars="bufferoverflowU.lib" + for i in $vars; do + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then + # Convert foo.lib to -lfoo for GCC. No-op if not *.lib + i=`echo "$i" | sed -e 's/^\([^-].*\)\.lib$/-l\1/i'` + fi + PKG_LIBS="$PKG_LIBS $i" + done + + + elif test "$doWince" != "no" ; then + CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin" + if test "${TARGETCPU}" = "X86"; then + CC="\"${CEBINROOT}/cl.exe\"" + else + CC="\"${CEBINROOT}/cl${ARCH}.exe\"" + fi + CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\"" + RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\"" + arch=`echo ${ARCH} | awk '{print tolower($0)}'` + defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS" + if test "${SHARED_BUILD}" = "1" ; then + # Static CE builds require static celib as well + defs="${defs} _DLL" + fi + for i in $defs ; do + +cat >>confdefs.h <<_ACEOF +#define $i 1 +_ACEOF + + done + +cat >>confdefs.h <<_ACEOF +#define _WIN32_WCE $CEVERSION +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define UNDER_CE $CEVERSION +_ACEOF + + CFLAGS_DEBUG="-nologo -Zi -Od" + CFLAGS_OPTIMIZE="-nologo -Ox" + lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'` + lflags="${lflags} -MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" + LINKBIN="\"${CEBINROOT}/link.exe\"" + + else + RC="rc" + lflags="${lflags} -nologo" + LINKBIN="link" + CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" + CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" + fi + fi + + if test "$GCC" = "yes"; then + # mingw gcc mode + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. +set dummy ${ac_tool_prefix}windres; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RC"; then + ac_cv_prog_RC="$RC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RC="${ac_tool_prefix}windres" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RC=$ac_cv_prog_RC +if test -n "$RC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RC" >&5 +$as_echo "$RC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RC"; then + ac_ct_RC=$RC + # Extract the first word of "windres", so it can be a program name with args. +set dummy windres; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RC"; then + ac_cv_prog_ac_ct_RC="$ac_ct_RC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RC="windres" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RC=$ac_cv_prog_ac_ct_RC +if test -n "$ac_ct_RC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC" >&5 +$as_echo "$ac_ct_RC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RC" = x; then + RC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RC=$ac_ct_RC + fi +else + RC="$ac_cv_prog_RC" +fi + + CFLAGS_DEBUG="-g" + CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" + SHLIB_LD='${CC} -shared' + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" + LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cross-compile version of gcc" >&5 +$as_echo_n "checking for cross-compile version of gcc... " >&6; } +if ${ac_cv_cross+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #ifdef _WIN32 + #error cross-compiler + #endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_cross=yes +else + ac_cv_cross=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cross" >&5 +$as_echo "$ac_cv_cross" >&6; } + if test "$ac_cv_cross" = "yes"; then + case "$do64bit" in + amd64|x64|yes) + CC="x86_64-w64-mingw32-gcc" + LD="x86_64-w64-mingw32-ld" + AR="x86_64-w64-mingw32-ar" + RANLIB="x86_64-w64-mingw32-ranlib" + RC="x86_64-w64-mingw32-windres" + ;; + *) + CC="i686-w64-mingw32-gcc" + LD="i686-w64-mingw32-ld" + AR="i686-w64-mingw32-ar" + RANLIB="i686-w64-mingw32-ranlib" + RC="i686-w64-mingw32-windres" + ;; + esac + fi + + else + SHLIB_LD="${LINKBIN} -dll ${lflags}" + # link -lib only works when -lib is the first arg + STLIB_LD="${LINKBIN} -lib ${lflags}" + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' + PATHTYPE=-w + # For information on what debugtype is most useful, see: + # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp + # and also + # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx + # This essentially turns it all on. + LDFLAGS_DEBUG="-debug -debugtype:cv" + LDFLAGS_OPTIMIZE="-release" + if test "$doWince" != "no" ; then + LDFLAGS_CONSOLE="-link ${lflags}" + LDFLAGS_WINDOW=${LDFLAGS_CONSOLE} + else + LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" + LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" + fi + fi + + SHLIB_SUFFIX=".dll" + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' + + TCL_LIB_VERSIONS_OK=nodots + ;; + AIX-*) + if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"; then : + + # AIX requires the _r compiler when gcc isn't being used + case "${CC}" in + *_r|*_r\ *) + # ok ... + ;; + *) + # Make sure only first arg gets _r + CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'` + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads" >&5 +$as_echo "Using $CC for compiling with threads" >&6; } + +fi + LIBS="$LIBS -lc" + SHLIB_CFLAGS="" + SHLIB_SUFFIX=".so" + + LD_LIBRARY_PATH_VAR="LIBPATH" + + # Check to enable 64-bit flags for compiler/linker + if test "$do64bit" = yes; then : + + if test "$GCC" = yes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 +$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} + +else + + do64bit_ok=yes + CFLAGS="$CFLAGS -q64" + LDFLAGS_ARCH="-q64" + RANLIB="${RANLIB} -X64" + AR="${AR} -X64" + SHLIB_LD_FLAGS="-b64" + +fi + +fi + + if test "`uname -m`" = ia64; then : + + # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + if test "$GCC" = yes; then : + + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + +else + + CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}' + +fi + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + +else + + if test "$GCC" = yes; then : + + SHLIB_LD='${CC} -shared -Wl,-bexpall' + +else + + SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" + LDFLAGS="$LDFLAGS -brtl" + +fi + SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" + CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +fi + ;; + BeOS*) + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -nostart' + SHLIB_SUFFIX=".so" + + #----------------------------------------------------------- + # Check for inet_ntoa in -lbind, for BeOS (which also needs + # -lsocket, even if the network functions are in -lnet which + # is always linked to, for compatibility. + #----------------------------------------------------------- + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind" >&5 +$as_echo_n "checking for inet_ntoa in -lbind... " >&6; } +if ${ac_cv_lib_bind_inet_ntoa+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbind $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char inet_ntoa (); +int +main () +{ +return inet_ntoa (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bind_inet_ntoa=yes +else + ac_cv_lib_bind_inet_ntoa=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_inet_ntoa" >&5 +$as_echo "$ac_cv_lib_bind_inet_ntoa" >&6; } +if test "x$ac_cv_lib_bind_inet_ntoa" = xyes; then : + LIBS="$LIBS -lbind -lsocket" +fi + + ;; + BSD/OS-4.*) + SHLIB_CFLAGS="-export-dynamic -fPIC" + SHLIB_LD='${CC} -shared' + SHLIB_SUFFIX=".so" + LDFLAGS="$LDFLAGS -export-dynamic" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + CYGWIN_*) + SHLIB_CFLAGS="" + SHLIB_LD='${CC} -shared' + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$@.a" + SHLIB_SUFFIX=".dll" + EXEEXT=".exe" + do64bit_ok=yes + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + Haiku*) + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork" >&5 +$as_echo_n "checking for inet_ntoa in -lnetwork... " >&6; } +if ${ac_cv_lib_network_inet_ntoa+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnetwork $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char inet_ntoa (); +int +main () +{ +return inet_ntoa (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_network_inet_ntoa=yes +else + ac_cv_lib_network_inet_ntoa=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_inet_ntoa" >&5 +$as_echo "$ac_cv_lib_network_inet_ntoa" >&6; } +if test "x$ac_cv_lib_network_inet_ntoa" = xyes; then : + LIBS="$LIBS -lnetwork" +fi + + ;; + HP-UX-*.11.*) + # Use updated header definitions where possible + +$as_echo "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h + + # TEA specific: Needed by Tcl, but not most extensions + #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) + #LIBS="$LIBS -lxnet" # Use the XOPEN network library + + if test "`uname -m`" = ia64; then : + + SHLIB_SUFFIX=".so" + # Use newer C++ library for C++ extensions + #if test "$GCC" != "yes" ; then + # CPPFLAGS="-AA" + #fi + +else + + SHLIB_SUFFIX=".sl" + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = yes; then : + + LDFLAGS="$LDFLAGS -Wl,-E" + CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' + LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' + LD_LIBRARY_PATH_VAR="SHLIB_PATH" + +fi + if test "$GCC" = yes; then : + + SHLIB_LD='${CC} -shared' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +else + + CFLAGS="$CFLAGS -z" + # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc + #CFLAGS="$CFLAGS +DAportable" + SHLIB_CFLAGS="+z" + SHLIB_LD="ld -b" + +fi + + # Check to enable 64-bit flags for compiler/linker + if test "$do64bit" = "yes"; then : + + if test "$GCC" = yes; then : + + case `${CC} -dumpmachine` in + hppa64*) + # 64-bit gcc in use. Fix flags for GNU ld. + do64bit_ok=yes + SHLIB_LD='${CC} -shared' + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 +$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} + ;; + esac + +else + + do64bit_ok=yes + CFLAGS="$CFLAGS +DD64" + LDFLAGS_ARCH="+DD64" + +fi + +fi ;; + IRIX-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' +fi + if test "$GCC" = yes; then : + + CFLAGS="$CFLAGS -mabi=n32" + LDFLAGS="$LDFLAGS -mabi=n32" + +else + + case $system in + IRIX-6.3) + # Use to build 6.2 compatible binaries on 6.3. + CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" + ;; + *) + CFLAGS="$CFLAGS -n32" + ;; + esac + LDFLAGS="$LDFLAGS -n32" + +fi + ;; + IRIX64-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' +fi + + # Check to enable 64-bit flags for compiler/linker + + if test "$do64bit" = yes; then : + + if test "$GCC" = yes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5 +$as_echo "$as_me: WARNING: 64bit mode not supported by gcc" >&2;} + +else + + do64bit_ok=yes + SHLIB_LD="ld -64 -shared -rdata_shared" + CFLAGS="$CFLAGS -64" + LDFLAGS_ARCH="-64" + +fi + +fi + ;; + Linux*|GNU*|NetBSD-Debian) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + + # TEA specific: + CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" + + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS_DEFAULT} -shared' + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + if test "`uname -m`" = "alpha"; then : + CFLAGS="$CFLAGS -mieee" +fi + if test $do64bit = yes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag" >&5 +$as_echo_n "checking if compiler accepts -m64 flag... " >&6; } +if ${tcl_cv_cc_m64+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -m64" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_cc_m64=yes +else + tcl_cv_cc_m64=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64" >&5 +$as_echo "$tcl_cv_cc_m64" >&6; } + if test $tcl_cv_cc_m64 = yes; then : + + CFLAGS="$CFLAGS -m64" + do64bit_ok=yes + +fi + +fi + + # The combo of gcc + glibc has a bug related to inlining of + # functions like strtod(). The -fno-builtin flag should address + # this problem but it does not work. The -fno-inline flag is kind + # of overkill but it works. Disable inlining only when one of the + # files in compat/*.c is being linked in. + + if test x"${USE_COMPAT}" != x; then : + CFLAGS="$CFLAGS -fno-inline" +fi + ;; + Lynx*) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + CFLAGS_OPTIMIZE=-02 + SHLIB_LD='${CC} -shared' + LD_FLAGS="-Wl,--export-dynamic" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + ;; + OpenBSD-*) + arch=`arch -s` + case "$arch" in + alpha|sparc64) + SHLIB_CFLAGS="-fPIC" + ;; + *) + SHLIB_CFLAGS="-fpic" + ;; + esac + SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' + SHLIB_SUFFIX=".so" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' + LDFLAGS="-Wl,-export-dynamic" + CFLAGS_OPTIMIZE="-O2" + if test "${TCL_THREADS}" = "1"; then : + + # On OpenBSD: Compile with -pthread + # Don't link with -lpthread + LIBS=`echo $LIBS | sed s/-lpthread//` + CFLAGS="$CFLAGS -pthread" + +fi + # OpenBSD doesn't do version numbers with dots. + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + TCL_LIB_VERSIONS_OK=nodots + ;; + NetBSD-*) + # NetBSD has ELF and can use 'cc -shared' to build shared libs + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' + SHLIB_SUFFIX=".so" + LDFLAGS="$LDFLAGS -export-dynamic" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + if test "${TCL_THREADS}" = "1"; then : + + # The -pthread needs to go in the CFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + +fi + ;; + DragonFly-*|FreeBSD-*) + # This configuration from FreeBSD Ports. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="${CC} -shared" + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$@" + SHLIB_SUFFIX=".so" + LDFLAGS="" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + if test "${TCL_THREADS}" = "1"; then : + + # The -pthread needs to go in the LDFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LDFLAGS="$LDFLAGS $PTHREAD_LIBS" +fi + case $system in + FreeBSD-3.*) + # Version numbers are dot-stripped by system policy. + TCL_TRIM_DOTS=`echo ${PACKAGE_VERSION} | tr -d .` + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1' + TCL_LIB_VERSIONS_OK=nodots + ;; + esac + ;; + Darwin-*) + CFLAGS_OPTIMIZE="-Os" + SHLIB_CFLAGS="-fno-common" + # To avoid discrepancies between what headers configure sees during + # preprocessing tests and compiling tests, move any -isysroot and + # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: + CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if ($i~/^(isysroot|mmacosx-version-min)/) print "-"$i}'`" + CFLAGS="`echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if (!($i~/^(isysroot|mmacosx-version-min)/)) print "-"$i}'`" + if test $do64bit = yes; then : + + case `arch` in + ppc) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag" >&5 +$as_echo_n "checking if compiler accepts -arch ppc64 flag... " >&6; } +if ${tcl_cv_cc_arch_ppc64+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_cc_arch_ppc64=yes +else + tcl_cv_cc_arch_ppc64=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64" >&5 +$as_echo "$tcl_cv_cc_arch_ppc64" >&6; } + if test $tcl_cv_cc_arch_ppc64 = yes; then : + + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + do64bit_ok=yes + +fi;; + i386) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag" >&5 +$as_echo_n "checking if compiler accepts -arch x86_64 flag... " >&6; } +if ${tcl_cv_cc_arch_x86_64+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch x86_64" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_cc_arch_x86_64=yes +else + tcl_cv_cc_arch_x86_64=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64" >&5 +$as_echo "$tcl_cv_cc_arch_x86_64" >&6; } + if test $tcl_cv_cc_arch_x86_64 = yes; then : + + CFLAGS="$CFLAGS -arch x86_64" + do64bit_ok=yes + +fi;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5 +$as_echo "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};; + esac + +else + + # Check for combined 32-bit and 64-bit fat build + if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ + && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '; then : + + fat_32_64=yes +fi + +fi + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -single_module flag" >&5 +$as_echo_n "checking if ld accepts -single_module flag... " >&6; } +if ${tcl_cv_ld_single_module+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +int i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_ld_single_module=yes +else + tcl_cv_ld_single_module=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$hold_ldflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_single_module" >&5 +$as_echo "$tcl_cv_ld_single_module" >&6; } + if test $tcl_cv_ld_single_module = yes; then : + + SHLIB_LD="${SHLIB_LD} -Wl,-single_module" + +fi + # TEA specific: link shlib with current and compatibility version flags + vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([0-9]\{1,5\}\)\(\(\.[0-9]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` + SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" + SHLIB_SUFFIX=".dylib" + # Don't use -prebind when building for Mac OS X 10.4 or later only: + if test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \ + "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4; then : + + LDFLAGS="$LDFLAGS -prebind" +fi + LDFLAGS="$LDFLAGS -headerpad_max_install_names" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5 +$as_echo_n "checking if ld accepts -search_paths_first flag... " >&6; } +if ${tcl_cv_ld_search_paths_first+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +int i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_ld_search_paths_first=yes +else + tcl_cv_ld_search_paths_first=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$hold_ldflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first" >&5 +$as_echo "$tcl_cv_ld_search_paths_first" >&6; } + if test $tcl_cv_ld_search_paths_first = yes; then : + + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + +fi + if test "$tcl_cv_cc_visibility_hidden" != yes; then : + + +$as_echo "#define MODULE_SCOPE __private_extern__" >>confdefs.h + + tcl_cv_cc_visibility_hidden=yes + +fi + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" + # TEA specific: for combined 32 & 64 bit fat builds of Tk + # extensions, verify that 64-bit build is possible. + if test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"; then : + + if test "${TEA_WINDOWINGSYSTEM}" = x11; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit X11" >&5 +$as_echo_n "checking for 64-bit X11... " >&6; } +if ${tcl_cv_lib_x11_64+:} false; then : + $as_echo_n "(cached) " >&6 +else + + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" + LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <X11/Xlib.h> +int +main () +{ +XrmInitialize(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_lib_x11_64=yes +else + tcl_cv_lib_x11_64=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_x11_64" >&5 +$as_echo "$tcl_cv_lib_x11_64" >&6; } + +fi + if test "${TEA_WINDOWINGSYSTEM}" = aqua; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit Tk" >&5 +$as_echo_n "checking for 64-bit Tk... " >&6; } +if ${tcl_cv_lib_tk_64+:} false; then : + $as_echo_n "(cached) " >&6 +else + + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" + LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <tk.h> +int +main () +{ +Tk_InitStubs(NULL, "", 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_lib_tk_64=yes +else + tcl_cv_lib_tk_64=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_tk_64" >&5 +$as_echo "$tcl_cv_lib_tk_64" >&6; } + +fi + # remove 64-bit arch flags from CFLAGS et al. if configuration + # does not support 64-bit. + if test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: Removing 64-bit architectures from compiler & linker flags" >&5 +$as_echo "$as_me: Removing 64-bit architectures from compiler & linker flags" >&6;} + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' + done +fi + +fi + ;; + OS/390-*) + CFLAGS_OPTIMIZE="" # Optimizer is buggy + +$as_echo "#define _OE_SOCKETS 1" >>confdefs.h + + ;; + OSF1-V*) + # Digital OSF/1 + SHLIB_CFLAGS="" + if test "$SHARED_BUILD" = 1; then : + + SHLIB_LD='ld -shared -expect_unresolved "*"' + +else + + SHLIB_LD='ld -non_shared -expect_unresolved "*"' + +fi + SHLIB_SUFFIX=".so" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' +fi + if test "$GCC" = yes; then : + CFLAGS="$CFLAGS -mieee" +else + + CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee" +fi + # see pthread_intro(3) for pthread support on osf1, k.furukawa + if test "${TCL_THREADS}" = 1; then : + + CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" + CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" + LIBS=`echo $LIBS | sed s/-lpthreads//` + if test "$GCC" = yes; then : + + LIBS="$LIBS -lpthread -lmach -lexc" + +else + + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + +fi + +fi + ;; + QNX-6*) + # QNX RTP + # This may work for all QNX, but it was only reported for v6. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="ld -Bshareable -x" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SCO_SV-3.2*) + if test "$GCC" = yes; then : + + SHLIB_CFLAGS="-fPIC -melf" + LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" + +else + + SHLIB_CFLAGS="-Kpic -belf" + LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" + +fi + SHLIB_LD="ld -G" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SunOS-5.[0-6]) + # Careful to not let 5.10+ fall into this case + + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + +$as_echo "#define _REENTRANT 1" >>confdefs.h + + +$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + + SHLIB_CFLAGS="-KPIC" + SHLIB_SUFFIX=".so" + if test "$GCC" = yes; then : + + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +else + + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +fi + ;; + SunOS-5*) + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + +$as_echo "#define _REENTRANT 1" >>confdefs.h + + +$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + + SHLIB_CFLAGS="-KPIC" + + # Check to enable 64-bit flags for compiler/linker + if test "$do64bit" = yes; then : + + arch=`isainfo` + if test "$arch" = "sparcv9 sparc"; then : + + if test "$GCC" = yes; then : + + if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5 +$as_echo "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;} + +else + + do64bit_ok=yes + CFLAGS="$CFLAGS -m64 -mcpu=v9" + LDFLAGS="$LDFLAGS -m64 -mcpu=v9" + SHLIB_CFLAGS="-fPIC" + +fi + +else + + do64bit_ok=yes + if test "$do64bitVIS" = yes; then : + + CFLAGS="$CFLAGS -xarch=v9a" + LDFLAGS_ARCH="-xarch=v9a" + +else + + CFLAGS="$CFLAGS -xarch=v9" + LDFLAGS_ARCH="-xarch=v9" + +fi + # Solaris 64 uses this as well + #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" + +fi + +else + if test "$arch" = "amd64 i386"; then : + + if test "$GCC" = yes; then : + + case $system in + SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) + do64bit_ok=yes + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 +$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};; + esac + +else + + do64bit_ok=yes + case $system in + SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + CFLAGS="$CFLAGS -xarch=amd64" + LDFLAGS="$LDFLAGS -xarch=amd64";; + esac + +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch" >&5 +$as_echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;} +fi +fi + +fi + + SHLIB_SUFFIX=".so" + if test "$GCC" = yes; then : + + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + if test "$do64bit_ok" = yes; then : + + if test "$arch" = "sparcv9 sparc"; then : + + # We need to specify -static-libgcc or we need to + # add the path to the sparv9 libgcc. + # JH: static-libgcc is necessary for core Tcl, but may + # not be necessary for extensions. + SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" + # for finding sparcv9 libgcc, get the regular libgcc + # path, remove so name and append 'sparcv9' + #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." + #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" + +else + if test "$arch" = "amd64 i386"; then : + + # JH: static-libgcc is necessary for core Tcl, but may + # not be necessary for extensions. + SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" + +fi +fi + +fi + +else + + case $system in + SunOS-5.[1-9][0-9]*) + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; + *) + SHLIB_LD='/usr/ccs/bin/ld -G -z text';; + esac + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + +fi + ;; + UNIX_SV* | UnixWare-5*) + SHLIB_CFLAGS="-KPIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers + # that don't grok the -Bexport option. Test that it does. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag" >&5 +$as_echo_n "checking for ld accepts -Bexport flag... " >&6; } +if ${tcl_cv_ld_Bexport+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-Bexport" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +int i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_ld_Bexport=yes +else + tcl_cv_ld_Bexport=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$hold_ldflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport" >&5 +$as_echo "$tcl_cv_ld_Bexport" >&6; } + if test $tcl_cv_ld_Bexport = yes; then : + + LDFLAGS="$LDFLAGS -Wl,-Bexport" + +fi + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + esac + + if test "$do64bit" = yes -a "$do64bit_ok" = no; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5 +$as_echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;} + +fi + + + + # Add in the arch flags late to ensure it wasn't removed. + # Not necessary in TEA, but this is aligned with core + LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" + + # If we're running gcc, then change the C flags for compiling shared + # libraries to the right flags for gcc, instead of those for the + # standard manufacturer compiler. + + if test "$GCC" = yes; then : + + case $system in + AIX-*) ;; + BSD/OS*) ;; + CYGWIN_*|MINGW32_*|MINGW64_*) ;; + IRIX*) ;; + NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;; + Darwin-*) ;; + SCO_SV-3.2*) ;; + windows) ;; + *) SHLIB_CFLAGS="-fPIC" ;; + esac +fi + + if test "$tcl_cv_cc_visibility_hidden" != yes; then : + + +$as_echo "#define MODULE_SCOPE extern" >>confdefs.h + + +fi + + if test "$SHARED_LIB_SUFFIX" = ""; then : + + # TEA specific: use PACKAGE_VERSION instead of VERSION + SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}' +fi + if test "$UNSHARED_LIB_SUFFIX" = ""; then : + + # TEA specific: use PACKAGE_VERSION instead of VERSION + UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a' +fi + + if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SEH support in compiler" >&5 +$as_echo_n "checking for SEH support in compiler... " >&6; } +if ${tcl_cv_seh+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + tcl_cv_seh=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#undef WIN32_LEAN_AND_MEAN + + int main(int argc, char** argv) { + int a, b = 0; + __try { + a = 666 / b; + } + __except (EXCEPTION_EXECUTE_HANDLER) { + return 0; + } + return 1; + } + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + tcl_cv_seh=yes +else + tcl_cv_seh=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_seh" >&5 +$as_echo "$tcl_cv_seh" >&6; } + if test "$tcl_cv_seh" = "no" ; then + +$as_echo "#define HAVE_NO_SEH 1" >>confdefs.h + + fi + + # + # Check to see if the excpt.h include file provided contains the + # definition for EXCEPTION_DISPOSITION; if not, which is the case + # with Cygwin's version as of 2002-04-10, define it to be int, + # sufficient for getting the current code to work. + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EXCEPTION_DISPOSITION support in include files" >&5 +$as_echo_n "checking for EXCEPTION_DISPOSITION support in include files... " >&6; } +if ${tcl_cv_eh_disposition+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# undef WIN32_LEAN_AND_MEAN + +int +main () +{ + + EXCEPTION_DISPOSITION x; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_eh_disposition=yes +else + tcl_cv_eh_disposition=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_eh_disposition" >&5 +$as_echo "$tcl_cv_eh_disposition" >&6; } + if test "$tcl_cv_eh_disposition" = "no" ; then + +$as_echo "#define EXCEPTION_DISPOSITION int" >>confdefs.h + + fi + + # Check to see if winnt.h defines CHAR, SHORT, and LONG + # even if VOID has already been #defined. The win32api + # used by mingw and cygwin is known to do this. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for winnt.h that ignores VOID define" >&5 +$as_echo_n "checking for winnt.h that ignores VOID define... " >&6; } +if ${tcl_cv_winnt_ignore_void+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define VOID void +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#undef WIN32_LEAN_AND_MEAN + +int +main () +{ + + CHAR c; + SHORT s; + LONG l; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_winnt_ignore_void=yes +else + tcl_cv_winnt_ignore_void=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_winnt_ignore_void" >&5 +$as_echo "$tcl_cv_winnt_ignore_void" >&6; } + if test "$tcl_cv_winnt_ignore_void" = "yes" ; then + +$as_echo "#define HAVE_WINNT_IGNORE_VOID 1" >>confdefs.h + + fi + fi + + # See if the compiler supports casting to a union type. + # This is used to stop gcc from printing a compiler + # warning when initializing a union member. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5 +$as_echo_n "checking for cast to union support... " >&6; } +if ${tcl_cv_cast_to_union+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + union foo { int i; double d; }; + union foo f = (union foo) (int) 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_cast_to_union=yes +else + tcl_cv_cast_to_union=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5 +$as_echo "$tcl_cv_cast_to_union" >&6; } + if test "$tcl_cv_cast_to_union" = "yes"; then + +$as_echo "#define HAVE_CAST_TO_UNION 1" >>confdefs.h + + fi + + + + + + + + + + + + + + # These must be called after we do the basic CFLAGS checks and + # verify any possible 64-bit or similar switches are necessary + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for required early compiler flags" >&5 +$as_echo_n "checking for required early compiler flags... " >&6; } + tcl_flags="" + + if ${tcl_cv_flag__isoc99_source+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +int +main () +{ +char *p = (char *)strtoll; char *q = (char *)strtoull; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_flag__isoc99_source=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _ISOC99_SOURCE 1 +#include <stdlib.h> +int +main () +{ +char *p = (char *)strtoll; char *q = (char *)strtoull; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_flag__isoc99_source=yes +else + tcl_cv_flag__isoc99_source=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_flag__isoc99_source}" = "xyes" ; then + +$as_echo "#define _ISOC99_SOURCE 1" >>confdefs.h + + tcl_flags="$tcl_flags _ISOC99_SOURCE" + fi + + + if ${tcl_cv_flag__largefile64_source+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/stat.h> +int +main () +{ +struct stat64 buf; int i = stat64("/", &buf); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_flag__largefile64_source=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGEFILE64_SOURCE 1 +#include <sys/stat.h> +int +main () +{ +struct stat64 buf; int i = stat64("/", &buf); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_flag__largefile64_source=yes +else + tcl_cv_flag__largefile64_source=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_flag__largefile64_source}" = "xyes" ; then + +$as_echo "#define _LARGEFILE64_SOURCE 1" >>confdefs.h + + tcl_flags="$tcl_flags _LARGEFILE64_SOURCE" + fi + + + if ${tcl_cv_flag__largefile_source64+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/stat.h> +int +main () +{ +char *p = (char *)open64; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_flag__largefile_source64=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGEFILE_SOURCE64 1 +#include <sys/stat.h> +int +main () +{ +char *p = (char *)open64; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_flag__largefile_source64=yes +else + tcl_cv_flag__largefile_source64=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_flag__largefile_source64}" = "xyes" ; then + +$as_echo "#define _LARGEFILE_SOURCE64 1" >>confdefs.h + + tcl_flags="$tcl_flags _LARGEFILE_SOURCE64" + fi + + if test "x${tcl_flags}" = "x" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}" >&5 +$as_echo "${tcl_flags}" >&6; } + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit integer type" >&5 +$as_echo_n "checking for 64-bit integer type... " >&6; } + if ${tcl_cv_type_64bit+:} false; then : + $as_echo_n "(cached) " >&6 +else + + tcl_cv_type_64bit=none + # See if the compiler knows natively about __int64 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +__int64 value = (__int64) 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_type_64bit=__int64 +else + tcl_type_64bit="long long" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + # See if we should use long anyway Note that we substitute in the + # type that is our current guess for a 64-bit type inside this check + # program, so it should be modified only carefully... + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +switch (0) { + case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; + } + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_type_64bit=${tcl_type_64bit} +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "${tcl_cv_type_64bit}" = none ; then + +$as_echo "#define TCL_WIDE_INT_IS_LONG 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: using long" >&5 +$as_echo "using long" >&6; } + elif test "${tcl_cv_type_64bit}" = "__int64" \ + -a "${TEA_PLATFORM}" = "windows" ; then + # TEA specific: We actually want to use the default tcl.h checks in + # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* + { $as_echo "$as_me:${as_lineno-$LINENO}: result: using Tcl header defaults" >&5 +$as_echo "using Tcl header defaults" >&6; } + else + +cat >>confdefs.h <<_ACEOF +#define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit} +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_cv_type_64bit}" >&5 +$as_echo "${tcl_cv_type_64bit}" >&6; } + + # Now check for auxiliary declarations + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5 +$as_echo_n "checking for struct dirent64... " >&6; } +if ${tcl_cv_struct_dirent64+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> +#include <dirent.h> +int +main () +{ +struct dirent64 p; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_struct_dirent64=yes +else + tcl_cv_struct_dirent64=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5 +$as_echo "$tcl_cv_struct_dirent64" >&6; } + if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then + +$as_echo "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat64" >&5 +$as_echo_n "checking for struct stat64... " >&6; } +if ${tcl_cv_struct_stat64+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/stat.h> +int +main () +{ +struct stat64 p; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_struct_stat64=yes +else + tcl_cv_struct_stat64=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_stat64" >&5 +$as_echo "$tcl_cv_struct_stat64" >&6; } + if test "x${tcl_cv_struct_stat64}" = "xyes" ; then + +$as_echo "#define HAVE_STRUCT_STAT64 1" >>confdefs.h + + fi + + for ac_func in open64 lseek64 +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for off64_t" >&5 +$as_echo_n "checking for off64_t... " >&6; } + if ${tcl_cv_type_off64_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> +int +main () +{ +off64_t offset; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_type_off64_t=yes +else + tcl_cv_type_off64_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_type_off64_t}" = "xyes" && \ + test "x${ac_cv_func_lseek64}" = "xyes" && \ + test "x${ac_cv_func_open64}" = "xyes" ; then + +$as_echo "#define HAVE_TYPE_OFF64_T 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + fi + + + +#-------------------------------------------------------------------- +# Set the default compiler switches based on the --enable-symbols option. +#-------------------------------------------------------------------- + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5 +$as_echo_n "checking for build with symbols... " >&6; } + # Check whether --enable-symbols was given. +if test "${enable_symbols+set}" = set; then : + enableval=$enable_symbols; tcl_ok=$enableval +else + tcl_ok=no +fi + + DBGX="" + if test "$tcl_ok" = "no"; then + CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG" + LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + else + CFLAGS_DEFAULT="${CFLAGS_DEBUG}" + LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" + if test "$tcl_ok" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5 +$as_echo "yes (standard debugging)" >&6; } + fi + fi + # TEA specific: + if test "${TEA_PLATFORM}" != "windows" ; then + LDFLAGS_DEFAULT="${LDFLAGS}" + fi + + + + + if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then + +$as_echo "#define TCL_MEM_DEBUG 1" >>confdefs.h + + fi + + if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then + if test "$tcl_ok" = "all"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem debugging" >&5 +$as_echo "enabled symbols mem debugging" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5 +$as_echo "enabled $tcl_ok debugging" >&6; } + fi + fi + + +#-------------------------------------------------------------------- +# This macro generates a line to use when building a library. It +# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, +# and TEA_LOAD_TCLCONFIG macros above. +#-------------------------------------------------------------------- + + + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then + MAKE_STATIC_LIB="\${STLIB_LD} -out:\$@ \$(PKG_OBJECTS)" + MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\$@ \$(PKG_OBJECTS)" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if defined(_MSC_VER) && _MSC_VER >= 1400 +print("manifest needed") +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "manifest needed" >/dev/null 2>&1; then : + + # Could do a CHECK_PROG for mt, but should always be with MSVC8+ + VC_MANIFEST_EMBED_DLL="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;2 ; fi" + VC_MANIFEST_EMBED_EXE="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;1 ; fi" + MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" + + CLEANFILES="$CLEANFILES *.manifest" + + +fi +rm -f conftest* + + MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\$@ \$(PKG_STUB_OBJECTS)" + else + MAKE_STATIC_LIB="\${STLIB_LD} \$@ \$(PKG_OBJECTS)" + MAKE_SHARED_LIB="\${SHLIB_LD} -o \$@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" + MAKE_STUB_LIB="\${STLIB_LD} \$@ \$(PKG_STUB_OBJECTS)" + fi + + if test "${SHARED_BUILD}" = "1" ; then + MAKE_LIB="${MAKE_SHARED_LIB} " + else + MAKE_LIB="${MAKE_STATIC_LIB} " + fi + + #-------------------------------------------------------------------- + # Shared libraries and static libraries have different names. + # Use the double eval to make sure any variables in the suffix is + # substituted. (@@@ Might not be necessary anymore) + #-------------------------------------------------------------------- + + if test "${TEA_PLATFORM}" = "windows" ; then + if test "${SHARED_BUILD}" = "1" ; then + # We force the unresolved linking of symbols that are really in + # the private libraries of Tcl and Tk. + if test x"${TK_BIN_DIR}" != x ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" + fi + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" + if test "$GCC" = "yes"; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc" + fi + eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" + else + eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + if test "$GCC" = "yes"; then + PKG_LIB_FILE=lib${PKG_LIB_FILE} + fi + fi + # Some packages build their own stubs libraries + eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + if test "$GCC" = "yes"; then + PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} + fi + # These aren't needed on Windows (either MSVC or gcc) + RANLIB=: + RANLIB_STUB=: + else + RANLIB_STUB="${RANLIB}" + if test "${SHARED_BUILD}" = "1" ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" + if test x"${TK_BIN_DIR}" != x ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" + fi + eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" + RANLIB=: + else + eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + fi + # Some packages build their own stubs libraries + eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + fi + + # These are escaped so that only CFLAGS is picked up at configure time. + # The other values will be substituted at make time. + CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" + if test "${SHARED_BUILD}" = "1" ; then + CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" + fi + + + + + + + + + + +#-------------------------------------------------------------------- +# Determine the name of the tclsh and/or wish executables in the +# Tcl and Tk build directories or the location they were installed +# into. These paths are used to support running test cases only, +# the Makefile should not be making use of these paths to generate +# a pkgIndex.tcl file or anything else at extension build time. +#-------------------------------------------------------------------- + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5 +$as_echo_n "checking for tclsh... " >&6; } + if test -f "${TCL_BIN_DIR}/Makefile" ; then + # tclConfig.sh is in Tcl build directory + if test "${TEA_PLATFORM}" = "windows"; then + if test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" ; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" + elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}s${EXEEXT}" ; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}s${EXEEXT}" + elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}t${EXEEXT}" ; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}t${EXEEXT}" + elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}st${EXEEXT}" ; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}st${EXEEXT}" + fi + else + TCLSH_PROG="${TCL_BIN_DIR}/tclsh" + fi + else + # tclConfig.sh is in install location + if test "${TEA_PLATFORM}" = "windows"; then + TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" + else + TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}" + fi + list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" + for i in $list ; do + if test -f "$i/${TCLSH_PROG}" ; then + REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" + break + fi + done + TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${TCLSH_PROG}" >&5 +$as_echo "${TCLSH_PROG}" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wish" >&5 +$as_echo_n "checking for wish... " >&6; } + if test -f "${TK_BIN_DIR}/Makefile" ; then + # tkConfig.sh is in Tk build directory + if test "${TEA_PLATFORM}" = "windows"; then + if test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" ; then + WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" + elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}s${EXEEXT}" ; then + WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}$s{EXEEXT}" + elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}t${EXEEXT}" ; then + WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}t${EXEEXT}" + elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}st${EXEEXT}" ; then + WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}st${EXEEXT}" + fi + else + WISH_PROG="${TK_BIN_DIR}/wish" + fi + else + # tkConfig.sh is in install location + if test "${TEA_PLATFORM}" = "windows"; then + WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" + else + WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_DBGX}" + fi + list="`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \ + `ls -d ${TK_BIN_DIR}/.. 2>/dev/null` \ + `ls -d ${TK_PREFIX}/bin 2>/dev/null`" + for i in $list ; do + if test -f "$i/${WISH_PROG}" ; then + REAL_TK_BIN_DIR="`cd "$i"; pwd`/" + break + fi + done + WISH_PROG="${REAL_TK_BIN_DIR}${WISH_PROG}" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${WISH_PROG}" >&5 +$as_echo "${WISH_PROG}" >&6; } + + + +#-------------------------------------------------------------------- +# Setup a *Config.sh.in configuration file. +#-------------------------------------------------------------------- + + + #-------------------------------------------------------------------- + # These are for tktableConfig.sh + #-------------------------------------------------------------------- + + # pkglibdir must be a fully qualified path and (not ${exec_prefix}/lib) + eval pkglibdir="${libdir}/tktable${PACKAGE_VERSION}" + if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then + eval tktable_LIB_FLAG="-ltktable${PACKAGE_VERSION}${DBGX}" + eval tktable_STUB_LIB_FLAG="-ltktablestub${PACKAGE_VERSION}${DBGX}" + else + eval tktable_LIB_FLAG="-ltktable`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}" + eval tktable_STUB_LIB_FLAG="-ltktablestub`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}" + fi + tktable_BUILD_LIB_SPEC="-L`$CYGPATH $(pwd)` ${tktable_LIB_FLAG}" + tktable_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` ${tktable_LIB_FLAG}" + tktable_BUILD_STUB_LIB_SPEC="-L`$CYGPATH $(pwd)` ${tktable_STUB_LIB_FLAG}" + tktable_STUB_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` ${tktable_STUB_LIB_FLAG}" + tktable_BUILD_STUB_LIB_PATH="`$CYGPATH $(pwd)`/${PKG_STUB_LIB_FILE}" + tktable_STUB_LIB_PATH="`$CYGPATH ${pkglibdir}`/${PKG_STUB_LIB_FILE}" + + + + + + + + + + + + +#AC_SUBST(SAMPLE_VAR) + +#-------------------------------------------------------------------- +# Specify files to substitute AC variables in. You may alternatively +# have a special pkgIndex.tcl.in or other files which require +# substituting the AC variables in. Include these here. +#-------------------------------------------------------------------- + +ac_config_files="$ac_config_files Makefile pkgIndex.tcl" + +ac_config_files="$ac_config_files tktableConfig.sh" + + +#-------------------------------------------------------------------- +# Finally, substitute all of the various values into the files +# specified with AC_CONFIG_FILES. +#-------------------------------------------------------------------- + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +ac_script=' +:mline +/\\$/{ + N + s,\\\n,, + b mline +} +t clear +:clear +s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g +t quote +s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g +t quote +b any +:quote +s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g +s/\[/\\&/g +s/\]/\\&/g +s/\$/$$/g +H +:any +${ + g + s/^\n// + s/\n/ /g + p +} +' +DEFS=`sed -n "$ac_script" confdefs.h` + + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS="" + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by tktable $as_me 2.10, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +tktable config.status 2.10 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h | --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "pkgIndex.tcl") CONFIG_FILES="$CONFIG_FILES pkgIndex.tcl" ;; + "tktableConfig.sh") CONFIG_FILES="$CONFIG_FILES tktableConfig.sh" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' <conf$$subs.awk | sed ' +/^[^""]/{ + N + s/\n// +} +' >>$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + + +eval set X " :F $CONFIG_FILES " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/tktable/configure.ac b/tktable/configure.ac new file mode 100644 index 0000000..70af8d3 --- /dev/null +++ b/tktable/configure.ac @@ -0,0 +1,192 @@ +#!/bin/bash -norc +dnl This file is an input file used by the GNU "autoconf" program to +dnl generate the file "configure", which is run during Tcl installation +dnl to configure the system for the local environment. + +#----------------------------------------------------------------------- +# Sample configure.ac for Tcl Extensions. The only places you should +# need to modify this file are marked by the string __CHANGE__ +#----------------------------------------------------------------------- + +#----------------------------------------------------------------------- +# __CHANGE__ +# Set your package name and version numbers here. +# +# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION +# set as provided. These will also be added as -D defs in your Makefile +# so you can encode the package version directly into the source files. +# This will also define a special symbol for Windows (BUILD_<PACKAGE_NAME> +# so that we create the export library with the dll. +#----------------------------------------------------------------------- + +AC_INIT([tktable], [2.10]) + +#-------------------------------------------------------------------- +# Call TEA_INIT as the first TEA_ macro to set up initial vars. +# This will define a ${TEA_PLATFORM} variable == "unix" or "windows" +# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. +#-------------------------------------------------------------------- + +TEA_INIT() + +AC_CONFIG_AUX_DIR(tclconfig) + +#-------------------------------------------------------------------- +# Load the tclConfig.sh file +#-------------------------------------------------------------------- + +TEA_PATH_TCLCONFIG +TEA_LOAD_TCLCONFIG + +#-------------------------------------------------------------------- +# Load the tkConfig.sh file if necessary (Tk extension) +#-------------------------------------------------------------------- + +TEA_PATH_TKCONFIG +TEA_LOAD_TKCONFIG + +#----------------------------------------------------------------------- +# Handle the --prefix=... option by defaulting to what Tcl gave. +# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. +#----------------------------------------------------------------------- + +TEA_PREFIX + +#----------------------------------------------------------------------- +# Standard compiler checks. +# This sets up CC by using the CC env var, or looks for gcc otherwise. +# This also calls AC_PROG_CC and a few others to create the basic setup +# necessary to compile executables. +#----------------------------------------------------------------------- + +TEA_SETUP_COMPILER + +#----------------------------------------------------------------------- +# __CHANGE__ +# Specify the C source files to compile in TEA_ADD_SOURCES, +# public headers that need to be installed in TEA_ADD_HEADERS, +# stub library C source files to compile in TEA_ADD_STUB_SOURCES, +# and runtime Tcl library files in TEA_ADD_TCL_SOURCES. +# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS +# and PKG_TCL_SOURCES. +#----------------------------------------------------------------------- + +TEA_ADD_SOURCES([tkTable.c tkTableWin.c tkTableTag.c tkTableEdit.c + tkTableCell.c tkTableCellSort.c tkTableCmds.c tkTableUtil.c]) +TEA_ADD_HEADERS([]) +TEA_ADD_INCLUDES([-I. -I${srcdir}/generic]) +TEA_ADD_LIBS([]) +TEA_ADD_CFLAGS([]) +TEA_ADD_STUB_SOURCES([]) +TEA_ADD_TCL_SOURCES([library/tkTable.tcl library/tktable.py]) + +#-------------------------------------------------------------------- +# __CHANGE__ +# +# You can add more files to clean if your extension creates any extra +# files by extending CLEANFILES. +# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure +# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. +# +# A few miscellaneous platform-specific items: +# TEA_ADD_* any platform specific compiler/build info here. +#-------------------------------------------------------------------- + +#CLEANFILES="$CLEANFILES pkgIndex.tcl" +if test "${TEA_PLATFORM}" = "windows" ; then + # Ensure no empty if clauses + : + #TEA_ADD_SOURCES([win/winFile.c]) + #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"]) +else + # Ensure no empty else clauses + : + #TEA_ADD_SOURCES([unix/unixFile.c]) + #TEA_ADD_LIBS([-lsuperfly]) +fi + +#-------------------------------------------------------------------- +# __CHANGE__ +# Choose which headers you need. Extension authors should try very +# hard to only rely on the Tcl public header files. Internal headers +# contain private data structures and are subject to change without +# notice. +# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG +#-------------------------------------------------------------------- + +TEA_PUBLIC_TCL_HEADERS +#TEA_PRIVATE_TCL_HEADERS + +TEA_PUBLIC_TK_HEADERS +#TEA_PRIVATE_TK_HEADERS +TEA_PATH_X + +#-------------------------------------------------------------------- +# Check whether --enable-threads or --disable-threads was given. +# This auto-enables if Tcl was compiled threaded. +#-------------------------------------------------------------------- + +TEA_ENABLE_THREADS + +#-------------------------------------------------------------------- +# The statement below defines a collection of symbols related to +# building as a shared library instead of a static library. +#-------------------------------------------------------------------- + +TEA_ENABLE_SHARED + +#-------------------------------------------------------------------- +# This macro figures out what flags to use with the compiler/linker +# when building shared/static debug/optimized objects. This information +# can be taken from the tclConfig.sh file, but this figures it all out. +#-------------------------------------------------------------------- + +TEA_CONFIG_CFLAGS + +#-------------------------------------------------------------------- +# Set the default compiler switches based on the --enable-symbols option. +#-------------------------------------------------------------------- + +TEA_ENABLE_SYMBOLS + +#-------------------------------------------------------------------- +# This macro generates a line to use when building a library. It +# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, +# and TEA_LOAD_TCLCONFIG macros above. +#-------------------------------------------------------------------- + +TEA_MAKE_LIB + +#-------------------------------------------------------------------- +# Determine the name of the tclsh and/or wish executables in the +# Tcl and Tk build directories or the location they were installed +# into. These paths are used to support running test cases only, +# the Makefile should not be making use of these paths to generate +# a pkgIndex.tcl file or anything else at extension build time. +#-------------------------------------------------------------------- + +TEA_PROG_TCLSH +TEA_PROG_WISH + +#-------------------------------------------------------------------- +# Setup a *Config.sh.in configuration file. +#-------------------------------------------------------------------- + +TEA_EXPORT_CONFIG([tktable]) +#AC_SUBST(SAMPLE_VAR) + +#-------------------------------------------------------------------- +# Specify files to substitute AC variables in. You may alternatively +# have a special pkgIndex.tcl.in or other files which require +# substituting the AC variables in. Include these here. +#-------------------------------------------------------------------- + +AC_CONFIG_FILES([Makefile pkgIndex.tcl]) +AC_CONFIG_FILES([tktableConfig.sh]) + +#-------------------------------------------------------------------- +# Finally, substitute all of the various values into the files +# specified with AC_CONFIG_FILES. +#-------------------------------------------------------------------- + +AC_OUTPUT() diff --git a/tktable/demos/basic.tcl b/tktable/demos/basic.tcl new file mode 100755 index 0000000..0d9a0ab --- /dev/null +++ b/tktable/demos/basic.tcl @@ -0,0 +1,61 @@ +#!/bin/sh +# the next line restarts using wish \ +exec wish "$0" ${1+"$@"} + +## basic.tcl +## +## This demo shows the basic use of the table widget +## +## jeff at hobbs org + +source [file join [file dirname [info script]] loadtable.tcl] + +array set table { + rows 8 + cols 8 + table .t + array t +} + +proc fill { array x y } { + upvar $array f + for {set i -$x} {$i<$x} {incr i} { + for {set j -$y} {$j<$y} {incr j} { set f($i,$j) "r$i,c$j" } + } +} + +## Test out the use of a procedure to define tags on rows and columns +proc rowProc row { if {$row>0 && $row%2} { return OddRow } } +proc colProc col { if {$col>0 && $col%2} { return OddCol } } + +label .label -text "TkTable v1 Example" + +fill $table(array) $table(rows) $table(cols) +table $table(table) -rows $table(rows) -cols $table(cols) \ + -variable $table(array) \ + -width 6 -height 6 \ + -titlerows 1 -titlecols 2 \ + -roworigin -1 -colorigin -2 \ + -yscrollcommand {.sy set} -xscrollcommand {.sx set} \ + -rowtagcommand rowProc -coltagcommand colProc \ + -colstretchmode last -rowstretchmode last \ + -selectmode extended -sparsearray 0 + +scrollbar .sy -command [list $table(table) yview] +scrollbar .sx -command [list $table(table) xview] -orient horizontal +button .exit -text "Exit" -command {exit} + +grid .label - -sticky ew +grid $table(table) .sy -sticky news +grid .sx -sticky ew +grid .exit -sticky ew -columnspan 2 +grid columnconfig . 0 -weight 1 +grid rowconfig . 1 -weight 1 + +$table(table) tag config OddRow -bg orange -fg purple +$table(table) tag config OddCol -bg brown -fg pink + +$table(table) width -2 7 -1 7 1 5 2 8 4 14 + +puts [list Table is $table(table) with array [$table(table) cget -var]] + diff --git a/tktable/demos/buttons.tcl b/tktable/demos/buttons.tcl new file mode 100755 index 0000000..29ffddf --- /dev/null +++ b/tktable/demos/buttons.tcl @@ -0,0 +1,82 @@ +#!/bin/sh +# next line is a comment in tcl \ +exec wish "$0" ${1+"$@"} + +## buttons.tcl +## +## demonstrates the simulation of a button array +## +## ellson@lucent.com +## modifications made by jeff at hobbs org + +source [file join [file dirname [info script]] loadtable.tcl] + +array set table { + rows 20 + cols 20 + table .table +} + +# create the table +set t $table(table) +table $t -rows [expr {$table(rows)+1}] -cols [expr {$table(cols)+1}] \ + -titlerows 1 -titlecols 1 \ + -roworigin -1 -colorigin -1 \ + -colwidth 4 \ + -width 8 -height 8 \ + -variable tab \ + -flashmode off \ + -cursor top_left_arrow \ + -borderwidth 2 \ + -state disabled \ + -xscrollcommand ".sx set" -yscrollcommand ".sy set" + +scrollbar .sx -orient h -command "$t xview" +scrollbar .sy -orient v -command "$t yview" + +grid $t .sy -sticky nsew +grid .sx -sticky ew +grid columnconfig . 0 -weight 1 +grid rowconfig . 0 -weight 1 + +# set up tags for the various states of the buttons +$t tag configure OFF -bg red -relief raised +$t tag configure ON -bg green -relief sunken +$t tag configure sel -bg gray75 -relief flat + +# clean up if mouse leaves the widget +bind $t <Leave> { + %W selection clear all +} + +# highlight the cell under the mouse +bind $t <Motion> { + if {[%W selection includes @%x,%y]} break + %W selection clear all + %W selection set @%x,%y + break + ## "break" prevents the call to tkTableCheckBorder +} + +# mousebutton 1 toggles the value of the cell +# use of "selection includes" would work here +bind $t <1> { + set rc [%W cursel] + if {[string match ON $tab($rc)]} { + set tab($rc) OFF + %W tag celltag OFF $rc + } { + set tab($rc) ON + %W tag celltag ON $rc + } +} + +# inititialize the array, titles, and celltags +for {set i 0} {$i < $table(rows)} {incr i} { + set tab($i,-1) $i + for {set j 0} {$j < $table(cols)} {incr j} { + if {! $i} {set tab(-1,$j) $j} + set tab($i,$j) "OFF" + $t tag celltag OFF $i,$j + } +} diff --git a/tktable/demos/command.tcl b/tktable/demos/command.tcl new file mode 100755 index 0000000..e0da582 --- /dev/null +++ b/tktable/demos/command.tcl @@ -0,0 +1,85 @@ +#!/bin/sh +# the next line restarts using wish \ + exec wish "$0" ${1+"$@"} + +## command.tcl +## +## This demo shows the use of the table widget's -command options +## +## jeff at hobbs org + +source [file join [file dirname [info script]] loadtable.tcl] + +array set table { + rows 10 + cols 10 + table .table + array DATA +} + +proc fill { array x y } { + upvar $array f + for {set i -$x} {$i<$x} {incr i} { + for {set j -$y} {$j<$y} {incr j} { set f($i,$j) "$i x $j" } + } +} + +## Test out the use of a procedure to define tags on rows and columns +proc rowProc row { if {$row>0 && $row%2} { return OddRow } } +proc colProc col { if {$col>0 && $col%2} { return OddCol } } + +proc tblCmd { arrayName set cell val } { + upvar \#0 $arrayName data + + if {$set} { + #echo set $cell $val + set data($cell) $val + } else { + #echo get $cell + if {[info exists data($cell)]} { + return $data($cell) + } else { + return + } + } +} + +label .label -text "TkTable -command Example" +label .current -textvar CURRENT -width 5 +entry .active -textvar ACTIVE + +bind .active <Return> "$table(table) curvalue \[%W get\]" + +fill $table(array) $table(rows) $table(cols) +set t $table(table) +table $table(table) -rows $table(rows) -cols $table(cols) \ + -command [list tblCmd $table(array) %i %C %s] -cache 1 \ + -width 6 -height 6 \ + -titlerows 1 -titlecols 1 \ + -yscrollcommand {.sy set} -xscrollcommand {.sx set} \ + -roworigin -1 -colorigin -1 \ + -rowtagcommand rowProc -coltagcommand colProc \ + -selectmode extended \ + -rowstretch unset -colstretch unset \ + -flashmode on -browsecommand { + set CURRENT %S + set ACTIVE [%W get %S] +} -validate 1 -validatecommand { + set ACTIVE %S + return 1 +} + +scrollbar .sy -command [list $table(table) yview] -orient v +scrollbar .sx -command [list $table(table) xview] -orient h +grid .label - - -sticky ew +grid .current .active - -sticky ew +grid $table(table) - .sy -sticky nsew +grid .sx - -sticky ew +grid columnconfig . 1 -weight 1 +grid rowconfig . 2 -weight 1 + +$table(table) tag config OddRow -bg orange -fg purple +$table(table) tag config OddCol -bg brown -fg pink + +puts [list Table is $table(table)] + diff --git a/tktable/demos/debug.tcl b/tktable/demos/debug.tcl new file mode 100755 index 0000000..c384920 --- /dev/null +++ b/tktable/demos/debug.tcl @@ -0,0 +1,112 @@ +#!/bin/sh +# the next line restarts using wish \ +exec wish "$0" ${1+"$@"} + +## version2.tcl +## +## This demo uses most features of the table widget +## +## jeff at hobbs org + +source [file join [file dirname [info script]] loadtable.tcl] + +array set table { + rows 25 + cols 20 + table .t + array t +} + +proc fill { array x y } { + upvar $array f + for {set i -$x} {$i<$x} {incr i} { + for {set j -$y} {$j<$y} {incr j} { set f($i,$j) "r$i,c$j" } + } +} + +## Test out the use of a procedure to define tags on rows and columns +proc colProc col { if {$col > 0 && $col % 2} { return OddCol } } + +label .label -text "TkTable v2 Example" + +fill $table(array) $table(rows) $table(cols) +table $table(table) \ + -rows $table(rows) -cols $table(cols) \ + -variable $table(array) \ + -width 6 -height 8 \ + -titlerows 1 -titlecols 2 \ + -roworigin -5 -colorigin -2 \ + -yscrollcommand {.sy set} \ + -xscrollcommand {.sx set} \ + -coltagcommand colProc \ + -selectmode extended \ + -rowstretch unset \ + -colstretch unset \ + -selecttitles 0 \ + -drawmode single + +scrollbar .sy -command [list $table(table) yview] +scrollbar .sx -command [list $table(table) xview] -orient horizontal +button .exit -text "Exit" -command {exit} +grid .label - -sticky ew +grid $table(table) .sy -sticky news +grid .sx -sticky ew +grid .exit -sticky ew -columnspan 2 +grid columnconfig . 0 -weight 1 +grid rowconfig . 1 -weight 1 + +$table(table) tag config OddCol -bg brown -fg pink +$table(table) tag config title -bg red -fg green -relief sunken +$table(table) tag config dis -state disabled + +set i -1 +set first [$table(table) cget -colorigin] +foreach anchor {n s e w nw ne sw se c} { + $table(table) tag config $anchor -anchor $anchor + $table(table) tag row $anchor [incr i] + $table(table) set $i,$first $anchor +} +font create courier -family Courier -size 10 +$table(table) tag config s -font courier -justify center + +image create photo logo \ + -file [file join [file dirname [info script]] tcllogo.gif] +$table(table) tag config logo -image logo -showtext 1 +$table(table) tag cell logo 1,2 2,3 4,1 +$table(table) tag cell dis 2,1 1,-1 3,0 +$table(table) width -2 8 -1 9 0 12 4 14 + +$table(table) set \ + 1,1 "multi-line\ntext\nmight be\ninteresting" \ + 3,2 "more\nmulti-line\nplaying\n" \ + 2,2 "null\0byte" + +set i -1 + +# This is in the row span +set l [label $table(table).s -text "Window s" -bg yellow] +$table(table) window config 6,0 -sticky s -window $l + +# This is in the row titles +set l [label $table(table).ne -text "Window ne" -bg yellow] +$table(table) window config 4,-1 -sticky ne -window $l + +# This will get swallowed by a span +set l [label $table(table).ew -text "Window ew" -bg yellow] +$table(table) window config 5,3 -sticky ew -window $l + +# This is in the col titles +set l [label $table(table).news -text "Window news" -bg yellow] +$table(table) window config -5,1 -sticky news -window $l + +set l [label [winfo parent $table(table)].l -text "Sibling l" -bg orange] +$table(table) window config 5,1 -sticky news -window $l + +if {![catch {$table(table) span}]} { + $table(table) span -1,-2 0,3 1,2 0,5 3,2 2,2 6,0 4,0 +} + +puts [list Table is $table(table) with array [$table(table) cget -var]] + +#$table(table) postscript -file out.ps -first origin -last 2,2 +#if {[string match {} [info commands tkcon]]} exit diff --git a/tktable/demos/dynarows.tcl b/tktable/demos/dynarows.tcl new file mode 100755 index 0000000..9006953 --- /dev/null +++ b/tktable/demos/dynarows.tcl @@ -0,0 +1,87 @@ +#!/bin/sh +# the next line restarts using wish \ +exec wish "$0" ${1+"$@"} + +## dynarows.tcl +## +## This demos shows the use of the validation mechanism of the table +## and uses the table's cache (no -command or -variable) with a cute +## dynamic row routine. +## +## jeff at hobbs org + +source [file join [file dirname [info script]] loadtable.tcl] + +proc table_validate {w idx} { + if {[scan $idx %d,%d row col] != 2} return + set val [$w get $idx] + + ## Entries in the last row are allowed to be empty + set nrows [$w cget -rows] + if {$row == ${nrows}-1 && [string match {} $val]} { return } + + if {[catch {clock scan $val} time]} { + bell + $w activate $idx + $w selection clear all + $w selection set active + $w see active + } else { + set date {} + foreach item [clock format $time -format "%m %d %Y"] { + lappend date [string trimleft $item "0"] + } + $w set $idx [join $date "/"] + if {$row == ${nrows}-1} { + ## if this is the last row and both cols 1 && 2 are not empty + ## then add a row and redo configs + if {[string comp [$w get $row,1] {}] && \ + [string comp [$w get $row,2] {}]} { + $w tag row {} $row + $w set $row,0 $row + $w configure -rows [incr nrows] + $w tag row unset [incr row] + $w set $row,0 "*" + $w see $row,1 + $w activate $row,1 + } + } + } +} + +label .example -text "Dynamic Date Validated Rows" + +set t .table +table $t -rows 2 -cols 3 -cache 1 -selecttype row \ + -titlerows 1 -titlecols 1 \ + -yscrollcommand { .sy set } \ + -xscrollcommand { .sx set } \ + -height 5 -colstretch unset -rowstretch unset \ + -autoclear 1 -browsecommand {table_validate %W %s} + +$t set 0,1 "Begin" 0,2 "End" 1,0 "*" +$t tag config unset -fg \#008811 +$t tag config title -fg red +$t tag row unset 1 +$t width 0 3 + +scrollbar .sy -command [list $t yview] +scrollbar .sx -command [list $t xview] -orient horizontal +grid .example - -sticky ew +grid $t .sy -sticky news +grid .sx -sticky ew +grid columnconfig . 0 -weight 1 +grid rowconfig . 1 -weight 1 + +bind $t <Return> { + set r [%W index active row] + set c [%W index active col] + if {$c == 2} { + %W activate [incr r],1 + } else { + %W activate $r,[incr c] + } + %W see active + break +} +bind $t <KP_Enter> [bind $t <Return>] diff --git a/tktable/demos/loadtable.tcl b/tktable/demos/loadtable.tcl new file mode 100755 index 0000000..c691ac7 --- /dev/null +++ b/tktable/demos/loadtable.tcl @@ -0,0 +1,52 @@ +# loadtable.tcl +# +# Ensures that the table library extension is loaded + +if {[string equal "Windows CE" $::tcl_platform(os)]} { + if {[info proc puts] != "puts" || ![llength [info command ::tcl::puts]]} { + # Rename puts to something innocuous on Windows CE, + # but only if it wasn't already renamed (thus it's a proc) + rename puts ::tcl::puts + proc puts args { + set la [llength $args] + if {$la<1 || $la>3} { + error "usage: puts ?-nonewline? ?channel? string" + } + set nl \n + if {[lindex $args 0]=="-nonewline"} { + set nl "" + set args [lrange $args 1 end] + } + if {[llength $args]==1} { + set args [list stdout [join $args]] ;# (2) + } + foreach {channel s} $args break + if {$channel=="stdout" || $channel=="stderr"} { + #$::putsw insert end $s$nl + } else { + set cmd ::tcl::puts + if {$nl==""} {lappend cmd -nonewline} + lappend cmd $channel $s + uplevel 1 $cmd + } + } + } +} + +set ::VERSION 2.10 +if {[string compare unix $tcl_platform(platform)]} { + set table(library) Tktable$::VERSION[info sharedlibextension] +} else { + set table(library) libTktable$::VERSION[info sharedlibextension] +} +if { + [string match {} [info commands table]] + && [catch {package require Tktable $::VERSION} err] + && [catch {load [file join [pwd] $table(library)]} err] + && [catch {load [file join [pwd] .. unix $table(library)]} err] + && [catch {load [file join [pwd] .. win $table(library)]} err] +} { + error $err +} else { + puts "Tktable v[package provide Tktable] loaded" +} diff --git a/tktable/demos/maxsize.tcl b/tktable/demos/maxsize.tcl new file mode 100755 index 0000000..198eefb --- /dev/null +++ b/tktable/demos/maxsize.tcl @@ -0,0 +1,76 @@ +#!/bin/sh +# the next line restarts using wish \ +exec wish "$0" ${1+"$@"} + +## maxsize.tcl +## +## This demo uses a really big table. The big startup time is in +## filling the table's Tcl array var. +## +## jeff at hobbs org + +source [file join [file dirname [info script]] loadtable.tcl] + +array set table { + rows 40000 + cols 10 + table .t + array t +} + +proc fill { array x y } { + upvar $array f + for {set row 0} {$row<$x} {incr row} { + for {set col 0} {$col<$y} {incr col} { + set f($row,$col) "$row,$col" + } + } +} + +## Test out the use of a procedure to define tags on rows and columns +proc colProc col { if {$col > 0 && $col % 2} { return OddCol } } + +label .label -text "TkTable v2 Example" + +fill $table(array) $table(rows) $table(cols) +table $table(table) \ + -rows $table(rows) -cols $table(cols) \ + -variable $table(array) \ + -width 6 -height 8 \ + -titlerows 1 -titlecols 1 \ + -yscrollcommand {.sy set} \ + -xscrollcommand {.sx set} \ + -coltagcommand colProc \ + -selectmode extended \ + -rowstretch unset \ + -colstretch unset \ + -selecttitles 0 \ + -drawmode slow + +scrollbar .sy -command [list $table(table) yview] +scrollbar .sx -command [list $table(table) xview] -orient horizontal +button .exit -text "Exit" -command {exit} +grid .label - -sticky ew +grid $table(table) .sy -sticky news +grid .sx -sticky ew +grid .exit -sticky ew -columnspan 2 +grid columnconfig . 0 -weight 1 +grid rowconfig . 1 -weight 1 + +$table(table) tag config OddCol -bg brown -fg pink +$table(table) tag config title -bg red -fg blue -relief sunken +$table(table) tag config dis -state disabled + +set i -1 +set first [$table(table) cget -colorigin] +foreach anchor {n s e w nw ne sw se c} { + $table(table) tag config $anchor -anchor $anchor + $table(table) tag row $anchor [incr i] + $table(table) set $i,$first $anchor +} +font create courier -family Courier -size 10 +$table(table) tag config s -font courier -justify center + +$table(table) width -2 8 -1 9 0 12 4 14 + +puts [list Table is $table(table) with array [$table(table) cget -var]] diff --git a/tktable/demos/spreadsheet.tcl b/tktable/demos/spreadsheet.tcl new file mode 100755 index 0000000..9a36c7e --- /dev/null +++ b/tktable/demos/spreadsheet.tcl @@ -0,0 +1,122 @@ +#!/bin/sh +# the next line restarts using wish \ + exec wish "$0" ${1+"$@"} + +## spreadsheet.tcl +## +## This demos shows how you can simulate a 3D table +## and has other basic features to begin a basic spreadsheet +## +## jeff at hobbs org + +source [file join [file dirname [info script]] loadtable.tcl] + +array set table { + rows 10 + cols 10 + page AA + table .table + default pink + AA orange + BB blue + CC green +} + +proc colorize num { if {$num>0 && $num%2} { return colored } } + +proc fill {array {r 10} {c 10}} { + upvar \#0 $array ary + for {set i 0} {$i < $r} {incr i} { + for {set j 0} {$j < $c} {incr j} { + if {$j && $i} { + set ary($i,$j) "$array $i,$j" + } elseif {$i} { + set ary($i,$j) "$i" + } elseif {$j} { + set ary($i,$j) [format %c [expr 64+$j]] + } + } + } +} + +proc changepage {w e name el op} { + global $name table + if {[string comp {} $el]} { set name [list $name\($el\)] } + set i [set $name] + if {[string comp $i [$w cget -var]]} { + $w sel clear all + $w config -variable $i + $e config -textvar ${i}(active) + $w activate origin + if {[info exists table($i)]} { + $w tag config colored -bg $table($i) + } else { + $w tag config colored -bg $table(default) + } + $w see active + } +} + +label .example -text "TkTable v1 Spreadsheet Example" + +label .current -textvar table(current) -width 5 +entry .active -textvar $table(page)(active) +label .lpage -text "PAGE:" -width 6 -anchor e +tk_optionMenu .page table(page) AA BB CC DD + +fill $table(page) +fill BB [expr {$table(rows)/2}] [expr {$table(cols)/2}] + +trace var table(page) w [list changepage $table(table) .active] + +set t $table(table) +table $t \ + -rows $table(rows) \ + -cols $table(cols) \ + -variable $table(page) \ + -titlerows 1 \ + -titlecols 1 \ + -yscrollcommand { .sy set } \ + -xscrollcommand { .sx set } \ + -coltagcommand colorize \ + -flashmode on \ + -selectmode extended \ + -colstretch unset \ + -rowstretch unset \ + -width 5 -height 5 \ + -browsecommand {set table(current) %S} + +$t tag config colored -bg $table($table(page)) +$t tag config title -fg red -relief groove +$t tag config blue -bg blue +$t tag config green -bg green +$t tag cell green 6,3 5,7 4,9 +$t tag cell blue 8,8 +$t tag row blue 7 +$t tag col blue 6 8 +$t width 0 3 2 7 + +scrollbar .sy -command [list $t yview] +scrollbar .sx -command [list $t xview] -orient horizontal +button .exit -text "Exit" -command exit + +grid .example - - - - -sticky ew +grid .current .active .lpage .page - -sticky ew +grid $t - - - .sy -sticky ns +grid .sx - - - -sticky ew +grid .exit - - - - -sticky ew +grid columnconfig . 1 -weight 1 +grid rowconfig . 2 -weight 1 +grid config $t -sticky news + +bind .active <Return> [list tkTableMoveCell $t 1 0] + +menu .menu +menu .menu.file +. config -menu .menu +.menu add cascade -label "File" -underline 0 -menu .menu.file +.menu.file add command -label "Fill Array" -command { fill $table(page) } +.menu.file add command -label "Quit" -command exit + +puts [list Table is $table(table) with array [$table(table) cget -var]] + diff --git a/tktable/demos/tcllogo.gif b/tktable/demos/tcllogo.gif Binary files differnew file mode 100755 index 0000000..4603d4f --- /dev/null +++ b/tktable/demos/tcllogo.gif diff --git a/tktable/demos/tktable.py b/tktable/demos/tktable.py new file mode 100644 index 0000000..51a2f9c --- /dev/null +++ b/tktable/demos/tktable.py @@ -0,0 +1,344 @@ +# +# #### OUTDATE MODULE #### +# This has been superceded by the tktable.py that ships in the lib area. +# This is kept for compatibility as the newer wrapper is not 100% compatible. +# #### OUTDATE MODULE #### +# +# This file is taken from the usenet: +# http://groups.google.com/groups?selm=351A52BC.27EA0BE2%40desys.de +# From: Klaus Roethemeyer <klaus.roethemeyer at desys.de> +# +# It is provided here as an example of using Tktable with Python/Tkinter. + +#============================================================================ +# +# MODULE: This module contains the wrapper class for the tktable widget +# +# CREATED: Roethemeyer, 20.01.98 +# +# VERSION: $Id: tktable.py,v 1.1.1.1 2011/03/01 20:00:38 joye Exp $ +# +#============================================================================ + +#============================================================================ +# import modules +#---------------------------------------------------------------------------- +import string, types, Tkinter +#---------------------------------------------------------------------------- + +#============================================================================ +# ArrayVar +#---------------------------------------------------------------------------- +class ArrayVar(Tkinter.Variable): + _default = '' + + def __init__(self, master = None): + Tkinter.Variable.__init__(self, master) + + def get(self, index = None): + if not index: + res = {} + for i in self.names(): + res[i] = self._tk.globalgetvar(self._name, i) + try: del res['None'] + except KeyError: pass + return res + else: + return self._tk.globalgetvar(self._name, index) + + def names(self): + return string.split(self._tk.call('array', 'names', self._name)) + + def set(self, index, value = ''): + if value == None: + value = '' + return self._tk.globalsetvar(self._name, index, value) +#---------------------------------------------------------------------------- + + +#============================================================================ +# Table +#---------------------------------------------------------------------------- +class Table(Tkinter.Widget): + + _switches1 = ('cols', 'holddimensions', 'holdtags', 'keeptitles', 'rows', '-') + _tabsubst_format = ('%c', '%C', '%i', '%r', '%s', '%S', '%W') + _tabsubst_commands = ('browsecommand', 'browsecmd', 'command', + 'selectioncommand', 'selcmd', + 'validatecommand', 'valcmd') + + def __init__(self, master, cnf={}, **kw): + try: + master.tk.call('package', 'require', 'Tktable') + except Tkinter.TclError: + master.tk.call('load', '', 'Tktable') + Tkinter.Widget.__init__(self, master, 'table', cnf, kw) + + def _options(self, cnf, kw = None): + if kw: + cnf = Tkinter._cnfmerge((cnf, kw)) + else: + cnf = Tkinter._cnfmerge(cnf) + res = () + for k, v in cnf.items(): + if v is not None: + if k[-1] == '_': k = k[:-1] + if callable(v): + if k in self._tabsubst_commands: + v = "%s %s" % (self._register(v, self._tabsubst), + string.join(self._tabsubst_format)) + else: + v = self._register(v) + res = res + ('-'+k, v) + return res + + def _tabsubst(self, *args): + tk = self.tk + if len(args) != len(self._tabsubst_format): return args + c, C, i, r, s, S, W = args + e = Tkinter.Event() + e.widget = self + e.c = tk.getint(c) + e.i = tk.getint(i) + e.r = tk.getint(r) + e.C = (e.r, e.c) + try: e.s = tk.getint(s) + except Tkinter.TclError: e.s = s + try: e.S = tk.getint(S) + except Tkinter.TclError: e.S = S + e.W = W + return (e,) + + + def _getCells(self, cellString): + res = [] + for i in string.split(cellString): + res.append(tuple(map(int, string.split(i, ',')))) + return res + + def _getLines(self, lineString): + return map(int, string.split(lineString)) + + def _prepareArgs1(self, args): + args = list(args) + + for i in xrange(len(args)): + if args[i] in self._switches1: + args[i] = "-" + args[i] + + return tuple(args) + + + def activate(self, index): + self.tk.call(self._w, 'activate', index) + + def bbox(self, first, last=None): + return self._getints(self.tk.call(self._w, 'bbox', first, last)) or None + + def border_mark(self, x, y, row=None, col=None): + self.tk.call(self._w, 'border', 'mark', x, y, row, col) + + def border_dragto(self, x, y): + self.tk.call(self._w, 'border', 'dragto', x, y) + + def curselection(self, setValue = None): + if setValue != None: + self.tk.call(self._w, 'curselection', 'set', setValue) + + else: + return self._getCells(self.tk.call(self._w, 'curselection')) + + def delete_active(self, index, more = None): + self.tk.call(self._w, 'delete', 'active', index, more) + + def delete_cols(self, *args): + apply(self.tk.call, (self._w, 'delete', 'cols') + self._prepareArgs1(args)) + + def delete_rows(self, *args): + apply(self.tk.call, (self._w, 'delete', 'rows') + self._prepareArgs1(args)) + + def flush(self, first=None, last=None): + self.tk.call(self._w, 'flush', first, last) + + def get(self, first, last=None): + return self.tk.call(self._w, 'get', first, last) + + def height(self, *args): + apply(self.tk.call, (self._w, 'height') + args) + + def icursor(self, arg): + self.tk.call(self._w, 'icursor', arg) + + def index(self, index, rc = None): + if rc == None: + return self._getCells(self.tk.call(self._w, 'index', index, rc))[0] + else: + return self._getCells(self.tk.call(self._w, 'index', index, rc))[0][0] + + def insert_active(self, index, value): + self.tk.call(self._w, 'insert', 'active', index, value) + + def insert_cols(self, *args): + apply(self.tk.call, (self._w, 'insert', 'cols') + self._prepareArgs1(args)) + + def insert_rows(self, *args): + apply(self.tk.call, (self._w, 'insert', 'rows') + self._prepareArgs1(args)) + + def reread(self): + self.tk.call(self._w, 'reread') + + def scan_mark(self, x, y): + self.tk.call(self._w, 'scan', 'mark', x, y) + + def scan_dragto(self, x, y): + self.tk.call(self._w, 'scan', 'dragto', x, y) + + def see(self, index): + self.tk.call(self._w, 'see', index) + + def selection_anchor(self, index): + self.tk.call(self._w, 'selection', 'anchor', index) + + def selection_clear(self, first, last=None): + self.tk.call(self._w, 'selection', 'clear', first, last) + + def selection_includes(self, index): + return int(self.tk.call(self._w, 'selection', 'includes', index)) + + def selection_set(self, first, last=None): + self.tk.call(self._w, 'selection', 'set', first, last) + + def set(self, *args): + apply(self.tk.call, (self._w, 'set') + args) + + def tag_cell(self, tagName, *args): + result = apply(self.tk.call, (self._w, 'tag', 'cell', tagName) + args) + if not args: return self._getCells(result) + + def tag_cget(self, tagName, option): + return self.tk.call(self._w, 'tag', 'cget', tagName, '-' + option) + + def tag_col(self, tagName, *args): + result = apply(self.tk.call, (self._w, 'tag', 'col', tagName) + args) + if not args: return self._getLines(result) + + def tag_configure(self, tagName, cnf={}, **kw): + if not cnf and not kw: + return self.tk.call(self._w, 'tag', 'configure', tagName) + if type(cnf) == types.StringType and not kw: + return self.tk.call(self._w, 'tag', 'configure', tagName, '-' + cnf) + if type(cnf) == types.DictType: + apply(self.tk.call, + (self._w, 'tag', 'configure', tagName) + + self._options(cnf, kw)) + else: + raise TypeError, "usage: <instance>.tag_configure tagName [option] | [option=value]+" + + def tag_delete(self, tagName): + self.tk.call(self._w, 'tag', 'delete', tagName) + + def tag_exists(self, tagName): + return self.getboolean(self.tk.call(self._w, 'tag', 'exists', tagName)) + + def tag_includes(self, tagName, index): + return self.getboolean(self.tk.call(self._w, 'tag', 'includes', tagName, index)) + + def tag_names(self, pattern=None): + return self.tk.call(self._w, 'tag', 'names', pattern) + + def tag_row(self, tagName, *args): + result = apply(self.tk.call, (self._w, 'tag', 'row', tagName) + args) + if not args: return self._getLines(result) + + def validate(self, index): + self.tk.call(self._w, 'validate', index) + + def width(self, *args): + result = apply(self.tk.call, (self._w, 'width') + args) + if not args: + str = string.replace(result, '{', '') + str = string.replace(str, '}', '') + lst = string.split(str) + x = len(lst) + x2 = x / 2 + return tuple(map(lambda i, j, l=lst: (int(l[i]), int(l[j])), + xrange(x2), xrange(x2, x))) + elif len(args) == 1: + return int(result) + else: + return result + + def xview(self, *args): + if not args: + return self._getdoubles(self.tk.call(self._w, 'xview')) + apply(self.tk.call, (self._w, 'xview') + args) + + def yview(self, *args): + if not args: + return self._getdoubles(self.tk.call(self._w, 'yview')) + apply(self.tk.call, (self._w, 'yview') + args) +#---------------------------------------------------------------------------- + + +#============================================================================ +# Test-Function +#---------------------------------------------------------------------------- +if __name__ == '__main__': + from Tkinter import Tk, Label, Button + import pprint + + prn = pprint.PrettyPrinter(indent = 6).pprint + + def test_cmd(event=None): + if event.i == 0: + return '%i, %i' % (event.r, event.c) + else: + return 'set' + + + def browsecmd(event): + print "event:", event.__dict__ + print "curselection:", test.curselection() + print "active:", test.index('active', 'row') + print "anchor:", test.index('anchor', 'row') + + root = Tk() + #root.tk.call('load', '', 'Tktable') + + var = ArrayVar(root) + for y in range(-1, 4): + for x in range(-1, 5): + index = "%i,%i" % (y, x) + var.set(index, index) + + label = Label(root, text="Proof-of-existence test for Tktable") + label.pack(side = 'top', fill = 'x') + + quit = Button(root, text="QUIT", command=root.destroy) + quit.pack(side = 'bottom', fill = 'x') + + test = Table(root, + rows=10, + cols=5, + state='disabled', + width=6, + height=6, + titlerows=1, + titlecols=1, + roworigin=-1, + colorigin=-1, + selectmode='browse', + selecttype='row', + rowstretch='unset', + colstretch='last', + browsecmd=browsecmd, + flashmode='on', + variable=var, + usecommand=0, + command=test_cmd) + test.pack(expand=1, fill='both') + test.tag_configure('sel', background = 'yellow') + test.tag_configure('active', background = 'blue') + test.tag_configure('title', anchor='w', bg='red', relief='sunken') + root.mainloop() +#---------------------------------------------------------------------------- diff --git a/tktable/demos/valid.tcl b/tktable/demos/valid.tcl new file mode 100755 index 0000000..8a16a11 --- /dev/null +++ b/tktable/demos/valid.tcl @@ -0,0 +1,95 @@ +#!/bin/sh +# the next line restarts using wish \ +exec wish "$0" ${1+"$@"} + +## valid.tcl +## +## This demos shows the use of the validation mechanism of the table +## and uses the table's cache (no -command or -variable) +## +## jeff at hobbs org + +source [file join [file dirname [info script]] loadtable.tcl] + +array set table { + rows 10 + cols 10 + table .table +} + +proc colorize num { + if {$num>0 && $num%2} { return colored } +} + +proc fill_headers {w {r 10} {c 10}} { + for {set i 1} {$i < $r} {incr i} { + $w set $i,0 "$i" + } + for {set j 1} {$j < $c} {incr j} { + if {$j%3==1} { + $w set 0,$j AlphaNum + } elseif {$j%2==1} { + $w set 0,$j Alpha + } elseif {$j} { + $w set 0,$j Real + } + } +} + +proc validate {c val} { + if {$c%3==1} { + ## Alphanum + set expr {^[A-Za-z0-9 ]*$} + } elseif {$c%2==1} { + ## Alpha + set expr {^[A-Za-z ]*$} + } elseif {$c} { + ## Real + set expr {^[-+]?[0-9]*\.?[0-9]*([0-9]\.?e[-+]?[0-9]*)?$} + } + if {[regexp $expr $val]} { + return 1 + } else { + bell + return 0 + } +} + +label .example -text "TkTable v1 Validated Table Example" + +set t $table(table) +table $t \ + -rows $table(rows) \ + -cols $table(cols) \ + -cache 1 \ + -titlerows 1 \ + -titlecols 1 \ + -yscrollcommand { .tsy set } \ + -xscrollcommand { .tsx set } \ + -width 5 -height 5 \ + -coltagcommand colorize \ + -flashmode on \ + -selectmode extended \ + -colstretch unset \ + -rowstretch unset \ + -validate yes \ + -vcmd {if {![%W tag includes title %C]} { validate %c %S } } + +fill_headers $t +$t tag config colored -bg lightblue +$t tag config title -fg red +$t width 0 3 + +scrollbar .tsy -command [list $t yview] +scrollbar .tsx -command [list $t xview] -orient horizontal +button .exit -text "Exit" -command {exit} + +grid .example - -sticky ew +grid $t .tsy -sticky news +grid .tsx -sticky ew +grid .exit - -sticky ew +grid columnconfig . 0 -weight 1 +grid rowconfig . 1 -weight 1 + +puts [list Table is $table(table)] + diff --git a/tktable/doc/tkTable.html b/tktable/doc/tkTable.html new file mode 100644 index 0000000..4b264ff --- /dev/null +++ b/tktable/doc/tkTable.html @@ -0,0 +1,2039 @@ +<!-- manual page source format generated by PolyglotMan v3.0.8+X.Org, --> +<!-- available at http://polyglotman.sourceforge.net/ --> + +<html> +<head> +<title>man page(1) manual page</title> +</head> +<body bgcolor='#efefef' text='black' link='blue' vlink='#551A8B' alink='red'> +<a href='#toc'>Table of Contents</a><p> +______________________________________________________________________________ + +<p> +<h2><a name='sect0' href='#toc0'><b>Name</b></a></h2> + +<p> +table - Create and manipulate tables + +<p> +<h2><a name='sect1' href='#toc1'><b>Synopsis</b></a></h2> + +<p> +<b>table</b> <i>pathName</i> ?<i>options</i>? + +<p> +<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> + +<p></dd> +</dl> +<p> +See the <b>options</b> manual entry for details on the standard options. + +<p> +<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><p> +A boolean value which specifies whether the first keypress in a +cell will delete whatever text was previously there. Defaults +to 0. + +<p><p> +Command-Line Name:<b>-bordercursor</b><br> + +Database Name: <b>borderCursor</b><br> + +Database Class: <b>Cursor</b> + +<p><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><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><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><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><p> +Specifies a command which will be evaluated anytime the active +cell changes. It uses the %-substition model described in COMMAND +SUBSTITUTION below. Any changes to the active cell while +the command is running are ignored to prevent recursion. + +<p><p> +Command-Line Name:<b>-cache</b><br> + +Database Name: <b>cache</b><br> + +Database Class: <b>Cache</b> + +<p><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><p> +Command-Line Name:<b>-colorigin</b><br> + +Database Name: <b>colOrigin</b><br> + +Database Class: <b>Origin</b> + +<p><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><p> +Command-Line Name:<b>-cols</b><br> + +Database Name: <b>cols</b><br> + +Database Class: <b>Cols</b> + +<p><p> +Number of cols in the table. Defaults to 10. + +<p><p> +Command-Line Name:<b>-colseparator</b><br> + +Database Name: <b>colSeparator</b><br> + +Database Class: <b>Separator</b> + +<p><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><p> +Command-Line Name:<b>-colstretchmode</b><br> + +Database Name: <b>colStretchMode</b><br> + +Database Class: <b>StretchMode</b> + +<p><p> +Specifies one of the following stretch modes for columns to fill +extra allocated window space: + +<p><p> +<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><p> +<b>unset</b> Only columns that do not have a specific width set will +be stretched. + +<p> +<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. + +<p></dd> +</dl> +<p> +<b>last</b> The last column will be stretched to fill the window +space allocated to the table. + +<p><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><p> +Command-Line Name:<b>-coltagcommand</b><br> + +Database Name: <b>colTagCommand</b><br> + +Database Class: <b>TagCommand</b> + +<p><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 occurring during the evaluation of the procedure, or the +return of an invalid tag name are silently ignored. + +<p><p> +Command-Line Name:<b>-colwidth</b><br> + +Database Name: <b>colWidth</b><br> + +Database Class: <b>ColWidth</b> + +<p><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><p> +Command-Line Name:<b>-command</b><br> + +Database Name: <b>command</b><br> + +Database Class: <b>Command</b> + +<p><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><p> +Command-Line Name:<b>-drawmode</b><br> + +Database Name: <b>drawMode</b><br> + +Database Class: <b>DrawMode</b> + +<p><p> +Sets the table drawing mode to one of the following options: + +<p><p> +<b>slow</b> The table is drawn to an offscreen pixmap using the Tk +bordering functions (double-buffering). This means there +will be no flashing, but this mode is slow for larger +tables. + +<p><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> +<dl> + +<dt><b>fast</b> </dt></dt> +<dd>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></dd> +</dl> +<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><p> +Command-Line Name:<b>-ellipsis</b><br> + +Database Name: <b>ellipsis</b><br> + +Database Class: <b>Ellipsis</b> + +<p><p> +This specifies a string to display at the end of a line that +would be clipped by its cell, like ``...''. An ellipsis will be +displayed only on non-wrapping, non-multiline cells that would +be clipped. The ellipsis will display on the left for east +anchored cells, otherwise it displays on the right. Defaults to + (no ellipsis). + +<p><p> +Command-Line Name:<b>-flashmode</b><br> + +Database Name: <b>flashMode</b><br> + +Database Class: <b>FlashMode</b> + +<p><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><p> +Command-Line Name:<b>-flashtime</b><br> + +Database Name: <b>flashTime</b><br> + +Database Class: <b>FlashTime</b> + +<p><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><p> +Command-Line Name:<b>-height</b><br> + +Database Name: <b>height</b><br> + +Database Class: <b>Height</b> + +<p><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><p> +Command-Line Name:<b>-invertselected</b><br> + +Database Name: <b>invertSelected</b><br> + +Database Class: <b>InvertSelected</b> + +<p><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><p> +Command-Line Name:<b>-ipadx</b><br> + +Database Name: <b>ipadX</b><br> + +Database Class: <b>Pad</b> + +<p><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><p> +Command-Line Name:<b>-ipady</b><br> + +Database Name: <b>ipadY</b><br> + +Database Class: <b>Pad</b> + +<p><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><p> +Command-Line Name:<b>-justify</b><br> + +Database Name: <b>justify</b><br> + +Database Class: <b>Justify</b> + +<p><p> +How to justify multi-line text in a cell. It must be one of +<b>left</b>, <b>right</b>, or <b>center</b>. Defaults to left. + +<p><p> +Command-Line Name:<b>-maxheight</b><br> + +Database Name: <b>maxHeight</b><br> + +Database Class: <b>MaxHeight</b> + +<p><p> +The max height in pixels that the window will request. Defaults +to 600. + +<p><p> +Command-Line Name:<b>-maxwidth</b><br> + +Database Name: <b>maxWidth</b><br> + +Database Class: <b>MaxWidth</b> + +<p><p> +The max width in pixels that the window will request. Defaults +to 800. + +<p><p> +Command-Line Name:<b>-multiline</b><br> + +Database Name: <b>multiline</b><br> + +Database Class: <b>Multiline</b> + +<p><p> +Specifies the default setting for the multiline tag option. +Defaults to 1. + +<p><p> +Command-Line Name:<b>-padx</b><br> + +Database Name: <b>padX</b><br> + +Database Class: <b>Pad</b> + +<p><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><p> +Command-Line Name:<b>-pady</b><br> + +Database Name: <b>padY</b><br> + +Database Class: <b>Pad</b> + +<p><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><p> +Command-Line Name:<b>-resizeborders</b><br> + +Database Name: <b>resizeBorders</b><br> + +Database Class: <b>ResizeBorders</b> + +<p><p> +Specifies what kind of interactive border resizing to allow, +must be one of row, col, both (default) or none. + +<p><p> +Command-Line Name:<b>-rowheight</b><br> + +Database Name: <b>rowHeight</b><br> + +Database Class: <b>RowHeight</b> + +<p><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><p> +Command-Line Name:<b>-roworigin</b><br> + +Database Name: <b>rowOrigin</b><br> + +Database Class: <b>Origin</b> + +<p><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><p> +Command-Line Name:<b>-rows</b><br> + +Database Name: <b>rows</b><br> + +Database Class: <b>Rows</b> + +<p><p> +Number of rows in the table. Defaults to 10. + +<p><p> +Command-Line Name:<b>-rowseparator</b><br> + +Database Name: <b>rowSeparator</b><br> + +Database Class: <b>Separator</b> + +<p><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><p> +Command-Line Name:<b>-rowstretchmode</b><br> + +Database Name: <b>rowStretchMode</b><br> + +Database Class: <b>StretchMode</b> + +<p><p> +Specifies the stretch modes for rows to fill extra allocated +window space. See <b>-colstretchmode</b> for valid options. + +<p><p> +Command-Line Name:<b>-rowtagcommand</b><br> + +Database Name: <b>rowTagCommand</b><br> + +Database Class: <b>TagCommand</b> + +<p><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><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><p> +Specifies a command to evaluate when the selection is retrieved +from a table via the selection mechanism (ie: evaluating +``<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><p> +Command-Line Name:<b>-selectmode</b><br> + +Database Name: <b>selectMode</b><br> + +Database Class: <b>SelectMode</b> + +<p><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><p> +Command-Line Name:<b>-selecttitle</b><br> + +Database Name: <b>selectTitles</b><br> + +Database Class: <b>SelectTitles</b> + +<p><p> +Specifies whether title cells should be allowed in the selection. +Defaults to 0 (disallowed). + +<p><p> +Command-Line Name:<b>-selecttype</b><br> + +Database Name: <b>selectType</b><br> + +Database Class: <b>SelectType</b> + +<p><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>&&</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><p> +Command-Line Name:<b>-sparsearray</b><br> + +Database Name: <b>sparseArray</b><br> + +Database Class: <b>SparseArray</b> + +<p><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><p> +Command-Line Name:<b>-state</b><br> + +Database Name: <b>state</b><br> + +Database Class: <b>State</b> + +<p><p> +Specifies one of two states for the entry: <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>. + +<p><p> +Command-Line Name:<b>-titlecols</b><br> + +Database Name: <b>titleCols</b><br> + +Database Class: <b>TitleCols</b> + +<p><p> +Number of columns to use as a title area. Defaults to 0. + +<p><p> +Command-Line Name:<b>-titlerows</b><br> + +Database Name: <b>titleRows</b><br> + +Database Class: <b>TitleRows</b> + +<p><p> +Number of rows to use as a title area. Defaults to 0. + +<p><p> +Command-Line Name:<b>-usecommand</b><br> + +Database Name: <b>useCommand</b><br> + +Database Class: <b>UseCommand</b> + +<p><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><p> +Command-Line Name:<b>-validate</b><br> + +Database Name: <b>validate</b><br> + +Database Class: <b>Validate</b> + +<p><p> +A boolean specifying whether validation should occur for the +active buffer. Defaults to 0. + +<p><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><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><p> +Command-Line Name:<b>-variable</b><br> + +Database Name: <b>variable</b><br> + +Database Class: <b>Variable</b> + +<p><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 does not require that 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><p> +Command-Line Name:<b>-width</b><br> + +Database Name: <b>width</b><br> + +Database Class: <b>Width</b> + +<p><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><p> +Command-Line Name:<b>-wrap</b><br> + +Database Name: <b>wrap</b><br> + +Database Class: <b>Wrap</b> + +<p><p> +Specifies the default wrap value for tags. Defaults to 0. +_________________________________________________________________ + +<p> +<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, +as well as optionally cache data in memory for speed. One of these +data sources <i>must</i> be configured before any data is retained by the table. +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 EMBEDDED WINDOWS respectively. + +<p><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><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><p> +In order to obtain good performance, the table widget supports multiple +drawing modes, two of which are fully Tk compatible. + +<p> +<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><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. + +<p> +<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><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). The values for row and column will +be constrained to actual values in the table, which means a +valid cell is always found. + +<p> +<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. + +<p></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. + +<p></dd> +</dl> +<p> +<b>bottomright</b> Indicates the bottom-rightmost cell visible in the table. + +<p> +<dl> + +<dt><b>end</b> </dt></dt> +<dd> Indicates the bottom right cell of the table. + +<p></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. + +<p></dd> + +<dt><b>topleft</b> </dt></dt> +<dd> Indicates the top-leftmost editable cell visible in the table +(this excludes title cells). + +<p></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. + +<p></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. + +<p> +<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. A tag can apply to an entire row or column, +or just a single cell. There are several permanent tags in each table +that can be configured by the user and will determine the attributes +for special cells: + +<p> +<dl> + +<dt><b>active</b> </dt></dt> +<dd> This tag is given to the <i>active</i> cell + +<p></dd> + +<dt><b>flash</b> </dt></dt> +<dd> If flash mode is on, this tag is given to any recently +edited cells. + +<p></dd> + +<dt><b>sel</b> </dt></dt> +<dd> This tag is given to any selected cells. + +<p></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. + +<p></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: + +<p> +<dl> + +<dt><b>-anchor</b> <i>anchor</i></dt></dt> +<dd> +Anchor for item in the cell space. + +<p></dd> + +<dt><b>-background</b> or <b>-bg</b> <i>color</i></dt></dt> +<dd> +Background color of the cell. + +<p></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). + +<p></dd> + +<dt><b>-ellipsis</b> <i>string</i></dt></dt> +<dd> +String to display at the end of a line that would be +clipped by its cell, like ``...''. An ellipsis will be +displayed only on non-wrapping, non-multiline cells that +would be clipped. The ellipsis will display on the left +for east anchored cells, otherwise it displays on the +right. + +<p></dd> + +<dt><b>-font</b> <i>fontName</i></dt></dt> +<dd> +Font for text in the cell. + +<p></dd> + +<dt><b>-foreground</b> or <b>-fg</b> <i>color</i></dt></dt> +<dd> +Foreground color of the cell. + +<p></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>. + +<p></dd> + +<dt><b>-image</b> <i>imageName</i></dt></dt> +<dd> +An image to display in the cell instead of text. + +<p></dd> + +<dt><b>-multiline</b> <i>boolean</i></dt></dt> +<dd> +Whether to display text with newlines on multiple lines. + +<p></dd> + +<dt><b>-relief</b> <i>relief</i></dt></dt> +<dd> +The relief for the cell. May be the empty string to +cause this tag to not disturb the value. + +<p></dd> + +<dt><b>-showtext</b> <i>boolean</i></dt></dt> +<dd> +Whether to show the text over an image. + +<p></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. + +<p></dd> + +<dt><b>-wrap</b> <i>boolean</i></dt></dt> +<dd> +Whether characters should wrap in a cell that is not wide +enough. + +<p></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>path</i><b>_N</b><i>ame</i> +<b>tag</b> <b>lower</b>'' and ``<i>pathName</i> <b>tag</b> <b>raise</b>'' widget commands. + +<p><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><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>. + +<p> +<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><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><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: + +<p> +<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. + +<p></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. + +<p></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). + +<p></dd> + +<dt><b>-padx</b> <i>pixels</i></dt></dt> +<dd> +As defined in the Tk options man page. + +<p></dd> + +<dt><b>-pady</b> <i>pixels</i></dt></dt> +<dd> +As defined in the Tk options man page. + +<p></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. + +<p></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. + +<p></dd> + +<dt><b>-window</b> <i>pathName</i></dt></dt> +<dd> +Specifies the name of a window (widget) to display in the +annotation. It must exist before being specified here. +When an empty string is specified, if a window was displayed +it will cease to be managed by the table widget. + +<p></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 `\n' and <b>-colseparator</b> to +`\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. + +<p> +<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><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><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><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. + +<p> +<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><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. + +<p> +<dl> + +<dt><b>%C</b> </dt></dt> +<dd>A convenience substitution for <i>%r</i>,<i>%c</i>. + +<p></dd> +</dl> +<p> +<b>%i</b> 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. + +<p><p> +<b>%r</b> For <b>SelectionCommand</b>, it is the number of rows in the selection. +Otherwise it is the row of the triggered cell. + +<p><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). + +<p><p> +<b>%S</b> 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. + +<p> +<dl> + +<dt><b>%W</b> </dt></dt> +<dd>The pathname to the window for which the command was generated. + +<p></dd> +</dl> + +<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><p> +The following commands are possible for <b>table</b> widgets: + +<p><p> +<i>pathName</i> <b>activate</b> <i>index</i><br> + +Sets the active cell to the one indicated by <i>index</i>. + +<p><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><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><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><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><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><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><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><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><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><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><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>pathName</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><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><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><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>: + +<p><p> +<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><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: + +<p> +<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>. + +<p></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.. + +<p></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. + +<p></dd> + +<dt><b>-holdwindows</b></dt></dt> +<dd> +Causes the embedded windows created with the <i>win</i><b>_</b>d<i>ow</i> +method to not move along with the data. By +default, these windows are properly adjusted. + +<p></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. + +<p></dd> + +<dt><b>--</b> </dt></dt> +<dd> Signifies the end of the switches. + +<p></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><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><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><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><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><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><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><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> +position 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><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><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><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 <Escape> is pressed to +abort the edit (a default binding). + +<p><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><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><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><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><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><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><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><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><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><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><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><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><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><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><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><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><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><p> +<i>pathName</i> <b>tag</b> <b>exists</b> <i>tagName</i><br> + +Returns 1 if the named tag exists, 0 otherwise. + +<p><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><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><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><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><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 rows 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><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><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><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><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><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><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><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><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>pattern</i> is used as a glob +pattern to show only cells matching that pattern. + +<p><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><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><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><p> +<i>pathName</i> <b>xview</b> <b>moveto</b> <i>fraction</i><br> + +Adjusts the view in the window so that <i>fraction</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><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> cells 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 cells farther to the left become visible; if +it is positive then cells farther to the right become +visible. + +<p><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><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><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><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><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> cells; if it is +<b>pages</b> then the view adjusts by <i>number</i> screenfuls. If +<i>number</i> is negative then earlier elements become visible; +if it is positive then later elements become visible. + +<p> +<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: + +<p> +<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. + +<p></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. + +<p></dd> + +<dt>[3] </dt></dt> +<dd> Moving the mouse while Button-2 is pressed causes scanning to +occur without any selection. + +<p></dd> + +<dt>[4] </dt></dt> +<dd> Home moves the table to have the origin in view. + +<p></dd> + +<dt>[5] </dt></dt> +<dd> End moves the table to have the <b>end</b> cell in view. + +<p></dd> + +<dt>[6] </dt></dt> +<dd> Control-Home moves the table to the origin and activates that +cell. + +<p></dd> + +<dt>[7] </dt></dt> +<dd> Control-End moves the table to the end and activates that cell. + +<p></dd> + +<dt>[8] </dt></dt> +<dd> Shift-Control-Home extends the selection to the origin. + +<p></dd> + +<dt>[9] </dt></dt> +<dd> Shift-Control-End extends the selection to the end. + +<p></dd> + +<dt>[10] </dt></dt> +<dd>The left, right, up and down arrows move the active cell. + +<p></dd> + +<dt>[11] </dt></dt> +<dd>Shift-<arrow> extends the selection in that direction. + +<p></dd> + +<dt>[12] </dt></dt> +<dd>Control-leftarrow and Control-rightarrow move the insertion cursor +within the cell. + +<p></dd> + +<dt>[13] </dt></dt> +<dd>Control-slash selects all the cells. + +<p></dd> + +<dt>[14] </dt></dt> +<dd>Control-backslash clears selection from all the cells. + +<p></dd> +</dl> +<p> +[15] Backspace deletes the character before the insertion cursor in +the active cell. + +<p><p> +[16] Delete deletes the character after the insertion cursor in the +active cell. + +<p><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><p> +[18] Control-a moves the insertion cursor to the beginning of the +active cell. + +<p><p> +[19] Control-e moves the insertion cursor to the end of the active +cell. + +<p> +<dl> + +<dt>[20] </dt></dt> +<dd>Control-minus and Control-equals decrease and increase the width +of the column with the active cell in it. + +<p></dd> + +<dt>[21] </dt></dt> +<dd>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></dd> +</dl> +<p> +Some bindings may have slightly different behavior dependent on the +<b>-selectionmode</b> of the widget. + +<p><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><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: [lindex $tcl_pkgPath 0]/Tktable<version>/tkTable.tcl". + +<p> +<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><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. + +<p> +<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.<br> + +$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] + +<p> +<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/tktable/doc/tkTable.n b/tktable/doc/tkTable.n new file mode 100755 index 0000000..5be90f2 --- /dev/null +++ b/tktable/doc/tkTable.n @@ -0,0 +1,1432 @@ +'\" +'\" The definitions below are for supplemental macros used in Tcl/Tk +'\" manual entries. +'\" +'\" RCS: @(#) $Id: tkTable.n,v 1.1.1.1 2011/03/01 20:00:38 joye Exp $ +'\" +'\" .AP type name in/out ?indent? +'\" Start paragraph describing an argument to a library procedure. +'\" type is type of argument (int, etc.), in/out is either "in", "out", +'\" or "in/out" to describe whether procedure reads or modifies arg, +'\" and indent is equivalent to second arg of .IP (shouldn't ever be +'\" needed; use .AS below instead) +'\" +'\" .AS ?type? ?name? +'\" Give maximum sizes of arguments for setting tab stops. Type and +'\" name are examples of largest possible arguments that will be passed +'\" to .AP later. If args are omitted, default tab stops are used. +'\" +'\" .BS +'\" Start box enclosure. From here until next .BE, everything will be +'\" enclosed in one large box. +'\" +'\" .BE +'\" End of box enclosure. +'\" +'\" .CS +'\" Begin code excerpt. +'\" +'\" .CE +'\" End code excerpt. +'\" +'\" .VS ?br? +'\" Begin vertical sidebar, for use in marking newly-changed parts +'\" of man pages. If an argument is present, then a line break is +'\" forced before starting the sidebar. +'\" +'\" .VE +'\" End of vertical sidebar. +'\" +'\" .DS +'\" Begin an indented unfilled display. +'\" +'\" .DE +'\" End of indented unfilled display. +'\" +'\" .SO +'\" Start of list of standard options for a Tk widget. The +'\" options follow on successive lines, in four columns separated +'\" by tabs. +'\" +'\" .SE +'\" End of list of standard options for a Tk widget. +'\" +'\" .OP cmdName dbName dbClass +'\" Start of description of a specific option. cmdName gives the +'\" option's name as specified in the class command, dbName gives +'\" the option's name in the option database, and dbClass gives +'\" the option's class in the option database. +'\" +'\" .UL arg1 arg2 +'\" Print arg1 underlined, then print arg2 normally. +'\" +'\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages. +.if t .wh -1.3i ^B +.nr ^l \n(.l +.ad b +'\" # Start an argument description +.de AP +.ie !'\\$4'' .TP \\$4 +.el \{\ +. ie !'\\$2'' .TP \\n()Cu +. el .TP 15 +.\} +.ie !'\\$3'' \{\ +.ta \\n()Au \\n()Bu +\&\\$1 \\fI\\$2\\fP (\\$3) +.\".b +.\} +.el \{\ +.br +.ie !'\\$2'' \{\ +\&\\$1 \\fI\\$2\\fP +.\} +.el \{\ +\&\\fI\\$1\\fP +.\} +.\} +.. +'\" # define tabbing values for .AP +.de AS +.nr )A 10n +.if !'\\$1'' .nr )A \\w'\\$1'u+3n +.nr )B \\n()Au+15n +.\" +.if !'\\$2'' .nr )B \\w'\\$2'u+\\n()Au+3n +.nr )C \\n()Bu+\\w'(in/out)'u+2n +.. +.AS Tcl_Interp Tcl_CreateInterp in/out +'\" # BS - start boxed text +'\" # ^y = starting y location +'\" # ^b = 1 +.de BS +.br +.mk ^y +.nr ^b 1u +.if n .nf +.if n .ti 0 +.if n \l'\\n(.lu\(ul' +.if n .fi +.. +'\" # BE - end boxed text (draw box now) +.de BE +.nf +.ti 0 +.mk ^t +.ie n \l'\\n(^lu\(ul' +.el \{\ +.\" Draw four-sided box normally, but don't draw top of +.\" box if the box started on an earlier page. +.ie !\\n(^b-1 \{\ +\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' +.\} +.el \}\ +\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' +.\} +.\} +.fi +.br +.nr ^b 0 +.. +'\" # VS - start vertical sidebar +'\" # ^Y = starting y location +'\" # ^v = 1 (for troff; for nroff this doesn't matter) +.de VS +.if !'\\$1'' .br +.mk ^Y +.ie n 'mc \s12\(br\s0 +.el .nr ^v 1u +.. +'\" # VE - end of vertical sidebar +.de VE +.ie n 'mc +.el \{\ +.ev 2 +.nf +.ti 0 +.mk ^t +\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' +.sp -1 +.fi +.ev +.\} +.nr ^v 0 +.. +'\" # Special macro to handle page bottom: finish off current +'\" # box/sidebar if in box/sidebar mode, then invoked standard +'\" # page bottom macro. +.de ^B +.ev 2 +'ti 0 +'nf +.mk ^t +.if \\n(^b \{\ +.\" Draw three-sided box if this is the box's first page, +.\" draw two sides but no top otherwise. +.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c +.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c +.\} +.if \\n(^v \{\ +.nr ^x \\n(^tu+1v-\\n(^Yu +\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c +.\} +.bp +'fi +.ev +.if \\n(^b \{\ +.mk ^y +.nr ^b 2 +.\} +.if \\n(^v \{\ +.mk ^Y +.\} +.. +'\" # DS - begin display +.de DS +.RS +.nf +.sp +.. +'\" # DE - end display +.de DE +.fi +.RE +.sp +.. +'\" # SO - start of list of standard options +.de SO +.SH "STANDARD OPTIONS" +.LP +.nf +.ta 4c 8c 12c +.ft B +.. +'\" # SE - end of list of standard options +.de SE +.fi +.ft R +.LP +See the \\fBoptions\\fR manual entry for details on the standard options. +.. +'\" # OP - start of full description for a single option +.de OP +.LP +.nf +.ta 4c +Command-Line Name: \\fB\\$1\\fR +Database Name: \\fB\\$2\\fR +Database Class: \\fB\\$3\\fR +.fi +.IP +.. +'\" # CS - begin code excerpt +.de CS +.RS +.nf +.ta .25i .5i .75i 1i +.. +'\" # CE - end code excerpt +.de CE +.fi +.RE +.. +.de UL +\\$1\l'|0\(ul'\\$2 +.. +.TH table n 2.8 Tk "Tk Table Extension" +.HS table tk +.BS +.SH NAME +table \- Create and manipulate tables +.SH SYNOPSIS +\fBtable\fI \fIpathName \fR?\fIoptions\fR? +.SO +\-anchor \-background \-cursor +\-exportselection \-font \-foreground +\-highlightbackground \-highlightcolor \-highlightthickness +\-insertbackground \-insertborderwidth \-insertofftime +\-insertontime \-insertwidth \-invertselected +\-relief \-takefocus \-xscrollcommand +\-yscrollcommand +.SE + +.SH "WIDGET-SPECIFIC OPTIONS" +.OP \-autoclear autoClear AutoClear +A boolean value which specifies whether the first keypress in a cell will +delete whatever text was previously there. Defaults to 0. +.OP \-bordercursor borderCursor Cursor +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 \fIcrosshair\fR. +.OP "\-borderwidth or \-bd" borderWidth BorderWidth +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 \fBrelief\fR 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 +\fB\-drawmode\fR for the table. Each value in the list must have one of +the forms acceptable to \fBTk_GetPixels\fR. +.OP "\-browsecommand or \-browsecmd" browseCommand BrowseCommand +Specifies a command which will be evaluated anytime the active cell changes. +It uses the %\-substition model described in COMMAND SUBSTITUTION below. +Any changes to the active cell while the command is running are ignored to +prevent recursion. +.OP \-cache cache Cache +A boolean value that specifies whether an internal cache of the table +contents should be kept. This greatly enhances speed performance when used +with \fB\-command\fR but uses extra memory. Can maintain state when both +\fB\-command\fR and \fB\-variable\fR are empty. The cache is automatically +flushed whenever the value of \fB\-cache\fR or \fB\-variable\fR changes, +otherwise you have to explicitly call \fBclear\fR on it. Defaults to off. +.OP \-colorigin colOrigin Origin +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. +.OP \-cols cols Cols +Number of cols in the table. Defaults to 10. +.OP \-colseparator colSeparator Separator +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. +.OP \-colstretchmode colStretchMode StretchMode +Specifies one of the following stretch modes for columns to fill extra +allocated window space: +.RS +.TP +\fBnone\fR +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. +.TP +\fBunset\fR +Only columns that do not have a specific width set will be stretched. +.TP +\fBall\fR +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. +.TP +\fBlast\fR +The last column will be stretched +to fill the window space allocated to the table. +.TP +\fBfill\fR (only valid for \fB\-rowstretch\fR 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. +.RE +.OP \-coltagcommand colTagCommand TagCommand +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 +\fBtag col\fR 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 occurring during the evaluation of the procedure, or the return of an +invalid tag name are silently ignored. +.OP \-colwidth colWidth ColWidth +Default column width, interpreted as characters in the default font when +the number is positive, or pixels if it is negative. Defaults to 10. +.OP \-command command Command +Specified a command to use as a procedural interface to cell values. +If \fB\-usecommand\fR is true, this command will be used instead of any +reference to the \fB\-variable\fR 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. +.OP \-drawmode drawMode DrawMode +Sets the table drawing mode to one of the following options: +.RS +.TP +\fBslow\fR +The table is drawn to an offscreen pixmap using the Tk bordering functions +(double-buffering). This means there will be no flashing, but this mode is +slow for larger tables. +.TP +\fBcompatible\fR +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. +.TP +\fBfast\fR +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 \fB\-borderwidth\fR 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. +.TP +\fBsingle\fR +The table is drawn to the screen as in fast mode, but only single pixel +lines are drawn (not square borders). +.RE +.OP \-ellipsis ellipsis Ellipsis +This specifies a string to display at the end of a line that would be +clipped by its cell, like ``...''. An ellipsis will be displayed only +on non-wrapping, non-multiline cells that would be clipped. The ellipsis +will display on the left for east anchored cells, otherwise it displays +on the right. +Defaults to "" (no ellipsis). +.OP \-flashmode flashMode FlashMode +A boolean value which specifies whether cells should flash when their value +changes. The table tag \fBflash\fR will be applied to these cells for the +duration specified by \fB\-flashtime\fR. Defaults to 0. +.OP \-flashtime flashTime FlashTime +The amount of time, in 1/4 second increments, for which a cell should flash +when its value has changed. \fB\-flashmode\fR must be on. Defaults to 2. +.OP \-height height Height +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 \fB\-maxheight\fR. +.OP \-invertselected invertSelected InvertSelected +Specifies whether the foreground and background of an item should simply +have their values swapped instead of merging the \fIsel\fR tag options +when the cell is selected. Defaults to 0 (merge \fIsel\fR tag). +.OP \-ipadx ipadX Pad +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 \fB\-padx\fR for an alternate padding +style. +.OP \-ipady ipadY Pad +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 \fB\-pady\fR for an alternate padding +style. +.OP \-justify justify Justify +How to justify multi\-line text in a cell. +It must be one of \fBleft\fR, \fBright\fR, or \fBcenter\fR. +Defaults to left. +.OP \-maxheight maxHeight MaxHeight +The max height in pixels that the window will request. Defaults to 600. +.OP \-maxwidth maxWidth MaxWidth +The max width in pixels that the window will request. Defaults to 800. +.OP \-multiline multiline Multiline +Specifies the default setting for the multiline tag option. Defaults to 1. +.OP \-padx padX Pad +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 \fBwidth\fR 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 \fB\-ipadx\fR for an alternate padding style. +.OP \-pady padY Pad +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 \fBheight\fR 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 \fB\-ipadx\fR for an alternate padding style. +.OP \-resizeborders resizeBorders ResizeBorders +Specifies what kind of interactive border resizing to allow, must be one of +row, col, both (default) or none. +.OP \-rowheight rowHeight RowHeight +Default row height, interpreted as lines in the default font when +the number is positive, or pixels if it is negative. Defaults to 1. +.OP \-roworigin rowOrigin Origin +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. +.OP \-rows rows Rows +Number of rows in the table. Defaults to 10. +.OP \-rowseparator rowSeparator Separator +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. +.OP \-rowstretchmode rowStretchMode StretchMode +Specifies the stretch modes for rows to fill extra +allocated window space. See \fB\-colstretchmode\fR for valid options. +.OP \-rowtagcommand rowTagCommand TagCommand +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 +\fB\-coltagcommand\fR, except that it applies to row tags. +.OP "\-selectioncommand or \-selcmd" selectionCommand SelectionCommand +Specifies a command to evaluate when the selection is retrieved from a +table via the selection mechanism (ie: evaluating ``\fBselection get\fR''). +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. +.OP \-selectmode selectMode SelectMode +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 \fBsingle\fR, \fBbrowse\fR, \fBmultiple\fR, or \fBextended\fR; the +default value is \fBbrowse\fR. These styles are like those for the Tk +listbox, except expanded for 2 dimensions. +.OP \-selecttitle selectTitles SelectTitles +Specifies whether title cells should be allowed in the selection. +Defaults to 0 (disallowed). +.OP \-selecttype selectType SelectType +Specifies one of several types of selection for the table. The value of the +option may be one of \fBrow\fR, \fBcol\fR, \fBcell\fR, or \fBboth\fR +(meaning \fBrow && col\fR); the default value is \fBcell\fR. These types +define whether an entire row/col is affected when a cell's selection is +changed (set or clear). +.OP \-sparsearray sparseArray SparseArray +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. +.OP \-state state State +Specifies one of two states for the entry: \fBnormal\fR or \fBdisabled\fR. +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 \fBnormal\fR. +.OP \-titlecols titleCols TitleCols +Number of columns to use as a title area. Defaults to 0. +.OP \-titlerows titleRows TitleRows +Number of rows to use as a title area. Defaults to 0. +.OP \-usecommand useCommand UseCommand +A boolean value which specifies whether to use the \fBcommand\fR option. +This value sets itself to zero if \fBcommand\fR is used and returns an error. +Defaults to 1 (will use \fBcommand\fR if specified). +.OP \-validate validate Validate +A boolean specifying whether validation should occur for the active buffer. +Defaults to 0. +.OP "\-validatecommand or \-vcmd" validateCommand ValidateCommand +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. +.OP \-variable variable Variable +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 \fIrow\fR,\fIcol\fR for cells and +the special key \fIactive\fR which contains the value of the active cell +buffer. The Tcl array is managed as a sparse array (the table does not +require that 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 \fB\-sparsearray\fR options is set to 0. +.OP \-width width Width +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 \fB\-maxwidth\fR. +.OP \-wrap wrap Wrap +Specifies the default wrap value for tags. Defaults to 0. +.BE + +.SH DESCRIPTION +.PP +The \fBtable\fR command creates a 2\-dimensional grid of cells. The table +can use a Tcl array variable or Tcl command for data storage and retrieval, +as well as optionally cache data in memory for speed. One of these data +sources \fImust\fR be configured before any data is retained by the table. +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 \fItags\fR, which can be used to change the style of a +row, column or cell (see TAGS for details). A cell \fIflash\fR 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 "EMBEDDED WINDOWS" respectively. +.PP +One or more cells may be selected as described below. If a table is +exporting its selection (see \fB\-exportselection\fR option), then it will +observe the standard X11 protocols for handling the selection. See THE +SELECTION for details. +.PP +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 +\fB\-xscrollcommand\fR and \fB\-yscrollcommand\fR options. They also support +scanning, as described below. +.PP +In order to obtain good performance, the table widget supports multiple +drawing modes, two of which are fully Tk compatible. + +.SH "INITIALIZATION" +.PP +When the \fBtable\fR command is loaded into an interpreter, a built-in +Tcl command, \fBtkTableInit\fR, is evaluated. This will search for the +appropriate table binding init file to load. The directories searched +are those in \fI$tcl_pkgPath\fR, both with Tktable(version) appended and +without, \fI$tk_library\fR and \fI[pwd]\fR (the current directory). You +can also define an \fI$env(TK_TABLE_LIBRARY)\fR to head this search list. +By default, the file searched for is called \fBtkTable.tcl\fR, but this +can be overridden by setting \fI$env(TK_TABLE_LIBRARY_FILE)\fR. +.PP +This entire init script can be overridden by providing your own +\fBtkTableInit\fR procedure before the library is loaded. Otherwise, the +aforementioned \fIenv(TK_TABLE_LIBRARY)\fR variable will be set with the +directory in which \fI$env(TK_TABLE_LIBRARY_FILE)\fR was found. + +.SH "INDICES" +.PP +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: +.TP 12 +\fInumber,number\fR +Specifies the cell as a numerical index of row,col which corresponds to the +index of the associated Tcl array, where \fB\-roworigin,\-colorigin\fR +corresponds to the first cell in the table (0,0 by default). The values +for row and column will be constrained to actual values in the table, +which means a valid cell is always found. +.TP 12 +\fBactive\fR +Indicates the cell that has the location cursor. +It is specified with the \fBactivate\fR widget command. +.TP 12 +\fBanchor\fR +Indicates the anchor point for the selection, which is set with the +\fBselection anchor\fR widget command. +.TP 12 +\fBbottomright\fR +Indicates the bottom\-rightmost cell visible in the table. +.TP 12 +\fBend\fR +Indicates the bottom right cell of the table. +.TP 12 +\fBorigin\fR +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. +.TP 12 +\fBtopleft\fR +Indicates the top\-leftmost editable cell visible in the table (this +excludes title cells). +.TP 12 +\fB@\fIx\fB,\fIy\fR +Indicates the cell that covers the point in the table window +specified by \fIx\fR and \fIy\fR (in pixel coordinates). If no +cell covers that point, then the closest cell to that +point is used. +.LP +In the widget command descriptions below, arguments named \fIindex\fR, +\fIfirst\fR, and \fIlast\fR always contain text indices in one of +the above forms. + +.SH TAGS +.PP +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. A tag can apply to an entire row or column, or just a +single cell. There are several permanent tags in each table that can be +configured by the user and will determine the attributes for special cells: +.RS +.TP 10 +\fBactive\fR +This tag is given to the \fIactive\fR cell +.TP 10 +\fBflash\fR +If flash mode is on, this tag is given to any recently +edited cells. +.TP 10 +\fBsel\fR +This tag is given to any selected cells. +.TP 10 +\fBtitle\fR +This tag is given to any cells in the title rows and columns. This +tag has \fB\-state\fR \fIdisabled\fR by default. +.RE +.PP +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 ``\fIpathName \fBtag configure\fR'' 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: +.RS +.TP +\fB\-anchor\fR \fIanchor\fR +Anchor for item in the cell space. +.TP +\fB\-background\fR or \fB\-bg\fR \fIcolor\fR +Background color of the cell. +.TP +\fB\-borderwidth\fR or \fB\-bd\fR \fIpixelList\fR +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). +.TP +\fB\-ellipsis\fR \fIstring\fR +String to display at the end of a line that would be clipped by its cell, +like ``...''. An ellipsis will be displayed only +on non-wrapping, non-multiline cells that would be clipped. The ellipsis +will display on the left for east anchored cells, otherwise it displays +on the right. +.TP +\fB\-font\fR \fIfontName\fR +Font for text in the cell. +.TP +\fB\-foreground\fR or \fB\-fg\fR \fIcolor\fR +Foreground color of the cell. +.TP +\fB\-justify\fR \fIjustify\fR +How to justify multi\-line text in a cell. +It must be one of \fBleft\fR, \fBright\fR, or \fBcenter\fR. +.TP +\fB\-image\fR \fIimageName\fR +An image to display in the cell instead of text. +.TP +\fB\-multiline\fR \fIboolean\fR +Whether to display text with newlines on multiple lines. +.TP +\fB\-relief\fR \fIrelief\fR +The relief for the cell. May be the empty string to cause this tag to +not disturb the value. +.TP +\fB\-showtext\fR \fIboolean\fR +Whether to show the text over an image. +.TP +\fB\-state\fR \fIstate\fR +The state of the cell, to allow for certain cells to be disabled. +This prevents the cell from being edited by the \fIinsert\fR or \fIdelete\fR +methods, but a direct \fIset\fR will not be prevented. +.TP +\fB\-wrap\fR \fIboolean\fR +Whether characters should wrap in a cell that is not wide enough. +.RE +.PP +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 ``\fIpathName \fBtag +lower\fR'' and ``\fIpathName \fBtag raise\fR'' widget commands. +.PP +If a cell has several tags associated with it that define the same display +options (eg - a \fBtitle\fR cell with specific \fBrow\fR and \fBcell\fR +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. +.PP +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 \fB\-showtext\fR. + +.SH "EMBEDDED WINDOWS" +.PP +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. +.PP +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 \fBwindow names\fR). +.PP +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: +.RS +.TP +\fB\-create \fIscript\fR +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. +.TP +\fB\-background\fR or \fB\-bg\fR \fIcolor\fR +Background color of the cell. If not +specified, it uses the table's default background. +.TP +\fB\-borderwidth\fR or \fB\-bd\fR \fIpixelList\fR +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). +.TP +\fB\-padx \fIpixels\fR +As defined in the Tk options man page. +.TP +\fB\-pady \fIpixels\fR +As defined in the Tk options man page. +.TP +\fB\-relief \fIrelief\fR +The relief to use for the cell in which the window lies. If not +specified, it uses the table's default relief. +.TP +\fB\-sticky \fIsticky\fR +Stickiness of the window inside the cell, as defined by the \fBgrid\fR command. +.TP +\fB\-window \fIpathName\fR +Specifies the name of a window (widget) to display in the annotation. It +must exist before being specified here. When an empty string is specified, +if a window was displayed it will cease to be managed by the table widget. +.RE + +.SH "THE SELECTION" +.PP +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 +\fB\-rowseparator\fR and \fB\-colseparator\fR options. For example, +default Excel format would be to set \fB\-rowseparator\fR to '\\n' and +\fB\-colseparator\fR to '\\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 +\fBtk_tablePasteHandler\fR. This might be necessary if +\fB\-selectioncommand\fR is set. + +.SH "ROW/COL SPANNING" +.PP +Individual cells can span multiple rows and/or columns. This is done +via the \fBspans\fR 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. +.PP +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. +.PP +Cells \fIhidden\fR 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 \fBget\fR or \fBset\fR. +.PP +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. + +.SH "COMMAND SUBSTITUTION" +.PP + +The various option based commands that the table supports all support the +familiar Tk %\-substitution model (see \fBbind\fR for more details). The +following %\-sequences are recognized and substituted by the table widget: +.TP 5 +\fB%c\fR +For \fBSelectionCommand\fR, it is the maximum number of columns in any +row in the selection. Otherwise it is the column of the triggered cell. +.TP 5 +\fB%C\fR +A convenience substitution for \fI%r\fR,\fI%c\fR. +.TP 5 +\fB%i\fR +For \fBSelectionCommand\fR, it is the total number of cells in the selection. +For \fBCommand\fR, it is 0 for a read (get) and 1 for a write (set). +Otherwise it is the current cursor position in the cell. +.TP 5 +\fB%r\fR +For \fBSelectionCommand\fR, it is the number of rows in the selection. +Otherwise it is the row of the triggered cell. +.TP 5 +\fB%s\fR +For \fBValidateCommand\fR, it is the current value of the cell being validated. +For \fBSelectionCommand\fR, it is the default value of the selection. +For \fBBrowseCommand\fR, it is the index of the last active cell. +For \fBCommand\fR, it is empty for reads (get) and the current value of the +cell for writes (set). +.TP 5 +\fB%S\fR +For \fBValidateCommand\fR, it is the potential new value of the cell +being validated. +For \fBBrowseCommand\fR, it is the index of the new active cell. +.TP 5 +\fB%W\fR +The pathname to the window for which the command was generated. +.LP + +.SH "WIDGET COMMAND" +.PP +The \fBtable\fR command creates a new Tcl command whose +name is \fIpathName\fR. This command may be used to invoke various +operations on the widget. It has the following general form: +.CS +\fIpathName option \fR?\fIarg arg ...\fR? +.CE +\fIOption\fR and the \fIarg\fRs +determine the exact behavior of the command. +.PP +The following commands are possible for \fBtable\fR widgets: +.TP +\fIpathName \fBactivate\fR \fIindex\fR +Sets the active cell to the one indicated by \fIindex\fR. +.TP +\fIpathName \fBbbox\fR \fIfirst\fR ?\fIlast\fR? +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. +.TP +\fIpathName \fBborder\fR \fIoption args\fR +This command is a voodoo hack to implement border sizing for tables. +This is normally called through bindings, with the following as valid +options: +.RS +.TP +\fIpathName \fBborder mark\fR \fIx y\fR ?\fIrow|col\fR? +Records \fIx\fR and \fIy\fR and the row and/or column border under that +point in the table window, if any; used in conjunction with later \fBborder +dragto\fR commands. Typically this command is associated with a mouse +button press in the widget. If \fIrow\fR or \fIcol\fR is not specified, it +returns a tuple of both border indices (an empty item means no border). +Otherwise, just the specified item is returned. +.TP +\fIpathName \fBborder dragto\fR \fIx y\fR +This command computes the difference between its \fIx\fR and \fIy\fR +arguments and the \fIx\fR and \fIy\fR arguments to the last \fBborder +mark\fR 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. +.RE +.TP +\fIpathName \fBcget\fR \fIoption\fR +Returns the current value of the configuration option given +by \fIoption\fR. \fIOption\fR may have any of the values accepted +by the \fBtable\fR command. +.TP +\fIpathName \fBclear\fR \fIoption\fR ?\fIfirst\fR? ?\fIlast\fR? +This command is a convenience routine to clear certain state information +managed by the table. \fIfirst\fR and \fIlast\fR represent valid table +indices. If neither are specified, then the command operates on the +whole table. The following options are recognized: +.RS +.TP +\fIpathName \fBclear cache\fR ?\fIfirst\fR? ?\fIlast\fR? +Clears the specified section of the cache, if the table has been +keeping one. +.TP +\fIpathName \fBclear sizes\fR ?\fIfirst\fR? ?\fIlast\fR? +Clears the specified row and column areas of specific height/width +dimensions. When just one index is specified, for example \fB2,0\fR, +that is interpreted as row 2 \fBand\fR column 0. +.TP +\fIpathName \fBclear tags\fR ?\fIfirst\fR? ?\fIlast\fR? +Clears the specified area of tags (all row, column and cell tags). +.TP +\fIpathName \fBclear all\fR ?\fIfirst\fR? ?\fIlast\fR? +Performs all of the above clear functions on the specified area. +.RE +.TP +\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR? +Query or modify the configuration options of the widget. +If no \fIoption\fR is specified, returns a list describing all of +the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for +information on the format of this list). If \fIoption\fR is specified +with no \fIvalue\fR, 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 \fIoption\fR is specified). If +one or more \fIoption\-value\fR 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. +\fIOption\fR may have any of the values accepted by the \fBtable\fR +command. +.TP +\fIpathName \fBcurselection\fR ?\fIvalue\fR? +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. +.TP +\fIpathName \fBcurvalue\fR ?\fIvalue\fR? +If no value is given, the value of the cell being edited (indexed by +\fBactive\fR) is returned, else it is set to the given value. +.TP +\fIpathName \fBdelete\fR \fIoption arg\fR ?\fIarg\fR? +This command is used to delete various things in a table. It has several +forms, depending on the \fIoption\fR: +.RS +.TP +\fIpathName \fBdelete active\fR \fIindex\fR ?\fIindex\fR? +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. \fIindex\fR can be a number, \fBinsert\fR or \fBend\fR. +.TP +\fIpathName \fBdelete cols\fR ?\fIswitches\fR? \fIindex\fR ?\fIcount\fR? +Deletes \fIcount\fR cols starting at (and including) col \fIindex\fR. The +\fIindex\fR will be constrained to the limits of the tables. If +\fIcount\fR is negative, it deletes cols to the left. Otherwise it deletes +cols to the right. \fIcount\fR defaults to 1 (meaning just the column +specified). At the moment, spans are +not adjusted with this action. Optional switches are: +.RS +.TP +\fB\-holddimensions\fR +Causes the table cols to be unaffected by the deletion (empty cols may +appear). By default the dimensions are adjusted by \fBcount\fR. +.TP +\fB\-holdselection\fR +Causes the selection to be maintained on the absolute cells values. +Otherwise, the selection will be cleared.. +.TP +\fB\-holdtags\fR +Causes the tags specified by the \fItag\fR method to not move along +with the data. Also prevents specific widths set by the \fIwidth\fR method +from being adjusted. By default, these tags are properly adjusted. +.TP +\fB\-holdwindows\fR +Causes the embedded windows created with the \fIwindow\fR method to not +move along with the data. By default, these windows are properly adjusted. +.TP +\fB\-keeptitles\fR +Prevents title area cells from being changed. Otherwise they are +treated just like regular cells and will move as specified. +.TP +\fB\-\-\fR +Signifies the end of the switches. +.RE +.TP +\fIpathName \fBdelete rows\fR ?\fIswitches\fR? \fIindex\fR ?\fIcount\fR? +Deletes \fBcount\fR rows starting at (and including) row \fBindex\fR. If +\fBcount\fR 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. +.RE +.TP +\fIpathName \fBget\fR \fIfirst\fR ?\fIlast\fR? +Returns the value of the cells specified by the table indices \fIfirst\fR +and (optionally) \fIlast\fR in a list. +.TP +\fIpathName \fBheight\fR ?\fIrow\fR? ?\fIvalue row value ...\fR? +If no \fIrow\fR is specified, returns a list describing all rows for which +a height has been set. If \fBrow\fR 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 \fIrow\-value\fR pairs are specified, +then it sets each row to be that height in lines (positive number) or +pixels (negative number). If \fIvalue\fR is \fIdefault\fR, then the row +uses the default height, specified by \fB\-rowheight\fR. +.TP +\fIpathName \fBhidden\fR ?\fIindex\fR? ?\fIindex ...\fR? +When called without args, it returns all the \fIhidden\fR 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. +.TP +\fIpathName \fBicursor\fR ?\fIarg\fR? +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 \fBinsert\fR or +\fBend\fR 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. +.TP +\fIpathName \fBindex\fR \fIindex\fR ?\fIrow|col\fR? +Returns the integer cell coordinate that corresponds to \fIindex\fR in the +form row,col. If \fBrow\fR or \fBcol\fR is specified, then only the row or +column index is returned. +.TP +\fIpathName \fBinsert\fR \fIoption arg arg\fR +This command is used to into various things into a table. It has several +forms, depending on the \fIoption\fR: +.RS +.TP +\fIpathName \fBinsert active\fR \fIindex value\fR +The \fIvalue\fR is a text string which is inserted at the \fIindex\fR +position of the active cell. The cursor is then positioned after the +new text. \fIindex\fR can be a number, \fBinsert\fR or \fBend\fR. +.TP +\fIpathName \fBinsert cols\fR ?\fIswitches\fR? \fIindex\fR ?\fIcount\fR? +Inserts \fBcount\fR cols starting at col \fBindex\fR. If \fBcount\fR 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. +.TP +\fIpathName \fBinsert rows\fR ?\fIswitches\fR? \fIindex\fR ?\fIcount\fR? +Inserts \fBcount\fR rows starting at row \fBindex\fR. If \fBcount\fR 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. +.RE +.TP +\fIpathName \fBreread\fR +Rereads the old contents of the cell back into the editing buffer. Useful +for a key binding when <Escape> is pressed to abort the edit (a default +binding). +.TP +\fIpathName \fBscan\fR \fIoption args\fR +This command is used to implement scanning on tables. It has +two forms, depending on \fIoption\fR: +.RS +.TP +\fIpathName \fBscan mark\fR \fIx y\fR +Records \fIx\fR and \fIy\fR and the current view in the table +window; used in conjunction with later \fBscan dragto\fR commands. +Typically this command is associated with a mouse button press in +the widget. It returns an empty string. +.TP +\fIpathName \fBscan dragto\fR \fIx y\fR. +This command computes the difference between its \fIx\fR and \fIy\fR +arguments and the \fIx\fR and \fIy\fR arguments to the last \fBscan mark\fR +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. +.RE +.TP +\fIpathName \fBsee\fR \fIindex\fR +Adjust the view in the table so that the cell given by \fIindex\fR 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. +.TP +\fIpathName \fBselection\fR \fIoption arg\fR +This command is used to adjust the selection within a table. It +has several forms, depending on \fIoption\fR: +.RS +.TP +\fIpathName \fBselection anchor\fR \fIindex\fR +Sets the selection anchor to the cell given by \fIindex\fR. The selection +anchor is the end of the selection that is fixed while dragging out a +selection with the mouse. The index \fBanchor\fR may be used to refer to +the anchor cell. +.TP +\fIpathName \fBselection clear\fR \fIfirst \fR?\fIlast\fR? +If any of the cells between \fIfirst\fR and \fIlast\fR (inclusive) are +selected, they are deselected. The selection state is not changed for cells +outside this range. \fIfirst\fR may be specified as \fBall\fR to remove +the selection from all cells. +.TP +\fIpathName \fBselection includes\fR \fIindex\fR +Returns 1 if the cell indicated by \fIindex\fR is currently +selected, 0 if it isn't. +.TP +\fIpathName \fBselection set\fR \fIfirst\fR ?\fIlast\fR? +Selects all of the cells in the range between \fIfirst\fR and \fIlast\fR, +inclusive, without affecting the selection state of cells outside that +range. +.RE +.TP +\fIpathName \fBset\fR ?\fIrow|col\fR? \fIindex\fR ?\fIvalue\fR? ?\fIindex value ...\fR? +Sets the specified index to the associated value. Table validation will +not be triggered via this method. If \fBrow\fR or \fBcol\fR 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 \fBrow\fR is +specified) or rows (for \fBcol\fR). For example, \fBset row 2,3 +{2,3 2,4 2,5}\fR will set 3 cells, from 2,3 to 2,5. The setting of cells +is silently bounded by the known table dimensions. +.TP +\fIpathName \fBspans\fR ?\fIindex\fR? ?\fIrows,cols index rows,cols ...\fR? +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 \fIindex\fR, the span for that +\fIindex\fR only is returned, if any. Otherwise an even number of +\fIindex rows,cols\fR pairs are used to set spans. A span starts at the +\fIindex\fR 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. +.TP +\fIpathName \fBtag\fR option ?\fIarg arg ...\fR? +This command is used to manipulate tags. The exact behavior of the command +depends on the \fIoption\fR argument that follows the \fBtag\fR argument. +\fIcget\fR, \fIcell\fR, and \fIrow|col\fR complain about unknown tag names. +The following forms of the command are currently supported: +.RS +.TP +\fIpathName \fBtag cell\fR \fItagName ?index ...?\fR +With no arguments, prints out the list of cells that use the \fItag\fR. +Otherwise it sets the specified cells to use the named tag, replacing any +tag that may have been set using this method before. If \fItagName\fR is +{}, the cells are reset to the default \fItag\fR. Tags added during +\-*tagcommand evaluation do not register here. If \fItagName\fR does +not exist, it will be created with the default options. +.TP +\fIpathName \fBtag cget\fR \fItagName option\fR +This command returns the current value of the option named \fIoption\fR +associated with the tag given by \fItagName\fR. \fIOption\fR may have any +of the values accepted by the \fBtag configure\fR widget command. +.TP +\fIpathName \fBtag col\fR \fItagName ?col ...?\fR +With no arguments, prints out the list of cols that use the \fItag\fR. +Otherwise it sets the specified columns to use the named tag, replacing any +tag that may have been set using this method before. If \fItagName\fR is +{}, the cols are reset to the default \fItag\fR. Tags added during +\-coltagcommand evaluation do not register here. If \fItagName\fR does +not exist, it will be created with the default options. +.TP +\fIpathName \fBtag configure \fItagName\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? +This command is similar to the \fBconfigure\fR widget command except that +it modifies options associated with the tag given by \fItagName\fR instead +of modifying options for the overall table widget. If no \fIoption\fR is +specified, the command returns a list describing all of the available +options for \fItagName\fR (see \fBTk_ConfigureInfo\fR for information on +the format of this list). If \fIoption\fR is specified with no +\fIvalue\fR, 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 \fIoption\fR is specified). If one or more +\fIoption\-value\fR pairs are specified, then the command modifies the +given option(s) to have the given value(s) in \fItagName\fR; in this case +the command returns an empty string. +See TAGS above for details on the options available for tags. +.TP +\fIpathName \fBtag delete\fR \fItagName\fR +Deletes a tag. No error if the tag does not exist. +.TP +\fIpathName \fBtag exists\fR \fItagName\fR +Returns 1 if the named tag exists, 0 otherwise. +.TP +\fIpathName \fBtag includes\fR \fItagName index\fR +Returns 1 if the specified index has the named tag, 0 otherwise. +.TP +\fIpathName \fBtag lower\fR \fItagName\fR ?\fIbelowThis\fR? +Lower the priority of the named tag. If \fIbelowThis\fR is not specified, +then the tag's priority is lowered to the bottom, otherwise it is lowered +to one below \fIbelowThis\fR. +.TP +\fIpathName \fBtag names\fR ?\fIpattern\fR? +If no pattern is specified, shows the names of all defined tags. +Otherwise the \fIpattern\fR is used as a glob pattern to show only +tags matching that pattern. Tag names are returned in priority order +(highest priority tag first). +.TP +\fIpathName \fBtag raise\fR \fItagName\fR ?\fIaboveThis\fR? +Raise the priority of the named tag. If \fIaboveThis\fR is not specified, +then the tag's priority is raised to the top, otherwise it is raised to +one above \fIaboveThis\fR. +.TP +\fIpathName \fBtag row\fR \fItagName\fR ?\fIrow ...\fR? +With no arguments, prints out the list of rows that use the \fItag\fR. +Otherwise it sets the specified rows to use the named tag, replacing any +tag that may have been set using this method before. If \fItagName\fR is +{}, the rows are reset to use the default tag. Tags added during +\-rowtagcommand evaluation do not register here. If \fItagName\fR does +not exist, it will be created with the default options. +.RE +.TP +\fIpathName \fBvalidate\fR \fIindex\fR +Explicitly validates the specified index based on the current +\fB\-validatecommand\fR and returns 0 or 1 based on whether the cell was +validated. +.TP +\fIpathName \fBwidth\fR ?\fIcol\fR? ?\fIvalue col value ...\fR? +If no \fIcol\fR is specified, returns a list describing all cols for which +a width has been set. If \fBcol\fR 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 \fIcol\-value\fR pairs are specified, +then it sets each col to be that width in characters (positive number) or +pixels (negative number). If \fIvalue\fR is \fIdefault\fR, then the col +uses the default width, specified by \fB\-colwidth\fR. +.TP +\fIpathName \fBwindow\fR option ?\fIarg arg ...\fR? +This command is used to manipulate embedded windows. The exact behavior of +the command depends on the \fIoption\fR argument that follows the +\fBwindow\fR argument. The following forms of the command are currently +supported: +.RS +.TP +\fIpathName \fBwindow cget\fR \fIindex option\fR +This command returns the current value of the option named \fIoption\fR +associated with the window given by \fIindex\fR. \fIOption\fR may have any +of the values accepted by the \fBwindow configure\fR widget command. +.TP +\fIpathName \fBwindow configure \fIindex\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? +This command is similar to the \fBconfigure\fR widget command except that +it modifies options associated with the embedded window given by +\fIindex\fR instead of modifying options for the overall table widget. If +no \fIoption\fR is specified, the command returns a list describing all of +the available options for \fIindex\fR (see \fBTk_ConfigureInfo\fR for +information on the format of this list). If \fIoption\fR is specified with +no \fIvalue\fR, 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 \fIoption\fR is specified). If one or more +\fIoption\-value\fR pairs are specified, then the command modifies the +given option(s) to have the given value(s) in \fIindex\fR; in this case +the command returns an empty string. +See EMBEDDED WINDOWS above for details on the options available for windows. +.TP +\fIpathName \fBwindow delete\fR \fIindex\fR ?\fIindex ...\fR? +Deletes an embedded window from the table. The associated window will +also be deleted. +.TP +\fIpathName \fBwindow move\fR \fIindexFrom indexTo\fR +Moves an embedded window from one cell to another. If a window already +exists in the target cell, it will be deleted. +.TP +\fIpathName \fBwindow names\fR ?\fIpattern\fR? +If no pattern is specified, shows the cells of all embedded windows. +Otherwise the \fIpattern\fR is used as a glob pattern to show only +cells matching that pattern. +.RE +.TP +\fIpathName \fBxview \fIargs\fR +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: +.RS +.TP +\fIpathName \fBxview\fR +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 \fB\-xscrollcommand\fR +option. +.TP +\fIpathName \fBxview\fR \fIindex\fR +Adjusts the view in the window so that the column given by +\fIindex\fR is displayed at the left edge of the window. +.TP +\fIpathName \fBxview moveto\fI fraction\fR +Adjusts the view in the window so that \fIfraction\fR of the +total width of the table text is off\-screen to the left. +\fIfraction\fR must be a fraction between 0 and 1. +.TP +\fIpathName \fBxview scroll \fInumber what\fR +This command shifts the view in the window left or right according to +\fInumber\fR and \fIwhat\fR. +\fINumber\fR must be an integer. +\fIWhat\fR must be either \fBunits\fR or \fBpages\fR or an abbreviation +of one of these. +If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by +\fInumber\fR cells on the display; if it is \fBpages\fR then the view +adjusts by \fInumber\fR screenfuls. +If \fInumber\fR is negative then cells farther to the left +become visible; if it is positive then cells farther to the right +become visible. +.RE +.TP +\fIpathName \fByview \fI?args\fR? +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: +.RS +.TP +\fIpathName \fByview\fR +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 \fB\-yscrollcommand\fR option. +.TP +\fIpathName \fByview\fR \fIindex\fR +Adjusts the view in the window so that the row given by +\fIindex\fR is displayed at the top of the window. +.TP +\fIpathName \fByview moveto\fI fraction\fR +Adjusts the view in the window so that the element given by \fIfraction\fR +appears at the top of the window. +\fIFraction\fR 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. +.TP +\fIpathName \fByview scroll \fInumber what\fR +This command adjusts the view in the window up or down according to +\fInumber\fR and \fIwhat\fR. \fINumber\fR must be an integer. \fIWhat\fR +must be either \fBunits\fR or \fBpages\fR. If \fIwhat\fR is \fBunits\fR, +the view adjusts up or down by \fInumber\fR cells; if it is \fBpages\fR then +the view adjusts by \fInumber\fR screenfuls. If \fInumber\fR is negative +then earlier elements become visible; if it is positive then later elements +become visible. +.RE + +.SH "DEFAULT BINDINGS" +.PP +The initialization creates class bindings that give the +following default behaviour: +.IP [1] +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. +.IP [2] +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. +.IP [3] +Moving the mouse while Button\-2 is pressed causes scanning to +occur without any selection. +.IP [4] +Home moves the table to have the origin in view. +.IP [5] +End moves the table to have the \fBend\fR cell in view. +.IP [6] +Control\-Home moves the table to the origin and activates that cell. +.IP [7] +Control\-End moves the table to the end and activates that cell. +.IP [8] +Shift\-Control\-Home extends the selection to the origin. +.IP [9] +Shift\-Control\-End extends the selection to the end. +.IP [10] +The left, right, up and down arrows move the active cell. +.IP [11] +Shift\-<arrow> extends the selection in that direction. +.IP [12] +Control\-leftarrow and Control\-rightarrow move the insertion +cursor within the cell. +.IP [13] +Control\-slash selects all the cells. +.IP [14] +Control\-backslash clears selection from all the cells. +.IP [15] +Backspace deletes the character before the insertion cursor +in the active cell. +.IP [16] +Delete deletes the character after the insertion cursor +in the active cell. +.IP [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. +.IP [18] +Control\-a moves the insertion cursor to the beginning of the active cell. +.IP [19] +Control\-e moves the insertion cursor to the end of the active cell. +.IP [20] +Control\-minus and Control\-equals decrease and increase the +width of the column with the active cell in it. +.IP [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 \fB\-resizeborders\fR. +.PP +Some bindings may have slightly different behavior dependent on the +\fB\-selectionmode\fR of the widget. +.PP +If the widget is disabled using the \fB\-state\fR 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. +.PP +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: "[lindex $tcl_pkgPath 0]/Tktable<version>/tkTable.tcl". + +.SH "PERFORMANCE ISSUES" +.PP +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. +.PP +The display cell with the insert cursor is redrawn each time the cursor +blinks, which causes a steady stream of graphics traffic. Set the +\fB\-insertofftime\fR option to 0 avoid this. The use of a \fB\-command\fR +with the table without a cache can cause significant slow\-down, as the +command is called once for each request of a cell value. + + +.SH EXAMPLES +.PP +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. +.CS +$table span [$table cget -roworigin],[$table cget -colorigin] [$table cget -titlerows],[$table cget -titlecols] +.CE +Force a table window refresh (useful for the slight chance that a bug +in the table is not causing proper refresh): +.CS +$table configure -padx [$table cget -padx] +.CE + +.SH KEYWORDS +table, widget, extension diff --git a/tktable/generic/tkAppInit.c b/tktable/generic/tkAppInit.c new file mode 100644 index 0000000..bc4fb61 --- /dev/null +++ b/tktable/generic/tkAppInit.c @@ -0,0 +1,132 @@ +/* + * tkAppInit.c -- + * + * Provides a default version of the Tcl_AppInit procedure for + * use in wish and similar Tk-based applications. + * + * Copyright (c) 1993 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * SCCS: @(#) tkAppInit.c 1.24 98/01/13 17:21:40 + */ + +#include "tk.h" +#include "locale.h" + +/* + * The following variable is a special hack that is needed in order for + * Sun shared libraries to be used for Tcl. + */ + +extern int matherr(); +int *tclDummyMathPtr = (int *) matherr; + +EXTERN int Tktable_Init _ANSI_ARGS_((Tcl_Interp *interp)); +#ifdef TK_TEST +EXTERN int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN int Tktest_Init _ANSI_ARGS_((Tcl_Interp *interp)); +#endif /* TK_TEST */ + +/* + *---------------------------------------------------------------------- + * + * main -- + * + * This is the main program for the application. + * + * Results: + * None: Tk_Main never returns here, so this procedure never + * returns either. + * + * Side effects: + * Whatever the application does. + * + *---------------------------------------------------------------------- + */ + +int +main(argc, argv) + int argc; /* Number of command-line arguments. */ + char **argv; /* Values of command-line arguments. */ +{ + Tk_Main(argc, argv, Tcl_AppInit); + return 0; /* Needed only to prevent compiler warning. */ +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_AppInit -- + * + * This procedure performs application-specific initialization. + * Most applications, especially those that incorporate additional + * packages, will have their own version of this procedure. + * + * Results: + * Returns a standard Tcl completion code, and leaves an error + * message in interp->result if an error occurs. + * + * Side effects: + * Depends on the startup script. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_AppInit(interp) + Tcl_Interp *interp; /* Interpreter for application. */ +{ + if (Tcl_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + if (Tk_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "Tk", Tk_Init, (Tcl_PackageInitProc *) NULL); +#ifdef TK_TEST + if (Tcltest_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init, + (Tcl_PackageInitProc *) NULL); + if (Tktest_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "Tktest", Tktest_Init, + (Tcl_PackageInitProc *) NULL); +#endif /* TK_TEST */ + + + /* + * Call the init procedures for included packages. Each call should + * look like this: + * + * if (Mod_Init(interp) == TCL_ERROR) { + * return TCL_ERROR; + * } + * + * where "Mod" is the name of the module. + */ + if (Tktable_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "Tktable", Tktable_Init, Tktable_SafeInit); + + /* + * Call Tcl_CreateCommand for application-specific commands, if + * they weren't already created by the init procedures called above. + */ + + /* + * Specify a user-specific startup file to invoke if the application + * is run interactively. Typically the startup file is "~/.apprc" + * where "app" is the name of the application. If this line is deleted + * then no user-specific startup file will be run under any conditions. + */ + + Tcl_SetVar(interp, "tcl_rcFileName", "~/.wishrc", TCL_GLOBAL_ONLY); + return TCL_OK; +} diff --git a/tktable/generic/tkTable.c b/tktable/generic/tkTable.c new file mode 100644 index 0000000..efb5f21 --- /dev/null +++ b/tktable/generic/tkTable.c @@ -0,0 +1,4090 @@ +/* + * tkTable.c -- + * + * This module implements table widgets for the Tk + * toolkit. An table displays a 2D array of strings + * and allows the strings to be edited. + * + * Based on Tk3 table widget written by Roland King + * + * Updates 1996 by: + * Jeffrey Hobbs jeff at hobbs org + * John Ellson ellson@lucent.com + * Peter Bruecker peter@bj-ig.de + * Tom Moore tmoore@spatial.ca + * Sebastian Wangnick wangnick@orthogon.de + * + * Copyright (c) 1997-2002 Jeffrey Hobbs + * + * See the file "license.txt" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkTable.c,v 1.3 2016/01/27 19:43:23 joye Exp $ + */ + +#include "tkTable.h" + +#ifdef DEBUG +#include "dprint.h" +#endif + +static char ** StringifyObjects(int objc, Tcl_Obj *CONST objv[]); + +static int Tk_TableObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); + +static int TableWidgetObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int TableConfigure(Tcl_Interp *interp, Table *tablePtr, + int objc, Tcl_Obj *CONST objv[], + int flags, int forceUpdate); +#ifdef HAVE_TCL84 +static void TableWorldChanged(ClientData instanceData); +#endif +static void TableDestroy(ClientData clientdata); +static void TableEventProc(ClientData clientData, XEvent *eventPtr); +static void TableCmdDeletedProc(ClientData clientData); + +static void TableRedrawHighlight(Table *tablePtr); +static void TableGetGc(Display *display, Drawable d, + TableTag *tagPtr, GC *tagGc); + +static void TableDisplay(ClientData clientdata); +static void TableFlashEvent(ClientData clientdata); +static char * TableVarProc(ClientData clientData, Tcl_Interp *interp, + char *name, char *index, int flags); +static void TableCursorEvent(ClientData clientData); +static int TableFetchSelection(ClientData clientData, + int offset, char *buffer, int maxBytes); +static Tk_RestrictAction TableRestrictProc(ClientData arg, XEvent *eventPtr); + +/* + * The following tables define the widget commands (and sub- + * commands) and map the indexes into the string tables into + * enumerated types used to dispatch the widget command. + */ + +static CONST84 char *selCmdNames[] = { + "anchor", "clear", "includes", "present", "set", (char *)NULL +}; +enum selCommand { + CMD_SEL_ANCHOR, CMD_SEL_CLEAR, CMD_SEL_INCLUDES, CMD_SEL_PRESENT, + CMD_SEL_SET +}; + +static CONST84 char *commandNames[] = { + "activate", "bbox", "border", "cget", "clear", "configure", + "curselection", "curvalue", "delete", "get", "height", + "hidden", "icursor", "index", "insert", +#ifdef POSTSCRIPT + "postscript", +#endif + "reread", "scan", "see", "selection", "set", + "spans", "tag", "validate", "version", "window", "width", + "xview", "yview", (char *)NULL +}; +enum command { + CMD_ACTIVATE, CMD_BBOX, CMD_BORDER, CMD_CGET, CMD_CLEAR, CMD_CONFIGURE, + CMD_CURSEL, CMD_CURVALUE, CMD_DELETE, CMD_GET, CMD_HEIGHT, + CMD_HIDDEN, CMD_ICURSOR, CMD_INDEX, CMD_INSERT, +#ifdef POSTSCRIPT + CMD_POSTSCRIPT, +#endif + CMD_REREAD, CMD_SCAN, CMD_SEE, CMD_SELECTION, CMD_SET, + CMD_SPANS, CMD_TAG, CMD_VALIDATE, CMD_VERSION, CMD_WINDOW, CMD_WIDTH, + CMD_XVIEW, CMD_YVIEW +}; + +/* -selecttype selection type options */ +static Cmd_Struct sel_vals[]= { + {"row", SEL_ROW}, + {"col", SEL_COL}, + {"both", SEL_BOTH}, + {"cell", SEL_CELL}, + {"", 0 } +}; + +/* -resizeborders options */ +static Cmd_Struct resize_vals[]= { + {"row", SEL_ROW}, /* allow rows to be dragged */ + {"col", SEL_COL}, /* allow cols to be dragged */ + {"both", SEL_ROW|SEL_COL}, /* allow either to be dragged */ + {"none", SEL_NONE}, /* allow nothing to be dragged */ + {"", 0 } +}; + +/* drawmode values */ +/* The display redraws with a pixmap using TK function calls */ +#define DRAW_MODE_SLOW (1<<0) +/* The redisplay is direct to the screen, but TK function calls are still + * used to give correct 3-d border appearance and thus remain compatible + * with other TK apps */ +#define DRAW_MODE_TK_COMPAT (1<<1) +/* the redisplay goes straight to the screen and the 3d borders are rendered + * with a single pixel wide line only. It cheats and uses the internal + * border structure to do the borders */ +#define DRAW_MODE_FAST (1<<2) +#define DRAW_MODE_SINGLE (1<<3) + +static Cmd_Struct drawmode_vals[] = { + {"fast", DRAW_MODE_FAST}, + {"compatible", DRAW_MODE_TK_COMPAT}, + {"slow", DRAW_MODE_SLOW}, + {"single", DRAW_MODE_SINGLE}, + {"", 0} +}; + +/* stretchmode values */ +#define STRETCH_MODE_NONE (1<<0) /* No additional pixels will be + added to rows or cols */ +#define STRETCH_MODE_UNSET (1<<1) /* All default rows or columns will + be stretched to fill the screen */ +#define STRETCH_MODE_ALL (1<<2) /* All rows/columns will be padded + to fill the window */ +#define STRETCH_MODE_LAST (1<<3) /* Stretch last elememt to fill + window */ +#define STRETCH_MODE_FILL (1<<4) /* More ROWS in Window */ + +static Cmd_Struct stretch_vals[] = { + {"none", STRETCH_MODE_NONE}, + {"unset", STRETCH_MODE_UNSET}, + {"all", STRETCH_MODE_ALL}, + {"last", STRETCH_MODE_LAST}, + {"fill", STRETCH_MODE_FILL}, + {"", 0} +}; + +static Cmd_Struct state_vals[]= { + {"normal", STATE_NORMAL}, + {"disabled", STATE_DISABLED}, + {"", 0 } +}; + +/* The widget configuration table */ +static Tk_CustomOption drawOpt = { Cmd_OptionSet, Cmd_OptionGet, + (ClientData)(&drawmode_vals) }; +static Tk_CustomOption resizeTypeOpt = { Cmd_OptionSet, Cmd_OptionGet, + (ClientData)(&resize_vals) }; +static Tk_CustomOption stretchOpt = { Cmd_OptionSet, Cmd_OptionGet, + (ClientData)(&stretch_vals) }; +static Tk_CustomOption selTypeOpt = { Cmd_OptionSet, Cmd_OptionGet, + (ClientData)(&sel_vals) }; +static Tk_CustomOption stateTypeOpt = { Cmd_OptionSet, Cmd_OptionGet, + (ClientData)(&state_vals) }; +static Tk_CustomOption bdOpt = { TableOptionBdSet, TableOptionBdGet, + (ClientData) BD_TABLE }; + +Tk_ConfigSpec tableSpecs[] = { + {TK_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor", "center", + Tk_Offset(Table, defaultTag.anchor), 0}, + {TK_CONFIG_BOOLEAN, "-autoclear", "autoClear", "AutoClear", "0", + Tk_Offset(Table, autoClear), 0}, + {TK_CONFIG_BORDER, "-background", "background", "Background", NORMAL_BG, + Tk_Offset(Table, defaultTag.bg), 0}, + {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL, (char *)NULL, 0, 0}, + {TK_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0}, + {TK_CONFIG_CURSOR, "-bordercursor", "borderCursor", "Cursor", "crosshair", + Tk_Offset(Table, bdcursor), TK_CONFIG_NULL_OK }, + {TK_CONFIG_CUSTOM, "-borderwidth", "borderWidth", "BorderWidth", "1", + Tk_Offset(Table, defaultTag), TK_CONFIG_NULL_OK, &bdOpt }, + {TK_CONFIG_STRING, "-browsecommand", "browseCommand", "BrowseCommand", "", + Tk_Offset(Table, browseCmd), TK_CONFIG_NULL_OK}, + {TK_CONFIG_SYNONYM, "-browsecmd", "browseCommand", (char *)NULL, + (char *)NULL, 0, TK_CONFIG_NULL_OK}, + {TK_CONFIG_BOOLEAN, "-cache", "cache", "Cache", "0", + Tk_Offset(Table, caching), 0}, + {TK_CONFIG_INT, "-colorigin", "colOrigin", "Origin", "0", + Tk_Offset(Table, colOffset), 0}, + {TK_CONFIG_INT, "-cols", "cols", "Cols", "10", + Tk_Offset(Table, cols), 0}, + {TK_CONFIG_STRING, "-colseparator", "colSeparator", "Separator", NULL, + Tk_Offset(Table, colSep), TK_CONFIG_NULL_OK }, + {TK_CONFIG_CUSTOM, "-colstretchmode", "colStretch", "StretchMode", "none", + Tk_Offset (Table, colStretch), 0 , &stretchOpt }, + {TK_CONFIG_STRING, "-coltagcommand", "colTagCommand", "TagCommand", NULL, + Tk_Offset(Table, colTagCmd), TK_CONFIG_NULL_OK }, + {TK_CONFIG_INT, "-colwidth", "colWidth", "ColWidth", "10", + Tk_Offset(Table, defColWidth), 0}, + {TK_CONFIG_STRING, "-command", "command", "Command", "", + Tk_Offset(Table, command), TK_CONFIG_NULL_OK}, + {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor", "xterm", + Tk_Offset(Table, cursor), TK_CONFIG_NULL_OK }, + {TK_CONFIG_CUSTOM, "-drawmode", "drawMode", "DrawMode", "compatible", + Tk_Offset(Table, drawMode), 0, &drawOpt }, + {TK_CONFIG_STRING, "-ellipsis", "ellipsis", "Ellipsis", "", + Tk_Offset(Table, defaultTag.ellipsis), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BOOLEAN, "-exportselection", "exportSelection", + "ExportSelection", "1", Tk_Offset(Table, exportSelection), 0}, + {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL, (char *)NULL, 0, 0}, + {TK_CONFIG_BOOLEAN, "-flashmode", "flashMode", "FlashMode", "0", + Tk_Offset(Table, flashMode), 0}, + {TK_CONFIG_INT, "-flashtime", "flashTime", "FlashTime", "2", + Tk_Offset(Table, flashTime), 0}, + {TK_CONFIG_FONT, "-font", "font", "Font", DEF_TABLE_FONT, + Tk_Offset(Table, defaultTag.tkfont), 0}, + {TK_CONFIG_BORDER, "-foreground", "foreground", "Foreground", "black", + Tk_Offset(Table, defaultTag.fg), 0}, +#ifdef PROCS + {TK_CONFIG_BOOLEAN, "-hasprocs", "hasProcs", "hasProcs", "0", + Tk_Offset(Table, hasProcs), 0}, +#endif + {TK_CONFIG_INT, "-height", "height", "Height", "0", + Tk_Offset(Table, maxReqRows), 0}, + {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground", + "HighlightBackground", NORMAL_BG, Tk_Offset(Table, highlightBgColorPtr), 0}, + {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", + HIGHLIGHT, Tk_Offset(Table, highlightColorPtr), 0}, + {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness", + "HighlightThickness", "2", Tk_Offset(Table, highlightWidth), 0}, + {TK_CONFIG_BORDER, "-insertbackground", "insertBackground", "Foreground", + "Black", Tk_Offset(Table, insertBg), 0}, + {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth", + "0", Tk_Offset(Table, insertBorderWidth), TK_CONFIG_COLOR_ONLY}, + {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth", + "0", Tk_Offset(Table, insertBorderWidth), TK_CONFIG_MONO_ONLY}, + {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime", "300", + Tk_Offset(Table, insertOffTime), 0}, + {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime", "600", + Tk_Offset(Table, insertOnTime), 0}, + {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", "2", + Tk_Offset(Table, insertWidth), 0}, + {TK_CONFIG_BOOLEAN, "-invertselected", "invertSelected", "InvertSelected", + "0", Tk_Offset(Table, invertSelected), 0}, + {TK_CONFIG_PIXELS, "-ipadx", "ipadX", "Pad", "0", + Tk_Offset(Table, ipadX), 0}, + {TK_CONFIG_PIXELS, "-ipady", "ipadY", "Pad", "0", + Tk_Offset(Table, ipadY), 0}, + {TK_CONFIG_JUSTIFY, "-justify", "justify", "Justify", "left", + Tk_Offset(Table, defaultTag.justify), 0 }, + {TK_CONFIG_PIXELS, "-maxheight", "maxHeight", "MaxHeight", "600", + Tk_Offset(Table, maxReqHeight), 0}, + {TK_CONFIG_PIXELS, "-maxwidth", "maxWidth", "MaxWidth", "800", + Tk_Offset(Table, maxReqWidth), 0}, + {TK_CONFIG_BOOLEAN, "-multiline", "multiline", "Multiline", "1", + Tk_Offset(Table, defaultTag.multiline), 0}, + {TK_CONFIG_PIXELS, "-padx", "padX", "Pad", "0", Tk_Offset(Table, padX), 0}, + {TK_CONFIG_PIXELS, "-pady", "padY", "Pad", "0", Tk_Offset(Table, padY), 0}, + {TK_CONFIG_RELIEF, "-relief", "relief", "Relief", "sunken", + Tk_Offset(Table, defaultTag.relief), 0}, + {TK_CONFIG_CUSTOM, "-resizeborders", "resizeBorders", "ResizeBorders", + "both", Tk_Offset(Table, resize), 0, &resizeTypeOpt }, + {TK_CONFIG_INT, "-rowheight", "rowHeight", "RowHeight", "1", + Tk_Offset(Table, defRowHeight), 0}, + {TK_CONFIG_INT, "-roworigin", "rowOrigin", "Origin", "0", + Tk_Offset(Table, rowOffset), 0}, + {TK_CONFIG_INT, "-rows", "rows", "Rows", "10", Tk_Offset(Table, rows), 0}, + {TK_CONFIG_STRING, "-rowseparator", "rowSeparator", "Separator", NULL, + Tk_Offset(Table, rowSep), TK_CONFIG_NULL_OK }, + {TK_CONFIG_CUSTOM, "-rowstretchmode", "rowStretch", "StretchMode", "none", + Tk_Offset(Table, rowStretch), 0 , &stretchOpt }, + {TK_CONFIG_STRING, "-rowtagcommand", "rowTagCommand", "TagCommand", NULL, + Tk_Offset(Table, rowTagCmd), TK_CONFIG_NULL_OK }, + {TK_CONFIG_SYNONYM, "-selcmd", "selectionCommand", (char *)NULL, + (char *)NULL, 0, TK_CONFIG_NULL_OK}, + {TK_CONFIG_STRING, "-selectioncommand", "selectionCommand", + "SelectionCommand", NULL, Tk_Offset(Table, selCmd), TK_CONFIG_NULL_OK }, + {TK_CONFIG_STRING, "-selectmode", "selectMode", "SelectMode", "browse", + Tk_Offset(Table, selectMode), TK_CONFIG_NULL_OK }, + {TK_CONFIG_BOOLEAN, "-selecttitles", "selectTitles", "SelectTitles", "0", + Tk_Offset(Table, selectTitles), 0}, + {TK_CONFIG_CUSTOM, "-selecttype", "selectType", "SelectType", "cell", + Tk_Offset(Table, selectType), 0, &selTypeOpt }, +#ifdef PROCS + {TK_CONFIG_BOOLEAN, "-showprocs", "showProcs", "showProcs", "0", + Tk_Offset(Table, showProcs), 0}, +#endif + {TK_CONFIG_BOOLEAN, "-sparsearray", "sparseArray", "SparseArray", "1", + Tk_Offset(Table, sparse), 0}, + {TK_CONFIG_CUSTOM, "-state", "state", "State", "normal", + Tk_Offset(Table, state), 0, &stateTypeOpt}, + {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus", (char *)NULL, + Tk_Offset(Table, takeFocus), TK_CONFIG_NULL_OK }, + {TK_CONFIG_INT, "-titlecols", "titleCols", "TitleCols", "0", + Tk_Offset(Table, titleCols), TK_CONFIG_NULL_OK }, +#ifdef TITLE_CURSOR + {TK_CONFIG_CURSOR, "-titlecursor", "titleCursor", "Cursor", "arrow", + Tk_Offset(Table, titleCursor), TK_CONFIG_NULL_OK }, +#endif + {TK_CONFIG_INT, "-titlerows", "titleRows", "TitleRows", "0", + Tk_Offset(Table, titleRows), TK_CONFIG_NULL_OK }, + {TK_CONFIG_BOOLEAN, "-usecommand", "useCommand", "UseCommand", "1", + Tk_Offset(Table, useCmd), 0}, + {TK_CONFIG_STRING, "-variable", "variable", "Variable", (char *)NULL, + Tk_Offset(Table, arrayVar), TK_CONFIG_NULL_OK }, + {TK_CONFIG_BOOLEAN, "-validate", "validate", "Validate", "0", + Tk_Offset(Table, validate), 0}, + {TK_CONFIG_STRING, "-validatecommand", "validateCommand", "ValidateCommand", + "", Tk_Offset(Table, valCmd), TK_CONFIG_NULL_OK}, + {TK_CONFIG_SYNONYM, "-vcmd", "validateCommand", (char *)NULL, + (char *)NULL, 0, TK_CONFIG_NULL_OK}, + {TK_CONFIG_INT, "-width", "width", "Width", "0", + Tk_Offset(Table, maxReqCols), 0}, + {TK_CONFIG_BOOLEAN, "-wrap", "wrap", "Wrap", "0", + Tk_Offset(Table, defaultTag.wrap), 0}, + {TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", + NULL, Tk_Offset(Table, xScrollCmd), TK_CONFIG_NULL_OK }, + {TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", + NULL, Tk_Offset(Table, yScrollCmd), TK_CONFIG_NULL_OK }, + {TK_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL, + (char *)NULL, 0, 0} +}; + +/* + * This specifies the configure options that will cause an update to + * occur, so we should have a quick lookup table for them. + * Keep this in sync with the above values. + */ + +static CONST84 char *updateOpts[] = { + "-anchor", "-background", "-bg", "-bd", + "-borderwidth", "-cache", "-command", "-colorigin", + "-cols", "-colstretchmode", "-coltagcommand", + "-drawmode", "-fg", "-font", "-foreground", + "-hasprocs", "-height", "-highlightbackground", + "-highlightcolor", "-highlightthickness", "-insertbackground", + "-insertborderwidth", "-insertwidth", "-invertselected", + "-ipadx", "-ipady", + "-maxheight", "-maxwidth", "-multiline", + "-padx", "-pady", "-relief", "-roworigin", + "-rows", "-rowstretchmode", "-rowtagcommand", + "-showprocs", "-state", "-titlecols", "-titlerows", + "-usecommand", "-variable", "-width", "-wrap", + "-xscrollcommand", "-yscrollcommand", (char *) NULL +}; + +#ifdef HAVE_TCL84 +/* + * The structure below defines widget class behavior by means of procedures + * that can be invoked from generic window code. + */ + +static Tk_ClassProcs tableClass = { + sizeof(Tk_ClassProcs), /* size */ + TableWorldChanged, /* worldChangedProc */ + NULL, /* createProc */ + NULL /* modalProc */ +}; +#endif + +#ifdef WIN32 +/* + * Some code from TkWinInt.h that we use to correct and speed up + * drawing of cells that need clipping in TableDisplay. + */ +typedef struct { + int type; + HWND handle; + void *winPtr; +} TkWinWindow; + +typedef struct { + int type; + HBITMAP handle; + Colormap colormap; + int depth; +} TkWinBitmap; + +typedef struct { + int type; + HDC hdc; +} TkWinDC; + +typedef union { + int type; + TkWinWindow window; + TkWinBitmap bitmap; + TkWinDC winDC; +} TkWinDrawable; +#endif + +/* + * END HEADER INFORMATION + */ + +/* + *--------------------------------------------------------------------------- + * + * StringifyObjects -- (from tclCmdAH.c) + * + * Helper function to bridge the gap between an object-based procedure + * and an older string-based procedure. + * + * Given an array of objects, allocate an array that consists of the + * string representations of those objects. + * + * Results: + * The return value is a pointer to the newly allocated array of + * strings. Elements 0 to (objc-1) of the string array point to the + * string representation of the corresponding element in the source + * object array; element objc of the string array is NULL. + * + * Side effects: + * Memory allocated. The caller must eventually free this memory + * by calling ckfree() on the return value. + * + int result; + char **argv; + argv = StringifyObjects(objc, objv); + result = StringBasedCmd(interp, objc, argv); + ckfree((char *) argv); + return result; + * + *--------------------------------------------------------------------------- + */ + +static char ** +StringifyObjects(objc, objv) + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + int i; + char **argv; + + argv = (char **) ckalloc((objc + 1) * sizeof(char *)); + for (i = 0; i < objc; i++) { + argv[i] = Tcl_GetString(objv[i]); + } + argv[i] = NULL; + return argv; +} + +/* + * As long as we wait for the Function in general + * + * This parses the "-class" option for the table. + */ +static int +Tk_ClassOptionObjCmd(Tk_Window tkwin, char *defaultclass, + int objc, Tcl_Obj *CONST objv[]) +{ + char *classname = defaultclass; + int offset = 0; + + if ((objc >= 4) && STREQ(Tcl_GetString(objv[2]),"-class")) { + classname = Tcl_GetString(objv[3]); + offset = 2; + } + Tk_SetClass(tkwin, classname); + return offset; +} + +/* + *-------------------------------------------------------------- + * + * Tk_TableObjCmd -- + * This procedure is invoked to process the "table" Tcl + * command. See the user documentation for details on what + * it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *-------------------------------------------------------------- + */ +static int +Tk_TableObjCmd(clientData, interp, objc, objv) + ClientData clientData; /* Main window associated with interpreter. */ + Tcl_Interp *interp; + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register Table *tablePtr; + Tk_Window tkwin, mainWin = (Tk_Window) clientData; + int offset; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?"); + return TCL_ERROR; + } + + tkwin = Tk_CreateWindowFromPath(interp, mainWin, Tcl_GetString(objv[1]), + (char *)NULL); + if (tkwin == NULL) { + return TCL_ERROR; + } + + tablePtr = (Table *) ckalloc(sizeof(Table)); + memset((VOID *) tablePtr, 0, sizeof(Table)); + + /* + * Set the structure elments that aren't 0/NULL by default, + * and that won't be set by the initial configure call. + */ + tablePtr->tkwin = tkwin; + tablePtr->display = Tk_Display(tkwin); + tablePtr->interp = interp; + tablePtr->widgetCmd = Tcl_CreateObjCommand(interp, + Tk_PathName(tablePtr->tkwin), TableWidgetObjCmd, + (ClientData) tablePtr, (Tcl_CmdDeleteProc *) TableCmdDeletedProc); + + tablePtr->anchorRow = -1; + tablePtr->anchorCol = -1; + tablePtr->activeRow = -1; + tablePtr->activeCol = -1; + tablePtr->oldTopRow = -1; + tablePtr->oldLeftCol = -1; + tablePtr->oldActRow = -1; + tablePtr->oldActCol = -1; + tablePtr->seen[0] = -1; + + tablePtr->dataSource = DATA_NONE; + tablePtr->activeBuf = ckalloc(1); + *(tablePtr->activeBuf) = '\0'; + + tablePtr->cursor = None; + tablePtr->bdcursor = None; + + tablePtr->defaultTag.justify = TK_JUSTIFY_LEFT; + tablePtr->defaultTag.state = STATE_UNKNOWN; + + /* misc tables */ + tablePtr->tagTable = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(tablePtr->tagTable, TCL_STRING_KEYS); + tablePtr->winTable = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(tablePtr->winTable, TCL_STRING_KEYS); + + /* internal value cache */ + tablePtr->cache = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(tablePtr->cache, TCL_STRING_KEYS); + + /* style hash tables */ + tablePtr->colWidths = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(tablePtr->colWidths, TCL_ONE_WORD_KEYS); + tablePtr->rowHeights = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(tablePtr->rowHeights, TCL_ONE_WORD_KEYS); + + /* style hash tables */ + tablePtr->rowStyles = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(tablePtr->rowStyles, TCL_ONE_WORD_KEYS); + tablePtr->colStyles = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(tablePtr->colStyles, TCL_ONE_WORD_KEYS); + tablePtr->cellStyles = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(tablePtr->cellStyles, TCL_STRING_KEYS); + + /* special style hash tables */ + tablePtr->flashCells = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(tablePtr->flashCells, TCL_STRING_KEYS); + tablePtr->selCells = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(tablePtr->selCells, TCL_STRING_KEYS); + + /* + * List of tags in priority order. 30 is a good default number to alloc. + */ + tablePtr->tagPrioMax = 30; + tablePtr->tagPrioNames = (char **) ckalloc( + sizeof(char *) * tablePtr->tagPrioMax); + tablePtr->tagPrios = (TableTag **) ckalloc( + sizeof(TableTag *) * tablePtr->tagPrioMax); + tablePtr->tagPrioSize = 0; + for (offset = 0; offset < tablePtr->tagPrioMax; offset++) { + tablePtr->tagPrioNames[offset] = (char *) NULL; + tablePtr->tagPrios[offset] = (TableTag *) NULL; + } + +#ifdef PROCS + tablePtr->inProc = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(tablePtr->inProc, TCL_STRING_KEYS); +#endif + + /* + * Handle class name and selection handlers + */ + offset = 2 + Tk_ClassOptionObjCmd(tkwin, "Table", objc, objv); +#ifdef HAVE_TCL84 + Tk_SetClassProcs(tkwin, &tableClass, (ClientData) tablePtr); +#endif + Tk_CreateEventHandler(tablePtr->tkwin, + PointerMotionMask|ExposureMask|StructureNotifyMask|FocusChangeMask|VisibilityChangeMask, + TableEventProc, (ClientData) tablePtr); + Tk_CreateSelHandler(tablePtr->tkwin, XA_PRIMARY, XA_STRING, + TableFetchSelection, (ClientData) tablePtr, XA_STRING); + + if (TableConfigure(interp, tablePtr, objc - offset, objv + offset, + 0, 1 /* force update */) != TCL_OK) { + Tk_DestroyWindow(tkwin); + return TCL_ERROR; + } + TableInitTags(tablePtr); + + Tcl_SetObjResult(interp, + Tcl_NewStringObj(Tk_PathName(tablePtr->tkwin), -1)); + return TCL_OK; +} + +/* + *-------------------------------------------------------------- + * + * TableWidgetObjCmd -- + * This procedure is invoked to process the Tcl command + * that corresponds to a 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. + * + *-------------------------------------------------------------- + */ +static int +TableWidgetObjCmd(clientData, interp, objc, objv) + ClientData clientData; + Tcl_Interp *interp; + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register Table *tablePtr = (Table *) clientData; + int row, col, i, cmdIndex, result = TCL_OK; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } + + /* parse the first parameter */ + result = Tcl_GetIndexFromObj(interp, objv[1], commandNames, + "option", 0, &cmdIndex); + if (result != TCL_OK) { + return result; + } + + Tcl_Preserve((ClientData) tablePtr); + switch ((enum command) cmdIndex) { + case CMD_ACTIVATE: + result = Table_ActivateCmd(clientData, interp, objc, objv); + break; + + case CMD_BBOX: + result = Table_BboxCmd(clientData, interp, objc, objv); + break; + + case CMD_BORDER: + result = Table_BorderCmd(clientData, interp, objc, objv); + break; + + case CMD_CGET: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option"); + result = TCL_ERROR; + } else { + result = Tk_ConfigureValue(interp, tablePtr->tkwin, tableSpecs, + (char *) tablePtr, Tcl_GetString(objv[2]), 0); + } + break; + + case CMD_CLEAR: + result = Table_ClearCmd(clientData, interp, objc, objv); + break; + + case CMD_CONFIGURE: + if (objc < 4) { + result = Tk_ConfigureInfo(interp, tablePtr->tkwin, tableSpecs, + (char *) tablePtr, (objc == 3) ? + Tcl_GetString(objv[2]) : (char *) NULL, 0); + } else { + result = TableConfigure(interp, tablePtr, objc - 2, objv + 2, + TK_CONFIG_ARGV_ONLY, 0); + } + break; + + case CMD_CURSEL: + result = Table_CurselectionCmd(clientData, interp, objc, objv); + break; + + case CMD_CURVALUE: + result = Table_CurvalueCmd(clientData, interp, objc, objv); + break; + + case CMD_DELETE: + case CMD_INSERT: + result = Table_EditCmd(clientData, interp, objc, objv); + break; + + case CMD_GET: + result = Table_GetCmd(clientData, interp, objc, objv); + break; + + case CMD_HEIGHT: + case CMD_WIDTH: + result = Table_AdjustCmd(clientData, interp, objc, objv); + break; + + case CMD_HIDDEN: + result = Table_HiddenCmd(clientData, interp, objc, objv); + break; + + case CMD_ICURSOR: + if (objc != 2 && objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?cursorPos?"); + result = TCL_ERROR; + break; + } + if (!(tablePtr->flags & HAS_ACTIVE) || + (tablePtr->flags & ACTIVE_DISABLED) || + tablePtr->state == STATE_DISABLED) { + Tcl_SetObjResult(interp, Tcl_NewIntObj(-1)); + break; + } else if (objc == 3) { + if (TableGetIcursorObj(tablePtr, objv[2], NULL) != TCL_OK) { + result = TCL_ERROR; + break; + } + TableRefresh(tablePtr, tablePtr->activeRow, + tablePtr->activeCol, CELL); + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(tablePtr->icursor)); + break; + + case CMD_INDEX: { + char *which = NULL; + + if (objc == 4) { + which = Tcl_GetString(objv[3]); + } + if ((objc < 3 || objc > 4) || + ((objc == 4) && (strcmp(which, "row") + && strcmp(which, "col")))) { + Tcl_WrongNumArgs(interp, 2, objv, "<index> ?row|col?"); + result = TCL_ERROR; + } else if (TableGetIndexObj(tablePtr, objv[2], &row, &col) + != TCL_OK) { + result = TCL_ERROR; + } else if (objc == 3) { + char buf[INDEX_BUFSIZE]; + /* recreate the index, just in case it got bounded */ + TableMakeArrayIndex(row, col, buf); + Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1)); + } else { /* INDEX row|col */ + Tcl_SetObjResult(interp, + Tcl_NewIntObj((*which == 'r') ? row : col)); + } + break; + } + +#ifdef POSTSCRIPT + case CMD_POSTSCRIPT: + result = Table_PostscriptCmd(clientData, interp, objc, objv); + break; +#endif + + case CMD_REREAD: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + result = TCL_ERROR; + } else if ((tablePtr->flags & HAS_ACTIVE) && + !(tablePtr->flags & ACTIVE_DISABLED) && + tablePtr->state != STATE_DISABLED) { + TableGetActiveBuf(tablePtr); + TableRefresh(tablePtr, tablePtr->activeRow, + tablePtr->activeCol, CELL|INV_FORCE); + } + break; + + case CMD_SCAN: + result = Table_ScanCmd(clientData, interp, objc, objv); + break; + + case CMD_SEE: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + result = TCL_ERROR; + } else if (TableGetIndexObj(tablePtr, objv[2], + &row, &col) == TCL_ERROR) { + result = TCL_ERROR; + } else { + /* Adjust from user to master coords */ + row -= tablePtr->rowOffset; + col -= tablePtr->colOffset; + if (!TableCellVCoords(tablePtr, row, col, &i, &i, &i, &i, 1)) { + tablePtr->topRow = row-1; + tablePtr->leftCol = col-1; + TableAdjustParams(tablePtr); + } + } + break; + + case CMD_SELECTION: + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?"); + result = TCL_ERROR; + break; + } + if (Tcl_GetIndexFromObj(interp, objv[2], selCmdNames, + "selection option", 0, &cmdIndex) != TCL_OK) { + result = TCL_ERROR; + break; + } + switch ((enum selCommand) cmdIndex) { + case CMD_SEL_ANCHOR: + result = Table_SelAnchorCmd(clientData, interp, + objc, objv); + break; + case CMD_SEL_CLEAR: + result = Table_SelClearCmd(clientData, interp, objc, objv); + break; + case CMD_SEL_INCLUDES: + result = Table_SelIncludesCmd(clientData, interp, + objc, objv); + break; + case CMD_SEL_PRESENT: { + Tcl_HashSearch search; + int present = (Tcl_FirstHashEntry(tablePtr->selCells, + &search) != NULL); + + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(present)); + break; + } + case CMD_SEL_SET: + result = Table_SelSetCmd(clientData, interp, objc, objv); + break; + } + break; + + case CMD_SET: + result = Table_SetCmd(clientData, interp, objc, objv); + break; + + case CMD_SPANS: + result = Table_SpanCmd(clientData, interp, objc, objv); + break; + + case CMD_TAG: + result = Table_TagCmd(clientData, interp, objc, objv); + break; + + case CMD_VALIDATE: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + result = TCL_ERROR; + } else if (TableGetIndexObj(tablePtr, objv[2], + &row, &col) == TCL_ERROR) { + result = TCL_ERROR; + } else { + i = tablePtr->validate; + tablePtr->validate = 1; + result = TableValidateChange(tablePtr, row, col, (char *) NULL, + (char *) NULL, -1); + tablePtr->validate = i; + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result == TCL_OK)); + result = TCL_OK; + } + break; + + case CMD_VERSION: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + result = TCL_ERROR; + } else { + Tcl_SetObjResult(interp, Tcl_NewStringObj(PACKAGE_VERSION, -1)); + } + break; + + case CMD_WINDOW: + result = Table_WindowCmd(clientData, interp, objc, objv); + break; + + case CMD_XVIEW: + case CMD_YVIEW: + result = Table_ViewCmd(clientData, interp, objc, objv); + break; + } + + Tcl_Release((ClientData) tablePtr); + return result; +} + +/* + *---------------------------------------------------------------------- + * + * TableDestroy -- + * This procedure is invoked by Tcl_EventuallyFree + * to clean up the internal structure of a table at a safe time + * (when no-one is using it anymore). + * + * Results: + * None. + * + * Side effects: + * Everything associated with the table is freed up (hopefully). + * + *---------------------------------------------------------------------- + */ +static void +TableDestroy(ClientData clientdata) +{ + register Table *tablePtr = (Table *) clientdata; + Tcl_HashEntry *entryPtr; + Tcl_HashSearch search; + + /* These may be repetitive from DestroyNotify, but it doesn't hurt */ + /* cancel any pending update or timer */ + if (tablePtr->flags & REDRAW_PENDING) { + Tcl_CancelIdleCall(TableDisplay, (ClientData) tablePtr); + tablePtr->flags &= ~REDRAW_PENDING; + } + Tcl_DeleteTimerHandler(tablePtr->cursorTimer); + Tcl_DeleteTimerHandler(tablePtr->flashTimer); + + /* delete the variable trace */ + if (tablePtr->arrayVar != NULL) { + Tcl_UntraceVar(tablePtr->interp, tablePtr->arrayVar, + TCL_TRACE_WRITES | TCL_TRACE_UNSETS | TCL_GLOBAL_ONLY, + (Tcl_VarTraceProc *)TableVarProc, (ClientData) tablePtr); + } + + /* free the int arrays */ + if (tablePtr->colPixels) ckfree((char *) tablePtr->colPixels); + if (tablePtr->rowPixels) ckfree((char *) tablePtr->rowPixels); + if (tablePtr->colStarts) ckfree((char *) tablePtr->colStarts); + if (tablePtr->rowStarts) ckfree((char *) tablePtr->rowStarts); + + /* delete cached active tag and string */ + if (tablePtr->activeTagPtr) ckfree((char *) tablePtr->activeTagPtr); + if (tablePtr->activeBuf != NULL) ckfree(tablePtr->activeBuf); + + /* + * Delete the various hash tables, make sure to clear the STRING_KEYS + * tables that allocate their strings: + * cache, spanTbl (spanAffTbl shares spanTbl info) + */ + Table_ClearHashTable(tablePtr->cache); + ckfree((char *) (tablePtr->cache)); + Tcl_DeleteHashTable(tablePtr->rowStyles); + ckfree((char *) (tablePtr->rowStyles)); + Tcl_DeleteHashTable(tablePtr->colStyles); + ckfree((char *) (tablePtr->colStyles)); + Tcl_DeleteHashTable(tablePtr->cellStyles); + ckfree((char *) (tablePtr->cellStyles)); + Tcl_DeleteHashTable(tablePtr->flashCells); + ckfree((char *) (tablePtr->flashCells)); + Tcl_DeleteHashTable(tablePtr->selCells); + ckfree((char *) (tablePtr->selCells)); + Tcl_DeleteHashTable(tablePtr->colWidths); + ckfree((char *) (tablePtr->colWidths)); + Tcl_DeleteHashTable(tablePtr->rowHeights); + ckfree((char *) (tablePtr->rowHeights)); +#ifdef PROCS + Tcl_DeleteHashTable(tablePtr->inProc); + ckfree((char *) (tablePtr->inProc)); +#endif + if (tablePtr->spanTbl) { + Table_ClearHashTable(tablePtr->spanTbl); + ckfree((char *) (tablePtr->spanTbl)); + Tcl_DeleteHashTable(tablePtr->spanAffTbl); + ckfree((char *) (tablePtr->spanAffTbl)); + } + + /* Now free up all the tag information */ + for (entryPtr = Tcl_FirstHashEntry(tablePtr->tagTable, &search); + entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) { + TableCleanupTag(tablePtr, (TableTag *) Tcl_GetHashValue(entryPtr)); + ckfree((char *) Tcl_GetHashValue(entryPtr)); + } + /* free up the stuff in the default tag */ + TableCleanupTag(tablePtr, &(tablePtr->defaultTag)); + /* And delete the actual hash table */ + Tcl_DeleteHashTable(tablePtr->tagTable); + ckfree((char *) (tablePtr->tagTable)); + ckfree((char *) (tablePtr->tagPrios)); + ckfree((char *) (tablePtr->tagPrioNames)); + + /* Now free up all the embedded window info */ + for (entryPtr = Tcl_FirstHashEntry(tablePtr->winTable, &search); + entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) { + EmbWinDelete(tablePtr, (TableEmbWindow *) Tcl_GetHashValue(entryPtr)); + } + /* And delete the actual hash table */ + Tcl_DeleteHashTable(tablePtr->winTable); + ckfree((char *) (tablePtr->winTable)); + + /* free the configuration options in the widget */ + Tk_FreeOptions(tableSpecs, (char *) tablePtr, tablePtr->display, 0); + + /* and free the widget memory at last! */ + ckfree((char *) (tablePtr)); +} + +/* + *---------------------------------------------------------------------- + * + * TableConfigure -- + * This procedure is called to process an objc/objv list, plus + * the Tk option database, in order to configure (or reconfigure) + * a table widget. + * + * Results: + * The return value is a standard Tcl result. If TCL_ERROR is + * returned, then interp result contains an error message. + * + * Side effects: + * Configuration information, such as colors, border width, etc. + * get set for tablePtr; old resources get freed, if there were any. + * Certain values might be constrained. + * + *---------------------------------------------------------------------- + */ +static int +TableConfigure(interp, tablePtr, objc, objv, flags, forceUpdate) + Tcl_Interp *interp; /* Used for error reporting. */ + register Table *tablePtr; /* Information about widget; may or may + * not already have values for some fields. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ + int flags; /* Flags to pass to Tk_ConfigureWidget. */ + int forceUpdate; /* Whether to force an update - required + * for initial configuration */ +{ + Tcl_HashSearch search; + int oldUse, oldCaching, oldExport, oldTitleRows, oldTitleCols; + int result = TCL_OK; + char *oldVar = NULL, **argv; + Tcl_DString error; + Tk_FontMetrics fm; + + oldExport = tablePtr->exportSelection; + oldCaching = tablePtr->caching; + oldUse = tablePtr->useCmd; + oldTitleRows = tablePtr->titleRows; + oldTitleCols = tablePtr->titleCols; + if (tablePtr->arrayVar != NULL) { + oldVar = ckalloc(strlen(tablePtr->arrayVar) + 1); + strcpy(oldVar, tablePtr->arrayVar); + } + + /* Do the configuration */ + argv = StringifyObjects(objc, objv); + result = Tk_ConfigureWidget(interp, tablePtr->tkwin, tableSpecs, + objc, (CONST84 char **) argv, (char *) tablePtr, flags); + ckfree((char *) argv); + if (result != TCL_OK) { + return TCL_ERROR; + } + + Tcl_DStringInit(&error); + + /* Any time we configure, reevaluate what our data source is */ + tablePtr->dataSource = DATA_NONE; + if (tablePtr->caching) { + tablePtr->dataSource |= DATA_CACHE; + } + if (tablePtr->command && tablePtr->useCmd) { + tablePtr->dataSource |= DATA_COMMAND; + } else if (tablePtr->arrayVar) { + tablePtr->dataSource |= DATA_ARRAY; + } + + /* Check to see if the array variable was changed */ + if (strcmp((tablePtr->arrayVar ? tablePtr->arrayVar : ""), + (oldVar ? oldVar : ""))) { + /* only do the following if arrayVar is our data source */ + if (tablePtr->dataSource & DATA_ARRAY) { + /* + * ensure that the cache will flush later + * so it gets the new values + */ + oldCaching = !(tablePtr->caching); + } + /* remove the trace on the old array variable if there was one */ + if (oldVar != NULL) + Tcl_UntraceVar(interp, oldVar, + TCL_TRACE_WRITES|TCL_TRACE_UNSETS|TCL_GLOBAL_ONLY, + (Tcl_VarTraceProc *)TableVarProc, (ClientData) tablePtr); + /* Check whether variable is an array and trace it if it is */ + if (tablePtr->arrayVar != NULL) { + /* does the variable exist as an array? */ + if (Tcl_SetVar2(interp, tablePtr->arrayVar, TEST_KEY, "", + TCL_GLOBAL_ONLY) == NULL) { + Tcl_DStringAppend(&error, "invalid variable value \"", -1); + Tcl_DStringAppend(&error, tablePtr->arrayVar, -1); + Tcl_DStringAppend(&error, "\": could not be made an array", + -1); + ckfree(tablePtr->arrayVar); + tablePtr->arrayVar = NULL; + tablePtr->dataSource &= ~DATA_ARRAY; + result = TCL_ERROR; + } else { + Tcl_UnsetVar2(interp, tablePtr->arrayVar, TEST_KEY, + TCL_GLOBAL_ONLY); + /* remove the effect of the evaluation */ + /* set a trace on the variable */ + Tcl_TraceVar(interp, tablePtr->arrayVar, + TCL_TRACE_WRITES|TCL_TRACE_UNSETS|TCL_GLOBAL_ONLY, + (Tcl_VarTraceProc *)TableVarProc, + (ClientData) tablePtr); + + /* only do the following if arrayVar is our data source */ + if (tablePtr->dataSource & DATA_ARRAY) { + /* get the current value of the selection */ + TableGetActiveBuf(tablePtr); + } + } + } + } + + /* Free oldVar if it was allocated */ + if (oldVar != NULL) ckfree(oldVar); + + if ((tablePtr->command && tablePtr->useCmd && !oldUse) || + (tablePtr->arrayVar && !(tablePtr->useCmd) && oldUse)) { + /* + * Our effective data source changed, so flush and + * retrieve new active buffer + */ + Table_ClearHashTable(tablePtr->cache); + Tcl_InitHashTable(tablePtr->cache, TCL_STRING_KEYS); + TableGetActiveBuf(tablePtr); + forceUpdate = 1; + } else if (oldCaching != tablePtr->caching) { + /* + * Caching changed, so just clear the cache for safety + */ + Table_ClearHashTable(tablePtr->cache); + Tcl_InitHashTable(tablePtr->cache, TCL_STRING_KEYS); + forceUpdate = 1; + } + + /* + * Set up the default column width and row height + */ + Tk_GetFontMetrics(tablePtr->defaultTag.tkfont, &fm); + tablePtr->charWidth = Tk_TextWidth(tablePtr->defaultTag.tkfont, "0", 1); + tablePtr->charHeight = fm.linespace + 2; + + if (tablePtr->insertWidth <= 0) { + tablePtr->insertWidth = 2; + } + if (tablePtr->insertBorderWidth > tablePtr->insertWidth/2) { + tablePtr->insertBorderWidth = tablePtr->insertWidth/2; + } + tablePtr->highlightWidth = MAX(0,tablePtr->highlightWidth); + + /* + * Ensure that certain values are within proper constraints + */ + tablePtr->rows = MAX(1, tablePtr->rows); + tablePtr->cols = MAX(1, tablePtr->cols); + tablePtr->padX = MAX(0, tablePtr->padX); + tablePtr->padY = MAX(0, tablePtr->padY); + tablePtr->ipadX = MAX(0, tablePtr->ipadX); + tablePtr->ipadY = MAX(0, tablePtr->ipadY); + tablePtr->maxReqCols = MAX(0, tablePtr->maxReqCols); + tablePtr->maxReqRows = MAX(0, tablePtr->maxReqRows); + CONSTRAIN(tablePtr->titleRows, 0, tablePtr->rows); + CONSTRAIN(tablePtr->titleCols, 0, tablePtr->cols); + + /* + * Handle change of default border style + * The default borderwidth must be >= 0. + */ + if (tablePtr->drawMode & (DRAW_MODE_SINGLE|DRAW_MODE_FAST)) { + /* + * When drawing fast or single, the border must be <= 1. + * We have to do this after the normal configuration + * to base the borders off the first value given. + */ + tablePtr->defaultTag.bd[0] = MIN(1, tablePtr->defaultTag.bd[0]); + tablePtr->defaultTag.borders = 1; + ckfree((char *) tablePtr->defaultTag.borderStr); + tablePtr->defaultTag.borderStr = (char *) ckalloc(2); + strcpy(tablePtr->defaultTag.borderStr, + tablePtr->defaultTag.bd[0] ? "1" : "0"); + } + + /* + * Claim the selection if we've suddenly started exporting it and + * there is a selection to export. + */ + if (tablePtr->exportSelection && !oldExport && + (Tcl_FirstHashEntry(tablePtr->selCells, &search) != NULL)) { + Tk_OwnSelection(tablePtr->tkwin, XA_PRIMARY, TableLostSelection, + (ClientData) tablePtr); + } + + if ((tablePtr->titleRows < oldTitleRows) || + (tablePtr->titleCols < oldTitleCols)) { + /* + * Prevent odd movement due to new possible topleft index + */ + if (tablePtr->titleRows < oldTitleRows) + tablePtr->topRow -= oldTitleRows - tablePtr->titleRows; + if (tablePtr->titleCols < oldTitleCols) + tablePtr->leftCol -= oldTitleCols - tablePtr->titleCols; + /* + * If our title area shrank, we need to check that the items + * within the new title area don't try to span outside it. + */ + TableSpanSanCheck(tablePtr); + } + + /* + * Only do the full reconfigure if absolutely necessary + */ + if (!forceUpdate) { + int i, dummy; + for (i = 0; i < objc-1; i += 2) { + if (Tcl_GetIndexFromObj(NULL, objv[i], updateOpts, "", 0, &dummy) + == TCL_OK) { + forceUpdate = 1; + break; + } + } + } + if (forceUpdate) { + /* + * Calculate the row and column starts + * Adjust the top left corner of the internal display + */ + TableAdjustParams(tablePtr); + /* reset the cursor */ + TableConfigCursor(tablePtr); + /* set up the background colour in the window */ + Tk_SetBackgroundFromBorder(tablePtr->tkwin, tablePtr->defaultTag.bg); + /* set the geometry and border */ + TableGeometryRequest(tablePtr); + Tk_SetInternalBorder(tablePtr->tkwin, tablePtr->highlightWidth); + /* invalidate the whole table */ + TableInvalidateAll(tablePtr, INV_HIGHLIGHT); + } + /* + * FIX this is goofy because the result could be munged by other + * functions. Could be improved. + */ + Tcl_ResetResult(interp); + if (result == TCL_ERROR) { + Tcl_AddErrorInfo(interp, "\t(configuring table widget)"); + Tcl_DStringResult(interp, &error); + } + Tcl_DStringFree(&error); + return result; +} +#ifdef HAVE_TCL84 +/* + *--------------------------------------------------------------------------- + * + * TableWorldChanged -- + * + * This procedure is called when the world has changed in some + * way and the widget needs to recompute all its graphics contexts + * and determine its new geometry. + * + * Results: + * None. + * + * Side effects: + * Entry will be relayed out and redisplayed. + * + *--------------------------------------------------------------------------- + */ + +static void +TableWorldChanged(instanceData) + ClientData instanceData; /* Information about widget. */ +{ + Table *tablePtr = (Table *) instanceData; + Tk_FontMetrics fm; + + /* + * Set up the default column width and row height + */ + Tk_GetFontMetrics(tablePtr->defaultTag.tkfont, &fm); + tablePtr->charWidth = Tk_TextWidth(tablePtr->defaultTag.tkfont, "0", 1); + tablePtr->charHeight = fm.linespace + 2; + + /* + * Recompute the window's geometry and arrange for it to be redisplayed. + */ + + TableAdjustParams(tablePtr); + TableGeometryRequest(tablePtr); + Tk_SetInternalBorder(tablePtr->tkwin, tablePtr->highlightWidth); + /* invalidate the whole table */ + TableInvalidateAll(tablePtr, INV_HIGHLIGHT); +} +#endif +/* + *-------------------------------------------------------------- + * + * TableEventProc -- + * This procedure is invoked by the Tk dispatcher for various + * events on tables. + * + * Results: + * None. + * + * Side effects: + * When the window gets deleted, internal structures get + * cleaned up. When it gets exposed, it is redisplayed. + * + *-------------------------------------------------------------- + */ +static void +TableEventProc(clientData, eventPtr) + ClientData clientData; /* Information about window. */ + XEvent *eventPtr; /* Information about event. */ +{ + Table *tablePtr = (Table *) clientData; + int row, col; + + switch (eventPtr->type) { + case MotionNotify: + if (!(tablePtr->resize & SEL_NONE) + && (tablePtr->bdcursor != None) && + TableAtBorder(tablePtr, eventPtr->xmotion.x, + eventPtr->xmotion.y, &row, &col) && + ((row>=0 && (tablePtr->resize & SEL_ROW)) || + (col>=0 && (tablePtr->resize & SEL_COL)))) { + /* + * The bordercursor is defined and we meet the criteria for + * being over a border. Set the cursor to border if not + * already done. + */ + if (!(tablePtr->flags & OVER_BORDER)) { + tablePtr->flags |= OVER_BORDER; + Tk_DefineCursor(tablePtr->tkwin, tablePtr->bdcursor); + } + } else if (tablePtr->flags & OVER_BORDER) { + tablePtr->flags &= ~OVER_BORDER; + if (tablePtr->cursor != None) { + Tk_DefineCursor(tablePtr->tkwin, tablePtr->cursor); + } else { + Tk_UndefineCursor(tablePtr->tkwin); + } +#ifdef TITLE_CURSOR + } else if (tablePtr->flags & (OVER_BORDER|OVER_TITLE)) { + Tk_Cursor cursor = tablePtr->cursor; + + //tablePtr->flags &= ~(OVER_BORDER|OVER_TITLE); + + if (tablePtr->titleCursor != None) { + TableWhatCell(tablePtr, eventPtr->xmotion.x, + eventPtr->xmotion.y, &row, &col); + if ((row < tablePtr->titleRows) || + (col < tablePtr->titleCols)) { + if (tablePtr->flags & OVER_TITLE) { + break; + } + tablePtr->flags |= OVER_TITLE; + cursor = tablePtr->titleCursor; + } + } + if (cursor != None) { + Tk_DefineCursor(tablePtr->tkwin, cursor); + } else { + Tk_UndefineCursor(tablePtr->tkwin); + } + } else if (tablePtr->titleCursor != None) { + Tk_Cursor cursor = tablePtr->cursor; + + TableWhatCell(tablePtr, eventPtr->xmotion.x, + eventPtr->xmotion.y, &row, &col); + if ((row < tablePtr->titleRows) || + (col < tablePtr->titleCols)) { + if (tablePtr->flags & OVER_TITLE) { + break; + } + tablePtr->flags |= OVER_TITLE; + cursor = tablePtr->titleCursor; + } +#endif + } + break; + + case Expose: + TableInvalidate(tablePtr, eventPtr->xexpose.x, eventPtr->xexpose.y, + eventPtr->xexpose.width, eventPtr->xexpose.height, + INV_HIGHLIGHT); + break; + + case DestroyNotify: + /* remove the command from the interpreter */ + if (tablePtr->tkwin != NULL) { + tablePtr->tkwin = NULL; + Tcl_DeleteCommandFromToken(tablePtr->interp, + tablePtr->widgetCmd); + } + + /* cancel any pending update or timer */ + if (tablePtr->flags & REDRAW_PENDING) { + Tcl_CancelIdleCall(TableDisplay, (ClientData) tablePtr); + tablePtr->flags &= ~REDRAW_PENDING; + } + Tcl_DeleteTimerHandler(tablePtr->cursorTimer); + Tcl_DeleteTimerHandler(tablePtr->flashTimer); + + Tcl_EventuallyFree((ClientData) tablePtr, + (Tcl_FreeProc *) TableDestroy); + break; + + case MapNotify: /* redraw table when remapped if it changed */ + if (tablePtr->flags & REDRAW_ON_MAP) { + tablePtr->flags &= ~REDRAW_ON_MAP; + Tcl_Preserve((ClientData) tablePtr); + TableAdjustParams(tablePtr); + TableInvalidateAll(tablePtr, INV_HIGHLIGHT); + Tcl_Release((ClientData) tablePtr); + } + break; + + case ConfigureNotify: + Tcl_Preserve((ClientData) tablePtr); + TableAdjustParams(tablePtr); + TableInvalidateAll(tablePtr, INV_HIGHLIGHT); + Tcl_Release((ClientData) tablePtr); + break; + + case FocusIn: + case FocusOut: + if (eventPtr->xfocus.detail != NotifyInferior) { + tablePtr->flags |= REDRAW_BORDER; + if (eventPtr->type == FocusOut) { + tablePtr->flags &= ~HAS_FOCUS; + } else { + tablePtr->flags |= HAS_FOCUS; + } + TableRedrawHighlight(tablePtr); + /* cancel the timer */ + TableConfigCursor(tablePtr); + } + break; + } +} + +/* + *---------------------------------------------------------------------- + * + * TableCmdDeletedProc -- + * + * This procedure is invoked when a widget command is deleted. If + * the widget isn't already in the process of being destroyed, + * this command destroys it. + * + * Results: + * None. + * + * Side effects: + * The widget is destroyed. + * + *---------------------------------------------------------------------- + */ +static void +TableCmdDeletedProc(ClientData clientData) +{ + Table *tablePtr = (Table *) clientData; + Tk_Window tkwin; + + /* + * This procedure could be invoked either because the window was + * destroyed and the command was then deleted (in which case tkwin + * is NULL) or because the command was deleted, and then this procedure + * destroys the widget. + */ + + if (tablePtr->tkwin != NULL) { + tkwin = tablePtr->tkwin; + tablePtr->tkwin = NULL; + Tk_DestroyWindow(tkwin); + } +} + +/* + *---------------------------------------------------------------------- + * + * TableRedrawHighlight -- + * Redraws just the highlight for the window + * + * Results: + * None. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ +static void +TableRedrawHighlight(Table *tablePtr) +{ + if ((tablePtr->flags & REDRAW_BORDER) && tablePtr->highlightWidth > 0) { + GC gc = Tk_GCForColor((tablePtr->flags & HAS_FOCUS) + ? tablePtr->highlightColorPtr : tablePtr->highlightBgColorPtr, + Tk_WindowId(tablePtr->tkwin)); + Tk_DrawFocusHighlight(tablePtr->tkwin, gc, tablePtr->highlightWidth, + Tk_WindowId(tablePtr->tkwin)); + } + tablePtr->flags &= ~REDRAW_BORDER; +} + +/* + *---------------------------------------------------------------------- + * + * TableRefresh -- + * Refreshes an area of the table based on the mode. + * row,col in real coords (0-based) + * + * Results: + * Will cause redraw for visible cells + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +void +TableRefresh(register Table *tablePtr, int row, int col, int mode) +{ + int x, y, w, h; + + if ((row < 0) || (col < 0)) { + /* + * Invalid coords passed in. This can happen when the "active" cell + * is refreshed, but doesn't really exist (row==-1 && col==-1). + */ + return; + } + if (mode & CELL) { + if (TableCellVCoords(tablePtr, row, col, &x, &y, &w, &h, 0)) { + TableInvalidate(tablePtr, x, y, w, h, mode); + } + } else if (mode & ROW) { + /* get the position of the leftmost cell in the row */ + if ((mode & INV_FILL) && row < tablePtr->topRow) { + /* Invalidate whole table */ + TableInvalidateAll(tablePtr, mode); + } else if (TableCellVCoords(tablePtr, row, tablePtr->leftCol, + &x, &y, &w, &h, 0)) { + /* Invalidate from this row, maybe to end */ + TableInvalidate(tablePtr, 0, y, Tk_Width(tablePtr->tkwin), + (mode&INV_FILL)?Tk_Height(tablePtr->tkwin):h, mode); + } + } else if (mode & COL) { + /* get the position of the topmost cell on the column */ + if ((mode & INV_FILL) && col < tablePtr->leftCol) { + /* Invalidate whole table */ + TableInvalidateAll(tablePtr, mode); + } else if (TableCellVCoords(tablePtr, tablePtr->topRow, col, + &x, &y, &w, &h, 0)) { + /* Invalidate from this column, maybe to end */ + TableInvalidate(tablePtr, x, 0, + (mode&INV_FILL)?Tk_Width(tablePtr->tkwin):w, + Tk_Height(tablePtr->tkwin), mode); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TableGetGc -- + * Gets a GC corresponding to the tag structure passed. + * + * Results: + * Returns usable GC. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ +static void +TableGetGc(Display *display, Drawable d, TableTag *tagPtr, GC *tagGc) +{ + XGCValues gcValues; + gcValues.foreground = Tk_3DBorderColor(tagPtr->fg)->pixel; + gcValues.background = Tk_3DBorderColor(tagPtr->bg)->pixel; + gcValues.font = Tk_FontId(tagPtr->tkfont); + if (*tagGc == NULL) { + gcValues.graphics_exposures = False; + *tagGc = XCreateGC(display, d, + GCForeground|GCBackground|GCFont|GCGraphicsExposures, + &gcValues); + } else { + XChangeGC(display, *tagGc, GCForeground|GCBackground|GCFont, + &gcValues); + } +} + +#define TableFreeGc XFreeGC + +/* + *-------------------------------------------------------------- + * + * TableUndisplay -- + * This procedure removes the contents of a table window + * that have been moved offscreen. + * + * Results: + * Embedded windows can be unmapped. + * + * Side effects: + * Information disappears from the screen. + * + *-------------------------------------------------------------- + */ +static void +TableUndisplay(register Table *tablePtr) +{ + register int *seen = tablePtr->seen; + int row, col; + + /* We need to find out the true last cell, not considering spans */ + tablePtr->flags |= AVOID_SPANS; + TableGetLastCell(tablePtr, &row, &col); + tablePtr->flags &= ~AVOID_SPANS; + + if (seen[0] != -1) { + if (seen[0] < tablePtr->topRow) { + /* Remove now hidden rows */ + EmbWinUnmap(tablePtr, seen[0], MIN(seen[2],tablePtr->topRow-1), + seen[1], seen[3]); + /* Also account for the title area */ + EmbWinUnmap(tablePtr, seen[0], MIN(seen[2],tablePtr->topRow-1), + 0, tablePtr->titleCols-1); + } + if (seen[1] < tablePtr->leftCol) { + /* Remove now hidden cols */ + EmbWinUnmap(tablePtr, seen[0], seen[2], + seen[1], MAX(seen[3],tablePtr->leftCol-1)); + /* Also account for the title area */ + EmbWinUnmap(tablePtr, 0, tablePtr->titleRows-1, + seen[1], MAX(seen[3],tablePtr->leftCol-1)); + } + if (seen[2] > row) { + /* Remove now off-screen rows */ + EmbWinUnmap(tablePtr, MAX(seen[0],row+1), seen[2], + seen[1], seen[3]); + /* Also account for the title area */ + EmbWinUnmap(tablePtr, MAX(seen[0],row+1), seen[2], + 0, tablePtr->titleCols-1); + } + if (seen[3] > col) { + /* Remove now off-screen cols */ + EmbWinUnmap(tablePtr, seen[0], seen[2], + MAX(seen[1],col+1), seen[3]); + /* Also account for the title area */ + EmbWinUnmap(tablePtr, 0, tablePtr->titleRows-1, + MAX(seen[1],col+1), seen[3]); + } + } + seen[0] = tablePtr->topRow; + seen[1] = tablePtr->leftCol; + seen[2] = row; + seen[3] = col; +} + +/* + * Generally we should be able to use XSetClipRectangles on X11, but + * the addition of Xft drawing to Tk 8.5+ completely ignores the clip + * rectangles. Thus turn it off for all cases until clip rectangles + * are known to be respected. [Bug 1805350] + */ +#if 1 || defined(MAC_TCL) || defined(UNDER_CE) || (defined(WIN32) && defined(TCL_THREADS)) || defined(MAC_OSX_TK) +#define NO_XSETCLIP +#endif +/* + *-------------------------------------------------------------- + * + * TableDisplay -- + * This procedure redraws the contents of a table window. + * The conditional code in this function is due to these factors: + * o Lack of XSetClipRectangles on Macintosh + * o Use of alternative routine for Windows + * + * Results: + * None. + * + * Side effects: + * Information appears on the screen. + * + *-------------------------------------------------------------- + */ +static void +TableDisplay(ClientData clientdata) +{ + register Table *tablePtr = (Table *) clientdata; + Tk_Window tkwin = tablePtr->tkwin; + Display *display = tablePtr->display; + Drawable window; +#ifdef NO_XSETCLIP + Drawable clipWind; +#elif defined(WIN32) + TkWinDrawable *twdPtr; + HDC dc; + HRGN clipR; +#else + XRectangle clipRect; +#endif + int rowFrom, rowTo, colFrom, colTo, + invalidX, invalidY, invalidWidth, invalidHeight, + x, y, width, height, itemX, itemY, itemW, itemH, + row, col, urow, ucol, hrow=0, hcol=0, cx, cy, cw, ch, borders, bd[6], + numBytes, new, boundW, boundH, maxW, maxH, cellType, + originX, originY, activeCell, shouldInvert, ipadx, ipady, padx, pady; + GC tagGc = NULL, topGc, bottomGc; + char *string = NULL; + char buf[INDEX_BUFSIZE]; + TableTag *tagPtr = NULL, *titlePtr, *selPtr, *activePtr, *flashPtr, + *rowPtr, *colPtr; + Tcl_HashEntry *entryPtr; + static XPoint rect[3] = { {0, 0}, {0, 0}, {0, 0} }; + Tcl_HashTable *colTagsCache = NULL; + Tcl_HashTable *drawnCache = NULL; + Tk_TextLayout textLayout = NULL; + TableEmbWindow *ewPtr; + Tk_FontMetrics fm; + Tk_Font ellFont = NULL; + char *ellipsis = NULL; + int ellLen = 0, useEllLen = 0, ellEast = 0; + + tablePtr->flags &= ~REDRAW_PENDING; + if ((tkwin == NULL) || !Tk_IsMapped(tkwin)) { + return; + } + + boundW = Tk_Width(tkwin) - tablePtr->highlightWidth; + boundH = Tk_Height(tkwin) - tablePtr->highlightWidth; + + /* Constrain drawable to not include highlight borders */ + invalidX = MAX(tablePtr->highlightWidth, tablePtr->invalidX); + invalidY = MAX(tablePtr->highlightWidth, tablePtr->invalidY); + invalidWidth = MIN(tablePtr->invalidWidth, MAX(1, boundW-invalidX)); + invalidHeight = MIN(tablePtr->invalidHeight, MAX(1, boundH-invalidY)); + + ipadx = tablePtr->ipadX; + ipady = tablePtr->ipadY; + padx = tablePtr->padX; + pady = tablePtr->padY; + +#ifndef WIN32 + /* + * if we are using the slow drawing mode with a pixmap + * create the pixmap and adjust x && y for offset in pixmap + * FIX: Ignore slow mode for Win32 as the fast ClipRgn trick + * below does not work for bitmaps. + */ + if (tablePtr->drawMode == DRAW_MODE_SLOW) { + window = Tk_GetPixmap(display, Tk_WindowId(tkwin), + invalidWidth, invalidHeight, Tk_Depth(tkwin)); + } else +#endif + window = Tk_WindowId(tkwin); +#ifdef NO_XSETCLIP + clipWind = Tk_GetPixmap(display, window, + invalidWidth, invalidHeight, Tk_Depth(tkwin)); +#endif + + /* set up the permanent tag styles */ + entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, "title"); + titlePtr = (TableTag *) Tcl_GetHashValue(entryPtr); + entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, "sel"); + selPtr = (TableTag *) Tcl_GetHashValue(entryPtr); + entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, "active"); + activePtr = (TableTag *) Tcl_GetHashValue(entryPtr); + entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, "flash"); + flashPtr = (TableTag *) Tcl_GetHashValue(entryPtr); + + /* We need to find out the true cell span, not considering spans */ + tablePtr->flags |= AVOID_SPANS; + /* find out the cells represented by the invalid region */ + TableWhatCell(tablePtr, invalidX, invalidY, &rowFrom, &colFrom); + TableWhatCell(tablePtr, invalidX+invalidWidth-1, + invalidY+invalidHeight-1, &rowTo, &colTo); + tablePtr->flags &= ~AVOID_SPANS; + +#ifdef DEBUG + tcl_dprintf(tablePtr->interp, "%d,%d => %d,%d", + rowFrom+tablePtr->rowOffset, colFrom+tablePtr->colOffset, + rowTo+tablePtr->rowOffset, colTo+tablePtr->colOffset); +#endif + + /* + * Initialize colTagsCache hash table to cache column tag names. + */ + colTagsCache = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(colTagsCache, TCL_ONE_WORD_KEYS); + /* + * Initialize drawnCache hash table to cache drawn cells. + * This is necessary to prevent spanning cells being drawn multiple times. + */ + drawnCache = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(drawnCache, TCL_STRING_KEYS); + + /* + * Create the tag here. This will actually create a JoinTag + * That will handle the priority management of merging for us. + * We only need one allocated, and we'll reset it for each cell. + */ + tagPtr = TableNewTag(tablePtr); + + /* Cycle through the cells and display them */ + for (row = rowFrom; row <= rowTo; row++) { + /* + * are we in the 'dead zone' between the + * title rows and the first displayed row + */ + if (row < tablePtr->topRow && row >= tablePtr->titleRows) { + row = tablePtr->topRow; + } + + /* Cache the row in user terms */ + urow = row+tablePtr->rowOffset; + + /* Get the row tag once for all iterations of col */ + rowPtr = FindRowColTag(tablePtr, urow, ROW); + + for (col = colFrom; col <= colTo; col++) { + activeCell = 0; + /* + * Adjust to first viewable column if we are in the 'dead zone' + * between the title cols and the first displayed column. + */ + if (col < tablePtr->leftCol && col >= tablePtr->titleCols) { + col = tablePtr->leftCol; + } + + /* + * Get the coordinates for the cell before possible rearrangement + * of row,col due to spanning cells + */ + cellType = TableCellCoords(tablePtr, row, col, + &x, &y, &width, &height); + if (cellType == CELL_HIDDEN) { + /* + * width,height holds the real start row,col of the span. + * Put the use cell ref into a buffer for the hash lookups. + */ + TableMakeArrayIndex(width, height, buf); + Tcl_CreateHashEntry(drawnCache, buf, &new); + if (!new) { + /* Not new in the entry, so it's already drawn */ + continue; + } + hrow = row; hcol = col; + row = width-tablePtr->rowOffset; + col = height-tablePtr->colOffset; + TableCellVCoords(tablePtr, row, col, + &x, &y, &width, &height, 0); + /* We have to adjust the coords back onto the visual display */ + urow = row+tablePtr->rowOffset; + rowPtr = FindRowColTag(tablePtr, urow, ROW); + } + + /* Constrain drawn size to the visual boundaries */ + if (width > boundW-x) { width = boundW-x; } + if (height > boundH-y) { height = boundH-y; } + + /* Cache the col in user terms */ + ucol = col+tablePtr->colOffset; + + /* put the use cell ref into a buffer for the hash lookups */ + TableMakeArrayIndex(urow, ucol, buf); + if (cellType != CELL_HIDDEN) { + Tcl_CreateHashEntry(drawnCache, buf, &new); + } + + /* + * Make sure we start with a clean tag (set to table defaults). + */ + TableResetTag(tablePtr, tagPtr); + + /* + * Check to see if we have an embedded window in this cell. + */ + entryPtr = Tcl_FindHashEntry(tablePtr->winTable, buf); + if (entryPtr != NULL) { + ewPtr = (TableEmbWindow *) Tcl_GetHashValue(entryPtr); + + if (ewPtr->tkwin != NULL) { + /* Display embedded window instead of text */ + + /* if active, make it disabled to avoid + * unnecessary editing */ + if ((tablePtr->flags & HAS_ACTIVE) + && row == tablePtr->activeRow + && col == tablePtr->activeCol) { + tablePtr->flags |= ACTIVE_DISABLED; + } + + /* + * The EmbWinDisplay function may modify values in + * tagPtr, so reference those after this call. + */ + EmbWinDisplay(tablePtr, window, ewPtr, tagPtr, + x, y, width, height); + +#ifndef WIN32 + if (tablePtr->drawMode == DRAW_MODE_SLOW) { + /* Correctly adjust x && y with the offset */ + x -= invalidX; + y -= invalidY; + } +#endif + + Tk_Fill3DRectangle(tkwin, window, tagPtr->bg, x, y, width, + height, 0, TK_RELIEF_FLAT); + + /* border width for cell should now be properly set */ + borders = TableGetTagBorders(tagPtr, &bd[0], &bd[1], + &bd[2], &bd[3]); + bd[4] = (bd[0] + bd[1])/2; + bd[5] = (bd[2] + bd[3])/2; + + goto DrawBorder; + } + } + + /* + * Don't draw what won't be seen. + * Embedded windows handle this in EmbWinDisplay. + */ + if ((width <= 0) || (height <= 0)) { continue; } + +#ifndef WIN32 + if (tablePtr->drawMode == DRAW_MODE_SLOW) { + /* Correctly adjust x && y with the offset */ + x -= invalidX; + y -= invalidY; + } +#endif + + shouldInvert = 0; + /* + * Get the combined tag structure for the cell. + * First clear out a new tag structure that we will build in + * then add tags as we realize they belong. + * + * Tags have their own priorities which TableMergeTag will + * take into account when merging tags. + */ + + /* + * Merge colPtr if it exists + * let's see if we have the value cached already + * if not, run the findColTag routine and cache the value + */ + entryPtr = Tcl_CreateHashEntry(colTagsCache, (char *)ucol, &new); + if (new) { + colPtr = FindRowColTag(tablePtr, ucol, COL); + Tcl_SetHashValue(entryPtr, colPtr); + } else { + colPtr = (TableTag *) Tcl_GetHashValue(entryPtr); + } + if (colPtr != (TableTag *) NULL) { + TableMergeTag(tablePtr, tagPtr, colPtr); + } + /* Merge rowPtr if it exists */ + if (rowPtr != (TableTag *) NULL) { + TableMergeTag(tablePtr, tagPtr, rowPtr); + } + /* Am I in the titles */ + if (row < tablePtr->titleRows || col < tablePtr->titleCols) { + TableMergeTag(tablePtr, tagPtr, titlePtr); + } + /* Does this have a cell tag */ + entryPtr = Tcl_FindHashEntry(tablePtr->cellStyles, buf); + if (entryPtr != NULL) { + TableMergeTag(tablePtr, tagPtr, + (TableTag *) Tcl_GetHashValue(entryPtr)); + } + /* is this cell active? */ + if ((tablePtr->flags & HAS_ACTIVE) && + (tablePtr->state == STATE_NORMAL) && + row == tablePtr->activeRow && col == tablePtr->activeCol) { + if (tagPtr->state == STATE_DISABLED) { + tablePtr->flags |= ACTIVE_DISABLED; + } else { + TableMergeTag(tablePtr, tagPtr, activePtr); + activeCell = 1; + tablePtr->flags &= ~ACTIVE_DISABLED; + } + } + /* is this cell selected? */ + if (Tcl_FindHashEntry(tablePtr->selCells, buf) != NULL) { + if (tablePtr->invertSelected && !activeCell) { + shouldInvert = 1; + } else { + TableMergeTag(tablePtr, tagPtr, selPtr); + } + } + /* if flash mode is on, is this cell flashing? */ + if (tablePtr->flashMode && + Tcl_FindHashEntry(tablePtr->flashCells, buf) != NULL) { + TableMergeTag(tablePtr, tagPtr, flashPtr); + } + + if (shouldInvert) { + TableInvertTag(tagPtr); + } + + /* + * Borders for cell should now be properly set + */ + borders = TableGetTagBorders(tagPtr, &bd[0], &bd[1], + &bd[2], &bd[3]); + bd[4] = (bd[0] + bd[1])/2; + bd[5] = (bd[2] + bd[3])/2; + + /* + * First fill in a blank rectangle. + */ + Tk_Fill3DRectangle(tkwin, window, tagPtr->bg, + x, y, width, height, 0, TK_RELIEF_FLAT); + + /* + * Correct the dimensions to enforce padding constraints + */ + width -= bd[0] + bd[1] + (2 * padx); + height -= bd[2] + bd[3] + (2 * pady); + + /* + * Don't draw what won't be seen, based on border constraints. + */ + if ((width <= 0) || (height <= 0)) { + /* + * Re-Correct the dimensions before border drawing + */ + width += bd[0] + bd[1] + (2 * padx); + height += bd[2] + bd[3] + (2 * pady); + goto DrawBorder; + } + + /* + * If an image is in the tag, draw it + */ + if (tagPtr->image != NULL) { + Tk_SizeOfImage(tagPtr->image, &itemW, &itemH); + /* Handle anchoring of image in cell space */ + switch (tagPtr->anchor) { + case TK_ANCHOR_NW: + case TK_ANCHOR_W: + case TK_ANCHOR_SW: /* western position */ + originX = itemX = 0; + break; + case TK_ANCHOR_N: + case TK_ANCHOR_S: + case TK_ANCHOR_CENTER: /* centered position */ + itemX = MAX(0, (itemW - width) / 2); + originX = MAX(0, (width - itemW) / 2); + break; + default: /* eastern position */ + itemX = MAX(0, itemW - width); + originX = MAX(0, width - itemW); + } + switch (tagPtr->anchor) { + case TK_ANCHOR_N: + case TK_ANCHOR_NE: + case TK_ANCHOR_NW: /* northern position */ + originY = itemY = 0; + break; + case TK_ANCHOR_W: + case TK_ANCHOR_E: + case TK_ANCHOR_CENTER: /* centered position */ + itemY = MAX(0, (itemH - height) / 2); + originY = MAX(0, (height - itemH) / 2); + break; + default: /* southern position */ + itemY = MAX(0, itemH - height); + originY = MAX(0, height - itemH); + } + Tk_RedrawImage(tagPtr->image, itemX, itemY, + MIN(itemW, width-originX), MIN(itemH, height-originY), + window, x + originX + bd[0] + padx, + y + originY + bd[2] + pady); + /* + * If we don't want to display the text as well, then jump. + */ + if (tagPtr->showtext == 0) { + /* + * Re-Correct the dimensions before border drawing + */ + width += bd[0] + bd[1] + (2 * padx); + height += bd[2] + bd[3] + (2 * pady); + goto DrawBorder; + } + } + + /* + * Get the GC for this particular blend of tags. + * This creates the GC if it never existed, otherwise it + * modifies the one we have, so we only need the one + */ + TableGetGc(display, window, tagPtr, &tagGc); + + /* if this is the active cell, use the buffer */ + if (activeCell) { + string = tablePtr->activeBuf; + } else { + /* Is there a value in the cell? If so, draw it */ + string = TableGetCellValue(tablePtr, urow, ucol); + } + +#ifdef TCL_UTF_MAX + /* + * We have to use strlen here because otherwise it stops + * at the first \x00 unicode char it finds (!= '\0'), + * although there can be more to the string than that + */ + numBytes = Tcl_NumUtfChars(string, (int) strlen(string)); +#else + numBytes = strlen(string); +#endif + + /* If there is a string, show it */ + if (activeCell || numBytes) { + register int x0 = x + bd[0] + padx; + register int y0 = y + bd[2] + pady; + + /* get the dimensions of the string */ + textLayout = Tk_ComputeTextLayout(tagPtr->tkfont, + string, numBytes, + (tagPtr->wrap > 0) ? width : 0, tagPtr->justify, + (tagPtr->multiline > 0) ? 0 : TK_IGNORE_NEWLINES, + &itemW, &itemH); + + /* + * Set the origin coordinates of the string to draw using + * the anchor. origin represents the (x,y) coordinate of + * the lower left corner of the text box, relative to the + * internal (inside the border) window + */ + + /* set the X origin first */ + switch (tagPtr->anchor) { + case TK_ANCHOR_NW: + case TK_ANCHOR_W: + case TK_ANCHOR_SW: /* western position */ + originX = ipadx; + break; + case TK_ANCHOR_N: + case TK_ANCHOR_S: + case TK_ANCHOR_CENTER: /* centered position */ + originX = (width - itemW) / 2; + break; + default: /* eastern position */ + originX = width - itemW - ipadx; + } + + /* then set the Y origin */ + switch (tagPtr->anchor) { + case TK_ANCHOR_N: + case TK_ANCHOR_NE: + case TK_ANCHOR_NW: /* northern position */ + originY = ipady; + break; + case TK_ANCHOR_W: + case TK_ANCHOR_E: + case TK_ANCHOR_CENTER: /* centered position */ + originY = (height - itemH) / 2; + break; + default: /* southern position */ + originY = height - itemH - ipady; + } + + /* + * If this is the active cell and we are editing, + * ensure that the cursor will be displayed + */ + if (activeCell) { + Tk_CharBbox(textLayout, tablePtr->icursor, + &cx, &cy, &cw, &ch); + /* we have to fudge with maxW because of odd width + * determination for newlines at the end of a line */ + maxW = width - tablePtr->insertWidth + - (cx + MIN(tablePtr->charWidth, cw)); + maxH = height - (cy + ch); + if (originX < bd[0] - cx) { + /* cursor off cell to the left */ + /* use western positioning to cet cursor at left + * with slight variation to show some text */ + originX = bd[0] - cx + + MIN(cx, width - tablePtr->insertWidth); + } else if (originX > maxW) { + /* cursor off cell to the right */ + /* use eastern positioning to cet cursor at right */ + originX = maxW; + } + if (originY < bd[2] - cy) { + /* cursor before top of cell */ + /* use northern positioning to cet cursor at top */ + originY = bd[2] - cy; + } else if (originY > maxH) { + /* cursor beyond bottom of cell */ + /* use southern positioning to cet cursor at bottom */ + originY = maxH; + } + tablePtr->activeTagPtr = tagPtr; + tablePtr->activeX = originX; + tablePtr->activeY = originY; + } + + /* + * Use a clip rectangle only if necessary as it means + * updating the GC in the server which slows everything down. + * We can't fudge the width or height, just in case the user + * wanted empty pad space. + */ + if ((originX < 0) || (originY < 0) || + (originX+itemW > width) || (originY+itemH > height)) { + if (!activeCell + && (tagPtr->ellipsis != NULL) + && (tagPtr->wrap <= 0) + && (tagPtr->multiline <= 0) + ) { + /* + * Check which side to draw ellipsis on + */ + switch (tagPtr->anchor) { + case TK_ANCHOR_NE: + case TK_ANCHOR_E: + case TK_ANCHOR_SE: /* eastern position */ + ellEast = 0; + break; + default: /* western position */ + ellEast = 1; + } + if ((ellipsis != tagPtr->ellipsis) + || (ellFont != tagPtr->tkfont)) { + /* + * Different ellipsis from last cached + */ + ellFont = tagPtr->tkfont; + ellipsis = tagPtr->ellipsis; + ellLen = Tk_TextWidth(ellFont, + ellipsis, (int) strlen(ellipsis)); + Tk_GetFontMetrics(tagPtr->tkfont, &fm); + } + useEllLen = MIN(ellLen, width); + } else { + ellEast = 0; + useEllLen = 0; + } + + /* + * The text wants to overflow the boundaries of the + * displayed cell, so we must clip in some way + */ +#ifdef NO_XSETCLIP + /* + * This code is basically for the Macintosh. + * Copy the the current contents of the cell into the + * clipped window area. This keeps any fg/bg and image + * data intact. + * x0 - x == pad area + */ + XCopyArea(display, window, clipWind, tagGc, x0, y0, + width, height, x0 - x, y0 - y); + /* + * Now draw into the cell space on the special window. + * Don't use x,y base offset for clipWind. + */ + Tk_DrawTextLayout(display, clipWind, tagGc, textLayout, + x0 - x + originX, y0 - y + originY, 0, -1); + + if (useEllLen) { + /* + * Recopy area the ellipse covers (not efficient) + */ + XCopyArea(display, window, clipWind, tagGc, + x0 + (ellEast ? width - useEllLen : 0), y0, + useEllLen, height, + x0 - x + (ellEast ? width - useEllLen : 0), + y0 - y); + Tk_DrawChars(display, clipWind, tagGc, ellFont, + ellipsis, (int) strlen(ellipsis), + x0 - x + (ellEast ? width - useEllLen : 0), + y0 - y + originY + fm.ascent); + } + /* + * Now copy back only the area that we want the + * text to be drawn on. + */ + XCopyArea(display, clipWind, window, tagGc, + x0 - x, y0 - y, width, height, x0, y0); +#elif defined(WIN32) + /* + * This is evil, evil evil! but the XCopyArea + * doesn't work in all cases - Michael Teske. + * The general structure follows the comments below. + */ + twdPtr = (TkWinDrawable *) window; + dc = GetDC(twdPtr->window.handle); + + clipR = CreateRectRgn(x0 + (ellEast ? 0 : useEllLen), y0, + x0 + width - (ellEast ? useEllLen : 0), y0 + height); + + SelectClipRgn(dc, clipR); + DeleteObject(clipR); + /* OffsetClipRgn(dc, 0, 0); */ + + Tk_DrawTextLayout(display, window, tagGc, textLayout, + x0 + originX, y0 + originY, 0, -1); + + if (useEllLen) { + clipR = CreateRectRgn(x0, y0, x0 + width, y0 + height); + SelectClipRgn(dc, clipR); + DeleteObject(clipR); + Tk_DrawChars(display, window, tagGc, ellFont, + ellipsis, (int) strlen(ellipsis), + x0 + (ellEast? width-useEllLen : 0), + y0 + originY + fm.ascent); + } + SelectClipRgn(dc, NULL); + ReleaseDC(twdPtr->window.handle, dc); +#else + /* + * Use an X clipping rectangle. The clipping is the + * rectangle just for the actual text space (to allow + * for empty padding space). + */ + clipRect.x = x0 + (ellEast ? 0 : useEllLen); + clipRect.y = y0; + clipRect.width = width - (ellEast ? useEllLen : 0); + clipRect.height = height; + XSetClipRectangles(display, tagGc, 0, 0, &clipRect, 1, + Unsorted); + Tk_DrawTextLayout(display, window, tagGc, textLayout, + x0 + originX, + y0 + originY, 0, -1); + if (useEllLen) { + clipRect.x = x0; + clipRect.width = width; + XSetClipRectangles(display, tagGc, 0, 0, &clipRect, 1, + Unsorted); + Tk_DrawChars(display, window, tagGc, ellFont, + ellipsis, (int) strlen(ellipsis), + x0 + (ellEast? width-useEllLen : 0), + y0 + originY + fm.ascent); + } + XSetClipMask(display, tagGc, None); +#endif + } else { + Tk_DrawTextLayout(display, window, tagGc, textLayout, + x0 + originX, y0 + originY, 0, -1); + } + + /* if this is the active cell draw the cursor if it's on. + * this ignores clip rectangles. */ + if (activeCell && (tablePtr->flags & CURSOR_ON) && + (originY + cy + bd[2] + pady < height) && + (originX + cx + bd[0] + padx - + (tablePtr->insertWidth / 2) >= 0)) { + /* make sure it will fit in the box */ + maxW = MAX(0, originY + cy + bd[2] + pady); + maxH = MIN(ch, height - maxW + bd[2] + pady); + Tk_Fill3DRectangle(tkwin, window, tablePtr->insertBg, + x0 + originX + cx - (tablePtr->insertWidth/2), + y + maxW, tablePtr->insertWidth, + maxH, 0, TK_RELIEF_FLAT); + } + } + + /* + * Re-Correct the dimensions before border drawing + */ + width += bd[0] + bd[1] + (2 * padx); + height += bd[2] + bd[3] + (2 * pady); + + DrawBorder: + /* Draw the 3d border on the pixmap correctly offset */ + if (tablePtr->drawMode == DRAW_MODE_SINGLE) { + topGc = Tk_3DBorderGC(tkwin, tagPtr->bg, TK_3D_DARK_GC); + /* draw a line with single pixel width */ + rect[0].x = x; + rect[0].y = y + height - 1; + rect[1].y = -height + 1; + rect[2].x = width - 1; + XDrawLines(display, window, topGc, rect, 3, CoordModePrevious); + } else if (tablePtr->drawMode == DRAW_MODE_FAST) { + /* + * This depicts a full 1 pixel border. + * + * Choose the GCs to get the best approximation + * to the desired drawing style. + */ + switch(tagPtr->relief) { + case TK_RELIEF_FLAT: + topGc = bottomGc = Tk_3DBorderGC(tkwin, tagPtr->bg, + TK_3D_FLAT_GC); + break; + case TK_RELIEF_RAISED: + case TK_RELIEF_RIDGE: + topGc = Tk_3DBorderGC(tkwin, tagPtr->bg, + TK_3D_LIGHT_GC); + bottomGc = Tk_3DBorderGC(tkwin, tagPtr->bg, + TK_3D_DARK_GC); + break; + default: /* TK_RELIEF_SUNKEN TK_RELIEF_GROOVE */ + bottomGc = Tk_3DBorderGC(tkwin, tagPtr->bg, + TK_3D_LIGHT_GC); + topGc = Tk_3DBorderGC(tkwin, tagPtr->bg, + TK_3D_DARK_GC); + break; + } + + /* draw a line with single pixel width */ + rect[0].x = x + width - 1; + rect[0].y = y; + rect[1].y = height - 1; + rect[2].x = -width + 1; + XDrawLines(display, window, bottomGc, rect, 3, + CoordModePrevious); + rect[0].x = x; + rect[0].y = y + height - 1; + rect[1].y = -height + 1; + rect[2].x = width - 1; + XDrawLines(display, window, topGc, rect, 3, + CoordModePrevious); + } else { + if (borders > 1) { + if (bd[0]) { + Tk_3DVerticalBevel(tkwin, window, tagPtr->bg, + x, y, bd[0], height, + 1 /* left side */, tagPtr->relief); + } + if (bd[1]) { + Tk_3DVerticalBevel(tkwin, window, tagPtr->bg, + x + width - bd[1], y, bd[1], height, + 0 /* right side */, tagPtr->relief); + } + if ((borders == 4) && bd[2]) { + Tk_3DHorizontalBevel(tkwin, window, tagPtr->bg, + x, y, width, bd[2], + 1, 1, 1 /* top */, tagPtr->relief); + } + if ((borders == 4) && bd[3]) { + Tk_3DHorizontalBevel(tkwin, window, tagPtr->bg, + x, y + height - bd[3], width, bd[3], + 0, 0, 0 /* bottom */, tagPtr->relief); + } + } else if (borders == 1) { + Tk_Draw3DRectangle(tkwin, window, tagPtr->bg, x, y, + width, height, bd[0], tagPtr->relief); + } + } + + /* clean up the necessaries */ + if (tagPtr == tablePtr->activeTagPtr) { + /* + * This means it was the activeCell with text displayed. + * We buffer the active tag for the 'activate' command. + */ + tablePtr->activeTagPtr = TableNewTag(NULL); + memcpy((VOID *) tablePtr->activeTagPtr, + (VOID *) tagPtr, sizeof(TableTag)); + } + if (textLayout) { + Tk_FreeTextLayout(textLayout); + textLayout = NULL; + } + if (cellType == CELL_HIDDEN) { + /* the last cell was a hidden one, + * rework row stuff back to normal */ + row = hrow; col = hcol; + urow = row+tablePtr->rowOffset; + rowPtr = FindRowColTag(tablePtr, urow, ROW); + } + } + } + ckfree((char *) tagPtr); +#ifdef NO_XSETCLIP + Tk_FreePixmap(display, clipWind); +#endif + + /* Take care of removing embedded windows that are no longer in view */ + TableUndisplay(tablePtr); + +#ifndef WIN32 + /* copy over and delete the pixmap if we are in slow mode */ + if (tablePtr->drawMode == DRAW_MODE_SLOW) { + /* Get a default valued GC */ + TableGetGc(display, window, &(tablePtr->defaultTag), &tagGc); + XCopyArea(display, window, Tk_WindowId(tkwin), tagGc, 0, 0, + (unsigned) invalidWidth, (unsigned) invalidHeight, + invalidX, invalidY); + Tk_FreePixmap(display, window); + window = Tk_WindowId(tkwin); + } +#endif + + /* + * If we are at the end of the table, clear the area after the last + * row/col. We discount spans here because we just need the coords + * for the area that would be the last physical cell. + */ + tablePtr->flags |= AVOID_SPANS; + TableCellCoords(tablePtr, tablePtr->rows-1, tablePtr->cols-1, + &x, &y, &width, &height); + tablePtr->flags &= ~AVOID_SPANS; + + /* This should occur before moving pixmap, but this simplifies things + * + * Could use Tk_Fill3DRectangle instead of XFillRectangle + * for best compatibility, and XClearArea could be used on Unix + * for best speed, so this is the compromise w/o #ifdef's + */ + if (x+width < invalidX+invalidWidth) { + XFillRectangle(display, window, + Tk_3DBorderGC(tkwin, tablePtr->defaultTag.bg, TK_3D_FLAT_GC), + x+width, invalidY, (unsigned) invalidX+invalidWidth-x-width, + (unsigned) invalidHeight); + } + + if (y+height < invalidY+invalidHeight) { + XFillRectangle(display, window, + Tk_3DBorderGC(tkwin, tablePtr->defaultTag.bg, TK_3D_FLAT_GC), + invalidX, y+height, (unsigned) invalidWidth, + (unsigned) invalidY+invalidHeight-y-height); + } + + if (tagGc != NULL) { + TableFreeGc(display, tagGc); + } + TableRedrawHighlight(tablePtr); + /* + * Free the hash table used to cache evaluations. + */ + Tcl_DeleteHashTable(colTagsCache); + ckfree((char *) (colTagsCache)); + Tcl_DeleteHashTable(drawnCache); + ckfree((char *) (drawnCache)); +} + +/* + *---------------------------------------------------------------------- + * + * TableInvalidate -- + * Invalidates a rectangle and adds it to the total invalid rectangle + * waiting to be redrawn. If the INV_FORCE flag bit is set, + * it does an update instantly else waits until Tk is idle. + * + * Results: + * Will schedule table (re)display. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ +void +TableInvalidate(Table * tablePtr, int x, int y, + int w, int h, int flags) +{ + Tk_Window tkwin = tablePtr->tkwin; + int hl = tablePtr->highlightWidth; + int height = Tk_Height(tkwin); + int width = Tk_Width(tkwin); + + /* + * Make sure that the window hasn't been destroyed already. + * Avoid allocating 0 sized pixmaps which would be fatal, + * and check if rectangle is even on the screen. + */ + if ((tkwin == NULL) + || (w <= 0) || (h <= 0) || (x > width) || (y > height)) { + return; + } + + /* If not even mapped, wait for the remap to redraw all */ + if (!Tk_IsMapped(tkwin)) { + tablePtr->flags |= REDRAW_ON_MAP; + return; + } + + /* + * If no pending updates exist, then replace the rectangle. + * Otherwise find the bounding rectangle. + */ + if ((flags & INV_HIGHLIGHT) && + (x < hl || y < hl || x+w >= width-hl || y+h >= height-hl)) { + tablePtr->flags |= REDRAW_BORDER; + } + + if (tablePtr->flags & REDRAW_PENDING) { + tablePtr->invalidWidth = MAX(x + w, + tablePtr->invalidX+tablePtr->invalidWidth); + tablePtr->invalidHeight = MAX(y + h, + tablePtr->invalidY+tablePtr->invalidHeight); + if (tablePtr->invalidX > x) tablePtr->invalidX = x; + if (tablePtr->invalidY > y) tablePtr->invalidY = y; + tablePtr->invalidWidth -= tablePtr->invalidX; + tablePtr->invalidHeight -= tablePtr->invalidY; + /* Do we want to force this update out? */ + if (flags & INV_FORCE) { + Tcl_CancelIdleCall(TableDisplay, (ClientData) tablePtr); + TableDisplay((ClientData) tablePtr); + } + } else { + tablePtr->invalidX = x; + tablePtr->invalidY = y; + tablePtr->invalidWidth = w; + tablePtr->invalidHeight = h; + if (flags & INV_FORCE) { + TableDisplay((ClientData) tablePtr); + } else { + tablePtr->flags |= REDRAW_PENDING; + Tcl_DoWhenIdle(TableDisplay, (ClientData) tablePtr); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TableFlashEvent -- + * Called when the flash timer goes off. + * + * Results: + * Decrements all the entries in the hash table and invalidates + * any cells that expire, deleting them from the table. If the + * table is now empty, stops the timer, else reenables it. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +static void +TableFlashEvent(ClientData clientdata) +{ + Table *tablePtr = (Table *) clientdata; + Tcl_HashEntry *entryPtr; + Tcl_HashSearch search; + int entries, count, row, col; + + entries = 0; + for (entryPtr = Tcl_FirstHashEntry(tablePtr->flashCells, &search); + entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) { + count = (int) Tcl_GetHashValue(entryPtr); + if (--count <= 0) { + /* get the cell address and invalidate that region only */ + TableParseArrayIndex(&row, &col, + Tcl_GetHashKey(tablePtr->flashCells, entryPtr)); + + /* delete the entry from the table */ + Tcl_DeleteHashEntry(entryPtr); + + TableRefresh(tablePtr, row-tablePtr->rowOffset, + col-tablePtr->colOffset, CELL); + } else { + Tcl_SetHashValue(entryPtr, (ClientData) count); + entries++; + } + } + + /* do I need to restart the timer */ + if (entries && tablePtr->flashMode) { + tablePtr->flashTimer = Tcl_CreateTimerHandler(250, TableFlashEvent, + (ClientData) tablePtr); + } else { + tablePtr->flashTimer = 0; + } +} + +/* + *---------------------------------------------------------------------- + * + * TableAddFlash -- + * Adds a flash on cell row,col (real coords) with the default timeout + * if flashing is enabled and flashtime > 0. + * + * Results: + * Cell will flash. + * + * Side effects: + * Will start flash timer if it didn't exist. + * + *---------------------------------------------------------------------- + */ +void +TableAddFlash(Table *tablePtr, int row, int col) +{ + char buf[INDEX_BUFSIZE]; + int dummy; + Tcl_HashEntry *entryPtr; + + if (!tablePtr->flashMode || tablePtr->flashTime < 1) { + return; + } + + /* create the array index in user coords */ + TableMakeArrayIndex(row+tablePtr->rowOffset, col+tablePtr->colOffset, buf); + + /* add the flash to the hash table */ + entryPtr = Tcl_CreateHashEntry(tablePtr->flashCells, buf, &dummy); + Tcl_SetHashValue(entryPtr, tablePtr->flashTime); + + /* now set the timer if it's not already going and invalidate the area */ + if (tablePtr->flashTimer == NULL) { + tablePtr->flashTimer = Tcl_CreateTimerHandler(250, TableFlashEvent, + (ClientData) tablePtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * TableSetActiveIndex -- + * Sets the "active" index of the associated array to the current + * value of the active buffer. + * + * Results: + * None. + * + * Side effects: + * Traces on the array can cause side effects. + * + *---------------------------------------------------------------------- + */ +void +TableSetActiveIndex(register Table *tablePtr) +{ + if (tablePtr->arrayVar) { + tablePtr->flags |= SET_ACTIVE; + Tcl_SetVar2(tablePtr->interp, tablePtr->arrayVar, "active", + tablePtr->activeBuf, TCL_GLOBAL_ONLY); + tablePtr->flags &= ~SET_ACTIVE; + } +} + +/* + *---------------------------------------------------------------------- + * + * TableGetActiveBuf -- + * Get the current selection into the buffer and mark it as unedited. + * Set the position to the end of the string. + * + * Results: + * None. + * + * Side effects: + * tablePtr->activeBuf will change. + * + *---------------------------------------------------------------------- + */ +void +TableGetActiveBuf(register Table *tablePtr) +{ + char *data = ""; + + if (tablePtr->flags & HAS_ACTIVE) { + data = TableGetCellValue(tablePtr, + tablePtr->activeRow+tablePtr->rowOffset, + tablePtr->activeCol+tablePtr->colOffset); + } + + if (STREQ(tablePtr->activeBuf, data)) { + /* this forced SetActiveIndex is necessary if we change array vars and + * they happen to have these cells equal, we won't properly set the + * active index for the new array var unless we do this here */ + TableSetActiveIndex(tablePtr); + return; + } + /* is the buffer long enough */ + tablePtr->activeBuf = (char *)ckrealloc(tablePtr->activeBuf, + strlen(data)+1); + strcpy(tablePtr->activeBuf, data); + TableGetIcursor(tablePtr, "end", (int *)0); + tablePtr->flags &= ~TEXT_CHANGED; + TableSetActiveIndex(tablePtr); +} + +/* + *---------------------------------------------------------------------- + * + * TableVarProc -- + * This is the trace procedure associated with the Tcl array. No + * validation will occur here because this only triggers when the + * array value is directly set, and we can't maintain the old value. + * + * Results: + * Invalidates changed cell. + * + * Side effects: + * Creates/Updates entry in the cache if we are caching. + * + *---------------------------------------------------------------------- + */ +static char * +TableVarProc(clientData, interp, name, index, flags) + ClientData clientData; /* Information about table. */ + Tcl_Interp *interp; /* Interpreter containing variable. */ + char *name; /* Not used. */ + char *index; /* Not used. */ + int flags; /* Information about what happened. */ +{ + Table *tablePtr = (Table *) clientData; + int row, col, update = 1; + + /* This is redundant, as the name should always == arrayVar */ + name = tablePtr->arrayVar; + + /* is this the whole var being destroyed or just one cell being deleted */ + if ((flags & TCL_TRACE_UNSETS) && index == NULL) { + /* if this isn't the interpreter being destroyed reinstate the trace */ + if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + Tcl_SetVar2(interp, name, TEST_KEY, "", TCL_GLOBAL_ONLY); + Tcl_UnsetVar2(interp, name, TEST_KEY, TCL_GLOBAL_ONLY); + Tcl_ResetResult(interp); + + /* set a trace on the variable */ + Tcl_TraceVar(interp, name, + TCL_TRACE_WRITES | TCL_TRACE_UNSETS | TCL_GLOBAL_ONLY, + (Tcl_VarTraceProc *)TableVarProc, (ClientData) tablePtr); + + /* only do the following if arrayVar is our data source */ + if (tablePtr->dataSource & DATA_ARRAY) { + /* clear the selection buffer */ + TableGetActiveBuf(tablePtr); + /* flush any cache */ + Table_ClearHashTable(tablePtr->cache); + Tcl_InitHashTable(tablePtr->cache, TCL_STRING_KEYS); + /* and invalidate the table */ + TableInvalidateAll(tablePtr, 0); + } + } + return (char *)NULL; + } + /* only continue if arrayVar is our data source */ + if (!(tablePtr->dataSource & DATA_ARRAY)) { + return (char *)NULL; + } + /* get the cell address and invalidate that region only. + * Make sure that it is a valid cell address. */ + if (STREQ("active", index)) { + if (tablePtr->flags & SET_ACTIVE) { + /* If we are already setting the active cell, the update + * will occur in other code */ + update = 0; + } else { + /* modified TableGetActiveBuf */ + CONST char *data = ""; + + row = tablePtr->activeRow; + col = tablePtr->activeCol; + if (tablePtr->flags & HAS_ACTIVE) + data = Tcl_GetVar2(interp, name, index, TCL_GLOBAL_ONLY); + if (!data) data = ""; + + if (STREQ(tablePtr->activeBuf, data)) { + return (char *)NULL; + } + tablePtr->activeBuf = (char *)ckrealloc(tablePtr->activeBuf, + strlen(data)+1); + strcpy(tablePtr->activeBuf, data); + /* set cursor to the last char */ + TableGetIcursor(tablePtr, "end", (int *)0); + tablePtr->flags |= TEXT_CHANGED; + } + } else if (TableParseArrayIndex(&row, &col, index) == 2) { + char buf[INDEX_BUFSIZE]; + + /* Make sure it won't trigger on array(2,3extrastuff) */ + TableMakeArrayIndex(row, col, buf); + if (strcmp(buf, index)) { + return (char *)NULL; + } + if (tablePtr->caching) { + Tcl_HashEntry *entryPtr; + int new; + char *val, *data; + + entryPtr = Tcl_CreateHashEntry(tablePtr->cache, buf, &new); + if (!new) { + data = (char *) Tcl_GetHashValue(entryPtr); + if (data) { ckfree(data); } + } + data = (char *) Tcl_GetVar2(interp, name, index, TCL_GLOBAL_ONLY); + if (data && *data != '\0') { + val = (char *)ckalloc(strlen(data)+1); + strcpy(val, data); + } else { + val = NULL; + } + Tcl_SetHashValue(entryPtr, val); + } + /* convert index to real coords */ + row -= tablePtr->rowOffset; + col -= tablePtr->colOffset; + /* did the active cell just update */ + if (row == tablePtr->activeRow && col == tablePtr->activeCol) { + TableGetActiveBuf(tablePtr); + } + /* Flash the cell */ + TableAddFlash(tablePtr, row, col); + } else { + return (char *)NULL; + } + + if (update) { + TableRefresh(tablePtr, row, col, CELL); + } + + return (char *)NULL; +} + +/* + *---------------------------------------------------------------------- + * + * TableGeometryRequest -- + * This procedure is invoked to request a new geometry from Tk. + * + * Results: + * None. + * + * Side effects: + * Geometry information is updated and a new requested size is + * registered for the widget. Internal border info is also set. + * + *---------------------------------------------------------------------- + */ +void +TableGeometryRequest(tablePtr) + register Table *tablePtr; +{ + int x, y; + + /* Do the geometry request + * If -width #cols was not specified or it is greater than the real + * number of cols, use maxWidth as a lower bound, with the other lower + * bound being the upper bound of the window's user-set width and the + * value of -maxwidth set by the programmer + * Vice versa for rows/height + */ + x = MIN((tablePtr->maxReqCols==0 || tablePtr->maxReqCols > tablePtr->cols)? + tablePtr->maxWidth : tablePtr->colStarts[tablePtr->maxReqCols], + tablePtr->maxReqWidth) + 2*tablePtr->highlightWidth; + y = MIN((tablePtr->maxReqRows==0 || tablePtr->maxReqRows > tablePtr->rows)? + tablePtr->maxHeight : tablePtr->rowStarts[tablePtr->maxReqRows], + tablePtr->maxReqHeight) + 2*tablePtr->highlightWidth; + Tk_GeometryRequest(tablePtr->tkwin, x, y); +} + +/* + *---------------------------------------------------------------------- + * + * TableAdjustActive -- + * This procedure is called by AdjustParams and CMD_ACTIVATE to + * move the active cell. + * + * Results: + * Old and new active cell indices will be invalidated. + * + * Side effects: + * If the old active cell index was edited, it will be saved. + * The active buffer will be updated. + * + *---------------------------------------------------------------------- + */ +void +TableAdjustActive(tablePtr) + register Table *tablePtr; /* Widget record for table */ +{ + if (tablePtr->flags & HAS_ACTIVE) { + /* + * Make sure the active cell has a reasonable real index + */ + CONSTRAIN(tablePtr->activeRow, 0, tablePtr->rows-1); + CONSTRAIN(tablePtr->activeCol, 0, tablePtr->cols-1); + } + + /* + * Check the new value of active cell against the original, + * Only invalidate if it changed. + */ + if (tablePtr->oldActRow == tablePtr->activeRow && + tablePtr->oldActCol == tablePtr->activeCol) { + return; + } + + if (tablePtr->oldActRow >= 0 && tablePtr->oldActCol >= 0) { + /* + * Set the value of the old active cell to the active buffer + * SetCellValue will check if the value actually changed + */ + if (tablePtr->flags & TEXT_CHANGED) { + /* WARNING an outside trace will be triggered here and if it + * calls something that causes TableAdjustParams to be called + * again, we are in data consistency trouble */ + /* HACK - turn TEXT_CHANGED off now to possibly avoid the + * above data inconsistency problem. */ + tablePtr->flags &= ~TEXT_CHANGED; + TableSetCellValue(tablePtr, + tablePtr->oldActRow + tablePtr->rowOffset, + tablePtr->oldActCol + tablePtr->colOffset, + tablePtr->activeBuf); + } + /* + * Invalidate the old active cell + */ + TableRefresh(tablePtr, tablePtr->oldActRow, tablePtr->oldActCol, CELL); + } + + /* + * Store the new active cell value into the active buffer + */ + TableGetActiveBuf(tablePtr); + + /* + * Invalidate the new active cell + */ + TableRefresh(tablePtr, tablePtr->activeRow, tablePtr->activeCol, CELL); + + /* + * Cache the old active row/col for the next time this is called + */ + tablePtr->oldActRow = tablePtr->activeRow; + tablePtr->oldActCol = tablePtr->activeCol; +} + +/* + *---------------------------------------------------------------------- + * + * TableAdjustParams -- + * Calculate the row and column starts. Adjusts the topleft corner + * variable to keep it within the screen range, out of the titles + * and keep the screen full make sure the selected cell is in the + * visible area checks to see if the top left cell has changed at + * all and invalidates the table if it has. + * + * Results: + * None. + * + * Side Effects: + * Number of rows can change if -rowstretchmode == fill. + * topRow && leftCol can change to fit display. + * activeRow/Col can change to ensure it is a valid cell. + * + *---------------------------------------------------------------------- + */ +void +TableAdjustParams(register Table *tablePtr) +{ + int topRow, leftCol, row, col, total, i, value, x, y, width, height, + w, h, hl, px, py, recalc, bd[4], + diff, unpreset, lastUnpreset, pad, lastPad, numPixels, + defColWidth, defRowHeight; + Tcl_HashEntry *entryPtr; + + /* + * Cache some values for many upcoming calculations + */ + hl = tablePtr->highlightWidth; + w = Tk_Width(tablePtr->tkwin) - (2 * hl); + h = Tk_Height(tablePtr->tkwin) - (2 * hl); + TableGetTagBorders(&(tablePtr->defaultTag), + &bd[0], &bd[1], &bd[2], &bd[3]); + px = bd[0] + bd[1] + (2 * tablePtr->padX); + py = bd[2] + bd[3] + (2 * tablePtr->padY); + + /* + * Account for whether default dimensions are in chars (>0) or + * pixels (<=0). Border and Pad space is added in here for convenience. + * + * When a value in pixels is specified, we take that exact amount, + * not adding in padding. + */ + if (tablePtr->defColWidth > 0) { + defColWidth = tablePtr->charWidth * tablePtr->defColWidth + px; + } else { + defColWidth = -(tablePtr->defColWidth); + } + if (tablePtr->defRowHeight > 0) { + defRowHeight = tablePtr->charHeight * tablePtr->defRowHeight + py; + } else { + defRowHeight = -(tablePtr->defRowHeight); + } + + /* + * Set up the arrays to hold the col pixels and starts. + * ckrealloc was fixed in 8.2.1 to handle NULLs, so we can't rely on it. + */ + if (tablePtr->colPixels) ckfree((char *) tablePtr->colPixels); + tablePtr->colPixels = (int *) ckalloc(tablePtr->cols * sizeof(int)); + if (tablePtr->colStarts) ckfree((char *) tablePtr->colStarts); + tablePtr->colStarts = (int *) ckalloc((tablePtr->cols+1) * sizeof(int)); + + /* + * Get all the preset columns and set their widths + */ + lastUnpreset = 0; + numPixels = 0; + unpreset = 0; + for (i = 0; i < tablePtr->cols; i++) { + entryPtr = Tcl_FindHashEntry(tablePtr->colWidths, (char *) i); + if (entryPtr == NULL) { + tablePtr->colPixels[i] = -1; + unpreset++; + lastUnpreset = i; + } else { + value = (int) Tcl_GetHashValue(entryPtr); + if (value > 0) { + tablePtr->colPixels[i] = value * tablePtr->charWidth + px; + } else { + /* + * When a value in pixels is specified, we take that exact + * amount, not adding in pad or border values. + */ + tablePtr->colPixels[i] = -value; + } + numPixels += tablePtr->colPixels[i]; + } + } + + /* + * Work out how much to pad each col depending on the mode. + */ + diff = w - numPixels - (unpreset * defColWidth); + total = 0; + + /* + * Now do the padding and calculate the column starts. + * Diff lower than 0 means we can't see the entire set of columns, + * thus no special stretching will occur & we optimize the calculation. + */ + if (diff <= 0) { + for (i = 0; i < tablePtr->cols; i++) { + if (tablePtr->colPixels[i] == -1) { + tablePtr->colPixels[i] = defColWidth; + } + tablePtr->colStarts[i] = total; + total += tablePtr->colPixels[i]; + } + } else { + switch (tablePtr->colStretch) { + case STRETCH_MODE_NONE: + pad = 0; + lastPad = 0; + break; + case STRETCH_MODE_UNSET: + if (unpreset == 0) { + pad = 0; + lastPad = 0; + } else { + pad = diff / unpreset; + lastPad = diff - pad * (unpreset - 1); + } + break; + case STRETCH_MODE_LAST: + pad = 0; + lastPad = diff; + lastUnpreset = tablePtr->cols - 1; + break; + default: /* STRETCH_MODE_ALL, but also FILL for cols */ + pad = diff / tablePtr->cols; + /* force it to be applied to the last column too */ + lastUnpreset = tablePtr->cols - 1; + lastPad = diff - pad * lastUnpreset; + } + + for (i = 0; i < tablePtr->cols; i++) { + if (tablePtr->colPixels[i] == -1) { + tablePtr->colPixels[i] = defColWidth + + ((i == lastUnpreset) ? lastPad : pad); + } else if (tablePtr->colStretch == STRETCH_MODE_ALL) { + tablePtr->colPixels[i] += (i == lastUnpreset) ? lastPad : pad; + } + tablePtr->colStarts[i] = total; + total += tablePtr->colPixels[i]; + } + } + tablePtr->colStarts[i] = tablePtr->maxWidth = total; + + /* + * The 'do' loop is only necessary for rows because of FILL mode + */ + recalc = 0; + do { + /* Set up the arrays to hold the row pixels and starts */ + /* FIX - this can be moved outside 'do' if you check >row size */ + if (tablePtr->rowPixels) ckfree((char *) tablePtr->rowPixels); + tablePtr->rowPixels = (int *) ckalloc(tablePtr->rows * sizeof(int)); + + /* get all the preset rows and set their heights */ + lastUnpreset = 0; + numPixels = 0; + unpreset = 0; + for (i = 0; i < tablePtr->rows; i++) { + entryPtr = Tcl_FindHashEntry(tablePtr->rowHeights, (char *) i); + if (entryPtr == NULL) { + tablePtr->rowPixels[i] = -1; + unpreset++; + lastUnpreset = i; + } else { + value = (int) Tcl_GetHashValue(entryPtr); + if (value > 0) { + tablePtr->rowPixels[i] = value * tablePtr->charHeight + py; + } else { + /* + * When a value in pixels is specified, we take that exact + * amount, not adding in pad or border values. + */ + tablePtr->rowPixels[i] = -value; + } + numPixels += tablePtr->rowPixels[i]; + } + } + + /* work out how much to pad each row depending on the mode */ + diff = h - numPixels - (unpreset * defRowHeight); + switch(tablePtr->rowStretch) { + case STRETCH_MODE_NONE: + pad = 0; + lastPad = 0; + break; + case STRETCH_MODE_UNSET: + if (unpreset == 0) { + pad = 0; + lastPad = 0; + } else { + pad = MAX(0,diff) / unpreset; + lastPad = MAX(0,diff) - pad * (unpreset - 1); + } + break; + case STRETCH_MODE_LAST: + pad = 0; + lastPad = MAX(0,diff); + /* force it to be applied to the last column too */ + lastUnpreset = tablePtr->rows - 1; + break; + case STRETCH_MODE_FILL: + pad = 0; + lastPad = diff; + if (diff && !recalc) { + tablePtr->rows += (diff/defRowHeight); + if (diff < 0 && tablePtr->rows <= 0) { + tablePtr->rows = 1; + } + lastUnpreset = tablePtr->rows - 1; + recalc = 1; + continue; + } else { + lastUnpreset = tablePtr->rows - 1; + recalc = 0; + } + break; + default: /* STRETCH_MODE_ALL */ + pad = MAX(0,diff) / tablePtr->rows; + /* force it to be applied to the last column too */ + lastUnpreset = tablePtr->rows - 1; + lastPad = MAX(0,diff) - pad * lastUnpreset; + } + } while (recalc); + + if (tablePtr->rowStarts) ckfree((char *) tablePtr->rowStarts); + tablePtr->rowStarts = (int *) ckalloc((tablePtr->rows+1)*sizeof(int)); + /* + * Now do the padding and calculate the row starts + */ + total = 0; + for (i = 0; i < tablePtr->rows; i++) { + if (tablePtr->rowPixels[i] == -1) { + tablePtr->rowPixels[i] = defRowHeight + + ((i==lastUnpreset)?lastPad:pad); + } else if (tablePtr->rowStretch == STRETCH_MODE_ALL) { + tablePtr->rowPixels[i] += (i==lastUnpreset)?lastPad:pad; + } + /* calculate the start of each row */ + tablePtr->rowStarts[i] = total; + total += tablePtr->rowPixels[i]; + } + tablePtr->rowStarts[i] = tablePtr->maxHeight = total; + + /* + * Make sure the top row and col have reasonable real indices + */ + CONSTRAIN(tablePtr->topRow, tablePtr->titleRows, tablePtr->rows-1); + CONSTRAIN(tablePtr->leftCol, tablePtr->titleCols, tablePtr->cols-1); + + /* + * If we don't have the info, don't bother to fix up the other parameters + */ + if (Tk_WindowId(tablePtr->tkwin) == None) { + tablePtr->oldTopRow = tablePtr->oldLeftCol = -1; + return; + } + + topRow = tablePtr->topRow; + leftCol = tablePtr->leftCol; + w += hl; + h += hl; + /* + * If we use this value of topRow, will we fill the window? + * if not, decrease it until we will, or until it gets to titleRows + * make sure we don't cut off the bottom row + */ + for (; topRow > tablePtr->titleRows; topRow--) { + if ((tablePtr->maxHeight-(tablePtr->rowStarts[topRow-1] - + tablePtr->rowStarts[tablePtr->titleRows])) > h) { + break; + } + } + /* + * If we use this value of topCol, will we fill the window? + * if not, decrease it until we will, or until it gets to titleCols + * make sure we don't cut off the left column + */ + for (; leftCol > tablePtr->titleCols; leftCol--) { + if ((tablePtr->maxWidth-(tablePtr->colStarts[leftCol-1] - + tablePtr->colStarts[tablePtr->titleCols])) > w) { + break; + } + } + + tablePtr->topRow = topRow; + tablePtr->leftCol = leftCol; + + /* + * Now work out where the bottom right is for scrollbar update and to test + * for one last stretch. Avoid the confusion that spans could cause for + * determining the last cell dimensions. + */ + tablePtr->flags |= AVOID_SPANS; + TableGetLastCell(tablePtr, &row, &col); + TableCellVCoords(tablePtr, row, col, &x, &y, &width, &height, 0); + tablePtr->flags &= ~AVOID_SPANS; + + /* + * Do we have scrollbars, if so, calculate and call the TCL functions In + * order to get the scrollbar to be completely full when the whole screen + * is shown and there are titles, we have to arrange for the scrollbar + * range to be 0 -> rows-titleRows etc. This leads to the position + * setting methods, toprow and leftcol, being relative to the titles, not + * absolute row and column numbers. + */ + if (tablePtr->yScrollCmd != NULL || tablePtr->xScrollCmd != NULL) { + Tcl_Interp *interp = tablePtr->interp; + char buf[INDEX_BUFSIZE]; + double first, last; + + /* + * We must hold onto the interpreter because the data referred to at + * tablePtr might be freed as a result of the call to Tcl_VarEval. + */ + Tcl_Preserve((ClientData) interp); + + /* Do we have a Y-scrollbar and rows to scroll? */ + if (tablePtr->yScrollCmd != NULL) { + if (row < tablePtr->titleRows) { + first = 0; + last = 1; + } else { + diff = tablePtr->rowStarts[tablePtr->titleRows]; + last = (double) (tablePtr->rowStarts[tablePtr->rows]-diff); + if (last <= 0.0) { + first = 0; + last = 1; + } else { + first = (tablePtr->rowStarts[topRow]-diff) / last; + last = (height+tablePtr->rowStarts[row]-diff) / last; + } + } + sprintf(buf, " %g %g", first, last); + if (Tcl_VarEval(interp, tablePtr->yScrollCmd, + buf, (char *)NULL) != TCL_OK) { + Tcl_AddErrorInfo(interp, + "\n\t(vertical scrolling command executed by table)"); + Tcl_BackgroundError(interp); + } + } + /* Do we have a X-scrollbar and cols to scroll? */ + if (tablePtr->xScrollCmd != NULL) { + if (col < tablePtr->titleCols) { + first = 0; + last = 1; + } else { + diff = tablePtr->colStarts[tablePtr->titleCols]; + last = (double) (tablePtr->colStarts[tablePtr->cols]-diff); + if (last <= 0.0) { + first = 0; + last = 1; + } else { + first = (tablePtr->colStarts[leftCol]-diff) / last; + last = (width+tablePtr->colStarts[col]-diff) / last; + } + } + sprintf(buf, " %g %g", first, last); + if (Tcl_VarEval(interp, tablePtr->xScrollCmd, + buf, (char *)NULL) != TCL_OK) { + Tcl_AddErrorInfo(interp, + "\n\t(horizontal scrolling command executed by table)"); + Tcl_BackgroundError(interp); + } + } + + Tcl_Release((ClientData) interp); + } + + /* + * Adjust the last row/col to fill empty space if it is visible. + * Do this after setting the scrollbars to not upset its calculations. + */ + if (row == tablePtr->rows-1 && tablePtr->rowStretch != STRETCH_MODE_NONE) { + diff = h-(y+height); + if (diff > 0) { + tablePtr->rowPixels[tablePtr->rows-1] += diff; + tablePtr->rowStarts[tablePtr->rows] += diff; + } + } + if (col == tablePtr->cols-1 && tablePtr->colStretch != STRETCH_MODE_NONE) { + diff = w-(x+width); + if (diff > 0) { + tablePtr->colPixels[tablePtr->cols-1] += diff; + tablePtr->colStarts[tablePtr->cols] += diff; + } + } + + TableAdjustActive(tablePtr); + + /* + * now check the new value of topleft cell against the originals, + * If they changed, invalidate the area, else leave it alone + */ + if (tablePtr->topRow != tablePtr->oldTopRow || + tablePtr->leftCol != tablePtr->oldLeftCol) { + /* set the old top row/col for the next time this function is called */ + tablePtr->oldTopRow = tablePtr->topRow; + tablePtr->oldLeftCol = tablePtr->leftCol; + /* only the upper corner title cells wouldn't change */ + TableInvalidateAll(tablePtr, 0); + } +} + +/* + *---------------------------------------------------------------------- + * + * TableCursorEvent -- + * Toggle the cursor status. Equivalent to EntryBlinkProc. + * + * Results: + * None. + * + * Side effects: + * The cursor will be switched off/on. + * + *---------------------------------------------------------------------- + */ +static void +TableCursorEvent(ClientData clientData) +{ + register Table *tablePtr = (Table *) clientData; + + if (!(tablePtr->flags & HAS_FOCUS) || (tablePtr->insertOffTime == 0) + || (tablePtr->flags & ACTIVE_DISABLED) + || (tablePtr->state != STATE_NORMAL)) { + return; + } + + if (tablePtr->cursorTimer != NULL) { + Tcl_DeleteTimerHandler(tablePtr->cursorTimer); + } + + tablePtr->cursorTimer = + Tcl_CreateTimerHandler((tablePtr->flags & CURSOR_ON) ? + tablePtr->insertOffTime : tablePtr->insertOnTime, + TableCursorEvent, (ClientData) tablePtr); + + /* Toggle the cursor */ + tablePtr->flags ^= CURSOR_ON; + + /* invalidate the cell */ + TableRefresh(tablePtr, tablePtr->activeRow, tablePtr->activeCol, CELL); +} + +/* + *---------------------------------------------------------------------- + * + * TableConfigCursor -- + * Configures the timer depending on the state of the table. + * Equivalent to EntryFocusProc. + * + * Results: + * None. + * + * Side effects: + * The cursor will be switched off/on. + * + *---------------------------------------------------------------------- + */ +void +TableConfigCursor(register Table *tablePtr) +{ + /* + * To have a cursor, we have to have focus and allow edits + */ + if ((tablePtr->flags & HAS_FOCUS) && (tablePtr->state == STATE_NORMAL) && + !(tablePtr->flags & ACTIVE_DISABLED)) { + /* + * Turn the cursor ON + */ + if (!(tablePtr->flags & CURSOR_ON)) { + tablePtr->flags |= CURSOR_ON; + /* + * Only refresh when we toggled cursor + */ + TableRefresh(tablePtr, tablePtr->activeRow, tablePtr->activeCol, + CELL); + } + + /* set up the first timer */ + if (tablePtr->insertOffTime != 0) { + /* make sure nothing existed */ + Tcl_DeleteTimerHandler(tablePtr->cursorTimer); + tablePtr->cursorTimer = + Tcl_CreateTimerHandler(tablePtr->insertOnTime, + TableCursorEvent, (ClientData) tablePtr); + } + } else { + /* + * Turn the cursor OFF + */ + if ((tablePtr->flags & CURSOR_ON)) { + tablePtr->flags &= ~CURSOR_ON; + TableRefresh(tablePtr, tablePtr->activeRow, tablePtr->activeCol, + CELL); + } + + /* and disable the timer */ + if (tablePtr->cursorTimer != NULL) { + Tcl_DeleteTimerHandler(tablePtr->cursorTimer); + } + tablePtr->cursorTimer = NULL; + } + +} + +/* + *---------------------------------------------------------------------- + * + * TableFetchSelection -- + * This procedure is called back by Tk when the selection is + * requested by someone. It returns part or all of the selection + * in a buffer provided by the caller. + * + * Results: + * The return value is the number of non-NULL bytes stored + * at buffer. Buffer is filled (or partially filled) with a + * NULL-terminated string containing part or all of the selection, + * as given by offset and maxBytes. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +static int +TableFetchSelection(clientData, offset, buffer, maxBytes) + ClientData clientData; /* Information about table widget. */ + int offset; /* Offset within selection of first + * character to be returned. */ + char *buffer; /* Location in which to place selection. */ + int maxBytes; /* Maximum number of bytes to place at buffer, + * not including terminating NULL. */ +{ + register Table *tablePtr = (Table *) clientData; + Tcl_Interp *interp = tablePtr->interp; + char *value, *data, *rowsep = tablePtr->rowSep, *colsep = tablePtr->colSep; + Tcl_DString selection; + Tcl_HashEntry *entryPtr; + Tcl_HashSearch search; + int length, count, lastrow=0, needcs=0, r, c, listArgc, rslen=0, cslen=0; + int numcols, numrows; + CONST84 char **listArgv; + + /* if we are not exporting the selection || + * we have no data source, return */ + if (!tablePtr->exportSelection || + (tablePtr->dataSource == DATA_NONE)) { + return -1; + } + + /* First get a sorted list of the selected elements */ + Tcl_DStringInit(&selection); + for (entryPtr = Tcl_FirstHashEntry(tablePtr->selCells, &search); + entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) { + Tcl_DStringAppendElement(&selection, + Tcl_GetHashKey(tablePtr->selCells, entryPtr)); + } + value = TableCellSort(tablePtr, Tcl_DStringValue(&selection)); + Tcl_DStringFree(&selection); + + if (value == NULL || + Tcl_SplitList(interp, value, &listArgc, &listArgv) != TCL_OK) { + return -1; + } + Tcl_Free(value); + + Tcl_DStringInit(&selection); + rslen = (rowsep?(strlen(rowsep)):0); + cslen = (colsep?(strlen(colsep)):0); + numrows = numcols = 0; + for (count = 0; count < listArgc; count++) { + TableParseArrayIndex(&r, &c, listArgv[count]); + if (count) { + if (lastrow != r) { + lastrow = r; + needcs = 0; + if (rslen) { + Tcl_DStringAppend(&selection, rowsep, rslen); + } else { + Tcl_DStringEndSublist(&selection); + Tcl_DStringStartSublist(&selection); + } + ++numrows; + } else { + if (++needcs > numcols) + numcols = needcs; + } + } else { + lastrow = r; + needcs = 0; + if (!rslen) { + Tcl_DStringStartSublist(&selection); + } + } + data = TableGetCellValue(tablePtr, r, c); + if (cslen) { + if (needcs) { + Tcl_DStringAppend(&selection, colsep, cslen); + } + Tcl_DStringAppend(&selection, data, -1); + } else { + Tcl_DStringAppendElement(&selection, data); + } + } + if (!rslen && count) { + Tcl_DStringEndSublist(&selection); + } + Tcl_Free((char *) listArgv); + + if (tablePtr->selCmd != NULL) { + Tcl_DString script; + Tcl_DStringInit(&script); + ExpandPercents(tablePtr, tablePtr->selCmd, numrows+1, numcols+1, + Tcl_DStringValue(&selection), (char *)NULL, + listArgc, &script, CMD_ACTIVATE); + if (Tcl_GlobalEval(interp, Tcl_DStringValue(&script)) == TCL_ERROR) { + Tcl_AddErrorInfo(interp, + "\n (error in table selection command)"); + Tcl_BackgroundError(interp); + Tcl_DStringFree(&script); + Tcl_DStringFree(&selection); + return -1; + } else { + Tcl_DStringGetResult(interp, &selection); + } + Tcl_DStringFree(&script); + } + + length = Tcl_DStringLength(&selection); + + if (length == 0) + return -1; + + /* Copy the requested portion of the selection to the buffer. */ + count = length - offset; + if (count <= 0) { + count = 0; + } else { + if (count > maxBytes) { + count = maxBytes; + } + memcpy((VOID *) buffer, + (VOID *) (Tcl_DStringValue(&selection) + offset), + (size_t) count); + } + buffer[count] = '\0'; + Tcl_DStringFree(&selection); + return count; +} + +/* + *---------------------------------------------------------------------- + * + * TableLostSelection -- + * This procedure is called back by Tk when the selection is + * grabbed away from a table widget. + * + * Results: + * None. + * + * Side effects: + * The existing selection is unhighlighted, and the window is + * marked as not containing a selection. + * + *---------------------------------------------------------------------- + */ +void +TableLostSelection(clientData) + ClientData clientData; /* Information about table widget. */ +{ + register Table *tablePtr = (Table *) clientData; + + if (tablePtr->exportSelection) { + Tcl_HashEntry *entryPtr; + Tcl_HashSearch search; + int row, col; + + /* Same as SEL CLEAR ALL */ + 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); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TableRestrictProc -- + * A Tk_RestrictProc used by TableValidateChange to eliminate any + * extra key input events in the event queue that + * have a serial number no less than a given value. + * + * Results: + * Returns either TK_DISCARD_EVENT or TK_DEFER_EVENT. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +static Tk_RestrictAction +TableRestrictProc(serial, eventPtr) + ClientData serial; + XEvent *eventPtr; +{ + if ((eventPtr->type == KeyRelease || eventPtr->type == KeyPress) && + ((eventPtr->xany.serial-(unsigned int)serial) > 0)) { + return TK_DEFER_EVENT; + } else { + return TK_PROCESS_EVENT; + } +} + +/* + *-------------------------------------------------------------- + * + * TableValidateChange -- + * This procedure is invoked when any character is added or + * removed from the table widget, or a set has triggered validation. + * + * Results: + * TCL_OK if the validatecommand accepts the new string, + * TCL_BREAK if the validatecommand rejects the new string, + * TCL_ERROR if any problems occured with validatecommand. + * + * Side effects: + * The insertion/deletion may be aborted, and the + * validatecommand might turn itself off (if an error + * or loop condition arises). + * + *-------------------------------------------------------------- + */ +int +TableValidateChange(tablePtr, r, c, old, new, index) + register Table *tablePtr; /* Table that needs validation. */ + int r, c; /* row,col index of cell in user coords */ + char *old; /* current value of cell */ + char *new; /* potential new value of cell */ + int index; /* index of insert/delete, -1 otherwise */ +{ + register Tcl_Interp *interp = tablePtr->interp; + int code, bool; + Tk_RestrictProc *rstrct; + ClientData cdata; + Tcl_DString script; + + if (tablePtr->valCmd == NULL || tablePtr->validate == 0) { + return TCL_OK; + } + + /* Magic code to make this bit of code UI synchronous in the face of + * possible new key events */ + XSync(tablePtr->display, False); + rstrct = Tk_RestrictEvents(TableRestrictProc, (ClientData) + NextRequest(tablePtr->display), &cdata); + + /* + * If we're already validating, then we're hitting a loop condition + * Return and set validate to 0 to disallow further validations + * and prevent current validation from finishing + */ + if (tablePtr->flags & VALIDATING) { + tablePtr->validate = 0; + return TCL_OK; + } + tablePtr->flags |= VALIDATING; + + /* Now form command string and run through the -validatecommand */ + Tcl_DStringInit(&script); + ExpandPercents(tablePtr, tablePtr->valCmd, r, c, old, new, index, &script, + CMD_VALIDATE); + code = Tcl_GlobalEval(tablePtr->interp, Tcl_DStringValue(&script)); + Tcl_DStringFree(&script); + + if (code != TCL_OK && code != TCL_RETURN) { + Tcl_AddErrorInfo(interp, + "\n\t(in validation command executed by table)"); + Tcl_BackgroundError(interp); + code = TCL_ERROR; + } else if (Tcl_GetBooleanFromObj(interp, Tcl_GetObjResult(interp), + &bool) != TCL_OK) { + Tcl_AddErrorInfo(interp, + "\n\tboolean not returned by validation command"); + Tcl_BackgroundError(interp); + code = TCL_ERROR; + } else { + code = (bool) ? TCL_OK : TCL_BREAK; + } + Tcl_SetObjResult(interp, Tcl_NewObj()); + + /* + * If ->validate has become VALIDATE_NONE during the validation, + * it means that a loop condition almost occured. Do not allow + * this validation result to finish. + */ + if (tablePtr->validate == 0) { + code = TCL_ERROR; + } + + /* If validate will return ERROR, then disallow further validations */ + if (code == TCL_ERROR) { + tablePtr->validate = 0; + } + + Tk_RestrictEvents(rstrct, cdata, &cdata); + tablePtr->flags &= ~VALIDATING; + + return code; +} + +/* + *-------------------------------------------------------------- + * + * ExpandPercents -- + * Given a command and an event, produce a new command + * by replacing % constructs in the original command + * with information from the X event. + * + * Results: + * The new expanded command is appended to the dynamic string + * given by dsPtr. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +void +ExpandPercents(tablePtr, before, r, c, old, new, index, dsPtr, cmdType) + Table *tablePtr; /* Table that needs validation. */ + char *before; /* Command containing percent + * expressions to be replaced. */ + int r, c; /* row,col index of cell */ + char *old; /* current value of cell */ + char *new; /* potential new value of cell */ + int index; /* index of insert/delete */ + Tcl_DString *dsPtr; /* Dynamic string in which to append + * new command. */ + int cmdType; /* type of command to make %-subs for */ +{ + int length, spaceNeeded, cvtFlags; +#ifdef TCL_UTF_MAX + Tcl_UniChar ch; +#else + char ch; +#endif + char *string, buf[INDEX_BUFSIZE]; + + /* This returns the static value of the string as set in the array */ + if (old == NULL && cmdType == CMD_VALIDATE) { + old = TableGetCellValue(tablePtr, r, c); + } + + while (1) { + if (*before == '\0') { + break; + } + /* + * Find everything up to the next % character and append it + * to the result string. + */ + + string = before; +#ifdef TCL_UTF_MAX + /* No need to convert '%', as it is in ascii range */ + string = (char *) Tcl_UtfFindFirst(before, '%'); +#else + string = strchr(before, '%'); +#endif + if (string == (char *) NULL) { + Tcl_DStringAppend(dsPtr, before, -1); + break; + } else if (string != before) { + Tcl_DStringAppend(dsPtr, before, string-before); + before = string; + } + + /* + * There's a percent sequence here. Process it. + */ + + before++; /* skip over % */ + if (*before != '\0') { +#ifdef TCL_UTF_MAX + before += Tcl_UtfToUniChar(before, &ch); +#else + ch = before[0]; + before++; +#endif + } else { + ch = '%'; + } + switch (ch) { + case 'c': + sprintf(buf, "%d", c); + string = buf; + break; + case 'C': /* index of cell */ + TableMakeArrayIndex(r, c, buf); + string = buf; + break; + case 'r': + sprintf(buf, "%d", r); + string = buf; + break; + case 'i': /* index of cursor OR |number| of cells selected */ + sprintf(buf, "%d", index); + string = buf; + break; + case 's': /* Current cell value */ + string = old; + break; + case 'S': /* Potential new value of cell */ + string = (new?new:old); + break; + case 'W': /* widget name */ + string = Tk_PathName(tablePtr->tkwin); + break; + default: +#ifdef TCL_UTF_MAX + length = Tcl_UniCharToUtf(ch, buf); +#else + buf[0] = ch; + length = 1; +#endif + buf[length] = '\0'; + string = buf; + break; + } + + spaceNeeded = Tcl_ScanElement(string, &cvtFlags); + length = Tcl_DStringLength(dsPtr); + Tcl_DStringSetLength(dsPtr, length + spaceNeeded); + spaceNeeded = Tcl_ConvertElement(string, + Tcl_DStringValue(dsPtr) + length, + cvtFlags | TCL_DONT_USE_BRACES); + Tcl_DStringSetLength(dsPtr, length + spaceNeeded); + } + Tcl_DStringAppend(dsPtr, "", 1); +} + +/* Function to call on loading the Table module */ + +#ifdef BUILD_Tktable +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLEXPORT +#endif +#ifdef MAC_TCL +#pragma export on +#endif +EXTERN int +Tktable_Init(interp) + Tcl_Interp *interp; +{ + /* This defines the static chars tkTable(Safe)InitScript */ +#include "tkTableInitScript.h" + + if ( +#ifdef USE_TCL_STUBS + Tcl_InitStubs(interp, "8.0", 0) +#else + Tcl_PkgRequire(interp, "Tcl", "8.0", 0) +#endif + == NULL) { + return TCL_ERROR; + } + if ( +#ifdef USE_TK_STUBS + Tk_InitStubs(interp, "8.0", 0) +#else +# if (TK_MAJOR_VERSION == 8) && (TK_MINOR_VERSION == 0) + /* We require 8.0 exact because of the Unicode in 8.1+ */ + Tcl_PkgRequire(interp, "Tk", "8.0", 1) +# else + Tcl_PkgRequire(interp, "Tk", "8.0", 0) +# endif +#endif + == NULL) { + return TCL_ERROR; + } + if (Tcl_PkgProvide(interp, "Tktable", PACKAGE_VERSION) != TCL_OK) { + return TCL_ERROR; + } + Tcl_CreateObjCommand(interp, TBL_COMMAND, Tk_TableObjCmd, + (ClientData) Tk_MainWindow(interp), + (Tcl_CmdDeleteProc *) NULL); + + /* + * The init script can't make certain calls in a safe interpreter, + * so we always have to use the embedded runtime for it + */ + return Tcl_Eval(interp, Tcl_IsSafe(interp) ? + tkTableSafeInitScript : tkTableInitScript); +} + +EXTERN int +Tktable_SafeInit(interp) + Tcl_Interp *interp; +{ + return Tktable_Init(interp); +} +#ifdef MAC_TCL +#pragma export reset +#endif + +#ifdef WIN32 +/* + *---------------------------------------------------------------------- + * + * DllEntryPoint -- + * + * This wrapper function is used by Windows to invoke the + * initialization code for the DLL. If we are compiling + * with Visual C++, this routine will be renamed to DllMain. + * routine. + * + * Results: + * Returns TRUE; + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +BOOL APIENTRY +DllEntryPoint(hInst, reason, reserved) + HINSTANCE hInst; /* Library instance handle. */ + DWORD reason; /* Reason this function is being called. */ + LPVOID reserved; /* Not used. */ +{ + return TRUE; +} +#endif diff --git a/tktable/generic/tkTable.h b/tktable/generic/tkTable.h new file mode 100644 index 0000000..32d5807 --- /dev/null +++ b/tktable/generic/tkTable.h @@ -0,0 +1,658 @@ +/* + * tkTable.h -- + * + * This is the header file for the module that implements + * table widgets for the Tk toolkit. + * + * Copyright (c) 1997-2002 Jeffrey Hobbs + * + * See the file "license.txt" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkTable.h,v 1.2 2016/01/12 18:59:57 joye Exp $ + */ + +#ifndef _TKTABLE_H_ +#define _TKTABLE_H_ + +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include <tk.h> +#ifdef MAC_TCL +# include <Xatom.h> +#else +# include <X11/Xatom.h> +#endif /* MAC_TCL */ + +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION == 0) /* Tcl8.0 stuff */ +#define Tcl_GetString(objPtr) Tcl_GetStringFromObj(objPtr, (int *)NULL) +#endif + +#if (TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)) +# define HAVE_TCL84 +#endif + +/* + * Tcl/Tk 8.4 introduced better CONST-ness in the APIs, but we use CONST84 in + * some cases for compatibility with earlier Tcl headers to prevent warnings. + */ +#ifndef CONST84 +# define CONST84 +#endif + +/* This EXTERN declaration is needed for Tcl < 8.0.3 */ +#ifndef EXTERN +# ifdef __cplusplus +# define EXTERN extern "C" +# else +# define EXTERN extern +# endif +#endif + +#ifdef TCL_STORAGE_CLASS +# undef TCL_STORAGE_CLASS +#endif +#ifdef BUILD_Tktable +# define TCL_STORAGE_CLASS DLLEXPORT +#else +# define TCL_STORAGE_CLASS DLLIMPORT +#endif + +#ifdef WIN32 +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# undef WIN32_LEAN_AND_MEAN +/* VC++ has an entry point called DllMain instead of DllEntryPoint */ +# if defined(_MSC_VER) +# define DllEntryPoint DllMain +# endif +#endif + +#if defined(WIN32) || defined(MAC_TCL) || defined(MAC_OSX_TK) +/* XSync call defined in the internals for some reason */ +# ifndef XSync +# define XSync(display, bool) {display->request++;} +# endif +#endif /* defn of XSync */ + +#ifndef NORMAL_BG +# ifdef WIN32 +# define NORMAL_BG "SystemButtonFace" +# define ACTIVE_BG NORMAL_BG +# define SELECT_BG "SystemHighlight" +# define SELECT_FG "SystemHighlightText" +# define DISABLED "SystemDisabledText" +# define HIGHLIGHT "SystemWindowFrame" +# define DEF_TABLE_FONT "{MS Sans Serif} 8" +# elif defined(MAC_TCL) || defined(MAC_OSX_TK) +# define NORMAL_BG "systemWindowBody" +# define ACTIVE_BG "#ececec" +# define SELECT_BG "systemHighlight" +# define SELECT_FG "systemHighlightText" +# define DISABLED "#a3a3a3" +# define HIGHLIGHT "Black" +# define DEF_TABLE_FONT "Helvetica 12" +# else +# define NORMAL_BG "#d9d9d9" +# define ACTIVE_BG "#fcfcfc" +# define SELECT_BG "#c3c3c3" +# define SELECT_FG "Black" +# define DISABLED "#a3a3a3" +# define HIGHLIGHT "Black" +# define DEF_TABLE_FONT "Helvetica -12" +# endif +#endif /* NORMAL_BG */ + +#define MAX(A,B) (((A)>(B))?(A):(B)) +#define MIN(A,B) (((A)>(B))?(B):(A)) +#define BETWEEN(val,min,max) ( ((val)<(min)) ? (min) : \ + ( ((val)>(max)) ? (max) : (val) ) ) +#define CONSTRAIN(val,min,max) if ((val) < (min)) { (val) = (min); } \ + else if ((val) > (max)) { (val) = (max); } +#define STREQ(s1, s2) (strcmp((s1), (s2)) == 0) +#define ARSIZE(A) (sizeof(A)/sizeof(*A)) +#define INDEX_BUFSIZE 32 /* max size of buffer for indices */ +#define TEST_KEY "#TEST KEY#" /* index for testing array existence */ + +/* + * Assigned bits of "flags" fields of Table structures, and what those + * bits mean: + * + * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has + * already been queued to redisplay the table. + * REDRAW_BORDER: Non-zero means 3-D border must be redrawn + * around window during redisplay. Normally + * only text portion needs to be redrawn. + * CURSOR_ON: Non-zero means insert cursor is displayed at + * present. 0 means it isn't displayed. + * TEXT_CHANGED: Non-zero means the active cell text is being edited. + * HAS_FOCUS: Non-zero means this window has the input focus. + * HAS_ACTIVE: Non-zero means the active cell is set. + * HAS_ANCHOR: Non-zero means the anchor cell is set. + * BROWSE_CMD: Non-zero means we're evaluating the -browsecommand. + * VALIDATING: Non-zero means we are in a valCmd + * SET_ACTIVE: About to set the active array element internally + * ACTIVE_DISABLED: Non-zero means the active cell is -state disabled + * OVER_BORDER: Non-zero means we are over a table cell border + * REDRAW_ON_MAP: Forces a redraw on the unmap + * AVOID_SPANS: prevent cell spans from being used + * + * FIX - consider adding UPDATE_SCROLLBAR a la entry + */ +#define REDRAW_PENDING (1L<<0) +#define CURSOR_ON (1L<<1) +#define HAS_FOCUS (1L<<2) +#define TEXT_CHANGED (1L<<3) +#define HAS_ACTIVE (1L<<4) +#define HAS_ANCHOR (1L<<5) +#define BROWSE_CMD (1L<<6) +#define REDRAW_BORDER (1L<<7) +#define VALIDATING (1L<<8) +#define SET_ACTIVE (1L<<9) +#define ACTIVE_DISABLED (1L<<10) +#define OVER_BORDER (1L<<11) +#define REDRAW_ON_MAP (1L<<12) +#define AVOID_SPANS (1L<<13) + +/* Flags for TableInvalidate && TableRedraw */ +#define ROW (1L<<0) +#define COL (1L<<1) +#define CELL (1L<<2) + +#define CELL_BAD (1<<0) +#define CELL_OK (1<<1) +#define CELL_SPAN (1<<2) +#define CELL_HIDDEN (1<<3) +#define CELL_VIEWABLE (CELL_OK|CELL_SPAN) + +#define INV_FILL (1L<<3) /* use for Redraw when the affected + * row/col will affect neighbors */ +#define INV_FORCE (1L<<4) +#define INV_HIGHLIGHT (1L<<5) +#define INV_NO_ERR_MSG (1L<<5) /* Don't leave an error message */ + +/* These alter how the selection set/clear commands behave */ +#define SEL_ROW (1<<0) +#define SEL_COL (1<<1) +#define SEL_BOTH (1<<2) +#define SEL_CELL (1<<3) +#define SEL_NONE (1<<4) + +/* + * Definitions for tablePtr->dataSource, by bit + */ +#define DATA_NONE 0 +#define DATA_CACHE (1<<1) +#define DATA_ARRAY (1<<2) +#define DATA_COMMAND (1<<3) + +/* + * Definitions for configuring -borderwidth + */ +#define BD_TABLE 0 +#define BD_TABLE_TAG (1<<1) +#define BD_TABLE_WIN (1<<2) + +/* + * Possible state values for tags + */ +typedef enum { + STATE_UNUSED, STATE_UNKNOWN, STATE_HIDDEN, + STATE_NORMAL, STATE_DISABLED, STATE_ACTIVE, STATE_LAST +} TableState; + +/* + * Structure for use in parsing table commands/values. + * Accessor functions defined in tkTableUtil.c + */ +typedef struct { + char *name; /* name of the command/value */ + int value; /* >0 because 0 represents an error or proc */ +} Cmd_Struct; + +/* + * The tag structure + */ +typedef struct { + Tk_3DBorder bg; /* background color */ + Tk_3DBorder fg; /* foreground color */ + + char * borderStr; /* border style */ + int borders; /* number of borders specified (1, 2 or 4) */ + int bd[4]; /* cell border width */ + + int relief; /* relief type */ + Tk_Font tkfont; /* Information about text font, or NULL. */ + Tk_Anchor anchor; /* default anchor point */ + char * imageStr; /* name of image */ + Tk_Image image; /* actual pointer to image, if any */ + TableState state; /* state of the cell */ + Tk_Justify justify; /* justification of text in the cell */ + int multiline; /* wrapping style of multiline text */ + int wrap; /* wrapping style of multiline text */ + int showtext; /* whether to display text over image */ + char * ellipsis; /* ellipsis to display on clipped text */ +} TableTag; + +/* The widget structure for the table Widget */ + +typedef struct { + /* basic information about the window and the interpreter */ + Tk_Window tkwin; + Display *display; + Tcl_Interp *interp; + Tcl_Command widgetCmd; /* Token for entry's widget command. */ + + /* + * Configurable Options + */ + int autoClear; + char *selectMode; /* single, browse, multiple, or extended */ + int selectType; /* row, col, both, or cell */ + int selectTitles; /* whether to do automatic title selection */ + int rows, cols; /* number of rows and columns */ + int defRowHeight; /* default row height in chars (positive) + * or pixels (negative) */ + int defColWidth; /* default column width in chars (positive) + * or pixels (negative) */ + int maxReqCols; /* the requested # cols to display */ + int maxReqRows; /* the requested # rows to display */ + int maxReqWidth; /* the maximum requested width in pixels */ + int maxReqHeight; /* the maximum requested height in pixels */ + char *arrayVar; /* name of traced array variable */ + char *rowSep; /* separator string to place between + * rows when getting selection */ + char *colSep; /* separator string to place between + * cols when getting selection */ + TableTag defaultTag; /* the default tag colors/fonts etc */ + char *yScrollCmd; /* the y-scroll command */ + char *xScrollCmd; /* the x-scroll command */ + char *browseCmd; /* the command that is called when the + * active cell changes */ + int caching; /* whether to cache values of table */ + char *command; /* A command to eval when get/set occurs + * for table values */ + int useCmd; /* Signals whether to use command or the + * array variable, will be 0 if command errs */ + char *selCmd; /* the command that is called to when a + * [selection get] call occurs for a table */ + char *valCmd; /* Command prefix to use when invoking + * validate command. NULL means don't + * invoke commands. Malloc'ed. */ + int validate; /* Non-zero means try to validate */ + Tk_3DBorder insertBg; /* the cursor color */ + Tk_Cursor cursor; /* the regular mouse pointer */ + Tk_Cursor bdcursor; /* the mouse pointer when over borders */ +#ifdef TITLE_CURSOR + Tk_Cursor titleCursor; /* the mouse pointer when over titles */ +#endif + int exportSelection; /* Non-zero means tie internal table + * to X selection. */ + TableState state; /* Normal or disabled. Table is read-only + * when disabled. */ + int insertWidth; /* Total width of insert cursor. */ + int insertBorderWidth; /* Width of 3-D border around insert cursor. */ + int insertOnTime; /* Number of milliseconds cursor should spend + * in "on" state for each blink. */ + int insertOffTime; /* Number of milliseconds cursor should spend + * in "off" state for each blink. */ + int invertSelected; /* Whether to draw selected cells swapping + * foreground and background */ + int colStretch; /* The way to stretch columns if the window + * is too large */ + int rowStretch; /* The way to stretch rows if the window is + * too large */ + int colOffset; /* X index of leftmost col in the display */ + int rowOffset; /* Y index of topmost row in the display */ + int drawMode; /* The mode to use when redrawing */ + int flashMode; /* Specifies whether flashing is enabled */ + int flashTime; /* The number of ms to flash a cell for */ + int resize; /* -resizeborders option for interactive + * resizing of borders */ + int sparse; /* Whether to use "sparse" arrays by + * deleting empty array elements (default) */ + char *rowTagCmd, *colTagCmd;/* script to eval for getting row/tag cmd */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr;/* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + char *takeFocus; /* Used only in Tcl to check if this + * widget will accept focus */ + int padX, padY; /* Extra space around text (pixels to leave + * on each side). Ignored for bitmaps and + * images. */ + int ipadX, ipadY; /* Space to leave empty around cell borders. + * This differs from pad* in that it is always + * present for the cell (except windows). */ + + /* + * Cached Information + */ +#ifdef TITLE_CURSOR + Tk_Cursor *lastCursorPtr; /* pointer to last cursor defined. */ +#endif + int titleRows, titleCols; /* the number of rows|cols to use as a title */ + /* these are kept in real coords */ + int topRow, leftCol; /* The topleft cell to display excluding the + * fixed title rows. This is just the + * config request. The actual cell used may + * be different to keep the screen full */ + int anchorRow, anchorCol; /* the row,col of the anchor cell */ + int activeRow, activeCol; /* the row,col of the active cell */ + int oldTopRow, oldLeftCol; /* cached by TableAdjustParams */ + int oldActRow, oldActCol; /* cached by TableAdjustParams */ + int icursor; /* The index of the insertion cursor in the + * active cell */ + int flags; /* An or'ed combination of flags concerning + * redraw/cursor etc. */ + int dataSource; /* where our data comes from: + * DATA_{NONE,CACHE,ARRAY,COMMAND} */ + int maxWidth, maxHeight; /* max width|height required in pixels */ + int charWidth, charHeight; /* size of a character in the default font */ + int *colPixels, *rowPixels; /* Array of the pixel widths/heights */ + int *colStarts, *rowStarts; /* Array of start pixels for rows|columns */ + int scanMarkX, scanMarkY; /* Used by "scan" and "border" to mark */ + int scanMarkRow, scanMarkCol;/* necessary information for dragto */ + /* values in these are kept in user coords */ + Tcl_HashTable *cache; /* value cache */ + + /* + * colWidths and rowHeights are indexed from 0, so always adjust numbers + * by the appropriate *Offset factor + */ + Tcl_HashTable *colWidths; /* hash table of non default column widths */ + Tcl_HashTable *rowHeights; /* hash table of non default row heights */ + Tcl_HashTable *spanTbl; /* table for spans */ + Tcl_HashTable *spanAffTbl; /* table for cells affected by spans */ + Tcl_HashTable *tagTable; /* table for style tags */ + Tcl_HashTable *winTable; /* table for embedded windows */ + Tcl_HashTable *rowStyles; /* table for row styles */ + Tcl_HashTable *colStyles; /* table for col styles */ + Tcl_HashTable *cellStyles; /* table for cell styles */ + Tcl_HashTable *flashCells; /* table of flashing cells */ + Tcl_HashTable *selCells; /* table of selected cells */ + Tcl_TimerToken cursorTimer; /* timer token for the cursor blinking */ + Tcl_TimerToken flashTimer; /* timer token for the cell flashing */ + char *activeBuf; /* buffer where the selection is kept + * for editing the active cell */ + char **tagPrioNames; /* list of tag names in priority order */ + TableTag **tagPrios; /* list of tag pointers in priority order */ + TableTag *activeTagPtr; /* cache of active composite tag */ + int activeX, activeY; /* cache offset of active layout in cell */ + int tagPrioSize; /* size of tagPrios list */ + int tagPrioMax; /* max allocated size of tagPrios list */ + + /* The invalid rectangle if there is an update pending */ + int invalidX, invalidY, invalidWidth, invalidHeight; + int seen[4]; /* see TableUndisplay */ + +#ifdef POSTSCRIPT + /* Pointer to information used for generating Postscript for the canvas. + * NULL means no Postscript is currently being generated. */ + struct TkPostscriptInfo *psInfoPtr; +#endif + +#ifdef PROCS + Tcl_HashTable *inProc; /* cells where proc is being evaled */ + int showProcs; /* whether to show embedded proc (1) or + * its calculated value (0) */ + int hasProcs; /* whether table has embedded procs or not */ +#endif +} Table; + +/* + * HEADERS FOR EMBEDDED WINDOWS + */ + +/* + * A structure of the following type holds information for each window + * embedded in a table widget. + */ + +typedef struct TableEmbWindow { + Table *tablePtr; /* Information about the overall table + * widget. */ + Tk_Window tkwin; /* Window for this segment. NULL means that + * the window hasn't been created yet. */ + Tcl_HashEntry *hPtr; /* entry into winTable */ + char *create; /* Script to create window on-demand. + * NULL means no such script. + * Malloc-ed. */ + Tk_3DBorder bg; /* background color */ + + char *borderStr; /* border style */ + int borders; /* number of borders specified (1, 2 or 4) */ + int bd[4]; /* border width for cell around window */ + + int relief; /* relief type */ + int sticky; /* How to align window in space */ + int padX, padY; /* Padding to leave around each side + * of window, in pixels. */ + int displayed; /* Non-zero means that the window has been + * displayed on the screen recently. */ +} TableEmbWindow; + +extern Tk_ConfigSpec tableSpecs[]; + +extern void EmbWinDisplay(Table *tablePtr, Drawable window, + TableEmbWindow *ewPtr, TableTag *tagPtr, + int x, int y, int width, int height); +extern void EmbWinUnmap(register Table *tablePtr, + int rlo, int rhi, int clo, int chi); +extern void EmbWinDelete(register Table *tablePtr, TableEmbWindow *ewPtr); +extern int Table_WinMove(register Table *tablePtr, + char *CONST srcPtr, char *CONST destPtr, int flags); +extern int Table_WinDelete(register Table *tablePtr, char *CONST idxPtr); +extern int Table_WindowCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int TableValidateChange(Table *tablePtr, int r, + int c, char *oldVal, char *newVal, int idx); +extern void TableLostSelection(ClientData clientData); +extern void TableSetActiveIndex(register Table *tablePtr); + +/* + * HEADERS IN tkTableCmds.c + */ + +extern int Table_ActivateCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_AdjustCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_BboxCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_BorderCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_ClearCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_CurselectionCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_CurvalueCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_GetCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_ScanCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_SeeCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_SelAnchorCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_SelClearCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_SelIncludesCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_SelSetCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_ViewCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); + +/* + * HEADERS IN tkTableEdit.c + */ + +extern int Table_EditCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern void TableDeleteChars(register Table *tablePtr, + int idx, int count); +extern void TableInsertChars(register Table *tablePtr, + int idx, char *string); + +/* + * HEADERS IN tkTableTag.c + */ + +extern TableTag *TableNewTag(Table *tablePtr); +extern void TableResetTag(Table *tablePtr, TableTag *tagPtr); +extern void TableMergeTag(Table *tablePtr, TableTag *baseTag, + TableTag *addTag); +extern void TableInvertTag(TableTag *baseTag); +extern int TableGetTagBorders(TableTag *tagPtr, + int *left, int *right, int *top, int *bottom); +extern void TableInitTags(Table *tablePtr); +extern TableTag *FindRowColTag(Table *tablePtr, + int cell, int type); +extern void TableCleanupTag(Table *tablePtr, + TableTag *tagPtr); +extern int Table_TagCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); + +/* + * HEADERS IN tkTableUtil.c + */ + +extern void Table_ClearHashTable(Tcl_HashTable *hashTblPtr); +extern int TableOptionBdSet(ClientData clientData, + Tcl_Interp *interp, Tk_Window tkwin, + CONST84 char *value, char *widgRec, int offset); +extern const char * TableOptionBdGet(ClientData clientData, + Tk_Window tkwin, char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr); +extern int TableTagConfigureBd(Table *tablePtr, + TableTag *tagPtr, char *oldValue, int nullOK); +extern int Cmd_OptionSet(ClientData clientData, + Tcl_Interp *interp, + Tk_Window unused, CONST84 char *value, + char *widgRec, int offset); +extern const char * Cmd_OptionGet(ClientData clientData, + Tk_Window unused, char *widgRec, + int offset, Tcl_FreeProc **freeProcPtr); + +/* + * HEADERS IN tkTableCell.c + */ + +extern int TableTrueCell(Table *tablePtr, int row, int col, + int *trow, int *tcol); +extern int TableCellCoords(Table *tablePtr, int row, + int col, int *rx, int *ry, int *rw, int *rh); +extern int TableCellVCoords(Table *tablePtr, int row, + int col, int *rx, int *ry, + int *rw, int *rh, int full); +extern void TableWhatCell(register Table *tablePtr, + int x, int y, int *row, int *col); +extern int TableAtBorder(Table *tablePtr, int x, int y, + int *row, int *col); +extern char * TableGetCellValue(Table *tablePtr, int r, int c); +extern int TableSetCellValue(Table *tablePtr, int r, int c, + char *value); +extern int TableMoveCellValue(Table *tablePtr, + int fromr, int fromc, char *frombuf, + int tor, int toc, char *tobuf, int outOfBounds); + +extern int TableGetIcursor(Table *tablePtr, char *arg, + int *posn); +#define TableGetIcursorObj(tablePtr, objPtr, posnPtr) \ + TableGetIcursor(tablePtr, Tcl_GetString(objPtr), posnPtr) +extern int TableGetIndex(register Table *tablePtr, + char *str, int *row_p, int *col_p); +#define TableGetIndexObj(tablePtr, objPtr, rowPtr, colPtr) \ + TableGetIndex(tablePtr, Tcl_GetString(objPtr), rowPtr, colPtr) +extern int Table_SetCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_HiddenCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern int Table_SpanCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern void TableSpanSanCheck(register Table *tablePtr); + +/* + * HEADERS IN TKTABLECELLSORT + */ +/* + * We keep the old CellSort true because it is used for grabbing + * the selection, so we really want them ordered + */ +extern char * TableCellSort(Table *tablePtr, char *str); +#ifdef NO_SORT_CELLS +# define TableCellSortObj(interp, objPtr) (objPtr) +#else +extern Tcl_Obj* TableCellSortObj(Tcl_Interp *interp, Tcl_Obj *listObjPtr); +#endif + +/* + * HEADERS IN TKTABLEPS + */ + +#ifdef POSTSCRIPT +extern int Table_PostscriptCmd(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +extern void Tcl_DStringAppendAllTCL_VARARGS(Tcl_DString *, arg1); +#endif + +/* + * HEADERS IN TKTABLE + */ + +EXTERN int Tktable_Init(Tcl_Interp *interp); +EXTERN int Tktable_SafeInit(Tcl_Interp *interp); + +extern void TableGetActiveBuf(register Table *tablePtr); +extern void ExpandPercents(Table *tablePtr, char *before, + int r, int c, char *oldVal, char *newVal, int idx, + Tcl_DString *dsPtr, int cmdType); +extern void TableInvalidate(Table *tablePtr, int x, int y, + int width, int height, int force); +extern void TableRefresh(register Table *tablePtr, + int arg1, int arg2, int mode); +extern void TableGeometryRequest(Table *tablePtr); +extern void TableAdjustActive(register Table *tablePtr); +extern void TableAdjustParams(register Table *tablePtr); +extern void TableConfigCursor(register Table *tablePtr); +extern void TableAddFlash(Table *tablePtr, int row, int col); + + +#define TableInvalidateAll(tablePtr, flags) \ + TableInvalidate((tablePtr), 0, 0, Tk_Width((tablePtr)->tkwin),\ + Tk_Height((tablePtr)->tkwin), (flags)) + + /* + * Turn row/col into an index into the table + */ +#define TableMakeArrayIndex(r, c, i) sprintf((i), "%d,%d", (r), (c)) + + /* + * Turn array index back into row/col + * return the number of args parsed (should be two) + */ +#define TableParseArrayIndex(r, c, i) sscanf((i), "%d,%d", (r), (c)) + + /* + * Macro for finding the last cell of the table + */ +#define TableGetLastCell(tablePtr, rowPtr, colPtr) \ + TableWhatCell((tablePtr),\ + Tk_Width((tablePtr)->tkwin)-(tablePtr)->highlightWidth-1,\ + Tk_Height((tablePtr)->tkwin)-(tablePtr)->highlightWidth-1,\ + (rowPtr), (colPtr)) + +/* + * end of header + * reset TCL_STORAGE_CLASS to DLLIMPORT. + */ +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKTABLE_H_ */ + diff --git a/tktable/generic/tkTableCell.c b/tktable/generic/tkTableCell.c new file mode 100644 index 0000000..4642aaa --- /dev/null +++ b/tktable/generic/tkTableCell.c @@ -0,0 +1,1420 @@ +/* + * tkTableCell.c -- + * + * This module implements cell oriented functions for table + * widgets. + * + * 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: tkTableCell.c,v 1.1.1.1 2011/03/01 20:00:38 joye Exp $ + */ + +#include "tkTable.h" + +/* + *---------------------------------------------------------------------- + * + * TableTrueCell -- + * Takes a row,col pair in user coords and returns the true + * cell that it relates to, either dimension bounded, or a + * span cell if it was hidden. + * + * Results: + * The true row, col in user coords are placed in the pointers. + * If the value changed for some reasons, 0 is returned (it was not + * the /true/ cell). + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +int +TableTrueCell(Table *tablePtr, int r, int c, int *row, int *col) +{ + *row = r; *col = c; + /* + * We check spans before constraints, because we don't want to + * constrain and then think we ended up in a span + */ + if (tablePtr->spanAffTbl && !(tablePtr->flags & AVOID_SPANS)) { + char buf[INDEX_BUFSIZE]; + Tcl_HashEntry *entryPtr; + + TableMakeArrayIndex(r, c, buf); + entryPtr = Tcl_FindHashEntry(tablePtr->spanAffTbl, buf); + if ((entryPtr != NULL) && + ((char *)Tcl_GetHashValue(entryPtr) != NULL)) { + /* + * This cell is covered by another spanning cell. + * We need to return the coords for that spanning cell. + */ + TableParseArrayIndex(row, col, (char *)Tcl_GetHashValue(entryPtr)); + return 0; + } + } + *row = BETWEEN(r, tablePtr->rowOffset, + tablePtr->rows-1+tablePtr->rowOffset); + *col = BETWEEN(c, tablePtr->colOffset, + tablePtr->cols-1+tablePtr->colOffset); + return ((*row == r) && (*col == c)); +} + +/* + *---------------------------------------------------------------------- + * + * TableCellCoords -- + * Takes a row,col pair in real coords and finds it position + * on the virtual screen. + * + * Results: + * The virtual x, y, width, and height of the cell + * are placed in the pointers. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +int +TableCellCoords(Table *tablePtr, int row, int col, + int *x, int *y, int *w, int *h) +{ + register int hl = tablePtr->highlightWidth; + int result = CELL_OK; + + if (tablePtr->rows <= 0 || tablePtr->cols <= 0) { + *w = *h = *x = *y = 0; + return CELL_BAD; + } + /* + * Real coords required, always should be passed acceptable values, + * but this is a possible seg fault otherwise + */ + CONSTRAIN(row, 0, tablePtr->rows-1); + CONSTRAIN(col, 0, tablePtr->cols-1); + *w = tablePtr->colPixels[col]; + *h = tablePtr->rowPixels[row]; + /* + * Adjust for sizes of spanning cells + * and ensure that this cell isn't "hidden" + */ + if (tablePtr->spanAffTbl && !(tablePtr->flags & AVOID_SPANS)) { + char buf[INDEX_BUFSIZE]; + Tcl_HashEntry *entryPtr; + + TableMakeArrayIndex(row+tablePtr->rowOffset, + col+tablePtr->colOffset, buf); + entryPtr = Tcl_FindHashEntry(tablePtr->spanAffTbl, buf); + if (entryPtr != NULL) { + int rs, cs; + char *cell; + + cell = (char *) Tcl_GetHashValue(entryPtr); + if (cell != NULL) { + /* This cell is covered by another spanning cell */ + /* We need to return the coords for that cell */ + TableParseArrayIndex(&rs, &cs, cell); + *w = rs; + *h = cs; + result = CELL_HIDDEN; + goto setxy; + } + /* Get the actual span values out of spanTbl */ + entryPtr = Tcl_FindHashEntry(tablePtr->spanTbl, buf); + cell = (char *) Tcl_GetHashValue(entryPtr); + TableParseArrayIndex(&rs, &cs, cell); + if (rs > 0) { + /* + * Make sure we don't overflow our space + */ + if (row < tablePtr->titleRows) { + rs = MIN(tablePtr->titleRows-1, row+rs); + } else { + rs = MIN(tablePtr->rows-1, row+rs); + } + *h = tablePtr->rowStarts[rs+1]-tablePtr->rowStarts[row]; + result = CELL_SPAN; + } else if (rs <= 0) { + /* currently negative spans are not supported */ + } + if (cs > 0) { + /* + * Make sure we don't overflow our space + */ + if (col < tablePtr->titleCols) { + cs = MIN(tablePtr->titleCols-1, col+cs); + } else { + cs = MIN(tablePtr->cols-1, col+cs); + } + *w = tablePtr->colStarts[cs+1]-tablePtr->colStarts[col]; + result = CELL_SPAN; + } else if (cs <= 0) { + /* currently negative spans are not supported */ + } + } + } +setxy: + *x = hl + tablePtr->colStarts[col]; + if (col >= tablePtr->titleCols) { + *x -= tablePtr->colStarts[tablePtr->leftCol] + - tablePtr->colStarts[tablePtr->titleCols]; + } + *y = hl + tablePtr->rowStarts[row]; + if (row >= tablePtr->titleRows) { + *y -= tablePtr->rowStarts[tablePtr->topRow] + - tablePtr->rowStarts[tablePtr->titleRows]; + } + return result; +} + +/* + *---------------------------------------------------------------------- + * + * TableCellVCoords -- + * Takes a row,col pair in real coords and finds it position + * on the actual screen. The full arg specifies whether + * only 100% visible cells should be considered visible. + * + * Results: + * The x, y, width, and height of the cell are placed in the pointers, + * depending upon visibility of the cell. + * Returns 0 for hidden and 1 for visible cells. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +int +TableCellVCoords(Table *tablePtr, int row, int col, + int *rx, int *ry, int *rw, int *rh, int full) +{ + int x, y, w, h, w0, h0, cellType, hl = tablePtr->highlightWidth; + + if (tablePtr->tkwin == NULL) return 0; + + /* + * Necessary to use separate vars in case dummies are passed in + */ + cellType = TableCellCoords(tablePtr, row, col, &x, &y, &w, &h); + *rx = x; *ry = y; *rw = w; *rh = h; + if (cellType == CELL_OK) { + if ((row < tablePtr->topRow && row >= tablePtr->titleRows) || + (col < tablePtr->leftCol && col >= tablePtr->titleCols)) { + /* + * A non-spanning cell hiding in "dead" space + * between title areas and visible cells + */ + return 0; + } + } else if (cellType == CELL_SPAN) { + /* + * we might need to treat full better is CELL_SPAN but primary + * cell is visible + */ + int topX = tablePtr->colStarts[tablePtr->titleCols]+hl; + int topY = tablePtr->rowStarts[tablePtr->titleRows]+hl; + if ((col < tablePtr->leftCol) && (col >= tablePtr->titleCols)) { + if (full || (x+w < topX)) { + return 0; + } else { + w -= topX-x; + x = topX; + } + } + if ((row < tablePtr->topRow) && (row >= tablePtr->titleRows)) { + if (full || (y+h < topY)) { + return 0; + } else { + h -= topY-y; + y = topY; + } + } + /* + * re-set these according to changed coords + */ + *rx = x; *ry = y; *rw = w; *rh = h; + } else { + /* + * If it is a hidden cell, then w,h is the row,col in user coords + * of the cell that spans over this one + */ + return 0; + } + /* + * At this point, we know it is on the screen, + * but not if we can see 100% of it (if we care) + */ + if (full) { + w0 = w; h0 = h; + } else { + /* + * if we don't care about seeing the whole thing, then + * make sure we at least see a pixel worth + */ + w0 = h0 = 1; + } + /* + * Is the cell visible? + */ + if ((x < hl) || (y < hl) || ((x+w0) > (Tk_Width(tablePtr->tkwin)-hl)) + || ((y+h0) > (Tk_Height(tablePtr->tkwin)-hl))) { + /* definitely off the screen */ + return 0; + } else { + /* if it was full, then w,h are already be properly constrained */ + if (!full) { + *rw = MIN(w, Tk_Width(tablePtr->tkwin)-hl-x); + *rh = MIN(h, Tk_Height(tablePtr->tkwin)-hl-y); + } + return 1; + } +} + +/* + *---------------------------------------------------------------------- + * + * TableWhatCell -- + * Takes a x,y screen coordinate and determines what cell contains. + * that point. This will return cells that are beyond the right/bottom + * edge of the viewable screen. + * + * Results: + * The row,col of the cell are placed in the pointers. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +void +TableWhatCell(register Table *tablePtr, int x, int y, int *row, int *col) +{ + int i; + x = MAX(0, x); y = MAX(0, y); + /* Adjust for table's global highlightthickness border */ + x -= tablePtr->highlightWidth; + y -= tablePtr->highlightWidth; + /* Adjust the x coord if not in the column titles to change display coords + * into internal coords */ + x += (x < tablePtr->colStarts[tablePtr->titleCols]) ? 0 : + tablePtr->colStarts[tablePtr->leftCol] - + tablePtr->colStarts[tablePtr->titleCols]; + y += (y < tablePtr->rowStarts[tablePtr->titleRows]) ? 0 : + tablePtr->rowStarts[tablePtr->topRow] - + tablePtr->rowStarts[tablePtr->titleRows]; + x = MIN(x, tablePtr->maxWidth-1); + y = MIN(y, tablePtr->maxHeight-1); + for (i = 1; x >= tablePtr->colStarts[i]; i++); + *col = i - 1; + for (i = 1; y >= tablePtr->rowStarts[i]; i++); + *row = i - 1; + if (tablePtr->spanAffTbl && !(tablePtr->flags & AVOID_SPANS)) { + char buf[INDEX_BUFSIZE]; + Tcl_HashEntry *entryPtr; + + /* We now correct the returned cell if this was "hidden" */ + TableMakeArrayIndex(*row+tablePtr->rowOffset, + *col+tablePtr->colOffset, buf); + entryPtr = Tcl_FindHashEntry(tablePtr->spanAffTbl, buf); + if ((entryPtr != NULL) && + /* We have to make sure this was not already hidden + * that's an error */ + ((char *)Tcl_GetHashValue(entryPtr) != NULL)) { + /* this is a "hidden" cell */ + TableParseArrayIndex(row, col, (char *)Tcl_GetHashValue(entryPtr)); + *row -= tablePtr->rowOffset; + *col -= tablePtr->colOffset; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TableAtBorder -- + * Takes a x,y screen coordinate and determines if that point is + * over a border. + * + * Results: + * The left/top row,col corresponding to that point are placed in + * the pointers. The number of borders (+1 for row, +1 for col) + * hit is returned. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +int +TableAtBorder(Table * tablePtr, int x, int y, int *row, int *col) +{ + int i, brow, bcol, borders = 2, bd[6]; + + TableGetTagBorders(&(tablePtr->defaultTag), + &bd[0], &bd[1], &bd[2], &bd[3]); + bd[4] = (bd[0] + bd[1])/2; + bd[5] = (bd[2] + bd[3])/2; + + /* + * Constrain x && y appropriately, and adjust x if it is not in the + * column titles to change display coords into internal coords. + */ + x = MAX(0, x); y = MAX(0, y); + x -= tablePtr->highlightWidth; y -= tablePtr->highlightWidth; + x += (x < tablePtr->colStarts[tablePtr->titleCols]) ? 0 : + tablePtr->colStarts[tablePtr->leftCol] - + tablePtr->colStarts[tablePtr->titleCols]; + x = MIN(x, tablePtr->maxWidth - 1); + for (i = 1; (i <= tablePtr->cols) && + (x + (bd[0] + bd[1])) >= tablePtr->colStarts[i]; i++); + if (x > tablePtr->colStarts[--i] + bd[4]) { + borders--; + *col = -1; + bcol = (i < tablePtr->leftCol && i >= tablePtr->titleCols) ? + tablePtr->titleCols-1 : i-1; + } else { + bcol = *col = (i < tablePtr->leftCol && i >= tablePtr->titleCols) ? + tablePtr->titleCols-1 : i-1; + } + y += (y < tablePtr->rowStarts[tablePtr->titleRows]) ? 0 : + tablePtr->rowStarts[tablePtr->topRow] - + tablePtr->rowStarts[tablePtr->titleRows]; + y = MIN(y, tablePtr->maxHeight - 1); + for (i = 1; i <= tablePtr->rows && + (y + (bd[2] + bd[3])) >= tablePtr->rowStarts[i]; i++); + if (y > tablePtr->rowStarts[--i]+bd[5]) { + borders--; + *row = -1; + brow = (i < tablePtr->topRow && i >= tablePtr->titleRows) ? + tablePtr->titleRows-1 : i-1; + } else { + brow = *row = (i < tablePtr->topRow && i >= tablePtr->titleRows) ? + tablePtr->titleRows-1 : i-1; + } + /* + * We have to account for spanning cells, which may hide cells. + * In that case, we have to decrement our border count. + */ + if (tablePtr->spanAffTbl && !(tablePtr->flags & AVOID_SPANS) && borders) { + Tcl_HashEntry *entryPtr1, *entryPtr2 ; + char buf1[INDEX_BUFSIZE], buf2[INDEX_BUFSIZE]; + char *val; + + if (*row != -1) { + TableMakeArrayIndex(brow+tablePtr->rowOffset, + bcol+tablePtr->colOffset+1, buf1); + TableMakeArrayIndex(brow+tablePtr->rowOffset+1, + bcol+tablePtr->colOffset+1, buf2); + entryPtr1 = Tcl_FindHashEntry(tablePtr->spanAffTbl, buf1); + entryPtr2 = Tcl_FindHashEntry(tablePtr->spanAffTbl, buf2); + if (entryPtr1 != NULL && entryPtr2 != NULL) { + if ((val = (char *) Tcl_GetHashValue(entryPtr1)) != NULL) { + strcpy(buf1, val); + } + if ((val = (char *) Tcl_GetHashValue(entryPtr2)) != NULL) { + strcpy(buf2, val); + } + if (strcmp(buf1, buf2) == 0) { + borders--; + *row = -1; + } + } + } + if (*col != -1) { + TableMakeArrayIndex(brow+tablePtr->rowOffset+1, + bcol+tablePtr->colOffset, buf1); + TableMakeArrayIndex(brow+tablePtr->rowOffset+1, + bcol+tablePtr->colOffset+1, buf2); + entryPtr1 = Tcl_FindHashEntry(tablePtr->spanAffTbl, buf1); + entryPtr2 = Tcl_FindHashEntry(tablePtr->spanAffTbl, buf2); + if (entryPtr1 != NULL && entryPtr2 != NULL) { + if ((val = (char *) Tcl_GetHashValue(entryPtr1)) != NULL) { + strcpy(buf1, val); + } + if ((val = (char *) Tcl_GetHashValue(entryPtr2)) != NULL) { + strcpy(buf2, val); + } + if (strcmp(buf1, buf2) == 0) { + borders--; + *col = -1; + } + } + } + } + return borders; +} + +/* + *---------------------------------------------------------------------- + * + * TableGetCellValue -- + * Takes a row,col pair in user coords and returns the value for + * that cell. This varies depending on what data source the + * user has selected. + * + * Results: + * The value of the cell is returned. The return value is VOLATILE + * (do not free). + * + * Side effects: + * The value will be cached if caching is turned on. + * + *---------------------------------------------------------------------- + */ +char * +TableGetCellValue(Table *tablePtr, int r, int c) +{ + register Tcl_Interp *interp = tablePtr->interp; + char *result = NULL; + char buf[INDEX_BUFSIZE]; + Tcl_HashEntry *entryPtr = NULL; + int new; + + TableMakeArrayIndex(r, c, buf); + + if (tablePtr->dataSource == DATA_CACHE) { + /* + * only cache as data source - just rely on cache + */ + entryPtr = Tcl_FindHashEntry(tablePtr->cache, buf); + if (entryPtr) { + result = (char *) Tcl_GetHashValue(entryPtr); + } + goto VALUE; + } + if (tablePtr->caching) { + /* + * If we are caching, let's see if we have the value cached. + * If so, use it, otherwise it will be cached after retrieving + * from the other data source. + */ + entryPtr = Tcl_CreateHashEntry(tablePtr->cache, buf, &new); + if (!new) { + result = (char *) Tcl_GetHashValue(entryPtr); + goto VALUE; + } + } + if (tablePtr->dataSource & DATA_COMMAND) { + Tcl_DString script; + Tcl_DStringInit(&script); + ExpandPercents(tablePtr, tablePtr->command, r, c, "", (char *)NULL, + 0, &script, 0); + if (Tcl_GlobalEval(interp, Tcl_DStringValue(&script)) == TCL_ERROR) { + tablePtr->useCmd = 0; + tablePtr->dataSource &= ~DATA_COMMAND; + if (tablePtr->arrayVar) + tablePtr->dataSource |= DATA_ARRAY; + Tcl_AddErrorInfo(interp, "\n\t(in -command evaled by table)"); + Tcl_AddErrorInfo(interp, Tcl_DStringValue(&script)); + Tcl_BackgroundError(interp); + TableInvalidateAll(tablePtr, 0); + } else { + result = (char *) Tcl_GetStringResult(interp); + } + Tcl_DStringFree(&script); + } + if (tablePtr->dataSource & DATA_ARRAY) { + result = (char *) Tcl_GetVar2(interp, tablePtr->arrayVar, buf, + TCL_GLOBAL_ONLY); + } + if (tablePtr->caching && entryPtr != NULL) { + /* + * If we are caching, make sure we cache the returned value + * + * entryPtr will have been set from above, but check to make sure + * someone didn't change caching during -command evaluation. + */ + char *val = NULL; + if (result) { + val = (char *)ckalloc(strlen(result)+1); + strcpy(val, result); + } + Tcl_SetHashValue(entryPtr, val); + } +VALUE: +#ifdef PROCS + if (result != NULL) { + /* Do we have procs, are we showing their value, is this a proc? */ + if (tablePtr->hasProcs && !tablePtr->showProcs && *result == '=' && + !(r-tablePtr->rowOffset == tablePtr->activeRow && + c-tablePtr->colOffset == tablePtr->activeCol)) { + Tcl_DString script; + /* provides a rough mutex on preventing proc loops */ + entryPtr = Tcl_CreateHashEntry(tablePtr->inProc, buf, &new); + if (!new) { + Tcl_SetHashValue(entryPtr, 1); + Tcl_AddErrorInfo(interp, "\n\t(loop hit in proc evaled by table)"); + return result; + } + Tcl_SetHashValue(entryPtr, 0); + Tcl_DStringInit(&script); + ExpandPercents(tablePtr, result+1, r, c, result+1, (char *)NULL, + 0, &script, 0); + if (Tcl_GlobalEval(interp, Tcl_DStringValue(&script)) != TCL_OK || + Tcl_GetHashValue(entryPtr) == 1) { + Tcl_AddErrorInfo(interp, "\n\tin proc evaled by table:\n"); + Tcl_AddErrorInfo(interp, Tcl_DStringValue(&script)); + Tcl_BackgroundError(interp); + } else { + result = Tcl_GetStringResult(interp); + } + /* + * XXX FIX: Can't free result that we still need. + * Use ref-counted objects instead. + */ + Tcl_FreeResult(interp); + Tcl_DStringFree(&script); + Tcl_DeleteHashEntry(entryPtr); + } + } +#endif + return (result?result:""); +} + +/* + *---------------------------------------------------------------------- + * + * TableSetCellValue -- + * Takes a row,col pair in user coords and saves the given value for + * that cell. This varies depending on what data source the + * user has selected. + * + * Results: + * Returns TCL_ERROR or TCL_OK, depending on whether an error + * occured during set (ie: during evaluation of -command). + * + * Side effects: + * If the value is NULL (empty string), it will be unset from + * an array rather than set to the empty string. + * + *---------------------------------------------------------------------- + */ +int +TableSetCellValue(Table *tablePtr, int r, int c, char *value) +{ + char buf[INDEX_BUFSIZE]; + int code = TCL_OK, flash = 0; + Tcl_Interp *interp = tablePtr->interp; + + TableMakeArrayIndex(r, c, buf); + + if (tablePtr->state == STATE_DISABLED) { + return TCL_OK; + } + if (tablePtr->dataSource & DATA_COMMAND) { + Tcl_DString script; + + Tcl_DStringInit(&script); + ExpandPercents(tablePtr, tablePtr->command, r, c, value, (char *)NULL, + 1, &script, 0); + if (Tcl_GlobalEval(interp, Tcl_DStringValue(&script)) == TCL_ERROR) { + /* An error resulted. Prevent further triggering of the command + * and set up the error message. */ + tablePtr->useCmd = 0; + tablePtr->dataSource &= ~DATA_COMMAND; + if (tablePtr->arrayVar) + tablePtr->dataSource |= DATA_ARRAY; + Tcl_AddErrorInfo(interp, "\n\t(in command executed by table)"); + Tcl_BackgroundError(interp); + code = TCL_ERROR; + } else { + flash = 1; + } + Tcl_SetResult(interp, (char *) NULL, TCL_STATIC); + Tcl_DStringFree(&script); + } + if (tablePtr->dataSource & DATA_ARRAY) { + /* Warning: checking for \0 as the first char could invalidate + * allowing it as a valid first char, but only with incorrect utf-8 + */ + if ((value == NULL || *value == '\0') && tablePtr->sparse) { + Tcl_UnsetVar2(interp, tablePtr->arrayVar, buf, TCL_GLOBAL_ONLY); + value = NULL; + } else if (Tcl_SetVar2(interp, tablePtr->arrayVar, buf, value, + TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) { + code = TCL_ERROR; + } + } + if (code == TCL_ERROR) { + return TCL_ERROR; + } + + /* + * This would be repetitive if we are using the array (which traces). + */ + if (tablePtr->caching && !(tablePtr->dataSource & DATA_ARRAY)) { + Tcl_HashEntry *entryPtr; + int new; + char *val = NULL; + + entryPtr = Tcl_CreateHashEntry(tablePtr->cache, buf, &new); + if (!new) { + val = (char *) Tcl_GetHashValue(entryPtr); + if (val) ckfree(val); + } + if (value) { + val = (char *)ckalloc(strlen(value)+1); + strcpy(val, value); + } + Tcl_SetHashValue(entryPtr, val); + flash = 1; + } + /* We do this conditionally because the var array already has + * it's own check to flash */ + if (flash && tablePtr->flashMode) { + r -= tablePtr->rowOffset; + c -= tablePtr->colOffset; + TableAddFlash(tablePtr, r, c); + TableRefresh(tablePtr, r, c, CELL); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TableMoveCellValue -- + * To move cells faster on delete/insert line or col when cache is on + * and variable, command is off. + * To avoid another call to TableMakeArrayIndex(r, c, buf), + * we optionally provide the buffers. + * outOfBounds means we will just set the cell value to "" + * + * Results: + * Returns TCL_ERROR or TCL_OK, depending on whether an error + * occured during set (ie: during evaluation of -command). + * + * Side effects: + * If the value is NULL (empty string), it will be unset from + * an array rather than set to the empty string. + * + *---------------------------------------------------------------------- + */ +int +TableMoveCellValue(Table *tablePtr, int fromr, int fromc, char *frombuf, + int tor, int toc, char *tobuf, int outOfBounds) +{ + if (outOfBounds) { + return TableSetCellValue(tablePtr, tor, toc, ""); + } + + if (tablePtr->dataSource == DATA_CACHE) { + char *val; + char *result = NULL; + Tcl_HashEntry *entryPtr; + + /* + * Let's see if we have the from value cached. If so, copy + * that to the to cell. The to cell entry value will be + * deleted from the cache, and recreated only if from value + * was not NULL. + * We can be liberal removing our internal cached cells when + * DATA_CACHE is our only data source. + */ + entryPtr = Tcl_FindHashEntry(tablePtr->cache, frombuf); + if (entryPtr) { + result = (char *) Tcl_GetHashValue(entryPtr); + /* + * we set tho old value to NULL + */ + Tcl_DeleteHashEntry(entryPtr); + } + if (result) { + int new; + /* + * We enter here when there was a from value. + * set 'to' to the 'from' value without new mallocing. + */ + entryPtr = Tcl_CreateHashEntry(tablePtr->cache, tobuf, &new); + /* + * free old value + */ + if (!new) { + val = (char *) Tcl_GetHashValue(entryPtr); + if (val) ckfree(val); + } + Tcl_SetHashValue(entryPtr, result); + } else { + entryPtr = Tcl_FindHashEntry(tablePtr->cache, tobuf); + if (entryPtr) { + val = (char *) Tcl_GetHashValue(entryPtr); + if (val) ckfree(val); + Tcl_DeleteHashEntry(entryPtr); + } + } + return TCL_OK; + } + /* + * We have to do it the old way + */ + return TableSetCellValue(tablePtr, tor, toc, + TableGetCellValue(tablePtr, fromr, fromc)); + +} + +/* + *---------------------------------------------------------------------- + * + * TableGetIcursor -- + * Parses the argument as an index into the active cell string. + * Recognises 'end', 'insert' or an integer. Constrains it to the + * size of the buffer. This acts like a "SetIcursor" when *posn is NULL. + * + * Results: + * If (posn != NULL), then it gets the cursor position. + * + * Side effects: + * Can move cursor position. + * + *---------------------------------------------------------------------- + */ +int +TableGetIcursor(Table *tablePtr, char *arg, int *posn) +{ + int tmp, len; + + len = strlen(tablePtr->activeBuf); +#ifdef TCL_UTF_MAX + /* Need to base it off strlen to account for \x00 (Unicode null) */ + len = Tcl_NumUtfChars(tablePtr->activeBuf, len); +#endif + /* ensure icursor didn't get out of sync */ + if (tablePtr->icursor > len) tablePtr->icursor = len; + /* is this end */ + if (strcmp(arg, "end") == 0) { + tmp = len; + } else if (strcmp(arg, "insert") == 0) { + tmp = tablePtr->icursor; + } else { + if (Tcl_GetInt(tablePtr->interp, arg, &tmp) != TCL_OK) { + return TCL_ERROR; + } + CONSTRAIN(tmp, 0, len); + } + if (posn) { + *posn = tmp; + } else { + tablePtr->icursor = tmp; + } + return TCL_OK; +} + +/* + *-------------------------------------------------------------- + * + * TableGetIndex -- + * Parse an index into a table and return either its value + * or an error. + * + * Results: + * A standard Tcl result. If all went well, then *row,*col is + * filled in with the index corresponding to string. If an + * error occurs then an error message is left in interp result. + * The index returned is in user coords. + * + * Side effects: + * Sets row,col index to an appropriately constrained user index. + * + *-------------------------------------------------------------- + */ +int +TableGetIndex(tablePtr, str, row_p, col_p) + register Table *tablePtr; /* Table for which the index is being + * specified. */ + char *str; /* Symbolic specification of cell in table. */ + int *row_p; /* Where to store converted row. */ + int *col_p; /* Where to store converted col. */ +{ + int r, c, len = strlen(str); + char dummy; + + /* + * Note that all of these values will be adjusted by row/ColOffset + */ + if (str[0] == '@') { /* @x,y coordinate */ + int x, y; + + if (sscanf(str+1, "%d,%d%c", &x, &y, &dummy) != 2) { + /* Make sure it won't work for "2,3extrastuff" */ + goto IndexError; + } + TableWhatCell(tablePtr, x, y, &r, &c); + r += tablePtr->rowOffset; + c += tablePtr->colOffset; + } else if (*str == '-' || isdigit(str[0])) { + if (sscanf(str, "%d,%d%c", &r, &c, &dummy) != 2) { + /* Make sure it won't work for "2,3extrastuff" */ + goto IndexError; + } + /* ensure appropriate user index */ + CONSTRAIN(r, tablePtr->rowOffset, + tablePtr->rows-1+tablePtr->rowOffset); + CONSTRAIN(c, tablePtr->colOffset, + tablePtr->cols-1+tablePtr->colOffset); + } else if (len > 1 && strncmp(str, "active", len) == 0 ) { /* active */ + if (tablePtr->flags & HAS_ACTIVE) { + r = tablePtr->activeRow+tablePtr->rowOffset; + c = tablePtr->activeCol+tablePtr->colOffset; + } else { + Tcl_SetObjResult(tablePtr->interp, + Tcl_NewStringObj("no \"active\" cell in table", -1)); + return TCL_ERROR; + } + } else if (len > 1 && strncmp(str, "anchor", len) == 0) { /* anchor */ + if (tablePtr->flags & HAS_ANCHOR) { + r = tablePtr->anchorRow+tablePtr->rowOffset; + c = tablePtr->anchorCol+tablePtr->colOffset; + } else { + Tcl_SetObjResult(tablePtr->interp, + Tcl_NewStringObj("no \"anchor\" cell in table", -1)); + return TCL_ERROR; + } + } else if (strncmp(str, "end", len) == 0) { /* end */ + r = tablePtr->rows-1+tablePtr->rowOffset; + c = tablePtr->cols-1+tablePtr->colOffset; + } else if (strncmp(str, "origin", len) == 0) { /* origin */ + r = tablePtr->titleRows+tablePtr->rowOffset; + c = tablePtr->titleCols+tablePtr->colOffset; + } else if (strncmp(str, "topleft", len) == 0) { /* topleft */ + r = tablePtr->topRow+tablePtr->rowOffset; + c = tablePtr->leftCol+tablePtr->colOffset; + } else if (strncmp(str, "bottomright", len) == 0) { /* bottomright */ + /* + * FIX: Should this avoid spans, or consider them in the bottomright? + tablePtr->flags |= AVOID_SPANS; + tablePtr->flags &= ~AVOID_SPANS; + */ + TableGetLastCell(tablePtr, &r, &c); + r += tablePtr->rowOffset; + c += tablePtr->colOffset; + } else { + IndexError: + Tcl_AppendStringsToObj(Tcl_GetObjResult(tablePtr->interp), + "bad table index \"", str, "\": must be active, anchor, end, ", + "origin, topleft, bottomright, @x,y, or <row>,<col>", + (char *)NULL); + return TCL_ERROR; + } + + /* Note: values are expected to be properly constrained + * as a user index by this point */ + if (row_p) *row_p = r; + if (col_p) *col_p = c; + return TCL_OK; +} + +/* + *-------------------------------------------------------------- + * + * Table_SetCmd -- + * This procedure is invoked to process the set method + * that corresponds to a 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_SetCmd(ClientData clientData, register Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + register Table *tablePtr = (Table *)clientData; + int row, col, len, i, j, max; + char *str; + + /* sets any number of tags/indices to a given value */ + if (objc < 3) { + CMD_SET_USAGE: + Tcl_WrongNumArgs(interp, 2, objv, + "?row|col? index ?value? ?index value ...?"); + return TCL_ERROR; + } + + /* make sure there is a data source to accept set */ + if (tablePtr->dataSource == DATA_NONE) { + return TCL_OK; + } + + str = Tcl_GetStringFromObj(objv[2], &len); + if (strncmp(str, "row", len) == 0 || strncmp(str, "col", len) == 0) { + Tcl_Obj *resultPtr = Tcl_GetObjResult(interp); + /* set row index list ?index list ...? */ + if (objc < 4) { + goto CMD_SET_USAGE; + } else if (objc == 4) { + if (TableGetIndexObj(tablePtr, objv[3], + &row, &col) != TCL_OK) { + return TCL_ERROR; + } + if (*str == 'r') { + max = tablePtr->cols+tablePtr->colOffset; + for (i=col; i<max; i++) { + str = TableGetCellValue(tablePtr, row, i); + Tcl_ListObjAppendElement(NULL, resultPtr, + Tcl_NewStringObj(str, -1)); + } + } else { + max = tablePtr->rows+tablePtr->rowOffset; + for (i=row; i<max; i++) { + str = TableGetCellValue(tablePtr, i, col); + Tcl_ListObjAppendElement(NULL, resultPtr, + Tcl_NewStringObj(str, -1)); + } + } + } else if (tablePtr->state == STATE_NORMAL) { + int listc; + Tcl_Obj **listv; + /* make sure there are an even number of index/list pairs */ + if (objc & 0) { + goto CMD_SET_USAGE; + } + for (i = 3; i < objc-1; i += 2) { + if ((TableGetIndexObj(tablePtr, objv[i], + &row, &col) != TCL_OK) || + (Tcl_ListObjGetElements(interp, objv[i+1], + &listc, &listv) != TCL_OK)) { + return TCL_ERROR; + } + if (*str == 'r') { + max = col+MIN(tablePtr->cols+tablePtr->colOffset-col, + listc); + for (j = col; j < max; j++) { + if (TableSetCellValue(tablePtr, row, j, + Tcl_GetString(listv[j-col])) + != TCL_OK) { + return TCL_ERROR; + } + if (row-tablePtr->rowOffset == tablePtr->activeRow && + j-tablePtr->colOffset == tablePtr->activeCol) { + TableGetActiveBuf(tablePtr); + } + TableRefresh(tablePtr, row-tablePtr->rowOffset, + j-tablePtr->colOffset, CELL); + } + } else { + max = row+MIN(tablePtr->rows+tablePtr->rowOffset-row, + listc); + for (j = row; j < max; j++) { + if (TableSetCellValue(tablePtr, j, col, + Tcl_GetString(listv[j-row])) + != TCL_OK) { + return TCL_ERROR; + } + if (j-tablePtr->rowOffset == tablePtr->activeRow && + col-tablePtr->colOffset == tablePtr->activeCol) { + TableGetActiveBuf(tablePtr); + } + TableRefresh(tablePtr, j-tablePtr->rowOffset, + col-tablePtr->colOffset, CELL); + } + } + } + } + } else if (objc == 3) { + /* set index */ + if (TableGetIndexObj(tablePtr, objv[2], &row, &col) != TCL_OK) { + return TCL_ERROR; + } else { + /* + * Cannot use Tcl_GetObjResult here because TableGetCellValue + * can corrupt the resultPtr. + */ + Tcl_SetObjResult(interp, Tcl_NewStringObj( + TableGetCellValue(tablePtr, row, col),-1)); + } + } else { + /* set index val ?index val ...? */ + /* make sure there are an even number of index/value pairs */ + if (objc & 1) { + goto CMD_SET_USAGE; + } + for (i = 2; i < objc-1; i += 2) { + if ((TableGetIndexObj(tablePtr, objv[i], &row, &col) != TCL_OK) || + (TableSetCellValue(tablePtr, row, col, + Tcl_GetString(objv[i+1])) != TCL_OK)) { + return TCL_ERROR; + } + row -= tablePtr->rowOffset; + col -= tablePtr->colOffset; + if (row == tablePtr->activeRow && col == tablePtr->activeCol) { + TableGetActiveBuf(tablePtr); + } + TableRefresh(tablePtr, row, col, CELL); + } + } + return TCL_OK; +} + +/* + *-------------------------------------------------------------- + * + * Table_SpanSet -- + * Takes row,col in user coords and sets a span on the + * cell if possible + * + * Results: + * A standard Tcl result + * + * Side effects: + * The span can be constrained + * + *-------------------------------------------------------------- + */ +static int +Table_SpanSet(register Table *tablePtr, int urow, int ucol, int rs, int cs) +{ + Tcl_Interp *interp = tablePtr->interp; + int i, j, new, ors, ocs, result = TCL_OK; + int row, col; + Tcl_HashEntry *entryPtr; + Tcl_HashSearch search; + char *dbuf, buf[INDEX_BUFSIZE], cell[INDEX_BUFSIZE], span[INDEX_BUFSIZE]; + + row = urow - tablePtr->rowOffset; + col = ucol - tablePtr->colOffset; + + TableMakeArrayIndex(urow, ucol, cell); + + if (tablePtr->spanTbl == NULL) { + tablePtr->spanTbl = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(tablePtr->spanTbl, TCL_STRING_KEYS); + tablePtr->spanAffTbl = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(tablePtr->spanAffTbl, TCL_STRING_KEYS); + } + + /* first check in the affected cells table */ + if ((entryPtr=Tcl_FindHashEntry(tablePtr->spanAffTbl, cell)) != NULL) { + /* We have to make sure this was not already hidden + * that's an error */ + if ((char *)Tcl_GetHashValue(entryPtr) != NULL) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "cannot set spanning on hidden cell ", + cell, (char *) NULL); + return TCL_ERROR; + } + } + /* do constraints on the spans + * title cells must not expand beyond the titles + * other cells can't expand negatively into title area + */ + if ((row < tablePtr->titleRows) && + (row + rs >= tablePtr->titleRows)) { + rs = tablePtr->titleRows - row - 1; + } + if ((col < tablePtr->titleCols) && + (col + cs >= tablePtr->titleCols)) { + cs = tablePtr->titleCols - col - 1; + } + rs = MAX(0, rs); + cs = MAX(0, cs); + + /* then work in the span cells table */ + if ((entryPtr = Tcl_FindHashEntry(tablePtr->spanTbl, cell)) != NULL) { + /* We have to readjust for what was there first */ + TableParseArrayIndex(&ors, &ocs, (char *)Tcl_GetHashValue(entryPtr)); + ckfree((char *) Tcl_GetHashValue(entryPtr)); + Tcl_DeleteHashEntry(entryPtr); + for (i = urow; i <= urow+ors; i++) { + for (j = ucol; j <= ucol+ocs; j++) { + TableMakeArrayIndex(i, j, buf); + entryPtr = Tcl_FindHashEntry(tablePtr->spanAffTbl, buf); + if (entryPtr != NULL) { + Tcl_DeleteHashEntry(entryPtr); + } + TableRefresh(tablePtr, i-tablePtr->rowOffset, + j-tablePtr->colOffset, CELL); + } + } + } else { + ors = ocs = 0; + } + + /* calc to make sure that span is OK */ + for (i = urow; i <= urow+rs; i++) { + for (j = ucol; j <= ucol+cs; j++) { + TableMakeArrayIndex(i, j, buf); + entryPtr = Tcl_FindHashEntry(tablePtr->spanAffTbl, buf); + if (entryPtr != NULL) { + /* Something already spans here */ + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "cannot overlap already spanned cell ", + buf, (char *) NULL); + result = TCL_ERROR; + rs = ors; + cs = ocs; + break; + } + } + if (result == TCL_ERROR) + break; + } + + /* 0,0 span means set to unspanned again */ + if (rs == 0 && cs == 0) { + entryPtr = Tcl_FindHashEntry(tablePtr->spanTbl, cell); + if (entryPtr != NULL) { + ckfree((char *) Tcl_GetHashValue(entryPtr)); + Tcl_DeleteHashEntry(entryPtr); + } + entryPtr = Tcl_FindHashEntry(tablePtr->spanAffTbl, cell); + if (entryPtr != NULL) { + Tcl_DeleteHashEntry(entryPtr); + } + if (Tcl_FirstHashEntry(tablePtr->spanTbl, &search) == NULL) { + /* There are no more spans, so delete tables to improve + * performance of TableCellCoords */ + Tcl_DeleteHashTable(tablePtr->spanTbl); + ckfree((char *) (tablePtr->spanTbl)); + Tcl_DeleteHashTable(tablePtr->spanAffTbl); + ckfree((char *) (tablePtr->spanAffTbl)); + tablePtr->spanTbl = NULL; + tablePtr->spanAffTbl = NULL; + } + return result; + } + + /* Make sure there is no extra stuff */ + TableMakeArrayIndex(rs, cs, span); + + /* Set affected cell table to a NULL value */ + entryPtr = Tcl_CreateHashEntry(tablePtr->spanAffTbl, cell, &new); + Tcl_SetHashValue(entryPtr, (char *) NULL); + /* set the spanning cells table with span value */ + entryPtr = Tcl_CreateHashEntry(tablePtr->spanTbl, cell, &new); + dbuf = (char *)ckalloc(strlen(span)+1); + strcpy(dbuf, span); + Tcl_SetHashValue(entryPtr, dbuf); + dbuf = Tcl_GetHashKey(tablePtr->spanTbl, entryPtr); + /* Set other affected cells */ + EmbWinUnmap(tablePtr, row, row + rs, col, col + cs); + for (i = urow; i <= urow+rs; i++) { + for (j = ucol; j <= ucol+cs; j++) { + TableMakeArrayIndex(i, j, buf); + entryPtr = Tcl_CreateHashEntry(tablePtr->spanAffTbl, buf, &new); + if (!(i == urow && j == ucol)) { + Tcl_SetHashValue(entryPtr, (char *) dbuf); + } + } + } + TableRefresh(tablePtr, row, col, CELL); + return result; +} + +/* + *-------------------------------------------------------------- + * + * Table_SpanCmd -- + * This procedure is invoked to process the span method + * that corresponds to a 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_SpanCmd(ClientData clientData, register Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + register Table *tablePtr = (Table *) clientData; + int rs, cs, row, col, i; + Tcl_HashEntry *entryPtr; + + if (objc < 2 || (objc > 4 && (objc&1))) { + Tcl_WrongNumArgs(interp, 2, objv, + "?index? ?rows,cols index rows,cols ...?"); + return TCL_ERROR; + } + + if (objc == 2) { + if (tablePtr->spanTbl) { + Tcl_HashSearch search; + Tcl_Obj *objPtr, *resultPtr = Tcl_NewObj(); + + for (entryPtr = Tcl_FirstHashEntry(tablePtr->spanTbl, &search); + entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) { + objPtr = Tcl_NewStringObj(Tcl_GetHashKey(tablePtr->spanTbl, + entryPtr), -1); + Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); + objPtr = Tcl_NewStringObj((char *) Tcl_GetHashValue(entryPtr), + -1); + Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); + } + Tcl_SetObjResult(interp, resultPtr); + } + return TCL_OK; + } else if (objc == 3) { + if (TableGetIndexObj(tablePtr, objv[2], &row, &col) == TCL_ERROR) { + return TCL_ERROR; + } + /* Just return the spanning values of the one cell */ + if (tablePtr->spanTbl && + (entryPtr = Tcl_FindHashEntry(tablePtr->spanTbl, + Tcl_GetString(objv[2]))) != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj((char *)Tcl_GetHashValue(entryPtr), -1)); + } + return TCL_OK; + } else { + for (i = 2; i < objc-1; i += 2) { + if (TableGetIndexObj(tablePtr, objv[i], &row, &col) == TCL_ERROR || + (TableParseArrayIndex(&rs, &cs, + Tcl_GetString(objv[i+1])) != 2) || + Table_SpanSet(tablePtr, row, col, rs, cs) == TCL_ERROR) { + return TCL_ERROR; + } + } + } + return TCL_OK; +} + +/* + *-------------------------------------------------------------- + * + * Table_HiddenCmd -- + * This procedure is invoked to process the hidden method + * that corresponds to a 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_HiddenCmd(ClientData clientData, register Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + register Table *tablePtr = (Table *) clientData; + int i, row, col; + Tcl_HashEntry *entryPtr; + char *span; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 2, objv, "?index? ?index ...?"); + return TCL_ERROR; + } + if (tablePtr->spanTbl == NULL) { + /* Avoid the whole thing if we have no spans */ + if (objc > 3) { + Tcl_SetBooleanObj(Tcl_GetObjResult(interp), 0); + } + return TCL_OK; + } + if (objc == 2) { + /* return all "hidden" cells */ + Tcl_HashSearch search; + Tcl_Obj *objPtr = Tcl_NewObj(); + + for (entryPtr = Tcl_FirstHashEntry(tablePtr->spanAffTbl, &search); + entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) { + if ((span = (char *) Tcl_GetHashValue(entryPtr)) == NULL) { + /* this is actually a spanning cell */ + continue; + } + Tcl_ListObjAppendElement(NULL, objPtr, + Tcl_NewStringObj(Tcl_GetHashKey(tablePtr->spanAffTbl, + entryPtr), -1)); + } + Tcl_SetObjResult(interp, TableCellSortObj(interp, objPtr)); + return TCL_OK; + } + if (objc == 3) { + if (TableGetIndexObj(tablePtr, objv[2], &row, &col) != TCL_OK) { + return TCL_ERROR; + } + /* Just return the spanning values of the one cell */ + entryPtr = Tcl_FindHashEntry(tablePtr->spanAffTbl, + Tcl_GetString(objv[2])); + if (entryPtr != NULL && + (span = (char *)Tcl_GetHashValue(entryPtr)) != NULL) { + /* this is a hidden cell */ + Tcl_SetObjResult(interp, Tcl_NewStringObj(span, -1)); + } + return TCL_OK; + } + for (i = 2; i < objc; i++) { + if (TableGetIndexObj(tablePtr, objv[i], &row, &col) == TCL_ERROR) { + return TCL_ERROR; + } + entryPtr = Tcl_FindHashEntry(tablePtr->spanAffTbl, + Tcl_GetString(objv[i])); + if (entryPtr != NULL && + (char *)Tcl_GetHashValue(entryPtr) != NULL) { + /* this is a hidden cell */ + continue; + } + /* We only reach here if it doesn't satisfy "hidden" criteria */ + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0)); + return TCL_OK; + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1)); + return TCL_OK; +} + +/* + *-------------------------------------------------------------- + * + * TableSpanSanCheck -- + * This procedure is invoked by TableConfigure to make sure + * that spans are kept sane according to the docs. + * See the user documentation for details on what it does. + * + * Results: + * void. + * + * Side effects: + * Spans in title areas can be reconstrained. + * + *-------------------------------------------------------------- + */ +void +TableSpanSanCheck(register Table *tablePtr) +{ + int rs, cs, row, col, reset; + Tcl_HashEntry *entryPtr; + Tcl_HashSearch search; + + if (tablePtr->spanTbl == NULL) { + return; + } + + for (entryPtr = Tcl_FirstHashEntry(tablePtr->spanTbl, &search); + entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) { + reset = 0; + TableParseArrayIndex(&row, &col, + Tcl_GetHashKey(tablePtr->spanTbl, entryPtr)); + TableParseArrayIndex(&rs, &cs, + (char *) Tcl_GetHashValue(entryPtr)); + if ((row-tablePtr->rowOffset < tablePtr->titleRows) && + (row-tablePtr->rowOffset+rs >= tablePtr->titleRows)) { + rs = tablePtr->titleRows-(row-tablePtr->rowOffset)-1; + reset = 1; + } + if ((col-tablePtr->colOffset < tablePtr->titleCols) && + (col-tablePtr->colOffset+cs >= tablePtr->titleCols)) { + cs = tablePtr->titleCols-(col-tablePtr->colOffset)-1; + reset = 1; + } + if (reset) { + Table_SpanSet(tablePtr, row, col, rs, cs); + } + } +} diff --git a/tktable/generic/tkTableCellSort.c b/tktable/generic/tkTableCellSort.c new file mode 100644 index 0000000..b2a7837 --- /dev/null +++ b/tktable/generic/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-2002 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; + CONST84 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/tktable/generic/tkTableCmds.c b/tktable/generic/tkTableCmds.c new file mode 100755 index 0000000..3668b01 --- /dev/null +++ b/tktable/generic/tkTableCmds.c @@ -0,0 +1,1306 @@ +/* + * tkTableCmds.c -- + * + * This module implements general commands of a table widget, + * based on the major/minor command structure. + * + * Copyright (c) 1998-2002 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, templen; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + return TCL_ERROR; + } else if (Tcl_GetStringFromObj(objv[2], &templen), templen == 0) { + /* + * Test implementation to clear active cell (becroft) + */ + tablePtr->flags &= ~HAS_ACTIVE; + tablePtr->flags |= ACTIVE_DISABLED; + tablePtr->activeRow = -1; + tablePtr->activeCol = -1; + TableAdjustActive(tablePtr); + TableConfigCursor(tablePtr); + } 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; + p++; + 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 CONST84 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 CONST84 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) { + Table_ClearHashTable(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], *value; + + 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))) { + value = (char *) Tcl_GetHashValue(entryPtr); + if (value) { ckfree(value); } + 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_SetObjResult(interp, Tcl_NewStringObj(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/tktable/generic/tkTableEdit.c b/tktable/generic/tkTableEdit.c new file mode 100644 index 0000000..4c56710 --- /dev/null +++ b/tktable/generic/tkTableEdit.c @@ -0,0 +1,723 @@ +/* + * 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: tkTableEdit.c,v 1.3 2016/01/27 19:43:23 joye Exp $ + */ + +#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 CONST84 char *modCmdNames[] = { + "active", "cols", "rows", (char *)NULL +}; +enum modCmd { + MOD_ACTIVE, MOD_COLS, MOD_ROWS +}; + +/* insert/delete row/col switches */ +static CONST84 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; + } + /* + * We need to call TableAdjustParams before TableModifyRC to + * ensure that side effect code like var traces that might get + * called will access the correct new dimensions. + */ + if (*dimPtr < 1) { + *dimPtr = 1; + } + TableAdjustParams(tablePtr); + 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)); + } + if (!(flags & HOLD_WINS)) { + /* + * This may be a little severe, but it does unmap the + * windows that need to be unmapped, and those that should + * stay do remap correctly. [Bug #551325] + */ + if (doRows) { + EmbWinUnmap(tablePtr, + first - tablePtr->rowOffset, + maxkey - tablePtr->rowOffset, + lo - tablePtr->colOffset, + hi - tablePtr->colOffset); + } else { + EmbWinUnmap(tablePtr, + lo - tablePtr->rowOffset, + hi - tablePtr->rowOffset, + first - tablePtr->colOffset, + maxkey - tablePtr->colOffset); + } + } + } 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; + } + /* + * We need to call TableAdjustParams before TableModifyRC to + * ensure that side effect code like var traces that might get + * called will access the correct new dimensions. + */ + if (*dimPtr < 1) { + *dimPtr = 1; + } + TableAdjustParams(tablePtr); + 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. + */ + if (*dimPtr < 1) { + *dimPtr = 1; + 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/tktable/generic/tkTableInitScript.h b/tktable/generic/tkTableInitScript.h new file mode 100644 index 0000000..a61d19b --- /dev/null +++ b/tktable/generic/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" PACKAGE_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/tktable/generic/tkTablePs.c b/tktable/generic/tkTablePs.c new file mode 100644 index 0000000..018f079 --- /dev/null +++ b/tktable/generic/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/tktable/generic/tkTableTag.c b/tktable/generic/tkTableTag.c new file mode 100644 index 0000000..f3d7ee8 --- /dev/null +++ b/tktable/generic/tkTableTag.c @@ -0,0 +1,1354 @@ +/* + * tkTableTag.c -- + * + * This module implements tags for table widgets. + * + * Copyright (c) 1998-2002 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: tkTableTag.c,v 1.3 2016/01/27 19:43:23 joye Exp $ + */ + +#include "tkTable.h" + +static TableTag *TableTagGetEntry _ANSI_ARGS_((Table *tablePtr, char *name, + int objc, CONST char **argv)); +static unsigned int TableTagGetPriority _ANSI_ARGS_((Table *tablePtr, + TableTag *tagPtr)); +static void TableImageProc _ANSI_ARGS_((ClientData clientData, int x, + int y, int width, int height, int imageWidth, int imageHeight)); +static int TableOptionReliefSet _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, Tk_Window tkwin, + CONST84 char *value, char *widgRec, int offset)); +static char * TableOptionReliefGet _ANSI_ARGS_((ClientData clientData, + Tk_Window tkwin, char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr)); + +static CONST84 char *tagCmdNames[] = { + "celltag", "cget", "coltag", "configure", "delete", "exists", + "includes", "lower", "names", "raise", "rowtag", (char *) NULL +}; + +enum tagCmd { + TAG_CELLTAG, TAG_CGET, TAG_COLTAG, TAG_CONFIGURE, TAG_DELETE, TAG_EXISTS, + TAG_INCLUDES, TAG_LOWER, TAG_NAMES, TAG_RAISE, TAG_ROWTAG +}; + +static Cmd_Struct tagState_vals[]= { + {"unknown", STATE_UNKNOWN}, + {"normal", STATE_NORMAL}, + {"disabled", STATE_DISABLED}, + {"", 0 } +}; + +static Tk_CustomOption tagStateOpt = +{ Cmd_OptionSet, Cmd_OptionGet, (ClientData) (&tagState_vals) }; +static Tk_CustomOption tagBdOpt = +{ TableOptionBdSet, TableOptionBdGet, (ClientData) BD_TABLE_TAG }; +static Tk_CustomOption tagReliefOpt = +{ TableOptionReliefSet, TableOptionReliefGet, (ClientData) NULL }; + +/* + * The default specification for configuring tags + * Done like this to make the command line parsing easy + */ + +static Tk_ConfigSpec tagConfig[] = { + {TK_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor", "center", + Tk_Offset(TableTag, anchor), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, + {TK_CONFIG_BORDER, "-background", "background", "Background", NULL, + Tk_Offset(TableTag, bg), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, + {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL, (char *)NULL, 0, 0}, + {TK_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0}, + {TK_CONFIG_CUSTOM, "-borderwidth", "borderWidth", "BorderWidth", "", + 0 /* no offset */, + TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK, &tagBdOpt }, + {TK_CONFIG_STRING, "-ellipsis", "ellipsis", "Ellipsis", "", + Tk_Offset(TableTag, ellipsis), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, + {TK_CONFIG_BORDER, "-foreground", "foreground", "Foreground", NULL, + Tk_Offset(TableTag, fg), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, + {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL, (char *)NULL, 0, 0}, + {TK_CONFIG_FONT, "-font", "font", "Font", NULL, + Tk_Offset(TableTag, tkfont), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, + {TK_CONFIG_STRING, "-image", "image", "Image", NULL, + Tk_Offset(TableTag, imageStr), + TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, + {TK_CONFIG_JUSTIFY, "-justify", "justify", "Justify", "left", + Tk_Offset(TableTag, justify), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, + {TK_CONFIG_INT, "-multiline", "multiline", "Multiline", "-1", + Tk_Offset(TableTag, multiline), TK_CONFIG_DONT_SET_DEFAULT }, + {TK_CONFIG_CUSTOM, "-relief", "relief", "Relief", "flat", + Tk_Offset(TableTag, relief), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK, + &tagReliefOpt }, + {TK_CONFIG_INT, "-showtext", "showText", "ShowText", "-1", + Tk_Offset(TableTag, showtext), TK_CONFIG_DONT_SET_DEFAULT }, + {TK_CONFIG_CUSTOM, "-state", "state", "State", "unknown", + Tk_Offset(TableTag, state), TK_CONFIG_DONT_SET_DEFAULT, &tagStateOpt }, + {TK_CONFIG_INT, "-wrap", "wrap", "Wrap", "-1", + Tk_Offset(TableTag, wrap), TK_CONFIG_DONT_SET_DEFAULT }, + {TK_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, 0, 0} +}; + +/* + * The join tag structure is used to create a combined tag, so it + * keeps priority info. + */ +typedef struct { + TableTag tag; /* must be first */ + unsigned int magic; + unsigned int pbg, pfg, pborders, prelief, ptkfont, panchor, pimage; + unsigned int pstate, pjustify, pmultiline, pwrap, pshowtext, pellipsis; +} TableJoinTag; + +/* + *---------------------------------------------------------------------- + * + * TableImageProc -- + * Called when an image associated with a tag is changed. + * + * Results: + * None. + * + * Side effects: + * Invalidates the whole table. + * This should only invalidate affected cells, but that info + * is not managed... + * + *---------------------------------------------------------------------- + */ +static void +TableImageProc(ClientData clientData, int x, int y, int width, int height, + int imageWidth, int imageHeight) +{ + TableInvalidateAll((Table *)clientData, 0); +} + +/* + *---------------------------------------------------------------------- + * + * TableNewTag -- + * ckallocs space for a new tag structure and inits the structure. + * + * Results: + * Returns a pointer to the new structure. Must be freed later. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +TableTag * +TableNewTag(Table *tablePtr) +{ + TableTag *tagPtr; + + /* + * If tablePtr is NULL, make a regular tag, otherwise make a join tag. + */ + if (tablePtr == NULL) { + tagPtr = (TableTag *) ckalloc(sizeof(TableTag)); + memset((VOID *) tagPtr, 0, sizeof(TableTag)); + + /* + * Set the values that aren't 0/NULL by default + */ + tagPtr->anchor = (Tk_Anchor)-1; + tagPtr->justify = (Tk_Justify)-1; + tagPtr->multiline = -1; + tagPtr->relief = -1; + tagPtr->showtext = -1; + tagPtr->state = STATE_UNKNOWN; + tagPtr->wrap = -1; + } else { + TableJoinTag *jtagPtr = (TableJoinTag *) ckalloc(sizeof(TableJoinTag)); + memset((VOID *) jtagPtr, 0, sizeof(TableJoinTag)); + tagPtr = (TableTag *) jtagPtr; + + tagPtr->anchor = (Tk_Anchor)-1; + tagPtr->justify = (Tk_Justify)-1; + tagPtr->multiline = -1; + tagPtr->relief = -1; + tagPtr->showtext = -1; + tagPtr->state = STATE_UNKNOWN; + tagPtr->wrap = -1; + jtagPtr->magic = 0x99ABCDEF; + jtagPtr->pbg = -1; + jtagPtr->pfg = -1; + jtagPtr->pborders = -1; + jtagPtr->prelief = -1; + jtagPtr->ptkfont = -1; + jtagPtr->panchor = -1; + jtagPtr->pimage = -1; + jtagPtr->pstate = -1; + jtagPtr->pjustify = -1; + jtagPtr->pmultiline = -1; + jtagPtr->pwrap = -1; + jtagPtr->pshowtext = -1; + jtagPtr->pellipsis = -1; + } + + return (TableTag *) tagPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TableResetTag -- + * This routine resets a given tag to the table defaults. + * + * Results: + * Tag will have values changed. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +void +TableResetTag(Table *tablePtr, TableTag *tagPtr) +{ + TableJoinTag *jtagPtr = (TableJoinTag *) tagPtr; + + if (jtagPtr->magic != 0x99ABCDEF) { + panic("bad mojo in TableResetTag"); + } + + memset((VOID *) jtagPtr, 0, sizeof(TableJoinTag)); + + tagPtr->anchor = (Tk_Anchor)-1; + tagPtr->justify = (Tk_Justify)-1; + tagPtr->multiline = -1; + tagPtr->relief = -1; + tagPtr->showtext = -1; + tagPtr->state = STATE_UNKNOWN; + tagPtr->wrap = -1; + jtagPtr->magic = 0x99ABCDEF; + jtagPtr->pbg = -1; + jtagPtr->pfg = -1; + jtagPtr->pborders = -1; + jtagPtr->prelief = -1; + jtagPtr->ptkfont = -1; + jtagPtr->panchor = -1; + jtagPtr->pimage = -1; + jtagPtr->pstate = -1; + jtagPtr->pjustify = -1; + jtagPtr->pmultiline = -1; + jtagPtr->pwrap = -1; + jtagPtr->pshowtext = -1; + jtagPtr->pellipsis = -1; + + /* + * Merge in the default tag. + */ + memcpy((VOID *) jtagPtr, (VOID *) &(tablePtr->defaultTag), + sizeof(TableTag)); +} + +/* + *---------------------------------------------------------------------- + * + * TableMergeTag -- + * This routine merges two tags by adding any fields from the addTag + * that are set to the baseTag. + * + * Results: + * baseTag will inherit all set characteristics of addTag + * (addTag thus has the priority). + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +void +TableMergeTag(Table *tablePtr, TableTag *baseTag, TableTag *addTag) +{ + TableJoinTag *jtagPtr = (TableJoinTag *) baseTag; + unsigned int prio; + + if (jtagPtr->magic != 0x99ABCDEF) { + panic("bad mojo in TableMergeTag"); + } + +#ifndef NO_TAG_PRIORITIES + /* + * Find priority for the tag to merge + */ + prio = TableTagGetPriority(tablePtr, addTag); + + if ((addTag->anchor != -1) && (prio < jtagPtr->panchor)) { + baseTag->anchor = addTag->anchor; + jtagPtr->panchor = prio; + } + if ((addTag->bg != NULL) && (prio < jtagPtr->pbg)) { + baseTag->bg = addTag->bg; + jtagPtr->pbg = prio; + } + if ((addTag->fg != NULL) && (prio < jtagPtr->pfg)) { + baseTag->fg = addTag->fg; + jtagPtr->pfg = prio; + } + if ((addTag->ellipsis != NULL) && (prio < jtagPtr->pellipsis)) { + baseTag->ellipsis = addTag->ellipsis; + jtagPtr->pellipsis = prio; + } + if ((addTag->tkfont != NULL) && (prio < jtagPtr->ptkfont)) { + baseTag->tkfont = addTag->tkfont; + jtagPtr->ptkfont = prio; + } + if ((addTag->imageStr != NULL) && (prio < jtagPtr->pimage)) { + baseTag->imageStr = addTag->imageStr; + baseTag->image = addTag->image; + jtagPtr->pimage = prio; + } + if ((addTag->multiline >= 0) && (prio < jtagPtr->pmultiline)) { + baseTag->multiline = addTag->multiline; + jtagPtr->pmultiline = prio; + } + if ((addTag->relief != -1) && (prio < jtagPtr->prelief)) { + baseTag->relief = addTag->relief; + jtagPtr->prelief = prio; + } + if ((addTag->showtext >= 0) && (prio < jtagPtr->pshowtext)) { + baseTag->showtext = addTag->showtext; + jtagPtr->pshowtext = prio; + } + if ((addTag->state != STATE_UNKNOWN) && (prio < jtagPtr->pstate)) { + baseTag->state = addTag->state; + jtagPtr->pstate = prio; + } + if ((addTag->justify != -1) && (prio < jtagPtr->pjustify)) { + baseTag->justify = addTag->justify; + jtagPtr->pjustify = prio; + } + if ((addTag->wrap >= 0) && (prio < jtagPtr->pwrap)) { + baseTag->wrap = addTag->wrap; + jtagPtr->pwrap = prio; + } + if ((addTag->borders) && (prio < jtagPtr->pborders)) { + baseTag->borderStr = addTag->borderStr; + baseTag->borders = addTag->borders; + baseTag->bd[0] = addTag->bd[0]; + baseTag->bd[1] = addTag->bd[1]; + baseTag->bd[2] = addTag->bd[2]; + baseTag->bd[3] = addTag->bd[3]; + jtagPtr->pborders = prio; + } +#else + if (addTag->anchor != -1) baseTag->anchor = addTag->anchor; + if (addTag->bg != NULL) baseTag->bg = addTag->bg; + if (addTag->fg != NULL) baseTag->fg = addTag->fg; + if (addTag->ellipsis != NULL) baseTag->ellipsis = addTag->ellipsis; + if (addTag->tkfont != NULL) baseTag->tkfont = addTag->tkfont; + if (addTag->imageStr != NULL) { + baseTag->imageStr = addTag->imageStr; + baseTag->image = addTag->image; + } + if (addTag->multiline >= 0) baseTag->multiline = addTag->multiline; + if (addTag->relief != -1) baseTag->relief = addTag->relief; + if (addTag->showtext >= 0) baseTag->showtext = addTag->showtext; + if (addTag->state != STATE_UNKNOWN) baseTag->state = addTag->state; + if (addTag->justify != -1) baseTag->justify = addTag->justify; + if (addTag->wrap >= 0) baseTag->wrap = addTag->wrap; + if (addTag->borders) { + baseTag->borderStr = addTag->borderStr; + baseTag->borders = addTag->borders; + baseTag->bd[0] = addTag->bd[0]; + baseTag->bd[1] = addTag->bd[1]; + baseTag->bd[2] = addTag->bd[2]; + baseTag->bd[3] = addTag->bd[3]; + } +#endif +} + +/* + *---------------------------------------------------------------------- + * + * TableInvertTag -- + * This routine swaps background and foreground for the selected tag. + * + * Results: + * Inverts fg and bg of tag. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +void +TableInvertTag(TableTag *baseTag) +{ + Tk_3DBorder tmpBg; + + tmpBg = baseTag->fg; + baseTag->fg = baseTag->bg; + baseTag->bg = tmpBg; +} + +/* + *---------------------------------------------------------------------- + * + * TableGetTagBorders -- + * This routine gets the border values based on a tag. + * + * Results: + * It returns the values in the int*'s (if not NULL), and the + * total number of defined borders as a result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +int +TableGetTagBorders(TableTag *tagPtr, + int *left, int *right, int *top, int *bottom) +{ + switch (tagPtr->borders) { + case 0: + if (left) { *left = 0; } + if (right) { *right = 0; } + if (top) { *top = 0; } + if (bottom) { *bottom = 0; } + break; + case 1: + if (left) { *left = tagPtr->bd[0]; } + if (right) { *right = tagPtr->bd[0]; } + if (top) { *top = tagPtr->bd[0]; } + if (bottom) { *bottom = tagPtr->bd[0]; } + break; + case 2: + if (left) { *left = tagPtr->bd[0]; } + if (right) { *right = tagPtr->bd[1]; } + if (top) { *top = 0; } + if (bottom) { *bottom = 0; } + break; + case 4: + if (left) { *left = tagPtr->bd[0]; } + if (right) { *right = tagPtr->bd[1]; } + if (top) { *top = tagPtr->bd[2]; } + if (bottom) { *bottom = tagPtr->bd[3]; } + break; + default: + panic("invalid border value '%d'\n", tagPtr->borders); + break; + } + return tagPtr->borders; +} + +/* + *---------------------------------------------------------------------- + * + * TableTagGetEntry -- + * Takes a name and optional args and creates a tag entry in the + * table's tag table. + * + * Results: + * A new tag entry will be created and returned. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +static TableTag * +TableTagGetEntry(Table *tablePtr, char *name, int objc, CONST char **argv) +{ + Tcl_HashEntry *entryPtr; + TableTag *tagPtr = NULL; + int new; + + entryPtr = Tcl_CreateHashEntry(tablePtr->tagTable, name, &new); + if (new) { + tagPtr = TableNewTag(NULL); + Tcl_SetHashValue(entryPtr, (ClientData) tagPtr); + if (tablePtr->tagPrioSize >= tablePtr->tagPrioMax) { + int i; + /* + * Increase the priority list size in blocks of 10 + */ + tablePtr->tagPrioMax += 10; + tablePtr->tagPrioNames = (char **) ckrealloc( + (char *) tablePtr->tagPrioNames, + sizeof(TableTag *) * tablePtr->tagPrioMax); + tablePtr->tagPrios = (TableTag **) ckrealloc( + (char *) tablePtr->tagPrios, + sizeof(TableTag *) * tablePtr->tagPrioMax); + for (i = tablePtr->tagPrioSize; i < tablePtr->tagPrioMax; i++) { + tablePtr->tagPrioNames[i] = (char *) NULL; + tablePtr->tagPrios[i] = (TableTag *) NULL; + } + } + tablePtr->tagPrioNames[tablePtr->tagPrioSize] = + (char *) Tcl_GetHashKey(tablePtr->tagTable, entryPtr); + tablePtr->tagPrios[tablePtr->tagPrioSize] = tagPtr; + tablePtr->tagPrioSize++; + } else { + tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr); + } + if (objc) { + Tk_ConfigureWidget(tablePtr->interp, tablePtr->tkwin, tagConfig, + objc, (CONST84 char **) argv, (char *)tagPtr, + TK_CONFIG_ARGV_ONLY); + } + return tagPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TableTagGetPriority -- + * Get the priority value for a tag. + * + * Results: + * returns the priority. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +static unsigned int +TableTagGetPriority(Table *tablePtr, TableTag *tagPtr) +{ + unsigned int prio = 0; + while (tagPtr != tablePtr->tagPrios[prio]) { prio++; } + return prio; +} + +/* + *---------------------------------------------------------------------- + * + * TableInitTags -- + * Creates the static table tags. + * + * Results: + * active, sel, title and flash are created as tags. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +void +TableInitTags(Table *tablePtr) +{ + static CONST char *activeArgs[] = {"-bg", ACTIVE_BG, "-relief", "flat" }; + static CONST char *selArgs[] = {"-bg", SELECT_BG, "-fg", SELECT_FG, + "-relief", "sunken" }; + static CONST char *titleArgs[] = {"-bg", DISABLED, "-fg", "white", + "-relief", "flat", + "-state", "disabled" }; + static CONST char *flashArgs[] = {"-bg", "red" }; + /* + * The order of creation is important to priority. + */ + TableTagGetEntry(tablePtr, "flash", ARSIZE(flashArgs), flashArgs); + TableTagGetEntry(tablePtr, "active", ARSIZE(activeArgs), activeArgs); + TableTagGetEntry(tablePtr, "sel", ARSIZE(selArgs), selArgs); + TableTagGetEntry(tablePtr, "title", ARSIZE(titleArgs), titleArgs); +} + +/* + *---------------------------------------------------------------------- + * + * FindRowColTag -- + * Finds a row/col tag based on the row/col styles and tagCommand. + * + * Results: + * Returns tag associated with row/col cell, if any. + * + * Side effects: + * Possible side effects from eval of tagCommand. + * IMPORTANT: This plays with the interp result object, + * so use of resultPtr in prior command may be invalid after + * calling this function. + * + *---------------------------------------------------------------------- + */ +TableTag * +FindRowColTag(Table *tablePtr, int cell, int mode) +{ + Tcl_HashEntry *entryPtr; + TableTag *tagPtr = NULL; + + entryPtr = Tcl_FindHashEntry((mode == ROW) ? tablePtr->rowStyles + : tablePtr->colStyles, (char *) cell); + if (entryPtr == NULL) { + char *cmd = (mode == ROW) ? tablePtr->rowTagCmd : tablePtr->colTagCmd; + if (cmd) { + register Tcl_Interp *interp = tablePtr->interp; + char buf[INDEX_BUFSIZE]; + /* + * Since no specific row/col tag exists, eval the given command + * with row/col appended + */ + sprintf(buf, " %d", cell); + Tcl_Preserve((ClientData) interp); + if (Tcl_VarEval(interp, cmd, buf, (char *)NULL) == TCL_OK) { + CONST char *name = Tcl_GetStringResult(interp); + if (name && *name) { + /* + * If a result was returned, check to see if it is + * a valid tag. + */ + entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, name); + } + } + Tcl_Release((ClientData) interp); + Tcl_ResetResult(interp); + } + } + if (entryPtr != NULL) { + /* + * This can be either the one in row|colStyles, + * or that returned by eval'ing the row|colTagCmd + */ + tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr); + } + return tagPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TableCleanupTag -- + * Releases the resources used by a tag before it is freed up. + * + * Results: + * None. + * + * Side effects: + * The tag is no longer valid. + * + *---------------------------------------------------------------------- + */ +void +TableCleanupTag(Table *tablePtr, TableTag *tagPtr) +{ + /* + * Free resources that the optionSpec doesn't specifically know about + */ + if (tagPtr->image) { + Tk_FreeImage(tagPtr->image); + } + + Tk_FreeOptions(tagConfig, (char *) tagPtr, tablePtr->display, 0); +} + +/* + *-------------------------------------------------------------- + * + * Table_TagCmd -- + * This procedure is invoked to process the tag method + * that corresponds to a 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_TagCmd(ClientData clientData, register Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + register Table *tablePtr = (Table *)clientData; + int result = TCL_OK, cmdIndex, i, newEntry, value, len; + int row, col, tagPrio, refresh = 0; + TableTag *tagPtr, *tag2Ptr; + Tcl_HashEntry *entryPtr, *scanPtr; + Tcl_HashTable *hashTblPtr; + Tcl_HashSearch search; + Tk_Image image; + Tcl_Obj *objPtr, *resultPtr; + char buf[INDEX_BUFSIZE], *keybuf, *tagname; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } + + result = Tcl_GetIndexFromObj(interp, objv[2], tagCmdNames, + "tag option", 0, &cmdIndex); + if (result != TCL_OK) { + return result; + } + /* + * Before using this object, make sure there aren't any calls that + * could have changed the interp result, thus freeing the object. + */ + resultPtr = Tcl_GetObjResult(interp); + + switch ((enum tagCmd) cmdIndex) { + case TAG_CELLTAG: /* add named tag to a (group of) cell(s) */ + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, "tag ?arg arg ...?"); + return TCL_ERROR; + } + tagname = Tcl_GetStringFromObj(objv[3], &len); + if (len == 0) { + /* + * An empty string was specified, so just delete the tag. + */ + tagPtr = NULL; + } else { + /* + * Get the pointer to the tag structure. If it doesn't + * exist, it will be created. + */ + tagPtr = TableTagGetEntry(tablePtr, tagname, 0, NULL); + } + + if (objc == 4) { + /* + * The user just wants the cells with this tag returned. + * Handle specially tags named: active, flash, sel, title + */ + + if ((tablePtr->flags & HAS_ACTIVE) && + STREQ(tagname, "active")) { + TableMakeArrayIndex( + tablePtr->activeRow+tablePtr->rowOffset, + tablePtr->activeCol+tablePtr->colOffset, buf); + Tcl_SetStringObj(resultPtr, buf, -1); + } else if ((tablePtr->flashMode && STREQ(tagname, "flash")) + || STREQ(tagname, "sel")) { + hashTblPtr = (*tagname == 's') ? + tablePtr->selCells : tablePtr->flashCells; + for (scanPtr = Tcl_FirstHashEntry(hashTblPtr, &search); + scanPtr != NULL; + scanPtr = Tcl_NextHashEntry(&search)) { + keybuf = (char *) Tcl_GetHashKey(hashTblPtr, scanPtr); + Tcl_ListObjAppendElement(NULL, resultPtr, + Tcl_NewStringObj(keybuf, -1)); + } + } else if (STREQ(tagname, "title") && + (tablePtr->titleRows || tablePtr->titleCols)) { + for (row = tablePtr->rowOffset; + row < tablePtr->rowOffset+tablePtr->rows; row++) { + for (col = tablePtr->colOffset; + col < tablePtr->colOffset+tablePtr->titleCols; + col++) { + TableMakeArrayIndex(row, col, buf); + Tcl_ListObjAppendElement(NULL, resultPtr, + Tcl_NewStringObj(buf, -1)); + } + } + for (row = tablePtr->rowOffset; + row < tablePtr->rowOffset+tablePtr->titleRows; + row++) { + for (col = tablePtr->colOffset+tablePtr->titleCols; + col < tablePtr->colOffset+tablePtr->cols; col++) { + TableMakeArrayIndex(row, col, buf); + Tcl_ListObjAppendElement(NULL, resultPtr, + Tcl_NewStringObj(buf, -1)); + } + } + } else { + /* + * Check this tag pointer amongst all tagged cells + */ + for (scanPtr = Tcl_FirstHashEntry(tablePtr->cellStyles, + &search); + scanPtr != NULL; + scanPtr = Tcl_NextHashEntry(&search)) { + if ((TableTag *) Tcl_GetHashValue(scanPtr) == tagPtr) { + keybuf = (char *) Tcl_GetHashKey( + tablePtr->cellStyles, scanPtr); + Tcl_ListObjAppendElement(NULL, resultPtr, + Tcl_NewStringObj(keybuf, -1)); + } + } + } + return TCL_OK; + } + + /* + * Loop through the arguments and fill in the hash table + */ + for (i = 4; i < objc; i++) { + /* + * Try and parse the index + */ + if (TableGetIndexObj(tablePtr, objv[i], &row, &col) + != TCL_OK) { + return TCL_ERROR; + } + /* + * Get the hash key ready + */ + TableMakeArrayIndex(row, col, buf); + + if (tagPtr == NULL) { + /* + * This is a deletion + */ + entryPtr = Tcl_FindHashEntry(tablePtr->cellStyles, buf); + if (entryPtr != NULL) { + Tcl_DeleteHashEntry(entryPtr); + refresh = 1; + } + } else { + /* + * Add a key to the hash table and set it to point to the + * Tag structure if it wasn't the same as an existing one + */ + entryPtr = Tcl_CreateHashEntry(tablePtr->cellStyles, + buf, &newEntry); + if (newEntry || (tagPtr != + (TableTag *) Tcl_GetHashValue(entryPtr))) { + Tcl_SetHashValue(entryPtr, (ClientData) tagPtr); + refresh = 1; + } + } + /* + * Now invalidate this cell for redraw + */ + if (refresh) { + TableRefresh(tablePtr, row-tablePtr->rowOffset, + col-tablePtr->colOffset, CELL); + } + } + return TCL_OK; + + case TAG_COLTAG: + case TAG_ROWTAG: { /* tag a row or a column */ + int forRows = (cmdIndex == TAG_ROWTAG); + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, "tag ?arg arg ..?"); + return TCL_ERROR; + } + tagname = Tcl_GetStringFromObj(objv[3], &len); + if (len == 0) { + /* + * Empty string, so we want to delete this element + */ + tagPtr = NULL; + } else { + /* + * Get the pointer to the tag structure. If it doesn't + * exist, it will be created. + */ + tagPtr = TableTagGetEntry(tablePtr, tagname, 0, NULL); + } + + /* + * Choose the correct hash table based on args + */ + hashTblPtr = forRows ? tablePtr->rowStyles : tablePtr->colStyles; + + if (objc == 4) { + /* the user just wants the tagged cells to be returned */ + /* Special handling for tags: active, flash, sel, title */ + + if ((tablePtr->flags & HAS_ACTIVE) && + strcmp(tagname, "active") == 0) { + Tcl_SetIntObj(resultPtr, + (forRows ? + tablePtr->activeRow+tablePtr->rowOffset : + tablePtr->activeCol+tablePtr->colOffset)); + } else if ((tablePtr->flashMode && STREQ(tagname, "flash")) + || STREQ(tagname, "sel")) { + Tcl_HashTable *cacheTblPtr; + + cacheTblPtr = (Tcl_HashTable *) + ckalloc(sizeof(Tcl_HashTable)); + Tcl_InitHashTable(cacheTblPtr, TCL_ONE_WORD_KEYS); + + hashTblPtr = (*tagname == 's') ? + tablePtr->selCells : tablePtr->flashCells; + for (scanPtr = Tcl_FirstHashEntry(hashTblPtr, &search); + scanPtr != NULL; + scanPtr = Tcl_NextHashEntry(&search)) { + TableParseArrayIndex(&row, &col, + Tcl_GetHashKey(hashTblPtr, scanPtr)); + value = forRows ? row : col; + entryPtr = Tcl_CreateHashEntry(cacheTblPtr, + (char *)value, &newEntry); + if (newEntry) { + Tcl_ListObjAppendElement(NULL, resultPtr, + Tcl_NewIntObj(value)); + } + } + + Tcl_DeleteHashTable(cacheTblPtr); + ckfree((char *) (cacheTblPtr)); + } else if (STREQ(tagname, "title") && + (forRows?tablePtr->titleRows:tablePtr->titleCols)) { + if (forRows) { + for (row = tablePtr->rowOffset; + row < tablePtr->rowOffset+tablePtr->titleRows; + row++) { + Tcl_ListObjAppendElement(NULL, resultPtr, + Tcl_NewIntObj(row)); + } + } else { + for (col = tablePtr->colOffset; + col < tablePtr->colOffset+tablePtr->titleCols; + col++) { + Tcl_ListObjAppendElement(NULL, resultPtr, + Tcl_NewIntObj(col)); + } + } + } else { + for (scanPtr = Tcl_FirstHashEntry(hashTblPtr, &search); + scanPtr != NULL; + scanPtr = Tcl_NextHashEntry(&search)) { + /* is this the tag pointer on this row */ + if ((TableTag *) Tcl_GetHashValue(scanPtr) == tagPtr) { + objPtr = Tcl_NewIntObj( + (int) Tcl_GetHashKey(hashTblPtr, scanPtr)); + Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); + } + } + } + return TCL_OK; + } + + /* + * Loop through the arguments and fill in the hash table + */ + for (i = 4; i < objc; i++) { + /* + * Try and parse the index + */ + if (Tcl_GetIntFromObj(interp, objv[i], &value) != TCL_OK) { + return TCL_ERROR; + } + if (tagPtr == NULL) { + /* + * This is a deletion + */ + entryPtr = Tcl_FindHashEntry(hashTblPtr, (char *)value); + if (entryPtr != NULL) { + Tcl_DeleteHashEntry(entryPtr); + refresh = 1; + } + } else { + /* + * Add a key to the hash table and set it to point to the + * Tag structure if it wasn't the same as an existing one + */ + entryPtr = Tcl_CreateHashEntry(hashTblPtr, + (char *) value, &newEntry); + if (newEntry || (tagPtr != + (TableTag *) Tcl_GetHashValue(entryPtr))) { + Tcl_SetHashValue(entryPtr, (ClientData) tagPtr); + refresh = 1; + } + } + /* and invalidate the row or column affected */ + if (refresh) { + if (cmdIndex == TAG_ROWTAG) { + TableRefresh(tablePtr, value-tablePtr->rowOffset, 0, + ROW); + } else { + TableRefresh(tablePtr, 0, value-tablePtr->colOffset, + COL); + } + } + } + return TCL_OK; /* COLTAG && ROWTAG */ + } + + case TAG_CGET: + if (objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName option"); + return TCL_ERROR; + } + tagname = Tcl_GetString(objv[3]); + entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname); + if (entryPtr == NULL) { + goto invalidtag; + } else { + tagPtr = (TableTag *) Tcl_GetHashValue (entryPtr); + result = Tk_ConfigureValue(interp, tablePtr->tkwin, tagConfig, + (char *) tagPtr, Tcl_GetString(objv[4]), 0); + } + return result; /* CGET */ + + case TAG_CONFIGURE: + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName ?arg arg ...?"); + return TCL_ERROR; + } + + /* + * Get the pointer to the tag structure. If it doesn't + * exist, it will be created. + */ + tagPtr = TableTagGetEntry(tablePtr, Tcl_GetString(objv[3]), + 0, NULL); + + /* + * If there were less than 6 args, we return the configuration + * (for all or just one option), even for new tags + */ + if (objc < 6) { + result = Tk_ConfigureInfo(interp, tablePtr->tkwin, tagConfig, + (char *) tagPtr, (objc == 5) ? + Tcl_GetString(objv[4]) : NULL, 0); + } else { + CONST84 char **argv; + + /* Stringify */ + argv = (CONST84 char **) ckalloc((objc + 1) * sizeof(char *)); + for (i = 0; i < objc; i++) + argv[i] = Tcl_GetString(objv[i]); + argv[objc] = NULL; + + result = Tk_ConfigureWidget(interp, tablePtr->tkwin, + tagConfig, objc-4, argv+4, (char *) tagPtr, + TK_CONFIG_ARGV_ONLY); + ckfree((char *) argv); + if (result == TCL_ERROR) { + return TCL_ERROR; + } + + /* + * Handle change of image name + */ + if (tagPtr->imageStr) { + image = Tk_GetImage(interp, tablePtr->tkwin, + tagPtr->imageStr, + TableImageProc, (ClientData)tablePtr); + if (image == NULL) { + result = TCL_ERROR; + } + } else { + image = NULL; + } + if (tagPtr->image) { + Tk_FreeImage(tagPtr->image); + } + tagPtr->image = image; + + /* + * We reconfigured, so invalidate the table to redraw + */ + TableInvalidateAll(tablePtr, 0); + } + return result; + + case TAG_DELETE: + /* delete a tag */ + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName ?tagName ...?"); + return TCL_ERROR; + } + /* run through the remaining arguments */ + for (i = 3; i < objc; i++) { + tagname = Tcl_GetString(objv[i]); + /* cannot delete the title tag */ + if (STREQ(tagname, "title") || + STREQ(tagname, "sel") || + STREQ(tagname, "flash") || + STREQ(tagname, "active")) { + Tcl_AppendStringsToObj(resultPtr, "cannot delete ", + tagname, " tag", (char *) NULL); + return TCL_ERROR; + } + entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname); + if (entryPtr != NULL) { + /* get the tag pointer */ + tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr); + + /* delete all references to this tag in rows */ + scanPtr = Tcl_FirstHashEntry(tablePtr->rowStyles, &search); + for (; scanPtr != NULL; + scanPtr = Tcl_NextHashEntry(&search)) { + if ((TableTag *)Tcl_GetHashValue(scanPtr) == tagPtr) { + Tcl_DeleteHashEntry(scanPtr); + refresh = 1; + } + } + + /* delete all references to this tag in cols */ + scanPtr = Tcl_FirstHashEntry(tablePtr->colStyles, &search); + for (; scanPtr != NULL; + scanPtr = Tcl_NextHashEntry(&search)) { + if ((TableTag *)Tcl_GetHashValue(scanPtr) == tagPtr) { + Tcl_DeleteHashEntry(scanPtr); + refresh = 1; + } + } + + /* delete all references to this tag in cells */ + scanPtr = Tcl_FirstHashEntry(tablePtr->cellStyles, + &search); + for (; scanPtr != NULL; + scanPtr = Tcl_NextHashEntry(&search)) { + if ((TableTag *)Tcl_GetHashValue(scanPtr) == tagPtr) { + Tcl_DeleteHashEntry(scanPtr); + refresh = 1; + } + } + + /* + * Remove the tag from the prio list and collapse + * the rest of the tags. We could check for shrinking + * the prio list as well. + */ + for (i = 0; i < tablePtr->tagPrioSize; i++) { + if (tablePtr->tagPrios[i] == tagPtr) break; + } + for ( ; i < tablePtr->tagPrioSize; i++) { + tablePtr->tagPrioNames[i] = + tablePtr->tagPrioNames[i+1]; + tablePtr->tagPrios[i] = tablePtr->tagPrios[i+1]; + } + tablePtr->tagPrioSize--; + + /* Release the tag structure */ + TableCleanupTag(tablePtr, tagPtr); + ckfree((char *) tagPtr); + + /* And free the hash table entry */ + Tcl_DeleteHashEntry(entryPtr); + } + } + /* since we deleted a tag, redraw the screen */ + if (refresh) { + TableInvalidateAll(tablePtr, 0); + } + return result; + + case TAG_EXISTS: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName"); + return TCL_ERROR; + } + Tcl_SetBooleanObj(resultPtr, + (Tcl_FindHashEntry(tablePtr->tagTable, + Tcl_GetString(objv[3])) != NULL)); + return TCL_OK; + + case TAG_INCLUDES: + /* does a tag contain a index ? */ + if (objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, "tag index"); + return TCL_ERROR; + } + tagname = Tcl_GetString(objv[3]); + /* check to see if the tag actually exists */ + entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname); + if (entryPtr == NULL) { + /* Unknown tag, just return 0 */ + Tcl_SetBooleanObj(resultPtr, 0); + return TCL_OK; + } + /* parse index */ + if (TableGetIndexObj(tablePtr, objv[4], &row, &col) != TCL_OK) { + return TCL_ERROR; + } + /* create hash key */ + TableMakeArrayIndex(row, col, buf); + + if (STREQ(tagname, "active")) { + result = (tablePtr->activeRow+tablePtr->rowOffset==row && + tablePtr->activeCol+tablePtr->colOffset==col); + } else if (STREQ(tagname, "flash")) { + result = (tablePtr->flashMode && + (Tcl_FindHashEntry(tablePtr->flashCells, buf) + != NULL)); + } else if (STREQ(tagname, "sel")) { + result = (Tcl_FindHashEntry(tablePtr->selCells, buf) != NULL); + } else if (STREQ(tagname, "title")) { + result = (row < tablePtr->titleRows+tablePtr->rowOffset || + col < tablePtr->titleCols+tablePtr->colOffset); + } else { + /* get the pointer to the tag structure */ + tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr); + scanPtr = Tcl_FindHashEntry(tablePtr->cellStyles, buf); + /* + * Look to see if there is a cell, row, or col tag + * for this cell + */ + result = ((scanPtr && + (tagPtr == (TableTag *) Tcl_GetHashValue(scanPtr))) || + (tagPtr == FindRowColTag(tablePtr, row, ROW)) || + (tagPtr == FindRowColTag(tablePtr, col, COL))); + } + /* + * Because we may call FindRowColTag above, we can't use + * the resultPtr, but this is almost equivalent, and is SAFE + */ + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); + return TCL_OK; + + case TAG_NAMES: + /* + * Print out the tag names in priority order + */ + if (objc < 3 || objc > 4) { + Tcl_WrongNumArgs(interp, 3, objv, "?pattern?"); + return TCL_ERROR; + } + tagname = (objc == 4) ? Tcl_GetString(objv[3]) : NULL; + for (i = 0; i < tablePtr->tagPrioSize; i++) { + keybuf = tablePtr->tagPrioNames[i]; + if (objc == 3 || Tcl_StringMatch(keybuf, tagname)) { + objPtr = Tcl_NewStringObj(keybuf, -1); + Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); + } + } + return TCL_OK; + + case TAG_LOWER: + case TAG_RAISE: + /* + * Change priority of the named tag + */ + if (objc != 4 && objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, (cmdIndex == TAG_LOWER) ? + "tagName ?belowThis?" : "tagName ?aboveThis?"); + return TCL_ERROR; + } + tagname = Tcl_GetString(objv[3]); + /* check to see if the tag actually exists */ + entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname); + if (entryPtr == NULL) { + goto invalidtag; + } + tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr); + tagPrio = TableTagGetPriority(tablePtr, tagPtr); + keybuf = tablePtr->tagPrioNames[tagPrio]; + /* + * In the RAISE case, the priority is one higher (-1) because + * we want the named tag to move above the other in priority. + */ + if (objc == 5) { + tagname = Tcl_GetString(objv[4]); + entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname); + if (entryPtr == NULL) { + goto invalidtag; + } + tag2Ptr = (TableTag *) Tcl_GetHashValue(entryPtr); + if (cmdIndex == TAG_LOWER) { + value = TableTagGetPriority(tablePtr, tag2Ptr); + } else { + value = TableTagGetPriority(tablePtr, tag2Ptr) - 1; + } + } else { + if (cmdIndex == TAG_LOWER) { + /* + * Lower this tag's priority to the bottom. + */ + value = tablePtr->tagPrioSize - 1; + } else { + /* + * Raise this tag's priority to the top. + */ + value = -1; + } + } + if (value < tagPrio) { + /* + * Move tag up in priority. + */ + for (i = tagPrio; i > value; i--) { + tablePtr->tagPrioNames[i] = tablePtr->tagPrioNames[i-1]; + tablePtr->tagPrios[i] = tablePtr->tagPrios[i-1]; + } + i++; + tablePtr->tagPrioNames[i] = keybuf; + tablePtr->tagPrios[i] = tagPtr; + refresh = 1; + } else if (value > tagPrio) { + /* + * Move tag down in priority. + */ + for (i = tagPrio; i < value; i++) { + tablePtr->tagPrioNames[i] = tablePtr->tagPrioNames[i+1]; + tablePtr->tagPrios[i] = tablePtr->tagPrios[i+1]; + } + tablePtr->tagPrioNames[i] = keybuf; + tablePtr->tagPrios[i] = tagPtr; + refresh = 1; + } + /* since we deleted a tag, redraw the screen */ + if (refresh) { + TableInvalidateAll(tablePtr, 0); + } + return TCL_OK; + + } + return TCL_OK; + + invalidtag: + /* + * When jumping here, ensure the invalid 'tagname' is set already. + */ + Tcl_AppendStringsToObj(resultPtr, "invalid tag name \"", + tagname, "\"", (char *) NULL); + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * TableOptionReliefSet -- + * + * This routine configures the borderwidth value for a tag. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * It may adjust the tag struct values of relief[0..4] and borders. + * + *---------------------------------------------------------------------- + */ + +static int +TableOptionReliefSet(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. */ + CONST84 char *value; /* Value of option. */ + char *widgRec; /* Pointer to record for item. */ + int offset; /* Offset into item. */ +{ + TableTag *tagPtr = (TableTag *) widgRec; + + if (*value == '\0') { + tagPtr->relief = -1; + } else { + return Tk_GetRelief(interp, value, &(tagPtr->relief)); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TableOptionReliefGet -- + * + * Results: + * Value of the tag's -relief option. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static char * +TableOptionReliefGet(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. */ +{ + return (char *) Tk_NameOfRelief(((TableTag *) widgRec)->relief); +} diff --git a/tktable/generic/tkTableUtil.c b/tktable/generic/tkTableUtil.c new file mode 100644 index 0000000..16fa8b4 --- /dev/null +++ b/tktable/generic/tkTableUtil.c @@ -0,0 +1,372 @@ +/* + * tkTableUtil.c -- + * + * This module contains utility functions for table widgets. + * + * Copyright (c) 2000-2002 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: tkTableUtil.c,v 1.2 2016/01/12 18:59:57 joye Exp $ + */ + +#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)); + +/* + *-------------------------------------------------------------- + * + * Table_ClearHashTable -- + * This procedure is invoked to clear a STRING_KEY hash table, + * freeing the string entries and then deleting the hash table. + * The hash table cannot be used after calling this, except to + * be freed or reinitialized. + * + * Results: + * Cached info will be lost. + * + * Side effects: + * Can cause redraw. + * See the user documentation. + * + *-------------------------------------------------------------- + */ +void +Table_ClearHashTable(Tcl_HashTable *hashTblPtr) +{ + Tcl_HashEntry *entryPtr; + Tcl_HashSearch search; + char *value; + + for (entryPtr = Tcl_FirstHashEntry(hashTblPtr, &search); + entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) { + value = (char *) Tcl_GetHashValue(entryPtr); + if (value != NULL) ckfree(value); + } + + Tcl_DeleteHashTable(hashTblPtr); +} + +/* + *---------------------------------------------------------------------- + * + * 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. */ + CONST84 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; + CONST84 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. + * + *---------------------------------------------------------------------- + */ + +const 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; + CONST84 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, CONST84 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. + * + *---------------------------------------------------------------------- + */ + +const 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/tktable/generic/tkTableWin.c b/tktable/generic/tkTableWin.c new file mode 100644 index 0000000..2a59088 --- /dev/null +++ b/tktable/generic/tkTableWin.c @@ -0,0 +1,955 @@ +/* + * tkTableWin.c -- + * + * This module implements embedded windows for table widgets. + * Much of this code is adapted from tkGrid.c and tkTextWind.c. + * + * Copyright (c) 1998-2002 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: tkTableWin.c,v 1.2 2016/01/12 18:59:57 joye Exp $ + */ + +#include "tkTable.h" + +static int StickyParseProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, Tk_Window tkwin, + CONST84 char *value, char *widgRec, int offset)); +static const char * StickyPrintProc _ANSI_ARGS_((ClientData clientData, + Tk_Window tkwin, char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr)); + +static void EmbWinLostSlaveProc _ANSI_ARGS_((ClientData clientData, + Tk_Window tkwin)); +static void EmbWinRequestProc _ANSI_ARGS_((ClientData clientData, + Tk_Window tkwin)); + +static void EmbWinCleanup _ANSI_ARGS_((Table *tablePtr, + TableEmbWindow *ewPtr)); +static int EmbWinConfigure _ANSI_ARGS_((Table *tablePtr, + TableEmbWindow *ewPtr, + int objc, Tcl_Obj *CONST objv[])); +static void EmbWinStructureProc _ANSI_ARGS_((ClientData clientData, + XEvent *eventPtr)); +static void EmbWinUnmapNow _ANSI_ARGS_((Tk_Window ewTkwin, + Tk_Window tkwin)); + +static Tk_GeomMgr tableGeomType = { + "table", /* name */ + EmbWinRequestProc, /* requestProc */ + EmbWinLostSlaveProc, /* lostSlaveProc */ +}; + +/* windows subcommands */ +static CONST84 char *winCmdNames[] = { + "cget", "configure", "delete", "move", "names", (char *) NULL +}; +enum winCommand { + WIN_CGET, WIN_CONFIGURE, WIN_DELETE, WIN_MOVE, WIN_NAMES +}; + +/* Flag values for "sticky"ness The 16 combinations subsume the packer's + * notion of anchor and fill. + * + * STICK_NORTH This window sticks to the top of its cavity. + * STICK_EAST This window sticks to the right edge of its cavity. + * STICK_SOUTH This window sticks to the bottom of its cavity. + * STICK_WEST This window sticks to the left edge of its cavity. + */ + +#define STICK_NORTH (1<<0) +#define STICK_EAST (1<<1) +#define STICK_SOUTH (1<<2) +#define STICK_WEST (1<<3) + +/* + * The default specification for configuring embedded windows + * Done like this to make the command line parsing easy + */ + +static Tk_CustomOption stickyOption = { StickyParseProc, StickyPrintProc, + (ClientData) NULL }; +static Tk_CustomOption tagBdOpt = { TableOptionBdSet, TableOptionBdGet, + (ClientData) BD_TABLE_WIN }; + +static Tk_ConfigSpec winConfigSpecs[] = { + {TK_CONFIG_BORDER, "-background", "background", "Background", NULL, + Tk_Offset(TableEmbWindow, bg), + TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, + {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL, (char *)NULL, 0, 0}, + {TK_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0}, + {TK_CONFIG_CUSTOM, "-borderwidth", "borderWidth", "BorderWidth", "", + 0 /* no offset */, + TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK, &tagBdOpt }, + {TK_CONFIG_STRING, "-create", (char *)NULL, (char *)NULL, (char *)NULL, + Tk_Offset(TableEmbWindow, create), + TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, + {TK_CONFIG_PIXELS, "-padx", (char *)NULL, (char *)NULL, (char *)NULL, + Tk_Offset(TableEmbWindow, padX), TK_CONFIG_DONT_SET_DEFAULT }, + {TK_CONFIG_PIXELS, "-pady", (char *)NULL, (char *)NULL, (char *)NULL, + Tk_Offset(TableEmbWindow, padY), TK_CONFIG_DONT_SET_DEFAULT }, + {TK_CONFIG_CUSTOM, "-sticky", (char *)NULL, (char *)NULL, (char *)NULL, + Tk_Offset(TableEmbWindow, sticky), TK_CONFIG_DONT_SET_DEFAULT, + &stickyOption}, + {TK_CONFIG_RELIEF, "-relief", "relief", "Relief", NULL, + Tk_Offset(TableEmbWindow, relief), 0 }, + {TK_CONFIG_WINDOW, "-window", (char *)NULL, (char *)NULL, (char *)NULL, + Tk_Offset(TableEmbWindow, tkwin), + TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, + {TK_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL, + (char *)NULL, 0, 0 } +}; + +/* + *---------------------------------------------------------------------- + * + * StickyPrintProc -- + * Converts the internal boolean combination of "sticky" bits onto + * a TCL string element containing zero or more of n, s, e, or w. + * + * Results: + * A string is placed into the "result" pointer. + * + * Side effects: + * none. + * + *---------------------------------------------------------------------- + */ +static const char * +StickyPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) + ClientData clientData; /* Ignored. */ + Tk_Window tkwin; /* Window for text widget. */ + char *widgRec; /* Pointer to TkTextEmbWindow + * structure. */ + int offset; /* Ignored. */ + Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with + * information about how to reclaim + * storage for return string. */ +{ + int flags = ((TableEmbWindow *) widgRec)->sticky; + int count = 0; + char *result = (char *) ckalloc(5*sizeof(char)); + + if (flags&STICK_NORTH) result[count++] = 'n'; + if (flags&STICK_EAST) result[count++] = 'e'; + if (flags&STICK_SOUTH) result[count++] = 's'; + if (flags&STICK_WEST) result[count++] = 'w'; + + *freeProcPtr = TCL_DYNAMIC; + result[count] = '\0'; + return result; +} + +/* + *---------------------------------------------------------------------- + * + * StringParseProc -- + * Converts an ascii string representing a widgets stickyness + * into the boolean result. + * + * Results: + * The boolean combination of the "sticky" bits is retuned. If an + * error occurs, such as an invalid character, -1 is returned instead. + * + * Side effects: + * none + * + *---------------------------------------------------------------------- + */ +static int +StickyParseProc(clientData, interp, tkwin, value, widgRec, offset) + ClientData clientData; /* Not used.*/ + Tcl_Interp *interp; /* Used for reporting errors. */ + Tk_Window tkwin; /* Window for text widget. */ + CONST84 char *value; /* Value of option. */ + char *widgRec; /* Pointer to TkTextEmbWindow + * structure. */ + int offset; /* Offset into item (ignored). */ +{ + register TableEmbWindow *ewPtr = (TableEmbWindow *) widgRec; + int sticky = 0; + char c; + + while ((c = *value++) != '\0') { + switch (c) { + case 'n': case 'N': sticky |= STICK_NORTH; break; + case 'e': case 'E': sticky |= STICK_EAST; break; + case 's': case 'S': sticky |= STICK_SOUTH; break; + case 'w': case 'W': sticky |= STICK_WEST; break; + case ' ': case ',': case '\t': case '\r': case '\n': break; + default: + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "bad sticky value \"", --value, + "\": must contain n, s, e or w", + (char *) NULL); + return TCL_ERROR; + } + } + ewPtr->sticky = sticky; + return TCL_OK; +} + +/* + * ckallocs space for a new embedded window structure and clears the structure + * returns the pointer to the new structure + */ +static TableEmbWindow * +TableNewEmbWindow(Table *tablePtr) +{ + TableEmbWindow *ewPtr = (TableEmbWindow *) ckalloc(sizeof(TableEmbWindow)); + memset((VOID *) ewPtr, 0, sizeof(TableEmbWindow)); + + /* + * Set the values that aren't 0/NULL by default + */ + ewPtr->tablePtr = tablePtr; + ewPtr->relief = -1; + ewPtr->padX = -1; + ewPtr->padY = -1; + + return ewPtr; +} + +/* + *---------------------------------------------------------------------- + * + * EmbWinCleanup -- + * Releases resources used by an embedded window before it is freed up. + * + * Results: + * Window will no longer be valid. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +static void +EmbWinCleanup(Table *tablePtr, TableEmbWindow *ewPtr) +{ + Tk_FreeOptions(winConfigSpecs, (char *) ewPtr, tablePtr->display, 0); +} + +/* + *-------------------------------------------------------------- + * + * EmbWinDisplay -- + * + * This procedure is invoked by TableDisplay for + * mapping windows into cells. + * + * Results: + * Displays or moves window on table screen. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +void +EmbWinDisplay(Table *tablePtr, Drawable window, TableEmbWindow *ewPtr, + TableTag *tagPtr, int x, int y, int width, int height) +{ + Tk_Window tkwin = tablePtr->tkwin; + Tk_Window ewTkwin = ewPtr->tkwin; + int diffx=0; /* Cavity width - slave width. */ + int diffy=0; /* Cavity hight - slave height. */ + int sticky = ewPtr->sticky; + int padx, pady; + + if (ewPtr->bg) tagPtr->bg = ewPtr->bg; + if (ewPtr->relief != -1) tagPtr->relief = ewPtr->relief; + if (ewPtr->borders) { + tagPtr->borderStr = ewPtr->borderStr; + tagPtr->borders = ewPtr->borders; + tagPtr->bd[0] = ewPtr->bd[0]; + tagPtr->bd[1] = ewPtr->bd[1]; + tagPtr->bd[2] = ewPtr->bd[2]; + tagPtr->bd[3] = ewPtr->bd[3]; + } + + padx = (ewPtr->padX < 0) ? tablePtr->padX : ewPtr->padX; + pady = (ewPtr->padY < 0) ? tablePtr->padY : ewPtr->padY; + + x += padx; + width -= padx*2; + y += pady; + height -= pady*2; + + if (width > Tk_ReqWidth(ewPtr->tkwin)) { + diffx = width - Tk_ReqWidth(ewPtr->tkwin); + width = Tk_ReqWidth(ewPtr->tkwin); + } + if (height > Tk_ReqHeight(ewPtr->tkwin)) { + diffy = height - Tk_ReqHeight(ewPtr->tkwin); + height = Tk_ReqHeight(ewPtr->tkwin); + } + if (sticky&STICK_EAST && sticky&STICK_WEST) { + width += diffx; + } + if (sticky&STICK_NORTH && sticky&STICK_SOUTH) { + height += diffy; + } + if (!(sticky&STICK_WEST)) { + x += (sticky&STICK_EAST) ? diffx : diffx/2; + } + if (!(sticky&STICK_NORTH)) { + y += (sticky&STICK_SOUTH) ? diffy : diffy/2; + } + + /* + * If we fall below a specific minimum width/height requirement, + * we just unmap the window + */ + if (width < 2 || height < 2) { + if (ewPtr->displayed) { + EmbWinUnmapNow(ewTkwin, tkwin); + } + return; + } + + if (tkwin == Tk_Parent(ewTkwin)) { + if ((x != Tk_X(ewTkwin)) || (y != Tk_Y(ewTkwin)) + || (width != Tk_Width(ewTkwin)) + || (height != Tk_Height(ewTkwin))) { + Tk_MoveResizeWindow(ewTkwin, x, y, width, height); + } + Tk_MapWindow(ewTkwin); + } else { + Tk_MaintainGeometry(ewTkwin, tkwin, x, y, width, height); + } + ewPtr->displayed = 1; +} + +/* + *-------------------------------------------------------------- + * + * EmbWinUnmapNow -- + * Handles unmapping the window depending on parent. + * tkwin should be tablePtr->tkwin. + * ewTkwin should be ewPtr->tkwin. + * + * Results: + * Removes the window. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +static void +EmbWinUnmapNow(Tk_Window ewTkwin, Tk_Window tkwin) +{ + if (tkwin != Tk_Parent(ewTkwin)) { + Tk_UnmaintainGeometry(ewTkwin, tkwin); + } + Tk_UnmapWindow(ewTkwin); +} + +/* + *-------------------------------------------------------------- + * + * EmbWinUnmap -- + * This procedure is invoked by TableAdjustParams for + * unmapping windows managed moved offscreen. + * rlo, ... should be in real coords. + * + * Results: + * None. + * + * Side effects: + * Unmaps embedded windows. + * + *-------------------------------------------------------------- + */ +void +EmbWinUnmap(Table *tablePtr, int rlo, int rhi, int clo, int chi) +{ + register TableEmbWindow *ewPtr; + Tcl_HashEntry *entryPtr; + int row, col, trow, tcol; + char buf[INDEX_BUFSIZE]; + + /* + * Transform numbers from real to user user coords + */ + rlo += tablePtr->rowOffset; + rhi += tablePtr->rowOffset; + clo += tablePtr->colOffset; + chi += tablePtr->colOffset; + for (row = rlo; row <= rhi; row++) { + for (col = clo; col <= chi; col++) { + TableTrueCell(tablePtr, row, col, &trow, &tcol); + TableMakeArrayIndex(trow, tcol, buf); + entryPtr = Tcl_FindHashEntry(tablePtr->winTable, buf); + if (entryPtr != NULL) { + ewPtr = (TableEmbWindow *) Tcl_GetHashValue(entryPtr); + if (ewPtr->displayed) { + ewPtr->displayed = 0; + if (ewPtr->tkwin != NULL && tablePtr->tkwin != NULL) { + EmbWinUnmapNow(ewPtr->tkwin, tablePtr->tkwin); + } + } + } + } + } +} + +/* + *-------------------------------------------------------------- + * + * EmbWinRequestProc -- + * This procedure is invoked by Tk_GeometryRequest for + * windows managed by the Table. + * + * Results: + * None. + * + * Side effects: + * Arranges for tkwin, and all its managed siblings, to + * be re-arranged at the next idle point. + * + *-------------------------------------------------------------- + */ +static void +EmbWinRequestProc(clientData, tkwin) + ClientData clientData; /* Table's information about + * window that got new preferred + * geometry. */ + Tk_Window tkwin; /* Other Tk-related information + * about the window. */ +{ + register TableEmbWindow *ewPtr = (TableEmbWindow *) clientData; + + /* + * Resize depends on the sticky + */ + if (ewPtr->displayed && ewPtr->hPtr != NULL) { + Table *tablePtr = ewPtr->tablePtr; + int row, col, x, y, width, height; + + TableParseArrayIndex(&row, &col, + Tcl_GetHashKey(tablePtr->winTable, ewPtr->hPtr)); + if (TableCellVCoords(tablePtr, row-tablePtr->rowOffset, + col-tablePtr->colOffset, &x, &y, &width, &height, + 0)) { + TableInvalidate(tablePtr, x, y, width, height, 0); + } + } +} + +static void +EmbWinRemove(TableEmbWindow *ewPtr) +{ + Table *tablePtr = ewPtr->tablePtr; + + if (ewPtr->tkwin != NULL) { + Tk_DeleteEventHandler(ewPtr->tkwin, StructureNotifyMask, + EmbWinStructureProc, (ClientData) ewPtr); + ewPtr->tkwin = NULL; + } + ewPtr->displayed = 0; + if (tablePtr->tkwin != NULL) { + int row, col, x, y, width, height; + + TableParseArrayIndex(&row, &col, + Tcl_GetHashKey(tablePtr->winTable, ewPtr->hPtr)); + /* this will cause windows removed from the table to actually + * cause the associated embdedded window hash data to be removed */ + Tcl_DeleteHashEntry(ewPtr->hPtr); + if (TableCellVCoords(tablePtr, row-tablePtr->rowOffset, + col-tablePtr->colOffset, &x, &y, &width, &height, + 0)) + TableInvalidate(tablePtr, x, y, width, height, 1); + } + /* this will cause windows removed from the table to actually + * cause the associated embdedded window hash data to be removed */ + EmbWinCleanup(tablePtr, ewPtr); + ckfree((char *) ewPtr); +} + +/* + *-------------------------------------------------------------- + * + * EmbWinLostSlaveProc -- + * This procedure is invoked by Tk whenever some other geometry + * claims control over a slave that used to be managed by us. + * + * Results: + * None. + * + * Side effects: + * Forgets all table-related information about the slave. + * + *-------------------------------------------------------------- + */ + +static void +EmbWinLostSlaveProc(clientData, tkwin) + ClientData clientData; /* Table structure for slave window that + * was stolen away. */ + Tk_Window tkwin; /* Tk's handle for the slave window. */ +{ + register TableEmbWindow *ewPtr = (TableEmbWindow *) clientData; + +#if 0 + Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) ewPtr); +#endif + EmbWinUnmapNow(tkwin, ewPtr->tablePtr->tkwin); + EmbWinRemove(ewPtr); +} + +/* + *-------------------------------------------------------------- + * + * EmbWinStructureProc -- + * This procedure is invoked by the Tk event loop whenever + * StructureNotify events occur for a window that's embedded + * in a table widget. This procedure's only purpose is to + * clean up when windows are deleted. + * + * Results: + * None. + * + * Side effects: + * The window is disassociated from the window segment, and + * the portion of the table is redisplayed. + * + *-------------------------------------------------------------- + */ +static void +EmbWinStructureProc(clientData, eventPtr) + ClientData clientData; /* Pointer to record describing window item. */ + XEvent *eventPtr; /* Describes what just happened. */ +{ + register TableEmbWindow *ewPtr = (TableEmbWindow *) clientData; + + if (eventPtr->type != DestroyNotify) { + return; + } + + EmbWinRemove(ewPtr); +} + +/* + *-------------------------------------------------------------- + * + * EmbWinDelete -- + * This procedure is invoked by ... whenever + * an embedded window is being deleted. + * + * Results: + * None. + * + * Side effects: + * The embedded window is deleted, if it exists, and any resources + * associated with it are released. + * + *-------------------------------------------------------------- + */ +void +EmbWinDelete(register Table *tablePtr, TableEmbWindow *ewPtr) +{ + Tcl_HashEntry *entryPtr = ewPtr->hPtr; + + if (ewPtr->tkwin != NULL) { + Tk_Window tkwin = ewPtr->tkwin; + /* + * Delete the event handler for the window before destroying + * the window, so that EmbWinStructureProc doesn't get called + * (we'll already do everything that it would have done, and + * it will just get confused). + */ + + ewPtr->tkwin = NULL; + Tk_DeleteEventHandler(tkwin, StructureNotifyMask, + EmbWinStructureProc, (ClientData) ewPtr); + Tk_DestroyWindow(tkwin); + } + if (tablePtr->tkwin != NULL && entryPtr != NULL) { + int row, col, x, y, width, height; + TableParseArrayIndex(&row, &col, + Tcl_GetHashKey(tablePtr->winTable, entryPtr)); + Tcl_DeleteHashEntry(entryPtr); + + if (TableCellVCoords(tablePtr, row-tablePtr->rowOffset, + col-tablePtr->colOffset, + &x, &y, &width, &height, 0)) + TableInvalidate(tablePtr, x, y, width, height, 0); + } +#if 0 + Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) ewPtr); +#endif + EmbWinCleanup(tablePtr, ewPtr); + ckfree((char *) ewPtr); +} + +/* + *-------------------------------------------------------------- + * + * EmbWinConfigure -- + * This procedure is called to handle configuration options + * for an embedded window. + * + * Results: + * The return value is a standard Tcl result. If TCL_ERROR is + * returned, then the interp's result contains an error message.. + * + * Side effects: + * Configuration information for the embedded window changes, + * such as alignment, stretching, or name of the embedded + * window. + * + *-------------------------------------------------------------- + */ +static int +EmbWinConfigure(tablePtr, ewPtr, objc, objv) + Table *tablePtr; /* Information about table widget that + * contains embedded window. */ + TableEmbWindow *ewPtr; /* Embedded window to be configured. */ + int objc; /* Number of objs in objv. */ + Tcl_Obj *CONST objv[]; /* Obj type options. */ +{ + Tcl_Interp *interp = tablePtr->interp; + Tk_Window oldWindow; + int i, result; + CONST84 char **argv; + + oldWindow = ewPtr->tkwin; + + /* Stringify */ + argv = (CONST84 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, + winConfigSpecs, objc, argv, (char *) ewPtr, + TK_CONFIG_ARGV_ONLY); + ckfree((char *) argv); + if (result != TCL_OK) { + return TCL_ERROR; + } + + if (oldWindow != ewPtr->tkwin) { + ewPtr->displayed = 0; + if (oldWindow != NULL) { + Tk_DeleteEventHandler(oldWindow, StructureNotifyMask, + EmbWinStructureProc, (ClientData) ewPtr); + Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL, + (ClientData) NULL); + EmbWinUnmapNow(oldWindow, tablePtr->tkwin); + } + if (ewPtr->tkwin != NULL) { + Tk_Window ancestor, parent; + + /* + * Make sure that the table is either the parent of the + * embedded window or a descendant of that parent. Also, + * don't allow a top-level window to be managed inside + * a table. + */ + + parent = Tk_Parent(ewPtr->tkwin); + for (ancestor = tablePtr->tkwin; ; + ancestor = Tk_Parent(ancestor)) { + if (ancestor == parent) { + break; + } + if (Tk_IsTopLevel(ancestor)) { + badMaster: + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "can't embed ", + Tk_PathName(ewPtr->tkwin), " in ", + Tk_PathName(tablePtr->tkwin), + (char *)NULL); + ewPtr->tkwin = NULL; + return TCL_ERROR; + } + } + if (Tk_IsTopLevel(ewPtr->tkwin) || + (ewPtr->tkwin == tablePtr->tkwin)) { + goto badMaster; + } + + /* + * Take over geometry management for the window, plus create + * an event handler to find out when it is deleted. + */ + + Tk_ManageGeometry(ewPtr->tkwin, &tableGeomType, (ClientData)ewPtr); + Tk_CreateEventHandler(ewPtr->tkwin, StructureNotifyMask, + EmbWinStructureProc, (ClientData) ewPtr); + } + } + return TCL_OK; +} + +/* + *-------------------------------------------------------------- + * + * Table_WinMove -- + * This procedure is invoked by ... whenever + * an embedded window is being moved. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * If an embedded window is in the dest cell, it is deleted. + * + *-------------------------------------------------------------- + */ +int +Table_WinMove(register Table *tablePtr, char *CONST srcPtr, + char *CONST destPtr, int flags) +{ + int srow, scol, row, col, new; + Tcl_HashEntry *entryPtr; + TableEmbWindow *ewPtr; + + if (TableGetIndex(tablePtr, srcPtr, &srow, &scol) != TCL_OK || + TableGetIndex(tablePtr, destPtr, &row, &col) != TCL_OK) { + return TCL_ERROR; + } + entryPtr = Tcl_FindHashEntry(tablePtr->winTable, srcPtr); + if (entryPtr == NULL) { + if (flags & INV_NO_ERR_MSG) { + return TCL_OK; + } else { + Tcl_AppendStringsToObj(Tcl_GetObjResult(tablePtr->interp), + "no window at index \"", srcPtr, "\"", (char *) NULL); + return TCL_ERROR; + } + } + /* avoid moving it to the same location */ + if (srow == row && scol == col) { + return TCL_OK; + } + /* get the window pointer */ + ewPtr = (TableEmbWindow *) Tcl_GetHashValue(entryPtr); + /* and free the old hash table entry */ + Tcl_DeleteHashEntry(entryPtr); + + entryPtr = Tcl_CreateHashEntry(tablePtr->winTable, destPtr, &new); + if (!new) { + /* window already there - just delete it */ + TableEmbWindow *ewPtrDel; + ewPtrDel = (TableEmbWindow *) Tcl_GetHashValue(entryPtr); + /* This prevents the deletion of it's own entry, since we need it */ + ewPtrDel->hPtr = NULL; + EmbWinDelete(tablePtr, ewPtrDel); + } + /* set the new entry's value */ + Tcl_SetHashValue(entryPtr, (ClientData) ewPtr); + ewPtr->hPtr = entryPtr; + + if (flags & INV_FORCE) { + int x, y, w, h; + /* Invalidate old cell */ + if (TableCellVCoords(tablePtr, srow-tablePtr->rowOffset, + scol-tablePtr->colOffset, &x, &y, &w, &h, 0)) { + TableInvalidate(tablePtr, x, y, w, h, 0); + } + /* Invalidate new cell */ + if (TableCellVCoords(tablePtr, row-tablePtr->rowOffset, + col-tablePtr->colOffset, &x, &y, &w, &h, 0)) { + TableInvalidate(tablePtr, x, y, w, h, 0); + } + } + return TCL_OK; +} + +/* + *-------------------------------------------------------------- + * + * Table_WinDelete -- + * This procedure is invoked by ... whenever + * an embedded window is being delete. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * Window info will be deleted. + * + *-------------------------------------------------------------- + */ +int +Table_WinDelete(register Table *tablePtr, char *CONST idxPtr) +{ + Tcl_HashEntry *entryPtr; + + entryPtr = Tcl_FindHashEntry(tablePtr->winTable, idxPtr); + if (entryPtr != NULL) { + /* get the window pointer & clean up data associated with it */ + EmbWinDelete(tablePtr, (TableEmbWindow *) Tcl_GetHashValue(entryPtr)); + } + return TCL_OK; +} + +/* + *-------------------------------------------------------------- + * + * Table_WindowCmd -- + * This procedure is invoked to process the window method + * that corresponds to a 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_WindowCmd(ClientData clientData, register Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + register Table *tablePtr = (Table *)clientData; + int result = TCL_OK, cmdIndex, row, col, x, y, width, height, i, new; + TableEmbWindow *ewPtr; + Tcl_HashEntry *entryPtr; + Tcl_HashSearch search; + char buf[INDEX_BUFSIZE], *keybuf, *winname; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } + + /* parse the next argument */ + if (Tcl_GetIndexFromObj(interp, objv[2], winCmdNames, + "option", 0, &cmdIndex) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum winCommand) cmdIndex) { + case WIN_CGET: + if (objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, "index option"); + return TCL_ERROR; + } + entryPtr = Tcl_FindHashEntry(tablePtr->winTable, + Tcl_GetString(objv[3])); + if (entryPtr == NULL) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "no window at index \"", + Tcl_GetString(objv[3]), "\"", (char *)NULL); + return TCL_ERROR; + } else { + ewPtr = (TableEmbWindow *) Tcl_GetHashValue(entryPtr); + result = Tk_ConfigureValue(interp, tablePtr->tkwin, winConfigSpecs, + (char *) ewPtr, + Tcl_GetString(objv[4]), 0); + } + return result; /* CGET */ + + case WIN_CONFIGURE: + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index ?arg arg ...?"); + return TCL_ERROR; + } + if (TableGetIndexObj(tablePtr, objv[3], &row, &col) == TCL_ERROR) { + return TCL_ERROR; + } + TableMakeArrayIndex(row, col, buf); + entryPtr = Tcl_CreateHashEntry(tablePtr->winTable, buf, &new); + + if (new) { + /* create the structure */ + ewPtr = TableNewEmbWindow(tablePtr); + + /* insert it into the table */ + Tcl_SetHashValue(entryPtr, (ClientData) ewPtr); + ewPtr->hPtr = entryPtr; + + /* configure the window structure */ + result = EmbWinConfigure(tablePtr, ewPtr, objc-4, objv+4); + if (result == TCL_ERROR) { + /* release the structure */ + EmbWinCleanup(tablePtr, ewPtr); + ckfree((char *) ewPtr); + + /* and free the hash table entry */ + Tcl_DeleteHashEntry(entryPtr); + } + } else { + /* window exists, do a reconfig if we have enough args */ + /* get the window pointer from the table */ + ewPtr = (TableEmbWindow *) Tcl_GetHashValue(entryPtr); + + /* 5 args means that there are values to replace */ + if (objc > 5) { + /* and do a reconfigure */ + result = EmbWinConfigure(tablePtr, ewPtr, objc-4, objv+4); + } + } + if (result == TCL_ERROR) { + return TCL_ERROR; + } + + /* + * If there were less than 6 args, we need + * to do a printout of the config, even for new windows + */ + if (objc < 6) { + result = Tk_ConfigureInfo(interp, tablePtr->tkwin, winConfigSpecs, + (char *) ewPtr, (objc == 5)? + Tcl_GetString(objv[4]) : NULL, 0); + } else { + /* Otherwise we reconfigured so invalidate + * the table for a redraw */ + if (TableCellVCoords(tablePtr, row-tablePtr->rowOffset, + col-tablePtr->colOffset, + &x, &y, &width, &height, 0)) { + TableInvalidate(tablePtr, x, y, width, height, 1); + } + } + return result; /* CONFIGURE */ + + case WIN_DELETE: + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index ?index ...?"); + return TCL_ERROR; + } + for (i = 3; i < objc; i++) { + Table_WinDelete(tablePtr, Tcl_GetString(objv[i])); + } + break; + + case WIN_MOVE: + if (objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, "srcIndex destIndex"); + return TCL_ERROR; + } + result = Table_WinMove(tablePtr, Tcl_GetString(objv[3]), + Tcl_GetString(objv[4]), INV_FORCE); + break; + + case WIN_NAMES: { + Tcl_Obj *objPtr = Tcl_NewObj(); + + /* just print out the window names */ + if (objc < 3 || objc > 4) { + Tcl_WrongNumArgs(interp, 3, objv, "?pattern?"); + return TCL_ERROR; + } + winname = (objc == 4) ? Tcl_GetString(objv[3]) : NULL; + entryPtr = Tcl_FirstHashEntry(tablePtr->winTable, &search); + while (entryPtr != NULL) { + keybuf = Tcl_GetHashKey(tablePtr->winTable, entryPtr); + if (objc == 3 || Tcl_StringMatch(keybuf, winname)) { + Tcl_ListObjAppendElement(NULL, objPtr, + Tcl_NewStringObj(keybuf, -1)); + } + entryPtr = Tcl_NextHashEntry(&search); + } + Tcl_SetObjResult(interp, TableCellSortObj(interp, objPtr)); + break; + } + } + return TCL_OK; +} diff --git a/tktable/generic/version.h b/tktable/generic/version.h new file mode 100755 index 0000000..91d1bbe --- /dev/null +++ b/tktable/generic/version.h @@ -0,0 +1,8 @@ +#if 0 +TBL_MAJOR_VERSION = 2 +TBL_MINOR_VERSION = 10 +PACKAGE_VERSION = $(TBL_MAJOR_VERSION).$(TBL_MINOR_VERSION) +#endif +#define TBL_MAJOR_VERSION 2 +#define TBL_MINOR_VERSION 10 +#define PACKAGE_VERSION "2.10" diff --git a/tktable/library/tkTable.tcl b/tktable/library/tkTable.tcl new file mode 100755 index 0000000..0343a43 --- /dev/null +++ b/tktable/library/tkTable.tcl @@ -0,0 +1,825 @@ +# table.tcl -- +# +# Version align with tkTable 2.7, jeff at hobbs org +# This file defines the default bindings for Tk table widgets +# and provides procedures that help in implementing those bindings. +# +# RCS: @(#) $Id: tkTable.tcl,v 1.1.1.1 2011/03/01 20:00:38 joye Exp $ + +#-------------------------------------------------------------------------- +# ::tk::table::Priv elements used in this file: +# +# x && y - Coords in widget +# afterId - Token returned by "after" for autoscanning. +# tablePrev - The last element to be selected or deselected +# during a selection operation. +# mouseMoved - Boolean to indicate whether mouse moved while +# the button was pressed. +# borderInfo - Boolean to know if the user clicked on a border +# borderB1 - Boolean that set whether B1 can be used for the +# interactiving resizing +#-------------------------------------------------------------------------- + +namespace eval ::tk::table { + # Ensure that a namespace is created for us + variable Priv + array set Priv [list x 0 y 0 afterId {} mouseMoved 0 \ + borderInfo {} borderB1 1] +} + +# ::tk::table::ClipboardKeysyms -- +# This procedure is invoked to identify the keys that correspond to +# the "copy", "cut", and "paste" functions for the clipboard. +# +# Arguments: +# copy - Name of the key (keysym name plus modifiers, if any, +# such as "Meta-y") used for the copy operation. +# cut - Name of the key used for the cut operation. +# paste - Name of the key used for the paste operation. + +proc ::tk::table::ClipboardKeysyms {copy cut paste} { + bind Table <$copy> {tk_tableCopy %W} + bind Table <$cut> {tk_tableCut %W} + bind Table <$paste> {tk_tablePaste %W} +} +::tk::table::ClipboardKeysyms <Copy> <Cut> <Paste> + +## +## Interactive cell resizing, affected by -resizeborders option +## +bind Table <3> { + ## You might want to check for cell returned if you want to + ## restrict the resizing of certain cells + %W border mark %x %y +} +bind Table <B3-Motion> { %W border dragto %x %y } + +## Button events + +bind Table <1> { ::tk::table::Button1 %W %x %y } +bind Table <B1-Motion> { ::tk::table::B1Motion %W %x %y } + +bind Table <ButtonRelease-1> { + if {$::tk::table::Priv(borderInfo) == "" && [winfo exists %W]} { + ::tk::table::CancelRepeat + %W activate @%x,%y + } +} +bind Table <Double-1> { + # empty +} + +bind Table <Shift-1> {::tk::table::BeginExtend %W [%W index @%x,%y]} +bind Table <Control-1> {::tk::table::BeginToggle %W [%W index @%x,%y]} +bind Table <B1-Enter> {::tk::table::CancelRepeat} +bind Table <B1-Leave> { + if {$::tk::table::Priv(borderInfo) == ""} { + array set ::tk::table::Priv {x %x y %y} + ::tk::table::AutoScan %W + } +} +bind Table <2> { + %W scan mark %x %y + array set ::tk::table::Priv {x %x y %y} + set ::tk::table::Priv(mouseMoved) 0 +} +bind Table <B2-Motion> { + if {(%x != $::tk::table::Priv(x)) || (%y != $::tk::table::Priv(y))} { + set ::tk::table::Priv(mouseMoved) 1 + } + if {$::tk::table::Priv(mouseMoved)} { %W scan dragto %x %y } +} +bind Table <ButtonRelease-2> { + if {!$::tk::table::Priv(mouseMoved)} { tk_tablePaste %W [%W index @%x,%y] } +} + +## Key events + +# This forces a cell commit if an active cell exists +bind Table <<Table_Commit>> { + catch {%W activate active} +} +# Remove this if you don't want cell commit to occur on every Leave for +# the table (via mouse) or FocusOut (loss of focus by table). +event add <<Table_Commit>> <Leave> <FocusOut> + +bind Table <Shift-Up> {::tk::table::ExtendSelect %W -1 0} +bind Table <Shift-Down> {::tk::table::ExtendSelect %W 1 0} +bind Table <Shift-Left> {::tk::table::ExtendSelect %W 0 -1} +bind Table <Shift-Right> {::tk::table::ExtendSelect %W 0 1} +bind Table <Prior> {%W yview scroll -1 pages; %W activate topleft} +bind Table <Next> {%W yview scroll 1 pages; %W activate topleft} +bind Table <Control-Prior> {%W xview scroll -1 pages} +bind Table <Control-Next> {%W xview scroll 1 pages} +bind Table <Home> {%W see origin} +bind Table <End> {%W see end} +bind Table <Control-Home> { + %W selection clear all + %W activate origin + %W selection set active + %W see active +} +bind Table <Control-End> { + %W selection clear all + %W activate end + %W selection set active + %W see active +} +bind Table <Shift-Control-Home> {::tk::table::DataExtend %W origin} +bind Table <Shift-Control-End> {::tk::table::DataExtend %W end} +bind Table <Select> {::tk::table::BeginSelect %W [%W index active]} +bind Table <Shift-Select> {::tk::table::BeginExtend %W [%W index active]} +bind Table <Control-slash> {::tk::table::SelectAll %W} +bind Table <Control-backslash> { + if {[string match browse [%W cget -selectmode]]} {%W selection clear all} +} +bind Table <Up> {::tk::table::MoveCell %W -1 0} +bind Table <Down> {::tk::table::MoveCell %W 1 0} +bind Table <Left> {::tk::table::MoveCell %W 0 -1} +bind Table <Right> {::tk::table::MoveCell %W 0 1} +bind Table <KeyPress> {::tk::table::Insert %W %A} +bind Table <BackSpace> {::tk::table::BackSpace %W} +bind Table <Delete> {%W delete active insert} +bind Table <Escape> {%W reread} + +#bind Table <Return> {::tk::table::MoveCell %W 1 0} +bind Table <Return> {::tk::table::Insert %W "\n"} + +bind Table <Control-Left> {%W icursor [expr {[%W icursor]-1}]} +bind Table <Control-Right> {%W icursor [expr {[%W icursor]+1}]} +bind Table <Control-e> {%W icursor end} +bind Table <Control-a> {%W icursor 0} +bind Table <Control-k> {%W delete active insert end} +bind Table <Control-equal> {::tk::table::ChangeWidth %W active 1} +bind Table <Control-minus> {::tk::table::ChangeWidth %W active -1} + +# Ignore all Alt, Meta, and Control keypresses unless explicitly bound. +# Otherwise, if a widget binding for one of these is defined, the +# <KeyPress> class binding will also fire and insert the character, +# which is wrong. Ditto for Tab. + +bind Table <Alt-KeyPress> {# nothing} +bind Table <Meta-KeyPress> {# nothing} +bind Table <Control-KeyPress> {# nothing} +bind Table <Any-Tab> {# nothing} +if {[string match "macintosh" $::tcl_platform(platform)]} { + bind Table <Command-KeyPress> {# nothing} +} + +# ::tk::table::GetSelection -- +# This tries to obtain the default selection. On Unix, we first try +# and get a UTF8_STRING, a type supported by modern Unix apps for +# passing Unicode data safely. We fall back on the default STRING +# type otherwise. On Windows, only the STRING type is necessary. +# Arguments: +# w The widget for which the selection will be retrieved. +# Important for the -displayof property. +# sel The source of the selection (PRIMARY or CLIPBOARD) +# Results: +# Returns the selection, or an error if none could be found +# +if {[string compare $::tcl_platform(platform) "unix"]} { + proc ::tk::table::GetSelection {w {sel PRIMARY}} { + if {[catch {selection get -displayof $w -selection $sel} txt]} { + return -code error "could not find default selection" + } else { + return $txt + } + } +} else { + proc ::tk::table::GetSelection {w {sel PRIMARY}} { + if {[catch {selection get -displayof $w -selection $sel \ + -type UTF8_STRING} txt] \ + && [catch {selection get -displayof $w -selection $sel} txt]} { + return -code error "could not find default selection" + } else { + return $txt + } + } +} + +# ::tk::table::CancelRepeat -- +# A copy of tkCancelRepeat, just in case it's not available or changes. +# This procedure is invoked to cancel an auto-repeat action described +# by ::tk::table::Priv(afterId). It's used by several widgets to auto-scroll +# the widget when the mouse is dragged out of the widget with a +# button pressed. +# +# Arguments: +# None. + +proc ::tk::table::CancelRepeat {} { + variable Priv + after cancel $Priv(afterId) + set Priv(afterId) {} +} + +# ::tk::table::Insert -- +# +# Insert into the active cell +# +# Arguments: +# w - the table widget +# s - the string to insert +# Results: +# Returns nothing +# +proc ::tk::table::Insert {w s} { + if {[string compare $s {}]} { + $w insert active insert $s + } +} + +# ::tk::table::BackSpace -- +# +# BackSpace in the current cell +# +# Arguments: +# w - the table widget +# Results: +# Returns nothing +# +proc ::tk::table::BackSpace {w} { + set cur [$w icursor] + if {[string compare {} $cur] && $cur} { + $w delete active [expr {$cur-1}] + } +} + +# ::tk::table::Button1 -- +# +# This procedure is called to handle selecting with mouse button 1. +# It will distinguish whether to start selection or mark a border. +# +# Arguments: +# w - the table widget +# x - x coord +# y - y coord +# Results: +# Returns nothing +# +proc ::tk::table::Button1 {w x y} { + variable Priv + # + # $Priv(borderInfo) is null if the user did not click on a border + # + if {$Priv(borderB1) == 1} { + set Priv(borderInfo) [$w border mark $x $y] + # account for what resizeborders are set [Bug 876320] (ferenc) + set rbd [$w cget -resizeborders] + if {$rbd == "none" || ![llength $Priv(borderInfo)] + || ($rbd == "col" && [lindex $Priv(borderInfo) 1] == "") + || ($rbd == "row" && [lindex $Priv(borderInfo) 0] == "")} { + set Priv(borderInfo) "" + } + } else { + set Priv(borderInfo) "" + } + if {$Priv(borderInfo) == ""} { + # + # Only do this when a border wasn't selected + # + if {[winfo exists $w]} { + ::tk::table::BeginSelect $w [$w index @$x,$y] + focus $w + } + array set Priv [list x $x y $y] + set Priv(mouseMoved) 0 + } +} + +# ::tk::table::B1Motion -- +# +# This procedure is called to start processing mouse motion events while +# button 1 moves while pressed. It will distinguish whether to change +# the selection or move a border. +# +# Arguments: +# w - the table widget +# x - x coord +# y - y coord +# Results: +# Returns nothing +# +proc ::tk::table::B1Motion {w x y} { + variable Priv + + # If we already had motion, or we moved more than 1 pixel, + # then we start the Motion routine + if {$Priv(borderInfo) != ""} { + # + # If the motion is on a border, drag it and skip the rest + # of this binding. + # + $w border dragto $x $y + } else { + # + # If we already had motion, or we moved more than 1 pixel, + # then we start the Motion routine + # + if { + $::tk::table::Priv(mouseMoved) + || abs($x-$::tk::table::Priv(x)) > 1 + || abs($y-$::tk::table::Priv(y)) > 1 + } { + set ::tk::table::Priv(mouseMoved) 1 + } + if {$::tk::table::Priv(mouseMoved)} { + ::tk::table::Motion $w [$w index @$x,$y] + } + } +} + +# ::tk::table::BeginSelect -- +# +# This procedure is typically invoked on button-1 presses. It begins +# the process of making a selection in the table. Its exact behavior +# depends on the selection mode currently in effect for the table; +# see the Motif documentation for details. +# +# Arguments: +# w - The table widget. +# el - The element for the selection operation (typically the +# one under the pointer). Must be in row,col form. + +proc ::tk::table::BeginSelect {w el} { + variable Priv + if {[scan $el %d,%d r c] != 2} return + switch [$w cget -selectmode] { + multiple { + if {[$w tag includes title $el]} { + ## in the title area + if {$r < [$w cget -titlerows]+[$w cget -roworigin]} { + ## We're in a column header + if {$c < [$w cget -titlecols]+[$w cget -colorigin]} { + ## We're in the topleft title area + set inc topleft + set el2 end + } else { + set inc [$w index topleft row],$c + set el2 [$w index end row],$c + } + } else { + ## We're in a row header + set inc $r,[$w index topleft col] + set el2 $r,[$w index end col] + } + } else { + set inc $el + set el2 $el + } + if {[$w selection includes $inc]} { + $w selection clear $el $el2 + } else { + $w selection set $el $el2 + } + } + extended { + $w selection clear all + if {[$w tag includes title $el]} { + if {$r < [$w cget -titlerows]+[$w cget -roworigin]} { + ## We're in a column header + if {$c < [$w cget -titlecols]+[$w cget -colorigin]} { + ## We're in the topleft title area + $w selection set $el end + } else { + $w selection set $el [$w index end row],$c + } + } else { + ## We're in a row header + $w selection set $el $r,[$w index end col] + } + } else { + $w selection set $el + } + $w selection anchor $el + set Priv(tablePrev) $el + } + default { + if {![$w tag includes title $el]} { + $w selection clear all + $w selection set $el + set Priv(tablePrev) $el + } + $w selection anchor $el + } + } +} + +# ::tk::table::Motion -- +# +# This procedure is called to process mouse motion events while +# button 1 is down. It may move or extend the selection, depending +# on the table's selection mode. +# +# Arguments: +# w - The table widget. +# el - The element under the pointer (must be in row,col form). + +proc ::tk::table::Motion {w el} { + variable Priv + if {![info exists Priv(tablePrev)]} { + set Priv(tablePrev) $el + return + } + if {[string match $Priv(tablePrev) $el]} return + switch [$w cget -selectmode] { + browse { + $w selection clear all + $w selection set $el + set Priv(tablePrev) $el + } + extended { + # avoid tables that have no anchor index yet. + if {[catch {$w index anchor}]} { return } + scan $Priv(tablePrev) %d,%d r c + scan $el %d,%d elr elc + if {[$w tag includes title $el]} { + if {$r < [$w cget -titlerows]+[$w cget -roworigin]} { + ## We're in a column header + if {$c < [$w cget -titlecols]+[$w cget -colorigin]} { + ## We're in the topleft title area + $w selection clear anchor end + } else { + $w selection clear anchor [$w index end row],$c + } + $w selection set anchor [$w index end row],$elc + } else { + ## We're in a row header + $w selection clear anchor $r,[$w index end col] + $w selection set anchor $elr,[$w index end col] + } + } else { + $w selection clear anchor $Priv(tablePrev) + $w selection set anchor $el + } + set Priv(tablePrev) $el + } + } +} + +# ::tk::table::BeginExtend -- +# +# This procedure is typically invoked on shift-button-1 presses. It +# begins the process of extending a selection in the table. Its +# exact behavior depends on the selection mode currently in effect +# for the table; see the Motif documentation for details. +# +# Arguments: +# w - The table widget. +# el - The element for the selection operation (typically the +# one under the pointer). Must be in numerical form. + +proc ::tk::table::BeginExtend {w el} { + # avoid tables that have no anchor index yet. + if {[catch {$w index anchor}]} { return } + if {[string match extended [$w cget -selectmode]] && + [$w selection includes anchor]} { + ::tk::table::Motion $w $el + } +} + +# ::tk::table::BeginToggle -- +# +# This procedure is typically invoked on control-button-1 presses. It +# begins the process of toggling a selection in the table. Its +# exact behavior depends on the selection mode currently in effect +# for the table; see the Motif documentation for details. +# +# Arguments: +# w - The table widget. +# el - The element for the selection operation (typically the +# one under the pointer). Must be in numerical form. + +proc ::tk::table::BeginToggle {w el} { + if {[string match extended [$w cget -selectmode]]} { + variable Priv + set Priv(tablePrev) $el + $w selection anchor $el + if {[$w tag includes title $el]} { + scan $el %d,%d r c + if {$r < [$w cget -titlerows]+[$w cget -roworigin]} { + ## We're in a column header + if {$c < [$w cget -titlecols]+[$w cget -colorigin]} { + ## We're in the topleft title area + set end end + } else { + set end [$w index end row],$c + } + } else { + ## We're in a row header + set end $r,[$w index end col] + } + } else { + ## We're in a non-title cell + set end $el + } + if {[$w selection includes $end]} { + $w selection clear $el $end + } else { + $w selection set $el $end + } + } +} + +# ::tk::table::AutoScan -- +# This procedure is invoked when the mouse leaves an table window +# with button 1 down. It scrolls the window up, down, left, or +# right, depending on where the mouse left the window, and reschedules +# itself as an "after" command so that the window continues to scroll until +# the mouse moves back into the window or the mouse button is released. +# +# Arguments: +# w - The table window. + +proc ::tk::table::AutoScan {w} { + if {![winfo exists $w]} return + variable Priv + set x $Priv(x) + set y $Priv(y) + if {$y >= [winfo height $w]} { + $w yview scroll 1 units + } elseif {$y < 0} { + $w yview scroll -1 units + } elseif {$x >= [winfo width $w]} { + $w xview scroll 1 units + } elseif {$x < 0} { + $w xview scroll -1 units + } else { + return + } + ::tk::table::Motion $w [$w index @$x,$y] + set Priv(afterId) [after 50 ::tk::table::AutoScan $w] +} + +# ::tk::table::MoveCell -- +# +# Moves the location cursor (active element) by the specified number +# of cells and changes the selection if we're in browse or extended +# selection mode. If the new cell is "hidden", we skip to the next +# visible cell if possible, otherwise just abort. +# +# Arguments: +# w - The table widget. +# x - +1 to move down one cell, -1 to move up one cell. +# y - +1 to move right one cell, -1 to move left one cell. + +proc ::tk::table::MoveCell {w x y} { + if {[catch {$w index active row} r]} return + set c [$w index active col] + set cell [$w index [incr r $x],[incr c $y]] + while {[string compare [set true [$w hidden $cell]] {}]} { + # The cell is in some way hidden + if {[string compare $true [$w index active]]} { + # The span cell wasn't the previous cell, so go to that + set cell $true + break + } + if {$x > 0} {incr r} elseif {$x < 0} {incr r -1} + if {$y > 0} {incr c} elseif {$y < 0} {incr c -1} + if {[string compare $cell [$w index $r,$c]]} { + set cell [$w index $r,$c] + } else { + # We couldn't find a non-hidden cell, just don't move + return + } + } + $w activate $cell + $w see active + switch [$w cget -selectmode] { + browse { + $w selection clear all + $w selection set active + } + extended { + variable Priv + $w selection clear all + $w selection set active + $w selection anchor active + set Priv(tablePrev) [$w index active] + } + } +} + +# ::tk::table::ExtendSelect -- +# +# Does nothing unless we're in extended selection mode; in this +# case it moves the location cursor (active element) by the specified +# number of cells, and extends the selection to that point. +# +# Arguments: +# w - The table widget. +# x - +1 to move down one cell, -1 to move up one cell. +# y - +1 to move right one cell, -1 to move left one cell. + +proc ::tk::table::ExtendSelect {w x y} { + if {[string compare extended [$w cget -selectmode]] || + [catch {$w index active row} r]} return + set c [$w index active col] + $w activate [incr r $x],[incr c $y] + $w see active + ::tk::table::Motion $w [$w index active] +} + +# ::tk::table::DataExtend +# +# This procedure is called for key-presses such as Shift-KEndData. +# If the selection mode isnt multiple or extend then it does nothing. +# Otherwise it moves the active element to el and, if we're in +# extended mode, extends the selection to that point. +# +# Arguments: +# w - The table widget. +# el - An integer cell number. + +proc ::tk::table::DataExtend {w el} { + set mode [$w cget -selectmode] + if {[string match extended $mode]} { + $w activate $el + $w see $el + if {[$w selection includes anchor]} {::tk::table::Motion $w $el} + } elseif {[string match multiple $mode]} { + $w activate $el + $w see $el + } +} + +# ::tk::table::SelectAll +# +# This procedure is invoked to handle the "select all" operation. +# For single and browse mode, it just selects the active element. +# Otherwise it selects everything in the widget. +# +# Arguments: +# w - The table widget. + +proc ::tk::table::SelectAll {w} { + if {[regexp {^(single|browse)$} [$w cget -selectmode]]} { + $w selection clear all + catch {$w selection set active} + } elseif {[$w cget -selecttitles]} { + $w selection set [$w cget -roworigin],[$w cget -colorigin] end + } else { + $w selection set origin end + } +} + +# ::tk::table::ChangeWidth -- +# +# Adjust the widget of the specified cell by $a. +# +# Arguments: +# w - The table widget. +# i - cell index +# a - amount to adjust by + +proc ::tk::table::ChangeWidth {w i a} { + set tmp [$w index $i col] + if {[set width [$w width $tmp]] >= 0} { + $w width $tmp [incr width $a] + } else { + $w width $tmp [incr width [expr {-$a}]] + } +} + +# tk_tableCopy -- +# +# This procedure copies the selection from a table widget into the +# clipboard. +# +# Arguments: +# w - Name of a table widget. + +proc tk_tableCopy w { + if {[selection own -displayof $w] == "$w"} { + clipboard clear -displayof $w + catch {clipboard append -displayof $w [::tk::table::GetSelection $w]} + } +} + +# tk_tableCut -- +# +# This procedure copies the selection from a table widget into the +# clipboard, then deletes the selection (if it exists in the given +# widget). +# +# Arguments: +# w - Name of a table widget. + +proc tk_tableCut w { + if {[selection own -displayof $w] == "$w"} { + clipboard clear -displayof $w + catch { + clipboard append -displayof $w [::tk::table::GetSelection $w] + $w cursel {} + $w selection clear all + } + } +} + +# tk_tablePaste -- +# +# This procedure pastes the contents of the clipboard to the specified +# cell (active by default) in a table widget. +# +# Arguments: +# w - Name of a table widget. +# cell - Cell to start pasting in. +# +proc tk_tablePaste {w {cell {}}} { + if {[string compare {} $cell]} { + if {[catch {::tk::table::GetSelection $w} data]} return + } else { + if {[catch {::tk::table::GetSelection $w CLIPBOARD} data]} { + return + } + set cell active + } + tk_tablePasteHandler $w [$w index $cell] $data + if {[$w cget -state] == "normal"} {focus $w} +} + +# tk_tablePasteHandler -- +# +# This procedure handles how data is pasted into the table widget. +# This handles data in the default table selection form. +# +# NOTE: this allows pasting into all cells except title cells, +# even those with -state disabled +# +# Arguments: +# w - Name of a table widget. +# cell - Cell to start pasting in. +# +proc tk_tablePasteHandler {w cell data} { + # + # Don't allow pasting into the title cells + # + if {[$w tag includes title $cell]} { + return + } + + set rows [expr {[$w cget -rows]-[$w cget -roworigin]}] + set cols [expr {[$w cget -cols]-[$w cget -colorigin]}] + set r [$w index $cell row] + set c [$w index $cell col] + set rsep [$w cget -rowseparator] + set csep [$w cget -colseparator] + ## Assume separate rows are split by row separator if specified + ## If you were to want multi-character row separators, you would need: + # regsub -all $rsep $data <newline> data + # set data [join $data <newline>] + if {[string compare {} $rsep]} { set data [split $data $rsep] } + set row $r + foreach line $data { + if {$row > $rows} break + set col $c + ## Assume separate cols are split by col separator if specified + ## Unless a -separator was specified + if {[string compare {} $csep]} { set line [split $line $csep] } + ## If you were to want multi-character col separators, you would need: + # regsub -all $csep $line <newline> line + # set line [join $line <newline>] + foreach item $line { + if {$col > $cols} break + $w set $row,$col $item + incr col + } + incr row + } +} + +# tk::table::Sort -- +# +# This procedure handles how data is sorted in the table widget. +# This isn't currently used by tktable, but can be called by the user. +# It's behavior may change in the future. +# +# Arguments: +# w - Name of a table widget. +# start - start cell of rectangle to sort +# end - end cell of rectangle to sort +# col - column within rectangle to sort on +# args - passed to lsort proc (ie: -integer -decreasing) + +proc ::tk::table::Sort {w start end col args} { + set start [$w index $start] + set end [$w index $end] + scan $start %d,%d sr sc + scan $end %d,%d er ec + if {($col < $sc) || ($col > $ec)} { + return -code error "$col is not within sort range $sc to $ec" + } + set col [expr {$col - $sc}] + + set data {} + for {set i $sr} {$i <= $er} {incr i} { + lappend data [$w get $i,$sc $i,$ec] + } + + set i $sr + foreach row [eval [list lsort -index $col] $args [list $data]] { + $w set row $i,$sc $row + incr i + } +} diff --git a/tktable/library/tktable.py b/tktable/library/tktable.py new file mode 100755 index 0000000..d293f9f --- /dev/null +++ b/tktable/library/tktable.py @@ -0,0 +1,651 @@ +# Updated tktable.py wrapper for Python 2.x with Tkinter. +# Improvements over previous version can be seen at: +# https://sf.net/tracker2/?func=detail&aid=2244167&group_id=11464&atid=311464 +# +# Copyright (c) 2008, Guilherme Polo +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +This contains a wrapper class for the tktable widget as well a class for using +tcl arrays that are, in some instances, required by tktable. +""" + +__author__ = "Guilherme Polo <ggpolo@gmail.com>" + +__all__ = ["ArrayVar", "Table"] + +import Tkinter + +def _setup_master(master): + if master is None: + if Tkinter._support_default_root: + master = Tkinter._default_root or Tkinter.Tk() + else: + raise RuntimeError("No master specified and Tkinter is " + "configured to not support default master") + return master + +class ArrayVar(Tkinter.Variable): + def __init__(self, master=None, name=None): + # Tkinter.Variable.__init__ is not called on purpose! I don't wanna + # see an ugly _default value in the pretty array. + self._master = _setup_master(master) + self._tk = self._master.tk + if name: + self._name = name + else: + self._name = 'PY_VAR%s' % id(self) + + def get(self, index=None): + if index is None: + res = {} + for key in self.names(): + res[key] = self._tk.globalgetvar(str(self), key) + return res + + return self._tk.globalgetvar(str(self), str(index)) + + def names(self): + return self._tk.call('array', 'names', self._name) + + def set(self, key, value): + self._tk.globalsetvar(str(self), str(key), value) + + +class Table(Tkinter.Widget): + """Create and manipulate tables.""" + + _switches = ('holddimensions', 'holdselection', 'holdtags', 'holdwindows', + 'keeptitles', '-') + _tabsubst_format = ('%c', '%C', '%i', '%r', '%s', '%S', '%W') + _tabsubst_commands = ('browsecommand', 'browsecmd', 'command', + 'selectioncommand', 'selcmd', + 'validatecommand', 'valcmd') + + def __init__(self, master=None, **kw): + master = _setup_master(master) + try: + master.tk.call('package', 'require', 'Tktable') + except Tkinter.TclError: + try: + master.tk.call('load', 'Tktable.dll', 'Tktable') + except Tkinter.TclError: + master.tk.call('load', '', 'Tktable') + + Tkinter.Widget.__init__(self, master, 'table', kw) + + + def _options(self, cnf, kw=None): + if kw: + cnf = Tkinter._cnfmerge((cnf, kw)) + else: + cnf = Tkinter._cnfmerge(cnf) + + res = () + for k, v in cnf.iteritems(): + if callable(v): + if k in self._tabsubst_commands: + v = "%s %s" % (self._register(v, self._tabsubst), + ' '.join(self._tabsubst_format)) + else: + v = self._register(v) + res += ('-%s' % k, v) + + return res + + + def _tabsubst(self, *args): + if len(args) != len(self._tabsubst_format): + return args + + tk = self.tk + c, C, i, r, s, S, W = args + e = Tkinter.Event() + + e.widget = self + e.c = tk.getint(c) + e.i = tk.getint(i) + e.r = tk.getint(r) + e.C = (e.r, e.c) + try: + e.s = tk.getint(s) + except Tkinter.TclError: + e.s = s + try: + e.S = tk.getint(S) + except Tkinter.TclError: + e.S = S + e.W = W + + return (e,) + + + def _handle_switches(self, args): + args = args or () + return tuple(('-%s' % x) for x in args if x in self._switches) + + + def activate(self, index): + """Set the active cell to the one indicated by index.""" + self.tk.call(self._w, 'activate', index) + + + def bbox(self, first, last=None): + """Return 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 tuple is returned.""" + return self._getints(self.tk.call(self._w, 'bbox', first, last)) or () + + + def clear(self, option, first=None, last=None): + """This is a convenience routine to clear certain state information + managed by the table. first and last represent valid table indices. + If neither are specified, then the command operates on the whole + table.""" + self.tk.call(self._w, 'clear', option, first, last) + + + def clear_cache(self, first=None, last=None): + """Clear the specified section of the cache, if the table has been + keeping one.""" + self.clear('cache', first, last) + + + def clear_sizes(self, first=None, last=None): + """Clear the specified row and column areas of specific height/width + dimensions. When just one index is specified, for example 2,0, that + is interpreted as row 2 and column 0.""" + self.clear('sizes', first, last) + + + def clear_tags(self, first=None, last=None): + """Clear the specified area of tags (all row, column and cell tags).""" + self.clear('tags', first, last) + + + def clear_all(self, first=None, last=None): + """Perform all of the above clear functions on the specified area.""" + self.clear('all', first, last) + + + def curselection(self, value=None): + """With no arguments, it returns the sorted indices of the currently + selected cells. Otherwise it sets all the selected cells to the given + value if there is an associated ArrayVar and the state is not + disabled.""" + result = self.tk.call(self._w, 'curselection', value) + if value is None: + return result + + + def curvalue(self, value=None): + """If no value is given, the value of the cell being edited (indexed + by active) is returned, else it is set to the given value. """ + return self.tk.call(self._w, 'curvalue', value) + + + def delete_active(self, index1, index2=None): + """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. index can be a number, insert or end.""" + self.tk.call(self._w, 'delete', 'active', index1, index2) + + + def delete_cols(self, index, count=None, switches=None): + args = self._handle_switches(switches) + (index, count) + self.tk.call(self._w, 'delete', 'cols', *args) + + + def delete_rows(self, index, count=None, switches=None): + args = self._handle_switches(switches) + (index, count) + self.tk.call(self._w, 'delete', 'rows', *args) + + + def get(self, first, last=None): + """Returns the value of the cells specified by the table indices + first and (optionally) last.""" + return self.tk.call(self._w, 'get', first, last) + + + def height(self, row=None, **kwargs): + """If row and kwargs are not given, a list describing all rows for + which a width has been set is returned. + If row is given, the height of that row is returnd. + If kwargs is given, then it sets the key/value pairs, where key is a + row and value represents the height for the row.""" + if row is None and not kwargs: + pairs = self.tk.splitlist(self.tk.call(self._w, 'height')) + return dict(pair.split() for pair in pairs) + elif row: + return int(self.tk.call(self._w, 'height', str(row))) + + args = Tkinter._flatten(kwargs.items()) + self.tk.call(self._w, 'height', *args) + + + def hidden(self, *args): + """When called without args, it returns all the hidden 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.""" + return self.tk.call(self._w, 'hidden', *args) + + + def icursor(self, arg=None): + """If arg is not specified, return the location of the insertion + cursor in the active cell. Otherwise, set the cursor to that point in + the string. + + 0 is before the first character, you can also use insert or end 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.""" + return self.tk.call(self._w, 'icursor', arg) + + + def index(self, index, rc=None): + """Return the integer cell coordinate that corresponds to index in the + form row, col. If rc is specified, it must be either 'row' or 'col' so + only the row or column index is returned.""" + res = self.tk.call(self._w, 'index', index, rc) + if rc is None: + return res + else: + return int(res) + + + def insert_active(self, index, value): + """The value is a text string which is inserted at the index postion + of the active cell. The cursor is then positioned after the new text. + index can be a number, insert or end. """ + self.tk.call(self._w, 'insert', 'active', index, value) + + + def insert_cols(self, index, count=None, switches=None): + args = self._handle_switches(switches) + (index, count) + self.tk.call(self._w, 'insert', 'cols', *args) + + + def insert_rows(self, index, count=None, switches=None): + args = self._handle_switches(switches) + (index, count) + self.tk.call(self._w, 'insert', 'rows', *args) + + + #def postscript(self, **kwargs): + # """Skip this command if you are under Windows. + # + # Accepted options: + # colormap, colormode, file, channel, first, fontmap, height, + # last, pageanchor, pageheight, pagewidth, pagex, pagey, rotate, + # width, x, y + # """ + # args = () + # for key, val in kwargs.iteritems(): + # args += ('-%s' % key, val) + # + # return self.tk.call(self._w, 'postscript', *args) + + + def reread(self): + """Rereads the old contents of the cell back into the editing buffer. + Useful for a key binding when <Escape> is pressed to abort the edit + (a default binding).""" + self.tk.call(self._w, 'reread') + + + def scan_mark(self, x, y): + self.tk.call(self._w, 'scan', 'mark', x, y) + + + def scan_dragto(self, x, y): + self.tk.call(self._w, 'scan', 'dragto', x, y) + + + def see(self, index): + self.tk.call(self._w, 'see', index) + + + def selection_anchor(self, index): + self.tk.call(self._w, 'selection', 'anchor', index) + + + def selection_clear(self, first, last=None): + self.tk.call(self._w, 'selection', 'clear', first, last) + + + def selection_includes(self, index): + return self.getboolean(self.tk.call(self._w, 'selection', 'includes', + index)) + + + def selection_set(self, first, last=None): + self.tk.call(self._w, 'selection', 'set', first, last) + + + def set(self, rc=None, index=None, *args, **kwargs): + """If rc is specified (either 'row' or 'col') then it is assumes that + args (if given) represents values which will be set into the + subsequent columns (if row is specified) or rows (for col). + If index is not None and args is not given, then it will return the + value(s) for the cell(s) specified. + + If kwargs is given, assumes that each key in kwargs is a index in this + table and sets the specified index to the associated value. Table + validation will not be triggered via this method. + + Note that the table must have an associated array (defined through the + variable option) in order to this work.""" + if not args and index is not None: + if rc: + args = (rc, index) + else: + args = (index, ) + return self.tk.call(self._w, 'set', *args) + + if rc is None: + args = Tkinter._flatten(kwargs.items()) + self.tk.call(self._w, 'set', *args) + else: + self.tk.call(self._w, 'set', rc, index, args) + + + def spans(self, index=None, **kwargs): + """Manipulate row/col spans. + + When called with no arguments, all known spans are returned as a dict. + When called with only the index, the span for that index only is + returned, if any. Otherwise kwargs is assumed to contain keys/values + pairs used to set spans. A span starts at the row,col defined by a key + and continues for the specified number of rows,cols specified by + its value. A span of 0,0 unsets any span on that cell.""" + if kwargs: + args = Tkinter._flatten(kwargs.items()) + self.tk.call(self._w, 'spans', *args) + else: + return self.tk.call(self._w, 'spans', index) + + + def tag_cell(self, tagname, *args): + return self.tk.call(self._w, 'tag', 'cell', tagname, *args) + + + def tag_cget(self, tagname, option): + return self.tk.call(self._w, 'tag', 'cget', tagname, '-%s' % option) + + + def tag_col(self, tagname, *args): + return self.tk.call(self._w, 'tag', 'col', tagname, *args) + + + def tag_configure(self, tagname, option=None, **kwargs): + """Query or modify options associated with the tag given by tagname. + + If no option is specified, a dict describing all of the available + options for tagname is returned. If option is specified, then the + command returns a list describing the one named option. Lastly, if + kwargs is given then it corresponds to option-value pairs that should + be modified.""" + if option is None and not kwargs: + split1 = self.tk.splitlist( + self.tk.call(self._w, 'tag', 'configure', tagname)) + + result = {} + for item in split1: + res = self.tk.splitlist(item) + result[res[0]] = res[1:] + + return result + + elif option: + return self.tk.call(self._w, 'tag', 'configure', tagname, + '-%s' % option) + + else: + args = () + for key, val in kwargs.iteritems(): + args += ('-%s' % key, val) + + self.tk.call(self._w, 'tag', 'configure', tagname, *args) + + + def tag_delete(self, tagname): + self.tk.call(self._w, 'tag', 'delete', tagname) + + + def tag_exists(self, tagname): + return self.getboolean(self.tk.call(self._w, 'tag', 'exists', tagname)) + + + def tag_includes(self, tagname, index): + return self.getboolean(self.tk.call(self._w, 'tag', 'includes', + tagname, index)) + + + def tag_lower(self, tagname, belowthis=None): + self.tk.call(self._w, 'tag', 'lower', belowthis) + + + def tag_names(self, pattern=None): + return self.tk.call(self._w, 'tag', 'names', pattern) + + + def tag_raise(self, tagname, abovethis=None): + self.tk.call(self._w, 'tag', 'raise', tagname, abovethis) + + + def tag_row(self, tagname, *args): + return self.tk.call(self._w, 'tag', 'row', tagname, *args) + + + def validate(self, index): + """Explicitly validates the specified index based on the current + callback set for the validatecommand option. Return 0 or 1 based on + whether the cell was validated.""" + return self.tk.call(self._w, 'validate', index) + + + @property + def version(self): + """Return tktable's package version.""" + return self.tk.call(self._w, 'version') + + + def width(self, column=None, **kwargs): + """If column and kwargs are not given, a dict describing all columns + for which a width has been set is returned. + If column is given, the width of that column is returnd. + If kwargs is given, then it sets the key/value pairs, where key is a + column and value represents the width for the column.""" + if column is None and not kwargs: + pairs = self.tk.splitlist(self.tk.call(self._w, 'width')) + return dict(pair.split() for pair in pairs) + elif column: + return int(self.tk.call(self._w, 'width', str(column))) + + args = Tkinter._flatten(kwargs.items()) + self.tk.call(self._w, 'width', *args) + + + def window_cget(self, index, option): + return self.tk.call(self._w, 'window', 'cget', index, option) + + + def window_configure(self, index, option=None, **kwargs): + """Query or modify options associated with the embedded window given + by index. This should also be used to add a new embedded window into + the table. + + If no option is specified, a dict describing all of the available + options for index is returned. If option is specified, then the + command returns a list describing the one named option. Lastly, if + kwargs is given then it corresponds to option-value pairs that should + be modified.""" + if option is None and not kwargs: + return self.tk.call(self._w, 'window', 'configure', index) + elif option: + return self.tk.call(self._w, 'window', 'configure', index, + '-%s' % option) + else: + args = () + for key, val in kwargs.iteritems(): + args += ('-%s' % key, val) + + self.tk.call(self._w, 'window', 'configure', index, *args) + + + def window_delete(self, *indexes): + self.tk.call(self._w, 'window', 'delete', *indexes) + + + def window_move(self, index_from, index_to): + self.tk.call(self._w, 'window', 'move', index_from, index_to) + + + def window_names(self, pattern=None): + return self.tk.call(self._w, 'window', 'names', pattern) + + + def xview(self, index=None): + """If index is not given a tuple containing two fractions is returned, + each fraction is between 0 and 1. Together they describe the + horizontal span that is visible in the window. + + If index is given the view in the window is adjusted so that the + column given by index is displayed at the left edge of the window.""" + res = self.tk.call(self._w, 'xview', index) + if index is None: + return self._getdoubles(res) + + + def xview_moveto(self, fraction): + """Adjusts the view in the window so that fraction of the total width + of the table text is off-screen to the left. The fraction parameter + must be a fraction between 0 and 1.""" + self.tk.call(self._w, 'xview', 'moveto', fraction) + + + def xview_scroll(self, number, what): + """Shift the view in the window left or right according to number and + what. The 'number' parameter must be an integer. The 'what' parameter + must be either units or pages or an abbreviation of one of these. + + If 'what' is units, the view adjusts left or right by number cells on + the display; if it is pages then the view adjusts by number screenfuls. + If 'number' is negative then cells farther to the left become visible; + if it is positive then cells farther to the right become visible. """ + self.tk.call(self._w, 'xview', 'scroll', number, what) + + + def yview(self, index=None): + """If index is not given a tuple containing two fractions is returned, + each fraction is 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. 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. + + If index is given the view in the window is adjusted so that the + row given by index is displayed at the top of the window.""" + res = self.tk.call(self._w, 'yview', index) + if index is None: + return self._getdoubles(res) + + + def yview_moveto(self, fraction): + """Adjusts the view in the window so that the element given by + fraction appears at the top of the window. The fraction parameter + must be a fraction between 0 and 1.""" + self.tk.call(self._w, 'yview', 'moveto', fraction) + + + def yview_scroll(self, number, what): + """Adjust the view in the window up or down according to number and + what. The 'number' parameter must be an integer. The 'what' parameter + must be either units or pages or an abbreviation of one of these. + + If 'what' is units, the view adjusts up or down by number cells; if it + is pages then the view adjusts by number screenfuls. + If 'number' is negative then earlier elements become visible; if it + is positive then later elements become visible. """ + self.tk.call(self._w, 'yview', 'scroll', number, what) + + +# Sample test taken from tktable cvs, original tktable python wrapper +def sample_test(): + from Tkinter import Tk, Label, Button + + def test_cmd(event): + if event.i == 0: + return '%i, %i' % (event.r, event.c) + else: + return 'set' + + def browsecmd(event): + print "event:", event.__dict__ + print "curselection:", test.curselection() + print "active cell index:", test.index('active') + print "active:", test.index('active', 'row') + print "anchor:", test.index('anchor', 'row') + + root = Tk() + + var = ArrayVar(root) + for y in range(-1, 4): + for x in range(-1, 5): + index = "%i,%i" % (y, x) + var.set(index, index) + + label = Label(root, text="Proof-of-existence test for Tktable") + label.pack(side = 'top', fill = 'x') + + quit = Button(root, text="QUIT", command=root.destroy) + quit.pack(side = 'bottom', fill = 'x') + + test = Table(root, + rows=10, + cols=5, + state='disabled', + width=6, + height=6, + titlerows=1, + titlecols=1, + roworigin=-1, + colorigin=-1, + selectmode='browse', + selecttype='row', + rowstretch='unset', + colstretch='last', + browsecmd=browsecmd, + flashmode='on', + variable=var, + usecommand=0, + command=test_cmd) + test.pack(expand=1, fill='both') + test.tag_configure('sel', background = 'yellow') + test.tag_configure('active', background = 'blue') + test.tag_configure('title', anchor='w', bg='red', relief='sunken') + root.mainloop() + +if __name__ == '__main__': + sample_test() diff --git a/tktable/license.txt b/tktable/license.txt new file mode 100644 index 0000000..fb155d2 --- /dev/null +++ b/tktable/license.txt @@ -0,0 +1,41 @@ + * COPYRIGHT AND LICENSE TERMS * + +(This file blatantly stolen from Tcl/Tk license and adapted - thus assume +it falls under similar license terms). + +This software is copyrighted by Jeffrey Hobbs <jeff at hobbs org>. The +following terms apply to all files associated with the software unless +explicitly disclaimed in individual files. + +The authors hereby grant permission to use, copy, modify, distribute, and +license this software and its documentation for any purpose, provided that +existing copyright notices are retained in all copies and that this notice +is included verbatim in any distributions. No written agreement, license, +or royalty fee is required for any of the authorized uses. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT +OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, +EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS +PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO +OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. + +RESTRICTED RIGHTS: Use, duplication or disclosure by the U.S. government +is subject to the restrictions as set forth in subparagraph (c) (1) (ii) +of the Rights in Technical Data and Computer Software Clause as DFARS +252.227-7013 and FAR 52.227-19. + +SPECIAL NOTES: + +This software is also falls under the bourbon_ware clause v2: + + This software is free, but should you find this software useful in your + daily work and would like to compensate the author, donations in the form + of aged bourbon and scotch are welcome by the author. The user may feel + exempt from this clause if they are below drinking age or think the author + has already partaken of too many drinks. diff --git a/tktable/pkgIndex.tcl.in b/tktable/pkgIndex.tcl.in new file mode 100644 index 0000000..d7566b4 --- /dev/null +++ b/tktable/pkgIndex.tcl.in @@ -0,0 +1,5 @@ +# +# Tcl package index file +# +package ifneeded @PACKAGE_NAME@ @PACKAGE_VERSION@ \ + [list load [file join $dir @PKG_LIB_FILE@] @PACKAGE_NAME@] diff --git a/tktable/release.txt b/tktable/release.txt new file mode 100755 index 0000000..91aa7be --- /dev/null +++ b/tktable/release.txt @@ -0,0 +1,38 @@ +WHAT: Tktable v2.10, 2D editable table/matrix widget
+
+WHERE: http://tktable.sourceforge.net/
+ Tktable binaries are part of ActiveTcl:
+ http://www.ActiveState.com/Tcl
+
+REQUIREMENTS: Tcl/Tk8.0+, compiling is required
+ Compiles everywhere Tk does!
+
+UPDATES TO 2.10:
+ * Code cleanup
+ * Work around Xft font clipping issues
+ * Updated build system
+
+ See ChangeLog and updated man page for full details
+
+BASIC FEATURES:
+ * multi-line cells
+ * support for embedded windows (one per cell)
+ * variable width columns / height rows (interactively resizable)
+ * row and column titles
+ * multiple data sources ((Tcl array || Tcl command) &| internal caching)
+ * supports standard Tk reliefs, fonts, etc.
+ * x/y scrollbar support
+ * 'tag' styles per row, column or cell to change
+ colors, font, relief, image, etc...
+ * in-cell editing - returns value back to data source
+ * support for disabled (read-only) tables or cells (via tags)
+ * multiple selection modes, with "active" cell
+ * optional 'flashes' when things update
+ * cell validation support
+ * Builds on Windows, Mac and Unix
+ * Unicode support (8.1+)
+
+Mailing list for Tktable users:
+ http://lists.sourceforge.net/lists/listinfo/tktable-users
+
+CONTACT: jeff at hobbs.org, Jeff Hobbs
diff --git a/tktable/tclconfig/ChangeLog b/tktable/tclconfig/ChangeLog new file mode 100644 index 0000000..9504def --- /dev/null +++ b/tktable/tclconfig/ChangeLog @@ -0,0 +1,1003 @@ +2016-03-11 Sean Woods <yoda@etoyoc.com> + *tcl.m4 Fixed the search for Tcl and Wish shells under MinGW. Static builds and threaded builds + get an "s" or "t" added to the name. + +2015-08-28 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: Rfe [00189c4afc]: Allow semi-static UCRT build on + Windows with VC 14.0 + +2013-10-08 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: Bug [172223e008]: Wrong filename in + --disable-shared compile on MinGW + +2013-10-04 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: stub library is no longer linked with msvcrt??.dll. + +2013-10-01 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: Workaround for MinGW bug #2065: "gcc --shared" links + with libgcc_s_dw2-1.dll when using 64-bit division in C + +2013-07-04 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: Bug [3324676]: AC_PROG_INSTALL incompat, + Bug [3606445]: Unneeded -DHAVE_NO_SEH=1 when not building on Windows + +2013-07-02 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: Bug [32afa6e256]: dirent64 check is incorrect in tcl.m4 + (thanks to Brian Griffin) + +2013-06-20 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: Use X11/Xlib.h for checking where X11 can be found + in stead of X11/XIntrinsic.h. Suggested by Pietro Cerutti. + +2013-06-04 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: Eliminate NO_VIZ macro as current + zlib uses HAVE_HIDDEN in stead. One more last-moment + fix for FreeBSD by Pietro Cerutti + +2013-05-19 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: Fix for FreeBSD, and remove support for old + FreeBSD versions. Patch by Pietro Cerutti + +2013-03-12 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: Patch by Andrew Shadura, providing better support for + * three architectures they have in Debian. + +2012-08-07 Stuart Cassoff <stwo@users.sourceforge.net> + + * tcl.m4: Added "-DNDEBUG" to CFLAGS_DEFAULT + when building with --disable-symbols. + +2012-08-07 Stuart Cassoff <stwo@users.sourceforge.net> + + * tcl.m4: [Bug 3555058]: Checkin [30736d63f0] broke + CFLAGS_DEFAULT, LDFLAGS_DEFAULT + +2012-08-07 Stuart Cassoff <stwo@users.sourceforge.net> + + * tcl.m4: [Bug 3511806]: Checkin [30736d63f0] broke CFLAGS + +2012-08-07 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: [Bug 3511806]: Checkin [30736d63f0] broke CFLAGS + +2012-07-25 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: My previous commit (2012-04-03) broke the ActiveTcl + build for AMD64, because of the quotes in "C:/<path>/AMD64/cl.exe". + It turns out that the AC_TRY_COMPILE macro cannot handle that. + +2012-07-22 Stuart Cassoff <stwo@users.sourceforge.net> + + * tcl.m4: Tidy: consistency, spelling, phrasing, whitespace. + No functional change. + +2012-04-03 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: [Bug 3511806] Compiler checks too early + This change allows to build the cygwin and mingw32 ports of + Tcl/Tk extensions to build out-of-the-box using a native or + cross-compiler, e.g. on Cygwin, Linux or Darwin. + +2011-04-02 Jan Nijtmans <nijtmans@users.sf.net> + + * install-sh: Fix issue with library stripping in install-sh + (backported from kevin_walzer's patch from Tcl 8.6 trunk) + +2011-04-05 Andreas Kupries <andreask@activestate.com> + + * tcl.m4: Applied patch by Jeff Lawson. Nicer error message when + tclConfig.sh was not found. + +2010-12-15 Stuart Cassoff <stwo@users.sourceforge.net> + + * install-sh: Upgrade to newer install-sh and use it. + * tcl.m4: + +2010-12-14 Stuart Cassoff <stwo@users.sourceforge.net> + + * tcl.m4: Better building on OpenBSD. + +2010-12-14 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: when using gcc, don't try to determine Win64 SDK + +2010-12-12 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: Determine correctly a cross-compiler-windres + +2010-11-23 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: add some cross-compile support, borrowed from Tcl 8.6 + +2010-09-16 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: correct HP-UX LDFLAGS (only used when building big shell) + +2010-09-14 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: add extra if check for .manifest file generation + Add notice about package name and version being built. + +2010-09-09 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: [FREQ #3058486] TEA_LOAD_CONFIG doesn't set all BUILD_ vars + Slightly related: defining BUILD_$1 on all platforms - not only win - + allows the -fvisibility feature to be used in extensions as well, at + least if you compile against tcl >= 8.5. + +2010-08-26 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: ensure safe quoting for autoheader usage + +2010-08-19 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: add TEA_ADD_CLEANFILES macro to make adding cleanfiles + easier, and add *.exp to CLEANFILES Windows default. + (TEA_MAKE_LIB): Enhanced to check for MSVC that requires manifests + and auto-embed it into proj DLL via MAKE_SHARED_LIB. Also define + VC_MANIFEST_EMBED_DLL and VC_MANIFEST_EMBED_EXE that do the same + magic in case it is needed for extended TEA projects. + +2010-08-16 Jeff Hobbs <jeffh@ActiveState.com> + + *** Bump to TEA_VERSION 3.9 *** + If upgrading from TEA_VERSION 3.8, copy over tcl.m4, change + TEA_INIT to use 3.9 and reconfigure (ac-2.59+). + BUILD_${PACKAGE_NAME} will be auto-defined on Windows for + correct setting of TCL_STORAGE_CLASS. + TEA_LOAD_CONFIG users should remove the SHLIB_LD_LIBS setting done + in configure.in (LIBS will be automagically populated by + TEA_LOAD_CONFIG). + TEA_EXPORT_CONFIG has been added for ${pkg}Config.sh creators + SHLIB_LD_FLAGS was deprecated a while ago, remove it if it is + still in your Makefile.in. + + * tcl.m4: add /usr/lib64 to set of auto-search dirs. [Bug 1230554] + Auto-define BUILD_$PACKAGE_NAME so users don't need to. This + needs to correspond with $pkg.h define magic for TCL_STORAGE_CLASS. + Auto-define CLEANFILES. Users can expand it. + (SHLIB_LD_LIBS): define to '${LIBS}' default and change it only if + necessary. Platforms not using this may simply not work or have + very funky linkers. + (TEA_LOAD_CONFIG): When loading config for another extension, + auto-add stub libraries found with TEA_ADD_LIBS. Eases + configure.in for modules like itk and img::*. + (TEA_EXPORT_CONFIG): Add standardized function for exporting a + ${pkg}Config.sh. See use by img::* and itcl. + +2010-08-12 Jeff Hobbs <jeffh@ActiveState.com> + + *** Bump to TEA_VERSION 3.8 *** + If upgrading from TEA_VERSION 3.7, copy over tcl.m4, change + TEA_INIT to use 3.8 and reconfigure (ac-2.59+). + No other changes should be necessary. + + * tcl.m4: remove more vestigial bits from removed platforms. + Add back SCO_SV-3.2*. + Remove use of DL_LIBS and DL_OBJS and related baggage - these are + only needed by the core to support 'load'. + Allow for macosx in TEA_ADD_SOURCES. + Correct check for found_xincludes=no in TEA_PATH_UNIX_X. + +2010-08-11 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: remove the following old platform configurations: + UNIX_SV*|UnixWare-5*, SunOS-4.*, SINIX*5.4*, SCO_SV-3.2*<readded>, + OSF1-1.*, NEXTSTEP-*, NetBSD-1.*|FreeBSD-[[1-2]].*, MP-RAS-*, + IRIX-5.*, HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*, dgux*, + BSD/OS-2.1*|BSD/OS-3* + (AIX): drop AIX-pre4 support and use of ldAix, use -bexpall/-brtl + +2010-07-05 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: [Patch #1055668] removal of exported internals from + tclInt.h (EXTERN macro) + +2010-04-14 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4 - Backport a lot of quoting fixes from tcl8.6/unix/tcl.m4 + - Fix determination of CYGPATH for CYGWIN + With those fixes, itcl and tdbc compile fine with CYGWIN + +2010-04-06 Jan Nijtmans <nijtmans@users.sf.net> + + * install-sh [Bug 2982540] configure and install* script files + should always have LF + +2010-02-19 Stuart Cassoff <stwo@users.sourceforge.net> + + * tcl.m4: Correct compiler/linker flags for threaded builds on + OpenBSD. + +2010-01-19 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: Detect CYGWIN variant: win32 or unix + +2010-01-03 Donal K. Fellows <dkf@users.sf.net> + + * unix/tcl.m4 (TEA_CONFIG_CFLAGS): [Tcl Bug 1636685]: Use the + configuration for modern FreeBSD suggested by the FreeBSD porter. + +2009-10-22 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: [Tcl Patch #2883533] tcl.m4 support for Haiku OS + +2009-04-27 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_CONFIG_CFLAGS): harden the check to add _r to CC on + AIX with threads. + +2009-04-10 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): check for 64-bit TkAqua. + +2009-03-26 Jan Nijtmans <nijtmans@users.sf.net> + + * tclconfig/tcl.m4: Adapt LDFLAGS and LD_SEARCH_FLAGS + together with SHLIB_LD definition to unbreak building on HPUX. + +2009-03-20 Andreas Kupries <andreask@activestate.com> + + * tclconfig/tcl.m4: Changed SHLIB_LD definition to unbreak + building on HPUX. + +2009-03-16 Joe English <jenglish@users.sourceforge.net> + + * tcl.m4(TEA_PUBLIC_TK_HEADERS): Look at ${TK_INCLUDE_SPEC} + (found in tkConfig.sh) when trying to guess where tk.h might be + [Patch 1960628]. + +2009-03-11 Joe English <jenglish@users.sourceforge.net> + + * tcl.m4: Allow ${SHLIB_SUFFIX} to be overridden at + configure-time [Patch 1960628]. Also fix some comment typos, + and an uninitialized variable bug-waiting-to-happen. + +2008-12-21 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: [Bug 2073255] Tcl_GetString(NULL) doesn't crash on HP-UX + (this bug report was for Tcl, but holds for TEA as well.) + +2008-12-20 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: sync with tdbc tcl.m4 changes + (SunOS-5.11): Sun cc SHLIB_LD: use LDFLAGS_DEFAULT instead of LDFLAGS + +2008-12-02 Jeff Hobbs <jeffh@ActiveState.com> + + *** Bump to TEA_VERSION 3.7 *** + + * tcl.m4: in private header check, check for <plat>Port.h instead + of Int.h to ensure all private headers are available. + +2008-11-04 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): sync TEA_PRIVATE_TK_HEADERS handling of + Tk.framework PrivateHeaders with TEA_PRIVATE_TCL_HEADERS. + +2008-11-04 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_PATH_TCLCONFIG, TEA_PATH_TKCONFIG): exit with error + when tclConfig.sh cannot be found. [Bug #1997760] + (TEA_PRIVATE_TCL_HEADERS, TEA_PRIVATE_TK_HEADERS): allow for + finding the headers installed in the public areas, e.g. a result of + make install-private-headers. [Bug #1631922] + +2008-08-12 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): link shlib with current and compatiblity version + flags; look for libX11.dylib when searching for X11 libraries. + +2008-06-12 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (SunOS-5.11): fix 64bit amd64 support with gcc & Sun cc. + +2008-03-27 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (SunOS-5.1x): fix 64bit support for Sun cc. [Bug 1921166] + +2008-02-01 Donal K. Fellows <donal.k.fellows@man.ac.uk> + + * tcl.m4 (TEA_CONFIG_CFLAGS): Updated to work at least in part with + more modern VC versions. Currently just made the linker flags more + flexible; more work may be needed. + +2007-10-26 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): add support for 64-bit X11. + +2007-10-23 Jeff Hobbs <jeffh@ActiveState.com> + + *** Tagged tea-3-branch to start TEA 4 development on HEAD *** + +2007-09-17 Joe English <jenglish@users.sourceforge.net> + + * tcl.m4: use '${CC} -shared' instead of 'ld -Bshareable' + to build shared libraries on current NetBSDs [Bug 1749251]. + +2007-09-15 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: replace all direct references to compiler by ${CC} to + enable CC overriding at configure & make time. + (SunOS-5.1x): replace direct use of '/usr/ccs/bin/ld' in SHLIB_LD by + 'cc' compiler driver. + +2007-08-08 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: check Ttk dir for Tk private headers (8.5). + Add some comments to other bits. + +2007-06-25 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_PROG_TCLSH, TEA_PROG_WISH): move where / is added. + +2007-06-13 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: fix --with-tkinclude alignment. [Bug 1506111] + +2007-06-06 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): fix 64bit arch removal in fat 32&64bit builds. + +2007-05-18 Donal K. Fellows <donal.k.fellows@man.ac.uk> + + * tcl.m4: Added quoting so that paths with spaces cause fewer + problems. + +2007-03-07 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): s/CFLAGS/CPPFLAGS/ in -mmacosx-version-min check. + +2007-02-15 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: correct private header check to search in generic subdir + +2007-02-09 Jeff Hobbs <jeffh@ActiveState.com> + + *** Bump to TEA_VERSION 3.6 *** + + * tcl.m4: correct -d to -f + (TEA_CONFIG_CFLAGS): SHLIB_SUFFIX is .so on HP ia64 [Bug 1615058] + +2007-02-08 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_PRIVATE_TCL_HEADERS, TEA_PRIVATE_TK_HEADERS): check + that the dirs actually have private headers. [Bug 1631922] + +2007-02-04 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: add caching to -pipe check. + +2007-01-25 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: integrate CPPFLAGS into CFLAGS as late as possible and + move (rather than duplicate) -isysroot flags from CFLAGS to CPPFLAGS to + avoid errors about multiple -isysroot flags from some older gcc builds. + +2006-01-19 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: ensure CPPFLAGS env var is used when set. [Bug 1586861] + (Darwin): add -isysroot and -mmacosx-version-min flags to CPPFLAGS when + present in CFLAGS to avoid discrepancies between what headers configure + sees during preprocessing tests and compiling tests. + +2006-12-19 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): --enable-64bit: verify linking with 64bit -arch flag + succeeds before enabling 64bit build. + +2006-12-16 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Linux): fix previous change to use makefile variable + LDFLAGS_DEFAULT instead of LDFLAGS in SHLIB_LD, to ensure linker + flags in sampleextension Makefile are picked up. + +2006-11-26 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Linux): --enable-64bit support. [Patch 1597389], [Bug 1230558] + +2006-08-18 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): add support for --enable-64bit on x86_64, for + universal builds including x86_64 and for use of -mmacosx-version-min + instead of MACOSX_DEPLOYMENT_TARGET. For Tk extensions, remove 64-bit + arch flags from CFLAGS like in the Tk configure, as neither TkAqua nor + TkX11 can be built for 64-bit at present. + +2006-03-28 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: []-quote AC_DEFUN functions. + (TEA_PATH_TKCONFIG): Fixed Windows-specific check for tkConfig.sh. + (TEA_MAKE_LIB): Prepend 'lib' for Windows-gcc configs. + +2006-03-07 Joe English <jenglish@users.sourceforge.net> + + * tcl.m4: Set SHLIB_LD_FLAGS='${LIBS}' on NetBSD, + as per the other *BSD variants [Bug 1334613]. + +2006-01-25 Jeff Hobbs <jeffh@ActiveState.com> + + *** Bump to TEA version 3.5 *** + + * tcl.m4: keep LD_SEARCH_FLAGS and CC_SEARCH_FLAGS synchronous + with core tcl.m4 meaning. + +2006-01-24 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): use makefile variable LDFLAGS_DEFAULT instead of + LDFLAGS in SHLIB_LD, to ensure linker flags in sampleextension Makefile + are picked up. [Bug 1403343] + +2006-01-23 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: add C:/Tcl/lib and C:/Progra~1/Tcl/lib dirs to check for + *Config.sh on Windows. [Bug 1407544] + +2006-01-23 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): for Tk extensions, remove -arch ppc64 from CFLAGS + like in the Tk configure, as neither TkAqua nor TkX11 can be built for + 64bit at present (no 64bit GUI libraries). + +2006-01-22 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: restore system=windows on Windows. + Remove error if 'ar' isn't found (it may not be on Windows). + Do not add -lxnet or define _XOPEN_SOURCE on HP-UX by default. + Ensure the C|LDFLAGS_DEFAULT gets the fully sub'd value at + configure time. + +2006-01-10 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: add caching, use AC_CACHE_CHECK instead of AC_CACHE_VAL + where possible, consistent message quoting, sync relevant + tcl/unix/tcl.m4 HEAD changes and gratuitous formatting differences + (notably sunc removal of support for for ancient BSD's, IRIX 4, + RISCos and Ultrix by kennykb), Darwin improvements to + TEA_LOAD_*CONFIG to make linking work against Tcl/Tk frameworks + installed in arbitrary location, change TEA_PROG_* search order + (look in *_BIN_DIR parents before *_PREFIX). + +2006-01-05 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: add dkf's system config refactor + +2006-01-04 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: remove extraneous ' that causes bash 3.1 to choke + +2005-12-19 Joe English <jenglish@users.sourceforge.net> + + * tcl.m4 (TEA_PATH_TCLCONFIG &c): Look for tclConfig.sh &c + in ${libdir}, where they are installed by default [Patch #1377407]. + +2005-12-05 Don Porter <dgp@users.sf.net> + + * tcl.m4 (TEA_PUBLIC_*_HEADERS): Better support for finding + header files for uninstalled Tcl and Tk. + +2005-12-02 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: correctly bump TEA_VERSION var to 3.4 + +2005-12-01 Daniel Steffen <das@users.sourceforge.net> + + * unix/tcl.m4 (Darwin): fixed error when MACOSX_DEPLOYMENT_TARGET unset + +2005-11-29 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: *** Bump to TEA version 3.4 *** + Add Windows x64 build support. + Remove TEA_PATH_NOSPACE and handle the problem with ""s where + necessary - the macro relied on TCLSH_PROG which didn't work for + cross-compiles. + +2005-11-27 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): add 64bit support, add CFLAGS to SHLIB_LD to + support passing -isysroot in env(CFLAGS) to configure (flag can't + be present twice, so can't be in both CFLAGS and LDFLAGS during + configure), don't use -prebind when deploying on 10.4. + (TEA_ENABLE_LANGINFO, TEA_TIME_HANDLER): add/fix caching. + +2005-10-30 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: fixed two tests for TEA_WINDOWINGSYSTEM = "aqua" that + should have been for `uname -s` = "Darwin" instead; added some + missing quoting. + (TEA_PROG_TCLSH, TEA_PROG_WISH): fix incorrect assumption that + install location of tclConfig.sh/tkConfig.sh allows to determine + the tclsh/wish install dir via ../bin. Indeed tcl/tk can be + configured with arbitrary --libdir and --bindir (independent of + prefix) and such a configuration is in fact standard with Darwin + framework builds. At least now also check ${TCL_PREFIX}/bin + resp. ${TK_PREFIX}/bin for presence of tclsh resp. wish (if tcl/tk + have been configured with arbitrary --bindir, this will still not + find them, for a general solution *Config.sh would need to contain + the values of bindir/libdir/includedir passed to configure). + +2005-10-07 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: Fix Solaris 5.10 check and Solaris AMD64 64-bit builds. + +2005-10-04 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_PRIVATE_TCL_HEADERS): add / to finish sed macro + (TEA_ENABLE_THREADS): don't check for pthread_attr_setstacksize func + +2005-09-13 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: *** Update to TEA version 3.3 *** + define TEA_WINDOWINGSYSTEM in TEA_LOAD_TKCONFIG. + Make --enable-threads the default (users can --disable-threads). + Improve AIX ${CC}_r fix to better check existing ${CC} value. + Do the appropriate evals to not require the *TOP_DIR_NATIVE vars + be set for extensions that use private headers. + Make aqua check for Xlib compat headers the same as win32. + +2005-07-26 Mo DeJong <mdejong@users.sourceforge.net> + + * tcl.m4 (TEA_PROG_TCLSH, TEA_BUILD_TCLSH, + TEA_PROG_WISH, TEA_BUILD_WISH): Remove + TEA_BUILD_TCLSH and TEA_BUILD_WISH because + of complaints that it broke the build when + only an installed version of Tcl was available + at extension build time. The TEA_PROG_TCLSH and + TEA_PROG_WISH macros will no longer search the + path at all. The build tclsh or installed + tclsh shell will now be found by TEA_PROG_TCLSH. + +2005-07-24 Mo DeJong <mdejong@users.sourceforge.net> + + * tcl.m4 (TEA_PROG_TCLSH, TEA_BUILD_TCLSH, + TEA_PROG_WISH, TEA_BUILD_WISH): + Split confused search for tclsh on PATH and + build and install locations into two macros. + TEA_PROG_TCLSH and TEA_PROG_WISH search the + system PATH for an installed tclsh or wish. + The TEA_BUILD_TCLSH and TEA_BUILD_WISH + macros determine the name of tclsh or + wish in the Tcl or Tk build directory even + if tclsh or wish has not yet been built. + [Tcl bug 1160114] + [Tcl patch 1244153] + +2005-06-23 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (TEA_PRIVATE_TK_HEADERS): add ${TK_SRC_DIR}/macosx to + TK_INCLUDES when building against TkAqua. + + * tcl.m4 (TEA_PATH_X): fixed missing comma in AC_DEFINE + + * tcl.m4: changes to better support framework builds of Tcl and Tk out + of the box: search framework install locations for *Config.sh, and if in + presence of a framework build, use the framework's Headers and + PrivateHeaders directories for public and private includes. [FR 947735] + +2005-06-18 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): add -headerpad_max_install_names to LDFLAGS to + ensure we can always relocate binaries with install_name_tool. + +2005-06-04 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (TEA_PATH_X): for TEA_WINDOWINGSYSTEM == aqua, check if xlib + compat headers are available in tkheaders location, otherwise add xlib + sourcedir to TK_XINCLUDES. + +2005-04-25 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: added AC_DEFINE* descriptions (from core tcl.m4) to allow + use with autoheader. + (Darwin): added configure checks for recently added linker flags + -single_module and -search_paths_first to allow building with older + tools (and on Mac OS X 10.1), use -single_module in SHLIB_LD. + (TEA_MISSING_POSIX_HEADERS): added caching of dirent.h check. + (TEA_BUGGY_STRTOD): added caching (sync with core tcl.m4). + +2005-03-24 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_TCL_64BIT_FLAGS): use Tcl header defaults for wide + int type only on Windows when __int64 is detected as valid. + +2005-03-24 Don Porter <dgp@users.sf.net> + + * README.txt: Update reference to "SC_* macros" to "TEA_* macros". + * tcl.m4: Incorporated recent improvements in SC_PATH_TCLCONFIG + and SC_PATH_TKCONFIG into TEA_PATH_TCLCONFIG and TEA_PATH_TKCONFIG. + Corrected search path in TEA_PATH_CONFIG and added + AC_SUBST($1_BIN_DIR) to TEA_LOAD_CONFIG so that packages that load + the configuration of another package can know where they loaded + it from. + +2005-03-18 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_CONFIG_CFLAGS): correct 2005-03-17 change to have + variant LD_SEARCH_FLAGS for gcc and cc builds. + + * tcl.m4 (TEA_PROG_TCLSH, TEA_PROG_WISH): correct x-compile check. + +2005-03-17 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: Correct gcc build and HP-UX-11. + +2005-02-08 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_ADD_LIBS): don't touch lib args starting with -. + (TEA_CONFIG_CFLAGS): only define _DLL for CE in shared build. + (TEA_MAKE_LIB): set RANLIB* to : on Windows (it's not needed). + +2005-02-01 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: redo of 2005-01-27 changes to correctly handle paths + with spaces. Win/CE and Win/64 builds now require a prebuilt + tclsh to handle conversion to short pathnames. This is done in + the new TEA_PATH_NOSPACE macro. For Win/CE|64, make CC just the + compiler and move the necessary includes to CFLAGS. + (TEA_CONFIG_CFLAGS): Add Solaris 64-bit gcc build support. + (TEA_PROG_TCLSH, TEA_PROG_WISH): Allow TCLSH_PROG and WISH_PROG to + be set in the env and prevent resetting. + (TEA_ADD_LIBS): On Windows using GCC (mingw), convert foo.lib + args to -lfoo, for use with mingw. + *** POTENTIAL INCOMPATABILITY *** + (TEA_CONFIG_CFLAGS): Fix AIX gcc builds to work out-of-box. + Bumped TEA to 3.2. + +2005-01-27 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: remove cygpath calls to support msys. + Update base CE build assumption to "420,ARMV4,ARM,Pocket PC 2003". + Make STLIB_LD use $LINKBIN -lib. + +2005-01-25 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): fixed bug with static build linking to dynamic + library in /usr/lib etc instead of linking to static library earlier + in search path. [Tcl Bug 956908] + Removed obsolete references to Rhapsody. + +2004-12-29 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: Updates for VC7 compatibility, fixing CFLAGS and LDFLAGS + options, using better default -O levels. [Bug 1092952, 1091967] + +2004-12-29 Joe English <jenglish@users.sourceforge.net> + + * tcl.m4: Do not use ${DBGX} suffix when building + shared libraries [patch #1081595, TIP #34] + +2004-09-07 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_CONFIG_CFLAGS): support eVC4 Win/CE builds + +2004-08-10 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_INIT, TEA_PREFIX): update handling of exec_prefix to + work around subdir configures since autoconf only propagates the + prefix (not exec_prefix). + +2004-07-23 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (TEA_CONFIG_CFLAGS): Darwin section: brought inline with + Tcl 8.5 HEAD config, removed core specific & obsolete settings. + +2004-07-22 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_PATH_X): check in TK_DEFS for MAC_OSX_TK to see if + we are compiling on Aqua. Add TEA_WINDOWINGSYSTEM var that + reflects 'tk windowingsystem' value. + +2004-07-16 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_ENABLE_THREADS): force a threaded build when + building against a threaded core. + (CFLAGS_WARNING): Remove -Wconversion for gcc builds + (TEA_CONFIG_CFLAGS): Reorder configure.in for better 64-bit build + configuration, replacing EXTRA_CFLAGS with CFLAGS. [Bug #874058] + Update to latest Tcl 8.5 head config settings. + Call this TEA version 3.1. + +2004-04-29 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_TCL_64BIT_FLAGS): replace AC_TRY_RUN test with + AC_TRY_COMPILE for the long vs. long long check. (kenny) + +2004-04-26 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_TCL_64BIT_FLAGS): update against core tcl.m4 to + define TCL_WIDE_INT_IS_LONG if 'using long'. + +2004-03-19 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: correct Windows builds getting LDFLAGS info in MAKE_LIB + +2004-02-11 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: correct TCL_INCLUDES for private headers on Windows - it + doesn't need the eval. + +2004-02-10 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: don't require TK_INCLUDES and TCL_INCLUDES to have the + DIR_NATIVE vars defined when using private headers on unix. + Allow $... to TEA_ADD_SOURCES for constructs like + TEA_ADD_SOURCES([\$(WIN_OBJECTS)]), that allow the developer to + place more in the Makefile.in. + tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and + CHECK on limits.h + +2003-12-10 Jeff Hobbs <jeffh@ActiveState.com> + + * Makefile.in: added TEA_ADD_LIBS, TEA_ADD_INCLUDES and + * configure: TEA_ADD_CFLAGS to configurable parameters with + * configure.in: PKG_* equivs in the Makefile. This allows the + * tclconfig/tcl.m4: user to worry less about actual magic VAR names. + Corrected Makefile.in to note that TEA_ADD_TCL_SOURCES requires + exact file names. + +2003-12-09 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: updated OpenBSD support based on [Patch #775246] (cassoff) + +2003-12-05 Jeff Hobbs <jeffh@ActiveState.com> + + * configure: + * configure.in: + * Makefile.in (VPATH): readd $(srcdir) to front of VPATH as the + first part of VPATH can get chopped off. + Change .c.$(OBJEXT) rule to .c.@OBJEXT@ to support more makes. + * tclconfig/tcl.m4: add TEA_ADD_STUB_SOURCES to support libstub + generation and TEA_ADD_TCL_SOURCES to replace RUNTIME_SOURCES as + the way the user specifies library files. + +2003-12-03 Jeff Hobbs <jeffh@ActiveState.com> + + * configure: Update of TEA spec to (hopefully) simplify + * configure.in: some aspects of TEA by making use of more + * Makefile.in: AC 2.5x features. Use PACKAGE_NAME (instead + * generic/tclsample.c: of PACKAGE) and PACKAGE_VERSION (instead of + * tclconfig/tcl.m4: VERSION) arguments to AC_INIT as the TEA + package name and version. + Provide a version argument to TEA_INIT - starting with 3.0. + Drop all use of interior shell substs that older makefiles didn't + like. Use PKG_* naming convention instead. + Move specification of source files and public headers into + configure.in with TEA_ADD_SOURCES and TEA_ADD_HEADERS. These will + be munged during ./configure into the right obj file names (no + $(SOURCES:.c=.obj) needed). + There is almost nothing that should be touched in Makefile.in now + for the developer. May want to add a TEA_ADD_TCL_SOURCES for the + RUNTIME_SOURCES that remains. + Use SHLID_LD_FLAGS (instead of SHLID_LDFLAGS) as Tcl does. + Only specify the user requested LDFLAGS/CFLAGS in the Makefile, + don't mention the _OPTIMIZE/_DEBUG variants. + +2003-10-15 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: create a TEA_SETUP_COMPILER_CC the precedes the + TEA_SETUP_COMPILER macro. They are split so the check for CC + occurs before any use of CC. Also add AC_PROG_CPP to the compiler + checks. + +2003-10-06 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: Updated for autoconf 2.5x prereq. + Where TCL_WIDE_INT_TYPE would be __int64, defer to the code checks + in tcl.h, which also handles TCL_LL_MODIFIER* properly. + +2003-04-22 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: correct default setting of ARCH for WinCE builds. + Correct \ escaping for CE sed macros. + +2003-04-10 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: replace $(syscal) construct with older `syscall` for + systems where sh != bash. + +2003-04-09 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_WITH_CELIB): add --enable-wince and --with-celib + options for Windows/CE compilation support. Requires the + Microsoft eMbedded SDK and Keuchel's celib emulation layer. + +2003-02-18 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_ENABLE_THREADS): Make sure -lpthread gets passed on + the link line when checking for the pthread_attr_setstacksize + symbol. (dejong) + + * tcl.m4 (TEA_SETUP_COMPILER): added default calls to + TEA_TCL_EARLY_FLAGS, TEA_TCL_64BIT_FLAGS, + TEA_MISSING_POSIX_HEADERS and TEA_BUGGY_STRTOD. + +2003-02-14 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: correct HP-UX ia64 --enable-64bit build flags + +2003-01-29 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: check $prefix/lib as well as $exec_prefix/lib when + looking for tcl|tkConfig.sh, as this check is done before we would + set exec_prefix when the user does not define it. + +2003-01-21 Mo DeJong <mdejong@users.sourceforge.net> + + * tcl.m4 (TEA_CONFIG_CFLAGS): Fix build support + for mingw, the previous implementation would + use VC++ when compiling with mingw gcc. Don't + pass -fPIC since gcc always compiles pic code + under win32. Change some hard coded cases + of gcc to ${CC}. + +2002-10-15 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: move the CFLAGS definition from TEA_ENABLE_SHARED to + TEA_MAKE_LIB because setting too early confuses other AC_* macros. + Correct the HP-11 SHLIB_LD_LIBS setting. + + * tcl.m4: add the CFLAGS definition into TEA_ENABLE_SHARED and + make it pick up the env CFLAGS at configure time. + +2002-10-09 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: add --enable-symbols=mem option to enable TCL_MEM_DEBUG. + Improved AIX 64-bit build support, allow it on AIX-4 as well. + Enable 64-bit HP-11 compilation with gcc. + Enable 64-bit IRIX64-6 cc build support. + Correct FreeBSD thread library linkage. + Add OSF1 static build support. + Improve SunOS-5 shared build SHLIB_LD macro. + +2002-07-20 Zoran Vasiljevic <zoran@archiware.com> + + * tcl.m4: Added MINGW32 to list of systems checked for Windows build. + Also, fixes some indentation issues with "--with-XXX" options. + +2002-04-23 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_ENABLE_THREADS): added USE_THREAD_ALLOC define to + use new threaded allocatory by default on Unix for Tcl 8.4. + (TEA_CONFIG_CFLAGS): corrected LD_SEARCH_FLAGS for FreeBSD-3+. + +2002-04-22 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_SETUP_COMPILER): removed call to AC_CYGWIN so that + we can use autoconf 2.5x as well as 2.13. This prevents us from + being able to warn against the use of cygwin gcc at configure + time, but allows autoconf 2.5x, which is what is shipped with most + newer systems. + +2002-04-11 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: Enabled COFF as well as CV style debug info with + --enable-symbols to allow Dr. Watson users to see function info. + More info on debugging levels can be obtained at: + http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp + +2002-04-03 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: change all SC_* macros to TEA_*. The SC_ was for + Scriptics, which is no more. TEA represents a better, independent + prefix that won't need changing. + Added preliminary mingw gcc support. [Patch #538772] + Added TEA_PREFIX macro that handles defaulting the prefix and + exec_prefix vars to those used by Tcl if none were specified. + Added TEA_SETUP_COMPILER macro that encompasses the AC_PROG_CC + check and several other basic AC_PROG checks needed for making + executables. This greatly simplifies user's configure.in files. + Collapsed AIX-5 defines into AIX-* with extra checks for doing the + ELF stuff on AIX-5-ia64. + Updated TEA_ENABLE_THREADS to take an optional arg to allow + switching it on by default (for Thread) and add sanity checking to + warn the user if configuring threads incompatibly. + +2002-03-29 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: made sure that SHLIB_LDFLAGS was set to LDFLAGS_DEFAULT. + Removed --enable-64bit support for AIX-4 because it wasn't correct. + Added -MT or -MD Windows linker switches to properly support + symbols-enabled builds. + +2002-03-28 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: called AC_MSG_ERROR when SC_TEA_INIT wasn't called first + instead of calling it as that inlines it each time in shell code. + Changed Windows CFLAGS_OPTIMIZE to use -O2 instead of -Oti. + Noted TCL_LIB_VERSIONS_OK=nodots for Windows builds. + A few changes to support itcl (and perhaps others): + Added support for making your own stub libraries to SC_MAKE_LIB. + New SC_PATH_CONFIG and SC_LOAD_CONFIG that take a package name arg + and find that ${pkg}Config.sh file. itk uses this for itcl. + +2002-03-27 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: made SC_LOAD_TKCONFIG recognize when working with a Tk + build dir setup. + Added EXTRA_CFLAGS and SHLIB_LD_LIBS substs to SC_CONFIG_CFLAGS. + Added XLIBSW onto LIBS when it is defined. + Remove TCL_LIBS from MAKE_LIB and correctly use SHLIB_LD_LIBS + instead to not rely as much on tclConfig.sh cached info. + Add TK_BIN_DIR to paths to find wish in SC_PROG_WISH. + These move towards making TEA much more independent of *Config.sh. + +2002-03-19 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: corrected forgotten (UN)SHARED_LIB_SUFFIX and + SHLIB_SUFFIX defines for Win. + (SC_PATH_X): made this only do the check on unix platforms. + +2002-03-12 Jeff Hobbs <jeffh@ActiveState.com> + + * README.txt: updated to reflect fewer files + +2002-03-06 Jeff Hobbs <jeffh@ActiveState.com> + + * config.guess (removed): + * config.sub (removed): removed unnecessary files + + * installFile.tcl (removed): + * mkinstalldirs (removed): these aren't really necessary for + making TEA work + + * tcl.m4 (SC_PUBLIC_TCL_HEADERS, SC_PUBLIC_TK_HEADERS): don't + check /usr(/local)/include for includes on Windows when not using + gcc + +2002-03-05 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: added warnings on Windows, removed RELPATH define and + added TCL_LIBS to MAKE_LIB macro. + + This import represents 2.0.0, or a new start at attempting to + make TEA much easier for C extension developers. + + **** moved from tclpro project to core tcl project, **** + **** renamed to 'tclconfig' **** + +2001-03-15 Karl Lehenbauer <karl@procplace.com> + + * installFile.tcl: Added updating of the modification time of + the target file whether we overwrote it or decided that it + hadn't changed. This was necessary for us to be able to + determine whether or not a module install touched the file. + +2001-03-08 Karl Lehenbauer <karl@procplace.com> + + * installFile.tcl: Added support for converting new-style (1.1+) + Cygnus drive paths to Tcl-style. + +2001-01-15 <brent.welch@interwoven.com> + + * tcl.m4: Added FreeBSD clause. + +2001-01-03 <brent.welch@interwoven.com> + + * tcl.m4: Fixed typo in SC_LIB_SPEC where it is checking + for exec-prefix. + +2000-12-01 <brent.welch@interwoven.com> + + * tcl.m4: Concatenated most of the Ajuba acsite.m4 file + so we don't need to modify the autoconf installation. + * config.guess: + * config.sub: + * installFile.tcl: + Added files from the itcl config subdirectory, + which should go away. + +2000-7-29 <welch@ajubasolutions.com> + + * Fixed the use of TCL_SRC_DIR and TK_SRC_DIR within + TCL_PRIVATE_INCLUDES and TK_PRIVATE_INCLUDES to match their recent + change from $(srcdir) to $(srcdir)/.. diff --git a/tktable/tclconfig/README.txt b/tktable/tclconfig/README.txt new file mode 100644 index 0000000..59b5a3e --- /dev/null +++ b/tktable/tclconfig/README.txt @@ -0,0 +1,26 @@ +These files comprise the basic building blocks for a Tcl Extension +Architecture (TEA) extension. For more information on TEA see: + + http://www.tcl.tk/doc/tea/ + +This package is part of the Tcl project at SourceForge, and latest +sources should be available there: + + http://tcl.sourceforge.net/ + +This package is a freely available open source package. You can do +virtually anything you like with it, such as modifying it, redistributing +it, and selling it either in whole or in part. + +CONTENTS +======== +The following is a short description of the files you will find in +the sample extension. + +README.txt This file + +install-sh Program used for copying binaries and script files + to their install locations. + +tcl.m4 Collection of Tcl autoconf macros. Included by a package's + aclocal.m4 to define TEA_* macros. diff --git a/tktable/tclconfig/install-sh b/tktable/tclconfig/install-sh new file mode 100755 index 0000000..7c34c3f --- /dev/null +++ b/tktable/tclconfig/install-sh @@ -0,0 +1,528 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-04-20.01; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -S $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -S) stripcmd="$stripprog $2" + shift;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/tktable/tclconfig/tcl.m4 b/tktable/tclconfig/tcl.m4 new file mode 100644 index 0000000..655be25 --- /dev/null +++ b/tktable/tclconfig/tcl.m4 @@ -0,0 +1,4176 @@ +# tcl.m4 -- +# +# This file provides a set of autoconf macros to help TEA-enable +# a Tcl extension. +# +# Copyright (c) 1999-2000 Ajuba Solutions. +# Copyright (c) 2002-2005 ActiveState Corporation. +# +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. + +AC_PREREQ(2.57) + +# Possible values for key variables defined: +# +# TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem') +# TEA_PLATFORM - windows unix +# TEA_TK_EXTENSION - True if this is a Tk extension +# + +#------------------------------------------------------------------------ +# TEA_PATH_TCLCONFIG -- +# +# Locate the tclConfig.sh file and perform a sanity check on +# the Tcl compile flags +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-tcl=... +# +# Defines the following vars: +# TCL_BIN_DIR Full path to the directory containing +# the tclConfig.sh file +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PATH_TCLCONFIG], [ + dnl TEA specific: Make sure we are initialized + AC_REQUIRE([TEA_INIT]) + # + # Ok, lets find the tcl configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tcl + # + + if test x"${no_tcl}" = x ; then + # we reset no_tcl in case something fails here + no_tcl=true + AC_ARG_WITH(tcl, + AC_HELP_STRING([--with-tcl], + [directory containing tcl configuration (tclConfig.sh)]), + with_tclconfig="${withval}") + AC_MSG_CHECKING([for Tcl configuration]) + AC_CACHE_VAL(ac_cv_c_tclconfig,[ + + # First check to see if --with-tcl was specified. + if test x"${with_tclconfig}" != x ; then + case "${with_tclconfig}" in + */tclConfig.sh ) + if test -f "${with_tclconfig}"; then + AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself]) + with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tclconfig}/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" + else + AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) + fi + fi + + # then check for a private Tcl installation + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ../tcl \ + `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../tcl \ + `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../../tcl \ + `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks/Tcl.framework 2>/dev/null` \ + `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Network/Library/Frameworks/Tcl.framework 2>/dev/null` \ + `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Tcl.framework 2>/dev/null` \ + ; do + if test -f "$i/Tcl.framework/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" + break + fi + done + fi + + # TEA specific: on Windows, check in common installation locations + if test "${TEA_PLATFORM}" = "windows" \ + -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d C:/Tcl/lib 2>/dev/null` \ + `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/pkg/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + `ls -d /usr/lib/tcl8.6 2>/dev/null` \ + `ls -d /usr/lib/tcl8.5 2>/dev/null` \ + `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ + `ls -d /usr/local/lib/tcl8.5 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ${srcdir}/../tcl \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + ]) + + if test x"${ac_cv_c_tclconfig}" = x ; then + TCL_BIN_DIR="# no Tcl configs found" + AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh]) + else + no_tcl= + TCL_BIN_DIR="${ac_cv_c_tclconfig}" + AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh]) + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_PATH_TKCONFIG -- +# +# Locate the tkConfig.sh file +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-tk=... +# +# Defines the following vars: +# TK_BIN_DIR Full path to the directory containing +# the tkConfig.sh file +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PATH_TKCONFIG], [ + # + # Ok, lets find the tk configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tk + # + + if test x"${no_tk}" = x ; then + # we reset no_tk in case something fails here + no_tk=true + AC_ARG_WITH(tk, + AC_HELP_STRING([--with-tk], + [directory containing tk configuration (tkConfig.sh)]), + with_tkconfig="${withval}") + AC_MSG_CHECKING([for Tk configuration]) + AC_CACHE_VAL(ac_cv_c_tkconfig,[ + + # First check to see if --with-tkconfig was specified. + if test x"${with_tkconfig}" != x ; then + case "${with_tkconfig}" in + */tkConfig.sh ) + if test -f "${with_tkconfig}"; then + AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself]) + with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tkconfig}/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`" + else + AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh]) + fi + fi + + # then check for a private Tk library + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in \ + ../tk \ + `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../tk \ + `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../../tk \ + `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks/Tcl.framework 2>/dev/null` \ + `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Network/Library/Frameworks/Tcl.framework 2>/dev/null` \ + `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Tcl.framework 2>/dev/null` \ + ; do + if test -f "$i/Tk.framework/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/pkg/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + `ls -d /usr/lib/tk8.6 2>/dev/null` \ + `ls -d /usr/lib/tk8.5 2>/dev/null` \ + `ls -d /usr/local/lib/tk8.6 2>/dev/null` \ + `ls -d /usr/local/lib/tk8.5 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tk8.6 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tk8.5 2>/dev/null` \ + ; do + if test -f "$i/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # TEA specific: on Windows, check in common installation locations + if test "${TEA_PLATFORM}" = "windows" \ + -a x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d C:/Tcl/lib 2>/dev/null` \ + `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ + ; do + if test -f "$i/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in \ + ${srcdir}/../tk \ + `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + ]) + + if test x"${ac_cv_c_tkconfig}" = x ; then + TK_BIN_DIR="# no Tk configs found" + AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh]) + else + no_tk= + TK_BIN_DIR="${ac_cv_c_tkconfig}" + AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh]) + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_LOAD_TCLCONFIG -- +# +# Load the tclConfig.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# TCL_BIN_DIR +# +# Results: +# +# Substitutes the following vars: +# TCL_BIN_DIR +# TCL_SRC_DIR +# TCL_LIB_FILE +# TCL_ZIP_FILE +# TCL_ZIPFS_SUPPORT +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_LOAD_TCLCONFIG], [ + AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh]) + + if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then + AC_MSG_RESULT([loading]) + . "${TCL_BIN_DIR}/tclConfig.sh" + else + AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh]) + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" + eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" + + # If the TCL_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TCL_LIB_SPEC will be set to the value + # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC + # instead of TCL_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" + TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" + TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tcl.framework installed in an arbitrary location. + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then + for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ + "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then + TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" + break + fi + done + fi + if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then + TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" + TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" + eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" + eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" + eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" + + AC_SUBST(TCL_VERSION) + AC_SUBST(TCL_PATCH_LEVEL) + AC_SUBST(TCL_BIN_DIR) + AC_SUBST(TCL_SRC_DIR) + + AC_SUBST(TCL_LIB_FILE) + AC_SUBST(TCL_LIB_FLAG) + AC_SUBST(TCL_LIB_SPEC) + + AC_SUBST(TCL_STUB_LIB_FILE) + AC_SUBST(TCL_STUB_LIB_FLAG) + AC_SUBST(TCL_STUB_LIB_SPEC) + + AC_MSG_CHECKING([platform]) + hold_cc=$CC; CC="$TCL_CC" + AC_TRY_COMPILE(,[ + #ifdef _WIN32 + #error win32 + #endif + ], [ + TEA_PLATFORM="unix" + CYGPATH=echo + ], [ + TEA_PLATFORM="windows" + AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo) ] + ) + CC=$hold_cc + AC_MSG_RESULT($TEA_PLATFORM) + + # The BUILD_$pkg is to define the correct extern storage class + # handling when making this package + AC_DEFINE_UNQUOTED(BUILD_${PACKAGE_NAME}, [], + [Building extension source?]) + # Do this here as we have fully defined TEA_PLATFORM now + if test "${TEA_PLATFORM}" = "windows" ; then + EXEEXT=".exe" + CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" + fi + + # TEA specific: + AC_SUBST(CLEANFILES) + AC_SUBST(TCL_LIBS) + AC_SUBST(TCL_DEFS) + AC_SUBST(TCL_EXTRA_CFLAGS) + AC_SUBST(TCL_LD_FLAGS) + AC_SUBST(TCL_SHLIB_LD_LIBS) +]) + +#------------------------------------------------------------------------ +# TEA_LOAD_TKCONFIG -- +# +# Load the tkConfig.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# TK_BIN_DIR +# +# Results: +# +# Sets the following vars that should be in tkConfig.sh: +# TK_BIN_DIR +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_LOAD_TKCONFIG], [ + AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh]) + + if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then + AC_MSG_RESULT([loading]) + . "${TK_BIN_DIR}/tkConfig.sh" + else + AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh]) + fi + + # eval is required to do the TK_DBGX substitution + eval "TK_LIB_FILE=\"${TK_LIB_FILE}\"" + eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\"" + + # If the TK_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TK_LIB_SPEC will be set to the value + # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC + # instead of TK_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TK_BIN_DIR}/Makefile" ; then + TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}" + TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}" + TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tk was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tk.framework installed in an arbitrary location. + case ${TK_DEFS} in + *TK_FRAMEWORK*) + if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then + for i in "`cd "${TK_BIN_DIR}"; pwd`" \ + "`cd "${TK_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then + TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}" + break + fi + done + fi + if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then + TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}" + TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TK_DBGX substitution + eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\"" + eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\"" + eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\"" + eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\"" + + # TEA specific: Ensure windowingsystem is defined + if test "${TEA_PLATFORM}" = "unix" ; then + case ${TK_DEFS} in + *MAC_OSX_TK*) + AC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X TkAqua?]) + TEA_WINDOWINGSYSTEM="aqua" + ;; + *) + TEA_WINDOWINGSYSTEM="x11" + ;; + esac + elif test "${TEA_PLATFORM}" = "windows" ; then + TEA_WINDOWINGSYSTEM="win32" + fi + + AC_SUBST(TK_VERSION) + AC_SUBST(TK_BIN_DIR) + AC_SUBST(TK_SRC_DIR) + + AC_SUBST(TK_LIB_FILE) + AC_SUBST(TK_LIB_FLAG) + AC_SUBST(TK_LIB_SPEC) + + AC_SUBST(TK_STUB_LIB_FILE) + AC_SUBST(TK_STUB_LIB_FLAG) + AC_SUBST(TK_STUB_LIB_SPEC) + + # TEA specific: + AC_SUBST(TK_LIBS) + AC_SUBST(TK_XINCLUDES) +]) + +#------------------------------------------------------------------------ +# TEA_PROG_TCLSH +# Determine the fully qualified path name of the tclsh executable +# in the Tcl build directory or the tclsh installed in a bin +# directory. This macro will correctly determine the name +# of the tclsh executable even if tclsh has not yet been +# built in the build directory. The tclsh found is always +# associated with a tclConfig.sh file. This tclsh should be used +# only for running extension test cases. It should never be +# or generation of files (like pkgIndex.tcl) at build time. +# +# Arguments: +# none +# +# Results: +# Substitutes the following vars: +# TCLSH_PROG +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PROG_TCLSH], [ + AC_MSG_CHECKING([for tclsh]) + if test -f "${TCL_BIN_DIR}/Makefile" ; then + # tclConfig.sh is in Tcl build directory + if test "${TEA_PLATFORM}" = "windows"; then + if test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" ; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" + elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}s${EXEEXT}" ; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}s${EXEEXT}" + elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}t${EXEEXT}" ; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}t${EXEEXT}" + elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}st${EXEEXT}" ; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}st${EXEEXT}" + fi + else + TCLSH_PROG="${TCL_BIN_DIR}/tclsh" + fi + else + # tclConfig.sh is in install location + if test "${TEA_PLATFORM}" = "windows"; then + TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" + else + TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}" + fi + list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" + for i in $list ; do + if test -f "$i/${TCLSH_PROG}" ; then + REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" + break + fi + done + TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" + fi + AC_MSG_RESULT([${TCLSH_PROG}]) + AC_SUBST(TCLSH_PROG) +]) + +#------------------------------------------------------------------------ +# TEA_PROG_WISH +# Determine the fully qualified path name of the wish executable +# in the Tk build directory or the wish installed in a bin +# directory. This macro will correctly determine the name +# of the wish executable even if wish has not yet been +# built in the build directory. The wish found is always +# associated with a tkConfig.sh file. This wish should be used +# only for running extension test cases. It should never be +# or generation of files (like pkgIndex.tcl) at build time. +# +# Arguments: +# none +# +# Results: +# Substitutes the following vars: +# WISH_PROG +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PROG_WISH], [ + AC_MSG_CHECKING([for wish]) + if test -f "${TK_BIN_DIR}/Makefile" ; then + # tkConfig.sh is in Tk build directory + if test "${TEA_PLATFORM}" = "windows"; then + if test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" ; then + WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" + elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}s${EXEEXT}" ; then + WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}$s{EXEEXT}" + elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}t${EXEEXT}" ; then + WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}t${EXEEXT}" + elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}st${EXEEXT}" ; then + WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}st${EXEEXT}" + fi + else + WISH_PROG="${TK_BIN_DIR}/wish" + fi + else + # tkConfig.sh is in install location + if test "${TEA_PLATFORM}" = "windows"; then + WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" + else + WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_DBGX}" + fi + list="`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \ + `ls -d ${TK_BIN_DIR}/.. 2>/dev/null` \ + `ls -d ${TK_PREFIX}/bin 2>/dev/null`" + for i in $list ; do + if test -f "$i/${WISH_PROG}" ; then + REAL_TK_BIN_DIR="`cd "$i"; pwd`/" + break + fi + done + WISH_PROG="${REAL_TK_BIN_DIR}${WISH_PROG}" + fi + AC_MSG_RESULT([${WISH_PROG}]) + AC_SUBST(WISH_PROG) +]) + +#------------------------------------------------------------------------ +# TEA_ENABLE_SHARED -- +# +# Allows the building of shared libraries +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-shared=yes|no +# --enable-stubs=yes|no +# +# Defines the following vars: +# STATIC_BUILD Used for building import/export libraries +# on Windows. +# +# Sets the following vars: +# SHARED_BUILD Value of 1 or 0 +# STUBS_BUILD Value if 1 or 0 +# USE_TCL_STUBS Value true: if SHARED_BUILD or --enable-stubs +# USE_TCLOO_STUBS Value true: if SHARED_BUILD or --enable-stubs +# USE_TK_STUBS Value true: if SHARED_BUILD or --enable-stubs +# AND TEA_WINDOWING_SYSTEM != "" +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ENABLE_SHARED], [ + AC_MSG_CHECKING([how to build libraries]) + AC_ARG_ENABLE(shared, + AC_HELP_STRING([--enable-shared], + [build and link with shared libraries (default: on)]), + [shared_ok=$enableval], [shared_ok=yes]) + + if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + shared_ok=$enableval + else + shared_ok=yes + fi + + AC_ARG_ENABLE(stubs, + AC_HELP_STRING([--enable-stubs], + [build and link with stub libraries. Always true for shared builds (default: on)]), + [stubs_ok=$enableval], [stubs_ok=yes]) + + if test "${enable_stubs+set}" = set; then + enableval="$enable_stubs" + stubs_ok=$enableval + else + stubs_ok=yes + fi + + # Stubs are always enabled for shared builds + if test "$shared_ok" = "yes" ; then + AC_MSG_RESULT([shared]) + SHARED_BUILD=1 + STUBS_BUILD=1 + else + AC_MSG_RESULT([static]) + SHARED_BUILD=0 + AC_DEFINE(STATIC_BUILD, 1, [This a static build]) + if test "$stubs_ok" = "yes" ; then + STUBS_BUILD=1 + else + STUBS_BUILD=0 + fi + fi + if test "${STUBS_BUILD}" = "1" ; then + AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs]) + AC_DEFINE(USE_TCLOO_STUBS, 1, [Use TclOO stubs]) + if test "${TEA_WINDOWINGSYSTEM}" != ""; then + AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs]) + fi + fi + + AC_SUBST(SHARED_BUILD) + AC_SUBST(STUBS_BUILD) +]) + +#------------------------------------------------------------------------ +# TEA_ENABLE_THREADS -- +# +# Specify if thread support should be enabled. If "yes" is specified +# as an arg (optional), threads are enabled by default, "no" means +# threads are disabled. "yes" is the default. +# +# TCL_THREADS is checked so that if you are compiling an extension +# against a threaded core, your extension must be compiled threaded +# as well. +# +# Note that it is legal to have a thread enabled extension run in a +# threaded or non-threaded Tcl core, but a non-threaded extension may +# only run in a non-threaded Tcl core. +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-threads +# +# Sets the following vars: +# THREADS_LIBS Thread library(s) +# +# Defines the following vars: +# TCL_THREADS +# _REENTRANT +# _THREAD_SAFE +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_ENABLE_THREADS], [ + AC_ARG_ENABLE(threads, + AC_HELP_STRING([--enable-threads], + [build with threads (default: on)]), + [tcl_ok=$enableval], [tcl_ok=yes]) + + if test "${enable_threads+set}" = set; then + enableval="$enable_threads" + tcl_ok=$enableval + else + tcl_ok=yes + fi + + if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then + TCL_THREADS=1 + + if test "${TEA_PLATFORM}" != "windows" ; then + # We are always OK on Windows, so check what this platform wants: + + # USE_THREAD_ALLOC tells us to try the special thread-based + # allocator that significantly reduces lock contention + AC_DEFINE(USE_THREAD_ALLOC, 1, + [Do we want to use the threaded memory allocator?]) + AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) + if test "`uname -s`" = "SunOS" ; then + AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, + [Do we really want to follow the standard? Yes we do!]) + fi + AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?]) + AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no) + if test "$tcl_ok" = "no"; then + # Check a little harder for __pthread_mutex_init in the same + # library, as some systems hide it there until pthread.h is + # defined. We could alternatively do an AC_TRY_COMPILE with + # pthread.h, but that will work with libpthread really doesn't + # exist, like AIX 4.2. [Bug: 4359] + AC_CHECK_LIB(pthread, __pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthread" + else + AC_CHECK_LIB(pthreads, pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthreads" + else + AC_CHECK_LIB(c, pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + if test "$tcl_ok" = "no"; then + AC_CHECK_LIB(c_r, pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -pthread" + else + TCL_THREADS=0 + AC_MSG_WARN([Do not know how to find pthread lib on your system - thread support disabled]) + fi + fi + fi + fi + fi + else + TCL_THREADS=0 + fi + # Do checking message here to not mess up interleaved configure output + AC_MSG_CHECKING([for building with threads]) + if test "${TCL_THREADS}" = 1; then + AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?]) + AC_MSG_RESULT([yes (default)]) + else + AC_MSG_RESULT([no]) + fi + # TCL_THREADS sanity checking. See if our request for building with + # threads is the same as the way Tcl was built. If not, warn the user. + case ${TCL_DEFS} in + *THREADS=1*) + if test "${TCL_THREADS}" = "0"; then + AC_MSG_WARN([ + Building ${PACKAGE_NAME} without threads enabled, but building against Tcl + that IS thread-enabled. It is recommended to use --enable-threads.]) + fi + ;; + esac + AC_SUBST(TCL_THREADS) +]) + +#------------------------------------------------------------------------ +# TEA_ENABLE_SYMBOLS -- +# +# Specify if debugging symbols should be used. +# Memory (TCL_MEM_DEBUG) debugging can also be enabled. +# +# Arguments: +# none +# +# TEA varies from core Tcl in that C|LDFLAGS_DEFAULT receives +# the value of C|LDFLAGS_OPTIMIZE|DEBUG already substituted. +# Requires the following vars to be set in the Makefile: +# CFLAGS_DEFAULT +# LDFLAGS_DEFAULT +# +# Results: +# +# Adds the following arguments to configure: +# --enable-symbols +# +# Defines the following vars: +# CFLAGS_DEFAULT Sets to $(CFLAGS_DEBUG) if true +# Sets to "$(CFLAGS_OPTIMIZE) -DNDEBUG" if false +# LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true +# Sets to $(LDFLAGS_OPTIMIZE) if false +# DBGX Formerly used as debug library extension; +# always blank now. +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_ENABLE_SYMBOLS], [ + dnl TEA specific: Make sure we are initialized + AC_REQUIRE([TEA_CONFIG_CFLAGS]) + AC_MSG_CHECKING([for build with symbols]) + AC_ARG_ENABLE(symbols, + AC_HELP_STRING([--enable-symbols], + [build with debugging symbols (default: off)]), + [tcl_ok=$enableval], [tcl_ok=no]) + DBGX="" + if test "$tcl_ok" = "no"; then + CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG" + LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" + AC_MSG_RESULT([no]) + else + CFLAGS_DEFAULT="${CFLAGS_DEBUG}" + LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" + if test "$tcl_ok" = "yes"; then + AC_MSG_RESULT([yes (standard debugging)]) + fi + fi + # TEA specific: + if test "${TEA_PLATFORM}" != "windows" ; then + LDFLAGS_DEFAULT="${LDFLAGS}" + fi + AC_SUBST(CFLAGS_DEFAULT) + AC_SUBST(LDFLAGS_DEFAULT) + AC_SUBST(TCL_DBGX) + + if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then + AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?]) + fi + + if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then + if test "$tcl_ok" = "all"; then + AC_MSG_RESULT([enabled symbols mem debugging]) + else + AC_MSG_RESULT([enabled $tcl_ok debugging]) + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_ENABLE_LANGINFO -- +# +# Allows use of modern nl_langinfo check for better l10n. +# This is only relevant for Unix. +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-langinfo=yes|no (default is yes) +# +# Defines the following vars: +# HAVE_LANGINFO Triggers use of nl_langinfo if defined. +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_ENABLE_LANGINFO], [ + AC_ARG_ENABLE(langinfo, + AC_HELP_STRING([--enable-langinfo], + [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]), + [langinfo_ok=$enableval], [langinfo_ok=yes]) + + HAVE_LANGINFO=0 + if test "$langinfo_ok" = "yes"; then + AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no]) + fi + AC_MSG_CHECKING([whether to use nl_langinfo]) + if test "$langinfo_ok" = "yes"; then + AC_CACHE_VAL(tcl_cv_langinfo_h, [ + AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);], + [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])]) + AC_MSG_RESULT([$tcl_cv_langinfo_h]) + if test $tcl_cv_langinfo_h = yes; then + AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?]) + fi + else + AC_MSG_RESULT([$langinfo_ok]) + fi +]) + +#-------------------------------------------------------------------- +# TEA_CONFIG_SYSTEM +# +# Determine what the system is (some things cannot be easily checked +# on a feature-driven basis, alas). This can usually be done via the +# "uname" command. +# +# Arguments: +# none +# +# Results: +# Defines the following var: +# +# system - System/platform/version identification code. +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_CONFIG_SYSTEM], [ + AC_CACHE_CHECK([system version], tcl_cv_sys_version, [ + # TEA specific: + if test "${TEA_PLATFORM}" = "windows" ; then + tcl_cv_sys_version=windows + else + tcl_cv_sys_version=`uname -s`-`uname -r` + if test "$?" -ne 0 ; then + AC_MSG_WARN([can't find uname command]) + tcl_cv_sys_version=unknown + else + if test "`uname -s`" = "AIX" ; then + tcl_cv_sys_version=AIX-`uname -v`.`uname -r` + fi + fi + fi + ]) + system=$tcl_cv_sys_version +]) + +#-------------------------------------------------------------------- +# TEA_CONFIG_CFLAGS +# +# Try to determine the proper flags to pass to the compiler +# for building shared libraries and other such nonsense. +# +# Arguments: +# none +# +# Results: +# +# Defines and substitutes the following vars: +# +# DL_OBJS, DL_LIBS - removed for TEA, only needed by core. +# LDFLAGS - Flags to pass to the compiler when linking object +# files into an executable application binary such +# as tclsh. +# LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib", +# that tell the run-time dynamic linker where to look +# for shared libraries such as libtcl.so. Depends on +# the variable LIB_RUNTIME_DIR in the Makefile. Could +# be the same as CC_SEARCH_FLAGS if ${CC} is used to link. +# CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/usr/local/tcl/lib", +# that tell the run-time dynamic linker where to look +# for shared libraries such as libtcl.so. Depends on +# the variable LIB_RUNTIME_DIR in the Makefile. +# SHLIB_CFLAGS - Flags to pass to cc when compiling the components +# of a shared library (may request position-independent +# code, among other things). +# SHLIB_LD - Base command to use for combining object files +# into a shared library. +# SHLIB_LD_LIBS - Dependent libraries for the linker to scan when +# creating shared libraries. This symbol typically +# goes at the end of the "ld" commands that build +# shared libraries. The value of the symbol defaults to +# "${LIBS}" if all of the dependent libraries should +# be specified when creating a shared library. If +# dependent libraries should not be specified (as on +# SunOS 4.x, where they cause the link to fail, or in +# general if Tcl and Tk aren't themselves shared +# libraries), then this symbol has an empty string +# as its value. +# SHLIB_SUFFIX - Suffix to use for the names of dynamically loadable +# extensions. An empty string means we don't know how +# to use shared libraries on this platform. +# LIB_SUFFIX - Specifies everything that comes after the "libfoo" +# in a static or shared library name, using the $PACKAGE_VERSION variable +# to put the version in the right place. This is used +# by platforms that need non-standard library names. +# Examples: ${PACKAGE_VERSION}.so.1.1 on NetBSD, since it needs +# to have a version after the .so, and ${PACKAGE_VERSION}.a +# on AIX, since a shared library needs to have +# a .a extension whereas shared objects for loadable +# extensions have a .so extension. Defaults to +# ${PACKAGE_VERSION}${SHLIB_SUFFIX}. +# CFLAGS_DEBUG - +# Flags used when running the compiler in debug mode +# CFLAGS_OPTIMIZE - +# Flags used when running the compiler in optimize mode +# CFLAGS - Additional CFLAGS added as necessary (usually 64-bit) +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_CONFIG_CFLAGS], [ + dnl TEA specific: Make sure we are initialized + AC_REQUIRE([TEA_INIT]) + + # Step 0.a: Enable 64 bit support? + + AC_MSG_CHECKING([if 64bit support is requested]) + AC_ARG_ENABLE(64bit, + AC_HELP_STRING([--enable-64bit], + [enable 64bit support (default: off)]), + [do64bit=$enableval], [do64bit=no]) + AC_MSG_RESULT([$do64bit]) + + # Step 0.b: Enable Solaris 64 bit VIS support? + + AC_MSG_CHECKING([if 64bit Sparc VIS support is requested]) + AC_ARG_ENABLE(64bit-vis, + AC_HELP_STRING([--enable-64bit-vis], + [enable 64bit Sparc VIS support (default: off)]), + [do64bitVIS=$enableval], [do64bitVIS=no]) + AC_MSG_RESULT([$do64bitVIS]) + # Force 64bit on with VIS + AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes]) + + # Step 0.c: Check if visibility support is available. Do this here so + # that platform specific alternatives can be used below if this fails. + + AC_CACHE_CHECK([if compiler supports visibility "hidden"], + tcl_cv_cc_visibility_hidden, [ + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" + AC_TRY_LINK([ + extern __attribute__((__visibility__("hidden"))) void f(void); + void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes, + tcl_cv_cc_visibility_hidden=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [ + AC_DEFINE(MODULE_SCOPE, + [extern __attribute__((__visibility__("hidden")))], + [Compiler support for module scope symbols]) + AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols]) + ]) + + # Step 0.d: Disable -rpath support? + + AC_MSG_CHECKING([if rpath support is requested]) + AC_ARG_ENABLE(rpath, + AC_HELP_STRING([--disable-rpath], + [disable rpath support (default: on)]), + [doRpath=$enableval], [doRpath=yes]) + AC_MSG_RESULT([$doRpath]) + + # TEA specific: Cross-compiling options for Windows/CE builds? + + AS_IF([test "${TEA_PLATFORM}" = windows], [ + AC_MSG_CHECKING([if Windows/CE build is requested]) + AC_ARG_ENABLE(wince, + AC_HELP_STRING([--enable-wince], + [enable Win/CE support (where applicable)]), + [doWince=$enableval], [doWince=no]) + AC_MSG_RESULT([$doWince]) + ]) + + # Set the variable "system" to hold the name and version number + # for the system. + + TEA_CONFIG_SYSTEM + + # Require ranlib early so we can override it in special cases below. + + AC_REQUIRE([AC_PROG_RANLIB]) + + # Set configuration options based on system name and version. + # This is similar to Tcl's unix/tcl.m4 except that we've added a + # "windows" case and removed some core-only vars. + + do64bit_ok=no + # default to '{$LIBS}' and set to "" on per-platform necessary basis + SHLIB_LD_LIBS='${LIBS}' + # When ld needs options to work in 64-bit mode, put them in + # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] + # is disabled by the user. [Bug 1016796] + LDFLAGS_ARCH="" + UNSHARED_LIB_SUFFIX="" + # TEA specific: use PACKAGE_VERSION instead of VERSION + TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' + ECHO_VERSION='`echo ${PACKAGE_VERSION}`' + TCL_LIB_VERSIONS_OK=ok + CFLAGS_DEBUG=-g + AS_IF([test "$GCC" = yes], [ + CFLAGS_OPTIMIZE=-O2 + CFLAGS_WARNING="-Wall" + ], [ + CFLAGS_OPTIMIZE=-O + CFLAGS_WARNING="" + ]) + AC_CHECK_TOOL(AR, ar) + STLIB_LD='${AR} cr' + LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" + AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION=""],[SHLIB_VERSION=".$SHLIB_VERSION"]) + case $system in + # TEA specific: + windows) + # This is a 2-stage check to make sure we have the 64-bit SDK + # We have to know where the SDK is installed. + # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs + # MACHINE is IX86 for LINK, but this is used by the manifest, + # which requires x86|amd64|ia64. + MACHINE="X86" + if test "$do64bit" != "no" ; then + if test "x${MSSDK}x" = "xx" ; then + MSSDK="C:/Progra~1/Microsoft Platform SDK" + fi + MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'` + PATH64="" + case "$do64bit" in + amd64|x64|yes) + MACHINE="AMD64" ; # default to AMD64 64-bit build + PATH64="${MSSDK}/Bin/Win64/x86/AMD64" + ;; + ia64) + MACHINE="IA64" + PATH64="${MSSDK}/Bin/Win64" + ;; + esac + if test "$GCC" != "yes" -a ! -d "${PATH64}" ; then + AC_MSG_WARN([Could not find 64-bit $MACHINE SDK to enable 64bit mode]) + AC_MSG_WARN([Ensure latest Platform SDK is installed]) + do64bit="no" + else + AC_MSG_RESULT([ Using 64-bit $MACHINE mode]) + do64bit_ok="yes" + fi + fi + + if test "$doWince" != "no" ; then + if test "$do64bit" != "no" ; then + AC_MSG_ERROR([Windows/CE and 64-bit builds incompatible]) + fi + if test "$GCC" = "yes" ; then + AC_MSG_ERROR([Windows/CE and GCC builds incompatible]) + fi + TEA_PATH_CELIB + # Set defaults for common evc4/PPC2003 setup + # Currently Tcl requires 300+, possibly 420+ for sockets + CEVERSION=420; # could be 211 300 301 400 420 ... + TARGETCPU=ARMV4; # could be ARMV4 ARM MIPS SH3 X86 ... + ARCH=ARM; # could be ARM MIPS X86EM ... + PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002" + if test "$doWince" != "yes"; then + # If !yes then the user specified something + # Reset ARCH to allow user to skip specifying it + ARCH= + eval `echo $doWince | awk -F, '{ \ + if (length([$]1)) { printf "CEVERSION=\"%s\"\n", [$]1; \ + if ([$]1 < 400) { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \ + if (length([$]2)) { printf "TARGETCPU=\"%s\"\n", toupper([$]2) }; \ + if (length([$]3)) { printf "ARCH=\"%s\"\n", toupper([$]3) }; \ + if (length([$]4)) { printf "PLATFORM=\"%s\"\n", [$]4 }; \ + }'` + if test "x${ARCH}" = "x" ; then + ARCH=$TARGETCPU; + fi + fi + OSVERSION=WCE$CEVERSION; + if test "x${WCEROOT}" = "x" ; then + WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0" + if test ! -d "${WCEROOT}" ; then + WCEROOT="C:/Program Files/Microsoft eMbedded Tools" + fi + fi + if test "x${SDKROOT}" = "x" ; then + SDKROOT="C:/Program Files/Windows CE Tools" + if test ! -d "${SDKROOT}" ; then + SDKROOT="C:/Windows CE Tools" + fi + fi + WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'` + SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'` + if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \ + -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then + AC_MSG_ERROR([could not find PocketPC SDK or target compiler to enable WinCE mode [$CEVERSION,$TARGETCPU,$ARCH,$PLATFORM]]) + doWince="no" + else + # We could PATH_NOSPACE these, but that's not important, + # as long as we quote them when used. + CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include" + if test -d "${CEINCLUDE}/${TARGETCPU}" ; then + CEINCLUDE="${CEINCLUDE}/${TARGETCPU}" + fi + CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" + fi + fi + + if test "$GCC" != "yes" ; then + if test "${SHARED_BUILD}" = "0" ; then + runtime=-MT + else + runtime=-MD + fi + case "x`echo \${VisualStudioVersion}`" in + x1[[4-9]]*) + lflags="${lflags} -nodefaultlib:libucrt.lib" + TEA_ADD_LIBS([ucrt.lib]) + ;; + *) + ;; + esac + + if test "$do64bit" != "no" ; then + # All this magic is necessary for the Win64 SDK RC1 - hobbs + CC="\"${PATH64}/cl.exe\"" + CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\"" + RC="\"${MSSDK}/bin/rc.exe\"" + lflags="${lflags} -nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\"" + LINKBIN="\"${PATH64}/link.exe\"" + CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" + CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" + # Avoid 'unresolved external symbol __security_cookie' + # errors, c.f. http://support.microsoft.com/?id=894573 + TEA_ADD_LIBS([bufferoverflowU.lib]) + elif test "$doWince" != "no" ; then + CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin" + if test "${TARGETCPU}" = "X86"; then + CC="\"${CEBINROOT}/cl.exe\"" + else + CC="\"${CEBINROOT}/cl${ARCH}.exe\"" + fi + CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\"" + RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\"" + arch=`echo ${ARCH} | awk '{print tolower([$]0)}'` + defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS" + if test "${SHARED_BUILD}" = "1" ; then + # Static CE builds require static celib as well + defs="${defs} _DLL" + fi + for i in $defs ; do + AC_DEFINE_UNQUOTED($i, 1, [WinCE def ]$i) + done + AC_DEFINE_UNQUOTED(_WIN32_WCE, $CEVERSION, [_WIN32_WCE version]) + AC_DEFINE_UNQUOTED(UNDER_CE, $CEVERSION, [UNDER_CE version]) + CFLAGS_DEBUG="-nologo -Zi -Od" + CFLAGS_OPTIMIZE="-nologo -Ox" + lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'` + lflags="${lflags} -MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" + LINKBIN="\"${CEBINROOT}/link.exe\"" + AC_SUBST(CELIB_DIR) + else + RC="rc" + lflags="${lflags} -nologo" + LINKBIN="link" + CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" + CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" + fi + fi + + if test "$GCC" = "yes"; then + # mingw gcc mode + AC_CHECK_TOOL(RC, windres) + CFLAGS_DEBUG="-g" + CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" + SHLIB_LD='${CC} -shared' + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" + LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" + + AC_CACHE_CHECK(for cross-compile version of gcc, + ac_cv_cross, + AC_TRY_COMPILE([ + #ifdef _WIN32 + #error cross-compiler + #endif + ], [], + ac_cv_cross=yes, + ac_cv_cross=no) + ) + if test "$ac_cv_cross" = "yes"; then + case "$do64bit" in + amd64|x64|yes) + CC="x86_64-w64-mingw32-gcc" + LD="x86_64-w64-mingw32-ld" + AR="x86_64-w64-mingw32-ar" + RANLIB="x86_64-w64-mingw32-ranlib" + RC="x86_64-w64-mingw32-windres" + ;; + *) + CC="i686-w64-mingw32-gcc" + LD="i686-w64-mingw32-ld" + AR="i686-w64-mingw32-ar" + RANLIB="i686-w64-mingw32-ranlib" + RC="i686-w64-mingw32-windres" + ;; + esac + fi + + else + SHLIB_LD="${LINKBIN} -dll ${lflags}" + # link -lib only works when -lib is the first arg + STLIB_LD="${LINKBIN} -lib ${lflags}" + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' + PATHTYPE=-w + # For information on what debugtype is most useful, see: + # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp + # and also + # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx + # This essentially turns it all on. + LDFLAGS_DEBUG="-debug -debugtype:cv" + LDFLAGS_OPTIMIZE="-release" + if test "$doWince" != "no" ; then + LDFLAGS_CONSOLE="-link ${lflags}" + LDFLAGS_WINDOW=${LDFLAGS_CONSOLE} + else + LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" + LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" + fi + fi + + SHLIB_SUFFIX=".dll" + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' + + TCL_LIB_VERSIONS_OK=nodots + ;; + AIX-*) + AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [ + # AIX requires the _r compiler when gcc isn't being used + case "${CC}" in + *_r|*_r\ *) + # ok ... + ;; + *) + # Make sure only first arg gets _r + CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'` + ;; + esac + AC_MSG_RESULT([Using $CC for compiling with threads]) + ]) + LIBS="$LIBS -lc" + SHLIB_CFLAGS="" + SHLIB_SUFFIX=".so" + + LD_LIBRARY_PATH_VAR="LIBPATH" + + # Check to enable 64-bit flags for compiler/linker + AS_IF([test "$do64bit" = yes], [ + AS_IF([test "$GCC" = yes], [ + AC_MSG_WARN([64bit mode not supported with GCC on $system]) + ], [ + do64bit_ok=yes + CFLAGS="$CFLAGS -q64" + LDFLAGS_ARCH="-q64" + RANLIB="${RANLIB} -X64" + AR="${AR} -X64" + SHLIB_LD_FLAGS="-b64" + ]) + ]) + + AS_IF([test "`uname -m`" = ia64], [ + # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + AS_IF([test "$GCC" = yes], [ + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + ], [ + CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}' + ]) + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + ], [ + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared -Wl,-bexpall' + ], [ + SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" + LDFLAGS="$LDFLAGS -brtl" + ]) + SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" + CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ]) + ;; + BeOS*) + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -nostart' + SHLIB_SUFFIX=".so" + + #----------------------------------------------------------- + # Check for inet_ntoa in -lbind, for BeOS (which also needs + # -lsocket, even if the network functions are in -lnet which + # is always linked to, for compatibility. + #----------------------------------------------------------- + AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"]) + ;; + BSD/OS-4.*) + SHLIB_CFLAGS="-export-dynamic -fPIC" + SHLIB_LD='${CC} -shared' + SHLIB_SUFFIX=".so" + LDFLAGS="$LDFLAGS -export-dynamic" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + CYGWIN_*) + SHLIB_CFLAGS="" + SHLIB_LD='${CC} -shared' + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$[@].a" + SHLIB_SUFFIX=".dll" + EXEEXT=".exe" + do64bit_ok=yes + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + Haiku*) + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' + AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"]) + ;; + HP-UX-*.11.*) + # Use updated header definitions where possible + AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?]) + # TEA specific: Needed by Tcl, but not most extensions + #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) + #LIBS="$LIBS -lxnet" # Use the XOPEN network library + + AS_IF([test "`uname -m`" = ia64], [ + SHLIB_SUFFIX=".so" + # Use newer C++ library for C++ extensions + #if test "$GCC" != "yes" ; then + # CPPFLAGS="-AA" + #fi + ], [ + SHLIB_SUFFIX=".sl" + ]) + AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) + AS_IF([test "$tcl_ok" = yes], [ + LDFLAGS="$LDFLAGS -Wl,-E" + CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' + LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' + LD_LIBRARY_PATH_VAR="SHLIB_PATH" + ]) + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ], [ + CFLAGS="$CFLAGS -z" + # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc + #CFLAGS="$CFLAGS +DAportable" + SHLIB_CFLAGS="+z" + SHLIB_LD="ld -b" + ]) + + # Check to enable 64-bit flags for compiler/linker + AS_IF([test "$do64bit" = "yes"], [ + AS_IF([test "$GCC" = yes], [ + case `${CC} -dumpmachine` in + hppa64*) + # 64-bit gcc in use. Fix flags for GNU ld. + do64bit_ok=yes + SHLIB_LD='${CC} -shared' + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ;; + *) + AC_MSG_WARN([64bit mode not supported with GCC on $system]) + ;; + esac + ], [ + do64bit_ok=yes + CFLAGS="$CFLAGS +DD64" + LDFLAGS_ARCH="+DD64" + ]) + ]) ;; + IRIX-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + AS_IF([test "$GCC" = yes], [ + CFLAGS="$CFLAGS -mabi=n32" + LDFLAGS="$LDFLAGS -mabi=n32" + ], [ + case $system in + IRIX-6.3) + # Use to build 6.2 compatible binaries on 6.3. + CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" + ;; + *) + CFLAGS="$CFLAGS -n32" + ;; + esac + LDFLAGS="$LDFLAGS -n32" + ]) + ;; + IRIX64-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + + # Check to enable 64-bit flags for compiler/linker + + AS_IF([test "$do64bit" = yes], [ + AS_IF([test "$GCC" = yes], [ + AC_MSG_WARN([64bit mode not supported by gcc]) + ], [ + do64bit_ok=yes + SHLIB_LD="ld -64 -shared -rdata_shared" + CFLAGS="$CFLAGS -64" + LDFLAGS_ARCH="-64" + ]) + ]) + ;; + Linux*|GNU*|NetBSD-Debian) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + + # TEA specific: + CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" + + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS_DEFAULT} -shared' + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"]) + AS_IF([test $do64bit = yes], [ + AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [ + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -m64" + AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_m64 = yes], [ + CFLAGS="$CFLAGS -m64" + do64bit_ok=yes + ]) + ]) + + # The combo of gcc + glibc has a bug related to inlining of + # functions like strtod(). The -fno-builtin flag should address + # this problem but it does not work. The -fno-inline flag is kind + # of overkill but it works. Disable inlining only when one of the + # files in compat/*.c is being linked in. + + AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"]) + ;; + Lynx*) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + CFLAGS_OPTIMIZE=-02 + SHLIB_LD='${CC} -shared' + LD_FLAGS="-Wl,--export-dynamic" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + ;; + OpenBSD-*) + arch=`arch -s` + case "$arch" in + alpha|sparc64) + SHLIB_CFLAGS="-fPIC" + ;; + *) + SHLIB_CFLAGS="-fpic" + ;; + esac + SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' + SHLIB_SUFFIX=".so" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' + LDFLAGS="-Wl,-export-dynamic" + CFLAGS_OPTIMIZE="-O2" + AS_IF([test "${TCL_THREADS}" = "1"], [ + # On OpenBSD: Compile with -pthread + # Don't link with -lpthread + LIBS=`echo $LIBS | sed s/-lpthread//` + CFLAGS="$CFLAGS -pthread" + ]) + # OpenBSD doesn't do version numbers with dots. + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + TCL_LIB_VERSIONS_OK=nodots + ;; + NetBSD-*) + # NetBSD has ELF and can use 'cc -shared' to build shared libs + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' + SHLIB_SUFFIX=".so" + LDFLAGS="$LDFLAGS -export-dynamic" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + AS_IF([test "${TCL_THREADS}" = "1"], [ + # The -pthread needs to go in the CFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + ]) + ;; + DragonFly-*|FreeBSD-*) + # This configuration from FreeBSD Ports. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="${CC} -shared" + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$[@]" + SHLIB_SUFFIX=".so" + LDFLAGS="" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + AS_IF([test "${TCL_THREADS}" = "1"], [ + # The -pthread needs to go in the LDFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LDFLAGS="$LDFLAGS $PTHREAD_LIBS"]) + case $system in + FreeBSD-3.*) + # Version numbers are dot-stripped by system policy. + TCL_TRIM_DOTS=`echo ${PACKAGE_VERSION} | tr -d .` + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1' + TCL_LIB_VERSIONS_OK=nodots + ;; + esac + ;; + Darwin-*) + CFLAGS_OPTIMIZE="-Os" + SHLIB_CFLAGS="-fno-common" + # To avoid discrepancies between what headers configure sees during + # preprocessing tests and compiling tests, move any -isysroot and + # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: + CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`" + CFLAGS="`echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`" + AS_IF([test $do64bit = yes], [ + case `arch` in + ppc) + AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag], + tcl_cv_cc_arch_ppc64, [ + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes, + tcl_cv_cc_arch_ppc64=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [ + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + do64bit_ok=yes + ]);; + i386) + AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag], + tcl_cv_cc_arch_x86_64, [ + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch x86_64" + AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes, + tcl_cv_cc_arch_x86_64=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [ + CFLAGS="$CFLAGS -arch x86_64" + do64bit_ok=yes + ]);; + *) + AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);; + esac + ], [ + # Check for combined 32-bit and 64-bit fat build + AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ + && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [ + fat_32_64=yes]) + ]) + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' + AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [ + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" + AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no) + LDFLAGS=$hold_ldflags]) + AS_IF([test $tcl_cv_ld_single_module = yes], [ + SHLIB_LD="${SHLIB_LD} -Wl,-single_module" + ]) + # TEA specific: link shlib with current and compatibility version flags + vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([[0-9]]\{1,5\}\)\(\(\.[[0-9]]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` + SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" + SHLIB_SUFFIX=".dylib" + # Don't use -prebind when building for Mac OS X 10.4 or later only: + AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \ + "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [ + LDFLAGS="$LDFLAGS -prebind"]) + LDFLAGS="$LDFLAGS -headerpad_max_install_names" + AC_CACHE_CHECK([if ld accepts -search_paths_first flag], + tcl_cv_ld_search_paths_first, [ + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes, + tcl_cv_ld_search_paths_first=no) + LDFLAGS=$hold_ldflags]) + AS_IF([test $tcl_cv_ld_search_paths_first = yes], [ + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + ]) + AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ + AC_DEFINE(MODULE_SCOPE, [__private_extern__], + [Compiler support for module scope symbols]) + tcl_cv_cc_visibility_hidden=yes + ]) + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" + # TEA specific: for combined 32 & 64 bit fat builds of Tk + # extensions, verify that 64-bit build is possible. + AS_IF([test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"], [ + AS_IF([test "${TEA_WINDOWINGSYSTEM}" = x11], [ + AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [ + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" + LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" + AC_TRY_LINK([#include <X11/Xlib.h>], [XrmInitialize();], + tcl_cv_lib_x11_64=yes, tcl_cv_lib_x11_64=no) + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done]) + ]) + AS_IF([test "${TEA_WINDOWINGSYSTEM}" = aqua], [ + AC_CACHE_CHECK([for 64-bit Tk], tcl_cv_lib_tk_64, [ + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" + LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" + AC_TRY_LINK([#include <tk.h>], [Tk_InitStubs(NULL, "", 0);], + tcl_cv_lib_tk_64=yes, tcl_cv_lib_tk_64=no) + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done]) + ]) + # remove 64-bit arch flags from CFLAGS et al. if configuration + # does not support 64-bit. + AS_IF([test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no], [ + AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags]) + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' + done]) + ]) + ;; + OS/390-*) + CFLAGS_OPTIMIZE="" # Optimizer is buggy + AC_DEFINE(_OE_SOCKETS, 1, # needed in sys/socket.h + [Should OS/390 do the right thing with sockets?]) + ;; + OSF1-V*) + # Digital OSF/1 + SHLIB_CFLAGS="" + AS_IF([test "$SHARED_BUILD" = 1], [ + SHLIB_LD='ld -shared -expect_unresolved "*"' + ], [ + SHLIB_LD='ld -non_shared -expect_unresolved "*"' + ]) + SHLIB_SUFFIX=".so" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [ + CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"]) + # see pthread_intro(3) for pthread support on osf1, k.furukawa + AS_IF([test "${TCL_THREADS}" = 1], [ + CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" + CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" + LIBS=`echo $LIBS | sed s/-lpthreads//` + AS_IF([test "$GCC" = yes], [ + LIBS="$LIBS -lpthread -lmach -lexc" + ], [ + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + ]) + ]) + ;; + QNX-6*) + # QNX RTP + # This may work for all QNX, but it was only reported for v6. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="ld -Bshareable -x" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SCO_SV-3.2*) + AS_IF([test "$GCC" = yes], [ + SHLIB_CFLAGS="-fPIC -melf" + LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" + ], [ + SHLIB_CFLAGS="-Kpic -belf" + LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" + ]) + SHLIB_LD="ld -G" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SunOS-5.[[0-6]]) + # Careful to not let 5.10+ fall into this case + + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) + AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, + [Do we really want to follow the standard? Yes we do!]) + + SHLIB_CFLAGS="-KPIC" + SHLIB_SUFFIX=".so" + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ], [ + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ]) + ;; + SunOS-5*) + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) + AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, + [Do we really want to follow the standard? Yes we do!]) + + SHLIB_CFLAGS="-KPIC" + + # Check to enable 64-bit flags for compiler/linker + AS_IF([test "$do64bit" = yes], [ + arch=`isainfo` + AS_IF([test "$arch" = "sparcv9 sparc"], [ + AS_IF([test "$GCC" = yes], [ + AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [ + AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system]) + ], [ + do64bit_ok=yes + CFLAGS="$CFLAGS -m64 -mcpu=v9" + LDFLAGS="$LDFLAGS -m64 -mcpu=v9" + SHLIB_CFLAGS="-fPIC" + ]) + ], [ + do64bit_ok=yes + AS_IF([test "$do64bitVIS" = yes], [ + CFLAGS="$CFLAGS -xarch=v9a" + LDFLAGS_ARCH="-xarch=v9a" + ], [ + CFLAGS="$CFLAGS -xarch=v9" + LDFLAGS_ARCH="-xarch=v9" + ]) + # Solaris 64 uses this as well + #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" + ]) + ], [AS_IF([test "$arch" = "amd64 i386"], [ + AS_IF([test "$GCC" = yes], [ + case $system in + SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) + do64bit_ok=yes + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + AC_MSG_WARN([64bit mode not supported with GCC on $system]);; + esac + ], [ + do64bit_ok=yes + case $system in + SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + CFLAGS="$CFLAGS -xarch=amd64" + LDFLAGS="$LDFLAGS -xarch=amd64";; + esac + ]) + ], [AC_MSG_WARN([64bit mode not supported for $arch])])]) + ]) + + SHLIB_SUFFIX=".so" + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + AS_IF([test "$do64bit_ok" = yes], [ + AS_IF([test "$arch" = "sparcv9 sparc"], [ + # We need to specify -static-libgcc or we need to + # add the path to the sparv9 libgcc. + # JH: static-libgcc is necessary for core Tcl, but may + # not be necessary for extensions. + SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" + # for finding sparcv9 libgcc, get the regular libgcc + # path, remove so name and append 'sparcv9' + #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." + #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" + ], [AS_IF([test "$arch" = "amd64 i386"], [ + # JH: static-libgcc is necessary for core Tcl, but may + # not be necessary for extensions. + SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" + ])]) + ]) + ], [ + case $system in + SunOS-5.[[1-9]][[0-9]]*) + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; + *) + SHLIB_LD='/usr/ccs/bin/ld -G -z text';; + esac + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + ]) + ;; + UNIX_SV* | UnixWare-5*) + SHLIB_CFLAGS="-KPIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers + # that don't grok the -Bexport option. Test that it does. + AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [ + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-Bexport" + AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no) + LDFLAGS=$hold_ldflags]) + AS_IF([test $tcl_cv_ld_Bexport = yes], [ + LDFLAGS="$LDFLAGS -Wl,-Bexport" + ]) + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + esac + + AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [ + AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform]) + ]) + +dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so +dnl # until the end of configure, as configure's compile and link tests use +dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's +dnl # preprocessing tests use only CPPFLAGS. + AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""]) + + # Add in the arch flags late to ensure it wasn't removed. + # Not necessary in TEA, but this is aligned with core + LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" + + # If we're running gcc, then change the C flags for compiling shared + # libraries to the right flags for gcc, instead of those for the + # standard manufacturer compiler. + + AS_IF([test "$GCC" = yes], [ + case $system in + AIX-*) ;; + BSD/OS*) ;; + CYGWIN_*|MINGW32_*|MINGW64_*) ;; + IRIX*) ;; + NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;; + Darwin-*) ;; + SCO_SV-3.2*) ;; + windows) ;; + *) SHLIB_CFLAGS="-fPIC" ;; + esac]) + + AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ + AC_DEFINE(MODULE_SCOPE, [extern], + [No Compiler support for module scope symbols]) + ]) + + AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [ + # TEA specific: use PACKAGE_VERSION instead of VERSION + SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}']) + AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [ + # TEA specific: use PACKAGE_VERSION instead of VERSION + UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a']) + + if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then + AC_CACHE_CHECK(for SEH support in compiler, + tcl_cv_seh, + AC_TRY_RUN([ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#undef WIN32_LEAN_AND_MEAN + + int main(int argc, char** argv) { + int a, b = 0; + __try { + a = 666 / b; + } + __except (EXCEPTION_EXECUTE_HANDLER) { + return 0; + } + return 1; + } + ], + tcl_cv_seh=yes, + tcl_cv_seh=no, + tcl_cv_seh=no) + ) + if test "$tcl_cv_seh" = "no" ; then + AC_DEFINE(HAVE_NO_SEH, 1, + [Defined when mingw does not support SEH]) + fi + + # + # Check to see if the excpt.h include file provided contains the + # definition for EXCEPTION_DISPOSITION; if not, which is the case + # with Cygwin's version as of 2002-04-10, define it to be int, + # sufficient for getting the current code to work. + # + AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files, + tcl_cv_eh_disposition, + AC_TRY_COMPILE([ +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# undef WIN32_LEAN_AND_MEAN + ],[ + EXCEPTION_DISPOSITION x; + ], + tcl_cv_eh_disposition=yes, + tcl_cv_eh_disposition=no) + ) + if test "$tcl_cv_eh_disposition" = "no" ; then + AC_DEFINE(EXCEPTION_DISPOSITION, int, + [Defined when cygwin/mingw does not support EXCEPTION DISPOSITION]) + fi + + # Check to see if winnt.h defines CHAR, SHORT, and LONG + # even if VOID has already been #defined. The win32api + # used by mingw and cygwin is known to do this. + + AC_CACHE_CHECK(for winnt.h that ignores VOID define, + tcl_cv_winnt_ignore_void, + AC_TRY_COMPILE([ +#define VOID void +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#undef WIN32_LEAN_AND_MEAN + ], [ + CHAR c; + SHORT s; + LONG l; + ], + tcl_cv_winnt_ignore_void=yes, + tcl_cv_winnt_ignore_void=no) + ) + if test "$tcl_cv_winnt_ignore_void" = "yes" ; then + AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1, + [Defined when cygwin/mingw ignores VOID define in winnt.h]) + fi + fi + + # See if the compiler supports casting to a union type. + # This is used to stop gcc from printing a compiler + # warning when initializing a union member. + + AC_CACHE_CHECK(for cast to union support, + tcl_cv_cast_to_union, + AC_TRY_COMPILE([], + [ + union foo { int i; double d; }; + union foo f = (union foo) (int) 0; + ], + tcl_cv_cast_to_union=yes, + tcl_cv_cast_to_union=no) + ) + if test "$tcl_cv_cast_to_union" = "yes"; then + AC_DEFINE(HAVE_CAST_TO_UNION, 1, + [Defined when compiler supports casting to union type.]) + fi + + AC_SUBST(CFLAGS_DEBUG) + AC_SUBST(CFLAGS_OPTIMIZE) + AC_SUBST(CFLAGS_WARNING) + + AC_SUBST(STLIB_LD) + AC_SUBST(SHLIB_LD) + + AC_SUBST(SHLIB_LD_LIBS) + AC_SUBST(SHLIB_CFLAGS) + + AC_SUBST(LD_LIBRARY_PATH_VAR) + + # These must be called after we do the basic CFLAGS checks and + # verify any possible 64-bit or similar switches are necessary + TEA_TCL_EARLY_FLAGS + TEA_TCL_64BIT_FLAGS +]) + +#-------------------------------------------------------------------- +# TEA_SERIAL_PORT +# +# Determine which interface to use to talk to the serial port. +# Note that #include lines must begin in leftmost column for +# some compilers to recognize them as preprocessor directives, +# and some build environments have stdin not pointing at a +# pseudo-terminal (usually /dev/null instead.) +# +# Arguments: +# none +# +# Results: +# +# Defines only one of the following vars: +# HAVE_SYS_MODEM_H +# USE_TERMIOS +# USE_TERMIO +# USE_SGTTY +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_SERIAL_PORT], [ + AC_CHECK_HEADERS(sys/modem.h) + AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [ + AC_TRY_RUN([ +#include <termios.h> + +int main() { + struct termios t; + if (tcgetattr(0, &t) == 0) { + cfsetospeed(&t, 0); + t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; + return 0; + } + return 1; +}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + if test $tcl_cv_api_serial = no ; then + AC_TRY_RUN([ +#include <termio.h> + +int main() { + struct termio t; + if (ioctl(0, TCGETA, &t) == 0) { + t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; + return 0; + } + return 1; +}], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + fi + if test $tcl_cv_api_serial = no ; then + AC_TRY_RUN([ +#include <sgtty.h> + +int main() { + struct sgttyb t; + if (ioctl(0, TIOCGETP, &t) == 0) { + t.sg_ospeed = 0; + t.sg_flags |= ODDP | EVENP | RAW; + return 0; + } + return 1; +}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + fi + if test $tcl_cv_api_serial = no ; then + AC_TRY_RUN([ +#include <termios.h> +#include <errno.h> + +int main() { + struct termios t; + if (tcgetattr(0, &t) == 0 + || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { + cfsetospeed(&t, 0); + t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; + return 0; + } + return 1; +}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + fi + if test $tcl_cv_api_serial = no; then + AC_TRY_RUN([ +#include <termio.h> +#include <errno.h> + +int main() { + struct termio t; + if (ioctl(0, TCGETA, &t) == 0 + || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { + t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; + return 0; + } + return 1; + }], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + fi + if test $tcl_cv_api_serial = no; then + AC_TRY_RUN([ +#include <sgtty.h> +#include <errno.h> + +int main() { + struct sgttyb t; + if (ioctl(0, TIOCGETP, &t) == 0 + || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { + t.sg_ospeed = 0; + t.sg_flags |= ODDP | EVENP | RAW; + return 0; + } + return 1; +}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=none, tcl_cv_api_serial=none) + fi]) + case $tcl_cv_api_serial in + termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);; + termio) AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);; + sgtty) AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);; + esac +]) + +#-------------------------------------------------------------------- +# TEA_PATH_X +# +# Locate the X11 header files and the X11 library archive. Try +# the ac_path_x macro first, but if it doesn't find the X stuff +# (e.g. because there's no xmkmf program) then check through +# a list of possible directories. Under some conditions the +# autoconf macro will return an include directory that contains +# no include files, so double-check its result just to be safe. +# +# This should be called after TEA_CONFIG_CFLAGS as setting the +# LIBS line can confuse some configure macro magic. +# +# Arguments: +# none +# +# Results: +# +# Sets the following vars: +# XINCLUDES +# XLIBSW +# PKG_LIBS (appends to) +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_PATH_X], [ + if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then + TEA_PATH_UNIX_X + fi +]) + +AC_DEFUN([TEA_PATH_UNIX_X], [ + AC_PATH_X + not_really_there="" + if test "$no_x" = ""; then + if test "$x_includes" = ""; then + AC_TRY_CPP([#include <X11/Xlib.h>], , not_really_there="yes") + else + if test ! -r $x_includes/X11/Xlib.h; then + not_really_there="yes" + fi + fi + fi + if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then + AC_MSG_CHECKING([for X11 header files]) + found_xincludes="no" + AC_TRY_CPP([#include <X11/Xlib.h>], found_xincludes="yes", found_xincludes="no") + if test "$found_xincludes" = "no"; then + dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include" + for i in $dirs ; do + if test -r $i/X11/Xlib.h; then + AC_MSG_RESULT([$i]) + XINCLUDES=" -I$i" + found_xincludes="yes" + break + fi + done + fi + else + if test "$x_includes" != ""; then + XINCLUDES="-I$x_includes" + found_xincludes="yes" + fi + fi + if test "$found_xincludes" = "no"; then + AC_MSG_RESULT([couldn't find any!]) + fi + + if test "$no_x" = yes; then + AC_MSG_CHECKING([for X11 libraries]) + XLIBSW=nope + dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib" + for i in $dirs ; do + if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then + AC_MSG_RESULT([$i]) + XLIBSW="-L$i -lX11" + x_libraries="$i" + break + fi + done + else + if test "$x_libraries" = ""; then + XLIBSW=-lX11 + else + XLIBSW="-L$x_libraries -lX11" + fi + fi + if test "$XLIBSW" = nope ; then + AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow) + fi + if test "$XLIBSW" = nope ; then + AC_MSG_RESULT([could not find any! Using -lX11.]) + XLIBSW=-lX11 + fi + # TEA specific: + if test x"${XLIBSW}" != x ; then + PKG_LIBS="${PKG_LIBS} ${XLIBSW}" + fi +]) + +#-------------------------------------------------------------------- +# TEA_BLOCKING_STYLE +# +# The statements below check for systems where POSIX-style +# non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. +# On these systems (mostly older ones), use the old BSD-style +# FIONBIO approach instead. +# +# Arguments: +# none +# +# Results: +# +# Defines some of the following vars: +# HAVE_SYS_IOCTL_H +# HAVE_SYS_FILIO_H +# USE_FIONBIO +# O_NONBLOCK +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_BLOCKING_STYLE], [ + AC_CHECK_HEADERS(sys/ioctl.h) + AC_CHECK_HEADERS(sys/filio.h) + TEA_CONFIG_SYSTEM + AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O]) + case $system in + OSF*) + AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) + AC_MSG_RESULT([FIONBIO]) + ;; + *) + AC_MSG_RESULT([O_NONBLOCK]) + ;; + esac +]) + +#-------------------------------------------------------------------- +# TEA_TIME_HANDLER +# +# Checks how the system deals with time.h, what time structures +# are used on the system, and what fields the structures have. +# +# Arguments: +# none +# +# Results: +# +# Defines some of the following vars: +# USE_DELTA_FOR_TZ +# HAVE_TM_GMTOFF +# HAVE_TM_TZADJ +# HAVE_TIMEZONE_VAR +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_TIME_HANDLER], [ + AC_CHECK_HEADERS(sys/time.h) + AC_HEADER_TIME + AC_STRUCT_TIMEZONE + + AC_CHECK_FUNCS(gmtime_r localtime_r) + + AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [ + AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;], + tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)]) + if test $tcl_cv_member_tm_tzadj = yes ; then + AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?]) + fi + + AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [ + AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;], + tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)]) + if test $tcl_cv_member_tm_gmtoff = yes ; then + AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?]) + fi + + # + # Its important to include time.h in this check, as some systems + # (like convex) have timezone functions, etc. + # + AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [ + AC_TRY_COMPILE([#include <time.h>], + [extern long timezone; + timezone += 1; + exit (0);], + tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)]) + if test $tcl_cv_timezone_long = yes ; then + AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) + else + # + # On some systems (eg IRIX 6.2), timezone is a time_t and not a long. + # + AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [ + AC_TRY_COMPILE([#include <time.h>], + [extern time_t timezone; + timezone += 1; + exit (0);], + tcl_cv_timezone_time=yes, tcl_cv_timezone_time=no)]) + if test $tcl_cv_timezone_time = yes ; then + AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) + fi + fi +]) + +#-------------------------------------------------------------------- +# TEA_BUGGY_STRTOD +# +# Under Solaris 2.4, strtod returns the wrong value for the +# terminating character under some conditions. Check for this +# and if the problem exists use a substitute procedure +# "fixstrtod" (provided by Tcl) that corrects the error. +# Also, on Compaq's Tru64 Unix 5.0, +# strtod(" ") returns 0.0 instead of a failure to convert. +# +# Arguments: +# none +# +# Results: +# +# Might defines some of the following vars: +# strtod (=fixstrtod) +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_BUGGY_STRTOD], [ + AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0) + if test "$tcl_strtod" = 1; then + AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[ + AC_TRY_RUN([ + extern double strtod(); + int main() { + char *infString="Inf", *nanString="NaN", *spaceString=" "; + char *term; + double value; + value = strtod(infString, &term); + if ((term != infString) && (term[-1] == 0)) { + exit(1); + } + value = strtod(nanString, &term); + if ((term != nanString) && (term[-1] == 0)) { + exit(1); + } + value = strtod(spaceString, &term); + if (term == (spaceString+1)) { + exit(1); + } + exit(0); + }], tcl_cv_strtod_buggy=ok, tcl_cv_strtod_buggy=buggy, + tcl_cv_strtod_buggy=buggy)]) + if test "$tcl_cv_strtod_buggy" = buggy; then + AC_LIBOBJ([fixstrtod]) + USE_COMPAT=1 + AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?]) + fi + fi +]) + +#-------------------------------------------------------------------- +# TEA_TCL_EARLY_FLAGS +# +# Check for what flags are needed to be passed so the correct OS +# features are available. +# +# Arguments: +# None +# +# Results: +# +# Might define the following vars: +# _ISOC99_SOURCE +# _LARGEFILE64_SOURCE +# _LARGEFILE_SOURCE64 +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_TCL_EARLY_FLAG],[ + AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]), + AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no, + AC_TRY_COMPILE([[#define ]$1[ 1 +]$2], $3, + [tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes, + [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no))) + if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then + AC_DEFINE($1, 1, [Add the ]$1[ flag when building]) + tcl_flags="$tcl_flags $1" + fi +]) + +AC_DEFUN([TEA_TCL_EARLY_FLAGS],[ + AC_MSG_CHECKING([for required early compiler flags]) + tcl_flags="" + TEA_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>], + [char *p = (char *)strtoll; char *q = (char *)strtoull;]) + TEA_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>], + [struct stat64 buf; int i = stat64("/", &buf);]) + TEA_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include <sys/stat.h>], + [char *p = (char *)open64;]) + if test "x${tcl_flags}" = "x" ; then + AC_MSG_RESULT([none]) + else + AC_MSG_RESULT([${tcl_flags}]) + fi +]) + +#-------------------------------------------------------------------- +# TEA_TCL_64BIT_FLAGS +# +# Check for what is defined in the way of 64-bit features. +# +# Arguments: +# None +# +# Results: +# +# Might define the following vars: +# TCL_WIDE_INT_IS_LONG +# TCL_WIDE_INT_TYPE +# HAVE_STRUCT_DIRENT64 +# HAVE_STRUCT_STAT64 +# HAVE_TYPE_OFF64_T +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_TCL_64BIT_FLAGS], [ + AC_MSG_CHECKING([for 64-bit integer type]) + AC_CACHE_VAL(tcl_cv_type_64bit,[ + tcl_cv_type_64bit=none + # See if the compiler knows natively about __int64 + AC_TRY_COMPILE(,[__int64 value = (__int64) 0;], + tcl_type_64bit=__int64, tcl_type_64bit="long long") + # See if we should use long anyway Note that we substitute in the + # type that is our current guess for a 64-bit type inside this check + # program, so it should be modified only carefully... + AC_TRY_COMPILE(,[switch (0) { + case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ; + }],tcl_cv_type_64bit=${tcl_type_64bit})]) + if test "${tcl_cv_type_64bit}" = none ; then + AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?]) + AC_MSG_RESULT([using long]) + elif test "${tcl_cv_type_64bit}" = "__int64" \ + -a "${TEA_PLATFORM}" = "windows" ; then + # TEA specific: We actually want to use the default tcl.h checks in + # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* + AC_MSG_RESULT([using Tcl header defaults]) + else + AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit}, + [What type should be used to define wide integers?]) + AC_MSG_RESULT([${tcl_cv_type_64bit}]) + + # Now check for auxiliary declarations + AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[ + AC_TRY_COMPILE([#include <sys/types.h> +#include <dirent.h>],[struct dirent64 p;], + tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)]) + if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then + AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?]) + fi + + AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[ + AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p; +], + tcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)]) + if test "x${tcl_cv_struct_stat64}" = "xyes" ; then + AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?]) + fi + + AC_CHECK_FUNCS(open64 lseek64) + AC_MSG_CHECKING([for off64_t]) + AC_CACHE_VAL(tcl_cv_type_off64_t,[ + AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset; +], + tcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)]) + dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the + dnl functions lseek64 and open64 are defined. + if test "x${tcl_cv_type_off64_t}" = "xyes" && \ + test "x${ac_cv_func_lseek64}" = "xyes" && \ + test "x${ac_cv_func_open64}" = "xyes" ; then + AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?]) + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + fi +]) + +## +## Here ends the standard Tcl configuration bits and starts the +## TEA specific functions +## + +#------------------------------------------------------------------------ +# TEA_INIT -- +# +# Init various Tcl Extension Architecture (TEA) variables. +# This should be the first called TEA_* macro. +# +# Arguments: +# none +# +# Results: +# +# Defines and substs the following vars: +# CYGPATH +# EXEEXT +# Defines only: +# TEA_VERSION +# TEA_INITED +# TEA_PLATFORM (windows or unix) +# +# "cygpath" is used on windows to generate native path names for include +# files. These variables should only be used with the compiler and linker +# since they generate native path names. +# +# EXEEXT +# Select the executable extension based on the host type. This +# is a lightweight replacement for AC_EXEEXT that doesn't require +# a compiler. +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_INIT], [ + TEA_VERSION="3.13" + + AC_MSG_CHECKING([TEA configuration]) + if test x"${PACKAGE_NAME}" = x ; then + AC_MSG_ERROR([ +The PACKAGE_NAME variable must be defined by your TEA configure.ac]) + fi + AC_MSG_RESULT([ok (TEA ${TEA_VERSION})]) + + # If the user did not set CFLAGS, set it now to keep macros + # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". + if test "${CFLAGS+set}" != "set" ; then + CFLAGS="" + fi + + case "`uname -s`" in + *win32*|*WIN32*|*MINGW32_*|*MINGW64_*) + AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo) + EXEEXT=".exe" + TEA_PLATFORM="windows" + ;; + *CYGWIN_*) + EXEEXT=".exe" + # CYGPATH and TEA_PLATFORM are determined later in LOAD_TCLCONFIG + ;; + *) + CYGPATH=echo + # Maybe we are cross-compiling.... + case ${host_alias} in + *mingw32*) + EXEEXT=".exe" + TEA_PLATFORM="windows" + ;; + *) + EXEEXT="" + TEA_PLATFORM="unix" + ;; + esac + ;; + esac + + # Check if exec_prefix is set. If not use fall back to prefix. + # Note when adjusted, so that TEA_PREFIX can correct for this. + # This is needed for recursive configures, since autoconf propagates + # $prefix, but not $exec_prefix (doh!). + if test x$exec_prefix = xNONE ; then + exec_prefix_default=yes + exec_prefix=$prefix + fi + + AC_MSG_NOTICE([configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}]) + + AC_SUBST(EXEEXT) + AC_SUBST(CYGPATH) + + # This package name must be replaced statically for AC_SUBST to work + AC_SUBST(PKG_LIB_FILE) + # Substitute STUB_LIB_FILE in case package creates a stub library too. + AC_SUBST(PKG_STUB_LIB_FILE) + + # We AC_SUBST these here to ensure they are subst'ed, + # in case the user doesn't call TEA_ADD_... + AC_SUBST(PKG_STUB_SOURCES) + AC_SUBST(PKG_STUB_OBJECTS) + AC_SUBST(PKG_TCL_SOURCES) + AC_SUBST(PKG_HEADERS) + AC_SUBST(PKG_INCLUDES) + AC_SUBST(PKG_LIBS) + AC_SUBST(PKG_CFLAGS) + + # Configure the installer. + TEA_INSTALLER +]) + +#------------------------------------------------------------------------ +# TEA_ADD_SOURCES -- +# +# Specify one or more source files. Users should check for +# the right platform before adding to their list. +# It is not important to specify the directory, as long as it is +# in the generic, win or unix subdirectory of $(srcdir). +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_SOURCES +# PKG_OBJECTS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_SOURCES], [ + vars="$@" + for i in $vars; do + case $i in + [\$]*) + # allow $-var names + PKG_SOURCES="$PKG_SOURCES $i" + PKG_OBJECTS="$PKG_OBJECTS $i" + ;; + *) + # check for existence - allows for generic/win/unix VPATH + # To add more dirs here (like 'src'), you have to update VPATH + # in Makefile.in as well + if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ + -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ + -a ! -f "${srcdir}/macosx/$i" \ + ; then + AC_MSG_ERROR([could not find source file '$i']) + fi + PKG_SOURCES="$PKG_SOURCES $i" + # this assumes it is in a VPATH dir + i=`basename $i` + # handle user calling this before or after TEA_SETUP_COMPILER + if test x"${OBJEXT}" != x ; then + j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" + else + j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" + fi + PKG_OBJECTS="$PKG_OBJECTS $j" + ;; + esac + done + AC_SUBST(PKG_SOURCES) + AC_SUBST(PKG_OBJECTS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_STUB_SOURCES -- +# +# Specify one or more source files. Users should check for +# the right platform before adding to their list. +# It is not important to specify the directory, as long as it is +# in the generic, win or unix subdirectory of $(srcdir). +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_STUB_SOURCES +# PKG_STUB_OBJECTS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_STUB_SOURCES], [ + vars="$@" + for i in $vars; do + # check for existence - allows for generic/win/unix VPATH + if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ + -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ + -a ! -f "${srcdir}/macosx/$i" \ + ; then + AC_MSG_ERROR([could not find stub source file '$i']) + fi + PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i" + # this assumes it is in a VPATH dir + i=`basename $i` + # handle user calling this before or after TEA_SETUP_COMPILER + if test x"${OBJEXT}" != x ; then + j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" + else + j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" + fi + PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j" + done + AC_SUBST(PKG_STUB_SOURCES) + AC_SUBST(PKG_STUB_OBJECTS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_TCL_SOURCES -- +# +# Specify one or more Tcl source files. These should be platform +# independent runtime files. +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_TCL_SOURCES +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_TCL_SOURCES], [ + vars="$@" + for i in $vars; do + # check for existence, be strict because it is installed + if test ! -f "${srcdir}/$i" ; then + AC_MSG_ERROR([could not find tcl source file '${srcdir}/$i']) + fi + PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" + done + AC_SUBST(PKG_TCL_SOURCES) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_HEADERS -- +# +# Specify one or more source headers. Users should check for +# the right platform before adding to their list. +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_HEADERS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_HEADERS], [ + vars="$@" + for i in $vars; do + # check for existence, be strict because it is installed + if test ! -f "${srcdir}/$i" ; then + AC_MSG_ERROR([could not find header file '${srcdir}/$i']) + fi + PKG_HEADERS="$PKG_HEADERS $i" + done + AC_SUBST(PKG_HEADERS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_INCLUDES -- +# +# Specify one or more include dirs. Users should check for +# the right platform before adding to their list. +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_INCLUDES +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_INCLUDES], [ + vars="$@" + for i in $vars; do + PKG_INCLUDES="$PKG_INCLUDES $i" + done + AC_SUBST(PKG_INCLUDES) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_LIBS -- +# +# Specify one or more libraries. Users should check for +# the right platform before adding to their list. For Windows, +# libraries provided in "foo.lib" format will be converted to +# "-lfoo" when using GCC (mingw). +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_LIBS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_LIBS], [ + vars="$@" + for i in $vars; do + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then + # Convert foo.lib to -lfoo for GCC. No-op if not *.lib + i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.lib[$]/-l\1/i'` + fi + PKG_LIBS="$PKG_LIBS $i" + done + AC_SUBST(PKG_LIBS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_CFLAGS -- +# +# Specify one or more CFLAGS. Users should check for +# the right platform before adding to their list. +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_CFLAGS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_CFLAGS], [ + PKG_CFLAGS="$PKG_CFLAGS $@" + AC_SUBST(PKG_CFLAGS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_CLEANFILES -- +# +# Specify one or more CLEANFILES. +# +# Arguments: +# one or more file names to clean target +# +# Results: +# +# Appends to CLEANFILES, already defined for subst in LOAD_TCLCONFIG +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_CLEANFILES], [ + CLEANFILES="$CLEANFILES $@" +]) + +#------------------------------------------------------------------------ +# TEA_PREFIX -- +# +# Handle the --prefix=... option by defaulting to what Tcl gave +# +# Arguments: +# none +# +# Results: +# +# If --prefix or --exec-prefix was not specified, $prefix and +# $exec_prefix will be set to the values given to Tcl when it was +# configured. +#------------------------------------------------------------------------ +AC_DEFUN([TEA_PREFIX], [ + if test "${prefix}" = "NONE"; then + prefix_default=yes + if test x"${TCL_PREFIX}" != x; then + AC_MSG_NOTICE([--prefix defaulting to TCL_PREFIX ${TCL_PREFIX}]) + prefix=${TCL_PREFIX} + else + AC_MSG_NOTICE([--prefix defaulting to /usr/local]) + prefix=/usr/local + fi + fi + if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ + -o x"${exec_prefix_default}" = x"yes" ; then + if test x"${TCL_EXEC_PREFIX}" != x; then + AC_MSG_NOTICE([--exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}]) + exec_prefix=${TCL_EXEC_PREFIX} + else + AC_MSG_NOTICE([--exec-prefix defaulting to ${prefix}]) + exec_prefix=$prefix + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_SETUP_COMPILER_CC -- +# +# Do compiler checks the way we want. This is just a replacement +# for AC_PROG_CC in TEA configure.ac files to make them cleaner. +# +# Arguments: +# none +# +# Results: +# +# Sets up CC var and other standard bits we need to make executables. +#------------------------------------------------------------------------ +AC_DEFUN([TEA_SETUP_COMPILER_CC], [ + # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) + # in this macro, they need to go into TEA_SETUP_COMPILER instead. + + AC_PROG_CC + AC_PROG_CPP + + #-------------------------------------------------------------------- + # Checks to see if the make program sets the $MAKE variable. + #-------------------------------------------------------------------- + + AC_PROG_MAKE_SET + + #-------------------------------------------------------------------- + # Find ranlib + #-------------------------------------------------------------------- + + AC_CHECK_TOOL(RANLIB, ranlib) + + #-------------------------------------------------------------------- + # Determines the correct binary file extension (.o, .obj, .exe etc.) + #-------------------------------------------------------------------- + + AC_OBJEXT + AC_EXEEXT +]) + +#------------------------------------------------------------------------ +# TEA_SETUP_COMPILER -- +# +# Do compiler checks that use the compiler. This must go after +# TEA_SETUP_COMPILER_CC, which does the actual compiler check. +# +# Arguments: +# none +# +# Results: +# +# Sets up CC var and other standard bits we need to make executables. +#------------------------------------------------------------------------ +AC_DEFUN([TEA_SETUP_COMPILER], [ + # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. + AC_REQUIRE([TEA_SETUP_COMPILER_CC]) + + #------------------------------------------------------------------------ + # If we're using GCC, see if the compiler understands -pipe. If so, use it. + # It makes compiling go faster. (This is only a performance feature.) + #------------------------------------------------------------------------ + + if test -z "$no_pipe" -a -n "$GCC"; then + AC_CACHE_CHECK([if the compiler understands -pipe], + tcl_cv_cc_pipe, [ + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" + AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no) + CFLAGS=$hold_cflags]) + if test $tcl_cv_cc_pipe = yes; then + CFLAGS="$CFLAGS -pipe" + fi + fi + + #-------------------------------------------------------------------- + # Common compiler flag setup + #-------------------------------------------------------------------- + + AC_C_BIGENDIAN +]) + +#------------------------------------------------------------------------ +# TEA_MAKE_LIB -- +# +# Generate a line that can be used to build a shared/unshared library +# in a platform independent manner. +# +# Arguments: +# none +# +# Requires: +# +# Results: +# +# Defines the following vars: +# CFLAGS - Done late here to note disturb other AC macros +# MAKE_LIB - Command to execute to build the Tcl library; +# differs depending on whether or not Tcl is being +# compiled as a shared library. +# MAKE_SHARED_LIB Makefile rule for building a shared library +# MAKE_STATIC_LIB Makefile rule for building a static library +# MAKE_STUB_LIB Makefile rule for building a stub library +# VC_MANIFEST_EMBED_DLL Makefile rule for embedded VC manifest in DLL +# VC_MANIFEST_EMBED_EXE Makefile rule for embedded VC manifest in EXE +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_MAKE_LIB], [ + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then + MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)" + MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS)" + AC_EGREP_CPP([manifest needed], [ +#if defined(_MSC_VER) && _MSC_VER >= 1400 +print("manifest needed") +#endif + ], [ + # Could do a CHECK_PROG for mt, but should always be with MSVC8+ + VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi" + VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi" + MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" + TEA_ADD_CLEANFILES([*.manifest]) + ]) + MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\[$]@ \$(PKG_STUB_OBJECTS)" + else + MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)" + MAKE_SHARED_LIB="\${SHLIB_LD} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" + MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)" + fi + + if test "${SHARED_BUILD}" = "1" ; then + MAKE_LIB="${MAKE_SHARED_LIB} " + else + MAKE_LIB="${MAKE_STATIC_LIB} " + fi + + #-------------------------------------------------------------------- + # Shared libraries and static libraries have different names. + # Use the double eval to make sure any variables in the suffix is + # substituted. (@@@ Might not be necessary anymore) + #-------------------------------------------------------------------- + + if test "${TEA_PLATFORM}" = "windows" ; then + if test "${SHARED_BUILD}" = "1" ; then + # We force the unresolved linking of symbols that are really in + # the private libraries of Tcl and Tk. + if test x"${TK_BIN_DIR}" != x ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" + fi + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" + if test "$GCC" = "yes"; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc" + fi + eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" + else + eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + if test "$GCC" = "yes"; then + PKG_LIB_FILE=lib${PKG_LIB_FILE} + fi + fi + # Some packages build their own stubs libraries + eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + if test "$GCC" = "yes"; then + PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} + fi + # These aren't needed on Windows (either MSVC or gcc) + RANLIB=: + RANLIB_STUB=: + else + RANLIB_STUB="${RANLIB}" + if test "${SHARED_BUILD}" = "1" ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" + if test x"${TK_BIN_DIR}" != x ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" + fi + eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" + RANLIB=: + else + eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + fi + # Some packages build their own stubs libraries + eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + fi + + # These are escaped so that only CFLAGS is picked up at configure time. + # The other values will be substituted at make time. + CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" + if test "${SHARED_BUILD}" = "1" ; then + CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" + fi + + AC_SUBST(MAKE_LIB) + AC_SUBST(MAKE_SHARED_LIB) + AC_SUBST(MAKE_STATIC_LIB) + AC_SUBST(MAKE_STUB_LIB) + AC_SUBST(RANLIB_STUB) + AC_SUBST(VC_MANIFEST_EMBED_DLL) + AC_SUBST(VC_MANIFEST_EMBED_EXE) +]) + +#------------------------------------------------------------------------ +# TEA_LIB_SPEC -- +# +# Compute the name of an existing object library located in libdir +# from the given base name and produce the appropriate linker flags. +# +# Arguments: +# basename The base name of the library without version +# numbers, extensions, or "lib" prefixes. +# extra_dir Extra directory in which to search for the +# library. This location is used first, then +# $prefix/$exec-prefix, then some defaults. +# +# Requires: +# TEA_INIT and TEA_PREFIX must be called first. +# +# Results: +# +# Defines the following vars: +# ${basename}_LIB_NAME The computed library name. +# ${basename}_LIB_SPEC The computed linker flags. +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_LIB_SPEC], [ + AC_MSG_CHECKING([for $1 library]) + + # Look in exec-prefix for the library (defined by TEA_PREFIX). + + tea_lib_name_dir="${exec_prefix}/lib" + + # Or in a user-specified location. + + if test x"$2" != x ; then + tea_extra_lib_dir=$2 + else + tea_extra_lib_dir=NONE + fi + + for i in \ + `ls -dr ${tea_extra_lib_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr ${tea_extra_lib_dir}/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr ${tea_lib_name_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr ${tea_lib_name_dir}/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr /usr/lib/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr /usr/lib/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr /usr/lib64/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr /usr/lib64/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr /usr/local/lib/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr /usr/local/lib/lib$1[[0-9]]* 2>/dev/null ` ; do + if test -f "$i" ; then + tea_lib_name_dir=`dirname $i` + $1_LIB_NAME=`basename $i` + $1_LIB_PATH_NAME=$i + break + fi + done + + if test "${TEA_PLATFORM}" = "windows"; then + $1_LIB_SPEC=\"`${CYGPATH} ${$1_LIB_PATH_NAME} 2>/dev/null`\" + else + # Strip off the leading "lib" and trailing ".a" or ".so" + + tea_lib_name_lib=`echo ${$1_LIB_NAME}|sed -e 's/^lib//' -e 's/\.[[^.]]*$//' -e 's/\.so.*//'` + $1_LIB_SPEC="-L${tea_lib_name_dir} -l${tea_lib_name_lib}" + fi + + if test "x${$1_LIB_NAME}" = x ; then + AC_MSG_ERROR([not found]) + else + AC_MSG_RESULT([${$1_LIB_SPEC}]) + fi +]) + +#------------------------------------------------------------------------ +# TEA_PRIVATE_TCL_HEADERS -- +# +# Locate the private Tcl include files +# +# Arguments: +# +# Requires: +# TCL_SRC_DIR Assumes that TEA_LOAD_TCLCONFIG has +# already been called. +# +# Results: +# +# Substitutes the following vars: +# TCL_TOP_DIR_NATIVE +# TCL_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PRIVATE_TCL_HEADERS], [ + # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh} + AC_REQUIRE([TEA_PUBLIC_TCL_HEADERS]) + AC_MSG_CHECKING([for Tcl private include files]) + + TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}` + TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\" + + # Check to see if tcl<Plat>Port.h isn't already with the public headers + # Don't look for tclInt.h because that resides with tcl.h in the core + # sources, but the <plat>Port headers are in a different directory + if test "${TEA_PLATFORM}" = "windows" -a \ + -f "${ac_cv_c_tclh}/tclWinPort.h"; then + result="private headers found with public headers" + elif test "${TEA_PLATFORM}" = "unix" -a \ + -f "${ac_cv_c_tclh}/tclUnixPort.h"; then + result="private headers found with public headers" + else + TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\" + if test "${TEA_PLATFORM}" = "windows"; then + TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\" + else + TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\" + fi + # Overwrite the previous TCL_INCLUDES as this should capture both + # public and private headers in the same set. + # We want to ensure these are substituted so as not to require + # any *_NATIVE vars be defined in the Makefile + TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}" + if test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use + # the framework's Headers and PrivateHeaders directories + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + if test -d "${TCL_BIN_DIR}/Headers" -a \ + -d "${TCL_BIN_DIR}/PrivateHeaders"; then + TCL_INCLUDES="-I\"${TCL_BIN_DIR}/Headers\" -I\"${TCL_BIN_DIR}/PrivateHeaders\" ${TCL_INCLUDES}" + else + TCL_INCLUDES="${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo "${TCL_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" + fi + ;; + esac + result="Using ${TCL_INCLUDES}" + else + if test ! -f "${TCL_SRC_DIR}/generic/tclInt.h" ; then + AC_MSG_ERROR([Cannot find private header tclInt.h in ${TCL_SRC_DIR}]) + fi + result="Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}" + fi + fi + + AC_SUBST(TCL_TOP_DIR_NATIVE) + + AC_SUBST(TCL_INCLUDES) + AC_MSG_RESULT([${result}]) +]) + +#------------------------------------------------------------------------ +# TEA_PUBLIC_TCL_HEADERS -- +# +# Locate the installed public Tcl header files +# +# Arguments: +# None. +# +# Requires: +# CYGPATH must be set +# +# Results: +# +# Adds a --with-tclinclude switch to configure. +# Result is cached. +# +# Substitutes the following vars: +# TCL_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PUBLIC_TCL_HEADERS], [ + AC_MSG_CHECKING([for Tcl public headers]) + + AC_ARG_WITH(tclinclude, [ --with-tclinclude directory containing the public Tcl header files], with_tclinclude=${withval}) + + AC_CACHE_VAL(ac_cv_c_tclh, [ + # Use the value from --with-tclinclude, if it was given + + if test x"${with_tclinclude}" != x ; then + if test -f "${with_tclinclude}/tcl.h" ; then + ac_cv_c_tclh=${with_tclinclude} + else + AC_MSG_ERROR([${with_tclinclude} directory does not contain tcl.h]) + fi + else + list="" + if test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use + # the framework's Headers directory + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" + ;; + esac + fi + + # Look in the source dir only if Tcl is not installed, + # and in that situation, look there before installed locations. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" + fi + + # Check order: pkg --prefix location, Tcl's --prefix location, + # relative to directory of tclConfig.sh. + + eval "temp_includedir=${includedir}" + list="$list \ + `ls -d ${temp_includedir} 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" + if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then + list="$list /usr/local/include /usr/include" + if test x"${TCL_INCLUDE_SPEC}" != x ; then + d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` + list="$list `ls -d ${d} 2>/dev/null`" + fi + fi + for i in $list ; do + if test -f "$i/tcl.h" ; then + ac_cv_c_tclh=$i + break + fi + done + fi + ]) + + # Print a message based on how we determined the include path + + if test x"${ac_cv_c_tclh}" = x ; then + AC_MSG_ERROR([tcl.h not found. Please specify its location with --with-tclinclude]) + else + AC_MSG_RESULT([${ac_cv_c_tclh}]) + fi + + # Convert to a native path and substitute into the output files. + + INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` + + TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + AC_SUBST(TCL_INCLUDES) +]) + +#------------------------------------------------------------------------ +# TEA_PRIVATE_TK_HEADERS -- +# +# Locate the private Tk include files +# +# Arguments: +# +# Requires: +# TK_SRC_DIR Assumes that TEA_LOAD_TKCONFIG has +# already been called. +# +# Results: +# +# Substitutes the following vars: +# TK_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PRIVATE_TK_HEADERS], [ + # Allow for --with-tkinclude to take effect and define ${ac_cv_c_tkh} + AC_REQUIRE([TEA_PUBLIC_TK_HEADERS]) + AC_MSG_CHECKING([for Tk private include files]) + + TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}` + TK_TOP_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}\" + + # Check to see if tk<Plat>Port.h isn't already with the public headers + # Don't look for tkInt.h because that resides with tk.h in the core + # sources, but the <plat>Port headers are in a different directory + if test "${TEA_PLATFORM}" = "windows" -a \ + -f "${ac_cv_c_tkh}/tkWinPort.h"; then + result="private headers found with public headers" + elif test "${TEA_PLATFORM}" = "unix" -a \ + -f "${ac_cv_c_tkh}/tkUnixPort.h"; then + result="private headers found with public headers" + else + TK_GENERIC_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/generic\" + TK_XLIB_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/xlib\" + if test "${TEA_PLATFORM}" = "windows"; then + TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\" + else + TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\" + fi + # Overwrite the previous TK_INCLUDES as this should capture both + # public and private headers in the same set. + # We want to ensure these are substituted so as not to require + # any *_NATIVE vars be defined in the Makefile + TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}" + # Detect and add ttk subdir + if test -d "${TK_SRC_DIR}/generic/ttk"; then + TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/generic/ttk\"" + fi + if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then + TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\"" + fi + if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then + TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/macosx\"" + fi + if test "`uname -s`" = "Darwin"; then + # If Tk was built as a framework, attempt to use + # the framework's Headers and PrivateHeaders directories + case ${TK_DEFS} in + *TK_FRAMEWORK*) + if test -d "${TK_BIN_DIR}/Headers" -a \ + -d "${TK_BIN_DIR}/PrivateHeaders"; then + TK_INCLUDES="-I\"${TK_BIN_DIR}/Headers\" -I\"${TK_BIN_DIR}/PrivateHeaders\" ${TK_INCLUDES}" + else + TK_INCLUDES="${TK_INCLUDES} ${TK_INCLUDE_SPEC} `echo "${TK_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" + fi + ;; + esac + result="Using ${TK_INCLUDES}" + else + if test ! -f "${TK_SRC_DIR}/generic/tkInt.h" ; then + AC_MSG_ERROR([Cannot find private header tkInt.h in ${TK_SRC_DIR}]) + fi + result="Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}" + fi + fi + + AC_SUBST(TK_TOP_DIR_NATIVE) + AC_SUBST(TK_XLIB_DIR_NATIVE) + + AC_SUBST(TK_INCLUDES) + AC_MSG_RESULT([${result}]) +]) + +#------------------------------------------------------------------------ +# TEA_PUBLIC_TK_HEADERS -- +# +# Locate the installed public Tk header files +# +# Arguments: +# None. +# +# Requires: +# CYGPATH must be set +# +# Results: +# +# Adds a --with-tkinclude switch to configure. +# Result is cached. +# +# Substitutes the following vars: +# TK_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PUBLIC_TK_HEADERS], [ + AC_MSG_CHECKING([for Tk public headers]) + + AC_ARG_WITH(tkinclude, [ --with-tkinclude directory containing the public Tk header files], with_tkinclude=${withval}) + + AC_CACHE_VAL(ac_cv_c_tkh, [ + # Use the value from --with-tkinclude, if it was given + + if test x"${with_tkinclude}" != x ; then + if test -f "${with_tkinclude}/tk.h" ; then + ac_cv_c_tkh=${with_tkinclude} + else + AC_MSG_ERROR([${with_tkinclude} directory does not contain tk.h]) + fi + else + list="" + if test "`uname -s`" = "Darwin"; then + # If Tk was built as a framework, attempt to use + # the framework's Headers directory. + case ${TK_DEFS} in + *TK_FRAMEWORK*) + list="`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`" + ;; + esac + fi + + # Look in the source dir only if Tk is not installed, + # and in that situation, look there before installed locations. + if test -f "${TK_BIN_DIR}/Makefile" ; then + list="$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`" + fi + + # Check order: pkg --prefix location, Tk's --prefix location, + # relative to directory of tkConfig.sh, Tcl's --prefix location, + # relative to directory of tclConfig.sh. + + eval "temp_includedir=${includedir}" + list="$list \ + `ls -d ${temp_includedir} 2>/dev/null` \ + `ls -d ${TK_PREFIX}/include 2>/dev/null` \ + `ls -d ${TK_BIN_DIR}/../include 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" + if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then + list="$list /usr/local/include /usr/include" + if test x"${TK_INCLUDE_SPEC}" != x ; then + d=`echo "${TK_INCLUDE_SPEC}" | sed -e 's/^-I//'` + list="$list `ls -d ${d} 2>/dev/null`" + fi + fi + for i in $list ; do + if test -f "$i/tk.h" ; then + ac_cv_c_tkh=$i + break + fi + done + fi + ]) + + # Print a message based on how we determined the include path + + if test x"${ac_cv_c_tkh}" = x ; then + AC_MSG_ERROR([tk.h not found. Please specify its location with --with-tkinclude]) + else + AC_MSG_RESULT([${ac_cv_c_tkh}]) + fi + + # Convert to a native path and substitute into the output files. + + INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}` + + TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + AC_SUBST(TK_INCLUDES) + + if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then + # On Windows and Aqua, we need the X compat headers + AC_MSG_CHECKING([for X11 header files]) + if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then + INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`" + TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + AC_SUBST(TK_XINCLUDES) + fi + AC_MSG_RESULT([${INCLUDE_DIR_NATIVE}]) + fi +]) + +#------------------------------------------------------------------------ +# TEA_PATH_CONFIG -- +# +# Locate the ${1}Config.sh file and perform a sanity check on +# the ${1} compile flags. These are used by packages like +# [incr Tk] that load *Config.sh files from more than Tcl and Tk. +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-$1=... +# +# Defines the following vars: +# $1_BIN_DIR Full path to the directory containing +# the $1Config.sh file +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PATH_CONFIG], [ + # + # Ok, lets find the $1 configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-$1 + # + + if test x"${no_$1}" = x ; then + # we reset no_$1 in case something fails here + no_$1=true + AC_ARG_WITH($1, [ --with-$1 directory containing $1 configuration ($1Config.sh)], with_$1config=${withval}) + AC_MSG_CHECKING([for $1 configuration]) + AC_CACHE_VAL(ac_cv_c_$1config,[ + + # First check to see if --with-$1 was specified. + if test x"${with_$1config}" != x ; then + case ${with_$1config} in + */$1Config.sh ) + if test -f ${with_$1config}; then + AC_MSG_WARN([--with-$1 argument should refer to directory containing $1Config.sh, not to $1Config.sh itself]) + with_$1config=`echo ${with_$1config} | sed 's!/$1Config\.sh$!!'` + fi;; + esac + if test -f "${with_$1config}/$1Config.sh" ; then + ac_cv_c_$1config=`(cd ${with_$1config}; pwd)` + else + AC_MSG_ERROR([${with_$1config} directory doesn't contain $1Config.sh]) + fi + fi + + # then check for a private $1 installation + if test x"${ac_cv_c_$1config}" = x ; then + for i in \ + ../$1 \ + `ls -dr ../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ + `ls -dr ../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ + `ls -dr ../$1*[[0-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ + ../../$1 \ + `ls -dr ../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ + `ls -dr ../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ + `ls -dr ../../$1*[[0-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ + ../../../$1 \ + `ls -dr ../../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ + `ls -dr ../../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ + `ls -dr ../../../$1*[[0-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ + ${srcdir}/../$1 \ + `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ + `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ + ; do + if test -f "$i/$1Config.sh" ; then + ac_cv_c_$1config=`(cd $i; pwd)` + break + fi + if test -f "$i/unix/$1Config.sh" ; then + ac_cv_c_$1config=`(cd $i/unix; pwd)` + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_$1config}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/pkg/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + ; do + if test -f "$i/$1Config.sh" ; then + ac_cv_c_$1config=`(cd $i; pwd)` + break + fi + done + fi + ]) + + if test x"${ac_cv_c_$1config}" = x ; then + $1_BIN_DIR="# no $1 configs found" + AC_MSG_WARN([Cannot find $1 configuration definitions]) + exit 0 + else + no_$1= + $1_BIN_DIR=${ac_cv_c_$1config} + AC_MSG_RESULT([found $$1_BIN_DIR/$1Config.sh]) + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_LOAD_CONFIG -- +# +# Load the $1Config.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# $1_BIN_DIR +# +# Results: +# +# Substitutes the following vars: +# $1_SRC_DIR +# $1_LIB_FILE +# $1_LIB_SPEC +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_LOAD_CONFIG], [ + AC_MSG_CHECKING([for existence of ${$1_BIN_DIR}/$1Config.sh]) + + if test -f "${$1_BIN_DIR}/$1Config.sh" ; then + AC_MSG_RESULT([loading]) + . "${$1_BIN_DIR}/$1Config.sh" + else + AC_MSG_RESULT([file not found]) + fi + + # + # If the $1_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable $1_LIB_SPEC will be set to the value + # of $1_BUILD_LIB_SPEC. An extension should make use of $1_LIB_SPEC + # instead of $1_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + # + + if test -f "${$1_BIN_DIR}/Makefile" ; then + AC_MSG_WARN([Found Makefile - using build library specs for $1]) + $1_LIB_SPEC=${$1_BUILD_LIB_SPEC} + $1_STUB_LIB_SPEC=${$1_BUILD_STUB_LIB_SPEC} + $1_STUB_LIB_PATH=${$1_BUILD_STUB_LIB_PATH} + $1_INCLUDE_SPEC=${$1_BUILD_INCLUDE_SPEC} + $1_LIBRARY_PATH=${$1_LIBRARY_PATH} + fi + + AC_SUBST($1_VERSION) + AC_SUBST($1_BIN_DIR) + AC_SUBST($1_SRC_DIR) + + AC_SUBST($1_LIB_FILE) + AC_SUBST($1_LIB_SPEC) + + AC_SUBST($1_STUB_LIB_FILE) + AC_SUBST($1_STUB_LIB_SPEC) + AC_SUBST($1_STUB_LIB_PATH) + + # Allow the caller to prevent this auto-check by specifying any 2nd arg + AS_IF([test "x$2" = x], [ + # Check both upper and lower-case variants + # If a dev wanted non-stubs libs, this function could take an option + # to not use _STUB in the paths below + AS_IF([test "x${$1_STUB_LIB_SPEC}" = x], + [TEA_LOAD_CONFIG_LIB(translit($1,[a-z],[A-Z])_STUB)], + [TEA_LOAD_CONFIG_LIB($1_STUB)]) + ]) +]) + +#------------------------------------------------------------------------ +# TEA_LOAD_CONFIG_LIB -- +# +# Helper function to load correct library from another extension's +# ${PACKAGE}Config.sh. +# +# Results: +# Adds to LIBS the appropriate extension library +#------------------------------------------------------------------------ +AC_DEFUN([TEA_LOAD_CONFIG_LIB], [ + AC_MSG_CHECKING([For $1 library for LIBS]) + # This simplifies the use of stub libraries by automatically adding + # the stub lib to your path. Normally this would add to SHLIB_LD_LIBS, + # but this is called before CONFIG_CFLAGS. More importantly, this adds + # to PKG_LIBS, which becomes LIBS, and that is only used by SHLIB_LD. + if test "x${$1_LIB_SPEC}" != "x" ; then + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes" ; then + TEA_ADD_LIBS([\"`${CYGPATH} ${$1_LIB_PATH}`\"]) + AC_MSG_RESULT([using $1_LIB_PATH ${$1_LIB_PATH}]) + else + TEA_ADD_LIBS([${$1_LIB_SPEC}]) + AC_MSG_RESULT([using $1_LIB_SPEC ${$1_LIB_SPEC}]) + fi + else + AC_MSG_RESULT([file not found]) + fi +]) + +#------------------------------------------------------------------------ +# TEA_EXPORT_CONFIG -- +# +# Define the data to insert into the ${PACKAGE}Config.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# $1 +# +# Results: +# Substitutes the following vars: +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_EXPORT_CONFIG], [ + #-------------------------------------------------------------------- + # These are for $1Config.sh + #-------------------------------------------------------------------- + + # pkglibdir must be a fully qualified path and (not ${exec_prefix}/lib) + eval pkglibdir="[$]{libdir}/$1${PACKAGE_VERSION}" + if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then + eval $1_LIB_FLAG="-l$1${PACKAGE_VERSION}${DBGX}" + eval $1_STUB_LIB_FLAG="-l$1stub${PACKAGE_VERSION}${DBGX}" + else + eval $1_LIB_FLAG="-l$1`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}" + eval $1_STUB_LIB_FLAG="-l$1stub`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}" + fi + $1_BUILD_LIB_SPEC="-L`$CYGPATH $(pwd)` ${$1_LIB_FLAG}" + $1_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` ${$1_LIB_FLAG}" + $1_BUILD_STUB_LIB_SPEC="-L`$CYGPATH $(pwd)` [$]{$1_STUB_LIB_FLAG}" + $1_STUB_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` [$]{$1_STUB_LIB_FLAG}" + $1_BUILD_STUB_LIB_PATH="`$CYGPATH $(pwd)`/[$]{PKG_STUB_LIB_FILE}" + $1_STUB_LIB_PATH="`$CYGPATH ${pkglibdir}`/[$]{PKG_STUB_LIB_FILE}" + + AC_SUBST($1_BUILD_LIB_SPEC) + AC_SUBST($1_LIB_SPEC) + AC_SUBST($1_BUILD_STUB_LIB_SPEC) + AC_SUBST($1_STUB_LIB_SPEC) + AC_SUBST($1_BUILD_STUB_LIB_PATH) + AC_SUBST($1_STUB_LIB_PATH) + + AC_SUBST(MAJOR_VERSION) + AC_SUBST(MINOR_VERSION) + AC_SUBST(PATCHLEVEL) +]) + + +#------------------------------------------------------------------------ +# TEA_PATH_CELIB -- +# +# Locate Keuchel's celib emulation layer for targeting Win/CE +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-celib=... +# +# Defines the following vars: +# CELIB_DIR Full path to the directory containing +# the include and platform lib files +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PATH_CELIB], [ + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-celib + + if test x"${no_celib}" = x ; then + # we reset no_celib in case something fails here + no_celib=true + AC_ARG_WITH(celib,[ --with-celib=DIR use Windows/CE support library from DIR], with_celibconfig=${withval}) + AC_MSG_CHECKING([for Windows/CE celib directory]) + AC_CACHE_VAL(ac_cv_c_celibconfig,[ + # First check to see if --with-celibconfig was specified. + if test x"${with_celibconfig}" != x ; then + if test -d "${with_celibconfig}/inc" ; then + ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)` + else + AC_MSG_ERROR([${with_celibconfig} directory doesn't contain inc directory]) + fi + fi + + # then check for a celib library + if test x"${ac_cv_c_celibconfig}" = x ; then + for i in \ + ../celib-palm-3.0 \ + ../celib \ + ../../celib-palm-3.0 \ + ../../celib \ + `ls -dr ../celib-*3.[[0-9]]* 2>/dev/null` \ + ${srcdir}/../celib-palm-3.0 \ + ${srcdir}/../celib \ + `ls -dr ${srcdir}/../celib-*3.[[0-9]]* 2>/dev/null` \ + ; do + if test -d "$i/inc" ; then + ac_cv_c_celibconfig=`(cd $i; pwd)` + break + fi + done + fi + ]) + if test x"${ac_cv_c_celibconfig}" = x ; then + AC_MSG_ERROR([Cannot find celib support library directory]) + else + no_celib= + CELIB_DIR=${ac_cv_c_celibconfig} + CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'` + AC_MSG_RESULT([found $CELIB_DIR]) + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_INSTALLER -- +# +# Configure the installer. +# +# Arguments: +# none +# +# Results: +# Substitutes the following vars: +# INSTALL +# INSTALL_DATA_DIR +# INSTALL_DATA +# INSTALL_PROGRAM +# INSTALL_SCRIPT +# INSTALL_LIBRARY +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_INSTALLER], [ + INSTALL='$(SHELL) $(srcdir)/tclconfig/install-sh -c' + INSTALL_DATA_DIR='${INSTALL} -d -m 755' + INSTALL_DATA='${INSTALL} -m 644' + INSTALL_PROGRAM='${INSTALL} -m 755' + INSTALL_SCRIPT='${INSTALL} -m 755' + + TEA_CONFIG_SYSTEM + case $system in + HP-UX-*) INSTALL_LIBRARY='${INSTALL} -m 755' ;; + *) INSTALL_LIBRARY='${INSTALL} -m 644' ;; + esac + + AC_SUBST(INSTALL) + AC_SUBST(INSTALL_DATA_DIR) + AC_SUBST(INSTALL_DATA) + AC_SUBST(INSTALL_PROGRAM) + AC_SUBST(INSTALL_SCRIPT) + AC_SUBST(INSTALL_LIBRARY) +]) + +### +# Tip 430 - ZipFS Modifications +### +#------------------------------------------------------------------------ +# SC_ZIPFS_SUPPORT +# Locate a zip encoder installed on the system path, or none. +# +# Arguments: +# none +# +# Results: +# Substitutes the following vars: +# TCL_ZIP_FILE +# TCL_ZIPFS_SUPPORT +# TCL_ZIPFS_FLAG +# ZIP_PROG +#------------------------------------------------------------------------ + +#------------------------------------------------------------------------ +# SC_PROG_ZIP +# Locate a zip encoder installed on the system path, or none. +# +# Arguments: +# none +# +# Results: +# Substitutes the following vars: +# ZIP_PROG +# ZIP_PROG_OPTIONS +# ZIP_PROG_VFSSEARCH +# ZIP_INSTALL_OBJS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ZIPFS_SUPPORT], [ + AC_MSG_CHECKING([for zipfs support]) + ZIP_PROG="" + ZIP_PROG_OPTIONS="" + ZIP_PROG_VFSSEARCH="" + INSTALL_MSGS="" + # If our native tclsh processes the "install" command line option + # we can use it to mint zip files + AS_IF([$TCLSH_PROG install],[ + ZIP_PROG=${TCLSH_PROG} + ZIP_PROG_OPTIONS="install mkzip" + ZIP_PROG_VFSSEARCH="." + AC_MSG_RESULT([Can use Native Tclsh for Zip encoding]) + ]) + if test "x$ZIP_PROG" = "x" ; then + AC_CACHE_VAL(ac_cv_path_zip, [ + search_path=`echo ${PATH} | sed -e 's/:/ /g'` + for dir in $search_path ; do + for j in `ls -r $dir/zip 2> /dev/null` \ + `ls -r $dir/zip 2> /dev/null` ; do + if test x"$ac_cv_path_zip" = x ; then + if test -f "$j" ; then + ac_cv_path_zip=$j + break + fi + fi + done + done + ]) + if test -f "$ac_cv_path_zip" ; then + ZIP_PROG="$ac_cv_path_zip " + AC_MSG_RESULT([$ZIP_PROG]) + ZIP_PROG_OPTIONS="-rq" + ZIP_PROG_VFSSEARCH="." + AC_MSG_RESULT([Found INFO Zip in environment]) + # Use standard arguments for zip + fi + fi + if test "x$ZIP_PROG" = "x" ; then + # It is not an error if an installed version of Zip can't be located. + ZIP_PROG="" + ZIP_PROG_OPTIONS="" + ZIP_PROG_VFSSEARCH="" + TCL_ZIPFS_SUPPORT=0 + TCL_ZIPFS_FLAG= + else + # ZIPFS Support + eval "TCL_ZIP_FILE=\"${TCL_ZIP_FILE}\"" + if test ${TCL_ZIP_FILE} = "" ; then + TCL_ZIPFS_SUPPORT=0 + TCL_ZIPFS_FLAG= + INSTALL_LIBRARIES=install-libraries + INSTALL_MSGS=install-msgs + else + if test ${SHARED_BUILD} = 1 ; then + TCL_ZIPFS_SUPPORT=1 + INSTALL_LIBRARIES=install-libraries-zipfs-shared + else + TCL_ZIPFS_SUPPORT=2 + INSTALL_LIBRARIES=install-libraries-zipfs-static + fi + TCL_ZIPFS_FLAG=-DTCL_ZIPFS_SUPPORT + fi + fi + + AC_SUBST(TCL_ZIP_FILE) + AC_SUBST(TCL_ZIPFS_SUPPORT) + AC_SUBST(TCL_ZIPFS_FLAG) + AC_SUBST(ZIP_PROG) + AC_SUBST(ZIP_PROG_OPTIONS) + AC_SUBST(ZIP_PROG_VFSSEARCH) + AC_SUBST(INSTALL_LIBRARIES) + AC_SUBST(INSTALL_MSGS) +]) + +# Local Variables: +# mode: autoconf +# End: diff --git a/tktable/tests/all.tcl b/tktable/tests/all.tcl new file mode 100644 index 0000000..b5d8544 --- /dev/null +++ b/tktable/tests/all.tcl @@ -0,0 +1,58 @@ +# all.tcl -- +# +# This file contains a top-level script to run all of the Tk table +# tests. Execute it by invoking "source all.tcl" when running tktest +# in this directory. +# +# Copyright (c) 1998-2000 Ajuba Solutions +# Copyright (c) 2000-2002 Jeffrey Hobbs +# +# See the file "license.txt" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: all.tcl,v 1.1.1.1 2011/03/01 20:00:38 joye Exp $ + +package require tcltest +namespace import -force ::tcltest::* + +set ::tcltest::testSingleFile false +set ::tcltest::testsDirectory [file dir [info script]] + +# We need to ensure that the testsDirectory is absolute +catch {::tcltest::normalizePath ::tcltest::testsDirectory} + +set chan $::tcltest::outputChannel + +puts $chan "Tk $tk_patchLevel tests running in interp: [info nameofexecutable]" +puts $chan "Tests running with pwd: [pwd]" +puts $chan "Tests running in working dir: $::tcltest::testsDirectory" +if {[llength $::tcltest::skip] > 0} { + puts $chan "Skipping tests that match: $::tcltest::skip" +} +if {[llength $::tcltest::match] > 0} { + puts $chan "Only running tests that match: $::tcltest::match" +} + +if {[llength $::tcltest::skipFiles] > 0} { + puts $chan "Skipping test files that match: $::tcltest::skipFiles" +} +if {[llength $::tcltest::matchFiles] > 0} { + puts $chan "Only sourcing test files that match: $::tcltest::matchFiles" +} + +set timeCmd {clock format [clock seconds]} +puts $chan "Tests began at [eval $timeCmd]" + +# source each of the specified tests +foreach file [lsort [::tcltest::getMatchingFiles]] { + set tail [file tail $file] + puts $chan $tail + if {[catch {source $file} msg]} { + puts $chan $msg + } +} + +# cleanup +puts $chan "\nTests ended at [eval $timeCmd]" +::tcltest::cleanupTests 1 +exit diff --git a/tktable/tests/tkTable.test b/tktable/tests/tkTable.test new file mode 100644 index 0000000..a4513c5 --- /dev/null +++ b/tktable/tests/tkTable.test @@ -0,0 +1,869 @@ +# This file is a Tcl script to test out the "table" command. +# It is organized in the standard fashion for Tcl tests. +# +# Copyright (c) 2000-2001 Jeffrey Hobbs +# +# See the file "license.txt" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: tkTable.test,v 1.1.1.1 2011/03/01 20:00:38 joye Exp $ + +# deletes: +# test 2 -5 +# test 4 -2 +# test 0 -1 (== 0 1) + +package require tcltest +namespace import -force ::tcltest::* + +set ::VERSION 2.10 +package require Tktable $::VERSION + +eval destroy [winfo children .] +wm geometry . {} +raise . +set fixed {Courier -12} + +proc getsize w { + regexp {(^[^+-]*)} [wm geometry $w] foo x + return $x +} + +# Procedure that creates a second table for checking things related +# to partially visible lines. + +proc mkPartial {{w .partial}} { + catch {destroy $w} + toplevel $w + wm geometry $w +0+0 + table $w.l -width 30 -height 5 + pack $w.l -expand 1 -fill both + $w.l insert end one two three four five six seven eight nine ten \ + eleven twelve thirteen fourteen fifteen + update + scan [wm geometry $w] "%dx%d" width height + wm geometry $w ${width}x[expr $height-3] + update +} + +proc Some args { # do nothing command } +proc Another args { # do nothing command } + + +# Create entries in the option database to be sure that geometry options +# like border width have predictable values. + +option add *Table.borderWidth 1 +option add *Table.highlightThickness 2 +option add *Table.font {Helvetica -12} + +pack [table .t] +update +set i 1 + +foreach test { + {-anchor n n left {bad anchor position "left": must be n, ne, e, se, s, sw, w, nw, or center}} + {-autoclear yes 1 xyzzy {expected boolean value but got "xyzzy"}} + {-background #ff0000 #ff0000 non-existent + {unknown color name "non-existent"}} + {-bd "4 2" "4 2" badValue {bad screen distance "badValue"}} + {-bg #ff0000 #ff0000 non-existent {unknown color name "non-existent"}} + {-bordercursor arrow arrow badValue {bad cursor spec "badValue"}} + {-borderwidth 1 1 badValue {bad screen distance "badValue"}} + {-browsecommand {Some command} {Some command} {} {}} + {-browsecmd {Some command} {Some command} {} {}} + {-cache yes 1 xyzzy {expected boolean value but got "xyzzy"}} + {-colorigin 1 1 xyzzy {expected integer but got "xyzzy"}} + {-cols 12 12 xyzzy {expected integer but got "xyzzy"}} + {-colseparator , , {} {}} + {-colstretchmode unset unset bogus {bad option "bogus" must be none, unset, all, last, fill}} + {-coltagcommand {Some command} {Some command} {} {}} + {-colwidth 5 5 xyzzy {expected integer but got "xyzzy"}} + {-command {Some command} {Some command} {} {}} + {-cursor arrow arrow badValue {bad cursor spec "badValue"}} + {-drawmode slow slow badValue {bad option "badValue" must be fast, compatible, slow, single}} + {-ellipsis {...} {...} {} {}} + {-exportselection yes 1 xyzzy {expected boolean value but got "xyzzy"}} + {-fg #110022 #110022 bogus {unknown color name "bogus"}} + {-flashmode yes 1 xyzzy {expected boolean value but got "xyzzy"}} + {-flashtime 3 3 xyzzy {expected integer but got "xyzzy"}} + {-font {Helvetica 12} {Helvetica 12} {} {font "" doesn't exist}} + {-foreground #110022 #110022 bogus {unknown color name "bogus"}} + {-height 30 30 20p {expected integer but got "20p"}} + {-highlightbackground #112233 #112233 ugly {unknown color name "ugly"}} + {-highlightcolor #123456 #123456 bogus {unknown color name "bogus"}} + {-highlightthickness 6 6 bogus {bad screen distance "bogus"}} + {-highlightthickness -2 0 {} {}} + {-insertbackground #110022 #110022 bogus {unknown color name "bogus"}} + {-insertborderwidth 1.3 1 2.6x {bad screen distance "2.6x"}} + {-insertofftime 100 100 3.2 {expected integer but got "3.2"}} + {-insertontime 100 100 3.2 {expected integer but got "3.2"}} + {-insertwidth 1.3 1 2.6x {bad screen distance "2.6x"}} + {-invertselected yes 1 xyzzy {expected boolean value but got "xyzzy"}} + {-ipadx 1.3 1 2.6x {bad screen distance "2.6x"}} + {-ipady 1.3 1 2.6x {bad screen distance "2.6x"}} + {-justify left left wrong {bad justification "wrong": must be left, right, or center}} + {-maxheight 300 300 2.6x {bad screen distance "2.6x"}} + {-maxwidth 300 300 2.6x {bad screen distance "2.6x"}} + {-multiline yes 1 xyzzy {expected boolean value but got "xyzzy"}} + {-padx 1.3 1 2.6x {bad screen distance "2.6x"}} + {-pady 1.3 1 2.6x {bad screen distance "2.6x"}} + {-relief groove groove 1.5 {bad relief type "1.5": must be flat, groove, raised, ridge, solid, or sunken}} + {-rowheight -20 -20 xyzzy {expected integer but got "xyzzy"}} + {-roworigin -20 -20 xyzzy {expected integer but got "xyzzy"}} + {-rows 20 20 xyzzy {expected integer but got "xyzzy"}} + {-rowseparator , , {} {}} + {-rowstretchmode unset unset bogus {bad option "bogus" must be none, unset, all, last, fill}} + {-rowtagcommand {Some command} {Some command} {} {}} + {-selcmd {Some command} {Some command} {} {}} + {-selectioncommand {Some command} {Some command} {} {}} + {-selectmode extended extended {} {}} + {-selecttitles yes 1 xyzzy {expected boolean value but got "xyzzy"}} + {-selecttype row row bogus {bad option "bogus" must be row, col, both, cell}} + {-sparsearray yes 1 xyzzy {expected boolean value but got "xyzzy"}} + {-state disabled disabled foo {bad option "foo" must be normal, disabled}} + {-takefocus "any string" "any string" {} {}} + {-titlecols 4 4 3p {expected integer but got "3p"}} + {-titlerows 4 4 3p {expected integer but got "3p"}} + {-usecommand yes 1 xyzzy {expected boolean value but got "xyzzy"}} + {-variable var var {} {}} + {-validate yes 1 xyzzy {expected boolean value but got "xyzzy"}} + {-validatecommand {Some command} {Some command} {} {}} + {-vcmd {Some command} {Some command} {} {}} + {-width 45 45 3p {expected integer but got "3p"}} + {-wrap yes 1 xyzzy {expected boolean value but got "xyzzy"}} + {-xscrollcommand {Some command} {Some command} {} {}} + {-yscrollcommand {Another command} {Another command} {} {}} +} { + set name [lindex $test 0] + test table-1.$i "configuration options, $name" { + .t configure $name [lindex $test 1] + list [lindex [.t configure $name] 4] [.t cget $name] + } [list [lindex $test 2] [lindex $test 2]] + incr i + if {[lindex $test 3] != ""} { + test table-1.$i "configuration options, $name" { + list [catch {.t configure $name [lindex $test 3]} msg] $msg + } [list 1 [lindex $test 4]] + } + .t configure $name [lindex [.t configure $name] 3] + incr i +} + +foreach test { + {-anchor n n left {bad anchor position "left": must be n, ne, e, se, s, sw, w, nw, or center}} + {-background #ff0000 #ff0000 non-existent + {unknown color name "non-existent"}} + {-bd "4 2" "4 2" badValue {bad screen distance "badValue"}} + {-bg #ff0000 #ff0000 non-existent {unknown color name "non-existent"}} + {-borderwidth 1 1 badValue {bad screen distance "badValue"}} + {-fg #110022 #110022 bogus {unknown color name "bogus"}} + {-font {Helvetica 12} {Helvetica 12} {} {font "" doesn't exist}} + {-foreground #110022 #110022 bogus {unknown color name "bogus"}} + {-image {} {} {} {}} + {-justify left left bogus {bad justification "bogus": must be left, right, or center}} + {-multiline 1 1 xyzzy {expected integer but got "xyzzy"}} + {-relief groove groove 1.5 {bad relief type "1.5": must be flat, groove, raised, ridge, solid, or sunken}} + {-showtext 1 1 xyzzy {expected integer but got "xyzzy"}} + {-state disabled disabled foo {bad option "foo" must be unknown, normal, disabled}} + {-wrap 1 1 xyzzy {expected integer but got "xyzzy"}} +} { + set name [lindex $test 0] + test table-1.$i "tag configuration options, $name" { + .t tag configure title $name [lindex $test 1] + list [lindex [.t tag configure title $name] 4] [.t tag cget title $name] + } [list [lindex $test 2] [lindex $test 2]] + incr i + if {[lindex $test 3] != ""} { + test table-1.$i "tag configuration options, $name" { + list [catch {.t tag configure title $name [lindex $test 3]} msg] $msg + } [list 1 [lindex $test 4]] + } + .t tag configure title $name [lindex [.t tag configure title $name] 3] + incr i +} + +test table-2.1 {Tk_TableCmd procedure} { + list [catch {table} msg] $msg +} {1 {wrong # args: should be "table pathName ?options?"}} +test table-2.2 {Tk_TableCmd procedure} { + list [catch {table gorp} msg] $msg +} {1 {bad window path name "gorp"}} +test table-2.3 {Tk_TableCmd procedure} { + catch {destroy .t} + table .t + list [winfo exists .t] [winfo class .t] [info commands .t] +} {1 Table .t} +test table-2.4 {Tk_TableCmd procedure} { + catch {destroy .t} + list [catch {table .t -gorp foo} msg] $msg [winfo exists .t] \ + [info commands .t] +} {1 {unknown option "-gorp"} 0 {}} +test table-2.5 {Tk_TableCmd procedure} { + catch {destroy .t} + table .t +} {.t} + +option clear +destroy .t +table .t -cache 1 +update +update +update +update +update +update + +test table-3.1 {TableWidgetCmd procedure} { + list [catch .t msg] $msg +} {1 {wrong # args: should be ".t option ?arg arg ...?"}} +test table-3.2 {TableWidgetCmd procedure, commands} { + list [catch {.t whoknows} msg] $msg +} {1 {bad option "whoknows": must be activate, bbox, border, cget, clear, configure, curselection, curvalue, delete, get, height, hidden, icursor, index, insert, reread, scan, see, selection, set, spans, tag, validate, version, window, width, xview, or yview}} +test table-3.3 {TableWidgetCmd procedure, commands} { + list [catch {.t c} msg] $msg +} {1 {ambiguous option "c": must be activate, bbox, border, cget, clear, configure, curselection, curvalue, delete, get, height, hidden, icursor, index, insert, reread, scan, see, selection, set, spans, tag, validate, version, window, width, xview, or yview}} + +test table-4.1 {TableWidgetCmd procedure, "activate" option} { + list [catch {.t activate} msg] $msg +} {1 {wrong # args: should be ".t activate index"}} +test table-4.2 {TableWidgetCmd procedure, "activate" option} { + list [catch {.t activate a b} msg] $msg +} {1 {wrong # args: should be ".t activate index"}} +test table-4.3 {TableWidgetCmd procedure, "activate" option} { + list [catch {.t activate fooey} msg] $msg +} {1 {bad table index "fooey": must be active, anchor, end, origin, topleft, bottomright, @x,y, or <row>,<col>}} +test table-4.4 {TableWidgetCmd procedure, "activate" option} { + .t activate 3,0 + .t index active +} 3,0 +test table-4.5 {TableWidgetCmd procedure, "activate" option} { + .t activate -1,0 + .t index active +} {0,0} +test table-4.6 {TableWidgetCmd procedure, "activate" option} { + .t activate 30,30 + .t index active +} {9,9} +test table-4.7 {TableWidgetCmd procedure, "activate" option} { + .t activate origin + .t index active +} {0,0} +test table-4.8 {TableWidgetCmd procedure, "activate" option} { + .t activate end + .t index active +} {9,9} + +test table-5.1 {TableWidgetCmd procedure, "bbox" option} { + list [catch {.t bbox} msg] $msg +} {1 {wrong # args: should be ".t bbox first ?last?"}} +test table-5.2 {TableWidgetCmd procedure, "bbox" option} { + list [catch {.t bbox a b c} msg] $msg +} {1 {wrong # args: should be ".t bbox first ?last?"}} +test table-5.3 {TableWidgetCmd procedure, "bbox" option} { + list [catch {.t bbox fooey} msg] $msg +} {1 {bad table index "fooey": must be active, anchor, end, origin, topleft, bottomright, @x,y, or <row>,<col>}} + +test table-6.1 {TableWidgetCmd procedure, "cget" option} { + list [catch {.t cget} msg] $msg +} {1 {wrong # args: should be ".t cget option"}} +test table-6.2 {TableWidgetCmd procedure, "cget" option} { + list [catch {.t cget a b} msg] $msg +} {1 {wrong # args: should be ".t cget option"}} +test table-6.3 {TableWidgetCmd procedure, "cget" option} { + list [catch {.t cget -gorp} msg] $msg +} {1 {unknown option "-gorp"}} +test table-6.4 {TableWidgetCmd procedure, "cget" option} { + .t cget -rows +} {10} + +test table-7.1 {TableWidgetCmd procedure, "configure" option} { + llength [.t configure] +} {71} +test table-7.2 {TableWidgetCmd procedure, "configure" option} { + list [catch {.t configure -gorp} msg] $msg +} {1 {unknown option "-gorp"}} +test table-7.3 {TableWidgetCmd procedure, "configure" option} { + .t configure -browsecommand +} {-browsecommand browseCommand BrowseCommand {} {}} +test table-7.4 {TableWidgetCmd procedure, "configure" option} { + list [catch {.t configure -gorp is_messy} msg] $msg +} {1 {unknown option "-gorp"}} +test table-7.5 {TableWidgetCmd procedure, "configure" option} { + set oldbd [.t cget -bd] + set oldht [.t cget -highlightthickness] + .t configure -bd 3 -highlightthickness 0 + set x "[.t cget -bd] [.t cget -highlightthickness]" + .t configure -bd $oldbd -highlightthickness $oldht + set x +} {3 0} + +test table-8.1 {TableWidgetCmd procedure, "curselection" option} { + list [catch {.t curselection a b} msg] $msg +} {1 {wrong # args: should be ".t curselection ?value?"}} +test table-8.2 {TableWidgetCmd procedure, "curselection" option} { + .t selection clear all + .t curselection +} {} +test table-8.2 {TableWidgetCmd procedure, "curselection" option} { + .t selection clear all + .t selection set 1,0 2,2 + .t selection set 3,3 + .t curselection +} {1,0 1,1 1,2 2,0 2,1 2,2 3,3} + +test table-9.1 {TableWidgetCmd procedure, "border" option} { + list [catch {.t border} msg] $msg +} {1 {wrong # args: should be ".t border mark|dragto x y ?row|col?"}} + +test table-10.1 {TableWidgetCmd procedure, "clear" option} { + list [catch {.t clear} msg] $msg +} {1 {wrong # args: should be ".t clear option ?first? ?last?"}} + +test table-11.1 {TableWidgetCmd procedure, "curvalue" option} { + list [catch {.t curvalue this that} msg] $msg +} {1 {wrong # args: should be ".t curvalue ?<value>?"}} + +test table-12.1 {TableWidgetCmd procedure, "delete" option} { + list [catch {.t delete} msg] $msg +} {1 {wrong # args: should be ".t delete option ?switches? arg ?arg?"}} + +test table-13.1 {TableWidgetCmd procedure, "get" option} { + list [catch {.t get} msg] $msg +} {1 {wrong # args: should be ".t get first ?last?"}} + +test table-14.1 {TableWidgetCmd procedure, "height" option} { + list [catch {.t height a} msg] $msg +} {1 {expected integer but got "a"}} + +#test table-15.1 {TableWidgetCmd procedure, "hidden" option} { +# list [catch {.t hidden fooey} msg] $msg +#} {1 {bad table index "fooey": must be active, anchor, end, origin, topleft, bottomright, @x,y, or <row>,<col>}} + +destroy .t +table .t +.t configure -cache 1 +.t set 1,1 abcde + +test table-16.1 {TableWidgetCmd procedure, "icursor" option} { + list [catch {.t icursor a b} msg] $msg +} {1 {wrong # args: should be ".t icursor ?cursorPos?"}} +test table-16.2 {TableWidgetCmd procedure, "icursor" option} { + # no active cell + .t icursor +} -1 + +.t activate 1,1 + +test table-16.3 {TableWidgetCmd procedure, "icursor" option} { + # activate sets cursor to end + .t icursor +} 5 +test table-16.4 {TableWidgetCmd procedure, "icursor" option} { + # change cursor + .t icursor 2 +} 2 +test table-16.5 {TableWidgetCmd procedure, "icursor" option} { + # retain changed cursor position + .t icursor +} 2 + +test table-17.1 {TableWidgetCmd procedure, "index" option} { + list [catch {.t index} msg] $msg +} {1 {wrong # args: should be ".t index <index> ?row|col?"}} + +test table-18.1 {TableWidgetCmd procedure, "insert" option} { + list [catch {.t insert} msg] $msg +} {1 {wrong # args: should be ".t insert option ?switches? arg ?arg?"}} + +test table-19.1 {TableWidgetCmd procedure, "reread" option} { + list [catch {.t reread foo} msg] $msg +} {1 {wrong # args: should be ".t reread"}} + +test table-20.1 {TableWidgetCmd procedure, "scan" option} { + list [catch {.t scan} msg] $msg +} {1 {wrong # args: should be ".t scan mark|dragto x y"}} + +test table-21.1 {TableWidgetCmd procedure, "see" option} { + list [catch {.t see} msg] $msg +} {1 {wrong # args: should be ".t see index"}} + +test table-22.1 {TableWidgetCmd procedure, "selection" option} { + list [catch {.t selection} msg] $msg +} {1 {wrong # args: should be ".t selection option ?arg arg ...?"}} + +test table-23.1 {TableWidgetCmd procedure, "set" option} { + list [catch {.t set} msg] $msg +} {1 {wrong # args: should be ".t set ?row|col? index ?value? ?index value ...?"}} + +test table-24.1 {TableWidgetCmd procedure, "spans" option} { + list [catch {.t spans this} msg] $msg +} {1 {bad table index "this": must be active, anchor, end, origin, topleft, bottomright, @x,y, or <row>,<col>}} + +test table-25.1 {TableWidgetCmd procedure, "tag" option} { + list [catch {.t tag} msg] $msg +} {1 {wrong # args: should be ".t tag option ?arg arg ...?"}} + +test table-25.2.1 {TableWidgetCmd procedure, "tag names" option} { + .t tag names +} {flash active sel title} +test table-25.2.2 {TableWidgetCmd procedure, "tag names" option} { + .t tag names * +} {flash active sel title} +test table-25.2.3 {TableWidgetCmd procedure, "tag names" option} { + .t tag names f* +} {flash} +test table-25.2.4 {TableWidgetCmd procedure, "tag names" option} { + .t tag configure foo +} [expr { + ([info tclversion] > 8.3) ? + {{-anchor anchor Anchor center {unknown anchor position}} {-background background Background {} {}} {-bd borderWidth} {-bg background} {-borderwidth borderWidth BorderWidth {} {}} {-ellipsis ellipsis Ellipsis {} {}} {-foreground foreground Foreground {} {}} {-fg foreground} {-font font Font {} {}} {-image image Image {} {}} {-justify justify Justify left {unknown justification style}} {-multiline multiline Multiline -1 -1} {-relief relief Relief flat {}} {-showtext showText ShowText -1 -1} {-state state State unknown unknown} {-wrap wrap Wrap -1 -1}} + : + {{-anchor anchor Anchor center {unknown anchor position}} {-background background Background {} {}} {-bd borderWidth} {-bg background} {-borderwidth borderWidth BorderWidth {} {}} {-ellipsis ellipsis Ellipsis {} {}} {-foreground foreground Foreground {} {}} {-fg foreground} {-font font Font {} {}} {-image image Image {} {}} {-justify justify Justify left {unknown justification style}} {-multiline multiline Multiline -1 -1} {-relief relief Relief flat {unknown relief}} {-showtext showText ShowText -1 -1} {-state state State unknown unknown} {-wrap wrap Wrap -1 -1}} +}] +test table-25.2.5 {TableWidgetCmd procedure, "tag names" option} { + .t tag names +} {flash active sel title foo} +test table-25.2.6 {TableWidgetCmd procedure, "tag names" option} { + .t tag names f* +} {flash foo} +test table-25.2.7 {TableWidgetCmd procedure, "tag names" option} { + .t tag raise foo + .t tag names f* +} {foo flash} +test table-25.2.8 {TableWidgetCmd procedure, "tag names" option} { + .t tag lower foo + .t tag names +} {flash active sel title foo} +test table-25.2.9 {TableWidgetCmd procedure, "tag names" option} { + .t tag raise foo active + .t tag names +} {flash foo active sel title} +test table-25.2.10 {TableWidgetCmd procedure, "tag names" option} { + .t tag raise foo sel + .t tag names +} {flash active foo sel title} +test table-25.2.11 {TableWidgetCmd procedure, "tag names" option} { + .t tag lower foo active + .t tag names +} {flash active foo sel title} +test table-25.2.12 {TableWidgetCmd procedure, "tag names" option} { + .t tag lower foo foo + .t tag names +} {flash active foo sel title} +test table-25.2.13 {TableWidgetCmd procedure, "tag names" option} { + .t tag lower foo sel + .t tag names +} {flash active sel foo title} +test table-25.2.14 {TableWidgetCmd procedure, "tag names" option} { + .t tag lower foo + .t tag names +} {flash active sel title foo} +test table-25.2.15 {TableWidgetCmd procedure, "tag names" option} { + .t tag raise foo foo + .t tag names +} {flash active sel title foo} +test table-25.2.16 {TableWidgetCmd procedure, "tag names" option} { + .t tag raise foo flash + .t tag names +} {foo flash active sel title} +test table-25.2.17 {TableWidgetCmd procedure, "tag names" option} { + .t tag lower foo title + .t tag names +} {flash active sel title foo} + +test table-26.1 {TableWidgetCmd procedure, "validate" option} { + list [catch {.t validate} msg] $msg +} {1 {wrong # args: should be ".t validate index"}} + +test table-27.1 {TableWidgetCmd procedure, "version" option} { + list [catch {.t version foo} msg] $msg +} {1 {wrong # args: should be ".t version"}} +test table-.1 {TableWidgetCmd procedure, "version" option} { + .t version +} $::VERSION + +test table-28.1 {TableWidgetCmd procedure, "window" option} { + list [catch {.t window} msg] $msg +} {1 {wrong # args: should be ".t window option ?arg arg ...?"}} + +test table-29.1 {TableWidgetCmd procedure, "width" option} { + list [catch {.t width a} msg] $msg +} {1 {expected integer but got "a"}} + + +test table-30.1 {Table_EditCmd insert with var trace Bug #487747} { + destroy .t + table .t -cols 7 -rows 0 -variable ::TableData + .t insert rows end 1 + .t set row 1,1 {1 2 3 4 5} + .t insert rows -- 0 9000 + .t insert rows -- 0 9000 + destroy .t +} {} + + +return +## +## STOP TESTS HERE +## +## The rest of the tests need to be adapted from the listbox tests. +## + +test table-3.30 {TableWidgetCmd procedure, "delete" option} { + list [catch {.t delete} msg] $msg +} {1 {wrong # args: should be ".t delete firstIndex ?lastIndex?"}} +test table-3.31 {TableWidgetCmd procedure, "delete" option} { + list [catch {.t delete a b c} msg] $msg +} {1 {wrong # args: should be ".t delete firstIndex ?lastIndex?"}} +test table-3.32 {TableWidgetCmd procedure, "delete" option} { + list [catch {.t delete badIndex} msg] $msg +} {1 {bad table index "badIndex": must be active, anchor, end, @x,y, or a number}} +test table-3.33 {TableWidgetCmd procedure, "delete" option} { + list [catch {.t delete 2 123ab} msg] $msg +} {1 {bad table index "123ab": must be active, anchor, end, @x,y, or a number}} +test table-3.34 {TableWidgetCmd procedure, "delete" option} { + catch {destroy .t2} + table .t2 + .t2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7 + .t2 delete 3 + list [.t2 get 2] [.t2 get 3] [.t2 index end] +} {el2 el4 7} +test table-3.35 {TableWidgetCmd procedure, "delete" option} { + catch {destroy .t2} + table .t2 + .t2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7 + .t2 delete 2 4 + list [.t2 get 1] [.t2 get 2] [.t2 index end] +} {el1 el5 5} + +test table-3.42 {TableWidgetCmd procedure, "get" option} { + list [catch {.t get} msg] $msg +} {1 {wrong # args: should be ".t get firstIndex ?lastIndex?"}} +test table-3.43 {TableWidgetCmd procedure, "get" option} { + list [catch {.t get a b c} msg] $msg +} {1 {wrong # args: should be ".t get firstIndex ?lastIndex?"}} +test table-3.44 {TableWidgetCmd procedure, "get" option} { + list [catch {.t get 2.4} msg] $msg +} {1 {bad table index "2.4": must be active, anchor, end, @x,y, or a number}} +test table-3.45 {TableWidgetCmd procedure, "get" option} { + list [catch {.t get end bogus} msg] $msg +} {1 {bad table index "bogus": must be active, anchor, end, @x,y, or a number}} +test table-3.46 {TableWidgetCmd procedure, "get" option} { + catch {destroy .t2} + table .t2 + .t2 insert 0 el0 el1 el2 el3 el4 el5 el6 el7 + list [.t2 get 0] [.t2 get 3] [.t2 get end] +} {el0 el3 el7} +test table-3.47 {TableWidgetCmd procedure, "get" option} { + catch {destroy .t2} + table .t2 + list [.t2 get 0] [.t2 get end] +} {{} {}} + +test table-3.57 {TableWidgetCmd procedure, "index" option} { + list [catch {.t index} msg] $msg +} {1 {wrong # args: should be ".t index index"}} +test table-3.58 {TableWidgetCmd procedure, "index" option} { + list [catch {.t index a b} msg] $msg +} {1 {wrong # args: should be ".t index index"}} +test table-3.59 {TableWidgetCmd procedure, "index" option} { + list [catch {.t index @} msg] $msg +} {1 {bad table index "@": must be active, anchor, end, @x,y, or a number}} +test table-3.60 {TableWidgetCmd procedure, "index" option} { + .t index 2 +} 2 +test table-3.61 {TableWidgetCmd procedure, "index" option} { + .t index -1 +} -1 +test table-3.62 {TableWidgetCmd procedure, "index" option} { + .t index end +} 18 +test table-3.63 {TableWidgetCmd procedure, "index" option} { + .t index 34 +} 34 + +test table-3.64 {TableWidgetCmd procedure, "insert" option} { + list [catch {.t insert} msg] $msg +} {1 {wrong # args: should be ".t insert index ?element element ...?"}} +test table-3.65 {TableWidgetCmd procedure, "insert" option} { + list [catch {.t insert badIndex} msg] $msg +} {1 {bad table index "badIndex": must be active, anchor, end, @x,y, or a number}} +test table-3.66 {TableWidgetCmd procedure, "insert" option} { + catch {destroy .t2} + table .t2 + .t2 insert end a b c d e + .t2 insert 3 x y z + .t2 get 0 end +} {a b c x y z d e} +test table-3.67 {TableWidgetCmd procedure, "insert" option} { + catch {destroy .t2} + table .t2 + .t2 insert end a b c + .t2 insert -1 x + .t2 get 0 end +} {x a b c} + +test table-3.74 {TableWidgetCmd procedure, "scan" option} { + list [catch {.t scan a b} msg] $msg +} {1 {wrong # args: should be ".t scan mark|dragto x y"}} +test table-3.75 {TableWidgetCmd procedure, "scan" option} { + list [catch {.t scan a b c d} msg] $msg +} {1 {wrong # args: should be ".t scan mark|dragto x y"}} +test table-3.76 {TableWidgetCmd procedure, "scan" option} { + list [catch {.t scan foo bogus 2} msg] $msg +} {1 {expected integer but got "bogus"}} +test table-3.77 {TableWidgetCmd procedure, "scan" option} { + list [catch {.t scan foo 2 2.3} msg] $msg +} {1 {expected integer but got "2.3"}} +test table-3.78 {TableWidgetCmd procedure, "scan" option} {fonts} { + catch {destroy .t} + toplevel .t + wm geom .t +0+0 + table .t.t -width 10 -height 5 + .t.t insert 0 "Short" "Somewhat longer" "Really, quite a whole lot longer than can possibly fit on the screen" "Short" a b c d e f g h i j + pack .t.t + update + .t.t scan mark 100 140 + .t.t scan dragto 90 137 + update + list [.t.t xview] [.t.t yview] +} {{0.249364 0.427481} {0.0714286 0.428571}} +test table-3.79 {TableWidgetCmd procedure, "scan" option} { + list [catch {.t scan foo 2 4} msg] $msg +} {1 {bad option "foo": must be mark or dragto}} + +test table-3.80 {TableWidgetCmd procedure, "see" option} { + list [catch {.t see} msg] $msg +} {1 {wrong # args: should be ".t see index"}} +test table-3.81 {TableWidgetCmd procedure, "see" option} { + list [catch {.t see a b} msg] $msg +} {1 {wrong # args: should be ".t see index"}} +test table-3.82 {TableWidgetCmd procedure, "see" option} { + list [catch {.t see gorp} msg] $msg +} {1 {bad table index "gorp": must be active, anchor, end, @x,y, or a number}} +test table-3.83 {TableWidgetCmd procedure, "see" option} { + .t yview 7 + .t see 7 + .t index @0,0 +} {7} +test table-3.84 {TableWidgetCmd procedure, "see" option} { + .t yview 7 + .t see 11 + .t index @0,0 +} {7} + +test table-3.93 {TableWidgetCmd procedure, "selection" option} { + list [catch {.t select a} msg] $msg +} {1 {wrong # args: should be ".t selection option index ?index?"}} +test table-3.94 {TableWidgetCmd procedure, "selection" option} { + list [catch {.t select a b c d} msg] $msg +} {1 {wrong # args: should be ".t selection option index ?index?"}} +test table-3.95 {TableWidgetCmd procedure, "selection" option} { + list [catch {.t selection a bogus} msg] $msg +} {1 {bad table index "bogus": must be active, anchor, end, @x,y, or a number}} +test table-3.96 {TableWidgetCmd procedure, "selection" option} { + list [catch {.t selection a 0 lousy} msg] $msg +} {1 {bad table index "lousy": must be active, anchor, end, @x,y, or a number}} +test table-3.97 {TableWidgetCmd procedure, "selection" option} { + list [catch {.t selection anchor 0 0} msg] $msg +} {1 {wrong # args: should be ".t selection anchor index"}} +test table-3.98 {TableWidgetCmd procedure, "selection" option} { + list [.t selection anchor 5; .t index anchor] \ + [.t selection anchor 0; .t index anchor] +} {5 0} +test table-3.99 {TableWidgetCmd procedure, "selection" option} { + .t selection anchor -1 + .t index anchor +} {0} +test table-3.100 {TableWidgetCmd procedure, "selection" option} { + .t selection anchor end + .t index anchor +} {17} +test table-3.101 {TableWidgetCmd procedure, "selection" option} { + .t selection anchor 44 + .t index anchor +} {17} +test table-3.102 {TableWidgetCmd procedure, "selection" option} { + .t selection clear 0 end + .t selection set 2 8 + .t selection clear 3 4 + .t curselection +} {2 5 6 7 8} +test table-3.103 {TableWidgetCmd procedure, "selection" option} { + list [catch {.t selection includes 0 0} msg] $msg +} {1 {wrong # args: should be ".t selection includes index"}} +test table-3.104 {TableWidgetCmd procedure, "selection" option} { + .t selection clear 0 end + .t selection set 2 8 + .t selection clear 4 + list [.t selection includes 3] [.t selection includes 4] \ + [.t selection includes 5] +} {1 0 1} +test table-3.105 {TableWidgetCmd procedure, "selection" option} { + .t selection set 0 end + .t selection includes -1 +} {0} +test table-3.106 {TableWidgetCmd procedure, "selection" option} { + .t selection clear 0 end + .t selection set end + .t selection includes end +} {1} +test table-3.107 {TableWidgetCmd procedure, "selection" option} { + .t selection set 0 end + .t selection includes 44 +} {0} +test table-3.108 {TableWidgetCmd procedure, "selection" option} { + catch {destroy .t2} + table .t2 + .t2 selection includes 0 +} {0} +test table-3.109 {TableWidgetCmd procedure, "selection" option} { + .t selection clear 0 end + .t selection set 2 + .t selection set 5 7 + .t curselection +} {2 5 6 7} +test table-3.110 {TableWidgetCmd procedure, "selection" option} { + .t selection set 5 7 + .t curselection +} {2 5 6 7} +test table-3.111 {TableWidgetCmd procedure, "selection" option} { + list [catch {.t selection badOption 0 0} msg] $msg +} {1 {bad option "badOption": must be anchor, clear, includes, or set}} + +test table-3.114 {TableWidgetCmd procedure, "xview" option} { + catch {destroy .t2} + table .t2 + update + .t2 xview +} {0 1} +test table-3.115 {TableWidgetCmd procedure, "xview" option} { + catch {destroy .t} + table .t -width 10 -height 5 -font $fixed + .t insert 0 a b c d e f g h i j k l m n o p q r s t + pack .t + update + .t xview +} {0 1} +catch {destroy .t} +table .t -width 10 -height 5 -font $fixed +.t insert 0 a b c d e f g h i j k l m n o p q r s t +.t insert 1 "0123456789a123456789b123456789c123456789d123456789" +pack .t +update +test table-3.116 {TableWidgetCmd procedure, "xview" option} {fonts} { + .t xview 4 + .t xview +} {0.08 0.28} +test table-3.117 {TableWidgetCmd procedure, "xview" option} { + list [catch {.t xview foo} msg] $msg +} {1 {expected integer but got "foo"}} +test table-3.118 {TableWidgetCmd procedure, "xview" option} { + list [catch {.t xview zoom a b} msg] $msg +} {1 {unknown option "zoom": must be moveto or scroll}} +test table-3.119 {TableWidgetCmd procedure, "xview" option} {fonts} { + .t xview 0 + .t xview moveto .4 + update + .t xview +} {0.4 0.6} +test table-3.120 {TableWidgetCmd procedure, "xview" option} {fonts} { + .t xview 0 + .t xview scroll 2 units + update + .t xview +} {0.04 0.24} +test table-3.121 {TableWidgetCmd procedure, "xview" option} {fonts} { + .t xview 30 + .t xview scroll -1 pages + update + .t xview +} {0.44 0.64} +test table-3.122 {TableWidgetCmd procedure, "xview" option} {fonts} { + .t configure -width 1 + update + .t xview 30 + .t xview scroll -4 pages + update + .t xview +} {0.52 0.54} + +test table-3.123 {TableWidgetCmd procedure, "yview" option} { + catch {destroy .t} + table .t + pack .t + update + .t yview +} {0 1} +test table-3.124 {TableWidgetCmd procedure, "yview" option} { + catch {destroy .t} + table .t + .t insert 0 el1 + pack .t + update + .t yview +} {0 1} +catch {destroy .t} +table .t -width 10 -height 5 -font $fixed +.t insert 0 a b c d e f g h i j k l m n o p q r s t +pack .t +update +test table-3.125 {TableWidgetCmd procedure, "yview" option} { + .t yview 4 + update + .t yview +} {0.2 0.45} +test table-3.126 {TableWidgetCmd procedure, "yview" option, partial last line} { + mkPartial + .partial.t yview +} {0 0.266667} +test table-3.127 {TableWidgetCmd procedure, "xview" option} { + list [catch {.t yview foo} msg] $msg +} {1 {bad table index "foo": must be active, anchor, end, @x,y, or a number}} +test table-3.128 {TableWidgetCmd procedure, "xview" option} { + list [catch {.t yview foo a b} msg] $msg +} {1 {unknown option "foo": must be moveto or scroll}} +test table-3.129 {TableWidgetCmd procedure, "xview" option} { + .t yview 0 + .t yview moveto .31 + .t yview +} {0.3 0.55} +test table-3.130 {TableWidgetCmd procedure, "xview" option} { + .t yview 2 + .t yview scroll 2 pages + .t yview +} {0.4 0.65} +test table-3.131 {TableWidgetCmd procedure, "xview" option} { + .t yview 10 + .t yview scroll -3 units + .t yview +} {0.35 0.6} +test table-3.132 {TableWidgetCmd procedure, "xview" option} { + .t configure -height 2 + update + .t yview 15 + .t yview scroll -4 pages + .t yview +} {0.55 0.65} + +test table-4.1 {TableGetCellValue, command with large result} { + # test bug 651685 + proc getcell {rc i} { + if {$i == 0} { + return [string repeat $rc 200] + } + } + destroy .t + table .t -rows 5 -cols 5 -command {getcell %C %i} + pack .t -fill both -expand 1 + update + list +} {} + +eval destroy [winfo children .] +option clear + +# cleanup +::tcltest::cleanupTests +return diff --git a/tktable/tktableConfig.sh.in b/tktable/tktableConfig.sh.in new file mode 100755 index 0000000..5ef77bc --- /dev/null +++ b/tktable/tktableConfig.sh.in @@ -0,0 +1,45 @@ +# tktableConfig.sh -- +# +# This shell script (for sh) is generated automatically by tktable's +# configure script. It will create shell variables for most of +# the configuration options discovered by the configure script. +# This script is intended to be included by the configure scripts +# for tktable extensions so that they don't have to figure this all +# out for themselves. This file does not duplicate information +# already provided by tclConfig.sh, so you may need to use that +# file in addition to this one. +# +# The information in this file is specific to a single platform. + +# tktable's version number. +tktable_VERSION='@PACKAGE_VERSION@' + +# The name of the tktable library (may be either a .a file or a shared library): +tktable_LIB_FILE=@PKG_LIB_FILE@ + +# String to pass to linker to pick up the tktable library from its +# build directory. +tktable_BUILD_LIB_SPEC='@tktable_BUILD_LIB_SPEC@' + +# String to pass to linker to pick up the tktable library from its +# installed directory. +tktable_LIB_SPEC='@tktable_LIB_SPEC@' + +# The name of the tktable stub library (a .a file): +#tktable_STUB_LIB_FILE=@PKG_STUB_LIB_FILE@ + +# String to pass to linker to pick up the tktable stub library from its +# build directory. +#tktable_BUILD_STUB_LIB_SPEC='@tktable_BUILD_STUB_LIB_SPEC@' + +# String to pass to linker to pick up the tktable stub library from its +# installed directory. +#tktable_STUB_LIB_SPEC='@tktable_STUB_LIB_SPEC@' + +# String to pass to linker to pick up the tktable stub library from its +# build directory. +#tktable_BUILD_STUB_LIB_PATH='@tktable_BUILD_STUB_LIB_PATH@' + +# String to pass to linker to pick up the tktable stub library from its +# installed directory. +#tktable_STUB_LIB_PATH='@tktable_STUB_LIB_PATH@' diff --git a/tktable/unix/tktable.spec b/tktable/unix/tktable.spec new file mode 100755 index 0000000..3ba135f --- /dev/null +++ b/tktable/unix/tktable.spec @@ -0,0 +1,56 @@ +# RPM specfile provided by Jean-Luc Fontaine +# $Id: tktable.spec,v 1.1.1.1 2011/03/01 20:00:38 joye Exp $ + +%define version 2.10 +%define directory /usr + +Summary: table/matrix widget extension to Tcl/Tk. +Name: tktable +Version: %{version} +Release: 1 +Copyright: public domain +Group: Development/Languages/Tcl +Source: http://prdownloads.sourceforge.net/tktable/Tktable%{version}.tar.gz +URL: http://tktable.sourceforge.net/ +Packager: Jean-Luc Fontaine <jfontain@free.fr> +BuildRequires: XFree86-libs >= 4, XFree86-devel >= 4, tk >= 8.3.1 +AutoReqProv: no +Requires: tk >= 8.3.1 +Buildroot: /var/tmp/%{name}%{version} + +%description +Tktable provides a table/matrix widget for Tk programs. Features: +multi-line cells, embedded windows, variable width columns/height rows +(interactively resizable), scrollbar support, tag styles per row, +column or cell, in-cell editing, works on UNIX, Windows and MacIntosh, +Unicode support with Tk 8.1 and above. + +%prep + +%setup -q -c + +%build +cd Tktable%{version} +./configure --with-tcl=%{directory}/lib --with-tk=%{directory}/lib +make TBL_CFLAGS=-O2 + +%install +cd Tktable%{version} +DIRECTORY=$RPM_BUILD_ROOT%{directory}/lib/%{name}%{version} +install -d $DIRECTORY +install libTktable%{version}.so $DIRECTORY/ +install -m 644 pkgIndex.tcl library/tkTable.tcl library/tktable.py $DIRECTORY +install -d $RPM_BUILD_ROOT%{directory}/man/mann +install -m 644 doc/tkTable.n $RPM_BUILD_ROOT%{directory}/man/mann +install -m 644 ChangeLog README.txt README.blt license.txt .. +install -d ../doc +install -m 644 doc/tkTable.html ../doc + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%doc ChangeLog README.txt README.blt license.txt doc/tkTable.html +%{directory}/lib/%{name}%{version} +%{directory}/man/mann/tkTable.n.gz diff --git a/tktable/win/makefile.vc b/tktable/win/makefile.vc new file mode 100644 index 0000000..55f3244 --- /dev/null +++ b/tktable/win/makefile.vc @@ -0,0 +1,264 @@ +# Makefile.vc +# +# This makefile builds Tktable.dll, a table widget as a dynamically +# loadable Tk extension. This makefile is suitable for use with VC++ 5+. +# +# TkTable assumes that Tcl/Tk has already been installed on Windows. +# +# This does not provide support for static builds on Windows +# + +# Set this to the appropriate value of /MACHINE: for your platform +# Choices: IX86, IA64 +MACHINE = IX86 + +PROJECT = Tktable +TBL_COMMAND = table +TBL_RUNTIME = tkTable.tcl + +# Project directories -- these may need to be customized for your site +# +# ROOT -- location of the source files. +# TMP_DIR -- location for .obj files. +# TOOLS32 -- location of VC++ compiler installation. +# DEST_DIR -- location of Tcl/Tk installation hierarchy +# DEST_DIRU -- same as above with "/" as path separator +# + +ROOT = .. +TMP_DIR = . + +!if "$(MACHINE)" == "IA64" + +# This assumes "-64" suffixes your Win64 build +v3 = 84-64 + +# IA64 support is based on the standard setup with v2 of the +# Microsoft SDK for XP, RC1 + +TOOLS32 = C:/Progra~1/Microsoft SDK + +CC = "$(TOOLS32)/bin/Win64/cl.exe" +LD = "$(TOOLS32)/bin/Win64/link.exe" +libpath32 = /LIBPATH:"$(TOOLS32)/lib/IA64" \ + /LIBPATH:"$(TOOLS32)/lib/Prerelease/IA64" +include32 = -I"$(TOOLS32)/Include/prerelease" \ + -I"$(TOOLS32)/Include/Win64/crt" \ + -I"$(TOOLS32)/Include/Win64/crt/sys" \ + -I"$(TOOLS32)/Include" + +!else + +# Visual Studio 5 default +#TOOLS32 = C:/Progra~1/devstudio/vc + +# Visual Studio 6 default +TOOLS32 = C:/Progra~1/Microsoft Visual Studio/VC98 + +CC = "$(TOOLS32)/bin/cl.exe" +LD = "$(TOOLS32)/bin/link.exe" -link50compat +libpath32 = /LIBPATH:"$(TOOLS32)/lib" +include32 = -I"$(TOOLS32)/include" + +!endif + +DEST_DIR = C:\Tcl +DEST_DIRU = C:/Tcl + +WIN_DIR = $(ROOT)\win +GENERIC_DIR = $(ROOT)\generic +VPATH = $(GENERIC_DIR):$(WIN_DIR) + +#Get version info (this is in Makefile and C format) +!include "$(GENERIC_DIR)\version.h" + +# Set your version of Tcl + +TCL_VERSION = 8.4 +TCL_VER = 84 + +INST_RUNTIME = $(DEST_DIR)\lib\$(PROJECT)$(VERSION) +INST_RUNTIMEU = $(DEST_DIRU)/lib/$(PROJECT)$(VERSION) + +# NO_EMBEDDED_RUNTIME means that the tkTable.tcl file will not be embedded +# into the executable, thus the default tkTable.tcl library file will not +# be available when the library is loaded. +# If this is defined, the tkTable.tcl file must be available in a +# predefined set of directories (see docs). +#TBL_CFLAGS += -DNO_EMBEDDED_RUNTIME + +# change the following line to compile with symbols +DEBUG = 0 + +CP = copy +RM = del + +###################################################################### +# Project specific targets +###################################################################### + +TBL_LIB_DIR = $(ROOT)\library +# Assume that WISH is already INSTALLED +TCLSH = $(DEST_DIR)\bin\tclsh$(TCL_VER) +WISH = $(DEST_DIR)\bin\wish$(TCL_VER) +WIN_LIBS = gdi32.lib user32.lib +LIBS = $(DEST_DIR)\lib\tclstub$(TCL_VER).lib \ + $(DEST_DIR)\lib\tkstub$(TCL_VER).lib $(WIN_LIBS) +LIBS = C:\build\tcl84-64\tclstub$(TCL_VER).lib \ + C:\build\tk84-64\tkstub$(TCL_VER).lib $(WIN_LIBS) +INCLUDES = -I"$(DEST_DIR)\include" -I. $(include32) + +DEFINES = -DDLL_BUILD -DBUILD_Tktable $(TBL_CFLAGS) \ + -DPACKAGE_VERSION=\"$(VERSION)\" \ + -DTBL_COMMAND=\"$(TBL_COMMAND)\" \ + -DTBL_RUNTIME="\"$(TBL_RUNTIME)\"" \ + -DTBL_RUNTIME_DIR="\"$(INST_RUNTIMEU)\"" + +## Define this if you want to use STUBS +## This only works for the dynamic library +## +DEFINES = $(DEFINES) -DUSE_TCL_STUBS -DUSE_TK_STUBS + +CC_SWITCHES = $(CFLAGS) $(EXTRA_CFLAGS) $(DEFINES) $(INCLUDES) + +#--------------------------------------------------------------------- +# Compile flags +#--------------------------------------------------------------------- + +!if !$(DEBUG) +# This cranks the optimization level to maximize speed +cdebug = -O2 -Gs +!else if "$(MACHINE)" == "IA64" +cdebug = -Od -Zi +!else +cdebug = -Z7 -Od -WX +DBGX = d +!endif + +# declarations common to all compiler options +cflags = -c -W3 -nologo -Fp$(TMP_DIR)\ -YX -MT$(DBGX) + +#--------------------------------------------------------------------- +# Link flags +#--------------------------------------------------------------------- + +!if $(DEBUG) +ldebug = -debug:full -debugtype:cv +!else +ldebug = -release +!endif + +# declarations common to all linker options +lflags = -nologo -machine:$(MACHINE) -warn:3 $(libpath32) + +# declarations for use on Intel i386, i486, and Pentium systems +!IF "$(MACHINE)" == "IX86" +DLLENTRY = @12 +dlllflags = $(lflags) -entry:_DllMainCRTStartup$(DLLENTRY) -dll +!ELSE IF "$(MACHINE)" == "IA64" +dlllflags = $(lflags) -dll +!ELSE +dlllflags = $(lflags) -entry:_DllMainCRTStartup$(DLLENTRY) -dll +!ENDIF + +conlflags = $(lflags) -subsystem:console -entry:mainCRTStartup +guilflags = $(lflags) -subsystem:windows -entry:WinMainCRTStartup + +# +# Global makefile settings +# +DLLOBJS = $(TMP_DIR)\tkTable.obj \ + $(TMP_DIR)\tkTableWin.obj \ + $(TMP_DIR)\tkTableTag.obj \ + $(TMP_DIR)\tkTableEdit.obj \ + $(TMP_DIR)\tkTableCell.obj \ + $(TMP_DIR)\tkTableCellSort.obj \ + $(TMP_DIR)\tkTableCmds.obj \ + $(TMP_DIR)\tkTableUtil.obj +# $(TMP_DIR)\tkTablePs.obj + +DLL=$(PROJECT).dll + +# +# Targets +# +all: pkgIndex.tcl + +test: pkgIndex.tcl + @"$(WISH)" << + lappend auto_path $(ROOT) + set code [catch { + package require $(PROJECT) + pack [$(TBL_COMMAND) .t] + } msg] + if {$$code != 0} { + tk_messageBox -type ok -message\ + "$(PROJECT) failed to load and run: $$msg" + } else { + tk_messageBox -type ok -message\ + "everything seems OK for 'package require $(PROJECT)'" + } + exit $$code +<< + +pkgIndex.tcl: $(DLL) + "$(TCLSH)" << pkgIndex.tcl + set out [open [lindex $$argv 0] w] + puts $$out {if {[catch {package require Tcl 8.2}]} return} + puts -nonewline $$out {package ifneeded $(PROJECT) $(VERSION) } + puts -nonewline $$out {"package require Tk 8.2; } + puts $$out {[list load [file join $$dir $(DLL)] $(PROJECT)]"} + close $$out +<< + +pkgIndex.tcl-NOSTUBS: $(DLL) + "$(TCLSH)" << pkgIndex.tcl + set out [open [lindex $$argv 0] w] + puts $$out {if {[catch {package require Tcl $(TCL_VERSION)}]} return} + puts -nonewline $$out {package ifneeded $(PROJECT) $(VERSION) } + puts -nonewline $$out {"package require Tk $(TCL_VERSION); } + puts $$out {[list load [file join $$dir $(DLL)] $(PROJECT)]"} + close $$out +<< + +$(DLL): tkTable.tcl.h $(DLLOBJS) + $(LD) $(linkdebug) $(dlllflags) $(LIBS) \ + $(guilibsdll) -out:$@ $(DLLOBJS) + +tkTable.tcl.h: $(TBL_LIB_DIR)\tkTable.tcl + "$(TCLSH)" << $(TBL_LIB_DIR)\tkTable.tcl >$(TMP_DIR)\tkTable.tcl.h + set in [open [lindex $$argv 0] r] + while {[gets $$in line] != -1} { + switch -regexp -- $$line "^$$" - {^#} continue + regsub -all {\\} $$line {\\\\} line + regsub -all {"} $$line {\"} line + puts "\"$$line\\n\"" + } +<< + +# Implicit Targets + +{$(WIN_DIR)}.c{$(TMP_DIR)}.obj: + $(CC) $(CC_SWITCHES) $(cdebug) $(cflags) $(cvarsdll) -Fo$(TMP_DIR)\ $< + +{$(GENERIC_DIR)}.c{$(TMP_DIR)}.obj: + $(CC) $(CC_SWITCHES) $(cdebug) $(cflags) $(cvarsdll) -Fo$(TMP_DIR)\ $< + +install: pkgIndex.tcl $(DLL) + if not exist "$(INST_RUNTIME)\" mkdir "$(INST_RUNTIME)" + copy "$(TBL_LIB_DIR)\tkTable.tcl" "$(INST_RUNTIME)" + copy "$(DLL)" "$(INST_RUNTIME)" + copy pkgIndex.tcl "$(INST_RUNTIME)" + +uninstall: + -$(RM) "$(INST_RUNTIME)\tkTable.tcl" + -$(RM) "$(INST_RUNTIME)\$(DLL)" + -$(RM) "$(INST_RUNTIME)\pkgIndex.tcl" + +clean: + -$(RM) $(TMP_DIR)\*.obj 2>nul + -$(RM) $(TMP_DIR)\$(DLL) 2>nul + -$(RM) $(TMP_DIR)\$(PROJECT).lib 2>nul + -$(RM) $(TMP_DIR)\$(PROJECT).exp 2>nul + -$(RM) $(TMP_DIR)\pkgIndex.tcl 2>nul + -$(RM) $(TMP_DIR)\tkTable.tcl.h 2>nul |